Laravel 4 Display ads to load any pictures from another table - php

I have a problem with displaying data from the form. He wants to load the data from two tables joined the foreign key.
I do not know what I'm doing wrong because I Chaly time returns the message:
Undefined property: Illuminate\Database\Eloquent\Relations\HasMany::$file
offers tabel:
id
user_id
title
...
photosofoffers tabel:
id
offer_id <- primary key offers.id
file (url photos)
...
my view:
#foreach($offers as $offer)
{{ HTML::image($offer->photosofoffers()->file, $offer->title, array('width'=>'50')) }}
my model Offer:
protected $fillable = array('id_category','user_id', 'title', 'description', 'price', 'availability');
public static $rules = array(
'id_category'=>'required|integer',
'title'=>'required|min:2',
'description'=>'required|min:2',
'price'=>'required|numeric',
'availability'=>'integer'
);
public function photosofoffers(){
return $this->hasMany('Photosofoffer');
}
public function category() {
return $this->belongsTo('Category');
}
}
my model Photosofoffer
<?php
class Photosofoffer extends Eloquent {
public function offer(){
return $this->belongsTo('Offer');
}
public function offers() {
return $this->hasMany('Offer');
}
}
How to display ads to load any pictures from another table?

hasMany means there are many photos of one offer. Therefore is it wise to call $something->photosofoffer()->photo ? If the return is an object, you'll definitely get an error.
First do dd($offer->photosofoffers()) or dd($offer->photosofoffers) to see what's happening. Then, if the object is properly being derived, You need to check loop through it. like #foreach($offer->photosofoffers as $photo) your loop of diplaying image #endforeach.
If there is nothing being derived, change the Controller function where you collect the actual $offer and make it Model::with('photoofoffers')->get() or first()
That should clear this up.
Hope this helps.
YK.

Related

Laravel Eloquent getting data from relations

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

Failure to extract data from a relationship with laravel

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));
}

Laravel count-function in Model, then sortBy count()

I am trying to Order the Posts table by the number of votes a Post has got.
The votes are stored in an other table
(Votes: post_id, user_id, vote_type)
Post-Model:
class Post extends Model
{
public function user()
{
return $this->hasOne(User::class);
}
public function votes()
{
return DB::table('votes')->where('post_id','=',$this->id)->sum('vote_type');
}
}
The votes functions returns the number of votes a post has recieved(The Votes a stored in a seperate table)
Now I am trying to order all the Posts by the number of votes they have got.
Post::get()->sortBy('votes');
This returns follwing Error:
Relationship method must return an object of type Illuminate\Database\Eloquent\Relations\Relation
I would be thankful about any help to fix this!
give it a try
Post::get()->sortBy(function($query){
return $query->votes();
});
Alternative
You can use withCount() as it will place a {relation}_count column on your resulting models.
Post::withCount(['votes'])
->orderBy('votes_count')
->get()
For Pagination
Refer docs for more details on paginations
Post::withCount(['votes'])
->orderBy('votes_count')
->paginate();
Add the following function in your Post Model
protected static function boot()
{
parent::boot();
static::addGlobalScope('voteCount', function ($builder) {
$builder->withCount('votes');
});
}
Now, each of your post model will always have a voteCount value and You can sort on that.
In your controller, use:
Post::get()->sortBy('voteCount');
Keep in mind that this will always return a votesCount with the PostModel, but I'm assuming it will be required as it usually does in this kind of applications.
If you want to sort votes as a attribute you have to to make it to be attribute by adding getVotesAttribute() method in your Post Model.
class Post extends Model
{
public function user()
{
return $this->hasOne(User::class);
}
public function getVotesAttribute()
{
return DB::table('votes')->where('post_id','=',$this->id)->sum('vote_type');
}
}

use relationship in model accessor in laravel

