Generating getters and setters in Doctrine without comments - symfony

I'm using Symfony2 and Doctrine, so to create getters and setters methods I do:
php app/console doctrine:generate:entities org/StoreBundle/Entity/Product
That works fine, but I would like to generate the getters and setters without comments. I think they are too obvious and redundant, for example:
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
Five lines !
Is there any option to do that?

Looking at the source for the Doctrine GenerateEntitiesCommand, it doesn't look like there is any way to do that: https://github.com/doctrine/DoctrineBundle/blob/master/Command/GenerateEntitiesDoctrineCommand.php
However, why would you want to remove the comments? It's not like there is a line limit in PHP, and it is barely a blip on your compiling in terms of a performance hit for comments (the different is so small, there is no way you could actually measure it on your computer).
Also, if you use PHPDoc to generate documentation for your code, that #return string is more useful than you might thing, because you'd then know the return types for each of your getters (which isn't always very obvious).

You may generate getter/setter using Netbeans IDE instead of Doctrine command line.

Related

Doctrine lifecycleCallbacks strange behaviour

I have defined lifecycleCallbacks in yaml as follows:
lifecycleCallbacks:
prePersist: [setCreatedAtValue]
preUpdate: [setUpdatedAtValue]
The above has generated entities with the respective functions as follows:
/**
* #ORM\PrePersist
*/
public function setCreatedAtValue()
{
if($this->created_at == null)
{
$this->created_at = new \DateTime();
}
}
Which looks all fine, right? However, when I try to open the sonata admin page, I get the following error
[Semantical Error] The annotation "#ORM\PrePersist" in method AppBundle\Entity\Article::setCreatedAtValue() was never imported. Did you maybe forget to add a "use" statement for this annotation?
I have never encountered this before and a bit confused about what to do. I am using symfony 2.7.6, Doctrine ORM version 2.5.1, Sonata Admin 2.3.7
Any help will be greatly appreciated
Since you defined your callbacks using yaml, you don´t need to define them again using annotations. Just remove the comments with the #ORM\PrePersist block before the function and everything will be fine.
If you wanted to use annotations to define your doctrine properties, you would need to import them before you can use them. To do so you would need to add this line at the beginning of your file:
use Doctrine\ORM\Mapping as ORM;
Same issue came with me.
In my case everything worked well until I did not Serialize my object in JsonResponse.
So problem was that previously I was not using that entity class (which was giving error) for sending JsonResponse, as soon as I tried to prepare JsonResponse containing that class, JsonResponse failed to serialize my class as it hadn't implemented Serializable interface.
This will happen if you will fetch objects with methods like findAll or findBy which returns Entity objects instead of php array.
So I just skipped those native methods and write doctrine query for fetching data.
You can also implement Serializable interface.

Doctrine2: Unable to override generated value strategy?

