Unable to find "Proxies\__CG__\App\Entity\EnseigneNationale" entity identifier associated with the UnitOfWork - doctrine

Client.php
/**
* #ORM\ManyToOne(targetEntity="EnseigneNationale", inversedBy="clients")
* ...
*/
private ?EnseigneNationale $enseigneNationale;
/**
* #ORM\OneToMany(targetEntity="ClientBanque", mappedBy="client", cascade={"persist", "remove"})
* ...
*/
private ?Collection $clientBanques;
My data comes from an old database, I have to create a command that corrects some data in the database.
if (Condition) {
/** #var ClientBanque $clientBanque */
$clientBanque = $clientBanques[0];
$clientBanque->setAA($aa);
$this->manager->persist($client);
}
When I persist, I got the error saying that doctrine unable to find "EnseigneNationale", that it can be nullable and I m not using it in my persist changes.
Somthing wrong with my code ?? Help Please
PHP : 7.4
Symfony : 5.3
Doctrine : 2.4

It was me !! Sorry for disturb, I was adding $manger->clear() who breaks everything

What is happening is basically you've detached your object from entity manager. The object was removed from the identity map and is no longer managed by this entity manager.
You can attach the object back by calling $managedCopy = $em->merge($object);
Pay attention to the fact that merge returns a new object.
The state of the passed entity will be merged into a managed copy of this entity and this copy will subsequently be returned.

Related

"AuthenticatorInterface" not found on Security\Guard, Symfony 6.2

I'm trying to create a custom Token authenticator for my Symfony 6.2 and API Platform project
class TokenAuthenticator extends JWTTokenAuthenticator
{
/**
* #param PreAuthenticationJWTUserToken $preAuthToken
* #param UserProviderInterface $userProvider
* #return UserInterface
*/
public function getUser($preAuthToken, UserProviderInterface $userProvider): UserInterface
{
$user = parent::getUser($preAuthToken, $userProvider);
var_dump($preAuthToken->getPayload());exit;
}
}
But I always get this error:
Attempted to load interface "AuthenticatorInterface" from namespace "Symfony\Component\Security\Guard".
Did you forget a "use" statement for "Symfony\Component\Security\Http\Authenticator\AuthenticatorInterface"?
that means, there's no AuthenticatorInterface on Security\Guard and Http\Authenticator replaces it, so the LexikJWTAuthenticationBundle must be updated to include the new change.
This new class contains new functions so is there any documentation regarding them? Also, the purpose of establishing this class TokenAuthenticator is to make the old token invalid when changing the password, so is there a better way to do this?

Doctrine - Set $id as UUID instead of Integer when creating new entity

I am working on a new project in Symfony 5.3. I am using this command bin/console make:entity for creating entities.
This wizard automatically creates an entity with $id as primary key of type integer. I am prefering UUID instead of integer.
How I should change settings to get Entity like this?
Thank you
namespace App\Entity;
use App\Repository\EventRepository;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\IdGenerator\UuidGenerator;
/**
* #ORM\Entity(repositoryClass=EventRepository::class)
*/
class Event
{
/**
* #ORM\Id
* #ORM\Column(type="uuid", unique=true)
* #ORM\GeneratedValue(strategy="CUSTOM")
* #ORM\CustomIdGenerator(class=UuidGenerator::class)
*/
private $id;
...
}
There is no option to set the generated identifier strategy on make entity.
You can see all available option using php bin/console make:entity -h
Also there are no configuration in doctrine.yaml file to define this.
It could be a good feature to add for current and next version
To request a new feature, you can create a new issue feature request type:
https://github.com/symfony/symfony/issues/new/choose
You will need a github account

How can I "validate" DELETE request in api-platform

