我是一个关于依赖注入的初学者,我在我的PHP 5.5.9(在Apache2和MySql下)项目中使用以下工具:
- PHP-DI:"4.2。* @dev"——(http://php-di.org)来管理DI (C);
- PHPActiveRecord: "dev-master" - (https://github.com/jpfuentes2/php-activerecord) as ORM;
我所有的类都是由composer自动加载的。
我已经对PHP-DI定义有了一些了解,通过阅读它的文档和运行它的例子有关自动装配,注释和配置,我已经把它与我自己的类一起工作,但现在我被困在如何设置供应商库,如PHPActiveRecord。
通常要使用PHPActiveRecord,你所需要的只是像这样定义连接设置:
$cfg = ActiveRecordConfig::instance();
$cfg->set_model_directory('/path/to/your/model_directory');
$cfg->set_connections(
['development' => 'mysql://username:password@localhost/database_name']
);
或:
ActiveRecordConfig::initialize(function($cfg)
{
$cfg->set_model_directory('/path/to/your/model_directory');
$cfg->set_connections(['development' =>
'mysql://username:password@localhost/database_name']);
});
最后,你的模型应该扩展ActiveRecordModel,你就可以开始了。
现在我正试图注入我的ActiveRecord模型到控制器通过使用注释,如PHP-DI的文档建议:
<?php
namespace Controller;
use ModelUser;
class TestController
{
/**
* @Inject
* @var User
*/
protected $user;
public function index()
{
echo $this->user->retrieveStatus();
}
}
这里我得到了错误:
Fatal error: Uncaught exception 'ActiveRecordDatabaseException' with message 'Empty connection string' in /home/ubuntu/workspace/vendor/php-activerecord/php-activerecord/lib/Connection.php:105
Stack trace:
#0 /home/ubuntu/workspace/vendor/php-activerecord/php-activerecord/lib/ConnectionManager.php(33): ActiveRecordConnection::instance(NULL)
#1 /home/ubuntu/workspace/vendor/php-activerecord/php-activerecord/lib/Table.php(117): ActiveRecordConnectionManager::get_connection(NULL)
#2 /home/ubuntu/workspace/vendor/php-activerecord/php-activerecord/lib/Table.php(93): ActiveRecordTable->reestablish_connection(false)
#3 /home/ubuntu/workspace/vendor/php-activerecord/php-activerecord/lib/Table.php(74): ActiveRecordTable->__construct('ModelUser')
#4 /home/ubuntu/workspace/vendor/php-activerecord/php-activerecord/lib/Model.php(749): ActiveRecordTable::load('ModelUser')
#5 /home/ubuntu/workspace/vendor/php-activerecord/php-activerecord/lib/Model.php(262): ActiveRecordModel::table()
#6 [internal function]: ActiveRecordModel- in /home/ubuntu/workspace/vendor/mnapoli/php-di/src/DI/Definition/Resolver/ClassDefinitionResolver.php on line 276
似乎没有提供给ActiveRecord的字符串连接。
我只是相信我需要一个适当的文件配置设置(我认为DIfactory)来返回一个基于上述连接定义的ActiveRecordConfig实例。
另一点让我担心的是,PHPActiveRecord有相当数量的单例和静态函数到它的API,据我所知,它被认为是一种反模式,由于有点紧耦合问题,它似乎没有好的DI的管理一旦在这种情况下,没有定义良好的"注入点",如构造函数和/或setter注入。
如果你认为我对我的问题不够清楚,问我,我可以提供更多的信息。
恐怕没有一个好的解决办法。正如你所说,PHPActiveRecord是一个建立在单例和静态方法上的库,它不能很好地与依赖注入混合。
但主要是,在你的例子中,你试图注入一个模型对象。那是(通常)你不应该做的事。你应该注入配置值或"服务"或任何在整个应用程序中共享的对象,但不是模型。
根据查询(例如ID)从数据库中获取模型。因此,在控制器中注入用户是没有意义的,因为根据定义,有许多用户(有一个完整的表)。 通常做的是注入提供检索模型的方法的对象/服务。根据库的不同,这些对象有时被称为"repository"。它是这样的- 你在控制器中注入UserRepository(或Database对象,或EntityManager,或任何它是)
- 然后使用该对象来获取控制器 中的任何用户
技术上,你在这里得到的问题是(我认为)PHP-DI试图创建一个新的用户实例(使用new
)和PHPActiveRecord试图自动连接到数据库。因为没有配置数据库(我猜),PHPActiveRecord失败。
总之,该怎么做?
- 保持PHPActiveRecord的初始化不在PHP-DI中,因为它需要在每个请求中执行
- 通过PHPActiveRecord的方式创建/获取/…模型,即静态方法。PHP-DI帮不上忙
如果你想转储PHPActiveRecord,也许看看Doctrine(这更复杂)或Propel(这应该更接近PHPActiveRecord做什么)。