Lumen with Eloquent arbitrary changes all fields - php

Here's the code:
$row = UserFields::where(['user_id' => $user['user_id'], 'field_id' => 'myfield'])->first();
if($row)
{
$row->field_value = "new value";
$row->save();
}
Suddenly all rows field_value in that table changes to the new value and only for that user!
That's really confusing, I don't know if it's a bug in Eloquent.

Laravel eloquent, like many other ORMs is not good at handling composite primary keys. If you see the code it have
protected function setKeysForSaveQuery(Builder $query)
{
$query->where($this->getKeyName(), '=', $this->getKeyForSaveQuery());
return $query;
}
public function getKeyName()
{
return $this->primaryKey;
}
since you seems to have a composite primary key it will only use the first field in it so all fields for the user will be updated.
The recommended option is to add an id field for primary key also on mapping tables or if you like me don't want to add redundant fields, you can use
UserFields::where(['user_id' => $user['user_id'], 'field_id' => 'myfield'])->update(['field_value', "new value"]);
or
DB::table('user_fields')->where(['user_id' => $user['user_id'], 'field_id' => 'myfield'])->update(['field_value', "new value"]);
Edit:
For anyone interested I did find a solution I have used before. In the model you can overload the setKeysForSaveQuery function like this
protected function setKeysForSaveQuery(Builder $query) {
$query->where('firstPKcolumn', $this->getAttribute('firstPKcolumn'))->where('otherPKcolumn', $this->getAttribute('otherPKcolumn'));
return $query;
}
Then you can use save as normal on the model

For anyone having the same issue I managed to solve this by using basic lumen db query method:
app('db')->update("UPDATE `xf_user_field_value` SET `field_value` = ? WHERE (user_id = ? AND field_id = ?);", [ $newValue, $user_id, $column ]);
I have completely disabled Eloquent as it was overkill for me and not flexible enough for my needs.

Related

select column from relationship besides main table [duplicate]

