0

我在我的 Repository 类中编写了这个函数,以从 Doctrine 接收一个简单的键值。没有内置的 Doctrine 功能可以做到这一点吗?(我找不到它)。或者也许可以改进代码。

这是我的功能:

public function getListBy($criteria=null, $key, $value) {
    $dql = "SELECT i.".$key." as k,
                   i.".$value." as v
              FROM MbFooBundle:Input i";

    if (isset($criteria) && is_array($criteria)) {
        foreach($criteria as $cKey => $cValue) {
            if (!isset($where))
                $where = " WHERE ";
            else
                $where .= " AND ";

            $where .= "i.".$cKey." = ".(is_numeric($cValue) ? $cValue : "'".$cValue."'");
        }

        $dql .= $where;
    }

    $query = $this->getEntityManager()
        ->createQuery($dql);

    $result = $query->getArrayResult();
    $list = array();

    if (count($result)) {
        foreach($result as $data) {
            $list[$data['k']] = $data['v'];
        }
    }

     return $list;
}
4

1 回答 1

2

我不会这样做的。然而,这段代码很容易受到SQL 注入的影响,但它也违反了一些标准

这是我的想法。
我将创建一种方法来操纵标准教义的findBy的结果

/**
 * Data Manipulator
 */
class DataManipulator
{
    /**
     * Associates any traversable input into its key and value
     *
     * @param  mixed  $input A Traversable input
     * @param  string $key   Key to associate
     * @param  string $value Value to associate
     * @return array  Associated array
     *
     * @throws InvalidArgumentException When Input is not traversable
     */
    public function associate($input, $key, $value)
    {
        if (!is_array($input) && !($input instanceof Traversable)) {
            throw new InvalidArgumentException("Expected traversable");
        }

        $out = array();

        foreach ($input as $row) {
            $out[$this->getInput($row, $key)] = $this->getInput($row, $value);
        }

        return $out;
    }

    /**
     * Fetches the input of a given property
     *
     * @param  mixed  $row  An array or an object
     * @param  string $find Property to find
     * @return mixed  Property's value
     *
     * @throws UnexpectedValueException When no matching with $find where found
     */
    protected function getInput($row, $find)
    {
        if (is_array($row) && array_key_exists($find, $row)) {
            return $row[$find];
        }

        if (is_object($row)) {
            if (isset($row->$find)) {
                return $row->$find;
            }

            $method = sprintf("get%s", $find);

            if (method_exists($row, $method)) {
                return $row->$method();
            }
        }

        throw new UnexpectedValueException("Could not find any method to resolve");
    }
}

然后你就可以使用它了

$em      = $this->getDoctrine()->getManager();
$results = $em->getRepository('AcmeFooBundle:Input')
               ->findBy(array('category' => 'foo'));

$manipulator = new DataManipulator;
$filtered    = $manipulator->associate($results, 'key', 'value');

你可以看到它工作


如果您只需要选择部分对象,您应该在您的存储库 中创建一个方法来获取您的部分输入。
这个函数只能获取对象,不能关联它的内容。

public function findPartialBy(array $values, array $criterias = array())
{
    $qb = $this->createQueryBuilder('i');
    $qb->select($values);

    foreach ($criterias as $key => $value) {
        $qb->andWhere(sprintf("i.%s", $key), sprintf(":%s", $key))
        $qb->setParameter(sprintf(":%s", $key), $value);
    }

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

然后你就可以使用它了

$fetch   = array('key', 'value');
$em      = $this->getDoctrine()->getManager();
$results = $em->getRepository('AcmeFooBundle:Input')
               ->findPartialBy($fetch, array('category' => 'foo'));

$manipulator = new DataManipulator;
$filtered    = $manipulator->associate($results, 'key', 'value');
于 2013-08-21T15:32:14.187 回答