I want to add some code that will run for every controller. Adding the code to CodeIgniter's CI_CONTROLLER class seems unconventional.
Where is the right place to include code you want to run for every controller?
Here is the code:
require_once 'vendor/autoload.php';
$bugsnag = Bugsnag\Client::make("my-secret-key-is-here");
Bugsnag\Handler::register($bugsnag);
These classes both come from a dependency installed with Composer.
I suspect I should create a helper, and include it in application/config/autoload.php. But new to CodeIgniter, so not sure of conventions.
Edit: I am using CodeIgniter 3.1.6.
If you want to execute arbitrary code at different points in CodeIgniter's life cycle, you can use the hooks feature.
Official Documentation:
https://codeigniter.com/user_guide/general/hooks.html
1. Enable hooks
Go to /application/config/config.php.
Search for enable_hooks and set it to true: $config['enable_hooks'] = TRUE;
2. Add desired code to CodeIgniter's hook file:
Go to /application/config/hooks.php.
Choose the desired lifecycle to hook into (see doc link above for a list)
Add code to the lifecycle, e.g. $hook['pre_controller'] = function(){... your code goes here ...}
For this question's example, my hooks.php looks like this:
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
// This is the code I added:
$hook['pre_system'] = function(){
require_once 'vendor/autoload.php';
$bugsnag = Bugsnag\Client::make("my-client-key");
Bugsnag\Handler::register($bugsnag);
}
?>
I would just extend the Controller Class.
See "Extending Core Class":
"If all you need to do is add some functionality to an existing library - perhaps add a method or two - then it’s overkill to replace the entire library with your version. In this case it’s better to simply extend the class."
...
"Tip: Any functions in your class that are named identically to the methods in the parent class will be used instead of the native ones (this is known as “method overriding”). This allows you to substantially alter the CodeIgniter core."
class MY_Controller extends CI_Controller {
....
}
Any function you put inside would be added to the core, otherwise, if you use the same name as an existing method, it would replace just that one method.
You'd name it MY_Controller.php and put it inside application/core/, where it's picked up to override CI_Controller automatically.
If you are extending the Controller core class, then be sure to extend your new class in your application controller’s constructors.
class Welcome extends MY_Controller {
public function __construct()
{
parent::__construct();
// Your own constructor code
}
public function index()
{
$this->load->view('welcome_message');
}
}
Looks like you could also use a pre_system or pre_controller hook as described here:
https://www.codeigniter.com/user_guide/general/hooks.html
Assuming it's CodeIgnitor 3.X
Go to application/config/config.php and change:
$config['composer_autoload'] = FALSE;
to
$config['composer_autoload'] = TRUE;
just below the above line include
require_once APPPATH.'vendor/autoload.php';
Or in your controller include
require_once APPPATH.'vendor/autoload.php';
From How to use composer packages in codeigniter?
Go to application/config/config.php and set $config['composer_autoload'] = FALSE; to TRUE:
Enabling this setting will tell CodeIgniter to look for a Composer
package auto-loader script in application/vendor/autoload.php.
As a result you need not to call require_once 'vendor/autoload.php';.
Related
I´m working on an application which is deployed at different locations.
Depending on the location, some functionality in some controllers/models/views work differently, is there a way to override/extend this classes? (I don´t want to change the code base directly as it will lead to problems in future releases)
I´m looking for a way similar to the MY_ override of core classes/functions.
As I can´t show the actual code, here is a simple example of what I would like to achieve:
The normal basic controller, used as is in most deployments:
class SomeController extends CI_Controller {
...
public function index()
{
$data['var'] = 10;
$this->load->view('someview',$data);
}
...
}
And here is how a special controller for just on location could look like:
class SomeController extends CI_Controller {
...
public function index()
{
$data['var'] = 5;
$this->load->view('someview',$data);
}
...
}
(in this case, the only change is in the var value)
If you only are changing the variables then instead of overriding your class based on the location (a.k.a independent environment), try using environment variables. For this, I would recommend using the DotEnv library via composer
composer require vlucas/phpdotenv
Once it is installed, add this into your index.php at the bottom before loading the bootstrap file
index.php
require_once './vendor/autoload.php';
$dotenv = new Dotenv\Dotenv(__DIR__);
$dotenv->load();
/*
* --------------------------------------------------------------------
* LOAD THE BOOTSTRAP FILE
...
Once that is setup, you can use the getEnv() function to retrieve the variables:
.env Example
CONTROLLER_VAR=5
DB_HOST=localhost
DB_PORT=3306
...
SomeController
class SomeController extends CI_Controller {
...
public function index()
{
$data['var'] = getEnv("CONTROLLER_VAR");
$this->load->view('someview',$data);
}
...
}
Also make sure Composer is autoloaded.
Hi I have a file called payment.php it contains some functions related to payments and some multiple classess. So I want to include that file in my symfony2 Controller to access its all methods and classless. I am trying it as follows:
//File location is in src/AppBundle/Controller/payment.php
namespace AppBundle\Controller;
require_once __DIR__.'/./payment.php';
//My controller
class ApiServicesController extends Controller
{
$this->payment(array('txnId'=>1112548));
}
But I am not able to access the file and its methods.
I am using this approach because keeping it in /vendor directory it also not able to access because this file contains multiple classless in same files.
Please advice me how can I access this file in my controller.
thanks in advance
If paymant.php have classes you need to make instance of that class to call method from it, that's like basic OOP stuff.
class ApiServicesController extends Controller
{
$this->payment(array('txnId'=>1112548));
}
First of all, where is the method in this controller where you want to call your method? Then, why you are calling payment on $this if it comes from diffrent class. It should be something like this
class ApiServicesController extends Controller
{
public function indexAction()
{
$somePaymentClass = new SomePaymantClass(); //whatever class you want from payment.php
$somePaymentClass->payment(array('txnId'=>1112548));
}
}
But iI strongly recommend to use it as a service and put it in some autoloader namespace.
You have to make a Payment class as a service and then you can use all functions of Payment class in controller. Please refer this document.
http://symfony.com/doc/current/service_container.html
The answer to my question ZF2 FormInput to show error class on validation fail is to create my own form view helper, overriding the render function. While this works beautifully for elements being rendered using forminput, it doesn't help on elements that inherit from forminput. For example, FormCheckbox inherits from forminput but not MY forminput:
<?php
namespace Zend\Form\View\Helper;
//...
class FormCheckbox extends FormInput {
//...
}
In this case I would need to create ANOTHER form view helper for formcheckbox exclusively to extend MY forminput. And again for any other view helpers I want to include (formdate, formemail, formpassword, etc).
Instead of creating multiple view helpers is it possible to create a single view helper and tell ZF2 to use that in all calls to the original view helper when made by a ZF2 view helper?
i.e. \Zend\Form\View\Helper\FormCheckbox would extend \RPK\Form\View\Helper\FormInput, which would extend \Zend\Form\View\Helper\FormInput.
A solution I can think of, is rewriting a part of the autoloader.
In the autoload function, you add an extra check to check if the requested class is \Zend\Form\View\Helper\FormInput, and if that's the case, you load your custom FormInput.
In your own FormInput you don't extend the Zend FormInput, but you create a copy of it, and modify the parts that are needed to be modified.
Unless ZF2 is using dependency injection for it's form helpers, this is the only way I can think of (without altering the base library code).
What I have used are view partial. With partials you can define your own html for every input-element and you have access to all attributes and messages (e.g error-messages) of the input-element:
in your partial phtml:
<?php
$options = $element->getOptions();
$t = $this->t();
$value = $element->getValue();
$messages = $element->getMessages();
$attr = $element->getAttributes();
you can use a partial like this:
$this->formRow($form->get('myelement'), null, null, 'mypartial');
I am using composer to install ZF2. As composer is generating my autoload functions I can specify an autoload path in the composer.json file:
"autoload": {
"psr-4": {
"Zend\\Form\\View\\Helper\\": "vendor/rpk/Rpk/Form/View/Helper"
}
},
This will search in my vendor folder for the class before looking in the zend folder.
This does not let me extend the FormInput, but calls my FormInput in its place. Calling extends on my FormInput puts the app into an infinite loop, so we need to copy the contents of FormInput into my class and make the changes there.
How can I integrate the Mailjet API PHP wrapper into my Codeigniter installation as a library?
Is it as simple as placing the contents of the repository into application/libraries/Mailjet and then creating a Mailjet.php file in application/libraries which initializes Mailjet like shown below?
require 'Mailjet/vendor/autoload.php';
use \Mailjet\Resources;
$mj = new \Mailjet\Client(getenv('MJ_APIKEY_PUBLIC'), getenv('MJ_APIKEY_PRIVATE'));
Please let me know if I'm on the right track. Thanks.
Yes, you are on right track. But you don't need to create CI library. Use Mailjet repository library in controller as well. Just use composer as stated in CI docs.
If you want CodeIgniter to use a Composer auto-loader, just set $config['composer_autoload'] to TRUE or a custom path in application/config/config.php.
Step by step instruction for using github repository in CodeIgniter
Set $config['composer_autoload'] = TRUE; in APPPATH.'config/config.php' file
Put composer.json file with wanted repositories/projects in APPPATH location
Do the job with composer install command through console which will make vendor and other related files and folders inside
Use it when needed in controller or in other code as shown in example bellow
example controller Mailman.php
<?php defined('BASEPATH') OR exit('No direct script access allowed');
use \Mailjet\Resources;
class Mailman extends CI_Controller
{
private $apikey = 'apy__key__here';
private $secretkey = 'apy__secret__here';
protected $mj = NULL;
public function __construct()
{
// $this->mj variable is becoming available to controller's methods
$this->mj = new \Mailjet\Client($this->apikey, $this->apisecret);
}
public function index()
{
$response = $this->mj->get(Resources::$Contact);
/*
* Read the response
*/
if ($response->success())
var_dump($response->getData());
else
var_dump($response->getStatus());
}
}
If you explicitly want to use Mailjet (or any other) repository through CI library, check in docs how to create custom library and merge this code above with it. Personaly I use repositories this way to avoid unnecessarily loading and parsing sufficient libraries.
In my CI 2.2 project I want to make my parent controll with app's common functionality for use in all app and for this I create file :
application/libraries/N_Controller.php :
<?php
class N_Controller extends Controller
{
public function __construct()
{
parent::__construct();
}
But on first attempt to use it in file
application/controllers/admin/admin.php
<?php
class Admin extends N_Controller
{
public function __construct()
{
parent::__construct();
I got error:
PHP Fatal error: Class 'N_Controller' not found in /controllers/admin/admin.php on line 3, referer: http://local-ci22.com/admin/hostel/edit/15
I tried to add in application/config/autoload.php file :
$autoload['libraries'] = array( 'AppSmarty', 'AppUtils', 'N_Controller');
But it did not help. Which is the correct way ?
if you want to extend the functionality of a system class. you need to follow this recomendations.
place your extended class in /application/core, be sure that you name it exactly like the name and casing of the class created.
your class should extend from CI_Model or CI_Controller, depending on your needs.
wherever you implement your new class, be sure that you honor the same name casing from your extended class.
you should have configured the $config['subclass_prefix'] on /application/config/config.php. let's say in your case with the value 'N_'
what i can see from your code, you are not extending from CI_Controller and your path seems wrong.
Informative note: the /application/library is used to place classes and libraries from 3rd parties that won't fit into CI schemas.