Doctrine ORM và Laravel 5 | Hỏi gì?

Là một nhà phát triển PHP, bạn có thể đã gặp thuật ngữ ORM. ORM là phương pháp làm việc với các database, tương tự như cách bạn sử dụng các class và object. Nếu bạn đã nghiên cứu sâu hơn về các ứng dụng web được thiết kế và xây dựng như thế nào, sau khi khám phá ORM của họ, bạn sẽ tìm thấy hai pattern nổi tiếng: Active Record và Data Mapper.

Active Record đề cập đến việc ánh xạ một object tới một row trong database. Thật vậy, mỗi row trong database được gán thành một object. Khi bạn lấy một row từ database, bạn có thể cập nhật, xóa hoặc lưu bằng chính object đó. Đó là cách Eloquent và Paris hoạt động và được thực hiện trong Ruby on Rails.

Mặt khác, Data Mapper là một layer của phần mềm giúp tách các object từ bộ nhớ trong (in-memory) ra khỏi database. Với Data Mapper, các object trong bộ nhớ thậm chí không cần biết đến sự tồn tại của database. Chúng không cần interface code cho SQL hoặc kiến ​​thức về database schema. Một giải pháp như vậy gọi là Doctrine.

Doctrine ORM

Doctrine là gì?

Doctrine là một ORM triển khai một pattern là Data Mapper và cho phép bạn tách biết riêng các business rules của ứng dụng khỏi persistence layer của database.

Một số ưu điểm mà tôi đã phát hiện khi sử dụng Doctrine với Laravel:

  • Nhanh hơn và dễ sử dụng hơn.
  • Entity (entity) chỉ là các object (object) PHP đơn giản.
  • Doctrine tiếp cận theo kiểu “code first”, vì vậy bạn có thể tạo các entity trước, sau đó tạo một database cho chúng một cách tự động. Trường hợp ngược lại cũng có thể, nhưng tôi không khuyến khích.
  • Hỗ trợ chú thích, XML và YAML cho schema.
  • DQL (thay thế cho SQL) tóm tắt các bảng của bạn.
  • Các sự kiện của Doctrine cho phép bạn dễ dàng kết nối vào các sự kiện database cụ thể và thực hiện một số hành động nhất định.
  • Các repository trung thành hơn với pattern repository.
  • Phương thức transactional write-behind cho phép Doctrine ít tương tác hơn với Database đến khi phương thức flush() được gọi.

Tất nhiên, Doctrine cũng có nhược điểm, nhưng chọn lựa ORM phù hợp là tuỳ vào lập trình viên.

Doctrine DQL

DQL viết tắt từ Doctrine Query Language. DQL cho phép bạn ngôn ngữ truy vấn object, có nghĩa là thay vì truy vấn relational (quan hệ) truyền thống, bạn có các truy vấn ở dạng object.

DQL cho phép bạn viết các truy vấn database theo hướng object, rất hữu ích khi bạn cần truy vấn database khi các phương thức mặc định từ repository không thể (hoặc khó) đạt được.

Mẫu truy vấn DQL:

SELECT b.id as ItemId, b.title as ItemTitle , b.url as ItemUrl FROM AlirezaDomainIdentityEntitiesMenu u WHERE u.id =:id

Bộ lọc Doctrine

Doctrine cho phép bạn giới hạn kết quả truy vấn bằng Filters. Ví dụ: có thể bạn chỉ muốn chỉnh sửa thông tin người dùng đã đăng nhập hoặc đảm bảo dữ liệu của khách hàng hiện tại được lấy được từ database. Filter là giải pháp tự động để ghi nhớ các điều kiện cụ thể cho tất cả các truy vấn của bạn.

Doctrine cung cấp các giới hạn cho mức độ SQL, vì vậy không cần phải duy trì mệnh đề trong repository của dự án của bạn. Điều này giúp gia tăng bảo mật và giúp code của bạn dễ đọc hơn.

Hãy xem một ví dụ:

/** * @ManyToOne(targetEntity=”User”) * @JoinColumn(name=”user_id”, referencedColumnName=”id”) **/ private $user;

Như bạn có thể thấy trong User entity, kết quả của JoinColumn chỉ giới hạn trong các mục có điều kiện là WHERE user_id =: user_id.

Cài đặt Doctrine 2

Để cài đặt Doctrine, có một chọn lựa để điều chỉnh phù hợp với cấu hình hiện tại của Laravel 5. Để cài đặt Doctrine 2 trong dự án Laravel, chạy lệnh sau đây:

composer require laravel-doctrine/orm

Như thường lệ, package sẽ được thêm vào app/config.php, với tư cách service provider:

LaravelDoctrineORMDoctrineServiceProvider::class,

Alias cũng phải được định cấu hình:

‘EntityManager’ => LaravelDoctrineORMFacadesEntityManager::class

Cuối cùng, chúng tôi xuất bản cấu hình cho package với:

php artisan vendor:publish -tag=”config”

Doctrine không cần cấu hình database và sử dụng cấu hình Laravel hiện tại, nhưng nếu bạn muốn thay đổi nó, bạn nên thay đổi file cấu hình Doctrine trong Config/doctrine.php:

