Laravel multiple morph relation in one table - php

i have problem in laravel. i have created multiple morph in one table.
table structure
table_name : morphicable
id:
model_id: eg: '1'
model_type: eg 'model/comment'
model_one_id: eg: '1'
model_one_type: eg 'model/order'
in above relationship we can saving the data from comment to order and order to comment like many to manay.
Now the problem is that how to get the both data from one ORM method. like some time we save comment in model type and some time in model typeOne.
i want to get the data from both models in one go.
public function morphicable(): MorphMany
{
return $this->morphMany(morphicable::class, 'model');
}

Related

Getting multiple pivot tables results together as 1 data set

I have the following data structure in my laravel application
user_comments
id - integer
name - string
created_at - timestamp
user_actions
id - integer
name - string
created_at - timestamp
users
id - integer
name - string
user_history
user_id - integer
history_id - integer
history_type - string
And my App\Models\User contains the following relationships
/**
* Get all of the comments that are associated with this user.
*/
public function comments() : BelongsToMany {
return $this->belongsToMany(UserComment::class, 'user_history', 'user_id', 'history_id')->where('user_history.history_type', 'comment');
}
/**
* Get all of the actions that are associated with this user.
*/
public function actions() : BelongsToMany {
return $this->belongsToMany(UserAction::class, 'user_history', 'user_id', 'history_id')->where('user_history.history_type', 'action');
}
My aim is to be able to get each history type separately when I need it, but then be able to get all of the users history together, as a combined history trail of everything the user has done in the order it was done, so I can loop through and print out a history log.
At the moment the only way I can think of is by getting each of the relationships, merging the collections and sorting by created_at DESC, which is working fine, but in a perfect world, I would like to make 1 relationship (maybe polymorphic?) that just gets the actions and comments pivots together as 1 big collection.
As far as i'm aware, I cant UNION in the database as the tables have different column counts (and I need all the data from each table).
Is there a way to do this neatly using relationships to get the database to do the legwork, rather than having to get the relationships separately and merge/sort them?
Going forward there will be more pivot relationships like user_photos, user_emails, etc, so 1 neat way to get them all would be perfect!
Whenever you need interact with a pivot table, you can create a pivot model and use it as a normal model, or you can write a DB statement that will get the data. I like the model way better.
class UserHistory extends Pivot
{
// since Pivot extends Model
// this just a normal model
// with Pivot specific stuff.
}
DB statement can be something like this:
DB::select('select * from user_history');

I don’t know how to get data in laravel correctly by linking the data in this database

In this figure, the remaining tables are linked to the datainfo table. I need to retrieve the entire table data from the datainfo table.
In this picture I have shown the tables themselves
You can create Eloquent Models for each table and define Relationships among them. This is the Correct Laravel Way.
Let's assume Your datainfo table represents your Datainfo model,
Your cars table represents Car model. Same as washtypes and boxes.
then depending on your relation type defined the relation in Datainfo model.
class Datainfo extends Model
{
public function cars()
{
return $this->hasMany(Car::class);
}
}
You also can use hasOne instead of hasMany for one - to one relation
Similarly, create relation defining functions as washtypes() and boxes().
Then To get Datainfo with all related data using something like think in your controller
return Datainfo::with('cars','washtypes','boxes')->get();
Alternatively, you can get the count
return Datainfo::with('cars','washtypes','boxes')->count();
To get a count on a date
return Datainfo::with('cars','washtypes','boxes')->where('created_at',$date_var)->count();
If you only want Datainfo that has relation with cars, washtypes or boxes:
return Datainfo::has('cars','washtypes','boxes')->where('created_at',$date_var)->count();
Use laravel eloquent join clauses, https://laravel.com/docs/8.x/queries#joins
For total amount in same day
You can use eloquent sum and group by methods based on the date

Laravel Eloquent Model can't sync with pivot data in Many-to-Many relationship

I would like to sync the data instead of attach the data to the particular relationship.
Pivot relation UserModel code
public function carts(){
return $this->belongsToMany(Product::class,'user_carts')->withPivot('quantity');
}
The attach code is
User::find(1)->carts()->attach($s,["quantity"=>1]);
The sync code is
User::find(1)->carts()->sync($s,["quantity"=>1]);
When I try to compile the sync, those pivot relation that matched user_id = 1 does not have the "1" in its respective quantity column.
If I would like to achieve the sync function without using attach, how can I do it because the attach() will create multiple redundant data in my database.
You have to pass key values in the sync method.
Assuming $s is the id (key) to be synced:
User::find(1)->carts()->sync([$s => ["quantity"=>1]]);

Dynamic tables and models in Laravel 5

I have the next tables:
pages
id
title
...
dynamic_table_1_infos
id
page_id
image_id
dynamic_field_1
dynamic_field_2
...
dynamic_table_2_infos
...
So there are "one to many" relationships.
Is there any way to use a general approach without creating a DynamicTable[No]Info model "on the fly" for each table?
And what if I will need some extra methods in these models?
The "Page" model will have many relationships with "dynamic_table_[no]_infos" tables. So I will probably need a general method for doing this.
(Has many dynamic_table_1_infos / has many dynamic_table_2_infos ...)
What I am trying to do is somehow inspired by Dupal`s content types.
If you want to save a single model data to multiple tables depending on the value of some model attribute, you'll need to override model's getTable() method to return the name of the table it should write to.
I'm not sure how you want to decide to which table Eloquent should save to - for example, if you had an attribute called segment in your mode, you could just do:
public function getTable() {
return 'dynamic_table_' . $this->segment . '_infos';
}

Best way to apply Eloquent's ORM with Laravel?

I have two tables:
treatments (
id,
name
)
companies (
id,
name
)
And I need to build a relation to a "price" table. I thougth in something like follows:
prices (
treatment_id,
company_id,
price
)
But i don know how to apply the ORM to a php aplication. I'm using Laravel with Eloguent's ORM. I think that the real question would be if this is a good way to design the db. Perhaps I should make it diferent?
Any advices?
Thanks,
Ban.
If a Company can have multiple Treatments and a treatment can be bought from multiple companies at different prices, then you have a Many-to-many relationship, with prices being the pivot table (which if you would adhere to convention would be named company_treament, but that's not a must). So you'll need to have two models for Treatments and Companies, which would look like this:
class Company extends \Eloquent {
public function treatments()
{
return $this->belongsToMany('Treatment', 'prices')->withPivot('price');
}
and
class Treatment extends \Eloquent {
public function companies()
{
return $this->belongsToMany('Company', 'prices')->withPivot('price');
}
}
The treatments() and companies() methods from the models are responsible for fetching the related items. Usually the hasMany method only requires the related model as the first parameter, but in your case the pivot table name is non-standard and is set to prices by passing it as the second parameter. Also normally for the pivot table only the relation columns would be fetched (treatment_id and company_id) so you need to specify the the extra column using withPivot. So if you want to get the treatments for a company with the id 1 list you whould to something like this:
$treatments = Company::find(1)->treatments;
The opposite is also true:
$companies = Treatment::find(1)->companies;
If you need to access the price for any of those relations you can do it like this:
foreach ($treatments as $treatment)
{
$price = $treatment->pivot->price;
}
You can read more about how to implement relationships using Eloquent in the Laravel Docs.
EDIT
To insert a relation entry in the pivot table you can use attach and to remove one use detach (for more info read the Docs).
$treatment->companies()->attach($companyId, array('price' => $price));
$treatment->companies()->detach($companyId);
To update a pivot table entry use updateExistingPivot:
$treatment->companies()->updateExistingPivot($companyId, array('price' => $price));

Categories