Cùng xây dựng website Laravel + Vuejs chi tiết cho người mới học phần 1
Bài đăng này đã không được cập nhật trong 6 năm
I. Lời mở đầu
Sau một thời gian tìm hiểu về Laravel và VueJS, cũng như áp dụng hai em nó vào một số project
. Nói vậy thôi chứ mấy project cũng nhỏ nhỏ thôi ạ (nguong) =)). Mình cũng đúc kết ra được một số kinh nghiệm khi xây dựng website có kết hợp Laravel với VueJS. Trong loạt series này mình sẽ hướng dẫn các bạn xây dựng nó với kiến trúc và công nghệ mà mình đã từng áp dụng.
Trước khi đọc các phần bên dưới đảm bảo rằng các bạn đã có các kiến thức nhất định về Laravel cũng như VueJS. Nếu bạn là người mới học có thể tham khảo thêm một số bài viết dưới đây:
Laravel:
-
Đinh Tài: Những method thông dụng của Collection trong Laravel, bạn đã sử dụng hết chưa?
-
Vũ Nguyễn: Sử dụng Fractal - Transformer trong Laravel - Phần 1, 2
VueJS:
II. Đôi chút về công nghệ áp dụng
Trong một lần lang thang trên web, mình từng được đọc một câu danh ngôn như này:
Viết code có lương tâm, dễ đọc dễ hiểu, nhớ comment đầy đủ. Hãy thương người maintain code của bạn (Đôi khi chính bạn phải maintain code của mình đấy, phải tự thương mình thôi).
Chính vì vậy trước khi bắt tay vào code, đảm bảo rằng bạn đã chọn cho mình những công nghệ phù hợp, một kiến trúc, và cách viết code sạch, "hợp lý" (hợp lý ở đây cũng khá khó để nói, tuy nhiên khi bạn và team của bạn cảm thấy đồng nhất và hiểu được code của nhau thì cũng "hợp lý" rồi).
1. Back-End:
Với một project không quá phức tạp các lựa chọn bên dưới là khá cần thiết cho 1 project sắp tới.
- Resource Controller:
Để triển khai các chức năng
CRUD
thì Resource Controller là lựa chọn không thể thiếu. Tại sao vậy ???
Để tạo PostController chỉ với command đơn giản như thế này:
php artisan make:controller PostController --resource
Là đã tạo ra được một PostController
với đầy đủ các actions (functions) cho chức năng CRUD
rồi.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Post;
class PostController extends Controller
{
/**
* Show all post
*
* @return \Illuminate\Http\Response
*/
public function index()
{
//
}
/**
* Show single post
*
* @param $id int Post ID
* @return \Illuminate\Http\Response
*/
public function show($id)
{
//
}
/**
* Create single post
*
* @param $request \Illuminate\Http\Request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
//
}
/**
* Update single post
*
* @param $request \Illuminate\Http\Request
* @param $id int Post ID
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
//
}
/**
* Delete single post
*
* @param $id int Post ID
* @return \Illuminate\Http\Response
*/
public function destroy($id)
{
//
}
}
Sau khi tạo xong Resource Controller
đăng ký resources trong Routes:
Route::resources(['posts' => 'PostController']);
Từng action (function) cùng các route chi tiết có thể tham khảo rõ hơn tại đây: https://laravel.com/docs/5.7/controllers#resource-controllers
- Model Binding:
Cách làm thông thường
/**
* Show single post
*
* @param $id int Post ID
* @return \Illuminate\Http\Response
*/
public function show($id)
{
$post = Post::findOrFail($id)
}
Với Model Binding
/**
* Show single post
*
* @param $post Post
* @return \Illuminate\Http\Response
*/
public function show(Post $post)
{
dd($post);
}
- Repository Pattern: Repository Pattern là lớp trung gian giữa tầng Business Logic và Data Access, giúp cho việc truy cập dữ liệu chặt chẽ và bảo mật hơn.Nó vai trò là một lớp kết nối giữa tầng Business và Model của ứng dụng. Các phần truy xuất, giao tiếp với database năm rải rác ở trong code, khi bạn muốn thực hiện một thao tác lên database thì phải tìm trong code cũng như tìm các thuộc tính trong bảng để xử lý. Điều này gây lãng phí thời gian và công sức rất nhiều, vì thế với Repository design pattern, thì việc thay đổi ở code sẽ không ảnh hưởng quá nhiều công sức chúng ta chỉnh sửa.
- Fratal - Transformer: Thay vì trả response APIs trực tiếp từ model, dùng Fratal - Transformer để tả về những dữ liệu tùy chỉnh theo lựa chọn của chúng ta. Chính vì vậy khi model có sự thay đổi, front-end sử dụng API của model đó sẽ không bị thay đổi theo.
Một ví dụ Fratal - Transformer trong Laravel:
<?php
namespace App\Models\Transformers;
use App\Models\Posts;
use League\Fractal\TransformerAbstract;
class PostTransformer extends TransformerAbstract
{
/**
* @param Post $post
* @return array
*/
public function transform(Post $post)
{
return [
'id' => $post->id,
'title' => $post->title,
'description' => $post->description,
];
}
- PostRepository:
<?php
namespace App\Repositories;
use App\Models\Post;
use App\Models\Transformers\PostTransformer;
use Illuminate\Database\Eloquent\Collection;
/**
* Class PostRepository
* @package App\Repositories
*/
class PostRepository extends AbstractRepository
{
/**
* @var Post
*/
protected $model;
/**
* PostRepository constructor.
* @param Post $model
*/
public function __construct(Post $model)
{
$this->model = $model;
}
/**
* Get list Post
* @param int|null $paginate
* @return Collection
*/
public function getListPosts($paginate = null)
{
$paginate = min($paginate ?: config('pagination.post.per_page'), 100);
$posts = $this->model->->orderBy('created_at', 'desc')
->paginate($paginate);
$posts['data'] = $this->refactorTransformer(
$posts['data'],
new PostTransformer()
)->toArray();
return $posts;
}
}
- PostController:
<?php
namespace App\Http\Controllers;
use App\Models\Post;
use App\Repositories\PostRepository;
use Illuminate\Http\Request;
use App\Models\Transformers\PostTransformer;
class PostController extends Controller
{
/**
* Entity of Controller
* @var PostRepository
*/
protected $entity;
/**
* @param PostRepository $postRepository
*/
public function __construct(PostRepository $postRepository)
{
$this->entity = $postRepository;
}
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index(Request $request)
{
return $this->responseOk($this->entity->getListPosts($request->perPage);
}
}
Cách mà mọi người hay làm:
<?php
namespace App\Http\Controllers;
use App\Models\Post;
use Illuminate\Http\Request;
class PostController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index(Request $request)
{
$paginate = min($request->paginate ?: config('pagination.post.per_page'), 100);
$posts = $this->model->->orderBy('created_at', 'desc')
->paginate($paginate);
return $posts;
}
}
Khi bắt đầu code có sử dụng Fratal - Transformer và repository chỉ một action bạn có thể thấy mệt mỏi khi phải viết tận mấy file thay vì viết trực tiếp trong controller như trên. Tuy nhiên, khi dự án lớn dần và đòi hỏi nhiều chức năng hơn, bạn sẽ thấy nó thật tuyệt vời không chỉ việc sử dụng lại các function dễ dàng mà khi specs thay đổi việc sửa code cũng như refactor, maintain lại cực kỳ nhẹ nhàng. Đặc biệt khi code bên Back-end nên comment đầy đủ và chính xác đảm bảo cho việc maintain sau này.
- Laravel-mix:
Có thể sử dụng
npm
hoặcyarn
. Cá nhân thì mình hay dùngyarn
2. Front-End:
-
Vue, Vuex:
- Vue component
- Vue router
- Vuex
-
Element-UI (or Vue material):
- Element-ui: https://element.eleme.io/#/en-US (Khuyên dùng)
- Vue-material: https://vuematerial.io/
-
SCSS và flexbox:
- Flexbox: là một kiểu dàn trang (layout mode) mà nó sẽ tự cân đối kích thước của các phần tử bên trong để hiển thị trên mọi thiết bị. Nói theo cách khác, bạn không cần thiết lập kích thước của phần tử, không cần cho nó float, chỉ cần thiết lập nó hiển thị chiều ngang hay chiều dọc, lúc đó các phần tử bên trong có thể hiển thị theo ý muốn.
- SCSS: Cú pháp của SCSS dựa trên cú pháp của CSS, bắt đầu sử dụng {} và ; như CSS, không còn quá quan trọng việc thụt lề hay các khoảng trắng.
.menu {
...
&__item {
...
}
&--fixed {
...
}
}
Tạm kết
Phần 1 tạm dừng lại ở đây, hy vọng bạn đã có đủ kiến thức nhất định để bắt đầu xây dựng project ở phần sau nhé.
All rights reserved