fetching data through model binding relationship in laravel - laravel

I was trying to get the user's photo src which is stored in the photos table and the photo id is stored in the users' table. My code -
I've written these lines in my User Model
Model - User
public function photo() {
return $this->belongsTo(Photo::class);
}
and my code for printing the photo src -
Route::get("/photo",function() {
$users = User::all();
foreach($users as $user) {
echo $user->photo->file . "<br>";
}
});
It shows an error saying -
Trying to get property 'file' of non-object
On the other hand, I have the same relationship binding which works fine -
In the User Model -
public function role() {
return $this->belongsTo(Role::class);
}
and for printing the role name of the user -
Route::get("/photo",function() {
$users = User::all();
foreach($users as $user) {
echo $user->role->name . "<br>";
}
});
so if the role name is printing by this way why the photo src is not printing

When you're using a Model relationship then you need to do it by calling it in your User::all()->with() method.
Whatever your relation may be it will be it's name will be called inside with() method in order to properly get the required data.
considering the relation ship is done properly you can do it like following:
Model User has the following relation with photos:
public function photo() {
return $this->hasMany(Photo::class);
}
Model Photo has the following relation with User.
public function user(){
return $this->belongsTo(User::class);
}
After this, you can call it inside your Controller
public function get_photo(){
$users = User::all()->with('photo');
return view('example.blade.php,compact('users'));
}
Routes
Route::get('/photo',[Controller::class,'get_photo'])->name('get.photo');
View
Your view can have the foreach loop to iterate through photos
foreach($users as $user) {
echo $user->photo->file . "<br>";
}

Related

Laravel 5 - Defining Two Relationships Between Models

I'm learning Laravel, and really OOP in general. I've followed several YouTube tutorial series, that teach you to create a blog in Laravel.
I'm building a task app for a brewery, and I'm trying to define the relationships between the users and the tasks. So I have two models: User.php and Task.php. I had no problem defining the user in a hasMany tasks relationship, and reciprocally, a task belongsTo a user. Where I'm confused is that I'd like to also have a user belong to the task as well. I have two MySQL columns, one with the heading of "user_id" and the other with "user_assigned_id". What I want is that a user has many tasks, but a task also has one assigned user, the idea being that the user that created the task might assign the task to another user. I've found several tutorials on creating relationships between three models, such as a user owning several messages, but only having one address, so I figured that I could just treat two models as if they were three models and connected the User model back to the Task model in a hasOne relationship, but I'm having a really hard time passing that through to the Controller and View.
Here is the relevant code in each file:
User.php
public function tasks()
{
return $this->hasMany('App\Task');
}
Task.php
public function user()
{
return $this->belongsTo('App\User');
}
// Added an user_assigned_id relationship
public function user_assigned()
{
return $this->hasOne('App\User', 'name', 'user_assigned_id');
}
DashboardController.php
public function index()
{
$user_id = auth()->user()->id;
$now = Carbon::now();
$tasks_assigned = Task::orderBy('date', 'asc')->whereDate('date', '>=', $now)->where('user_assigned_id', '=', $user_id)->user_assigned()->where('name', '=', 1)->get();
$tasks_created = Task::orderBy('date', 'asc')->whereDate('date', '>=', $now)->where('user_id', '=', $user_id)->get();
return view('dashboard')->with('tasks_assigned', $tasks_assigned)->with('tasks_created', $tasks_created);
}
I've gotten a bit turned around in the Controller, so I'm not sure if I messed something up there. Basically, I'm getting results from tasks owned by the logged in user, but not assigned to the logged in user.
You can just add a second relationship defined on your Task.php Model and assign a different agent based on user_assigned_id. You can manipulate it as expected via Eloquent.
Task.php
public function user() {
return $this->belongsTo('App\User');
}
public function assignedUser() {
return $this->belongsTo('App\User', 'user_assigned_id');
}
Then on DashboardController.php
$tasks_assigned = Task::orderBy('date', 'asc')->whereDate('date', '>=', $now)->where('user_assigned_id', '=', $user_id)->get();
should work
public function user()
{
return $this->belongsTo('App\User');
}
// Added an user_assigned_id relationship
public function assignee()
{
return $this->belongsTo('App\User', 'user_assigned_id');
}
The relationship is still a belongsTo, you just need to provide the column where the foreign key is held.
Other files:
User.php
public function ownedTasks()
{
return $this->hasMany('App\Task');
}
public function assignedTasks()
{
return $this->hasMany('App\Task', 'user_assigned_id');
}
Dashboard Controller
public function index()
{
$now = Carbon::now();
$tasks_assigned = Auth::user()->assignedTasks()->where('date', '>=', $now)->get();
$tasks_created = Auth::user()->ownedTasks()->where('date', '>=', $now)->get();
return view('dashboard')->with(compact('tasks_assigned', 'tasks_created'));
}

detach() in pivot table

Can't figure out how to delete record from pivot table.
I have users that belongsToMany documents with pivot document_user table.
here is my attach method:
public function share(Request $request, $company_id, $id)
{
$document = Document::find($id);
$user = $request['user'];
$document->users()->attach($user);
flash('Document has been shared!');
return back();
}
But how to make detach function? Should I build a form for this and what function should be? Something like $document->users()-detach($user). I have tried this, but doesn't work
You can do this in a couple ways:
First, you can use the detach() functionality (requires a second function in your controller). An example using a similar format to the one you provided:
public function unshare(Request $request, $id)
{
$document = Document::findOrFail($id);
$userId = $request['user']; //Assuming this is the User ID
$user = User::findOrFail($userId);
$user->documents()->detach($document->id);
flash('Document has been detached!');
return back();
}
Second, you can create a single function that toggles the association. Essentially you send a Document ID and if it is already associated to the User then it is Detached, if it is NOT associated to the User then it will Attach.
public function share(Request $request, $id)
{
$document = Document::findOrFail($id);
$userId = $request['user']; //Assuming this is the User ID
$user = User::findOrFail($userId);
$user->documents()->toggle($document->id); //This can also be an array of IDs
flash('Document has been toggled!'); //You might want to pass something or look up the association if you want custom messaging for attach or detach
return back();
}
Hope this helps!

Get username from ID

I have a blade template in a Laravel 5.5 app that is returning a user ID integer
I am looking for a way to get the users name from that value within the blade template
The value is just saved in the table and there is no relationship setup, is there a way to get the username without having to set up a relationship?
** UPDATE **
My products controller looks like this...
public function index()
{
$users = User::all();
$products= Product::all();
return view('products.index',compact('products', 'users'));
}
So now I have the users available inside the blade template but now I need to get the user from the id that is contained in produts
In your controller that's passing the user data to the view, you can either pass the entire $user object and print it in your view like {{ $user->name }} or set yourself a variable that holds just the username and pass that in for however you're using it.
I would do the first one though, something like:
public function index()
{
$user = User::where('id',$id)->firstOrFail();
return view('dashboard.index', compact('user'));
}
Or if you're getting all users from the database, an example would be:
public function index()
{
$users = User::all();
return view('dashboard.index', compact('users'));
}
Then in your view you can do
#foreach($users as $user)
{{ $user->name }}
#endforeach
Edit
Since seeing your updated question, you would benefit from making a relationship between your users and your products. So, you would say that a user has many products and that a product belongs to a user.
class User extends Model
{
/**
* Get all of the products for the user.
*/
public function products()
{
return $this->hasMany('App\Product');
}
}
And then
class Product extends Model
{
/**
* Get the user that is assigned to the product
*/
public function user()
{
return $this->belongsTo('App\User');
}
}
Once you have set this up, you can loop through your products and get the username like this:
#foreach($products as $product)
{{ $product->user->name }}
#endforeach
Create helper file: follow this rule to make it : https://laravel-news.com/creating-helpers
and make one function like this:
function getUsername($uerId) {
return \DB::table('users')->where('user_id', $userId)->first()->name;
}
and call this function from your view like this :
{{getUsername($id))}} //it will print user name;
{{\App\User::findOrFail($id)->name}}
Auth::user()->name if user is online. if not you must have controller function like:
$users = User::all();
and in blade
#foerach($users as $user)
{{$user->name}}
#endforeach