I have a an entity with an ID as such:
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
I'm migrating data into this entity, and want to preserve existing keys. I looked at "Explicitly set Id with Doctrine when using "AUTO" strategy" and found that I should be able to do the following:
$newData = ... // array containing data to bring in
$newEntity = new MyEntity();
$newEntity->setId($newData['id']);
$newEntity->... // set other data fields
$em->persist($newEntity);
$metadata = $em->getClassMetadata('\CS\AcmeBundle\Entity\MyEntity');
$metadata->setIdGenerator(new \Doctrine\ORM\Id\AssignedGenerator());
$em->flush();
However, Doctrine is not using the provided ID. It's ignoring it when inserting. I've also tried this approach instead, since some people seemed to have had luck with it (even tried both):
$metadata->setIdGeneratorType(\Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_NONE);
But that doesn't change anything. ID's are still inserted automatically by the database. In the query log, I see that Doctrine isn't even attempting to insert the ID.
If I remove #ORM\GeneratedValue(strategy="AUTO") from MyEntity annotations, then the migration will respect the provided ID I give it. But I want to override it just during the migration.
I'm using Doctrine 2.4.2.
For this technique to work, you must use the second of these:
$metadata = $em->getClassMetadata('\CS\AcmeBundle\Entity\MyEntity');
$metadata = $em->getClassMetadata('CS\AcmeBundle\Entity\MyEntity');
The problem is that Doctrine will return the same class meta data values for both.
They will both correctly identify the class file, read its annotations, etc. Obviously they are equivalent, except that one is an absolute namespace and the other is not.
But these strings will return different instances from getClassMetadata. Changes to one won't reflect in the other. If you want your intended technique to work, you must use the second form, because that is what UnitOfWork uses. It uses this normalization:
// \Doctrine\ORM\UnitOfWork->getCommitOrder()
...
$className = $this->em->getClassMetadata(get_class($entity))->name;
$class = $this->em->getClassMetadata($className);
...
Note that in the linked-to question, the solution uses get_class($entity). That is probably sufficient to get the correct behavior.
Even more detail: after a lot of stepping through code, I noticed that \Doctrine\Common\Persistence\Mapping\AbstractClassMetadataFactory was memoizing both versions of the class name string in its private property $loadedMetadata. The version that was being used to actually flush the entities was the one without the leading slash, and I was editing the one with the leading slash.
Because both strings return the same data, I think this represents a bug in the implementation.
The differences between GeneratedValue strategies
Inside your entity
Replace
#ORM\GeneratedValue(strategy="AUTO")
with
#ORM\GeneratedValue(strategy="NONE")
I am not sure whether you are using annotations or xml, or yml files. So better to change the xml or yml doctrine entity files inside your bundle config as well.

How to auto complete methods from Symfony 2 DI in netbeans

I am starting to develop with symfony 2 and it uses a lot dependency injection. I would like to know if is there any way that makes netbeans detect the type of object based on the string and auto complete with their methods?
For example, $this->container->get('doctrine') returns a Doctrine\Bundle\DoctrineBundle\Registry instance. In the container, the key doctrine corresponds to Doctrine\Bundle\DoctrineBundle\Registry.
Something like it, could be useful for zendframework 2 also.
I don't want to create new methods in the controller and nor use /* #var $var Symfony...*/, I would automatic detection.
As far as I know, there's no way for an IDE to detect the type of the object your container returns. My solution is to wrap those calls to the container into private getter functions. IMHO this improves code readability as well – especially, if you do this call more than once per class.
/**
* #return \Doctrine\Bundle\DoctrineBundle\Registry
*/
private function getDoctrine()
{
return $this->container->get('doctrine');
}
The IDE "PhpStorm" permits to suggest "use" declarations.
And this IDE propose specific features for Symfony2 and Drupal !
edited by JetBrains : http://www.jetbrains.com/phpstorm/
Not free but power full enough to reduce time developpement time (and time is money...)
Enjoy : )
phpStorm:
$foobar= $this->get('foobar'); //returns mixed
/* #var \MyNamespace\FooBar $foobar*/
or
$foobar= $this->get('foobar'); //returns mixed
/* #var FooBar $foobar*/
You can do this with eclipse PDT:
$foobar= $this->get('foobar'); //returns mixed
/* #var $foobar \MyNamespace\FooBar*/
( Walk around ) When comes to Symfony services:
Instead of
$doctrine = $this->container->get('doctrine');
use
$doctrine = $this->getDoctrine();
As you can see, Symfony allows you to access most of it services directly from $this variable. NetBeans will know what auto completion to use.
Lets have a look why this works (inside Controller class)
It is possible because Controller class imports Registry class with USE statement,
use Doctrine\Bundle\DoctrineBundle\Registry;
and then in method comment annotation it declares the returning object type with
/*
* #return Registry
*/
If you call $this->container->get('doctrine'); directly then auto completion will be get omitted and you will have to use whats below.
( Answer ) No magic auto completion works so far. Use Php Storm (it does what you request). For those who pick to stick with NetBeans you need to use manual annotation like in example below:
We can point NetBeans to a class it should be using for auto completion.
1) In terminal from project directory search for service you want to import:
php bin/console debug:container
If you know what you looking for use this instead:
php bin/console d:container | grep doctrine
...
doctrine --------------------------------------------------------
Doctrine\Bundle\DoctrineBundle\Registry
...
2) If this is not a service use get_class() PHP build in function to get class name of the object it particular variable. Or use reflection class. It's up to you.
3) Once you know the class name declare USE statement for better readability
use Doctrine\Bundle\DoctrineBundle\Registry;
4) Now wen we know what is the class name of the object instance in particular variable we are ready to inform NetBeans about what we know by using comment annotations so that it can enable auto completion.
/**
* #var $doctrine Registry
*/
$doctrine = $this->container->get('doctrine');
Now auto completion is enabled. Type
$doctrine->|
then press Ctrl+Space. See the image below:

