Criação de um arquivo de configuração em PHP

101

Quero criar um arquivo de configuração para meu projeto PHP, mas não tenho certeza de qual é a melhor maneira de fazer isso.

Tenho 3 ideias até agora.

1-Use Variável

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

2-Use Const

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

3-Use Database

Eu estarei usando a configuração nas aulas, então não tenho certeza de qual seria a melhor ou se existe uma maneira melhor.

Ali Akbar Azizi
fonte
12
4) Use um arquivo ini. 5) Use um arquivo YAML. 6) Use um arquivo JSON. 7) ... Existem tantas maneiras ... Defina alguns critérios para julgar pelo menos, não há "melhor" geral.
deceze
@deceze qual é a forma de jejum? (memória e rápido)
Ali Akbar Azizi
Esta deve ser uma leitura interessante para você: stackoverflow.com/questions/823352/…
dia
1
Eu uso a forma como o Laravel faz (quando não estou usando o Laravel). Eu crio uma classe que carrega um arquivo de configuração específico dependendo do nome do host. Eu então chamo usando Config::get('key');. pastebin.com/4iTnjEuM
MisterBla

Respostas:

217

Uma maneira simples, mas elegante, é criar um config.phparquivo (ou o nome que você quiser) que apenas retorne uma matriz:

<?php

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

E depois:

$configs = include('config.php');
Hugo Mota
fonte
10
Também gosto desse método - acho que é mais limpo do que apenas declarar uma variável em um arquivo incluído e presumir que ela estará no seu script
Colin M
Onde está neste método de resposta de criação de arquivo de configuração? Para novatos em php como eu?
Luka
@Luka Você pode usar a função var_export .
Hasan Bayat
77

Usar um arquivo INI é uma solução flexível e poderosa! O PHP tem uma função nativa para manipulá-lo adequadamente. Por exemplo, é possível criar um arquivo INI como este:

app.ini

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

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

Portanto, a única coisa que você precisa fazer é ligar para:

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

Em seguida, você pode acessar as definições facilmente usando o $iniarray.

echo $ini['db_name'];     // mydatabase
echo $ini['db_user'];     // myuser
echo $ini['db_password']; // mypassword
echo $ini['app_email'];   // [email protected]

IMPORTANTE: Por razões de segurança, o arquivo INI deve estar em uma pasta não pública