Suppose I have a Course model like this :
class Course extends Model
{
public $primaryKey = 'course_id';
protected $appends = ['teacher_name'];
public function getTeacherNameAttribute ()
{
$this->attributes['teacher_name'] = $this->teacher()->first()->full_name;
}
public function teacher ()
{
return $this->belongsTo('App\User', 'teacher', 'user_id');
}
}
And in the other hand there is a User model like this :
class User extends Authenticatable
{
public $primaryKey = 'user_id';
protected $appends = ['full_name'];
public function getFullNameAttribute ()
{
return $this->name . ' ' . $this->family;
}
public function course ()
{
return $this->hasMany('App\Course', 'teacher', 'user_id');
}
}
As you can see there is a hasMany relationship between those.
There is an full_name accessor in User model.
Now I want to add a teacher_name accessor to Course model that uses it's teacher relations and gets full_name of teacher and appends to Course always.
In fact I want whenever call a Course model, it's related teacher name included like other properties.
But every time , when call a Course model , I got this error :
exception 'ErrorException' with message 'Trying to get property of non-object' in D:\wamp\www\lms-api\app\Course.php:166
That refers to this line of Course model :
$this->attributes['teacher_name'] = $this->teacher()->first()->full_name;
I do not know how can I solve that and what is problem exactly.
Yikes some interesting answers here.
FYI to those coming after me- getFooAttribute() should return the data, and not modify the internal attributes array.
If you set a new value in the attributes array (that doesnt exist in this model's db schema) and then attempt to save the model, you'll hit a query exception.
It's worth reading up the laravel docs on attribute accessors/mutators for more info.
Furthermore, if you need to access a related object from within the model (like in an accessor) you ought to call $related = $this->getRelation('foo'); - note that if the relation isnt loaded (e.g., if you didnt fetch this object/collection with eager loaded relations) then $this->getRelation() could return null, but crucially if it is loaded, it won't run the same query(ies) to fetch the data again. So couple that with if (!$this->relationLoaded('foo')) { $this->loadRelation('foo'); }. You can then interact with the related object/collection as normal.
$this->attributes['teacher_name'] = $this->teacher()->first()->full_name;
Should be
$this->attributes['teacher_name'] = $this->teacher->full_name;
First thing is that you want to reference the relationship, so loose the brackets (), and because the relationship is belongsTo, you will have one user / teacher returned. So you don't need the first().
We haven't seen your fields but probably you will have to change:
return $this->belongsTo('App\User', 'teacher', 'user_id');
to
return $this->belongsTo('App\User', 'foreign_key', 'other_key');
where foreign_key and other_key are the primary keys that you need to make the join on.
Check this link from the documentation for reference:
https://laravel.com/docs/5.4/eloquent-relationships#one-to-many-inverse
the right way to do this is:
COURSE
public function setTeacherNameAttribute ()
{
$this->attributes['teacher_name'] = $this->teacher->full_name;
}
100% working for me.
I have one to one relationship between Order and Shipment. I have to add the accessor of shipments table column from orders table.
function getOrderNoAttribute()
{
$appendText = "OR100";
if($this->orderShipment()->first()) {
$appendText = $this->orderShipment()->first()->is_shipping === 1 ? "ORE100" : "OR100";
}
return $appendText . $this->attributes['id'];
}
This error is only object data to array use or array data to object data use.
example::
$var->feild insted of $var[feild]
$var[feild] insted of $var->feild
You should use return for accessors . something like this :
public function getTeacherNameAttribute ()
{
return $this->teacher()->first()->full_name ?? '';
}
maybe a course hasn't teacher.

Laravel simplify nested relation output

I get all items owned by authenticated user.
$items=Auth::user()->with('items')->get();
In my view i can access items collection, but instead of title_id want to retrieve item_title value.
Currently i'm able to get item_title value using code below:
$item->title->title
Is it possible to simplify it to retrieve title like this:
$item->title
?
Here is my models and relations:
Users
id
username
Item
id
user_id
title_id
Item_Titles
id
title
User model:
public function items()
{
return $this->hasMany('Item', 'user_id', 'id');
}
Item model:
public function user(){
return $this->belongsTo('User', 'user_id', 'id');
}
public function title()
{
return $this->belongsTo('ItemTitle','title_id','id');
}
ItemTitle model:
public function item()
{
return $this->hasMany('Item', 'title_id', 'id');
}
UPDATE
Excuse me probably I wasn't clear. To be precise - I just want to find Eloquent alternative to:
$items=Item::where('user_id','=',Auth::id())->leftJoin('item_titles', 'item.title_id', '=', 'item_titles.id')->get();
#foreach ($items as $item)
{{ $item->title }}
#endforeach
Just change your relationship function to
Item model:
public function title()
{
return $this->belongsTo('ItemTitle','title_id','id')->first()->title;
}
You will need to call it as $item->title() unless you also do
public function getTitleAttribute(){
return $this->title();
}
You might get some funny stuff with everything being called 'title' but with this $item->title should also work I think
Yes it is. It looks like you setup a many-to-many relationship with the Item model being the pivot table.
User Model
public function titles()
{
return $this->belongsToMany('ItemTitle', 'items');
}
Note: Change ItemTitle to the correct namespace. Also, change items to the Item model's table name.
You can also define the inverse relationship like this:
ItemTitle Model
public function users()
{
return $this->belongsToMany('User', 'items');
}
From there, you can get all the authenticated user's ItemTitles like this:
$titles = Auth::user()->titles;
Link to the documentation: https://laravel.com/docs/5.1/eloquent-relationships#many-to-many
Editing based on the comments below (thanks to #ash for helping clarify and for his suggestion):
The other answer is more along the lines of what you are trying to achieve so I would recommend taking a look at that. However, there is an error in your question. This does not return items:
$items=Auth::user()->with('items')->get();
That returns all users with their items eager loaded. To see proof of this, if you dd($items), you will most likely see every single user in the database.
That is most likely not what you want to do. To get all items for the authenticated users, you should do this:
$items = Auth::user()->items;
It's that simple to get a collection of items. This will run 2 queries - 1 to get the user and another to get all of his items.

Categories