I want to check the entity variable and check if it is allowed to delete the entity. For example if the owner entity of the association is linked to another entity, I want to make the deletion impossible.
I've looked in the documentation of api-platform bu I could not find any help regarding my problems. Either you give the right to delete or not. I could not find how to control it (equivalent to validation for POST, PUT and PATCH).
You can use the access control feature of Api-Platform and Symfony Expression Language to achieve what you want. This way you can write pretty complex expressions.
I hope this example makes it clear.
user is the currently logged in user.
object is the resource user is trying to delete.
/**
* #ApiResource(
* itemOperations={
* "delete"={
* "access_control"="is_granted('ROLE_USER') and object.getUsers().contains(user),
* }
* }
* )
*/
class Entity
{
/**
* #var ArrayCollection
*
* #ORM\OneToMany(targetEntity="User", inversedBy="entities")
* #ORM\JoinTable(name="entity_users")
*/
private $users;
/**
* #return ArrayCollection
*/
public function getUsers(): ArrayCollection
{
return $this->users;
}
}
In this case only users who are stored in users Array of Entity can delete this resource.

When Container::clearResolvedInstance should be used

Out of curiosity, I'd like to know why Http/Kernel->sendRequestThroughRouter($request) sets an instance of request and immediately right after wipes it out.
protected function sendRequestThroughRouter($request)
{
$this->app->instance('request', $request);
Facade::clearResolvedInstance('request');
...
What is the purpose of doing that?
Seems that I finally got the point:
Facades just hold references to the actual service instances located in the Container
If the instance is replaced by a new instance via $app->instance() or by other means, then the Facade reference becomes obsolete since it is still pointing to the previous deleted instance
By clearing the facade instance reference with clearResolvedInstance, it forces the facade to store a new reference the next time the facade is invoked via resolveFacadeInstance($name)
Did I get it right?
This leads to another question:
What's the point of managing and returning these resolvedInstances:
if (isset(static::$resolvedInstance[$name])) {
return static::$resolvedInstance[$name];
}
return static::$resolvedInstance[$name] = static::$app[$name];
Instead of just always return the instance directly from Container like this:
return static::$app[$name];
because it is registerd app wide
/**
* Register an existing instance as shared in the container.
*
* #param string $abstract
* #param mixed $instance
* #return void
*/
public function instance($abstract, $instance);
after it is registered in the container then unresolved version is wiped as far as I am understanding

Doctrine 2 result cache invalidation

I'm using Doctrine 2's result cache on a query retrieving the number of new messages of a user (messaging app):
$query->useResultCache(true, 500, 'messaging.nb_new_messages.'.$userId);
I tried to invalidate this cache like this (in my entity repository):
public function clearNbNewMessagesOfUserCache($userId) {
$cacheDriver = $this->getEntityManager()->getConfiguration()->getResultCacheImpl();
$result = $cacheDriver->delete('skepin_messaging.nbNewMessages.'.$userId);
if (!$result) {
return false;
}
return $cacheDriver->flushAll();
}
So that I don't need to make a useless query on each page of my website.
My questions: is that a recommended practice? Will I eventually run into problems?
I had the idea to build an onFlush hook.
There you have all entities queued for inserts, updates and deletes hence you can invalidate the caches depending on entity name and identifier etc.
Unfortunately, I have not yet build any event listeners but I definitely plan to build such a thing for my project.
Here is a link to the doctrine documentation for the onFlush event
Edit:
There is even an easier way to implement events.
In an entity class you can add #HasLifecycleCallbacks to the annotations and than you can define a function with a #PreUpdate or #PrePersist annotation.
Than every time this model is updated or persisted this function will be called.
/**
* #Entity
* #Table(name="SomeEntity")
* #HasLifecycleCallbacks
*/
class SomeEntity
{
...
/**
* #PreUpdate
* #PrePersist
*/
public function preUpdate()
{
// This function is called every time this model gets updated
// or a new instance of this model gets persisted
// Somethink like this maybe...
// I have not yet completely thought through all this.
$cache->save(get_class($this) . '#' . $this->getId(), $this);
}
}
So maybe this can be used to invalidate every single instance of an entity?
This is an old question I stumbled upon. It's really simple using Doctrine 2.8 nowadays:
/** #var \Psr\Cache\CacheItemPoolInterface|null $cache */
$cache = $em->getConfiguration()->getResultCache();
$cache->deleteItem('skepin_messaging.nbNewMessages.'.$userId);
$cache->clear(); // clear all items
Please be aware that Doctrine internally generates a "real cache key" which won't look like yours. I don't know how to generate that cache key, without re-creating the used query.

Resources