0

関連付けテーブル ( ) を介して、スポーツ クラス/コース ( courses) とそのトレーナー ( ) を選択する SQL ステートメントがあります。一部のコースには複数のトレーナーがいるため、関数を使用してトレーナー名を 1 つのフィールドに取得します。一部のトレーナー行は空 orであるため、トレーナーの句にand条件を追加します。trainerscourses_trainersGROUP_CONCAT(...)NULLtrainers.name IS NOT NULLtrainers.name != ""ONJOIN

SQL声明

SELECT
    courses.id AS id,
    GROUP_CONCAT(DISTINCT trainers.name SEPARATOR "|||") AS trainers
    ...
FROM
    courses
    ...
LEFT JOIN
    courses_trainers ON courses.id = courses_trainers.course_id
LEFT JOIN
    trainers ON trainer_id = trainers.id
    AND trainers.name IS NOT NULL
    AND trainers.name != ""
    ...
...
WHERE `courses`.`id` = '898'
GROUP BY
    courses.id
;

CourseTableクラスの OO バリアント

public function findOnceByID($id) { 
    $concatDelimiter = self::CONCAT_DELIMITER;
    $select = new Select();
    ...
    $select->columns(array(
        'id', ...
    ));
    $select->from($this->tableGateway->getTable());
    $select
        ...
        ->join('courses_trainers', 'courses.id = courses_trainers.course_id', array(), Select::JOIN_LEFT)
        ->join('trainers', 'trainer_id = trainers.id AND trainers.name IS NOT NULL AND trainers.name != ""', array(
            'trainers' => new Expression('GROUP_CONCAT(DISTINCT trainers.name SEPARATOR "' . $concatDelimiter . '")')
            ), Select::JOIN_LEFT)
        ...
    ;
    $where
        ->equalTo('courses.id', $id)
    ;
    $select->where($where, Predicate::OP_AND);
    $select->group('courses.id');
    $resultSet = $this->tableGateway->selectWith($select);
    return $resultSet;
}

生成されたJOINコードは次のようになります。

LEFT JOIN
    `courses_trainers` ON `courses`.`id` = `courses_trainers`.`course_id`
LEFT JOIN
    `trainers` ON `trainer_id` = `trainers`.`id`
    AND `trainers`.`name` `IS` `NOT` `NULL`
    AND `trainers`.`name` `!`= `"``"`

だから、ここに多くの引用があります。

などを引用してはならないことISをZF に「説明」する方法は?NOT"

4

2 に答える 2

0

このメソッドは、句joinの 2 番目のパラメーターとして式を受け入れますON

->join('trainers', new Expression('trainer_id = trainers.id AND trainers.name IS NOT NULL AND trainers.name != ""'),
于 2013-04-17T13:58:11.583 に答える
0

引用を担当するのはZend\Db\Adapter\Platform\PlatformInterface#quoteIdentifierInFragment(...)(またはより正確にはその実装、この場合はZend\Db\Adapter\Platform\Mysql) で、2 番目の引数として「安全な単語」の配列を取得します。Zend\Db\Sql\Select#processJoins(...) を渡しますarray('=', 'AND', 'OR', '(', ')', 'BETWEEN', '<', '>')ISNOT!などはリストにないため、引用されています。

解決策は、 を拡張してZend\Db\Sql\Selectその を上書きしprocessJoins(...)、必要な追加の「安全な単語」をquoteIdentifierInFragment(...)呼び出しの 2 番目の引数のリストに追加することです。

<?php
namespace MyNamespace\Db\Sql;

use Zend\Db\Adapter\Driver\DriverInterface;
use Zend\Db\Adapter\StatementContainerInterface;
use Zend\Db\Adapter\ParameterContainer;
use Zend\Db\Adapter\Platform\PlatformInterface;
use Zend\Db\Sql\Select as ZendSelect;

class Select extends ZendSelect
{

    ...

    protected function processJoins(PlatformInterface $platform, DriverInterface $driver = null, ParameterContainer $parameterContainer = null)
    {
        ...
        // process joins
        $joinSpecArgArray = array();
        foreach ($this->joins as $j => $join) {
            ...
            $joinSpecArgArray[$j][] = ($join['on'] instanceof ExpressionInterface)
                ? $this->processExpression($join['on'], $platform, $driver, $this->processInfo['paramPrefix'] . 'join' . ($j+1) . 'part')
                : $platform->quoteIdentifierInFragment($join['on'], array('=', 'AND', 'OR', '(', ')', 'BETWEEN', '<', '>', '!', 'IS', 'NULL', 'NOT', '"')); // on
            ...
        }

        return array($joinSpecArgArray);
    }

    ...

}
于 2013-04-17T12:57:10.913 に答える