-
tomasoma Junior Member
 
-
Posts: 16
Threads: 6
Joined: Feb 2015
Reputation:
0
Hello,
I just followed the documentation about the Entity getCreatedAt() function (on this page https://codeigniter4.github.io/userguide...ness-logic) but it don't understand why the date format i set is ignored :
Model :
PHP Code: <?php namespace App\Models ;
use CodeIgniter\Model ;
class UserModel extends Model {
protected $table = 'user'; protected $primaryKey = 'id'; protected $returnType = 'App\Entities\User'; protected $useSoftDeletes = true ; protected $allowedFields = ['email','password','level','civilite','prenom','nom','sign','tel','add1','add2','cp','ville','pays'] ; protected $dateFormat = 'int' ; protected $useTimestamps = true ; protected $createdField = 'created_at' ; protected $updatedField = 'updated_at' ; protected $deletedField = 'deleted_at' ; protected $validationRules = [] ; protected $validationMessages = [] ; protected $skipValidation = false ;
}
Entity :
PHP Code: <?php namespace App\Entities ;
use CodeIgniter\Entity ; use CodeIgniter\I18n\Time;
class User extends Entity { protected $attributes = [ 'id' => null , 'email' => null , 'password' => null , 'level' => null , 'civilite' => null , 'prenom' => null , 'nom' => null , 'sign' => null , 'tel' => null , 'add1' => null , 'add2' => null , 'cp' => null , 'ville' => null , 'pays' => null , 'created_at' => null , 'updated_at' => null , 'deleted_at' => null ] ;
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
public function identite(){ return trim($this->civilite.' '.ucwords($this->prenom)).' '.strtoUpper($this->nom) ; } # /identite()
public function adresse() { $t = $this->add1 ; if(trim($this->add2) != '') $t .= '<br >/'.$this->add2 ; $t .= '<br />'.$this->cp.' '.strtoupper($this->ville) ; if(trim(strtolower($this->pays)) != 'france') $t .= '<br />'.$this->pays ; return $t ; } # /adresse()
public function getCreatedAt(string $format = 'd/m/Y H:i:s') { $this->attributes['created_at'] = $this->mutateDate($this->attributes['created_at']) ; $timezone = $this->timezone ?? app_timezone() ; $this->attributes['created_at']->setTimezone($timezone) ; return $this->attributes['created_at']->format($format) ; } # /getCreatedAt()
public function getUpdatedAt(string $format = 'd/m/Y H:i:s') { $this->attributes['updated_at'] = $this->mutateDate($this->attributes['updated_at']) ; $timezone = $this->timezone ?? app_timezone() ; $this->attributes['updated_at']->setTimezone($timezone) ; return $this->attributes['updated_at']->format($format) ; } # /getUpdatedAt
public function getDeletedAt(string $format = 'd/m/Y H:i:s') { if($this->attributes['deleted_at'] == null) return false ; $this->attributes['deleted_at'] = $this->mutateDate($this->attributes['deleted_at']) ; $timezone = $this->timezone ?? app_timezone() ; $this->attributes['deleted_at']->setTimezone($timezone) ; return $this->attributes['deleted_at']->format($format) ; } # /getDeletedAt
}
Controller :
PHP Code: <?php namespace App\Controllers;
class Home extends BaseController { public function index() {
$vars = [ 'tac' => 'blabla' ] ; return view('welcome_message',$vars); }
public function test() { $dom_id = random_string('alpha',13) ;
$config = config('Config\Database') ;
$content = '' ;
$user_model = model('App\Models\UserModel') ; $users = $user_model->findAll() ;
if($users) { $table = new \CodeIgniter\View\Table() ; $table->setTemplate(['table_open' => '<table class="table table-hover table-striped">']) ; $table->setHeading(['id','email','level','identite','adresse','tel','created_at','updated_at','deleted_at']) ; foreach($users as $user){ $table->addRow([ $user->id , $user->email , $user->level , $user->identite() , $user->adresse() , $user->tel , $user->created_at , $user->updated_at , $user->deleted_at ]) ; } $content .= $table->generate() ; } else $content .= wrap('Aucun user trouvé par le findAll',['balise' => 'code']) ;
$vars = [ 'title' => 'MON BLABLA '.__CLASS__.'::'.__FUNCTION__ , 'content' => wrap($content ,['id' => $dom_id]) ] ; $params = (object)[ 'dom_id' => $dom_id ] ;
$this->scripts->addPath(base_url('boot/not_compiled/home-test-0.0.1.js')) ; $this->scripts->init('home_test',$params) ; return $this->html($vars) ; }
}
and in the HTML table, the dates created_at and updated_at still display in the 'Y-d-m H:i:s' format.
Where did I make a mistake ?
-
InsiteFX Super Moderator
     
-
Posts: 6,728
Threads: 344
Joined: Oct 2014
Reputation:
246
You need to add them to the models allow fields array.
PHP Code: $allowedFields = ['created_at', 'updated_at'] // etc;
What did you Try? What did you Get? What did you Expect?
Joined CodeIgniter Community 2009. ( Skype: insitfx )
-
tomasoma Junior Member
 
-
Posts: 16
Threads: 6
Joined: Feb 2015
Reputation:
0
09-18-2020, 02:01 AM
(This post was last modified: 09-18-2020, 02:35 AM by tomasoma.)
(09-18-2020, 01:04 AM)InsiteFX Wrote: You need to add them to the models allow fields array.
PHP Code: $allowedFields = ['created_at', 'updated_at'] // etc;
Thanks for trying but It doesn't change anything.
I added a log_message() to check if my own function was called and it is, with or without the add in the allowedFields array.
PHP Code: public function getCreatedAt(string $format = 'd/m/Y H:i:s') { $this->attributes['created_at'] = $this->mutateDate($this->attributes['created_at']) ; $timezone = $this->timezone ?? app_timezone() ; $this->attributes['created_at']->setTimezone($timezone) ; log_message('error',__CLASS__.'::'.__FUNCTION__.'() l:'.__LINE__. ' I’m done') ; return $this->attributes['created_at']->format($format) ; } # /getCreatedAt()
I also change the return line with the string format :
PHP Code: return $this->attributes['created_at']->format('d/m/Y H:i:s') ;
and it still doesn't work
but when i include a mistake in the date format string :
PHP Code: return $this->attributes['created_at']->format('d/m/Y H:i:xs') ;
then Exception error ...
so I'm trying to find this native ...->format() function to understand why it 'partially' ignore the argument....
From the logs of the error generated by the 'mistake' in the date format, it looks like my own getCreatedAt() is called and then overridden by ??? the default one ???
Code: CRITICAL - 2020-09-18 11:01:00 --> DateTime::__construct(): Failed to parse time string (12:/04/1981 01:15:00) at position 0 (1): Unexpected character
#0 /var/www/clients/client0/common-libraries/codeigniter.versions/framework-4.0.4/system/I18n/Time.php(138): DateTime->__construct('12:/04/1981 01:...', Object(DateTimeZone))
#1 /var/www/clients/client0/common-libraries/codeigniter.versions/framework-4.0.4/system/I18n/Time.php(174): CodeIgniter\I18n\Time->__construct('12:/04/1981 01:...', 'Europe/Berlin', NULL)
#2 /var/www/clients/client0/common-libraries/codeigniter.versions/framework-4.0.4/system/Entity.php(500): CodeIgniter\I18n\Time::parse('12:/04/1981 01:...')
#3 /var/www/clients/client0/common-libraries/codeigniter.versions/framework-4.0.4/system/Entity.php(301): CodeIgniter\Entity->mutateDate('12:/04/1981 01:...')
#4 /var/www/clients/client0/web22/private/app/Controllers/Home.php(59): CodeIgniter\Entity->__get('created_at')
#5 /var/www/clients/client0/common-libraries/codeigniter.versions/framework-4.0.4/system/CodeIgniter.php(918): App\Controllers\Home->test()
#6 /var/www/clients/client0/common-libraries/codeigniter.versions/framework-4.0.4/system/CodeIgniter.php(404): CodeIgniter\CodeIgniter->runController(Object(App\Controllers\Home))
#7 /var/www/clients/client0/common-libraries/codeigniter.versions/framework-4.0.4/system/CodeIgniter.php(312): CodeIgniter\CodeIgniter->handleRequest(NULL, Object(Config\Cache), false)
#8 /var/www/clients/client0/web22/web/index.php(45): CodeIgniter\CodeIgniter->run()
#9 {main}
when i call
it works fine, but I think it was what the "auto getter" was done to avoid .?.?.
So I checked the System/Entity->__get() :
PHP Code: public function __get(string $key) { $key = $this->mapProperty($key); $result = null; // Convert to CamelCase for the method $method = 'get' . str_replace(' ', '', ucwords(str_replace(['-', '_'], ' ', $key)));
// if a set* method exists for this key, // use that method to insert this value. if (method_exists($this, $method)) { $result = $this->$method(); } // Otherwise return the protected property // if it exists. else if (array_key_exists($key, $this->attributes)) { $result = $this->attributes[$key]; } // Do we need to mutate this into a date? if (in_array($key, $this->dates)) { $result = $this->mutateDate($result); } // Or cast it as something? else if ($this->_cast && ! empty($this->casts[$key])) { $result = $this->castAs($result, $this->casts[$key]); } return $result; }
it calls my method and then if the $key is in the $date array it mutates my result into a date one more time.
So I removed my $date array
PHP Code: // protected $dates = ['created_at', 'updated_at', 'deleted_at'];
... still doesn't work
So I empty my date array :
WOOOW ok finally .... I got my result !!!!
So I guess that the $useTimestamps automatically fills the $date array with the $createdField , $updatedField and the $deletedFields.
Solved.
CI4 is great but its documentation is not yet.
-
tomasoma Junior Member
 
-
Posts: 16
Threads: 6
Joined: Feb 2015
Reputation:
0
Perhaps it is a dumb newbie ideas but i dare :
Wouldn't that be more logic to check the method at the end of the __get() so if it is a date it would be already mutated ?
Or to directly return the result of the method if there is a method ?
From the comment i guess the __get() has been written after the __set() method and perhaps the execution logic order has not been inverted ?
-
nicojmb Junior Member
 
-
Posts: 38
Threads: 7
Joined: Feb 2015
Reputation:
2
hi, i try to do the same but does't work, can you share you working code?
Regards!
-
InsiteFX Super Moderator
     
-
Posts: 6,728
Threads: 344
Joined: Oct 2014
Reputation:
246
(09-18-2020, 11:06 AM)nicojmb Wrote: hi, i try to do the same but does't work, can you share you working code?
Regards!
PHP Code: The $useTimestamps automatically fills the $date array with the $createdField , $updatedField and the $deletedFields.
So set this to true.
PHP Code: /** * If true, will set created_at, and updated_at * values during insert and update routines. * * @var boolean */ protected $useTimestamps = false;
What did you Try? What did you Get? What did you Expect?
Joined CodeIgniter Community 2009. ( Skype: insitfx )
-
nicojmb Junior Member
 
-
Posts: 38
Threads: 7
Joined: Feb 2015
Reputation:
2
09-18-2020, 01:27 PM
(This post was last modified: 09-18-2020, 01:42 PM by nicojmb.)
(09-18-2020, 01:10 PM)InsiteFX Wrote: (09-18-2020, 11:06 AM)nicojmb Wrote: hi, i try to do the same but does't work, can you share you working code?
Regards!
PHP Code: The $useTimestamps automatically fills the $date array with the $createdField , $updatedField and the $deletedFields.
So set this to true.
PHP Code: /** * If true, will set created_at, and updated_at * values during insert and update routines. * * @var boolean */ protected $useTimestamps = false;
Not work, i use custom model extended from MyTh.
I have tried everything, $useTimestamps to "true", $useTimestamps to "false", with $dates array, etc...
PHP Code: namespace App\Models;
use Myth\Auth\Models\UserModel as BaseModel;
class UserModel extends BaseModel {
protected $dates = [];
protected $returnType = \App\Entities\User::class;
protected $useTimestamps = true; }
PHP Code: namespace App\Entities;
use \Myth\Auth\Entities\User as BaseEntity; use CodeIgniter\I18n\Time;
class User extends BaseEntity {
public function getUpdatedAt(string $format = 'd/m/y H:i') { $this->attributes['updated_at'] = $this->mutateDate($this->attributes['updated_at']);
$timezone = $this->timezone ?? app_timezone();
$this->attributes['updated_at']->setTimezone($timezone);
return $this->attributes['updated_at']->format($format); }
public function getCreatedAt(string $format = 'd/m/y H:i') { $this->attributes['created_at'] = $this->mutateDate($this->attributes['created_at']);
$timezone = $this->timezone ?? app_timezone();
$this->attributes['created_at']->setTimezone($timezone);
return $this->attributes['created_at']->format($format); } }
PHP Code: "title": "Exception", "type": "Exception", "code": 500, "message": "DateTime::__construct(): Failed to parse time string (15/09/2020 17:43:11) at position 0 (1): Unexpected character", "file": "/var/www/vhosts/nicojmb.com/yani.nicojmb.com/vendor/codeigniter4/framework/system/I18n/Time.php", "line": 138,
-
tomasoma Junior Member
 
-
Posts: 16
Threads: 6
Joined: Feb 2015
Reputation:
0
09-21-2020, 01:13 AM
(This post was last modified: 09-21-2020, 01:23 AM by tomasoma.)
Ok sorry for the delay here is my working code :
Model :
PHP Code: <?php namespace App\Models ;
use CodeIgniter\Model ;
class UserModel extends Model {
protected $table = 'user'; protected $primaryKey = 'id'; protected $returnType = 'App\Entities\User'; protected $useSoftDeletes = true ; protected $allowedFields = ['email','password','level','civilite','prenom','nom','sign','tel','add1','add2','cp','ville','pays'] ; protected $dateFormat = 'int' ; protected $useTimestamps = true ; protected $createdField = 'created_at' ; protected $updatedField = 'updated_at' ; protected $deletedField = 'deleted_at' ; protected $validationRules = [] ; protected $validationMessages = [] ; protected $skipValidation = false ;
}
Controller :
PHP Code: <?php namespace App\Controllers;
class Users extends BaseController {
private $UM ; # pour le user model pas être obligé de le rappeler à chaque fonction
/***************************************************** __construct *****************************************************/ public function __construct(){ $this->UM = model('App\Models\UserModel') ; }
/***************************************************** index *****************************************************/ public function index(){ $vars = [ 'dom_id' => random_string('alpha',13) , 'table' => '' , 'pagination' => '' ] ; $users = $this->UM->findAll() ; if($users) { $table = new \CodeIgniter\View\Table() ; $table->setTemplate(['table_open' => '<table class="table table-hover table-striped">']) ; $table->setHeading(['','id','email','level','identite','adresse','tel','created_at','updated_at','deleted_at']) ; foreach($users as $user){ $table->addRow([ wrap( admin_show_btn('users',$user->id) .admin_edit_btn('users',$user->id) .admin_supprim_btn('users',$user->id) ,['class' => 'btn-group btn-group-sm'] ) , $user->id , $user->email , $user->level , $user->identite() , $user->adresse() , $user->tel , $user->created_at , $user->updated_at , $user->deleted_at ]) ; } $vars['table'] = $table->generate() ; } else $vars['table'] = alert('warning','Aucun utilisateur trouvé') ;
return $this->tpl('users/index',$vars,'content') ->set_var('title',__CLASS__.'::'.__FUNCTION__) ->html() ; } # /index
Entity :
PHP Code: <?php namespace App\Entities ;
use CodeIgniter\Entity ; use CodeIgniter\I18n\Time;
class User extends Entity { protected $attributes = [ 'id' => null , 'email' => null , 'password' => null , 'level' => null , 'civilite' => null , 'prenom' => null , 'nom' => null , 'sign' => null , 'tel' => null , 'add1' => null , 'add2' => null , 'cp' => null , 'ville' => null , 'pays' => null , 'created_at' => null , 'updated_at' => null , 'deleted_at' => null ] ;
protected $dates = [] ; # !! declare a empty array
public function identite(){ return trim($this->civilite.' '.ucwords($this->prenom)).' '.strtoUpper($this->nom) ; } # /identite()
public function adresse() { $t = $this->add1 ; if(trim($this->add2) != '') $t .= '<br >/'.$this->add2 ; $t .= '<br />'.$this->cp.' '.strtoupper($this->ville) ; if(trim(strtolower($this->pays)) != 'france') $t .= '<br />'.$this->pays ; return $t ; } # /adresse()
public function getCreatedAt(string $format = 'd/m/Y H:i:s') { $this->attributes['created_at'] = $this->mutateDate($this->attributes['created_at']) ; $timezone = $this->timezone ?? app_timezone() ; $this->attributes['created_at']->setTimezone($timezone) ; log_message('error',__CLASS__.'::'.__FUNCTION__.'() l:'.__LINE__. ' I’m done') ; return $this->attributes['created_at']->format($format) ; } # /getCreatedAt()
public function getUpdatedAt(string $format = 'd/m/Y H:i:s') { $this->attributes['updated_at'] = $this->mutateDate($this->attributes['updated_at']) ; $timezone = $this->timezone ?? app_timezone() ; $this->attributes['updated_at']->setTimezone($timezone) ; return $this->attributes['updated_at']->format($format) ; } # /getUpdatedAt
public function getDeletedAt(string $format = 'd/m/Y H:i:s') { if($this->attributes['deleted_at'] == null) return false ; $this->attributes['deleted_at'] = $this->mutateDate($this->attributes['deleted_at']) ; $timezone = $this->timezone ?? app_timezone() ; $this->attributes['deleted_at']->setTimezone($timezone) ; return $this->attributes['deleted_at']->format($format) ; } # /getDeletedAt
} # EOC Entity\User
(09-18-2020, 01:27 PM)nicojmb Wrote: (09-18-2020, 01:10 PM)InsiteFX Wrote: (09-18-2020, 11:06 AM)nicojmb Wrote: hi, i try to do the same but does't work, can you share you working code?
Regards!
PHP Code: The $useTimestamps automatically fills the $date array with the $createdField , $updatedField and the $deletedFields.
So set this to true.
PHP Code: /** * If true, will set created_at, and updated_at * values during insert and update routines. * * @var boolean */ protected $useTimestamps = false;
Not work, i use custom model extended from MyTh.
I have tried everything, $useTimestamps to "true", $useTimestamps to "false", with $dates array, etc...
PHP Code: namespace App\Models;
use Myth\Auth\Models\UserModel as BaseModel;
class UserModel extends BaseModel {
protected $dates = [];
protected $returnType = \App\Entities\User::class;
protected $useTimestamps = true; }
It is not in the model that you declare $date array empty, it is in the Entity class
It works for display but i didn't get further yet, I hope that the empty $date array will not prevent from CI to automatically update the value at creation, update and delete action as it is supposed to do ... I'll check it when I write my create,edit,delete function in my controller...
I think our problem is more from the __get() function of the system Entity class ... but noone reply on this point.
Sorry for the delay, I'm busy on many projects and I'm just working on CI4 when I have time to learn how to deal with it for the futur.
|