Requests to web applications typically result in one of two types of responses:

  • A Full HTML Page
  • A Data Structure or HTML snippet

The View service can be thought of as the orchestrator of the eventual output that will be your web page for a specific route. This includes handling the production of both types of outputs listed above. It's in charge of holding all the html/javascript/css/data pieces that will go into creating the page as well as providing the functionality to accomplish the task of organizing and outputting the page.

The _layout.html template serves as the layout for all non AJAX requests:

<!doctype html>
<html lang='{{ View.lang }}'>
        <meta charset='{{ View.charset }}' />
        <meta content='{{ View.robots }}' name='robots'>

        <meta name='viewport' content='width=device-width, initial-scale=1.0' />

        <title>{{ View.title }}</title>

        {% if View.description %}
        <meta name='description' content="{{ View.description }}">
        {% endif %}

        {% if View.favIcon %}
        <link type='image/x-icon' href='{{ View.favIcon }}' rel='shortcut icon'>
        {% endif %}

        {{ View.printStyleSrcs() }}

        {{ View.printStyles() }}

        {{ View.printHeadScriptSrcs() }}

        {% if View.headExtra %}
            {{ View.headExtra }}
        {% endif %}

    {% set bodyClasses = View.bodyClasses() %}
    <body{% if bodyClasses %} class='{{ bodyClasses }}'{% endif %}> 

        {% block content %}{% endblock %}

        {{ View.printScriptSrcs() }}
        {{ View.printScripts() }}


The _default.html template serves as the default page structure. It is what populates the block content in the _layout.html template above or the block content in _ajax_layout.html.

{% extends View.isAjax ? "_ajax_layout.html" : "_layout.html" %}

{% block content %}

    <div class='body-content-wrapper'>
        <div class='header'>{{ View.getHeader }}</div>
        <div class='body'>{{ View.body }}</div>

    <div class='footer'>{{ View.getFooter }}</div>

{% endblock %}

You can change the default base template and default AJAX template on the fly:

// Set a new base template

// Set a new ajax base template

Creating Views #

Views should be stored in the app/view/ directory and extend the Disco\classes\View class.

Lets check out some basic view classes:

// This is the default extended view that ships with disco

namespace App\view;
Class Standard extends \Disco\classes\View {

    // Override the header function and return the header template
    public function header(){
        return \Template::build('header.html');

    // Add the javascript and css resources that are used on every page of the application
    public function __construct(){


    // Override the footer function and return the header template
    public function footer(){
        return \Template::build('footer.html');


// Lets use the view
App::make('View', 'App\view\Standard');

// Lets create another view specific to users
// only this time lets extend our standard view so we get all its resources
class User extends Standard {

    public function header(){
        return Template::render('user/header');

    public function __construct(){


        // Lets use a different base template on this view




// Where and when would we specify we want to use the User view?
// Anytime you want really, but a common pattern is to register it in the constructor of the controller
// So say below is our user controller
namespace App\controller;
class User {

    public function __construct(){
        App::make('View', 'App\view\User');


Adding Content to the View #

Below are examples of methods that allow adding content and resources to the current view.

// Append html to the body of the response

// Set the body of the response overwriting any html already added via the html method
View::body('<p>Your html is mine!</p>');

// Set the title of the view
View::title('Your page title');

// Set the description of the view
View::desc('The description for your page');

// Set the header of the view
View::setHeader( Template::render('header') );

// Set the footer of the view
View::setFooter('<div>The foot</div>');

// Set the favicon of the page

// Set the lang of the page

// Set the charset of the page

// Include a javascript resource

// Include a javascript resource in the <head> element of the page

// Use the prop method in combination with scriptSrc & headScriptSrc 
// methods to set properties on the <script> element

// Include javascript code
View::script('alert("Hey there");');

// Include a css resource

// Use the prop method in combination with the styleSrc
// method to set properties on the <link> element
View::styleSrc('/css/800px.css')->prop('media','screen and (min-device-width: 800px)');

// Include css style definitions
    .red {

// Add arbitrary elements to the <head> element
    <meta name="geo.region" content="US-FL">
    <meta name="geo.placename" content="Tampa">

// Set a class to be applied to the <body> element

// Robot indexing for <meta> robots tag
View::index(); // index,follow
View::noIndex() // noindex,nofollow
View::indexNoFollow(); // index,nofollow
View::noIndexFollow(); // noindex,follow

// Add json-ld to the head of the page
// You can pass an array which will be merged with the current schema
    '@type' => 'SoftwareApplication',
    'name' => 'Disco PHP Framework'

// Or you can pass individual key value pairs to set
View::schema('description','A PHP framework');

// You can get the entire current schema
$schema = View::getSchema();

// And set the entire schema
$schema['downloadUrl'] = '';


// Specify that the view is AJAX

// Ask if the view is AJAX
if( View::isAjax() ){
   // Its AJAX

// Specify that the view is returing JSON
// this will set the response header type to `application/json`

// Ask if the view is JSON
if( View::isJson() ){
   // Its JSON

// Immediately return a JSON response
$response = ['data' => ['new_id' => 2309], 'error' => false];