Codeigniter template library and HMVC ( mx library ) the static method run() - codeigniter

i have this testing code which am working with ..
i have a module called ms and and another one called test
the test controller code is :
<?php
class Test extends MX_Controller {
public function __construct()
{
parent::__construct();
$this->template->title($this->config->item('site_name','app'));
}
public function index()
{
$this->template->build('index');
}
}
and the code inside ms is :
<?php
//ms module
class Msrofi extends MX_Controller {
public function __construct()
{
parent::__construct();
$this->template->title($this->config->item('site_name','app'));
}
public function index()
{
$t = Modules::run('test/test/index');
var_dump($t);
$this->template->build('index_message');
}
}
the problem is that the build function inside test is trying to find the index view file inside the ms views folder not the test views folder ..
i checked the $this->_module and it gave me the ms module name ..
any one know how to fix that ??

Since the test module is being called in the context of the ms one, $this->template->build() is looking for a view file in the ms module. The same way you can load models and libraries cross-module, you would have to do this for your view path as well:
class Test extends MX_Controller {
public function index()
{
// This path works only from the "test" module
// $this->template->build('index');
// This path works from any module
$this->template->build('test/index');
}
}
It's a little annoying maybe to have to explicitly call the module path in the module itself, but cross-module dependency defeat some of the goals of modularity in the first place.
A quick aside: Modules::run() output not returned, but directly echoed, so you can't assign it to a variable or print_r/var_dump it without using an output buffer:
ob_start();
Modules::run('test/test/index');
$t = ob_get_clean();
var_dump($t);

You can try to change the module.php the run method
The following example is I have to use the fix solution:
Open the third_party/MX/Modules.php
Near 75 lines to find
$buffer = ob_get_clean();
Increase in its following:
if($output === NULL && $buffer === ''){
$output = CI::$APP->output->get_output();
}
At this time, it should be able to work properly...

Related

How to extend Code igniter cache class Redis class

I am using redis for caching in one of my assignment. I am using CI default redis library for this purpose.
Now the issue with library is that it has some specific set of method which are used to set, get, delete , increment and decrement the redis keys & values.
I want to additional function of redis like lpush, rpush,lrem, lrange etc.
So to achieve this , i am trying to extend default CI redis class. which i am putting in application/libraries/driver/cache_redis_extended.php.
my code for this class is as follow.
<?php defined('BASEPATH') OR exit('No direct script access allowed');
class Cache_redis_extended extends CI_Cache_redis
{
function __construct()
{
parent::self;
}
public function rpush($list, $data)
{
$push = $this->_redis->multi(Redis::PIPELINE);
return $push->rpush($list, json_encode($data));
}
public function lrem($list, $data)
{
if((is_string($data) && (is_object(json_decode($data)) || is_array(json_decode($data))))) {
$data = $data;
}else{
json_encode($data);
}
return $this->_redis->lrem($list,-1, $data);
}
public function __destruct()
{
if ($this->_redis)
{
$this->_redis->close();
}
}
}
and in my model I am loading this class as follows
$CI->load->driver('cache', array('adapter' => 'redis'));
But I get this error:
Unable to load the requested class: cache_redis_extended
Any help is appreciated for this issue.
As I can see your driver name is not started with Capitalized , so
it can be possible the cause of your issue.
Because according to codeigniter the naming rule of a class as follows
Naming Conventions
File names must be capitalized. For example: Myclass.php
Class declarations must be capitalized. For example: class Myclass
Class names and file names must match.
change your file name
from cache_redis_extended.php
to Cache_redis_extended.php
I hope it will be helpful for you.

CodeIgniter: How to load my own class of static functions into a controller?