Symfony 2 getters and setters

I would like to know if it is possible to avoid using getters and setters for a Symfony 2 entity. Although the php app/console doctrine:generate:entities is very helpful, line codes seem to increase a lot for an entity with a lot of fields
You can define the visibility of your properties from protected or private to public so you now have access to them in this way:
// on entity
public $someProp;
// On your code
$someEntity->someProp = someValue;
This is not a good OOP practice and should be avoided, getters and setters are the way to go if you want clean and secure code.
You Code won't work properly if skip getters and setters.
Especially if you have mapping with different Entities.
Doctrine uses getters nad setters to populate various members fields during storing and fetching of information
Its very bad practice to use public for every property in Entity.
and also you will end up wasting lot of time in changing the property to public as doctinr uses proted when it autogenerate the code

Delete child entity when modifying parent entity

I'm working in modify file action in my controller. Child entity(StrOrigin) has the following relationship with File entity:
/**
* #ORM\ManyToOne(targetEntity="File" )
* #ORM\JoinColumn(name="STOR_FILE", referencedColumnName="id", onDelete="CASCADE")
*/
Now in my modify action in the controller, I get the file to modify, set the form and do some tests then upload the file, persist file entity and override the StrOrigin (which is many strings from file) with the new modified file. I'm stuck in how to override the StrOrigin. I've tried deleting the old file when submitting and persisting the new one:
$this_file_STROR=$em->getRepository('File')->find(array('id'=>$idfile));
$em->remove($this_file_STROR);
$em->flush();
But that didn't seem to work.
Following up on the comments:
You don't want to remove your actual file. You are misinterpreting the onDelete="CASCADE"! It means that when you delete a file, all StrOrigin will also get deleted. It has nothing to do with what you want to achieve.
What you want is the following:
$this_file_STROR=$em->getRepository('File')->find($idfile);
foreach($this_file_STROR->getStrOrigins() AS $strOrigin){
$em->remove($strOrigin);
}
// now $this_file_STROR as no StrOrigins anymore
$em->flush();
Also note that you don't need to flush at this point. A flush is simply persisting your current objects to the database. As long as you work with the objects, there is no need to flush. Normally you can flush right before your script ends, e.g. before you call render in your controller. If you flush several times, your application may be slow due to interaction with the database.
I found another solution which may be much faster:
It's described here and is called orphan removal. The idea is to simply remove the association and tell doctrine that related entities which are not refered to anymore shall be removed. In your case, you would do the following:
/**
* #ORM\ManyToOne(targetEntity="File" )
* #ORM\JoinColumn(name="STOR_FILE", referencedColumnName="id", orphanRemoval=true)
*/
public function deleteStrOrigins(){
$this->strOrigins = new ArrayCollection(); // you can also try to use = null. I'm using ArrayCollections, so this is my way and I never tried the null approach.
}
Now calling in your code
$this_file_STROR=$em->getRepository('File')->find($idfile);
$this_file_STROR->deleteStrOrigins();
$em->flush();
should delete all related StrOrigins as long as they are not related anywhere else.

Resources