Laravel 5.2 relationship with pivot table - php

my tables:
every part contain many of card.
every card belong to many of part.
now,using laravel eloquent model how can fetch all card for a part without add more column to database

You need to define your relationships like below:
class Part extends Model
{
public function cards()
{
return $this->belongsToMany('App\Cards', 'user_cards');
}
}
Then you can fetch all the cards for a part like below:
$cards = Part::with('cards')->find($part_id);

Part::whereHas('cards', function($query) use ($cardId){
$query->where('id', $cardId);
})->get();
And your model relation should contain like this, for Part.php
public function cards(){
return $this->belongsToMany('App\Card');
}
And for Card.php
public function parts(){
return $this->belongsToMany('App\Part');
}

Related

how to retrieve eloquent model, where a field in a related model equals "xx"?

I have a two models "user" and "user_groups"
there is a relation between the two models like so:
public function usergroup()
{
return $this->hasOne('App\user_group','id','group_id');
}
I can get all users of the group "drivers" using this method.
$driversx = User::where('group_id',3)->get();
but I wanna get these users using the "group_name" field in the "user_groups" model.
how can I achieve that?
Use whereHas() method:
User::whereHas('usergroup', function ($q) {
$q->where('group_name', 'drivers');
})->get();
Generally we used like this way
public function Menus(){
return $this->hasOne('App\Models\MainMenu', 'id', 'menu_id');
}
Controller:
$menu_listing=MenuListing::with('Menus')->get();
But if you want to use with group_name go for belongs to
For your belongsTo relationship :
public function users()
{
return $this->hasMany('App\User','id','group_id');
}
and then :
$users = UserGroup::where('group_name', 'drivers')->first()->users
the name of your model may be not UserGroup :)

Laravel 5.3 Polymorphic many to many - how to get all the related rows regardless of their table sorted by pivot column?

I have a model Page and many models called SomethingSection - they're connected through a polymorphic m-m realtionship and the pivot has an additional column 'position'.
I need to write a relationship (or accessor maybe?) on the Page model that will return a collection of all connected Sections, regardless of their model (read: table).
My models:
class Page extends Model {
public function introSections()
{
return $this->morphedByMany(IntroSection::class, 'pagable');
}
public function anotherSections()
{
return $this->morphedByMany(AnotherSection::class, 'pagable');
}
}
class IntroSection extends Model {
public function pages()
{
return $this->morphToMany(Page::class, 'pagable');
}
}
class AnotherSection extends Model {
public function pages()
{
return $this->morphToMany(Page::class, 'pagable');
}
}
The pivot column looks like this:
pagables
-page_id
-pagable_id
-pagable_type
-position
I'm looking for a way to call a method/attribute on the Page model and get all the connected sections in a single collection, sorted too. What would be a good way to go about this?
I understand that the connected sections do not have the same interface, but in my case that's not a problem at all (in terms of what I will do with the data).
I also understand that relationships perform a separate query (for each relationship), so getting all of them with 1 query is impossible (also different interfaces would be a problem here). And for the same reason the sorting will need to be done on the collection level, not in query.
How could I make this as maintainable as possible and preferably with as small a performance hit as possible.
Thanks in advance.
You can use withPivot() method after your relationship to get the pivot columns with relation like this:
class Page extends Model {
public function introSections()
{
return $this->morphedByMany(\HIT\Models\Sections\IntroSection::class, 'pagable')
->withPivot(['position']);
}
public function anotherSections()
{
return $this->morphedByMany(AnotherSection::class, 'pagable');
}
}
class IntroSection extends Model {
public function pages()
{
return $this->morphToMany(Page::class, 'pagable')
->withPivot(['position']);
}
}
and you can use collection's sortBy to sort the collection by using sortBy() method like this:
$sorted_collection = IntroSection::pages->sortBy('pagables.position');
UPDATE:
You can use collection's combine() method to get all the relationships like this, add this method inside your Page Class:
public function getAllSections()
{
return $this->introSections->combine($this->anotherSections-toArray())
->sortBy('pagables.position'):
}
Hope this helps!

laravel pulling data from database

I'm still trying to wrap my head around whereHas() method. My case is this. I want to pull all users that belong to class
This is relations
Classes model
public function users() {
return $this->belongsToMany('App\User')->withTimestamps();
}
User model
public function classes() {
return $this->belongsToMany('App\Classes')->withTimestamps();
}
controller
$class_us = User::whereHas('classes', function ($query) {
$query->where('class',1);
})->get();
When I do dd($class_us) I get an empty collection.
How can I resolve this problem?
Thanks.
in whereHas clouse the builder instance is coming from the related model so,
$class_us = User::whereHas('classes', function ($query) {
// here the builder belongs to Class model not User model
$query->where('id',1); // id because classes table has column as id
})->get();

How to count most popular (recurring) attribute through Many-To-Many relationship in Laravel 5.3?

I have two Models called Channel and AppUser which are related through a pivot table called app_user_channels.
Users are able to "follow" many channels, and channels can have many users so I defined my relationship as follows:
class AppUser extends Model {
protected $fillable = ['country'];
public function channels () {
return $this->belongsToMany('App\Channel', 'app_user_channels');
}
}
class Channel extends Model {
public function appUser () {
return $this->belongsToMany('App\AppUser', 'app_user_channels');
}
}
class AppUserChannel extends Model {
public function appUser() {
return $this->belongsTo('App\AppUser');
}
public function channel() {
return $this->belongsTo('App\Channel');
}
}
I need to get the top five most recurring countries amongst the Channel's AppUsers. Now, I know that I can get the Channel's followers from the Channel Model by doing something like return $this->appUser->groupBy('country'), but how can I get the country and count for the most common countries among the Channel's followers (AKA AppUsers)?
I'm using Laravel 5.3 and have read through the Eloquent documentation, but am still unable to figure it out. Any hints would be highly appreciated.
Try the following, the code hasn't been tested, but hopwfully, it should work. Don't forget to import DB.
return $this->appUser
->select('country', DB::raw('count(*) as total'))
->groupBy('country')
->orderBy('total', 'desc')
->get()
->take(5)
->pluck('country','total');

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