最大实体原则_在原则实体中使用特征

最大实体原则

Since PHP 5.4.0, PHP supports a pretty way to reuse code called “Traits” – a set of methods that you can include within another class in order not to repeat yourself. You can read more about traits in previously published SitePoint posts: here, here and here.

从PHP 5.4.0开始,PHP支持一种漂亮的方法来重用代码,即“特质”(Traits)-可以在另一个类中包含的一组方法,以免重复。 您可以在以前发布的SitePoint帖子中( 此处此处此处)阅读有关特征的更多信息。

Copy - Flat icon for web and mobile apps

Today, I am going to show you how they can be used with Doctrine ORM in a Symfony Environment.

今天,我将向您展示如何在Symfony环境中将它们与Doctrine ORM一起使用。

特质基础 (Trait Basics)

<?php
trait ExampleTrait {
    public function sayHello() {
        echo "Hello";
    }
}

class A {
    use ExampleTrait;
}

class B {
    use ExampleTrait;
}

$one = new A();
$one->sayHello();    /* return `Hello` */

$two = new B();
$two->sayHello();    /* return `Hello`, too */

As we can see, a basic method sayHello() is declared inside a Trait that is implemented by both A and B classes with a use statement. Easy, right? This example is really short but it should give you the basic knowledge to work with Traits.

如我们所见,基本方法sayHello()在Trait中声明,该Trait由ABuse语句实现。 容易吧? 这个例子确实很简短,但是它应该为您提供使用Traits的基本知识。

If you are interested in Traits, I recommend you read the official documentation and previously published SitePoint posts here, here and here, to fully grasp the concept. Allow me to warn you about the fact that many people tend not to see a difference between Traits and Interfaces. Here is a pragmatic explanation:

如果您对特质感兴趣,我建议您在此处此处此处阅读官方文档和以前发布的SitePoint帖子,以全面了解该概念。 请允许我警告您以下事实:许多人往往不会看到“特性”和“ 接口”之间的差异。 这是一个务实的解释:

An interface is a contract that says “this object is able to do this thing”, whereas a Trait is giving the object the ability to do the thing.

界面是一个契约,上面写着“该对象能够执行此操作”,而“特性”则赋予该对象执行该操作的能力。

For a more in-depth explanation, feel free to take a look at this insightful post by Philip Brown, which the previous quote comes from.

要获得更深入的解释,请随时阅读Philip Brown的这篇富有洞察力的文章 ,该文章先前的引用来自此。

When it comes to organizing one’s database architecture, it is not uncommon to face code duplication. As an example, suppose we have to develop the usual blog application. At some point, it is likely that we are going to create a basic Article entity and probably a Comment entity as well.

在组织数据库架构时,面对代码重复并不少见。 例如,假设我们必须开发通常的博客应用程序。 在某个时候,我们可能会创建一个基本的Article实体,也可能会创建一个Comment实体。

Both entities would benefit from having created_at and updated_at fields (so we can sort results on those columns later). But before digging into traits, let’s see how we could build those entities in Doctrine without them.

这两个实体都将从具有created_atupdated_at字段中受益(因此我们以后可以在这些列上对结果进行排序)。 但是在深入研究特征之前,让我们先看看如何在没有这些特征的情况下在教义中建立这些实体。

步骤1:建立实体 (Step 1: create the entities)

文章实体 (Article entity)

<?php
namespace Blog\AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Table(name="article")
 * @ORM\Entity(repositoryClass="Blog\AppBundle\Entity\ArticleRepository")
 */
class Article
{
    /**
     * @ORM\Column(name="idArticle" type="integer")
     * @ORM\Id()
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /* Other properties you need in your entity: $title, $content, $author...  */

    /** @ORM\Column(name="created_at" type="datetime") */
    private $createdAt;

    /** @ORM\Column(name="updated_at" type="datetime") */
    private $updatedAt;

   /* Getters & Setters */
}

评论实体 (Comment entity)

<?php
namespace Blog\AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Table(name="comment")
 * @ORM\Entity(repositoryClass="Blog\AppBundle\Entity\CommentRepository")
 */
class Comment
{
    /**
     * @ORM\Column(name="idComment" type="integer")
     * @ORM\Id()
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /* Other properties you need in your entity */

    /** @ORM\Column(name="created_at" type="datetime") */
    private $createdAt;

    /** @ORM\Column(name="updated_at" type="datetime") */
    private $updatedAt;

    /* Getters & Setters */
}

The same properties $createdAt and $updatedAt are included in both classes. This is far from DRY. Would Traits be able to help us clean this code up?

两个类都包含相同的属性$createdAt $updatedAt$updatedAt 。 这远不是DRY。 特性可以帮助我们清理此代码吗?

步骤2:建立特质 (Step 2: create the Trait)

<?php
// src/Blog/AppBundle/Entity/Traits/TimestampableTrait.php

namespace Blog\AppBundle\Entity\Traits;

use Doctrine\ORM\Mapping as ORM;

