Hi I have a table in my database which contains a column with integer values which are actually the primary key of another tabel
Table 1: Details
column : subjects
value : 12,10,1,50,89,88
And another table is subject from where I should fetch the result. I want to know if I can fetch them using my model instead of repeating my code in controller everytime I need to fetch them.
I know you can define relations using
$this->belongsTo()
Or hasMany() depending on circumstances. I want to see If I can use this using scope on Model.
The final result I am looking for is json data returned from table Subject
I would recommend using a polymorphic relationship for this rather than the way you are comma delimiting in a single database table field.
You will have a new record for each association which may seem bad to you at first but it really is worthwhile, work with Eloquent so you don't need to add custom logic to explode those id's and associate manually.
students
id - integer
name - string
subjects
id - integer
name - string
subjectable_id - integer
subjectable_type - string
Then in your models something like this
class Subject extends Model
{
/**
* Get all of the owning subjectable models.
*/
public function subjectable()
{
return $this->morphTo();
}
}
class Student extends Model
{
/**
* Get all of the post's comments.
*/
public function subjects()
{
return $this->morphMany('App\Subject', 'subjectable');
}
}
You can then attach subjects to many different models the same way I demonstrated it attached to Students here.
Edit: If you would like to keep with your same interpretation of how this data is used, you could potentially do this in the Model but it's difficult to say without seeing the logic you are trying not to repeat.
Related
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');
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
I'm just getting going with Laravel, and have used Eloquent to define my Campaign table. I have a Campaign model which is currently empty.
I'm not sure how to add attributes to this model to represent the fields in the db - or even if I should. The Laravel documentation seems thin on models and searches keep leading me to accessors and mutators.
If I have a database field called platform_type in my campaigns table, how do I link the PlatformType model attribute to this field?
To clarify:
This is not a question about relationships - there is only one entity in my solution thus far.
platform_type is a field in my campaigns table because it is an attribute of a campaign - I'm asking how to represent this in my model.
The model has an internal array which stores the attributes of a given row (it's called $attributes and replicated by $original if you look for them in the source code). The reason it's replicated is so when you call save() it will only do a save if you actually changed them from the originals.
You can access said attributes via $modelInstance->getAttribute("platform_type") or $modelInstance->platform_type which will call the magic __get method that in turn calls the getAttribute
So in your case you can have:
$campaign = Campaign::find($id);
echo $campaign->platform_type;
The ORM will automatically create the relevant SQL query and fill the model instance with the attributes of the row it finds.
You need to define relationships. In the PlatformType model:
public function campaigns()
{
return $this->hasMany(Campaign::class, 'platform_type');
}
And in the Campaign model:
public function platformType()
{
return $this->belongsTo(PlatformType::class, 'platform_type');
}
You also need to rename the campaign table to campaigns. Or you should add this to the model to be able to use a custom name:
protected $table = 'campaign';
At this point, these tables will be connected and relationships will work. However, it is recommended to add foreign key constraints.
I have 3 tables namely A, B and C.
All 3 of them need to make use of a notes table(i.e. A has many notes and a note belongs to A. The same follows for remaining 2 tables).
So I created 3 more tables: A_note, B_note and C_note(as mentioned here: multiple tables need one to many relationship).
Is there a way to do CRUD operations on these tables(A_note, B_note and C_note) similar to the way we handle pivot table in many-to-many relationship?
Please suggest a way forward.
You should be using polymorphic relationships for this. It allows multiple models to make use of a single table.
Have a look at the documentation here
In your particular case, each of your tables would reference a noteable_id column and a noteable_type.
The noteable_id will contain the id of the (A/B/C) model.
The noteable_type will contain the string name of the model (A/B/C).
The (A/B/C) models will now get a new attribute:
/**
* (A/B/C) Model(s)
*/
public function notes()
{
return $this->morphMany('App\Notes', 'noteable');
}
And the note model will initiate it's polymorphic properties against the attribute name used to identify your polymorphic ids and types:
/**
* Note Model
*/
public function noteable()
{
return $this->morphTo();
}
Now you can simply call ->noteable on the (A/B/C) models, and they all share 1 table without the need of another pivot table for each table.
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';
}