Documentation

This is the documentation of all available features in Niuware WebFramework.

  1. Installation
    1.1 Configuration File
  2. Routing
    2.1 Application Main Space
    2.2 Application Admin Space
    2.3 Application Spaces
    2.4 Mapped Variables
    2.5 Options
    2.6 Custom Requests
    2.7 Overriding Methods
    2.8 API-Only Mode
    2.9 YAML/JSON Definition
  3. Controllers
    3.1 Definition
    3.2 Calls
    3.3 Protocol Restriction
    3.4 GET Protocol Methods
    3.5 POST Protocol Methods
    3.6 Request Attributes
    3.7 Recycling
    3.8 With JSON Response
  4. Models
    4.1 Definition
    4.2 Eloquent
  5. Views
    5.1 Definition
    5.2 Rendering
    5.3 Main Views
    5.4 Template Attributes
    5.5 View/Controller Binding
    5.6 Functions and Filters
  6. Sessions
    6.1 Authentication
    6.2 Custom Values
    6.3 Termination
  7. Customization
    7.1 Helper Class
    7.1 Definition of Custom Classes
  8. API Classes
    8.1 Definition
    8.1 Method Syntax
    8.2 Protocol Restriction
    8.3 Request Parameters
    8.4 Response Rendering
    8.5 Multiple Version Support
  9. Security
    9.1 Passwords
    9.2 Tokens
    9.3 CSRF Token Form Validation
  10. Requests
    10.1 Definition
    10.2 Validation
    10.3 Mutation
  11. Files
    11.1 Attributes
  12. Console
  13. Database Migrations
    13.1 Migration Definitions
    13.2 Seeding
    13.3 Rollback
    13.4 Status
    13.5 Custom Connection
  14. Pagination
  15. Exceptions
  16. PHP < 7.0 Compatibility

1. Installation

For using the Niuware WebFramework follow this steps:

  1. Download or clone the repository from GitHub.
  2. Run composer install to install the dependencies.

Installation: Configuration File

The framework uses a single configuration file to store private information such as database connection strings, third party API tokens etc. It also contains the default values for the Web application. You can find this file in App/Config/Settings.php

Global Constants

The following table shows the application constants that you need to configure:

Name Description
SERVER_ENV_VAR How PHP receive requests.
Either \INPUT_SERVER or \INPUT_ENV
BASE_PATH If your BASE_URL has a sub path (subdirectory), write it here.
For example: If BASE_URL is http://my_url.com/ then BASE_PATH should be '/'.
If BASE_URL is http://my_url.com/sub_domain/ then BASE_PATH should be sub_domain/
Should include the trailing slash.
BASE_URL Absolute URL for the Web Main application.
For example: http://my_domain/
Should include the trailing slash.
BASE_URL_SSL Absolute URL for the Web Main application's SSL protocol. (Optional)
For example: https://my_domain/
Should include the trailing slash.
DEBUG_MODE Sets the debug mode for the application
Either true or false
DEFAULT_RENDERER Sets the default template renderer.
Either twig or php
CONSOLE_MODE Sets if the framework console will be available for executing commands such as migrations.
Either: terminal, web, enabled or disabled
HOMEPAGE The default path for the Web Main application.
For example: home then the path will be {BASE_URL}/home
DEFAULT_TITLE The default title for any view. (Optional)
For example: Niuware WebFramework
DEFAULT_DESCRIPTION The default description for any view. (Optional)
For example: This is my web application.
DEFAULT_KEYWORDS The default keywords for any view. (Optional)
For example: One, Two, Three

You can also set here the default timezone for your application using the date_default_timezone_set function located at the top of the file. For more information check the PHP documentation.

Settings Class

The Settings class contains database connection parameters, third party API’s tokens and timezone formats. There are three array variables where you can set these values:

$database Add arrays for setting connection configurations for databases.
$apps Add arrays for all 3rd party API's configurations.
$languages Add arrays for timezone and location configurations.

2. Routing

Defining easy to access routes for your application is one important task for your project and for users. With Niuware WebFramework its simple to create friendly URLs by just adding the string of the path you need.

Web applications created with Niuware WebFramework have application spaces and the application admin space. For example suppose you create an online shop; you’ll need the frontend side where all the products will be browsable by your customers, and an admin panel side where your staff will be able to add or edit products for the shop.

Routing: Application Main Space

The main application path views can be public (by default) or require a user login. For adding routes for the main space application you only need to edit the App/Config/Routes.php file.

For example, let’s suppose you want people to access this sections in your web application:

http://my_url/home
http://my_url/my-cart
http://my_url/category/category-name

Then your Routes.php file should look like this:

[App/Config/Routes.php]

<?php 

namespace App\Config;

/**
 * Defines the routes for the web application
 */
final class Routes {
    
    public static $views = [
        'main' => [
            // Simple route
            'home' => ['use' => 'Home'], 

            // Login required
            'my-cart' => ['use' => 'Cart', 'require' => ['login']],  

            // Login and CSRF validation required
            'my-form' => ['use' => 'Cart', 'require' => ['login', 'csrf']],

            // Login and CSRF custom validation
            'my-form' => ['use' => 'Cart', 'require' => ['login' => false, 'csrf' => ['get', 'post', 'delete']]],

            // Mapped variables
            'category/{name}' => ['use' => 'Category'],

            // Overriding methods
            'login' => ['use' => 'Login@logout']

            // Overriding custom request
            'search' => ['use' => 'Search', 'request' => 'CustomSearchRequest']
            ...
        ],
        ...
    ];
}

In the previous example you can notice each path has an array value as well. This array has two keys: use which points to the Controller class that will listen to the path and require, that has values such as ‘login’ or ‘csrf’ and tells the framework if the path requires an active logged in session and/or a CSRF validation when sending data to the server (see CSRF Token Form Validation for more details). This values are set to false by default so you can omit the whole ‘require’ key. The usage of Controllers is detailed in the Controllers section of this page.

Routing: Application Admin Space

All the application admin space path views require a user login by default. The framework will add the prefix admin/ to all routes set for the Admin application. As with the previous Main application routing section, you only need to edit the App/Config/Routes.php file.

For example, let’s suppose you want people to access this sections in your web application:

http://my_url/admin/home
http://my_url/admin/products
http://my_url/admin/accounts

Then your Routes.php file should look like this:

[App/Config/Routes.php]

<?php 

namespace App\Config;

/**
 * Defines the routes for the web application
 */
final class Routes {
    
    public static $views = [
        ...
        'admin' => [
            'home' => ['use' => 'Home'], 
            'products' => ['use' => 'Products'],
            'accounts' => ['use' => 'Accounts'],
            ...
        ]
    ];
}

As mentioned before, all paths for the admin side require a logged in session. Additionally an automatic CSRF validation will be executed within POST and DELETE requests. You can also activate or deactivate the CSRF validation for any request (GET, POST, DELETE) of any route as prefered.

Routing: Application Spaces

Just as the application admin space, you can create custom spaces. Each of the spaces has its own session so a login in the ‘main’ space, won’t grant access to the ‘admin’ or any other spaces. This is very useful not only for splitting access to your application but to have a better order in your project.

Let’s suppose you want an space called ‘user’, and you want to define the following routes:

http://my_url/staff/home
http://my_url/staff/settings

Then your Routes.php file should look like this:

[App/Config/Routes.php]

<?php 

namespace App\Config;

/**
 * Defines the routes for the web application
 */
final class Routes {
    