I have two tables, User and Post. One User can have many posts and one post belongs to only one user.
In my User model I have a hasMany relation...
public function post(){
return $this->hasmany('post');
}
And in my post model I have a belongsTo relation...
public function user(){
return $this->belongsTo('user');
}
Now I want to join these two tables using Eloquent with() but want specific columns from the second table. I know I can use the Query Builder but I don't want to.
When in the Post model I write...
public function getAllPosts() {
return Post::with('user')->get();
}
It runs the following queries...
select * from `posts`
select * from `users` where `users`.`id` in (<1>, <2>)
But what I want is...
select * from `posts`
select id,username from `users` where `users`.`id` in (<1>, <2>)
When I use...
Post::with('user')->get(array('columns'....));
It only returns the column from the first table. I want specific columns using with() from the second table. How can I do that?
Well I found the solution. It can be done one by passing a closure function in with() as second index of array like
Post::query()
->with(['user' => function ($query) {
$query->select('id', 'username');
}])
->get()
It will only select id and username from other table. I hope this will help others.
Remember that the primary key (id in this case) needs to be the first param in the
$query->select() to actually retrieve the necessary results.*
You can do it like this since Laravel 5.5:
Post::with('user:id,username')->get();
Care for the id field and foreign keys as stated in the docs:
When using this feature, you should always include the id column and
any relevant foreign key columns in the list of columns you wish to
retrieve.
For example, if the user belongs to a team and has a team_id as a foreign key column, then $post->user->team is empty if you don't specifiy team_id
Post::with('user:id,username,team_id')->get();
Also, if the user belongs to the post (i.e. there is a column post_id in the users table), then you need to specify it like this:
Post::with('user:id,username,post_id')->get();
Otherwise $post->user will be empty.
For loading models with specific column, though not eager loading, you could:
In your Post model
public function user()
{
return $this->belongsTo('User')->select(['id', 'username']);
}
Original credit goes to Laravel Eager Loading - Load only specific columns
When going the other way (hasMany):
User::with(['post'=>function($query){
$query->select('id','user_id');
}])->get();
Don't forget to include the foreign key (assuming it is user_id in this example) to resolve the relationship, otherwise you'll get zero results for your relation.
In Laravel 5.7 you can call specific field like this
$users = App\Book::with('author:id,name')->get();
It is important to add foreign_key field in the selection.
If you want to get specific columns using with() in laravel eloquent then you can use code as below which is originally answered by #Adam in his answer here in response of this same question, the answer's main code is as below :
Post::with('user:id,username')->get();
So i have used it in my code but it was giving me error of 1052: Column 'id' in field list is ambiguous, so if you guys are also facing same problem
Then for solving it you have to specify table name before the id column in with() method as below code:
Post::with('user:user.id,username')->get();
I came across this issue but with a second layer of related objects. #Awais Qarni's answer holds up with the inclusion of the appropriate foreign key in the nested select statement. Just as an id is required in the first nested select statement to reference the related model, the foreign key is required to reference the second degree of related models; in this example the Company model.
Post::with(['user' => function ($query) {
$query->select('id','company_id', 'username');
}, 'user.company' => function ($query) {
$query->select('id', 'name');
}])->get();
Additionally, if you want to select specific columns from the Post model you would need to include the user_id column in the select statement in order to reference it.
Post::with(['user' => function ($query) {
$query->select('id', 'username');
}])
->select('title', 'content', 'user_id')
->get();
In your Post model:
public function userWithName()
{
return $this->belongsTo('User')->select(array('id', 'first_name', 'last_name'));
}
Now you can use $post->userWithName
There is another alternative you can eager load specific columns
public function show(Post $post)
{
$posts = $post->has('user')->with('user:id,name,email,picture')->findOrFail($post->id);
return view('your_blade_file_path',compact('posts);
}
In your Post model you should have user relationship also
public function user()
{
return $this->belongsTo( User::class, 'user_id')->withDefault();
}
Note: It is mentioned in Laravel docs.
https://laravel.com/docs/8.x/eloquent-relationships#eager-loading-specific-columns
Note that if you only need one column from the table then using 'lists' is quite nice. In my case i am retrieving a user's favourite articles but i only want the article id's:
$favourites = $user->favourites->lists('id');
Returns an array of ids, eg:
Array
(
[0] => 3
[1] => 7
[2] => 8
)
If you use PHP 7.4 or later you can also do it using arrow function so it looks cleaner:
Post::with(['user' => fn ($query) => $query->select('id','username')])->get();
I faced the same issue while using belongsToMany relationship with my user model (Laravel 8.x.x).
After a long search and trial and test method. I found out this answer
You have to make sure you are selecting the id's and any foreign keys that would be needed for the relationship from either side of that relationship. This allows Eloquent to match up parents to their children.
Original credit goes to https://stackoverflow.com/a/64233242/1551102
So I included
Groups::select('groupid')
...
And it worked like a charm. Although now I want to know how to hide the groupid field after fetching.
I know I can simply loop through the array and remove it. But is there any other method? potentially a simpler and better one.
You can also specify columns on related model at the time of accessing it.
Post::first()->user()->get(['columns....']);
You can try this code . It is tested in laravel 6 version.
Controller code
public function getSection(Request $request)
{
Section::with(['sectionType' => function($q) {
$q->select('id', 'name');
}])->where('position',1)->orderBy('serial_no', 'asc')->get(['id','name','','description']);
return response()->json($getSection);
}
Model code
public function sectionType(){
return $this->belongsTo(Section_Type::class, 'type_id');
}
Be careful that if you don't add the key column(s) it won't return anything. If you want to show only the username without the id you could instead define the $visible/$hidden properties within the Model, like so:
app/Models/User.php
protected $visible = ['username'];
Then it will retrieve only username column with:
Post::with('user')->get();
Hiding the key columns:
Alternatively you could hide the key column(s) and then retrieve only the columns you wish.
app/Models/User.php
protected $hidden = ['id'];
Specify which columns you want including the key or else it won't return anything, but this will actually only return the username, because id is $hidden.
Post::with('user:id,username')->get();
Now you can use the pluckmethod on a Collection instance:
This will return only the uuid attribute of the Post model
App\Models\User::find(2)->posts->pluck('uuid')
=> Illuminate\Support\Collection {#983
all: [
"1",
"2",
"3",
],
}
Try with conditions.
$id = 1;
Post::with(array('user'=>function($query) use ($id){
$query->where('id','=',$id);
$query->select('id','username');
}))->get();
So, similar to other solutions here is mine:
// For example you have this relation defined with "user()" method
public function user()
{
return $this->belongsTo('User');
}
// Just make another one defined with "user_frontend()" method
public function user_frontend()
{
return $this->belongsTo('User')->select(array('id', 'username'));
}
// Then use it later like this
$thing = new Thing();
$thing->with('user_frontend');
// This way, you get only id and username,
// and if you want all fields you can do this
$thing = new Thing();
$thing->with('user');
EmployeeGatePassStatus::with('user:id,name')->get();

Laravel One-to-many relationship

Trying to get a one-to-many relationship working in Laravel 5.4. I've read through the documentation and other resources online and in each instance can't get it working, and various ways I've tried results in different errors.
I have the following three tables:
accounts
contacts
account_contact (pivot table) has the fields: account_id (int/Foreign key), contact_id (int/Foreign key), primary (int), billing (int)
I'm trying to make it so the account can (but not necessarily) have one or more contacts.
My Models are as follows:
accounts
public function contacts()
{
return $this->hasMany(Contact::class);
}
contact
public function account()
{
return $this->belongsTo(Account::class)->withPivot('primary', 'billing');
}
Then say in a controller I attempt:
$account = Account::find($id);
if($account->isEmpty())
return response()->json(['Account not found.'], 404);
$contact = $account->contacts()->exists();
I get the following error:
(1/1) BadMethodCallException
Method contacts does not exist.
Obviously what I'm trying to do is make it so when a contact is made, it can be attached to an Account through the Pivot table.
And when getting the Account, I can then, through the Pivot table get the extra Pivot table fields, and the contact(s) that belong to that Account.
Just to clarify a little further, I am trying to use eloquent, using pivots to do the following query, without having to write it out in every instance.
$contacts = DB::table('account_contact')
->select('contact_id', 'primary', 'billing')
->where('account_id', $id)
->get();
$accountContacts = [];
foreach($contacts as $c){
$accountContact = Contact::find($c->id);
$accountContacts[] = array(
"id" => $accountContact->id,
"sal" => $sal = $accountContact->salutation == null? '' : $accountContact->salutation,
"firstName" => $accountContact->first_name,
"lastName" => $accountContact->last_name,
);
}
I was hoping to just be able to do something like
$accounts->pivot->contacts
and get a name like so:
$accounts->pivot->contacts->first_name
Your relationship is many to many so you need to do this:
accounts
public function contacts()
{
return $this->belongsToMany(Contact::class)->withPivot('primary', 'billing');
}
contact
public function account()
{
return $this->belongsToMany(Account::class)->withPivot('primary', 'billing');
}
Then you should do this via eloquent all the way to avoid the N+1 issue
$account = Account::with("contacts")->where("id", $id)->get();
foreach ($account->contacts as $contact) {
$accountContacts[] = array(
"id" => $accountContact->id,
"sal" => $sal = $accountContact->salutation == null? '' :
$accountContact->salutation,
"firstName" => $accountContact->first_name,
"lastName" => $accountContact->last_name,
);
}
In your account model, make one relationship like this:
public function account_contact()
{
return $this->belongsToMany('App\Account', 'account_contact', 'account_id', 'contact_id');
}
And then fetch using the function you wrote. I hope it would work.
Please try this out and tell me how it goes.

how to make fetching from two three model with clause and fetch selected fields in laravel [duplicate]

I have two tables, User and Post. One User can have many posts and one post belongs to only one user.
In my User model I have a hasMany relation...
public function post(){
return $this->hasmany('post');
}
And in my post model I have a belongsTo relation...
public function user(){
return $this->belongsTo('user');
}
Now I want to join these two tables using Eloquent with() but want specific columns from the second table. I know I can use the Query Builder but I don't want to.
When in the Post model I write...
public function getAllPosts() {
return Post::with('user')->get();
}
It runs the following queries...
select * from `posts`
select * from `users` where `users`.`id` in (<1>, <2>)
But what I want is...
select * from `posts`
select id,username from `users` where `users`.`id` in (<1>, <2>)
When I use...
Post::with('user')->get(array('columns'....));
It only returns the column from the first table. I want specific columns using with() from the second table. How can I do that?
Well I found the solution. It can be done one by passing a closure function in with() as second index of array like
Post::query()
->with(['user' => function ($query) {
$query->select('id', 'username');
}])
->get()
It will only select id and username from other table. I hope this will help others.
Remember that the primary key (id in this case) needs to be the first param in the
$query->select() to actually retrieve the necessary results.*
You can do it like this since Laravel 5.5:
Post::with('user:id,username')->get();
Care for the id field and foreign keys as stated in the docs:
When using this feature, you should always include the id column and
any relevant foreign key columns in the list of columns you wish to
retrieve.
For example, if the user belongs to a team and has a team_id as a foreign key column, then $post->user->team is empty if you don't specifiy team_id
Post::with('user:id,username,team_id')->get();
Also, if the user belongs to the post (i.e. there is a column post_id in the users table), then you need to specify it like this:
Post::with('user:id,username,post_id')->get();
Otherwise $post->user will be empty.
For loading models with specific column, though not eager loading, you could:
In your Post model
public function user()
{
return $this->belongsTo('User')->select(['id', 'username']);
}
Original credit goes to Laravel Eager Loading - Load only specific columns
When going the other way (hasMany):
User::with(['post'=>function($query){
$query->select('id','user_id');
}])->get();
Don't forget to include the foreign key (assuming it is user_id in this example) to resolve the relationship, otherwise you'll get zero results for your relation.
In Laravel 5.7 you can call specific field like this
$users = App\Book::with('author:id,name')->get();
It is important to add foreign_key field in the selection.
If you want to get specific columns using with() in laravel eloquent then you can use code as below which is originally answered by #Adam in his answer here in response of this same question, the answer's main code is as below :
Post::with('user:id,username')->get();
So i have used it in my code but it was giving me error of 1052: Column 'id' in field list is ambiguous, so if you guys are also facing same problem
Then for solving it you have to specify table name before the id column in with() method as below code:
Post::with('user:user.id,username')->get();
I came across this issue but with a second layer of related objects. #Awais Qarni's answer holds up with the inclusion of the appropriate foreign key in the nested select statement. Just as an id is required in the first nested select statement to reference the related model, the foreign key is required to reference the second degree of related models; in this example the Company model.
Post::with(['user' => function ($query) {
$query->select('id','company_id', 'username');
}, 'user.company' => function ($query) {
$query->select('id', 'name');
}])->get();
Additionally, if you want to select specific columns from the Post model you would need to include the user_id column in the select statement in order to reference it.
Post::with(['user' => function ($query) {
$query->select('id', 'username');
}])
->select('title', 'content', 'user_id')
->get();
In your Post model:
public function userWithName()
{
return $this->belongsTo('User')->select(array('id', 'first_name', 'last_name'));
}
Now you can use $post->userWithName
There is another alternative you can eager load specific columns
public function show(Post $post)
{
$posts = $post->has('user')->with('user:id,name,email,picture')->findOrFail($post->id);
return view('your_blade_file_path',compact('posts);
}
In your Post model you should have user relationship also
public function user()
{
return $this->belongsTo( User::class, 'user_id')->withDefault();
}
Note: It is mentioned in Laravel docs.
https://laravel.com/docs/8.x/eloquent-relationships#eager-loading-specific-columns
Note that if you only need one column from the table then using 'lists' is quite nice. In my case i am retrieving a user's favourite articles but i only want the article id's:
$favourites = $user->favourites->lists('id');
Returns an array of ids, eg:
Array
(
[0] => 3
[1] => 7
[2] => 8
)
If you use PHP 7.4 or later you can also do it using arrow function so it looks cleaner:
Post::with(['user' => fn ($query) => $query->select('id','username')])->get();
I faced the same issue while using belongsToMany relationship with my user model (Laravel 8.x.x).
After a long search and trial and test method. I found out this answer
You have to make sure you are selecting the id's and any foreign keys that would be needed for the relationship from either side of that relationship. This allows Eloquent to match up parents to their children.
Original credit goes to https://stackoverflow.com/a/64233242/1551102
So I included
Groups::select('groupid')
...
And it worked like a charm. Although now I want to know how to hide the groupid field after fetching.
I know I can simply loop through the array and remove it. But is there any other method? potentially a simpler and better one.
You can also specify columns on related model at the time of accessing it.
Post::first()->user()->get(['columns....']);
You can try this code . It is tested in laravel 6 version.
Controller code
public function getSection(Request $request)
{
Section::with(['sectionType' => function($q) {
$q->select('id', 'name');
}])->where('position',1)->orderBy('serial_no', 'asc')->get(['id','name','','description']);
return response()->json($getSection);
}
Model code
public function sectionType(){
return $this->belongsTo(Section_Type::class, 'type_id');
}
Be careful that if you don't add the key column(s) it won't return anything. If you want to show only the username without the id you could instead define the $visible/$hidden properties within the Model, like so:
app/Models/User.php
protected $visible = ['username'];
Then it will retrieve only username column with:
Post::with('user')->get();
Hiding the key columns:
Alternatively you could hide the key column(s) and then retrieve only the columns you wish.
app/Models/User.php
protected $hidden = ['id'];
Specify which columns you want including the key or else it won't return anything, but this will actually only return the username, because id is $hidden.
Post::with('user:id,username')->get();
Now you can use the pluckmethod on a Collection instance:
This will return only the uuid attribute of the Post model
App\Models\User::find(2)->posts->pluck('uuid')
=> Illuminate\Support\Collection {#983
all: [
"1",
"2",
"3",
],
}
Try with conditions.
$id = 1;
Post::with(array('user'=>function($query) use ($id){
$query->where('id','=',$id);
$query->select('id','username');
}))->get();
So, similar to other solutions here is mine:
// For example you have this relation defined with "user()" method
public function user()
{
return $this->belongsTo('User');
}
// Just make another one defined with "user_frontend()" method
public function user_frontend()
{
return $this->belongsTo('User')->select(array('id', 'username'));
}
// Then use it later like this
$thing = new Thing();
$thing->with('user_frontend');
// This way, you get only id and username,
// and if you want all fields you can do this
$thing = new Thing();
$thing->with('user');
EmployeeGatePassStatus::with('user:id,name')->get();

Get Specific Columns Using “With()” Function in Laravel Eloquent

I have two tables, User and Post. One User can have many posts and one post belongs to only one user.
In my User model I have a hasMany relation...
public function post(){
return $this->hasmany('post');
}
And in my post model I have a belongsTo relation...
public function user(){
return $this->belongsTo('user');
}
Now I want to join these two tables using Eloquent with() but want specific columns from the second table. I know I can use the Query Builder but I don't want to.
When in the Post model I write...
public function getAllPosts() {
return Post::with('user')->get();
}
It runs the following queries...
select * from `posts`
select * from `users` where `users`.`id` in (<1>, <2>)
But what I want is...
select * from `posts`
select id,username from `users` where `users`.`id` in (<1>, <2>)
When I use...
Post::with('user')->get(array('columns'....));
It only returns the column from the first table. I want specific columns using with() from the second table. How can I do that?
Well I found the solution. It can be done one by passing a closure function in with() as second index of array like
Post::query()
->with(['user' => function ($query) {
$query->select('id', 'username');
}])
->get()
It will only select id and username from other table. I hope this will help others.
Remember that the primary key (id in this case) needs to be the first param in the
$query->select() to actually retrieve the necessary results.*
You can do it like this since Laravel 5.5:
Post::with('user:id,username')->get();
Care for the id field and foreign keys as stated in the docs:
When using this feature, you should always include the id column and
any relevant foreign key columns in the list of columns you wish to
retrieve.
For example, if the user belongs to a team and has a team_id as a foreign key column, then $post->user->team is empty if you don't specifiy team_id
Post::with('user:id,username,team_id')->get();
Also, if the user belongs to the post (i.e. there is a column post_id in the users table), then you need to specify it like this:
Post::with('user:id,username,post_id')->get();
Otherwise $post->user will be empty.
For loading models with specific column, though not eager loading, you could:
In your Post model
public function user()
{
return $this->belongsTo('User')->select(['id', 'username']);
}
Original credit goes to Laravel Eager Loading - Load only specific columns
When going the other way (hasMany):
User::with(['post'=>function($query){
$query->select('id','user_id');
}])->get();
Don't forget to include the foreign key (assuming it is user_id in this example) to resolve the relationship, otherwise you'll get zero results for your relation.
In Laravel 5.7 you can call specific field like this
$users = App\Book::with('author:id,name')->get();
It is important to add foreign_key field in the selection.
If you want to get specific columns using with() in laravel eloquent then you can use code as below which is originally answered by #Adam in his answer here in response of this same question, the answer's main code is as below :
Post::with('user:id,username')->get();
So i have used it in my code but it was giving me error of 1052: Column 'id' in field list is ambiguous, so if you guys are also facing same problem
Then for solving it you have to specify table name before the id column in with() method as below code:
Post::with('user:user.id,username')->get();
I came across this issue but with a second layer of related objects. #Awais Qarni's answer holds up with the inclusion of the appropriate foreign key in the nested select statement. Just as an id is required in the first nested select statement to reference the related model, the foreign key is required to reference the second degree of related models; in this example the Company model.
Post::with(['user' => function ($query) {
$query->select('id','company_id', 'username');
}, 'user.company' => function ($query) {
$query->select('id', 'name');
}])->get();
Additionally, if you want to select specific columns from the Post model you would need to include the user_id column in the select statement in order to reference it.
Post::with(['user' => function ($query) {
$query->select('id', 'username');
}])
->select('title', 'content', 'user_id')
->get();
In your Post model:
public function userWithName()
{
return $this->belongsTo('User')->select(array('id', 'first_name', 'last_name'));
}
Now you can use $post->userWithName
There is another alternative you can eager load specific columns
public function show(Post $post)
{
$posts = $post->has('user')->with('user:id,name,email,picture')->findOrFail($post->id);
return view('your_blade_file_path',compact('posts);
}
In your Post model you should have user relationship also
public function user()
{
return $this->belongsTo( User::class, 'user_id')->withDefault();
}
Note: It is mentioned in Laravel docs.
https://laravel.com/docs/8.x/eloquent-relationships#eager-loading-specific-columns
Note that if you only need one column from the table then using 'lists' is quite nice. In my case i am retrieving a user's favourite articles but i only want the article id's:
$favourites = $user->favourites->lists('id');
Returns an array of ids, eg:
Array
(
[0] => 3
[1] => 7
[2] => 8
)
If you use PHP 7.4 or later you can also do it using arrow function so it looks cleaner:
Post::with(['user' => fn ($query) => $query->select('id','username')])->get();
I faced the same issue while using belongsToMany relationship with my user model (Laravel 8.x.x).
After a long search and trial and test method. I found out this answer
You have to make sure you are selecting the id's and any foreign keys that would be needed for the relationship from either side of that relationship. This allows Eloquent to match up parents to their children.
Original credit goes to https://stackoverflow.com/a/64233242/1551102
So I included
Groups::select('groupid')
...
And it worked like a charm. Although now I want to know how to hide the groupid field after fetching.
I know I can simply loop through the array and remove it. But is there any other method? potentially a simpler and better one.
You can also specify columns on related model at the time of accessing it.
Post::first()->user()->get(['columns....']);
You can try this code . It is tested in laravel 6 version.
Controller code
public function getSection(Request $request)
{
Section::with(['sectionType' => function($q) {
$q->select('id', 'name');
}])->where('position',1)->orderBy('serial_no', 'asc')->get(['id','name','','description']);
return response()->json($getSection);
}
Model code
public function sectionType(){
return $this->belongsTo(Section_Type::class, 'type_id');
}
Be careful that if you don't add the key column(s) it won't return anything. If you want to show only the username without the id you could instead define the $visible/$hidden properties within the Model, like so:
app/Models/User.php
protected $visible = ['username'];
Then it will retrieve only username column with:
Post::with('user')->get();
Hiding the key columns:
Alternatively you could hide the key column(s) and then retrieve only the columns you wish.
app/Models/User.php
protected $hidden = ['id'];
Specify which columns you want including the key or else it won't return anything, but this will actually only return the username, because id is $hidden.
Post::with('user:id,username')->get();
Now you can use the pluckmethod on a Collection instance:
This will return only the uuid attribute of the Post model
App\Models\User::find(2)->posts->pluck('uuid')
=> Illuminate\Support\Collection {#983
all: [
"1",
"2",
"3",
],
}
Try with conditions.
$id = 1;
Post::with(array('user'=>function($query) use ($id){
$query->where('id','=',$id);
$query->select('id','username');
}))->get();
So, similar to other solutions here is mine:
// For example you have this relation defined with "user()" method
public function user()
{
return $this->belongsTo('User');
}
// Just make another one defined with "user_frontend()" method
public function user_frontend()
{
return $this->belongsTo('User')->select(array('id', 'username'));
}
// Then use it later like this
$thing = new Thing();
$thing->with('user_frontend');
// This way, you get only id and username,
// and if you want all fields you can do this
$thing = new Thing();
$thing->with('user');
EmployeeGatePassStatus::with('user:id,name')->get();

Kohana 3.2 ORM define foreign keys consisting of two columns

I am building an application on the Kohana framework. For content management, I will be using the Joomla framework, so our copywriters can easily add and edit content in a to them familiar UI.
I have defined several categories to which an article can belong to. E.g. blog (catid = 1) and product (catid = 2). With the xreference column in the joomla content table, the user must assign the article to a specific id in the category selected (because Model_Blog can contain id = 1, as well as Model_Product can).
So every article in Joomla consists of a unique combination of catid and xreference. Now I want to bind this one-to-one relation to my Kohana ORM models (e.g. Model_Blog), but the standard Kohana ORM $_has_one property only supports foreign keys consisting of one column instead of multiple AFAIK.
I tried the following, which, of course, doesn't work:
protected $_has_one = array(
'content' => array('model' => 'cms_content', 'foreign_key' => 'xreference', 'catid' => '1')
);
Can anyone advise me on how to bind this relationship correctly?
After a lookup in the source code, I found out that Kohana ORM doesn't support the feature I described and I had to extend the ORM module (which is because of Kohana's nature, a piece of cake :)), to implement multi-column FK's.
class ORM_Modified extends ORM {
public function __get($column) {
if (isset($this->_has_one[$column])) {
$model = $this->_related($column);
$pk = $this->pk();
// Use this model's primary key value (if no value set) and foreign model's column(s)
if(!is_array($this->_has_one[$column]['foreign_key'])) {
$col = ;
$model->where($model->_object_name.'.'.$this->_has_one[$column]['foreign_key'], '=', $pk);
} else {
foreach($this->_has_one[$column]['foreign_key'] as $col => $value) {
$model->where($model->_object_name.'.'.$col, '=', $value == null ? $pk : $value);
}
}
$model->find();
return $this->_related[$column] = $model;
} else {
return parent::__get($column);
}
}
}
Now I can define an array of columns which form the foreign key in the relationship with the following syntax:
protected $_has_one = array(
'content' => array('model' => 'cms_content', 'foreign_key' => array('xreference' => null, 'catid' => '1'))
);
Please note that my solution only applies to a 1-to-1 relationship, because in my case there's no need to implement it for 1-to-many, although I suspect this would require a similar modification

Categories