Joining pivot table to access data - laravel

I am trying to access data from a database query which I think will need a join. I have users that can be apart of many groups. I am using a belongsToMany
relationship. My Models are like so
class User extends Model
{
protected $table = 'users';
protected $guarded = [];
public function group()
{
return $this->belongsToMany('App\Group', 'users_user_groups')->withPivot('user_id', 'group_id');
}
}
class Group extends Model
{
protected $table = 'user_groups';
protected $guarded = [];
use SoftDeletes;
public function user()
{
return $this->belongsToMany('App\User', 'users_user_groups')->withPivot('user_id', 'group_id');
}
}
When I run everything I need too, I might get data like the following.
users
+----+---------------+
| id | name |
+----+---------------+
| 1 | John Doe |
+----+---------------+
user_groups
+----+---------------+-----------------+
| id | name | description |
+----+---------------+-----------------+
| 1 | Group AA | Something |
+----+---------------+-----------------+
| 2 | Group BB | Something |
+----+---------------+-----------------+
users_user_groups
+----+---------------+-----------------+
| id | user_id | group_id |
+----+---------------+-----------------+
| 1 | 1 | 1 |
+----+---------------+-----------------+
| 2 | 1 | 2 |
+----+---------------+-----------------+
So I know user with the id 1 belongs to the user_groups with ids of 1 and 2. What I am trying to do is grab all the users within my database who
belong to a user_group with the name admin. So I am trying something like this
DB::table('users')->select('userName')
->join('user_groups', 'users_user_groups')
->where('name', '=', 'admin')->get();
This I know is all wrong, how can I get all users within a group when using belongsToMany and a pivot table?
Thanks

Eloquent uses relations, not the query builder.
You can achieve what you're aiming for by doing something like this:
$group = Group::where('name', 'admin')->first();
$users = $group->users; // Where users is the name of your relationship (At the moment you have user)
Under the hood that will do two SQL statements and map them together in eloquent objects, rather than a join. The statements will look something like this:
select * from user_groups where name = ? and deleted_at is not null limit 1
select * from users where id in (?, ?)
When you have an instance Group you execute the relationship by calling it as if it was a property. So after that $users will contain a collection of User instances, so you can just loop through them:
foreach ($users as $user) {
// Do something with $user
}

Related

How to query a table based on criteria of another table in Laravel?

In my laravel project I have an inventory and a medicine table which the formats are as the following:
Inventory Table
id | medicine_id | expiry_date
-------|-----------------|-------------
1 | 1 | 13-11-2021
2 | 2 | 01-01-2020
3 | 2 | 23-05-2024
Medicine Table
id | name | category
-------|-----------------|-------------
1 | Hemophine | Syringe
2 | andrenalin | Tablet
3 | aspirin | Capsule
The models are set as below:
Inventory Model
class Inventory extends Model
{
public $incrementing = false;
public function medicine(){
return $this->belongsTo('App\Medicine', 'medicine_id');
}
}
Medicine Model
class Medicine extends Model
{
public $incrementing = false;
public function inventory(){
return $this->hasMany('App\Inventory', 'medicine_id');
}
}
For retrieving all the inventories with a specific category such as Syringe, I tried eager loading, but couldn't figure out the flaws. Here is what I did to get all the inventories with a Syringe category, but it didn't work.
public function index()
{
$medicines = Inventory::where('medicine_id'->category, "Syringe")->get();
foreach($medicines as $medicine){
echo $medicine->medicine->name ." ".$medicine->expiry_date;
echo "<br>";
}
}
Now, Is there anyway to get all the inventory items based on their categories they are in? in this case in "Syringe" category?
Your syntax is a bit wrong, in order to load the medicine for each inventory you need to use with and the where function is where('column', value)
So change it to this:
$medicines = Inventory::with([
'medicine' => function($query) {
$query->where('category', "Syringe");
}
])->get();
or even better the other way around:
$medicines = Medicine::with('inventory')->where('category', 'Syringe')->get();

How to combine models and order by model two data in Laravel 5.4

I would like to be able to output leaders in a section by their position in a group. I'm thinking of combining these tables through a pivot table ordered by position from the groups table.
These are the three class I have relationships established
class Leader extends Model
{
public function groups()
{
return $this->belongsToMany('App\Group');
}
}
class Group extends Model
{
public function leaders()
{
return $this->belongsToMany('App\Leader');
}
}
class GroupLeader extends Model
{
// Maybe some function here?
}
I would like to be able to get the groups in the controller and pass them individually kinda like this.
$group1 = Leader::where('group', '=', 'group1_name')->orderBy('position', 'asc');
$group2 = Leader::where('group', '=', 'group2_name')->orderBy('position', 'asc');
return view('page.leadership')->with([
'group1' => $group1,
'group2' => $group2,
]);
Then I would pass the variables to include files which would loop through them in order.
Here is my table structure
leaders
--------
| id
| first_name
| last_name
| deceased
----------
groups
----------
| id
| group
| title
| position
-----------
group_leader
-------------
| id
| group_id
| leader_id
------------
Try it
$groups = Leader::whereIn('group', ['group1_name', 'group2_name'])
->orderBy('position', 'asc')
->groupBy('group', 'id')
->get(['group', 'id']);

