Gedmo doesn't fill dates on record flush - symfony

I am using Gedmo for it's Timestampable options, to automatically add created_at and updated_at dates but getting error:
Integrity constraint violation: 1048 Column 'created_at' cannot be null
Why they are not filled? That's how I am implementing it:
#[ORM\Column]
#[Gedmo\Timestampable(on: 'create')]
private ?\DateTime $createdAt;
#[ORM\Column]
#[Gedmo\Timestampable]
private ?\DateTime $updatedAt;
Doing the things as per the documentation. Am I missing something ?

Related

Why doctrine migrations ignore my index declaration?

I would like to create a table with an indexed columned to speed up searches.
Here is a sample:
#[ORM\Entity(repositoryClass: SettingRepository::class)]
#[ORM\Table(name: '`tr_setting`', indexes: [
new ORM\Index(columns: ['code'], name: 'idx_setting_code')
])]
class Setting
{
#[ORM\Column(type: 'string', length: 15)]
private ?string $code;
#[ORM\Column(type: 'text')]
private string $content;
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
private ?int $id;
// Getter and setter...
}
When I use DoctrineBundle migration, the file is generated, but index is ignored...
// ....
final class Version20220719140604 extends AbstractMigration
{
public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE SEQUENCE "tr_setting_id_seq" INCREMENT BY 1 MINVALUE 1 START 1');
$this->addSql('CREATE TABLE "tr_setting" (id INT NOT NULL, code VARCHAR(15) NOT NULL, content TEXT NOT NULL, PRIMARY KEY(id))');
}
For other projects, I already did it with annotations instead of attributes.
I carefully read this answer, but it doesn't help me.
I'm on PHP8.1.8, doctrine/orm 2.12.3 , doctrine-migrations: 3.2, postgresql: 13
My index shall be declared with this syntax:
#[
ORM\Entity(repositoryClass: SettingRepository::class),
ORM\Table(name: '`tr_setting`'),
ORM\Index(columns: ['code'], name: 'idx_setting_code'),
]
or this one:
#[ORM\Entity(repositoryClass: SettingRepository::class)]
#[ORM\Table(name: '`tr_setting`')]
#[ORM\Index(columns: ['code'], name: 'idx_setting_code')]

How to convert smallint to boolean in Symfony Form?

I have an entity that contains a smallint value:
#[ORM\Column(type: 'smallint')]
private $isActive;
And when I want to generate a form with $form = $this->createForm(UserTestType::class, $user) that uses CheckBox to represent this isActive value, I get the following error:
Unable to transform value for property path "isActive": Expected a Boolean.
Is there a way to solve this?

Relation with composite unique constraint (symfony + doctrine)

I'm trying to create relation where foreign key reference NOT to primary key but to composite unique constraint.
Why? Denormalize database schema for decrease join's count.
#[ORM\Entity(repositoryClass: CurrencyRepository::class)]
#[ORM\UniqueConstraint(fields: ['slug', 'type'])]
#[UniqueEntity(
fields: ['type', 'slug'],
message: 'This slug is already in use on that type.',
errorPath: 'slug',
)]
class Currency
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
private ?int $id;
#[ORM\Column(type: 'smallint', length: 1)]
private ?int $type;
#[ORM\Column(type: 'string', length: 25)]
private ?string $slug;
// ...
}
#[ORM\Entity(repositoryClass: ExchangeRateHistoryTypeRepository::class)]
class ExchangeRateHistoryType
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column(type: 'integer')]
private int $id;
#[ORM\ManyToOne(targetEntity: Currency::class)]
#[ORM\JoinColumn(name: 'currency_slug', referencedColumnName: 'slug', nullable: false)]
#[ORM\JoinColumn(name: 'currency_type', referencedColumnName: 'type', nullable: false)]
private ?Currency $currency;
php bin/console make:migration
php bin/console doctrine:migrations:migrate
All good. But when i try to add data to ExchangeRateHistoryType - error.
Client code:
$exchangeRateHistoryType = new ExchangeRateHistoryType();
$exchangeRateHistoryType->setCurrency($currency);
// ...
$this->entityManager->persist($exchangeRateHistoryType);
$this->entityManager->flush();
In BasicEntityPersister.php line 674: Warning: Undefined array key "slug"
What i'm doing wrong?
Doctrine's documentation:
It is not possible to use join columns pointing to non-primary keys. Doctrine will think these are the primary keys and create lazy-loading proxies with the data, which can lead to unexpected results. Doctrine can for performance reasons not validate the correctness of this settings at runtime but only through the Validate Schema command.
Source: https://www.doctrine-project.org/projects/doctrine-orm/en/2.10/reference/limitations-and-known-issues.html#join-columns-with-non-primary-keys

