This is my hooks.php
$hook['pre_controller'] = array(
'class' => 'UpdateSession',
'function' => 'index',
'filename' => 'UpdateSession.php',
'filepath' => 'hooks',
'params' => array()
);
And this is my UpdateSession.php which is placed in hooks folder.
<?php
class UpdateSession extends CI_Controller
{
public function __construct()
{
$this->CI =& get_instance();
$this->CI->load->library("session");
}
public function index()
{
if($this->CI->session->userdata('user_id'))
{
$query = $this->CI->db->get_where('cp_sessions', array('user_id' => $this->CI->session->userdata('user_id')));
$session_info = $query->row_array();
if($session_info['session_id'] != $this->CI->session->userdata('user_id'))
{
$new_session_id = array('session_id' => $this->CI->session->userdata('user_id'));
$this->db->update('cp_sessions', $new_session_id, array('user_id' => $this->CI->session->userdata('user_id')));
}
}
}
}
This gives me the following error
Fatal error: Call to a member function library() on a non-object in
C:\xampp\htdocs\website\pokeradda\application\hooks\UpdateSession.php on line 8
I have tried to remove extends CI_Controller but same problem is there.
if you are using pre-controller hook means you are calling your class before controllers are loaded. so that You can not get the CI instance in this hook, because CI is not loaded yet!
you can’t get the CI instance in SOME hooks :
CAN’T : pre_system , pre_controller
CAN : post_controller_constructor, post_controller, display_override, cache_override, post_system
you can use My_controller and extend your controller from it. add the functionality in My_controller constructor. (a suggestion as a work-around)
Related
My first controller is
class MatchesController extends AbstractActionController {
public function checkLogsAction() {
// $logs=new LogsController();
$logs=$this->getServiceLocator()->get('Admin\LogsController');
$logs->writeLogs("log data");
die();
}
Logs Controller
class LogsController extends AbstractActionController {
public function writeLogs($logData) {
$this->getServiceLocator()->get('Zend\Log\opta')->info($logData);
return true;
}
global.php
'service_manager' => array(
'factories' => array(
'Zend\Db\Adapter\Adapter' => 'Zend\Db\Adapter\AdapterServiceFactory',
'Zend\Log\opta' => function ($sm) {
$fileName=date("Y-m-d");
$log = new Zend\Log\Logger();
$writer = new Zend\Log\Writer\Stream("./data/opta/$fileName");
$log->addWriter($writer);
return $log;
}
),
),
module.php
public function getServiceConfig() {
return array(
"factories"=>array(
'Admin\LogsController' => function ($sm) {
$logsController = new LogsController();
return $logsController;
},
I am getting this error:
Fatal error: Call to a member function get() on null
Please help me to solve the solution
Your Admin\LogsController extends AbstractActionController. But you do not use it as AbstractActionController!
An AbstractActionController is usuallay invoked by processing the (http) request, whereby the ZF2 application is going to route the request to a controller and executes an action method. During this processing, an instance of ServiceLocator/ServiceManager is passed to the controller. That is what you are missing. Hence, you try to call a method on a null object.
You can not simply instantiate an ActionController from another ActionController. (of course, it is possible, with a lot of afford). If you use it this way, you to make sure the new controller instance holds an instance of the ServiceLocator, request, response etc...
You should consider:
a) is Admin\LogsController really a AbstractActionController in your application? (I assume it is not, respectively your code example)
b) inject the ServiceLocator in to your custom object (LogsController), or a way cleaner: inject the logger instance.
Example:
public function getServiceConfig() {
return array(
'factories' => array(
'Admin\LogsController' => function ($sm) {
$logsController = new LogsController();
$logsController->setServiceLocator($sm); // you have to implement!
return $logsController;
},
);
}
I have created on hook to set current visiting URL to session. I have to use this URL later on. I have called session method of codeIgniter using $this->CI =& get_instance(); and then $this->CI->session->userdata but it is giving
Trying to get property of non-object on $this->CI->session->userdata line
I have done following things to enable hooks in CI
config.php
$config['enable_hooks'] = TRUE;
hooks.php
$hook['pre_controller'] = array(
'class' => 'Preclass',
'function' => 'checkreq',
'filename' => 'preclass.php',
'filepath' => 'hooks',
'params' => array()
);
preclass.php
class Preclass
{
private $CI;
public function __construct()
{
$this->CI =& get_instance();
}
public function checkreq($value='')
{
var_dump($this->CI->session->userdata);
die;
}
}
Note: Don't close this post as Duplicate of PHP errors. As I know about errors. This is in CodeIgniter and I want to check session before any controller method gets invoked.
From comment: "But I want it before controller methods invoke even before constructor"
To solve your issue, this is about the best you can do:
Make an MY_Controller.php in application/core:
class MY_Controller extends CI_Controller {
public function __construct() {
parent::__construct();
// class is just an alias for the controller name
if (!$this->user->is_allowed($this->router->class)) {
redirect('somepage');
}
}
}
Then have all your controllers extend MY_Controller:
class Somecontroller extends MY_Controller {
public function __construct() {
parent::__construct();
// nothing below the above line will be reached
// if the user isn't allowed
}
}
Whether or not you have a __construct() method in the class: nothing will happen so long as the user isn't allowed to access the page e.g. nothing after parent::__construct() will be called - even methods. Again, the fact that the parent constructor is called is implied if no constructor exists for the controller.
Note: if you autoload a model and do the same logic in the MY_Controller in the models __construct() the same results should be achieved. I just find this method cleaner.
This is not possible in Codeigniter as session itself a library and you are trying to call it pre_controller. When controllers not loaded yet how can you use it even in hook.
Solution
You may use post_controller_constructor instead what are using now
$hook['post_controller_constructor'] = array(
'class' => 'Preclass',
'function' => 'checkreq',
'filename' => 'preclass.php',
'filepath' => 'hooks',
'params' => array()
);
otherwise you may also use native session here
hope it help
I have a post-controller hook:
$hook['post_controller'][] = array(
'class' => 'PostControllerHook',
'function' => 'post_controller',
'filename' => 'PostControllerHook.php',
'filepath' => 'hooks',
'params' => array('controller')
);
The hooks documentation says that I can specify paramaters for my hook. How do I specify these parameters? Also, I need to have access to my controller object, which is why I'm trying to pass it as a parameter.
You are passing the parameters correctly.
Are you expecting to have access to the controller that just ran, prior to the post_controller hook? That won't work quite the way you expect. Code Igniter will try to instantiate a class if you pass it one for the hook, so you can't pass the controller instance directly.
Imagine first you have a controller
class Blog extends CI_Controller
{
public function doHookStuff()
{
echo "I'm running in a hook I hope!";
}
}
What you can do is call the get_instance helper function from your hook.
class PostControllerHook
{
function post_controller($params)
{
// $params[0] = 'controller' (given the params in the question)
// $controller is now your controller instance,
// the same instance that just handled the request
$controller =& get_instance();
$controller->doHookStuff();
}
}
If you want more info, all the answers are sitting in system/core/CodeIgniter.php and system/core/Hooks.php. A little complicated, but not too bad.
I was hoping I could find someone that could answer a question for me. I'm Jamie Rumbelow's MY_Model and curious to know if I can use it functionality if I need to run a function from it inside of a hook.
$hook['pre_controller'] = array(
'class' => 'Logins_model',
'function' => 'pre_init', // Run some sort of get function here
'filename' => 'logins_model.php',
'filepath' => 'models',
//'params' => array('beer', 'wine', 'snacks')
);
EDIT 2 : Would you say that this is an okay hook or have I lost all grasp of this?
<?php
if (!defined('BASEPATH'))
exit('No direct script access allowed');
class User_hook {
private $CI;
function __construct() {
$CI =& get_instance();
}
public function validate_user() {
$this->CI->load->model('logins_model', 'login'); //Alternatively put this in autoload.php
$this->CI->load->model('users_model', 'user');
$user_id = $this->CI->session->userdata('user_id');
if (($user_id !== TRUE) && (!is_numeric($user_id)) && (strlen($user_id) < 5))
{
redirect('login');
}
$user_data = $this->CI->user->get($user_id);
$user_data->login = $this->CI->login->get_by('user_id', $user_id);
if (empty($user_data))
{
redirect('login');
}
}
}
Yes, but not using the code that you suggest. You need to create your own custom hook class and then load (or autoload) and call your model there.
It is also important to note that this will not work for pre_controller hooks as the CodeIgniter object is not yet available. The hook must be post_controller_constructor or later. Take this hook class for example for hooks/some_hook.php.
class some_hook {
private $CI;
function __construct() {
$CI =& get_instance();
}
public function some_function() {
$this->CI->load->model('logins_model'); //Alternatively put this in autoload.php
$this->CI->logins_model->some_function_in_logins();
}
}
Then you would load it using:
$hook['post_controller_constructor'] = array(
'class' => 'some_hook',
'function' => 'some_function',
'filename' => 'some_hook.php',
'filepath' => 'hooks'
);
Why do I get a
Class 'Search_Controller' not found
when doing this:
class Snippets_Controller extends Search_Controller {
public $restful = true;
public function get_index()
{
$snippets = Snippet::all();
$categories = Categorie::all();
return View::make('snippet.index')->with(array(
'snippets' => $snippets,
'categories' => $categories,
'active_categorie' => Session::get('active_categorie_id')
)
);
}
The Search Controller:
class Search_Controller extends Base_Controller {
protected static function build_html_for_search_results($search_results)
{
...
You should autoload this in you application start.php folder.
If you open that file, and you search for "Base_Controller", you will see something like this:
Autoloader::map(array(
'Base_Controller' => path('app').'controllers/base.php'
));
The only thing you have to do is add the search controller there:
Autoloader::map(array(
'Base_Controller' => path('app').'controllers/base.php',
'Search_Controller' => path('app').'controllers/search.php'
));
And that should do the trick.
Laravel loads controllers based on the name that's requested, and it doesn't autload any of the controllers, as it would be a waste of time for 90% of the controllers.