Laravel的Controller主要提供filter的功能。
值得一提的是,在執行工作:Routing/Route.php裏面我們看到,Route類別有變數去儲存before與after等filter動作。然而此處的Controller類別又有beforeFilters與afterFilters去儲存filter動作。
這樣的設計允許了filter的兩種寫法:一種是在設定routes規則時撰寫、一種是寫在controller內。參見官網「Controller Filters」一節的舉例。
beforeFilters[] = $this->parseFilter($filter, $options); } /** * Register an "after" filter on the controller. * * @param \Closure|string $filter * @param array $options * @return void */ public function afterFilter($filter, array $options = array()) { $this->afterFilters[] = $this->parseFilter($filter, $options); } /** * Parse the given filter and options. * * @param \Closure|string $filter * @param array $options * @return array */ protected function parseFilter($filter, array $options) { $parameters = array(); $original = $filter; if ($filter instanceof Closure) { $filter = $this->registerClosureFilter($filter); } elseif ($this->isInstanceFilter($filter)) { $filter = $this->registerInstanceFilter($filter); } else { list($filter, $parameters) = Route::parseFilter($filter); } return compact('original', 'filter', 'parameters', 'options'); } /** * Register an anonymous controller filter Closure. * * @param \Closure $filter * @return string */ protected function registerClosureFilter(Closure $filter) { $this->getFilterer()->filter($name = spl_object_hash($filter), $filter); return $name; } /** * Register a controller instance method as a filter. * * @param string $filter * @return string */ protected function registerInstanceFilter($filter) { $this->getFilterer()->filter($filter, array($this, substr($filter, 1))); return $filter; } /** * Determine if a filter is a local method on the controller. * * @param mixed $filter * @return boolean * * @throws \InvalidArgumentException */ protected function isInstanceFilter($filter) { if (is_string($filter) && starts_with($filter, '@')) { if (method_exists($this, substr($filter, 1))) return true; throw new \InvalidArgumentException("Filter method [$filter] does not exist."); } return false; } /** * Remove the given before filter. * * @param string $filter * @return void */ public function forgetBeforeFilter($filter) { $this->beforeFilters = $this->removeFilter($filter, $this->getBeforeFilters()); } /** * Remove the given after filter. * * @param string $filter * @return void */ public function forgetAfterFilter($filter) { $this->afterFilters = $this->removeFilter($filter, $this->getAfterFilters()); } /** * Remove the given controller filter from the provided filter array. * * @param string $removing * @param array $current * @return array */ protected function removeFilter($removing, $current) { return array_filter($current, function($filter) use ($removing) { return $filter['original'] != $removing; }); } /** * Get the registered "before" filters. * * @return array */ public function getBeforeFilters() { return $this->beforeFilters; } /** * Get the registered "after" filters. * * @return array */ public function getAfterFilters() { return $this->afterFilters; } /** * Get the route filterer implementation. * * @return \Illuminate\Routing\RouteFiltererInterface */ public static function getFilterer() { return static::$filterer; } /** * Set the route filterer implementation. * * @param \Illuminate\Routing\RouteFiltererInterface $filterer * @return void */ public static function setFilterer(RouteFiltererInterface $filterer) { static::$filterer = $filterer; } /** * Create the layout used by the controller. * * @return void */ protected function setupLayout() {} /** * Execute an action on the controller. * * @param string $method * @param array $parameters * @return \Symfony\Component\HttpFoundation\Response */ public function callAction($method, $parameters) { $this->setupLayout(); $response = call_user_func_array(array($this, $method), $parameters); // If no response is returned from the controller action and a layout is being // used we will assume we want to just return the layout view as any nested // views were probably bound on this view during this controller actions. if (is_null($response) && ! is_null($this->layout)) { $response = $this->layout; } return $response; } /** * Handle calls to missing methods on the controller. * * @param array $parameters * @return mixed * * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException */ public function missingMethod($parameters = array()) { throw new NotFoundHttpException("Controller method not found."); } /** * Handle calls to missing methods on the controller. * * @param string $method * @param array $parameters * @return mixed * * @throws \BadMethodCallException */ public function __call($method, $parameters) { throw new \BadMethodCallException("Method [$method] does not exist."); } }