DI、ServiceProvider、抽象父节点和Laravel 5.3



我有一些问题和小误解Laravel SP (ServiceProvider)。我有抽象类Repository和她的接口:

abstract class Repository implements RepositoryInterface {
private $model;
private $parser;
public function __construct() {
    $this->model = new $this->model_name();
} }

interface RepositoryInterface {
public function create(array $attributes);
public function update($id, array $attributes);
public function delete($id);
public function all();
public function find($id);
public function filter(array $parameters, $query=null);
public function query(array $parameters, $query=null); }

和一些子UserRepository,例如:

class UserRepository extends Repository implements UserRepositoryInterface {
protected $model_name = "AppModelsUser";
public function __construct() {
    parent::__construct();
}
public function activation($user_id) {
    return "user";
}
public function deactivation($user_id) {
    return "user";
} }

和简单ModelParser类:

class ModelParser {
protected $parameters;
protected $model;
public function __construct($model) {
    $this->model = $model;
} }

这个工作很好,但我将传递ModelParser作为DI在我的抽象Repository与参数$model的结构。我不知道。我该怎么做呢?

我这样使用它:

class UserController extends Controller {
private $repository;
public function __construct(UserRepository $repository) {
    $this->repository = $repository;
} }

嗯,这有点复杂,因为你的ModelParser需要$model作为它的参数。因为这个$model可能会根据它的存储库而变化,如果我们试图使用Laravel服务容器绑定来解决它,那就太复杂了。

有一个更简单的方法,我们可以让ModelParser类的构造函数接收一个可选的$model参数。然后我们可以添加一个额外的方法来设置这个$model属性,如下所示:

namespace AppModels;
class ModelParser
{
    protected $parameters;
    protected $model;
    // Make $model parameter optional by providing default value.
    public function __construct($model = null) {
        $this->model = $model;
    }
    // Add setter method for $model.
    public function setModel($model)
    {
        $this->model = $model;
        return $this;
    }
}

现在您可以将ModelParser注入到抽象Repository类中。Laravel将很容易地解析这个ModelParser参数

namespace AppModels;
use AppModelsModelParser;
use AppModelsRepositoryInterface;
abstract class Repository implements RepositoryInterface
{
    private $model;
    private $parser;
    // Pass ModelParser instance to your constructor!
    public function __construct(ModelParser $parser)
    {
        $this->model = new $this->model_name();
        // Set the parser's model property.
        $this->parser = $parser->setModel($this->model);
    }
    // Rest of your code.
}

如果你要扩展抽象的Repository类,你仍然需要像这样传递这个ModelParser给构造函数:

namespace AppModels;
use AppModelsModelParser;
use AppModelsUserRepositoryInterface;
class UserRepository extends Repository implements UserRepositoryInterface
{
    protected $model_name = "AppModelsUser";
    public function __construct(ModelParser $parser)
    {
        parent::__construct($parser);
    }
}

实际上,如果您不打算在类实例化期间传递另一个参数或执行其他操作,您可以简单地从UserRepository中删除__construct()方法,并依赖其父方法(抽象Repository)。

希望这有帮助!

最新更新