0

まず、この質問が長くなってしまったことをお詫びしたいと思います。多くの背景情報がないと、質問を適切に行う方法がわかりませんでした。我慢してください。

スキルを磨くために使用する単純なアプリケーションを、独自のカスタム データベース アクセス スキーマから Doctrine に変換しています。私が Doctrine を選んだ理由はいくつかありますが、そのうちの 1 つとして、日常の仕事で定期的に使用していることが挙げられます。また、Doctrine が一般的に非常に薄い (見た目の) レイヤーであり、多くの機能を追加しながら邪魔にならないことも気に入っています。

usersデータベース内のテーブルのデータ アクセス レイヤーを Doctrine に変換しました。いくつかの細かい点を除いて、非常に目立たない (単にゲッターとセッター)。

  • 特定のクエリ用のカスタム リポジトリが必要で、
  • UserオブジェクトにはArrayCollection、コンストラクターでインスタンス化され たデフォルトがあります

namespace model\entities;

/**
 * @Entity(repositoryClass="model\repositories\UserRepository")
 * @Table(name="users")
 */
class User{
    /* snip variables */

    /**
     * @OneToOne(targetEntity="Authentication", mappedBy="user", cascade="persist")
     */
    private $authentication;

    /**
     * @OneToMany(targetEntity="Contact", mappedBy="user", cascade="persist")
     */
    private $contacts;

    public function __construct() {
        $this->contacts = new \Doctrine\Common\Collections\ArrayCollection();
    }

    /* snip getters and setters */  
}

私の古いスキーマには、usersテーブルのサブセットを選択する 2 つのカスタム クエリがありました。

彼らです:

public function search( $term = null ){
    if( !$term ){
        $sql = "SELECT *
                FROM
                " . $this->tableName . "
                ORDER BY
                    lname ASC,
                    fname ASC";
        $res = $this->db->q($sql);
    }
    else{
        $sql = "SELECT *
                FROM
                " . $this->tableName . "
                WHERE
                    lname LIKE ?
                    OR fname LIKE ?
                    OR CONCAT(fname, ' ', lname) LIKE ?
                ORDER BY
                    lname ASC,
                    fname ASC";
        $values = array( '%' . $term . '%', '%' . $term . '%', '%' . $term . '%' );
        $res = $this->db->qwv( $sql, $values );
    }

    return $this->wrap( $res );
}

と:

public function getAllWithRestrictions(){
    $sql = "SELECT *
            FROM
            " . $this->tableName . "
            WHERE
                userid IN
                (
                    SELECT
                        userid
                    FROM
                        " . $this->uiPre . "authentications
                    WHERE
                        resetPassword = 1
                        OR disabled = 1
                )";
    $res = $this->db->q( $sql );

    return $this->wrap($res);
}

where$this->dbは薄いPHP PDO ラッパーであり、ゼロ/単一/複数の行が返され、それらをデータ オブジェクトに変換する$this->wrap魔法を行います。

さて、これを Doctrine に変換するのはとても簡単だと思いました。の場合は、getAllWithRestrictions単に->where->orWhereセットですよね?もうわからない。

クエリを作成するために使用したこれらの Stackoverflow の質問を見つけましたが、エラーが次々と発生しており、うさぎの穴のどこまで行く必要があるのか​​ わかりません。

SQL 複数の並べ替えとグループ化
Doctrine を使用した複数の列による並べ替え
Doctrine: 複数 (whereIn OR whereIn) クエリ?
教義 - またはどこで?

現在、私のカスタム リポジトリは次のようになっていますが、長い間いじっていたため、正確に近いとは言えません。これは、機能すると思われるものの寄せ集めにすぎません。

<?php
namespace model\repositories;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Query\Expr;