‘managers’ => [ ‘default’ => [ ‘dev’ => env(‘APP_DEBUG’), ‘meta’ => env(‘DOCTRINE_METADATA’, ‘annotations’), ‘connection’ => env(‘DB_CONNECTION’, ‘mysql’), ‘namespaces’ => [ ‘App’ ],

Đó là tất cả cần làm!

Entity là gì?

“Entity” tham chiếu đến một object có danh tính riêng biệt. Một entity phải có một identifier cụ thể và duy nhất xuyên suốt hệ thống, chẳng hạn như khách hàng hoặc sinh viên. Sẽ có các object khác, chẳng hạn như địa chỉ email, không phải là entity, mà là các value objects.

Hãy tạo một Post Entity App/Entity/Post.php:

namespace AppEntity; use DoctrineORMMapping as ORM; /** * @ORMEntity * @ORMTable(name=”posts”) * @ORMHasLifecycleCallbacks() */ class Post { /** * @var integer $id * @ORMColumn(name=”id”, type=”integer”, unique=true, nullable=false) * @ORMId * @ORMGeneratedValue(strategy=”AUTO”) * */ private $id; /** * @ORMColumn(type=”string”) */ private $title; /** * @ORMColumn(type=”text”) */ private $body; public function __construct($input) { $this->setTitle($input[‘title’]); $this->setBody($input[‘body’]); } public function getId() { return $this->id; } public function getTitle() { return $this->title; } public function setTitle($title) { $this->title = $title; } public function getBody() { return $this->body; } public function setBody($body) { $this->body = $body; } }

Thuộc tính của class phải giống với các field trong bảng của database hoặc bạn có thể xác định chúng bằng chú thích @Colum (“name”=”myfield”).

Repository là gì?

Repository cho phép tất cả code của bạn sử dụng các object mà không cần biết các object được lưu giữ như thế nào. Repository chứa tất cả các thông tin về persistence, gồm cả mapping từ table đến object. Điều này cung cấp một góc nhìn hướng đối tượng hơn của persistence layer và làm mapping code có tính đóng gói hơn (encapsulated).

Bây giờ là lúc tạo Repository trong App/Repository/PostRepo.php:

namespace AppRepository; use AppEntityPost; use DoctrineORMEntityManager; class PostRepo { /** * @var string */ private $class = ‘AppEntityPost’; /** * @var EntityManager */ private $em; public function __construct(EntityManager $em) { $this->em = $em; } public function create(Post $post) { $this->em->persist($post); $this->em->flush(); } public function update(Post $post, $data) { $post->setTitle($data[‘title’]); $post->setBody($data[‘body’]); $this->em->persist($post); $this->em->flush(); } public function PostOfId($id) { return $this->em->getRepository($this->class)->findOneBy([ ‘id’ => $id ]); } public function delete(Post $post) { $this->em->remove($post); $t
his->em->flush(); } /** * create Post * @return Post */ private function prepareData($data) { return new Post($data); } }

Doctrine EntityManager hoạt động như access point để quản lý hoàn toàn các entity của bạn. Sau đó, tạo ra Controller App/Http/Controllers/PostController.php:

namespace AppHttpControllers; use AppRepositoryPostRepo as repo; use AppValidationPostValidator; class PostController extends Controller { private $repo; public function __construct(repo $repo) { $this->repo = $repo; } public function edit($id=NULL) { return View(‘admin.index’)->with([‘data’ => $this->repo->postOfId($id)]); } public function editPost() { $all = Input::all(); $validate = PostValidator::validate($all); if (!$validate->passes()) { return redirect()->back()->withInput()->withErrors($validate); } $Id = $this->repo->postOfId($all[‘id’]); if (!is_null($Id)) { $this->repo->update($Id, $all); Session::flash(‘msg’, ‘edit success’); } else { $this->repo->create($this->repo->perpare_data($all)); Session::flash(‘msg’, ‘add success’); } return redirect()->back(); } public function retrieve() { return View(‘admin.index’)->with([‘Data’ => $this->repo->retrieve()]); } public function delete() { $id = Input::get(‘id’); $data = $this->repo->postOfId($id); if (!is_null($data)) { $this->repo->delete($data); Session::flash(‘msg’, ‘operation Success’); return redirect()->back(); } else { return redirect()->back()->withErrors(‘operationFails’); } } }

View và Route giống như bình thường.

Tôi thích tạo ra Validator của riêng mình dựa trên class Validator của Laravel. Dưới đây là Validator AppValidationPostValidator.php:

namespace AppValidation; use Validator; class PostValidator { public static function validate($input) { $rules = [ ‘title’ => ‘Required|Min:4|Max:80|alpha_spaces’, ‘body’ => ‘Required’, ]; return Validator::make($input, $rules); } }

Tổng kết

Nếu trước đây bạn chưa từng làm việc với Doctrine 2, tôi hy vọng bài viết này thú vị và đủ thông tin. Laravel 5 không sử dụng Doctrine, nhưng như bạn có thể thấy, có một số gói cho phép chúng ta dễ dàng sử dụng thư viện này cùng với Laravel. Tôi đã tạo một ứng dụng blog đơn giản với Laravel 5 và Doctrine ORM và hy vọng điều này có thể giúp bạn tạo ứng dụng mà bạn mong muốn. Tôi luôn đón chờ những góp ý từ bạn.