weavora/doctrine-extensions

Doctrine2 ORM 扩展

0.1.0 2013-08-21 16:00 UTC

This package is not auto-updated.

Last update: 2024-09-23 15:18:18 UTC


README

Total Downloads Latest Stable Version

此库通过一些有用的功能扩展了 Doctrine2 基础类。

安装

您可以使用 Composer 或从其 GitHub 仓库克隆它来安装此库。以下将描述这两种选项。

Composer

您可以在 https://packagist.org.cn 上了解更多关于 Composer 和其主要仓库的信息。要使用 Composer 安装这些 doctrine 扩展,首先根据 Packagist 主页上的说明安装您的项目中的 Composer。然后,您可以使用以下建议的参数定义对 doctrine-extensions 的开发依赖。虽然我们尽力保持主分支的稳定性,但您可能更喜欢使用当前的稳定版本标签。

{
    "require-dev": {
        "weavora/doctrine-extensions": "dev-master@dev"
    }
}

要安装,您可以调用

composer.phar install

Git / GitHub

git 仓库在其 master 分支中托管开发版本。您可以通过在项目的 composer.json 文件中将 dev-master 作为您首选的版本来引用,如前面的示例所示,使用 Composer 安装它。

您也可以安装此开发版本

git clone git://github.com/weavora/doctrine-extensions.git
cd doctrine-extensions

上述过程将库安装到 doctrine-extensions 文件夹中。

ORM 扩展

Doctrine 建议使用包含与实体检索相关的业务逻辑的实体仓库。您很可能会在仓库中使用查询构建器来构建 DQL。问题是标准查询构建器具有相当通用的 API,并且不提供诸如命名范围、应用自定义条件参数的单个方法等有用的快捷方式。

此库旨在填补这些空白,使您的生活更加轻松。

如何组织仓库

假设您想创建一个博客应用程序。您可能会创建一个帖子实体,它将引用类别、作者和评论。现在您正在考虑组织仓库的方法。

仓库的常见问题

  • 一旦有重复的条件,就必须重复代码
  • 即使简单的具有少量条件和排序的方法看起来也很庞大

您可以通过为每个实体创建自定义查询构建器来解决第一个问题。它还将隐藏您的条件细节,这些细节对于不需要真正知道这些的仓库来说并不重要。

为了解决庞大且不太描述性的方法的难题,您将创建一个查询构建器的扩展,其中包含一些有用的快捷方式,使代码更易于阅读。

PostQueryBuilder & PostRepository 可能的样子示例

<?php

namespace Acme\BlogBundle\Entity;

use Weavora\Doctrine\ORM as ORM;

/**
 * Custom query class for Post entity
 * Contains useful criteria set for posts filtering
 */
class PostQueryBuilder extends ORM\EntityQueryBuilder
{
    public function published()
    {
        return $this->filterByColumn('Post.publishStatus', Post::STATUS_PUBLISHED);
    }

    public function recentFirst()
    {
        return $this->orderBy('Post.publishedAt', 'DESC');
    }
}

/**
 * Post entity repository
 * Contains methods for fetch posts
 */
class PostRepository extends ORM\EntityRepository
{
    /**
     * Instantiate custom query builder
     * @return PostQueryBuilder
     */
    public function filter()
    {
        return new PostQueryBuilder($this->getEntityManager(), $this);
    }

    /**
     * Find 10 recent posts
     *
     * @return Post[]
     */
    public function findRecent()
    {
        return $this
            ->filter() // use PostQueryBuilder
                ->published() // get only published posts
                ->limit(10) // get only first 10 posts
                ->recentFirst() // most recent posts should go first
            ->fetchAll(); // get posts
    }

    /**
     * Find posts by category
     *
     * @param Category $category
     * @param int $page
     * @param int $itemsPerPage
     * @return Post[]
     */
    public function findByCategory(Category $category, $page = 1, $itemsPerPage = 10)
    {
        return $this
            ->filter() // use PostQueryBuilder
                ->filterByColumn('Post.category', $category) // get only posts in the specified category
                ->paginate($page, $itemsPerPage) // get only the specified page
                ->recentFirst()  // most recent posts should go first
            ->fetchAll(); // get posts
    }