    public static $views = [
        ...
        'staff' => [
            'home' => ['use' => 'Home', 'require' => ['login']], 
            'settings' => ['use' => 'Settings', 'require' => ['login']],
            ...
        ]
    ];
}

Routing: Mapped Variables

It is easy to map variables in a route path by declaring them between {curly braces}. For example, for the following route:

http://my_url/product/edit/34/something-else

You can map it in the Routes.php file as:

[App/Config/Routes.php]

<?php 

...    
    public static $views = [
        ...
        'main' => [
            'product/edit/{id}/{other}' => ['use' => 'Product'], 
            ...
        ]
    ];
}

With this you will recieve the id and other parameters inside the HttpRequest object in a controller method. See controllers for learning more about it.

Routing: Options

You can define some extra options for a route. For this you only need to add the require array with the options you need. At the moment the following options are supported:

login Defines if the route requires a valid session to be accessed. You can define either true/false to verify the session.
csrf Defines if the route requires a valid CSRF token to be accessed. You can define either of the request methods to verify (get, post, and/or delete).

Here is an example using routing options. The first route will ignore a valid session even if it’s contained in the Application Admin Space (which defines a login required by default). The second route will validate the CSRF token only if it is accessed through a POST or DELETE request method. The third route will verify the CSRF token for all requests and a valid session:

[App/Config/Routes.php]

<?php 

...    
    public static $views = [
        ...
        'admin' => [
            'product' => ['use' => 'Product', 'require' => ['login' => false]], 
            'cart' => ['use' => 'Cart', 'require' => ['csrf' => ['post', 'delete']]], 
            ...
        ],
        'main' => [
            'special-contact' => ['use' => 'Contact', 'require' => ['login', 'csrf']]
        ]
    ];
}

Routing: Custom Requests

Sometimes you will want to reuse custom Request classes. In this case, you need to add the request parameter with the name of the Request class you require. Here is an example:

[App/Config/Routes.php]

<?php 

...    
    public static $views = [
        ...
        'main' => [
            'special' => ['use' => 'Product', 'request' => 'SearchRequest'], 
            ...
        ]
    ];
}

Routing: Overriding Methods

By default the framework will try to execute a method which matches the path in the route. You can override this feature by defining your controller as follows:

[App/Config/Routes.php]

<?php 

...    
    public static $views = [
        ...
        'main' => [
            'special' => ['use' => 'Product@index'], 
            ...
        ]
    ];
}

In the previous example the url: http://my_url/special will load the Product controller and execute the index method, either getIndex or postIndex depending on the request method to your server. See Protocol Restriction for more details.

Routing: API-Only Mode

You can also leave the routes empty to get an HTTP 403 response. This is useful when you want to use the framework only as an API, without any public web access:

[App/Config/Routes.php]

<?php 

namespace App\Config;

final class Routes {
    
    public static $views = [
        'main' => [],
        'admin' => []
    ];
}

Routing: YAML/JSON Definition

Besides defining your application routes with the native PHP arrays, you can use a YAML or JSON file for an easier and simplier way to define your routes.

Once you finish the definition of your routes file (App/Config/routes.yml or App/Config/routes.json), use the routes command to update your Routes.php file automatically. This command receives an optional argument {format} with the file format you want to use, either yml or json. For more information on how to use commands check the Console section.

Terminal mode:

$ php vendor/bin/nwf routes update [format]

Web mode:

http://my_url/console/routes/update/{format}

For the following example:

[App/Config/Routes.php]

<?php 

...    
    public static $views = [
        ...
        'admin' => [
            'product' => ['use' => 'Product', 'require' => ['login' => false]], 
            'cart' => ['use' => 'Cart', 'require' => ['csrf' => ['post', 'delete']]], 
            ...
        ],
        'main' => [
            'special-contact' => ['use' => 'Contact', 'require' => ['login', 'csrf']]
        ]
    ];
}

the YAML version definition is:

[App/Config/routes.yml]

admin:
    product: 
        use: Product
        require:
            login: false
    cart:
        use: Cart
        require:
            csrf:
                post: true
                delete: true

main:
    special-contact:
        use: Contact
        require:
            login: true
            csrf: true

and the JSON version definition is as follows:

[App/Config/routes.json]

{
    "admin": {
        "product": {
            "use": "Product",
            "require": {
                "login": false
            }
        },
        "cart": {
            "use": "Cart",
            "require": {
                "csrf": {
                    "post": true,
                    "delete": true
                }
            }
        }
    },
    "main": {
        "special-contact": {
            "use": "Contact",
            "require": {
                "login": true,
                "csrf": true
            }
        }
    }
}

3. Controllers

Controller classes describe the functionality of your web application. Each controller can be called by any route or be created and executed in runtime.

Controllers: Definition

All controllers inherit from the Niuware WebFramework core class Controller and must be placed in the App/Controllers directory. The name of the file and the class name must match as well. A controller class file must exist inside the namespace App\Controllers. Here is an example of how it should look like:

[App/Controllers/MyController.php]

<?php 

namespace App\Controllers;
    
use Niuware\WebFramework\Application\Controller;

final class MyController extends Controller {

    ...
}

For the application Admin space, the controller class files should be in the Controllers/Admin subdirectory and use the App\Controllers\Admin namespace:

[App/Controllers/Admin/MyAdminController.php]

<?php 

namespace App\Controllers\Admin;
    
use Niuware\WebFramework\Application\Controller;

final class MyAdminController extends Controller {

    ...
}

For other application spaces, the controllers class files should be located in the Controllers/NameOfSpace subdirectory and use the App\Controllers\NameOfSpace namespace. For example:

[App/Controllers/NameOfSpace/MyController.php]

<?php 

namespace App\Controllers\NameOfSpace;
    
use Niuware\WebFramework\Application\Controller;

final class MyController extends Controller {

    ...
}

Controllers: Calls

Controllers are there for listening to the routes you defined. There is no need to create a controller class for each different path because each path will answer to a method with its corresponding name. For example, suppose you have this path:

http://my_url/my-cart

And its route is defined like this:

[App/Config/Routes.php]

<?php
...

'my-cart' => ['use' => Cart]

...

then the controller like this:

[App/Controllers/Cart.php]

<?php 

namespace App\Controllers;
    
use Niuware\WebFramework\Application\Controller;

final class Cart extends Controller {

}

Notice that Cart was defined in the Routes.php file as the controller who will listen to the path my-cart. Also notice that the controller class has the name Cart.php.

Now the Cart controller class will be called when a user access this path, but nothing will happen. We are still missing to define the method that will be executed. This is as simple as adding a public method with the same name as the path, in this case:

[App/Controllers/Cart.php]

<?php 

namespace App\Controllers;
    
use Niuware\WebFramework\Application\Controller;
use Niuware\WebFramework\Http\HttpRequest;

final class Cart extends Controller {

    public function myCart(HttpRequest $request) {

    }
}

Notice the method name can use camelBack or CamelCase naming convention without problems. If your path uses hyphen [ - ] or underscore [ _ ], you should remove this characters from the method name (even in PHP you can use underscore to define methods, the framework will ignore them).

For example for the path: my-cart or my_cart a method named myCart() or MyCart() can be executed.

Controllers: Protocol Restriction

It is easy to restrict the HTTP protocol that a Controller class can accept. For the previous example our method myCart would allow GET and POST protocol to execute the call; but if we want to restrict this, is as easy as adding the get or post prefix to our method. For example:

[App/Controllers/Cart.php]

<?php 

namespace App\Controllers;
    
use Niuware\WebFramework\Application\Controller;
use Niuware\WebFramework\Http\HttpRequest;

