Laravel - SQLSTATE[42S22]: Column not found: 1054 Unknown column [closed] - php

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
Hello im getting this error Illuminate\Database\QueryException with message 'SQLSTATE[42S22]: Column not found: 1054 Unknown column 'posts.user_id' in 'where clause' (SQL: select * frompostswhereposts.user_id= 1 andposts.user_idis not null)' and I don't know why if in my database I don't have user_id, I have id_user...
This is my migration table
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateUsersTable extends Migration
{
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('user')->unique();
$table->string('email')->unique();
$table->string('password', 60);
$table->string('img');
$table->rememberToken();
$table->timestamps();
});
}
public function down()
{
Schema::drop('users');
}
}
This other is my posts migration archive
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddPosts extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->increments('id');
$table->string('nombre');
$table->longText('contenido');
$table->unsignedInteger('id_user');
$table->timestamps();
});
Schema::table('posts', function($table) {
$table->foreign('id_user')->references('id')->on('users');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('posts');
}
}
this is my Post model
<?php
namespace NacionGrita;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
protected $table = "posts";
protected $fillable = ['nombre', 'contenido', 'id_user'];
public function imagenes() {
return $this->belongsToMany('NacionGrita\Imagen');
}
public function categorias() {
return $this->belongsToMany('NacionGrita\Categoria');
}
public function tags() {
return $this->belongsToMany('NacionGrita\Tag');
}
public function user() {
return $this->belongsTo('NacionGrita\User');
}
}
and this is my users Model
<?php
namespace NacionGrita;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Model
{
protected $table = "users";
protected $fillable = [
'user', 'email', 'password', 'img'
];
public function posts() {
return $this->hasMany('NacionGrita\Post');
}
protected $hidden = [
'password', 'remember_token',
];
}
If I change my "posts" table column from id_user to user_id it works but I don't know why I have to change the column name if its supposed to works because I specified the foreigns keys or Im doing something wrong?
Thanks for help

In order to specify the foreign keys, you need to do so in the model when you define the relationships.
From the docs for a belongsTo relationship:
In the example above, Eloquent will try to match the user_id from the Phone model to an id on the User model. Eloquent determines the default foreign key name by examining the name of the relationship method and suffixing the method name with _id. However, if the foreign key on the Phone model is not user_id, you may pass a custom key name as the second argument to the belongsTo method
In other words, in your Post model where you define the relationship with the User, you need to add a second argument that specifies the foreign key name:
public function user() {
return $this->belongsTo('NacionGrita\User', 'id_user');
}
From the docs for a hasOne and hasMany relationship:
Eloquent assumes the foreign key of the relationship based on the model name. In this case, the Phone model is automatically assumed to have a user_id foreign key. If you wish to override this convention, you may pass a second argument to the hasOne method:
In other words, in your User model where you define the relationship with the Post, you need to once again add a second argument that specifies the foreign key name:
public function posts() {
return $this->hasMany('NacionGrita\Post', 'id_user');
}
Link to docs: https://laravel.com/docs/5.1/eloquent-relationships

Related

Laravel Sanctum with uuid column in User model doesn't save tokenable_id

