So i'm trying to get my head around using eloquent for many to many relationships in my application.
I have three tables as followed
user
+----------------+------------------+------+-----+---------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------+------------------+------+-----+---------------------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| first_name | varchar(255) | NO | | NULL | |
| last_name | varchar(255) | NO | | NULL | |
| email | varchar(255) | NO | UNI | NULL | |
| password | varchar(60) | NO | | NULL | |
| remember_token | varchar(100) | YES | | NULL | |
| created_at | timestamp | NO | | 0000-00-00 00:00:00 | |
| updated_at | timestamp | NO | | 0000-00-00 00:00:00 | |
| active | enum('yes','no') | NO | | NULL | |
| last_login | timestamp | NO | | 0000-00-00 00:00:00 | |
+----------------+------------------+------+-----+---------------------+----------------+
user_has_address
+------------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+------------------+------+-----+---------+-------+
| address_id | int(10) unsigned | YES | MUL | NULL | |
| users_id | int(10) unsigned | YES | MUL | NULL | |
+------------+------------------+------+-----+---------+-------+
address
+---------------+----------------------------+------+-----+---------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+----------------------------+------+-----+---------------------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| name_number | varchar(45) | NO | | NULL | |
| first_line | varchar(45) | NO | | NULL | |
| second_line | varchar(45) | NO | | NULL | |
| town_city | varchar(45) | NO | | NULL | |
| state_country | varchar(45) | NO | | NULL | |
| post_zip | varchar(45) | NO | | NULL | |
| type | enum('delivery','billing') | NO | | NULL | |
| created_at | timestamp | NO | | 0000-00-00 00:00:00 | |
| updated_at | timestamp | NO | | 0000-00-00 00:00:00 | |
| deleted_at | timestamp | YES | | NULL | |
+---------------+----------------------------+------+-----+---------------------+----------------+
in my user repository i have the following
namespace App\Libraries\Repositories\Core\Users;
use Schema;
use App\Models\Core\User;
use Bosnadev\Repositories\Eloquent\Repository;
use Symfony\Component\HttpKernel\Exception\HttpException;
class UserRepository extends Repository
{
public function getUsersAddresses()
{
return $this->userModel->hasManyThrough('App\Models\Bundle\Addresses\Address','App\Models\Bundle\Addresses\UserHasAdress','id','address_id');
}
}
Im returned an object that shows parent and related classes but im not actually returned my users address. Is there something im missing?
Alexrussell made some good points in his comment that you could possibly address, however I believe your immediate problem is a missing ->get() at the end of your return line.
Without it, you would be required to call your method like:
$repository->getUsersAddresses()->get();
As hasManyThrough will return an instance of Illuminate/Database/Eloquent/Relations/HasManyThrough not the actual results
For reference:
https://laravel.com/api/5.2/Illuminate/Database/Eloquent/Relations/HasManyThrough.html
Note in the example here: https://laravel.com/docs/5.1/eloquent-relationships#many-to-many
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* The roles that belong to the user.
*/
public function roles()
{
return $this->belongsToMany('App\Role');
}
}
The example usage includes a get(): $roles = App\User::find(1)->roles()->orderBy('name')->get();
Hope this helps
Related
I have a trouble with relationship on laravel 9 with code detail below:
namespace App\Models;
use App\Traits\HasMeta
class PostModel extends Model{
use HasMeta;
}
namespace App\Traits;
use App\Models\MetaModel;
trait HasMeta{
public function meta() {
return $this->morphOne(MetaModel::class, 'metas', 'model_type', 'model_id') ;
}
}
And my schemas is:
+---------------------+-------------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------------+-------------------------+------+-----+---------+----------------+
| id | bigint(20) unsigned | NO | PRI | NULL | auto_increment |
| model_id | int(11) | NO | MUL | NULL | |
| model_type | varchar(255) | NO | | NULL | |
| meta_slug | varchar(255) | NO | UNI | NULL | |
| meta_title | varchar(255) | YES | | NULL | |
| meta_description | text | YES | | NULL | |
| meta_keywords | text | YES | | NULL | |
| meta_canonical | varchar(255) | YES | | NULL | |
| meta_index | enum('index','noindex') | NO | | noindex | |
| meta_og_title | varchar(255) | YES | | NULL | |
| meta_og_description | text | YES | | NULL | |
| meta_tw_title | varchar(255) | YES | | NULL | |
| meta_tw_description | text | YES | | NULL | |
| created_at | timestamp | YES | | NULL | |
| updated_at | timestamp | YES | | NULL | |
+---------------------+-------------------------+------+-----+---------+--------------
But when i used method $post->meta()->save(array $data) -> it's ok and insert to database with value
+----+----------+----------------------+
| id | model_id | model_type |
+----+----------+----------------------+
| 1 | 83 | App\Models\PostModel |
+----+----------+----------------------+
However when i used $post->meta --> it always return null.
My sql laravel output:
select * from `ord_metas` where `ord_metas`.`model_id` in (83) and `ord_metas`.`model_type` = 'App\Models\PostModel'
If model_type with double slash like 'App\\Models\\PostModel' --> it will be ok on mysql query
How can i fix it. Thank for reading and sorry for my bad english
Make a method inside the MetaModel like
public function metable ()
{
return $this->morphTo();
}
and make another method inside your trait or postModel like
public function meta()
{
return $this->morphOne(MetaModel::class , 'metable');
}
Now you can load the relationship as $post->meta Hope this helps you.
I have three tables
users table
+--------------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------------------+--------------+------+-----+---------+----------------+
| Id | bigint | NO | PRI | NULL | auto_increment |
| AccountNumber | varchar(50) | YES | | NULL | |
| DisplayName | varchar(255) | YES | MUL | NULL | |
| ParentAccountId | bigint | YES | MUL | NULL | |
| AccountTypeRef | bigint | YES | MUL | NULL | |
| PhoneNo | varchar(255) | YES | | NULL | |
| FaxNo | varchar(50) | YES | | NULL | |
| Website | varchar(200) | YES | | NULL | |
| Email | varchar(100) | YES | | NULL | |
| StateRef | bigint | YES | MUL | NULL | |
| Address | longtext | YES | | NULL | |
| PostalCode | varchar(50) | YES | | NULL |
products table
+-------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+--------------+------+-----+---------+----------------+
| Id | bigint | NO | PRI | NULL | auto_increment |
| ProductId | bigint | YES | MUL | NULL | |
| PackName | varchar(255) | YES | | NULL | | |
| Price | double | YES | | NULL | |
| OnlineInfoAddress | varchar(255) | YES | | NULL | |
| Description | longtext | YES | | NULL | |
| IsDelete | tinyint | YES | | NULL | |
| CreateUserId | bigint | YES | | NULL | |
| CreateDate | datetime | YES | | NULL | |
| EditDate | datetime | YES | | NULL | |
| EditUserId | bigint | YES | | NULL | |
| Tag | int | YES | | NULL | |
| Ref | varchar(50) | YES | | NULL | |
| deleted_at | timestamp | YES | | NULL | |
+-------------------+--------------+------+-----+---------+----------------+
users_buy table
+---------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-----+---------+----------------+
| Id | bigint | NO | PRI | NULL | auto_increment |
| users_id | bigint | YES | MUL | NULL | |
| product_id | bigint | YES | MUL | NULL | |
| BuyDate | datetime | YES | | NULL | |
| CountBuy | int | YES | | NULL | |
| TotalPrice | double | YES | | NULL | |
| Description | longtext | YES | | NULL | |
| invoiceNumber | varchar(255) | YES | | NULL | |
+---------------+--------------+------+-----+---------+----------------+
I want to get users who did not buy a specific product
for example, user number 20 bought 5 product with ids [1,2,3,4,5]
and user number 19 bought 3 product with ids [1,2,3]
And user number 18 bought 2 product with ids [1,3]
I want to get users who did not buy any product with the id 5
ie I want user 18 and 19
How can I do this?
This will list of all users that did not buy product id 5:
SELECT *
FROM users
WHERE
Id NOT IN (
SELECT users_id
FROM users_buy
WHERE product_id = 5
)
One more solution used LEFT JOIN:
SELECT users.*
FROM users
LEFT JOIN users_buy
ON users_buy.users_id = users.id AND users_buy.product_id = 5
WHERE users_buy.user_id IS NULL;
The above query will return records from users table have not matched rows in users_buy table with product_id 5
I have two tables, users and lifts.
On my UI (php webpage), I have two drop downs (as well as others, irrelevant), one drop down is [userlastname, userfirstname], and the other is [destination]
the query i am using is this:
SELECT * FROM lifts l JOIN users u ON l.user_id=u.uid GROUP BY l.id;
which gives me the list of usernames in users (correctly)
[Harvey Fletcher]
[Ronald McDonald]
[Harvey Fletcher]
and also a list of all destinations
[Destination 1]
[Destination 2]
[Destination 3]
But as you can see from the usernames list, [Harvey Fletcher] has appeared twice. How can I stop this from happening? Table structure below.
Users:
+---------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------------+--------------+------+-----+---------+----------------+
| uid | int(10) | NO | PRI | NULL | auto_increment |
| title | varchar(10) | NO | | NULL | |
| firstname | varchar(100) | NO | | NULL | |
| lastname | varchar(100) | NO | | NULL | |
| email | varchar(500) | NO | | NULL | |
| password | varchar(500) | NO | | NULL | |
| reg_no | varchar(10) | YES | | NULL | |
| vehicle_make | varchar(50) | YES | | NULL | |
| vehicle_colour | varchar(25) | YES | | NULL | |
| licence_no | varchar(50) | YES | | NULL | |
| address_line1 | varchar(75) | NO | | NULL | |
| address_line2 | varchar(75) | NO | | NULL | |
| town_city | varchar(75) | NO | | NULL | |
| postcode | varchar(10) | NO | | NULL | |
| reputation_positive | int(10) | YES | | 0 | |
| reputation_negative | int(10) | YES | | 0 | |
| telephone_number | char(11) | NO | | NULL | |
+---------------------+--------------+------+-----+---------+----------------+
Lifts:
+-----------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+--------------+------+-----+---------+----------------+
| id | int(10) | NO | PRI | NULL | auto_increment |
| user_id | int(10) | NO | | NULL | |
| lift_to | varchar(50) | NO | | NULL | |
| lift_from | varchar(50) | NO | | NULL | |
| quote_price | varchar(50) | NO | | NULL | |
| available_seats | int(2) | YES | | 1 | |
| depart_date | varchar(20) | NO | | NULL | |
| depart_time | varchar(10) | NO | | NULL | |
| pickup_location | varchar(100) | NO | | NULL | |
+-----------------+--------------+------+-----+---------+----------------+
Info:
Harvey Fletcher is only in users table once
Harvey Fletcher has two 'lifts', which is why it appears twice.
Ronald McDonald only has one, so only appears once, but if I added a second lift, would be displayed 2 times.
Group your query to users instead of lifts:
SELECT * FROM lifts l JOIN users u ON l.user_id=u.uid GROUP BY u.uid;
I'm working in Laravel and need help with database relations. I have three tables:
projects:
+------------+--------------------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| title | varchar(191) | NO | | NULL | |
| url | varchar(191) | YES | | NULL | |
| updated | bigint(20) unsigned | YES | | NULL | |
| type | enum('adobe','invision','pdf') | NO | | NULL | |
| preview_id | int(10) unsigned | YES | MUL | NULL | |
+------------+--------------------------------+------+-----+---------+----------------+
users:
+----------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | | NULL | |
| email | varchar(150) | NO | UNI | NULL | |
| password | varchar(179) | NO | UNI | NULL | |
| remember_token | varchar(100) | YES | | NULL | |
+----------------+------------------+------+-----+---------+----------------+
projects_users
+------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| project_id | int(10) unsigned | YES | MUL | NULL | |
| user_id | int(10) unsigned | NO | MUL | NULL | |
+------------+------------------+------+-----+---------+----------------+
Situation: There are several projects, and multiple users can work on multiple projects (ManyToMany).
I need to select (SELECT-statement) all users working on project with e.g ID 1.
How would I do that in plain SQL, and how would I do that in Laravel code (without a raw-sql-query function).
I already looked here but I ain't really catching it.
Thanks!
Use the whereHas() method:
$users = User::whereHas('projects', function($q) use($projectId) {
$q->where('id', $projectId);
})->get();
class Project extends Model{
public function users()
{
return $this->belongsToMany('App\User', 'projects_users');
}
}
class User extends Model{
public function projects()
{
return $this->belongsToMany('App\Project', 'projects_users');
}
}
$project = Project::find(1);
$project->users //list of all the users
I have two tables. This one is called teams:
+------------+--------------+------+----------------------+----------+
| Column | Type | Null | Default | Comments |
+------------+--------------+------+----------------------+----------+
| id | int(10) | No | | |
| apikey | varchar(255) | Yes | NULL | |
| name | varchar(255) | Yes | NULL | |
| logo | varchar(255) | Yes | NULL | |
| url | varchar(255) | Yes | NULL | |
| hashtag | varchar(255) | Yes | NULL | |
| created_at | timestamp | No | 0000-00-00 00:00:00 | |
| updated_at | timestamp | No | 0000-00-00 00:00:00 | |
+------------+--------------+------+----------------------+----------+
The other one is called streamers:
+--------------+--------------+------+----------------------+----------+
| Column | Type | Null | Default | Comments |
+--------------+--------------+------+----------------------+----------+
| id | int(10) | No | | |
| apikey | varchar(255) | Yes | NULL | |
| name | varchar(255) | Yes | NULL | |
| team | int(11) | Yes | NULL | |
| type | varchar(255) | Yes | NULL | |
| twitch | varchar(255) | Yes | NULL | |
| mlg | int(11) | Yes | NULL | |
| url | varchar(255) | Yes | NULL | |
| twitter | varchar(255) | Yes | NULL | |
| status | int(11) | Yes | NULL | |
| viewers | int(11) | Yes | NULL | |
| created_at | timestamp | No | 0000-00-00 00:00:00 | |
| updated_at | timestamp | No | 0000-00-00 00:00:00 | |
| last_live | timestamp | No | 0000-00-00 00:00:00 | |
| last_edit_by | int(11) | Yes | NULL | |
+--------------+--------------+------+----------------------+----------+
As you can see, the streamers table has a team field which is only the team ID.
My Team.php model already has this:
public function streamers()
{
return $this->hasMany('Streamer', 'team');
}
Here's what I want to do
I want to search the streamers by team, HOWEVER the end user should only have to use the name not the ID. How do I make the table relationship so that I can query the streamers table for the team name instead of the ID? Is this possible at all?
I would've assumed this is exactly what relationship hasOne is for, but apparently I was wrong. Since I obviously don't have the streamer ID's in the team table because every streamer ID on a team would be awful. Laravel relationships seems kinda wrong here... Because hasOne would fit on streamers but it only works with teams, but essentially the streamers have a team and the team belongs to many streamers and that would mean belongsToMany would make sense.
Thanks
What you're looking for is the belongsTo relationship.
In streamers include:
public function team()
{
$this->belongsTo('Team','team');
}
You can then query streamers by team like so:
$streamer = Streamer::whereHas('team', function($q)
{
$q->where('name', 'like', $teamName);
})->get();
More details can be found in the docs: http://laravel.com/docs/eloquent#querying-relations