Laravel get model with relation's pivot condition - php

I need to get all appeals, that have appeal_stage.expiration_date less than NOW().
Now I have following solution:
public function scopeExpired($query) {
$query->join('appeal_stage', 'appeals.id', 'appeal_stage.appeal_id')
->where('appeal_stage.expiration_date', '<=', new Expression('NOW()'));
}
but resulted model dump shows that joined table is recognized as pivot table:
So, I want to ask - Is there some more convenient way to perform this request?
My suggestions is use Illuminate\Database\Eloquent\Relations\Pivot somehow, bu I do not quiet understand, how Pivot can be used here.
UPD 1
Models has next relations:
public function stages()
{
return $this->belongsToMany(Stage::class)->withPivot('prolongated_count', 'expiration_date')->withTimestamps();
}
public function appeals() {
return $this->belongsToMany(Appeal::class);
}

You should be able to do something like this:
$appeal->stages()->wherePivot('expiration_date', '<', $now)->get()

You should create relationship in appeal model
public function stages()
{
return $this->belongsToMany(Stage::class,'appeal_stage','appeal_id','stage_id')->wherePivot('expiration_date','<',Carbon::now())->withTimestamps();
}
In belongs To Many relationship second argument is your Pivot table name

Related

Laravel - Many to Many on pivot table with Eloquent

I have three table which I wanna associate. Shipment_methods, Ship_companies and Payment_methods.
Relations:
Shipment_methods <- pivot1 -> Ship_companies
pivot1 <- pivot2 -> Payment_methods
Well, what I wanna do is e.g. ShipmentMethod_A is attached to ShipCompany_B and for this record (from pivot1) I wanna attach record from Payment_method table through pivot2 table.
ShipmentMethod Model:
public function ship_companies()
{
return $this->belongsToMany(ShipCompany::class, 'shipment_methods_ship_companies', 'shipment_method_id', 'ship_company_id')->withPivot('price_kc', 'price_ha');
}
ShipCompany Model:
public function shipment_methods()
{
return $this->belongsToMany(ShipCompany::class, 'shipment_methods_ship_companies', 'ship_company_id', 'shipment_method_id');
}
What I need to do is I wanna retrieve all Payments for ShipCompany of specific ShipmentMethod like
ShipmentMethods->ship_companies->pivot->payments_methods
Thanx.
I think best way is for you to have a Model that extend Pivoted class for you pivot1. the pivot1 should have id column to use in pivot2. so the code should be like this,
ShipmentMethod Model:
public function ship_companies()
{
return $this->belongsToMany(ShipCompany::class, 'shipment_methods_ship_companies', 'shipment_method_id', 'ship_company_id')->using('App\pivot1')->withPivot('id','price_kc', 'price_ha');
}
note that I have put id in withPrivot and chain using() method
your pivot1 model should be like this,
pivot1 Model:
use Illuminate\Database\Eloquent\Relations\Pivot;
class pivot1 extends Pivot
{
public function Payment_methods()
{
return $this->belongsToMany(Payment_methods::class, 'pivot2_table_name', 'pivot1_id', 'payment_method_id');
}
}
and at the end you can do like this to save to pivot2
ShipmentMethods->ship_companies->pivot->payments_methods()->sync([payment_method_ids])
as all pivot relationship return a collection of array note that you need to loop ShipmentMethods->ship_companies relationship to get to pivot relationship.
Hope this helps!

Laravel relationship returns NULL

I'm try to get relations via laravel Eloquement model. I'm have two models ex Books.php and Magazine.php
in Books.php i have
public function magazines()
{
return $this->hasMany('App\BOOKS', 'id', 'id');
}
Then i'm try to return all magazines, which relate with books
$books = Book::find(123);
$magazines = $books->magazines()->get();
return $magazines;
but i'm have NULL magazines! When i'm add
$magazines = $books->magazines()->toSql();
i'm see this select: select * from "MAGAZINE" where "MAGAZINE"."ID" is null and "MAGAZINE"."ID" is not null - what is it? Why laravel model put "is null and is not null"?
Notice, if i'm change
public function magazines()
{
return $this->belongsToo('App\BOOKS', 'id', 'id');
}
Select would be like this: select * from "MAGAZINE" where "MAGAZINE"."ID" is null
Anyone know, what is this?
There are several problems in your code:
HasMany takes as first parameter the related model class so in your case is pointless to pass App\Book. You should pass App\Magazine assuming that your magazine model is called Magazine
you are not saying to the HasMany relationship what is the name of the foreign key on your magazines table.
That should do the job
public function magazines()
{
return $this->hasMany('App\Magazine', 'book_id', 'id');
}
IMHO i suggest you to read the Laravel documentation before posting here, there are a lot of examples that will explain to you how to work with relationships and database tables. Take a look to One to Many relationships.
EDIT
You can omit the ->get() on the relationship and simply fetch your magazines doing
$magazines = $books->magazines;
You should try this:
Please change and try:
public function magazines()
{
return $this->hasMany('App\MAGAZINE');
}

Laravel -- Flatten data appended via `with`

