I just started using a PHP framework, Kohana (V2.3.4) and I am trying to set up a config file for each of my controllers.
I never used a framework before, so obviously Kohana is new to me. I was wondering how I should set up my controllers to read my config file.
For example, I have an article controller and a config file for that controller. I have 3 ways of loading config settings
// config/article.php
$config = array(
'display_limit' => 25, // limit of articles to list
'comment_display_limit' => 20, // limit of comments to list for each article
// other things
);
Should I
A) Load everything into an array of settings
// set a config array
class article_controller extends controller{
public $config = array();
function __construct(){
$this->config = Kohana::config('article');
}
}
B) Load and set each setting as its own property
// set each config as a property
class article_controller extends controller{
public $display_limit;
public $comment_display_limit;
function __construct(){
$config = Kohana::config('article');
foreach ($config as $key => $value){
$this->$key = $value;
}
}
}
C) Load each setting only when needed
// load config settings only when needed
class article_controller extends controller{
function __construct(){}
// list all articles
function show_all(){
$display_limit = Kohana::config('article.display_limit');
}
// list article, with all comments
function show($id = 0){
$comment_display)limit = Kohana::config('article.comment_display_limit');
}
}
Note: Kohana::config() returns an array of items.
Thanks
If you are reading a group of configuration items for a controller, store them in class member ($this->config), if you are reading a single configuration item; read it individually.
I think first method (A) should be fine, it has lesser code and serves the purpose fine.
If you have site wide stuff that you want access to from "anywhere", another way of doing it may be to put something like:
Kohana::$config->attach(new Kohana_Config_File('global'));
in bootstrap.php. Then create global.php in the application/config directory with something like:
return (array ('MyFirstVar' => 'Is One',
'MySecondVar' => 'Is Two'));
And then when you need it from your code:
Kohana::config ('global.MyFirstVar');
But I suppose all of this comes down to where and how you want to use it.
Related
I have a database that holds several basis configuration settings for my site. The idea is to pull the values from the database and then make the values accessible globally. I also would like to implement $this->cachePage(DAY); to make sure the site is not constantly asking for configurations settings.
This is mysql table
I have put the following code into public function initController method of the
BaseController:
$global_app_settings = array();
$this->AppSettingModel = new \App\Models\AppSettingModel;
$app_settings = $this->AppSettingModel->getAppSettings();
foreach ($app_settings as $row) {
$global_app_settings[$row->app_setting_key] = $row->app_setting_value;
}
The above code works fine. If I print to screen, it produces the following;
Array
(
[dh_company_name] => A Big Company
[dh_phone_number] => +81-3-5555-5555
[dh_fax_number] => +81-3-5555-5556
)
My questions are as follows;
how can I make the array viable globally in my app?
Where can I add this? $this->cachePage(DAY);
It's simple actually.
public function loadGlobalSettings()
{
$globalSettings = cache('global_settings');
if (null === $globalSettings) {
$appSettingModel = model('\App\Models\AppSettingModel');
$app_settings = $appSettingModel->getAppSettings();
$globalSettings = [];
foreach ($app_settings as $row) {
$globalSettings[$row->app_setting_key] = $row->app_setting_value;
}
cache()->save('global_settings', $globalSettings, DAY*15);
}
return $globalSettings;
}
How it runs:
Try to get from cache.
If cache not exists (returned null), load model, get settings, then cache it.
Return settings array.
Have fun!
Define a protected variable in BaseController class and set it in initController
Put this in your controller
public function __construct()
{
this->cachePage(15);
}
I am working in a custom library for a project to be used in CI3.1 (CodeIgniter 3.1). This is a piece of code:
class NavigationMenu
{
protected $CI;
public function __construct($params = ['config' => 'navigation'])
{
$this->CI =& get_instance();
$this->CI->load->helper('url');
$this->CI->config->load($params['config'], true);
$this->CI->load->model('nav_model', 'nav');
}
....
}
The default config 'navigation.php` file have the following code:
$config['navigation_open'] = '<ul class="nav">';
$config['navigation_close'] = '</ul>';
$config['item_open'] = '<li>';
$config['item_open_active_class'] = 'active';
As you can see I am loading the url helper, the navigation config file and the nav_model model. Is there any way to check if them has been loaded previously? Could be the case when I want to save time and then setup the autoload.php as follow:
$autoload['helper'] = ['url'];
$autoload['config'] = ['navigation'];
$autoload['model'] = ['nav_model'];
If that's the case how do I check if has been loaded in order to not try to load once again?
I have look over the documentation for config class and couldn't find anything helpful
You can check is any function from url helper available at the moment, so You'll be able to understand was helper loaded or You should do it by Yourself:
if(!function_exists('site_url'))
$this->CI->load->helper('url');
It's an easy trick if You need to check is any helper was loaded, but it's not too clear how to check is config/model loaded, so if You really want to create Your own autoloader, You need to do similar checks with the core object ($this->CI):
if(!method_exists($this->CI,'nav'))
$this->CI->load->model('nav_model', 'nav');
Hi,
In Zend Framwork 1, I used to have an application\configs\appsettings.xml, where I used to store params and values like hostnames for Rest API URLs, debug settings and other application specific settings for dev, test and prod environments. This registry was available to me across all controllers and models and was created in index.php
$applicationEnvironment = 'development';
$config = new Zend_Config_Xml( APPLICATION_PATH . '/configs/appsettings.xml',
$applicationEnvironment, true );
Zend_Registry::set( 'config', $config );
How do I achieve similar thing in Zend Framework 2?
Thanks
There is no such thing as a Registry in ZF2 because it is kind of an anti pattern. It's just a fancy substitution for global variables, which can cause all sort of unwanted side effects in your application.
In ZF2 you have the serviceManager and this allow to cleanly inject all your dependencies into your controllers/models/services. All config files in the config/autoload directory are automaticaly merged into one single array by ZF2 and you can retrieve this from the service manager using $serviceLocator->get('Config'). Whenever you need to use configuration in your controller just create a serviceFactory and inject the config.
class FooController
{
protected $config;
public __construct($config)
{
$this->config = $config;
}
public barAction()
{
//use $this->config
}
}
class Module
{
public function getControllerConfig()
{
return array(
'factories' => array(
'fooController' => function(ControllerManager $cm)
{
$sm = $cm->getServiceLocator();
$config = $sm->get('Config');
$controller = new FooController($config);
return $controller;
},
),
);
}
}
For sake of simplicity the factory above is defined as a closure, but I'd suggest to create a seperate factory class. There are many resources which explain how to do that.
In this example we are injecting the complete configuration, but depending on your use case it will generally be better to only inject the config keys you need.
Alternatively you can wrap certain config values into a dedicated config object with explicit getters and setters and inject this into your controller. Zend\StdLib\AbstractOptions can help you.
If you wish to work with config files and you dont have access to the Service Manager or you wish to write content to it, you can use Zend\Config
To read from, you can do something like:
$config = new Config(include 'config/autoload/my_amazing_config.global.php');
$details = $config->get('array_key')->get(sub_key)->toArray();
To write to, you can do:
// Create the config object
$config = new Zend\Config\Config(array(), true);
$config->production = array();
$config->production->webhost = 'www.example.com';
$config->production->database = array();
$config->production->database->params = array();
$config->production->database->params->host = 'localhost';
$config->production->database->params->username = 'production';
$config->production->database->params->password = 'secret';
$config->production->database->params->dbname = 'dbproduction';
$writer = new Zend\Config\Writer\Xml();
echo $writer->toString($config);
The class support ini, xml, phpArray, json, yaml
You can read more at:
http://framework.zend.com/manual/2.2/en/modules/zend.config.introduction.html
I hope someone can help me with this one before I jump off the window. I spent few hours on this one and don't know what am I doing wrong.
Basically, I've installed HMVC in CodeIgniter 2.1.2 and everything works fine, BUT for some reason I can't load models the same way I'm doing it in standard controllers. In the old codeigniter 1.7.1 I could use it simply by invoking $this->load->model('my_model') but now I can't?!
Every single time I'm trying to load model I get this error:
A PHP Error was encountered
Severity: Notice
Message: Undefined property: Special_cart::$db
Filename: core/Model.php
Line Number: 51
I have had installed it step-by-step according to the instructions. I got third_party next to modules folder. In modules I have few modules stored like this:
modules
--boxes
----controller
----models
----views
I invoke module in my code like this:
<?=modules::run('boxes/special_cart/index');?>
My module controller code looks like this:
class Special_cart extends CI_Controller
{
public function __construct()
{
parent::__construct();
}
public function index()
{
if ($this->session->userdata('cart'))
{
# get product id's and each quantity
$cart_product_list = array_count_values($this->session->userdata('cart'));
# get list of product_id
$product_list = array_keys($cart_product_list);
# get product details
$this->load->model('productmodel');
$this->load->model('stockmodel');
$cart_products = $this->productmodel->cart_get_products_details($product_list);
$final_cart_array = array();
foreach($cart_products as $cart_product){
$product_stock = $this->stockmodel->view_product_stock($cart_product["id"]);
if(empty($product_stock) || $product_stock["UNITS"]<=0)
$cart_product["UNITS"] = 0;
else{
if($cart_product_list[$cart_product["id_web"]]>$product_stock["UNITS"])
$cart_product["UNITS"] = $product_stock["UNITS"];
else{
$cart_product["UNITS"] = $cart_product_list[$cart_product["id_web"]];
}
}
$final_cart_array[] = $cart_product;
}
$refresh_cart_array = array();
foreach($final_cart_array as $cart_product){
for($i=1;$i<=$cart_product["UNITS"];$i++){
$refresh_cart_array[] = $cart_product["id_web"];
}
}
$this->load->view("special_cart",array(
'refresh_cart_array' => $refresh_cart_array,
'final_cart_array' => $final_cart_array
));
} else {
$this->load->view("special_cart",array(
'refresh_cart_array' => NULL,
'final_cart_array' => NULL
));
}
}
}
I've tried every possible solution found on internet - none of them work....
I hope you understand my problem but in case you need some further explanation please ask me. Can anyone help?
Looks like the model you're trying to load wants to connect to the db, but the database driver is not available. If you use database queries in your application, why don't you load the database driver automatically?
Just insert "database" in the "libraries" array in application/config/autoload.php file. Don't forget to insert your database credentials into application/config/database.php.
$autoload['libraries'] = array('database');
If you need database connection just in one single model, load it before trying to access database library.
$this->load->database();
Try loading the model stating the module name as follows
$this->load->model('module_name/productmodel');
Class Models extends MX_Loader{
function getUser($username){
$sql="SELECT * FROM user WHERE username = ? ";
return $this->db->query($sql,array($username))->row();
}
}
you must using extends MX_Loader because i don't know if using CI_Model the database core cant be load in Codeigniter,,,
Try to use extend MX_Controller class (not CI_Contoller like you are doing atm)
Based on what you have wrote in comment above, I figured that you tried to create new instance of DB in module (based on chrises comment).
Do it on constuctor of Special_cart
So update current construct to be like
public function __construct()
{
parent::__construct();
$this->load->database('default');
}
(I'm writing this from top of my head, so check the methods)
Now for sure db driver should be available in your models.
Regarding issue with HMVC I dont think there are any. I'm using HMVC for a while now, and I found no problems in it (working with databases)
I had the same problem and mistake. I missed to extend controllers to MX_Controller. So the solution would be to change CI_Controller to MX_Controller like this:
class Special_cart extends MX_Controller
{
public function __construct()
{
parent::__construct();
$this->load->model('productmodel');
$this->load->model('stockmodel');
}
public function index()
{
if ($this->session->userdata('cart'))
{
# get product id's and each quantity
$cart_product_list = array_count_values($this->session->userdata('cart'));
# get list of product_id
$product_list = array_keys($cart_product_list);
# get product details
$cart_products = $this->productmodel->cart_get_products_details($product_list);
$final_cart_array = array();
foreach($cart_products as $cart_product){
$product_stock = $this->stockmodel->view_product_stock($cart_product["id"]);
if(empty($product_stock) || $product_stock["UNITS"]<=0)
$cart_product["UNITS"] = 0;
else{
if($cart_product_list[$cart_product["id_web"]]>$product_stock["UNITS"])
$cart_product["UNITS"] = $product_stock["UNITS"];
else{
$cart_product["UNITS"] = $cart_product_list[$cart_product["id_web"]];
}
}
$final_cart_array[] = $cart_product;
}
$refresh_cart_array = array();
foreach($final_cart_array as $cart_product){
for($i=1;$i<=$cart_product["UNITS"];$i++){
$refresh_cart_array[] = $cart_product["id_web"];
}
}
$this->load->view("special_cart",array(
'refresh_cart_array' => $refresh_cart_array,
'final_cart_array' => $final_cart_array
));
} else {
$this->load->view("special_cart",array(
'refresh_cart_array' => NULL,
'final_cart_array' => NULL
));
}
}
}
this is also explained in the documentation
https://bitbucket.org/wiredesignz/codeigniter-modular-extensions-hmvc/
, here the quote:
Notes:
To use HMVC functionality, such as Modules::run(), controllers must
extend the MX_Controller class. To use Modular Separation only,
without HMVC, controllers will extend the CodeIgniter Controller
class. You must use PHP5 style constructors in your controllers. ie:
<?php
class Xyz extends MX_Controller
{
function __construct()
{
parent::__construct();
}
}
I have a library in code igniter that looks like class MyClass($options = array())
The file is Myclass.php
I have a file (config/Myclass.php) that looks like
$Myclass = array(
'something' => 'value',
'another' => 'value'
);
Which I thought should pass the $Myclass array in when I initialize my class, but apparently not?
What do I need to do to fix it?
AH I found the answer,
The array inside your config file must be called $config.
The name of the file must also be a lower case representation of the library file name.
e.g
LIB FILE: Somelibrary.php
LIB CONTENTS: class Somelibrary($options = array()){...
CONF FILE: somelibrary.php
CONF CONTENTS: $config = array('something' => 'value');
The way this usually works is that you pass in an array of options you wish to override, or pass in nothing to use the defaults.
var myObject = new MyClass(); // default settings
var myObject = new MyClass(array('something' => 'value2')); // override only "something"
Honestly, I wouldn't create your own file in config without a good reason; instead, just put the defaults in your class definition, and then override in your constructor:
class MyClass {
var $default_options = array(
'something' => 'value',
'another' => 'value',
);
var $options = array();
function MyClass($override_options = array())
{
$this->options = array_merge($this->default_options, $override_options);
// your code here...
}
}
Fast-forward to 2013, someone is still having problems with this. So my situation was the same but slightly different, so I thought I'd try to save someone else some time.
I was naming my config file after my extended class, that was wrong. The Config file should always be form_validation.php, (this is because eventually it is handed to the CI_Form_validation class and that's what it expects)
Thanks to the folks who answered this question above, I realized that I had to pass the config to the parent class and using codeigniter v2.1.3 I did it as follows:
public function __construct( $config = array() )
{
parent::__construct($config);
}