nitra/doctrine-behaviors

Doctrine2 行为特性

dev-master 2013-05-06 05:49 UTC

This package is auto-updated.

Last update: 2024-09-14 19:14:39 UTC


README

Build Status

这是一个php 5.4+库,它是一组特性集合,可以向Doctrine2实体和仓库添加行为。

它目前处理

注意

一些行为(可翻译、时间戳、软删除、可追溯、可地理编码)需要Doctrine监听器才能工作。请通过阅读监听器部分来确保它们被激活。

一些特性基于注解驱动。
您需要在实体顶部声明use Doctrine\ORM\Mapping as ORM;

监听器

如果您使用symfony2,可以通过导入服务定义文件轻松注册它们

    # app/config/config.yml
    imports:
        - { resource: ../../vendor/knplabs/doctrine-behaviors/config/orm-services.yml }

您也可以使用doctrine2 API注册它们

<?php

$em->getEventManager()->addEventSubscriber(new \Knp\DoctrineBehaviors\ORM\Translatable\TranslatableListener);
// register more if needed

使用方法

您只需定义一个Doctrine2实体并使用特性即可

<?php

use Doctrine\ORM\Mapping as ORM;
use Knp\DoctrineBehaviors\Model as ORMBehaviors;

/**
 * @ORM\Entity(repositoryClass="CategoryRepository")
 */
class Category implements ORMBehaviors\Tree\NodeInterface, \ArrayAccess
{
    use ORMBehaviors\Tree\Node,
        ORMBehaviors\Translatable\Translatable,
        ORMBehaviors\Timestampable\Timestampable,
        ORMBehaviors\SoftDeletable\SoftDeletable,
        ORMBehaviors\Blameable\Blameable,
        ORMBehaviors\Geocodable\Geocodable,
        ORMBehaviors\Sluggable\Sluggable
    ;

    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="NONE")
     */
    protected $id;
}

对于一些行为,如树结构,您可以使用仓库特性

<?php

use Doctrine\ORM\EntityRepository;
use Knp\DoctrineBehaviors\ORM as ORMBehaviors;

class CategoryRepository extends EntityRepository
{
    use ORMBehaviors\Tree\Tree,
}

就是这样!

现在您有一个工作的Category,其行为如下

树结构

<?php

    $category = new Category;
    $category->setId(1); // tree nodes need an id to construct path.
    $child = new Category;
    $child->setId(2);

    $child->setChildOf($category);

    $em->persist($child);
    $em->persist($category);
    $em->flush();

    $root = $em->getRepository('Category')->getTree();

    $root->getParent(); // null
    $root->getNodeChildren(); // collection
    $root[0][1]; // node or null
    $root->isLeaf(); // boolean
    $root->isRoot(); // boolean

可翻译

可翻译行为等待一个CategoryTranslation实体。
这种命名约定避免了您手动处理实体关联。它由TranslationListener自动处理。

为了使用可翻译特性,您必须创建此实体。

<?php

use Doctrine\ORM\Mapping as ORM;
use Knp\DoctrineBehaviors\Model as ORMBehaviors;

/**
 * @ORM\Entity
 */
class CategoryTranslation
{
    use ORMBehaviors\Translatable\Translation;

    /**
     * @ORM\Column(type="string", length=255)
     */
    protected $name;

    /**
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * @param  string
     * @return null
     */
    public function setName($name)
    {
        $this->name = $name;
    }
}

现在您可以使用translategetTranslations方法来处理翻译。

<?php

    $category = new Category;
    $category->translate('fr')->setName('Chaussures');
    $category->translate('en')->setName('Shoes');
    $em->persist($category);

    $category->translate('en')->getName();

猜测当前区域设置

您可以通过提供一个可调用的对象作为其第一个参数来配置监听器猜测当前区域设置的方式。此库提供了一个可调用的对象(Knp\DoctrineBehaviors\ORM\Translatable\CurrentLocaleCallable),它使用Symfony2返回当前区域设置。

代理翻译

一个额外功能允许您代理可翻译实体的翻译字段。

您可以在可翻译实体的魔法__call方法中使用它,这样当您尝试调用getName(例如)时,它将返回当前区域设置的名称的翻译值。

<?php

    public function __call($method, $arguments)
    {
        return $this->proxyCurrentLocaleTranslation($method, $arguments);
    }

软删除

<?php

    $category = new Category;
    $em->persist($category);
    $em->flush();

    // get id
    $id = $em->getId();

    // now remove it
    $em->remove($category);

    // hey, i'm still here:
    $category = $em->getRepository('Category')->findOneById($id);

    // but i'm "deleted"
    $category->isDeleted(); // === true
