9: Instance Management

Phlo uses its own instance manager to initialize and reuse objects efficiently and predictably. This system determines when controller code runs, how instances are stored, and how circular references are prevented.

9.1: The basics

When you define a .phlo file, the build phase turns it into a class. Every call to an object via %name goes through the instance manager (phlo() in /phlo/phlo.php).

Example:

prop title = 'Welcome'

route GET home => $this->main

method main => view($this->home)

view home:
<h1>$this->title</h1>

When the route /home is requested:

  1. The instance manager checks whether an instance of this class already exists.
  2. If not, it is created and stored.
  3. After creation, the controller code runs (see §8.2).
  4. Then the requested method is called.

9.2: Controller code

All code in a .phlo file that does not belong to route, prop, static, method, function, view, <style> or <script> is controller code. This code runs after instantiation, once the instance fully exists.

Example:

prop ready = false

%session->start()
$this->ready = true

The last two lines are controller code because they sit at top level.

9.3: The role of `__handle()`

Phlo generates a special __handle() method for every class. The instance manager calls it whenever an instance is requested via %name.

__handle():

You never call or override __handle() yourself; it is part of the generated class and the instance manager.

9.4: Lazy initialization

Because controller code runs only after construction, instances can reference each other without triggering unwanted recursive creation.

Example:

a.phlo:

prop message = 'A ready'

b.phlo:

prop message = 'B ready'

main.phlo:

route GET test => $this->show

method show {
  dx(%a->message, %b->message)
}

9.5: The obj base class: powertools

Every compiled class extends obj, and obj is more than __get/__set. These are the tools you reach for when a class needs to behave dynamically.

Interception hooks. Implement objCall, objGet or objSet to trap the access chain. Returning null falls through to the normal behavior; anything non-null short-circuits:

method objGet($key) => $this->cache[$key] ?? null

method objCall($method, ...$args) => str_starts_with($method, 'find') ? $this->finder($method, $args) : null

method objSet($key, $value) => $key === 'id' ? true : null

objGet runs before data/closure/method/prop lookup on every read, objCall on every unknown method call, and objSet before every write (a non-null return swallows the write). This is the mechanism behind decorators, lazy loading and read-only guards.

Bound closures. Assign a closure and it binds to the instance: $obj->greet = fn() => "Hi $this->name", later $obj->greet() runs with $this bound. Handy for per-instance behavior without subclassing.

Data API. objImport(name: 'x', age: 3) bulk-assigns and returns $this (chainable). objKeys(), objValues() and objLength() inspect the data; objClear() wipes it. Iterating an obj (foreach $record AS $key => $value) and json_encode($record) expose exactly the stored data. Every write flips objChanged, the dirty flag the ORM uses to decide whether objSave writes anything.

Computed prop caching. prop x => ... caches on first access; the argument form caches per argument set. The same applies to computed statics, cached per class.

Worker persistence. prop objPers = true makes an instance survive between worker-mode requests: the phlo() registry only keeps objPers instances on its per-request reset. Right for DB connections and parsed config; wrong for anything request- or user-scoped.

Lesson. A plain prop in a parent class SHADOWS a computed prop in a child. prop dir = void in an abstract parent compiles to a real PHP property, so a child's prop dir => guide getter is never consulted: $this->dir silently reads void. When children must override with a computed prop, declare the parent prop computed as well: prop dir => void.

9.6: Best practices

We use essential cookies to make this site work. With your permission we also use analytics to improve the site.