PHP에서 구성 파일 만들기


101

내 PHP 프로젝트에 대한 구성 파일을 만들고 싶지만이 작업을 수행하는 가장 좋은 방법이 무엇인지 잘 모르겠습니다.

지금까지 3 가지 아이디어가 있습니다.

1- 사용 변수

$config['hostname'] = "localhost";
$config['dbuser'] = "dbuser";
$config['dbpassword'] = "dbpassword";
$config['dbname'] = "dbname";
$config['sitetitle'] = "sitetitle";

2 상수 사용

define('DB_NAME', 'test');
define('DB_USER', 'root');
define('DB_PASSWORD', '');
define('DB_HOST', 'localhost');
define('TITLE', 'sitetitle');

3-Use 데이터베이스

클래스에서 구성을 사용하므로 어떤 방법이 가장 좋은지 또는 더 나은 방법이 있는지 확실하지 않습니다.


12
4) ini 파일을 사용하십시오. 5) YAML 파일을 사용하십시오. 6) JSON 파일을 사용합니다. 7) ... 너무 많은 방법이 있습니다 ... 최소한에 대해 판단 할 기준을 정의하십시오. 전반적인 "최고"는 없습니다.
deceze

@deceze 금식 방법은 무엇입니까? (메모리 및 빠른)
Ali Akbar Azizi 2013

이것은 흥미로운 읽을 거리가 될 것입니다 : stackoverflow.com/questions/823352/…
eithed

1
나는 라 라벨이하는 방식을 사용합니다 (라 라벨을 사용하지 않을 때). 호스트 이름에 따라 특정 구성 파일을로드하는 클래스를 만듭니다. 그런 다음을 사용하여 호출합니다 Config::get('key');. pastebin.com/4iTnjEuM
MisterBla 2015

답변:


217

간단하지만 우아한 방법 중 하나 config.php는 배열 만 반환하는 파일 (또는 호출하는 모든 파일 )을 만드는 것입니다 .

<?php

return array(
    'host' => 'localhost',
    'username' => 'root',
);

그리고:

$configs = include('config.php');

10
나는 또한이 방법처럼 - 난 그냥 포함 된 파일에 변수를 선언하고 스크립트에있을거야 가정보다 그것의 청소기를 생각
콜린 M

구성 파일을 만드는이 응답 방법은 어디에 있습니까? 나 같은 PHP 초보자를 위해?
Luka

@Luka var_export 기능을 사용할 수 있습니다 .
Hasan Bayat 2017 년

77

INI 파일 사용은 유연하고 강력한 솔루션입니다! PHP에는 제대로 처리 하는 기본 기능 이 있습니다. 예를 들어, 다음과 같은 INI 파일을 생성 할 수 있습니다.

app.ini

[database]
db_name     = mydatabase
db_user     = myuser
db_password = mypassword

[application]
app_email = mailer@myapp.com
app_url   = myapp.com

그래서 당신이해야 할 유일한 일은 다음과 같이 전화하는 것입니다.

$ini = parse_ini_file('app.ini');

그런 다음 $ini배열을 사용하여 쉽게 정의에 액세스 할 수 있습니다 .

echo $ini['db_name'];     // mydatabase
echo $ini['db_user'];     // myuser
echo $ini['db_password']; // mypassword
echo $ini['app_email'];   // mailer@myapp.com

중요 : 보안상의 이유로 INI 파일은 비 공용 폴더에 있어야합니다.


이것도 사용하기에 안전한가요? 사용자가 ini 파일의 경로를 추측하고 브라우저로 이동하면 파일에있는 내용을 볼 수 있습니까?
NickGames

1
@NickGames는, 당신은 그렇지 않으면 당신은 심각한 보안 위험 아래에있을 것입니다, 비 공용 폴더에 파일을 삽입해야합니다
마르 Mazzucato

2
@NickGames에 1 코멘트에서 찾아보세요 () parse_ini_file의 문서
R Picheta

19
나는이 접근 방식을 좋아합니다. 보너스 팁 : 파일 이름을 app.ini.php로 바꿉니다. 그런 다음 첫 번째 줄에 추가하십시오 ;<?php die(); ?>. 이 파일이 실수로 공용 폴더에 나타나면 PHP 파일로 취급되어 첫 번째 줄에서 죽습니다. 파일을 읽을 경우 parse_ini_file, 그 때문에의 주석으로 첫 번째 줄을 처리합니다 ;.
안드레아스

