How to retrieve data with many to many relationship in Laravel resource - laravel

I am using Laravel 7.
I have three table with many to many relationship. The tables are users, task_user and tasks.
The models have the following relationships:
Task.php:
public function users()
{
return $this->belongsToMany('App\User')
->withPivot('user_id', 'task_id')
->withTimestamps();
}
TaskUser.php:
public function task()
{
return $this->belongsTo('App\Task');
}
public function user()
{
return $this->belongsTo('App\User');
}
User.php:
public function tasks()
{
return $this->belongsToMany('App\Task')
->withTimestamps();
}
This is my controller method:
public function get_delayed_tasks() {
$tasks = Task::select('id', 'name', 'description', 'deadline', 'closed_at', 'status_id', 'project_id')
->whereRaw('closed_at > deadline')
->get();
return TaskResource::collection($tasks);
}
This is my resource:
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'description' => $this->description,
'deadline' => $this->deadline,
'closed_at' => $this->deadline,
'status' => $this->status->name,
'project' => $this->project->name,
'devs' => $this->relationLoaded('users')
? $this->users->pluck('users.name')->unique()->all()
: [], //problem
];
}
Unfortunately in the key dev in the resource I receive always [], even if I should receive an array of names.
How can I retrieve all the users that have worked with the task?

You have to load the relationship to use it within the resource
Controller
public function get_delayed_tasks() {
$tasks = Task::with(['users']) // <-- load relationship
->select('id', 'name', 'description', 'deadline', 'closed_at', 'status_id', 'project_id')
->whereRaw('closed_at > deadline')
->get();
return TaskResource::collection($tasks);
}
Resource
'devs' => $this->whenLoaded(
'users',
$this->users->pluck('name')->unique()->all(),
[]
)
Advanced modification for the Resource, if you decide to create a UserResource to get more data:
'devs' => UserResource::collection($this->whenLoaded('users'))

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

Attempt to read property "id" on null - Laravel 8

I have problem with this error. I made relationship between :
Meals-Category (hasOne)
Meals-Ingredients (hasMany)
Meals-Tags (hasMany)
Everything is normal with seeding, but when I want to open on endpoint, this messege shows :
"Attempt to read property "id" on null"
Here is my code from Meals Resources, Model and Controller :
Resource:
class Meals extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'title' => $this->title,
'description' => $this->description,
'status' => $this->deleted_at > 0 ? 'deleted' : 'created',
'category' => [
'id' => $this->category->id,
'title' => $this->category->title,
'slug' => $this->category->slug,
],
'tags' => TagsResource::collection($this->tags),
'ingredients' => IngredientsResource::collection($this->ingredients),
];
}
}
Model:
class Meals extends Model
{
use SoftDeletes;
use HasFactory;
protected $fillable = ['title', 'description'];
protected $dates = ['deleted_at'];
public function category()
{
return $this->hasOne(Category::class, 'meals_id');
}
public function tags()
{
return $this->hasMany(Tag::class, 'meals_id', 'id');
}
public function ingredients()
{
return $this->hasMany(Ingredient::class, 'meals_id', 'id');
}
}
Controller:
public function index()
{
$meals = Meals::with('category', 'tags', 'ingredients')->get();
return MealsResource::collection($meals);
}
your error means that $this->category is null
assign the category attribute like this :
'category' => $this->load('category')

Unique Rule for two fields failed in Laravel

