I am new to laravel. i am having difficulties to store foreign key value in database. I have read the documentation, searched on stackoverflow. But its confusing me more.
I have a User table and an idea table. User can create many idea. Let me show the code:
Controller function:
public function storePost(IdeaRequest $request) {
Idea::create([
'title' => $request->input('idea_title'),
'user_id' => $request->hasMany('user_id'),
'image' => $request->file('idea_image')->move('images'),
'info' => $request->input('idea_info'),
'communitySelection' => $request->input('selection'),
'location' => $request->input('idea_location'),
'goal' => $request->input('idea_goal'),
'description' => $request->input('idea_description')
]);
}
Idea Model:
class Idea extends Model
{
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'idea_title', 'idea_info','user_id', 'idea_image', 'idea_description', 'duration', 'idea_goal', 'pledge_amount', 'set_equity',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'remember_token',
];
public function Post() {
return $this->hasMany('User');
}
}
Idea Migration:
public function up()
{
//
Schema::create('ideas', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->string('idea_title');
$table->string('idea_info', 150);
$table->string('idea_image');
$table->string('selection');
$table->longText('idea_description');
$table->string('idea_location');
$table->integer('idea_goal')->unsigned();
$table->integer('pledge_amount')->unsigned();
$table->string('set_equity')->nullable();
$table->rememberToken();
$table->timestamps();
});
}
User Migration:
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name',50);
$table->string('email')->unique();
$table->string('password',32);
$table->string('profile_picture')->nullable();
$table->string('address');
$table->string('phone_number',15);
$table->boolean('status')->nullable();
$table->string('user_type',15);
$table->string('credit_card',16)->unique();
$table->rememberToken();
$table->timestamps();
});
}
It can be seen that foreign key is being set. I am unable to store the value of foreign key on a user table. Any help would be appreciated.
In the Idea Migration, you can declare the foreign key like this
public function up()
{
//
Schema::create('ideas', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->string('idea_title');
$table->string('idea_info', 150);
$table->string('idea_image');
$table->string('selection');
$table->longText('idea_description');
$table->string('idea_location');
$table->integer('idea_goal')->unsigned();
$table->integer('pledge_amount')->unsigned();
$table->string('set_equity')->nullable();
$table->rememberToken();
$table->timestamps();
});
//Declare foreign key
Schema::table('ideas', function(Blueprint $table) {
$table->foreign('user_id')->references('id')->on('users')
->onDelete('restrict')
->onUpdate('restrict');
});
}
I do not agree with the relation you added in the Idea Model. You should use belongsTo instead of hasMany. And according to the comments, change Post() to User() .
public function User() {
return $this->belongsTo('User');
}
If so, you need also change 'user_id' => $request->hasMany('user_id') in the Controller function.
Related
I have a set that has a list of group and each group has a list of attributes like this
//sets
Schema::create('sets', function (Blueprint $table) {
$table->id();
$table->string('name');
});
//groups
Schema::create('groups', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->foreignId('set_id')->constrained('sets')->onDelete('cascade');
});
//attributes
Schema::create('attributes', function (Blueprint $table) {
$table->id();
$table->string('name');
});
//set_group_attributes
Schema::create('set_group_attributes', function (Blueprint $table) {
$table->foreignId('set_id')->constrained('sets')->onDelete('cascade');
$table->foreignId('group_id')->constrained('groups')->onDelete('cascade');
$table->foreignId('attribute_id')->constrained('attributes')->onDelete('cascade');
$table->integer('position');
$table->unique(['set_id', 'attribute_id']);
});
I need to save the set with groups and attributes, this is my code :
$set = Set::create(['name' => $request->name]); ---> save the set
$set->groups()->createMany($request->groups); ---> save the group
//set model
public function groups(): HasMany
{
return $this->hasMany(Group::class, 'set_id','id');
}
My question is how to save the attributes with laravel eloquent?
Here we can use attach like in Docs with belongsToMany
//group model
/**
* #return BelongsToMany
*/
public function attributes(): BelongsToMany
{
return $this->belongsToMany(Attribute::class, 'set_group_attributes', 'group_id', 'attribute_id')->withPivot('position');
}
// save attributes of groups
foreach ($attributes as $attribute) {
$group->attributes()->attach($attribute['id'], ['set_id' => $model->id, 'position' => $attribute['position']]);
}
I have this model :
class User extends Authenticatable
{
protected $fillable = [
'email',
'password',
'role_id',
];
.........
public function language() {
return $this->hasOne(Language::class, 'language_id');
}
}
And Language model :
class Language extends Model
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name',
'iso'
];
/**
* #return BelongsTo
*/
public function user()
{
return $this->belongsTo(User::class);
}
Now When I try to save user :
$newUser->language()->save(Language::find($input['language']));
I get the error:
Column not found: 1054 Unknown column 'language_id' in 'field list' (SQL: update `languages` set `language_id` = 4, `languages`.`updated_at` = 2021-08-02 13:51:32 where `id` = 1)"
User migration :
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->integer('role_id')->default(UserRoles::TRANSLATOR);
$table->integer('language_id')->references('id')->on('languages')->nullable();
$table->rememberToken();
$table->timestamps();
$table->softDeletes();
});
}
Language migration :
public function up()
{
Schema::create('languages', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->string('name');
$table->string('iso')->unique();
});
}
I confirm that I have language id inside users table and I don't have user_id inside language table, because I want to keep just language_id inside table. What can I try next?
When you have hasOne in User model:
public function language() {
return $this->hasOne(Language::class, 'language_id');
}
eloquent assumes that languages table would have language_id. Hence the error 'no language_id in languages table'
So, hasOne should be defined in the the Language model.
//Language model
public function user() {
return $this->hasOne(User::class); //this assumes users table would have language_id
}
And, the belongsTo should be defined in User model.
//User model
public function language() {
return $this->belongsTo(Language::class);
}
as the first answer, change the sintax of your relationship and add the language_id to the fillable array
user model
protected $fillable = [
'email',
'password',
'role_id',
'language_id'
];
public function language() {
return $this->belongsTo(Language::class);
}
and on user creation
$user = User::create(
'email' => ...
'password' => ...
'role_id' => ...
'language_id' => $input['language']
);
you can see more here https://laravel.com/docs/8.x/eloquent-relationships#the-save-method, so in this case if you want to use the save method on this relation you must do it like
$language = Language::find($input['language']);
$language->user()->save($newuser);
I suggest use the Laravel documentation sintax for the relationship in migration
$table->foreignId('language_id')->constrained()->nullable();
I built two models User and Institution.
How do I update the pivot data between them, after adding additional Pivot columns?
<?php
class User extends Authenticatable
{
public function institutions()
{
$pivots = ['id', 'program_choice', 'session'];
return $this->belongsToMany('App\Institution')
->withPivot($pivots);
}
}
class Institution extends Authenticatable
{
public function users()
{
$pivots = ['id', 'program_choice', 'session'];
return $this->belongsToMany('App\User', 'institution_user')
->withPivot($pivots);;
}
}
Here are the migrations
class CreateUsersTable extends Migration
{
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->integer('user_id')->unsigned();
$table->rememberToken();
$table->timestamps();
});
}
class CreateInstitutionsTable extends Migration
{
public function up()
{
Schema::create('institutions', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name')->unique();
$table->string('city')->nullable();
$table->string('state')->nullable();
$table->string('country')->nullable();
$table->string('address')->nullable();
$table->string('user_id')->nullable();
$table->string('postal_code')->nullable();
$table->timestamps();
});
}
}
This is the what the pivot table looks like
I am able to attach the information to the pivot table
public function storeInstitution(Request $request)
{
$user_id = auth()->user()->id;
$user = User::find($user_id);
$institution_id = $request->input('institution_id');
$user_program_choice = $request->input('program_choice');
$user_session = $request->input('session');
$user_inst = array(
'program_choice' => $user_program_choice,
'session' => $user_session,
'user_id' => $user_id,
'institution_id' => $institution_id
);
$user->institutions()->attach($institution_id, $user_inst);
return 'success';
}
But unable to update the attached pivot E.g I can't change the program_choice, particle physics to something like digital art
Here's my current code
public function updateInstitutions(Request $request, $pivot_id)#TODO id is pivot_id
{
$user_id = auth()->user()->id;
$user = User::find($user_id);
$institution_id = $request->input('institution_id');
$pivot_attributes = array(
'user_id' => $user_id,
'institution_id' => $institution_id,
'session' => $request->input('session'),
'program_choice' => $request->input('program_choice'),
);
$user->institutions()->updateExistingPivots($institution_id, $pivot_attributes, false);
return 'success';
}
How do I update my pivot data, using the pivot id?
Check the documentation regarding this aspect.
Updating A Record On A Pivot Table
If you need to update an existing row in your pivot table, you may use
updateExistingPivot method. This method accepts the pivot record
foreign key and an array of attributes to update:
$user = App\Models\User::find(1);
$user->roles()->updateExistingPivot($roleId, $attributes);
I'm trying to define a role for my users using a "role_id" foreign key which referes to the "id" of my "roles" table.
The migrations worked well but when I'm trying to register I get an error.
Migration users
class CreateUsersTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->char('nni', 6);
$table->string('firstname');
$table->string('lastname');
$table->string('email')->unique();
$table->unsignedBigInteger('role_id')->default(1);
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
$table->foreign('role_id')->references('id')->on('roles');
});
}
Models/User
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'nni', 'firstname', 'lastname', 'email', 'role_id', 'admin', 'password',
];
[...]
public function role()
{
return $this->belongsTo(Role::class);
}
}
Migration roles
class CreateRolesTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('roles', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('description');
$table->timestamps();
});
}
[...]
}
The error
SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update >a child row: a foreign key constraint fails (projectsms.users, >CONSTRAINT users_role_id_foreign FOREIGN KEY (role_id) REFERENCES >roles (id))
If you know where is my problem let me know !
Since your structure depends on the fact that every use must have a role, you should include the insertion of the default role in your migration.
class CreateRolesTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('roles', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('description');
$table->timestamps();
});
DB::table('roles')->insert([
'id' => 1, //must be 1
'name' => 'default',
'description' => 'default role (just registered)',
'created_at' => \Carbon\Carbon::now(),
'updated_at' => \Carbon\Carbon::now(),
]);
}
[...]
}
I now know that I can create a User using the haveMany relationship between a Region and User by doing this:
$region = Region::find($data['region_id']);
$region->users()->create([
'username' => $data['username'],
'email' => $data['email'],
'first_name' => $data['first_name'],
'last_name' => $data['last_name'],
'password' => bcrypt($data['password']),
]);
But what if there are multiple foreign keys, how do you create a user without making them fillable for more than 1 foreign key constraint? What if there were 3 or 4?
Example of the relationships setup in the different models:
Region hasMany Users, or
User belongsTo a Region
Location hasMany Users, or
User belongsTo a Location
A stripped down version of my migration looks like this if it helps to understand the relationships better:
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->integer('region_id')->unsigned();
$table->integer('location_id')->unsigned();
$table->timestamps();
$table->foreign('region_id')
->references('id')
->on('regions');
$table->foreign('location_id')
->references('id')
->on('locations');
});
Schema::create('regions', function (Blueprint $table) {
$table->increments('id');
$table->string('name', 100);
$table->timestamps();
});
Schema::create('locations', function (Blueprint $table) {
$table->increments('id');
$table->string('street_address', 100);
$table->string('city', 50);
$table->string('province', 50);
$table->string('country', 50);
$table->string('postal_code', 10);
$table->timestamps();
});
Example of Region and Location Models:
/**
* Region may have many users.
*
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function users()
{
return $this->hasMany('App\User');
}
/**
* Location may have many users.
*
* #return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function users()
{
return $this->hasMany('App\Location');
}
I assume you have a model for Region and Location. Each of your region has an id and location has an id, then just add
$this->hasMany('where your Region model is', 'region_id', 'id');
$this->hasMany('where your Location model is', 'location_id', 'id');
to your User model
Reference: http://laravel.com/docs/5.0/eloquent#one-to-many
Edit: You can also do in any of your model
if ($this->create()) {
return (new Model())->create(the params you need in another model);
}