    /**
     * Count posts by author
     *
     * @param Author $author
     * @return int
     */
    public function countByAuthor(Author $author)
    {
        return $this
            ->filter() // use PostQueryBuilder
                ->select('COUNT(Post.id)') // calculate count
                ->filterByColumn('Post.author', $author) // calculate only author's posts
                ->groupBy('Post.author') // group by author
            ->fetchScalar(); // get scalar results (the first column of the first row)
    }
}

很简单,对吧?

API / EntityQueryBuilder

getEntityAlias() : string | 获取查询中的实体别名

// entity class name -> alias
// \Entity\Post -> Post
// \Acme\DemoBundle\Entity\AuthorSettings -> AuthorSettings
// \Comment -> Comment
$alias = $queryBuilder->getEntityAlias();

filterByColumn($columnName, $value, $strict = true) : EntityQueryBuilder | 将列与指定的值进行比较

// SELECT * FROM Entity\Post Post WHERE Post.title = :p1, [p1 = 'Post 1']
$queryBuilder->filterByColumn('Post.title', 'Post 1');

// SELECT * FROM Entity\Post Post WHERE Post.category IN (1,2,3)
$queryBuilder->filterByColumn('Post.category', array(1,2,3));

// SELECT * FROM Entity\Post Post WHERE Post.author IS NULL
$queryBuilder->filterByColumn('Post.author', null);

// SELECT * FROM Entity\Post Post
$queryBuilder->filterByColumn('Post.author', null, false);

// SELECT * FROM Entity\Post Post WHERE Post.author = 1
$queryBuilder->filterByColumn('Post.author', 1, false);

filterByStatement($statement, $parameters = array()) : EntityQueryBuilder | 添加自定义语句

// SELECT * FROM Entity\Post Post WHERE Post.title = :title, [title = 'Post 1']
$queryBuilder->filterByStatement('Post.title = :title', ['title' => 'Post 1']);

// SELECT * FROM Entity\Post Post WHERE Post.category IN (1,2,3)
$queryBuilder->filterByColumn('Post.category IN (1,2,3)');

limit($maxResults, $offset = null) : EntityQueryBuilder | 限制结果

// SELECT * FROM Entity\Post Post LIMIT 0, 10
$queryBuilder->limit(10);

// SELECT * FROM Entity\Post Post LIMIT 15, 10
$queryBuilder->limit(10, 15);

fetchAll($parameters = array()) : EntityClass[] | 获取结果

// SELECT * FROM Entity\Post Post -> Post[]
$queryBuilder->fetchAll();

// SELECT * FROM Entity\Post Post LIMIT 0, 10 -> Post[]
$queryBuilder->filterByStatement('Post.title = :title')->fetchAll(['title' => 'Post 1']);

fetchOne($parameters = array()) : EntityClass | 获取第一个结果

// SELECT * FROM Entity\Post Post LIMIT 0, 1 -> Post
$queryBuilder->fetchOne();

fetchScalar($parameters = array()) : int|string|float|null | 获取标量结果

// SELECT COUNT(*) FROM Entity\Post Post LIMIT 0, 1 -> int
$queryBuilder->select('COUNT(*)')->fetchScalar();

DBAL 扩展

对DBAL类只有一个小的增强 - Connection::lockSafeUpdate,允许你在事务被锁定并失败的情况下重新启动查询。也许,这会展示如何通过自定义方法扩展Doctrine连接类。

如何配置

# config.yml
doctrine:
    dbal:
        wrapper_class: 'Weavora\Doctrine\DBAL\Connection'

使用示例

// Method will retry a query if it failed because of lock the first time
// You can specify the retry number as the 3rd argument
$doctrine->getConnection()->locksSafeUpdate("UPDATE posts SET category_id = :category", ['category' => 2]);

关于

稳定性

目前还不稳定。请自行承担使用风险。

要求

  • PHP 5.3或更高版本中的任何版本都应该可以
  • [可选] PHPUnit 3.5+ 执行测试套件(phpunit --version)

提交错误和功能请求

错误和功能请求在GitHub上跟踪

作者

Weavora LLC - http://weavora.com - http://twitter.com/weavora
还可以查看参与此项目的贡献者列表

许可

此库采用MIT许可 - 详细信息请参阅LICENSE文件