Overview

Namespaces

  • None
  • PHP
  • Pry
    • Auth
      • Interfaces
    • Config
    • Controller
    • Date
    • Db
    • Feed
      • Abstracts
      • Writers
    • File
      • Decorator
    • Form
      • Element
    • Image
    • Log
      • Writer
    • Net
      • Exception
    • Session
    • Util
    • Validate
      • Validator
    • View

Classes

  • BaseController
  • Router
  • Overview
  • Namespace
  • Class
  • Tree
  1: <?php
  2: 
  3: /**
  4:  * Pry Framework
  5:  *
  6:  * LICENSE
  7:  *
  8:  * This source file is subject to the new BSD license that is bundled
  9:  * with this package in the file LICENSE.txt.
 10:  * 
 11:  */
 12: 
 13: namespace Pry\Controller;
 14: 
 15: use Pry\Net\Request;
 16: 
 17: /**
 18:  * Router permettant la mise en place du pattern MVC
 19:  * Gère les routes classiques ainsi que les règles de routages
 20:  * <code>
 21:  * $router = Router::getInstance();
 22:  * $router->setPath(ROOT_PATH.'includes/controllers/'); // Chemin vers les controlleurs
 23:  * $router->addRule('test/regles/:id/hello',array('controller'=>'index','action'=>'withRule'));
 24:  * </code>
 25:  * Nécessite une règle de routage du type RewriteRule ^(.*)$ index.php?url=$1 [QSA,L] dans le serveur web
 26:  * 
 27:  * @category Pry
 28:  * @package Controller
 29:  * @version 1.3.5
 30:  * @author Olivier ROGER <oroger.fr>
 31:  *
 32:  */
 33: class Router
 34: {
 35: 
 36:     /**
 37:      * Instance du router
 38:      * @static
 39:      * @var Controller_Router
 40:      */
 41:     static private $instance;
 42: 
 43:     /**
 44:      * Controller à utiliser. Par defaut index
 45:      * @var string
 46:      */
 47:     private $controller;
 48: 
 49:     /**
 50:      * Action du controller. Par défaut index
 51:      * @var string
 52:      */
 53:     private $action;
 54: 
 55:     /**
 56:      * Tableau des paramètres
 57:      * @var array
 58:      */
 59:     private $params;
 60: 
 61:     /**
 62:      * Liste des règles de routage
 63:      * @var array
 64:      */
 65:     private $rules;
 66: 
 67:     /**
 68:      * Chemin vers le dossier contenant les controllers
 69:      * @var string
 70:      */
 71:     private $path;
 72: 
 73:     /**
 74:      * Objet de vue
 75:      * @var mixed 
 76:      */
 77:     private $view;
 78: 
 79:     /**
 80:      * Fichier à inclure
 81:      * @var string
 82:      */
 83:     private $file;
 84: 
 85:     /**
 86:      * Controller par defaut (index)
 87:      * @var string
 88:      */
 89:     private $defaultController;
 90: 
 91:     /**
 92:      * Action par defaut (index)
 93:      * @var string
 94:      */
 95:     private $defaultAction;
 96: 
 97:     /**
 98:      * Controller à appelé en cas d'erreur. Par defaut error
 99:      * @var string
100:      */
101:     private $errorController;
102: 
103:     /**
104:      * Action à appelé en cas d'erreur. par defaut index
105:      * @var string
106:      */
107:     private $errorAction;
108: 
109:     /**
110:      * Le router gère t'il les url du type site.com/fr/controller/action
111:      * @var boolean 
112:      */
113:     private $isMultiLangue = false;
114: 
115:     /**
116:      * Code langue choisie
117:      * @var string 
118:      */
119:     private $codeLangue = '';
120: 
121:     /**
122:      * Liste des traduction d'url
123:      * @var array 
124:      */
125:     private $tradController;
126: 
127:     /**
128:      * Requete HTTP
129:      * @var Net_Request
130:      */
131:     private $request;
132: 
133:     /**
134:      * Singleton de la classe
135:      * @return Controller_Router
136:      */
137:     public static function getInstance()
138:     {
139:         if (!isset(self::$instance))
140:             self::$instance = new Router();
141:         return self::$instance;
142:     }
143: 
144:     /**
145:      * Charge le controller demandé.
146:      * Prend en compte les règles de routages si nécessaire
147:      */
148:     public function load()
149:     {
150:         $this->request = new Request();
151:         $tmp           = $this->request->url;
152: 
153:         $url      = !empty($tmp) ? $tmp : '';
154:         $tabUrl   = explode('/', $url);
155:         $isCustom = false;
156: 
157:         //Suppression des éventuelles partie vide de l'url
158:         $this->clear_empty_value($tabUrl);
159: 
160:         if (!empty($this->rules))
161:         {
162:             foreach ($this->rules as $key => $data) {
163:                 $params = $this->matchRules($key, $tabUrl);
164:                 if ($params)
165:                 {
166:                     $this->controller = $data['controller'];
167:                     $this->action     = $data['action'];
168:                     $this->params     = $params;
169:                     $isCustom         = true;
170:                     break;
171:                 }
172:             }
173:         }
174: 
175:         if (!$isCustom)
176:             $this->getRoute($tabUrl);
177: 
178:         $this->controller = (!empty($this->controller)) ? $this->controller : $this->defaultController;
179:         $this->action     = (!empty($this->action)) ? $this->action : $this->defaultAction;
180:         $ctrlPath         = str_replace('_', '/', $this->controller); // Gestion des sous dossiers dans les controllers
181:         $this->file       = realpath($this->path) . DIRECTORY_SEPARATOR . $ctrlPath . '.php';
182: 
183:         //Enrichissement de la requête
184:         $this->params['action']     = $this->action;
185:         $this->params['controller'] = $this->controller;
186:         $this->request->add($this->params);
187: 
188:         //is_file bien plus rapide que file_exists
189:         if (!is_file($this->file))
190:         {
191:             header("Status: 404 Not Found");
192:             $this->controller = $this->errorController;
193:             $this->action     = $this->errorAction;
194:             $this->file       = $this->path . $this->controller . '.php';
195:         }
196: 
197:         //Inclusion du controller
198:         include $this->file;
199: 
200:         $class = $this->controller . 'Controller';
201: 
202:         if (!empty($this->codeLangue))
203:         {
204:             $controller = new $class($this->request, $this->codeLangue);
205:         }
206:         else
207:         {
208:             $controller = new $class($this->request);
209:         }
210: 
211:         if (!empty($this->view))
212:             $controller->setView($this->view);
213: 
214:         if (!is_callable(array($controller, $this->action)))
215:         {
216:             $action = $this->defaultAction;
217:         }
218:         else
219:         {
220:             $action = $this->action;
221:         }
222: 
223:         $controller->$action();
224:     }
225: 
226:     /**
227:      * Ajoute une règle de routage.
228:      *
229:      * @param string $rule Règles de routage : /bla/:param1/blabla/:param2/blabla
230:      * @param array $target Cible de la règle : array('controller'=>'index','action'=>'test')
231:      */
232:     public function addRule($rule, $target)
233:     {
234:         if ($rule[0] != '/')
235:             $rule = '/' . $rule; //Ajout du slashe de début si absent
236: 
237:         $this->rules[$rule] = $target;
238:     }
239: 
240:     /**
241:      * Vérifie si l'url correspond à une règle de routage
242:      * @link http://blog.sosedoff.com/2009/07/04/simpe-php-url-routing-controller/
243:      * @param string $rule
244:      * @param array $dataItems
245:      * @return boolean|array
246:      */
247:     public function matchRules($rule, $dataItems)
248:     {
249:         $ruleItems = explode('/', $rule);
250:         $this->clear_empty_value($ruleItems);
251: 
252:         if (count($ruleItems) == count($dataItems))
253:         {
254:             $result = array();
255:             foreach ($ruleItems as $rKey => $rValue) {
256:                 if ($rValue[0] == ':')
257:                 {
258:                     $rValue          = substr($rValue, 1); //Supprime les : de la clé
259:                     $result[$rValue] = $dataItems[$rKey];
260:                 }
261:                 else
262:                 {
263:                     if ($rValue != $dataItems[$rKey])
264:                         return false;
265:                 }
266:             }
267:             if (!empty($result))
268:                 return $result;
269: 
270:             unset($result);
271:         }
272:         return false;
273:     }
274: 
275:     /**
276:      * Retourne l'action
277:      * @return string 
278:      */
279:     public function getAction()
280:     {
281:         return $this->action;
282:     }
283: 
284:     /**
285:      * Retourne le controller
286:      * @return string
287:      */
288:     public function getController()
289:     {
290:         return $this->controller;
291:     }
292: 
293:     /**
294:      * Défini une route simple
295:      * @param array $url
296:      */
297:     private function getRoute($url)
298:     {
299:         $items = $url;
300: 
301:         if (!empty($items))
302:         {
303:             if ($this->isMultiLangue)
304:                 $this->codeLangue = array_shift($items);
305: 
306:             $this->controller = array_shift($items);
307:             $this->action     = array_shift($items);
308:             $size             = count($items);
309:             if ($size >= 2)
310:                 for ($i = 0; $i < $size; $i += 2) {
311:                     $key                = (isset($items[$i])) ? $items[$i] : $i;
312:                     $value              = (isset($items[$i + 1])) ? $items[$i + 1] : null;
313:                     $this->params[$key] = $value;
314:                 }
315:             else
316:                 $this->params       = $items;
317: 
318: 
319: 
320:             //Permet d'avoir des URL multilangue
321:             if (!empty($this->tradController))
322:             {
323:                 if (isset($this->tradController[$this->codeLangue][$this->controller]['controllerName']))
324:                 {
325:                     $controller       = $this->tradController[$this->codeLangue][$this->controller]['controllerName'];
326:                     if (!empty($controller))
327:                         $this->controller = $controller;
328:                 }
329: 
330:                 if (isset($this->tradController[$this->codeLangue][$this->controller]['actionsNames'][$this->action]))
331:                 {
332:                     $action       = $this->tradController[$this->codeLangue][$this->controller]['actionsNames'][$this->action];
333:                     if (!empty($action))
334:                         $this->action = $action;
335:                 }
336:             }
337:         }
338:     }
339: 
340:     /**
341:      * Défini le chemin des controllers
342:      * @param string $path
343:      */
344:     public function setPath($path)
345:     {
346:         if (is_dir($path) === false)
347:         {
348:             throw new \InvalidArgumentException('Controller invalide : ' . $path);
349:         }
350: 
351:         $this->path = $path;
352:     }
353: 
354:     public function setView($view)
355:     {
356:         $this->view = $view;
357:     }
358: 
359:     /**
360:      * Défini le router comme pouvant gérer ou non le multinlangue
361:      * @param boolean $is 
362:      */
363:     public function setMultiLangue($is)
364:     {
365:         $this->isMultiLangue = $is;
366:     }
367: 
368:     /**
369:      * Défini un tableau permettant d'avoir des URL multi langue.
370:      * Format du tableau : 
371:      * 
372:      * @param array $trad format : 
373:      * $urlTraduction = array(
374:       'fr'=>array(
375:       'accueil'=>array(
376:       'controllerName'  => 'index',
377:       'actionsNames'        => array(
378:       'presentation'    => 'index',
379:       'liste'           => 'list',
380:       'recherche'       => 'search'
381:       )
382:       )
383:       ),
384:       'en'=>array(...));
385:      */
386:     public function setControllerTraduction($trad)
387:     {
388:         $this->tradController = $trad;
389:     }
390: 
391:     /**
392:      * Défini le controller et l'action par défaut
393:      * @param string $controller
394:      * @param string $action
395:      */
396:     public function setDefaultControllerAction($controller, $action)
397:     {
398:         $this->defaultController = $controller;
399:         $this->defaultAction     = $action;
400:     }
401: 
402:     /**
403:      * Défini le controller et l'actionen cas d'erreur
404:      * @param string $controler
405:      * @param string $action
406:      */
407:     public function setErrorControllerAction($controller, $action)
408:     {
409:         $this->errorController = $controller;
410:         $this->errorAction     = $action;
411:     }
412: 
413:     /**
414:      * Renvoi les paramètres disponibles
415:      * @return array
416:      */
417:     public function getParameters()
418:     {
419:         return $this->params;
420:     }
421: 
422:     /**
423:      * Constructeur
424:      */
425:     private function __construct()
426:     {
427:         $this->rules = array();
428:         $this->defaultController = 'index';
429:         $this->defaultAction     = 'index';
430:         $this->errorController   = 'error';
431:         $this->errorAction       = 'index';
432:     }
433: 
434:     /**
435:      * Supprime d'un tableau tous les élements vide
436:      * @param array $array
437:      */
438:     private function clear_empty_value(&$array)
439:     {
440:         foreach ($array as $key => $value) {
441:             if (empty($value) && $value != 0)
442:                 unset($array[$key]);
443:         }
444:         $array = array_values($array); // Réorganise les clés
445:     }
446: 
447: }
448: 
Pry API documentation generated by ApiGen 2.8.0