undefined variable when trying to fetch data from database laravel - php

Hi I'm having trouble getting data from database after adding a new function inside my controller. Can anyone explain to me this error and what should I do?
Background information: I have 3 different type of tables, personal_infos, user_infos and user_info1s table where personal_infos hasMany user_infos and user_info1s. I am using user_id as a foreign key to link together with personal_infos table
I'm using this video as a reference and want to do something like his end result (see 17.17 of video), but I get this error:
Error: Undefined variable: data
What I want to do:
Route.php
Route::get('/home/{id}', 'HomeController#getData')->name('home');
HomeController
public function getData($id) {
$data['data'] = DB::table('personal_infos')->get()->sortByDesc('upload_time');
if (count($data) > 0) {
return view('home',$data)
->with('test', personal_info::find($id)); // --> after adding this got error
} else {
return view('home');
}
}
Home.blade.php
<table class="table table-bordered">
<tr>
<th><strong><big>Name: </big></strong></th>
</tr>
<td>
<tr>
#foreach($data as $value)
<tr>
<th>{{HTML::link_to_route('home',$value->Name, array($value->id)) }}</th>
</tr>
#endforeach
</tr>
</tr>
</table>
Code that I have now after some changes:
HomeController:
public function getData($id = null){
$data['data'] = DB::table('personal_infos')->orderBy('created_at', 'desc')->get();
return view('home')
->with('personalInfos', $personalInfos)
->with('test', personal_info::find($id));
}
}
home.blade.php
<ul>
#foreach ($personalInfos as $info)
<li>{{ HTML::link_to_route('home', $info->Name, [ $info->id ]) }}</li>
#endforeach
</ul>
Route
Route::get('/home/{id?}', 'HomeController#getData')->name('home');
personal_info model: (don't know if needed but just in case)
class personal_info extends Eloquent
{
protected $fillable = array('Email', 'Name', 'Mobile_No');
protected $table = 'personal_infos';
protected $primaryKey = 'id';
public function user_infos() {
return $this->hasMany('App\user_info','user_id');
}
public function user_info1s() {
return $this->hasMany('App\user_info1','user_id');
}
}
user_info1 and user_info (they are similar so I will just put 1 of them)
class user_info1 extends Eloquent
{
protected $fillable = array('hobby','sport','user_id');
public function personal_infos() {
return $this->belongsTo('App\personal_info', 'user_id', 'id');
}
}

I can tell you're learning Laravel. There are several issues with the code posted in your question. Let's walk through each of these to see if we can improve your understanding.
First, let's take a look at the controller method signature:
public function getData($id)
This method expects an $id parameter defined in the corresponding route. However, if we take a look at the route:
Route::get('/home/(:any)', 'HomeController#getData')->name('home');
...it doesn't properly declare that the URL contains a parameter (the video you're watching is about a very old version of Laravel). As described in the docs, we'll need to change the route signature to include a parameter for $id:
Route::get('/home/{id}', 'HomeController#getData')->name('home');
Next, let's see how the controller method fetches its data:
$data['data'] = DB::table('personal_infos')->get()->sortByDesc('upload_time');
This query fetches all records from personal_infos into a Collection, and then sorts them by upload_time. This is fine, but database engines can usually sort data faster than our PHP application, so we can instruct the DB to sort our data for us:
$data['data'] = DB::table('personal_infos')->orderBy('upload_time', 'desc')->get();
Notice how we changed the call to sortByDesc() on the collection to orderBy() for the database query. Now, the database sorts the results for us, so the collection doesn't need to.
Finally, let's try to fix the error you experience when passing the data to the view. Here's how your controller method currently does it:
if (count($data) > 0) {
return view('home', $data)
->with('test', personal_info::find($id)); // --> after adding this got error
} else {
return view('home');
}
There are a couple problems with the code above:
count($data) will always be greater than zero, because we're setting $data['data'] every time we call the method, so the else block will never execute. This is probably fine because...
...when count($data) equals zero, the controller doesn't pass the view any data, so $data in the view will be undefined.
The view in question uses #foreach to loop through each of the results, so we can simplify the code in the controller method because foreach won't iterate over an empty collection:
$personalInfos = DB::table('personal_infos')->orderBy('upload_time', 'desc')->get();
return view('home')
->with('personalInfos', $personalInfos)
->with('test', personal_info::find($id));
The view will receive two variables from the method above: $personalInfos and $test. I took the liberty of renaming $data['data'] into a more meaningful variable. This becomes very important as the project grows. Here's how we can use the data in the view:
<ul>
#foreach ($personalInfos as $info)
<li>{{ HTML::link_to_route('home', $info->Name, [ $info->id ]) }}</li>
#endforeach
</ul>
The template above outputs an unordered list as shown in the image in the question. The original table contains several row/column nesting errors and will not display the information like the question describes. As we can see, this template loops through each result in $personalInfos. If $personalInfos is empty, the list will not display any items.
If we want our controller method to handle the route with or without an ID, we'll need to tell Laravel that the ID is optional. For the route, a question mark (?) after the parameter makes it optional:
Route::get('/home/{id?}', 'HomeController#getData')->name('home');
Then, we can set a default value for the controller method that handles the route. In this case, we'll use null:
public function getData($id = null)
Of course, after we update this, we'll need to change the method to handle a null $id argument, which we use to fetch a personal_info for the view's $test variable. The question doesn't explain how the view uses $test, so I'll leave this as an exercise to the reader :)

