我将举一个基本的例子,假设我有3个班级 - Config
,Database
和User
。 User
需要Database
和Database
需要Config
,但User
可能还需要Config
。所有类只需要一个实例,因为我只需要加载一次配置文件,只需连接一次数据库并检查用户是否已登录并只获取一次数据。现在,从每个类中告诉它需要哪些类并让它们自动加载的最佳方法是什么?或者这是不好的做法而我只是在偷懒?我尝试制作所有课程的单身人士,并在每个课程中像这样访问它们:
user.php的
$this->db = Module::get('Database');
但是我必须创建一个自定义的__construct()
方法,并且每当我第一次创建一个类的新实例时就会运行它,这感觉很糟糕。我做了一些研究,并认为singletons
并不是一个好的做法,而dependency-injection
将是一个更好的解决方案,但我不知道如何用dependency-injection
实现这一目标。所以我想知道,这是一个好主意还是我应该重新考虑一下我希望一切都能发挥作用?
答案 0 :(得分:1)
用户需要数据库和数据库需要配置,但用户可能还需要配置
听起来你需要依赖注入。现有的包可以做到这一点,但如果您自己制作它,您可以创建一个名为DIContainer的类,其目的只是设置和获取对象实例,然后将此类传递给其他可能的类。需要什么。
class DIContainer {
protected $_objects = array();
public function __set( $name='', $instance=null )
{
if( !empty( $name ) && is_object( $instance ) )
{
$this->_objects[ $name ] = $instance;
}
}
public function __get( $name='' )
{
if( !empty( $name ) && array_key_exists( $name, $this->_objects ) )
{
return $this->_objects[ $name ];
}
throw new Exception( 'Object not found ('.$name.').' );
}
}
然后只需实例化并设置您的公共类并将它们添加到DIContainer:
// setup config
$config = new Config();
$config->loadFile( './conf.php' );
// setup db
$database = new Database( $config );
$database->connect();
// setup session
$session = new Session( $config );
$session->start();
// save dependencies
$container = new DIContainer;
$container->config = $config;
$container->database = $database;
$container->session = $session;
// later when you start a new User class
$user = new User( $container );
现在用户类可以得到它需要的东西,只需设置构造函数方法来处理DIContainer:
class User {
protected $container = null;
public function __construct( DIContainer $container )
{
$this->container = $container;
}
public function getRows()
{
$rows = $this->container->database->getRows( '...' );
}
}
答案 1 :(得分:0)
你正在寻找在php中自动加载。已经在SO上讨论了这个主题,并且有一些很好的解释here。
简而言之,在文件的开头(声明命名空间之后),告诉php你的类依赖什么。
namespace Entity;
use ORM\Database;
use Config;
//...
$d = new Database();
Config::set('a', 'b');
在使用外部库并在代码中管理自动加载而不重新发明轮子时,您可能还想使用Composer来获取DI。
这是Composer文档关于自动加载的内容:
对于指定自动加载信息的库,Composer会生成一个 vendor / autoload.php文件。你可以简单地包含这个文件 将免费自动加载。
require __DIR__ . '/vendor/autoload.php';
这使得使用第三方代码变得非常容易。例如:如果 你的项目取决于Monolog,你可以开始使用来自的类 它,它们将被自动加载。
$log = new Monolog\Logger('name'); $log->pushHandler(new Monolog\Handler\StreamHandler('app.log', Monolog\Logger::WARNING)); $log->addWarning('Foo');
您甚至可以通过添加自动加载功能将自己的代码添加到自动加载器中 field to composer.json。
{ "autoload": { "psr-4": {"Acme\\": "src/"} } }