class UserRepository extends EntityRepository{
    public function search( $term ){
        if( !$term ){
            return $this
                    ->_em
                    ->createQuery('SELECT u FROM model\entities\User u')
                    ->addOrderBy( 'u.lname' )
                    ->addOrderBy( 'u.fname' )
                    ->getResult();
        }
        else{
            $qb     = $this->_em->createQueryBuilder();

            $qb ->select(array('u'))
                ->from('model\entities\User', 'u')
                ->where( $qb->expr()->like( 'u.lname', '?1' ) )
                ->orWhere( $qb->expr()->like( 'u.fname', '?2' ) )
                ->orWhere( $qb->expr()->like( 'CONCAT(u.fname, \' \', u.lname)', '?3' ) )
                ->addOrderBy( 'u.lname' )
                ->addOrderBy( 'u.fname' )
                ->setParameters(
                    array(
                        1 => $term,
                        2 => $term,
                        3 => $term
                    )
                );

            $query = $qb->getQuery();
            return $query->getResult();
        }
    }

    public function getAllWithRestrictions(){
        $qb     = $this->_em->createQueryBuilder();

        $qb ->select(array('u'))
            ->from('model\entities\User', 'u')
            ->add('where', $qb->expr()->orx(
               $qb->expr()->eq('u.disabled', '1'),
               $qb->expr()->eq('u.resetPassword', '1')
           ));

        $query = $qb->getQuery();
        return $query->getResult();
    }
} 

getAllWithRestrictions編集:間違ったテーブルでクエリを実行していることに気付きました (そうである必要がありauthenticationsます)。ただし、次のようなことを行う方法も知る必要があり、$qb->expr()->eq('u.Authentication.disabled = '1')DQL が実際にどのように機能するかはわかりません。

私が今得ている特定のエラーは

  • Fatal error: Uncaught exception 'Doctrine\ORM\Query\QueryException' with message 'SELECT u FROM model\entities\User u WHERE u.lname LIKE ?1 OR u.fname LIKE ?2 OR CONCAT(u.fname, ' ', u.lname) LIKE ?3 ORDER BY u.lname ASC, u.fname ASC'

に続く

  • Doctrine\ORM\Query\QueryException: [Syntax Error] line 0, col 99: Error: Expected Doctrine\ORM\Query\Lexer::T_CLOSE_PARENTHESIS, got ','

しかし、DQL/Query Builder をどのように構築するかによって、さまざまな問題が発生しました。

繰り返しますが、これら 2 つの SQL クエリは簡単に Doctrine / DQL に変換できると思っていました。Doctrineを介して生のSQLに頼らずにこれを行いたいと思います(私がリンクした受け入れられた回答の多くが示唆しているように)。これは簡単でなければなりません。 エレガントな Doctrine クエリを作成する方法を知っている人はいますか?

4

2 に答える 2

1

doctrineの関数パーサーによるとCONCAT、カンマで区切られた 2 つのパラメーターのみが必要です。

//Doctrine/ORM/Query/AST/Functions/ConcatFunction.php
$parser->match(Lexer::T_IDENTIFIER);
$parser->match(Lexer::T_OPEN_PARENTHESIS);

$this->firstStringPrimary = $parser->StringPrimary();
$parser->match(Lexer::T_COMMA);
$this->secondStringPrimary = $parser->StringPrimary();

$parser->match(Lexer::T_CLOSE_PARENTHESIS);

したがって、この

->orWhere( $qb->expr()->like( 'CONCAT(u.fname, \' \', u.lname)', '?3' ) )

する必要があります

->orWhere( $qb->expr()->like( 'CONCAT(u.fname, u.lname)', '?3' ) )

これによりエラーはスローされませんが、実際に必要なものではない場合があります。その場合、独自のカスタム関数をロールする必要がありますCONCAT:)

于 2013-02-19T03:53:44.330 に答える
1

上記の @Broncha の回答 (ネストされたCONCATlikeを追加することでエラーを解決するのに役立ちました) に加えて、必要なエンティティに結合し、次のように結合に句を'CONCAT(u.fname, CONCAT(\' \', u.lname))'追加することで、他の関数を修正できます。WHERE

$qb ->select(array('u'))
    ->from('model\entities\User', 'u')
    ->leftJoin('u.authentication', 'a')
    ->add('where', $qb->expr()->orx(
        $qb->expr()->eq('a.disabled', '1'),
        $qb->expr()->eq('a.resetPassword', '1')
    ));
于 2013-02-20T01:21:24.217 に答える