How to get relation 'table1' OR 'table2' OR 'table3' into one table in laravel? - laravel

I'm a newbie here and also in Laravel, so please excuse me. I have a table named 'products' and this table related to the 'recipes' table via many-to-one relation(One of the recipes has a lot of products). -'recipes' table keeps reference code- Here's where I stuck; the 'recipes' table has one-to-one relations to three different tables that keeping the "real" product recipes. Those tables have different recipe contents like,
Alkaline table;
Schema::create('alkalines', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('recipe_id');
$table->integer('sodium_bicarbonate');
$table->timestamps();
});
Acets table;
Schema::create('acets', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('recipe_id');
$table->integer('sodium_chloride');
$table->integer('acetic_acid');
$table->timestamps();
});
I'm able to fetch all relations if I start with one of these(e.g with Acet model). But if, I list all of products and try to fetch it's recipe, I have to use a bunch of 'if and else's. Just can't get the recipe like;
$product->recipe-> "one of the three recipe tables' content"
And my 'recipes' table:
Schema::create('recipes', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('ref');
$table->timestamps();
});
I believe it's easy, just missing something. Please help! Thanks in advance!

I think
You can get every relation individual them merge the arrays
like
$arr1=Alkalines::with('recipe')->get()->toArray();
$arr2==Acets::with('recipe')->get()->toArray();
$arr3=***************************;
array_merge($arr1,$arr2,$arr3)

Welcome to SO.
If you have relations set up properly, you can use 'collection->pluck()' to retrieve their results, no matter how deeply nested in different relations.
Example:
$game->players->stats won't work, because players is a collection that doesn't have a stats attribute, method or field.
So, what you can do is use pluck() and collapse() to retrieve result of relations:
$game->players->pluck('stats')->collapse()

I edit the code from #mohamedhassan a little bit, and it worked!
public function solutionMerge()
{
$arr1=Alkaline::with('recipe')->get();
$arr2=Acet::with('recipe')->get();
$arr3=Glucose::with('recipe')->get();
$solutionMerge = collect([$arr1,$arr2,$arr3]);
return $solutionMerge;
}
Just assigned arrays into a collection. And then use collapse().
And now, I'm able to fetch data like $solutionMerge->recipe->id
Thank you people, for your precious time and immense knowledge!

Related

Laravel - is there a library that lets me do a hasManyThrough relationship where my models PK is either value

Is there a library where I am able to use a pivot table that points to the same model twice (i.e User) where I can have the PK as either column 2 or 3 for something like a friending or associating system?
Code Example
migration
Schema::create('friends', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('requestor_id');
$table->unsignedBigInteger('requested_id');
$table->boolean('accepted')->default(0);
});
model
public function friends(){
return $this->[LibraryMethod](Friend::class, 'requestor_id', 'requested_id')->where('accepted', 1);
}
So then I could then either look at 'requestor_id' or 'requested_id' for my PK and get the PK of an associated User.
Ideally this should also work with eloquent functions.
I recognise that friends isn't the best example as you could have a handshake-like system, but for simple associations (i.e, between products) something like this would be pretty useful.

Struggling to define a polymorphic relationship which includes a BelongsTo

I'm working on a text-based, rng-based motorsport "simulator" and I'm now at the point where I want to add qualifying. Since there's many different types of qualifying sessions across real life motorsport, I want to give the user the ability to use whatever format they like.
I have a Season model, to which the a qualifying format will belong. The different formats are defined as separate models themselves, for example ThreeSessionElimination and SingleSession. The migrations for these would look something like this;
Schema::create('three_session_eliminations', function (Blueprint $table) {
$table->unsignedBigInteger('id')->primary();
$table->foreignId('season_id')->constrained();
$table->unsignedInteger('q2_driver_count');
$table->unsignedInteger('q3_driver_count');
$table->unsignedInteger('runs_per_session');
$table->unsignedInteger('min_rng');
$table->unsignedInteger('max_rng');
$table->timestamps();
});
and
Schema::create('single_sessions', function (Blueprint $table) {
$table->unsignedBigInteger('id')->primary();
$table->foreignId('season_id')->constrained();
$table->unsignedInteger('runs_per_session');
$table->unsignedInteger('min_rng');
$table->unsignedInteger('max_rng');
$table->timestamps();
});
My initial thought was to add
public function season(): BelongsTo
{
return $this->belongsTo(Season::class);
}
to each qualifying format model, but obviously the inverse can't be a HasOne since there's different tables for each different format.
I've had a look at the "One To Many (Polymorphic)" relation documentation, but I can't quite wrap my head around how I should apply that in my case. Would I have to add a qualifying_format_id and qualifying_format_type to my Season model and remove the season_id column from each format migration to make this work?

How to model a dependency graph in Laravel

