Laravel naming convention with similar Model names - php

This is a very basic question but trying to wrap my head around the preferred naming conventions for models/tables with similar names.
A model 'Task' can have many 'Comments' so the tables would be
- tasks
- comments (with a foreign key for task_id)
However, I have another model 'Post' which will also need a 'Comments' which is of course separate from the Comments for Tasks
In this scenario, does one generally go with
- Task & TaskComment (model) / tasks & task_comments (database table)
- Post & PostComment (model) / posts & post_comments (database table)
or some other convention?

If you use polymorphic relations you can even make a Comments has its own comments (like a reply system).
In the model you want to have comments you need to add a method like this:
public function comments() {
return $this->morphMany(Comment::class, 'commentable');
}
Then in your Comment model, you just add
public function commentable() {
return $this->morphTo();
}
Notice how important it is that your method name in Comment matches with the second parameter passed to the morpMany() function.
Last but not least, the model in which you morph to needs to have special fields in its schema:
You must place them at the end of the traditional schema structure:
// Your comment dedicated schema
$table->integer('commentable_id');
$table->string('commentable_type');
I really don't know if it is important but notice how the field prefix matches with the method name in which we are morphing.

What you want for this is polymorphism.
Follow the example on https://laravel.com/docs/5.4/eloquent-relationships#polymorphic-relations . It's really close to what you are trying to do, so hopefully it will be enough. If you get stuck let me know and i'll help you along

Related

Select other data in another table using eloquent

I have cases, cases_judges, judges and witness tables.
A case can have many judges and witness
I want to be able to select all the judges and witness associated to a case
I don't know how to create a relationship between case and judges because their is no direct link between judges and case. Cases_judges is the only intermediary between case and judge. I also tried using Hasmanythrough relationship but without success
Cases model
public function case_judges(){
return $this->hasMany(Cases_judges::class,'case_id','id');
}
public function witness(){
return $this->hasMany(Witness::class,'case_id','id');
}
public function judges(){
return $this->hasManyThrough(Judges::class, Case_judge::class,'judge_id','id');
}
Judges model
public function judges(){
return $this->hasMany(Case_judge::class,'case_id','id');
}
Cases_judge model
public function case(){
return $this->belongsTo(Cases::class);
}
Cases Controller
My case controller is something like this
public function index()
{
return Cases::with('case_judge','witness')->get();
}
This fiddle (http://sqlfiddle.com/#!9/217dcb/2/0)shows how I would have done it using raw query but I want to do it the eloquent way
To arrive at the solution, first we have to uncover what really is the relationship between your Case and Judge models.
The simplified diagram highlights the connection between your Case and Judge models via an intermediate CaseJudge model. Indeed, a Case really can have multiple Judges. However, we must not miss out the fact that a Judge can handle multiple Cases.
From this, we can conclude that Case and Judge models have a many-to-many relationship.
To establish a many-to-many relationship between models in Laravel, you must use belongsToMany relationship method, as opposed to hasManyThrough which only applies to one-to-many relationship.
class Cases extends Model {
...
public function judges() {
return $this->belongsToMany(Judges::class, 'case_judges', 'case_id', 'judge_id');
}
}
Here, belongsToMany has four arguments:
Model that has the many-to-many relationship with our Cases model.
Intermediate table connecting tables cases and judges.
Foregin key on intermediate table that connects to table cases.
Foregin key on intermediate table that connects to table judges.
When all is set and done, running:
return Cases::with(['judges', 'witness'])->get();
will now return what you want — a collection of cases, along with witnesses and judges associated to their respective cases.
As a side note: you might want to follow Laravel's conventions on naming things, to avoid running into weird default Eloquent behaviors as consequence, and enjoy any conveniences it brings when you conform to these conventions.
I think cases and judges are 'Many to Many' relationship with intermediate table cases_judges.
You can follow this document to setup this : https://laravel.com/docs/9.x/eloquent-relationships#many-to-many

Laravel model relation - change to mutator, without chaning anything in cotrollers

I have 2 tables, estimates and models.
There's a 1-to-1 relation between the two.
I want to move model names from the models table to the estimates table. That will be done with a script that I will have to write myself.
The way this database was set up was wrong, for many reasons I don't need to specify here.
The models table has only 2 columns - id and name.
I access this relation in a lot of controllers, and views all over my app :
$estimate->model_info->name
So I would keep both the models table (with no records) and the Model.php model, keep the old code in the controllers and views, but the new code of accessing model names would be just :
$estimate->name
In the Estimate.php model I have this relation :
public function model_info() {
return $this->hasOne('App\Models\Model', 'id', 'model_id');
}
How can I just change this relation into a mutator, so the old way of accessing model names and the new way would work at the same time?
I've tried the withDefault() callback method with no luck, it returns an empty value :
public function model_info() {
return $this->hasOne('App\Models\Model', 'id', 'model_id')
->withDefault([
'name' => $this->attribute->name
]);
}
Do I have to update my code in all controllers and views or if there's an easier way to do this?

how to implement sub model in Laravel

my base class is post
and many submodel such as : video post , image post
all class have specific attribute & inherit parent attrib
& all class need specific behaviors
Problem
when find on post model elequent give super model(post) instance, its wrong
i need instance of submodel
If I understood you correctly, you need relationships
Add a hasMany relationship to your Post.php model:
public function videos()
return $this->hasMany(App\PostVideo::class);
}
As long as your post_video table has a post_id column that references a post, you can call this relationship like this:
foreach($post->videos as $video) {
// Do something
}
And the inverse relationship:
Add a relationship to your PostVideo.php model:
public function post() {
return $this->belongsTo(App\Post::class);
}
And of course, if you have a video, you can access the post it belongs to by doing:
$video->post
It is looked like you want a single table inheritance. In laravel this could be done manually or use package like nanigans or intrip. To use single table inheritance manually, i could suggest you start with reading this stackoverflow question first. However, notice that single table inheritance put everything in a single table but refered by several models that have different behavior. If this is not what you want, just use simple eloquent queries and models - which already explained by Pistachio.

