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-データベースを使用

私はクラスで設定を使用するので、どちらの方法が最適であるか、またはより良い方法があるかどうかはわかりません。


12
4)iniファイルを使用します。5)YAMLファイルを使用します。6)JSONファイルを使用します。7)...非常に多くの方法があります...少なくともに対して判断するいくつかの基準を定義します。全体的に「最善」はありません。
だます

@deceze断食の方法は何ですか?(メモリと高速)
Ali Akbar Azizi 2013

これはあなたのための興味深い読まれるべきである:stackoverflow.com/questions/823352/...
eithed

1
私はLaravelが行う方法を使用します(Laravelを使用しない場合)。ホスト名に応じて特定の設定ファイルをロードするクラスを作成します。次に、を使用して呼び出しますConfig::get('key');pastebin.com/4iTnjEuM
MisterBla

回答:


217

シンプルでありながらエレガントな方法の1つconfig.phpは、配列を返すだけのファイル(または、ファイルと呼ばれるもの)を作成することです。

<?php

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

その後:

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

10
私もこの方法が好きです。インクルードファイルで変数を宣言し、スクリプト内にあると仮定するよりもクリーンだと思います
Colin M

設定ファイルを作成するこの回答方法はどこにありますか?私のようなphp初心者のために?
ルカ

@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 2016

1
@NickGames、ファイルは非パブリックフォルダーに配置する必要があります。そうしないと、深刻なセキュリティリスクにさらされます
Marcio Mazzucato


19
私はこのアプローチが好きです。おまけのヒント:ファイルの名前をapp.ini.phpに変更します。次に、最初の行に追加し;<?php die(); ?>ます。このファイルが誤ってパブリックフォルダーに表示された場合、PHPファイルとして扱われ、最初の行で終了します。ファイルがで読み取られた場合、parse_ini_file最初の行は;。のためにコメントとして扱われます。
andreas

1
注:iniファイルの値に英数字以外の文字が含まれている場合は、二重引用符")で囲む必要があります。たとえば、パスワードには英数字以外の文字が含まれています。
Key Shang

24

@hugo_leonardoのソリューションを少し進化させて使用します

<?php

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

?>

これはあなたがPHPを含む場合、オブジェクト構文を使用することができます:$configs->host代わりに$configs['host']

また、アプリにクライアント側で必要な設定がある場合(Angularアプリの場合など)、このconfig.phpファイルにすべての設定を含めることができます(JavaScript用とPHP用ではなく、1つのファイルに集中化)。トリックはecho、クライアント側の情報のみを含む別のPHPファイルを作成することです(データベース接続文字列のように表示したくない情報が表示されないようにするため)。それを言うと言うget_app_info.php

<?php

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

?>

上記はあなたconfig.phpapp_infoパラメータを含んでいると仮定します:

<?php

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

?>

したがって、データベースの情報はサーバー側に残りますが、アプリの情報には、たとえば、$http.get('get_app_info.php').then(...);一種の呼び出しを使用して、JavaScriptからアクセスできます。


なぜそれをオブジェクトにするのですか?
TheCrazyProfessor 2017年

4
オブジェクトにすると、データの処理がはるかに簡単になります。たとえばapp_info、JavaScriptへのすべてのパラメーターをJSONとして最小限のコード行で取得できます。
BoDeX 2017年

PHP 5以降、オブジェクトには参照渡しの副作用もあります。これは良いことかもしれませんし、そうでないかもしれません。配列は値によって渡される(ただしCOWとして実装される)ため、構成オブジェクトの代わりに構成配列を使用する方がよい場合があります。
ミッコランタライネン2017年

@BoDeX私はいつもこの方法が好きで、ほとんどの記事で推奨されるアプローチのようですが、クラスを介してこれにアクセスするにはどうすればよいですか?セキュリティの記事を読んで、グローバル変数を作成するのは良い考えではないので、何を提案しますか?
Kevlwig 2018

22

私が相対的なメリット/弱点で見るオプションは次のとおりです。

ファイルベースのメカニズム

これらでは、iniファイルを見つけるためにコードが特定の場所を調べる必要があります。これは解決するのが難しい問題であり、大きなPHPアプリケーションでは常に発生する問題です。ただし、実行時に組み込まれる/再利用されるPHPコードを見つけるために、問題を解決する必要がある可能性があります。

これに対する一般的なアプローチは、常に相対ディレクトリを使用するか、現在のディレクトリから上方向に検索して、アプリケーションのベースディレクトリでのみ指定されたファイルを見つけることです。

構成ファイルに使用される一般的なファイル形式は、PHPコード、ini形式のファイル、JSON、XML、YAML、シリアル化されたPHPです。

PHPコード

これは、さまざまなデータ構造を表現するための非常に大きな柔軟性を提供し、(includeまたはrequireを介して処理されると仮定して)解析されたコードはopcodeキャッシュから利用できるようになり、パフォーマンス上の利点が得られます。

include_pathのは、追加のコードに依存することなく、ファイルの潜在的な場所を抽象化するための手段を提供します。

一方、構成をコードから分離する主な理由の1つは、責任を分離することです。ランタイムに追加コードを注入するためのルートを提供します。