final class Cart extends Controller {

    // Executed when the server receives a GET request
    public function getMyCart(HttpRequest $request) {

    }

    // Executed when the server receives a POST request
    public function postMyCart(HttpRequest $request) {

    }

    // Executed for any request (GET or POST)
    public function myCart(HttpRequest $request) {

    }
}

Notice that if you cannot use an any-protocol method combined with a GET/POST protocol method at the same time as the latter ones have execution priority.

Requests other than GET, POST and DELETE will render an HTTP 405 Method Not Allowed error.

Controllers: GET Protocol Methods

The request parameters for a GET protocol method can be placed as part of the url, split by slashes as the following example:

http://my_url/my-cart/param_0_value/param_1_value/ …

The GET protocol method will recieve the values in the HttpRequest object $request with the names you defined in the Routes.php file. For example if the route is:

[App/Config/Routes.php]

<?php
...

'my-cart/{cartName}/{user}' => ['use' => Cart]

...

Then you can access those values as follows:

<?php 

...

    public function getMyCart(HttpRequest $request) {

        $request->cartName = param_0_value;
        $request->user = param_1_value;
    }
...

You can also receive GET request parameters as a query string, for example:

http://my_url/my-cart/?param0=value0&param1=value1

and your GET protocol method will recieve the parameters values in an HttpRequest object as follows:

<?php 

...

    public function getMyCart(HttpRequest $request) {

        $request->param0 = value0;
        $request->param1 = value1;
    }
...

If by some reason you want to combine both ways of receiving request parameters as this:

http://my_url/my-cart/param0_value/param1_value/?param2=value2&param3=value3

using the previous route example, then your GET protocol method will recieve the parameters as:

<?php 

...

    public function getMyCart(HttpRequest $request) {

        // From the URL
        $request->cartName = param0;
        $request->user = param1;

        // From the query string
        $request->param2 = value2;
        $request->param3 = value3;
    }
...

Controllers: POST Protocol Methods

The request parameters for a POST protocol method can be placed as part of the url just as the GET Protocol methods:

http://my_url/my-cart/param_0_value/param_1_value/ …

[App/Config/Routes.php]

<?php
...

'my-cart/{cartName}/{user}' => ['use' => Cart]

...

The POST protocol method will recieve the values in an HttpRequest object $request as:

<?php 

...

    public function postMyCart(HttpRequest $request) {

        $request->cartName = param_0_value;
        $request->user = param_1_value;
    }
...

You can also receive POST request parameters as a usual POST request, for example data in an HTML form. The POST protocol will receive the parameters as an HttpRequest object:

<form method="POST" action="http://my_url/my-cart/">
    <input type="text" name="form_elem_name_0" value="value0" />
    <input type="text" name="form_elem_name_2" value="value1" />
</form>
<?php 

...

    public function postMyCart(HttpRequest $request) {

        // From the query string
        $request->form_elem_name_0 = value0;
        $request->form_elem_name_1 = value1;
    }
...

Although DELETE requests are accepted it is reserved for being used by API classes. By default, a DELETE request method will only process request parameters in JSON format. If you want to use a DELETE request method, remember to send your data as a JSON.

Controllers: Request Attributes

To verify if the request has attributes you can use the has method as follows:

<?php 

...

    public function postMyCart(HttpRequest $request) {

        // Verify if access_token and option POST parameters exist and have 
        // a valid value
        if ($request->has(['access_token', 'option'])) {

            // do something
        }

        // Verifies if access_token and option POST parameters exist and have
        // a value including empty string as a valid value
        if ($request->has(['access_token', 'option'], true)) {

            // do something
        }

        // You can use the above method with a single parameter as well
        if ($request->has('access_token')) {

            // do something
        }
    }

For verifying attached files, go to the Files section.

Controllers: Recycling

Sometimes the functionality of one method in a Controller class can be reused after completing some other processing in the current called method. This option is very useful in the following scenarios:

  1. When you want to use the same view template for different data sources
  2. When you want to use the same view template for different paths
  3. When you want to redirect one path to another controller without reloading the browser

For this is as easy as instance an object of the Controller class you want.

[App/Controllers/Cart.php]

<?php 

namespace App\Controllers;
    
use Niuware\WebFramework\Application\Controller;
use Niuware\WebFramework\Http\HttpRequest;

final class Cart extends Controller {

    public function getMyCart(HttpRequest $request) {

        // Do something here

        $otherController = new OtherController();

        // Additionally set controller options like
        // the view file name. For example:
        $otherController->view = "other.twig";

        return $otherController->getOtherMethod($request);
    }
}

If you want to redirect the browser, call the render method with the name of the path:

[App/Controllers/Cart.php]

<?php 

namespace App\Controllers;
    
use Niuware\WebFramework\Application\Controller;
use Niuware\WebFramework\Http\HttpRequest;

final class Cart extends Controller {

    public function getMyCart(HttpRequest $request) {

        return $this->render('path');
    }
}

Controllers: With JSON Response

A Controller can also render a JSON response (like an API class) instead of a view. For this, just use the core Response class as the following example:

[App/Controllers/Cart.php]

<?php 

namespace App\Controllers;
    
use Niuware\WebFramework\Application\Controller;
use Niuware\WebFramework\Http\HttpRequest;
use Niuware\WebFramework\Http\Response;

final class Cart extends Controller {

    public function getMyCart(HttpRequest $request) {

        $response = new Response();

        $response->something = "value";

        return $response;
    }
}

The response will be something like this:

{
    "error" : false,
    "data" : {
        "something" : "value"
    }
}

4. Models

Models are the way to connect a datasource with a Controller (and a View). Niuware WebFramework integrates Illuminate’s Database module for this part of the framework.

Models: Definition

All models inherit from the Illuminate\Database\Eloquent class Model and must be placed in the App/models directory. The model class file must exist inside the namespace App\Models. Here is an example of how it should look like:

[App/Models/Product.php]

<?php

namespace App\Models;
    
use Illuminate\Database\Eloquent\Model as Eloquent;

class Product extends Eloquent {
    
}

Models: Eloquent

To learn more on how to define and use models using Eloquen please visit the Laravel documentation.

5. Views

The view holds the template where all the controller data will be displayed.

Views: Definition

All views must be placed in the public/views/route-path directory and their file must be defined with the extension .twig. For the case of application spaces and application admin space views, the files should be inside the public/views/spaceName/route-path subdirectory. The content of the views use Twig syntax, for more information visit the Twig documentation.

By default, the framework will load a view filename that matches the current loaded path. For example for the next URLs:

http://my_url/cart http://my_url/cart/edit/{id}

the framework will try to load the following view files:

public/views/cart/index.twig
public/views/cart/edit.twig

You can change the name of the view filename to load by setting the attribute view as shown in section Views: Template Attributes.

For the application Admin space, all views filenames should be in the views/admin/route-path subdirectory. For example for the next URLs:

http://my_url/admin/account
http://my_url/admin/account/edit

public/views/admin/account/index.twig
public/views/admin/account/edit.twig

And the same for other application spaces:

public/views/spaceName/my-path/my-view.twig

Views: Rendering

To render a view template file, you need to tell the controller to do it. This is done by calling the render method. For example for the following URL:

http://my_url/my-cart

we can simply call the render method as this:

[App/Controllers/Cart.php]

<?php 

namespace App\Controllers;
    
use Niuware\WebFramework\Application\Controller;
use Niuware\WebFramework\Http\HttpRequest;

final class Cart extends Controller {

    public function getIndex(HttpRequest $request) {

        // By default it will render the public/views/cart/index.twig file
        return $this->render();
    }