Linking a Model (ie. comment) to many other Models (ie. post, profile)

I am building a PHP application with Laravel where I have a Comment Model and many other models to which Comment can be attached to.
For example, a Profile can have many Comment but also a Post can have many Comment.
Should I split Comment in two models (ProfileComment and PostComment) or should I keep them together like this?
class Comment {
public function user()
{
return $this->hasOne('User');
}
public function profile()
{
return $this->belongsTo('Profile');
}
public function post()
{
return $this->belongsTo('Post');
}
}
If I keep them together, then on a database level how should I manage the comments table?
I was thinking about having the following columns:
integer: id - auto-incrementing id
integer: user_id - the user id
integer: foreign_id - profile/post id
varchar: type - which model? profile or post?
varchar: content - the actual comment
Is this the wrong approach?
if you want to use 1 table you will need to make Comment model morph.
if you don't want to use morph, make separated.
I think if you will use schema from your question, you will use morph.
I don't tkink where is need to make more tables, because all comments will have same structure (id, user_id (author), comment)
so in this case you will need just to make it morph (tagable).

How to implement CRUD with many:many relationship

I'm new to atk4, but I couldn't find some simple examples for using CRUD with many:many relationships between tables.
I read in some instructions that M:M is best implemented with intermediate table, which seems logical.
For example
Model ONE has:
$this->hasMany('Table1Table2','table1_id');
Model TWO has:
$this->hasMany('Table1Table2','table2_id');
And Intermediate Model (Table1Table2) has:
$this->hasOne('Table1');
$this->hasOne('Table2');
Which generates this table, which is OK:
create table table1table2 (
id int auto_increment not null primary key,
table1_id varchar(255),
table2_id varchar(255));
But how to implement CRUD? - how to implement listings, adding new, edit etc..
When on page I simply insert like this:
$this->add('CRUD')->setModel('Table1');
There is no relationship generated... It would be nice that user could select (on add and edit of table1) values from table2.
From reading and watching tutorials I have idea, but maybe is totally overwork, so I'm really asking what is the best way at ATK4 for this problem?
My idea:
add multiple dropdown to edit and add form and populate it with table2 values. If in edit, check in intermediate table for what is already checked.
extend basic CRUD, on formSubmitSuccess insert selected values from dropdown to intermediate table
do it differently for edit/add new..
later, do similar check for GRID&other stuff... can generate a lot of extra work..
So, I see its doable, but I'm sure M:M relationships are very common (it's basically two 1:M), so maybe is there much better solution?
No doubts you'll need intermediate table in relational DB design.
Question is, how you define Models. One solution is, as you already explained yourself, with 3 models. But you can also do something similar with just two models and using joins in your model definitions to join them directly to intermediate DB table.
Idea here is - Model is not the same as DB table in general. Model is something more than DB table. One model can join up like 10 tables and do something fancy with them :)
I guess there is no nice out-of-the-box solution for such interface (View) which will fit all needs. But in some cases, if you only need to set links (yes/no) between two tables, you can use form + grid + grid->addSelectable() or form + crud + crud->grid->addSelectable(). With such construct you can, for example, associate multiple user roles to users or Apps to Admins or favorite colors to people etc.
If you have more data fields in intermediate table than just linking id's, then you'll have to come up with some custom code. But I guess you can still take a peek on grid->addSelectable() method to grab some idea.
P.S. Sorry, this time I have no ready-to-use example :)
You need to create proxy table and create one to many relations between three tables
class Model_Admin extends Model_Table {
function init() {
parent::init();
$this->haveMany('AdminApp');
}
}
class Model_App extends Model_Table {
function init() {
parent::init();
$this->haveMany('AdminApp');
}
}
// this is proxy table
class Model_AdminApp extends Model_Table {
function init() {
parent::init();
$this->haveOne('Admin');
$this->haveOne('App');
}
}
actually there is no other way to create many-to-many relations

Categories