Eloquent - Many to many where not found in the pivot table - php

My DB is set up like...
Accounts --< Accounts_Games >-- Games
Accounts
---------
id INT
Accounts_Games
---------
id INT
account_id INT
game_id INT
Games
---------
id INT
I have managed to get a list of Games by a single Account quite easily using belongsToMany. Now I need to get a list of Games that an Account is NOT joined to.
How can I achieve this in Eloquent?
Thanks

I am didn't know your tables fields in your each tables.
but you can do with this way : add 1 method like this in GamesEloquent file :
public function account_not_join()
{
return $this->belongsToMany('Account', 'accounts_games', 'game_id', 'account_id')->where('is_join', 0);
}

Related

Laravel: fetch pivot relationship through another relationship

Using Laravel, I'd like to fetch an order status (order_status table) from an order (orders table) based on the
locale relationship stored in the orders table using a pivot table (order_status_locale table).
The pivot table contains the "localised" order status from the order.
Of course, I could fetch the localised order status (order_status_locale) directly from the database, but I'd like to
fetch the localised order status through a Laravel relationship.
Something like this:
$order = Order::find(123);
$order->localisedOrderStatus->label;
This is an example of the database structure:
orders:
id: int
locale_id: int
...other columns
locales:
id: int
...other columns
order_statuses:
id: int
...other columns
order_status_locale:
order_status_id: int
locale_id: int
label: varchar
its sometimes better to make model of your pivot table. like OrderStatusLocale.php
then you can make the relation through it.
lastly if you want to achieve
$order->localisedOrderStatus->label;
you can use laravel has one through. or i think its better to go through the relation like $order->order_status->locale->label

Laravel the right way for Many to Many table structure

I'm having a many to many relation. Lets say that I have Many users that can be in Many groups and the other way around.
I wan't to make a table that contains the following columns
group_user
id / name / user_id / group_id
Since I have only 3 groups Junior, Middle and Senior I don't want to make another separated table for them. My idea here is to make the following approach:
Creating 3 records in the same table group_user with the following data
id / name / user_id / group_id
1 / Junior / null / null
2 / Middle / null / null
3 / Senior / null / null
So now when I want to insert a group_id I will use this 3 ID's that I just created with NULL user_id and group_id.
My records will look something like this:
id / name / user_id / group_id
4 / NULL / 125 / 1 -> The id of the Junior group that is in the same table.
5 / NULL / 125 / 3 -> The id of the Senior group that is in the same table.
Is this a valid way to do it? How wrong it is?
I would recommend following the correct procedures as follows:
Table 1 users table:
id | name
Table 2 groups table:
id | name
Table 3 group_user pivot table:
id | user_id | group_id
Note: Table 3 should never hold a nullable value
The relation would be as follows, right now we have two models, a User model and a Group model.
both will have a belongsToMany relation towards each other.
Here is the method you will use in the User model:
public function groups()
{
$this->belongsToMany(User::class);
}
And here is the method you will use in the Group model:
public function users()
{
$this->belongsToMany(Group::class);
}
This is the recommended way to continue.

Resolving table(mysql, php)

I got 3 table, called class , student and class_student(resolving table) . This is due to many to many relationship between class and student. A student can have many class and a class can have many student. The fields inside class is(class_id, class_start_time and class_end_time) , student(student_id, student_name, student_age) , class_student(student_id , class_id). My question would be : Inside a class, it includes student , how do I add student into the class table ? Or should I make use of the resolving table? My understanding of resolving table is weak and I'm not sure what's the purpose of it.
Thank you all for your answer !
What about when I add a new record to class student table , do I add a new record to class table as well?
The most common way to resolve a many to many relationship is via a seperate relation table (as Barmar noted).
In your case that table could have these fields:
table class_students
--------------------
id // an unique id of that relationship;
// could be ommitted, could be an autoincrement,
// could also be a "handcrafted" id like classid_userid -> 21_13 (I need this kind of id's for an ember-api.
// All depending on your needs
class // the id of the related class
student // the id of the related student
// maybe add additional fields:
type // to describe that relationship
sort
You then would get all the students of a specific class like so:
$class_id = 1;
$sql = "Select * from students, class_students where students.id=class_students.student AND class_student.class=".$class_id;
// note, that you should do that via prepared statements,
// this is only for simplicity to show how to proceed.
You are not going to add students in the class table. If you do so, there is no point separating class from student in the first( you have prevented redundancy of data ). I believe the table structure is good enough to achieve your objectives. The secondary keys (student_id , class_id) which are primary key in the student and the class tables respectively does the job.
class table
id| title | start | end
1 Biology 8am 10am
2 English 10am 12pm
student table
id | name |
1 John
2 Doe
student_class table
student_id | class_id
1 1
1 2
2 1
from the table, i could
Get all courses John( user.id: 1 ) registered for
SELECT FROM student_class WHERE student.student_id = '1'
All the students that registered for Biology (class.id: 1)
SELECT FROM student_class WHERE student.class_id = '1'
Note I know you will need the name of the student here in the result.
Very simply , just 'LEFT JOIN' class table with student_class table on student_class.class_id = student.id
Then for each record you get from student_class table, the 'name' (or other columns you choose to include in the result set) will be added from the class table.
Note the way you just joined the class table, you can do the same for student table. for example, You want the student to print their time table for classed they registered for, you will still select from student_class table and get the start and the end time using LEFT JOIN

