Revision #17 was created by grigori on Jan 21, 2020, 9:45:55 AM.
added a note on case conversion
Content
> I have a dream ...
> I am happy to join with you today in what will go down in history as the > greatest demonstration of
bad design of Active Record.
[...]
```php //check if value is a valid UUID
['id','match', 'pattern'=>'/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i'],
// convert UUID from text value to binary and store the text value in a private variable,
// this is a workaround for lack of mapping in active record
['id','filter','skipOnError' => true, 'filter' => function($uuid) {
[...]
if ($this->idText === NULL && $this->getIsNewRecord()){
//the filter did not convert ID to binary yet, return the data from input
return strtoupper($this->getAttribute('id'));
}
//ID is converted
return strtoupper($this->idText ?? $this->getAttribute('id_text'));
}
```
Active Record does not callWhen we call the `$model->id` property we need the `getter method if attributes contain the property. It should not be this way, so I return the default component behavior and make ID returned the right wayId()` executed. But Active Record base class overrides Yii compoent default behavior and does not call a getter method of an object if a property is a field in a table. So I override the magic getter.
From the other hand, the firsta regexp valiator I wrote calls `$model->id`, triggering the getter before the UUID is saved to the private property so I ne. I check if the object is newly created to serve the text value from user input.
It is strangeor validator.
Note the `strtoupper()` call: client may send UUID in both upper and low cases, but after unpacking from binary we will have a value in upper case. I received different string values before storing data to DB and after fetching it. Convert the textual UUID value to an upper or lower case everywhere to avoid problems.
It looks weird to mutate data in a validator, but I found this is the onlybest way. I belive I shouldn't use `beforeSave()` callback to set the binary value for generating SQL, and return the text value back in `afterSave()` - supporting this code would be a classic hell like `#define true false;`.
Step 4. Define the mapping for output
[...]
```
Step 5. Use Object Relation Mapping in Yii 3 when it's available and write simple mapping instead.mapping instead of these hacks.