    public function getMyOtherCart(HttpRequest $request) {

        // You can also redirect to another controller adding a valid path 
        // set on the application Routes.php file
        // For more details see the Controllers: Recycling section
        return $this->render('some-other-path');
    }
}

If you want to specify the filename of the view to load, simply set the template attribute as described here.

If you are using PHP as the template renderer change your view template file names from xyz.twig to xyz.php. Also be sure to set ‘php’ as the DEFAULT_RENDERER value in your application settings file.

Views: Main Views

There are 2 main views included out of the box with the framework, which are ready to render all your views.

Name Filename Description
main main.twig
admin/main.twig
Contains HTML used by all views. Defines CSS stylesheet, JS files and other HTML headers meta tags Twig blocks. The main and admin side have their own main vies files.

Then you can use them in your controller view template files as follows:

{% extends 'main.twig' %}

{% block main %}
    
<div>Here goes your view specific content</div>

...

{% endblock %}

If you want to add specific stylesheet, js, etc. to the current view use the already defined Twig blocks:

Block/Var name Usage Description
metas {% block metas %}
meta tags here
{% endblock %}
Adds additional meta tag content to the view template.
title {% set title = 'MyTitle' %} Sets an additional title after the DEFAULT_TITLE.
stylesheets {% block stylesheets %}
css stylesheet files here
{% endblock %}
Adds additional stylesheet files to the view template.
stylesheets {% block scripts %}
script files here
{% endblock %}
Adds additional script files to the view template.

For example:

{% extends 'main.twig' %}

{% block stylesheets %}

<link rel="stylesheet" href="file.css" />

{% endblock %}

{% block scripts %}

<script src="file.js"></script>

{% endblock %}

{% block main %}
    
<div>Here goes your view specific content with the additional stylesheet and script files</div>

...

{% endblock %}

Views: Template Attributes

All Controller classes can set template attributes before rendering the view file. Here is the list of available attributes:

view String (optional) The filename of the view to load.
Default: A filename with the same name as the URL path.

Usage:

[MyController.php]

<?php

final class MyController extends Controller {

    public function getMyPage(HttpRequest $request) {

        $this->view = "my-controller/view_filename.twig";

        ...

        return $this->render();
    }

Output:

Loaded file: public/views/my-controller/view_filename.twig

or when using PHP as renderer:

Loaded file: public/views/my-controller/view_filename.php

Views: View/Controller Binding

You can bind variables from a controller to a view by assigning new properties to the Controller object. For example let’s suppose you need to render some array:

[App/Controllers/MyController.php]

<?php

final class MyController extends Controller {

    public function getMyPage(HttpRequest $request) {

        // Assign the array as an attribute to the controller
        $this->myArray = [ ... ]

        ...

        return $this->render();
    }

Then in your view, you just need to use it as you would expect:

[public/views/my-controller.twig]

...

<ul>
    
    {% for data in myArray %}
        <li>{{ data }}</li>
    {% endfor %}
    
</ul>

...

When using PHP:

[public/views/my-controller.php]

...

<ul>
    <?php
        foreach ($this->myArray as $data => $value) {
    ?>
        <li><?php echo $data; ?></li>
    <?php
        }
    ?>
</ul>

...

Views: Functions and Filters

You can use the TwigFilters.php and TwigFunctions.php classes to define custom functions and filters. For example:

<?php
[App/Helpers/TwigFunctions.php]

namespace App\Helpers;

use Niuware\WebFramework\Application\Helper;

class TwigFunctions {
    
    public function myCustomFunc($params) {

        // Notice that $params is an array 
        // $params[0] = 'something'
        // $params[1] = 'other thing'
        
        return Helper::myHelperFunc($params);
    }
}

And use it in the view as:

[public/views/my-controller/my-view.twig]

...
<div>
    
    {{ myCustomFunc('something', 'other thing') }}
    
</div>

The following is a list of defined functions that are ready to use within your views in the framework:

url url('path', [mode]) Returns a valid route string
The second optional parameter can be either 'main' or 'admin' which correspond to the Routes file.
By default the path will be searched in the 'main' array
csrfToken csrfToken() Returns an input hidden field with the CSRF token

You can use these functions as the following example:

[public/views/my-controller/my-view.twig]

...
<form>
    
    {{ csrfToken() }}
    
    <a href="{{ url('create') }}">Create user</a>
    <a href="{{ url('edit/id') }}">Edit user</a>
</form>

The output will be something like:

<form>
    <input type="hidden" name="csrf_token" value="73aef6s76d7s6bd6ad7" />
    <a href="http://my_url/create">Create user</a>
</form>

6. Sessions

Sessions are very useful for saving data for active users while they use your Web application. The Auth core class helps you manage sessions in a simple way.

Sessions: Authentication

The Auth class can help you verify if a user has successfully logged in to either the Main or Admin application. For this you can use the grantAuth or revokeAuth methods. Usually this methods will be called in the Login controller.

The Niuware WebFramework comes with a default configuration for auto logging a user who navigates to login-protected views as you can see in the following Login controller:

[Controllers/Login.php]

<?php 

namespace App\Controllers;
    
use Niuware\WebFramework\Application\Controller;
use Niuware\WebFramework\Http\HttpRequest;
use Niuware\WebFramework\Auth\Auth;

final class Login extends Controller {

    public function getLogin(HttpRequest $request) {
        
        Auth::grantAuth();
    }
    
    public function getLogout(HttpRequest $request) {
        
        Auth::revokeAuth();
    }
}

You can implement the authentication in any controller you want by using the Auth class as:

<?php 

namespace App\Controllers;
    
use Niuware\WebFramework\Application\Controller;
use Niuware\WebFramework\Http\HttpRequest;
use Niuware\WebFramework\Auth\Auth;

final class MyController extends Controller {

    public function getMyPage(HttpRequest $request) {

        // For main application use:
        Auth::grantAuth();
        // and/or
        Auth::revokeAuth();

        // For admin application use:
        Auth::granthAuth('admin');
        // and/or
        Auth::revokeAuth('admin');
    }

To verify if a user has logged in to your Web application use the following method:

<?php 

namespace App\Controllers;
    
use Niuware\WebFramework\Application\Controller;
use Niuware\WebFramework\Http\HttpRequest;
use Niuware\WebFramework\Auth\Auth;

final class MyController extends Controller {

    public function getMyPage(HttpRequest $request) {

        if (!Auth::verifiedAuth()) {

            // User is not logged in, so we could 
            // redirect to the login page

            $loginController = new Login();

            return $loginController->getLogin();
        }
    }

For verifying the authentication for the Admin application, add 'admin' to the method:

Auth::verifiedAuth('admin');

Sessions: Custom Values

For adding and removing values to the current session, the Auth class contains 4 methods: has, add, get, and remove with simple functionality as shown in the following example:

<?php 

namespace App\Controllers;
    
use Niuware\WebFramework\Application\Controller;
use Niuware\WebFramework\Http\HttpRequest;
use Niuware\WebFramework\Auth\Auth;

final class MyController extends Controller {

    public function getMyPage(HttpRequest $request) {

        // Verify if a session variable exists
        if (Auth::has('myVar')) {

            // Add a session variable
            Auth::add('myVar', 'myValue');
        }

        // $sessionValue = 'myValue'
        $sessionValue = Auth::get('myVar');

        // Remove a session variable
        Auth::remove('myVar');

        // $otherValue = null
        $otherValue = Auth::get('myVar');
    }

For handling custom session variables for the application Admin space, add to each of the methods an extra parameter with the string 'admin', for example:

Auth::has('myVar', 'admin');

And for other application spaces just use the extra parameter with the string name of the space, for example:

Auth::has('myVar', 'staff');

Sessions: Termination

You can easily destroy all custom values using the Auth class method destroy. If you want to delete all the framework session variables, including authentication, then use the method end.

<?php 

namespace App\Controllers;
    
use Niuware\WebFramework\Application\Controller;
use Niuware\WebFramework\Http\HttpRequest;
use Niuware\WebFramework\Auth\Auth;

final class MyController extends Controller {

    public function getMyPage(HttpRequest $request) {

        // Authentication session variables remain active
        Auth::destroy();

        // User and authentication session variables are destroyed
        Auth::end();
    }

For destroying session variables from the application Admin space or other spaces, add to each of the methods the parameter 'admin', or the name of the space. For example:

Auth::destroy('admin');

Auth::end('admin');

7. Customization

Sometimes you need to have access to share classes and methods all over the Controllers and or Views. For this reason it is very easy to add functionality to the framework by using the Helper class.

Customization: Helper Class

For adding global access functions and constants, add them in the Custom trait with public static modifiers:

[Helpers/Custom.php]

<?php

namespace App\Helpers;

trait Custom {
    
    public static $myCustomVar = 'value';

    public static function myCustomFunc() {

        // Do something
    }
}

Then you can access them in Controller classes as follows:

[App/Controllers/MyController.php]

<?php 

namespace App\Controllers;
    
use Niuware\WebFramework\Application\Controller;
use Niuware\WebFramework\Http\HttpRequest;
use Niuware\WebFramework\Application\Helper;

final class MyController extends Controller {

    public function getMyPage(HttpRequest $request) {

        Helper::myCustomFunc();

        $localVar = Helper::myCustomVar;

        ...
    }

Customization: Definition of Custom Classes

For adding custom helper classes add them in the path Helpers/ within the namespace App\Helpers. Here is a simple example:

[App/Helpers/MyCustomClass.php]

<?php 

namespace App\Helpers;

final class MyCustomClass {

    function __construct() {

    }

    public function someFunc() {

    }

    ...
}

When you want to access your custom class remember to use the namespace App\Helpers:

[App/Controllers/MyController.php]

<?php 

namespace App\Controllers;
    
use Niuware\WebFramework\Application\Controller;
use Niuware\WebFramework\Http\HttpRequest;
use App\Helpers;

final class MyController extends Controller {

    public function getMyPage(HttpRequest $request) {

        $myCustom = new Helpers\MyCustomClass();

        $myCustom->someFunc();

        ...
    }

8. API Classes

Niuware WebFramework can be used to create a RESTful API to build asynchronous Web applications and API services.

API Classes: Definition

API classes should be add in the App/Api directory. Also the classes should exist inside the namespace App\Api and extend from the core class Niuware\WebFramework\Http\ApiResponse. The filename should be in lowercase so your API URL’s remain in lowercase. Here is an example of how it should look like:

[App/Api/MyApi.php]

<?php 

namespace App\Api;

use Niuware\WebFramework\Http\ApiResponse;

final class MyApi extends ApiResponse {

    ...
}

API Classes: Method Syntax

As the application Routing you can create your API URL paths as you need. For example, for the following URL:

http://my_url/api/cart/add_product

you should have a corresponding declaration in a file called cart.php with a class Cart and a case insensitive method name like methodname or MethodName or methodName, etc. (NOT method_name). As stated before, it is not necessary to include “-“ or “_”, in your method name definition even you use this characters in your API URL path.

In this case the class can be defined like the following example:

[App/Api/Cart.php]

<?php 

namespace App\Api;

use Niuware\WebFramework\Http\ApiResponse;

final class Cart extends ApiResponse {

    public function addProduct(HttpRequest $request) {

    }

    // The following declarations will work as well
    public function addproduct(HttpRequest $request) {}
    public function AddProduct(HttpRequest $request) {}

    // The following private method won't be accessed
    private function addProduct(HttpRequest $request) {}
}

Notice that only public methods are accessible to an API call, so you define private methods as they will never be accessed even if the API URL path contains the name of a valid method.

API Classes: Protocol Restriction

Same as the Controller classes, you can define protocol restriction using the prefix get, post or delete with your method. If you omit this prefix, the request will accept API calls via GET, POST and DELETE request methods. All other request methods will render an HTTP 405 Method Not Allowed error.

API Classes: Request Parameters

To recieve parameters from an API call use the HttpRequest $request object for a GET, POST or DELETE request.

GET Request:

http://my_url/api/cart/product/?id=6&token=7458ABDG83

[App/Api/Cart.php]

<?php 

namespace App\Api;

use Niuware\WebFramework\Http\ApiResponse;

final class Cart extends ApiResponse {

    public function getProduct(HttpRequest $request) {

        $request->id = '6';
        $request->token = '7458ABDG83';

        // Get the product details
    }
}

POST Request:

// Using jQuery / Ajax

var requestData = {
    id : 6,
    token : '7458ABDG83'
};

...

$.ajax({
    type: "POST",
    url: "http://my_url/api/cart/product",
    dataType: 'json',
    data: requestData,
    ...
})
Using HTTP native request

POST /api/cart/add_product HTTP/1.1
Host: my_url
Content-Type: application/json
Cache-Control: no-cache

{
	"id": 6, 
	"token": "7458ABDG83"
}
[App/Api/Cart.php]

<?php 

namespace App\Api;

use Niuware\WebFramework\Http\ApiResponse;

final class Cart extends ApiResponse {

    public function postProduct(HttpRequest $request) {

        $request->id = '6';
        $request->token = '7458ABDG83';

        // Create or edit product
    }
}

DELETE Request:

// Using jQuery / Ajax

var requestData = {
    id : 6,
    token : '7458ABDG83'
};

...

$.ajax({
    type: "DELETE",
    url: "http://my_url/api/cart/product",
    dataType: 'json',
    data: requestData,
    ...
})
Using HTTP native request

DELETE /api/cart/add_product HTTP/1.1
Host: my_url
Content-Type: application/json
Cache-Control: no-cache

{
	"id": 6, 
	"token": "7458ABDG83"
}
[App/Api/Cart.php]

<?php 

namespace App\Api;

use Niuware\WebFramework\Http\ApiResponse;

final class Cart extends ApiResponse {

    public function deleteProduct(HttpRequest $request) {

        $request->id = '6';
        $request->token = '7458ABDG83';

        // Delete the product
    }
}

A DELETE request will only accept request parameters in JSON format, in other words, it will only process parameters from an ‘application/json’ CONTENT-TYPE method request. If you are using an HTML form, remember to send a JSON to your DELETE endpoint or use a POST request instead.

API Classes: Response Rendering

An API endpoint will render a response in JSON format. For this you only need to set the data you want to render using the response attribute and finally call the render method as the following example:

[App/Api/Cart.php]

<?php 

namespace App\Api;

use Niuware\WebFramework\Http\ApiResponse;

final class Cart extends ApiResponse {

