Hmvc avec Laravel 4

Grr, Laravel n’est pas un framework HMVC.

Le hmvc est en fait relativement simple, on découpe  son site (sa page) en fonctionnalités MVC. Dans mon exemple je désire un petit lecteur rss qui pourra être inséré dans  quelques pages(n’importe ou) de mon site; en Hmvc ce lecteur rss est un mvc a part entière.

Après cet article, il m’est venu l’idée pour faire ce type d’architecture : je vais réécrire un moteur de template et … le template sera en fait un appel a un contrôleur! oui,oui pas du vrai hmvc :-o

Utilisation du template hmvc

dans une vue Blade, ajouter un include vers une « vue » hmvc.

@extends(\Config::get('layout'))
@section('content')
    ...
	<h4>test mon rss comme hmvc</h4>
        <div id="monlecteur">
             @include ('myrss' , array('max'=>4) )
        </div>
    ... 
@stop

Créer un template .hmvc :

<?php // myrss.hmvc
return array(
	'controller' => 'RssController',
	'action' => 'index',
	'attr' => array( // peut etre ecrasé dans vue blade
		'url' =>    'http://www.planet-php.fr/rss.php',
		'max' => 12
	)
);

Et voila :) j’ai un composant (ici lecteur rss) qui est autonome avec son propre contrôleur vues qui peut-être inclus x fois dans mon site. De plus il est configurable (tableau « attr ») dans chaque vue.
Ça pourrait être aussi un carrousel d’images qui pioche dans une bd, un bandeau de pub lié lui aussi a une bd, un menu, un panier, un chat…

Le package Hmvc

Après cet article,  c’est vraiment très très simple

<?php namespace Papajoker\Hmvc;
use Illuminate\Support\ServiceProvider;

class HmvcServiceProvider extends ServiceProvider {

	protected $defer = false;

	public function register()	{
		list($app, $view) = array($this->app, $this->app['view']);
		$view->addExtension('hmvc', 'hmvc', function() use ($app) {
			return new HmvcEngine();
		});
	}

	public function provides()	{
		return array();
	}

}

Le provider attache simplement l’extension .hmvc au moteur HmvcEngine.

<?php namespace papajoker\Hmvc;
use Illuminate\View\Engines\EngineInterface;

class HmvcEngine implements EngineInterface {

	private $controller = false;
	private $attr = array();
	private $action = 'index';

	public function get($path, array $data = array())
	{
		$this->extract($data);
		$this->setConfig($path,$data);

		return $this->run();
	}

	protected function setConfig($path, array $data) {
		$conf = \File::getRequire($path);
		$this->controller=$conf['controller'];

		$this->attr = (array_key_exists('attr',$conf)) ? $conf['attr'] : array();
		// surchage attr dans fichier hmvc ?
		$this->attr = array_merge($this->attr, $data);
		$this->action = (array_key_exists('action',$conf)) ? $conf['action'] : 'index';
	}

	protected function run()	{ // php artisan dump-autoload
		$controller = new $this->controller();
		return $controller->{$this->action}(
			 $this->attr
			);
	}

	private function extract(&$data) {
		unset($data['__env']);
		unset($data['app']);
		unset($data['errors']);
		unset($data['path']);
	}	
}

Le moteur charge (->setConfig) le fichier .hmvc, insère(écrase) les données venant de la vue($data) puis appelle(->run) le contrôleur.

Voila c’est fini, le code source est sur gitHub a: https://github.com/papajoker/Hmvc


Un contrôleur exemple

C’est plus simple avec un exemple (code source sur gitHub dans /exemple/), mais ce n’est qu’un simple contrôleur avec sa vue pour afficher un flux rss.

<?php 

class RssController extends Controller {
    protected $url;
    protected $max;

    public function index($attr) {
        $this->url= $attr['url'];
        $this->max= $attr['max'];

        return \View::make('rss',
                    array(
                        'messages' => $this->load(),
                        'max' => $this->max,
                        'i' => 0
                    )
                );
    }

    protected function load() {
        $xml= \File::getRemote($this->url);
        $xml = simplexml_load_string($xml);
        return $xml->channel->item;
    }
}

et sa vue rss.blade.php très classique

<div style="width:40%" class="rss">

@foreach( $messages as $item)
	<?php $i++; if ($i>$max) continue; ?>
<div class="alert alert-info alert-block">
	<button type="button" class="close" data-dismiss="alert">×</button>
	<h5 style="margin:0">{{$item->title}}</h5>
	<a href="{{ $item->link }}" target="rss">go</a>  
</div>
@endforeach

</div>
Share Button

Vous devriez aimer...

1 Response

  1. Eric dit :

    Je n’ai pas bien compris pourquoi tu disais que laravel n’est pas un framework HMVC, c’est certain il lui manque quelques petites choses, mais déjà il reprend le concept de bundle de symfony2 dejà dans sa version 3, nous avons totalement un système HMVC au contraire hormis les requêtes HMVC dont je suis en attente sur le forum si il existe un moyen d’effectuer ce type de requête. En quel cas je devrais le développer moi même mais c’est dommage sachant que la plus part des frameworks tel que Zend, symfony2, cakephp, kohana et le très bon Fuelphp le font déjà.
    On peut appeler une méthode de controller depuis une vue, le controller et ses méthodes pourra donc être indépendant et global du coup. En imaginant que vous désireriez appeler un package datagrid qui vous permettrez de générer automatiquement un tableau de donné en lui envoyant simplement les variables nécessaires. Le template, le javascript et tout le processus de traitement se trouvera donc dans ce package datagrid et on pourrait l’appeler depuis la vue ou dans un controller comme tel {render (‘bundlename::controller@methode’, array(mes variables)}
    C’est un exemple bien entendu ne prenait pas la syntaxe comme fonctionnel.

    On pourrait tout autant réaliser cela pour générer aussi un menu dynamiquement. certain appellent cela un partial notamment dans cakephp mais bon.