構成がツールから作成された場合、ツールでデータを検証できる可能性がありますが、HTML、URL、MySQLステートメント、シェルコマンドなどに存在するPHPコードに埋め込むためのデータをエスケープする標準関数はありません... 。

シリアル化されたデータ これは、少量の構成(最大200項目)で比較的効率的で、任意のPHPデータ構造を使用できます。データファイルの作成/解析に必要なコードはごくわずかです(そのため、適切な権限でのみファイルが書き込まれるようにするための努力を費やすことができます)。

ファイルに書き込まれたコンテンツのエスケープは自動的に処理されます。

オブジェクトをシリアル化できるため、構成ファイル(__wakeupマジックメソッド)を読み取るだけで、コードを呼び出す機会が生まれます。

構造化ファイル

Marcel、JSON、またはXMLで提案されているようにINIファイルとして保存すると、ファイルをPHPデータ構造にマップする(そしてXMLを除いて、データをエスケープしてファイルを作成する)シンプルなAPIも提供され、コードの呼び出しが不要になります。シリアル化されたPHPデータを使用した脆弱性。

シリアル化されたデータと同様のパフォーマンス特性があります。

データベースストレージ

これは、大量の構成がある場合に最もよく考慮されますが、現在のタスクに必要なものを選択します-約150のデータ項目で、ローカルのMySQLインスタンスからデータを取得する方が、データファイルのシリアル化を解除します。

OTOHは、データベースへの接続に使用する資格情報を保存するのに適した場所ではありません。

実行環境

PHPが実行されている実行環境で値を設定できます。

これにより、PHPコードが構成の特定の場所を探す必要がなくなります。OTOHは、大量のデータに適切にスケーリングできず、実行時に普遍的に変更することが困難です。

クライアント上

構成データを保存するために言及しなかった場所の1つはクライアントです。繰り返しになりますが、ネットワークのオーバーヘッドは、これが大量の構成にうまく対応できないことを意味します。また、エンドユーザーはデータを制御できるため、改ざんが検出可能な形式で(つまり、暗号化署名を使用して)保存する必要があり、その開示によって侵害される(つまり、可逆的に暗号化される)情報を含めることはできません。

逆に、これには、エンドユーザーが所有する機密情報を保存するための多くの利点があります。これをサーバーに保存しないと、そこから盗むことはできません。

ネットワークディレクトリ 構成情報を保存するもう1つの興味深い場所は、DNS / LDAPです。これは、少数の小さな情報に対して機能しますが、第1正規形に固執する必要はありません。たとえば、SPFを検討してください。

インフラストラクチャは、キャッシング、レプリケーション、配布をサポートしています。したがって、非常に大規模なインフラストラクチャに適しています。

バージョン管理システム

コードのように構成を管理し、バージョン管理する必要があります。したがって、VCシステムから直接構成を取得することは、実行可能なソリューションです。しかし、多くの場合、これにはかなりのパフォーマンスオーバーヘッドが伴うため、キャッシングをお勧めします。


6

ええと、データベースにデータベース構成データを格納するのはちょっと難しいでしょう。そう思いませんか?

しかし、実際には、これはかなり厳しい意見の質問です。これは、どのスタイルも実際に機能し、すべて好みの問題であるためです。個人的には、定数ではなく構成変数を使用します。これは、一般的に、必要がない限り、グローバルスペースでの作業が好きではないためです。コードベースのどの関数もデータベースパスワードに簡単にアクセスできないようにする必要があります(データベース接続ロジックを除く)。そのため、そこで使用し、おそらくそれを破棄します。

編集:あなたのコメントに答えるために-どの解析メカニズムも最速ではありません(ini、jsonなど)-しかし、速度の違いにより、最適化に集中する必要があるアプリケーションの部分でもありませんそのような小さなファイルでは無視できます。


2

Defineは、グローバルを使用する必要なく、クラス内のどこでも定数を使用できるようにしますが、変数はクラス内でグローバルを必要としますが、DEFINEを使用します。しかし、繰り返しになりますが、プログラムの実行中にdb paramsを変更する必要がある場合は、変数を使用することをお勧めします。


PHPを実行する最も速い方法は何ですか?constまたはvar?
Ali Akbar Azizi 2013

1
@CooPer定数の定義は、変数の定義よりもかなり低速です。しかし、それらを使用すると、少し速くなります。これらは1か所で使用されるため、変数は全体としてより高いパフォーマンスを提供します。
コリンM

「かなり」はそのための少し重い言葉です。もしあなたがこのように見ているなら、多分あなたはphp開発者に連絡して彼らに継続的なサポートを削除するように頼むべきです!
phpalix 2013

@phpalix定数の定義は、同じ値の変数を定義するよりも10〜20倍遅くなる可能性があります。それは重要だと思います。ただし、アプリケーション全体で定数を頻繁に使用する場合は、十分に効果がある場合があります。ただし、定数を作成して一度使用することはお勧めしません。
Colin M

2

何らかの理由で複数のdbを使用すると思われる場合は、1つのパラメーターを変更して完全に異なる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オブジェクトをシステム内の任意の場所から取得し、常に同じコピーを取得できます(おかげでstatic)。クラスのinit()メソッドはコンストラクターで呼び出され、1回の実行のみを保証します。Init()ボディは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
こんにちは!使い方の例を挙げていただけませんか?ありがとう
ニック
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.