I am stuck modelling the following relationship in a new application:
A Module can require (many) other Modules.
In Laravel I added the Module model and a ModuleRequirement model with its migrations. The second one has a foreign id field for the module it belongs to:
Schema::create('module_requirements', function (Blueprint $table) {
$table->id();
$table->foreignId('module_id')->constrained();
// How to reference other modules?
$table->integer('requires');
});
The relationship itself is defined by:
// Module.php
public function moduleRequirements()
{
return $this->hasMany(ModuleRequirement::class);
}
This method returns a collection of ModuleRequirements as expected. Unfortunately in order to get the real Module objects I need a foreach loop and build my own collection. I wonder if there is a simpler and faster solution. The perfect way I could imagine is sth. like $module->moduleRequirements returning a collection of the actual models instead of its ids.
My understanding that a module has relation with other modules in the same table.
you should use many to many relationship ,in that case you will not need a model for ModuleRequirement just a pivot table would be sufficient.
In your case module_requirements would act as the pivot table and you just need to change the relation in Module.php to :-
public function moduleRequirements(){
return $this->belongsTomany(Module::class,"module_requirements", 'module_id', 'requires');
}
the migration should be something like :-
Schema::create('module_requirements', function (Blueprint $table) {
$table->foreignId('module_id');
$table->foreignId('requires');
$table->foreign('module_id')->references('id')->on('models')->onDelete('cascade');
$table->foreign('requires')->references('id')->on('models')->onDelete('cascade');
});

Best practice for storing a polymorphic belongsTo relation

We have a need for multiple models to share a documents relation. Due to that, I've used a polymorphic one to many as per the below schema.
Schema::create('client', function (Blueprint $table) {
$table->id();
$table->string('name');
});
Schema::create('documents', function (Blueprint $table) {
$table->id();
$table->foreignId('type_id')->constrained('document_types');
$table->string('path'),
$table->morphTo('documentable');
});
Documents Model
public function documentable()
{
return $this->morphTo();
}
Client Model
public function documents()
{
return $this->morphMany(Document::class, 'documentable');
}
Each document will need to relate to a specific type. For example, one document might relate to the customers signed agreement and another may relate to a completely different document - These types will need to be 'query-able'.
What's the best way to proceed with this? As far as I'm aware, my options are;
Create a document_types table and set a belongsTo relation on the documents table.
Create an enum column on the documents table.
A side note on this. This will be consumed via an API. There will be the following resources:
Route::apiResource('client', 'ClientController');
Route::apiResource('client.documents', 'ClientDocumentController');
With whichever solution is proposed above, how would you propose the API handles the document type when creating/updating a document?
If the use of a documents_type table, would the end-user have to hit a resource for the document type, to obtain the document type ID prior to creating/updating a document?
If the use of enums, would the API just expect a string for the given document type?
Many thanks in advance.

How to create a new many to many record with attach

Okey, i seen some posts about this but i don't understand the concept of attach at all, i have three tables:
Llistes(Lists):
$table->increments('id');
$table->string('nom_llista');
$table->integer('user_id')->unsigned();
});
Cancons(Songs):
$table->increments('id');
$table->string('titol');
$table->integer('genere_id')->unsigned();
$table->integer('artista_id')->unsigned();
$table->integer('album_id')->unsigned();
Pivot table: llistes_cancons (lists_songs):
$table->increments('id');
$table->integer('id_canco')->unsigned();
$table->integer('id_llista')->unsigned();
$table->timestamps();
I have two other Classes that i think that are correct, but i''m not sure:
In Canco.php (Song.php):
public function llistescancons_llistes()
{
return $this->belongsToMany('App\Llista');
}
In Llista.php (List.php):
public function llistescancons_cancons()
{
return $this->belongsToMany('App\Canco');
}
So, the question is how can I implement in my controller a function that let me add new record to the pivot table (many to many) and if it's possible another funtion to show the records, i'm newbie in Laravel and it's a bit hard for me.
There's no need to implement methods to add/remove records from the pivot table. Eloquent has attach/detach methods that can do that for you, but first you need to give Eloquent the column names of the pivot table since you are not using Eloquent's column name convention.
In Canco.php (Song.php):
public function llistescancons_llistes()
{
return $this->belongsToMany('App\Llista','llistes_cancons','id_canco','id_llista');
}
In Llista.php (List.php):
public function llistescancons_cancons()
{
return $this->belongsToMany('App\Canco','llistes_cancons','id_llista','id_canco');
}
Then if you want to attach a song to list, you can easily use the song id to do that
$list = App\Llista::find(1);
$list->llistescancons_cancons()->attach($songId);
or the other way around
$song = App\Canco::find(1);
$song->llistescancons_llistes()->attach($listId);

Resources