How do I order by a property that isn't a DB column using Doctrine?
Asked Answered
I

1

2

When defining a relationship, there is a property on the related model (not a DB column), but I would like to sort by it (in the @OrderBy annotation).

I have a base model that is extended using single table inheritance. The property in question is basically an order property that is specified in each child class, but is not saved to the DB.

(I don't want to add an order column to the DB table, since the ordering depends purely on which child class the discriminator is mapped to. There is already a unique constraint so that each child class can be used no more than once in the relationship.)

Here's a really simplified version of my code...

Base entity:

/**
 * @ORM\Entity
 * @ORM\Table(name="base")
 * @ORM\InheritanceType("SINGLE_TABLE")
 * @ORM\DiscriminatorColumn(name="class_name", type="string")
 *
 * @ORM\DiscriminatorMap({
 *   "Base" = "Models\Base",
 *   "ChildA" = "Models\ChildB",
 *   "ChildB" = "Models\ChildA"
 * })
 **/
class Base 
{
    /** @ORM\Column(type="string") **/
    protected $class_name;

    /**
     * @ORM\ManyToOne(targetEntity="Related", inversedBy="collection")
     **/
    protected $related;

    // this is just a plain ol' property (not in the DB)
    protected $order;

    public function getClassName()
    {
        return $this->class_name;
    }
}

Children:

/**
 * @ORM\Entity
 * @ORM\Table(name="child_a")
 **/
class ChildA extends Base
{
    $order = 1;
}

/**
 * @ORM\Entity
 * @ORM\Table(name="child_b")
 **/
class ChildB extends Base
{
    $order = 2;
}

Related entity:

/**
 * @ORM\Entity
 * @ORM\Table(name="related")
 **/
class Related
{
    /**
     * @ORM\OneToMany(targetEntity="Base", mappedBy="related")
     * @ORM\OrderBy({"order"="ASC"})
     **/
    protected $collection;

    public function getCollection()
    {
        $em = App::make('Doctrine\ORM\EntityManagerInterface');

        // map each Base instance to the appropriate child class
        return $this->collection->map(function ($base) use ($em) {
            $class_name = $base->getClassName();
            return $em->find($class_name, $base->getId());
        });
    }
}

Is it possible to use the order property for ordering the collection relationship? (Ordering based on class_name using a switch-like construct would also be valid, but I haven't found any way to do that either, and it would be harder to maintain.)

Thanks in advance!

Industrials answered 21/9, 2015 at 17:32 Comment(1)
Possibly related: #19406366Industrials
T
1

The directive beginning with ORM is very much telling Doctrine you're doing referencing a property that has a relationship with a table field. You can't use ORM directives on fields that don't exist. Doctrine annotations: OrderBy

You would have to implement this in a function, best in the model itself (within your getCollection() function), or if you're using a framework like Symfony place it in a function of the repository class for this entity. You'd have to use PHP sorting functions to do this. SQL/DQL won't work either because the property isn't related to a field in the table.

Tva answered 9/10, 2015 at 4:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.