• 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
date auto getter in Entity ignore my date format

#1
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 ?
Reply

#2
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 )
Reply

#3
(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
PHP Code:
$user->getCreatedAt() ; 
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 :
PHP Code:
protected $dates = [] ; 

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.
Reply

#4
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 ?
Reply

#5
hi, i try to do the same but does't work, can you share you working code?

Regards!
Reply

#6
(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 )
Reply

#7
(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
Reply

#8
It creates the datetime on its own, if you want it different then you need to create your custom table field using an integer type.
What did you Try? What did you Get? What did you Expect?

Joined CodeIgniter Community 2009.  ( Skype: insitfx )
Reply

#9
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 Wink

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.
Reply

#10
Yes, i can confirm that empty $date array the display is correct.
Reply


Digg   Delicious   Reddit   Facebook   Twitter   StumbleUpon  


  Theme © 2014 iAndrew  
Powered By MyBB, © 2002-2020 MyBB Group.