1
참고 : ini 파일의 값에 영숫자가 아닌 문자 가 포함 된 경우 큰 따옴표 ( ") 로 묶어야합니다 . 예를 들어 모든 암호에는 영숫자가 아닌 문자가 포함됩니다.
키 샹

24

@hugo_leonardo 솔루션 의 약간의 진화를 사용합니다 .

<?php

return (object) array(
    'host' => 'localhost',
    'username' => 'root',
    'pass' => 'password',
    'database' => 'db'
);

?>

이렇게하면 php $configs->host대신 php :를 포함 할 때 객체 구문을 사용할 수 있습니다 $configs['host'].

또한 앱에 클라이언트 측에 필요한 구성이있는 경우 (예 : Angular 앱의 경우)이 config.php파일에 모든 구성 이 포함되도록 할 수 있습니다 (JavaScript 용 파일과 PHP 용 파일 대신 하나의 파일에 중앙 집중화 됨). 그런 다음 트릭은 echo클라이언트 측 정보 만 포함하는 다른 PHP 파일을 갖는 것입니다 (데이터베이스 연결 문자열처럼 표시하고 싶지 않은 정보를 표시하지 않기 위해). 그것을 말한다 get_app_info.php:

<?php

    $configs = include('config.php');
    echo json_encode($configs->app_info);

?>

위의 가정 config.php에는 app_info매개 변수 가 포함되어 있습니다 .

<?php

return (object) array(
    'host' => 'localhost',
    'username' => 'root',
    'pass' => 'password',
    'database' => 'db',
    'app_info' => array(
        'appName'=>"App Name",
        'appURL'=> "http://yourURL/#/"
    )
);

?>

따라서 데이터베이스 정보는 서버 측에 유지되지만 앱 정보는 JavaScript에서 액세스 할 수 있습니다 (예 : $http.get('get_app_info.php').then(...);호출 유형).


왜 그것을 객체로 만드나요?
TheCrazyProfessor

4
객체로 만들면 데이터 처리가 훨씬 쉬워집니다. 예를 들어 app_info최소한의 코드 줄로 JSON으로 JavaScript에 대한 모든 매개 변수 를 가져올 수 있습니다.
BoDeX

객체는 PHP 5부터 참조로 전달되는 부작용도 있습니다. 이것은 좋은 것일 수도 있고 아닐 수도 있습니다. 배열은 값으로 전달되지만 (COW로 구현 됨) 구성 개체 대신 구성 배열을 사용하는 것이 더 나을 수 있습니다.
Mikko Rantalainen

@BoDeX 나는 항상 이런 방식을 좋아하고 대부분의 기사에서 선호되는 접근 방식 인 것 같지만 클래스를 통해 어떻게 액세스 할 수 있습니까? 나는 보안 기사에서 전역 변수를 만드는 것이 좋은 생각이 아니라고 읽었으므로 무엇을 제안합니까?
Kevlwig

22

상대적인 장점 / 약점으로 보는 옵션은 다음과 같습니다.

파일 기반 메커니즘

이를 위해서는 코드가 특정 위치에서 ini 파일을 찾아야합니다. 이것은 해결하기 어려운 문제이며 큰 PHP 응용 프로그램에서 항상 발생하는 문제입니다. 그러나 런타임에 통합 / 재사용되는 PHP 코드를 찾으려면 문제를 해결해야 할 것입니다.

이에 대한 일반적인 접근 방식은 항상 상대 디렉터리를 사용하거나 현재 디렉터리에서 위쪽으로 검색하여 응용 프로그램의 기본 디렉터리에서 독점적으로 명명 된 파일을 찾는 것입니다.

구성 파일에 사용되는 일반적인 파일 형식은 PHP 코드, ini 형식 파일, JSON, XML, YAML 및 직렬화 된 PHP입니다.

PHP 코드

이는 다양한 데이터 구조를 표현할 수있는 엄청난 유연성을 제공하며 (include 또는 require를 통해 처리된다고 가정 할 때) 구문 분석 된 코드를 opcode 캐시에서 사용할 수있어 성능상의 이점을 제공합니다.

의 include_path 추가 코드에 의존하지 않고 파일의 잠재적 인 위치를 추출하는 수단을 제공합니다.

반면에 구성을 코드에서 분리하는 주된 이유 중 하나는 책임을 분리하는 것입니다. 런타임에 추가 코드를 삽입하기위한 경로를 제공합니다.

구성이 도구에서 생성 된 경우 도구에서 데이터의 유효성을 검사 할 수 있지만 HTML, URL, MySQL 문, 셸 명령에 대해 존재하는 것처럼 PHP 코드에 삽입하기 위해 데이터를 이스케이프하는 표준 기능이 없습니다. .

직렬화 된 데이터 이것은 적은 양의 구성 (최대 약 200 개 항목)에 상대적으로 효율적이며 모든 PHP 데이터 구조를 사용할 수 있습니다. 데이터 파일을 생성 / 파싱하는 데 코드가 거의 필요하지 않으므로 대신 파일이 적절한 권한으로 만 작성되도록 노력할 수 있습니다.

파일에 기록 된 내용의 이스케이프는 자동으로 처리됩니다.

객체를 직렬화 할 수 있으므로 구성 파일 (__wakeup 매직 메서드)을 읽는 것만으로 코드를 호출 할 수 있습니다.

구조화 된 파일

Marcel, JSON 또는 XML에서 제안한대로 INI 파일로 저장하면 코드 호출을 제거하면서 파일을 PHP 데이터 구조 (XML 제외, 데이터 이스케이프 및 파일 생성)로 매핑하는 간단한 API도 제공됩니다. 직렬화 된 PHP 데이터를 사용하는 취약점.

직렬화 된 데이터와 유사한 성능 특성을 갖습니다.

데이터베이스 저장소

이것은 엄청난 양의 구성이 있지만 현재 작업에 필요한 것은 선택적인 경우에 가장 적합합니다. 약 150 개의 데이터 항목에서 로컬 MySQL 인스턴스에서 데이터를 검색하는 것이 더 빠르다는 사실에 놀랐습니다. 데이터 파일을 직렬화 해제합니다.

OTOH는 데이터베이스에 연결하는 데 사용하는 자격 증명을 저장하기에 좋은 곳이 아닙니다!

실행 환경

PHP가 실행되는 실행 환경 에서 값을 설정할 수 있습니다 .

이렇게하면 PHP 코드가 구성의 특정 위치를 찾는 데 필요한 모든 요구 사항이 제거됩니다. OTOH는 많은 양의 데이터로 잘 확장되지 않으며 런타임에 보편적으로 변경하기가 어렵습니다.

클라이언트에서

구성 데이터 저장에 대해 언급하지 않은 한 곳은 클라이언트입니다. 다시 말하지만 네트워크 오버 헤드는 이것이 많은 양의 구성으로 잘 확장되지 않음을 의미합니다. 그리고 최종 사용자가 데이터를 제어 할 수 있으므로 변조가 감지 될 수있는 형식 (즉, 암호화 서명 사용)으로 저장되어야하며 공개로 인해 손상되는 정보 (예 : 가역적으로 암호화 됨)를 포함해서는 안됩니다.

반대로 이것은 최종 사용자가 소유 한 민감한 정보를 저장하는 데 많은 이점이 있습니다. 서버에 저장하지 않으면 거기에서 도난 당할 수 없습니다.

네트워크 디렉토리 구성 정보를 저장하는 또 다른 흥미로운 장소는 DNS / LDAP입니다. 이것은 소수의 작은 정보에 대해 작동하지만 첫 번째 정규 형식을 고수 할 필요는 없습니다 . 예를 들어 SPF를 고려하십시오 .

인프라는 캐싱, 복제 및 배포를 지원합니다. 따라서 매우 큰 인프라에서 잘 작동합니다.

버전 관리 시스템

코드와 같은 구성을 관리하고 버전을 제어해야합니다. 따라서 VC 시스템에서 직접 구성을 가져 오는 것이 실행 가능한 솔루션입니다. 그러나 종종 이것은 상당한 성능 오버 헤드를 동반하므로 캐싱이 권장 될 수 있습니다.


6

글쎄-데이터베이스 구성 데이터를 데이터베이스에 저장하는 것은 다소 어려울 것입니다. 그렇지 않습니까?

그러나 실제로 이것은 모든 스타일이 실제로 작동하고 모든 것이 선호도의 문제이기 때문에 상당히 의견이 많은 질문입니다. 개인적으로 상수보다는 구성 변수를 사용합니다. 일반적으로 필요한 경우가 아니면 전역 공간에있는 것을 좋아하지 않기 때문입니다. 내 코드베이스의 어떤 함수도 내 데이터베이스 암호에 쉽게 액세스 할 수 없어야합니다 (데이터베이스 연결 논리 제외). 그래서 거기에서 사용하고 파괴 할 가능성이 높습니다.

편집 : 귀하의 의견에 대답하기 위해-파싱 메커니즘 중 어느 것도 가장 빠르지 않을 것입니다 (ini, json 등)-그러나 속도 차이가 있기 때문에 최적화에 실제로 집중 해야하는 응용 프로그램의 일부가 아닙니다. 이러한 작은 파일에서는 무시할 수 있습니다.


2

Define은 전역을 사용할 필요없이 클래스의 모든 곳에서 상수를 사용할 수 있도록하는 반면 변수는 클래스에서 전역을 요구하지만 DEFINE을 사용합니다. 그러나 다시 말하지만, 프로그램 실행 중에 db 매개 변수가 변경되어야하는 경우 변수를 사용하는 것이 좋습니다.


PHP를 실행하는 가장 빠른 방법은 무엇입니까? const 또는 var?
Ali Akbar Azizi 2013

1
@CooPer 상수를 정의하는 것은 변수를 정의하는 것보다 훨씬 느립니다. 그러나 그것들을 사용하는 것이 약간 더 빠릅니다. 이들은 한곳에서 사용될 것이기 때문에 변수는 전반적으로 더 높은 성능을 제공합니다.
Colin M

"중요하게"는 약간 무거운 단어입니다. 이런 식으로보고 있다면 PHP 개발자에게 연락하여 지속적인 지원을 제거하도록 요청해야합니다!
phpalix 2013

@phpalix 상수를 정의하는 것은 같은 값을 가진 변수를 정의하는 것보다 10-20 배 더 느릴 수 있습니다. 나는 그것이 중요하다고 말하고 싶습니다. 그러나 응용 프로그램 전체에서 상수를 많이 사용하면 매우 좋은 결과를 얻을 수 있습니다. 그러나 한 번 사용하기 위해 상수를 만드는 것은 권장되지 않습니다.
Colin M

2

어떤 이유로 든 둘 이상의 db를 사용할 것이라고 생각되면 하나의 매개 변수를 변경하여 완전히 다른 db로 전환 할 수 있으므로 변수를 사용하십시오. 즉 테스트, 자동 백업 등에 사용됩니다.


2

구성 클래스 마녀 정적 속성을 만들 수 있습니다.

class Config 
{
    static $dbHost = 'localhost';
    static $dbUsername = 'user';
    static $dbPassword  = 'pass';
}

그런 다음 간단하게 사용할 수 있습니다.

Config::$dbHost  

때때로 내 프로젝트에서 SINGLETON 디자인 패턴을 사용하여 구성 데이터에 액세스합니다. 사용하기에 매우 편안합니다.

왜?

예를 들어 프로젝트에 2 개의 데이터 소스가 있습니다. 그리고 그들의 마녀를 선택할 수 있습니다.

  • mysql
  • json

선택한 구성 파일의 어딘가 :

$dataSource = 'mysql' // or 'json'

소스 전체 앱을 변경하면 새 데이터 소스로 전환하면 정상적으로 작동하며 코드를 변경할 필요가 없습니다.

예:

구성 :

class Config 
{
  // ....
  static $dataSource = 'mysql';
  / .....
}

싱글 톤 클래스 :

class AppConfig
{
    private static $instance;
    private $dataSource;

    private function __construct()
    {
        $this->init();
    }

    private function init()
    {
        switch (Config::$dataSource)
        {
            case 'mysql':
                $this->dataSource = new StorageMysql();
                break;
            case 'json':
                $this->dataSource = new StorageJson();
                break;
            default:
                $this->dataSource = new StorageMysql();
        }
    }

    public static function getInstance()
    {
        if (empty(self::$instance)) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    public function getDataSource()
    {
        return $this->dataSource;
    }
}

... 그리고 코드의 어딘가 (예 : 일부 서비스 클래스) :

$container->getItemsLoader(AppConfig::getInstance()->getDataSource()) // getItemsLoader need Object of specific data source class by dependency injection

시스템의 어느 위치에서나 AppConfig 객체를 얻을 수 있으며 항상 동일한 복사본을 얻을 수 있습니다 (정적 덕분에). 클래스의 init () 메서드는 생성자에서 호출되어 하나의 실행 만 보장합니다. Init () body는 config $ dataSource의 값을 확인하고 특정 데이터 소스 클래스의 새 개체를 만듭니다. 이제 우리 스크립트는 어떤 특정 구현이 실제로 존재하는지조차 알지 못하면서 객체를 가져 와서 작동 할 수 있습니다.


1

일반적으로 데이터베이스 연결이있는 단일 conn.php 파일을 생성합니다. 그런 다음 데이터베이스 쿼리가 필요한 모든 파일에 해당 파일을 포함합니다.


1
나는 그것을 알고 있지만 어떻게 당신의 데이터베이스 파일을 변수 또는 const로 저장합니까? 그리고 왜?
Ali Akbar Azizi 2013

0

여기 내 방식입니다.

<?php

define('DEBUG',0);

define('PRODUCTION',1);



#development_mode : DEBUG / PRODUCTION

$development_mode = PRODUCTION;



#Website root path for links

$app_path = 'http://192.168.0.234/dealer/';



#User interface files path

$ui_path = 'ui/';

#Image gallery path

$gallery_path = 'ui/gallery/';


$mysqlserver = "localhost";
$mysqluser = "root";
$mysqlpass = "";
$mysqldb = "dealer_plus";

?>

의심이 있으시면 댓글을 남겨주세요


3
여보세요! 사용법의 예를 들어 주시겠습니까? 감사합니다
Nick
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.