Laravel implicit binding with pivot relation on user

I don't think this is possible in Laravel, but I am still going to ask it ;)
I have a Group model that has a pivot relation(via group_user) to User. I have a group controller where this is the index method:
public function index(Request $request)
{
return $request->user()->groups;
}
groups in User is a belongsToMany relation. It will load all groups that have a relation to a user. This will also load the pivot table in the pivot relation.
But now I want to get a single group, this is the controller to get a group with pivot relation:
public function show($id, Request $request)
{
$group = $request->user()->groups()->findOrFail($id);
$this->authorize('view', $group); // Authorization....
return $group;
}
But I would like to use Implicit binding like this:
public function show(Group $group)
{
$this->authorize('view', $group);
return $group;
}
But it won't load the pivot table because I don't get it via the user...
So I should get the group via the user. But how can I do this with implicit binding?
When this isn't possible: How can I load a pivot relation when I already have the group model?
public function show(Group $group, Request $request)
{
// Load the pivot relation here in $group by using the user in $request->user()?
$this->authorize('view', $group);
return $group;
}
Put this is the RouteServiceProvider:
Route::bind('group', function ($value) {
if (auth()->check()) {
return auth()->user()->groups()->findOrFail($value);
} else {
abort(404);
}
});
The view policy isn't even needed this way because the group is from the groups relation:
public function show(Group $group)
{
return $group;
}

hasManyThrough() or similar database model

I have a database setup similar to this:
items
id - integer
user_id - int
users
id - integer
name - string
contacts
id - integer
user_id - integer
name - string
Using Eloquent ORM how would I query for that returns the associated user, and their contacts? I'm currently using
Items::with('user')->get();
Models and relationship:
// User model
class User extends Eloquent {
public function items()
{
return $this->hasMany('Item');
}
public function contacts()
{
return $this->hasMany('Contact');
}
}
// Contact model
class Contact extends Eloquent {
public function user()
{
return $this->belongsTo('User');
}
}
// Item model
class Item extends Eloquent {
public function user()
{
return $this->belongsTo('User');
}
}
Usage:
$items = Item::with('user.contacts')->get(); // Result will be a collection object
$firstItem = $items->first(); // get the first item from collection
// Or this to get first one
$firstItem = $items->get(0); // get the first item from collection
$firstItem->user; // Get related User Model
$firstItem->user->contacts; // get collection of Contact models
If you pass the $items to your view then you may use a loop, for example:
$items = Item::with('user.contacts')->get();
return View::make('viewname')->with('items', $items);
In your view:
#foreach($items as $item)
{{ $item->property_name }}
{{ $item->user->property_name }}
#foreach($item->user->contacts as $contact)
{{ $contact->propertyname }}
#endforeach
#endforeach
It's called loading nested relations - last example on http://laravel.com/docs/eloquent#eager-loading
$items = Items::with('user.contacts')->get();
// then for example:
$item = $items->first();
$item->user; // user Model
$item->user->contacts; // Collection of Contact models
A note: there is no relation to access such relation directly. hasManyThrough won't work in this setup.

Resources