Laravel - HasManyThrough in a different way - orm

In the laravel docu is the following example for has-many-through relationship: Country has many posts through user.
But in my case i need something like this:
User has many roles through customer.
I would like to have the has-many-through relationship from user to role.
Is there a way to get it working this way?
EDIT
I solved my problem with a collection method:
public function roles() {
$roles = $this->hasMany('SC\Customer')->get()->each(function($item) {
return $item->role();
});
return $roles;
}

It all depends on what you're trying to accomplish.
In most cases where someone needs to define roles, creating a separate pivot table that joins tables would be a good way to do it.
Luckily, Laravel's documentation covers this pretty well, you will likely find the answer in this section: http://laravel.com/docs/5.1/eloquent-relationships#many-to-many
Keep reading through that section and all the way down, Taylor goes deeper into the subject and various solutions for different scenarios..
Let's say you have many users and many roles (admin, user, moderator) etc. Many of these users can have different roles and perhaps other attributes, such as if they are a customer or not. You start by creating the user, roles tables (or whatever else needed).
You can then create a joining pivot table, let's say role_user. In it, you can specify foreign keys like user_id which represents id from the user table and role_id which represents id from the role table.
By specifying the foreign keys, you attach a user to a role and then to whatever attribute you would like in another column. So if you have another column in the pivot table that is "customer", which can 1/0 (is customer / is not customer) or maybe you want to add another foreign key which can be customer_id that represents id column in a customer table.
It all depends on what you're trying to accomplish, but it's easy to get snowed in. Using a UML software to model it all out before actually coding to get a abstract overview, could be a good idea. I would recommend StarUML.
Then in your User model you can just bind them by specifying the relationships, something like this:
return $this->belongsToMany('App\Role')->withPivot('column1', 'column2');

Related

How to implement One-To-Many relationship with the same table?

I have a table called user. Now I am building an app where a user can have many users as friends. So I think I should create a new table called friends_list and implement one-to-many relationship where (user) is one and (friends_list) is many. Then to get the list of friends the user has, I could do select * from friends where userId = XXXx.
Is this the best approach? Or is there another better way to create a relationship with the same table?
Your approach is the best approach. You want to represent an n-m relationship (one user has many friends and vice versa).
There are some considerations. If "friendship" is symmetric (that is A friends B automatically means that B friends A), then you probably want to include both in the table when one is inserted. You may also want to prevent a user from self-friending.
If you want to retrieve user's friends as a list, you can do so using a string concatenation function. In Standard SQL, this is:
select listagg(friendid, ',') within group (order by friendid) as friendids
from friends
where userid = XXX;
Different databases have different function names for listagg().
An approach, and clearly NOT the best, would be to use an extra column to store a comma separated value of friend's user_ids.
If the answer to the question "who are my friends?" would not be too difficult to get, you'll need to rely on LIKE %XXXx% conditions and shouldnt expect very fast response times.
Another drawback would be some complexity with the relationship maintenance while editing the friend list.
Therefore, the two tables schema is both the most semantically correct and reliable one.

Is it a good practice to map UserAccount Table with all other tables in SQL Server?

I have UserAccount table and other tables like Employee, Student etc. I want to have an audit like who created a student record or who created a certain employee record. Is it a good practice to have UserAccountId as foreign key in all other tables like Employee, Student etc? I am using hibernate if I mapped like this I have to maintain one to many relationship between UserAccount and All other Classes so code increases and for me that is a burden.
Well it breaks all normalisation rules. Have a link/href table instead. UserAccountID, EmployeeID(NULL), StudentID(NULL). Have one massive linked table like this. The foreign Keys needs to be nullable besides UserAccountID(Primary Key and Foreign Key).
"Good habit/practice" is subjective.
If the business domain includes the fact that the person who created an entity is a meaningful piece of information, and that this is likely to be a regular request by end users, then adding a "createdBy" attribute to your tables/classes is, indeed, good practice.
The best way to know whether this is true is to ask the product owner whether they would need a screen showing "all employees created by user x". If they say "no, only if something goes wrong", you have an audit requirement; if they say "yes, we'll use that regularly", it's an integral part of your business domain.
You may find, that your users want to know not just who created a row, but also who modified it. In that case, there are similar questions on SO.

Relationship redundant?

I'm designing a database and I have a user table with users, and a group table with user's group.
These groups will have a owner (a user that has created it), and a set of users that are part of the group (like a Whatsapp group).
To represent this I have this design:
Do you think the owner column on Group table is necessary? Maybe I can add an owner column on Group table I can know easily the group's owner.
If you don't add the owner in the group then where are you going to add it? The only way I see apart from this is adding a boolean isowner to the usergroup. Anyway, this would not make sense if there will only be 1 owner. If there can be N owners then that would be the way to go.
You are on the right track, but you'll need one more step to ensure an owner must actually belong to the group she owns:
There is a FOREIGN KEY in Group {groupID, owner} that references UserGroup {groupID, userID}.
If your DBMS supports deferred foreign keys, you can make owner NOT NULL, to ensure a group cannot be owner-less. Otherwise you can leave it NULL-able (and you will still be able to break the "chicken-and-egg" problem with circular references if your DBMS supports MATCH SIMPLE FKs - almost all do).
You need 4 tables:
User
UserGroup
Group
UserRole (associated with UserGroup) - Shows the role of a user in a group (admin/owner, etc.) - If your roles are Admin and Ordinary user, you could use a Binary column on UserGroup instead.
I know a solution has already been proposed, but I am so convinced there is a better one ...
At the higher level, the concept of owner can be seen as a property of the relation existing between users and groups. It should then ideally be set as a field in the UserGroup table.
It could be either a boolean field or, even better, a generalized userGroupNatureOfRelation field, that could hold values such as 'owner', 'participant', 'user', or whatever could be the status.
Of course, such a solution allows you to implement any specific business rule, like 'there is only one owner per group'. It will let you implement any other more sophisticated business rule when needed, and it will even allow you to add a level of complexity by adding fields such as:
userGroupRelationStartDate
userGroupRelationEndDate
where you'll be able to follow the nature of the relation between a group and a person through time ...
Of course you could say 'I don't need it'. But implementing such an 'open' model does not cost anything more than what you are thinking of now. Then, if for any reason, in a near or far future, business rules have to be changed or improved, your model stays valid and efficient ...
This said, building views and manipulating data should be a lot easier with this model. So this a good and immediate reason to adopt it!

