I am creating a polymorphic relationship which defaults to null, as it doesn't have an association originally.
I then create the association and I want to be able to update the polymorphic table to have a link between the original and the morphed class.
post_images:
| id | post_id | width | height | created_at | updated_at
files:
| id | fileable_type | fileable_id | file_disk_id | created_at | updated_at
So basically, inside of the polymorphic table the type and the id they default to null as it has to be processed first and converted to a standard format etc.
I then create the associated row inside of the morphed table, however I am unsure how to update the polymorphic to have the type and the id from the morphed table.
I have tried to do something like $post->images()->create(...); and then try and do something like $file->where('id', $fileId)->firstOrFail()->associate($post); but this just seems to return null.
So the current process is:
Upload the file -> creates a row in the files table which contains the polymorphic relationships but columns are defaulted to null.
Standardize the file -> the file then gets converted and compressed into a standard format that is used for the site.
Create post_images row -> The site then creates a row for post_images table which then needs to link the update the files row to contain the new polymorphic relation.
Eloquent relationships:
File.php
public function fileable()
{
return $this->morphTo();
}
PostImage.php
public function file()
{
return $this->morphMany(File::class, 'fileable');
}
Post.php
public function images()
{
return $this->hasMany(PostImage::class);
}
I think you should just be able to call the save method on the relationship. For example:
$post->file()->save($file)
Related
I'm working on an older project that I've been tasked to speed up certain parts of while we work on a complete re-write since the code is just badly maintained, poorly written and outdated for what it's suppose to do.
I stumbled into an issue to the core of the project and because of this I can't change it without breaking almost everything else. So I need to load a "relation" the eloquent way (using Planning:with('availability') but there isn't a real foreign ID, it rather laps with multiple fields.
Would there be a way to load it all in one query with the overlapping fields rather than have it load separately creating an n+1 problem?
+--------------+-----------------+
| Planning | Availability |
+--------------+-----------------+
| planning_id | availability_id |
| date | date |
| startHour | startHour |
| stopHour | stopHour |
| candidate_id | candidate_id |
| section_id | section_id |
+--------------+-----------------+
From the above example you can see the overlapping fields are date, startHour, stopHour, candidate_id and section_id.
I tried get...attribute but that still loads with n+1, I tried including it with ->with(['availabilities']) but that doesn't work since I ask for the
model and not the relation:
Edit for more clarity:
Planning Model:
public function availabilities()
{
return Availability::where('section_id', $this->section_id)
->where('candidate_id', $this->candidate_id)
->where('planningDate', $this->planningDate)
->where('startHour', $this->startHour)
->where('stopHour', $this->stopHour)
->get();
}
public function availabilities2()
{
return $this->hasMany('App\Models\Availability', 'candidate_id', 'candidate_id')
}
Controller:
$plannings = Planning::with(['availabilities'])->get();
$plannings = Planning::with(['availabilities2' => function ($query) {
// $this is suppose to be Planning model but doesn't work
$query->where('section_id', $this->section_id)
->where('planningDate', $this->planningDate)
->where('startHour', $this->startHour)
->where('stopHour', $this->stopHour);
// ---- OR ---- //
// Don't have access to planning table here
$query->where('section_id', 'planning.section_id')
->where('planningDate', 'planning.planningDate')
->where('startHour', 'planning.startHour')
->where('stopHour', 'planning.stopHour');
}])->get();
First of all to be able to load my relation I took one of the keys that matched and took the one which had the least matches which in my case was section_id.
So on my Planning model I have a function:
public function availabilities()
{
return $this->hasMany('App\Models\Availability', 'section_id', 'section_id');
}
This way I can load the data when needed with: Planning:with('availability').
However since I had a few other keys that needed to match I found a way to limit this relation by adding a subquery to it:
$planning = Planning::with([
'availabilities' => function ($query) {
$query->where('candidate_id', $this->candidate_id)
->where('startHour', $this->startHour)
->where('stopHour', $this->stopHour);
},
// Any other relations could be added here
])
->get();
It's not the best way but it is the only way I found it not getting too much extra data, while also respecting my relationship
When you want to use multiple fields in where() method you most insert a array in the where() method:
This document can help you
change your code to this:
return Availability::where([
['section_id', $this->section_id],
['candidate_id', $this->candidate_id],
['planningDate', $this->planningDate],
['startHour', $this->startHour],
['stopHour', $this->stopHour]
])->firstOrFail();
I have these two models: Tag and Translate, I have these tables: tags, translates, translatables, Tag model uses translatable.
my table columns is like this:
translates: translatables: tags:
id name lang | translate_id translatable_id translatable_type | id
-- ---- ---- | ------------- --------------- ----------------- | --
| |
I want to write a function to get current translation of tag based on app locale which means I should query on translates tables based on translatables table data and using translateble_id and translatable_type find id in the translate table and get the name based on lang.
do you know how i can do this?
this is translatable trait:
trait Translatable{
public function translates(){
return $this->morphToMany(Translate::class,'translatable','translatables','translatable_id','translate_id');
}
}
and this is how I get locale:
$locale=app()->getLocale();
I get tags translates with querybuilder like:
$locale=app()->getLocale();
$tags=DB::table('translates as T')
->where('lang','=',$locale)
->join('translatables as R','R.translate_id','=','T.id')
->where('R.translatable_type','=','App\Models\Tag')
->join('tags as M','R.translatable_id','=','M.id')
->get();
but i want to use a function in model and eloquent.
I have an Employee evaluation form which stores the supervisor (FTO) and employee (FTE) in the database by their ID number (EID).
I can retrieve the data and display the EID of both the supervisor and the employee, but how can I setup it up to pull their names from the user table and display those?
My User Table
ID | EID | first name | last name | email | password
Evaluation Table
ID | ftoEid | fteEid | date | rating1 | etc...
Currently using in the model:
$dor = Dor::find($id);
return view('dor.show', compact('dor'));
You need to set up relationships.
class Evaluation extends Model {
public function user() {
return $this->belongsTo("App\User", 'fteEid');
}
}
Dor::find(1)->user->first_name;
Your field names are confusing so I am not sure if they are correct; hopefully you get the idea.
I've been dealing with this issue on almost every sync() to the pivot tables where, in Laravel 5.6, when I perform the following it adds one row that is non existent in the request:
$firm_data = request()->all(); // get the request data
$firm = Firm::where('id', request('firm_id')); // get the Firm model
$firm->update($firm_data); // update the model
// add the firm address with a belongsToMany() relationship set on Models\Firm and on Models\Address
$address = $firm->with('addresses')->first();
$addresses = request('addresses'); // get the request data for address
$address->update($addresses); // all ok till here
// deal with the pivot table
// here's the issue...
$address->cities()->sync([request('firm_id'), $addresses['city_id']]);
The firm data and the address data state is saved correctly in the DB, although, the pivot table is filled with two columns instead of one.
I have, in the whole request, one only city_id = 3034856 but to the pivot table it is added the first row firm_id = 1, city_id = 1, "which comes from nowhere":
The pivot table - firm_city
+---------+---------+
| firm_id | city_id |
+---------+---------+
| 1 | 1 |
| 1 | 3034856 |
+---------+---------+
Any thoughts on why this might be happening?
Just to make sure it's right, here the methods for each model Firm and Address:
// On the Firm model
public function cities()
{
return $this->belongsToMany(City::class, 'firm_city');
}
// on the City model
public function firms()
{
$this->belongsToMany(Firm::class, 'firm_city');
}
Thanks in advance for any insight on why this might be happening,
Remove the firm_id:
$address->cities()->sync([$addresses['city_id']]);
Eloquent gets the firm_id from $address, you don't have to specify it.
If you specify
it, Eloquent assumes that you want to sync a City with id=1.
I'm making a table that essentially maps rows in a table to rows in another table where the structures are as follows:
|--- Words --| |- Synonyms -|
|------------| |------------|
| id | | id |
| en | | word_id |
| ko | | synonym_id |
| created_at | | created_at |
| updated_at | | updated_at |
|------------| |------------|
Now then, I know I can essentially have the words model have many Synonyms through a function like:
public function synonyms()
{
return $this->hasMany('Synonym');
}
No problem, but this method always gets it by the the word_id, and I would like to get it from word_id OR synonym_id that way I don't have to make multiple entries in the DB.
Is there anyway I can do this?
Check laravel docs Eloquent relationships. It would only get word_id because that's the only foreign key I believe.
Also why do you have synonym_id in your Synonyms table?
I believe you are looking for polymorphic relationship.
http://laravel.com/docs/eloquent#polymorphic-relations
I think your best bet is to create a many-to-many relationship with words on itself using the synonyms table as your pivot table.
Add this to your Word model.
public function synonyms()
{
return $this->belongsToMany('Word', 'synonyms', 'user_id', 'synonym_id');
}
Using it:
$word = Word::where('en', '=', 'someword')->first();
foreach($word->synonyms as $synonym) {
// This method would probably return the same word as a synonym of itself so we can skip that iteration.
if($synonym->en == $word->en) {
continue;
}
// Echo the synonym.
echo $synonym->en;
}
I'm a bit confused on you wanting to be able to find synonyms by the word_id or synonym_id but I think if you are using the many-to-many, it won't matter because if you know the synonym, it's still technically just a word, and you'd do the exact same thing.