I want to create a somewhat polymorphic laravel morphTo.
I want to create multiple 'dimension' polymorphic properties but don't see a need to create four separate (identical) tables for their values (width, length, height, weight).
The problem is, I just stumbled upon how it creates the linking and I'm not quite sure how to specify the type of dimension.
I was looking at creating an abstract 'Dimension' model then wrapping it with inherited 'Width', 'Length', 'Height' and 'Weight' models that would set the 'axis' attribute before calling the parent __constructor($attributes)
I thought I found the solution but it does not seem to be working. I created a 'widthable' method in my Width() class (inherited from DimensionAbstract) and gave it the name and id fields 'dimensionable_name', 'dimensionable_id' respectively. e.g.:
public function widthable()
{
return $this->morphTo(__FUNCTION__, 'dimensionable_type', 'dimensionable_id');
}
But it complains that widthable_id column not found. Is there some way to key a morphOne (or a pseudo variant of same) hinging on one of the properties of the morphed class? (In my case, I use an enum for 'axis' that can include 'width', 'length', 'height' or 'weight' - then I set that attribute in the constructor) I was trying to do similar things in each of the other inherited classes for Length, Height and Weight.
CodePudding user response:
So as far as I can understand you have a table called dimensions and you want to use id dynamically.
Why aren't you creating a model called Dimension, than create other separate models for Width, Length, Height and Weight which will extend that Dimension model, and on every model that extends Dimension use a global scope where you filter on axis for ex. ->where('axis', 'width')
, and make a function in each Model such as setAxisAttribute()
which sets axis to corresponding value based on model ex:
public function setAxisAttribute($value)
{
$this->attributes['axis'] = 'width';
}
Or maybe I didn't understand you correctly.
CodePudding user response:
After deep tracing the code, I finally figured out what I needed (which was something I half expected). To use the different keys, I also needed to define them on the morphOne side as well as the inverse morphTo. Then find the one that matched when pulling the result of what was actually a morph one from many (the documentation was not clear on that). e.g.:
public function width()
{
return $this->morphOne(Height::class, __FUNCTION__.'able', 'dimensionable_type', 'dimensionable_id')->where('axis', __FUNCTION__);
}
I also have a similar (actual) morphOne for pricing information. Currently it's still basic enough it could technically be supported by the same framework, but I want to add additional method-behaviors to pricing such as having the value represent a percentage that can be used as a modifier on the total price for sub-component parts. (e.g. select option 'a' and get 10% off)
I'm now thinking that for these basic key/value/unit properties, I can wrap them in a single 'dimensions' class to act as a go between then use a magic method for handling the morphOne (technically many-to-one) relations.