我使用存储库模式遇到了这个问题。目前我使用一个接口和一个自定义类来实现它,然后在控制器的构造中键入提示,并且由于Laravel,它将自动和递归地解决存储库的依赖关系。
我也在服务提供商中这样做:
$this->app->bind(path/to/repoInterface,path/to/implementationClass)
但是,由于我编写这些存储库的方式,为了避免代码重复,我创建了一个抽象类,它具有所有这些存储库的通用方法。这个课程如下:
abstract class CommonRepo{
public function __construct(SomeModelClass model){}
public function commonMethod(){//Code here}
我的存储库具有以下结构:
public class ExampleRepository extends CommonRepo implements ExampleRepositoryI{
public function __construct(){
parent::__construct();
}
}
Laravel不喜欢这样,所以它给出了这个错误:
Argument 1 passed to path/to/repo/CommonRepo::__construct() must be an instance of path/to/model/SomeModelClass, none given, called in...
因此,显然不是解析类CommonRepo的依赖关系,但它确实解决了对普通存储库的依赖。
我想,如果可能的话,使用类型提示(Laravel方式)而不必执行与 new 运算符相关的任何操作
那么,我怎样才能解决该类的依赖关系? PD:使用Laravel 5.2
答案 0 :(得分:2)
父构造函数与普通函数一样被调用,而不会触及依赖项解析器,因此您应该执行以下两种方法之一:
public class ExampleRepository extends CommonRepo implements ExampleRepositoryI
{
public function __construct(SomeModelClass $model){
parent::__construct($model);
}
}
或
public class ExampleRepository extends CommonRepo implements ExampleRepositoryI
{
public function __construct(){
parent::__construct(App::make(SomeModelClass::class));
}
}
答案 1 :(得分:2)
我们假设您已将$i=0;
$linkname = $_POST["recname"][0];
while($linkname != ""){
$linkname = $_POST["recname"][$i];
$linkurl = $_POST["reclink"][$i];
$linktype = $_POST["rectype"][$i];
$linkname = $res->real_escape_string($linkname);
$linkurl = $res->real_escape_string($linkurl);
$linktype = $res->real_escape_string($linktype);
$result299 = mysqli_query($res, "INSERT INTO user_links (linkname,linkurl,linktype,sort) VALUES ('$linkname','$linkurl','$linktype','0')");
$i++;
}
模型类存储在User
中:
app\Models\User.php
然后,为所有存储库类创建基本抽象类:<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
//
}
。您可以在此处放置存储库类的所有常用功能。但是,您可以添加一个名为app\Repositories\BaseRepository.php
的方法,为您的存储库动态创建一个Eloquent模型实例,而不是通过构造函数注入Eloquent实例。
getModel()
现在让我们假设您要为<?php
namespace App\Repositories;
use ReflectionClass;
use RuntimeException;
use Illuminate\Support\Str;
abstract class BaseRepository
{
protected $modelNamespace = 'App\\Models\\';
public function getById($id)
{
return $this->getModel()->find($id);
}
public function getModel()
{
$repositoryClassName = (new ReflectionClass($this))->getShortName();
$modelRepositoryClassName = $this->modelNamespace . Str::replaceLast('Repository', '', $repositoryClassName);
if (! class_exists($modelRepositoryClassName)) {
throw new RuntimeException("Class {$modelRepositoryClassName} does not exists.");
}
return new $modelRepositoryClassName;
}
}
模型创建存储库,此用户的存储库必须实现以下界面:User
app\Repositories\UserRepositoryInterface.php
您创建<?php
namespace App\Repositories;
interface UserRepositoryInterface
{
public function getByEmail($email);
}
类,只需从app\Repositories\UserRepository.php
类扩展它。另外,请不要忘记实施BaseRepository
上定义的所有特定实现。
UserRepositoryInterface
这样您可以将<?php
namespace App\Repositories;
use App\Repositories\BaseRepository;
use App\Repositories\UserRepositoryInterface;
class UserRepository extends BaseRepository implements UserRepositoryInterface
{
public function getByEmail($email)
{
return $this->getModel()->where('email', $email)->firstOrFail();
}
}
绑定到它的实现,如下所示:
UserRepositoryInterface
最后,您可以自由地将$this->app->bind(\App\Repositories\UserRepositoryInterface::class, \App\Repositories\UserRepository::class);
注入控制器的构造函数或方法。您也可以通过服务容器解决此问题:
UserRepositoryInterface
当然,这种方法很有吸引力。应使用关联的模型启动存储库类,因此$userRepository = App::make(App\Repositories\UserRepositoryInterface::class);
$userRepository->getByEmail('john@example.com');
专用于InvoiceRepository.php
模型类。
希望这有帮助!
答案 2 :(得分:0)
这可能会有所帮助。您可以监听对象何时解析并设置属性。
$this->app->resolving(CommonRepo::class, function ($object, $app) {
// Called when container resolves object of any type...
$object->commonObject = app(CommonObject::class);
});