Welcome Guest, Not a member yet? Register   Sign In
What is the correct way to load data from a databse once for use everywhere?
#1

(This post was last modified: 02-11-2023, 03:06 PM by objecttothis. Edit Reason: Clarification )

I want to load into memory as an associative array all the rows from an app_config table so that the array can be accessed in Models, Views, Controllers, Helpers and Libraries and not need to do a database query each time.

This guy is doing it by creating a custom config, then populating the data in the constructor for that config: https://stackoverflow.com/questions/6463...gs-from-db

From what I can tell that will work, but unless I'm mistaken, every time config('foo')->bar gets called its going to call the constructor and pull all that data down from the database.  This defeats the purpose of trying to "load it into memory" once for use everywhere.

I was doing this through an event:

PHP Code:
$config = new Load_config();
Events::on('post_controller_constructor', [$config'load_config']); 

which is calling the load_config() function and that function populates the custom config I created.  The problem that I'm finding is that the data loaded into the custom config isn't persisting throughout.

Another idea that crossed my mind is loading the contents of the app_config table into the session data triggered by a post_controller_constructor event.  Any reason not to do that?

What is the best way to do what I'm trying to do here?
Reply
#2

There could be multiple different ways to do this.

Cache
You can  fetch the required data and store it in cache (say in your BaseController) and give it a reasonable expiration time.
This would have the added benefit of being available for a multiple different requests too.

Factories
Factories is something that sounds like an exact match for you.


Of course you can also combine the above two... have a Factory instantiate a configuration object for you and then use a setter method in the object to set it's internal properties form cache/database call.
This way you will have the config loaded from cache and also you can access your object in all classes/models/etc.. where you need it.

Personally, in one of my projects I use factories to pass around the user. When a request comes in a filter checks the JWT token (from Auth header/cookie) and after validation it instantiates a user object using factories.
This way i can access the user details in my controllers/models and other libraries where i need it.
Reply
#3

(02-11-2023, 08:32 AM)objecttothis Wrote: From what I can tell that will work, but unless I'm mistaken, every time config('foo')->bar gets called its going to call the constructor and pull all that data down from the database.  This defeats the purpose of trying to "load it into memory" once for use everywhere.

You are mistaken.
See https://codeigniter4.github.io/CodeIgnit...-factories
Reply
#4

(02-11-2023, 02:52 PM)kenjis Wrote:
(02-11-2023, 08:32 AM)objecttothis Wrote: From what I can tell that will work, but unless I'm mistaken, every time config('foo')->bar gets called its going to call the constructor and pull all that data down from the database.  This defeats the purpose of trying to "load it into memory" once for use everywhere.

You are mistaken.
See https://codeigniter4.github.io/CodeIgnit...-factories

Sounds like you are both saying Factories. Is there an advantage that factories has over loading the table values into session data and then referencing them using session('key');?
Reply
#5

(This post was last modified: 02-11-2023, 05:33 PM by kenjis.)

The session saves the data in session files (by default).
You can use the session data until the session expired/destroyed.
Each visitor will have their own session file.
So you should use Session for the data only for the visitor.

The Config (or any other) object is not saved, just in memory and you can share it with Factories only in one request.

You can save the object (if it can be serialized) with Cache.
https://codeigniter4.github.io/CodeIgnit...ching.html
Reply
#6

(This post was last modified: 02-12-2023, 10:02 AM by objecttothis. Edit Reason: clarity )

https://codeigniter4.github.io/CodeIgnit...tml#config So this is what's confusing me. 

I have a custom config class,
PHP Code:
class OSPOS extends BaseConfig
{
 public array 
$settings = [];

 public 
string $commit_sha1 '123abcd';


According to the factories documentation the config() convenience method calls a new instance of this class, so I am using factories already (without knowing it).  So factories doesn't help me to get the same set of data throughout the code.  I'm initially populating values in a post_controller_constructor event.

PHP Code:
public function load_config()
 {
 
//Database Configuration
 
$config config('OSPOS');
 
$appconfig model('Appconfig');

 foreach(
$appconfig->get_all()->getResult() as $app_config)
 {
 
$config->settings[$app_config->key] = $app_config->value;
 } 

The problem is that using the factory method I either need to do this work in the constructor, which pulls down the whole table every time config('OSPOS')->settings['variable_name'] is called or figure out how to have this instance persist.  If there is a way to make it persist using factories alone, it's unclear to me how.  It sounds like I may need to do what @qury is suggesting and use the load_config() function to instead load the app_config data into cache, then in the constructor/setter of the config class load the array from cache...

I guess in the end I'm trying to have something I don't have to reference in every single controller, model, view, helper and library I'm using it in... The config() convenience method seems to only be convenient if your config only has static data in it.
Reply
#7

If you want persistant data then you need to make your array settings STATIC.
What did you Try? What did you Get? What did you Expect?

Joined CodeIgniter Community 2009.  ( Skype: insitfx )
Reply




Theme © iAndrew 2016 - Forum software by © MyBB