Laravel 5.4 hasManyThrough - php

can someone please explain how the hasManyThrough relates to the sql statement I am trying to acheive?
--offers table
id, network_id, mobile_id
--networks table
id, name
--mobiles table
id, name
I am trying to get Mobile::with('networks')
I would write this as
SELECT DISTINCT networks.name from networks, offers where offers.network_id = networks.id and offers.mobile_id in (1,2,3,4)
In relation to the above sql statement where does each arg live in the hasManyThrough method? i.e
hasManyThrough(Network::class,Offer::class,'network_id','mobile_id')

I think this is many to many relationship
--offers table
id, network_id, mobile_id
--networks table
id, name
--mobiles table
id, name
Network Model
namespace App;
use Illuminate\Database\Eloquent\Model;
class Network extends Model
{
public function mobile(){
return $this->belongsToMany('App\Mobile', 'offers')->withPivot('mobile_id');
}
}
Mobile Model
namespace App;
use Illuminate\Database\Eloquent\Model;
class Mobile extends Model
{
public function network(){
return $this->belongsToMany('App\Network', 'offers')->withPivot('network_id');
}
}
You may use pivot to fetch relationship
For more info visit Laravel Docs
However for such conditions you must use a pivot table, i.e mobile_network instead of offers.

Related

How to get a particular column value by using Eloquent ORM?

I have two migration tables and two models
1)User.
2)Subscription.
in subscriptions Model i write one method called user() which has hasMany relationship and in Users model it will contain subscriptions() method which have belongs() relationship.
in user table id acts as an primary key and in subscription table sub_id acts as a foriegn key,for example if the user subscribed to any subscription the user id will store in the sub_id in the subscription table upto this it's working fine.
$is_subscription=Subscription::where('sub_id',$user->id)->value('sub_id');
from the above code i am able to get the value but now what i want is is there any better way to write the query based on models ,please help me to write this one..
According to your descriptions, I believe this is what you have:
class User extends Model
{
public function subscriptions()
{
return $this->hasMany(Subscription::class);
}
}
class Subscription extends Model
{
public function user()
{
return $this->belongsTo(User::class);
}
}
So you want to check whether an user has any subscriptions. You can do one of the followings:
$user->subscriptions()->exists();
// Or
$user->subscriptions->isNotEmpty();
You can use pluck() method:
$is_subscription=Subscription::where('sub_id',$user->id)->pluck('sub_id');
You can find details on the methods that are available for collection using the Laravel Documentation

Laravel How to correctly select fields from multiple database tables?

I have a giveaway table, it has a winner_id column in which the user ID on the site is entered. It is necessary that the ID from the winner_id column looks in the users table and displays the user login that has found on the site. How can this be done correctly?
You are looking for a One to Many (inversed) relationship from the "Giveway" model side. First, you need to create a "Giveaway" model which represents your "giveaway" database table, in case you don't have that already. You should have the "user" model, as this exists by default. Your "giveaway" model could look like this:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Giveaway extends Model
{
/**
* Get the user that is related to the giveaway.
*/
public function user()
{
return $this->belongsTo('App\User', 'id', 'winner_id');
}
}
Now, get the giveaway instance and you can do something like this:
// this will print the user instance which is associated to the giveaway row with id #1
dd(Giveaway::find(1)->user);
For further details, please check the Laravel Docs: https://laravel.com/docs/6.x/eloquent-relationships#one-to-many-inverse

Better way to execute join query in Laravel

Currently I have two tables; Users and Employees
All users are employees but not all employees are users,
I have a models Users and Employee, the personal details of a user are pulled his respective employee record.
Now I wanted to display all users and I can do it using User::all();
but also I wanted to have their personal details too.
currently I'm doing a DB:: call to join table in a function on my Users Model.
is there a better approach to this?
You can do it the Laravel way - eager load the relationship
$users = User::with('employee')->get();
This assumes that you have your relationships defined, at least on User side.
use Illuminate\Foundation\Auth\User as Authenticatable;
use App\Employee;
class User extends Authenticatable
{
// ...
public function employee()
{
return $this->hasOne(Employee::class, 'employee_no');
}
}
FYI the Laravel way doesn't necessarily mean the fastest or the best way. It's usually syntactically more expensive/terse and convenient though.
Eager loading a relationship requires an additional query. In your case two queries will be executed under the hood and then employee property will be materialized for each User model in a collection.
So your way with a join and one roundtrip to the database might be more performant at the end of the day.
You should establish a relation. In this case your users can relate to your employees as such
public function employee()
{
return $this->hasOne(Employee::class);
}
With Eloquent, you can just define methods in your User model to access the relation and be done with it.
public function role
{
return $this->employee->role;
}
However, when fetching users, you want to ensure you "eager load" your employee relation so that you're not individually fetching employees when using these methods. When you fetch your users:
User::with('employee')->all()
If you will always require the employee record you can eager load by default:
class User extends Authenticatable
{
protected $with = ['employee'];
}
Sounds like you need to use an Eloquent One to One Relationship
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
public function employee()
{
return $this->hasOne('App\Employee');
}
}

Laravel-Many-to-one Polymorphic relationship

