Trying to get property of non-object with Model Relationship - php

I'm trying to get a relationship between models in a laravel template.
I want to get the product fields respective to an ad.
This is my AdController:
public function ads(Request $request)
{
$this->adRepository->pushCriteria(new RequestCriteria($request));
$hash = Auth::user()->environment_hash;
$ads = $this->adRepository->findByHash($hash);
return view('ads.index')
->with('ads', $ads);
}
This how I'm parsing to my blade template:
#foreach($ads as $ad)
<tr>
<td>{!! $ad->product->name !!}</td>
</tr>
#endforeach
But I keep getting this error:
Trying to get property of non-object
This is the adRepository file:
public function findByHash($hash = null)
{
$model = $this->model;
if($hash)
$this->model->where('environment_hash', $hash);
else
$this->model->where('environment_hash', Auth::user()->environment_hash);
return $model;
}
This my Ad Model: Ad.php
<?php
namespace App\Models;
use Eloquent as Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Ad extends Model
{
public function product()
{
return $this->belongsTo(Product::class);
}
}
This is my ad table:
id
product_id
environment_hash
And my product table:
id
environment_hash
name
What is wrong with the code?

Not sure but there must be some ad which has no product in your database. So this may be the reason you are getting error. Make sure that all of your ad has related product in database.
You can test it by running following code:
#foreach($ads as $ad) <tr> <td>Test {!! $ad->product !!}</td> </tr> #endforeach
If you get result like this:
Test some_name
Test
Test some_another_name
Then this is confirm that some ad has no related product.
If this is the case then you need to if() check before accessing the attributes of product.
Update
The problem is that you are missing get() in your findByHash().
It should be as:
public function findByHash($hash = null)
{
$model = $this->model;
if($hash)
$this->model->where('environment_hash', $hash);
else
$this->model->where('environment_hash', Auth::user()->environment_hash);
return $model->get();
}

Related

Laravel : load objects on many level

