Welcome Guest, Not a member yet? Register   Sign In
Model files in CI4
#11

(07-19-2021, 10:57 AM)Filippo65 Wrote: 1) I'm already grouping many tabel's data into big multi-table objects, i.e:
$GC->Tabella1, from AA_Tabella1,
$GC->Tabella2, from AA_Tabella2...
How can I replicate this in CI4?
1A) in the models, reading multiple tables and constructing there the multi-table objects?
or
1B) in some 0-level libraries, reading from CI4-standard single-tabel models?
Option "1B" can work if I can declare the used model in the library file header, instead of in the controller. May I?

I would do it with your 1B solution. This is how I did it in my tutorial. Simple models and entities for recipes and ingredients, and the library build the final object containing one recipe with all its ingredients. But you can also do it in the model if that's what you prefer. It's really is a personal choice on how you want to organize your code. Personally I prefer my models to be simple and to do selects in a single table. 

(07-19-2021, 10:57 AM)Filippo65 Wrote: 2) $GC is declared "static" in the Controller. So I can handle it with the librarie's functions.
This will not change from CI3 to Ci4, right?

What is $GC and why does it need to be static?

(07-19-2021, 10:57 AM)Filippo65 Wrote: 3) In each library I had this header:
protected $CI;
public function __construct()
{
// Assign the CodeIgniter super-object
$this->CI =& get_instance();
}
In this way I can use in the libraries the header of the controller.
How does it work/translate this in CI4?

There's no longer a CI super-object in CI4. You can use service('.....') to get a reference to the shared instance of the object you need. For example, if your need the request object in a library:
PHP Code:
use CodeIgniter\HTTP\IncomingRequest;

$request service('request'); 

Note that the request object is already available in the controller with $this->request.

(07-19-2021, 10:57 AM)Filippo65 Wrote: 4) In CI4 standard Model there is a Key declaration:
i.e: protected $primaryKey = 'id';
It assumes that the table has a single key.
90% of my tables have multiple keys, i.e. GameID, ItemID: can the standard CI4 models handle this?

This is to define the primary key. Not the foreign keys. If you have a table where the primary key is a combination of several columns, I would advise to change that to use a single column with an auto-increment id. If you can't do this, you won't be able to use some functions from the Model class because it needs a single column for the primary key. But if your other column are just reference to other tables, it won't cause any problem.
CodeIgniter 4 tutorials (EN/FR) - https://includebeer.com
/*** NO support in private message - Use the forum! ***/
Reply
#12

