detach() in pivot table - laravel

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!

Related

How to get model id from the global scope

Users are related to each other with many to many relationships.
I have a scope to check if a user is a friend of the user who sends the request.
There is a request that fetches all users.
I need to write a condition in my query to check if the pivot table contains an entry with the friend_id column equals to the id of the querying user. Here is the apply method of my scope:
class IsFriendScope implements Scope
{
public function apply(Builder $builder, Model $model)
{
if (!auth()->check()) return;
$id = $model->id;
$authId = auth()->id();
$builder->selectSub(function (\Illuminate\Database\Query\Builder $query) use ($authId, $id) {
$query->selectRaw("EXISTS(SELECT * FROM friendships WHERE user_id = $authId AND friend_id = $id)");
}, 'is_friend');
}
}
The query does not work, as the $model variable is always null. So what is the way of achieving this goal?
Try this
public function apply(Builder $builder)
{
$model = $builder->getModel();
}

Laravel get value from 2 column with relationship one to one

I have 2 tables and have relationship one to one. Second table use a FK from first one, and I want to display a list with all values .
public function index(Request $request)
{
$listOfPersons = new Person();
$listOfRegisters = new Register();
$listOfRegisters->listOfPersons()->associate();
return $listOfRegisters;
}
In Register Model
public function people(){
return $this->hasOne(Person::class);
}
In Person Model
public function register(){
return $this->hasOne(Register::class);
}
If you just want a list with all pairs of values, it should be enough with this code:
public function index(Request $request)
{
$registers = Register::all();
$list = [];
foreach($registers as $register){
array_push($list,['register'=> $register, 'person'=>$register->people]);
}
return $list;
}
But remember you can just have the list of registers and access the person via the relationship. Moreover, you should change the hasOne relationship to belongsTo in register.
I hope that helps.
I think you have to use leftjoin. (not foreach and php loop)
Because:
The alternative of handling this inside your PHP code with a foreach
loop is unattractive for several reasons. First, you would probably
need to bring in all information from both tables, which is wasteful
from both a memory and network usage point of view. Then, even after
you have brought in the data, you would be relying on PHP to perform
the join. PHP wasn't really designed for in house database operations,
and cannot use something like an index to speed up the process.
So you can write your query like:
User::leftJoin('register', 'register.user_id', '=', 'id');
However, I prefer to add a scope in my model for this situation
<?php
class User extends Authenticatable
{
public function scopeRegister($builder)
{
$query = $query->leftJoin('register', 'register.user_id', '=', 'id');
return $query;
}
and in my controller
public function index(Request $request)
{
$records = User::register()->get();
}

Model Relationships not finding the property

I'm trying to create a relationship between two models. My first model is the User Model, the second one is Company.
I tried adding in the User model the hasMany('App\Comapny') property, and in the Company one, belongsTo('App\User').
// In User Model
public function companies(){
return $this->hasMany('App\Company');
}
// In Company Model
public function user(){
return $this->belongsTo('App\User');
}
// And in the controller:
$user_id = auth()->user('id');
$user = User::find($user_id);
return view('devices.show')->with('companies', $user->companies);
It should return an array with all the companies that my User has when using "$user->comapnies", however, it returns this message instead:
Property [companies] does not exist on this collection instance.
Thanks, any help is welcome
Thanks for the quick response. I figured it out, the problem was this line:
$user_id = auth()->user('id');
It should be instead
$user_id = auth()->user()->id;
Try this,
$user_id = auth()->user->id;
$user = User::with('companies')->where('id', $user_id)->first();
return view('devices.show', compact('user'));
Then you can access the company relation with
$user->company[index]->
in the view.

How to retrieve all related models in a many to many relationship Laravel?

I am trying to retrieve all related models with another model through an intermediary table but can't figure out how. The Laravel docs say you can do something like this:
$roles = App\User::find(1)->roles()->orderBy('name')->get();
But when I try to apply that to my code
$roles = User::where('id', $user->id)->roles()->get();
It does not work. I am accepting the user model through my controller, so I do have access to it.
The relationship is also defined like so:
User
public function roles()
{
return $this->belongsToMany(Role::class);
}
Role
public function users()
{
return $this->belongsToMany(User::class);
}
How can I get all of the roles associated with a particular user?
edit/update:
I know I can simply use a foreach loop and get all of the roles associated with a particular user, but I am trying to return a resource collection, so I cannot do it that way
Try this,
I am assuming that $user_id is the parameter which is passed into the controller from the URL,
$roles=User::findOrFail($user_id)->roles;
But before running the above code, I assume that you have created the pivot table for many to many relationship with columns user_id and role_id. And have named the pivot table as role_user.
Hope this works
the problem with your second approach is calling roles() function on an 'Eloquent Query Builder' instance. You need to make sure to call roles() function on a 'User Model'.
this part of code User::where('id', $user->id) doesn't return a 'User Model'.
To get an 'User Model' from a 'Query Builder' instance you need to call first() function.
possible solution.
$roles = User::where('id', $user->id)->first()->roles;
The reason why you're getting the errors, is because before calling the method first() (or find() or findOrFail()), the instance is a QueryBuilder. and the roles() method exist only on an User::class instance.
if you are trying to get the user with an attribute roles containing a collection (array) of all his roles do:
$user = User::where('id', $user->id)->with('roles')->first();
if you need just the array of roles, you have two choices;
either get the user and then get his roles:
$user = App\User::find($userId);
$roles = $user->roles()->orderBy('name')->get();
//the same as
$roles = App\User::find($userId)->roles()->orderBy('name')->get();
or get the Roles (only one query)
$roles = Role::whereHas('users', function($users) use($userId) {
$users->where('id','=',$userId);
})->get();
Hope this gives you enough insight to build the exact code you need.
User
use App\User;
public function roles()
{
return $this->belongsToMany('App\Users', 'user_id');
}
Role
use App\Roles;
public function users()
{
return $this->belongsToMany('App\Roles');
}
Controller
$roles = User::where('id', $user->id)->roles()->get();
Try this one. I think your relationship is not correct.
You can read more information here Many To Many
You can use the following solution to retrieve all related models in a many to many relationship in Laravel:
$roles = User::where('id', $user->id)->get();
foreach($roles as $rol){
$rol->roles;
}

Saving related records in laravel

I have users, and users belong to a dealership.
Upon user registration, I'm trying to save a new user, and a new dealership.
User database has a dealership_id column, which I want to be populated with the ID of the newly created dealership.
This is my current code in the UserController store method.
public function store()
{
$user = new User();
$user->email = Input::get('email');
$user->password = Input::get('password');
$dealership = new Dealership();
$dealership->name = Input::get('dealership_name');
$user->push();
return "User Saved";
}
Trying to use $user->push(); User data gets updated, but dealership is not created or updated.
Eloquent's push() saves the model and its relationships, but first you have to tell what you want to be involved in the relationsship.
Since your user-model/table holds the id of the dealership, I assume that a user can belong to only one dealership, so the relationship should look like this:
User Model:
public function dealership()
{
return $this->belongsTo('Dealership');
}
Dealership Model:
public function users()
{
return $this->hasMany('User');
}
To save a User from the Dealership perspective, you do this:
$dealership->users()->save($user);
To associate a dealership with a user, you do this:
$user->dealership()->associate($dealership);
$user->save();
Please check this answer to see the difference of push() and save()
You will need to define correctly your models relationships as per documentation
If this is done correctly, it should work .
This is what push() does :
/**
* Save the model and all of its relationships.
*
* #return bool
*/
public function push()
{
if ( ! $this->save()) return false;
// To sync all of the relationships to the database, we will simply spin through
// the relationships and save each model via this "push" method, which allows
// us to recurse into all of these nested relations for the model instance.
foreach ($this->relations as $models)
{
foreach (Collection::make($models) as $model)
{
if ( ! $model->push()) return false;
}
}
return true;
}
In your case, you have a one (dealership) belongs to many (users)
In your Users model :
class Users extends Eloquent {
public function dealership()
{
return $this->belongsTo('Dealership');
}
}
In the example above, Eloquent will look for a dealership_id column on the users table.
In your Dealership Model :
class Dealership extends Eloquent {
public function users()
{
return $this->hasMany('User');
}
}
In your store function :
public function store()
{
$user = new User();
$user->email = Input::get('email');
$user->password = Input::get('password');
$user->dealership = new Dealership();
$user->dealership->name = Input::get('dealership_name');
$user->push();
return "User Saved";
}
Learn here more about eloquent relationships
Also please take a look at my answer here
By using push on the User model, Laravel is basically recursively calling save on all the related models (which, in this case, is none, since you haven't associated any other models to it yet).
Therefore, in order to accomplish what you're trying to do, you can do first create the user then associate the dealership with it by doing the following:
$user = new User();
$user->email = Input::get('email');
$user->password = Input::get('password');
$user->save();
$dealership = new Dealership();
$dealership->name = Input::get('dealership_name');
$user->dealerships()->save($dealership);
return "User Saved";
However, prior to doing this, you must ensure your User and Dealership models have their relationships set up correctly:
User Model:
public function dealership()
{
return $this->belongsTo('Dealership');
}
Dealership Model:
public function users()
{
return $this->hasMany('User');
}
This is how I manage to do it.
In your controller: (Laravel 5)
use Auth;
$dealership->user = Auth::user()->ref_user->staff_id;

Resources