I have the following tables :
orders : id, etc...
order_lines : id, order_id, product_id, etc...
products : id, name, etc...
Foreign keys are defined.
My Laravel Models are defined as :
class Order
public function orderLine()
{
return $this->hasMany('App\OrderLine');
}
class OrderLine
public function order()
{
return $this->belongsTo('App\Order');
}
public function product()
{
return $this->belongsTo('App\Product');
}
class Product
public function orderLine()
{
return $this->hasMany('App\OrderLine');
}
I've tried many things, but nothing is working. Here is the best solution for me, but it's not working.
class OrderController
public function show($id)
{
$user = Auth::user();
$order = Order::where('user_id', '=', $user->id)->with(['orderLine.product'])->findOrFail($id);
return view('layouts/order/index', compact('order'));
}
I struggle to display the following data in the view :
#foreach($order->orderLine as $key => $orderLine)
<tr>
<td>{{$orderLine->product->name}}</td>
<tr>
#endforeach
Product object is not loaded. I want to display the product name in the above loop.
Try to do like this:
public function show($id)
{
$user = Auth::user();
$order = Order::with(['orderLines', 'orderLines.product'])
->where('user_id', '=', $user->id)
->findOrFail($id);
return view('layouts/order/index', compact('order'));
}
class OrderLine
public function order()
{
return $this->belongsTo(\App\Order::class, 'order_id');
}
public function product()
{
return $this->belongsTo(\App\Product::class, 'product_id');
}
class Order
public function orderLines()
{
return $this->hasMany(\App\OrderLine::class);
}
Change name of orderLine to orderLines because order has many orderLines.
And in your blade:
#foreach($order->orderLines as $orderLine)
<tr>
<td>{{$orderLine['product']->title}}</td>
<tr>
#endforeach
Hello Dezaley and welcome to StackOverflow!
Let's investigate your problem.
As far as I can see you are selecting the model in the wrong way. Let me help you:
$order = Order::where(['id' => $id, 'user_id' => $user->id])->with('orderLine.product')->firstOrFail();
The answer from mare96, who was very friendly to help me, is working. However, I found out someting.
You can implement as (mare96 solution)
public function show($id)
{
$user = Auth::user();
$order = Order::with(['orderLines', 'orderLines.product'])
->where('user_id', '=', $user->id)
->findOrFail($id);
return view('layouts/order/index', compact('order'));
}
#foreach($order->orderLines as $orderLine)
<tr>
<td>{{$orderLine['product']->title}}</td>
<tr>
#endforeach
In the view, I don't like the array syntax "$orderLine['product']->title". The following solution without the array is also working.
Solution is below :
public function show($id)
{
$user = Auth::user();
$order = Order::with('orderLines', 'orderLines.product')
->where('user_id', '=', $user->id)
->findOrFail($id);
return view('layouts/order/index', compact('order'));
}
#foreach($order->orderLines as $orderLine)
<tr>
<td>{{$orderLine->product->title}}</td>
<tr>
#endforeach
In fact, my issue was that product was defined to null in the model, so Product was always null in the view.
Class OrderLine extends Model {
public $product = null
I remove line "public $product = null" and it's working as expected. Thanks to the people who helped me.
give it a try -
#foreach($order as $ordr)
<tr>
<td>{{$ordr->product_id->name}}</td>
<tr>
#endforeach

Laravel: Trying to get property of non-Object Error

I have three tables viz:
Site:
id|name|slug|location|description
Accounthead:
id|accountname|slug
Transaction:
id|name|slug|site_id|accounthead_id|...
My Site model looks like:
class Site extends Model
{
protected $fillable = [
'name',
'slug',
'location',
'description'
];
public function transactions()
{
return $this->hasMany('App\Transaction', 'site_id');
}
}
My AccountHead Model Looks like:
class AccountHead extends Model
{
protected $fillable = [
'slug',
'accountname'
];
public function transactions()
{
return $this->hasMany('App\Transaction','accounthead_id');
}
}
And my Transaction model looks like:
class Transaction extends Model
{
public function site()
{
return $this->belongsTo('App\Site','id');
}
public function accounthead()
{
return $this->belongsTo('App\AccountHead','id');
}
}
In One of my blade I want to display all the transactions and the associated fields:
My blade File
#forelse($transactions as $key => $transaction)
<tr>
<td>{{++$key}}</td>
<td>{{$transaction->updated_at->format('M d Y')}}</td>
<td>{{str_limit($transaction->name, 47) }}</td>
<td>{{str_limit($transaction->accounthead->accountname,47)}}</td>
<td>{{str_limit($transaction->site->Name,47)}}</td>
<td>{{str_limit($transaction->amount,47)}}</td>
</tr>
#empty
<tr>
<td colspan="4" class="text-center">No Transactions available.</td>
</tr>
#endforelse
It is working fine, unless one Site/AccountHead is used for more than one Transaction. Once a Site/Accounthead is used for more than one transaction Its throwing:
(2/2) ErrorException
Trying to get property of non-object
Am I missing anything really stupid here?
The problem is typo in your code. Instead of:
str_limit($transaction->accountheads->accountname,47)
you should have:
str_limit($transaction->accounthead->accountname,47)
because that's the name of your relationship.
Also it might happen later that you don't have accounthead for some relationship - in such case take a look at Laravel 5 get data other table
First of all, you should fix the relationships:
public function site()
{
return $this->belongsTo('App\Site', 'site_id', 'id');
}
public function accounthead()
{
return $this->belongsTo('App\AccountHead', 'accounthead_id' 'id');
}
Or just:
public function site()
{
return $this->belongsTo('App\Site');
}
public function accounthead()
{
return $this->belongsTo('App\AccountHead');
}
After that, if it still doesn't work, you need to make sure every transaction has both 'site' and 'accounthead' relationships. In other words, every row in the transactions table should have a correct ID in site_id and column_id columns.
If not every transaction has site or account head, you need to check it before trying to use related object property:
<td>{{ str_limit(optional($transaction->accounthead)->accountname, 47) }}</td>
<td>{{ str_limit(optional($transaction->site)->Name, 47) }}</td>

Laravel nested eager loading error when showing it to output

I have nested looping view on laravel and i am having problem when i try to show the list of my items.
Here is the code where i have the error
#foreach($project->codes->items as $item)
<tr>
<td>{!! $item->item !!}</td>
</tr>
#endforeach
and it produces this error.
Cannot access protected property Illuminate\Database\Eloquent\Collection::$items
I have setup the models for project, code and items as.
Project Model
class Project extends Model
{
public $table = 'projects';
public function codes() {
return $this->hasMany('App\Models\Code');
}
}
Code Model
public function code() {
return $this->belongsTo('App\Models\Project');
}
public function items() {
return $this->hasMany('App\Models\Item');
}
item model
public function item() {
return $this->belongsTo('App\Models\Code');
}
And here's how i implement it on the controller
public function index(Request $request)
{
$this->projectRepository->pushCriteria(new RequestCriteria($request));
$projects = $this->projectRepository->with('codes.items')->all();
return view('projects.index')
->with('projects', $projects);
}
I have run the code on artisan tinker and it shows the correct data. But not loading on the output php.
Thank You for your support.
Please share the output
i think it should be like this
#foreach($project->codes as $code)
#foreach($code->items as $it)
<tr>
<td>{!! $it->item !!}</td>
</tr>
#endforeach
#endforeach

laravel eloquent repository query foreign key tables

hi i am using a custom repository and I am getting comfortable with querying one table to retrieve data like so:
public function getAll()
{
// get all logged in users projects order by project name asc and paginate 9 per page
return \Auth::user()->projects()->orderBy('project_name', 'ASC')->paginate(9);
}
and in my controller I simply call
public function __construct(ProjectRepositoryInterface $project) {
$this->project = $project;
}
public function index()
{
$projects = $this->project->getAll();
echo View::make('projects.index', compact('projects'));
}
and my view is as so:
#if (Auth::check())
#if (count($projects) > 0)
#foreach ($projects as $project)
{{ $project->project_name }}
#endforeach
#else
<p>No records, would you like to create some...</p>
#endif
{{ $projects->links; }}
#endif
However within my projects table I have a status_id and a client_id and I want to retrieve records of this these tables with the logged in user but I am not sure how to structure my query, does anyone have any guidance?
According to the laravel documentation, In your project model you can add the following function:
class Project extends Eloquent
{
public function clients()
{
return $this->hasMany(Client::class);
}
}
In your client model you can then add the inverse of the relationship with the function:
class Client extends Eloquent
{
public function project()
{
return $this->belongsTo(Project::class);
}
}
Then you can retrieve the data with a function like:
$clients = Project::find(1)->clients;

How do display a variable from a databse with through Relational Models?

I have a list of books and a list of authors. I made the Model relations, so that my Book Model says, that books->belongTo('Author') and my Author Model says, that authors->hasMany('Book').
So normally I could access the a variable through this:
$books = Book::all();
And then in the view:
#foreach($books as $book)
<div>{{$book->id}}</div>
<div>{{$book->title}}</div>
<div>{{$book->authors->firstname}}</div>
#endforeach
But this does not work. I get the error message: Trying to get property of non-object
So here are my files:
My Models:
Book.php
class Book extends \Eloquent {
protected $guarded = [];
public function religions()
{
return $this->belongsTo('Religion');
}
public function branches()
{
return $this->belongsTo('Branch');
}
public function authors()
{
return $this->belongsTo('Author');
}
public function quotes()
{
return $this->hasMany('Quote');
}
public function chapters()
{
return $this->hasMany('Chapter');
}
}
Author.php
class Author extends \Eloquent {
protected $guarded = [];
public function books()
{
return $this->hasMany('Book');
}
public function quotes()
{
return $this->hasMany('Quote');
}
public function branches()
{
return $this->belongsTo('Branch');
}
public function religions()
{
return $this->belongsTo('Religion');
}
}
Then come my controller:
ReligionBranchBookController
class ReligionBranchBookController extends \BaseController {
/**
* Display a listing of the resource.
*
* #return Response
*/
public function index($religionId, $branchId)
{
//
// $books = Book::where('religion_id', $religionId)->where('branch_id', $branchId)->get();
$books = Book::all();
$authors = Author::all();
// dd($books->toArray());
return View::make('books.index')
->with('religionId', $religionId)
->with('branchId', $branchId)
->with('books', $books)
->with('authors', $authors);
}
}
My Views:
index.blade.php
#extends('layout.main')
#section('content')
<h1>Books List!!</h1>
<table>
<tr>
<th>ID</th>
<th>Title</th>
<th>Author</th>
</tr>
#foreach($books as $book)
<tr>
<td>{{$book->id}}</td>
<td>{{$book->title}}</td>
<td>{{$book->authors->firstname}}</td>
</tr>
#endforeach
</table>
#stop
I know that it should normally work, I rebuild it with only books and authors, and it works fine there.
So, does anyone have an idea, where I am going wrong?
Thanks,
George
In your Book model change the authors method to author like this:
public function author()
{
return $this->belongsTo('Author');
}
Because, one book belongs to one author according to your relationship and when you call authors the belongsTo->getResults() get called and runs the wrong query so authors get null and you get the error. Things to remember:
For hasOne and belongsTo relationship use singular form of relationship method, i.e, author not authors.
hasOne or belongsTo returns a single model object.
For hasMany and belongsToMany relationship use plural form of relationship method, i.e, authors not author.
hasMany and belongsToMany returns a collection of model objects.

Categories