Symfony entity on Postgres view

I need to map an entity to a Postgres view which doesn't have primary id, no id defined.
Views in Postgresql can't have primary keys. On the same time Doctrine entities need a primary key defined.
Can I create a "virtual" property some like this?
class MyEntityClass
{
/**
* #var int
*
* #ORM\Id
* #ORM\Column(type="uuid")
*/
private $id;
public function getId(): string
{
return generate_unique_id_just_for_my_join()
}
}
This entity need to be used only for select data. Never for insert/update.
Problem solved using Doctrine somposite primary keys
https://www.doctrine-project.org/projects/doctrine-orm/en/2.7/tutorials/composite-primary-keys.html

Relation OneToOne cascade="persist, remove" not work

I have a relationship OneToOne bidirectional, configurate how cascade persis, remove, but when i call controller eliminarPersonaFisicaAction, this show the next error:
An exception occurred while executing 'DELETE FROM entidad WHERE id = ?' with params [84]:
SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails (`xxx`.`personafisica`, CONSTRAINT `FK_D55D20169B1A19BB` FOREIGN KEY (`id_entidad`) REFERENCES `entidad` (`id`))
This is my configure in entities:
First entity:
//code
/**
* #ORM\OneToOne(targetEntity="XXX\EntidadBundle\Entity\PersonaFisica", mappedBy="entidad", cascade={"persist", "remove"})
* #ORM\JoinColumn(name="persona_fisica_id", referencedColumnName="id")
**/
private $personaFisica;
//code
Second entity:
//code
/**
* #ORM\OneToOne(targetEntity="XXX\EntidadBundle\Entity\Entidad", inversedBy="personaFisica", cascade={"persist", "remove"})
* #ORM\JoinColumn(name="id_entidad", referencedColumnName="id")
*/
protected $entidad;
//code
eliminarPersonaFisicaAction:
public function eliminarPersonaFisicaAction($id){
$em = $this->getDoctrine()->getManager();
$personaFisica = $em->getRepository("EntidadBundle:Entidad")->find($id);
if($personaFisica->getPresupuestosEnLosQueEsContacto()->isEmpty() && $personaFisica->getPresupuestos()->isEmpty() && $personaFisica->getDocumentos()->isEmpty() && $personaFisica->getAsignacionesExternas()->isEmpty()){
$em->remove($personaFisica);
}
$em->flush();
return $this->redirect($this->generateUrl('ver_personas_fisicas'));
}
Please note that cascade={"persist", "remove"} only affect the internal Doctrine2 persistence and removal. It has nothing to do with the database.
In order to tell DB to explicitly add 'onDelete' property to the column you should use onDelete="CASCADE"in JoinColumn config.
//code
/**
* #ORM\OneToOne(targetEntity="XXX\EntidadBundle\Entity\PersonaFisica", mappedBy="entidad", cascade={"persist", "remove"})
* #ORM\JoinColumn(name="persona_fisica_id", referencedColumnName="id", onDelete="CASCADE")
**/
private $personaFisica;
//code
You don't need to specify JoinColumn on two tables, it is enough that only one table have extra id field. From what I see in your code you should add JoinColumn to Entidad entity. That will make Entidad entity to be deleted when PersonaFisica is deleted.

Resources