首页 > 解决方案 > Laravel 服务容器:父类的上下文绑定,适用于所有子类

问题描述

我试图基于需要它的存储库来实现DatabaseConnectionClass实现的上下文绑定。

这是必需的,因此从不同数据库获取数据的存储库可以使用相关连接来执行此操作。

我的数据库连接界面是这样的

/**
 * Interface DatabaseConnectionInterface
 *
 * @package App\Database\Connection
 */
interface DatabaseConnectionInterface {

    /**
     * Get the database connection
     *
     * @return Connection
     */
    public function getConnection(): Connection;

}

我的基础存储库

/**
 * Class MiRepository
 *
 * Base repository centralising connection injection
 *
 * @package App\Repositories\Mi
 */
class MiRepository {

    /**
     * The connection to the database
     *
     * @var DatabaseConnectionInterface
     */
    protected $connection;

    /**
     * MiRepository constructor.
     *
     * @param DatabaseConnectionInterface $connection
     */
    public function __construct(DatabaseConnectionInterface $connection){
        $this->connection = $connection->getConnection();
    }

}

存储库的扩展

/**
 * Class SchemeRepository
 *
 * @package App\Mi\Repositories
 */
class SchemeRepository extends MiRepository {

    /**
     * Find and return all stored SchemeValidator
     *
     * @return Scheme[]|NULL
     */
    public function findAll(): ?array {
        $results = $this->connection->select('EXEC [webapi_get_products_schemes]');

        if(empty($results)){
            return NULL;
        }

        $schemes = array();
        foreach($results as $result){
            $schemes[] = Scheme::create($result->SCHEMENAME);
        }

        return $schemes;
    }

}

服务容器绑定

/**
 * Class MiServiceProvider
 *
 * @package App\Providers
 */
class MiServiceProvider extends ServiceProvider
{

    /**
     * Register services.
     *
     * @return void
     */
    public function register()
    {
        $this->app->when(MiRepository::class)
            ->needs(DatabaseConnectionInterface::class)
            ->give(function(){
                return new MiDatabaseConnection();
            });
    }
}

问题是当我尝试注入基本存储库的扩展时,我认为没有触发上下文绑定并且我得到了异常

Target [App\\Common\\Database\\Connection\\DatabaseConnectionInterface] is not instantiable ...

以前有没有人遇到过这个问题,并且知道在父类上使用上下文绑定并为所有子类触发它的方法?

我知道这可以通过为所有子类实现上下文绑定定义来实现,但这似乎有点笨拙。

提前致谢!

标签: phplaravel

解决方案


据我所知,因为 PHP 和依赖注入作为一个整体依赖于反射来了解构造函数正在寻找的类,所以它基本上是在进行字符串模式匹配以找到正确的绑定。因为您还没有为扩展类定义绑定字符串,所以它找不到相关的绑定函数。所以我怀疑你想做的事情不会奏效。

避免过多重复代码的解决方法可能是:

public function register()
{
    foreach($repo in ['Foo', 'Bar', 'Baz']) {

        $this->app->when($repo . Repository::class)
            ->needs(DatabaseConnectionInterface::class)
            ->give(function () use ($repo) {
                $theClass = $repo . 'DatabaseConnection';
                return new $theClass();
            });
    }
}

推荐阅读