Doctrine entity field not recognized at all - symfony

I am working with FOSUserBundle to authenticate. The authentication worked, so far so good. I have a couple of extra fields which populated nicely.
I then added a Roles-table (with the according entity), where the id-field is referenced by a roleid field in the database.
However, this field is not recognized by doctrine at all. Even
php app/console doctrine:schema:update --dump-sql
doesn't show it! Even when I rename my current table and then try to generate a create table-query, the field doesn't show up. I also tried renaming the field, but to no luck.
My field (in the class, of course):
/*
* #var int $roleid
*
* #ManyToOne(targetEntity="Roles")
* #JoinColumn(name="roleid", referencedColumnName="id")
*/
protected $roleid;
If anyone could point me in the right direction of what is going on, I would greatly appreciate it.

Use
/**
instead of
/*
otherwise the annotations will not be recognized

You have to follow the exact syntax
Use /** and not /*

Related

Symfony Login form with existing user class

I'm trying to use (and understand) how Security works in Symfony. I've created a login form and it works with hard-coded users.
Now I want to use an existing user table in my database. The table has all the requiered fields but with different column names. The entity also exists, also with different names (for example "customUserId" instead of "id").
Something like (with "MAGIC_MAPPING"):
/**
* #ORM\Table(name="custom_user_table")
* #ORM\Entity
*/
class User implements UserInterface, \Serializable
{
/**
* #ORM\Column(name="customUserId", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
* #MAGIC_MAPPING so it links this to the mandatory "id" field
*/
private $customUserId;
...
}
Is there a way to map my existing fields so Symfony uses them for login purpose? Or at least can I make it work without changing my database structure (only the entity class)?
I've tried seleveral actions, from this forum and from Symfony documentation, but it always ends with ugly error I can't fix.
Any idea or lead? Thanks a lot for your help, I've been struggling on this for several hours now...
You have to change the providers configuration inside the security.yml file
here is an example, i use the email field from my administrator entity, I think you can do the same with your entity
providers:
administrator:
entity: { class: Entity:Administrator, property: email }
Try changing the ORM file of that table.
create an ORM file using Command promt.
then edit the orm file .
<mapped-superclass name="FOS\UserBundle\Entity\User" table="your_table_name">
/.../
</mapped>
BenoƮt 's answer help me figure it out. I gave too much attention to Symfony documentation's creation process that I forgot the essential: the UserInterface. No need to map anything, just implement this interface and defined methods like:
public function getUsername() {
return $this->customLogin;
}
Then update the provider configuration (thanks Benoit):
providers:
db_sam_provider:
entity:
class: AppBundle:User
property: customLogin
The other parts are conform to Symfony documentation: here and here

Symfony2 which doctrine relationship for blog between posts and comments

I am building a blog with symfony2 and I am wondering which doctrine relation mapping should be used for the comments. The thing is that I would like to use the comments in different parts, like commenting on pictures (which are not posts) or commenting on comments. So I need my comment entity to be independent of the post.
I wanted to try the OneToMany unidirectionnal but it forces a unique key on the post which is not great.
Thanks for your help
Simple way
The simplest way would be to create a OneToMany relationship for each linked entity. It's quite ugly and maybe is not effective when searching entities, but it works.
The mapping would be similar to this:
class Comment
{
/**
* #ORM\ManyToOne(targetEntity="Post")
* #ORM\JoinColumn(nullable=true)
**/
protected $post;
/**
* #ORM\ManyToOne(targetEntity="Picture")
* #ORM\JoinColumn(nullable=true)
**/
protected $picture;
/**
* #ORM\ManyToOne(targetEntity="Comment")
* #ORM\JoinColumn(nullable=true)
**/
protected $comment;
}
You'll have to handle security by yourself to make sure the comment has at least ONE linked element, and searching might be harder, but it's a basic way to do it.
Complex way
The most effective way to do it (but maybe the most complex) would be to create a "discriminant" property and a "element-to-be-commented" property, coupled with a Custom Doctrine hydrator to retrieve all objects at once, but each one being the correct entity.
The "element-to-be-commented" property would then be either a Comment, Picture or Post, and the discriminant would be here to tell which class is linked.
In SQL terms, it means no foreign key between tables, and that the element_id is dependent of the discriminant.
You may want to take a look at Single Table Inheritance. Disclaimer: I don't have direct experience with it, but it's been suggested often as an answer to similar questions.

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.

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.

Extend Symfony2 White October Admin Bundle Form Fields?

This question is quite specific.
I'm using Symfony2 White October Admin Bundle for generating administration for my application.
I wonder if anyone has experience with this bundle and knows how to modify specific fields added to Admin class. The bundle is not documented very well and I'd like to know, if there are methods for doing this, or does the bundle core need to be extended.
For example I've got a Speaker entity with a field storing the path to one's avatar:
/**
* #var string $picturePath
*
* #ORM\Column(name="picture_path", type="string", length=128, nullable=false)
*/
private $picturePath;
Then in the Admin class I'm adding the field:
protected function configure()
{
...
...
->addFields(array(
...
...
'picturePath'=> array("label" => "Avatar"),
));
}
Is there an easy way to tell the bundle that I'd like this field to be an upload field instead of a text field, and define extra methods to call after submitting the form? (e.g. resize the image, store it, and then just store the image path in the DB)
As I haven't found any solution yet, I had to rape my entities to do that. So I modified the basic setter methods to call other methods inside the entity that do the dirty job. This is not a solution, and I'll still be happy if I could find better answers here.

Resources