Symfony2: how can I load a user taking into account its mapping entity? - symfony

Although I'm using Symfony 2.1 with FOSUserBundle and everything works perfectly, I don't know how I can resolve a problem.
Basically, I would like to know if there is a way to find (load or get) a user from the database taking into account a relationship with another entity.
This is the situation:
I have made that users can also login into my site thru a social network (Google, Facebook, LinkedIn, etc). I besides ask them for an offline access, so I can access their social accounts any time.
As each user can have as many connections as they want (or maybe none cause they are optionals), I've decided not to save this information in the user table. I've created an abstract entity called "SocialConnection" which is extended by the real ones (Google, Facebook, ect). In this entity I store the user information that I get when the user logs in my site thru those networks (user_id, social_id, access_token, etc), so in my User class I have mapped a collection of the abstract "SocialEngine" that allows me to have all networks together.
In order to be able to add others networks like Twitter, Yahoo and so on in the future, I think it is the way it should be.
So, the problem now is that when the user logs into my site thru any of these social networks I need to load him from the database knowing his social id, but I don't know how to do it.
I've seen that the method $this->findUserBy of UserManager find a user regarding a property but I think this is not the case.
What should I do to find a nice solution?
Thanks in advance.
Best regards,
Izzy.

To achieve this, you need to get deeper into doctrine's api. The base repositories methods (find, findBy etc...) won't be enough.
You need to use doctrine's DQL. It looks like SQL but you query based on your mapping metadata and not based on the database schema directly.
If your User has a OneToMany $socialAccounts property to the SocialEngine. You will be able to do something like:
SELECT u
FROM Bundle:User AS u
JOIN u.socialAccounts AS sa
WHERE sa.id = 34
But you can only query on SocialEngine's properties, not on the subclasses one ... (ie: You can't query on a SocialFacebookEngine's facebookId).
You either have to put all the twitter/facebook/etc data in the base SocialEngine class, on in the User class.
Or you could create an entity for each "Social Engine", and create a OneToOne relation relation between each of theses engines and the User.

Related

FOSUserBundle proper solution for team consist with multiple users