I have a class of static functions (common utility functions) that I wish to load into codeigniter. Currently I am loading it normally using an include_once(...) and it works as expected.
However, I want to load it using codeigniter's methodology. I understand that I should save my class file into the third_party directory; and that I should create a library class (saving it in the library directory) which requires my class.
Below are the three components, but it does not work.
1
// my class, saved at: APPPATH.'third_party/My_Class.php'
class My_Class
{
public static function my_static_utility_method ( )
{
return "booger" ;
}
// ...
}
2 - I understand that I am supposed to create a wrapper that obeys the CI rules of 'library' instantiation:
// saved at: APPPATH.'libraries/Library_Wrapper.php'
if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Library_Wrapper
{
public function __construct()
{
require_once APPPATH.'third_party/My_Class.php';
}
}
3 - Now I want to access the static methods of My_Class from my controller:
// saved at: APPPATH.'controllers/my_controller.php'
class My_Controller extends CI_Controller
{
public function __constructor( )
{
parent::__construct();
$this->load->library( 'Library_Wrapper' ) ;
}
public function some_function()
{
echo $this->My_Class->my_static_utility_method( ) ;
}
}
Try the following steps:
Create a new controller file: application/core/MY_Controller.php. In that file you may add your static functions.
<?php
class MY_Controller extends CI_Controller {
protected function static_fn1() {
//code
}
}
The controllers which need to access the static functions may extend this class like:
File: application/controllers/Welcome.php :
<?php
class Welcome extends MY_Controller {
public function fnname() {
//code
}
}
You've almost got the 3rd step in place but not quite. Loading the library will take the same name that you loaded it with:
//Load library
$this->load->library( 'Some_name' );
//Use Library
$this->some_name->someFunction();
So in your case, you'd need to switch method which accesses the library from:
//Will throw an PHP undefined My_Class error
echo $this->My_Class->my_static_utility_method();
to Library_wrapper instead:
//from $this->load->library( 'Library_wrapper' );
echo $this->library_wrapper->my_static_utility_method();
But this presents the next problem as My_Class is a property of library_wrapper so calling it gets a bit lengthy:
echo $this->library_wrapper->My_Class->my_static_utility_method();
Which should successfully call the My_Class descendent methods if publicly accessible.
This isn't clean as you would perfer. It would better to extend My_Class into Library_wrapper instead to share the static instances:
/**
* Static helper methods:
**/
class Library_wrapper extends My_Class {
}
It is possible to bind the 'load' the library to a different name (See "Assigning a Library to a different object name" header).
You can try the solution below:
in this hierarchy $this->library_wrapper->My_Class->my_static_utility_method();
use the php function listed at Php Functions to find out the methods/variables at each point in the hierarchy. This will pin point to the exact location where the things are going wrong.
I do NOT think you need to construct a class. The easiest way would be a helper ("Helpers, as the name suggests, help you with tasks. Each helper file is simply a collection of functions in a particular category" - just read the article from the official tutorial).
Your helper file with a name like myfunctions_helper.php will be located into /application/helpers folder and could have a structure like this:
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
if (!function_exists('my_static_fuction')) {
function my_static_fuction ( )
{
return "booger" ;
}
}
// etc...
Then you can autoload the helper declaring it to the /application/config/autoload.php.
$autoload['helper'] = array('url','myfunctions');
If you need to construct a class then a library like #MackieeE wrote will do the job (check the tutorial for more info).

Where to put this code in codeigniter

