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');
Related
I am attempting to override a module in Prestashop but the changes are just not appearing.
I have overridden a template file and a controller so I have added the following files:
\override\modules\blockwishlist\views\templates\front\mywishlist.tpl
\override\modules\blockwishlist\controllers\front\mywishlist.php
These are very simple changes where I add another column to a table that contains a button. When the button is clicked the controller generates a CSV file.
Any idea why these changes are just not being shown?
Note: I have turned on 'Force Compile' and turned of caching.
Edit:
Re overridding a controller is it:
class BlockWishListMyWishListModuleFrontController extends BlockWishListMyWishListModuleFrontControllerCore // extends ModuleFrontController
or
class BlockWishListMyWishListModuleFrontControllerOverride extends BlockWishListMyWishListModuleFrontController
okay, I did some code research (maybe thre is exists easiest way, not sure), so:
in code Dispatcher class we have
// Dispatch module controller for front office
case self::FC_MODULE :
$module_name = Validate::isModuleName(Tools::getValue('module')) ? Tools::getValue('module') : '';
$module = Module::getInstanceByName($module_name);
$controller_class = 'PageNotFoundController';
if (Validate::isLoadedObject($module) && $module->active) {
$controllers = Dispatcher::getControllers(_PS_MODULE_DIR_.$module_name.'/controllers/front/');
if (isset($controllers[strtolower($this->controller)])) {
include_once(_PS_MODULE_DIR_.$module_name.'/controllers/front/'.$this->controller.'.php');
$controller_class = $module_name.$this->controller.'ModuleFrontController';
}
}
$params_hook_action_dispatcher = array('controller_type' => self::FC_FRONT, 'controller_class' => $controller_class, 'is_module' => 1);
break;
where we see that controllers loaded without overrides, but from other side below in code we see hook execution:
// Loading controller
$controller = Controller::getController($controller_class);
// Execute hook dispatcher
if (isset($params_hook_action_dispatcher)) {
Hook::exec('actionDispatcher', $params_hook_action_dispatcher);
}
so one of possible solution (without overriding core class) :
how to override module and hope you have core version >= 1.6.0.11
in blockwishlist.php in install() method add
this->registerHook('actionDispatcher')
to condition with other hooks, so it will looks like ... !this->registerHook('actionDispatcher') || ... because this hook not registered by default and we can't just place module there.
create method (can't beautify code here)
public function hookActionDispatcher($params)
{
if ('blockwishlistmywishlistModuleFrontController' == $params['controller_class']) {
include_once(_PS_OVERRIDE_DIR_ . 'modules/' . $this->name . '/controllers/front/mywishlist.php');
$controller = Controller::getController('BlockWishListMyWishListModuleFrontControllerOverride');
}
}
you already have override/modules/blockwishlist/controllers/front/mywishlist.php file by this path
reinstall module.
it works!
more about overriding some behaviors in docs
Turns out that to override a module you dont place your files in:
~/overrides/module/MODULE_NAME
Instead you place it in:
~/themes/MY_THEME/modules/MODULE_NAME
Now the changes are exhibiting themselves.
Does anyone know if/when the module is auto-updated, will my changes get lost/overrwritten?
I would like to create my own function called anchor_admin() based on anchor() function in CodeIgniter.
I was thinking like:
I have defined admin path in config.php file e.g. like this:
$config['base_url'] = '';
$config['base_url_admin'] = 'my-custom-admin-folder';
and then
I need somehow create a new anchor_admin() function that extends anchor() function.
so instead of typing:
<?php echo anchor('my-custom-admin-folder/gallery', 'Gallery', 'class="admin-link"'); ?>
I would type only:
<?php echo anchor_admin('gallery', 'Gallery', 'class="admin-link"'); ?>
But the output wold be always:
Gallery
Basically I only need to ad the config variable $this->config->item('base_url_admin') at the end of the url generated by the core anchor() function.
How to do that?
Which files do I nned to create and where to put?
I guess creating a helper is not the way to go.
Should I create a library or could it be put as a function within my MY_Controller file in core folder of my application that I already have created and I am using it to load some stuff already?
In CodeIgniter you can 'extend' helpers ('extend' being a catch all term in this case as they're not actually classes). This allows you to add your own helper functions that will be loaded with the standard ones (in your case, the URL Helper).
It's explained in the CodeIgniter docs here - http://ellislab.com/codeigniter/user-guide/general/helpers.html
In your case you would want to do the following:
1- Create the file MY_url_helper.php in application/helpers/
2- Create your anchor_admin() function as below:
function anchor_admin($uri = '', $title = '', $attributes = '') {
// Get the admin folder from your config
$CI =& get_instance();
$admin_folder = $CI->config->item('base_url_admin');
$title = (string) $title;
if ( ! is_array($uri)) {
// Add the admin folder on to the start of the uri string
$site_url = site_url($admin_folder.'/'.$uri);
} else {
// Add the admin folder on to the start of the uri array
array_unshift($uri, $admin_folder);
$site_url = site_url($uri);
}
if ($title == '') {
$title = $site_url;
}
if ($attributes != '') {
$attributes = _parse_attributes($attributes);
}
return '<a href="'.$site_url.'"'.$attributes.'>'.$title.'</a>';
}
3- Use the helper and function how you normally would:
$this->load->helper('url');
echo anchor_admin('controller/method/param', 'This is an Admin link', array('id' => 'admin_link'));
Hope that helps!
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();
}
}
dir:
application
-controllers
-models
-views
-mobile_views
How do I auto load templates at mobile_views when I use $this->load->view and view by iphone or other mobile phone?
Check this
You can do it in two way.
Way 1: Its very simple. In the above answer (the link I have given) add following line in the end of MyController function
$this->load->_ci_view_path . = $this->view_type .'/';
You are done. You can simply load view like normal view load.
Way 2:
To autoload a view based on user agent, I think you can implement it using hooks. To implement this hooks you need to follow the following steps
Autoload user agent library in autoload.php
$autoload['libraries'] = array('user_agent');
Enable hooks in config.php
$config['enable_hooks'] = TRUE;
Not implement hooks on post_controller_constructor. Add following codes to hooks.php
$hook['post_controller_constructor'][] = array('class' => 'Loadview',
'function' => 'load',
'filename' => 'loadview.php',
'filepath' => 'hooks'
);
Now create a page named loadview.php under hooks directory having following code
class Loadview
{
public static $MOBILE_PLATFORM = 'mobile';
public static $DEFAULT_PLATFORM = 'default';
public function load(){
$this->CI =& get_instance();
$view_type = $this->CI->agent->is_mobile() ? self::$MOBILE_PLATFORM : self::$DEFAULT_PLATFORM;
$this->CI->load->_ci_view_path = $this->CI->load->_ci_view_path . $view_type .'/';
}
}
You are done now. You can simply load view like normal view load.
to load views from another dir aside from "views", i found this forum topic to be helpful
http://codeigniter.com/forums/viewthread/132960/
function external_view($path, $view, $vars = array(), $return = FALSE)
{
$full_path = $path.$view.'.php';
if (file_exists($full_path))
{
return $this->_ci_load(array('_ci_path' => $full_path, '_ci_view' => $view, '_ci_vars' => $this->_ci_object_to_array($vars), '_ci_return' => $return));
}
else
{
show_error('Unable to load the requested module template file: '.$view);
}
}
and you can work the rest from the controller.
I do this in my controller:
public function index()
{
if($this->agent->is_mobile())
{
$this->load_mobile();
}
else
{
$this->load_web();
}
}
public function load_mobile()
{
$this->load->view('mobile/home');
}
public function load_web()
{
$this->load->view('web/home');
}
In this way I can add different data to mobile and to web pages.
I also extend the default controller and add some useful extra features:
Enables the usage of master page/templates.
Can add css and javascript files.
Uses the _output method for controlling the controllers output.
Can load relative content with in the form of modules (views)
So I can manage better the different pages.
Bye!!
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.