Thanks includebeer.
Regard Models, since my primary keys are a combination of several columns (in order to avoid future overflows), I need a different way to handle the DB.
The User Guide speaks about a "Manual Model Creation" (https://codeigniter4.github.io/userguide...l-creation), but I can't find how does it work.
Is it the old Ci3's $this->db object?
Copying from there, I made my new Model file: M_Comuni_2db.php

<?php
namespace App\Models;
use CodeIgniter\Database\ConnectionInterface;
class M_Comuni_2db
{
protected $db;
public function __construct(ConnectionInterface &$db)
{
$this->db = &$db;
}
public function leggi_lingue($lingua = FALSE)
{
if ($lingua === FALSE)
{
$query = $this->db->get('AA_Tabella1');
return $query->result_object();
}
// Else:
$query = $this->db->get_where('AA_Tabella1', array('Lingua' => $lingua));
return $query->row_object();
}
}

But now how can I use it from the controller?
Reply
#13

2.nd version of Model:

<?php
namespace App\Models;
use CodeIgniter\Database\ConnectionInterface;

class M_Comuni_2db
{
protected $db;
public function __construct()
{
$this->db = \Config\Database::connect();
}
public function leggi_lingue($lingua = FALSE)
{
if ($lingua === FALSE)
{
$query = $this->db->get('AA_Tabella1'); // <--- error happens here
return $query->result_object();
}
// Else:
$query = $this->db->get_where('AA_Tabella1', array('Lingua' => $lingua));
return $query->row_object();
}
}

Then, in the Controller I have:
use App\Models\M_Comuni_2db;
(...)
$modello = new \App\Models\M_Comuni_2db();
$ListaLingue = $modello->leggi_lingue();
(...)

In this way the error is:
"Call to undefined method CodeIgniter\Database\MySQLi\Connection::get()"
i.e. the $db object does NOT work like the old one... :-(
How does it work?
Reply
#14

Got it!
I must use $this->db->query($sql);
So, now my Model is:

<?php
namespace App\Models;
use CodeIgniter\Database\ConnectionInterface;

class M_Comuni_2db
{
protected $db;
public function __construct()
{
$this->db = \Config\Database::connect();
}
public function leggi_lingue($lingua = FALSE)
{
if ($lingua === FALSE)
{
$sql = "SELECT * FROM AA_Tabella1";
$query = $this->db->query($sql);
$Risultato_Obj = $query->getResultObject();
}
else
{
$sql = "SELECT * FROM AA_Tabella1 where Lingua='".$lingua."'";
$query = $this->db->query($sql);
$Risultato_Obj = $query->getRow();
}
$query->freeResult();
return $Risultato_Obj;
}
}

It works.

I'll check if the Query Builder Class can work here too. If not, I can maybe make my own class for setting up the $sql string.
Reply
#15

(07-21-2021, 10:30 AM)Filippo65 Wrote: I'll check if the Query Builder Class can work here too. If not, I can maybe make my own class for setting up the $sql string.

Of course you can use the Query Builder in your custom model. Read this page of the user guide: http://codeigniter.com/user_guide/databa...ilder.html

Quote:The Query Builder is loaded through the table() method on the database connection. This sets the FROM portion of the query for you and returns a new instance of the Query Builder class:
PHP Code:
$db      = \Config\Database::connect();
$builder $db->table('users'); 
CodeIgniter 4 tutorials (EN/FR) - https://includebeer.com
/*** NO support in private message - Use the forum! ***/
Reply
#16

OK for the Model file, thanks.
But I still have some doubt on controller and libraries (the part that handles the model):

Previous version, in CI3, was:
File Home.php:
PHP Code:
// nothing on header

public function __construct()
{
 parent::__construct();
 $this->load->model('mymodel01');
}

public function 
index()
{
 $tableA $this->mymodel01->read_file_aaaa();
 ...



File Library01.php:
PHP Code:
class Library01
{
 protected $CI;
 public function __construct()
 {$this->CI =& get_instance();}

 public function some_subroutine()
 {
  $tableB $this->CI->mymodel01->read_file_bbbb();
  ...
 }

My new version, in CI4, is:
Home.php:
PHP Code:
use App\Models\Mymodel01;

class 
Home extends BaseController
{
 public function __construct()
 {static $G_Mymodel01;}

 public function index()
 {
  global $G_Mymodel01;
  $G_Mymodel01 = new \App\Models\Mymodel01();
  ...
  $tableA $G_Mymodel01->read_file_aaaa();
  ...
 }

Library01.php:
PHP Code:
use ??? // not yet checked

class Library01
{
 public function some_subroutine()
 {
  global $G_Mymodel01;
  ...
  $tableB $G_Mymodel01->read_file_bbbb();
  ...
 }


Is this correct?
I mean: it works (at least the controller; library not yet checked), but in this new version I have more code lines to write, instead of less. Maybe is there some "trick" that I haven't yet found?
Reply
#17

(This post was last modified: 08-20-2021, 12:51 PM by ikesela.)

// path for MyModel01 location file
use App\Models\Mymodel01;

// load model
$G_Mymodel01 = model('Mymodel01');
Reply
#18

Sorry for the very late reply. I was busy with "life"...
Anyway, like ikesela said, use the model() function to load a model. It will return a shared instance by default. So you you don't need to use a global variable, this is PHP 4 era mentality.  Cool
CodeIgniter 4 tutorials (EN/FR) - https://includebeer.com
/*** NO support in private message - Use the forum! ***/
Reply
#19

Also remember that the Entity and Model Class names must match the file name.

MyEntity - MyEntity.php
MyModel - MyModel.php
What did you Try? What did you Get? What did you Expect?

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

(09-05-2021, 03:39 PM)includebeer Wrote: Sorry for the very late reply. I was busy with "life"...
Anyway, like ikesela said, use the model() function to load a model. It will return a shared instance by default. So you you don't need to use a global variable, this is PHP 4 era mentality.  Cool

1)
Does this work in the subroutines in the libraries too?
I mean: in Library01.php methods I don't need to declare global $G_Mymodel01?

2)
I'm an old man, born with Commodore64's Basic. Maybe I'm not using objects in the best way...
But I can't imagine how to avoid global variables. My site is a game of strategy: the execute_move.php controller must load all the DB tables (80, more or less), then elaborate all orders, move units, solve combats, and so on; at the end, write the changes on the DB. I use 3 levels of subroutines, in 3 libraries. How can I do this, withot global objects?
Reply




Theme © iAndrew 2016 - Forum software by © MyBB