symfony / doctrine : entity wont delete - symfony

I have this code in Symfony 3:
(...)
$annonceActive = $em->getRepository('AppBundle:AnnonceActive')
->find($SomeKnownId);
$profilPresta = $em->getRepository('AppBundle:Profil')
->find($SomeKnownId);
$annonceEnCours = new AnnonceEnCours();
$this->get('app_annonce_transportateur')
->transporterAnnonce($annonceActive, $annonceEnCours);
$annonceEnCours->setPresta($profilPresta);
$em->remove($annonceActive);
$em->persist($annonceEnCours);
$em->flush();
dump($annonceActive);
//annonceActive stills exists !!
Now I have the service used :
class TransportateurElementAnnonce
{
protected $em;
public function __construct(EntityManager $entityManager){
$this->em = $entityManager;
}
protected function copierInfosAnnonceVersAnnonce(&$annonceSource, &$annonceTarget)
{
$annonceTarget->setAuteur($annonceSource->getAuteur());
$annonceTarget->setPresta($annonceSource->getPresta());
$annonceTarget->setCompetence($annonceSource->getCompetence());
$annonceTarget->setGroupeCompetence($annonceSource->getGroupeCompetence());
$annonceTarget->setTitre($annonceSource->getTitre());
$annonceTarget->setSlug($annonceSource->getSlug());
$annonceTarget->setDescription($annonceSource->getDescription());
$annonceTarget->setPrix($annonceSource->getPrix());
$annonceTarget->setServiceADistance($annonceSource->getServiceADistance());
$annonceTarget->setDateCreation($annonceSource->getDateCreation());
}
public function transporterAnnonce(&$annonceSource, &$annonceTarget)
{
$this->copierInfosAnnonceVersAnnonce($annonceSource, $annonceTarget);
$this->em->persist($annonceSource);
$this->em->persist($annonceTarget);
$this->em->remove($annonceSource);
$this->em->flush();
}
}
How can I use $em->remove($annonceActive) in the controller, and still have an object !
I really tried everything, I dont get it.
Thanks in advance !

You can use clone to "copy" an object, that way you can use the copied object after you've changed the original using the entity manager (or whatever you want to do with it).
$originalObject = new SomeClass();
$clonedObject = clone $originalObject;
// Change the original object here, for example use it with the entity manager..
$originalObject->setWhatever('bla');
$this->em->persist($originalObject);
$this->em->flush();
// At this point $clonedObject is still unchanged.
More information on cloning objects: http://php.net/manual/en/language.oop5.cloning.php
Hope this helps..

the solution was given by #jacek : I remove all interaction with the entity manager in the service, and used it only in the controller.
My service looks like before, except I dont use entity manager !
Thanks guys for the precious help.

Related

why i got error inspite of that correctly set value to entity?

Hello my website is made by symfony and mysql.
Now im stuck in this error.
publisher_id cannot be null.
this errror means that publisher_id column of volume table can not be null.
this error is correct but i set value to publisher_id
and i did var_dump like below and i got correct Entity.
$volume = new Volume(); //instanciate Volume Entity.
$volume->setISBN($ISBN);
$volume->setStorePublisher($publisher); //set Publisher Entity to Volume Entity.
var_dump($publisher->getId()); //correct id shown.why no publisher id???
$volume->setCreatedAt(Context::now());
$volume->setUpdatedAt(Context::now());
$em = Context::getEntityManagerWrite();
$em->transactional(function (EntityManager $em) use (&$volume) {
$volume = $em->merge($volume); // i got error here.why ??
$em->flush();
//....
}
Your Error:
To begin with your problem you're trying to merge an unmanaged Entity,
Persist it inside the em first as such :
$volume = new Volume();
$volume->setISBN($ISBN);
$volume->setStorePublisher($publisher);
$volume->setCreatedAt(Context::now());
$volume->setUpdatedAt(Context::now());
$em->persist($volume);
// do stuff
FYI:
in you entity add the __construct method to remove this ugly createAt()from your controller
class Volume {
public function __construct()
{
$this->setCreateAt(new \DateTime());
}
}
For the updateAt() you can use services as shown in the Doc. The objective is to keep your Controlleras light as possible.

Controller class not seeing method from repository class

I have spent the last few hours trying to find an answer however not gaining at all. I feel that it will end up being something simple that I did not have knowledge of. This section of code is of course incorrect but I wanted to show the idea of what I was trying to do here. I currently have a base repository class that has the findAllQueryBuilder method within it that will allow for reduced code. Right now I have about 10 repository classes that all need to use findAllQueryBuilder. This function is within the basecontroller I have built. The main issue is that this controllor does not see findAllQueryBuilder because as you can see this takes in the parameters to determine which data location is needed. I've done this once already in another location in my code with an interface however that was with a class I will put that example here also.
public function listAction(Request $request, RepositoryTypeInterface $repositoryName, $table, $sql, $route)
{
$filter = $request->query->get('filter');
$repository = "Bundle:$repositoryName";
$qb = $this->getDoctrine()
->getRepository($repository, 'tenant')
->findAllQueryBuilder($filter, $table, $sql);
As you can see in the following I set the type as the interface to make sure it knew that it was going to be that then.
public function newAction(Request $request, EntityTypeInterface $controllerType, formType, $repository, $routeName)
{
And then instantiated it within the childclass controllor
public function newAction(Request $request, EntityTypeInterface $controllerType = null, $formType = ContactType::class, $repository = 'Contact', $routeName = 'api_contacts_show')
{
$controllerType = new Contact();
return parent::newAction($request, $controllerType, $formType, $repository, $routeName);
}
So The first example above has me attempting the same thing however I am not sure how to apply this to this situation. as "Bundle:$repository" is a string and the parameter used is a string and it's not an entity so creating an instance doesn't make sense when all I need is its functionality. I just need some way to have access to this functionality. any ideas would work but I'm feeling like I'm missing something simple.
Here is the exact error I get,
Method 'findAllQueryBuilder' not found in \Doctrine\Common\Persistence\ObjectRepository
Referenced method is not found in subject class.
I'm sure there is a way to apply this concept to fix the lack of 'seeing' the function however as of right now I'm not completely sure.
Thank you anyone in advance.
EDIT:
I'm using a basecontrollor that is setting this up for the other controllers ie:cantactscontrollor class which uses the ContactEntity class mapped to the contactrepository class which is a child of a baserepository class which is where findAllQueryBuilder is located, I'm not sure how to map that.
public function listAction(Request $request, $repositoryName, $table, $sql, $route)
{
$filter = $request->query->get('filter');
$repository = "TenantBundle:$repositoryName";
/** #var RepositoryTypeInterface $qb */
$qb = $this->getDoctrine()
->getRepository($repository, 'tenant');
$queryResults = $qb->findAllQueryBuilder($filter, $table, $sql);
Sorry for the late response on this but here is the answer I was able to find. As I thought it was a simple thing but essentially the Docblock labeled $qb as the said interface above making sure it knew that any class that implements it will be accepted. Now knowing what type it will be, the error message is no longer there. Notice also how I split it up.

Symfony2-entityManager inside an Entity

I am using Symfony version 2.7.6. I have created an entity named EmployeeBasicInfo having fields
firstname
lastname
identificationCode etc
I have created a callback function for validating Identification code in EmployeeBasicInfo entity itself which looks like
/**
* #Assert\Callback(groups={"edit_myinfo"})
*/
public function validateIdentificationCode(ExecutionContextInterface $context)
{
if ($this->getEmployeeFirstName() == 'fakename') {
$context->buildViolation('This name sounds totally fake!')
->atPath('employeeFirstName')
->addViolation();
}
}
and this callback function works properly
Actually I want such a callback functionality which checks identidfication code against database. I have added $em = $this->getDoctrine()->getManager(); inside the callback function and the error is like Attempted to call an undefined method named "getDoctrine" of class "XXX\EmployeeBundle\Entity\EmployeeBasicInfo".. Please advise me the effective way
Do not inject the EntityManager in your Entity. One basic concept of the DataMapper-Pattern is, that your entity does not have to know about your data source and its connectors.
I'd suggest to write a custom validation constraint, in which you inject the dependencies you need.
EntityManager, Repository to query, etc. Whatever service suits you.
Have a look at how to create custom constraint validators with dependencies
I would suggest you use a service to do this
class EmployeeUtility($connection)
{
public function __construct($conn) { $this->connection = $v; }
public function validateIdentificationCode($emloyeeId, $validationCode)
{
// Your code here
}
}
In your controller, you inject the service:
$employeeUtility = $this->get('employee.utility');
$employeeUtility->validateIdentificationCode(1,'GF38883dkDdW3373d');
Alternatively, add the code in a repository class.

Symfony2 Entity properties loaded from db

So , i'm working on a news portal , and i have two entities :
News Entity (id,title...source)
Source Entity(id,title...)
In News Entity,field named 'Source' is an id to Source Entity;
So , i need to access Source Title when publishing news . I know there's posibility doing thing relationships ManyToOne . But i don't want do it , because it makes my life harder in some cases . Is there posibility to execute a Query in Entity ? like :
public function getSourceTitle()
{
$query = ...;
return $query->getScalarResult();
}
Can i do it ? or is there another posibility ?
It's not a good practice to query insiide Entity class. Entity class should hold just fields, setters and getters, nothing else. So, if you want to query the db, and how are you planning to do it? Injecting EntityManager? Ok, If you really want to do it you can simply do it like this:
...
private $entityManager;
public function __construct(EntityManagerINterface $entityManager)
{
$this->entityManager = $entityManager;
}
...
public function getSourceTitle()
{
$sourceRepository = $this->entityManager->getRepository('VendorMyBundle:Source');
$queryBuilder = $sourceRepository->createQueryBuilder('s')
->....
return $queryBuilder->getScalarResult();
}
and use it as new MyEntity($entityManager) on entity creation.. But, you should know that this is considered as very bad practice...

Access database in BeforeFeature

How do I access my database via doctrine in a BeforeFeature? I am unable to get my entity manager because my kernel is null...this is what I am trying:
/**
* #BeforeFeature
*/
public static function cleanDatabase(FeatureEvent $event)
{
$context = new FeatureContext(array());
$context->thereAreNoUsersInTheDatabase();
}
It tells me that I cannot get container from a non-object (the kernel). Why isn't KernelAwareInterface assigning the kernel when I manually create that FeatureContext?
KernelAwareInterface just provides a method "setKernel" method, you still have to call manually if you instantiate a new FeatureContext object
You can use FriendlyContext that provide you a "#reset-schema" annotation. See https://github.com/KnpLabs/FriendlyContexts/blob/master/doc/context-entity.md#reset-schema .
Do not hesitate to read the full documentation and the code that doesn't uses the SymfonyExtension.

Resources