eftec / bladeonehtml

Blade 模板引擎的独立版本,Laravel 中单 PHP 文件实现

2.4 2024-03-02 12:27 UTC

This package is auto-updated.

Last update: 2024-08-31 00:29:49 UTC


README

这是一个 PHP 库,可以轻松、干净且不牺牲性能地创建表单(视图)。它使用 BladeOne 库来渲染视图。此库只使用一个依赖项,一个文件,没有更多。

此库以两种方式工作

  • 它将脚本(我们使用我们标签的视图)编译成原生 PHP 代码。
  • 如果脚本存在,则在下一次读取时使用它(而不是重新编译)。由于脚本是原生代码,因此它就像在 vanilla-php 中工作一样,但编写和维护要容易得多。

Packagist Total Downloads Maintenance composer php php php CocoaPods

用法

  1. 此库需要 eftec/bladeone。您可以通过在项目的根目录中使用 Composer 安装它:

composer require eftec/bladeonehtml

  1. 并且您应该按以下方式扩展类(BladeOneHtml 是一个特性):
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]);
  1. 创建一个名为 📁 "\views" 的文件夹和 📁 "\compiles" 文件夹
  2. 在 views 中创建以下文件 📄 "\views\exampleview.blade.php"
<body>
    @form()
        @input(type="text" name="myform" value=$myvalue)
        @button(type="submit" value="Send")
    @endform()
</body>

$blade=new myBlade();

模板基础

此库为模板添加了新的标签集。这些标签使用命名参数,因此很容易配置。

@<tag>(argument1="value" argument2='value' argument3=value argument4=$variable argument5=function(), argument6="aaa $aaa")

此库使用原生 HTML 参数,但某些参数是特殊的

让我们看看以下示例

@input(value="hello world" type="text" )

它被渲染为

<input value="hello world" type="text" />

如果标签使用变量或函数,则此视图

@input(value=$hello type="text" )

将转换为

<input value="<?php echo $this->e($hello);?>" type="text" /> 

方法 $this->e 用于转义方法。

注意:此库允许任何标签,甚至是自定义标签(但前提是它们不会与特殊标签冲突,见表格)

@input(value="hello world" type="text" mycustomtag="hi" )

将转换为

<input value="hello world" type="text" mycustomtag="hi" />

模板用法

输入

它显示一个输入 HTML。

基本示例

@input(id="id1" value="hello world$somevar" type="text" )

隐藏

它生成一个隐藏字段

基本示例

@hidden(name="id1" value="hello world$somevar" )

标签

它显示一个标签 HTML

@label(for="id1" text="hello world:") 

图像

它显示一个图像

@image(src="https://via.placeholder.com/350x150")

选择

它显示一个选择(下拉列表)HTML 对象

示例

@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

注1:@items 需要父元素(@select)中的参数值、value(可选择的值)和text(可见的值)。注2:@items 需要一个id,该id在同一个标签或父标签(在这种情况下,父元素是@select)中指定。注3:按照标准,参数id必须是唯一的。

@item 是一个在其它标签内使用的工具标签。它的行为取决于其父标签。它向父对象添加一个简单的行/行。

示例

@select()
    @item(value='aaa' text='hello world')
@endselect

渲染结果

<select>
<option value="aaa">hello world</option>
</select>

项列表

@items 是一些标签内使用的实用标签。它的行为取决于其父标签。它使用标签 values 向父对象添加多个行/行。

注意:此标签需要一些参数

  • 父元素(或此标签)需要标签 values
  • 父元素需要标签 value 它表示当前选择(如果有的话)
  • 父元素(或此标签)需要标签 alias 如果缺少别名,则使用 values 的名称加 "Row",例如 values=product -> alias= productRow
  • 父元素(或此标签)需要标签 id
    • 渲染的 "id" 将使用此 id+"_"+"行的 id" 生成。例如 id="idproduct" -> idproduct_0, idproduct_1
    • 为什么?因为 id 必须是唯一的(HTML 规范)