I am using FOSUserBundle in my Symfony2 project.
My goal is to make the teams consist with multiple users. Users are invites by administrator (owner) by e-mail confirmation.
If a user belongs to one team, can't set up new accounts using the same address. Of course, each user should have the opportunity to unsubscribe from the team.
Are there any ready-made solutions? I looked for Groups With FOSUserBundle.
Or do you have any good advice?
You were right, groups can be a good ready-to-use solution to make your logic.
The association is already setup and it's also easy to extend.
The documentation (now part of Symfony's doc) contains a great guide to use groups.
Of course, you can make your own entity, take example from the FOSUB User->Group logic (association) .
You should see the Security and Roles part of the documentation to manage authorisations of your different kind of users.
You can assign roles to your different groups, and make your users directly inherit the roles of their group for manage access permissions.
For the confirmation email, see the corresponding documentation too .
And for the unsubscribing, just remove the association between the user you want remove from a Group and the Group (or Team).
This is also part of the association, see the doctrine documentation.
Good use.

Symfony2, 2 similiar types of users, best approach

i have this project where i have an issue, there are 3 relevant enteties.
User:
has_many: Leads
Bot:
has_many: Leads
Lead:
has_one: User/Bot
Now, a user and a bot share a lot of the same things, but they use different firewalls, they have many different fields etc, but i want a user and a bot to be interchangeable in regards of who a lead belongs to, it can either belong to a bot or a user, never both at the same time.
And in many of my other enteties where i run stats etc, i refere to a single field, i dont check if there is a user or a bot.
Is it possible to make these 2 enteties share the same Primary key and then just somehow refer to a single entity in the Lead field ?
Or what would be the best design approach in Symfony?
If you have all fields the same in 2 entities I would recommend you to drop Bot entity at all. All you need is just one field type with available values bot and user. To optimize SQL queries I would recommend you to declare this field as ENUM type.
Also if you really need different entities you can use Single table inheritance with discriminator field type described above.

Symfony working with different entity managers

I want to create an application with some subsections like a blog and a forum for example. Now I want users to be able to create an account on my site, and with that account they can use the forum and the blog. That's easy so far. But I want to keep the tables in seperate databases to keep a nice and clean structure. Let's say I use 3 databases, one for the UserBundle, one for the BlogBundle and one for the ForumBundle. This requires 3 entity managers. But that means that I can't use relationships from entities from ForumBundle or BlogBundle to the user entity in UserBundle. Simply adding UserBundle under the mappings for the other managers will create new tables in the other databases and that's the thing I'm trying to avoid.
So, is there a way to make bundles 'aware' of entities in other bundles?
I know it technically isn't a good thing to make bundles dependent on other bundles, but how else would I acheive my idea?
One approach that has worked reasonably well for me is to query using the event system.
Assume you are in the Forum Bundle, you have retrieved a list of posts for a given thread and now you need the user information for each post. You make an array of user id's then:
$userIds = array(...list of users you need information for...);
$findUsersEvent = new FindUsersEvent($userIds);
$dispatcher->dispatch('FindUsers',$findUsersEvent);
$users = $findUsersEvent->getUsers();
So now I have a list of user information all nicely indexed by user id from which I can then pull additional information.
The only coupling between the Forum and User bundles is the FindUsersEvent class which could be in a common bundle of some sort. The forum bundles does not care how the users are loaded. The user bundle just needs a listener.
==================================================================
A second approach is to basically use a REST like api for grabbing user information.

Doctrine2 dynamic table prefix based on logged in user in Symfony2

I am trying to get a multi-tenant system setup where each user has their own prefixed tables.
So my database might look like
users
acme_posts
my_posts
their_posts
our_posts
A solution like this is a good start, but it does not allow for the prefix to be dynamically created.
Is it possible to modify the doctrine solution above to set the database prefix based on the logged in user?
Another approach might be to have a main users database and then have separate databases for the user specific tables, but I am not sure if Doctrine can handle relationships between multiple databases.
All suggestions are welcome.
You can quite easily get access to the service container in a Doctrine EventListener like that, simply by defining the EventListener as a service (instructions located here). However, that approach won't help you for your situation, as all the class metadata will be loaded just once and cached, so it can't know about different users.
I don't know your use-case, obviously, but is there any reason that you can't simply add a field to your *_posts table, such that you have one posts table with "user_namespace" or similar as part of the key?
If your objection is simply to cluttering your controller logic with information about what user is logged in, you can simplify things by using a prePersist Doctrine EventListener to set the appropriate user_namespace on new entities, and either a Filter (for Doctrine >=2.2) or a custom DQL walker (for everything else) to restrict all your queries to only retrieve entities from the appropriate user_namespace.

ASP.NET Membership - A design for tracking additional information

I'm working on an ASP.NET4.0/C# application for a public site that needs to authenticate only the employees that work at the associated business. The idea is for the site to have a CMS such that employees can go in and make changes to certain content without having to work with any html.
My question relates to the design and use of a ASP.NET membership provider. I'm not trying to make the site work with an existing database, so there's no need to create my own MembershipProvider for that purpose. However, since each user is an employee, I want to track additional information such as name and office number. I can think of two readily apparent ways to accomplish this:
Use the default SqlMembershipProvider class. As a result, I would need to add the appropriate tables to my database and create a separate table for any "additional" information I want to store. This effectively creates a vertical partition on the user table, since I would use the asp.net-assigned userID as the primary key of the employee table as well. To retrieve the "additional" information, I could ask the provider for information about the current user and requery the database in the event I want to know anything else.
Create one table for all employee information (including login and password) and create my own custom MembershipProvider and MembershipUser classes with the functionality I desire.
I've also considered the use of profiles to store such information, however, the site will publicly contain employee listings, and these pages will need to access some of this information. As a result, I should probably cache this data and it seems like using the serialized fields that profiles provide would cause a problem.
Thus, purely in regards to design... would it be best to make a distinction between a user and an employee and use the default SqlMembershipProvider and associated tables, or write my own user tables that store the information I need and my own MembershipProvider for accessing that information?
If I understand your question correctly, you'd like to store additional user info within the ASP.NET Membership. I've created a number of sites using the following setup.
Install the default .NET Membership using the aspnet_regsql.exe tool
Create a UserProfile table with a uniqueidentifier (PK) UserID column that is linked via a foreign key to the aspnet_Users table
To access that information, all you need is the UserId of a particular User, then you can query your custom table for more information.
Microsoft has written an excellent post on how to do this.
Good luck!
M
I am doing something similar, using your option 1. Works great for me.
My business logic has some functions for mutating users. It knows when to touch my users table or the Membership functionality.
Using a custom MembershipProvider for this sort of thing will give you more work than you bargained for.
SQL Table profile provider (http://weblogs.asp.net/scottgu/archive/2006/01/10/435038.aspx ) will help you do just that.
You will get the power of the Profiles and on the same time not worry about caching or serialization since this provider stores the profile information in clear database table without any serialization. You can use them directly in your queries.

Resources