How to load hook for particular controller - codeigniter

I am new in codeigniter. I want to load hooks for admin panel controller.
$hook['post_controller_constructor'][] = array(
'class' => 'AdminData',
'function' => 'myfunction',
'filename' => 'loginhelp.php',
'filepath' => 'hooks',
'params' => array()
);

Ok this is the simplest way to do this:
declare a public variable in your Controller
public $is_hookable = TRUE;
Then inside your hook function do this:
$ci=&get_instance();
if($ci->is_hookable){
... enter whatever you want here;
}
hope this was helpful

please read the document clearly https://ellislab.com/codeigniter/user-guide/general/hooks.html
The hooks feature can be globally enabled/disabled by setting the
following item in the application/config/config.php file:
$config['enable_hooks'] = TRUE;
Hooks are defined in application/config/hooks.php file.
You cannot load it for specific controller.You need to check controller name at hooks function and write code. suppose your post_controller_constructor hooks function name is myfunction you can check it inside the function
$CI =& get_instance();
if($CI ->router->class=="AdminData"){//write your code}

Application/config/hooks.php
$hook['post_controller'] = array(
'class' => 'LogoutBlockedUser',
'function' => 'logout',
'filename' => 'LogoutBlockedUser.php',
'filepath' => 'hooks',
'params' => ""
);
Enable hooks in config.php
$config['enable_hooks'] = TRUE;
Application/hooks/LogoutBlockedUser.php
class LogoutBlockedUser {
public function __construct()
{
}
public function logout()
{
$CI =& get_instance();
if(!(empty($CI->session->userdata('user_id'))))
{
$CI->load->model('Your_model', 'web');
$result = $CI->common->select_query;
if(!empty($result))
{
$CI->session->unset_userdata('user_id');
session_destroy();
redirect(base_url() . 'yourcontroller/function');
}
}
}
}

The post_controller_constructor hook gets called after a $class is loaded. The class that gets loaded is based on the route parameters.
system/core/Codeigniter.php
/**
*<code>
* http://example.com/adminData/method
*</code>
*
* $CI = new adminData(); => application/controllers/adminData.php
**/
$CI = new $class();
$EXT->call_hook('post_controller_constructor');
So if you wanted to call a method on the adminData controller, you could do something like this.
This method is not ideal, as its not very OOP like, however the way CI is built from a design point of view, you have to do a few workarounds like the example below
application/controllers/adminData.php
class AdminData extends CI_Controller
{
public function __construct(){}
// This cannot be called directly in the browser
public function _filter()
{
/**
* Put your logic in here
*<code>
* $this->model->logic()
*</code>
**/
exit('I have just be called!');
}
}
application/hooks/loginhelp.php
class AdminData
{
protected $ci;
public function __construct()
{
global $CI;
$this->ci = $CI;
}
public function myfunction()
{
// If the class is not == AdminData, just bail
if(get_class($this->ci) != 'AdminData') return;
if(!is_callable(array($this->ci, '_filter'))) return;
//calls $AdminData->_filter()
return call_user_func(array($this->ci, '_filter'));
}
}

Related

Laravel, call many artisan commands with progress bar output

I have created a simple trait to generate a progress bar during command executions.
<?php
namespace App\Console\Commands;
trait ProgressBarOutput
{
public function runProcess(\Countable $countable, callable $callback)
{
$bar = $this->output->createProgressBar(count($countable));
$bar->start();
foreach ($countable as $item) {
call_user_func($callback, $item);
$bar->advance();
}
$bar->finish();
$this->line('');
}
}
That works, inside my command page:
<?php
namespace App\Console\Commands;
use App\Console\Commands\ProgressBarOutput;
use Illuminate\Console\Command;
class MigrateUsers extends Command
{
use ProgressBarOutput;
protected $signature = 'migrate:users';
protected $description = 'Migrate users table from old to new';
public function __construct()
{
parent::__construct();
}
public function handle()
{
$this->info("users");
$rows = \DB::connection('old')->table('users')->get();
$this->runProcess($rows, function($row) {
\DB::connection('mysql')->table('users')->insert([
'id' => $row->id,
'name' => $row->name,
'surname' => $row->surname,
]);
});
$this->info("cars");
$rows = \DB::connection('old')->table('cars')->get();
$this->runProcess($rows, function($row) {
\DB::connection('mysql')->table('cars')->insert([
'id' => $row->id,
'model' => $row->model,
]);
});
}
}
The problem occurs when I try to split these micro imports into separate files then merge together:
public function handle()
{
\Artisan::call("migrate:users");
\Artisan::call("migrate:cars");
}
The commands get correctly called, but no output is printed nor a progress bar.
Have you ever faced this kind of problem?
Thank you!
migrate command need the user to confirm the process to continue. Adding --no-interaction along with the call will remove all user interactions. In this example it will be like,
public function handle()
{
\Artisan::call("migrate:users --no-interaction");
\Artisan::call("migrate:cars --no-interaction");
}
I solved the problem.
Just call $this->call("your-command"); instead of \Artisan::call("your-command");
public function handle()
{
$this->call("migrate:users");
$this->call("migrate:cars");
}

How get model's table name in October Cms static?

My plugin code:
public function boot()
{
**I can:**
$user = new User();
$table = $user->getTable();
**I would like to:**
echo User::getTable();
exit;
$user = $this->user;
\Serviom\Guestpage\Models\Post::extend(function($model) use ($user) {
$model->rules = [
'name' => 'required|between:3,100',
'subject' => 'required|between:3,100',
'desc' => 'required|between:10,1000',
'parent_id' => 'nullable|exists:serviom_guestpage_posts,id',
'user_id' => 'nullable|exists:' . $table . ',id',
Variable in modal $table is protected member so its really nothing we can do about that but we can simply access it by adding public method to class [ extend it ]
In any of your plugin you can add this snippet
use RainLab\User\Models\User as UserModel;
class Plugin extends PluginBase
{
public function boot() {
UserModel::extend(function($model) {
$model->addDynamicMethod('getTableName', function() use ($model) {
return $model->getTable();
});
});
//....
Now you can able to call
echo User::getTableName();
Its like kind of hack but its only if you really badly needed it then you do something like this
if any doubt please comment.
You can add a static method to your Model as a helper :
class MyModel extends Model
{
public static function getTableName()
{
return with(new static)->getTable();
}
}
Usage : MyModel::getTableName()
Source

Codeigniter & HMVC - Callback not working

I've pretty much gone through a lot of link and solutions provided here and other locations, but I am just not able to solve the callback issue that I am facing. I'm using Codeigniter with HMVC the code is below.
The following code is from My_Form_validation.php:
class MY_Form_validation extends CI_Form_validation {
function run($module = '', $group = ''){
(is_object($module)) AND $this->CI = &$module;
return parent::run($group);
}
}
Below if the Callback function :
public function _unique_email($str) {
// Check if user already exists
// Process only for current user
$id = $this->uri->segment(4);
$this->db->where('email', $this->input->post('email'));
!$id || $this->db->where('id !=', $id);
$user = $this->mdl_admin_users->get();
if (count($user)) {
$this->form_validation->set_message('_unique_email', 'User already exists. Please check %s.');
return FALSE;
}
return TRUE;
}
and the function :
public function user_edit($id = NULL) {
// Fetch a user or set a new one
if ($id) {
$data['user'] = $this->mdl_admin_users->get($id);
count($data['user']) || $data['errors'][] = 'User could not be found';
}
else {
$data['user'] = $this->mdl_admin_users->get_new();
}
// setup the form
$rules = $this->mdl_admin_users->rules_admin;
$id || $rules['password'] = '|required';
$this->form_validation->set_rules($rules);
//process the form
if ($this->form_validation->run($this) == TRUE) {
$data = $this->mdl_admin_users->array_from_post(array('firstname', 'lastname', 'email', 'password'));
$data['password'] = $this->mdl_admin_users->hash($data['password']);
$this->mdl_admin_users->save($data, $id);
redirect('admin/user');
}
// Load the view
$data['title'] = 'Edit Users';
$data['module'] = 'admin';
$data['header_file'] = 'header_admin';
$data['nav_file'] = 'nav_admin';
$data['view_file'] = 'edit_users';
$data['footer_file'] = 'footer_admin';
echo Modules::run('template/base_template', $data);
}
Would be a great help if someone could point me at the right direction to resolve the issue. Thanks in advance
Naveen
According to wiredesignz,
When using form validation with MX you will need to extend the CI_Form_validation class as shown below,
/** application/libraries/MY_Form_validation **/
class MY_Form_validation extends CI_Form_validation
{
public $CI;
}
before assigning the current controller as the $CI variable to the form_validation library. This will allow your callback methods to function properly.
class Xyz extends MX_Controller
{
function __construct()
{
parent::__construct();
$this->load->library('form_validation');
$this->form_validation->CI =& $this;
}
}
This will remove HMVC related callback problem without any changes to your code.
First of you are missing in the rules
$rules['email'] = 'required|callback__uniqueemail';
Also call back function should be not like this callback__unique_email for some reason I found codeigniter call back not like extra gap this better callback__uniqueemail
If private do not work make public function removing underscore
public function uniqueemail() // no need $str
When make public do not for get to remove extra underscore from here callback_uniqueemail
Another thing with echo Modules run best to be loaded from view only.
In your controller replace echo Modules run with $this->load->view();
You need to add $this->form_validation->run($this) add $this to run after create library below.
And Create a new library
<?php
class MY_Form_validation extends CI_Form_validation {
function run($module = '', $group = '') {
(is_object($module)) AND $this->CI = &$module;
return parent::run($group);
}
}
Tutorial Best https://www.youtube.com/watch?v=8fy8E_C5_qQ

Passing parameter between two function/view

I have two functions in controller named step1 and step2. I want to pass $data array between theme. Below is controller code. In step1 i have input in step2 i have simple echo which shows value of $data['text1']. This value is allays NULL in step2 controller, no meter what I type in step1.
public $data = array(
'id' => '',
'text1' => '',
'text2' => ''
);
public function __construct()
{
parent::__construct();
}
public function step1()
{
$this->load->helper(array('form', 'url'));
$this->load->library('form_validation');
$this->form_validation->set_rules('text1', 'Text 1', 'rquired');
if($this->form_validation->run() === FALSE)
{
$this->load->view('test/step1', $this->data);
}
else
{
$this->data['text1'] = $this->input->post('text1');
redirect('test/step2');
}
}
public function step2()
{
$this->load->view('test/step2', $this->data);
}
public function step3()
{
}
}
You're redirecting to step2 by redirect('test/step2'); That basically reloads the page and your $data property gets emptied.
Instead, you should try something like that:
$this->data['text1'] = $this->input->post('text1');
$this->step2(); //would call your existing step2() method
If you actually want to have a header redirect to url like test/step2 , you may need to have your $data stored in a session.

Routing zend request through a default controller when controller not found

Below is a function defined in my Bootstrap class. I must be missing something fundamental in the way Zend does routing and dispatching. What I am trying to accomplish is simple: For any request /foo/bar/* that is not dispatchable for any reason try /index/foo/bar/. The problem I'm having is when the FooController exists I get Action "foo" does not exist. Basically, the isDispatchable is always false.
public function run() {
$front = Zend_Controller_Front::getInstance();
$request = $front->getRequest();
$dispatcher = $front->getDispatcher();
//$controller = $dispatcher->getControllerClass($request);
if (!$dispatcher->isDispatchable($request)) {
$route = new Zend_Controller_Router_Route(
':action/*',
array('controller' => 'index')
);
$router = $front->getRouter();
$router->addRoute('FallBack', $route);
}
$front->dispatch();
}
So this seems to work, but is not the best answer as it simply drops all the params. I might try shortly doing a forward to /index/[original uri] within the plugin:
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap {
protected function _initRoute() {
$front = Zend_Controller_Front::getInstance();
$routes = array(
'FallBack' => new Zend_Controller_Router_Route(
':controller/:action/*',
array('controller' => 'index', 'action' => 'index')
)
);
$router = $front->getRouter();
$router->removeDefaultRoutes();
$router->addRoutes($routes);
$front->setRouter($router);
return $router;
}
protected function _initPlugin() {
$front = Zend_Controller_Front::getInstance();
$front->registerPlugin(new My_Controller_Plugin_FallBack());
}
}
class My_Controller_Plugin_FallBack extends Zend_Controller_Plugin_Abstract {
public function preDispatch(Zend_Controller_Request_Abstract $request) {
$front = Zend_Controller_Front::getInstance();
$dispatcher = $front->getDispatcher();
$router = $front->getRouter();
if (($router->getCurrentRouteName() == 'FallBack') &&
!$dispatcher->isDispatchable($request)) {
$request->setActionName($request->getControllerName());
$request->setControllerName('index');
}
}
}
if i understand your idea right
would you try to use __call magic method ??
then use $this->_redirect(); to your default action for example
more info are here http://php.net/manual/en/language.oop5.overloading.php
UPDATE
if you opened Zend/Controller/Action.php on line 480
public function __call($methodName, $args)
{
require_once 'Zend/Controller/Action/Exception.php';
if ('Action' == substr($methodName, -6)) {
$action = substr($methodName, 0, strlen($methodName) - 6);
throw new Zend_Controller_Action_Exception(sprintf('Action "%s" does not exist and was not trapped in __call()', $action), 404);
}
throw new Zend_Controller_Action_Exception(sprintf('Method "%s" does not exist and was not trapped in __call()', $methodName), 500);
}
what i meant to do is to extend this class and override __call function exactly to be
classs My_Controller_Action extends Zend_Controller_Action{
public function __call($methodName, $args)
{
///// do your magic here ......redirection or logging the request or what ever
}
}
and make sure your controller extend your newly created class
class FooController extends My_Controller_Action
{
public function indexAction()
{
// action body
}
}
so if some how you called inexistent action __call will run
this idea was about inexistent action only
it won't work if the controller doesn't exist

Resources