I'm using Laravel 8 to create an API and ran into a rather troubling problem.
When calling the create command Laravel can't find the right table and outputs an error.
IlluminateDatabaseQueryException: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'homestead.user' doesn't exist (SQL: select count(*) as aggregate from `user` where `email` = [email protected]) in file /home/vagrant/code/feniks/vendor/laravel/framework/src/Illuminate/Database/Connection.php on line 678
The error output is correct, as the tablename is actually homestead.users. I've seen some questions posted about Laravel automatically adding an 's' to the end of a table when automatically looking for one, but as this seems to be the other way around, I couldn't find any solutions. The weird part is that every other command; update, show, index and destroy do find the right table. Some other question's answers gave the solution of setting the table name manually in the model like this:
protected $table = 'users';
However, this doesn't seem to change anything.
Here is the User Model that I use:
class User extends Authenticatable
{
use Notifiable, HasApiTokens, SoftDeletes, HasFactory;
protected $table = 'users';
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'first_name', 'last_name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
/**
* @return HasMany
*/
public function memberships() : hasMany
{
return $this->hasMany(Membership::class, 'user_id');
}
}
As well as the controller method handling the API call:
public function store(): Response
{
if (!$object = $this->model->create($this->inputStore()))
{
return ResponseBuilder::error(409);
}
return ResponseBuilder::success($object, 201);
}
Here is a working destroy() method to compare with:
public function destroy(): Response
{
foreach (request()->except('membership') as $item)
{
if($object = $this->model->find($item))
{
$object->delete();
$this->success[] = $object;
}
else
{
$this->failed[] = $item;
}
}
if($this->failed)
{
return ResponseBuilder::error( 404,[],['failed' => $this->failed,'success' => $this->success]);
}
return ResponseBuilder::success($this->success, 200);
}
The inputStore() method is just a fancy way of validating data, but if it proves to be useful, here it is:
protected function inputStore($attributes = []): array
{
if (!empty($attributes))
{
foreach ($attributes as $attribute => $value)
{
request()->merge([
$attribute => $value
])->except('membership');
}
}
return request()->validate([
'email' => 'required|email|unique:user',
'password' => 'required|max:255',
'first_name' => 'string|max:255',
'last_name' => 'string|max:255',
'dob' => 'date',
'phone' => 'string|max:255',
'language' => 'string|max:8',
]);
}