Scope resource controller based on pivot table in Laravel - laravel

I have a User and an Organization model, bound together by a many-to-many relationship in a organization_user pivot table.
The User model contains:
public function organizations()
{
return $this->belongsToMany(Organization::class);
}
And likewise the Organization model contains:
public function users()
{
return $this->belongsToMany(User::class);
}
Organizations are a resource that a user can create, view, update, delete, and so forth. Of course, users should only be able to view, update and delete the organizations they're part of. I manage to scope the organizations to the current user in the OrganizationController index method, but I'm not sure how to do the same for the edit, update and delete methods. Such guards are not necessary for the create and store methods, I believe.
The controller looks like this:
class OrganizationController extends Controller
{
public function index(Request $request)
{
$organizations = $request->user()->organizations()->get();
return view('organizations.index', compact('organizations'));
}
public function create()
{
return view('organizations.create');
}
public function store(Request $request)
{
$request->validate([
'name' => ['required', 'string', 'max:255'],
]);
$request->user()->organizations()->create([
'name' => $request->name,
]);
return redirect()->route('organizations.index');
}
public function edit(Request $request, Organization $organization)
{
// How to make make sure the user is part of the organization?
return view('organizations.edit', [
'organization' => $organization,
]);
}
public function update(Request $request, Organization $organization)
{
// How to make make sure the user is part of the organization?
$request->validate([
'name' => ['required', 'string', 'max:255'],
]);
$organization->update([
'name' => $request->name,
]);
return redirect()->route('organizations.index');
}
}

Related

Undefined method 'posts' inside controller - Laravel

I am getting error for undefined method which is defined inside my User model.
My controller:
$inputs = request()->validate([
'title' => 'required|min:8|max:255',
'post_image' => 'file',
'body' => 'required'
]);
auth()->user()->posts()->create($inputs);
My Post model:
public function user() {
return $this->belongsTo('App\Models\User');
}
My User model:
public function posts() {
return $this->hasMany('App\Models\Post');
}
correct your relationship
public function posts() {
return $this->hasMany(Post::class);
}
First your posts relationship is wrong, it must be hasMany NOT belongsTo
public function posts() {
return $this->hasMany(User::class);
}
Then it should work.
You can also try to create the model in a different way:
$validated = request()->validate([
'title' => 'required|min:8|max:255',
'post_image' => 'file',
'body' => 'required'
]);
// Here you should check if $validated has all required fields
// because some could fail, in that case aren't in the array
Post::create([
'title' => $validated['title'],
'user_id' => auth()->id, // or auth()->user->id
'post_image' => $validated['post_image'],
'body' => $validated['body'],
]);
Laravel Validation Docs

Laravel JetStream get HasRole of user in resource method

I am using Laravel Jetstream teams feature and wants to get list of all team members with their role.
following method from JetStream can return role of user
public function teamRole($team)
{
if ($this->ownsTeam($team)) {
return new OwnerRole;
}
if (! $this->belongsToTeam($team)) {
return;
}
return Jetstream::findRole($team->users->where(
'id', $this->id
)->first()->membership->role);
}
When user hits route /teams/{team} I would like to response with all team members name along with their role in team so I have created a TeamResource like following.
class Team extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'user_id' => $this->user_id,
'owner_name' => $this->owner->name,
'owner_email' => $this->owner->email,
'name' => $this->name,
'personal_team' => $this->personal_team,
'users' => TeamMemberResource::collection($this->allUsers()),
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}
}
Following is my TeamMemberResource which is User model
class TeamMember extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'first_name' => $this->first_name,
'last_name' => $this->last_name,
'role' => //How do I get user's role in this team
'name' => $this->name,
'email' => $this->email,
'active' => $this->active,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
];
}
}
Relationship is User has many Team.
TeamUser table has the column role.
How do I access role of user in given team?
Thank you
The neatest way to do this is to define a separate model for a user within a specific team. Then you don't have to figure out which team you're dealing with. That's probably out of scope for this question, though.
Assuming you want to achieve this using the default models, you need to figure out how to tell the "team member" collection which team it's dealing with.
Start by defining a separate TeamMemberCollection resource. Override the default ResourceCollection constructor, and pass the team as a second argument.
class TeamMemberCollection extends ResourceCollection
{
public $team;
public function __construct($collection, $team)
{
$this->team = $team;
parent::__construct($collection);
}
}
Then update the TeamMember::toArray method to accept a team, and the TeamMemberCollection::toArray method to pass the team.
class TeamMember extends JsonResource
{
public function toArray($request, $team)
{
return [
// Other properties...
'role' => $this->teamRole($team),
];
}
}
class TeamMemberCollection extends ResourceCollection
{
public function toArray($request)
{
return $this->collection
->map
->toArray($request, $this->team)
->all();
}
}
Finally, don't forget to update the Team resource to pass the team to the TeamMemberCollection constructor.
class Team extends JsonResource
{
public function toArray($request)
{
return [
// Other properties...
'users' => new TeamMemberCollection($this->allUsers(), $this),
];
}
}

