Laravel Eloquent nesting - php

I'm trying to return nested JSON response, need to connect multiple tables, but for now, I'm just trying with 3, the levels can go deeper. My models are following:
Update #1:
class Sport extends Eloquent {
protected $table = 'sportovi';
protected $fillable = ['id', 'sport_eng'];
public $timestamps = false;
public function liga(){
return $this->hasMany('League', 'sport_id');
}
}
class League extends Eloquent {
protected $table = 'lige';
protected $fillable = ['league_id', 'liga', 'sport_id'];
public $timestamps = true;
public function mec(){
return $this->hasMany('Match', 'match_id');
}
}
class Match extends Eloquent {
protected $table = 'mecevi';
protected $fillable = ['match_id', 'home', 'away', 'kotime', 'day', 'kolo', 'sport_id', 'league_id', 'date', 'long_id'];
public $timestamps = false;
public function liga(){
return $this->belongsTo('Match', 'league_id');
}
}
If I do:
$sportovi = Sport::with('liga')->get();
return $sportovi;
everything is normal, children of "lige" are nested where they should be, as shown on the link here, but, if I try to add the Match, like this:
$mecevi = Sport::with('liga.mec')->get();
I get a "mec" node, which is an empty array, as shown here, instead going one level deeper, like in the previous example.
I've also tried making multiple with() conditions which throws an error
Call to undefined method Illuminate\Database\Query\Builder::mec()
Update: Still the same, mec:[], empty array.
I'm using Laravel 4.2.

From my understanding, you want to get all the matches of leagues
The problem might be in the second parameter in hasMany function
public function mec(){
return $this->hasMany('Match', 'league_id');
}
The second parameter need to be foreign_key
public function mec(){
return $this->hasMany('Match', 'match_id', 'league_id');
}
source: http://laravel.com/docs/4.2/eloquent#one-to-many

Figured it out, my table relations were off, after giving all the conditions, like
return $this->hasMany('Comment', 'foreign_key', 'local_key'); everything started working as it should. Thanks everybody.

Related

how can we append two attributes by one function?

I want to add two appends variables in laravel model. by using one getVariableNameAttribute() function.
Is this possible?
MY motto is, I want to reduce SQL query load 2 times to into 1 time
class Like extends Model{
use HasFactory;
protected $fillable = ['like_id', 'like_type', 'liked', 'user_id'];
protected $appends = ['likes','dislikes'];
protected function getLikesAttribute($type)
{
return \DB::table("likes")
->select(\DB::raw("SUM(liked) as likes"))
->where('like_type',self::class)->where('like_id',$this->id)->first()->likes;
}
public function getDislikesAttribute()
{
return \DB::table("likes")
->select(\DB::raw("SUM(!liked) as dislikes"))
->where('like_type',self::class)->where('like_id',$this->id)->first()->dislikes;
}}
Combining both methods to return an object is possible.
protected function getVariableNameAttribute()
{
return \DB::table("likes")
->selectRaw("SUM(liked) as likes")
->selectRaw("SUM(!liked) as dislikes")
->where('like_type', self::class)
->where('like_id', $this->id)
->first();
}
$...->variable_name->likes
$...->variable_name->dislikes

Getting id from another table in a relationship laravel

I want to get the data from pdf_Files table where it will only show the name of files based on it user_id. I don't really know how to explain it but maybe if you see my codes, you would understand. I have already finish making the relationship between this 2 tables already
I want it to be something like:
DB::table('pdf_files')->where(table:personal_infos->id = pdf_files->user_id)->get(); --> I want it to be something like that but I do not know how to get it
Here is my code:
Controller:
public function downfunc(Request $request){
$downloads=DB::table('pdf_files')->get();
return view('download.viewfile',compact('downloads'));
}
pdfFile model:
protected $fillable = array('file_name','file_size','user_id');
public function personal_infos() {
return $this->belongsTo('App\personal_info', 'user_id', 'id');
}
personal_info model:
class personal_info extends Eloquent
{
protected $fillable = array('Email', 'Name');
protected $table = 'personal_infos';
protected $primaryKey = 'id';
public function pdfFiles() {
return $this->hasMany('App\pdfFile','user_id');
}
}
Are you going to search multiple user ids at once or are you getting the id from the request?
If you are getting the info from the request, you would want to do something like this:
use App\pdfFile; //Put this above the class
pdfFile::where('user_id', $request->user_id)->get(); //If you are checking to see if something equals something else in eloquent, you do not have to use equals

Obtaining a list of non-linked models, in many_to_many relations, using Laravel Eloquent

