duanqiao1926
2017-05-19 06:06
浏览 30
已采纳

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

I don't know if this is possible in symfony, that is getting the last array when using respository. In my controller a have this function

/**
 * @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;
}

this will show the single food that I need. In my repository I have this code

/**
     * 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;
    }

This code successfully displaying the data of food Foods

 - 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
     }

How can I get the last transaction of food? I just want to display the last part of transaction that is like this one.

update

     - id
     - name
     - price
     - packages
         - id
         - name_package
         - category
     - User
         - id
         - username
         - password
         - email
    - transaction []
         3 - {
             - id
             - date
             - emailStatus
             - email
         }
  • 写回答
  • 好问题 提建议
  • 关注问题
  • 收藏
  • 邀请回答

5条回答 默认 最新

  • doudiecai1572 2017-05-22 01:20
    已采纳

    Thanks everyone here. I have an idea now how to solve. What I did is just a simple way. In my Food entity class, I add this method

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

    and then in my Food controller

     /**
         * @param $id
         * @return Food
         */
        public function getFood($id)
        {
    
            $em = $this->getDoctrine()->getManager();
            $food = $em->getRepository("AppBundle:Food")->find($id);
            $food->getLastTransactions();
    
    
            return $food;
        }
    

    I can now control the transaction and then you can see the full info of my food entity.

    已采纳该答案
    评论
    解决 无用
    打赏 举报
  • douxing8855 2017-05-19 06:10

    You could slice your transaction array and retrieve a new one with only the last item in it. Then you can reset the indices for the array and fetch the only item with the index 0.

    $transaction = array_values(array_slice($food, -1))[0];
    
    评论
    解决 无用
    打赏 举报
  • dtvfxzq3802 2017-05-19 06:12

    I assume that transation field (containing transactions) in Food is an ArrayCollection

    If so, there's a method last() which returns last element from the collection.

    So you can do something like this, if you have getter for transactions:

    $food->getTransaction()->last();
    
    评论
    解决 无用
    打赏 举报
  • douluanzhao6689 2017-05-19 06:21

    Also you can add method to Food class

    /**
     * @return Transaction|null
     */
    public function getLastTransaction()
    {
        $transactions = $this->getTransaction();
    
        return !empty($transactions) ? end($transactions) : null;
    }
    
    评论
    解决 无用
    打赏 举报
  • doubai9014 2017-05-19 07:07

    There are several ways to get what you need.

    First, update your findById() method. Since you look for Id, I assume you'd like to get only one record, right ?

    /**
         * 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;
    }
    

    then navigate to your Food entity an extend your relation to transaction => add fetch="EXTRA_LAZY" This is a important Part for later "filtering"

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

    then stay in your Food entity add additional method(s) for transaction depending on your current usecase(s).

    for example:

    that would be your regular transactions getter which gives you all transaction for current Food as ArrayCollection

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

    so the easy way would be to use first()/last() methods

    like

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

    now you have two (or even more) separate method(s) for a different task(s)

    but... first() and last() are handy wrappers for php's native reset() and end() functions, so if your Food have say 100 transaction, doctine will fetch all from DB and hydrate to Transaction entity just only to get first. Not the best way.

    at this point you can make use of Doctrine's Criteria

    so now you can update your getOnlyLastTransaction() method with following

    /**
     * @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 );
    }
    

    the best part of it -> you get still ArrayCollection back so all methods like first(), last() and isEmpty() are still available, the only difference is you have a collection of one

    so my fav is to extend method with param $as_object like

    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);
    }
    

    Now you have full controll and only one transaction in a separate method, so if you still want all of then, you can use your regular getter

    usage: in your controller

    /** * @param $id * @return Food */ public function 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;
    

    }

    GOTCHAS

    last() and first() could lead to a confusing if someone changed default sorting of your relation via @ORM\OrderBy({...}) For Example. If your relation looks like this

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

    So now when you call

    $food->getTransaction()->last() and awaiting the last record, you get the last entry of colllection which in this case actualy the first record from DB

    评论
    解决 无用
    打赏 举报

相关推荐 更多相似问题