Data fetching in a one to many relationship in laravel - php

I want to fetch data from my database but I am stuck when I try to get data from another table.
This is what I want to do, when a user login to the web page, he would be able to see a list of people name. By clicking on their name, user will be redirected to another page which will show the person details such as name, address and email. But because there is so many of them (assuming around 200 people)
Questions:
Q1. how do I redirect the user to another page which is the name (eg: jack, user click on jack name, jack id = 1, how do I relate it back to the user_id = 1 which is the foreign key)
Q2. how do I do a loop to get their information instead of specifying it 1 by 1 (eg: I don't want to keep saying id=1, is there something like id++ which will help auto add)
This is how it looks like with my code: (picture I took from the internet but it something similar to this)
home.blade.php
<table class="table table-bordered">
<tr>
<th><strong><big>Name AS PER NRIC/PASSPORT: </big></strong></th>
</tr>
<td>
<tr>
#foreach($data as $value)
<tr>
<th> {{$value->Name}}</th> --> I don't know how to redirect it to show user details
</tr>
#endforeach
</tr>
</tr>
</table>
Controller
public function index()
{
return view('home');
}
public function getData(){
$data['data'] = DB::table('personal_infos')->get()->sortByDesc('upload_time');
if(count($data)>0){
return view('home',$data);
}else{
return view('home');
}
}
}
Route
Route::get('/test','testController#getData');
personal_info model
class personal_info extends Eloquent
{
protected $fillable = array('Email', 'Name', 'address');
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_info and user_info1 model
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');
}

First add a route like
Route::get('/test/{id}','testController#getPerson')->name("showPerson");
Then setup a redirect
<a href="{{route('showPerson', $value)}}">
Use this line instead of your href="www.google.com"
Make getPerson() from testController return a new page, on that page, print out all the info of a person.
I would also suggest you google Laracast and watch all of the free videos. They're about 30 and they give you a good understanding of the laravel framework

Alter the link of your page to redirect you to the detail page:
<th> {{$value->Name}}</th>
route should be:
Route::get('user/show/{id}','testController#getInfo')->name("user.show");
controller should be:
public function getInfo($id) {
$user_info1 = user_info1::where('user_id',$id)->get();
return $user_info1;//change this with your view
}

Related

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.;)

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>

Getting id from another table in a relationship laravel

I want to get the data from pdf_Files table where it will only show the name of files based on it user_id. I don't really know how to explain it but maybe if you see my codes, you would understand. I have already finish making the relationship between this 2 tables already
I want it to be something like:
DB::table('pdf_files')->where(table:personal_infos->id = pdf_files->user_id)->get(); --> I want it to be something like that but I do not know how to get it
Here is my code:
Controller:
public function downfunc(Request $request){
$downloads=DB::table('pdf_files')->get();
return view('download.viewfile',compact('downloads'));
}
pdfFile model:
protected $fillable = array('file_name','file_size','user_id');
public function personal_infos() {
return $this->belongsTo('App\personal_info', 'user_id', 'id');
}
personal_info model:
class personal_info extends Eloquent
{
protected $fillable = array('Email', 'Name');
protected $table = 'personal_infos';
protected $primaryKey = 'id';
public function pdfFiles() {
return $this->hasMany('App\pdfFile','user_id');
}
}
Are you going to search multiple user ids at once or are you getting the id from the request?
If you are getting the info from the request, you would want to do something like this:
use App\pdfFile; //Put this above the class
pdfFile::where('user_id', $request->user_id)->get(); //If you are checking to see if something equals something else in eloquent, you do not have to use equals

Laravel models and relations tickets with feedback and users

I am trying to grasp the concept of Eloquent ORM by creating a ticketing system at the moment. What I am trying to achieve is:
The tickets with the user who posted the ticket
The feedback belonging to the ticket and the user who entered the
feedback
This is what I have right now:
// TicketController.php
public function index()
{
$tickets = Ticket::with('feedback')->with('user')->orderBy("created_at", "desc")->get();
//dd($tickets);
return View::make('modules.helpdesk.index')->withTickets($tickets);
}
And the following models
// Ticket.php
class Ticket extends Eloquent {
protected $table = 'helpdesk_tickets';
public function feedback()
{
return $this->hasMany('Feedback');
}
public function user()
{
return $this->belongsTo('User');
}
}
// Feedback.php
class Feedback extends Eloquent {
protected $table = 'helpdesk_tickets_feedback';
public function ticket()
{
return $this->belongsTo('Ticket');
}
}
// User.php
class User extends Eloquent {
protected $table = 'users';
public function ticket()
{
return $this->belongsTo('Ticket');
}
}
What I have now is the tickets, their related feedback and user who created the ticket. What I am trying to achieve now is to also get the user who created the feedback.
You need to fix the relation:
// User model
public function tickets()
{
return $this->hasMany('Ticket'); // adjust namespace if needed
}
Next add the relation:
// Feedback model
public function user()
{
return $this->belongsTo('User'); // namespace like above
}
then use eager loading:
// it will execute 4 queries:
// 1st for tickets
// 2nd for feedback
// 3rd for feedbacks' user
// 4th for tickets' user
$tickets = Ticket::with('feedback.user', 'user')->latest()->get();
you can then access the relations in a loop, like below:
#foreach ($tickets as $ticket)
{{ $ticket->title }} by {{ $ticket->user->name }}
#foreach ($ticket->feedback as $feedback)
{{ $feedback->content }}
#endforeach
#endforeach
What you want to do is create nested relations, just like Ticket add a belgonsTo relation on feeback
When you want to use it you can chain relations using the dot notation feedback.user
The code
// Feedback.php
class Feedback extends Eloquent {
protected $table = 'helpdesk_tickets_feedback';
public function ticket()
{
return $this->belongsTo('Ticket');
}
public function user()
{
return $this->belgonsTo('User')
}
}
// TicketController.php
public function index()
{
$tickets = Ticket::with('feedback')->with('user')->with('feedback.user')->orderBy("created_at", "desc")->get();
//dd($tickets);
return View::make('modules.helpdesk.index')->withTickets($tickets);
}
EDIT:
Even though this would work, it will execute more queries than needed. See Jareks answer.
Original Answer:
First of all you need to get your relationships straightened, in User.php you should call the user relationship with HasMany.
public function ticket() {
return $this->hasMany('Ticket');
}
In modules.helpdesk.index you should now have a Ticket Collection since your attaching the $ticket variable to the view.
If you loop through this collection with a foreach loop then what you should get is a model each loop:
foreach($tickets as $ticket) {
// Prints the name property of the Ticket model
print $ticket->name;
// Since a ticket only belongs to ONE user then that means that you are trying to fetch a model
// What we're doing here is getting the User model via the relationship you made in the model Ticket.php and then getting the name.
print $ticket->user()->first()->username;
// Since a ticket can have MANY feedbacks that means were fetching a collection
// which needs to be broken down to models so we do that looping the collection.
// Here we are doing the same thing as with the User model except with a collection.
foreach($ticket->feedback()->get() as $feedback) {
$feedback->text;
}
}
You should definitely check out the Laravel API and see Collection and Model there. http://laravel.com/api/ You get alot of help from there when you get stuck, trust me :)
I hope this answered your question.

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
}

Categories