I'm running into a problem with the Symfony2 Security system, particularly when trying to load Roles from a database. Before going further, I am aware of FOSUserBundle, but at the moment, in an effort to better understand the Symfony2 framework, I want to try and make my bundle work using Symfony2 components only. TL;DR -> please don't tell me to just use the FOSUserBundle. :-)
I have 3 entities configured in my bundle, Accounts, AccountsRoles, and AccountsRepository.
src\RedK\Core\IndexBundle\Entity\Accounts.php
http://pastebin.com/0VgXvtJp
src\RedK\Core\IndexBundle\Entity\AccountsRoles.php
http://pastebin.com/GiKNnYg3
src\RedK\Core\IndexBundle\Entity\AccountsRepository.php
http://pastebin.com/SVuMVdpN
MySQL demo_template.accounts Table
http://pastebin.com/YzmjD9e4
MySQL demo_template.accounts_roles Table
http://pastebin.com/Ybwr4f7y
All aspects of the bundle were working correctly (registration, confirmation, password reset, and login) before I attempted to add the loading of user roles from a database. When I simply set the role to array('ROLE_USER') via the getRoles() { return array('ROLE_USER') }, authentication worked and the user successfully logged into the site.
However, upon attempting to integrate roles from the database, I receive the following error, which I understand is an instance of AuthenticationException:
Notice: Undefined index: id in /home/humplebert/Websites/www/template/vendor/doctrine/lib/Doctrine/ORM/Query/SqlWalker.php line 804
Stack Trace
http://pastebin.com/Sr5RvZaY
The exception is only generated when I modify the query in AccountsRepository and remove
the "->select()" and "->leftJoin()" components. In looking at the Stack Trace, around line 16 on the pastebin.com link, it appears I have all sorts of "crazy" happening with regards to the many-to-many mapping in the BasicEntityPersister.
I've searched high and low in my Entity classes for any reference to plain "id" and can find none. I've noticed that if I change the names of my "ID" columns in my entities to just "id" (i.e. replace "AccountsID" with "id" in src\RedK\Core\IndexBundle\Entity\Accounts) the error goes away (and is replaced with another error, more on that in a moment).
Question 1)
Is there something blatently wrong with my Entities to be generating the "Undefined index: id" error I am receiving? If not, does Symfony2/Doctrine2 require that Auto-Increment columns in be labeled "id"?
As I have continued to tinker, I decided to try renaming my table ID columns to "id". Therefore, src\RedK\Core\IndexBundle\Accounts replaces AccountsID with just "id". And likewise, src\RedK\Core\IndexBundle\AccountsRoles replaces RolesID with just "id". Upon doing so, the "Undefined index: id" error goes away. However, I am presented with a new error: "table or view demo_template.accounts_accountsroles does not exist". Well of course it doesn't exist, I don't have a table defined as accounts_accountsroles. I have two tables, accounts and accounts_roles.
Question 2)
In order to use the Symfony2/Doctrine2 tools for importing user roles from a database, what rules are there regarding the naming of the tables? Based on the error I received, it seems that some form of concatenation is taking place. Or have I just simply screwed up my annotations somewhere along the line?
Any help would be greatly appreciated.
Regarding Question 1) the short answer is no! For the long answer see section 5.3 Mapping Defaults in the Doctrine Association Mapping documentation:
It states that if you use this short annotation:
/** #ManyToMany(targetEntity="Group") */
private $groups;
"In that case, the name of the join table defaults to a combination of the simple, unqualified class names of the participating classes, separated by an underscore character. The names of the join columns default to the simple, unqualified class name of the targeted class followed by “_id”. The referencedColumnName always defaults to “id”, just as in one-to-one or many-to-one mappings."
You can override the defaults by providing more detailed many to many annotations (see link above) and therefore avoid the id error.
Regarding Question 2) the concatenation is correct. Many to many relationships require a third 'junction' table. The Doctrine paragraph above explains how the name of this table is generated.
I don't know why the 'table ... does not exist' error is occurring for the junction table as the annotations look ok to me. It appears as though your database schema is somehow out of sync with your annotations.
I implemented a solution, above FOSUserBundle and described it here
After implementing Role access throug Doctrine you still need to make a RoleHierarchy service aware of it.
Related
I'm building an app that allows a user to create reports for advertisers. The entities are set up so that there is a relation between the Report object and the Advertiser object - so that the advertiser has a getReports() method to get them.
I would like to change the app so that instead of actually deleting entities, that it simply changes a "deleted" property to true. That part is no problem, but I'm unsure how to make it so that the getReports() on the Advertiser entity only returns reports for the advertiser that have a deleted property of false.
Please let me know if you have any suggestions how that should be done in accordance with Symfony best practices.
You should look into Gedmo Doctrine Extensions. http://atlantic18.github.io/DoctrineExtensions/
Specifically for your case:
http://atlantic18.github.io/DoctrineExtensions/doc/softdeleteable.html
TLDR; they allow you to configure behavior of your entities in a way you desire, so for example when you "delete" an entity, Gedmo's listeners would set it's deleted value to a current datetime. Now you'd still have that record in your database but with not null value of deleted column marking it 'soft deleted', so when querying, it wouldn't be returned (because Doctrine knows how to query these stuff and would add a condition i.e.: ... where deleted ...) unless you explicitly say you want to see those soft deleted records.
I have an existing view in my SQL database "view_account" which represents a account entity. This view is read only and has no primary_key field. Actually it has a primary key "id" but the field is not declared as primary key. I can also not change the table design, because its an automatic export from another application generating this tables (the automatic export is every week).
But thats not the problem cause doctrine don't care about "primary key" flag in the database until you don't update the schema.
But whenever i try to "doctrine:schema:update --force" doctrine wants to create this table. How can i ignore this view (or better the entity) from updating by doctrine? Marking the entity read_only with doctrine annotation is not working. Extending a own update-command will also not work, as i found out, it will not work since doctrine 2.4.7 to extend the doctrine-schema-update command (the update command method is ignored in any way).
Whats the best solution?
Edit:
I also tried to configure two entitymanager. One for the "internal" entities and for the "foreign" entities. Since all entities are linked to each other on some point, it is also not possible to have two separated manager don't knowing from each other entities.
I have a problem concerning the usage of a DataTransformer.
Basically, I am developing a translation tool for my application whose goal is to be as generic as possible.
For that, I chose to follow that model : Database modeling for international and multilingual purposes
So, in different entities in my application, I have translatable attributes that simply are references to i18n elements. Then, this i18n ID is referenced in Translation table entries, that handle translation strings.
I succeed handling my translation interface, but I now have a problem with my forms : Indeed, I want some of my entities to be created/updated via forms. The problem is that I don't want the user to set a i18n ID for the translatable fields, of course, but a text, so that it can be handled by my application to either update or create the related translation in database.
I thought then that creating a DataTransformer could be a good idea, so that I can get the related translation string from the i18nID that is in my Entity entry (for that way, no problem). But my problem here is for the opposite way :
How can I deal with creating/updating i18n entries in my reverseTransform() method without knowing the entity values context?
Is there any way to get the previous entity values so that I could get the i18 ID that is stored originally in my entity? I understand that a Data Transformer is theorically totally independent from my forms and my entities, but I'm totally blocked about how to handle this case.
Indeed, when I save my entity with my translated string, I have no way to know the entity context in my reverseTransform() method, that would have permitted me to get the i18nID of the entity and to update it.
I just have the string that typed the user, but I can't do anything with that, because I can't know if it is an update or not since I don't have access to my entities.
Do you have any clue to do that? Is trying to use a DataTransformer to perform this a bad idea?
Thank you !
I need to create a fairly complex rule in Drupal - I am willing to use either code or the interface to do so.
I am more familiar with the interface, however, as opposed to the Rules API.
Anyway, the rule will be as follows:
It will happen based on a form submission from entityforms (which is one entity). It will take the checkbox value of a field (not just the true or false, but rather the value submitted when a value is true or false). It will convert this number to an integer.
At this point things get interesting - I want to create a new entity of registrations (a different entity), which as far as I can tell, means I'll have to bring a registration into scope. I also need to bring node (and not just node: type and other data selectors, but specifically node) into scope, because the next step requires it.
So at this point, I should have three entities loaded into scope:
entityforms
registration
node
I believe the best way to bring registration into scope would be entity is of type? The documentation page says that content of type should be appropriate - but that seems like it might be related to the specific use case of the example - not in my more complex example where registration isn't the first entity dealt with, but rather a second.
https://drupal.org/node/1463042
So anyway, if all three of these entities is called in correctly, the ultimate result should be the following:
Value from boolean field (not the straight 1 or 0, but whatever the value to be submitted is switched to) from the entityform is converted to an integer, and inserted where entity host ID is required. In the section where host entity type is the value should be node.
I am also open to alternative suggestions if this seems overly complex or poorly architected.
The Host Entity Type cannot be of Entityform? Why be a Node since a Registration can be attached to any entity? Then you will get the id of the Entityform as also as any other fields from that entity type instead of Node. Next steps are the same.
Using the Dynamics CRM I'm trying to create an instance of an entity. I would like to manually set the GUID, but if I had the attribute that is the primary key to the DynamicEntity, I get following error.
Service could not process request
I am building a DynamicEntity, and setting the [entityname]id attribute causes the request to fail. It's moving data between two CRM instances, so if anyone knows of a better way to copy records between CRMs, that'd work too. Otherwise, I'd like the GUID to match across instances... as that's the point of a GUID.
Happily, it IS possible to do this across two CRM instances! A co-worker knew the solution, so credit really belongs to him.
My mistake was creating a Property with type UniqueIdentifierProperty. The primary key attribute on an entity needs to be filled in with a KeyProperty. These two properties are nearly identical -- the Property types are, except that one holds a Key, the other a UniqueIdentifier. The Key/UniqueIdentifier both hold GUIDs. (Another day in the mind of Microsoft!)
Precisely, what I'm doing is creating a DynamicEntity, filling in the entity name, and filling in the majority of the attributes. The PK attribute (which you can determine from the metadata) can be filled in with a KeyProperty. I was filling it in with a UniqueIdentifierProperty, which CRM rejects and responds with a nondescript and unhelpful error message.
I apologize if I am over-simplifying the solution, but why not add a custom field in both instances that would be a mirror of the other instances guid?