Getting Started

Installation

In order to start a new project, I recommend that you install the skeleton application later described in this Getting Started section. For the simplicity of this tutorial, I will only install the application core and write the bootstrap file from scratch. I execute the following command line with Composer:

composer require gobline/application

Hello, world!

Writing “Hello, world!” with minimum lines of code.

<?php
require 'vendor/autoload.php';

$app = new Gobline\Application\Facade();

$app->get('/', function($request$response) {
    
$response->getBody()->write('Hello, world!');

    return 
$response;
});

$app->run();

Writing “Hello, <your name>!”.

<?php
require 'vendor/autoload.php';

$app = new Gobline\Application\Facade();

$app->get('/', function($request$response) {
    
$response->getBody()->write('Hello, world!');

    return 
$response;
});

$app->get('/:name', function($request$response$name) {
    
$response->getBody()->write("Hello, $name!");

    return 
$response;
});

$app->run();

The code above can be simplified by making the :name placeholder optional:

<?php
$app
->get('/(:name)', function($request$response$name 'world') { 
    
$response->getBody()->write("Hello, $name!"); 

    return 
$response
});

Template rendering

<?php
require 'vendor/autoload.php'

$app = new Gobline\Application\Facade(); 

$app->get('/')->view(['text/html' => 'view/hello.html.php']);

$app->run();

view/hello.html.php

Hello, world!

Generates:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
Hello, world!
</body>
</html>

View helpers

Add a title and a CSS file for hello.html.php view.

<?php
$title
('Hello World');
$css('css/main.css');
?>
Hello, world!

Generates:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello World</title>
<link rel="stylesheet" href="/css/main.css">
</head>
<body>
Hello, world!
</body>
</html>

Find a list of all available view helpers in the Template Rendering section.

Layouts

<?php
$app
->get('/')
    ->
view(['text/html' => 'view/hello.html.php'])
    ->
layouts(['view/layout.html.php']);

view/layout.html.php

<?php
$title
->suffix(' | Sample Application');
$css('css/main.css'); // moved from template to layout
?>
<header>
    Some header
</header>
<?= $this->content() ?>
<footer>
    Some footer
</footer>

Generates:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello World | Sample Application</title>
<link rel="stylesheet" href="/hello/css/main.css">
</head>
<body>
<header>
    Some header
</header>
Hello, world!<footer>
    Some footer
</footer>
</body>
</html>

Hello world in JSON

<?php
$app
->get('/')
    ->
view([
        
'text/html' => 'view/hello.html.php',
        
'application/json' => 'view/hello.json.php',
    ])
    ->
layouts(['view/layout.html.php']);

view/hello.json.php

<?php
return ['msg' => 'Hello, world!'];

Generates (with Content-Type: application/json) :

{ "msg": "Hello, world!" }

Action Models

In order to render the template for the route /:name, we will need to use an Action Model, which will let the value for the name parameter be accessible to the view.

<?php
namespace ActionModel;

class 
HelloActionModel
{
    public 
$name;

    public function 
__invoke($request$name 'world')
    {
        
$this->name $name;
    }
}

view/hello.html.php

<?php
$title
('Hello World');
?>
Hello, <?= $model->name ?>!

view/hello.json.php

<?php
return [
    
'msg' => 'Hello, '.$model->name.'!'
];
<?php
require 'vendor/autoload.php'

$app = new Gobline\Application\Facade();

$app->get('/(:name)')
    ->
action(ActionModel\HelloActionModel::class)
    ->
view([
        
'text/html' => 'view/hello.html.php',
        
'application/json' => 'view/hello.json.php',
    ])
    ->
layouts(['view/layout.html.php']);

$app->run();

Services & dependency injection

In most cases your Action Models will require services like an ORM for updating the database, a mailer for sending emails, etcetera.

For this example we will simply log "hello!" in a file from our previous HelloActionModel class.

<?php
namespace ActionModel;

use 
Psr\Log\LoggerInterface;

class 
HelloActionModel {
    public 
$name;
    private 
$logger;

    public function 
__construct(LoggerInterface $logger)
    {
        
$this->logger $logger;
    }

    public function 
__invoke($request$name null)
    {
        
$this->name $name ?: 'world';

        
$this->logger->info('hello!');
    }
}

The easiest way to inject the logger dependency into the Action Model, is by simply adding the logger into the dependency container. The request dispatcher automatically resolves the Action Models' dependencies.

<?php
require 'vendor/autoload.php'

$app = new Gobline\Application\Facade();

$writer = new Gobline\Logger\Writer\FileLogWriter('./logs');

$app->getContainer()
    ->
share($writer)
    ->
alias(Psr\Log\LoggerInterface::class, $writer);

$app->get('/(:name)')
    ->
action(ActionModel\HelloActionModel::class)
    ->
view([
        
'text/html' => 'view/hello.html.php',
        
'application/json' => 'view/hello.json.php',
    ])
    ->
layouts(['view/layout.html.php']);

$app->run();

We usually want to instantiate our dependencies on demand:

<?php
$app
->getContainer()
    ->
share(Gobline\Logger\Writer\FileLogWriter::class, ['./logs'])
    ->
alias(Psr\Log\LoggerInterface::class, Gobline\Logger\Writer\FileLogWriter::class);

Config file

We can register our services through config files. For this example, I will define the route and the logger in config files.

You specify your config files through the Registrar object:

<?php
require 'vendor/autoload.php'

$app = new Gobline\Application\Facade();

$app->getRegistrar()
    ->
register('config/services.php')
    ->
register('config/routes.php');

$app->run();

config/services.php

<?php
return [
    
Gobline\Logger\Writer\FileLogWriter::class => [
        
'construct' => [
            
'arguments' => ['./logs'],
        ],
        
'alias' => Psr\Log\LoggerInterface::class,
    ],
];

config/routes.php

<?php
return [
    
Gobline\Router\RouteCollection::class => [
        
'configure' => [
            
'configurator' => 
                
Gobline\Router\Provider\Gobline\RouteCollectionConfigurator::class,
            
'data' => [
                
'routes' => [
                    [
                        
'path' => '/(:name)',
                        
'allows' => 'GET',
                        
'values' => [
                            
'_action' => ActionModel\HelloActionModel::class,
                            
'_view' => [
                                
'text/html' => 'view/hello.html.php',
                                
'application/json' => 'view/hello.json.php',
                            ],
                            
'_layouts' => [
                                
'view/layout.html.php',
                            ],
                        ],
                    ],
                ],
            ],
        ],
    ],
];

Skeleton application

The skeleton application generates for you a suggested folder structure and minimal bootstrap and config files.

composer create-project gobline/skeleton my-site-name

You can then run it on http://localhost/my-site-name/public