Laravel, Call to a member function sync() on null - laravel

I have a FatalThrowableError in my laravel projects - Call to a member function sync() on null. Debuger show mi, that is this line of code
Post::findOrFail($post_id)->tags()->sync([1, 2, 3], false);
Complete method this line look like:
public function store(Request $request)
{
// validate a post data
$this->validate($request, [
'title' => 'required|min:3|max:240',
'body' => 'required|min:50',
'category' => 'required|integer',
]);
// store post in the database
$post_id = Post::Create([
'title' => $request->title,
'body' => $request->body,
])->id;
Post::findOrFail($post_id)->tags()->sync([1, 2, 3], false);
// rediect to posts.show pages
return Redirect::route('posts.show', $post_id);
}
My Post model its looks like
class Post extends Model
{
protected $fillable = [ ... ];
public function category() {...}
public function tags()
{
$this->belongsToMany('App\Tag', 'post_tag', 'post_id', 'tag_id');
}
}
And my Tag model its look like
class Tag extends Model
{
protected $fillable = [ ... ];
public function posts()
{
return $this->belongsToMany('App\Post', 'post_tag', 'tag_id', 'post_id');
}
}
Thanks for yours anser!

The error states that you're calling sync() on a null object, which means the result of your tags() method is null.
If you take a look at your tags() method, you can see that you forgot to return the relationship, therefore it is returning null. Add the return keyword and you should be good.
public function tags()
{
return $this->belongsToMany('App\Tag', 'post_tag', 'post_id', 'tag_id');
}

Try this
// store post in the database
$post = new Post([
'title' => $request->title,
'body' => $request->body,
]);
$post->save();
$post->tags()->sync([1, 2, 3], false);

Related

Howto reusing Form Request inside loop

I am making a "/bulk" endpoint for my API/REST made in Laravel 8.
My problem is that I don't know how to reuse the same FormRequest that I have for the create or update
json post to: /cars/bulk
{
"cars": [{"model": "A", "year": 2021, "plate": "AA11BB"},{"model": "B", "year": 2021, "plate": "AA12BB"},{"model": "C", "plate": "AA13BB"}]
}
// CarController.php
public function store(CarRequest $request)
{
$car = $this->carService->store($request, Car::class);
}
public function update(CarRequest $request, Car $car)
{
$this->carService->update($request, $car);
}
public function bulk(Request $request)
{
$this->carService->bulk($request);
}
// CarService.php
public function store($request, $modelClass)
{
# My code....
}
public function update($request, $model)
{
# My code....
}
public function bulk($request)
{
foreach ($request->cars AS $carData )
{
$car = Car::where('plate','=',$carData->plate)->first()
# here is the problem,
# howto validate each $car by reusing CarRequest
if ($car){
$this->update($carData, $car);
} else {
$this->store($carData, Car::class);
}
}
}
This is de form request for each item, i have use to for bulk or one request
class CarRequest extends BaseRequest
{
public function authorize()
{
$this->setModel(Car::class);
return $this->isAuthorized();
}
public function rules()
{
$this->setModel(Car::class);
$rules = parent::rules();
$rules = [
'model' => 'required',
'year' => 'required|numeric',
'plate' => 'required'
];
return $rules;
}
public function messages()
{
# multiples messages
}
}
I need reuse my request
Edit: add form request
So I wouldn't suggest using it within a loop how you have in your example, what would be better would be to create a second, bulk request that valiates an array like this.
public function rules()
{
$this->setModel(Car::class);
$rules = parent::rules();
$rules = [
'cars' => ['required', 'array'],
'cars.*.model' => 'required',
'cars.*.year' => 'required|numeric',
'cars.*.plate' => 'required'
];
return $rules;
}
You can do it with same CarRequest form request class as follows.
public function rules()
{
return[
'cars.*.model' => 'required',
'cars.*.year' => 'required',
'cars.*.plate' => 'required',
];
}
Laravel will expect that you are sending nested array. If you dont want to mix it up with CarRequest you can do it with creating another FormRequest class.

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)

Laravel: "Trying to get property 'comments' of non-object"

I setup an api resource collection for the post model, called PostCollection. I have a problem with my comments query for a post. Getting non-object for $comments. The comment table currently has no records.
$author = \App\Post::find(1);
$comments = \App\Post::find(1)->comments;
return [
'id' => $this->id,
'user_id' => $this->user_id,
'description' => $this->description,
'media' => $this->media,
'media_type' => $this->media_type,
'likes' => $this->likes,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
'author_avatar' => $author->setting->user_profile_photo,
'author_profile_name' => $author->name,
'author_user_name' => $author->setting->user_name,
'visible' => true,
'comments' => $comments,
];
In the post model, I have:
public function user()
{
return $this->belongsTo(User::class);
}
public function comments()
{
return $this->hasMany(Comment::class);
}
In the comment model I have:
public function user()
{
return $this->belongsTo(User::class);
}
public function post()
{
return $this->belongsTo(Post::class);
}
You should this
public function comments()
{
return $this->hasMany('App\Comment', 'foreign_key', 'local_key');
}
in your controller
$post = \App\Post::find(1);
$comments = $post->comments;

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

Validation request with Laravel 5

I am trying to make validation with Laravel 5 on right way:
Here is my working code in model:
public function apiAddNewComment() {
if (Input::get("task") == 'addComment') {
$user = Auth::id();
$inputs = array(
'comment' => Input::get('comment'),
'projectID' => Input::get('projectID'),
'order' => Input::get("order"),
'level' => Input::get("level"),
);
$rules = array(
'comment' => 'required|between:15,600',
'projectID' => "required|exists:project_group,project_id,user_id,$user|numeric",
'order' => "required|numeric",
'level' => "required|numeric"
);
$validator = Validator::make($inputs, $rules);
if ($validator->fails()) {
return json_encode(array('err' => true, 'errors' => $validator->messages()->all()));
} else {
return $this->createNewComment();
}
}
}
here is my controller:
public function update($id, Comment $update)
{
return $update->apiUpdateComment();
}
How can I make validation with request?
And can someone explain me how this method works inside request:
public function authorize()
{
return false;
}
?
The Request has to basic functions: rules() and authorize()
rules returns an array that is used for the validation.
The authorize method can for example check if the user is allowed to do this request.
public function authorize() {
return Auth::check();
}
So you don't have to check it each time when you use the request in a controller.
If you need no check just return true.
UPDATE:
Generate a request File with artisan
php artisan make:request CommandRequest
then edit the generate file like this:
class CommandRequest extends FormRequest
{
public function rules()
{
return [
'comment' => 'required|between:15,600',
'projectID' => "required|exists:project_group,project_id,user_id,$user|numeric",
'order' => "required|numeric",
'level' => "required|numeric"
];
}
public function authorize()
{
return true;
}
}
Also update the controller method:
public function update($id, Comment $update, CommandRequest $request)
{
// create your comment here like:
return Comment::create($request->all());
}
You are using a Laravel 4 code I guess, you need to translate it to L5 where Input::get('var') turns into $request->input('var') for instance:
public function apiAddNewComment(Illuminate\Http\Request $request) { //Remember to add the Request as a parameter of the method
if ($request->input("task") == 'addComment') {
...
Then the validation part looks fine

Resources