i'm trying to display this json column into blade file
But i get Trying to get proprty 'en' of non object
<tr>
<th>Title en</th>
<th>Title ar</th>
<th>Description</th>
<th>Session Number</th>
<th>Session Per Week</th>
<th>Session Duration</th>
<th>Show</th>
</tr>
#foreach($model as $program)
<tr>
<th>{{json_decode($program->title)->en}}</th>
<th>{{json_decode($program->title)->ar}}</th>
<th>{{$program->description}}</th>
<th>{{$program->sessions_number}}</th>
<th>{{$program->sessions_per_week}}</th>
<th>{{$program->session_duration}}</th>
<th>{{$program->is_shown ? 'Yes' : 'No'}}</th>
</tr>
#endforeach
</thead>```
if your JSON format is something like
{"en":"title", "ar":"other-title"}
Then it should work.
My best guess is the en key doesn't exist on that title property.
If you are using the latest PHP then you can use the Nullsafe operator (?->) if not then use the isset check or use the null coalescing operator ??
<th>{{json_decode($program->title)->en ?? '' }}</th>
Also, be sure that $program->title itself is not null doing something like:
#php $title = isset($program->title) ? json_decode($program->title): null #endphp
<th>{{$title->en ?? '' }}</th>
But it is better to create a Accessor for this type of thing in the eloquent model. So you can directly do something like
$program->en_title;
So the blade file is clean and easy to understand but I don't suggest to go Accessor path if you are not reusing the code even if it makes the code cleaner. It is just my preference.
It looks like your title property is not an object, you should debug first to check it out, use dd() function to see inside this property
it appeared that my column was in trasnlatable array
and i just needed to call getTranslation mehtod and path to it the col and the app local jsu like that
{{getTranslation('title', 'en')}}
Related
I have a laravel crud with relations. but when i want to load the page some table rows dont have a value. and this gives the error: 'Attempt to read property "name" on null'
But how do i ignore this message and keep loading in the page?
index.blade:
#foreach($files as $file)
<tr>
<td>{{$file->id}}</td>
<td>{{$file->title}} </td>
<td>{{$file->description_short}} </td>
<td>{{$file->description_long}} </td>
<td>{{$file->file}}</td>
<td>{{$file->language->name}} </td>
<td>{{$file->subfolder->name}} </td>
<td>{{$file->role->name}} </td>
<td>
Edit
</td>
<td>
<form action="{{ route('admin.file.destroy', $file->id)}}" method="post">
#csrf
#method('DELETE')
<button class="btn btn-danger" type="submit">Delete</button>
</form>
</td>
</tr>
#endforeach
</tbody>
</table>
controller:
public function index()
{
$files = File::with('subfolder', 'language', 'tag')->get();
$languages = Language::all();
$tags = Tag::all();
$subfolders = Subfolder::all();
$users = User::all();
return view('admin.file.index', compact('files', 'languages', 'tags', 'users', 'subfolders'));
}
i want the index to ignore all the NULL properties
Using the # before your php Variable will work for you like below.
{{#$file->language->name}}
There are various ways:
Error control operator:
#$file->language->name the # operator suppress the errors messages (imho not very clean :) , but same result)
From documentation:
// Note: The #-operator works only on expressions. A simple rule of thumb is: if one can take the value of something, then one can prepend the # operator to it.
// For instance, it can be prepended to variables, functions calls, certain language construct calls (e.g. include), and so forth.
// It cannot be prepended to function or class definitions, or conditional structures such as if and foreach, and so forth.
Classical ternary operator way
$file->language ? $file->language->name : null;
From PHP7+ : Null Coalescing Operator
$file->language->name ?? null;
From PHP8+ : null safe Operator
$file->language?->name; (amazing! :-))
And also, by using
{{ $file->language->name ?? '' }} # typical PHP way
{{ $file->language?->name }} # if object/relation "language" exist then access "name" propery
Note:
When you use # to the variable {{#$file->language->name}}, we're skipping the error message. This means we're telling Laravel to "Leave this Variable alone". And It's not the best way to check if empty
Laravel has a built-in helper for this, called optional().
https://laravel.com/docs/9.x/helpers#method-optional
<td>{{ optional($file->language)->name }} </td>
The optional function accepts any argument and allows you to access properties or call methods on that object. If the given object is null, properties and methods will return null instead of causing an error.
I am doing a proof-of-concept/toy example to try and familiarize myself with the ins and outs of Laravel and I ended up running into an error that I wasn't expecting.
Within my blade template, I made a call to a helper function contained within the controller (controller was generated via php artisan make:controller CBookController). And the call from within the blade template was {{isset($val->prep) ? CBookController::toDate($val->prep) : ''}}. I got it working and all was dandy. I decided that I wanted to pull that helper function out of that controller so that I could use it elsewhere in the project.
NOTE: I could only call the code from within the view if I included the line:
<?php use app\Http\Controllers\CBookController; ?> within the blade template
Mind you, this all worked properly and didn't throw any errors.
So here is where it started to get funky.
I made the call >php artisan make:controller Helper
I refactored all of the references in the view to say Helper instead of CBookController i.e.
{{isset($val->prep) ? CBookController::toDate($val->prep) : ''}} --> {{isset($val->prep) ? Helper::toDate($val->prep) : ''}}
and
<?php use app\Http\Controllers\CBookController; ?> --> <?php use app\Http\Controllers\Helper; ?>
before I refactored everything, it all worked properly. But after said refactoring, things started to get all screwy.
Please note: I do realize that for a more advanced laravel user, making a "helper" controller doesn't make sense. Again, as a more novice user, I was just trying to make small incremental changes that would still work as expected.
I am not trying to figure out the proper way to use helper functions (at least at this junction), nor figure out anything else other than, why would creating a new controller and then referencing that controller within the view give me guff.
My intuition is telling me that the make:controller is doing more behind the scenes than I am aware of and that is what is causing the issue, but I do not know what to look for or where to look.
Any explanation on why this small change breaks the page would be helpful
I can confirm that both the CBookController.php and the Helper.php are in the same directory, so there shouldn't be a filepath issue with the use statement in the view.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class CBookController extends Controller
{
public function main()
{
$result = \DB::connection('database')
->table("docs")
->join("plans","docs.bn","=","plans.bn")
->select('docs.bn',
"plans.a",
'b as Status',
'c as fee',
'd as exec',
'e as mail',
'f as prep')
->where('id','=','19')
->where('b','=','N')
->get()
->toArray();
return view('test.Control_Book_Test')->with('result',$result);
}
public static function toDate($strToConvert)
{
return date("m-d-Y",strtotime($strToConvert));
}
}
this is the original controller (edited column fields for anonymity, I believe everything was kept consistent, but regardless, it did work before hand)
The new controller is as follows
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class Helper extends Controller
{
public static function toDate($strToConvert)
{
return date("m-d-Y",strtotime($strToConvert));
}
}
and finally, here is the view (before refactoring)
<?php use app\Http\Controllers\CBookController; ?>
#section('content')
<div style = "overflow-x: scroll">
<table class="table table-striped- table-bordered table-hover table-checkable" id="magicWand">
<thead>
<tr>
<th>Col 1</th>
<th>Col 2</th>
<th>Col 3/th>
<th>Col 4</th>
<th>Col 5</th>
<th>Col 6</th>
<th>Col 7n</th>
<th>Col 8</th>
<th>Col 9</th>
<th>Col 10</th>
<th>Col 11</th>
<th>Col 12</th>
<th>Col 13</th>
<th>Col 14<br></th>
</tr>
</thead>
<tbody>
#foreach($result as $k => $val)
<tr>
<td>{{isset($val->bn) ? $val->bn : ''}}</td>
<td>{{isset($val->ShortPlanName) ? $val->ShortPlanName : ''}}</td>
<td>n/a</td>
<td>{{isset($val->Status) ? $val->Status : ''}}</td>
<td>{{isset($val->fee) ? "$".number_format($val->fee,2) : ''}}</td>
<td>{{isset($val->exec) ? CBookController::toDate($val->exec) : ''}}</td>
<td>{{isset($val->mail) ? CBookController::toDate($val->mail) : ''}}</td>
<td>{{isset($val->prep) ? CBookController::toDate($val->prep) : ''}}</td>
<td>n/a</td>
<td>n/a</td>
<td>n/a</td>
<td>n/a</td>
<td>n/a</td>
<td>n/a</td>
</tr>
#endforeach
</tbody>
</table>
</div>
#endsection
For brevity's sake, there's no point in repasting the entire file with just some refactored names, but here are the lines that contain the refactored reference
<?php use app\Http\Controllers\CBookController; ?> (very first line)
<td>{{isset($val->exec) ? CBookController::toDate($val->exec) : ''}}</td> (within the #foreach)
<td>{{isset($val->mail) ? CBookController::toDate($val->exec) : ''}}</td> (within the #foreach)
<td>{{isset($val->prep) ? CBookController::toDate($val->exec) : ''}}</td> (within the #foreach)
I expected the page to work just fine, but I end up getting the an error page with the message "Class 'app\Http\Controllers\Helper' not found"
What you can do is create a custom facade, for your custom function.
Create a folder in App/Http/Custom
Create a class DateHelper
Add Your Function to the class
Use the custom facade in your view using the #inject
usage
#inject('helper', 'App\http\DateHelper');
{{ $helper->toDate('params') }};
This is data I have:
but with this blade template code:
<tbody>
#foreach ($orders as $order)
<tr>
<td>{{$order->id}}</td> //51 line
<td>{{$order->order->b_first_name}} {{$order->order->b_last_name}}</td>
<td>{{$order->order->r_first_name}} {{$order->order->r_last_name}}</td>
<td>£{{$order->total}}</td>
<td>{{$order->validity->diffForHumans()}}</td>
</tr>
#endforeach
</tbody>
I got this error:
ErrorException in fbe60fc17d23b35313269a941fc4d6f0 line 51: Trying to
get property of non-object (View:
/home/dgadmin/public_html/test/resources/views/admin/expired.blade.php)
What is the problem here? Why I cant use #foreach loop ?
First, go into your /storage/framework/views folder and look at line 51 for the file called fbe60fc17d23b35313269a941fc4d6f0. I see you said that it was $order->id, but I was not sure if you checked the compiled view that is actually served or admin/expired.blade.php. The compiled view is the one throwing the error, so the line number will correspond with the compiled view, not the blade you are making. When you look on this line you will see what is missing. This error is thrown because you are trying to access a null value on the model. If you want to go the lazy route, change your loop to this:
<tbody>
#foreach ($orders as $order)
<tr>
<td>{{isset($order->id)? $order->id: ''}}</td> //51 line
<td>{{isset($order->order->b_first_name)? $order->order->b_first_name : '' }} {{isset($order->order->b_last_name)? $order->order->b_last_name : ''}}</td>
<td>{{isset($order->order->r_first_name)? $order->order->r_first_name : ''}} {{isset($order->order->r_last_name)? $order->order->r_last_name : ''}}</td>
<td>£{{isset($order->total)?$order->total : ''}}</td>
<td>{{$order->validity->diffForHumans()}}</td>
</tr>
#endforeach
</tbody>
This will print the loop as expected, changing any missing values (like the one that triggered this errror) to a blank string.
I have a table and I want to enumerate each element.
Something like this
#foreach($elements as $element)
<tr>
<td>{{ (isset($a))?$a++:($a = 1) }}</td>
<td>...
</tr>
#endforeach
I expect the table to begin with 1 and then count on, however, the first two columns are always 1. I have already solved this problem by giving the template an $a = 0; on the controller but I want to know why my first solution doesn't work and if there is a workaround
Laravel Blade has a very handy variable for loops, called the $loop variable. This lets you gather information about the current element of the list, including the index and iteration count.
So you can do just this:
#foreach($elements as $element)
<tr>
<td>{{ $loop->iteration }}</td>
<td>...
</tr>
#endforeach
I have a Laravel application where I create a page layout, adding a table to it as a "content" variable (pretty much all from tutorials I found). Here's the controller action:
public function getMain() {
$js_config = Category::all();
$resources = Resource::all()->take(100);
$this->layout->content = View::make('categories.show')->with('js_config', $js_config)->with('resources', $resources);
}
This uses the main layout template and inserts this table using the content variable:
<table class="table table-striped table-bordered">
<thead>
<tr>
<td>ID</td>
<td>Name</td>
</tr>
</thead>
<tbody>
#foreach($resources as $key => $value)
<tr>
<td>{{ $value->id }}</td>
<td>{{ $value->title }}</td>
</tr>
#endforeach
</tbody>
</table>
But then comes the problem: I have a jstree where the user can select nodes, triggering a jQuery method:
$('#jstree2').on("changed.jstree", function (e, data) {
console.log(data.selected);
$.get("filter", { category: data.selected })
.done(function (resultdata) {
//Test only, this returns the data wanted in json, which I stringify just to display in test
alert("Data Loaded: " + JSON.stringify(resultdata));
});
});
The jQuery calls this action method in the controller:
public function getFilter()
{
$input = Input::get('category.0');
$categories = Category::find($input);
//category is the name from the model below
return Response::json(array(
'error' => false,
'category' => $categories->toArray()),
200
);
}
(The reason there's an array as input is I eventually want to be able to allow picking multiple nodes in the tree)
This action gets the data from the DB correctly and returns it as json. The callback in the jQuery above then alerts this at the moment, just as a test.
But what I really want to do, of course, is to repopulate the table. Now, as you can see I have used Bootstrap to create a pretty table and all, and I just want to be able to let the user repopulate it at will, without refreshing the page.
But I don't know how to do that, except by painstakingly recreate this table in some sort of string return value, but that doesn't seem like a good idea.
I'm hoping there's some way of passing the return value back to the view and have it reload the values in the table, utilizing the same "sub view" that I loaded in the php variable "content" as described above?
Any help greatly appreciated!
EDIT:
As requested, here's a sample of the json (taken from the browser console output, and it's actually not the categories table, but the same format):
[{"id":"1","title":"Transportation AC 4494","created_by":"4","modified_by":null},{"id":"2","title":"Safety First AC 4294","created_by":"3","modified_by":null},{"id":"3","title":"Warranty AC 34066","created_by":"4","modified_by":null}]
EDIT 2 (Just realized there was some crap from the controller in the previous edit of the json, so I changed it to a cleaner sample now)
EDIT 3:
I have made this work by creating the table rows in jQuery:
var trHTML = '';
$.each(resultdata, function (i, item) {
trHTML += '<tr><td>' + item.id + '</td><td>' + item.title + '</tr>';
});
$('#ajaxtable').html(trHTML);
But mainly I'm hoping this might explain my question better: this is not what I wanted to do. What I would have wanted was to just create a partial view and then load that ready-made view with the jquery:
A partial view like this:
<table class="table table-striped table-bordered" id="resultstable">
<thead>
<tr>
<td>ID</td>
<td>Name</td>
</tr>
</thead>
<tbody id="ajaxtable">
#foreach($resources as $key => $value)
<tr>
<td>{{ $value->id }}</td>
<td>{{ $value->title }}</td>
</tr>
#endforeach
</tbody>
</table>
I tested this by creating and calling a new function in the controller from the jquery code:
public function getTable()
{
$resources = Resource::all()->take(5);
return View::make('categories.results')->with('resources', $resources);
}
But it doesn't work. Although it does indeed give me the html of that view, it is unprocessed. I.e, the foreach loop is not resolved, but still there as code in the table. See the image:
So how can I load this view with the jquery code? It feels to me that even if the jquery creation of table rows works, doing the view in php and then just loading it with jquery should be the more correct way of doing it...?
Have you looked into the Datatables jQuery plugin? There is actually a nice package for Laravel that helps integrate Laravel and Datatables. The Laravel package generates the json and you can use Datables+AJAX to repopulate the data. Might be working checking out...
https://github.com/Chumper/datatable
http://datatables.net/
Otherwise, you'll just need to use AJAX to repopulate the table.
As Sirago answered, using jQuery Datatables is a good option to load data into tables in ajax manner.
In addition to what Sirago suggested, here is another great Laravel 4 package which is dedicated to generate JSON data from server side.
https://github.com/bllim/laravel4-datatables-package
But apart from server side configuration(modifying files like composer.json, config/app.php etc.), you need to code in Javascript, utilizing Datatables as well.