In my Laravel-5.8, I have this model:
class HrDepartment extends Model
{
public $timestamps = false;
protected $table = 'hr_departments';
protected $fillable = [
'company_id',
'dept_name',
];
public function company()
{
return $this->belongsTo('App\Models\Organization\OrgCompany', 'company_id');
}
}
I tried to use Request Rules
Rules
class StoreDepartmentRequest extends FormRequest
{
public function authorize()
{
return \Gate::allows('department_create');
}
public function rules()
{
return [
'dept_name' => [
'required',
'string',
'min:2',
'max:80',
Rule::unique('hr_departments', 'dept_name', 'company_id')
],
];
}
public function messages()
{
return [
'dept_name.max:80' => 'Department Name cannot be more than 80 characters.',
'dept_name.unique' => 'Department Name already exists.',
'dept_name.required' => 'Please enter the Department Name.',
];
}
}
Controller
public function store(StoreDepartmentRequest $request)
{
$department = HrDepartment::create([
'dept_name' => $request->dept_name,
'company_id' => Auth::user()->company_id,
]);
Session::flash('success', 'Department is created successfully');
return redirect()->route('hr.departments.index');return redirect()->route('hr.departments.index');
}
}
I entered dept_name, Services for company 1, when I entered Services for company 2, I got this error:
'Department Name already exists.',
Why and how do I resolve it?
Thanks
use this code for unique validation
Rule::unique('hr_departments')->ignore($hr_department->id)

How to handle nested relation in laravel resource - 2

So I've been trying to get a second level relation out of my "CategoryResource" but it's not working, here is some of my code :
First, My model :
public function children()
{
return $this->hasMany(Category::class, 'parent_id', 'id');
}
public function sub_children()
{
return $this->hasMany(Category::class, 'parent_id');
}
and then the "CategoryResource" :
$data = [
'id' => $this->id,
'parent_id' => $this->parent_id,
'order' => $this->order,
'name' => $this->name,
'slug' => $this->slug,
'childs' => CategoryResource::collection($this->whenLoaded('children') && $this->whenLoaded('children')),
'created_at' => (string) $this->created_at,
'updated_at' => (string) $this->updated_at,
];
My Controller
return CategoryResource::collection(Category::where('parent_id',null)->with('children.sub_children')->get());
Is there anyway i can retrieve my nested relation through laravel resource ?
You could use with function in the relationship. It would be something like this:
public function children()
{
return $this->hasMany(Category::class, 'parent_id', 'id')
->with('children');
}
It is going to load the children and then "subChildren" as relations of the first object.
So, you are going to load it as:
$children = $originalObject->children;
foreach ($children as $c) {
$subChildren = $c->children;
}
Check if this works for your problem.

Error storing Topic Model into the database using Sentinel

I have a small forum, im trying to create topic and replies for the store method.
routes.php
Route::get('board/{id}/create', 'TopicsController#create');
Route::post('board/{id}/create', 'TopicsController#store');
TopicsController.php
public function store()
{
$this->request->user()->topics()->create([
'board_id' => $this->request->id,
'title' => $this->request->title,
'body' => $this->request->body
]);
return redirect(url('/board/' . $this->request->id));
}
I am receiving this error.
Call to a member function topics() on null
Also note, i am using Sentinel https://github.com/rydurham/Sentinel from this repo.
<?php namespace App\Models;
class User extends \Sentinel\Models\User
{
protected $fillable = ['email', 'first_name', 'last_name'];
protected $hidden = ['password'];
public function topics()
{
return $this->hasMany(Topic::class);
}
public function replies()
{
return $this->hasMany(Reply::class);
}
public function getGravatarAttribute()
{
$hash = md5(strtolower(trim($this->attributes['email'])));
return "https://www.gravatar.com/avatar/$hash";
}
}
Updated Model
public function store($id)
{
$user = Sentry::getUser($id);
$user->topics()->create([
'board_id' => $this->request->id,
'title' => $this->request->title,
'body' => $this->request->body
]);
return redirect(url('/board/' . $this->request->id));
}
It seems that your user object is null. Properly retrieve the user using the id
public function store($id)
{
$user = \App\Models\User::find(\Sentinel::getUser()->id);
$user->topics()->create([
'board_id' => $this->request->id,
'title' => $this->request->title,
'body' => $this->request->body
]);
return redirect(url('/board/' . $this->request->id));
}

Resources