trait TimestampableTrait
{
    /**
     * @var datetime $createdAt
     *
     * @ORM\Column(name="created_at", type="datetime")
     */
    private $createdAt;

    /**
     * @var datetime $updatedAt
     *
     * @ORM\Column(name="updated_at", type="datetime")
     */
    private $updatedAt;


    /**
     * Get createdAt
     *
     * @return datetime
     */
    public function getCreatedAt()
    {
        return $this->createdAt;
    }

    /**
     * Set createdAt
     *
     * @param datetime $createdAt
     */
    public function setCreatedAt($createdAt)
    {
        $this->createdAt = $createdAt;

        return $this;
    }

    /**
     * Get updatedAt
     *
     * @return datetime
     */
    public function getUpdatedAt()
    {
        return $this->updatedAt;
    }

    /**
     * Set updatedAt
     *
     * @param datetime $updatedAt
     */
    public function setUpdatedAt($updatedAt)
    {
        $this->updatedAt = $updatedAt;

        return $this;
    }
}

Here is a pretty trait file into which we have moved the initial duplicated code. Both $createdAt and $updatedAt as well as all the associated methods are now separated from the entities. As a result, it will be much easier to use them somewhere else. Remember the introduction section with the keyword use.

这是一个漂亮的特征文件,我们将初始重复的代码移入其中。 无论$createdAt$updatedAt以及所有相关的方法现在从实体分离。 结果,在其他地方使用它们会容易得多。 记住带有关键字use的介绍部分。

步骤3:重构实体 (Step 3: refactor the entities)

文章实体 (Article entity)

<?php
// src/Blog/AppBundle/Entity/Article.php

namespace Blog\AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Blog\AppBundle\Entity\Traits\TimestampableTrait;

class Article
{
    use TimestampableTrait;

    /**
     * @ORM\Column(name="idArticle" type="integer")
     * @ORM\Id()
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /* Other properties you need in your entity */

    /* Getters & Setters */
}

评论实体 (Comment entity)

<?php
// src/Blog/AppBundle/Entity/Comment.php

namespace Blog\AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Blog\AppBundle\Entity\Traits\TimestampableTrait;

/**
 * @ORM\Table(name="comment")
 * @ORM\Entity(repositoryClass="Blog\AppBundle\Entity\CommentRepository")
 */
class Comment
{
    use TimestampableTrait;

    /**
     * @ORM\Column(name="idComment" type="integer")
     * @ORM\Id()
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /* Other properties you need in your entity */

    /* Getters & Setters */
}

Done! Let’s play with the command line. First, let’s create the entities in our database:

做完了! 让我们玩命令行。 首先,让我们在数据库中创建实体:

php app/console doctrine:schema:create

This command would yield:

该命令将产生:

`Article Entity`
	
	| idArticle | *All our other fields...* | created_at | updated_at |
	|-----------|---------------------------|------------|------------|
	
	`Comment Entity`
	
	| idComment | *All our other fields...* | created_at | updated_at |
	|-----------|---------------------------|------------|------------|

Now, if you want to create new objects from these classes, you would find that they both have the common methods available:

现在,如果您想从这些类中创建新对象,则会发现它们都有可用的通用方法:

<?php
    $article = new Article();
    $article->setUpdatedAt(new \Datetime('now'));

    $comment = new Comment();
    $comment->setUpdatedAt(new \Datetime('now'));
?>

Obviously, we are now ready to persist the data.

显然,我们现在可以保留数据了。

更进一步 (Going further)

Currently, in the Symfony sphere, many bundles and extensions tend to stick to this way of doing things. The DoctrineBehaviors library from KNPLabs provides a great collection of Traits for entities and repositories. In the same state of mind, I recommend you have an in-depth look at the well known DoctrineExtensions bundle and especially everything about the Timestampable behavior extension.

当前,在Symfony领域中,许多捆绑包和扩展都倾向于坚持这种做事方式。 KNPLabsDoctrineBehaviors库为实体和存储库提供了大量特性集。 出于同样的考虑,我建议您深入了解著名的DoctrineExtensions捆绑包,尤其是有关Timestampable行为扩展的一切。

最后的想法 (Final Thoughts)

Traits are not difficult to absorb. They are an excellent way to produce lighter and more flexible code. Be careful not to abuse them: sometimes, it is better to construct a unique class implementation. I can’t stress enough how crucial it is to take enough time in order to properly design your app. Give them a go if you think they could help you. Create yours, test them and tell us how you used them!

性状不难吸收。 它们是产生更轻便,更灵活的代码的绝佳方法。 注意不要滥用它们:有时,最好构造一个独特的类实现。 我无法强调足够的时间来正确设计您的应用程序是多么关键。 如果您认为他们可以帮助您,请给他们一个机会。 创建您的产品,对其进行测试,并告诉我们您的使用方式!

翻译自: https://www.sitepoint.com/using-traits-doctrine-entities/

最大实体原则

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值