I am using laravel 5.1. The scenario is as follows(this is an example. The real scenario is similar to this example)
I have 3 models
College
Student
Teacher
A college can have many students but a student can belong to only 1 college.
A college can have many teachers but a teacher can belong to only 1 college.
I want to establish relationships between these tables in laravel.
One of the methods for this is to place a college_id foreign key on the Students and Teachers table. But in my case, this foreign key will be null a lot of times. So rather than have separate columns in 3-4 tables with mostly null values, I wanted to explore the option of having a polymorphic relationship for College table.
This is what I tried:
The example given in the laravel docs(link below) depict a one-to-many relationship whereas my scenario is more of a many to one relationship.
http://laravel.com/docs/5.1/eloquent-relationships#polymorphic-relations
As given in the example, having collegeable_id and collegeable_type columns on the College table would not have fulfilled my requirement as a college can contain many students/teachers so I created a pivot table:
Schema::create('collegeables', function (Blueprint $table) {
$table->integer('college_id')->unsigned();
$table->integer('collegeable_id')->unsigned();
$table->string('collegeable_type');
});
And I have the following models
College Model:
namespace App;
use Illuminate\Database\Eloquent\Model;
class College extends Model
{
public function students()
{
return $this->morphedByMany('App\Student', 'collegeable');
}
}
Student Model:
namespace App;
use Illuminate\Database\Eloquent\Model;
class Student extends Model
{
public function college()
{
return $this->morphOne('App\Colleges', 'collegeable');
}
}
With this arrangement, I am able to store students using College model instance like this
$college = \App\College::find(1);
$student = new \App\Student;
$student->name = 'John Doe';
$college->students()->save($student);
But when I try to retrieve a College model instance using a student model instance as specified below, it gives me an error:-
public function index()
{
return \App\Student::find(1)->college;
}
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'colleges.collegeable_id'
This is kind of expected as morphOne works with columns in a table I suppose.
If I change the morphOne function in Student Model to morphToMany, the code starts working and I am able to retrieve values as well. But that make this relationship a many to many which again is not what I want.
So my question is this:-
Is their a morphSomething function I can use in the student model to be able to retrieve values for the student's college while maintaining the relationship as a one-to-many?
Any help would be really appreciated. Thanks.
There's no reason to use Polymorphic relationships here. Instead, just add a foreign key to your colleges table on both your students and teachers tables. Like this:
colleges
id
name
teachers
id
name
college_id
students
id
name
college_id
Then your models can use the belongsTo() and hasMany() relations, like so:
class College extends Model {
public function students() {
return $this->hasMany(App\Student::class);
}
public function teachers() {
return $this->hasMany(App\Teacher::class);
}
}
class Teacher extends Model {
public function colleges() {
return $this->belongsTo(App\College::class);
}
}
class Student extends Model {
public function colleges() {
return $this->belongsTo(App\College::class);
}
}
Polymorphic one-to-many relations are for the opposite of this relationship where you have a model that can only be related to a single record, but that record can be many different models.
Edit: To further explain why a polymorphic relationship isn't needed here, let's take a look at where it would be needed. Say you have a simple CRM style website. There are Customers and Projects and you want to have Comments on both. In this case, you would make Comments a polymorphic relationship because Comments belong to a single Customer or a single Project, but not both.
Your relationship is the exact opposite. In your case, Students and Teachers belong to a college. If you were to follow the previous example's pattern, a college would have belonged to a single student or teacher.
I had a similar need and managed to improvise in another way, taking advantage of morph's table structure.
You will need a Collegeable class to be Pivot (https://laravel.com/docs/9.x/eloquent-relationships#defining-custom-intermediate-table-models)
And then the magic:
public function college(){
return $this->hasOneThrough(Colleges::class,
Collegeable::class,
'collegeable_id',
'id',
'id',
'college_id',
);
}
And on the Collegeable Pivot class:
namespace App\Models;
use Illuminate\Database\Eloquent\Relations\Pivot;
class Collegeable extends Pivot
{
protected $table = 'collegeables';
}

Laravel ORM User can favorite Multiple Models

I am trying to find out the best way to define the following relation using Laravel's Eloquent Laravel.
I have a User table and 3 Objects ( Player, Team, League) that the user can add as favorites.
I know I can create three pivot tables with the User Model and each one of the objects but then I will need to run a Union query to list all favorites from user regardless of type.
User
id
Favorite
id
user_id
favorited_id ( player_id or team_id or league id)
favorite_type ( player , team or league)
Player
id
Team
id
League
id
Here is my model.
https://www.dropbox.com/s/6au8giufaejcghc/Screen%20Shot%202014-04-07%20at%209.06.51%20AM.png
i'd do it the same with a Favourite table. laravel covers this with its polymorphic relations.
your tables could look like
class Favourite extends Eloquent {
public function favourable()
{
return $this->morphTo();
}
}
class Team extends Eloquent {
public function favourite()
{
return $this->morphMany('Favourite', 'favourable');
}
}
...
your Favourite table would look like
Favourite
favourable_id: int
favourable_type: string
you'd call it like a normal property on the model like $player->favourable().
You can either use polymorphism as suggested by user3158900, or my preference would be to use Laravel's Query Builder to perform the Union query.
http://laravel.com/docs/queries#unions
$first = DB::table('users')->whereNull('first_name');
$users = DB::table('users')->whereNull('last_name')->union($first)->get();

Categories