示例,如果 $countries 是对象列表,则

@select(id="aaa" value=$selection values=$countries alias=$country)
    @items( id="chkx" value=$country->id text=$country->name)
@endselect

如果 $countries 是数组列表,则

@select(id="aaa" value=$selection values=$countries alias=$country)
    @items( id="chkx" value=$country['id'] text=$country['name'])
@endselect

在 items 标签内部,你可以使用以下变量

分组选项

它开始一个可选的组(select)

示例

@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

注意:此标签必须使用 @endoptgroup 标签结束

复选框

它添加一个单选复选框

示例

@checkbox(id="idsimple" value="1" checked="1" post="it is a selection")

单选按钮

它添加一个单选按钮

示例

@radio(id="idsimple" value="1" checked="1" post="it is a selection")

文本区域

它绘制一个文本区域。

示例

@textarea(id="aaa" value="3333 3333 aaa3333 ")

按钮

它绘制一个按钮

示例

@button(value="click me" type="submit" class="test" onclick='alert("ok")')

链接

它添加一个超链接

示例

@link(href="https://www.google.cl" text="context")

复选框列表

它显示一个复选框列表

@checkboxes(id="checkbox1" value=$selection alias=$country)
    @item(id="aa1" value='aaa' text='hello world' post="<br>")
    @item(id="aa2" value='aaa' text='hello world2' post="<br>")
    @items(values=$countries value='id' text='name' post="<br>")
@endcheckboxes

单选按钮列表

它显示一个单选按钮列表

@radios(id="radios1" name="aaa" value=$selection  alias=$country)
    @item(value='aaa' text='hello world' post="<br>")
    @item(value='aaa' text='hello world2' post="<br>")
    @items(values=$countries value='id' text='name' post="<br>")
@endradios

文件

它生成一个文件输入值

@file(name="file" value="123.jpg" post="hello world")

注意:它还渲染一个名为 "name"+"_file" 的隐藏文件,其中包含原始值

无序列表

它生成一个未排序的列表

@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

有序列表

它生成一个排序列表

@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

分页

它生成分页。它需要 bootstrap3、bootstrap4 或 bootstrap5。

您可以在 examples/examplepagination.php 找到示例

PHP 代码

$current=isset($_GET['_page']) ? $_GET['_page'] : 1;
echo $blade->run("examplepagination", 
    ['totalpages'=>count($products)
     ,'current'=>$current
     ,'pagesize'=>10
     ,'products'=>$items
    ]);

模板

@pagination(numpages=$totalpages current=$current  pagesize=$pagesize urlparam='_page')

注意:页面基准为 1。注意:urlparam 参数用于构建链接(domain.dom/web.php?_page=999)

您可以按如下方式更改按钮的名称 prevnext

$this->setTranslation(['pagination'=>['prev'=>'<&lt;>','next'=>'&gt;']]);

表格

它渲染一个表格

@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

表头

它渲染表格的头部(可选)。添加到其中的每个单元格都渲染为 "th" HTML 标签

表体

它渲染表格的主体(可选)。添加到表格中的每个单元格都渲染为 "td" HTML 标签

表尾

它渲染表格的底部(可选)。添加到其中的每个单元格都渲染为 "th" HTML 标签

表格行

它在主体中生成一个行

单元格

它在 tablehead、tablebody(tablerows)或 tablefooter 中渲染一个单元格

CSS 框

它在框中渲染添加的 CSS

<head>   
	@cssbox
</head>

如何将新的 CSS 添加到 CSS 框中?

使用方法 addCss($css,$name)

$this->addCss('<link rel="stylesheet" href="mystyle.css">','mystyle'); 
$this->addCss('css/stylename.css'); 

$css 可以是一个链接或链接标签

$name 是可选的,但可以避免添加重复项。如果我们添加一个与之前相同的名称的新 CSS,则它将被忽略。

JS 框

它在框中渲染所有添加的 JavaScript 链接

<body>
    <!-- our page -->
	@jsbox
</body>

如何将新的 JavaScript 添加到 JS 框中?

使用方法 addJs($script,$name)

$this->addJs('<script src="js/jquery.js"></script>','jquery');

JS 代码框

<body>
    <!-- our page -->
    @jsbox <!-- we could load jquery here -->
	@jscodebox(ready)
</body>

此代码会自动添加 < script > 标签。

参数 ready 表示是否在文档准备好时执行函数。

如何在 jscodebox 中添加新的 JavaScript 代码?

$blade->addJsCode('alert("hello");');

模板定制

BladeOneHtml 允许修改使用的标签,并为每个类设置默认类。

您可以使用以下方法设置Bootstrap 3/4/5的默认类和标签(请选择其中一个)。

// 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); 

或者,您可以创建自己的标签和类

设置默认类

$blade->defaultClass[$tagname]='default class';

设置自定义模式

$blade->pattern['nametag']='pattern';

其中nametag可以是以下形式

代码中的模式变量

普通标签的示例

$blade->pattern['input']='{{pre}}<input{{inner}} >{{between}}</input>{{post}}';

注意:(*)什么是转义?例如,文本"",如果它被转义,它将显示为"&lt;hello&gt;"

自定义属性

您可以在模式内添加自定义属性。

例如,让我们添加一个名为customtag的自定义标签

$blade->customAttr['customtag']='This attr is missing!'; 
$blade->pattern['alert']='{{pre}}<div {{inner}}><h1>{{customtag}}</h1>{{between}}</div>{{post}}';

在视图中

@alert(text="hi there" class="alert-danger" customtag="it is a custom tag")<br>
@alert(text="hi there" class="alert-danger" )<br>

方法

库提供了一系列方法,可以用来初始化和配置库。它们是可选的。

useBootstrap5

它设置模式和类以与Bootstrap 4兼容。

如果参数为true,则将CSS添加到CDN中的css box

我们的代码

$blade->useBootstrap5(true); 

注意:如果我们想使用 CSS 框,那么我们需要在我们的视图中添加以下代码

<header>
	@cssbox
</header>

useBootstrap4

它设置模式和类以与Bootstrap 4兼容。

如果参数为true,则将CSS添加到CDN中的css box

我们的代码

$blade->useBootstrap4(true); 

注意:如果我们想使用 CSS 框,那么我们需要在我们的视图中添加以下代码

<header>
	@cssbox
</header>

useBootstrap3

它设置模式和类以与Bootstrap 3兼容。

如果参数为true,则将CSS添加到CDN中的css box

$blade->useBootstrap3(true); 

addCss

它向css box添加CSS。

$this->addCss('css/datepicker.css','datepicker'); 

addJS

它向js box添加javascript链接。

$this->addJs('<script src="js/jquery.js"></script>','jquery');

addJSCode

它向js box添加javascript代码。

$blade->addJsCode('alert("hello");');

公共字段

这是类的公共字段列表。字段是公共的,因为为了性能(相对于使用setter和getter)

$pattern

它存储代码使用的模式列表。

$this->pattern['sometag']='{{pre}}<tag {{inner}}>{{between}}</tag>{{post}}';

注意:请参阅“代码中的模式-变量”以查看模式-变量列表。

$defaultClass

默认CSS类添加到特定标签。

$this->defaultClass['sometag']='classred classbackgroundblue';

$customAttr

它添加了一个自定义添加,可以与 $this->pattern 一起使用

$this->customAttr['customtag']='XXXXX'; // So we could use the tag {{customtag}}. 'XXXXX' is the default value

自定义属性始终删除引号和双引号,因此如果我们的值是 "hello" -> hello

创建新的模式

您可以通过扩展PHP类来添加新的模式。

1- 添加新的模式

$this->pattern['mynewtag']='<mycustomtag {{inner}}>{{between}}</mycustomtag>';

2- 创建新的方法

您可以创建一个新的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.
    }
}

使用特性(推荐,为什么?因为特性更灵活)

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- 创建新的父方法(容器方法)

为了创建父方法,您必须将新值推入 $this->htmlItem。您可以存储您想要的任何内容。

$this->pattern['mynewtag']='<mycustomtag {{inner}}>{{between}}';
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);
}

我们的目标是渲染PHP代码,而不是评估代码。例如,如果 $args['somearg']=$variable,则我们的值是 $variable(作为文本),无论变量的实际值如何。

您还必须创建一个方法来结束容器,并且我们还必须添加一个新模式。

$this->pattern['mynewtag_end']='</mycustomtag>';
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
}

我们的项目可以通过以下操作知道它们是否在标签内部

$parent = \end($this->htmlItem);

4- 高级

我们可以创建一个需要CSS和JavaScript的组件。

例如日期选择器。

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('<script src="js/jquery.js"></script>','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);
}

注意:在我们的代码中最好一次添加jQuery和日期选择器库

版本历史

  • 2.4 2024-03-02
    • 更新依赖项到PHP 7.4。PHP 7.2的扩展支持已于3年前结束。
    • 在代码中添加了更多类型提示。
  • 2.3.2 2023-01-31
    • 分页中的错误
  • 2.3.1 2023-01-31
    • 修复了分页问题。
    • 一些清理
    • 更新依赖项。
  • 2.3 2022-02-04
    • 现在这个库与PHP 7.2及以上版本兼容。
    • 一些清理和类型提示(返回方法)
  • 2.2 2021-12-11
    • 修复了optgroup和当参数是关联数组时的一个问题。
  • 2.1 2021-10-01
    • 添加了对Bootstrap 5.0的支持。
    • 更新了Bootstrap CDNs。
    • 添加了@container、@row、@col标签。
  • 2.0 2021-09-24
    • 停止支持PHP 5.x。更新对BladeOne 4.0的支持。
  • 1.8.1 2021/07/03
    • 它解决了当参数定义为id="somevalue$id"时的问题。
  • 1.8 2021/06/09
    • @checkbox和@radio现在与变量一起工作。只有当值不为null、空或零时,元素才被选中。
  • 1.7.1 2021/02/06
    • @item现在将值 "checked" 或 "selected" 标记为等于父对象的当前值。
    • Bootstrap 4 CDN现在使用4.6版本。
    • 对于 @item 和 @items,字段名和 idname 会自动创建。如果设置了 id,则使用它。
  • 1.7 2021/01/12
    • @button 现在将 value 视为参数值,而 text 视为视觉内容。
    • 它还使用了 in_array 代替 isset()。
    • 兼容 PHP 8.x
  • 1.6.1 2020/08/31
    • 分页现在有了 "first" 和 "last" 按钮。
  • 1.6 2020/08/30
    • 添加了标签 @pagination
    • 添加了 setTranslationControl() 和 getTranslationControl() 方法
  • 1.5 2020/06/07
    • 添加了 processArgs() 和 render() 的新可选参数
    • 添加了单元测试。
  • 1.4 2020/05/02
    • 现在它允许空参数。它需要 BladeOne 3.43 或更高版本。
    • 添加了单元测试。
  • 1.3 2020/04/22
    • 添加了 useBootstrap3() 方法
    • 在 useBootstrap4() 中为 textarea 添加了默认类
  • 1.2 2020/04/21
    • 标签 @@alert()
    • 修复:@@items() 现在它保留了选择
    • 标签 @@cssbox, @@jsbox 和 @jscodebox
    • useBootstrap4($cdn=false) 方法有一个新参数
  • 1.1 2020/04/21
    • isVariablePHP() 方法已移至 BladeOne
    • 更新 LICENSE。
    • 添加了更多文档。
  • 1.0 2020-04-20 第一个版本