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 }}'>
    <head>
        <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 %}

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

        {% block content %}{% endblock %}

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

    </body>
</html>

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>

    <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
View::setBaseTemplate('your-new-base-template.html');

// Set a new ajax base template
View::setAjaxTemplate('your-new-ajax-template.html');

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(){
        $this->scriptSrc('http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js');
        $this->scriptSrc('/js/modernizr.js');
        $this->scriptSrc('/js/foundation.min.js');
        $this->scriptSrc('/js/js.js');

        $this->styleSrc('/css/foundation.min.css');
        $this->styleSrc('/css/css.css');
    }

    // 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(){

        parent::__construct();

        // Lets use a different base template on this view
        $this->setBaseTemplate('_user-default.html');

        $this->scriptSrc('/js/user.js');
        $this->styleSrc('/css/user.css');

    }

}


// 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
View::html('<h1>Title</h1>');


// 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
View::favIcon('/img/favicon.png');


// Set the lang of the page
View::lang('en');


// Set the charset of the page
View::charset('utf-8');


// Include a javascript resource
View::scriptSrc('/js/js.js');


// Include a javascript resource in the <head> element of the page
View::headScriptSrc('http://cdn.com/library/core.js');


// Use the prop method in combination with scriptSrc & headScriptSrc 
// methods to set properties on the <script> element
View::scriptSrc('/js/big.js')->prop('async','true');


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


// Include a css resource
View::styleSrc('/css/css.css');


// 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
View::style('
    .red {
        background-color:red;
    }
');


// Add arbitrary elements to the <head> element
View::headExtra('
    <meta name="geo.region" content="US-FL">
    <meta name="geo.placename" content="Tampa">
');


// Set a class to be applied to the <body> element
View::bodyClass('has-comments');


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


// Add schema.org json-ld to the head of the page
// You can pass an array which will be merged with the current schema
View::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'] = 'https://github.com/discophp/framework';
View::setSchema($schema);

AJAX & JSON #

// Specify that the view is AJAX
View::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`
View::json();

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


// Immediately return a JSON response
$response = ['data' => ['new_id' => 2309], 'error' => false];
View::json($response);