Laravel - Display data from multiple tables in one page - laravel

I have 3 tables in my database. I want to display all 3 table data on a single page.
Student.php
public function hobbies() {
return $this->hasMany(Student::class);
}
Hobbie.php
public function student()
{
return $this->belongsTo(Student::class);
}
Controller.php
$students->name= request('name');
$students->address = request('address');
if($students->save())
for ($i=0; $i < count(request('hob')); ++$i)
{
$hobbies = new Hobby;
$hobbies->name= request('hob')[$i];
$students->hobbies()->save($hobbies);
}
View.blade.php
$students->hobbies()->hob;
But it does not show any hobby. What is the proper solution?

Your entire controller code would be helpful.
In your view $students->hobbies()->hob; you are accessing the property hob of the Collection $students->hobbies(). You want to access the property hob of an element of the Collection $students->hobbies() so you probably want to access $students->hobbies()[0]->hob or loop through the Collection with a foreach.
Accessing $students->hobbies() in your view actually queries your database, so you would be better off setting a $hobbies variable in your controller and passing that to the view, then looking through your variable.
#foreach ($hobbies as $hobby)
{{ $hobby->hob }}<br/>
#endforeach

Related

Laravel Livewire Save to Collection and Show in Component View

I am using Laravel Livewire to choose an item from a dropdown list (which passes an ID), I then find the Model that ID belongs to and I want to add that Model to a collection. Then each additional time I choose something from the dropdown list I want to update the existing collection with that new Model.
public $workoutExercises;
public function mount()
{
$this->workoutExercises = collect([]);
}
public function submitExercise()
{
$newExercise = Exercise::where('id', $this->exercise)->first();
$this->workoutExercises->push($newExercise);
return;
}
In the component view:
#foreach ($workoutExercises as $workoutExercise)
{{ $workoutExercise->exercise_name }}
#endforeach
When I submit a new exercise it adds it to the collection and shows up in my view as intended. However, when I go to add an ADDITIONAL exercise I get this error..."Attempt to read property "exercise_name" on array".
I don't get it. It's like it adds the first one fine, but resorts to an array instead of a collection for any subsequent submissions?
TIA!
Behind the back, Livewire uses all the things like an array, so when the component first loads your $workoutExercises is a collection, but after the first request it turns into an array. What I usually do is create an array of id's selected and query the data as a computed property.
public array $workoutExerciseIds = [];
public function submitExercise(): void
{
array_push($workoutExerciseIds, $this->exercise);
}
public function getWorkoutExecisesProperty()
{
return Exercise::query()
->whereIn('id', $this->workoutExerciseIds)
->get();
}
Then on my front end:
#foreach ($this->workoutExercises as $workoutExercise)
{{ $workoutExercise->exercise_name }}
#endforeach

ManytoMany relations in Laravel, retrieve data from related tables and display in blade