I'm try to use Laravel 8.x and Laravel sanctum 2.14.2 to authenticate my API and UUIDs as the primary key for my User model.
My custom PersonalAccessToken model
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Laravel\Sanctum\PersonalAccessToken as SanctumPersonalAccessToken;
class PersonalAccessToken extends SanctumPersonalAccessToken
{
use HasFactory;
protected $table = 'personal_access_tokens';
public function tokenable()
{
return $this->morphTo('tokenable', "tokenable_type", "tokenable_id", "uuid");
}
}
My personal_access_tokens migration schema
...
public function up()
{
Schema::dropIfExists('personal_access_tokens');
Schema::create('personal_access_tokens', function (Blueprint $table) {
$table->id();
$table->uuidMorphs('tokenable');
$table->string('name');
$table->string('token', 64)->unique();
$table->text('abilities')->nullable();
$table->timestamp('last_used_at')->nullable();
$table->timestamps();
});
}
...
My AppServiceProvider
...
use App\Models\PersonalAccessToken;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\ServiceProvider;
use Laravel\Sanctum\Sanctum;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* #return void
*/
public function register()
{
Sanctum::ignoreMigrations();
}
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
if($this->app->environment('production')) {
URL::forceScheme('https');
}
Sanctum::usePersonalAccessTokenModel(PersonalAccessToken::class);
}
}
When I try to get the token with $user->createToken($user->email)->plainTextToken, I get this error:
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'tokenable_id' cannot be null (SQL: insert into `personal_access_tokens` (`name`, `token`, `abilities`, `tokenable_id`, `tokenable_type`, `updated_at`, `created_at`) values (admin#gmail.com, 85dbe44c32a999a01f4a97d9c9eab0710125a6ac5f861ab546a5822f61015b23, [\"*\"], ?, App\\Models\\User, 2022-03-20 19:16:43, 2022-03-20 19:16:43))
I think the cause of the error is that I am using uuid as the primary key in the users table
Schema::create('users', function (Blueprint $table) {
$table->uuid('uuid')->primary();
...
});
UPDATE
My User Model
...
class User extends Authenticatable
{
use HasUUID;
use HasApiTokens;
use HasFactory;
use Notifiable;
use HasRoles;
...
public function tokens()
{
return $this->morphMany(Sanctum::$personalAccessTokenModel, 'tokenable', "tokenable_type", "tokenable_id");
}
...
}
Any help would be appreciated.
Is there any particular reason for you to create custom PersonalAccessToken model?
If it's just UUID that you want for the primary key of your User model, you can achieve it without creating the custom PersonalAccessToken model.
Your personal_access_tokens migration schema seems fine.
I think the cause of the error is that I am using uuid as the primary
key in the users table
Schema::create('users', function (Blueprint $table) {
$table->uuid('uuid')->primary();
...
});
This could be the issue. Try changing the column name to just id from uuid and see if it works
$table->uuid('id')->primary();
If you must use the column name as uuid for primary key, then try adding the following to your User model
protected $primaryKey='uuid'
By default eloquent assumes the name of the primary key column as 'id'. This will let eloquent know to look for 'uuid' as primary key column for User model.
Also since you are not using the default integer data type for primary key make sure you have the following in your User model
public $incrementing=false
protected $keyType='string'
You can refer to Laravel Documentation for
Primary Keys
Sorry for late reply. I answer with the solution for anyone who is having the same problem as above.
The problem is in my UUId Traits. We should use boot magic method as Laravel suggested when we want to create our own Traits.
Solution:
Using App\Traits\HasUUID with the correct code
<?php
namespace App\Traits;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
trait HasUUID
{
/**
* Boot functions from Laravel.
*/
// protected static function boot() <- This line is INCORRECT
protected static function bootHasUUID()
{
static::creating(function (Model $model) {
$model->primaryKey = 'uuid';
$model->keyType = 'string'; // In Laravel 6.0+ make sure to also set $keyType
$model->incrementing = false;
if (empty($model->{$model->getKeyName()})) {
$model->{$model->getKeyName()} = Str::uuid()->toString();
}
});
}
/**
* Get the value indicating whether the IDs are incrementing.
*
* #return bool
*/
public function getIncrementing()
{
return false;
}
/**
* Get the auto-incrementing key type.
*
* #return string
*/
public function getKeyType()
{
return 'string';
}
}
And finally, add the App\Traits\HasUUID in User Model.
...
use App\Traits\HasUUID;
...
class User extends Authenticatable
{
use HasUUID;
...
}
No need to customize Sanctum's Model. Thank you so much #Hussain, #Dharman

Issues with pivot table with Laravel

I have a problem with creating pivot table in Laravel. That's the first time I'm using it, and after searching on Internet, I can't manage to fix my issue.
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'champions_teams.teams_id' in 'field list' (SQL: select `champions`.*, `champions_teams`.`teams_id` as `pivot_teams_id`, `champions_teams`.`champions_id` as `pivot_champions_id`, `champions_teams`.`champion_id` as `pivot_champion_id` from `champions` inner join `champions_teams` on `champions`.`id` = `champions_teams`.`champions_id` where `champions_teams`.`teams_id` = 1) (View: C:\laragon\www\proyecto-web\resources\views\teams\teamIndex.blade.php)
Following, the way I created my classes "Champions" and "Teams", with my pivot table migration.
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\softDeletes;
class Teams extends Model
{
use SoftDeletes;
protected $table = 'teams';
protected $fillable = ['user_id','name','rank','region'];
public function user(){
return $this->belongsTo(User::class);
}
public function champions(){
return $this->belongsToMany(Champions::class)->withPivot('champion_id');
}
public function files(){
return $this->morphMany(File::class, 'model');
}
public function setNameAttribute($value){
$this->attributes['name'] = strtoupper($value);
}
public function getTeamsNameAttribute(){
return $this->name;
}
}
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Champions extends Model
{
protected $table = 'champions';
protected $fillable = ['name','health_points','type','role'];
public function teams(){
return $this->belongsToMany(Teams::class)->withPivot('team_id');;
}
public function items(){
return $this->hasMany(Items::class, 'champion_id');
}
}
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class PivotTables extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('champions_teams', function(Blueprint $table){
$table->unsignedBigInteger('champion_id');
$table->unsignedBigInteger('team_id');
$table->foreign('champion_id')
->references('id')
->on('champions')
->onDelete('cascade');
$table->foreign('team_id')
->references('id')
->on('teams')
->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
//
}
}
Thanks for your help ! You can also access the whole code right here : https://github.com/ValentinDelpy/proyecto-web
Many to Many
Since you are not following the name conventions which Laravel expects, you should customize the name of the joining table, the column names of the keys on the table by passing additional arguments to the belongsToMany method. The third argument is the foreign key name of the model on which you are defining the relationship, while the fourth argument is the foreign key name of the model that you are joining to:
class Champions extends Model
{
public function teams(){
return $this->belongsToMany(Teams::class, 'champions_teams', 'team_id', 'champion_id');
}
}
class Teams extends Model
{
public function champions(){
return $this->belongsToMany(Champions::class, 'champions_teams', 'champion_id', 'team_id');
}
}
Seems You have collision with teams and team.
You model is named Teams (should be Team).
Checkout how to make many to many relations propely:
Laravel docs
Probably Laravel is generating the id from the Model name, so if the Project is brand new, just change it, otherwise, you have to declare the foreign keys name in the belogsToMany function (check https://laravel.com/api/6.x/Illuminate/Database/Eloquent/Concerns/HasRelationships.html#method_belongsToMany).
Also keep in mind that the witPivot function is to let Laravel know the existence of other fields more than the only 2 foreign keys, not the foreign keys themself (check https://laravel.com/api/6.x/Illuminate/Database/Eloquent/Relations/BelongsToMany.html#method_withPivot)

Auth::user() relationship return null laravel 5.3

I have the following code in my App\User model.
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'username','dob','name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token','created_at','updated_at',
];
protected $dates =[
'dob',
];
public function roleuser(){
return $this->belongsTo('App\Role');
}
}
class CreateRolesTable extends Migration
{
public function up()
{
Schema::create('roles', function (Blueprint $table) {
$table->increments('id');
$table->string('rolename');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('roles');
}
}
class CreateUsersTable extends Migration
{
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->integer('role_id')->unsigned()->default(2);
$table->string('username',32);
$table->date('dob');
$table->string('name');
$table->string('email');
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('users');
}
}
i'm using 1 to 1 relationship between user and role.
Calling {{ Auth::user()->roleuser }} from a Blade template returns null but I am expecting a App\Role instance.
Can someone tell me what's wrong?
I'm using 1 to 1 relationship between user and role.
If you're using a one to one relationship, you should use the hasOne method that way it will return an instance of the model and not a collection which I think is what you're getting now (not null) like you thought.
You have to define the key used for the relationship. You are not passing any additional paremeters to the relationship method to override the naming conventions. By default it looks for very particular named fields. It is going to look for roleusers_id because you named the method roleusers instead of the more normal role name. If you named it role it would look for the role_id field by default. You will need to override the key used if you keep it named roleusers. [The docs mention this directly]
Laravel 5.3 Docs - Eloquent - Relationships - One to Many (Inverse)

Undefined table: 7 ERROR: relation "expenses" does not exist

Since i am a spanish speaker, i wrote the controllers and models of income and expense in spanish; while all the rest were on english..
I renamed and changed manually Routes, Controllers, Migrations and even Models.
And when i run php artisan migrate:reset this is my error.
Undefined table: 7 ERROR: relation "expenses" does not exist (SQL: alter table "expenses" drop column "location_id")**
I use psgql and laravel 5.3
This is my code:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Expense extends Model
{
protected $fillable = ['id', 'description', 'quantity'];
public function locations()
{
return $this->hasMany('App\Location');
}
public function icons()
{
return $this->hasMany('App\Icon');
}
public function types()
{
return $this->hasMany('App\Type');
}
public function stores()
{
return $this->hasMany('App\Store');
}
}
Migration:
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateExpensesTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('expenses', function (Blueprint $table) {
$table->increments('id');
$table->float('quantity');
$table->string('description');
$table->integer('location_id')->unsigned();
$table->integer('icon_id')->unsigned();
$table->integer('type_id')->unsigned();
$table->integer('store_id')->unsigned();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('expenses');
}
}
Location Migration:
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateLocationsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('locations', function (Blueprint $table) {
$table->increments('id');
$table->string('address');
$table->float('lat');
$table->float('long');
$table->integer('store_id')->unsigned();
$table->timestamps();
$table->foreign('store_id')->references('id')->on('stores')->onDelete('cascade');
});
Schema::table('expenses', function (Blueprint $table) {
$table->foreign('location_id')->references('id')->on('locations')->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::table('expenses', function (Blueprint $table) {
$table->dropColumn('location_id');
});
Schema::dropIfExists('locations');
}
}
Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Location extends Model
{
protected $fillable = ['id', 'address', 'lat', 'long'];
public function expenses()
{
return $this->belongsTo('App\Expense');
}
public function stores()
{
return $this->hasOne('App\Store');
}
}
Hope you can help me.
When it says
relation "expenses" does not exist
It usually happens when your expenses table must have been dropped before migration:reset rolled back CreateLocationsTable.
Check the order of execution of your migrations.
As you were trying to reset, to fix it now, open your database, drop all tables manually and execute migrate again.
Schema::table('expenses', function (Blueprint $table) {
$table->foreign('location_id')->references('id')->on('locations')->onDelete('cascade');
});
change this to
Schema::alter('expenses', function (Blueprint $table) {
$table->foreign('location_id')->references('id')->on('locations')->onDelete('cascade');
});
I had this error. I had to resolve it by adding the prefix of the database to my model. There is a way to change this in the database, and it is supposed to be changed. it's something, like $user, public. It's the schema profile. Mine is changed when I login, but for some reason the model is not binding to schema. So I had to specify it in the model. Instead of
protected $table = 'table_name';
I had to do
protected $table = 'schema_name.table_name';
Note: By schema_name or table_name, I'm not referring for you to put schema_ then the name. That is just so it's easier to read.
The model is located in the model folder under the App/Models folder depending on which version of Laravel you using and how your Models are organized. If your model name is not the same as the table name, then you will need to put the protected $table. But if the schema is not there, then you will need to add that.
I do have this set in my DB_DATABASE_SECOND= in .env file. But it somehow still doesn't pick up the prefix.
But yeah. Pretty much I couldn't find the answer anywhere, but I
Solution found in:
Laravel assumes the database table is the plural form of the model name
https://laravel.com/docs/8.x/eloquent#table-names
you need to declare the singularity name of your table.
add this line
protected $table = 'expense'
at the end of your model file
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Expense extends Model
{
protected $fillable = ['id', 'description', 'quantity'];
public function locations()
{
return $this->hasMany('App\Location');
}
public function icons()
{
return $this->hasMany('App\Icon');
}
public function types()
{
return $this->hasMany('App\Type');
}
public function stores()
{
return $this->hasMany('App\Store');
}
protected $table = 'expense';
}

Eloquent relationships: cloumn doesn't exist

I'm new to Laravel and am having a bit of a hard time cracking how relationships work. I'm building a simple e-commerce application, where each user has some orders, and order has one or many sub-orders, and each sub-order is linked to only one item (please don't comment on my scheme yet; for now I just need to figure out Eloquent and will be doing refactoring later :) ).
Following are my models:
class Order extends Model
{
//timestamp
protected $created_at;
public function sub_orders() {
return $this->hasMany('App\SubOrder');
}
public function user() {
return $this->belongsTo('App\User');
}
}
class SubOrder extends Model
{
protected $fillable = array('delivery_date', 'quantity', 'total_price', 'delivery_status');
public function item() {
return $this->hasOne('App\Item');
}
public function order() {
return $this->belongsTo('App\Order');
}
}
class Item extends Model
{
//note - slug is kind of categorization and is common to many items
protected $fillable = array('sku', 'name', 'slug', 'unit_price');
}
And here are the migrations:
class CreateOrdersTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('orders', function (Blueprint $table) {
$table->increments('id');
$table->timestamp('created_at');
//foreign keys
$table->unsignedInteger('user_id')->after('id');
$table->foreign('user_id')->references('id')->on('users') ->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('orders');
}
}
class CreateSubOrdersTable extends Migration
{
public function up()
{
Schema::create('sub_orders', function (Blueprint $table) {
$table->increments('id');
$table->date('delivery_date');
$table->decimal('quantity', 5, 2);
$table->decimal('total_price', 7, 2);
$table->enum('delivery_status', ['pending_from_farmer', 'ready_for_customer', 'out_for_delivery', 'delivered']);
//foreign keys
$table->unsignedInteger('order_id')->after('id');
$table->foreign('order_id')->references('id')->on('orders') ->onDelete('cascade');
$table->unsignedInteger('item_id')->after('order_id');
$table->foreign('item_id')->references('id')->on('items') ->onDelete('cascade');
});
}
public function down()
{
Schema::dropIfExists('sub_orders');
}
}
class CreateItemsTable extends Migration
{
public function up()
{
Schema::create('items', function (Blueprint $table) {
$table->increments('id');
$table->string('sku')->unique();
$table->string('name');
$table->string('slug');
$table->decimal('unit_price', 5, 2);
});
}
public function down()
{
Schema::dropIfExists('items');
}
}
The problematic expression is why I write App\Order::all()[0]->sub_orders[0]->item in my web.php and get the following error:
SQLSTATE[42703]: Undefined column: 7 ERROR: column items.sub_order_id does not exist
LINE 1: select * from "items" where "items"."sub_order_id" = $1 and ...
^ (SQL: select * from "items" where "items"."sub_order_id" = 1 and "items"."sub_order_id" is not null limit 1)
I don't understand why it's looking for sub_order_id in the items table. And what's the right way to go about doing it?
Overall: define the 1-to-1 relationship using hasOne or belongsTo will affect the target table where Laravel find the foreign key. hasOne assume there is a my_model_id in target table.And belongsTo assume there is a target_model_id in my table.
class SubOrder extends Model
{
public function item() {
return $this->hasOne('App\Item', 'id', 'item_id');
}
}
or
class SubOrder extends Model
{
public function item() {
return $this-> belongsTo('App\Item');
}
}
According to Laravel Doc
class User extends Model
{
/**
* Get the phone record associated with the user.
*/
public function phone()
{
return $this->hasOne('App\Phone');
}
}
Eloquent determines the foreign key of the relationship based on the model name. In the above case, the Phone model is automatically assumed to have a user_id foreign key. If you wish to override this convention, you may pass a second argument to the hasOne method:
$this->hasOne('App\Phone', 'foreign_key', 'local_key');
Or Defining The Inverse Of The Relationship
class Phone extends Model
{
/**
* Get the user that owns the phone.
*/
public function user()
{
return $this->belongsTo('App\User');
}
}
In the example above, Eloquent will try to match the user_id from the Phone model to an id on the User model.
Your SubOrder item has relationship of type OneToOne (hasOne is bidirectional) with an Item.
So Eloquent expects to have sub_order_id in the items table.
So the solution is to define the inverse of this relationship (belongsTo) in the Item model

Categories