简体   繁体   中英

How do I search by properties of entity which do not have @Column anotation in Doctrine2?

 /**
* @ORM\Entity
*/
class Order extends BaseEntity
{
// this is trait for @Id
use Identifier;

/**
* @ORM\Column(type="integer")
*/
protected $costPerUnit;

/**
* @ORM\Column(type="integer")
*/
protected $numberOfUnits;

// i want to search by this property
protected $totalCost;

public function getTotalCost()
{
 return $this->numberOfUnits * $this->costPerUnit;
}

}

I have an entity like this and I'd like to be able to do for example

$orderRepository->findOneByTotalCost('999')
$orderRepository->findBy(['totalCost' => '400']);

Is this possible in Doctrine2? Or would I go about it differently?

Like I said in my comments, it's likely you're wrestling with an issue that shouldn't have occurred in the first place. Still, having a SUM value mapped to a property is possible using doctrine, in a variety of ways: Check the aggregate field docs to find out which would solve your problem best.

To my eyes, is that you're using entities as more than what they really are: Entities represent records in a database, Doctrine is a DBAL. Searching data using entities (or repositories) is querying the database. You could solve the problem by adding custom methods to your entity manager or a custom repository class that'll query all of the data required to compute the totalCost value for all entities, and return only those you need. Alternatively, use the connection from your DBAL to query for the id's you're after (for example), then use those values to get to the actual entities. Or, like I said before: use aggregate fields.


The problems you have with the findOneByTotalCost and findBy examples you show is that the first requires you to write a method Called findOneByTotalCost yourself. The problem with your use of findBy is simply that your argument is malformed: the array should be associative: use the mapped column names as keys, and the values are what you want to query for:

$repo->findBy(
    ['totalCost' => 400]
);

is what you're looking for, not ['totalCost', 400] . As for the entity itself, you'll need to add an annotation:

Yes it is, judging by your use of @ORM\\Entity annotations in the doc-blocks, this ought to do it:

/**
 * @ORM\Column(type="string", length=255)
 */
protected $regioun = 'Spain';

The update the table, and you'll be able to:

$entities = $repo->findBy(
    ['region' => 'Spain']
);

Don't forget that this code represents a table in a DB: you can search on any of the fields, but use indexes, which you can do by adding annotations at the top of your class definition:

/**
 * @ORM\Table(name="tblname", indexes={
 *  @ORM\Index(name="region", columns={"region"})
 * })
 */
class Foo
{}

As ever: in DB's, indexes matter

You should write a method findOneByTotalCost on your entity repository, something like:

public function findOneByTotalCost ($queryParams){

    $query = 'select o
                from <yourEntity> o
               where o.numberOfUnits * o.costPerUnit = :myParam';


    $dql = $this->getEntityManager()->createQuery($query);
    $dql->setParameter('myParam', $queryParams);       

    return $dql ->execute();


}

Them, $orderRepository->findOneByTotalCost('999') should work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM