Auto load views

Submitted by stygian - 10 years ago

This trick is what we use to make writing controllers very quick and easy. The base controller has methods plugged in where needed to automatically load views to a set of templates on it's own. All you need to do is pass it the data you want displayed. It also handles missingmethod to automatically look for logical views. Let me know what you think or any ideas for improving upon it. As a note, I use a separate controller to set the page title and menu items.

<?php
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

class BaseController extends Controller {

	protected $data	  = array();

	protected $pageTitle;

	protected $route;

	protected $activeUser;

	protected $layout;

	protected $redirectPath = null;

	protected $skipView = false;

	protected $hasView = false;

	/**
	 * Layouts array
	 *
	 * @var string[] $layouts Array of layout templates
	 */
	protected $layoutOptions = array(
		'default' => 'layouts.default',
		'ajax'    => 'layouts.ajax',
	);

	/**
	 * Create a new Controller instance.
	 * Assigns the active user
	 *
	 * @return void
	 */
	public function __construct()
	{
		// Login required options
		if (Auth::check()) {
			if (!Session::has('activeUser')) {
				Session::put('activeUser', Auth::user());
			}
			$this->activeUser = Session::get('activeUser');
		}
	}

	/********************************************************************
	 * Templating
	 *******************************************************************/
	protected function cleanRoute($route, $returnArray = false)
	{
		// Format a proper route for view to use
		$route         = str_replace('_', '.', $route);
		$routeParts    = explode('@', $route);
		$routeParts[1] = preg_replace('/^get/', '', $routeParts[1]);
		$routeParts[1] = preg_replace('/^post/', '', $routeParts[1]);
		$route         = strtolower(str_replace('Controller', '', implode('.', $routeParts)));

		if ($returnArray) {
			$routeParts	= explode('.', $route);
		}

		// If the route still does not exist, throw a 404
		if (!View::exists($route)) {
			if (Config::get('app.debug') == false) {
				App::abort(404);
			}
		}

		return $route;
	}

	public function missingMethod($method, $parameters = array())
	{
		$route = Route::currentRouteAction();

		$route = str_replace('missingMethod', $method, $route);

		$this->route = $this->cleanRoute($route);

		$this->makeView();
	}

	/**
	 * Master template method
	 * Sets the template based on location and passes variables to the view.
	 *
	 * @return void
	 */
	public function setupLayout()
	{
		if ($this->route == null) {
			$route       = Route::currentRouteAction();
			$this->route = $this->cleanRoute($route);
		}

		if ( is_null($this->layout) ) {
			if ( Request::ajax()) {
				$this->layout = View::make($this->layoutOptions['ajax']);
			} else {
				$this->layout = View::make($this->layoutOptions['default']);
			}
		} else {
			$this->layout = View::make($this->layout);
		}

		$this->data['activeUser'] = $this->activeUser;

		$this->layout->pageTitle  = $this->pageTitle;
		$this->layout->activeUser = $this->activeUser;

		if (strpos($this->route, 'missingmethod') === false) {
			$this->makeView();
		}
	}

	public function makeView()
	{
		if (!$this->skipView && View::exists($this->route)) {
			$this->layout->menu    = $this->menu;
			$this->layout->subMenu = $this->subMenu;
			$this->layout->content = View::make($this->route)->with($this->data);

			$this->hasView = true;
		}
	}

	public function setViewData($text, $data)
	{
		$content = array();
		$content[$text] = $data;

		$this->data[$text] = $data;

		if ($this->hasView) {
			$this->layout->content->with($content);
		}
	}

	public function setViewPath($view)
	{
		$this->route = $view;
		$this->makeView();
	}

	public function setPageTitle($title)
	{
		$this->pageTitle = $title;
		$this->makeView();
	}

	public function skipView()
	{
		$this->skipView = true;
	}

	protected function checkView($view)
	{
		return View::exists($view);
	}
}

// Example usage for passing data to the view

<?php

class HomeController extends BaseController {

    public function getMemberlist()
    {
        $users = User::orderBy('username', 'asc')->get();

        $this->setViewData('users', $users);
    }
}

// Example usage when skipping views (helpful for ajax requests)

<?php

class ForumController extends BaseController {
    public function getMarkAllRead()
	{
		$this->skipView();

		$forum = new Forum;
		$forum->markAllReadByUser($this->activeUser->id);

		Redirect::back()->with('message', 'All posts marked read.');
	}
}

// Example for using a specific view
<?php

class CharacterController extends BaseController {

	public function getPaginationCharacters()
	{
		$characters = Character::where('user_id', $this->activeUser->id)->orderByNameAsc()->paginate(3);

    	$this->setViewPath('character.pagination');
		$this->setViewData('characters', $characters);
	}