Welcome Guest, Not a member yet? Register   Sign In
models in CI4 - OK to put in app/Models? What about naming/namespacing/autoloading?
#1

I was reading the Model documentation for CI4 and it says :
Quote:Models provide a way to interact with a specific table in your database.

While I'm pretty happy to see CI4 supporting these types of database-specific classes, I also know from experience that there are many business logic situations which are not just interacting with a single database table. I'm wondering if it's an acceptable practice to create other types of classes in the app/Models directory. I.e., classes that either don't interact with a db table at all or which might interact with several tables using Composition/Aggregation/Assocation. For example, I might have some business logic that checks one or more tables and then creates a record in some other table. Or I might have some business logic which doesn't involve db tables at all but encrypts or decrypts data or enforces rules of some turn-based game or which calculates some funky calculation. Is it an acceptable practice to put this sort of code into classes in the app/Models directory? Is it OK if these classes don't extend any existing class? I'm also wondering what naming & namespacing conventions I should follow so that CodeIgniter's autoloading functionality will be sure to find these models when I refer to them in my code.

Any input would be much appreciated.
Reply
#2

You can still create your own models without using CodeIgniter's Model.
What did you Try? What did you Get? What did you Expect?

Joined CodeIgniter Community 2009.  ( Skype: insitfx )
Reply
#3

(This post was last modified: 12-11-2020, 02:08 PM by sneakyimp.)

(12-11-2020, 12:50 PM)InsiteFX Wrote: You can still create your own models without using CodeIgniter's Model.
EDIT: like many of your other responses, this one is not especially informative. I was rather hoping that someone might read my entire post and comment with something a bit less terse and more in the spirit of discussion.

I would also point out that the documentation I linked in my original post makes it clear that one need not extend CodeIgniter\Model:
Quote:You do not need to extend any special class to create a model for your application. All you need is to get an instance of the database connection and you’re good to go. This allows you to bypass the features CodeIgniter’s Model gives you out of the box, and create a fully custom experience.
PHP Code:
<?php namespace App\Models;

use 
CodeIgniter\Database\ConnectionInterface;

class 
UserModel
{
    protected 
$db;

    public function 
__construct(ConnectionInterface &$db)
    {
        
$this->db =& $db;
    }

Reply
#4

(This post was last modified: 12-12-2020, 01:22 AM by tgix.)

My main gripe with CI4's models is that they don't work the way I expect - to represent a single record. 
Maybe I am wrong about how a model should or should not work, but in my other main framework (Ext JS), the Model represents the database record. CI4 models sort of represents the database table. This means that you cannot (at least I haven't found a reasonable way) work on the actual record data in the model-code. 
My models are tied with a corresponding Entity that is returned on a Model::find() and that works fine when accessing and transforming the data of the record. However saving an Entity requires you to use the Model again with a Model::update($id, $data). I have been working on adding CRUD functions directly to the Entity but scrapped that put code in the Controller instead, for example:
PHP Code:
public function delete($id)
    {
        $credits = new ExamTypeModel();
        $data $credits->find($id);
        if (is_null($data)) {
            return $this->failNotFound();
        }

        // Check to see so there are balance on this credit type
        $db db_connect();
        $builder $db->table(Table::credits);
        $company_balance $builder->selectSum('balance''sum')
            ->where('typeLink'$id)
            ->get()
            ->getRowObject(0)->sum;

        $builder $db->table(Table::user_credits);
        $user_balance $builder->selectSum('balance''sum')
            ->where('typeLink'$id)
            ->get()
            ->getRowObject(0)->sum;

        if (((int)$user_balance 0) || ((int)$company_balance 0)) {
            return $this->failValidationError();
        }

        $credits->delete($id);
        return $this->respondNoContent();
    

This snipped I would really like to reduce to:

PHP Code:
    public function delete($id)
    {
        $record = new ExamTypeModel($id);
        if (is_null($record)) {
            return $this->failNotFound();
        }

        if (($record->userBalance() > 0) || ($record->companyBalance() > 0)) {
            return $this->failValidationError();
        }
        
        $record
->delete();
        
        
return $this->respondNoContent();
    

Where userBalance() and companyBalance() would be functions in the Model (or Entity).

Namespacing:
I wouldn't worry too much about this. I use composer to install CI4 and the dependencies I need and so far there have been zero problems (other than me mistyping something). Your code should live in App namespace which by default points to your app/ directory. As long as you follow the PSR-4 specifications and name things properly in the app/ directory you can create anything your like (some restrictions with reserved keywords applies of course). As long as you make sure that the autoloader can find it you will be able to use it.
Folders should be named as the namespace, so a class App\Models\pickers\BrandPickerModel should be defined in a file located in app/Models/pickers/BrandPickerModel.php. Upper/lower case is important, especially if you are on macOS or Windows because the filesystems are case-insensitive which is something that will bite you if your production environment is Linux.
In some places in CI4 the docs tells you type the name of the class as a string, for example when configuring a $returnType of an Entity (https://codeigniter4.github.io/userguide...-the-model). This is error prone and makes refactoring hard. My guess is this is because of not having to autoload everything which would be the case if you were to use ::class instead. I am using ::class in many places where the docs shows a string and haven't seen any issues.
I use PHPstorm IDE and it helps a lot to keep things organized.

https://codeigniter4.github.io/userguide...oader.html
https://www.php-fig.org/psr/psr-4/

My project directory:
   
Reply




Theme © iAndrew 2016 - Forum software by © MyBB