skip to Main Content

I want to use CodeIgniter 4’s Models’ ability to automatically set the created_at, updated_at, and deleted_at fields in database tables.

For that, should I set those fields as TIMESTAMP in MySQL or DATETIME?

If I set them as TIMESTAMP, I know that they will record the real-time regardless of the timezone, but the deleted_at column cannot be null. On the other hand, if I set them as DATETIME, I am not sure if CodeIgniter will store the time in ‘UTC’ or in the server’s time, which may not be ‘UTC’.

4

Answers


  1. I would use TIMESTAMP, however, working with date-time objects is always a pain. It’s a matter of if you want it the data to be human readable in your database I think. Since deleted_at cant be NULL setting its default value to either super far in the past or super far in the future will allow you to run checks. ie

    if deleted_at != DISTANT_DATETIME run xyz

    Login or Signup to reply.
  2. Did you ever think to use a Unix Time Stamp (epoch time), saving at bigint or varchar column definition?

    Using the CodeIgniter Model you can validate insert, update and delete actions to affect as desired.

    When getting the record is more easy to convert using DateTime PHP class, like:

    $dt = new DateTime($row->created_at);
    print $dt->format("m, d/Y H:i:s");
    

    But if you want to use DATETIME or TIMESTAMP, my suggestion is

    • created_at : TIMESTAMP, this will store
    • updated_at : DATETIME, but
      you must control when to save, and be aware that is going to get the
      time zone reference
    • deleted_at : DATETIME, same specs as updated_at

    Take this as advice:

    The DATETIME type is used for values that contain both date and time parts. MySQL retrieves and displays DATETIME values in ‘YYYY-MM-DD hh:mm:ss’ format. The supported range is ‘1000-01-01 00:00:00’ to ‘9999-12-31 23:59:59’.

    The TIMESTAMP data type is used for values that contain both date and time parts. TIMESTAMP has a range of ‘1970-01-01 00:00:01’ UTC to ‘2038-01-19 03:14:07’ UTC.

    Check this link

    Login or Signup to reply.
  3. Background Information

    Every time CodeIgniter runs, there are several base classes that are initialized automatically as part of the core framework. One of which is the CodeIgniterCodeIgniter system class.

    In this particular class, a default timezone used by all date/time functions on your server (date_default_timezone_set) and a default runtime locale (Locale::setDefault) are set.

    Excerpt from the CodeIgniterCodeIgniter system class

    public function initialize()
    {
        // ...
    
        // Set default locale on the server
        Locale::setDefault($this->config->defaultLocale ?? 'en');
    
        // Set default timezone on the server
        date_default_timezone_set($this->config->appTimezone ?? 'UTC');
    
        $this->initializeKint();
    }
    

    If you look closely enough, the application’s ‘locale’ and ‘timezone’ settings are primarily based on what you defined in the app/Config/App.php configuration file or in the .env environment variable file that resides at the root of your project.

    Excerpt from the app/Config/App.php configuration file.

    Default Locale and Application Timezone

        /**
         * --------------------------------------------------------------------------
         * Default Locale
         * --------------------------------------------------------------------------
         *
         * The Locale roughly represents the language and location that your visitor
         * is viewing the site from. It affects the language strings and other
         * strings (like currency markers, numbers, etc), that your program
         * should run under for this request.
         */
        public string $defaultLocale = 'en';
    
        // ...
    
        /**
         * --------------------------------------------------------------------------
         * Application Timezone
         * --------------------------------------------------------------------------
         *
         * The default timezone that will be used in your application to display
         * dates with the date helper, and can be retrieved through app_timezone()
         */
        public string $appTimezone = 'UTC';
    
    

    So, to answer your inquiry,

    • OP’s inquiry:

    … I am not sure if CodeIgniter will store the time in UTC or in the
    server’s time, which may not be UTC.

    Answer: That will depend on your app timezone setting in the app/Config/App.php configuration file or in the .env environment variable file that resides at the root of your project. By default, the $appTimezone property is set to ‘UTC’.


    Additional Explanation

    With the background information out of the way, if you want to inform CodeIgniter 4 to automatically set the created_at and updated_at fields in addition to the deleted_at field for soft deleted records, you need to override the $useTimestamps property on your Model and set it to true.

    $useTimestamps

    This boolean value determines whether the current date is
    automatically added to all inserts and updates. If true, will set the
    current time in the format specified by $dateFormat. This requires
    that the table have columns named created_at, updated_at and
    deleted_at in the appropriate data type.

    These fields/columns (created_at, updated_at & deleted_at) are automatically filled/set when you call the following methods on your Model instance:

    1. ->save(...).
    2. ->insert(...).
    3. ->insertBatch(...).
    4. ->update(...).
    5. ->updateBatch(...).
    6. ->delete(...).

    Now, coming back to your question,

    • OP’s question:

    For that, should I set those fields as timestamp in MySQL or datetime?

    Response:

    Firstly, at the time of writing this post, CodeIgniter 4 supports 3 formats by default, namely:

    1. ‘datetime’. I.e: ‘Y-m-d H:i:s’.
    2. ‘date’. I.e: ‘Y-m-d’.
    3. ‘int’. I.e: (a PHP timestamp).

    $dateFormat

    This value works with $useTimestamps and $useSoftDeletes to ensure
    that the correct type of date value gets inserted into the database.
    By default, this creates DATETIME values, but valid options are:
    'datetime', 'date', or 'int' (a PHP timestamp). Using
    useSoftDeletes or useTimestamps with an invalid or missing dateFormat will cause an exception.

    With the linked resource above, CodeIgniter 4 expects the fields (created_at, updated_at & deleted_at) to have a DATETIME data type. To supplement on this, one of CodeIgniter 4’s official packages called CodeIgniter Shield also uses DATETIME as it’s preferred column data type for theses specific fields.

    Excerpt from Shield’s Database/Migrations/2020-12-28-223112_create_auth_tables.php file

    public function up(): void
    {
        // Users Table
        $this->forge->addField([
            // ...
            'last_active'    => ['type' => 'datetime', 'null' => true],
            'created_at'     => ['type' => 'datetime', 'null' => true],
            'updated_at'     => ['type' => 'datetime', 'null' => true],
            'deleted_at'     => ['type' => 'datetime', 'null' => true],
        ]);
        $this->forge->addPrimaryKey('id');
        $this->forge->addUniqueKey('username');
        $this->forge->createTable($this->tables['users']);
    
    // ...
    }
    

    CodeIgniter Settings, another official package also uses DATETIME as it’s preferred column data type for these specific fields.

    Excerpt from Settings’s Database/Migrations/2021-07-04-041948_CreateSettingsTable.php file

    public function up()
    {
        $this->forge->addField('id');
        $this->forge->addField([
        // ...
            'created_at' => [
                'type' => 'datetime',
                'null' => false,
            ],
            'updated_at' => [
                'type' => 'datetime',
                'null' => false,
            ],
        ]);
        $this->forge->createTable($this->config->database['table'], true);
    }
    

    Important notes:

    1. The deleted_at field must be nullable. In addition, it is expected to have a column data type of either DATETIME or INTEGER.

    $useSoftDeletes

    If true, then any delete() method calls will set deleted_at in the
    database, instead of actually deleting the row. This can preserve data
    when it might be referenced elsewhere, or can maintain a “recycle bin”
    of objects that can be restored, or even simply preserve it as part of
    a security trail. If true, the find()* methods will only return
    non-deleted rows, unless the withDeleted() method is called prior to
    calling the find()* method.

    This requires either a DATETIME or INTEGER field in the database
    as per the model’s $dateFormat setting. The default field name is
    deleted_at however this name can be configured to any name of your
    choice by using $deletedField property.

    Important

    The deleted_at field must be nullable.

    Login or Signup to reply.
  4. TIMESTAMP can only store dates up to ‘2038-01-19 03:14:07’ UTC. To avoid bugs or a database migration in the near future, you definitely want to use DATETIME.
    Source: https://dev.mysql.com/doc/refman/8.0/en/datetime.html

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search