Dependency Injection решит все ваши проблемы. Суть в том что бы небыло глобального объекта содержащего все настройки, доступного из любой точки приложения. Вы должны давать параметры при инициализации. Тогда это сделает ваш код более гибким. Что бы не париться с этим, можно делегировать обязанности по созданию этих ваших компонентов отдельному компоненту. Он будет держать все все все параметры, но сами компоненты к ним доступ иметь не будут, только то что им дали в конструктор.
Вот вам простенький примерчик, но лучше взять чего готовое. А лучше вообще взять Silex или чего такого.
class Container
{
private $definitions;
private $settings;
private $instances;
public function __construct(array $settings = array())
{
$this->instances = [];
$this->definitions = [];
$this->settings = $settings;
}
public function get($name) {
if (!isset($this->instances[$name])){
if (!isset($this->definitions[$name])) {
throw new \InvalidArgumentException(sprintf('service "%s" not defined', $name));
}
$this->instance[$name] = $this->definitions[$name]($this);
}
return $this->instance[$name];
}
public function getParam($name) {
return array_key_exists($this->settings, $name) ?
$this->settings[$name] : null;
}
public function setParam($name, $value) {
$this->settings[$name] = $value;
}
public function setDefinition($name, $definition) {
if (!is_callable($definition)) {
throw new \InvalidArgumentException('Service definition should be callable');
}
$this->definitions[$name] = $definition;
}
}
Использование:
// params.php
return [
'db.hostname' => 'localhost',
'db.username' => 'user',
'db.password' => 'pass'
];
// services.php
$container = new Container(require __DIR__ . '/params.php');
$container->setDefinition('db', function (Container $c) {
return new DB($c->getParam('db.hostname'), $c->getParam('db.username'), $c->getParam('db.password'));
});
return $container;
//app.php
$container = require __DIR__ . '/container.php';
$db = $container->get('db');
$db->query('...');