    public function postAddProduct(HttpRequest $request) {

        $request->id = '6';
        $request->token = '7458ABDG83';

        $this->response->error = false;
        $this->response->access_token = "7458ABDG83";
        $this->response->other_var = "other value";

        // Or bulk add.
        // If the second parameter is true, clears all previous
        // set attributes (the attribute 'error' remains unaffected)
        $this->response->add([
            'access_token' => "7458ABDG83",
            'other_var' => "other value"
        ], true);

        return $this->render();
    }
}

The output will be something like this:

{
    "error" : false,
    "data" : {
        "access_token" : "7458ABDG83",
        "other_var" : "other value"
    }
}

API Classes: Multiple Version Support

The framework supports multiple versions for your API. You just need to add the version pattern as v#.#.# to the URL and add the API classes inside a directory corresponding to the version.

For example if you access:

http://my_url/api/cart/product

the framework will load the default class version which should be found in App/Api/Cart and execute the method product. On the contrary, if you access:

http://my_url/api/v2.1.0/cart/product

then the framework will try to load the class version found in the subdirectory v2.1.0 -> V210: App/Api/V210/Cart and execute the method product.

Notice that there is no fallback to the default version, so if the looked up version is not found an API Not found class error code will be rendered instead.

9. Security

The core includes 3 simple methods to manage string hashing.

Security: Passwords

Use the methods hash and verifyHash from the Security core class to create and verify password strings.

<?php 

use Niuware\WebFramework\Auth\Security;

final class MyClass {

    public function someMethod() {

        $savedPassword = Security::hash($newPassword);

        ...

        if (Security::verifyHash($inputPassword, $savedPassword)) {

            // Password is correct
        }
        else {

            // Password is incorrect
        }
    }
}

Security: Tokens

Use the method generateToken from the Security core class to generate securily cryptographic token strings.

<?php 

use Niuware\WebFramework\Auth\Security;

final class MyClass {

    public function someMethod() {

        $token = Security::generateToken();
    }
}

Security: CSRF Token Form Validation

In your form, use the csrfToken function to create the hidden field which contains the CSRF token.

<form>
{{ csrfToken() }}
</form>

The output will be:

<form>
    <input type="hidden" name="csrf_token" value="token_will_be_here" />
</form>

You can set the route for automatically validating the CSRF token by defining the csrf value in the require array for your routes:

[App/Config/Routes.php]

...

            // Login and CSRF validation required
            'my-form' => ['use' => 'Cart', 'require' => ['csrf']],
}

If you send a request with an invalid CSRF Token to a CSRF protected route, then the framework will render an HTTP 403 response.

Note that by default, all POST and DELETE requests within the Application Admin space will be CSRF validated. If you additionally need a CSRF validation for GET requests in this applicacion space, add the require => ['csrf'] attribute to the route.

If you want to implement the validation manually within your controller, you can either use the hasValidCsrf method of the HttpRequest core class which validated the application CSRF token with the recieved csrf_token parameter (for example when using the previos csrfToken function in your Twig template):

[App/Controllers/MyController.php]

<?php 

namespace App\Controllers;
    
use Niuware\WebFramework\Application\Controller;
use Niuware\WebFramework\Http\HttpRequest;
use Niuware\WebFramework\Auth\Security;

final class MyController extends Controller {

    public function getMyPage(HttpRequest $request) {

        if ($request->hasValidCsrf()) {

            // do something
        }
    }

or use the verifyCsrfToken method of the Security core class, where you can pass any parameter to validate with the application CSRF token:

[App/Controllers/MyController.php]

<?php 

namespace App\Controllers;
    
use Niuware\WebFramework\Application\Controller;
use Niuware\WebFramework\Http\HttpRequest;
use Niuware\WebFramework\Auth\Security;

final class MyController extends Controller {

