I want to make an API first application in Laravel. I don't know what is the best approach to do this, I will explain what I am trying to do, but please feel free to give answers how to do this in a different way.

I don't want all my frontend to be written in javascript and parse the JSON output of the API with angular.js or something similar. I want my Laravel application to produce the HTML views. I am trying to go down the road of having two controllers one on for the API and one for the web. For the show User action my routes.php looks like this:

# the web controller
Route::controller('user', 'WebUserController');

# the api controller 
Route::group(array('prefix' => 'api'), function() {
    Route::resource('user', 'UserController');
});

所以/user会把我带到WebUserController/api/user会把我带到UserController.现在我想把我所有的逻辑放在APIUserController中,并从WebUserController调用它的操作.以下是这两个项目的代码:

class UserController extends BaseController 
{
    public function show($id)
    {
        $user = User::find($id);
        return Response::json(array('success'=>true,'user'=>$user->toArray()));
    }
}

class WebUserController extends UserController 
{
    public function getView($id) 
    {
         # call the show method of the API's User Controller
         $response =  $this->show($id);
         return View::make('user.view')->with('data', $response->getData());
    }
}

In the WebUserController I am able to get the json content of the response with getData(), but I am not able to get the headers and status code (they are protected properties of Illuminate\Http\JsonResponse).

我认为我的方法可能不是最好的,所以我愿意接受如何制作这个应用的建议.

EDIT: The question how to get the headers and status of the response has been answered by Drew Lewis, but I still think that there might be a better way how to design this

推荐答案

You should utilize the Repository / Gateway design pattern: please see the answers here.

For example, when dealing with the User model, first create a User Repository. The only responsibility of the user repository is to communicate with the database (performing CRUD operations). This User Repository extends a common base repository and implements an interface containing all methods you require:

class EloquentUserRepository extends BaseRepository implements UserRepository
{
    public function __construct(User $user) {
        $this->user = $user;
    }


    public function all() {
        return $this->user->all();
    }

    public function get($id){}

    public function create(array $data){}

    public function update(array $data){}

    public function delete($id){}

    // Any other methods you need go here (getRecent, deleteWhere, etc)

}

Then, create a service provider, which binds your user repository interface to your eloquent user repository. Whenever you require the user repository (by resolving it through the IoC container or injecting the dependency in the constructor), Laravel automatically gives you an instance of the Eloquent user repository you just created. This is so that, if you change ORMs to something other than eloquent, you can simply change this service provider and no other changes to your codebase are required:

use Illuminate\Support\ServiceProvider;

class RepositoryServiceProvider extends ServiceProvider {

    public function register() {
        $this->app->bind(
            'lib\Repositories\UserRepository',        // Assuming you used these
            'lib\Repositories\EloquentUserRepository' // namespaces
        );
    }

}

接下来,创建一个User Gateway,它的目的是与任意数量的存储库对话,并执行应用程序的任何业务逻辑:

use lib\Repositories\UserRepository;

class UserGateway {

    protected $userRepository;

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

        public function createUser(array $input)
        {
            // perform any sort of validation first
            return $this->userRepository->create($input);
        }

}

最后,创建用户web控制器.此控制器与您的用户网关对话:

class UserController extends BaseController 
{
    public function __construct(UserGatway $userGateway)
    {
        $this->userGateway = $userGateway;
    }

    public function create()
    {
        $user = $this->userGateway->createUser(Input::all());

    }
}

By structuring the design of your application in this way, you get several benefits: you achieve a very clear separation of concerns, since your application will be adhering to the Single Responsibility Principle (by separating your business logic from your database logic) . This enables you to perform unit and integration testing in a much easier manner, makes your controllers as slim as possible, as well as allowing you to easily swap out Eloquent for any other database if you desire in the future.

例如,如果从Elount更改为Mongo,则只需要更改服务Provider 绑定,以及创建一个实现UserRepository接口的MongouseRepository.这是因为存储库是与数据库对话的only件事——它不知道其他任何事情.因此,新的MongouseRepository可能看起来像:

class MongoUserRepository extends BaseRepository implements UserRepository
{
    public function __construct(MongoUser $user) {
        $this->user = $user;
    }


    public function all() {
        // Retrieve all users from the mongo db
    }

    ...

}

And the service provider will now bind the UserRepository interface to the new MongoUserRepository:

 $this->app->bind(
        'lib\Repositories\UserRepository',       
        'lib\Repositories\MongoUserRepository'
);

Throughout all your gateways you have been referencing the UserRepository, so by making this change you're essentially telling Laravel to use the new MongoUserRepository instead of the older Eloquent one. No other changes are required.

Laravel相关问答推荐

Uncaught ReferenceError:未定义require[Shopify PHP React Browser问题]

Laravel:通过数据透视表数据限制多对多Eager 加载

Laravel 9 中使用 WHERE 子句的列的 SUM

Laravel where 子句只返回一个数据库条目

Laravel 5 - 更改模型文件位置

在laravel中将数据插入数据透视表

安卓 retrofit |发布自定义对象(将 json 发送到服务器)

插入重复键时,laravel eloquent 忽略错误

如何监控 Laravel 队列是否正在运行?

Laravel 5 - 仅在特定页面/控制器(页面特定assets资源)上添加样式表

如何使用 laravel eloquent 获得select count(*) group by

调用未定义的函数 mb_strimwidth

Laravel / Eloquent内存泄漏重复检索相同的记录

Laravel 获取文件内容

如何以及在哪里可以使用 laravel 存储图像?

如何在 Eloquent Orm 中实现自引用(parent_id)模型

如何在 laravel eloquent 中保存布尔值

Laravel 更新后用户模型错误(用户类包含 3 个抽象方法)

Laravel Eager加载与显式连接

laravel中的动态网址?