Laravel: Trying to get property of non-Object Error - php

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>

Related

count(): Parameter must be an array or an object that implements Countable in Laravel 6

I want to display data from multiple table to one view, first table is Transaction_in and second table is Transaction_in_detail but beside those two other table are involved.
This is Transcation_in Controller
class Transactions_inController extends Controller
{
public function show($id)
{
$supplierList = Supplier::where('id', 'nama')->first();
$transactionin = Transaction_in::where('id', $id)->first();
$deviceTypeList = DeviceType::where('id', 'nama_tipe_device')->first();
$deviceBrandList = DeviceBrand::where('id', 'nama_brand_device')->first();
$transactionindetail = Transaction_in_detail::where('id', 'Transansaction_in_id')->first();
//return view('transactionsin.show', compact('supplierList', 'transactionsin', 'deviceTypeList', 'deviceBrandList', 'transactionindetail'));
return view('transactionsin.show')->with('transactionsin', $transactionin);
return view('transactionsin.show')->with('transactionsindetail', $transactionindetail);
}
}
Transaction_in Model
class Transaction_in extends Model
{
protected $guarded = [];
public function get_suppliers()
{
return $this->belongsTo(Supplier::class, 'Supplier_id');
}
public function get_devicetypes()
{
return $this->belongsToMany(DeviceType::class, 'DeviceType_id');
}
public function get_devicebrands()
{
return $this->belongsToMany(DeviceBrand::class, 'DeviceBrand_id');
}
public function get_transactionindetail()
{
return $this->belongsToMany(Transaction_in_detail::class, 'Transaction_in_id');
}
}
Transaction_in_detail Model
class Transaction_in_detail extends Model
{
protected $guarded = [];
public function get_transction_in_id()
{
return $this->belongsTo(Transaction_in::class, 'Transaction_in_id');
}
public function get_devicetypes()
{
return $this->belongsToMany(DeviceType::class, 'DeviceType_id');
}
public function get_devicebrands()
{
return $this->belongsToMany(DeviceBrand::class, 'DeviceBrand_id');
}
}
I want to display data from Transaction_in_detail table to Transaction_in Controller, but i have this error
count(): Parameter must be an array or an object that implements
Countable (View:
C:\xampp\htdocs\inventory\resources\views\transactionsin\show.blade.php)
and this is transactionsin.show code https://hastebin.com/ilewesucej.xml
What does your table setup look like, specifically what is the relationship between Transaction_in and Transaction_in_detail? You have a One To Many relationship given in Transaction_in_detail::get_transaction_in_id and a Many to Many relationship given in Transaction_in::get_transactionindetail.
The belongsToMany relationship is for Many to Many relationships with a pivot table. Maybe this is supposed to be hasMany instead?
Start by clarifying that relationship correctly. See the docs on relationships in Laravel. Then you can pull the correct data.
Are you trying to get ONE Transaction_in instance with the id $id? In that case, no, you can't iterate over it. Maybe you're trying for something like this?
$transactionin = Transaction_in::find($id);
$transactionindetail = $transactionin->get_transactionindetail;
// $transactionindetail will now be a `Collection` which implements `Countable`.
Also note that you're (and some of the other answers) are mixing up transactionsin and transactionin (without the 's').
1.
You are using first() method which returns a single object , not array. Instead of returning a collection of models, first() method returns a single model instance. Rewrite your code as following -
$transactionin = Transaction_in::where('id', $id)->get();
For reference, Laravel Docs
2.
You don't have to return view and variables twice. Return once as following -
return view('transactionsin.show',compact('transactionsin','transactionsindetail'));
You don't need to return view two times. use compact for set multiple variable.
public function show($id)
{
$supplierList = Supplier::where('id', 'nama')->first();
$transactionin = Transaction_in::where('id', $id)->first();
$deviceTypeList = DeviceType::where('id', 'nama_tipe_device')->first();
$deviceBrandList = DeviceBrand::where('id', 'nama_brand_device')->first();
$transactionindetail = Transaction_in_detail::where('id', 'Transansaction_in_id')->first();
//return view('transactionsin.show', compact('supplierList', 'transactionsin', 'deviceTypeList', 'deviceBrandList', 'transactionindetail'));
return view('transactionsin.show',compact('transactionsin','transactionsindetail'));
}
In blade file check with empty condition.
#if (!empty($transactionsin))
<div class="tale-responsive">
<table class="table table-hover table-bordered">
<thead align="center">
<tr class="table-primary">
<th>Tipe Perangkat</th>
<th>Brand Perangkat</th>
<th>Spesifikasi</th>
<th>Jumlah</th>
<th>Harga</th>
<th>Total Harga</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{ $transactionin->get_devicetypes->nama_tipe_device }}</td>
<td>{{ $transactionin->get_devicebrands->nama_brand_device }}</td>
<td>{{ $transactionin->get_transactionindetail->spek_device }}</td>
<td>{{ $transactionin->get_transactionindetail->harga_device }}</td>
<td>{{ $transactionin->get_transactionindetail->jumlah_device }}</td>
<td>{{ $transactionin->get_transactionindetail->total_harga_device }}</td>
</tr>
</tbody>
</table>
</div>
#else
<h6>No Data Found</h6>
#endif
if you want to make object countable you have to use $object->count()in your case $transactionin->count()

