作为控制器的Laravel服务 - 使用多个控制器

时间:2017-04-14 23:59:10

标签: php laravel laravel-5

我是巴西的开发者,所以......对不起我的英语有限的英语。

嗯,实际上我的问题更多是一个常规问题,因为到目前为止我还没有使用Laravel的服务(到目前为止,我的应用程序非常简单)。

在提出这个问题之前,我已经读到了这个问题,但在这个具体情况下没有任何帮助。我会尝试以客观的方式描述。

之前,只是评论:我知道在这些例子中只使用控制器的错误。提问真的是关于那个错误。

嗯,实际结构是:

abstract class CRUDController extends Controller {

    protected function __construct($data, $validatorData) {
        // store the data in a attribute
        // create with Validator facade the validation and store too
    }

    abstract protected function createRecord();

    protected function create() {
        try {
            // do the validation and return an Response instance with error messages
            // if the data is ok, store in the database with models
            // (here's where the magic takes place) in that store!
            // to do that, calls the method createRecord (which is abstract)
            $this->createRecord();
            // return a success message in an Response instance
        }
        catch(\Exception $e) {
            // return an Response instance with error messages
        }
    }

}

class UserController extends CRUDController {

    public function __construct($data) {
        parent::__construct($data, [
            'rules' => [
                 // specific user code here
             ],
            'messages' => [
                 // specific user code here
             ],
            'customAttributes' => [
                 // specific user code here
             ]
        ]);
    }

    protected function createRecord() {
        $user = new UserModel();
        // store values here...
        $user->save();
        return $user;
    }

}

// here's the route to consider in that example
Route::post('/user', 'WebsiteController@register');

class WebsiteController extends Controller {

    private $request;

    public function __construct(Request $request) {
        $this->request = $request;
    }

    public function register() {
        $user = new UserController();
        $user->create($this->request);
        // here's the problem: controller working with another controller
    }

}

class UserAPIController extends Controller {
    // use here the UserController too
}

以及以同样的方式扩展CRUDController的许多其他类......

我想要什么

我想创建一个控制器(在这里称为CRUDController)来重用模式所说的方法(创建,读取,更新和删除)。 为了真正客观,我将使用create方法作为示例。 有了上面的代码,它的目的似乎很明确吗?我想是这样的...我的所有控制器都具有相同且可重用的验证代码。这就是事情。 除此之外,我希望我的网站路由调用另一个控制器(UserController)来存储新用户......但同样地,我将以相同的方式创建一个使用相同控制器的API(带有验证等) )。这就是CRUDController中响应的目的(我将在WebSiteController中读取它们以解决要做的事情,比如显示视图,另一方面使用API​​我会基本上返回响应

我的真正问题

公约和模式。这里打破了MVC模式。控制器调用另一个控制器是错误的,我知道。 我想知道我应该用什么东西!服务?是对的吗?我看到很多(真的)服务的例子,但没有那样,使用模型和重用代码等。我从不使用服务,但我知道如何使用,但我不知道它是否是对这些案件的权利。

我真的希望有人可以在这里提供帮助,并再次对与英语的错误表示遗憾。非常感谢。

2 个答案:

答案 0 :(得分:1)

您将CRUD控制器称为控制器,但它不像MVC控制器那样。它充其量只是一个帮助类。你总是可以这样做:

abstract class CRUDManager {        
    //As you had the CRUDController
}

class UserManager extends CRUDManager {
     //As you had the UserController
}

在AppServiceProvider中:

public function boot() {
     $app->bind(UserManager::class, function ($app) {
           return new UserManager(request()->all()); //I guess that's what you need.
     });
}

无论何时需要使用它,您都可以:

public function register(UserManager $user) {
    $user->create();
}

现在有一点需要指出。在构造函数中初始化请求不是一个好主意。您应该在控制器方法中使用依赖注入。我甚至不知道在构建控制器时请求是否可用(我知道会话不是)。我之所以这么说是因为中间件在构造控制器之后运行,因此在调用控制器方法时可以修改请求。

另一个注意事项:如果您因为需要使用某些控制器方法而执行原始解决方案,那么您可以使用相应的特征(因为控制器本身并没有真正的方法)。我猜测像ValidatesRequests这样的特质是use所需要的。

答案 1 :(得分:0)

我会回答我自己的问题。我使用一种名为Repository Pattern的模式来解决问题(或者我尝试使用,因为它是第一次使用这种模式:也许我不会在每个步骤中以正确的方式使用它。)

文件结构

Controllers
  UserController.php
Models
  UserModel.php
Providers
  UserRepositoryServiceProvider.php
Repositories
 RepositoryInterface.php
 Repository.php
 User
   UserRepositoryInterface.php
   UserRepository.php
Traits
  InternalResponse.php

通过这种结构,我在我的问题中做了我想做的事,而不需要只使用控制器。

我创建了一个名为InternalResponse的特征。该特性包含一些接收事务的方法,验证是否是这种情况然后返回响应(在我的逻辑中称为“内部”,因为控制器将读取并可能在最终返回之前更改响应)。

Repository类,它是抽象的(因为另一个类必须扩展它才有意义使用。在这种情况下,UserRepository类将扩展...),使用提到的Trait。

嗯,考虑到这一点,我们可以知道UserController使用UserRepositoryInterface,它提供了一个UserRepository对象:因为UserRepositoryServiceProvider在该接口上注册了它。

我认为没有必要在这里编写代码来解释,因为问题是关于一个模式,这些词很好地解释了问题(在问题中)和这个答案的解决方案。

我在这里写一个结论,我的意思是,文件结构带有注释来解释一下,结束答案。

结论:带注释的文件结构

Controllers
  UserController.php
    // the controller uses dependency injection and call methods of 
    // UserRepository, read and changes the Response receveid to finally
    // create the final Response, like returning a view or the response
    // itself (in the case it's an API controller)
Models
  UserModel.php
    // an normal model
Providers
  UserRepositoryServiceProvider.php
    // register the UserRepositoryInterface to
    // return a UserRepository object
Repositories
 RepositoryInterface.php
   // the main interface for the Repository
 Repository.php
   // the main repository. It's an abstract class.
   // All the others repositories must extend that class, because
   // there's no reason to use a class Repository without an Model
   // to access the database... That class share methods like create,
   // read, update and delete, and the methods validate and transaction
   // too because uses the trait InternalResponse.
 User
   UserRepositoryInterface.php
     // the interface for UserRepository class
   UserRepository.php
     // that class extend Repository and uses the UserModel
Traits
  InternalResponse.php
    // trait with methods like validate and transaction. the method
    // validate, read and validate the data receveid for the methods
    // create and update. and all the CRUD methods uses the method
    // transaction to perform the data to the database and return a
    // response of that action.

这就是我之前所说的,就像我之前说过的那样,我不知道在参考存储库模式时它是否正确百分之百。

我希望这也可以帮助别人。 谢谢大家。