Method Illuminate\Database\Eloquent\Collection::salarylevels does not exist - laravel

I have a many to many relationship between users and salary_levels. All I have is an error stating Method Illuminate\Database\Eloquent\Collection::salarylevels does not exist. The salarylevels method is defined under User model. How could this happen?
User Model:
public function salarylevels(){
return $this->belongsToMany(SalaryLevel::class)->withPivot(['leave_entitlement']);
}
SalaryLevel:
public function users(){
return $this->belongsToMany(User::class)->withPivot(['leave_entitlement']);
}
Store Method:
public function store(Request $request) {
$users = User::where('id',$request->input('employee_id', []))->get();
$Ids = [
1 => ['leave_entitlement' => '30'],
3 => ['leave_entitlement' => '22']
];
$users->salarylevels()->sync($Ids);
}

Your issue is that $users->salaryLevels() is not correct. $users is a Collection because you have done:
$users = User::where('id', $request->input('employee_id', []))->get();
get() returns a Collection, so you should do:
$users = User::where('id', $request->input('employee_id', []))->first();

Related

Counting relations inside a loop

I have a many-to-many relationship between 'forms' and 'fields', on my intermediate table I have an additional column called 'order' so that I can edit the order of fields on a form.
I have this code for adding fields to forms. It takes an array of field ids and then loops through them and attaches them to the form. But once the fields are attached, the order is 0 for both of them when I dd?
I thought on the first iteration of the foreach, order would = 0 and on the second time it would = 1?
Assuming I was adding 2 fields to a form that didn't have any fields before.
public function store(Request $request)
{
$form = Form::findOrFail($request->formId);
foreach($request->fieldIds as $field) {
$form->fields()->attach($field, ['order' => count($form->fields)]);
}
dd($form->fields()->get());
}
I recommend doing it like this:
public function store(Request $request)
{
$form = Form::findOrFail($request->formId);
foreach($request->fieldIds as $order=>$field) {
$form->fields()->attach($field, ['order' => $order]);
}
}
After a bit more trial and error this seems to work.
public function store(Request $request)
{
$form = Form::findOrFail($request->formId);
foreach($request->fieldIds as $field) {
$form->fields()->attach($field, ['order' => $form->fields()->count()]);
}
}
try this here:
public function store(Request $request)
{
$form = Form::findOrFail($request->formId);
foreach($request->fieldIds as $field) {
$form->fields()->attach($field, ['order' => $form->fields()->get()->count()]);
}
}

Laravel: getting data from index method in a controller with pagination or without pagination

I am using paginate() method to get paginated data in index method in controller but sometimes I need whole data so I wrote code like this.
public function index(Request $request)
{
if ($request->page === 'all') {
$posts = Post::all();
} else {
$posts = Post::paginate(10);
}
return response([
'posts' => $posts
], Response::HTTP_OK);
}
So if I want to get all data I send page value as all.
If I want paginated data I send page value as integer.
It works fine but just wondering if there are any other better way to do this?
You can further simplify the code you're using.
public function index(Request $request)
{
$page = $request->page;
return response([
'posts' => $page === 'all' ? Post::all() : Post::paginate($page)
], Response::HTTP_OK);
}
Avoid load several time of model instance.
public function index(Request $request)
{
$post = Post::query();
$data = ($request->page === 'all') ? $post : $post->paginate(10);
return response()->json(['posts' => $data], 200);
}

Create new Post with default Category belongsToMany

