-1

I want to automatically add columns (that are in all my entities) like 'lastEditedTime' and 'createdTime' to DQL queries but I don't know if it is possible?

I already did a SQLFilter to add constraint, but didn't find a solution to add columns automatically to each results...

Does someone have an idea?

Regards

FindL
  • 495
  • 6
  • 25

2 Answers2

0

One of the best ways to do this is to use extentions or filters or entity manager hooks

Filter to add SQL More about them check symfonycast

<?php
namespace Example;
use Doctrine\ORM\Mapping\ClassMetadata,
    Doctrine\ORM\Query\Filter\SQLFilter;

class MyLocaleFilter extends SQLFilter
{
    public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAlias)
    {
        // Check if the entity implements the LocalAware interface
        if (!$targetEntity->reflClass->implementsInterface('LocaleAware')) {
            return "";
        }

        return $targetTableAlias.'.locale = ' . $this->getParameter('locale'); // getParameter applies quoting automatically
    }
}

Hooks :

<?php

/** @Entity @HasLifecycleCallbacks */
class User
{
    // ...

    /**
     * @Column(type="string", length=255)
     */
    public $value;

    /** @Column(name="created_at", type="string", length=255) */
    private $createdAt;

    /** @PrePersist */
    public function doStuffOnPrePersist()
    {
        $this->createdAt = date('Y-m-d H:i:s');
    }

    /** @PrePersist */
    public function doOtherStuffOnPrePersist()
    {
        $this->value = 'changed from prePersist callback!';
    }

    /** @PostPersist */
    public function doStuffOnPostPersist()
    {
        $this->value = 'changed from postPersist callback!';
    }

    /** @PostLoad */
    public function doStuffOnPostLoad()
    {
        $this->value = 'changed from postLoad callback!';
    }

    /** @PreUpdate */
    public function doStuffOnPreUpdate()
    {
        $this->value = 'changed from preUpdate callback!';
    }
}

This will allow you to write logic at desired point.

There are Doctrine Events as well, which you can utilize if your logic is complex or you want to move out and manage code separately.

If you have ability to change schema, you can use prebuilt traits that has all the logic you need as described in doctrine extensions package and avoid rewriting logic for many common usecases.

Maulik Parmar
  • 617
  • 4
  • 10
  • Hello, already did this to only get the entities with archive = 0, but know, I wan't to get for all my entities, the "editedAt" and "createdAt" fields, I don't want to add the select to each request but only at one place, is it possible? – FindL Sep 10 '21 at 07:17
0

From your question it is not completely clear what you would like to achieve. Do you want to add shared/common properties to entities? This can be done using by extending a common parent class.

Or, if the entity classes do not / cannot extend a common parent class, you could use a trait to add the common code to your classes.

The following example shows how to use a common parent calls and HasLifecycleCallbacks which will take care of automatically updating the timestamps:

Example:

/**
 * @ORM\MappedSuperclass
 * @HasLifecycleCallbacks
 */
abstract class TimeLoggedEntity {
    /**
     * @ORM\Column(type="datetime", nullable=true)
     */
    protected $lastEditedTime;

    /**
     * @ORM\Column(type="datetime", nullable=true)
     */
    protected $createdTime;

    ...

    /**
     * @ORM\PrePersist
     */
    public function prePersist() {
        $this->createdTime = \DateTime();
        $this->lastEditedTime = \DateTime();
    }


    /**
     * @ORM\PreUpdate
     */
    public function preUpdate() {
        $this->lastEditedTime = \DateTime();
    }
}

/**
 * @ORM\Entity
 */
class SomeEntityA extends TimeLoggedEntity {
    /**
     * @ORM\Column(type="string", nullable=true)
     */
    protected $someProperty;
}


/**
 * @ORM\Entity
 */
class OtherEntityB extends TimeLoggedEntity {
    /**
     * @ORM\Column(type="string", nullable=true)
     */
    protected $otherProperty;
}

In this example Doctrine would create tables for SomeEntityA and OtherEntityB which both have column for your timestamps.

Note that TimeLoggedEntity does not to be abstract necessarily.

Andrei Herford
  • 17,570
  • 19
  • 91
  • 225
  • Sorry for my bad explanation about my issue. I want to add "select" to all my DQL queries automatically (like SQLFilter does), Eg: all request returns "editedAt" and "createdAt" fields. – FindL Sep 10 '21 at 07:18
  • @FindL And what is the problem with using SQLFilters? They should also be applied to DQL queries as described in the docs: https://www.doctrine-project.org/projects/doctrine-orm/en/2.9/reference/filters.html Please update your question to show your current code, what it does and what you like it to do. – Andrei Herford Sep 10 '21 at 07:44