Model

A model is a representation of your code, that you either read or create.

Model Overview

There are different types of models available which are explained in this section.

Structured Models

Structured models are composites and can contain other models, these are:

  • PhpClass
  • PhpTrait
  • PhpInterface

Generateable Models

There is only a couple of models available which can be passed to a generator. These are the mentioned structured models + PhpFunction.

Part Models

Structured models can be composed of various members. And functions and methods can itself contain zero to many parameters. All parts are:

  • PhpConstant
  • PhpProperty
  • PhpMethod
  • PhpParameter

Name vs. Namespace vs. Qualified Name ?

There can be a little struggle about the different names, which are name, namespace and qualified name. Every model has a name and generateable models additionally have a namespace and qualified name. The qualified name is a combination of namespace + name. Here is an overview:

Name Tool
Namespace my\cool
Qualified Name my\cool\Tool

Create Models programmatically

You can create models with the provided fluent API. The functionality is demonstrated for a PhpClass but also works accordingly for all the other generateable models.

Create your first Class

Let’s start with a simple example:

<?php
use gossi\codegen\model\PhpClass;

$class = new PhpClass();
$class->setQualifiedName('my\\cool\\Tool');

which will generate an empty:

<?php
namespace my\cool;

class Tool {

}

Adding a Constructor

It’s better to have a constructor, so we add one:

<?php
use gossi\codegen\model\PhpClass;
use gossi\codegen\model\PhpMethod;
use gossi\codegen\model\PhpParameter;

$class = new PhpClass('my\\cool\\Tool');
$class
    ->setMethod(PhpMethod::create('__construct')
        ->addParameter(PhpParameter::create('target')
            ->setType('string')
            ->setDescription('Creates my Tool')
        )
    )
;

you can see the fluent API in action and the snippet above will generate:

<?php
namespace my\cool;

class Tool {

    /**
     *
     * @param $target string Creates my Tool
     */
    public function __construct($target) {
    }
}

Adding members

We’ve just learned how to pass a blank method, the constructor to the class. We can also add properties, constants and of course methods. Let’s do so:

<?php
use gossi\codegen\model\PhpClass;
use gossi\codegen\model\PhpMethod;
use gossi\codegen\model\PhpParameter;
use gossi\codegen\model\PhpProperty;
use gossi\codegen\model\PhpConstant;

$class = PhpClass::create('my\\cool\\Tool')
    ->setMethod(PhpMethod::create('setDriver')
        ->addParameter(PhpParameter::create('driver')
            ->setType('string')
        )
        ->setBody('$this->driver = $driver');
    )
    ->setProperty(PhpProperty::create('driver')
        ->setVisibility('private')
        ->setType('string')
    )
    ->setConstant(new PhpConstant('FOO', 'bar'))
;

will generate:

<?php
namespace my\cool;

class Tool {

    /**
     */
    const FOO = 'bar';

    /**
     * @var string
     */
    private $driver;

    /**
     *
     * @param $driver string
     */
    public function setDriver($driver) {
        $this->driver = $driver;
    }
}

Declare use statements

When you put code inside a method there can be a reference to a class or interface, where you normally put the qualified name into a use statement. So here is how you do it:

<?php
use gossi\codegen\model\PhpClass;
use gossi\codegen\model\PhpMethod;

$class = new PhpClass();
$class
    ->setName('Tool')
    ->setNamespace('my\\cool')
    ->setMethod(PhpMethod::create('__construct')
        ->setBody('$request = Request::createFromGlobals();')
    )
    ->declareUse('Symfony\\Component\\HttpFoundation\\Request')
;

which will create:

<?php
namespace my\cool;

use Symfony\Component\HttpFoundation\Request;

class Tool {

    /**
     */
    public function __construct() {
        $request = Request::createFromGlobals();
    }
}

Much, much more

The API has a lot more to offer and has almost full support for what you would expect to manipulate on each model, of course everything is fluent API.

Create from existing Models

You can also read a model from existing code. Reading from a file is probably the best option here. It will parse the file and fill up the model. Alternatively if you do have the class already loaded you can use reflection to load the model.

From File

Reading from a file is the simplest way to read existing code, just like this:

<?php
use gossi\codegen\model\PhpClass;

$class = PhpClass::fromFile('path/to/MyClass.php');

Through Reflection

If you already have your class loaded, then you can use reflection to load your code:

<?php
use gossi\codegen\model\PhpClass;

$reflection = new \ReflectionClass('MyClass');
$class = PhpClass::fromReflection($reflection->getFileName());

Also reflection is nice, there is a catch to it. You must make sure MyClass is loaded. Also all the requirements (use statements, etc.) are loaded as well, anyway you will get an error when initializing the the reflection object.

Understanding Values

The models PhpConstant, PhpParameter and PhpProperty support values; all of them implement the ValueInterface. Though, there is a difference between values and expressions. Values refer to language primitives (string, int, float, bool and null). Additionally you can set a PhpConstant as value (the lib understands this as a library primitive ;-). If you want more complex control over the output, you can set an expression instead, which will be generated as is.

Some Examples:

<?php
PhpProperty::create('foo')->setValue('hello world.');
// $foo = 'hello world.';

PhpProperty::create('foo')->setValue(300);
// $foo = 300;

PhpProperty::create('foo')->setValue(3.14);
// $foo = 3.14;

PhpProperty::create('foo')->setValue(false);
// $foo = false;

PhpProperty::create('foo')->setValue(null);
// $foo = null;

PhpProperty::create('foo')->setValue(PhpConstant::create('BAR'));
// $foo = BAR;

PhpProperty::create('foo')->setExpression('self::MY_CONST');
// $foo = self::MY_CONST;

PhpProperty::create('foo')->setExpression("['my' => 'array']");
// $foo = ['my' => 'array'];

For retrieving values there is a hasValue() method which returns true whether there is a value or an expression present. To be sure what is present there is also an isExpression() method which you can use as a second check:

<?php

if ($prop->hasValue()) {
    if ($prop->isExpression()) {
        // do something with an expression
    } else {
        // do something with a value
    }
}