From 79d4fd2ea117f5eb2c713aaf6f7f4b1413d6b38d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Nowacki?= Date: Sat, 22 Dec 2018 11:50:10 +0100 Subject: [PATCH 1/2] Nullable support for __set. I wrote it and works like a charm. Slightly more efficient, because I some of array_key_exists don't exist anymore ;). But... I noticed an issue when I am trying to save this entity. Property which is set to null is excluded from INSERT what should cause problem if default column value is not set to null but different value - in that case we cannot save null during insert. In my case should be: ``` INSERT INTO `t_table_search` (`dcs_identifier`, `dcs_conditions`, `dcs_dsc_id`) VALUES ('e77d630b7be1484cb4b7b4f8dbc15c45', '{\"v-school\":[\"1\"],\"v-center\":[\"44\"]}', NULL) // dcs_dsc_id = null; ``` it is: ``` INSERT INTO `t_table_search` (`dcs_identifier`, `dcs_conditions`) VALUES ('e77d630b7be1484cb4b7b4f8dbc15c45', '{\"v-school\":[\"1\"],\"v-center\":[\"44\"]}')// no null for dcs_dsc_id ``` I think it is because of entity value of property in _original is the same as actual value of property (i.e.: dcs_dsc_id == null) ```object(App\Entities\entityname)#40 (7) { ["dcs_identifier":protected]=> string(32) "e77d630b7be1484cb4b7b4f8dbc15c45" ["dcs_conditions":protected]=> string(52) "{"driving-school":["1"],"examination-center":["44"]}" ["dcs_dsc_id":protected]=> NULL ["dcs_updated_at":protected]=> NULL ["_options":protected]=> array(3) { ["casts"]=> array(3) { ["dcs_identifier"]=> string(6) "string" ["dcs_conditions"]=> string(10) "json-array" ["dcs_dsc_id"]=> string(11) "?json-array" } ["dates"]=> array(2) { [0]=> NULL [1]=> string(14) "dcs_updated_at" } ["datamap"]=> array(0) { } } ["_original":protected]=> array(4) { ["dcs_identifier"]=> NULL ["dcs_conditions"]=> NULL ["dcs_dsc_id"]=> NULL ["dcs_updated_at"]=> NULL } ["_cast":"CodeIgniter\Entity":private]=> bool(true)``` I saw PR month or two ago which was changing entity saving but IMHO it should be turned ON for update or replace but should NOT work for INSERT. --- system/Entity.php | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/system/Entity.php b/system/Entity.php index 5068762507b1..8626f5662ec4 100644 --- a/system/Entity.php +++ b/system/Entity.php @@ -267,24 +267,38 @@ public function __set(string $key, $value = null) $value = $this->mutateDate($value); } - // Array casting requires that we serialize the value - // when setting it so that it can easily be stored - // back to the database. - if (array_key_exists($key, $this->_options['casts']) && $this->_options['casts'][$key] === 'array') + $is_nullable = false; + $cast_to = false; + + if(array_key_exists($key, $this->_options['casts'])) { - $value = serialize($value); + $is_nullable = substr($this->_options['casts'][$key],0,1) === '?'; + $cast_to = $is_nullable ? substr($this->_options['casts'][$key], 1) : $this->_options['casts'][$key]; } - // JSON casting requires that we JSONize the value - // when setting it so that it can easily be stored - // back to the database. - if (function_exists('json_encode') && array_key_exists($key, $this->_options['casts']) && ($this->_options['casts'][$key] === 'json' || $this->_options['casts'][$key] === 'json-array')) + if(!$is_nullable || !is_null($value)) { - $value = json_encode($value); + // Array casting requires that we serialize the value + // when setting it so that it can easily be stored + // back to the database. + if ($cast_to === 'array') + { + $value = serialize($value); + } + + // JSON casting requires that we JSONize the value + // when setting it so that it can easily be stored + // back to the database. + if (($cast_to === 'json' || $cast_to === 'json-array') && function_exists('json_encode')) + { + $value = json_encode($value); + } + } // if a set* method exists for this key, // use that method to insert this value. + // *) should be outside $is_nullable check - SO maybe wants to do sth with null value automatically $method = 'set' . str_replace(' ', '', ucwords(str_replace(['-', '_'], ' ', $key))); if (method_exists($this, $method)) { @@ -304,6 +318,7 @@ public function __set(string $key, $value = null) return $this; } + //-------------------------------------------------------------------- /** From 843cc9eada94fbd02894861b04eb1d667f834109 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Nowacki?= Date: Mon, 31 Dec 2018 10:26:41 +0100 Subject: [PATCH 2/2] Update Entity.php --- system/Entity.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/system/Entity.php b/system/Entity.php index 8626f5662ec4..3ff5b7ce675b 100644 --- a/system/Entity.php +++ b/system/Entity.php @@ -267,21 +267,21 @@ public function __set(string $key, $value = null) $value = $this->mutateDate($value); } - $is_nullable = false; - $cast_to = false; + $isNullable = false; + $castTo = false; if(array_key_exists($key, $this->_options['casts'])) { - $is_nullable = substr($this->_options['casts'][$key],0,1) === '?'; - $cast_to = $is_nullable ? substr($this->_options['casts'][$key], 1) : $this->_options['casts'][$key]; + $isNullable = substr($this->_options['casts'][$key],0,1) === '?'; + $castTo = $isNullable ? substr($this->_options['casts'][$key], 1) : $this->_options['casts'][$key]; } - if(!$is_nullable || !is_null($value)) + if(!$isNullable || !is_null($value)) { // Array casting requires that we serialize the value // when setting it so that it can easily be stored // back to the database. - if ($cast_to === 'array') + if ($castTo === 'array') { $value = serialize($value); } @@ -289,7 +289,7 @@ public function __set(string $key, $value = null) // JSON casting requires that we JSONize the value // when setting it so that it can easily be stored // back to the database. - if (($cast_to === 'json' || $cast_to === 'json-array') && function_exists('json_encode')) + if (($castTo === 'json' || $castTo === 'json-array') && function_exists('json_encode')) { $value = json_encode($value); } @@ -298,7 +298,7 @@ public function __set(string $key, $value = null) // if a set* method exists for this key, // use that method to insert this value. - // *) should be outside $is_nullable check - SO maybe wants to do sth with null value automatically + // *) should be outside $isNullable check - SO maybe wants to do sth with null value automatically $method = 'set' . str_replace(' ', '', ucwords(str_replace(['-', '_'], ' ', $key))); if (method_exists($this, $method)) {