I'm starting with Laravel and I have two simple entities that are users and notes, which are related as follows:
User
public function notes()
{
return $this->hasMany('App\Note');
}
Notes
public function user()
{
return $this->belongsTo('App\User');
}
Now within my controller notes with eloquent, I would like to return all the notes that I have, but instead of receiving the id of the user I would like to return the name of this, there something that I have to specify in the relationship of both entities or simply I should adjust something in my query, at the moment I am using this:
$notes = Note::orderBy('id', 'desc')->get();
You can retrieve user name as below:
$notes = Note:: orderBy ('id', 'desc') -> get ();
foreach ($notes as $note)
{
$name = $note->user->name;
}
If you want to pass the whole $note data with the 'user_name' define your own class first. Something like this.
class my_class{
public $data;
public $user_name;
}
You can run a loop just after you get the $note variable and save the data to a new array as this code here.
$notes = Note::orderBy('id', 'desc')->get();
//define an empty Array
$data_arry=array();
foreach($notes as $note)
{
$custom=new my_class();
$name=User::where('u_user_id', $note->n_user_id)->limit(1)->get();
//First 'u_user_id' for column name in user table second 'n_user_id' for column name in note table
$user_name=$name[0]->u_user_name; // 'u_user_name' for column name of stored the name in user table
//pushing data to the object
$custom->data=$note;
$custom->user_name=$user_name;
$data_arry[]=$custom;
}
Now you can Manage data with new Array.
Related
I have Task model. My Task model has some relationships and it currently looks like this:
class Task extends Model
{
use HasFactory;
public $timestamps = false;
public function city()
{
return $this->hasOne(City::class, 'id', 'city_id');
}
public function type()
{
return $this->hasOne(Type::class, 'id', 'type_id');
}
public function note()
{
return $this->hasOne(Note::class, 'id', 'note_id');
}
public function operator()
{
return $this->hasOne(User::class, 'id', 'operator_id');
}
}
Now, in my TasksController I need to get Tasks that match certain criteria, like this:
$tasks = Task::whereCityId($city->id)->whereTypeId($type->id)->get()->toArray();
The problem is that fields named city_id type_id note_id operator_id will get my integer values that they have.
Instead I would like to get certain value from a related Model.
For example:
operator_id should be replaced with username from User table that corresponds to the user id.
An obvious solution to this would be to simply use foreach loop, go through my results and get the data I need and simply create another array with the information replaced, but I am not sure if this is the best idea and perhaps there is something better.
You have to change in your code:
$this->hasOne(ClassName::class, 'id', 'foreign_key');
To
$this->belongsTo(ClassName::class, 'foreign_key', 'id');
because Task's id does not available as foreign key in these tables. These table's id present in task table as foreign key so you have to use belongsTo() relationship to tell script from where these id belongs.
Then access properties like this:
$tasks = Task::with("type", "city", "operator")
->whereCityId($city->id)->whereTypeId($type->id)->get();
foreach($tasks as $task){
echo $task->city->name;
}
first you should fix your relation:
public function city()
{
return $this->hasOne(City::class,'city_id','id');
}
and so one the same error, foreign key in argument order comes before the primary key.
after that you can use addSelect:
$tasks = Task::whereCityId($city->id)->whereTypeId($type->id)
->addSelect(['userName' => User::select('name')
->whereColumn('users.id', 'tasks.operator_id')
->limit(1)])->get()->toArray();
i think this will help better than what you ask.
$tasks = Task::whereCityId($city->id)
->whereTypeId($type->id)
->with('operator')
->get()->toArray();
with('operator') is ORM feature that make you collection to include its relation as collection property. In this case it will convert to array property.
you could access it from your foreach function as
#foreach($task as $key)
$key['operator']['username']
#endforeach
Have a nice day
I am trying to make a one-to-many relationship, but I get the following error
Undefined property: stdClass::$client (View:
C:\wamp\www\intranet\resources\views\users\list.blade.php)
The problem is that I am working with an existing database that in the tables does not have id fields, and the foreign keys would also be the typical ones like client_id
My model Client.php
class Client extends Model
{
protected $connection = 'dpnmwin';
protected $table = 'nmundfunc';
public function employee(){
return $this->hasMany('App\Employee');
}
}
My model Employee.php
class Employee extends Model
{
protected $connection = 'dpnmwin';
protected $table = 'nmtrabajador';
public function client(){
return $this->belongsTo('App\Client', 'COD_UND');
}
}
In nmtrabajador COD_UND field would be the foreign key that relates to nmundfunc.
And I try to get the data out like this: {{$user->client->CEN_DESCRI}}.
but it does not throw me the error, how can I solve it?
My Controller where I send in sight
public function index(){
$users = DB::connection('dpnmwin')->table('nmtrabajador')->where('CONDICION', '=', 'A')->get();
return view('users.list',array(
'users' => $users
));
}
You have to call basis on relations.
This code will return you data.
If you have id then you can find by id like below
$employee=Employee::find(1);
Or if you want to fetch all data then you can call all method.
Employee::all();
And then you can just get it by relation as you define in models.
$client=$employee->client->CEN_DESCRI;
Retrieving data from the instance is based on the methods which we have use.
Here in this answer, you can get that
Property [title] does not exist on this collection instance
I hope it will work.
If table doesn't have 'id' as primary key you should specify what the primary key is inside your model:
protected $primaryKey = 'your_primary_key';
Relation looks good, after that you must make sure $user is a defined instance of Employee, because your error probably means that your instance wasn't even defined, so for example if you are using list.blade.php, you need to change the return of your controller and indicate that you want to pass data to your view, for example you could do it like this:
return view('users.list', compact('user'));
Where user is an instance of Employee saved on '$user'
Update
First you should check your user is retrieved properly, you can check it by placing a dd($user)
And when you return a view you can pass information to it, a cleaner way of doing what you are trying to do is what I wrote earlier so you would end up having something like this:
public function index()
{
$users = DB::table('nmtrabajador')
->where('CONDICION', '=', 'A')
->get();
// dd($user) for debugging you are retrieving the user properly
return view('users.list', compact($users));
}
im sory, im noob in laravel. later, im build web just use php native, and i have code like this
$query1 = select * from user where id='$id';
while($data1 = mysql_fetch_array($query1){
$query2 = select * from komen where iduser=$data['id'];
}
so to convert to laravel be what.
I already read the documentation laravel but did not find
Where id = $id should only return 1 value (given that id is your unique primary key), so you would never have to loop through the result of your $query1, it's just 1 or nothing.
Best thing you can do to fetch the related Komen is to setup a relation in the model. For more info see: https://laravel.com/docs/5.3/eloquent-relationships
Best option for you is to create the User model first (already exists after Laravel installation) and add the komens() relation (1:n)
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
protected $table = 'user'; // should be users
// define has many relationship
public function komens()
{
// you will have to set userid, as laravel searches for user_id (singular tablename _ key)
return $this->hasMany(Komen::class, 'userid');
}
}
Then create the Komen model (check your naming conventions, laravel looks for the table name as the lowercase snake_cased plural version of your model name, so in this case komens. If you want to overwrite this, you have to set the protected $table = 'komen';
use Illuminate\Database\Eloquent\Model;
class Komen extends Model
{
protected $table = 'komen'; // should be komens
// define the inverse of the user model's komens() method
public function user()
{
return $this->belongsTo(User::class, 'userid');
}
}
Now in your code you can do something like this:
// fetch the user by id
$user = User::find($id);
// check if user exists
if ($user) {
// fetch all related komens from the database and loop through the collection
$user->komens->each(function($komen) {
// do foo here
dump($komen);
});
}
Check out the Eloquent ORM documentation here: https://laravel.com/docs/5.3/eloquent
First create the UserModel and KomenModel.
then use this
$queryData = UserModel::find($id);
foreach ($queryData as $data) {
$query2 = KomenModel::find($data->id);
}
or instead of above code you can do this using laravel join query.
There are two way of creating Queries...
1.Query...using normal DB::table...
2.Eloquent Model...
description
1.
`$data = DB::table('Tablname')->where('id',$id)->all();`
in here USE DB;
and there are severl methods such as all() , get()
2.
$this->model->where($attrib, '=', $value)->get();
where we go from the model option...
But as i understood you can go with DB query method..
$result= DB::table('komen')->where('id', $id)->all();
//check the previous query have got any data...
if($result)
{
//go for the second Query.....
}
If there is any need just mention...I am also new to laravel 5.3
You can get by following code without use any model.
$Data = DB::table('user')->where('id', '=', $id)->get();
foreach ($Data as $data) {
$query2 = DB::table('komen')->where('iduser', '=', $data->id)->get();
}
I have database tables like this:
shoot: id, name, programme
programme: id, name
The eloquent relationship in the shoot is defined like this:
public function programme() {
return $this->belongsTo('App\Programme', 'programme', 'id');
}
When using dd(), I can see this is working correctly:
dd(Shoot:where('id','=',1)->with('programme')->first());
// prints the object with programme listed under the relationship
However when I eager-load the shoot and attempt to get the programme object, I retrieve the shoot attribute "programme" instead. E.g.:
$shoot = Shoot:where('id','=',1)->with('programme')->first();
echo $shoot->programme; // returns 1, not App\Programme object.
Is there a solution to this without having to rewrite masses of the codebase?
You shouldn't use the same name for the both relationship and column name, else you'll receive always the column name so try to edit one of them, I think the easiest one here is the relationship name :
public function programmeObj() {
return $this->belongsTo('App\Programme', 'programme', 'id');
}
Then call it as :
echo $shoot->programmeObj;
NOTE : But if you want to follow conventions you should replace the name attribute by programme_id so :
public function programme() {
return $this->belongsTo('App\Programme', 'programme_id', 'id');
}
Hope this helps.
To achieve what you after you will need to do the following:
$shoot = Shoot:where('id','=',1)->with('programme')->first();
$variable = $shoot->programme; // returns 1
$obj = $page->getRelationValue('programme') // returns App\Programme object.
This will returns always the column in your database if it exists, that's ID 1.
When you call dump($shoot); you should get the array with all attributes. But when you run the following you should get the name:
Your model:
public function programmeData() {
return $this->belongsTo('App\Programme', 'programme', 'id');
}
And your controller:
$shoot = Shoot:where('id','=',1)->first();
return $shoot->programmeData->name; // returns name
Hope this works!
If I have a Users table and Tags table, and a pivot table for a Belongs To Many relationship, how do I use Eloquent to load only the IDs of the relation?
If I do User::with('tags'), this will do a join on the pivot table and also a join on the tags table. However, this is unnecessary and inefficient in my case, as I want to be able to only select the IDs of the tags from the pivot table, not the other columns in the Tags table. In other words, I only want it to do a single join from Users to Users_Tags.
Thank you.
OK, since #WereWolf's suggestions are not correct (1st will cause error, 3rd might be wrong if there are custom keys), here are the options for you, that not fetch related models.
Starting with the most obvious:
// for single model:
$user = User::first();
$user->tags()->allRelatedIds(); // select id from related table -> join
This is what you may use, but it is not the answer, since you want to eager load those ids.
That being said, you need to create another model for pivot table:
// UserTag model
protected $table = 'user_tag';
// this is not required, just to make it read-only
public static function boot()
{
parent::boot();
static::saving(function() {
return false;
}
}
// User model
public function tagsPivot()
{
return $this->hasMany('UserTag')->select('tag_id', 'user_id'); // appropriate keys here
}
public function getTagsIds()
{
return $this->tagsPivot->lists('tag_id');
}
// then you can do this:
$users = User::with('tagsPivot')->get(); // no join, select category_id from pivot table
foreach ($users as $user)
{
$user->getTagsIds();
}
.
You can also make some changes on the User model, depending on your liking:
// to be able to do this:
$users = User::with('tagsIds')->get();
foreach ($users as $user)
{
$user->tagsIds;
}
// User model
public function tagsIds()
{
return $this->hasMany('UserTag')->select('tag_id', 'user_id'); // appropriate keys here
}
public function getTagsIdsAttribute()
{
if ( ! array_key_exists('tagsIds', $this->relations)) $this->load('tagsIds');
return $this->getRelation('tagsIds')->lists('tag_id');
}
Give it a try (not tested):
$user = User::query();
$ids = $user->getRelation('tags')->getRelatedIds();
Or maybe something like this (but does some extra queries during the tags call):
$user = User::find(1);
$ids = $user->tags->fetch('id');
Update: (Another way)
$user = User::find(1);
$ids = array_fetch(DB::table($user->joiningTable('tag'))
->where($user->getForeignKey(), $user->getKey())
->get(), 'tag_id');