I have a User-Roles model, using Laravel 4 where a user can have many roles, using Eloquent. I can access all roles linked to a user easily using this code :
class User extends Model {
protected $table = 'user';
protected $fillable = array('name');
public function rolesLinked() {
return $this->hasMany('App\UserRoleLink', 'user_id');
}
}
I've been trying to obtain the roles that are not linked to a user, to display on the specific user's page in a select box. Using this function, included in the User class.
public function rolesNotLinked() {
$user = this
$roles = Roles::whereDoesntHave('App\UserRoleLink',function($query) use ($user){
$query->where('user_id',$user->id);
});
}
The problem is, calling this function gives me the following error.
Call to undefined method Illuminate\Database\Query\Builder::App\UserRoleLink()
I've tried using has with < 1 to see if the function was problematic, but after reading this and the online source code, the function call pretty much does what I've tried.
Is something wrong in my function call, or have I messed up configurations somewhere?
For reference, here are my other Model classes:
class UserRoleLink extends Model{
protected $table = 'user_role_link';
protected $fillable = array('role_id','user_id);
public function role() {
return $this->hasOne('App\Role', 'role_id');
}
}
class Role extends Model{
protected $table = 'role';
protected $fillable = array('name');
}
EDIT: I've found out that I messed up by fillables when I copy-pasted. It didn't fix the issue, but I guess that's one step closer.
To use whereDoesntHave method, you must add the relation in your Role Model.
class Role extends Model{
protected $table = 'role';
protected $fillable = array('name');
public function UserRoles() {
return $this->hasMany('App\UserRoleLink', 'id');
}
}
Also, the whereDoesntHave method first parameter is not thte model but the function of the relation:
public function rolesNotLinked() {
$user = this
$roles = Roles::whereDoesntHave('UserRoles',function($query) use ($user){
$query->where('user_id',$user->id);
});
}

Ordering of nested relation by attribute with laravel

Hi there i'm trying to sort a collection by attribute of the relation.
This is my model
class Song extends \Eloquent {
protected $fillable = ['title', 'year'];
public function artist(){
return $this->hasOne('Artist','id', 'artist_id');
}
}
class SongDance extends \Eloquent {
protected $table = 'song_dances';
protected $fillable = ['rating'];
public function dance(){
return $this->belongsTo('Dance', 'dance_id');
}
public function song(){
return $this->belongsTo('Song', 'song_id');
}
}
class Dance extends \Eloquent {
protected $fillable = ['name'];
public function song_dances(){
return $this->hasMany('SongDance','dance_id','id');
}
public function songs(){
return $this->belongsToMany('Song', 'song_dances', 'dance_id', 'song_id');
}
}
this is how far i'm by now:
$dance = Dance::find(1);
$songs = $dance->songs()
->with('artist')->whereHas('artist', function ($query) {
$query->where('urlName','LIKE','%robbie%');})
->where('song_dances.rating', '=', $rating)
->orderBy('songs.title','asc')
->where('songs.year', '=', 2012)
->get();
Yeah i just could add a ->sortBy('artist.name'); to the query, but he result-collection can be quite big (about 6000 items) therefore i would prefer a databased sorting.
is there a possibility to do this?
Since Eloquent's relations are all queried separately (not with JOINs), there's no way to achieve what you want in the database layer. The only thing you can do is sort the collection in your app code, which you've already dismissed.
If you feel you must sort it in the database then you should write your own join queries instead of relying on Eloquent's relations.

relationship array null when eager loading in laravel

I am having issues getting the relationship array back when eager loading in laravel 4. for example:
controller:
foreach (Apps::with('extra')->get() as $app)
{
print_r($app->toArray());//returns array but my relationship array at the bottom says null
echo $app->extra; //this will show my relationship details
}
model:
class Apps extends Eloquent
{
protected $connection = 'mysql_2';
protected $table = 'apps';
public $timestamps = false;
protected $primaryKey = 'name';
public function host()
{
return $this->belongsTo('Hosts','name');
}
public function extra()
{
$this->primaryKey='app_ip';
return $this->hasone('Extra','ip');
}
//other functions below.......
}
class Extra extends Eloquent
{
protected $connection = 'mysql_3';
protected $table = 'extra';
public $timestamps = false;
protected $primaryKey = 'ip';
public function app(){
return $this->belongsTo('Apps', 'app_ip');
}
mysql:
My mysql tables were not created through laravel they were previously existent. the app_ip column in the Apps table relates to the ip column in the extra table. it is a 1 to 1 relationship and I have specified the primary key in the relationship function. I am getting relationships back so I know that it is working.
I am able to get relationship data back when I call the function directly, but it does not show the relationship data when I try and print the full array. The main goal is to be able to return both the relationship columns and the app columns in one response.
You need to do this:
$apps = Apps::all();
$apps->load('extra');
foreach ($apps as $app)
{
print_r($app->toArray()); // prints your relationship data as well
}
What you have should work and iterating through the collection or using ->load() to eager load shouldn't make a difference. Are you using the visible restriction on your models? If so you will need to include the relationships.
class Apps extends Eloquent {
protected $visible = array(
'id',
'name',
'created_at',
'extra', // Make the relationship 'visible'
);
public function extra()
{
return $this->hasMany('Extra');
}
}

Categories