I put the following code in every controller under public function index(). As of now I have 3 controllers and it will increase until my website is finish. I need the code below in all pages (i.e. views).
$type = $this->input->post('type');
$checkin = $this->input->post('sd');
$checkout = $this->input->post('ed');
My question is where can I put the code above in just one location so it will be available on all pages (i.e. views) and avoid putting it in every controller.
If you have for example a main view file, and you need that code on every page, then I suggest you put in the main view file (view/index.php)
I think, with #KadekM answer, you should call a function every time in every controller, because you sad, you want this code in every controllers every function.
You can create your own controller (for example MY_cotroller) extending CI_controller, put shared code there, and then your three controllers should extend MY_controller.
You can then call it wherever you need it (or even put it to constructor if you need it everywhere).
Here's the sample I promised (assuming you have default codeigniter settings)
in core folder create file named MY_Controller.php
class MY_Controller extends CI_Controller{
protected $type;
protected $checkin;
protected $checkout;
protected $bar;
public function __construct()
{
parent::__construct();
$this->i_am_called_all_the_time();
}
private function i_am_called_all_the_time() {
$this->type = $this->input->post('type');
$this->checkin = $this->input->post('sd');
$this->checkout = $this->input->post('ed');
}
protected function only_for_some_controllers() {
$this->bar = $this->input->post('bar');
}
protected function i_am_shared_function_between_controllers() {
echo "Dont worry, be happy!";
}
}
then create your controller in controllers folder
class HelloWorld extends MY_Controller {
public function __construct() {
parent::__construct();
}
public function testMyStuff() {
// you can access parent's stuff (but only the one that was set), for example:
echo $this->type;
//echo $this->bar; // this will be empty, because we didn't set $this->bar
}
public function testSharedFunction() {
echo "some complex stuff";
$this->i_am_shared_function_between_controllers();
echo "some complex stuff";
}
}
then for example, another controller:
class HappyGuy extends MY_Controller {
public function __construct() {
parent::__construct();
$this->only_for_some_controllers(); // reads bar for every action
}
public function testMyStuff() {
// you can access parent's stuff here, for example:
echo $this->checkin;
echo $this->checkout;
echo $this->bar; // bar is also available here
}
public function anotherComplexFunction() {
echo "what is bar ?".$this->bar; // and here
echo "also shared stuff works here";
$this->i_am_shared_function_between_controllers();
}
}
Those are just examples, of course you won't echo stuff like this, but pass it to view etc., but I hope it's enough for illustration. Maybe someone comes with better design, but this is what I've used a few times.
id suggest , adding it to a library and then auto load the library so that each and every page on your website can access the same.
for autoloading reffer : autoload in codeigniter

How can I use CodeIgniter's active record (or models) object in a command line script?

Title pretty much sums it up. I'd like to write a script to import some data from a third party. Is there any way I can get either an instance of CodeIgniter's Active Record class, or of a particular model inside of an a script that can be run from the command line?
Say you have your CodeIgnited application inside ignited/, you have your command line script running in cli/. Here is your folder layout:
ignited/
application/
system/
index.php
cli/
mycli.php
Now you want cli/mycli.php to use some model from ignited/
First, you should do something with your ignited app:
Modify your default controller (which is set in ignited/application/config/routes.php). For example ignited/application/controllers/welcome.php:
class Welcome extends CI_Controller {
public function index()
{
$this->load->view('welcome_message');
}
}
add these code:
if ($this->input->is_cli_request())
{
return;
}
so it would look like:
class Welcome extends CI_Controller {
public function index()
{
if ($this->input->is_cli_request())
{
return;
}
$this->load->view('welcome_message');
}
}
For testing, I created a test model ignited/application/models/do_nothing_model.php:
class Do_nothing_model extends CI_Model {
public function __construct()
{
parent::__construct();
}
public function do_nothing()
{
return "Do nothing";
}
}
OK! Now try this in cli/mycli.php:
require_once('../ignited/index.php');
$ci =& get_instance();
$ci->load->model('do_nothing_model');
echo $ci->do_nothing_model->do_nothing();
Drawback: unable to run the default action of your default controller in command line
UPDATE 2012-06-08: from CodeIgniter Wiki
Not sure if this is what you want, but if you just need to run CI from CLI, here is the userguide reference:
http://codeigniter.com/user_guide/general/cli.html
To clarify, you don't need it web facing, just setup your app and run the commands you need (controller method input):
$ php index.php tools message "John Smith"
that example would run the primary index.php file for CI, then the tools controller and method message, "John Smith" is your input to message (could be a file reference that is local on the machine for your file import).