Laravel Eloquent join throug pivot tables

Unfortunately, I don't have that much experience with Eloquent yet. I try to create a query from three tables which have two pivot tables.
My tables:
My Models:
Player
class Player extends Model
{
protected $table = 'players';
protected $fillable = [
'name'
];
public function layout(){
return $this->belongsToMany('App\Layout', 'layout_player', 'player_id', 'layout_id');
}
public function information(){
return $this->hasMany('App\Information', 'player_id');
}
}
Layout
class Layout extends Model
{
protected $table = 'layouts';
protected $fillable = [
'name'
];
public function player(){
return $this->belongsToMany('App\Player', 'layout_player', 'layout_id', 'player_id');
}
public function item(){
return $this->belongsToMany('App\Item', 'item_layout', 'layout_id', 'item_id');
}
}
Item
class Item extends Model
{
protected $table = 'items';
protected $fillable = [
'name'
];
public function layout(){
//return $this->hasOne(Layout::class);
return $this->belongsToMany('App\Layout', 'item_layout', 'item_id', 'layout_id');
}
}
Starting from the player, I want to retrieve the current player, all layouts and the corresponding items. Unfortunately I can't do it.
I call up the player and layouts as follows:
Player::where('id',1)->with('layout')->get();
How do I additionally get all items in the query?
You made a relationship perfectly. Now from Player to layout you're getting it with('layout'). Try it.
$players = Player::with('layout.item')->where('id',1)->get();
It'll give you players along with layouts with items.
If I understand your question, I think you are almost there.
Add this to Player model too, like other methods you did.
public function contents(){
return $this->belongsToMany('App\Content');
}
To get all contents regarding a player write these in controller and pass it to view file.
$player = Player::findOrFail(1);
return view('path.to.file_name',compact('player'));
In view file
//get all contents of a player
#foreach($player->contents as $content)
<p>{{ $content->text}}</p>
#endforeach
//get all layouts of a player
#foreach($player->layout as $layout)
<p>{{ $layout->name}}</p>
#endforeach
//get all items of a player
#foreach($player->layout as $layout)
<p>{{ $layout->name}}</p>
#foreach($layout->item as $item)
<p>{{ $item->name }}</p>
#endforeach
#endforeach
Thank you very much for the quick answer. Unfortunately this does not solve my problem.
I call the PlayerController via the api route and need all objects of the player in the form as return:
player
layout
item
public function show($id)
{
$player = Player::findOrFail($id);
//$player = Player::where('id',$id)->with('layout')->get();
return $player;
}
I get this response:
{"id":1,"name":"Testplayer","created_at":"2019-09-22 15:53:07","updated_at":"2019-09-22 15:53:07"}
But I need also the layouts and Items.
I hope you still understand my bad English.;)

Trying to get property of non-object with Model Relationship

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

Laravel resource::all with values from another table