Follow are two ways to pass multiple variables to view:
//Passing variable to view using with Method
return view('home')->with(['test'=>personal_info::find($id),'data'=>$data['data']]);
//Passing variable to view using Associative Array
return view('home', ['test'=>personal_info::find($id),'data'=>$data['data']]);

Related

unable to define relationship in laravel 5.7

I have two table as sbj_topics and difficulty_level_sbj_topic so, I want to define relationship b\w them to fetch records, so to make relationship I have done this,
SbjTopic.php:
public function difficulty_level_sbj_topic() {
return $this->hasMany('App\DiffiLvlSbjTopic');
}
And in DiffiLvlSbjTopic.php:
protected $table = 'difficulty_level_sbj_topic';
public function sbj_topics() {
return $this->belongsTo('App\SbjTopic');
}
After that I returned the data to a view as:
$easy = DiffiLvlSbjTopic::where(['subject_id' => $id, 'difficulty_level_id' => 2])->get();
return view('diffi_lvls.show', compact('easy'));
Then in the view I done this:
#foreach($easy as $easy)
{{ $easy->sbj_topics }}
#endforeach
but the page is blank, and when I do this {{ $easy->sbj_topics->sbj_topic_name }} trying to get property of undefined! comes.
The main purpose of creating relationship is to display Subject Topic Name because I have foreign key as sbj_topic_id in difficulty_level_sbj_topic table so if anyone has any other idea to do this without relationship that will be awesome.
Break this down:
SbjTopic - has many difflevels
a difflevel belongs to aSbjTopic
With this understanding, I can see you are getting the difflevels (DiffiLvlSbjTopic). This is actually what you are passing to your blade.
So first off: complete your relationship by specify the foreign keys. i.e:
In the SbjTopics model:
public function difficulty_level_sbj_topic() {
return $this->hasMany('App\DiffiLvlSbjTopic', 'subject_id');
}
with this, you know that in the 'difficulty_level_sbj_topic' you must have the column subject_id.
Now define the reverse relationship in your DiffiLvlSbjTopic model:
public function sbj_topics() {
return $this->belongsTo('App\SbjTopic', 'subject_id');
}
With all these in place in your controller or route all you need to do is fetch the DiffiLvlSbjTopic model properties. For instance:
public function index () {
$easy = DiffiLvlSbjTopic::all();
return view('diffi_lvls.show', compact('easy'));
}
Finally in your view:
#foreach($easy as $difflevel)
<div>{{ $difflevel->sbj_topics->name }} </div>
#endforeach
That's it.
Your both variables should not be $easy it can be something like $easy as $easySingle. And add a loop inside like
#foreach($easy as $easySingle)
foreach ($easySingle->sbj_topics as $topic) {
$topic->property;
}
#endforeach

Laravel Error: Property [id] does not exist on this collection instance. Yet it works on the local server

