如何在实体symfony中显示最后一个数组?

时间:2017-05-19 06:06:17

标签: php symfony

我不知道symfony中是否可以这样做,即在使用存储库时获取最后一个数组。在我的控制器中有一个这个功能

/**
 * @param $id
 * @return Food
 */
public function getFood($id)
{

    $em = $this->getDoctrine()->getManager();
    $food = $em->getRepository("AppBundle:Food")->findById($id);
    if (!$food) {
        throw $this->createNotFoundException("Invalid Food");
    }

    return $food;
}
这将显示我需要的单一食物。在我的存储库中,我有这个代码

/**
     * Display Food and get the last transaction
     * @param $id
     */
    public function findById($id){

        $query =  $this->createQueryBuilder(f)
            ->where('f.id = :id')
            ->setParameter('id', $id)
            ->getQuery()
            ->getResult()[0];

        return $query;
    }

此代码成功显示食物数据 食品

 - id
 - name
 - price
 - packages
     - id
     - name_package
     - category
 - User
     - id
     - username
     - password
     - email
- transaction []
    1 - {
         - id
         - date
         - emailStatus
         - email
     }
    2 - {
         - id
         - date
         - emailStatus
         - email
     }
    3 - {
         - id
         - date
         - emailStatus
         - email
     }

我怎样才能获得食物的最后一笔交易?我只想显示与此类似的交易的最后部分。

更新

     - id
     - name
     - price
     - packages
         - id
         - name_package
         - category
     - User
         - id
         - username
         - password
         - email
    - transaction []
         3 - {
             - id
             - date
             - emailStatus
             - email
         }

5 个答案:

答案 0 :(得分:1)

您可以对事务数组进行切片并检索仅包含其中最后一项的新事务数组。然后,您可以重置数组的索引并获取索引为0的唯一项。

$transaction = array_values(array_slice($food, -1))[0];

答案 1 :(得分:1)

我认为transation中的Food字段(包含交易)是ArrayCollection

如果是这样,有一个方法last(),它返回集合中的最后一个元素。

所以你可以做这样的事情,如果你有交易的吸气剂:

$food->getTransaction()->last();

答案 2 :(得分:1)

您还可以向Food class

添加方法
/**
 * @return Transaction|null
 */
public function getLastTransaction()
{
    $transactions = $this->getTransaction();

    return !empty($transactions) ? end($transactions) : null;
}

答案 3 :(得分:1)

有几种方法可以满足您的需求。

首先,更新您的findById()方法。既然你在寻找我,我认为你只想得到一个记录,对吗?

/**
     * Display Food and get the last transaction
     * @param $id
     * @return Food|null
     */

public function findById($id){

  $query =  $this->createQueryBuilder('f')
            ->where('f.id = :id')
            ->setParameter('id', $id)
            ->getQuery()
            ->getOneOrNullResult();     
            // returns single Object instead of an array of Objects 

  return $query;
}

然后导航到您的Food实体,扩展您与交易的关系=>添加fetch="EXTRA_LAZY"这是以后“过滤”的重要部分

/**
* @ORM\OneToMany(targetEntity="...", mappedBy="...", fetch="EXTRA_LAZY")
*/
private $transaction;

然后留在您的Food实体中,根据您当前的用例添加其他方法进行交易。

例如:

这将是您的常规事务getter,它为您提供当前Food的所有事务作为ArrayCollection

public function getTransaction()
{
  return $this->transaction;
}

所以简单的方法是使用first()/last()方法

喜欢

public function getOnlyLastTransaction()
{
  return $this->transaction->last();
}

现在你有两个(甚至更多)单独的方法用于不同的任务

但是...... first()last()是php的原生reset()end()函数的方便包装器,所以如果你的Food说100个事务, doctine将从DB中获取所有内容,并且仅为了获得第一个而保存到Transaction实体。不是最好的方式。

此点您可以使用Doctrine's Criteria

现在您可以使用以下

更新getOnlyLastTransaction()方法
/**
 * @return ArrayCollection
 */
public function getOnlyLastTransaction ()
{
    // here you filter your transactions at SQL level
    // so you could sa, get all transaction of current food ordered by ID in desc order and get only ONE of them by LIMIT 1
    $criteria = Criteria::create();
    $criteria->orderBy( [ 'id' => Criteria::DESC ] ); // id of transaction Entity
    // $criteria->orderBy(['date' => Criteria::DESC ]); // to get last by date
    $criteria->setMaxResults( 1 ); // LIMIT 1

    return $this->transaction->matching( $criteria );
}

最好的部分 - >你仍然得到ArrayCollection,所以所有方法如first()last()isEmpty()仍然可用,唯一的区别是你有一个

所以我最喜欢用param $as_object扩展方法,如

public function getOnlyLastTransaction ( $as_object = TRUE )
{
    // here you filter your transactions at SQL level
    // so you could sa, get all transaction of current food ordered by ID in desc order and get only ONE of them by LIMIT 1
    $criteria = Criteria::create();
    $criteria->orderBy( [ 'id' => Criteria::DESC ] ); // id of transaction Entity
    // $criteria->orderBy(['date' => Criteria::DESC ]); // to get last by date
    $criteria->setMaxResults( 1 ); // LIMIT 1
    $found = $this->transaction->matching( $criteria );
    return ($as_object ? $found->first() : $found);
}

现在你在一个单独的方法中拥有完全控制和只有一个交易,所以如果你仍然需要全部,那么你可以使用常规的getter

控制器中的

用法

/ **  * @param $ id  * @return Food  * / 公共函数getFood($ id) {

$em = $this->getDoctrine()->getManager();
$food = $em->getRepository("AppBundle:Food")->findById($id);
if (fasle === $food instanceof Food ) {
    throw $this->createNotFoundException("Invalid Food");
}
$lastTrans = $food->getOnlyLastTransaction();
dump($lastTrans);


return $food;

}

<强>陷阱

如果有人通过last()更改了您的关系的默认排序,则

first()@ORM\OrderBy({...})会导致混淆 例如。如果您的关系看起来像这样

/**
 * @ORM\OneToMany(targetEntity="...", mappedBy="...", fetch="EXTRA_LAZY")
 * @ORM\OrderBy({"date"="DESC"})
 */
private $transaction;

现在当你打电话

$food->getTransaction()->last()等待最后一条记录,你得到最后一个条件,在这种情况下,实际上是来自DB的第一条记录

答案 4 :(得分:0)

谢谢大家。我现在有一个想法如何解决。我所做的只是一个简单的方法。在我的Food实体类中,我添加了这个方法

/**
     * @return Transactions
     */
    public function getLastTransactions()
    {
        $this->transactions = $this->getTransactions()->last();

        return $this->transactions;
    }

然后在我的食物控制器中

 /**
     * @param $id
     * @return Food
     */
    public function getFood($id)
    {

        $em = $this->getDoctrine()->getManager();
        $food = $em->getRepository("AppBundle:Food")->find($id);
        $food->getLastTransactions();


        return $food;
    }

我现在可以控制交易,然后您可以看到我的食品实体的完整信息。