当前位置: 动力学知识库 > 问答 > 编程问答 >

activerecord - How to set PHP-DI definition to PHPActiveRecord Connection?

问题描述:

I'm a beginner about Dependency Injection and I'm using the following tools into my PHP 5.5.9 (under Apache2 and MySql) project:

  • PHP-DI: "4.2.*@dev" - (http://php-di.org) to manage DI(C);
  • PHPActiveRecord: "dev-master" - (https://github.com/jpfuentes2/php-activerecord) as ORM;

All my classes use to be autoloaded by composer.

I already got some insight about PHP-DI Definitions by reading it's docs and running it's examples related to autowiring , annotations and config and I've been put it to work with my own classes, but now I'm stuck about how to set vendor libraries such as PHPActiveRecord.

Usually to use PHPActiveRecord all you need is to define connections settings like this:

$cfg = ActiveRecord\Config::instance();

$cfg->set_model_directory('/path/to/your/model_directory');

$cfg->set_connections(

['development' => 'mysql://username:[email protected]/database_name']

);

Or this:

ActiveRecord\Config::initialize(function($cfg)

{

$cfg->set_model_directory('/path/to/your/model_directory');

$cfg->set_connections(['development' =>

'mysql://username:[email protected]/database_name']);

});

Finally your models should extends ActiveRecord\Model and you're ready to go.

For now I'm trying to inject my ActiveRecord models into controllers by using annotations such as PHP-DI's documentation suggests:

<?php

namespace Controller;

use Model\User;

class TestController

{

/**

* @Inject

* @var User

*/

protected $user;

public function index()

{

echo $this->user->retrieveStatus();

}

}

Here I got the error:

Fatal error: Uncaught exception 'ActiveRecord\DatabaseException' 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): ActiveRecord\Connection::instance(NULL)

#1 /home/ubuntu/workspace/vendor/php-activerecord/php-activerecord/lib/Table.php(117): ActiveRecord\ConnectionManager::get_connection(NULL)

#2 /home/ubuntu/workspace/vendor/php-activerecord/php-activerecord/lib/Table.php(93): ActiveRecord\Table->reestablish_connection(false)

#3 /home/ubuntu/workspace/vendor/php-activerecord/php-activerecord/lib/Table.php(74): ActiveRecord\Table->__construct('Model\User')

#4 /home/ubuntu/workspace/vendor/php-activerecord/php-activerecord/lib/Model.php(749): ActiveRecord\Table::load('Model\User')

#5 /home/ubuntu/workspace/vendor/php-activerecord/php-activerecord/lib/Model.php(262): ActiveRecord\Model::table()

#6 [internal function]: ActiveRecord\Model- in /home/ubuntu/workspace/vendor/mnapoli/php-di/src/DI/Definition/Resolver/ClassDefinitionResolver.php on line 276

As it seems, no string connection provided to ActiveRecord.

I just believe that I need a proper File Configuration setting (DI\factory I think) to return a ActiveRecord\Config instance based on the connection definitions above.

Another point the bring me worries is that PHPActiveRecord have a considerable amount of Singletons and statics functions into it's API and as far as I know it's considered an anti-pattern due to kinda tight coupling issues and it seems no good to DI's management once in this cases there's no well defined "injection points" such as constructor and/or setter injections.

If you think I'm not clear enough about my problem, aske me for and I can provide more info.

网友答案:

I'm afraid there isn't a good solution for your problem. As you have said, PHPActiveRecord is a library built on singletons and static methods, that doesn't mix well with dependency injection.

But mainly, in your example, you are trying to inject a model object. That's (usually) something you should never do. You should inject configuration values or "services" or whatever objects are shared throughout the application, but not models.

Models are fetched from the database depending on queries (for example an ID). So it doesn't make sense to inject a user in the controller since by definition there are many users (there's a whole table of them).

What is usually done is inject the object/service that provides a way to retrieve the models. Those objects are sometimes called "repository" depending on the library. So it goes like this:

  • you inject the UserRepository in the controller (or the Database object, or the EntityManager, or whatever it is)
  • you then use that object to fetch whichever user you want inside the controller

Technically, the problem you get here is (I think) PHP-DI trying to create a new User instance (using new) and PHPActiveRecord trying to connect to the database automatically. Since nothing was configured for the database (I guess), PHPActiveRecord fails.

So in short, what to do?

  • keep the initialization of PHPActiveRecord out of PHP-DI since it needs to be executed on each request
  • create/fetch/… models through PHPActiveRecord's way, i.e. static methods. PHP-DI can't help there

If you want to dump PHPActiveRecord, maybe have a look at Doctrine (which is more complex) or Propel (which should be closer to what PHPActiveRecord do).

分享给朋友:
您可能感兴趣的文章:
随机阅读: