作为PHP开发人员,您可能遇到过ORM这个词。 ORM是一种与使用类和对象相同的方式来处理数据库。 如果要深入研究Web应用程序的设计和构建方式,则在对其ORM进行一些探索之后,您会发现两种众所周知的模式: Active Record和Data Mapper 。
活动记录是指将对象映射到数据库行。 实际上,数据库中的每一行都与一个对象相关联。 从数据库检索行时,可以使用对象本身进行更新,删除或保存。 这就是Eloquent和Paris的工作方式,以及它在Ruby on Rails中的完成方式。
另一方面, Data Mapper
是将内存对象与数据库分开的软件层。 使用Data Mapper,内存中对象无需知道甚至存在数据库。 他们不需要SQL接口代码或数据库架构知识。 这样的解决方案之一就是教义 。
![主义ORM](https://i60.tinypic.com/f527mt.png)
什么是学说?
Doctrine是一个ORM,它实现数据映射器模式,并允许您将应用程序的业务规则与数据库的持久层完全分开。
我将Larcavel与Doctrine结合使用时发现了一些优点:
- 更快,更容易使用。
- 实体只是普通的PHP对象。
- Doctrine利用“代码优先”方法,因此您可以先创建实体,然后自动为其创建数据库。 相反的情况也是可能的,但我不建议这样做。
- 支持模式的注释,XML和YAML。
- DQL(SQL的替代品)使您的表抽象化。
- 通过事件事件,您可以轻松挂钩特定的数据库事件并执行某些操作。
- 存储库更忠实于存储库模式。
-
Transactional write-behind
方法使Doctrine与数据库的交互较少,直到调用flush()
方法为止。
当然,Doctrine也有缺点,但是程序员要选择正确的ORM。
教义DQL
DQL代表主义查询语言。 DQL为您带来了对象查询语言,这意味着您可以使用对象形式的查询来代替传统的关系查询。
DQL允许您以面向对象的方式编写数据库查询,这在需要使用默认存储库方法无法实现(或非常困难)的方式查询数据库时非常有用。
样本DQL查询:
SELECT b.id as ItemId, b.title as ItemTitle , b.url as ItemUrl
FROM Alireza\Domain\Identity\Entities\Menu u
WHERE u.id =:id
教义过滤器
通过Doctrine,您可以使用Filters限制查询结果。 例如,您可能只想编辑登录用户的信息,或确保从数据库返回了当前客户端的数据。 过滤器是一种自动解决方案,用于记住所有查询的特定条件。
Doctrine提供了SQL级别的限制,因此无需在项目的多个存储库中维护该子句。 这样可以增强安全性,并使您的代码更易于阅读。
让我们看一个例子:
/**
* @ManyToOne(targetEntity="User")
* @JoinColumn(name="user_id", referencedColumnName="id")
**/
private $user;
如您在用户实体中所见, JoinColumn
的结果仅限于WHERE user_id = :user_id
条件的项目。
设置学说2
要设置Doctrine,有一个桥梁可以与Laravel 5的现有配置匹配。 要在Laravel项目中安装Doctrine 2,我们运行以下命令:
composer require laravel-doctrine/orm
与往常一样,应将包作为服务提供者添加到app/config.php
:
LaravelDoctrine\ORM\DoctrineServiceProvider::class,
别名也应配置:
'EntityManager' => LaravelDoctrine\ORM\Facades\EntityManager::class
最后,我们发布带有以下内容的软件包配置:
php artisan vendor:publish --tag="config"
Doctrine不需要数据库配置并使用当前的Laravel配置,但是如果要覆盖它,则应在Config/doctrine.php
更改Doctrine配置文件:
'managers' => [
'default' => [
'dev' => env('APP_DEBUG'),
'meta' => env('DOCTRINE_METADATA', 'annotations'),
'connection' => env('DB_CONNECTION', 'mysql'),
'namespaces' => [
'App'
],
这里的所有都是它的。
什么是实体?
“实体”是指具有独特身份的对象。 实体(例如客户或学生)必须具有在整个系统中唯一的特定标识符。 还有其他对象,例如电子邮件地址,它们不是实体,而是值对象 。
让我们创建一个Post Entity App/Entity/Post.php
:
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
* @ORM\Table(name="posts")
* @ORM\HasLifecycleCallbacks()
*/
class Post
{
/**
* @var integer $id
* @ORM\Column(name="id", type="integer", unique=true, nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*
*/
private $id;
/**
* @ORM\Column(type="string")
*/
private $title;
/**
* @ORM\Column(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;
}
}
类属性应与数据库表中的字段相同,或者可以使用@Colum("name"="myfield")
批注定义它们。
什么是存储库?
该存储库允许您所有的代码使用对象,而无需知道对象是如何持久化的。 该存储库包含所有持久性知识,包括从表到对象的映射。 这提供了持久层的更面向对象的视图,并使映射代码更加封装。
现在是时候在App/Repository/PostRepo.php
创建存储库了:
namespace App\Repository;
use App\Entity\Post;
use Doctrine\ORM\EntityManager;
class PostRepo
{
/**
* @var string
*/
private $class = 'App\Entity\Post';
/**
* @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);
$this->em->flush();
}
/**
* create Post
* @return Post
*/
private function prepareData($data)
{
return new Post($data);
}
}
教义EntityManager
用作完全管理实体的访问点。 然后,创建Controller App/Http/Controllers/PostController.php
:
namespace App\Http\Controllers;
use App\Repository\PostRepo as repo;
use App\Validation\PostValidator;
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');
}
}
}
视图和路由与通常相同。
我更喜欢根据Laravel的Validator类创建自己的Validator。 这是Validator App\Validation\PostValidator.php
:
namespace App\Validation;
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);
}
}
结论
如果您以前没有使用过教义2,我希望本文有趣而有益。 Laravel 5不使用Doctrine,但是如您所见,有些软件包使我们可以轻松地将其与Laravel一起使用。 我使用Laravel 5和Doctrine ORM创建了一个简单的博客应用程序,希望这可以帮助您创建所需的应用程序。 我欢迎您的评论。
翻译自: https://code.tutsplus.com/tutorials/doctrine-orm-and-laravel-5--cms-24914