DI,ServiceProvider,抽象父级和Laravel 5.3

时间:2016-11-11 19:31:28

标签: php laravel service dependency-injection

我有一些问题,并且很少误解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 = "App\Models\User";

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的抽象Repository构造中将$model作为DI传递。我不知道。我该怎么办?

我这样用:

class UserController extends Controller {

private $repository;

public function __construct(UserRepository $repository) {
    $this->repository = $repository;
} }

1 个答案:

答案 0 :(得分:1)

因为ModelParser需要$model作为参数,所以它有点复杂。并且因为$model可能会因其存储库而异,如果我们尝试使用Laravel service container binding来解决它,则会太复杂。

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

namespace App\Models;

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 App\Models;

use App\Models\ModelParser;
use App\Models\RepositoryInterface;

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 App\Models;

use App\Models\ModelParser;
use App\Models\UserRepositoryInterface;

class UserRepository extends Repository implements UserRepositoryInterface
{
    protected $model_name = "App\Models\User";

    public function __construct(ModelParser $parser)
    {
        parent::__construct($parser);
    }
}

实际上,如果您在课程实例化过程中没有计划传递其他参数或执行其他操作,则只需从__construct()中移除UserRepository方法并依赖其父级( abstract Repository)。

希望这有帮助!