# BladeOneHtml It is a PHP library that allows to create forms (view) easily, cleanly and without killing the performance. It uses the library BladeOne to renders the view. This library only uses a single dependency, one file and nothing more. This library works in two ways: * It compiles a script (our view that use our tags), in a native PHP code. * And the next read, if the script exists, then it uses it (instead of re-compiling). And since the script is native code, then it is exactly like to work in vanilla-php, but it is way easy to write and to maintenance. [![Packagist](https://img.shields.io/packagist/v/eftec/bladeonehtml.svg)](https://packagist.org/packages/eftec/bladeonehtml) [![Total Downloads](https://poser.pugx.org/eftec/bladeonehtml/downloads)](https://packagist.org/packages/eftec/bladeonehtml) [![Maintenance](https://img.shields.io/maintenance/yes/2025.svg)]() [![composer](https://img.shields.io/badge/composer-%3E2.0-blue.svg)]() [![php](https://img.shields.io/badge/php-7.4-green.svg)]() [![php](https://img.shields.io/badge/php-8.4-green.svg)]() [![CocoaPods](https://img.shields.io/badge/docs-71%25-yellow.svg)]() * [BladeOneHtml](#bladeonehtml) * [Usage](#usage) * [Template basic](#template-basic) * [Template usage](#template-usage) * [input](#input) * [hidden](#hidden) * [label](#label) * [image](#image) * [select](#select) * [item](#item) * [items](#items) * [optgroup](#optgroup) * [checkbox](#checkbox) * [radio](#radio) * [textarea](#textarea) * [button](#button) * [link](#link) * [checkboxes](#checkboxes) * [radios](#radios) * [file](#file) * [ul](#ul) * [ol](#ol) * [pagination](#pagination) * [table](#table) * [tablehead](#tablehead) * [tablebody](#tablebody) * [tablefooter](#tablefooter) * [tablerows](#tablerows) * [cells](#cells) * [cssbox](#cssbox) * [How to add a new css into the cssbox?](#how-to-add-a-new-css-into-the-cssbox) * [jsbox](#jsbox) * [How to add a new JavaScript into the cssbox?](#how-to-add-a-new-javascript-into-the-cssbox) * [jscodebox](#jscodebox) * [Template Customization](#template-customization) * [Set a default class](#set-a-default-class) * [Set a custom pattern](#set-a-custom-pattern) * [Pattern-Variables inside the code](#pattern-variables-inside-the-code) * [Custom attribute](#custom-attribute) * [Methods](#methods) * [useBootstrap5](#usebootstrap5) * [Note: If we want to use the css box, then we need to add to our view the next code](#note-if-we-want-to-use-the-css-box-then-we-need-to-add-to-our-view-the-next-code) * [useBootstrap4](#usebootstrap4) * [Note: If we want to use the css box, then we need to add to our view the next code](#note-if-we-want-to-use-the-css-box-then-we-need-to-add-to-our-view-the-next-code-1) * [useBootstrap3](#usebootstrap3) * [addCss](#addcss) * [addJS](#addjs) * [addJSCode](#addjscode) * [Public Fields](#public-fields) * [$pattern](#pattern) * [$defaultClass](#defaultclass) * [$customAttr](#customattr) * [Creating a new pattern](#creating-a-new-pattern) * [1- Adding a new pattern](#1--adding-a-new-pattern) * [2- Creating a new method](#2--creating-a-new-method) * [3- Creating a new parent Method (container method)](#3--creating-a-new-parent-method-container-method) * [4- Advanced](#4--advanced-) * [Version history](#version-history) ## Usage 1. This library requires eftec/bladeone. You could install via Composer in the root folder of your project as > composer require eftec/bladeonehtml 2. And you should extend the class as follows (BladeOneHtml is a Trait) ```php include "vendor/autoload.php"; use eftec\bladeone\BladeOne; use eftec\bladeonehtml\BladeOneHtml; class myBlade extends BladeOne { use BladeOneHtml; } $blade=new myBlade(); // for our example: $myvalue=@$_REQUEST['myform']; echo $blade->run("exampleview", ['myvalue'=>$myvalue]); ``` 3. Create a folders called 📁 "\views" and 📁 "\compiles" 4. Inside views, creates the next file 📄 "\views\exampleview.blade.php" ```html @form() @input(type="text" name="myform" value=$myvalue) @button(type="submit" value="Send") @endform() ``` $blade=new myBlade(); ![](docs/img1.jpg) ## Template basic This library adds a new set of tags for the template. The tags uses named arguments, so it is easily configurable. > @<tag>(argument1="value" argument2='value' argument3=value argument4=$variable argument5=function(), argument6="aaa $aaa") This library uses the native html arguments but some arguments are special | Argument | Description | example | |----------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------| | text | It adds a content between the tags. **The inner value is always un-quoted.** | @tag(text="hello") -> <tag>hello</tag> | | pre | It adds a content before the tag | @tag(pre="hello") -> hello<tag></tag> | | post | It adds a content after the tag | @tag(post="hello") -> <tag></tag>hello | | between | It adds a content between the tags (it works similar than text) | @tag(between="hello") -> <tag>hello</tag> | | value | Usually it works as the normal "**value**" of html but it also could works differently (in @textarea works like **text**) | @tag(value="hello") -> < tag value="hello"></tag> | | values | Some components needs a list of object/arrays. This argument is used to sets the list of values | @tag(values=$countries) | | alias | Some components needs or use a list of object/array. This argument is to reference any row inside the list. If **values** is set and **alias** is missing, then it creates a new alias called values+"Row". | @tag($values=$countries alias=$country)
@tag($values=$countries ) **it asumes alias=$countriesRow** | | optgroup | The tag @select could list grouped elements. This argument is used to set the grouping | @tag($values=$countries alias=$country @optgroup=$country->continent) | Let's say the next example ``` @input(value="hello world" type="text" ) ``` It is rendered as ``` ``` If the tag uses a variable of function, then this view ``` @input(value=$hello type="text" ) ``` Is converted into ``` // the ``` The method $this->e is used to escape the method. > Note: This library allows any tag, even custom tags (but only if they don't enter in conflict with the special tags, see table) > > @input(value="hello world" type="text" mycustomtag="hi" ) > > Is converted into ````html ```` ## Template usage ### input It shows an input HTML. Basic example: ```html @input(id="id1" value="hello world$somevar" type="text" ) ``` ![](docs/input_label.jpg) ### hidden It generates a hidden field Basic example: ``` @hidden(name="id1" value="hello world$somevar" ) ``` ### label It shows a label html ```html @label(for="id1" text="hello world:") ``` ![](docs/input_label.jpg) ### image It shows an image ``` @image(src="https://via.placeholder.com/350x150") ``` ![](docs/image.jpg) ### select It shows a select (dropdown list) html object Example: ``` @select(id="aaa" value=$selection values=$countries alias=$country) @item(value='aaa' text='hello world') @item(value='aaa' text='hello world') @item(value='aaa' text='hello world') @items( id="chkx" value=$country->id text=$country->name) @endselect ``` > Note 1: @items requires the arguments values in the parent (@select) and the arguments **value** (the selectable value) and **text** (the visible value) > Note 2: @items requires an **id**, assigned in the same tag or in the parent tag (in this case, the parent is @select) > Note 3: By standard, the argument **id** must be unique. ![](docs/select.jpg) ### item **@item** is a utility tag used inside other tags. This behaves depending on of their parent tag. It adds a simple line/row to the parent object. Example: ``` @select() @item(value='aaa' text='hello world') @endselect ``` It renders ``` ``` ### items **@items** is a utilitarian tag used inside some tags. This behaves depending on of their parent tag. It adds a multiples lines/rows to the parent object using the tag **values** > Note: This tag requires some arguments: > > * the parent(or this tag) requires the tag **values** > * the parent requires the tag **value** It indicates the current selection (if any) > * the parent(or this tag) requires the tag **alias** If alias is missing then it uses the name of values + "Row", i.e. values=product -> alias= productRow > * the parent(or this tag) requires the tag **id** > * The rendered "id" will be generated using this id+"_"+"id of the row". i.e. id="idproduct" => idproduct_0, idproduct_1 > * Why? It is because the id must be unique (html specs) Example, if $countries is a list of objects then : ``` @select(id="aaa" value=$selection values=$countries alias=$country) @items( id="chkx" value=$country->id text=$country->name) @endselect ``` If $countries is a list of arrays then: ``` @select(id="aaa" value=$selection values=$countries alias=$country) @items( id="chkx" value=$country['id'] text=$country['name']) @endselect ``` Inside the tag items, you could use the next variables | variable (where values is the variable used) | Specification | |----------------------------------------------------------|-----------------------------------------------------------------------| | **$values**OptGroup | It stores the current optgroup (if any). Example: $productOptGroup | | **$values**Key | It indicates the current key of the current row. Example: $productKey | | $alias (if not alias is set then it uses **$values**Row) | The current row of the variable. Example: $productRow | ### optgroup It starts an optional group (select) Example: ``` @select(id="aaa" value=$selection values=$countries alias=$country) @optgroup(label="group1") @item(value='aaa' text='hello world') @item(value='aaa' text='hello world') @item(value='aaa' text='hello world') @endoptgroup @endselect ``` > Note: this tag must be ended with the tag @endoptgroup ![](docs/optgroup.jpg) ### checkbox It adds a single checkbox Example: ``` @checkbox(id="idsimple" value="1" checked="1" post="it is a selection") ``` ![](docs/checkbox.jpg) ### radio It adds a single radio button Example: ``` @radio(id="idsimple" value="1" checked="1" post="it is a selection") ``` ![](docs/radio.jpg) ### textarea It draws a text area. Example: ``` @textarea(id="aaa" value="3333 3333 aaa3333 ") ``` ![](docs/textarea.jpg) ### button It draws a button Example: ``` @button(value="click me" type="submit" class="test" onclick='alert("ok")') ``` ![](docs/button.jpg) ### link It adds a hyperlink Example: ``` @link(href="https://www.google.cl" text="context") ``` ![](docs/link.jpg) ### checkboxes It shows a list of checkboxes ``` @checkboxes(id="checkbox1" value=$selection alias=$country) @item(id="aa1" value='aaa' text='hello world' post="
") @item(id="aa2" value='aaa' text='hello world2' post="
") @items(values=$countries value='id' text='name' post="
") @endcheckboxes ``` ![](docs/checkbox.jpg) ### radios It shows a list of radio buttons ``` @radios(id="radios1" name="aaa" value=$selection alias=$country) @item(value='aaa' text='hello world' post="
") @item(value='aaa' text='hello world2' post="
") @items(values=$countries value='id' text='name' post="
") @endradios ``` ![](docs/radio.jpg) ### file It generates a file input value ``` @file(name="file" value="123.jpg" post="hello world") ``` > Note: it also renders a hidden file with name "name"+"_file" with the original value ![](docs/file.jpg) ### ul It generates an unsorted list ``` @ul(id="aaa" value=$selection values=$countries alias=$country) @item(value='aaa' text='hello world') @item(value='aaa' text='hello world') @item(value='aaa' text='hello world') @items(value=$country->id text=$country->name) @endul ``` ![](docs/ul.jpg) ### ol It generates a sorted list ``` @ol(id="aaa" value=$selection values=$countries alias=$country) @item(value='aaa' text='hello world') @item(value='aaa' text='hello world') @item(value='aaa' text='hello world') @items(value=$country->id text=$country->name) @endol ``` ![](docs/ol.jpg) ### pagination It generates a pagination. It requires bootstrap3, bootstrap4 or bootstrap5. You can find an example at [examples/examplepagination.php](examples/examplepagination.php) PHP code ```php $current=isset($_GET['_page']) ? $_GET['_page'] : 1; echo $blade->run("examplepagination", ['totalpages'=>count($products) ,'current'=>$current ,'pagesize'=>10 ,'products'=>$items ]); ``` Template ```html @pagination(numpages=$totalpages current=$current pagesize=$pagesize urlparam='_page') ``` > Note: The page is base 1. > Note: the argument urlparam is used to build the link (domain.dom/web.php?_page=999) You can change the name of the buttons **prev** and **next** as follows: ```php $this->setTranslation(['pagination'=>['prev'=>'<<>','next'=>'>']]); ``` ![](docs/pagination.jpg) ### table It renders a table ``` @table(class="table" values=$countries alias=$country border="1") @tablehead @cell(text="id") @cell(text="cod") @cell(text="name") @endtablehead @tablebody(id='hello world' ) @tablerows(style="background-color:azure") @cell(text=$country->id style="background-color:orange") @cell(text=$country->cod ) @cell(text=$country->name) @endtablerows @endtablebody @tablefooter @cell(text="id" colspan="3") @endtablefooter @endtable ``` ![](docs/table.jpg) #### tablehead It renders the header of the table (optional). Each cell added inside it, is rendered as "th" HTML tag #### tablebody It renders the body of the table (optional). Each cell added inside the table is rendered as "td" HTML tag #### tablefooter It renders the footer of the table (optional). Each cell added inside it, is rendered as "th" HTML tag #### tablerows It generates a row inside the body #### cells It renders a cell inside the tablehead,tablebody (tablerows) or tablefooter ### cssbox It renders and css added into the box ```html @cssbox ``` #### How to add a new css into the cssbox? Using the method addCss($css,$name) ```php $this->addCss('','mystyle'); $this->addCss('css/stylename.css'); ``` **$css** could be a link or a link tag **$name** is optional but it avoids to add duplicates. If we add a new CSS with the same name as a previous one, then it is ignored. ### jsbox It renders all JavaScript links added to the box ```html @jsbox ``` #### How to add a new JavaScript into the cssbox? Using the method addJs($script,$name) ```php $this->addJs('','jquery'); ``` ### jscodebox ```html @jsbox @jscodebox(ready) ``` This code adds the tags < script > automatically. The argument **ready** indicates if we want to execute the function when the document is ready. How to add a new JavaScript code into the **jscodebox**? ```php $blade->addJsCode('alert("hello");'); ``` ## Template Customization **BladeOneHtml** allows to modify the tags used and to set a default classes for each class. You can set a default class and tags for Bootstrap 3/4/5 using the next method (pick only one). ```php // if true then it loads the css and js from a cdn into the css and jsbox so it requires @cssbox and @jsbox $blade->useBootstrap5(true); // if true then it loads the css and js from a cdn into the css and jsbox so it requires @cssbox and @jsbox $blade->useBootstrap4(true); // if true then it loads the css and js from a cdn into the css and jsbox so it requires @cssbox and @jsbox $blade->useBootstrap3(true); ``` Or you could create your own tags and classes ### Set a default class ```php $blade->defaultClass[$tagname]='default class'; ``` ### Set a custom pattern ```php $blade->pattern['nametag']='pattern'; ``` Where nametag could be as follows | Name | Description | Example | Code | |---------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------|------------------------------------------------------| | nametag | It uses the pattern to use when the tag is used | input | {{pre}}{{between}}< /input>{{post}} | | nametag_empty | The system uses this pattern if the content (between/text) is empty or not set (a self close tag). If not set, then the system uses **nametag** even if the content is empty | input_empty | {{pre}}< input{{inner}} />{{post}} | | nametag_item | The system uses this pattern for tags @item and @items | select_item | < option{{inner}} >{{between}}< /option> | | nametag_end | It uses this pattern when the tag must be closed | form_end | < /form> | #### Pattern-Variables inside the code | variable | explanation | Escaped (*) | |-------------|--------------------------------------------------------------------------------------|-------------------------------------------------------------------| | {{pre}} | The code before the tag : **pre** <tag ></tag> | no | | {{post}} | The code after the tag : < tag ></tag> **post** | no | | {{inner}} | The attributes inside the tag : < tag **inside** > </tag> | yes | | {{between}} | The content between the tag : < tag >**between**</tag> | By default this value is escaped
but it could be un-escaped | | {{id}} | The id attribute (it is also included in {{inner}}): < tag **id** > </tag> | yes | | {{name}} | The name attribute (it is also included in {{inner}}): < tag **name** > </tag> | yes | Example of a normal tag: ```php $blade->pattern['input']='{{pre}}{{between}}{{post}}'; ``` > Note :(*) What is escaped?. For example the text "", if it escaped, it is displayed as "&lt;hello&gt;" #### Custom attribute It is possible to add a custom attribute that it could be used inside a pattern. For example, let's add the custom tag called **customtag** ```php $blade->customAttr['customtag']='This attr is missing!'; $blade->pattern['alert']='{{pre}}

{{customtag}}

{{between}}
{{post}}'; ``` And in the view ```html @alert(text="hi there" class="alert-danger" customtag="it is a custom tag")
@alert(text="hi there" class="alert-danger" )
``` ## Methods The library has a lit of methods that they could be used to initialize and configure the library. They are optionals. ### useBootstrap5 It sets the patterns and classes to be compatible with bootstrap 4. if argument is true, then it adds the CSS to the **css box** from the CDN Our code ```php $blade->useBootstrap5(true); ``` #### Note: If we want to use the css box, then we need to add to our view the next code ```html
@cssbox
``` ### useBootstrap4 It sets the patterns and classes to be compatible with bootstrap 4. if argument is true, then it adds the CSS to the **css box** from the CDN Our code ```php $blade->useBootstrap4(true); ``` #### Note: If we want to use the css box, then we need to add to our view the next code ```html
@cssbox
``` ### useBootstrap3 It sets the patterns and classes to be compatible with bootstrap 3. if argument is true, then it adds the CSS to the **css box** from the CDN ```php $blade->useBootstrap3(true); ``` ### addCss It adds a CSS to the **css box** ```php $this->addCss('css/datepicker.css','datepicker'); ``` ### addJS It adds a javascript link to the **js box** ```php $this->addJs('','jquery'); ``` ### addJSCode It adds a javascript code to the **js box** ```php $blade->addJsCode('alert("hello");'); ``` ## Public Fields It is the list of public fields of the class. The fields are public because for performance purpose (versus to use setter and getters) ### $pattern It stores the list of patterns used by the code ```php $this->pattern['sometag']='{{pre}}{{between}}{{post}}'; ``` > Note: see "Pattern-Variable inside the code" to see the list of pattern-variables ### $defaultClass The default CSS class added to a specific tag. ```php $this->defaultClass['sometag']='classred classbackgroundblue'; ``` ### $customAttr It adds a custom adds that it could be used together with $this->pattern ```php $this->customAttr['customtag']='XXXXX'; // So we could use the tag {{customtag}}. 'XXXXX' is the default value ``` > The custom attribute always removes the quotes and double quotes, so if our value is "hello" -> hello ## Creating a new pattern It is possible to add a new pattern by extending the PHP class. #### 1- Adding a new pattern ``` $this->pattern['mynewtag']='{{between}}'; ``` #### 2- Creating a new method You could create a new PHP class or trait and extend our class. Inside this new structure, you must add a new method with the next structure Using a new class ```php use eftec\bladeone\BladeOne; use eftec\bladeonehtml\BladeOneHtml; class MyBlade extends BladeOne { use BladeOneHtml; } class MyClass extends MyBlade { protected function compileMyNewTag($expression) { // the method must be called "compile" + your name of tag. $args = $this->getArgs($expression); // it separates the values of the tags $result = ['', '', '', '']; // inner, between, pre, post // your custom code here return $this->render($args, 'mynewtag', $result); // we should indicate to use our pattern. } } ``` Using a trait (recommended, why? It is because trait are more flexible) ```php trait MyTrait { protected function compileMyNewTag($expression) { // the method must be called "compile" + your name of tag. $args = $this->getArgs($expression); // it separates the values of the tags $result = ['', '', '', '']; // inner, between, pre, post // your custom code here return $this->render($args, 'mynewtag', $result); // we should indicate to use our pattern. } } class MyClass extends BladeOne { use BladeOneHtml; use MyTrait; // <-- our trait } ``` #### 3- Creating a new parent Method (container method) For creating a parent method, you must push a new value inside $this->htmlItem. You can store whatever you want to. ```php $this->pattern['mynewtag']='{{between}}'; ``` ```php protected function compileMyNewTag($expression) { $args = $this->getArgs($expression); // it loads and separates the arguments. $this->htmlItem[] = ['type' => 'mynewtag','value' => @$args['value'] ]; $result = ['', '', '', '']; // inner, between, pre, post //unset($args['value']); // we could unset values that we don't want to be rendered. return $this->render($args, 'select', $result); } ``` > Our objective is to render PHP code, not to evaluate a code. For example, if $args['somearg']=$variable, then our value is $variable (as text), no matter the real value of the variable. You must also create a method to end the container, and we must also add a new pattern. ```php $this->pattern['mynewtag_end']=''; ``` ```php protected function compileEndNewTag() { $parent = @\array_pop($this->htmlItem); // remove the element from the stack if (\is_null($parent) || $parent['type']!=='newtag') { // if no element in the stack or it's a wrong one then error $this->showError("@endnewtag", "Missing @initial tag", true); } // our code return $this->pattern[$parent['type'] . '_end']; // renders the element of the stack } ``` Our items could know if they are inside a tag with the next operation ```php $parent = \end($this->htmlItem); ``` #### 4- Advanced We could create a component that requires CSS and JavaScript. For example a date picker. ```php protected function compileDatePicker($expression) { $args = $this->getArgs($expression); // it loads and separates the arguments. \array_push($this->htmlItem, ['type' => 'mynewtag','value' => @$args['value']]); $result = ['', '', '', '']; // inner, between, pre, post if(!isset($args['id'])) { $this->showError("@datepicker", "Missing @id tag", true); } $this->addJs('','jquery'); // our script needs jquery (if it is not loaded) $this->addCss('css/datepicker.css','datepicker'); $this->addjscode('$(.'.$args['id'].').datepicker();'); //unset($args['value']); // we could unset values that we don't want to be rendered. return $this->render($args, 'select', $result); } ``` > Note: It's better to add the library of jQuery and date picker once in our code ## Version history * 2.5 2024-12-31 * Updated to PHP 8.4 * 2.4 2024-03-02 * Updating dependency to PHP 7.4. The extended support of PHP 7.2 ended 3 years ago. * Added more type hinting in the code * 2.3.2 2023-01-31 * a typo in pagination * 2.3.1 2023-01-31 * fixed a problem with pagination. * some cleanups * update dependencies. * 2.3 2022-02-04 * Now this library is compatible with PHP 7.2 and higher. * Some cleanups and type hinting (return methods) * 2.2 2021-12-11 * fixed a problem with optgroup and when the argument is an associative array. * 2.1 2021-10-01 * Added support for Bootstrap 5.0 * Updated Bootstrap CDNs * added tags @container, @row, @col * 2.0 2021-09-24 * Dropped support for PHP 5.x. Updated support for BladeOne 4.0 * 1.8.1 2021/07/03 * It solves a problem when the argument is defined as id="somevalue$id" * 1.8 2021/06/09 * @checkbox and @radio now works with variables. The element is checked only if the value is not null, empty or zero. * 1.7.1 2021/02/06 * @item now marks the value "checked" or "selected" if the values is equals to the current value of the parent object * Bootstrap 4 **CDN** now it uses the version 4.6 * for @item and @items, the field name and **idname** are created automatically. If id is set, then it uses it. * 1.7 2021/01/12 * @button now considers value as the value of argument while text the visual content. * It also uses in_array instead of isset(). * Compatible with PHP 8.x * 1.6.1 2020/08/31 * Pagination now it has "first" and "last" buttons. * 1.6 2020/08/30 * Added tag @pagination * Added the method setTranslationControl() and getTranslationControl() * 1.5 2020/06/07 * Added a new optional argument to processArgs() and render(); * Added unit test. * 1.4 2020/05/02 * now it allows empty arguments. It requires BladeOne 3.43 or higher. * added unit test. * 1.3 2020/04/22 * added method useBootstrap3() * added default class for textarea in useBootstrap4() * 1.2 2020/04/21 * tag @@alert() * fixed: @@items() now it keeps the selection * tag @@cssbox, @@jsbox and @jscodebox * method useBootstrap4($cdn=false) has a new argument * 1.1 2020/04/21 * Method isVariablePHP() moved to BladeOne * Update LICENSE. * Added more documentation. * 1.0 2020-04-20 First version