Database design relations in User and Profile

I'm designing a web application for a school. So far, I'm stuck with the database which has these tables:
users
id
username
password
profile
user_id (FK)
name
last_name
sex
group_id (FK)
(other basic information)
... And other tables irrelevant now, like events, comitees, groups and so on.
So, the users table stores basic information about the login, and the profiles table stores all the personal data about the user.
Now, the *group_id* column in the profile table has a foreign key that references the ID column of the group in which the user is currently enrolled, in the groups table. A user can only be enrolled in one group at once, so there's no need for any additional tables.
The thing is that it doesn't make much sense to me declaring a relation like group HAS MANY profiles. Instead, the relation should be group HAS MANY users, but then, I would have to put a *group_id* column on the users table, which doesn't really fit in, since the users table only stores auth information.
On the other side, I would like to list all the users enrolled in a group using an ORM and getting the a users collection and not profiles. The way I see it, is that the users table is like the 'parent' and the profiles table extends the users table.
The same problem would occur when setting attendances for events. Should I reference the profile as a foreign key in the events_attendance table? Or should I reference the user ID?
Of course both solutions could be implemented and work, but which of them is the best choice?
I have dug a little and found that both solutions would comply with 3NF, so in theory, would be correct, but I'm having a hard time designing the right way my database.
This is a question of your own conventions. You need to decide what is the main entity, right after that you can easiy find a proper solution. Both ways are good, but if you think of User as of the main entity while Profile is a property then you should put GroupId into User, otherwise, if you mean User and Profile as a single entity, you can leave GroupId in Profile, and by this you're not saying group HAS MANY profiles but group HAS MANY users.
By setting a proper one-to-one relation (User-Profile) you can force your data integrity good enough.

What to do if 2 (or more) relationship tables would have the same name?

So I know the convention for naming M-M relationship tables in SQL is to have something like so:
For tables User and Data the relationship table would be called
UserData
User_Data
or something similar (from here)
What happens then if you need to have multiple relationships between User and Data, representing each in its own table? I have a site I'm working on where I have two primary items and multiple independent M-M relationships between them. I know I could just use a single relationship table and have a field which determines the relationship type, but I'm not sure whether this is a good solution. Assuming I don't go that route, what naming convention should I follow to work around my original problem?
To make it more clear, say my site is an auction site (it isn't but the principle is similar). I have registered users and I have items, a user does not have to be registered to post an item but they do need to be to do anything else. I have table User which has info on registered users and Items which has info on posted items. Now a user can bid on an item, but they can also report a item (spam, etc.), both of these are M-M relationships. All that happens when either event occurs is that an email is generated, in my scenario I have no reason to keep track of the actual "report" or "bid" other than to know who bid/reported on what.
I think you should name tables after their function. Lets say we have Cars and People tables. Car has owners and car has assigned drivers. Driver can have more than one car. One of the tables you could call CarsDrivers, second CarsOwners.
EDIT
In your situation I think you should have two tables: AuctionsBids and AuctionsReports. I believe that report requires additional dictinary (spam, illegal item,...) and bid requires other parameters like price, bid date. So having two tables is justified. You will propably be more often accessing bids than reports. Sending email will be slightly more complicated then when this data is stored in one table, but it is not really a big problem.
I don't really see this as a true M-M mapping table. Those usually are JUST a mapping. From your example most of these will have additional information as well. For example, a table of bids, which would have a User and an Item, will probably have info on what the bid was, when it was placed, etc. I would call this table... wait for it... Bids.
For reporting items you might want what was offensive about it, when it was placed, etc. Call this table OffenseReports or something.
You can name tables whatever you want. I would just name them something that makes sense. I think the convention of naming them Table1Table2 is just because sometimes the relationships don't make alot of sense to an outside observer.
There's no official or unofficial convention on relations or tables names. You can name them as you want, the way you like.
If you have multiple user_data relationships with the same keys that makes absolutely no sense. If you have different keys, name the relation in a descriptive way like: stores_products_manufacturers or stores_products_paymentMethods
I think you're only confused because the join tables are currently simple. Once you add more information, I think it will be obvious that you should append a functional suffix. For example:
Table User
UserID
EmailAddress
Table Item
ItemID
ItemDescription
Table UserItem_SpamReport
UserID
ItemID
ReportDate
Table UserItem_Post
UserID -- can be (NULL, -1, '', ...)
ItemID
PostDate
Table UserItem_Bid
UserId
ItemId
BidDate
BidAmount
Then the relation will have a Role. For instance a stock has 2 companies associated: an issuer and a buyer. The relationship is defined by the role the parent and child play to each other.
You could either put each role in a separate table that you name with the role (IE Stock_Issuer, Stock_Buyer etc, both have a relationship one - many to company - stock)
The stock example is pretty fixed, so two tables would be fine. When there are multiple types of relations possible and you can't foresee them now, normalizing it into a relationtype column would seem the better option.
This also depends on the quality of the developers having to work with your model. The column approach is a bit more abstract... but if they don't get it maybe they'd better stay away from databases altogether..
Both will work fine I guess.
Good luck, GJ
GJ