Has Many Through where the middle table has both forain keys in laravel 5.6 - has-many-through

I need to make a HasManyThough relation where the middle Model holds the foreign keys of both Models.
Here is detail:
Migrations:
Schema::create('carriers', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
});
Schema::create('shipping_zones', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
});
Schema::create('shipping_rates', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->integer('shipping_zone_id')->unsigned()->index();
$table->integer('carrier_id')->unsigned()->index();
$table->decimal('rate', 20, 6);
});
Now I need something like
$carrier->shippingZone()
Is there any easy way to get this?

As per your migrations you need Many To Many relation rather than the HasManyThough relation.
Carrier.php
public function shippingZones()
{
return $this->belongsToMany('App\ShippingZone', 'shipping_rates);
}
You can access all shipping zones related to the carrier using, $carrier->shippingZones.
If you need to chain the query you can use $shippingZones = $carrier->shippingZones()->orderBy('id')->get(); here
If you need to use HasManyThough you would have to change the migrations. here

Related

3 Table Laravel Migration need advice

I think I am doing this correctly. I have a users, profile, and application table. Below are the migrations. I think I am linking them correctly in the migration but need advice to make sure. 1 user can have 1 profile but many applications.
User Table
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
Profile Table
public function up()
{
Schema::create('profile', function (Blueprint $table) {
$table->id();
$table->integer('user_id')->unsigned();
$table->string('address')->nullable();
$table->string('apt')->nullable();
$table->string('city')->nullable();
$table->string('state')->nullable();
$table->string('zipcode')->nullable();
$table->string('homephone')->nullable();
$table->string('mobile')->nullable();
$table->string('occupation')->nullable();
$table->boolean('over18')->nullable();
$table->string('homechurch')->nullable();
$table->string('homechurchcity')->nullable();
$table->string('pastor')->nullable();
$table->string('howoftenattend')->nullable();
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
Application
public function up()
{
Schema::create('pilgrim_application', function (Blueprint $table) {
$table->id();
$table->string('besttimetocall');
$table->string('nickname');
$table->foreignId('user_id')->constrained('users')->onDelete('cascade');
$table->foreignId('profile_id')->constrained('profile')->onDelete('cascade');
$table->timestamps();
});
Does your migration work at the moment?
First check your migration file order, for example
0000_user
0001_profile
1000_ pilgrim_application
1001_app_two
in case of multiple applications you could begin the migration with a different number for grouping files in a list, this can be handy if you want to create multiple applications.
Also, is it necessary to specify the relations user and profile in the pilgrim_application migration?
Through relationships in your models you can also access the pilgrim_application from the user model and vice versa.
$user->profile->pilgrim_application

Laravel combine multiple collections into one query

I'm wondering if this is possible. I have 3 models.
Users
TenantPreferances
PropertyAdverts
I'm trying to find out if I can do a query like so.
Find all tenants, whose preferences, match the currently signed in users properties.
The 3 databases are like so
User Model
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('userType');
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
PropertyAdverts
Schema::create('property_adverts', function (Blueprint $table) {
$table->increments('id');
$table->string("photo");
$table->string('address');
$table->string('county');
$table->string('town');
$table->string('type');
$table->string('rent');
$table->string('date');
$table->string('bedrooms');
$table->string('bathrooms');
$table->string('furnished');
$table->longText('description');
$table->integer('user_id'); //Landlord ID
$table->timestamps();
});
Tenant Preferances
Schema::create('tenant_preferances', function (Blueprint $table) {
$table->increments('id');
$table->string('county');
$table->string('type');
$table->string('rent');
$table->string('bedrooms');
$table->string('bathrooms');
$table->boolean('status')->default('0');
$table->integer('user_id'); //Tenant ID
$table->timestamps();
});
Yes, that is possible. You need to dig in on relations. You can then create a function to define the relation on you model:
function propertyAdverts() {
return $this->hasMany(PropertyAdverts::class);
}
You can access the relation from the user model by using $user->propertyAdverts. If you want to eager load them you can do so:
User::with('propertyAdverts')->find(3);
But notice that Laravel does not do a regular join by default. It first fetches all users, and then fetches all propertyAdverts using a single query using a in statement.

how can I use event and listener by laravel to handle the booking?

I have rooms in hospitals. Each room has beds with numbers. I want to assign beds to patients. How can I handle this in an easy way:
rooms migration:
Schema::create('rooms', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->integer('floor');
$table->text('description');
$table->timestamps();
});
beds migration:
Schema::create('beds', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('quality');
$table->string('charge');
$table->integer('room_id')->unsigned();;
$table->foreign('room_id')->references('id')->on('rooms')
->onUpdate('cascade')->onDelete('cascade');
$table->boolean('status');
$table->timestamps();
});
reservations migration:
Schema::create('reservations', function (Blueprint $table) {
$table->increments('id');
$table->date('date_in');
$table->date('date_out');
$table->boolean('status');
$table->integer('patient_id')->unsigned();
$table->foreign('patient_id')->references('id')->on('patients');
$table->integer('bed_id')->unsigned();
$table->foreign('bed_id')->references('id')->on('beds');
$table->timestamps();
});
How can I check for available beds? Get the available beds? Be sure the bed is available. How can I use events and listeners to make the whole thing work?
pluck() retrieve a Collection containing the values of a single column.
Here, it retrieves a Collection of reservation bed_id:
$reserved = Reservation::pluck('bed_id)->all();
The whereNotIn method verifies that the given column's value is not contained in the given array:
$bed_available = Bed::whereNotIn('id' , $reserved)->get();
This query gives you all the bed whose id is not available in that collection $reserved , which i think is your requirement .

One-To-Many Relation with Pivot Table

I have 2 tables Manufacturers and Suppliers ,and they have Many-to-Many relation
Schema::create('manufacturers', function (Blueprint $table) {
$table->increments('id');
$table->string('name')->unique();
$table->timestamps();
});
Schema::create('suppliers', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('location');
$table->timestamps();
​ });
so i created a pivot table called "manufacturer_supplier" and it works fine.
Schema::create('manufacturer_supplier', function (Blueprint $table) {
$table->increments('id');
$table->integer('manufacturer_id')->unsigned()->index();
$table->integer('supplier_id')->unsigned()->index();
$table->timestamps();
$table->foreign('manufacturer_id')->references('id')->on('manufacturers')->onDelete('cascade');
$table->foreign('supplier_id')->references('id')->on('suppliers')->onDelete('cascade');
});
My confusion comes from adding a new table "devices"
Schema::create('devices', function (Blueprint $table) {
$table->increments('id');
$table->string('serial')->unique();
$table->string('name');
​$table->integer('supplier_id')->unsigned()->nullable();
$table->integer('manufacturer_id')->unsigned()->nullable();
$table->text('notes')->nullable();
$table->timestamps();
$table->foreign('supplier_id')->references('id')->on('suppliers')->onDelete('cascade');
$table->foreign('manufacturer_id')->references('id')->on('manufacturers')->onDelete('cascade');
});
where i want to have a one-to-many relation with each of suppliers and manufacturers , so i would have a select list of manufacturers and then populate the next list from with suppliers from Pivot table that relate to the selected manufacturer.
currently my "device"​ model has the following relations which it relate them to the original table not the pivot so it doesn't work
//5
public function manufacturer(){
return $this->belongsTo('App\Manufacturer');
}
//6
public function supplier(){
return $this->belongsTo('App\Supplier');
}
I haven't done that before so i'm curious to know what will be the best fix for this to work.
Thanks a lot ,
If you want all suppliers associated with a single manufacturer you could get them using the many-to-many relation.
$suppliersList = $supplier->manufacturer()->suppliers();
howerver I don't understand why a device should be associated with a single supplier .... but that's up to you.

Laravel: How do I model this Article/Category scenario?

I have a scenario with Articles and Categories where each article can have only one category through a CategoryGroup.
This means the article can have more than one category but only one unique category from each category_group. Or, to put it another way, the article can have only one category from each category_group.
Do I model this scenario at the level of relationships? Or is this a matter of using custom validation?
This seems like a hasOneThrough scenario but this doesn't exist. So what's the workaround?
I have tried a many-to-many relationship between articles and categories but how do I constrain the article from having more than one of each category type while attaching categories to single articles?
Schema::create('articles', function (Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->text('body');
$table->string('slug');
$table->timestamps();
});
Schema::create('categories', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->text('description');
$table->string('slug');
$table->string('handle');
$table->integer('category_group_id')->index()->nullable();
$table->timestamps();
});
Schema::create('article_category', function (Blueprint $table) {
$table->integer('article_id')->unsigned();
$table->integer('category_id')->unsigned();
$table->primary(['article_id', 'category_id']);
$table->timestamps();
});

Resources