Laravel: How to get associated table's columns in eager loading - php

I have three Database Tables.
CREATE TABLE `tblproject` (
`ProjectID` int(11) NOT NULL,
`ProjectStatusID` varchar(30) NOT NULL,
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `tblSkills` (
`SkillID` int(11) NOT NULL,
`Skill` varchar(100) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `tblprojectSkills` (
`ProjectSkillID` int(11) NOT NULL,
`ProjectID` int NOT NULL,
`SkillID` int NOT NULL,
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
In the above tables. SkillID is related in tblSkills and tblprojectSkills.
ProjectID is related in Project and projectSkills Table
My project Model is below.
class Project_Model extends Model
{
protected $table = "tblproject";
protected $primaryKey = "ProjectID";
public $timestamps = false;
public function ProjectSkills() {
return $this->hasMany('\App\Models\ProjectSkill_Model', 'ProjectID');
}
}
Database Query in laravel 5.1 is below.
\App\Models\Project\Project_Model
::with('ProjectSkills')
->where('ProjectID', '=', $ProjectID)->first();
Question
I can get the Skill ID, But, How can I get the Skill Name from Skill Table ?

You can select the fields you want with a closure:
\App\Models\Project\Project_Model
::with('ProjectSkills' => function($q)
{
$q->select('SkillID', 'Skill');
})
->where('ProjectID', '=', $ProjectID)->first();
Alternatively, you could add the fields you want directly in the relation of your model:
public function ProjectSkills() {
return $this->hasMany('\App\Models\ProjectSkill_Model', 'ProjectID')
->select('SkillID', 'Skill');
}

Related

Eloquent hasMany doesn't load collection

I'm relatively new to eloquent, and have problems loading data from a hasMany relation in an app that uses eloquent as the database layer. My (simplified) code is as follows:
use Illuminate\Database\Eloquent\Model;
class Answer extends Model{
protected $table = 'answer';
public $timestamps = false;
public $incrementing = false;
protected $fillable = [
"nerdId",
"invitationid",
"eatingno",
"price",
"haspaid",
"attending",
"noeating",
];
public function topping() {
return $this->hasMany(AnswerTopping::class, 'answerid');
}
}
class AnswerTopping extends Model{
protected $table = 'eating';
public $timestamps = false;
protected $fillable = [
'answerid',
'toppingid',
'add'
];
public function answer() {
return $this->belongsTo(Answer::class);
}
}
The SQL Schema is like below
CREATE TABLE `answer` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`nerdid` int(11) NOT NULL,
`invitationid` int(11) NOT NULL,
`eatingno` tinytext,
`price` float NOT NULL,
`haspaid` tinyint(4) NOT NULL,
`attending` tinyint(1) NOT NULL DEFAULT '0',
`noeating` tinyint(4) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2119 DEFAULT CHARSET=utf8;
CREATE TABLE `eating` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`answerId` int(11) NOT NULL,
`toppingid` int(11) NOT NULL,
`add` tinyint(4) NOT NULL DEFAULT '1',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=280 DEFAULT CHARSET=utf8;
I then do the following query:
$answer = Answer::with('topping')->find(32);
return $answer->toJson());
This results in a json like the following
{"id":32,"nerdid":1,"invitationid":54,"eatingno":"51","price":60,"haspaid":1,"attending":2,"noeating":0,"topping":[]}
Raw SQL query shows me that I do have data in the relation, so it should return more in "topping".
UPDATE
Checking sql queries in mysql (Setting it up for logging), I see that it actually do the expected queries on the database:
select * from `answer` where `answer`.`id` = 32 limit 1;
select * from `eating` where `eating`.`answerid` in (32);
Manually executing the SQL are giving me 2 entries in the eating table. But they are not showing up on the upper "Answer" json.
Found the culprit.. db schema for the "eating" table, had answerId (uppercase I), and the relation in hasMany used answerid (lowercase i), which apparently confused eloquent..
Now I get the expected json..

Column not found: 1054 Unknown column 'taggables.tags_model_id' in 'field list' laravel eloquent

I am going to implement a query that retrieves all my blogs with their tags. I am using Laravel Eloquent polymorphic relations but I have an error that is Column not found: 1054 Unknown column 'taggables.tags_model_id' in 'field list'. All my codes in both laravel and my SQL are presented below:
my tables:
create table tags
(
id int auto_increment
primary key,
name varchar(200) null,
created_at timestamp default CURRENT_TIMESTAMP not null,
updated_at timestamp null,
deleted_at timestamp null
);
create table taggables
(
id int auto_increment
primary key,
tag_id int null,
taggable_type varchar(512) null,
taggable_id int null,
created_at timestamp default CURRENT_TIMESTAMP not null,
updated_at timestamp null,
deleted_at timestamp null,
constraint fk23
foreign key (tag_id) references tags (id)
on update cascade on delete cascade
);
create index taggables_tag_id_index
on taggables (tag_id);
create table blog
(
id int auto_increment
primary key,
title varchar(200) null,
passage text null,
author varchar(200) null,
category varchar(200) null,
img_url varchar(200) null,
created_at timestamp default CURRENT_TIMESTAMP not null,
updated_at timestamp null,
deleted_at timestamp null,
user_id int not null,
category_id int null,
constraint fk18
foreign key (user_id) references users (id)
on update cascade on delete cascade,
constraint fk19
foreign key (category_id) references blog (id)
on update cascade on delete cascade
);
create index blog_index
on blog (category_id);
create index blog_users_index
on blog (user_id);
Eloquent Models
class BaseModel extends Model
{
protected $table;
protected $primaryKey;
use SoftDeletes;
}
class BlogModel extends BaseModel
{
protected $table = 'blog';
protected $primaryKey = 'id';
public function tags()
{
return $this->morphToMany(TagsModel::class,"taggable");
}
}
class TagsModel extends BaseModel
{
protected $table = 'tags';
protected $primaryKey = 'id';
public function blog()
{
return $this->morphedByMany(BlogModel::class,"taggable");
}
}
when I called this query the result is an empty array
public function getItemsWithTags(array $attr)
{
return BlogModel::find(1)->tags;
}
thank you very much.
Laravel's polymorphic relations use reflection, by default, to determine the name of your key columns. Because your model is called TagModel, Laravel assumes that the foreign key will be tag_model_id.
// Illuminate\Database\Eloquent\Model
public function getForeignKey()
{
return Str::snake(class_basename($this)).'_'.$this->getKeyName();
}
You can fix this by explicitly passing the correct foreign key to the morphedByMany method:
public function tags()
{
return $this->morphedByMany(TagsModel::class, 'taggable', null, 'tag_id');
}
You can't do an intermediate parenting class like BaseModel. Because it won't work in the Laravel with property $table, try to do this:
class BlogModel extends Model
{
use SoftDeletes;
protected $table = 'blog';
protected $primaryKey = 'id';
public function tags()
{
return $this->morphToMany(TagsModel::class,"taggable");
}
}
class TagsModel extends Model
{
use SoftDeletes;
protected $table = 'tags';
protected $primaryKey = 'id';
public function blog()
{
return $this->morphedByMany(BlogModel::class,"taggable");
}
}
Try this example, you need to reference 'tags' in your eloquent method.
BlogModel::with('tags')->find(1);

Lumen Eloquent save() don't update data at database

I have buyer model, but when i want to change current it's data and save it, it won't save. $buyer->save() return 1 but data at my database won't change.
P.S.
My database has id, created_at and updated_at fields. And $buyer is not empty, it's object with data that i request ('pCode', 'banned', 'hwid')
My code
namespace App\Http\Controllers;
use App\TGOBuyer as Buyer;
class SubController extends Controller
{
public function ban($key){
$buyer = Buyer::where('pCode', $key)->select('pCode', 'banned', 'hwid')->first();
if (!$buyer || $buyer->banned)
return response()->json(['wrong' => 'key']);
$buyer->comment = 'test';
$buyer->banned = 1;
$buyer->save();
}
}
Buyer model
namespace App;
use Illuminate\Database\Eloquent\Model;
class TGOBuyer extends Model {
protected $table = 'buyers';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'banned', 'comment', 'pCode', 'hwid'
];
}
Update
I tryed to return $buyer->id and it gives me null, i don't get it why it happens.
This is my db
CREATE TABLE IF NOT EXISTS `buyers` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`pCode` varchar(20) NOT NULL,
`banned` tinyint(1) NOT NULL DEFAULT '0',
`comment` text NOT NULL,
`created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `pCode` (`pCode`),
UNIQUE KEY `id_2` (`id`),
KEY `id` (`id`),
KEY `hwid` (`hwid`),
KEY `pID` (`pID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=22468 ;
I get it. I just need to include id to my select query. Now all work's fine.
$buyer = Buyer::where('pCode', $key)->select('id', 'pCode', 'banned', 'hwid')->first();

Get Filtered and associated records in Laravel 5.1

I have three Database Tables.
CREATE TABLE `tblprojecttype` (
`ProjectTypeID` int(11) NOT NULL,
`ProjectType` varchar(30) NOT NULL,
`Description` varchar(500) NOT NULL,
`IsActive` tinyint(1) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `tblprojecttypecurrencyprice` (
`ProjectTypeCurrencyID` int(11) NOT NULL,
`CurrencyID` int(11) NOT NULL,
`ProjectTypeID` int(11) NOT NULL,
`Price` decimal(10,0) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `tblcurrency` (
`CurrencyID` int(11) NOT NULL,
`Currency` varchar(100) NOT NULL,
`IsActive` tinyint(1) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Models
class Currency_Model extends Model
{
protected $table = "tblcurrency";
protected $primaryKey = "CurrencyID";
public $timestamps = false;
}
class ProjectType_Model extends Model
{
protected $table = "tblprojecttype";
protected $primaryKey = "ProjectTypeID";
public $timestamps = false;
public function projecttypecurrencyprice()
{
return $this->hasOne('\App\Models\ProjectTypeCurrencyPrice_Model',
"ProjectTypeID");
}
}
class ProjectTypeCurrencyPrice_Model extends Model
{
protected $table = "tblprojecttypecurrencyprice";
protected $primaryKey = "ProjectTypeCurrencyID";
public $timestamps = false;
public function Currency()
{
return $this->belongsTo('\App\Models\Currency_Model', "CurrencyID");
}
}
There is CurrencyID relationship and ProjectTypeID relationship
What I am trying ?
In my Laravel 5.1 code, I am trying to achive below sql statement so that I can get projecttypecurrencyprice records for each ProjectType record. Finally it should also show records from currency Table for each projecttypecurrencyprice record
$ProjectTypes = \App\Models\project\ProjectType\ProjectType_Model
::with("projecttypecurrencyprice")
->with("projecttypecurrencyprice.Currency")
->get();
What's the Problem ?
I am getting all Currency records for each projecttypecurrencyprice record. I just want those where currency ID = 1
You need to apply additional criteria when fetching related ** projecttypecurrencyprice** objects. You can do that with whereHas() method. The following code should do the trick:
$ProjectTypes = \App\Models\project\ProjectType\ProjectType_Model
::with("projecttypecurrencyprice")
->with(["projecttypecurrencyprice.Currency" => function($query) {
$query->where('CurrencyID', 1);
}])
->get();
If I am not missing something, shouldn't a simple where() clause in your eloquent query builder do the trick?
Like this:
$ProjectTypes = \App\Models\project\ProjectType\ProjectType_Model
::with("projecttypecurrencyprice")
->with("projecttypecurrencyprice.Currency")
->where('id', 1)
->get();
(not tested of course, please don't slap me)

Get nested associated records in Laravel 5.1

I have three Database Tables.
CREATE TABLE `tblprojecttype` (
`ProjectTypeID` int(11) NOT NULL,
`ProjectType` varchar(30) NOT NULL,
`Description` varchar(500) NOT NULL,
`IsActive` tinyint(1) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `tblprojecttypecurrencyprice` (
`ProjectTypeCurrencyID` int(11) NOT NULL,
`CurrencyID` int(11) NOT NULL,
`ProjectTypeID` int(11) NOT NULL,
`Price` decimal(10,0) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `tblcurrency` (
`CurrencyID` int(11) NOT NULL,
`Currency` varchar(100) NOT NULL,
`IsActive` tinyint(1) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Models
class Currency_Model extends Model
{
protected $table = "tblcurrency";
protected $primaryKey = "CurrencyID";
public $timestamps = false;
}
class ProjectType_Model extends Model
{
protected $table = "tblprojecttype";
protected $primaryKey = "ProjectTypeID";
public $timestamps = false;
public function projecttypecurrencyprice()
{
return $this->hasOne('\App\Models\ProjectTypeCurrencyPrice_Model',
"ProjectTypeID");
}
}
class ProjectTypeCurrencyPrice_Model extends Model
{
protected $table = "tblprojecttypecurrencyprice";
protected $primaryKey = "ProjectTypeCurrencyID";
public $timestamps = false;
public function Currency()
{
return $this->hasOne('\App\Models\Currency_Model', "CurrencyID");
}
}
There is CurrencyID relationship and ProjectTypeID relationship
What I am trying ?
In my Laravel 5.1 code, I am trying to achive below sql statement so that I can get projecttypecurrencyprice records for each ProjectType record. Finally it should also show records from currency Table for each projecttypecurrencyprice record
$ProjectTypes = \App\Models\project\ProjectType\ProjectType_Model
::with("projecttypecurrencyprice")
->with("projecttypecurrencyprice.Currency")
->get();
What's the Problem ?
I am not able to get Currency records for each projecttypecurrencyprice record.
For ProjectTypeCurrencyPrice_Model you should change Currency relationship this way:
public function Currency()
{
return $this->belongsTo('\App\Models\Currency_Model', "CurrencyID");
}
because you have CurrencyId column in tblprojecttypecurrencyprice and you don't have any connection to ProjectTypeCurrencyPrice_Model in tblcurrency.
And to get data instead of:
$ProjectTypes = \App\Models\project\ProjectType\ProjectType_Model
::with("projecttypecurrencyprice")
->with("projecttypecurrencyprice.Currency")
->get();
you can omit 1st with:
$ProjectTypes = \App\Models\project\ProjectType\ProjectType_Model
::with("projecttypecurrencyprice.Currency")
->get();
By the way if you start this project, you should consider changes in your database structure and read about PSR in PHP - you should rather not use ProjectTypeCurrencyPrice_Model as your model name if you really don't have to, same for ProjectTypeID columns in MySQL

Categories