Bridge Views: PHP

Creates a bridge between HTML Markup and PHP code, allowing you to connect HTML to complex functions and to a database.

Supports inline PHP that auto-exposes the object as a variable. Supports auto-filling of forms as well as any other HTML. It is intended for extension by frameworks & libraries, but you can use it on an individual site as well.

Notice

This package is poorly documented and needs a significant refactor. I do not recommend using it at this time.

Example

View the full example

A Fresh View:

<div rb-table="note" rb-find="id:<?php echo $id?>">
    <h1 rb-prop="name"></h1>
    <p rb-prop="body" rb-format="markdown"></p>
    <p>My note's name is <?=$note->name?>. See, inline PHP works too!</p>
</div>

The PHP to display it:

$note = new \Fresh\Component($componentDir);
$view = $note->view('Note',['id'=>1]);
echo $view;

yields

<div>
    <h1>The Note's Name</h1>
    <p>The note's body, formatted with CommonMark</p>
    <p>My note's name is The Note's Name. See, inline PHP works too!</p>
</div>

Install

composer require taeluf/fresh-compo

{
    "name":"vendor/a-cool-package",
    "require":{
        "taeluf/fresh-compo": "dev-version_1"
    }
}

This will install dependencies RBDoc and CommonMark

Integrations

Attributes

We handle a few attributes, but you can extend it to handle more. Liaison Fresh Package is a thorough example.

Entity Attributes

To declare an entity to be autoloaded from the database into an HTML view, you must declare these attributes on the html node.

rb-table

The name of the table to load from

rb-find

A simple list of key:value;key2:value2; items which will (generally) be parsed into a key=>value array and used to lookup the items with your custom find. You'll add a find handler to handle lookups, so I guess you can change the format.

Property Attributes

These apply to elements which will hold a property value

rb-prop

The name of the property on the entity. It will be loaded by your find handler.
Most elements will have their innerHTML set to the loaded object's property by the same name. <a> has its href set. <img> it's src.

rb-format

The name of the formatter to use. Currently markdown is built in, thanks to CommonMark

tf-format

Declare tf-format="markdown" on ANY node containing markdown, to convert to HTML. You can implement your own formatter too.

find handler, submit handler

Submitting data sort of automaticallyish

You must still set a submit handler like so:

$myDbObj = get_my_db_instance();
$compo->setSubmitHandler(
    function (string $tableName, array $dataToSave, $itemId) use ($myDbObj){
        $myDbObj->save($tableName,$dataToSave,$itemId);
    }
);

Uploading files

To enable automatic file uploads, call $component->setUpload($storageDir, $urlPrefix). You are responsible for routing that file.
The $urlPrefix is used to prepend the file-url when passing formdata to your submit handler

Routing, Setting things up

Use the setup step to do routing, basically. This requires you to append setup code to views. Here's a simple (bad) example:

$phpCode = '<?php if ($url=='/')echo $this; ?>`
/`$this` refers to the view which is being setup.
$view = $compo->view("Page_Home"); //this points to $compoDir/view/Page_HomeView.php
$view->appendSetupCode($phpCode);

This setup code must be appended pre-compile or inside a compile handler.

Then to execute your setup:

$compo = new \Fresh\Component($name,$componentDir);
$forceRecompilation = true;// good when developing. Bad for production.
$compo->compile($forceRecompilation); //  Defaults to false, if you don't pass a paramater
$passthru = ['url'=> cleanMyUrl( $_SERVER['REQUEST_URI'] ) ];
$compo->setup($passthru);

All your setup code will be run, in no particular order, and your Page_Home view will be displayed when yoursite.atld/ is requested

Compiling

Call $compo->compile(true) to force re-compilation of all views & forms. Call $compo->compile() to use the default $forceRecompile value of false to only compile views that have changed.
You should use true in development probably.
I've had troubles with conditional recompiling (passing false) on my localhost, and I think it was because of file permissions issues, but I'm not sure.

And you can set a host of your own compile handlers.

View Queries: A compile handler

In my Liaison Package, I use this for routing. Here's a simplified version.

$compo->addViewQuery('//lia-route', //runs on every `<lia-route` tag
    function($rbDoc, $view, $compiler, $node){
        $route = $node->getAttribute('pattern');
        $escRoute = var_export($route, true); // because `$route` is only available during this compile step. 
        $phpCode = '<?php if ($url==$escRoute)echo $this; ?>`
        $view->appendSetupCode($phpCode);
    }
);

This function will be run during the compile step for each <lia-route tag your view contains. No errors if not found.
It will append setup code that does routing.
Then when you call $compo->setup['url'=>$theUrl], the setup code will run and your view will be displayed if the route matches the url.

Runtime Handlers

Use $compo->setRuntimeHandler(...) or $compo->addRuntimeHandler($handlerName,$function). What the handler receives varies greatly.
setRuntimeHandler will only allow one handler per $name & the callback's value will be returned when the runtime handler is called. addRuntimeHandler will allow multiple handlers. When the named handler is called, each callback's value will be stored in an array & that array will be returned.

Noteable runtime handlers:

  • find: function($table, $findProperty){return $anArrayOfObjects};
    • This MUST be declared to use the entity features
  • format_formatterName: function($value){return convertToMyFormat($value);}
    • $compo->setRuntimeHandler('runtime','format_'.$formatterName,$callback);
    • or $compo->view($view)->addFormatter($name,$callback)
  • addResources: `function($viewObj, $resourcesList){...use your framework or whatever...}

Compile Handlers

These will be run during the compile step.

NEED TO REDO THIS DOC FOR COMPILE HANDLERS

Use $compo->addCompileHandler($handlerName,$function). What the handler receives varies greatly.

Noteable Compile handlers: (name: Callable example)

  • preDoc: function($cleanSource,$viewContent,$compiler,$view){ return str_replace('<bad-tag', '<good-tag',$cleanSource); }
    • This runs before the RBDoc (DOMDocument) instance is created
    • Generally, you should return a modified version of the $cleanSource
    • $cleanSource is the view's source code with the PHP extracted by $compiler
    • $viewContent is the view's source code, with inline PHP still in tact
    • $compiler is an instance of \RBDoc\Compiler, which extracted the php
    • $view is an instance of the view object
  • form: function($formViewObj,$doc,$compiler,$formNode){$formNode->setAttribute('action','/some/url/');}
    • Return values are discarded, but you can modify the objects.
    • I'm not sure, but some things might be overwritten by this library, such as the action or method attributes on the node.
    • $formViewObj is an instance of \Fresh\Form
    • $doc is \RBDoc instance
    • $compiler is an \RBDoc\Compiler
    • $formNode is an \RBDoc\Node (DOMElement) instance, who's tag is <form ...>