Marcio Mazzucato
fonte
Também é seguro usar? Se um usuário adivinhasse o caminho para o arquivo ini e for lá em seu navegador, ele veria o que há no arquivo?
NickGames
1
@NickGames, Você deve colocar o arquivo em uma pasta não pública, caso contrário, você estará sob um sério risco de segurança
Marcio Mazzucato
2
@NickGames, por favor, olhe o 1 comentário no Docs de parse_ini_file ()
R Picheta
19
Eu gosto dessa abordagem. Dica bônus: renomeie o arquivo para app.ini.php. Em seguida, adicione à primeira linha ;<?php die(); ?>. Caso este arquivo apareça acidentalmente em uma pasta pública, ele será tratado como arquivo PHP e morrerá na primeira linha. Se o arquivo for lido com parse_ini_file, ele tratará a primeira linha como um comentário devido ao ;.
andreas
1
Nota: Se um valor no arquivo ini contiver qualquer caractere não alfanumérico , ele precisa ser colocado entre aspas ( "). Por exemplo, qualquer senha contém caracteres não alfanuméricos.
Key Shang
24

Eu uso uma ligeira evolução da @hugo_leonardo 's solução :

<?php

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

?>

Isso permite que você use a sintaxe do objeto ao incluir o php: em $configs->hostvez de $configs['host'].

Além disso, se seu aplicativo tiver configurações de que você precisa no lado do cliente (como para um aplicativo Angular), você pode fazer com que esse config.phparquivo contenha todas as suas configurações (centralizado em um arquivo em vez de um para JavaScript e outro para PHP). O truque seria então ter outro arquivo PHP que contivesse echoapenas as informações do lado do cliente (para evitar mostrar informações que você não quer mostrar como a string de conexão do banco de dados). Chame-o por dizer get_app_info.php:

<?php

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

?>

Acima, pressupondo que você config.phpcontém um app_infoparâmetro:

<?php

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

?>

Portanto, as informações do seu banco de dados permanecem no lado do servidor, mas as informações do seu aplicativo são acessíveis a partir do seu JavaScript, com, por exemplo, um $http.get('get_app_info.php').then(...);tipo de chamada.

BoDeX
fonte
por que torná-lo um objeto?
TheCrazyProfessor
4
Torná-lo um objeto torna o manuseio dos dados muito mais fácil. Ele permite, por exemplo, obter todos os app_infoparâmetros do JavaScript como um JSON com um mínimo de linhas de código.
BoDeX
Objetos também têm o efeito colateral de serem passados ​​por referência desde o PHP 5. Isso pode ou não ser uma coisa boa. Os arrays são passados ​​por valor (mas implementados como COW), então pode ser melhor usar arrays de configuração em vez de objetos de configuração.
Mikko Rantalainen
@BoDeX eu sempre gosto desse jeito e parece ser a abordagem preferida na maioria dos artigos, mas como eu acessaria isso via aula? Eu li em um artigo de segurança que criar variáveis ​​globais não é uma boa ideia, então o que você sugere?
Kevlwig
22

As opções que vejo com méritos / pontos fracos relativos são:

Mecanismos baseados em arquivos

Isso requer que seu código procure em locais específicos para encontrar o arquivo ini. Este é um problema difícil de resolver e que sempre surge em grandes aplicativos PHP. No entanto, você provavelmente precisará resolver o problema para encontrar o código PHP que é incorporado / reutilizado no tempo de execução.

As abordagens comuns para isso são sempre usar diretórios relativos ou pesquisar a partir do diretório atual para encontrar um arquivo nomeado exclusivamente no diretório base do aplicativo.

Os formatos de arquivo comuns usados ​​para arquivos de configuração são código PHP, arquivos formatados ini, JSON, XML, YAML e PHP serializado

Código PHP

Isso fornece uma grande flexibilidade para representar diferentes estruturas de dados e (assumindo que seja processado por meio de include ou require) o código analisado estará disponível no cache de opcode - proporcionando um benefício de desempenho.

O include_path fornece um meio de abstrair os locais potenciais do arquivo sem depender de código adicional.

Por outro lado, um dos principais motivos para separar a configuração do código é separar responsabilidades. Ele fornece uma rota para injetar código adicional no tempo de execução.

Se a configuração for criada a partir de uma ferramenta, pode ser possível validar os dados na ferramenta, mas não há uma função padrão para escapar os dados para incorporação no código PHP como existe para HTML, URLs, instruções MySQL, comandos shell ... .

Dados serializados Isso é relativamente eficiente para pequenas quantidades de configuração (até cerca de 200 itens) e permite o uso de qualquer estrutura de dados PHP. Requer muito pouco código para criar / analisar o arquivo de dados (então você pode, em vez disso, despender seus esforços para garantir que o arquivo seja escrito apenas com a autorização apropriada).

O escape do conteúdo gravado no arquivo é tratado automaticamente.

Uma vez que você pode serializar objetos, isso cria uma oportunidade para invocar código simplesmente lendo o arquivo de configuração (o método mágico __wakeup).

Arquivo estruturado

Armazená-lo como um arquivo INI conforme sugerido por Marcel ou JSON ou XML também fornece uma API simples para mapear o arquivo em uma estrutura de dados PHP (e com exceção de XML, para escapar dos dados e criar o arquivo), eliminando a invocação do código vulnerabilidade usando dados PHP serializados.

Ele terá características de desempenho semelhantes aos dados serializados.

Armazenamento de banco de dados

Isso é melhor considerado quando você tem uma grande quantidade de configuração, mas é seletivo no que é necessário para a tarefa atual - fiquei surpreso ao descobrir que em cerca de 150 itens de dados, era mais rápido recuperar os dados de uma instância local do MySQL do que desserializar um arquivo de dados.

OTOH não é um bom lugar para armazenar as credenciais que você usa para se conectar ao seu banco de dados!

O ambiente de execução

Você pode definir valores no ambiente de execução em que o PHP está sendo executado.

Isso remove qualquer requisito para o código PHP procurar em um local específico para a configuração. O OTOH não se adapta bem a grandes quantidades de dados e é difícil de alterar universalmente em tempo de execução.

No cliente

Um lugar que não mencionei para armazenar dados de configuração é no cliente. Novamente, a sobrecarga da rede significa que isso não se ajusta bem a grandes quantidades de configuração. E uma vez que o usuário final tem controle sobre os dados, eles devem ser armazenados em um formato onde qualquer violação seja detectável (ou seja, com uma assinatura criptográfica) e não deve conter nenhuma informação que seja comprometida por sua divulgação (ou seja, criptografada de forma reversível).

Por outro lado, isso tem muitos benefícios para armazenar informações confidenciais de propriedade do usuário final - se você não as estiver armazenando no servidor, elas não poderão ser roubadas de lá.

Diretórios de rede Outro lugar interessante para armazenar informações de configuração é no DNS / LDAP. Isso funcionará para um pequeno número de pequenos pedaços de informação - mas você não precisa se ater à 1ª forma normal - considere, por exemplo, SPF .

A infra-estrutura suporta armazenamento em cache, replicação e distribuição. Por isso, funciona bem para grandes infraestruturas.

Sistemas de controle de versão

A configuração, como o código, deve ser gerenciada e controlada por versão - portanto, obter a configuração diretamente do seu sistema VC é uma solução viável. Mas geralmente isso vem com uma sobrecarga de desempenho significativa, portanto, o cache pode ser aconselhável.

symcbean
fonte
6

Bem - seria meio difícil armazenar seus dados de configuração de banco de dados em um banco de dados - você não acha?

Mas, realmente, esta é uma questão fortemente opinativa porque qualquer estilo funciona realmente e é tudo uma questão de preferência. Pessoalmente, prefiro uma variável de configuração em vez de constantes - geralmente porque não gosto das coisas no espaço global, a menos que seja necessário. Nenhuma das funções em minha base de código deve ser capaz de acessar facilmente minha senha de banco de dados (exceto minha lógica de conexão de banco de dados) - então eu a usaria lá e provavelmente a destruiria.

Edit : para responder ao seu comentário - nenhum dos mecanismos de análise seria o mais rápido (ini, json, etc) - mas eles também não são as partes do seu aplicativo que você realmente precisa se concentrar na otimização, já que a diferença de velocidade seria ser insignificante em arquivos tão pequenos.

Colin M
fonte
2

Define tornará a constante disponível em toda a sua classe sem a necessidade de usar global, enquanto a variável requer global na classe, eu usaria DEFINE. mas, novamente, se os parâmetros db devem mudar durante a execução do programa, você pode querer ficar com a variável.

phpalix
fonte
qual é a maneira mais rápida de executar o php? const ou var?
Ali Akbar Azizi
1
@CooPer Definir constantes é significativamente mais lento do que definir variáveis. Mas usá-los é um pouco mais rápido. Visto que eles serão usados ​​em um só lugar, as variáveis ​​em geral ofereceriam um desempenho superior.
Colin M
"Significativamente" é uma palavra um pouco pesada para isso, se você está olhando dessa forma, talvez você deva contatar o pessoal de desenvolvimento do php e pedir a eles que removam o suporte constante!
phpalix
@phpalix Definir uma constante pode ser de 10 a 20x mais lento do que definir uma variável com o mesmo valor. Eu diria que isso é significativo. No entanto, se você usar a constante intensamente em todo o seu aplicativo, pode muito bem valer a pena. Mas criar uma constante para usá-la uma vez não é aconselhável.
Colin M
2

Se você acha que usará mais de 1 db por qualquer motivo, use a variável porque você poderá alterar um parâmetro para mudar para um banco de dados totalmente diferente. Ou seja, para teste, backup automático, etc.

trigun0x2
fonte
2

Você pode criar uma classe de configuração com propriedades estáticas

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

então você pode simplesmente usá-lo:

Config::$dbHost  

Às vezes, em meus projetos, eu uso um padrão de design SINGLETON para acessar os dados de configuração. É muito confortável de usar.

Por quê?

Por exemplo, você tem 2 fontes de dados em seu projeto. E você pode escolher a bruxa deles está habilitada.

  • mysql
  • json

Em algum lugar no arquivo de configuração que você escolher:

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

Quando você muda a fonte, o aplicativo inteiro deve mudar para uma nova fonte de dados, funciona bem e não precisa mudar no código.

Exemplo:

Config:

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

Classe Singleton:

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;
    }
}

... e em algum lugar em seu código (por exemplo, em alguma classe de serviço):

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

Podemos obter um objeto AppConfig de qualquer lugar no sistema e sempre obter a mesma cópia (graças à estática). O método init () da classe é chamado de In no construtor, o que garante apenas uma execução. Init () body checks O valor de config $ dataSource, e cria um novo objeto de classe de fonte de dados específica. Agora nosso script pode obter o objeto e operar nele, sem saber até mesmo qual implementação específica realmente existe.

Sebastian Skurnóg
fonte
1

Normalmente acabo criando um único arquivo conn.php que contém minhas conexões de banco de dados. Em seguida, incluo esse arquivo em todos os arquivos que requerem consultas de banco de dados.

Mihir Chhatre
fonte
1
Eu sei disso, mas como você salva seu arquivo de banco de dados, com variável ou const? e porque?
Ali Akbar Azizi
0

Aqui está o meu caminho.

<?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";

?>

Qualquer duvida comente

Alok Rajasukumaran
fonte
3
Olá! Você poderia colocar um exemplo de uso? Obrigado
Nick