I've got two models, User and Seminar. In English, the basic idea is that a bunch of users attend any number of seminars. Additionally, exactly one user may volunteer to speak at each of the seminars.
My implementation consists of a users table, a seminars table, and a seminar_user pivot table.
The seminar_user table has a structure like this:
seminar_id | user_id | speaking
-------------|-----------|---------
int | int | bool
The relationships are defined as follows:
/** On the Seminar model */
public function members()
{
return $this->belongsToMany(User::class);
}
/** On the User model */
public function seminars()
{
return $this->belongsToMany(Seminar::class);
}
I am struggling to figure out how to set up a "relationship" which will help me get a Seminar's speaker. I have currently defined a method like this:
public function speaker()
{
return $this->members()->where('speaking', true);
}
The reason I'd like this is because ultimately, I'd like my API call to look something like this:
public function index()
{
return Seminar::active()
->with(['speaker' => function ($query) {
$query->select('name');
}])
->get()
->toJson();
}
The problem is that since the members relationship is actually a belongsToMany, even though I know there is only to ever be a single User where speaking is true, an array of User's will always be returned.
One workaround would be to post-format the response before sending it off, by first setting a temp $seminars variable, then going through a foreach and setting each $seminar['speaker'] = $seminar['speaker'][0] but that really stinks and I feel like there should be a way to achieve this through Eloquent itself.
How can I flatten the data that is added via the with call? (Or rewrite my relationship methods)
Try changing your speaker function to this
public function speaker()
{
return $this->members()->where('speaking', true)->first();
}
This will always give you an Item as opposed to a Collection that you currently receive.
You can define a new relation on Seminar model as:
public function speaker()
{
return $this->belongsToMany(User::class)->wherePivot('speaking', true);
}
And your query will be as:
Seminar::active()
->with(['speaker' => function ($query) {
$query->select('name');
}])
->get()
->toJson();
Docs scroll down to Filtering Relationships Via Intermediate Table Columns

Laravel belongsToMany not returning results

I have the following schema set up:
users:
id
departments:
id
department_user:
id
department_id
user_id
I also have the following relationships set up:
User Model
public function departments()
{
return $this->belongsToMany('App\Resources\Eloquent\Models\Department', 'department_users');
}
Department Model
public function users()
{
return $this->belongsToMany(User::class, 'department_users');
}
For some reason, when I am trying to access through the user model $user->departments, it doesn't work - but $department->users does.
Outputting the eloquent query is as follows:
select `departments`.*, `department_users`.`user_id` as `pivot_user_id`, `department_users`.`department_id` as `pivot_department_id` from `departments` inner join `department_users` on `departments`.`id` = `department_users`.`department_id` where `department_users`.`user_id` is null
I can't seem to figure out why it is looking to see if department_users.user_id is null, when it should be looking for the user's id.
Any ideas?
Why don't you set up your models like it is suggested in the documentation here:
So your models would look something like this:
User Model
public function departments()
{
return $this->belongsToMany('path\to\your\model\Department');
}
Department Model
public function users()
{
return $this->belongsToMany(path\to\your\model\User);
}
Eloquent will join the two related model names in alphabetical order.So you don't need extra arguments when defining your relationship and Laravel also by default, makes model keys present on the pivot object. And then you can do something like this:
$department = path\to\your\model\Department::find(1);
foreach ($department->users as $user) {
echo $user;
}
For some reason, if I make the relationship the following - it works.
return $this->belongsToMany(Department::class, 'department_users')->orWhere('department_users.user_id', $this->id);
If anyone knows why, please let me know

Laravel 5.2 hasManyThrough relationship issue

I have 3 tables: orders, codes, events
I want to be able to pull all events that an order has, but there's an intermediary table that acts as a pivot table. I've been trying to use hasManyThrough and belongsToMany (along with withPivot) without any luck.
Examples:
public function events()
{
return $this->belongsToMany('events'); // tried this, fails
return $this->hasManyThrough('events', 'codes'); // tried this, fails
return $this->hasManyThrough('events', 'codes', 'event_id', 'id'); // tried this, fails
}
Any pointers would be great!
That's a belongsToMany setup. First, the first parameter is the name of the related class. Second, since your pivot table doesn't follow the Laravel naming conventions, you need to specify the name of the pivot table in your relationship definition:
public function events()
{
// first parameter is the name of the related class
// second parameter is pivot table name
return $this->belongsToMany(Event::class, 'codes');
}
With this setup, you can do:
// get an order
$order = Order::first();
// has all the events related to an order
$events = $order->events;
There are many ways to do this. I will show a one you can get it done.
In Order.php model
public function codes(){
return $this->has('App\Http\Code');
}
In Code.php model
public function orders(){
return $this->belongsTo('App\Http\Order');
}
public function events(){
return $this->hasMany('App\Http\Event');
}
In Event.php model
public function codes(){
return $this->belongsTo('App\Http\Code');
}
Then in you Controller, call them to get required data.
In your case you can do it like below:
$orders = Order::with(['codes' => function($q){
$q->with('events');
})->get();
May be you can get them with nested manner(not sure about this because i didn't tried before posting):
$orders = Order::with('codes.events')->get();
put return $orders; in your controller to see the query.
Enjoy!

Categories