Update two tables using one function in Laravel

I'm building an app using Laravel 5.7 and Vue.js2. I have two tables: departments and users. A user can be a chief of a department. I made the relationship between the models. I want it so that when I create a new department, the type of the chief will be changed on the user's table to 'chief.'
DepartmentController
public function store(Request $request)
{
$this->validate($request, [
'name' => 'string|required|max:191',
'bio' => 'string|required',
'user_id' => 'integer|required|unique:departements'
]);
return Department::create([
'name' => $request['name'],
'user_id' => $request['user_id'],
'bio' => $request['bio']
]);
}
Can you try this.
Controller
public function store(Request $request)
{
$this->validate($request,[
'name'=>'string|required|max:191',
'bio'=>'string|required',
'user_id'=>'integer|required|unique:departements'
]);
$new_department = Department::create([
'name'=>$request['name'],
'user_id'=>$request['user_id'],
'bio'=>$request['bio']
]);
$get_user = User::where('id', $request['user_id'])->first();
if($get_user)
{
$get_user->type = 'chief';
$get_user->save();
}
return ['message' => 'success'];
}
In this code, After saving the New Department I get the UserData in UserModel where id is the $request['user_id] then check it if exists.
If exists, I change the type to 'chief' and save.
If you have relationship between two models then you can update like this
$product = Department::with('relationship_function_name')->find($id);
$product->fields= $request->input_name;
$product->relationship_function_name->field_name = $request->input_name;
$product->update();
Hope this helps :)

Laravel - Can't upload the user in multiauth system

I am using multi auth login system. I made register, login and mail system. But i don't know how to make update function. Every member needs to update own profile. My problem is i can't get the related users details. id, name, etc...
In my auth.php customer guards was created:
'customer' => [
'driver' => 'session',
'provider' => 'customers',
]
Also this is the CustomerLoginController:
class CustomerLoginController extends Controller{
public function __construct()
{
$this->middleware('guest:customer')->except('logout', 'userLogout');
}
public function showLoginForm(){
return redirect()->route('homepage');
}
public function login(Request $request){
$this->validate($request, [
'email' => 'required|email',
'password' => 'required',
]);
if (Auth::guard('customer')->attempt(['email' => $request->email, 'password' => $request->password], $request->remember)) {
return redirect()->intended(route('homepage'));
}
return redirect('/')->with('error_login', 'Login Fail');
}
public function logout(Request $request) {
Auth::guard('customer')->logout();
return redirect('/');
}
I added the function show($id) and function update(Request $request)
But as i told. Can't get the related user.
My last try is:
$user = Customer::find($id);
this is the right way to doing this i think. But i can't connect them.
ps: i am not using --resources (crud). I must do that manually.

laravel validation custom requested fields

I have used front end is Angular and backend is Laravel,
Create user call store function, it triggers to validate the user request using "UserRequest".
All validation working perfectly.
Now I will update the user record based on the field value change, not all fields.
The UserController update function triggers while updates the record, but not all fields I passed to update. one specific field.
Example:
The requests pass "Age=40" to the only update. but UserRequest validates all the fields and throw the error required fields.
How to I use reuse the request also achieve the output.
// UserController
public function store(UserRequest $request)
{
//TODO...
}
and
// UserRequest
public function rules()
{
return [
'name' => 'required',
'email' => 'required|email',
'age' => 'required|integer|min:15',
];
}
and
// UserController
public function Update(UserRequest $request, User $user)
{
//TODO...
$user->update($request->all());
}
Add sometimes to your rules
public function rules()
{
return [
'name' => 'sometimes|required',
'email' => 'sometimes|required|email',
'age' => 'sometimes|required|integer|min:15',
];
}
This will only validate if the data is present see more https://laravel.com/docs/5.4/validation#conditionally-adding-rules

Resources