i have two table
media and trainingVideo.
training video having two column video_id and second_video_id
videos store in media table.
i want two relationship both video in trainigtable.
//Model
// trainingModel
public function media()
{
return $this->belongsTo(Media::class, ['video_id', 'second_video']);
}
// Media model
public function trainingVideos()
{
return $this->hasMany(TrainingVideo::class, 'id');
}
$a = TrainingVideo::with('media')->get();
i want both video in this relationship.
please help me to solved this.
Answer
Syntax:-
$model = Model::with('relatedModel', 'relatedModelTwo')->get();
So in your case, it can be something like this.
$a = TrainingVideo::with('media','trainingVideos')->get();
When you dd($a), you should see the related models in the relations array attribute.
To access the relations' properties from there, it is simply
$a->media->media_Attribute
$a->trainingVideos->trainingVideos_Attribute
Laravel Relationship Doc :- https://laravel.com/docs/5.1/eloquent-relationships#one-to-one
use model belongsTo two Ids in laravel for relationship
https://stackoverflow.com
Eloquent: Relationships - Laravel - The PHP Framework For Web Artisans
https://laravel.com
Related
I'm new to Laravel. I am developing a project. and in this project I have 4 tables related to each other
-Users
-Orders
-OrderParcels
-Situations
When listing the parcels of an order, I want to get the information of that order only once, the user information of that order once again, and list the parcels as a table under it. so far everything ok. but I also want to display the status of the parcels listed in the table as names. I couldn't add the 4th table to the query. do you have a suggestion? I'm putting pictures that explain the structure below.
My current working code is
$orderParcels = Orders::whereId($id)
->with('parcels')
->with('users:id,name')
->first();
and my 'orders' model has method
public function parcels(){
return $this->hasMany(OrderParcels::class);
}
public function users(){
return $this->hasOne(User::class,'id','affixer_id');
}
Note[edit]: I already know how to connect like this
$orderParcels = DB::table('order_parcels as op')
->leftjoin('orders as o','op.orders_id','o.id')
->leftjoin('users as u','o.affixer_id','u.id')
->leftjoin('situations as s','op.status','s.id')
->select('op.*','o.*','u.name','s.situations_name')
->where('op.orders_id',$id)->get();
but this is not working for me, for each parcels record it returns me orders and user info. I want once orders info and once user info.
Laravel provides an elegant way to manage relations between models. In your situation, the first step is to create all relations described in your schema :
1. Model Order
class User extends Model {
public function parcels()
{
return $this->hasMany(OrderParcels::class);
}
public function users()
{
return $this->hasOne(User::class,'id','affixer_id');
}
}
2. Model Parcel
class Parcel extends Model {
public function situations()
{
return $this->hasOne(Situation::class, ...);
}
}
Then, you can retrieve all desired informations simply like this :
// Retrieve all users of an order
$users = $order->users; // You get a Collection of User instances
// Retrieve all parcels of an order
$parcels = $order->parcels; // You get a Collection of User instances
// Retrieve the situation for a parcel
$situations = $parcel->situations // You get Situation instance
How it works ?
When you add a relation on your model, you can retrieve the result of this relation by using the property with the same name of the method. Laravel will automatically provide you those properties ! (e.g: parcels() method in your Order Model will generate $order->parcels property.
To finish, in this situation where you have nested relations (as describe in your schema), you should use with() method of your model to eager load all the nested relation of order model like this :
$orders = Orders::with(['users', 'parcels', 'parcels.situations'])->find($id)
I encourage you to read those stubs of Laravel documentation :
Define model relations
Eager loading
Laravel Collection
Good luck !
Use join to make a perfect relations between tables.
$output = Orders::join('users', 'users.id', '=', 'orders.user_id')
->join('order_parcels', 'order_parcels.id', '=', 'orders.parcel_id')
->join('situations', 'situation.id', '=', 'order_parcels.situation_id')
->select([
'orders.id AS order_id',
'users.id AS user_id',
'order.parcels.id AS parcel_id',
'and so on'
])
->where('some row', '=', 'some row or variable')->get();
Hi I have a problem with Laravel`s pivot table.
I have the following tables: students, courses and lessons.
The table lessons is connected with courses through a foreign key courses_id, and the tables students and courses are connected through a pivot courses_students.
So I can access the information through students like this:
//Students model
public function courses()
{
return $this->belongsToMany(Courses::class,'courses_students','student_id', 'course_id')
->with('lessons');
}
//Courses model
public function lessons()
{
return $this->hasMany(Lesson::class);
}
This works completely fine for this kind of relationship, but I want to add a third column in the pivot with name lesson_id for the lessons table.
I am doing this because, sometimes I need to get a specific set of lessons from each course for each user.
I succeeded in doing so, by using a model courseStudent for the pivot table.
Using the model for pivot my calls became like this.
Student->with('courseStudent.courses')
->with('courseStudent.lessons')
->get();
This partially does what I need it to do, but I want to maintain the relation ship between courses and students.
Is there a way to achieve that?
Example from docs(go through Many To Many):
return $this->belongsToMany('App\Role')->withPivot('column1', 'column2');
Pivot table is meant to use belongsToMany relationship on both entities.
So your students and courses should have it defined if you want pivot table between that is using eloquent default capacity.
As a side note pay attention on naming convention because that way you will reduce issues on minimum: pivot table should be tableanamesingular_tablebnamesingular where order is set by alphabetical order of tables' names (i.e. post_user Yes, user_post No).
Id fields in pivot table should be tablenamesingular_id.
You can set names however you want but this way you will have less unepected behavior in future using eloquent. All of this you have in documentation page and I recommend you go through it thoroughly.
Other way is to use dynamic properties for getting certain values. Example from docs:
$user = App\User::find(1);
foreach ($user->roles as $role) {
echo $role->pivot->created_at;
}
If you would like to manually change values in pivot table, you should create separate model for it that would be connected with that entity/table (pay attention that pivot model extends Pivot as in example from docs rather than Model):
<?php
namespace App;
use Illuminate\Database\Eloquent\Relations\Pivot;
class PostUser extends Pivot
{
// other definitions related
}
You can use join for third relation:
public function courses(){
return $this->belongsToMany(Courses::class,'courses_students','student_id', 'course_id')
->withPivot('lesson_id')
->join('lessons','lesson_id','=','lessons.id')
->select('lessons.id','lessons.title', ...);
}
If you are going to use the same pivot table for courses and lessons, you can to do something like this:
//Students model
public function courses()
{
return $this->belongsToMany(Courses::class,'courses_students','student_id', 'course_id')
->whereNotNull('course_id');
}
public function lessons()
{
return $this->belongsToMany(Lessons::class,'courses_students','student_id', 'lesson_id')
->whereNotNull('lesson_id');
}
Then just use it:
$courses = $student->courses;
$lessons = $student->lessons;
I am trying to retrieve the thumb image path by joining the images table to the listing table. As such, I have the following query in my controller.
$listings = Listing::select('listings.*, images.path as image_path')
->where('listings.ownerid', '=', $ownerid)
->leftJoin('images', 'listings.thumbId', '=', 'images.id')->get();
After testing out the function, the query fails since laravel interprets the query as
select `listings`.`*, images`.`path` as `image_path` from `listings` left join `images` on `listings`.`thumbId` = `images`.`id` where `listings`.`ownerid` = 1)
Notice the asterisk (*) is joined with the ", images" word making it '*, images'.
The query works fine without laravel's odd typo. How does one fix this issue?
You need to do one change in your query. You are passing raw select fields so you need to use selectRaw() instead of select(). Like
$listings = Listing::selectRaw('listings.*, images.path as image_path')
->where('listings.ownerid', '=', $ownerid)
->leftJoin('images', 'listings.thumbId', '=', 'images.id')->get();
check by try above query.
I suggest you to use Laravel Eloquent Relationships feature. Since your code above is more like Query Builder rather than Eloquent. Let's see the example bellow:
You will have 2 Models, 1 for each table (listings, images):
App\Listing Model:
<?php
...
use App\Image;
class Listing extends Eloquent {
...
protected $table = 'listings';
// define Eloquent Relationship of Listing model to Image model
public function image() {
return $this->belongsTo(Image::class, 'thumbId');
}
...
}
App\Image Model:
<?php
...
use App\Listing;
class Image extends Eloquent {
...
protected $table = 'images';
...
// define Eloquent Relationship of Image model to Listing model
public function listings() {
return $this->hasMany(Listing::class, 'thumbId');
}
}
So how to get the data?
// get all listing data
$listings = Listing::all();
// loop through the data
foreach ($listing as $listing) {
dump($listing->id);
// because we have define the relationship, we can access the related data of image
dump($listing->image->path);
// call $this->image will return related Image model
dump($listing->image);
}
You can see Laravel official documentation for more example and explanation.
Hope it helps.
I have a complicated relationship I'm trying to establish between two models.
The goal is to use $supplier->supply_orders to access the orders where the user supplies an item.
This throws: LogicException: Relationship method must return an object of type Illuminate\Database\Eloquent\Relations\Relation.
With the code I've got I can use $supplier->supply_orders()->get(), however, when I try to use it as a relationship it throws. Since this is a relationship I should be able to wrap it in a relationship, but how would I go about doing that?
Supplier Model:
class Supplier extends Model {
public function supply_orders() {
return Order::query()
->select('order.*')
->join('item_order', 'order.id', '=', 'item_order.order_id')
->join('item', 'item_order.item_id', '=', 'item.id')
->where('item.supplier_id', '=', $this->id);
}
}
~~~ A whole lot of back info that I don't think you need but might ~~~
sql tables:
supplier
- id
items:
- id
- supplier_id
item_order:
- id
- order_id
- item_id
orders:
- id
The other Eloquent Models:
class Item extends Model {
public function orders() {
return $this->belongsToMany('Order');
}
}
class Order extends Model {}
Example of how this should work:
$supplier = factory(Supplier::class)->create();
$item = factory(Item::class)->create([
'supplier_id' => $supplier->id,
]);
$order = factory(Order::class)->create();
$order->items()->attach($item);
$orders = $supplier->supply_orders // Throws LogicException
This throws: LogicException: Relationship method must return an object of type Illuminate\Database\Eloquent\Relations\Relation
Sounds like a hasManyThrough with a many to many relationship. Laravel has no inbuilt support for this but you can always go ahead and write your own relationship like this: https://laravel.io/forum/03-04-2014-hasmanythrough-with-many-to-many
If you dont want relationships you can always do something like:
Order::whereHas('items.supplier', function($query) use($supplier) {
$query->where('id', $supplier->id);
});
For this to work, you need to have a relationship function items in your Order model and a relationship function supplier in your item model
I believe the reason it throws a relationship error is that you haven't created an Eloquent relation for
$supplier->supply_orders.
Instead, Laravel looks at your supply_orders() as a method in the class, and thus can't figure out which table to use as the pivot. To get the base relationship to work within Eloquent, you'd need to create a new pivot table for the relationship between suppliers and orders something like:
suppliers
-id
orders
-id
order_supplier
-id
-order_id
-supplier_id
From here, Laravel will accept a simple many to many relationship between the two (this would not cause a failure):
Supplier Class:
/**
* Get all orders associated with this supplier via order_supplier table
*
* #return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function orders(){
return $this->belongsToMany("\App\Order");
}
Now that the relationship is solid both between the suppliers and orders, as well as the orders and items, you can eager load the relationship in all directions. Where it gets complicated for your particular need with the current DB setup is that you have a 3rd parameter from the items table that is not a direct pivot. Without having to re-structure the DB, I think the easiest would be to load your suppliers and the relationships like normal:
$suppliers = Supplier::with('orders', function($query) {
$query->with('items');
});
From here you've got all the relationships loaded and can draw down the ones with the right item->ids in a follow-up to the $suppliers collection. There are quite a few ways to skin the cat (even including all in one query) now that you have the Eloquent relationship... but I tend to keep it a little more simple by breaking it into a few readable bits.
Hope this helps.
Good day to you all...
I'm trying to access a collection based on a column in a related table within Eloquent (Laravel 4.2).
I have the following tables:
tags:
(int) id
(string) name
tag_usage:
(int) id
(string) model (the name of the model that is allowed to use the tag)
tag_tag_usage: (pivot)
(int) id
(int) tag_id
(int) tag_usage_id
I also have a taggables (polymorphic to store tags for multiple models) table which I believe is out of scope here as I only want to retrieve the tags that am allowed to use for each model.
My tag model has the relationship
public function usage()
{
return $this->belongsToMany('TagUsage');
}
and the TagUsage model has
public function tags() {
return $this->belongsToMany('Tag');
}
Now, what I want to do is return the tags that ONLY have a specific usage, some pseudo code would be
get_tags->where(tag_usage.model = modelname)
which would return only a subset of the tags.
Tried a few things with no success so over to the many fine brains available here.
Many thanks.
You need to use whereHas in the following way:
$tags = Tag::whereHas('usage', function($q)
{
$q->whereModel('modelname');
})->get();