Extending CodeIgniter core classes - codeigniter

I have in my core folder, 2 controllers:
MY_Controller
MY_AdminController
Both extend CI_Controller. First one works great, but second one no, when I call the controller which is inheriting from MY_AdminController I get an error:
Fatal error: Class 'MY_AdminController' not found
After doing some research I found:
https://codeigniter.com/user_guide/general/core_classes.html
In this document it says you use "MY_" prefix (possible to change it in config) to extend core classes, I am doing that.
What am I missing?
UPDATE
I am wondering if the problem is because since I am creating a file inside "core" folder, CI checks if it does exist an original on its own core with same name but prefix CI?

to allow any new class . means which class are note defined in system/core
solution could be as follow.
Try putting below function at the bottom of config file
/application/config/config.php
function __autoload($class) {
if(strpos($class, 'CI_') !== 0)
{
#include_once( APPPATH . 'core/'. $class . '.php' );
} }
My core class My_head not found in codeigniter

Here is a good explanation as to why you can't do it the way you have described. Essentially CodeIgniter looks for ['subclass_prefix'] . $Classname, e.g. 'MY_' . 'Controller'. And here is the same question for CI2
Solution:
Put both MY_Controller and MY_AdminController in MY_Controller.php
MY_Controller.php
class MY_Controller extends CI_Controller {
public function __construct() {
parent::__construct();
}
...
}
class MY_AdminController extends CI_Controller {
public function __construct() {
parent::__construct();
}
...
}

Related

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).

controller and routes doesn't generate the index.php I'm using laravel 4.1

I am a newbie at laravel. I have a problem about rooting and views. I am following a tutorial. But the output with the tutorial and my output are not the same.
when i insert this at address bar localhost/laravel/2nd_project/public/authors, i am not generating the index.php which supposed to be have a output just like the tutorial
here is the controllers/authors.php
<?php
class Authors_Controller extends Base_Controller{
public $restful = true;
public function get_index(){
return View::make('authors.index');
}
}
app/routes.php
<?php
Route::get('/', function()
{
return View::make('hello');
});
Route::get('authors',array('uses'=>'Authors_Controller#get_index'));
views/authors/index.php
<h1>Hi User!!</h1>
It looks like you're following the tutorial based on Laravel 3. In Laravel 4, things have changed. In laravel 4, the controllers name must follow the pattern SomethingController, so the filename for your controller must be AuthorsController.php and the class name muse be AuthorsController.
So, inside of controllers directory, you'll have a file named AuthorsController.php which will be like:
<?php
class AuthorsController extends BaseController {
public function getIndex()
{
return View::make('authors.index');
}
}
Also, if you need to have a file named BaseController.php with the class BaseController, if you're extending BaseController from the AuthorsController.
In the routes file you can do the following:
Route::get('authors', array('uses'=>'AuthorsController#getIndex'));
If you want RESTful controllers in Laravel 4, you can read more about it in the official documentation here: http://laravel.com/docs/controllers#restful-controllers

default language codeigniter

i want to run this code at the first of all my webpages,
I'm using codeigniter
the code is:
if(!$this->session->userdata('lang')):
$this->session->set_userdata('lang','ar');
endif;
how to do that?
If you haven't already, it may be worth looking at CodeIgniter's language class.
You can extend the native CI_Controller class. Extending this class allows you to add your additional functionality, while the original functionality of the native core class remains.
For the code to run first on all pages, you can add your code to the constructor of the newly created subclass - if you extend your controller(s) with the new subclass, then this code will be run when any function in your controller(s) is called. To do this:
Create a subclass
Create a file named MY_Controller.php in the application/core/ directory of your project. This new class needs to extend CI_Controller and the parent constructor. The class should look something like this:
<?php
class MY_Controller extends CI_Controller {
public function __construct()
{
parent::__construct(); //make sure you extend the parent constructor
//Your code:
if( ! $this->session->userdata('lang') )
$this->session->set_userdata('lang','ar');
}
}
Ensure the class prefix is correct
If you've used MY_ as the prefix for the new class then you shouldn't need to do anything here, but it's useful to know anyway.
You'll also need to ensure that the sub-class prefix is set correctly in the application/config/config.php file.
$config['subclass_prefix'] = 'MY_';
This prefix must match the prefix of the new class that you create. By default it is MY_ but you can change it to what you want as long as they correspond - FOO_, BAR_, WHATEVER_... The exception is CI_, which is reserved for CodeIgniter's native libraries.
Extend all of you application's controller with the new subclass
Your controller(s) in application/controllers/ is(/are) probably extending CI_Controller. To make use of the newly created subclass, your controller should extend MY_Controller and the parent constructor.
class Welcome extends MY_Controller {
function __construct()
{
parent::__construct();
}
//More functions...
}

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

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...

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