<?php

    $category = new Category;
    $em->persist($category);
    $em->flush();
    
    // I'll delete you tomorow
    $category->setDeletedAt((new \DateTime())->modify('+1 day'));

    // Ok, I'm here
    $category->isDeleted(); // === false
    
    /*
     *  24 hours later...
     */
     
    // Ok I'm deleted
    $category->isDeleted(); // === true

时间戳

<?php

    $category = new Category;
    $em->persist($category);
    $em->flush();

    $id = $category->getId();
    $category = $em->getRepository('Category')->findOneById($id);

    $category->getCreatedAt();
    $category->getUpdatedAt();

可追溯

可追溯能够跟踪特定实体的创建者和更新者。一个可追溯的可调用用于从您的应用程序中获取当前用户。

如果您使用Doctrine实体来表示您的用户,您可以将监听器配置为自动管理此用户实体和您的实体之间的关联。

使用symfony2,您只需配置DI参数%knp.doctrine_behaviors.blameable_listener.user_entity%为完全限定名称空间,例如

# app/config/config.yml

parameters:
    knp.doctrine_behaviors.blameable_listener.user_entity: AppBundle\Entity\User

然后,您可以像这样使用它

<?php

    $category = new Category;
    $em->persist($category);

    // instances of %knp.doctrine_behaviors.blameable_listener.user_entity%
    $creator = $em->getCreatedBy();
    $updater = $em->getUpdatedBy();

可记录

可记录

可地理编码

可地理编码为PostgreSQL平台提供扩展,以便与cube和earthdistance扩展一起工作。

它允许您根据地理坐标查询实体。
它还提供了一个简单的入口点,用于使用像geocoder这样的第三方库将地址转换为纬度和经度。

<?php

    $geocoder = new \Geocoder\Geocoder;
    // register geocoder providers

    // $listener instanceof GeocodableListener
    $listener->setGeolocationCallable(function($entity) use($geocoder) {
        $location = $geocoder->geocode($entity->getAddress());
        $geocoder->setLocation(new Point(
            $location->getLatitude(),
            $location->getLongitude()
        ));
    });

    $category = new Category;
    $em->persist($category);

    $location = $category->getLocation(); // instanceof Point

    // find cities in a cricle of 500 km around point 47 lon., 7 lat.
    $nearCities = $repository->findByDistance(new Point(47, 7), 500);

可生成短名

Sluggable 为实体生成短网址(唯一性不保证)。在更新/持久化时自动生成(您可以通过覆盖 getRegenerateSlugOnUpdate 方法并返回 false 来禁用更新时的生成。您还可以通过覆盖 getSlugDelimiter 方法来覆盖默认的短横线作为分隔符。适用场景包括 SEO(例如,像 http://mysite.com/post/3/introduction-to-php 这样的网址)

<?php

use Doctrine\ORM\Mapping as ORM;
use Knp\DoctrineBehaviors\Model as ORMBehaviors;

/**
 * @ORM\Entity
 */
class BlogPost
{
    use ORMBehaviors\Sluggable\Sluggable;

    /**
     * @ORM\Column(type="string")
     */
    protected $title;

    public function getSluggableFields()
    {
        return [ 'title' ];
    }
}

可筛选

可筛选功能可以在仓库级别使用

它允许我们简单地筛选结果

连接筛选示例

<?php

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="ProductRepository")
 */
class ProductEntity
{

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

    /**
     * @ORM\Column(type="string", nullable=true)
     */
    private $name;

    /**
     * @ORM\Column(type="integer")
     */
    private $code;

    /**
     * @ORM\OneToMany(targetEntity="Order", mappedBy="product")
     */
    protected $orders;
}

和仓库

<?php

use Knp\DoctrineBehaviors\ORM\Filterable;
use Doctrine\ORM\EntityRepository;

class ProductRepository extends EntityRepository
{
    use Filterable\FilterableRepository;

    public function getLikeFilterColumns()
    {
        return ['e:name', 'o:code'];
    }

    public function getEqualFilterColumns()
    {
        return [];
    }

    protected function createFilterQueryBuilder()
    {
        return $this
            ->createQueryBuilder('e')
            ->leftJoin('e.orders', 'o');
    }
}

现在我们可以使用

    $products = $em->getRepository('Product')->filterBy(['o:code' => '21']);

可调用函数进行筛选

可调用函数被一些监听器(如 blameable 和 geocodable)使用,以根据第三方系统填写信息。

例如,blameable 可调用函数可以是任何实现 __invoke 方法的 symfony2 服务或任何匿名函数,只要它们返回当前登录用户表示(这意味着一切,一个用户实体、一个字符串、用户名等)。有关被调用的 DI 服务的示例,请参阅 Knp\DoctrineBehaviors\ORM\Blameable\UserCallable 类。

对于 geocodable,您可以将其设置为任何实现 __invoke 的服务或返回 Knp\DoctrineBehaviors\ORM\Geocodable\Type\Point 对象的匿名函数。