Codeigniter : calling a method of one controller from other

I have two controllers a and b.
I would like to call a method of controller a from a method of controller b.
Could anyone help explain how I can achieve this?
This is not supported behavior of the MVC System. If you want to execute an action of another controller you just redirect the user to the page you want (i.e. the controller function that consumes the url).
If you want common functionality, you should build a library to be used in the two different controllers.
I can only assume you want to build up your site a bit modular. (I.e. re-use the output of one controller method in other controller methods.) There's some plugins / extensions for CI that help you build like that. However, the simplest way is to use a library to build up common "controls" (i.e. load the model, render the view into a string). Then you can return that string and pass it along to the other controller's view.
You can load into a string by adding true at the end of the view call:
$string_view = $this->load->view('someview', array('data'=>'stuff'), true);
test.php Controller File :
Class Test {
function demo() {
echo "Hello";
}
}
test1.php Controller File :
Class Test1 {
function demo2() {
require('test.php');
$test = new Test();
$test->demo();
}
}
Very simple way in codeigniter to call a method of one controller to other controller
1. Controller A
class A extends CI_Controller {
public function __construct()
{
parent::__construct();
}
function custom_a()
{
}
}
2. Controller B
class B extends CI_Controller {
public function __construct()
{
parent::__construct();
}
function custom_b()
{
require_once(APPPATH.'controllers/a.php'); //include controller
$aObj = new a(); //create object
$aObj->custom_a(); //call function
}
}
I agree that the way to do is to redirect to the new controller in usual cases.
I came across a use case where I needed to display the same page to 2 different kind of users (backend user previewing the page of a frontend user) so in my opinion what I needed was genuinely to call the frontend controller from the backend controller.
I solved the problem by making the frontend method static and wrapping it in another method.
Hope it helps!
//==========
// Frontend
//==========
function profile()
{
//Access check
//Get profile id
$id = get_user_id();
return self::_profile($id);
}
static function _profile($id)
{
$CI = &get_instance();
//Prepare page
//Load view
}
//==========
// Backend
//==========
function preview_profile($id)
{
$this->load->file('controllers/frontend.php', false);
Frontend::_profile($id);
}
I posted a somewhat similar question a while back, but regarding a model on CI.
Returning two separate query results within a model function
Although your question is not exactly the same, I believe the solution follows the same principle: if you're proposing to do what you mention in your question, there may be something wrong in the way you're coding and some refactoring could be in order.
The take home message is that what you're asking is not the way to go when working with MVC.
The best practice is to either use a Model to place reusable functions and call them in a controller that outputs the data through a view -- or even better use helpers or libraries (for functions that may be needed repeatedly).
You can do like
$result= file_get_contents(site_url('[ADDRESS TO CONTROLLER FUNCTION]'));
Replace [ADDRESS TO CONTROLLER FUNCTION] by the way we use in site_url();
You need to echo output in controller function instead of return.
You can use the redirect() function.
Like this
class ControllerA extends CI_Controller{
public function MethodA(){
redirect("ControllerB/MethodB");
}
}
Controller to be extended
require_once(PHYSICAL_BASE_URL . 'system/application/controllers/abc.php');
$report= new onlineAssessmentReport();
echo ($report->detailView());
You can use the redirect URL to controller:
Class Ctrlr1 extends CI_Controller{
public void my_fct1(){
redirect('Ctrlr2 /my_fct2', 'refresh');
}
}
Class Ctrlr2 extends CI_Controller{
public void my_fct2(){
$this->load->view('view1');
}
}
very simple
in first controllr call
$this->load->model('MyController');
$this->MyController->test();
place file MyController.php to /model patch
MyController.php should be contain
class MyController extends CI_Model {
function __construct() {
parent::__construct();
}
function test()
{
echo 'OK';
}
}

Resources