How to Access Discriminator Field from PHP in Doctrine2

Can I access discriminator field from php in doctrine2?

Extending what beberlei said, you could declare some constants in the Attribute class, and an abstract getType() function. Then, overload it in every derived attribute class.

Something like:

abstract class Attribute {
const TYPE_BOOL = 0;
const TYPE_INT = 1;
...
abstract public function getType();
}

class BooleanAttribute extends Attribute {
public function getType() {
return parent::TYPE_BOOL;
}
}

How to get the discriminator type from repository

According to the docs, you can use INSTANCE OF to do it.

As you want to use the discriminator values, using the class metadata and constructing a CASE expression, you can select the value for each instance:

$meta = $em->getMetadataFactory()->getMetadataFor(Flux::class);
$discriminatorMap = $meta->discriminatorMap;
$caseQl = '(case';
foreach ($discriminatorMap as $fieldValue => $class) {
$caseQl .= " when p INSTANCE OF " . $class . " then '" . $fieldValue . "'";
}
$caseQl .= ' else 0 end) as HIDDEN atype';
$qb->addSelect($caseQl);
$qb->having("atype LIKE :type");
$qb->setParameter('type', '%FluxNew%');

Note that the field atype is defined as HIDDEN, so that it is not returned in the result.

Also for this solution having needs to be used, not where(since the atype is a calculated value).

Alternatively, you could use Doctrine\ORM\Query::HINT_INCLUDE_META_COLUMNS to include the foreign key column values in the result:

$paginator->getQuery()
->setHint(\Doctrine\ORM\Query::HINT_INCLUDE_META_COLUMNS, true)
->setHydrationMode(\Doctrine\ORM\Query::HYDRATE_ARRAY);

References:

  • how to get discriminator map values
  • Calculated column
  • Force 'fetch joined' relations to include IDENTITY of their ManyToOne relations using HYDRATE_ARRAY?

Map a discriminator column to a field with Doctrine 2

Sadly, there is no documented way to map the discr column to an entity. That's because the discr column is really part of the database and not the entity.

However, it's quite common to just put the discr value directly in your class definition. It's not going to change and you will always get the same class for the same value anyways.

class Person
{
protected $discr = 'person';

class Employee extends Person
{
protected $discr = 'employee';

Doctrine 2 - How to use discriminator column in where clause

I think that you should use INSTANCE OF

Doctrine Inheritance: Discriminator from Entity attribute and not table column?

Given the fact that shopType is a rather static property (in the sense that it will always be the same for all instances of a class) you can simply define the shopType as default for the property, and use the existing column as discriminator column:

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
* @ORM\Entity
* @ORM\InheritanceType("SINGLE_TABLE")
* @ORM\DiscriminatorColumn(name="shopType", type="string")
* @ORM\DiscriminatorMap({"local" = "LocalShop", "foreign" = "ForeignShop"})
*/
class Shop
{
protected const TYPE_LOCAL = 'local';
protected const TYPE_FOREIGN = 'foreign';

// ...
}

/**
* @Entity
*/
class LocalShop extends Shop
{
protected $shopType = Shop::TYPE_LOCAL;
// ...
}

/**
* @Entity
*/
class ForeignShop extends Shop
{
protected $shopType = Shop::TYPE_FOREIGN;
// ...
}

Doctrine's hydrators will take a new instance of your class, which gets instantiated with all default values applied, and then write all the fetched information from the database to the mapped properties.

Since your property has the expected value in the defaults, and is not mapped, its correct default value will not be changed by the hydration process and have the expected value, even when fetched from the database.

In that process, the constructor is not called (Entities are either cloned or produced by Reflection's newInstanceWithoutConstructor), which is why the original code did not work.

Doctrine2 / querying discriminator value

It's not so much that you're doing something wrong, but there is a method to work around the issue. You can make it possible to return the card type with the following.

In class Card add:

public function getCardType()
{
return $this->discr;
}

in class MemberCard add:

protected $discr = 'member';

in class ClientCard add:

protected $discr = 'client';


Related Topics



Leave a reply



Submit