I'm learning Laravel right now and i have following tables and resources (models, controllers, ect.):
tickets
- id
- title
- projectID
- statusID
projects
- id
- title
status
- id
- title
I have to make a list of my Tickets on the Startpage. Not nessesary to say that i need the Project- and Statustiltles and not the IDs. Currently i do:
Route::get('/', function()
{
$tickets = Ticket::all();
return View::make('layout')->with('tickets', $tickets);
});
My current output is:
tickets->id, tickets->title, tickets->projectID, tickets->statusID
The output i want is
tickets->id, tickets->title, tickets->projects->title, tickets->status->title
So i hope anyone can understand what i'm trying to ask here and maybe provide me some help. Thank you!
Resolution: I had to set the foreign_keys first in my DB. Then i used the relationships mentioned in the answers and it works fine.
My Model:
class Ticket extends \Eloquent {
protected $fillable = [];
public function project()
{
return $this->hasOne('Project', 'id', 'projectID');
}
public function status()
{
return $this->hasOne('Status', 'id', 'statusID');
}
}
My View:
#foreach($tickets as $key => $value)
...
<td>{{ $value->project->title }}</td>
<td>{{ $value->status->title }}</td>
...
#endforeach
If you configure you relationships correctly you can do that without problems using the Laravel Eager Loading feature, for example:
Eager Loading (Laravel docs)
Eager loading exists to alleviate the N + 1 query problem...
class Ticket extends Eloquent {
public function project()
{
return $this->belongsTo('Project', 'projectID', 'id');
}
public function status()
{
return $this->belongsTo('Status', 'statusID', 'id');
}
}
Now, just call the fields you want, for example:
foreach (Ticket::all() as $ticket)
{
echo $ticket->project->title;
echo $ticket->status->title;
}
Obs.: In your return object/array you can't see the relationships fields unless you do manual joins, etc. So, just configure your relationships and call the fields you want.
Sorry for my english
Define relationships specifying custom foreign keys (defaults would be status_id and project_id for your models):
// Ticket model
public function project()
{
return $this->belongsTo('Project', 'projectID');
}
public function status()
{
return $this->belongsTo('Status', 'statusID');
}
Then eager load related models:
$tickets = Ticket::with('project','status')->get();
// accessing:
foreach ($tickets as $ticket)
{
$ticket->status; // Status model with all its properties
$ticket->project; // Project model
}

Laravel: returning results from multiple related tables using eloquent

I'm using Laravel 4 and in particular I'm looking for an answer that uses eloquent ORM.
I have a table "tasks" which containers a client_id and a user_id assigned to each row.
client_id refers to a client on a "clients" table and user_id refers to a user on a "users" table.
What I want to do: show all tasks and display the "clients" name and "users" first_name
So the result would look like this in my (blade) view:
#foreach($tasks as $task)
<tr>
<td>{{ $task->user->first_name }}</td>
<td>{{ $task->client->name }}</td>
<td>{{ $task->description }}</td>
</tr>
#endforeach
The above view spits out the $task->client->name perfectly fine but unfortunately shows a "Trying to get property of non-object" when I add the line $task->user->first_name
My controller looks like this:
$tasks = Task::with(array('user', 'client'))->get();
return View::make('index', compact('tasks'));
As I understand it my models make a difference too, so my models look like this:
class Task extends Eloquent {
protected $guarded = array();
public static $rules = array();
public function client() {
return $this->belongsTo('Client');
}
public function user() {
return $this->belongsTo('User');
}
}
And:
class User extends Eloquent implements UserInterface, RemindableInterface {
public function task()
{
return $this->hasMany('Task');
}
}
And:
class Client extends Eloquent {
public function projects(){
return $this->hasMany('Project', 'client_id');
}
}
Any ideas on how to make this work? I've been scratching my head for a while - also note I'm not a database relationship pro so the simpler the explanation the better :)
I just worked through this and learned quite a few things myself. What I did was setup a many to many relationship between users and clients and created a pivot table for handling the relationship called tasks which also stores the description for each task.
It was too much to type here, but you can check out my code at http://paste.laravel.com/Fpv
Many-to-many relationships can be done like this with Eloquent:
class User extends Eloquent implements UserInterface, RemindableInterface {
public function client()
{
return $this->belongsToMany('Client', 'tasks', 'client_id')->withPivot('description');
}
}
and the inverse relationship...
class Client extends Eloquent {
public function users()
{
return $this->belongsToMany('User', 'tasks', 'user_id');
}
}
Haven't tested this, but it should be correct.

Categories