Laravel 5 - Eloquent relationship

I have three tables as below:
------------------------------
| users | projects | clients |
|--------|-----------|-------- |
| id | id | id |
| name | client_id | name |
| | user_id | |
| | name | |
------------------------------
So basically the relationship is like:
User hasMany Project
Project belongsTo Client
My question is:
How can I get all clients of a user using eloquent?
Seems like I cannot user hasManyThrough method as there are no project_id in clients table.
So what I wish to achieve is :
foreach($users as $user)
foreach($user->clients as $client) //HOW TO SET UP THIS RELATION?
foreach($client->projects($user)->get() as $project)
$users = User::with('projects')->get();
// organize cleints' project and add for each user
foreach ($users as $user) {
// order projects by client_id
$projects = Collect($user->projects->toArray());
$clients = $projects->groupBy('client_id');
// keep projects data in 'projects' index
$temp = array();
foreach($clients as $client => $projects){
$temp[$client] = array('projects' => $projects);
}
// add clinets data for each user
$user['clients'] = $temp;
}
// output
foreach($users as $user)
foreach($user->clients as $client)
foreach($client['projects'] as $project)
echo 'user-'.$project['user_id'].', clinet-'.$project['client_id'].', project-'.$project['name'].'<br>';
Above code generated this output for me:

Laravel - How to get data like hasOne in a many-to-many relationship

Here are my tables having a many-to-many relationship and group_user as the intermediate table.
| users | groups | group_user |
-------------------------------------------
| id | id | group_id |
| name | name | user_id |
| created_at| creator_id | created_at |
| updated_at| created_at | updated_at |
| | updated_at | |
groups.creator is the user id referenced from users table.
When I try to query the group table, it returns something like this.
[{"id":1,"name":"Akatsuki","creator":1,"created_at":"2015-10-13 12:22:20","updated_at":"2015-10-13 12:22:20"}]
What I want is when I query the groups table, it also returns the user data of the creator like hasOne relationships do.
In User Model
public function groups()
{
return $this->belongsToMany('App\Group')->withTimestamps();
}
In Group Model
public function users()
{
return $this->belongsToMany('App\User')->withTimestamps();
}
After I query the groups, I just overwrite the group_creator column.
foreach($available as $data) {
$data['group_creator'] = User::find($data['group_creator']);
}
Now it returns
[{"id":1,"group_name":"Akatsuki","creator":{"id":1,"firstname":"John","lastname":"Doe","created_at":"2015-10-13 12:19:35","updated_at":"2015-10-13 14:14:41"},"created_at":"2015-10-13 12:22:20","updated_at":"2015-10-13 12:22:20"}]
Along with the user details.

Laravel - Eloquent - Polymorphic relationships with namespaces

I have 2 tables related by a polimorphic relationship:
The Store table:
id | name | ...
15 | my_store | ...
And the Tag table, that is connected to the Store table through the related_id key and the type.
id | related_id | tag | created | type
1 | 15 | test | 00:00:00 | store
2 | 15 | dummy | 00:00:00 | product
So, in that example, the Store "my_store" only has the tag "test" ("dummy" is a tag for a product, not a Store, besides it has the same related_id).
I have the Store model defined in my code as follows:
class Store extends Model {
protected $table = 'store';
public function tags()
{
return $this->morphMany('App\Tag', 'related', 'type');
}
}
And the tag model:
class Tag extends Model {
protected $table = 'tags';
public function related()
{
return $this->morphTo();
}
}
But when I try to run
$store->tags;
I saw that the query that Laravel is trying to run is:
SQL: select * from `mwp_tags` where `mwp_tags`.`related_id` = 46
and `mwp_tags`.`related_id` is not null
and `mwp_tags`.`type` = App\Store)
The query is looking for App\Store instead of store
I cannot change the value in DB and I wouldn't like to use the
protected $morphClass = 'store';
inside the Store model as I don't know if a would have to create another morphMany relationship, probably with another type name.
Somebody knows how to skip this issue? Thanks!
You could try something like this:
public function tags()
{
$default_morph_class = $this->morphClass ?: null;
$this->morphClass = 'store';
$morph_many_query = $this->morphMany('App\Tag', 'related', 'type');
$this->morphClass = $default_morph_class;
return $morph_many_query;
}
The idea being you change the morphClass on the fly and set it back. That allows you to use a different morphClass for a different relationship.

Resources