您没有发现任何明确的内容,因为除了“您的理解和项目需求感觉正确的内容”之外,没有什么可谈的。如果您发现自己非常不确定,请随意潜入做任何对您有意义的事情,然后在获得更多经验时重新调整结构。
另外,阅读有关系统架构的书籍,这些会有很大帮助。
仅使用 laravel 作为数据 API 并保持 Vue 与 Laravel 分开是个好主意吗?
我假设您的意思是 SPA?老实说,如果您的应用程序很小,那么我认为这很好。
如果是 SPA,大型应用程序往往难以维护。
阅读:https://medium.com/@NeotericEU/single-page-application-vs-multiple-page-application-2591588efe58
如果你最终使用 Laravel 作为 API 端点,那么请使用它的精简版 Lumen,因为它没有 Blade 和其他一些东西。 Lumen 是精简版以充当 API 端点。
实现 SPA 和 MPA 混合的最佳方法。
根据我尝试构建 4 个以上混合项目的经验,这是我发现的最佳结构:
我的示例将是关于保存“帖子”的应用程序。
1。使用存储库设计模式。
这将为您在维护代码和维护代码中的 DRY(不要重复自己)概念时省去很多麻烦。
创建一个新类PostsRepository。这个是与数据库通信的,包含大部分逻辑。
创建一个新类PostsService。这个将在其构造函数中包含PostsRepository。
服务类将是一种从 Web 控制器或 API 控制器获取用户输入的处理。
<?php
namespace App\Service;
use App\Repositories\PostsRepository;
class PostsService;
{
protected $repository;
public function __construct(PostsRepository $repository)
{
$this->repository = $repository;
}
}
对于网络控制器,您可以像往常一样创建控制器:
php artisan make:controller PostsController
对于 API 控制器,您可以在 Api 文件夹中创建控制器。
php artisan make:controller Api\PostsController
最后一个命令将创建目录 App\Http\Controllers\Api 并将控制器放置在其中。
回顾
现在我们有不同的控制器来返回适合起点(web / api)的结果。
我们有服务,两个(web / api)控制器都发送他们的数据进行验证(并让存储库采取行动)。
例子:
<?php
namespace App\Http\Controllers;
use App\Service\PostsService;
class PostsController extends Controller
{
protected $service;
public function __construct(PostsService $service)
{
$this->service = $service;
}
public function index()
{
/**
* Instead of returning a Blade view and
* sending the data to it like:
*
* $posts = $this->service->all();
* return views('posts.index', compact('posts'));
*
* We go ahead and just return the boilerplate of
* our posts page (Blade).
*/
return view('posts.index');
}
}
...
<?php
namespace App\Http\Controllers\Api;
use App\Service\PostsService;
class PostsController extends Controller
{
protected $service;
public function __construct(PostsService $service)
{
$this->service = $service;
}
/**
* Returns all posts.
*
* A vue component calls this action via a route.
*/
public function index()
{
$posts = $this->service->all();
return $posts;
}
/**
* Notice we don't have a store() in our
* Web controller.
*/
public function store()
{
return $this->service->store();
}
}
...
<?php
namespace App\Services;
use App\Repositories\PostsRepository;
class PostsService extends Controller
{
protected $repository;
public function __construct(PostsRepository $repository)
{
$this->repository = $repository;
}
public function all()
{
$posts = $this->repository->all();
return $posts;
}
public function store()
{
$request = request()->except('_token');
$this->validation($request)->validate();
return $this->repository->store($request);
}
public function validation(array $data)
{
return Validator::make($data, [
'content' => 'required|string|max:255',
//
]);
}
}
在我们的 PostsRepository 中,我们实际上调用了保存数据的方法。例如。 Post::insert($request);.
2。专门的 API 组
Route::prefix('api/v1')->middleware('auth')->group(function() {
Route::post('posts/store', 'Api\PostsController@store')->name('api.posts.store');
});
在进行 phpunit 测试时,为 API 路由提供 ->name() 会有所帮助。
3。刀片视图
这些应该被简单地剥离。
views/posts/index.blade.php:
@extends('layouts.app', ['title' => trans('words.posts')])
@section('content')
<!-- Your usual grid columns and stuff -->
<div class="columns">
<div class="column is-6">
<!-- This comp. can have a modal included. -->
<new-post-button></new-post-button>
<div class="column is-6">
<posts-index-page></posts-index-page>
</div>
</div>
@endsection
4。 Vue 结构。
https://github.com/pablohpsilva/vuejs-component-style-guide
因此,这些 Vue 组件可能存在于 resources/assets/js/components/posts/ 中,而在 /posts/ 内部,我会有标题为 IndexPage、CreateModal、EditModal 的文件夹,每个文件夹都有其 .vue 和 README.md。
我会在index.blade.php 中使用<posts-index-page>,并在需要时随时添加<post-create-modal> 和<edit-post-modal>。
所有的 vue 组件都将使用我们在 Routes 文件中指定的 API 端点。