Neoan3 Frame

Settings for your project

At the heart of Neoan3's ideology is abstraction. Abstraction empowers creators to hone in on an ongoing issue without having to review thousands of lines of code that has nothing to do with it. Frames allow for global control over the project. Usually when routing in a Controller file, you declare the frame that the component uses. Frames can be chained as well, giving your application to load configuration depending on request type or route. Conceptually, frames fulfill what some other frameworks use middleware architecture for.

How to create a frame

Much like with anything in Neoan3 it's easier to use the neoan3-cli tool. Using the following command will generate a new frame:

neoan3 new frame [frame-name]

How to use a Frame

The new frame will appear in the "frame" folder in the project. Typically the folder will contain a php file with the name that you gave the frame. The file itself will not contain a lot of code in the beginning. With the exception of a single empty class extending Serve. While this seems anti-climactic, what is important is that your frame has now been set up to serve up information to Neoan3.


As an example, let's set up a frame named Test.

        
            namespace Neoan3\Frame;

            use Neoan3\Apps\Ops;
            use Neoan3\Core\Serve;


            class Test extends Serve
            {
                function __construct(Database $db = null)
                {
                    // make sure to run the original constructor
                    parent::__construct();

                    // example: add the header located in component/Header/header.view.html to every route
                    $this->hook('header','header');

                    // example: enable injection of a Database provider.
                    // if no (mock?) provider is injected, the database will use the my_database credentials
                    // and connect via the default DatabaseWrapper
                    $this->assignProvider('db', $db, function(){
                        try{
                            $credentials = getCredentials();
                            if(isset($credentials[$this->dbCredentials])){
                                $this->provider['db'] = new DatabaseWrapper($credentials['my_database']);
                            }
                        } catch (Exception $e) {
                            echo 'No credentials found. Run "neoan3 credentials"';
                        }
                    });
                }

                function constants()
                {
                    return [
                        'base' => [base],
                        'link' => [
                            [
                                'sizes' => '32x32',
                                'type' => 'image/png',
                                'rel' => 'icon',
                                'href' => 'asset/neoan-favicon.png'
                            ]
                        ],
                        'js' => [
                            ['src' => path .'/frame/test/main.js', 'data' => ['base' => base]]
                        ],
                        'meta'       => [
                            ['name' => 'viewport', 'content' => 'width=device-width, initial-scale=1']
                        ],
                        'stylesheet' => [
                            '' . base . 'frame/test/index.css',
                        ]
                    ];
                }
            }
        
    

As you will soon notice, a frame enables you to place global functionality for your project or single routes & endpoints. Don't confuse this concept with middleware. Since it is possible to overwrite core-functionality (e.g. the output function), you can define functionality run both before and after a particular route or endpoint.

Global configuration

Instead of using single Core\Serve method calls to set variables, one can define configuration variables on the frame-level using an associative array of arrays. These arrays are always representations of Core\Serve methods (e.g. 'meta' => Serve->addToHead() ):

js-section

Each array should have "src" and can have "data" and "type". Using "data" will provide possibility to use the template engine to substitute key-value pairs. The result will be rendered into the DOM. Omitting this attribute will lead to an inclusion of the file.

stylesheet-section

Accepts an array of stylesheet locations to be included in every execution of a route-component.

meta-section & link section

Generates meta- or link-tags using the provided key-value combination(s) as attributes.

['name' => 'viewport', 'content' => 'width=device-width, initial-scale=1']

=>

<meta name="viewport" content="width=device-width, initial-scale=1">