I want to increase the functionality of my CodeIgniter project by integrating some code that is written in laravel? how do I approach,
Can I include the code via library in CodeIgniter ? If yes How?
I only want to include controllers and ORM into the CI.
Laravel code is a kind of api fetcher with function talks with other
3rd party services.
Yes you can use composer to install Laravel specific modules/projects, third-party projects in your CodeIginter. Just include autoload in your `index.php' file at top
// Composer autoload
require_once __DIR__.'/vendor/autoload.php';
I am using Eloquent as ORM in my CodeIgniter codebase.
Create a classmap to your app directory in composer.json
"autoload": {
"psr-4": { "YourApp\\": ["application/"] },
Use Eloquent
To use Eloquent, you will require to create a library to setup Eloquent for use.
/**
* Capsule setting manager for Illuminate/database
*/
use Illuminate\Database\Capsule\Manager as CapsuleManager;
use Illuminate\Events\Dispatcher;
use Illuminate\Container\Container;
class Capsule extends CapsuleManager {
public function __construct()
{
parent::__construct();
//Loaded by CI
if(function_exists('get_instance')) {
$ci = &get_instance();
$db = new stdClass;
$db = $ci->db;
} else {
require_once __DIR__.'/../config/database.php';
$db = (object) $db['default'];
}
$this->addConnection(array(
'driver' => $db->dbdriver,
'host' => $db->hostname,
'database' => $db->database,
'username' => $db->username,
'password' => $db->password,
'charset' => $db->char_set,
'collation' => $db->dbcollat,
'prefix' => $db->dbprefix,
));
$this->setEventDispatcher(new Dispatcher(new Container));
// Make this Capsule instance available globally via static methods... (optional)
$this->setAsGlobal();
// Setup the Eloquent ORM... (optional; unless you've used setEventDispatcher())
$this->bootEloquent();
}
}
// END Capsule Class
Now load the auto load the library, and you have the eloquent beauty.
Similarly, you can use MonoLog for logging, Whoops for error display, Formers\Former for form building etc.
Use Whoops
You can place this code somewhere after autload and defining CI Environment in your index.php to use beautiful https://github.com/filp/whoops library
if (ENVIRONMENT == 'development') {
$whoops = new \Whoops\Run;
$whoops->pushHandler(new Whoops\Handler\PrettyPageHandler());
$whoops->register();
}
You can also extend CI_Router to use Laravel style routing in your Code Igniter app.
Blade Templating
You can extend the CI_Loader to use Blade templating in Code Igniter. Create a new file MY_Loader in your application/core directory with this code.
use Illuminate\Blade\Environment;
use Illuminate\Blade\Loader;
use Illuminate\Blade\View;
class MY_Loader extends CI_Loader {
public function __construct()
{
parent::__construct();
}
public function blade($view, array $parameters = array())
{
$CI =& get_instance();
$CI->config->load('blade', true);
return new View(
new Environment(Loader::make(
$CI->config->item('views_path', 'blade'),
$CI->config->item('cache_path', 'blade')
)),
$view, $parameters
);
}
}
You may have to create a config file blade.php in your application/config directory to store blade specific configurations.
//config/blade.php
$config['views_path'] = APPPATH . 'views/blade/';
$config['cache_path'] = APPPATH . 'cache/blade/';
Now you can do something like this in your controller
class Home extends CI_Controller {
public function index()
{
// Prepare some test data for our views
$array = explode('-', date('d-m-Y'));
list($d, $m, $y) = $array;
// Basic view with no data
echo $this->load->blade('home.index');
// Passing a single value
echo $this->load->blade('home.index')->with('day', $d);
// Multiple values with method chaining
echo $this->load->blade('home.index')
->with('day', $d)
->with('month', $m)
->with('year', $y);
// Passing an array
echo $this->load->blade('home.index', array(
'day' => $d,
'month' => $m,
'year' => $y
));
}
}
Related
I am migrating a project from Zend framework 1.4 to 2.4, I have a class in "vendor/custom/classes/User.php"
<?php
namespace Classes;
use Zend\Db\TableGateway\TableGateway;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\Db\Adapter\Adapter;
class User
{
public function getItemById($id)
{
//$config = $this->getServiceLocator()->get('config');
//This only work in controller
$configs = array();
$adapter = new Adapter($configs);
$projectTable = new TableGateway('project', $adapter);
$rowset = $projectTable->select(array('type' => 'PHP'));
echo 'Projects of type PHP: ';
foreach ($rowset as $projectRow) {
echo $projectRow['name'] . PHP_EOL;
}
}
}
?>
I need to load merged configurations in my files in "config/autoload" , global.php and local.php. $config = $this->getServiceLocator()->get('config'); Can someone guide me how can I get these configurations from a custom class. Basically I am trying to do is writing set of classes like User, Project, Customer outside of Models and use them commonly in all modules like CMS, Admin Panel, Web site. Appreciate your guidance.
An approach could be using a factory.
You create a class UserFactory implementing Zend\ServiceManager\FactoryInterface. This class will have a method createService with a $serviceLocator parameter. You use this service locator to retrieve your dependencies and pass them to your User class.
In your User class you need to use a controller that accepts as parameters the dependencies that you need to pass to it
Since there is no direct way to access those configurations. I have wrote constants with DB access information in the local and global php files in config/autoload and used it in my class.
class DBManager
{
protected $adapter ;
protected $connection ;
/**
* Constructor
*/
public function __construct()
{
$configs = array(
'hostname' => DB_SERVER_NAME,
'driver' => 'Pdo_Mysql',
'database' => DB_DATABASE_NAME,
'username' => DB_USER_NAME,
'password' => DB_PASSWORD ,
);
$this->adapter = new Adapter($configs);
}
}
I have been racking my brain now for the better part of two days. I'm using Zend Apigility to create a RESTful web API application. Apigility builds its application using ZF2.
I created a custom class that I use throughout my API.
I would like to read in some autoloaded configuration information to make a connection to an memcache server. The file that is being autoloaded into the service manager is:
memcache.config.local.php:
return array(
'memcache' => array(
'server' => '10.70.2.86',
'port' => '11211',
),
);
My custom class that my REST services are calling is called checkAuth:
checkAuth.php:
namespace equiAuth\V1\Rest\AuthTools;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
class checkAuth implements ServiceLocatorAwareInterface{
protected $services;
public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
{
$this->services = $serviceLocator;
}
public function getServiceLocator()
{
return $this->services;
}
public function userAuths() {
//** Some Code
$config = $this->getServiceLocator()->get('config');
// **
}
}
I believe I'm injecting the service manager into the class from my module.config.php with the following code:
'service_manager' => array(
'invokables' => array(
'checkAuth' => 'equiAuth\V1\Rest\AuthTools\checkAuth',
),
),
When I hit the code when I'm trying to read the 'config' from the get method of the ServiceLocator I get the following error:
Fatal error: Call to a member function get() on a non-object
I know I'm missing something, but I cant for the life of me figure out what.
Give your class an API that allow's you to 'set' the configuration from client code. This could be via the constructor or
a public setter.
namespace equiAuth\V1\Rest\AuthTools;
class CheckAuth
{
protected $config;
public function __construct(array $config = array())
{
$this->setConfig($config);
}
public function setConfig(array $config)
{
$this->config = $config;
}
public function doStuff()
{
$server = $this->config['server'];
}
}
In order to 'set' the configuration you would also need to also create a service factory class. The idea in the factory is to give you an area to inject the configuration in to the service; with the updates to CheckAuth above we can now do so very easily.
namespace equiAuth\V1\Rest\AuthTools;
use equiAuth\V1\Rest\AuthTools\CheckAuth;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\ServiceManager\FactoryInterface;
class CheckAuthFactory implements FactoryInterface
{
public function createService(ServiceLocatorInterface $serviceLocator)
{
$config = $serviceLocator->get('config');
return new CheckAuth($config['memcache']);
}
}
Lastly, change the registered service with the service manager; the change here is service key form invokables to factories as we need to register the
above factory to create it.
// module.config.php
'service_manager' => array(
'factories' => array(
'checkAuth' => 'equiAuth\V1\Rest\AuthTools\CheckAuthFactory',
),
),
ZF2 use ServiceManager Container as well.
Your code is right at all, but
To auto-inject the servicelocator on your class you just need to use
$checkAuth = $this->getServiceLocator()->get('checkAuth');
then you can call
$checkAuth->userAuths();
and should work.
If you try to use:
$checkAuth = new \equiAuth\V1\Rest\AuthTools\checkAuth();
$checkAuth->userAuths(); //error
Will not work because what inject the serviceLocator into your class is just the
ServiceManager, once you use serviceManager you need to be evangelist with them.
But if you try:
$checkAuth = new \equiAuth\V1\Rest\AuthTools\checkAuth();
$checkAuth->setServiceLocator($serviceLocator)
//get $serviceLocator from ServiceManager Container
$checkAuth->userAuths();
Will work too.
Good job!
I have a file called application.config.php in my apps root directory. I want to require it or autoload it for my tests. The config file is like so:
<?php
// database connection
$config = array(
'database' => array(
'dsn' => 'mysql:host=localhost;dbname=budgetz',
'user' => 'budgetz_user',
'password' => 't1nth3p4rk',
),
);
My app uses these to connect to the database. So, to test my models they also need to connect to the database, .. or some database. Is it just a matter of something along the lines of requiring it in the test file:
<?php
require_once 'vendor/autoload.php';
require_once 'application.config.php';
class MapperTest extends PHPUnit_Framework_TestCase {
public function testFetchOne() {
$dbAdapter = new DatabaseAdapter($config['database']);
$userMapper = new UserMapper($dbAdapter); // using UserMapper but any child of Mapper will do
$user = $userMapper->fetchOne(1);
$this->assertsEquals(1, $user->id, 'message');
}
}
I tried this but I get the error:
There was 1 error:
1) MapperTest::testFetchOne
Undefined variable: config
/var/www/new_orm/test/MapperTest.php:8
What am I doing wrong? Also, I appreciate anyone giving some advise on best practise here. Perhaps this approach to requiring a config file in every page is a little old. Thanks
Globals is an option, but not good one.
Create your class, witch extends PHPUnit_Framework_TestCase. Then use the setup to set your config.
e.g.
class myTestCase extends PHPUnit_Framework_TestCase {
private $config;
public function setUp() {
$this->config = ....
}
public function getConfig() {
return $this->configl
}
Then your testcases should extends myTestCase. You could access config with
$this->getConfig();
Anyway, accessing dev db is not a good idea, maybe it is better to mock the work with the db ?
Try
public function testFetchOne() {
global $config;
I have a cropping tool component and helper which work on cake 2.x but now I need to use this cropping tool into one of the older project in cakephp 1.3. How should I do this?
The component:
<?php
App::uses('Component', 'Controller');
class JcropComponent extends Component {
public $components = array('Session');
public $options = array(
'overwriteFile' => true,
'boxWidth' => '940'
);
/**
* Constructor
*/
public function __construct(ComponentCollection $collection, $options = array()) {
parent::__construct($collection,$options);
$this->options = array_merge($this->options, $options);
}
?>
The Helper
<?php
App::uses('AppHelper', 'View/Helper');
class JcropHelper extends AppHelper {
public $helpers = array('Html','Form','Js');
public $options = array(
'tooltip' => true,
'boxWidth' => '940'
);
public function __construct(View $view, $options = null) {
parent::__construct($view,$options);
$this->options = array_merge($this->options, $options);
}
?>
I tried to change it into this, it can show the image, but how can I merge the options array?
the one where __construct ($options = array())
<?php
class JcropComponent extends Component {
var $components = array('Session');
public $options = array(
'overwriteFile' => true,
'boxWidth' => '940'
);
//public function initialize(&$controller, $settings = array()) {
// $this->controller =& $controller;
//parent::__construct($collection,$options);
//$this->options = array_merge($this->options, $options);
//}
?>
<?php
class JcropHelper extends AppHelper {
var $helpers = array('Html','Form','Js');
public $options = array(
'tooltip' => true,
'boxWidth' => '940'
);
public function __construct($settings = null) {
//parent::__construct($view,$options);
//$this->options = array_merge($this->options, $options);
}
?>
Components in 1.3 don't use the constructor for settings
The first significant problem you have is: the way components receive settings changed between major versions.
in 1.3:
//Component(Collection) Class
$component->initialize($controller, $settings);
in 2.x:
//ComponentCollection class
new $componentClass(ComponentCollectionObject, $settings);
Therefore the way to make the component work the same way in 1.3 - is to define the initialize method.
Helpers have a different constructor
A similar change was made to helpers:
In 1.3:
//View class
new $helperCn($options);
In 2.x:
//HelperCollection class
new $helperClass(ViewObject, $settings);
In this case it should be more obvious - any overridden method should have the same method signature as the parent class. Therefore: change the helper to have the same expected arguments in the constructor
Warning: extends Component
In 1.3, components do not extend Component, they extend Object. Component is the class which acts as a collection in 1.3, extending it will cause unexpected and undesired behavior (i.e. it'll likely cause unexpected "random" warnings and fatal errors). As such you should change the component class to be analogous to all other components, extending Object (or quite simply - not extending component).
If this class is something you use and maintain in various projects, it'd be a good idea to extract the main functionality into a standalone class, and implement only a thin wrapper class (component/behavior) to interface with it. In this way any changes made to the main functionality can be leveraged irrespective of the version of cake - or any other framework - used.
I'm just really starting with the Zend Framework, and currently I'm having a problem with the Zend_Loader_PluginLoader.
I managed to get a module specific plugin working easily enough using the following code:
class Api_Bootstrap extends Zend_Application_Module_Bootstrap
{
protected function _initPlugins()
{
$loader = new Zend_Loader_PluginLoader(array(
'Api_Plugin' => 'application/modules/api/plugins',
));
$front = Zend_Controller_Front::getInstance();
$front->registerPlugin(new Api_Plugin_ErrorControllerSelectorPlugin());
}
}
Edit: The class file is located at application/modules/api/plugins/ErrorControllerSelectorPlugin.php
I then tried to adapt this to get a plugin loaded for the whole application using:
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
protected function _initAppAutoload()
{
$autoloader = new Zend_Application_Module_Autoloader(array(
'namespace' => 'App',
'basePath' => dirname(__FILE__),
));
return $autoloader;
}
protected function _initPlugins()
{
$loader = new Zend_Loader_PluginLoader(array(
'My_Plugin' => 'application/plugins',
));
$front = Zend_Controller_Front::getInstance();
$front->registerPlugin(new My_Plugin_ModuleConfigLoaderPlugin());
}
}
But I'm getting errors:
Fatal error: Class 'My_Plugin_ModuleConfigLoaderPlugin' not found in /var/www/localhost/application/Bootstrap.php on line 22
Edit: The class file is located at application/plugins/ModuleConfigLoaderPlugin.php
So - since the files are where I would expect them to be as far as the prefix/path pairs sent to Zend_Loader_PluginLoader() and the code in both cases are the same, what's the difference?
How do I get it to recognise my application-level plugins?
If you want the app-level plugin to reside within the namespace My_, you either need to put the My folder out in the library folder or declare the app-level namespace to be My_.
Assuming that you already have other stuff within your top-level app that uses the App_ namespace, then the easiest thing would be the former: move your My folder out into the library.
So, the plugin would reside in:
library/My/Plugins/ModuleConfigLoaderPlugin.php.
Then make sure that your configs/application.ini registers the My_ namespace:
autoloaderNamespaces[] = "My_"
Then the app-level Bootstrap could contain something like:
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
protected function _initAppAutoload()
{
$autoloader = new Zend_Application_Module_Autoloader(array(
'namespace' => 'App',
'basePath' => dirname(__FILE__),
));
return $autoloader;
}
protected function _initPlugins()
{
$front = Zend_Controller_Front::getInstance();
$front->registerPlugin(new My_Plugin_ModuleConfigLoaderPlugin());
}
}
Alternatively, since your plugin does not sem to require any params, you could instantiate it via configs/application.ini using:
resources.frontcontroller.plugins[] = "My_Plugin_ModuleConfigLoaderPlugin"