ClanCats Logo

Container

Container File Syntax

Container files are written in a very simple meta language.


Types

The language supports the following scalar types:

  • Strings Single and double quoted.
    'hello' & "world"
  • Numbers float / double, int.
    3.14, 42
  • Booleans
    true and false.
  • Null
    null
  • Arrays list and associative.
    {'A', 'B', 'C'}, {'A': 10, 'B': 20}

Numbers

Container files do not differentiate between different number types because it would be an unnecessary overhead, we forward that job directly to PHP.

42 # Int
42.01 # Float
-42.12345678912345 # Double

That means that also the floating point precision is handled by PHP. All values are interpreted means large doubles might be stored rounded.


Strings

Strings must always be encapsulated with a single ' or double " quote. This serves mainly a comfort purpose when having many quotes inside your string not having to escape them all.

Escaping of special characters works just the usual way.

:say: 'Hello it\'s me!'`

Beloved or Hated emojis will also work just fine.

:snails: '🐌🐌🐌'

Booleans and Null

There is not much to say about them:

:nothing: null
:positive: true
:negative: false

Arrays

It's important to notice that all arrays are internally associative. When defining a simple list the associative key is automatically generated and represents the index of the item.

This means that the array {'A', 'B'} equals {0: 'A', 1: 'B'}.

Arrays can be defined multidimensional:

{
    'title': 'Some catchy title with Star Wars',
    'tags': {'top10', 'movies', 'space'},
    'body': 'Lorem ipsum ...',
    'comments': 
    {
        {
            'text': 'Awesome!',
            'by': 'Some Dude',
        }
    }
}

Parameters

Parameters or configuration values can also be defined inside the container files.

A parameter is always prefixed with a : character.

:database.hostname: "production.db.example.com"
:database.port: 7878
:database.cache: true

Service Definition

A service definition is always named and must be prefixed with a @ character.

# <service name>: <class name>
@log.adapter: FileAdapter

The class name can contain the full namespace.

@log.adapter: Acme\Log\FileAdapter

Constructor

Constructor arguments can be passed after the class name.

@dude: Person("Jeffery Lebowski")

Referenced arguments

Arguments can reference a parameter or service.

:name: 'Jeffery Lebowski'

@dude: Person(:name)
@mysql: MySQLAdapter('localhost', 'root', '')

@repository.posts: Repositories/Post(@mysql)

Method calls

Method calls can be assigned to a service definition.

@jones: Person('Duncan Jones')
@sam: Person('Sam Rockwell')

@movie.moon: Movie('Moon')
  - setDirector(@jones)
  - addCast(@sam)
  - setTags({'Sci-fi', 'Space'})

Service metadata

Metadata can be assigned to every service definition.

Its then possible to fetch the services matching a metadata key.

@controller.auth.sign_in: Controller\Auth\SignInController(@auth)
  = route: {'GET', 'POST'}, '/signin'

The metadata key is always a vector / array so you can add multiple of the same type:

@controller.auth.sign_in: Controller\Auth\SignInController(@auth)
  = route: {'GET', 'POST'}, '/signin'
  = tag: 'users'
  = tag: 'auth'

The elements inside the metadata definition can have named keys:

@app.bootstrap: Bootstrap()
  = on: 'app.start' call: 'onAppStart'

Service Updates

It is possible to update already defined services with more construction calls and metadata. This is quite handy to organize large amount of dependencies with a dynamic lookups.

You could for example define your logger in one file.

@logger.main: Acme\Logger

And add observers using a construction call where you need them.

@logger.observers.email_devs: Acme\EmailLogObserver('[email protected]')
@logger.observers.email_support: Acme\EmailLogObserver('[email protected]')

@logger.main
  - addObserver(@logger.observers.email_devs)
  - addObserver(@logger.observers.email_support)

Imports

Other container files can be imported from the container namespace.

import config
import app/dashboard
import app/user
import app/shop

Overriding

Services and Parameters have been explicit overwritten if they have already been defined.

:ship: 'Star Destroyer'

override :ship: 'X-Wing'