    public function getMyPage(HttpRequest $request) {

        if (Security::verifyCsrfToken($request->csrf_token)) {

            // do something
        }
    }

10. Requests

By default each controller method recieves the request in an Niuware\WebFramework\Http\HttpRequest object, but you can define your own Request classes and its independent validation rules.

Requests: Definition

All requests inherit from the Niuwre WebFramework core class Request and implement the RequestInterface. A request class file must exist inside the namespace App\Requests. If you are inside a subspace then you will need to append the correct namespace path. For example for the application Admin space the request class files shoudl be in the Requests/Admin subdirectory and use the `App\Requests\Admin namespace:

[App/Requests/MyRequest.php]

<?php 

namespace App\Requests;
    
use Niuware\WebFramework\Http\Request;
use Niuware\WebFramework\Http\RequestInterface;

final class MyRequest extends Request implements RequestInterface {

    function __construct(array $params, $method = "") {
        parent::__construct($params, $method);
    }
    
    public function rules() {
        
        return [];
    }
    
    public function validate() {
        parent::validateWith($this->rules());
    }

Requests: Validation

You can add validation rules for your custom request as follows:

[App/Requests/MyRequest.php]

<?php 

namespace App\Requests;
    
use Niuware\WebFramework\Http\Request;
use Niuware\WebFramework\Http\RequestInterface;

final class MyRequest extends Request implements RequestInterface {

    ...
    
    public function rules() {
        
        return [
            // Rules for GET request method
            'get' => [
                'fieldName' => [
                    'rule|parameter' => 'Error message string'
                ],
                'otherFieldName' => [
                    ...
                ]
            ],
            // Rules for POST request method
            'post' => [
                'fieldName' => [
                    'rule|parameter' => 'Error message string'
                ],
                ...
            ],
            // Rules for DELETE request method
            'delete' => [
                'fieldName' => [
                    'rule|parameter' => 'Error message string'
                ],
                ...
            ]
        ];
    }
    
    ...

As you may notice, the rules can be set independently for each Request Method (GET, POST or DELETE). The current valid rules are:

Rule Parameters Description
required boolean (optional) Sets the field as required in the request. If the parameter is true, the field will be considered as valid if the request contains it even its value is empty.
pattern string Sets a pattern to take for validating the field. The pattern string is defined in the parameter.
numeric - Validates if the field is numeric.
minlength number Sets a minimum string length for the field.
maxlength number Sets a maximum string length for the field.

When you use a custom Request class in your controller the validation will be executed during the request and you can verify its result using the isValid or getErrors methods as in the following example:

[App/Controllers/MyController.php]

<?php 

namespace App\Controllers;
    
use Niuware\WebFramework\Application\Controller;

use App\Requests\MyRequest

final class MyController extends Controller {

    public function getMyPage(MyRequest $request) {

        $valid = $request->validation()->isValid();
        $errors = $request->validation()->getErrors();

        $firstError = $request->validation()->getFirstError();
        $lastError = $request->validation()->getLastError();
        ... 

        return $this->render();
    }

Requests: Mutation

A request validation ensures the user has sent valid data to your application, but the ability to automtically mutate this data helps you optmize your controller code. For example let’s suppose you want to cast a variable to a certain type, or execute a function over the value, in this case you can add mutable rules to your Request class. The current available mutable rules are:

Rule Parameters Description
default string (optional) Adds the field with the default value if it does not exist otherwise mutates the value if it is different from the parameter string value. The string can be a comma separated array of values.
cast - Casts the field as a given valid type: bool, int, double, object, string, or array.
callback boolean (optional) Executes a PHP or global valid function over the field. If the parameters is true, the function mutates the value by reference.

In the following example the field search will be trimmed, and then cast to an integer type. The order field will be added to the request if does not exist with a value of ASC. It also will be assigned de ASC value if it has a different value from DESC. Finally the third field orderBy will have the default value name if its value is different from id, name or date, if it does not exist in the request, orderBy will be equal to name as well.

[App/Requests/MyRequest.php]

<?php 

namespace App\Requests;
    
use Niuware\WebFramework\Http\Request;
use Niuware\WebFramework\Http\RequestInterface;

final class SearchRequest extends Request implements RequestInterface {

    ...
    
    public function rules() {
        
        return [
            // Rules for GET request method
            'get' => [
                'search' => [
                    'callback' => 'trim',
                    'cast' => 'int'
                ],
                'order' => [
                    'default|DESC' => 'ASC'
                ],
                'orderBy' => [
                    'default|id,name,date' => 'name'
                ]
            ]
        ];
    }
    
    ...

Finally you can use your request in any controller method as:

[App/Controllers/MyController.php]

<?php 

namespace App\Controllers;
    
use Niuware\WebFramework\Application\Controller;

use App\Requests\MyRequest

final class MyController extends Controller {

    public function getMyPage(SearchRequest $request) {

        if ($request->validation()->isValid()) {

            // $search is a trimmed string cast to an integer type
            $search = $request->search;

            // $order is either 'ASC' or 'DESC'. By default will be 'ASC'
            $order = $request->order;
        }

        return $this->render();
    }

11. Files

It’s very easy to get files from a POST request using the HttpRequest parameter. To get an uploaded file and move it to a directory use the following example:

POST Request:

<!-- Using an HTML From -->
<form method="post" action="mypage">
    {{ csrfToken() }}
    <input type="file" name="myfile" />
</form>
// Using jQuery / Ajax

var form = new FormData();
form.append("myfile", "somefile.ext");

$.ajax({
    type: "POST",
    async : true,
    url: "http://my_url/my-page",
    mimeType: 'multipart/form-data',
    contentType : false,
    processData : false,
    headers : { "cache-control" : "no-cache" }
    data: form,
    ...
})
Using HTTP native request

POST /api/media/upload HTTP/1.1
Host: my_url
Cache-Control: no-cache
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW

------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="myfile"; filename=""
Content-Type: 


------WebKitFormBoundary7MA4YWxkTrZu0gW--

Controller:

[App/Controllers/MyController.php]

<?php 

namespace App\Controllers;
    
use Niuware\WebFramework\Application\Controller;
use Niuware\WebFramework\Http\HttpRequest;
use Niuware\WebFramework\Auth\Security;
use Niuware\WebFramework\Exception\FrameworkException;

final class MyController extends Controller {

    public function getMyPage(HttpRequest $request) {

        // When verifying a CSRF Token
        //if (Security::verifyCsrfToken($request->csrf_token)) {
        //}

        if ($request->hasFile('myfile')) {

            // Use one of the following options to save a file
            try {
                // Option 1
                // Upload the file with default options
                $file = $request->getFile('myfile')->save();

                // Option 2
                // Renaming the file
                // Notice no extension is needed
                $request->getFile('myfile')->save('newName');

                // Option 3
                // Renaming the file to a unique random 32 lenght filename
                $request->getFile('myfile')->save('unique');

                // Option 4
                // Changing the save path
                $request->getFile('myfile')->save('', 'my/new/path');

                // Option 5
                // Renaming the file and changing the save path
                $request->getFile('myfile')->save('newName', 'my/new/path');

                // Option 6
                // By default a MIME type directory will be appended to the path
                // If the file is an image then the file path will be:
                // my/new/path/image
                // You can remove this setting the third argument as false
                $request->getFile('myfile')->save('newName', 'my/new/path', false);

                // Option 7
                // Add the fourth parameter to overwrite the file if exists
                // By default if the file exists the framework will append a 
                // timestamp to the file name
                $request->getFile('myfile')->save('newName', 'my/new/path', false, true);

                // Option 8
                // Add the fifth parameter to restrict the file extensions for 
                // the uploaded file. This will throw an exception if the file  
                // extension is not present in the provided array
                $request->getFile('myfile')->save('newName', 'my/new/path', false, false, ['jpg', 'png', 'gif']);
            }
            catch FrameworkException $exception {

                // File path access denied or extension not allowed
                throw $exception;
            }
        }

        ... 

        return $this->render();
    }

Files: Attributes

The return value for the save method is an Niuware\WebFramework\Http\File object when succeed or null if there was an error uploading the file (no file in the request or fail to moving the file from the temporary directory to the specified destination). It will throw a FrameworkException if there was an error creating the path to save the file (for example, access denied) or the extension is not contained in the allowed extensions array.

You can retrieve the following attributes from the returned Niuware\WebFramework\Http\File instance:

[App/Controllers/MyController.php]

<?php 

namespace App\Controllers;
    
use Niuware\WebFramework\Application\Controller;
use Niuware\WebFramework\Http\HttpRequest;

final class MyController extends Controller {

    public function getMyPage(HttpRequest $request) {

        if ($request->hasFile('myfile')) {

            // Upload the file with default options
            $file = $request->getFile('myfile')->save();

            $fileName = $file->filename;
            $fileExtension = $file->extension; // As provided in the file name
            $fileSize = $file->size;
            $fileType = $file->filetype; // Real MIME Content-Type
            $filePath = $file->filepath;
            $fileNameAndPath = $file->filenameAndPath;
            $fileUrl = $file->public_url; // may be empty if the path is not public

            // Or you can have the following case as well

            if (($fileName = $request->getFile('myfile')->save('', 'public/assets/other/')->filename) !== null) {

                // save the $filename string somewhere
            }
        }

        ... 

        return $this->render();
    }

In the previous example the name for the file will be the same as the uploaded one (if the file exists, a timestamp will be appended to the original name of the uploaded file).

The path will be automatically selected checking the MIME type (only image, video, audio; other MIME types will be uploaded to the ‘public/assets/other’ directory). For example an image file will be uploaded to public/assets/image by default. You can change the name and path using the parameters for the move method as move(filename, path).

12. Console

You can use the framework console to execute commands such as migratinos. To access it just go to the terminal and type:

~$ php vendor/bin/nwf {command} [command_args]

or if you enabled the web mode, go to your browser and type:

http://my_url/console/{command}/{command_args}

You have to enable the console in your Settings.php file configuration. The following are the valid values for the console configuration:

Option Description
terminal Enables the use of the console using the terminal command nwf.
For example: ~$ php vendor/bin/nwf migrations rollback -d XXXXXXXX
web Enables the use of the console using a web browser through the console path.
For example: http://my_url/console/migrations/rollback/-d/XXXXXXXX
enabled Enables the use of the console using either the termianl of the web browser.
disabled Disables the use of the console.

13. Database Migrations

Use the power of database migration definitions to have a robust way to enhance your web application. Migrations are integrated into Niuware WebFramework using Phinx. Notice not all Phinx functionality is available through the Niuware WebFramework console.

Database Migrations: Migration definitions

To create a migration file use the command create:

Terminal mode:

$ php vendor/bin/nwf migrations create

Web mode:

http://my_url/console/migrations/create

This will create a new migration class in the App/Migrations/Migrations directory as MigrationVersion_vTimestamp.php. Notice the MigrationVersion part of the file as you can use this number for targetting commands suchs as migrate and rollback. For example:

[App/Migrations/20170605063432_v1496644472.php]

<?php

use Niuware\WebFramework\Database\Migration;
use Illuminate\Database\Schema\Blueprint;

class V1496644472 extends Migration
{
    /**
     * Illuminate\Database\Schema\Builder $schema
     * Use the $schema object to execute your migration queries
     *
     * Created on Y/m/d h:i:s
     * Migration comments:
     * 
     */
    
    public function up()
    {
        
    }
    
    public function down()
    {
        
    }
}

Then use Eloquent (Blueprint class) to create your definition, for example:

[App/Migrations/20170605063432_v1496644472.php]

<?php

use Niuware\WebFramework\Database\Migration;
use Illuminate\Database\Schema\Blueprint;

class V1496644472 extends Migration
{
    /**
     * Illuminate\Database\Schema\Builder $schema
     * Use the $schema object to execute your migration queries
     *
     * Created on Y/m/d h:i:s
     * Migration comments:
     * 
     */
    
    public function up()
    {
        $this->schema->create('sources', function (Blueprint $table) {
            
            $table->increments('id');
            $table->string('source', 45);
        });
        
        $this->schema->create('users', function (Blueprint $table) {
            
            $table->bigIncrements('id');
            $table->integer('source_id')->unsigned();
            $table->timestamps();
            $table->string('account_id', 100);
            $table->boolean('is_valid');
            
            $table->foreign('source_id')->references('id')->on('sources');
        });

    public function down()
    {
        
    }
}

Then run the migrations with the command migrate:

Terminal mode:

$ php vendor/bin/nwf migrations migrate -t [MigrationVersion]

Web mode:

http://my_url/console/migrations/migrate/-t/MigrationVersion

Notice that if you do not add the target for the migration (Migration class name), all migrations that haven’t been run will be executed.

For more information on Eloquent syntax for migrations visit the documentation for:
Tables
Columns
Indexes

Notice that the previous documentation has an static access to the Schema class Schema::method, whilst in Niuware WebFramework the access is through an instance as $this->schema->method.

Database Migrations: Rollback

If you want to rollback use the command rollback:

Terminal mode:

$ php vendor/bin/nwf migrations rollback [-t TargetMigrationVersion] $ php vendor/bin/nwf migrations rollback [-d RollbackToDate]

Web mode:

http://my_url/console/migrations/rollback/-t/TargetMigrationVersion http://my_url/console/migrations/rollback/-d/RollbackToDate

For more information on how to use the rollback -t and -d commands, visit the Phinx documentation.

Database Migrations: Seeding

To create a seeding file use the command seedcreate:

Terminal mode:

$ php vendor/bin/nwf migrations seedcreate [NameOfSeedClass]

Web mode:

http://my_url/console/migrations/seedcreate/NameOfSeedClass

This will create a new seeding class in the App/Migrations/Seeds directory. For example:

<?php

use Phinx\Seed\AbstractSeed;

class NameOfSeedClass extends AbstractSeed
{
    /**
     * Run Method.
     *
     * Write your database seeder using this method.
     *
     * More information on writing seeders is available here:
     * http://docs.phinx.org/en/latest/seeding.html
     */
    public function run()
    {

    }
}

Then use Phinx syntax to create your definition, for example:

<?php

use Phinx\Seed\AbstractSeed;

class NameOfSeedClass extends AbstractSeed
{
    /**
     * Run Method.
     *
     * Write your database seeder using this method.
     *
     * More information on writing seeders is available here:
     * http://docs.phinx.org/en/latest/seeding.html
     */
    public function run()
    {
        $sourcesData = [
            ['source' => 'Service A'],
            ['source' => 'Service B'],
            ['source' => 'Service C'],
            ['source' => 'Service D']
        ];
        
        $sources = $this->table('sources');
        $sources->insert($sourcesData)->save();
    }
}

For more information on the Phynx syntax for seed definitions visit the documentation

Then run the seed with the command seedrun:

Terminal mode:

$ php vendor/bin/nwf migrations seedrun -s [NameOfSeedClass]

Web mode:

http://my_url/console/migrations/seedrun/-s/NameOfSeedClass

Notice that if you do not add the name of the seed class name, all seed files will be run. Be careful as seeds do not look up for repeated data, so if you run all seeds twice, data will be duplicated.

Database Migrations: Status

You can output the migrations status using the command status

Terminal mode:

$ php vendor/bin/nwf migrations status

Web mode:

http://my_url/console/migrations/status

Database Migrations: Custom Connection

You can add the parameter conn={connection_name} to use any of the connections defined in your application Settings.php file. For example, for migrating your database using a development connection you can use:

Terminal mode:

$ php vendor/bin/nwf migrations migrate conn=development

Web mode:

http://my_url/console/migrations/migrate/conn=development

14. Pagination

When querying data from your database it is easy to paginate results using the Paginate core class. Here is a basic example of how to use this feature:

First, set the data in your controller class:

[App/Controllers/MyController.php]

<?php 

namespace App\Controllers;
    
use Niuware\WebFramework\Application\Controller;
use Niuware\WebFramework\Http\HttpRequest;
use Niuware\WebFramework\Pagination\Paginate;

use App\Models\Item;

final class MyController extends Controller {

    public function getMyPage(HttpRequest $request) {

        // Let's suppose you have an 'Item' model
        $items = Item::orderBy('name', 'asc')->get();

        $this->paginate = new Paginate();

        // You can optionally customize the number of items per page
        $this->paginate->itemsPerPage = 15

        $this->paginate->paginate($items, $request);

        return $this->render();
    }

In the view, use the method data in the paginate object to display the items por the current page.

[public/views/my-page.twig]

...

<ul>
    
    {% for item in paginate.data %}
        <li>{{ item.name }}</li>
        ...
    {% endfor %}
    
</ul>

For displaying the menu to navigate through pages, use the method render in the paginate object. This method receives 5 optional string parameters which define in order: the Previous button link label, the Next button link label, the class for the <li> tag, the class for the <a> tag and finally the class for the current page (active) <li> tag. The default values are: ‘<‘, ‘>‘, ‘page-item’, ‘page-link’ and ‘active’.

[public/views/my-page.twig]

...


{% if paginate is defined and paginate.shouldRender %}
<nav>
    <ul>
        {{ paginate.render('Prev', 'Next') }}
    </ul>
</nav>

...

For the previous example the HTML output will be something like this:

...

<nav>
    <ul>
        <li class="page-item"><a class="page-link" href="myurl/?p=1">Prev</a></li>
        <li class="page-item active"><a class="page-link" href="myurl/?p=1">1</a></li>
        <li class="page-item"><a class="page-link" href="myurl/?p=2">2</a></li>
        ...
        <li class="page-item"><a class="page-link" href="myurl/?p=2">Next</a></li>
    </ul>
</nav>

Note that if your current URL has query parameters, they will be included safely into the pagination result links.

15. Exceptions

If there is a problem with the configuration of your Controller classes, view template files or other exceptions, the FrameworkException will be thrown and you will see the complete list of all thrown exceptions and errors on the screen. In general it is not needed to throw exceptions but you can throw a FrameworkException in your Controller class as follows:

[App/Controllers/MyController.php]

<?php 

namespace App\Controllers;
    
use Niuware\WebFramework\Application\Controller;
use Niuware\WebFramework\Http\HttpRequest;
use Niuware\WebFramework\FrameworkException;

final class MyController extends Controller {

    public function getMyPage(HttpRequest $request) {

        if ($somethingIsWrong) {

            throw new FrameworkException($message, $error_code);
        }

        return $this->render();
    }

When debug mode is enabled, the trace of the Exception will not be displayed.

In the case of the API classes, you will see only the last error/exception directly in the JSON rendered response.

16. PHP < 7.0 compatibility

The core of Niuware WebFramework is compatible with PHP 5.6+. On the other hand, the default versions for the dependencies Eloquent and Twig are set to use a minimum version of PHP 7.0. If you require to use a version lower than PHP 7.0 you can update the composer file for using aliases on illuminate/database < 5.5.0 and twig/twig < 2.0.0

{
    "require": {
        "niuware/webframework" : "dev-master",
        "illuminate/database": "<5.5.0 as 5.5.x-dev",
        "twig/twig" : "<2.0.0 as 2.x-dev"
    }
}