How to integrate pimple in a custom mvc framework?

780 views Asked by At

I have a basic mvc like framework, and I would like to use pimple for dependance injection, but I don't know how to use it inside the framework. This is my app structure.

x-framework
  - config
  - app
      controller
         homeController.php
  - core
  - vendor
     pimple
       lib
         pimple.php
  - public

Now, in homeController.php I would like to use Pimple, but without actually doing new Pimple as seen in this example.

use vendor\pimple; 

class homeController
{
 function index(){
  $app = new Pimple();
  $app['orm'] = $app->share({ return new vendor\orm; });

  $orm = $app['orm'];


  $orm->table('foo'); 
  $orm->findFirst(['name'=>'john']);
}
}

It seems as seen in this example, it would be a very cumbersome task to initialize the pimple class on every controller. How is this done correctly?

2

There are 2 answers

2
Félix Adriyel Gagnon-Grenier On BEST ANSWER

My answer was not relevant, though the principle of abstract classes stays interesting. Now:

I would like to use Pimple, but without actually doing new Pimple as seen in this example.

At some point you have to instantiate an object, if you want to use it.

Pimple uses a container to store and retrieve services and parameters:

$container = new \Pimple\Container();
// define some services
$container['session_storage'] = function ($c) {
    return new SessionStorage('SESSION_ID');
};

this exemple from the doc defines an anonymous function which returns a session storage object

integrating a container

Pimple, or any container, can be made available using the dependency injection pattern.

either pass it as a parameter to the index

function index(\Pimple $app){

or pass it to homeController's constructor

function __construct(\Pimple $app){
  $this->app = $app;

then use it as a property or a variable

$orm = $app['orm']; // through index() parameters
$orm = $this->app['orm']; // through constructor

abstract classes allow you to define a method for every extending classes, or forcing every extending classes to define a method.

here, we define a constructor for every extending classes, typehinting the Pimple class so that php will ensure your controller receives a real pimple object

abstract class Pimpleized {
  function __construct(\Pimple $pimple) {
    $this->app = $pimple;
  }
}

then your controller

class homeController extends Pimpleized {
  function foo() {
    $this->app->accessSomePimpleMethod();
  }
}

that way, you only have to create your Pimple object once, then pass it to your controllers:

$pimp = new Pimple();
$controller = new homeController($pimp);
1
Shadar On

Just extend HomeController class with pimple

class HomeController extends Pimple {
  public function __construct() {
    $this['orm.class']= 'vendor\orm'; 
    $this['orm'] = $this->share(function($c){ return new $c['orm.class']; });
  }
}

//and use it directly just after instanciation
$controller = new HomeController();
// you can modify parameters if you need
$controller['orm.class'] = 'myothervendor\orm';
//And get class
$orm = $controller['orm'];
$orm->table('foo'); 
$orm->findFirst(['name'=>'john']);

i hope it's you want :) cheers