I have two tables related by many to many relation in Laravel Framework. I can display data from each table separately, but not through relation by taking one record from the 1st table and checking related records in the 2nd table. In tinker it accesses data fine.
Relations:
public function underperformances() {
return $this->belongsToMany(Underperformance::Class);
}
...
public function procedures() {
return $this->belongsToMany(Procedure::class);
}
My resource controller part:
...
use App\Underperformance;
use App\Procedure;
...
public function index()
{
$books = Underperformance::orderBy('id','desc')->paginate(9);
$procedures = Procedure::all();
return view('underpcon.underps', compact('books', 'procedures'));
}
Route:
Route::get('/underps', 'UnderpsController#index');
If I try to display data like this:
#foreach($procedures as $procedure)
<li>{{$procedure->underperformances}}</li>
#endforeach
I get such format to the browser:
[{"id":1,"title":"Spare part not taken before service","description":"tekstas","level":"1","costs":600 ...
This is correct data from related table, but I cannot select further the specific column from that table. For example this does not work:
#foreach($procedures as $procedure)
<li>{{$procedure->underperformances->id}}</li>
#endforeach
Nor this one:
#foreach ($procedures->underperformances as $underperformance)
<li>{{$underperformance->id}}</li>
#endforeach
How do I select records of the related table and display specific data from that table?
What would be a conventional way to do this?
#foreach($procedures as $procedure)
<li>{{$procedure->underperformances->id}}</li>
#endforeach
^ This right there $procedure->underperformances will return a collection, not a single item, so you need to treat it as array, you will not be able to access the id directly, you can either #foreach that, or use the pluck method in Laravel Collections.

Laravel Eloquent Nested Relationships. Storing rows in controller variable

I have some working queries that are not ideal and I'd like to try perform them the Eloquent way to tidy it up.
I think I've got the relationships defined correctly but I can't figure out how to write the queries and store them in variables in the controller. I need to return these variables back to the view because I json encode them for use in JavaScript.
Here's what I have in my controller:
public function show($idProject)
{
$project = ProjectsModel::with('user')->where('idProjects','=',$idProject)->first();
$objsettings = ObjSettingsModel::where('idObjSettings','=',$project['ObjSettingsID1'])->first();
$obj = ObjModel::where('idObjs','=',$objsettings['Objs_idObjs'])->first();
return view('project')->with('project',$project)->with('obj',$obj)->with('objsettings',$objsettings);
}
The naming conventions are a bit off so here's what this does.
I pass the $idProject to the controller from a link on my index page where I've looped through and paginated all rows from the Projects table.
The first query finds the project row where it's id (idProjects) matches the variable passed from the index page via the link (idProject). I've also successfully pulled the related user row from the user table using an eloquent relationship.
The next query pulls from an ObjSettings table which stores a number of settings values for an object which is shown on the page. I match the idObjSettings column of the ObjSettings table to the previously pulled $project['ObjSettingsID1'] which is essentially the foreign key in the projects table. There can be several ObjSettings for each Project.
The 3rd query pulls from the Obj table which stores details about an object. These are static details on objects such as name or size for example. I match the idObjs column to the previously pulled $objsettings['Objs_idObjs'] which is the foreign key in the ObjSettings table. One Obj can have many ObjSettings which are used in other Projects.
Here's how I'm passing the php variables to JS:
<script>var obj = #json($obj);</script>
<script>var objsettings = #json($objsettings);</script>
Here are my relationships
ProjectsModel
public function user()
{
return $this->belongsTo('App\User', 'Username', 'id');
}
public function objsettings()
{
return $this->hasMany('App\ObjSettingsModel', 'idObjSettings', 'ObjSettingsID1' );
}
ObjSettingsModel
public function objs()
{
return $this->belongsTo('App\ObjsModel', 'Objs_idObjs', 'idObjs');
}
public function projects()
{
return $this->belongsTo('App\ProjectsModel', 'ObjSettingsID1', 'idObjSettings' );
}
ObjModel
public function objsettings()
{
return $this->hasMany('App\ObjSettingsModel', 'idObjs', 'Objs_idObjs');
}
I've tried a whole range of queries such as:
$project = ProjectsModel::with('user')->with('objsettings.objs')->where('idProjects','=',$idProject)->first();
$objsettings = $project->objsettings;
$obj = $project->objsettings->objs;
but I keep running into issues such as "Property [objs] does not exist on this collection instance." I suppose I'm returning multiple rows in this case? Any help would be appreciated.
You need to loop through objsettings
$project = ProjectsModel::with('user')->with('objsettings.objs')->where('idProjects','=',$idProject)->first();
$objsettings = $project->objsettings;
foreach($objsettings as $objsetting){
$objs = $objsetting->objs;
}

Eloquent to combine data from 2 x tables?

Table Structure:
games
id | name
awards
id | award name | game_id (fk)
Relationships
A game can have many awards.
An award has one game.
class Games extends Model
{
public $timestamps = false;
public function awards()
{
return $this->hasMany('award');
}
}
I need to get all the games out of my database. I do this using:
Game::all();
I then need to get all of the games out of my database but include data from the awards table.
I want to have an array which I can loop through to output the games, and if the game has an award - output this also.
What would be the correct eloquent statement?
Laravel's relations are brilliant for this kind of thing. Everything you have so far is on the correct path.
// Controller
public function index()
{
$games = Game::all();
return view('games.index', compact('games'));
}
// View
#foreach($games as $game)
{{ $game->name }}
#if(count($game->awards) > 0)
// Game has some awards, lets loop through them
#foreach($game->awards as $award)
{{ $award->name }}
#endforeach
#endif
#endforeach
Using the relation you've setup in your Game model you can instantly access the related data from other tables. Now each time you call $game->awards it will query the database, however using Laravel's Eager Loading you can pull all this information out at the same time rather than on demand.
// Controller
public function index()
{
$games = Game::with('awards')->get();
return view('games.index', compact('games'));
}
and by doing the exact same thing in the view you're no longer running a new query each time you want to get a games awards as they've already be fetched from the database. More on eager loading here http://laravel.com/docs/5.0/eloquent#eager-loading

cakephp3.0 query Builder Retrieve data

Hey I am facing some problem I am trying to create a patientcontroller.php in which I want to get data for only one user id from users table so that I can create a dashboard for sngle patient here is my code :
PatientsController.php
<?php
namespace App\Controller;
use App\Controller\AppController;
use Cake\Event\Event;
use Cake\Network\Exception\NotFoundException;
use Cake\ORM\TableRegistry;
class PatientsController extends AppController
{
public function isAuthorized($user)
{
return true;
}
public function index (){
echo $this->Auth->user('id');
$users = TableRegistry::get('Users');
$users->find('all')->where(['id' => 4]);
$this->set('users', $users);
}
I want to get username bio and profile information in my Index.ctp I am trying to pass data using query builder but I am confused so any help
So you have a number of issues with both your approach, techniques and also your code.
Methods
http://book.cakephp.org/3.0/en/controllers.html
If you want to get a single patients record, you should be using the view() method in your controller. So you need to create a new method called view(), in which you can return your record. This method should, in most cases, take an id as the parameter.
Tables
http://book.cakephp.org/3.0/en/orm/table-objects.html
In CakePHP the table which is associated with the controller will be loaded by default. So there is no need to use the TableRegistry to load the table.
Fetching data
http://book.cakephp.org/3.0/en/orm/retrieving-data-and-resultsets.html
When you are looking for a single record you have two choices. You can either just use a find, with a first().
$this->Patients->find()
->where(['id' => $id])
->first();
Or you can use get() which will throw an exception if a record isn't found.
$this->Patients->get($id);
Joining associated data
http://book.cakephp.org/3.0/en/orm/associations.html
If you want to join data to your user, then you'll need Tables to manage that data, which can then be contained, using foreign keys in your database. This will change your finds, to include a contain() call.
$this->Patients->find()
->where(['id' => $id])
->contain(['Profiles])
->first();
Outputting data in the view
You can set the result of your find to the view as you have done, and then you can loop through, or output it how you like, using the variable you've set. In your case $user.
Summary
So overall you can see that there is quite a bit you are missing. Hopefully this will help get you on track.
Given that this is basically your third question here asking for exactly the same thing (getting the results of a query) I will point you to these very useful resources that you should read:
The tutorials: http://book.cakephp.org/3.0/en/tutorials-and-examples.html
They basically have everything you need to understand how queries work and how they can be used in the view and forms.
The ORM manual: http://book.cakephp.org/3.0/en/orm.html
You will find plenty examples of getting data and using it after retrieving it.
I Found A solution for this query : Full code for this kind of problem :
PatientsController.php
<?php
namespace App\Controller;
use App\Controller\AppController;
use Cake\Event\Event;
use Cake\Network\Exception\NotFoundException;
use Cake\ORM\TableRegistry;
class PatientsController extends AppController {
public function isAuthorized($user) {
return true;
}
public function index () {
$id = $this->Auth->user('id');
$articles = TableRegistry::get('Users');
$query = $articles->find()
->where(['id' => $id]);
$this->set(compact('query'));
}
}
For Index.ctp
<!-- File: src/Template/Articles/index.ctp (edit links added) -->
<h1>Patient Dashboard</h1>
I am patient
<?php
foreach ($query as $row) {
echo $row->username ,$row->password;
}
?>
This kind of solution is veryhelpful if you are just trying to move from procedural php to oops in cakephp .

Resources