Skip to content

Object Constructors

Imants Horsts edited this page Apr 11, 2017 · 2 revisions

typora-copy-images-to: ./images

This document explains everything you need to know about object creation in Agile Toolkit libraries (Agile UI, Agile Data, DSQL and Agile Core).

Object Lifecycle

Most objects in Agile Toolkit live through 3 cycles:

  • Creation of the object
  • Adding object into Render Tree
  • Rendering object

Steps 2 and 3 can be repeated several times.

Object Creation and constructor patterns

Object creation guidelines wary from library to library in Agile Toolkit. I'll go over all the object categories and look at how they are created:

Components (extend \atk4\ui\View)

use atk4\ui\Button;

$button = new Button();

All constructors will accept the same argument style which is called "Seed". Additional rule is that constructor will not perform any actions apart from setting properties. All components must support ability to set properties directly in a very IDE-friendly way:

use atk4\ui\Button;
use atk4\ui\Icon;

$button = new Button();
$button->content = 'Click Me';
$button->icon = new Icon();
$button->icon->content = 'book';

However we often prefer a more concise format:

$button = new Button('Click Me');
$button->icon = new Icon('book');

"Seed" allow us to specify default properties also:

$button = new Button(['Click Me', 'icon'=> new Icon('book')]);

Finally 'icon' property can also be specified as a "seed" intended for the Icon property:

$button = new Button(['Click Me', 'icon' => 'book']);

IMPORTANT: injected component objects don't need to be in Render Tree.

JavaScript actions (implements jsExpressionable)

Those objects can be converted into JavaScript code. Classes are typically named "jsSomething" and their constructor will typically have different arguments:

$action = new jsReload($crud);

$action = new jsModal($title, $virtualPage);

Actions are rather simple and they require a very specific set of arguments.

Models

All model constructors can be passed persistence object:

$user = new User($db);

When passing model into component, it must already be associated with the database, unless specified otherwise.

Dependency Injection

Some components will compose themselves out of many other objects, for example CRUD relies on Grid, Forms, VirtualPages for most of it's actions. In order to give you flexibility, those objects can be injected:

$crud = new CRUD([
  'formAdd'=>new \atk4\ui\Form([
    'layout'=>new \atk4\ui\FormLayout\Generic()
  ])
]);

By default a CRUD forms will use a multi-column form layouts when model has too many fields, but the above code will use Generic, single-column layout form.

addField (hasOne, hasMany etc)

Those methods follow a principle where the first argument is the name, and the second specified a "seed".

$user->addField('age', ['type'=>'integer']);

add()

This method accepts 2 arguments. The first is a either an object or a "seed". If you specify a seed though, it's "0" key must be the name of the class. The rest of the keys will be shifted and passed into the object.

factory()

This method can be used to initialize object from the "seed". When class is specified by string, it will be looked up inside '\atk4\ui' namespace. If you are defining any classes inside your own namespace, you should simply use the class name:

$crud = $layout->add(['CRUD', 'formEdit'=>new MyForm());

You can configure your App class to resolve objects through other namespaces too. This is useful if you are looking to use add-on that overrides default components.

Other classes

Some classes are on their own:

  • App - will accept string as constructor argument.
  • Persistence - will accept connection string argument
  • DSQL's Query
  • DSQL Expression

Seed Explained

Either no arguments or single array argument, which will be set to properties. Constructor is not allowed to do anything apart from initializing properties.

$form = new Form(['defaultTemplate'=>'blah.html']);

// same as

$form = new Form();
$form->defaultTemplate = 'blah.html';

We make sure that the second-form works mainly for heavy IDE users, however for simple and clean code we tend to use the first, more compact form. Constructor will pass arguments like this:

  • If argument with key 0 is specified, it will be set to "$content" new Button(['Hello']). Exception is when $content is set to false, in which case the value is added as a class: new Form(['small'])
  • If arguments with numeric keys are specified they will be added as class. new Button(['Hello', 'red'])- 'Hello' will be content and 'red' will be added as CSS class
  • If symbolic key is used, but no property with this name is defined, exception will be raised
  • Property is set to value in array unless it's null
  • If property value is array and value is null then it is ignored