Structuring MySQL table (infinite amount columns)

like title says, I'm wondering how you can structure a mySQL table to be able to add infinite (or high, ≈1000) amount columns.
Basically, I want a table containing column with school classes. Each class has some students in it with their name and last name. The structure I want it something like this:
-----Class 1-----------
Lastname-Surname
1. Michel Ericsson
2. Erica Bloom
....
-----Class 2-----------
Lastname-Surname
1. Fred Jackson
2. Erica Hancock
....
......
I think what you want to do is create a Many to Many relation between a "Class" table and your "Student" table. For example you have a table
Class
id: int (primary key auto-incremented)
name: varchar
And another table :
Student
id: int (primary key auto-incremented)
name: varchar
surname: varchar
And then, you need a table that will be the link between these previous two :
Class_student
class_id: int (primary key)
student_id: int (primary key)
This way you can link as many Students to as many classes you want.

PHP select row from db where ID is found in group of IDs

I have 3 employers IDs: 1, 2 and 3. I am generating tasks for each one by adding a line in database and in column "for_emp" I insert IDs I want to assign this task for and could be all 3 of them separated by comma. So let's say I got a task and "for_emp" is "1,2,3", the employers IDs. If I would like to select all tasks for the ID 2, will I be able to select from the row that has "1,2,3" as IDs and just match "2" there ? If not, how do you suggest I insert my emp IDs into one row in database ? The db is MySQL.
Any ideas ? Thanks.
Don't do it like that, you should normalize your database.
What you want to do is have a table such as task, and then task_assignee. task_assignee would have fields task_id and user_id. If a task has eg. three assignees (IDs 1, 2 and 3), then you'll create three rows in the task_assignee table for that one task, like this:
+--------+---------+
|task_id | user_id |
+--------+---------+
| 1 | 1 [
| 1 | 2 [
| 1 | 3 [
+--------+---------+
Then it's just a simple matter of querying the task_assignee table to find all tasks that are assigned to a given user.
Here's an example of how to get all the tasks for user_id 2:
SELECT t.* FROM task AS t INNER JOIN task_assignee AS ta WHERE ta.user_id = 2
EDIT.
Just as a related note, even if you didn't do it the right way (which I described in my answer previously), doing it with hacks such as LIKE would still be far from the optimal solution. If you did store a list of comma-separated values, and needed to check if eg. the value 2 is in the list, you could use the MySQL's FIND_IN_SET function:
SELECT * FROM task WHERE FIND_IN_SET(2, for_emp)
But you shouldn't do this unless you have no choice (eg. you're working with someone's shitty DB design), because it's way more inefficient and won't let you index the the employee ID.
The following query should do what you want:
SELECT * FROM tasks WHERE for_emp LIKE '%2%';
However, be aware that that would also match employers 12, 20, 21 etc; so take care if you expect you might end up in double-digits.
However, the other answers about renormalising your database are definitely preferable.
You're doing it wrong. Create a relation table with two fields: employee id and task id. If one task should be assigned to three employees, insert three rows in the relation table.
You then use JOIN to join the task, employee and relation tables.
then its no proper relation...
I would suggest a "mapping table" for the n:m relation
employee
id
task
id
employeetask
task_id
employee_id
Make a table for your employers. Insert your three rows in it.
Then make a table for mapping tasks to employers. If a task is assigned to three employers, insert three rows into this table. This is basic entity-relation work.
I would make 2 different tables.
1 with employees, and 1 with tasks.
then make another table which combines the two tables, I will call it Assigned Tasks.
Then in assigned tasks I make a assigned id, a employeenumber which is a FK to the employee table and a taskid which is a FK to the Tasks table.
If an employee has more than 1 task. Just insert another row in the assigned table. ;)
When its about Databases, try to think in solo entities! Combining those entities is able in antoher table.
sql example:
Select * from Assignedtasks where employeeID = 1 will give you all his/her tasks. :)
You could use a LIKE '%,2,%' clause in your SELECT statement.
eg:
SELECT * FROM table where for_emp LIKE '%,2,%'
However performance of such non-sargable queries is usually quite bad.
I would suggest that you insert a row each for each employee who is assigned to the task using a separate TASK_EMPLOYEE_MAPPING table with taskId, employeeId as a composite primary key.
With such a design, your query will be
SELECT * FROM TASK_EMPLOYEE_MAPPING WHERE employeeId = '2'

Categories