I am currently trying to save a customer and using a hasMany Eloquent-Relationship to store addresses with it in a seperate table. Now i ran into the problem, that laravel is storing every value right in both tables except the foreignID. Here are some code snippets which I am using. The request returns to success, although the supplier_id (foreignKey) in the supplier_addresses table is not set.
Supplier Migration:
Schema::create('suppliers', function (Blueprint $table) {
$table->string('supplier_id')->primary();
$table->string('supplierName');
$table->string('taxNumber');
$table->timestamps();
});
SupplierAddresses Migration:
Schema::create('supplier_addresses', function (Blueprint $table) {
$table->id();
$table->string('supplier_id');
$table->string('street');
$table->string('houseNumber');
$table->string('stairway')->nullable();
$table->string('floor')->nullable();
$table->string('door')->nullable();
$table->string('zipCode');
$table->string('city');
$table->string('type');
$table->timestamps();
});
Supplier Model:
class Supplier extends Model
{
use HasFactory;
protected $primaryKey = 'supplier_id';
protected $keyType = 'string';
public $incrementing = 'false';
protected $guarded = [];
protected $fillable = [
'supplier_id',
'supplierName',
'taxNumber'
];
public function address() {
return $this->hasMany(SupplierAddress::class, "supplier_id");
}
}
SupplierAddresses Model:
class SupplierAddress extends Model
{
use HasFactory;
protected $fillable = [
'street',
'houseNumber',
'stairway',
'floor',
'door',
'zipCode',
'city',
'type',
'supplier_id'
];
}
Suppliers Controller:
class SuppliersController extends Controller
{
public function show() {
return view('addSupplier');
}
public function submit() {
request()->validate([
'supplier_id' => 'required',
'supplierName' => 'required',
'taxNumber' => 'required'
]);
$supplier = Supplier::create([
'supplier_id' => request('supplier_id'),
'supplierName' => request('supplierName'),
'taxNumber' => request('taxNumber')
]);
$supplier->address()->create([
'supplier_id' => request('supplier_id'),
'street' => request('street'),
'houseNumber' => request('houseNumber'),
'stairway' => request('stairway'),
'floor' => request('floor'),
'door' => request('door'),
'zipCode' => request('zipCode'),
'city' => request('city'),
'type' => 'P'
]);
return redirect()->back()->with('success', 'Das Anlegen eines neuen Lieferanten war erfolgreich.');
}
}
Suppliers Table:
SupplierAddresses Table:
You need to assign foreign key constrained between suppliers and supplier_addresses table
example
primary key
Schema::create('suppliers', function (Blueprint $table) {
$table->id();
$table->string('supplier_id');
$table->timestamps();
});
foregin key
Schema::table('supplier_addresses', function (Blueprint $table) {
$table->unsignedBigInteger('supplier_id');
$table->foreign('supplier_id')->references('id')->on('suppliers');
});
Or
Schema::table('supplier_addresses', function (Blueprint $table) {
$table->foreignId('supplier_id')->constrained('suppliers');
});
for more details you can see this https://laravel.com/docs/9.x/migrations#foreign-key-constraints
Related
Hello I need a help with laravel 8 many to many relationship pivot table, when I updating or deleting data in API.
These are my files info.
Firstly I created two tables:
Companies (migration file)
public function up()
{
Schema::create('companies', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamps();
});
}
Contacts (migration file)
public function up()
{
Schema::create('contacts', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamps();
});
}
After this created pivot table company_contact (migration file)
public function up()
{
Schema::create('company_contact', function (Blueprint $table) {
$table->foreignId('company_id')->constrained();
$table->foreignId('contact_id')->constrained();
});
}
Models looks like this:
Company model
class Company extends Model{
use HasFactory;
protected $fillable = [
'name',
'email'
];
public function contacts()
{
return $this->belongsToMany(Contact::class);
}
}
Contact model
class Company extends Model{
use HasFactory;
protected $fillable = [
'name',
'email'
];
public function contacts()
{
return $this->belongsToMany(Contact::class);
}
}
My routes file
Route::apiResource('companies', CompanyController::class);
My company controller
class CompanyController extends Controller{
public function index()
{
return CompanyResource::collection(Company::all());
}
public function store(CompanyStoreRequest $request)
{
$company = Company::create($request->validated());
$company->contacts()->attach($request->input('contact_id'));
return new CompanyResource($company);
}
public function show(Company $company)
{
//
}
public function update(CompanyStoreRequest $request,Company $company)
{
$contacts = Company::where('id', $company->id)->contacts()->get();
$company->contacts()->sync($request->input(['contact_id']));
$company->update($request->validated());
return new CompanyResource($company);
}
public function destroy(Company $company)
{
}
}
Company store request
public function rules()
{
return [
'name' => ['required'],
'email' => ['required', 'email'],
'contact_id' =>['required']
];
}
company resource
public function toArray($request)
{
//return parent::toArray($request);
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'contact_count' => $this->contacts()->count()
];
}
Maybe somebody can help my to write correct store() and destroy() methods in to company controller. For example when I updating company data also I want to add more contacts and to save these contacts id's in the pivot table.
With destroy method, when I delete certain company, also I want automatically delete these id’s in pivot table (relation company with contacts).
Thanks for any help.
First, you can pass the data of the contacts in an array together with the company's, using an array for several contacts and to record with the relationship use a foreach with the attach method, search on it. About the deletion you can use the softDelete, search on it too, it makes the cascade deletion of the items.
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 understand how I can join the tables users and teams to members in fact ?
Users Table:
id | name | email | password
1 alain alain#gmail.com *****
2 eric eric1#gmail.com *****
Teams Table:
id | name
1 R.O.S
2 Stephanois
Members Table:
id | user_id (email) | team_id (name)
1 1 1
2 2 1
DataBase:
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
public function up()
{
Schema::create('members', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned()->nullable();
$table->foreign('user_id')->references('id')->on('users');
$table->integer('team_id')->unsigned()->nullable();
$table->foreign('team_id')->references('id')->on('teams');
$table->timestamps();
});
}
public function up()
{
Schema::create('teams', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->integer('user_id')->unsigned()->nullable();
$table->foreign('user_id')->references('id')->on('users');
$table->timestamps();
});
}
User Model:
protected $fillable = [
'name', 'email', 'password',
];
public function team(){
return $this->hasOne('App\Team', 'user_id', 'id'); ?
}
public function member(){
return $this->hasOne('App\Member', 'user_id', 'id'); ?
}
Team Model:
protected $fillable = [
'user_id', 'name'
];
public function member(){
return $this->hasMany('App\Member', 'team_id'); ?
}
public function user(){
return $this->belongsTo('App\User', 'id', 'user_id'); ?
}
Member Model:
protected $fillable = [
'id', 'user_id', 'team_id'
];
public function team(){
return $this->belongsTo('App\Team', 'team_id');
}
public function user(){
return $this->belongsTo('App\User', 'id', 'user_id'); ?
}
I thank you in advance for your help
Edit: when I log in with the user 'alain#gmail.com' I don't retrieve the information for the user 'alain#gmail.com' ? ie user_id and team_id.
public function index(Request $request)
{
$user = $request->user();
$members = Member::query()
->when($user->hasRole('admin') !== true, function (Builder $query) use ($user) {
$query->where('id???', $user->email); ????
})
->when($request->has('search'), function (Builder $query) use ($request) {
$query->where('name??', 'like', '%' . $request->input('search') . '%');
})->with('team:id,name')
->paginate(5);
return view('admin.members.index', compact('members'))
->with('display_search', $user->hasRole('admin'));
}
Which one is you're trying to achieve is not enough clear. If I guess, you want to find out which user is in which team then, in this situation you can go through -
User.php model -
protected $fillable = [
'name', 'email', 'password',
];
public function member(){
return $this->belongsTo('App\Member', 'user_id', 'id');
}
Member.php model -
protected $fillable = [
'id', 'user_id', 'team_id'
];
public function team(){
return $this->belongsTo('App\Team', 'team_id');
}
public function user(){
return $this->belongsTo('App\User', 'user_id', 'id');
}
Team.php model (keep as it is for now)-
class Team extends Model
{
protected $fillable = [
'name'
];
}
And finally call your members those are already in a team in your controller method-
$members = Member::with('team', 'user')->get();
return view('your-blade-file-name', compact('members'));
And, in your blade file -
#foreach($members as $member)
<p>Name: {{ $member->user->name }} , Email: {{ $member->user->email }} , Team - {{ $member->team->name }}</p>
#endforeach
Output:
Name: alain, Email: alain#gmail.com , Team - R.O.S
Name: eric, Email: eric1#gmail.com , Team - R.O.S
If you want a user can belong to a single team, then you don't need an intermediate table. Just add a column in the user table like team_id that will hold the value of which team the user belong.
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->unsignedInteger('team_id'); //make it nullable or anything based on your need
$table->rememberToken();
$table->timestamps();
});
Schema::create('teams', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
And now make the relationships in the models:
User Model
protected $fillable = [
'name', 'email', 'password','team_id'
];
public function team()
{
return $this->belongsTo('App\Team', 'team_id');
}
Team Model
protected $fillable = [
'name'
];
public function users()
{
return $this->hasMany('App\User', 'team_id');
}
In the above relationships a user belongs to a single team and a team has many users. I am pretty sure you are trying to achieve this. Feel free to ask if you find anything hard to understand.
Look you don't need the intermediate model Member. If you want a many to many relationship then you need to use an intermediate table.
1- User table, make id uuid type.
No problem
php artisan migrate:refresh
But this error
php artisan db:seed
Error : ("SQLSTATE[HY000]: General error: 1364 Field 'id' doesn't have a default value")
2- Also companies want to be randomly distributed to users. In the user table, uuid type will be held in the user_id column.
Thank you from now...
User Model :
use UsesUuid;
protected $fillable = ['name', 'email', 'password', 'role', 'slug',];
protected $hidden = ['password', 'remember_token',];
protected $casts = ['email_verified_at' => 'datetime',];
public function companies()
{
return $this->hasMany('App\Company', 'user_id', 'id');
}
UsesUuid trait:
protected static function boot()
{
parent::boot();
static::creating(function ($post) {
$post->{$post->getKeyName()} = (string)Str::uuid();
});
}
public $incrementing = false;
public function getKeyType()
{
return 'string';
}
Users migration:
Schema::create('users', function (Blueprint $table) {
$table->uuid('id')->primary()->unique();
$table->string('name',100);
$table->string('email',100);
$table->timestamp('email_verified_at')->nullable();
$table->string('password',100);
$table->string('role',20)->nullable();
$table->string('slug',100);
$table->rememberToken();
$table->timestamps();
$table->softDeletes();
});
Companies migration:
Schema::create('companies', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('user_id',36);
$table->string('name', 100);
$table->timestamps();
$table->softDeletes();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
User factory:
$name = $faker->name;
return [
'id' => Str::uuid(),
'name' => $name,
'email' => $faker->unique()->safeEmail,
'email_verified_at' => now(),
'password' => Hash::make(123), // password
'remember_token' => Str::random(10),
'role' => 'user',
'slug' => Str::slug($name),
];
Company factory:
$name = $faker->company;
return [
'user_id' => Str::uuid(),
'name' => $name,
];
DatabaseSeeder :
factory(App\User::class, 5)->create();
factory(App\Company::class, 1500)->create();
modify your trait like this:
static::creating(function ($post) {
empty($post->{$post->getKeyName()}) && $post->{$post->getKeyName()} = (string)Str::uuid();
});
there is no need to make UUID unique,
in your migration, because it is already!
$table->uuid('id');
$table->primary('id');
and factory must create primary UUID itself, don't add it yourself
I think with these changes, seeder must run successfully
I have three model Developer model:
migration:
$table->increments('id');
$table->string('email')->unique();
$table->unsignedInteger('programming_language_id');
$table->unsignedInteger('language_id');
$table->timestamps();
and function
class Developer extends Model
{
public function programming_languages() {
return $this->hasMany('App\ProgrammingLanguage');
}
public function languages() {
return $this->hasMany('App\Language');
}
}
ProgrammingLanguage model:migration:
$table->increments('id');
$table->string('name')->unique();
$table->timestamps();
and function:
protected $table = 'programming_languages';
public function developers() {
return $this->belongsToMany('App\Developer');
}
Language model: migration:
$table->increments('id');
$table->string('code', 30)->unique();
$table->timestamps();
and function:
public function developers() {
return $this->belongsToMany('App\Developer');
}
I want to make db seeder and being relationships between those. How can i do that?
I am trying: creating a factory DeveloperFactory
$factory->define(App\Developer::class, function (Faker $faker) {
return [
'email' => $faker->unique()->safeEmail,
'programming_language_id' => function () {
return factory(App\ProgrammingLanguage::class)->create()->id;
},
'language_id' => function () {
return factory(App\Language::class)->create()->id;
}
];
});
seed OK, But it doesnot make any relationships. just seed the data.How can i do that by db:seed?
Seed your languages and programming languages tables first, then query for records in the developer seeder.
return [
'email' => $faker->unique()->safeEmail,
'programming_language_id' => App\ProgrammingLanguage::inRandomOrder()->first()->getKey(),
'language_id' => App\Language::inRandomOrder()->first()->getKey()
];