I have a Post/Category manyToMany relations and would like to be able to attach a default category named "Uncategorised" to each new post that is created. How can I do that? A BelongsToMany method only works on the Details page, not on Create page.
BelongsToMany::make(__('Categories'), 'categories', Category::class),
You can also set default value to your database field so that you can omit passing category and will be taken default to Uncategorised like if you are using MySQL you can do it this way by creating migration
$table->text('category')->default(0);
Because the BelongsToMany not show on mode create in Post Nova model. So we have to make our custom Select, by add this code to your fields:
public function fields(Request $request)
{
if($request->editMode=="create"){
$categories = \App\Category::get(['id','name']);
$options = [];
foreach($categories as $value){
$options[$value->id] = $value->name;
}
return [
ID::make()->sortable(),
Text::make('Title'),
Text::make('Summary'),
Textarea::make('Content'),
Select::make('Categories', 'category_id')
->options($options)
->displayUsingLabels()
->withMeta(['value' => 1]) // 1 = id of Uncategorised in categories table
];
}
return [
ID::make()->sortable(),
Text::make('Title'),
Text::make('Summary'),
Textarea::make('Content'),
BelongsToMany::make('Categories','categories')->display('name'),
];
}
Don’t forget relationship function in both, Post and Category model:
class Post extends Model
{
public function categories(){
return $this->belongsToMany(Category::class, 'category_post', 'post_id', 'category_id');
}
}
And:
class Category extends Model
{
public function posts(){
return $this->belongsToMany(Post::class,'category_post', 'category_id', 'post_id');
}
}
Then, custom the function process the data on mode Create of Post resource page, it’s at nova\src\Http\Controllers\ResourceStoreController.php, change function handle to this:
public function handle(CreateResourceRequest $request)
{
$resource = $request->resource();
$resource::authorizeToCreate($request);
$resource::validateForCreation($request);
$model = DB::transaction(function () use ($request, $resource) {
[$model, $callbacks] = $resource::fill(
$request, $resource::newModel()
);
if ($request->viaRelationship()) {
$request->findParentModelOrFail()
->{$request->viaRelationship}()
->save($model);
} else {
$model->save();
// your code to save to pivot category_post here
if(isset($request->category_id)&&($resource=='App\Nova\Post')){
$category_id = $request->category_id;
$post_id = $model->id;
\App\Post::find($post_id)->categories()->attach($category_id);
}
}
ActionEvent::forResourceCreate($request->user(), $model)->save();
collect($callbacks)->each->__invoke();
return $model;
});
return response()->json([
'id' => $model->getKey(),
'resource' => $model->attributesToArray(),
'redirect' => $resource::redirectAfterCreate($request, $request->newResourceWith($model)),
], 201);
}
}
All runs well on my computer. A fun question with me! Hope best to you, and ask me if you need!
What I ended up doing was saving the data on Post Model in boot().
public static function boot()
{
parent::boot();
static::created(function (Post $post) {
$post->categories()->attach([1]);
});
}

Getting all posts from a user

I'm really new to Laravel and ran it some problems. I have a /user/USERNAME view, which obviously, shows the users profile. But now I want to get ALL posts the user posted to be shown on his profile.
My web.php
Route::group(['middleware' => 'auth'], function() {
Route::any('/user/{username}', [
'as' => 'user',
'uses' => 'UserController#view_user'
]);
});
My User model
public function posts() {
return $this->hasMany(Post::class);
}
My Post model
public function user() {
return $this->belongsTo(User::class);
}
My UserController
public function view_user($username = null) {
$user = null;
$user = User::where('name', $username)->firstOrFail();
$posts = Post::where('creator', $username)->get();
return view('/user', [
'user' => $user,
'posts' => $posts
]);
}
public function index() {
$posts = Post::all();
return view('user', compact('posts'));
}
When I'm trying to get the posts with for example {{ $posts->title }} it gives me: Property [title] does not exist on this collection instance.
How am I supposed to do this the correct way?
$posts returns a collection, so in order to retrieve the title of a post you need to loop through the single items of the collection. Then you can use $post->title.

Laravel : Call to undefined method Illuminate\\Database\\Query\\Builder

On query get the error with undefine method. Simply i want to get data from two tables query look linke
public static function userDetail($id){
$result = User::whereHas('user_details', function ($query) {
$query->where('user_details.user_id',$id);
})->first();
return $result ;
}
Relationship
On Model User define relationship
public function userDetails()
{
return $this->hasOne(UserDetails::class);
}
and in userDetails model
public function user()
{
return $this->belongsTo(User::class);
}
just change
public static function userDetail($id){
$result = User::whereHas('user_details', function ($query) use($id) {
$query->where('user_id',$id);
})->first();
return $result ;
}
If you dont need to use static, you can use this $result value on userDetails
public function userDetail($id){
$result = userDetails::where('user_id', '=', $id)->first();
return $result ;
}
Then the result can get access to the user from the vale by using $value->user->{user property}

Resources