As mentioned in the title I get the error "Property [id] does not exist on this collection instance." Only when I run the code online here are my relevant codes.
1-EmployeeController (browser tells me that the error is here the second line)
public function show(Employee $employee)
{
$employee = Employee::find ($employee);
$edocument = EDocument::where ('employee_id',$employee->id)->first();
return view ('employee.show')->withEmployee($employee)->withEdocument($edocument);
}
2-show.blade.php
<div class="jumbotron">
<h1>{{$employee->name}} ({{$employee->position}})</h1>
#if (isset($edocument))
Go To Employee Database Page
#else
<p class="lead bg-danger">Employee documents are not uploaded</p>
#endif
Create Employee Contract
if anyone can explain to me this error in more details that would be great also. thanks
ps.. this is my first laravel project (;
You use route model binding in your controller method to get the Employee model. But you also run a find, which would fail since you're passing the model instead of the id. Do as one of the codes shown below and don't mix them.
Do this if you want to use route model binding.
public function show(Employee $employee)
{
$edocument = EDocument::where ('employee_id', $employee->id)->first();
return view ('employee.show')->with(compact('employee', 'edocument'));
}
Do this if you want to pass the employee id and fetch the model in controller.
public function show($employee)
{
$employee = Employee::find($employee);
$edocument = EDocument::where ('employee_id', $employee->id)->first();
return view ('employee.show')->with(compact('employee', 'edocument'));
}
Maybe this can help you. Why don't you pass the information in the controller using -
return view('employee.show', ['employee' => $employee, 'edocument'=>$edocument]);
It worked for me. (Do not have to change anything in the show.blade .php)

Laravel 5.4 relationship beLongsToMany

Hi i need fix returning view. I made relation and its returning array. How i can change this and i am not sure i made good function to relationship. I just trying lerning it i saw many tutorials and i know in Laravel is so kind magic tips to returning.
My function must showing events what user was joining. I think i make it but its returning array and when i try do something like that
#foreach($zapisevents as $zapisevent)
<table class="table">
<th>{{$zapisevent->eventsave->name}}</th>
</table>
#endforeach
i got error:
Property [name] does not exist on this collection instance. (View: /home/mariusz/Pulpit/www/szpital/resources/views/profil/profil.blade.php)
but when i use <th>{{$zapisevent->eventsave}}</th> its returning array.
There is function for joining to event
public function index()
{
$userid = Auth::user();
$zapisevents = User::with('eventsave')->where('id',(Auth::user()->id))->get();
return view('profil.profil', ['userid' => $userid], ['zapisevents' => $zapisevents]);
}
Model User:
public function eventsave()
{
return $this->belongsToMany(HomeModel::class,'save_events','users_id','events_id')->withTimestamps();
}
Model HomeModel <<<
public function usersave()
{
return $this->belongsToMany(User::class,'save_events','events_id','users_id');
}
Its returning:
[{"id":5,"name":"asdasdsa","title":"Wydzial 1","start":"2017-04-04
03:00:00","end":"2017-04-04 07:59:00","created_at":"2017-04-01
18:50:40","updated_at":"2017-04-01
18:50:40","pivot":{"users_id":3,"events_id":5,"created_at":"2017-04-01
18:50:58","updated_at":"2017-04-01
18:50:58"}},{"id":7,"name":"kkkkkkkkkkkkkkkkkkkkkkkk","title":"Wydzial
4","start":"2017-04-01 00:00:00","end":"2017-04-01
23:59:59","created_at":"2017-04-01 19:54:24","updated_at":"2017-04-01
19:54:24","pivot":{"users_id":3,"events_id":7,"created_at":"2017-04-01
19:55:41","updated_at":"2017-04-01 19:55:41"}}]
the
#foreach($zapisevents as $zapisevent)
<table class="table">
<th>{{$zapisevent->eventsave->name}}</th>
</table>
#endforeach
Should ne
#foreach($zapisevents as $zapisevent)
<table class="table">
#foreach($zapisevent->eventsave as $eventSave)
<th>{{$eventsave->name}}</th>
#endForeach
</table>
#endforeach
in you code the name property is being called in a collection of HomeModel but it needs to be called in a model itself
When using arrays, you need to access their properties via their index like this:
$zapisevent->eventsave['name']
as opposed to:
$zapisevent->eventsave->name

Route with multiple Id's (Laravel 5.2)

I want a URI like this
http://localhost:8000/category/1/3
The first id is Category_id and second is Food_id.
My route is:
Route::get('category/{Category_id?}/{Food_id?}', 'DetailsController#categ');
And in Controller I have:
public function categ($Category_id,$Food_id)
{
$category = Categories::with('food')->findOrFail($Category_id);
$food = Food::with('restaurant','categories')->findOrFail($Food_id);
return view('category', compact('category','food'));
}
But it gives error Missing argument 2 for App\Http\Controllers\Detailscontroller::categ().Can anyone tell where is the problem.I am new to laravel.What I want to do is first shows food items based on category_id and then shows the deatails of foods according to food_id.
For showing relevant category of foods,in my view I have
#foreach ($Category as $categories)
{{$categories->CategoryName}}
#endforeach
and it shows me food items.Then I want when I click on any food item it shows me detail based on food_id. so my nxt view look like:
#foreach ($category->food as $food)
{{ $food->FoodName }}
#endforeach
The comment Anish left was correct, however, you main problem will come when you're trying to find models with null. To get around this you could have something like:
public function categ($Category_id,$Food_id)
{
$category = is_null($Category_id) ? []: Categories::with('food')->findOrFail($Category_id);
$food = is_null($Food_id) ? [] : Food::with('restaurant','categories')->findOrFail($Food_id);
return view('category', compact('category','food'));
}
NB They may be more errors in your view file depending on if you're trying to access.
However, I would go with a much more RESTful approach: https://laravel.com/docs/5.2/controllers#restful-resource-controllers
Essentially, this would mean having a controller for you Categories:
public function index() {
//Code to get all categories (if you have a lot you may want to paginate them)
}
public function show($Category_Id) {
$category = Categories::with('food')->findOrFail($Category_id);
//etc
}
and then a controller for you Foods with just a show() method:
public function show($Food_Id) {
$food = Food::with('restaurant','categories')->findOrFail($Food_id);
}
OR depending on how you set your route up you could also include the category as well if you need to (but if it's just a one2Many relationship it might be redundant) so you would have
public function show($category_ID, $Food_Id) //etc
Your routes would then be set up like this:
Route::get('categories', 'CategoriesController#index');
Route::get('categories/{$category_id}', 'CategoriesController#show');
//Assuming you go with the first option - something like:
Route::get('foods/{$food_id}', 'FoodsController#show');
//Assuming you go with the section option for Foods
Route::get('categories/{$category_id}/{$food_id}', 'FoodsController#show');
Obviously, the above is just an example so feel free to set you controllers/routes up how you like.
If you do end up going down the RESTful route (recommended) you then might want to look at: https://laravel.com/docs/5.2/routing#route-model-binding
Hope this help!

Query foreign key data from Blade template

I have two models: MenuCategory and MenuItem, I want to display MenuItem data on my blade page along with its MenuCategory. I know its possible to do this by adding it to the return data in my controller however I would like to do it leveraging Eloquent instead, however I receive errors.
Here are my codes:
MenuCategory model
public function items()
{
return $this->hasMany('App\MenuItem');
}
MenuItem model
public function category()
{
return $this->belongsTo('App\MenuCategory');
}
Controller
public function show($id)
{
$item = MenuItem::findOrFail($id);
return view('menu.admin.single', compact('item'));
}
Blade Page
{{ $item->category->name }}
UPDATE:
Table menu_item
id
name
menu_category_id
Table menu_category
id
name
When using all the above I get the following error:
Trying to get property of non-object
This error is due to the naming convention of Eloquent.
Provide the optional foreign key variable in your relationship method to make it work, ie.
$this->belongsTo('App\MenuCategory', 'menu_category_id');
Probably every Item doesn't contain a related category but to make sure you may try something like this, it'll try to retrieve the name only if there is a related category is available:
{{ $item->category ? $item->category->name : 'No Name or empty string' }}
Alternatively you may try something like this:
$item = MenuItem::has('category') // check if there is a related category
->with('category') // if yes then load it with that category
->findOrFail($id);
You used a different foreign key than Laravel expect so explicitly mention it like:
public function category()
{
return $this->belongsTo('App\MenuCategory', 'menu_category_id', 'id');
}

Categories