Steps to reproduce the issue I'm facing
1- Create the Item:
php artisan make:model Item --all
2- Create the resource in web.php:
Route::resource('items', ItemController::class);
3- Then, in the ItemController's constructor, link the ItemPolicy:
public function __construct()
{
$this->authorizeResource(Item::class);
}
4- Return true in all of the ItemPolicy's methods (so you get authorized)
public function view(User $user, Item $item)
{
return true;
}
5- Add SoftDeletes trait in Item model:
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Item extends Model
{
use HasFactory, SoftDeletes;
}
6- Add SoftDeletes in Item migration. Run it.
public function up()
{
Schema::create('items', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->softDeletes();
});
}
7- Write a dd in show method in ItemController to check out if you are actually entering inside the method:
public function show(Item $item)
{
dd('You are inside the show function');
}
8- Create a item in the db and go to GET /items/1. You should see the dd message.
Route::get('/testCreate', function () {
$item = Item::create();
return redirect("/items/$item->id");
});
9- Delete the item. Now, in GET /items/1, the message doesn't appear anymore (instead, I get 404).
Route::get('/testDelete', function () {
$item = Item::firstOrFail();
$item->delete();
return redirect("/items/$item->id");
});
The question
How to enter the show method in GET /items/1 despite the model is soft-deleted?
Notes
Make sure you are logged in
I already checked out this question but I'm not able to make it to work
I also tried to change the show method in the controller to this way ($id instead of Item $item), but anyways I get 404. I'm not entering the method, policy is in the middle and doesn't let me in:
public function show($id)
{
dd($id);
// dd($item);
}
It was as that easy as adding the withTrashed() function at the end of the route resource route defined in routes/web.php file.
Before:
Route::resource('items', ItemController::class);
After:
Route::resource('items', ItemController::class)->withTrashed(['show']);
Related docs here & here.
Update
In an older project I had, despite of doing the explained above, I was getting this error:
Method Illuminate\Routing\PendingResourceRegistration::withTrashed does not exist.
I solved it by updating the project's composer pagackes:
composer update
Now works fine.
I have this method on my User Model.
public function reviews()
{
return $this->belongsToMany(Review::class, 'review_user')->withTimestamps();
}
and its inverse here at Review Model.
public function reviewers()
{
return $this->belongsToMany(User::class, 'review_user')->withTimestamps();
}
They are connected via a pivot table review_user with following structure.
$table->id();
// User ID
$table->unsignedBigInteger('user_id')->nullable();
$table->foreign('user_id')
->references('id')
->on('users');
// Review ID
$table->unsignedBigInteger('review_id')->nullable();
$table->foreign('review_id')
->references('id')
->on('reviews');
$table->timestamps();
The review model has a boolean column status.
What I want is a users all reviews which has a status of true?
I have been able to achieve users all reviews using Auth::user()->reviews()->get();
How can I add a where clause, which can filter by status column ?
You can achieve this by using scope or Defining same Relationship with Extra Where Clause
Using Relation:
public function Activereviews()
{
return $this->belongsToMany(Review::class, 'review_user')
->whereStatus(true)
->withTimestamps();
}
OR Using Scope:
public function scopeActivereviews()
{
return $this->reviews()
->whereStatus(true);
}
Now you can do:
Auth::user()->ActiveReviews()->get();
Hope it helps.
Thanks
Try this code like that, does works
$reviews = auth()->user()->whereHas('reviews', function ($query) {
return $query->where('status', '=', true);
})->get();
And you check the official documentation
like option use documentation
Like all other relationship types, you may call the roles method to continue chaining query constraints onto the relationship:
$roles = App\User::find(1)->roles()->orderBy('name')->get();
I'm building a system where a user can have many teachers (Same User model) and teachers can have many users. When I hit the controller I get:
BadMethodCallException with message 'Call to undefined method App/User::teachers()
Code
Controller
public function requestTeacher()
{
$teacher = User::where(['hashed_id' => 'auserhash123', 'is_teacher' => 1])->first();
$user = auth()->user()->first();
$teacher->notify(new teacherRequest($user));
$user->teachers()->attach($teacher->id);
}
User Model
public function teachers()
{
return $this->belongsToMany('App\User','teacher_approval','user_id','teacher_id');
}
public function clients()
{
return $this->belongsToMany('App\User','teacher_approval','teacher_id','user_id');
}
teacher_approval table
Schema::create('teacher_approval', function (Blueprint $table) {
$table->unsignedInteger('user_id');
$table->unsignedInteger('teacher_id');
$table->unsignedInteger('status')->default(0);
$table->timestamp('decission_date')->nullable();
$table->foreign('user_id')->references('id')->on('users')
->onDelete('cascade');
$table->foreign('teacher_id')->references('id')->on('users')
->onDelete('cascade');
});
Edit:
I wonder if this is because the User is extending SparkUser (I'm using laravel Spark) class User extends SparkUser { }
I have an eloquent many to many relationship and I want to use attach() to easily create role_permissions data but the problem is I'm using an UUID for my ID and it throws an error Field 'id' doesn't have a default value. Any way of hijacking the attach() method? so I can set my UUID?
My migration
Schema::create('role_permissions', function (Blueprint $table) {
$table->increments('count')->unique();
$table->string('id')->unique();
$table->string('role_id');
$table->string('permission_id');
$table->timestamps();
});
My model
class Role extends Model
{
//
public $incrementing = false;
public function users()
{
return $this->belongsToMany('App\User', 'user_roles', 'role_id', 'user_id');
}
public function permissions()
{
return $this->belongsToMany('App\Permission', 'role_permissions', 'role_id', 'permission_id');
}
}
My attach code
$role->permissions()->attach($permission_ids);
I know the problem here is that my id is not an incrementing number it's an unique string. My question is how do I "Inject" that unique string to the attach() method? Thank you guys.
The error
Field 'id' doesn't have a default value
refers to the fact that your database does not know how to fill the id field when it's not specified.
Either you edit the schema adding a nullable:
Schema::create('role_permissions', function (Blueprint $table) {
$table->increments('count')->unique();
$table->string('id')->unique()->nullable(); // Bad idea
$table->string('role_id');
$table->string('permission_id');
$table->timestamps();
});
or injecting it via attach:
$role->permissions()->attach($permission_ids, ["id" => null]);
More info on Laravel official doc
Update
For the future developers who encounter this problem you can also set anything inside the attach array, for example:
$role->permissions()->attach($permission_ids, ["id" => Uuid::generate()]);
Update 2
There's also a more clean way to handle this to be honest. I will try to explain it.
You can handle the Pivot events inside the event service provider by simply hooking into the bootmethod:
Here's a snippet
/App/Providers/EventServiceProvider.php
public function boot()
{
Pivot::creating(function($pivot) {
if ($pivot->getTable() == 'role_permissions') {
$pivot->id = Uuid::generate();
}
});
}
Be aware I do not know if this is actually possible on your laravel version. Mine (5.4.*) works as intended
Okay managed to fixed it, what I did with the help of #Claudio Ludovico Panneta's tip.
foreach($permission_ids as $permission_id)
{
$role->permissions()->attach($permission_id, ["id" => Uuid::generate()]);
}
I am a new of laravel I try to create relationship many to many between table,My problem when I am insert data in to database I got errors
QueryException in Connection.php line 713: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'learn.category_posts' doesn't exist (SQL: insert into category_posts (category_id, posts_id) values (4, ))
can anyone help me pls . and here below is my migrate and code:
2016_08_04_131009_create_table_posts.php
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->increments('id');
$table->text('title');
$table->text('body');
$table->timestamps();
});
}
2016_08_04_131053_create_table_categories.php
public function up()
{
Schema::create('categories', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
}
2016_08_04_131413_create_table_category_posts.php
public function up()
{
Schema::create('category_post', function (Blueprint $table) {
$table->increments('id');
$table->integer('category_id')->unsigned();
$table->integer('post_id')->unsigned();
$table->foreign('category_id')->references('id')->on('categories')->onUpdate('cascade')->onDelete('cascade');
$table->foreign('post_id')->references('id')->on('posts')->onUpdate('cascade')->onDelete('cascade');
$table->timestamps();
});
}
and my model Posts.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Posts extends Model
{
protected $table = 'posts';
public function categories()
{
return $this->belongsToMany('App\Category');
}
}
Category.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
protected $table = 'categories';
public function posts()
{
return $this->belongsToMany('App\Posts');
}
}
My PostsController.php
public function create()
{
$categories = Category::all();
return view('create',compact('categories'));
}
public function store(Request $request)
{
$post = new Posts;
$post->title = $request->title;
$post->body = $request->body;
$post->categories()->attach($request->categories_id);
return redirect()->route('posts.index');
}
My View create.blade.php
{!!Form::open(array('route' => 'store', 'method' => 'POST'))!!}
{{Form::text('title')}}<br>
{{Form::textarea('body')}}<br>
<select name="categories_id" multiple>
#foreach ($categories as $category)
<option value="{{ $category->id }}">{{ $category->name }}</option>
#endforeach
</select>
<br>
{{Form::submit('submit')}}
{!!Form::close()!!}
It seems Laravel is trying to use category_posts table (because of many-to-many relationship). But you don't have this table, because you've created category_post table. Change name of the table to category_posts.
Laravel tries to guess the name of the table, you have to specify it directly so that it does not give you that error..
Try this:
class NameModel extends Model {
public $table = 'name_exact_of_the_table';
I hope that helps!
Schema::table is to modify an existing table, use Schema::create to create new.
The main problem for causing your table unable to migrate, is that you have running query on your "AppServiceProvider.php" try to check your serviceprovider and disable code for the meantime, and run php artisan migrate
You can add this in Post Model,
public function categories()
{
return $this->belongsToMany('App\Category','category_post','post_id','category_id');
}
category_post indicate the table you want to use.
post_id indicate the column where you want to store the posts id.
category_id indicate the column where you want to store the categories id.
For solving your Base Table or view not found error you can do As #Alexey Mezenin said that change table name category_post to category_posts,
but if you don't want to change the name like in my case i am using inventory table so i don't want to suffix it by s so i will provide table name in model as protected $table = 'Table_name_as_you_want' and then there is no need to change table name:
Change your Model of the module in which you are getting error for example:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Inventory extends Model
{
protected $table = 'inventory';
protected $fillable = [
'supply', 'order',
];
}
you have to provide table name in model then it will not give error.
The simplest thing to do is, change the default table name assigned for the model. Simply put following code,
protected $table = 'category_posts'; instead of protected $table = 'posts'; then it'll do the trick.
However, if you refer Laravel documentation you'll find the answer. Here what it says,
By convention, the "snake case", plural name of the class(model) will be used as the table name unless another name is explicitly specified
Better to you use artisan command to make model and the migration file at the same time, use the following command,
php artisan make:model Test --migration
This will create a model class and a migration class in your Laravel project. Let's say it created following files,
Test.php
2018_06_22_142912_create_tests_table.php
If you look at the code in those two files you'll see,
2018_06_22_142912_create_tests_table.php files' up function,
public function up()
{
Schema::create('tests', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
});
}
Here it automatically generated code with the table name of 'tests' which is the plural name of that class which is in Test.php file.
You should change/add in your PostController: (and change PostsController to PostController)
public function create()
{
$categories = Category::all();
return view('create',compact('categories'));
}
public function store(Request $request)
{
$post = new Posts;
$post->title = $request->get('title'); // CHANGE THIS
$post->body = $request->get('body'); // CHANGE THIS
$post->save(); // ADD THIS
$post->categories()->attach($request->get('categories_id')); // CHANGE THIS
return redirect()->route('posts.index'); // PS ON THIS ONE
}
PS: using route() means you have named your route as such
Route::get('example', 'ExampleController#getExample')->name('getExample');
UPDATE
The comments above are also right, change your 'Posts' Model to 'Post'
try checking in the app if you are using the tables before it's created
such as appServiceProvider.php
you might be calling the table without being created it, if you are, comment it then run php artisan migrate.
This problem occur due to wrong spell or undefined database name. Make sure your database name, table name and all column name is same as from phpmyadmin
If you're facing this error but your issue is different and you're tired of searching for a long time then this might help you.
If you have changed your database and updated .env file and still facing same issue then you should check C:\xampp\htdocs{your-project-name}\bootstrap\cache\config.php file and replace or remove the old database name and other changed items.
Just run the command:
php artisan migrate:refresh --seed
If you are getting the error "SQLSTATE[42S02]: Base table or view not found" and you have no problem in your code, check if you have wrote the first letter of the table in capital letter.
Inspections >> inspections
capital case and small case letters matters on AWS environments.