NetBeans
最后更新于:2022-04-01 11:04:39
找到项目定义文件:/nbproject/customs.json, 添加下面的代码,保存后,即可实现指令的自动提示
~~~
{
"elements": {},
"attributes": {
"php-include": {},
"php-repeat": {},
"php-for": {},
"php-foreach": {},
"php-show": {},
"php-hide": {},
"php-switch": {},
"php-case": {},
"php-default": {},
"php-function": {},
"php-if": {},
"php-else": {},
"php-elseif": {},
"php-extends": {},
"php-block": {},
"php-literal": {},
"php-after": {},
"php-select": {},
"php-checked": {},
"php-model": {}
}
}
~~~
代码提示
最后更新于:2022-04-01 11:04:37
[NetBeans](NetBeans.md)
更新日志
最后更新于:2022-04-01 11:04:35
## 更新日志
#### 2018-04-24
* 兼容tp5.1
* 修复assign一个 cache_file 变量导致找不到模板和报错的问题
#### 2016-12-21
* 修复php-include变量支持问题
* 修复tp5中控制器大小写支持问题
#### 2016-10-17
* 增加 php-model指令, 方便做内容编辑功能,value会自动转移特殊字符(htmlentities), 保证 input的value正确输出
#### 2016-08-18
* 增加 php-selected 和 php-checked 指令, 方便后台做表单的自动选中功能
#### 2016-07-18
* 调整配置参数 `attr` 为 `directive_prefix`
* 调整配置参数 `max_num` 为 `directive_max`
* 指令规范
#### 2016-06-24
* 项目迁移到top-think下
* 增加命名空间支持
#### 2016-06-05
* 增加自定义扩展功能Angular::extend
* 所有函数和属性改为public修饰, 方便扩展调用配置信息和解析规则
* thinkphp5驱动更新, 解决tp5部分常量不能使用的问题
ThinkPHP 6.0.x
最后更新于:2022-04-01 11:04:32
## 安装方法
`composer require topthink/think-angular:3.0.x`
### 模板配置
```
// config/view.php
return [
// 模板引擎类型 Angular
'type' => 'Angular',
'debug' => true, // 是否开启调试模式
'tpl_suffix' => '.html', // 模板后缀
'tpl_cache_suffix' => '.php', // 模板缓存文件后缀
'directive_prefix' => 'php-', // 指令前缀
'directive_max' => 10000, // 指令的最大解析次数
];
```
### 模板输出和调用
```
// 模板变量赋值
View::assign('name','ThinkPHP');
View::assign('email','thinkphp@qq.com');
// 或者批量赋值
View::assign([
'name' => 'ThinkPHP',
'email' => 'thinkphp@qq.com'
]);
// 模板输出, 模板路径不能为空, 必须写全路径
return View::fetch('index');
```
> 注意, 只有开启调试模式, 修改模板才能实时看到效果, 线上修改模板后, 一定要清理一次模板缓存, 否则会导致模板不生效
ThinkPHP 5.1.x
最后更新于:2022-04-01 11:04:30
## 安装方法
### tp5.1.x版本
```
composer require topthink/think-angular:2.0.*
```
### 模板配置
```
// config/template.php
return [
// 模板引擎类型 Angular
'type' => 'Angular',
'debug' => true, // 是否开启调试模式
'tpl_suffix' => '.html', // 模板后缀
'tpl_cache_suffix' => '.php', // 模板缓存文件后缀
'directive_prefix' => 'php-', // 指令前缀
'directive_max' => 10000, // 指令的最大解析次数
];
```
> 注意, 只有开启调试模式, 修改模板才能实时看到效果, 线上修改模板后, 一定要清理一次模板缓存, 否则会导致模板不生效
ThinkPHP 5.0.x
最后更新于:2022-04-01 11:04:28
## 安装方法
### tp5.0.x版本
<code>composer require topthink/think-angular:1.0.*</code>
### 模板配置
```
// 修改模板配置: /application/config.php
'template' => [
// 模板引擎类型 Angular
'type' => 'Angular',
'debug' => true, // 是否开启调试模式
'tpl_suffix' => '.html', // 模板后缀
'tpl_cache_suffix' => '.php', // 模板缓存文件后缀
'directive_prefix' => 'php-', // 指令前缀
'directive_max' => 10000, // 指令的最大解析次数
],
```
> 注意, 只有开启调试模式, 修改模板才能实时看到效果, 线上修改模板后, 一定要清理一次模板缓存, 否则会导致模板不生效
结合框架使用
最后更新于:2022-04-01 11:04:26
[ThinkPHP 5.0.x](ThinkPHP%205.0.x.md)
[ThinkPHP 5.1.x](ThinkPHP5.1.x.md)
[ThinkPHP 6.0.x](ThinkPHP6.0.x.md)
数据列表输出
最后更新于:2022-04-01 11:04:23
> 最常用的列表输出, 这里提供一个参考案例, 具体项目可就该对应的dom结构
## 控制器代码
```
<?php
// 总页数
$view->assign('pagecount', 100);
// 模拟用户列表
$data = [
'title' => 'Hello PHP Angular',
'list' => [
['id' => 1, 'name' => 'user_1', 'email' => 'email_1@qq.com', 'status' => 1],
['id' => 2, 'name' => 'user_2', 'email' => 'email_2@qq.com', 'status' => 0],
['id' => 3, 'name' => 'user_3', 'email' => 'email_3@qq.com', 'status' => -1],
['id' => 4, 'name' => 'user_4', 'email' => 'email_4@qq.com', 'status' => 1],
['id' => 5, 'name' => 'user_5', 'email' => 'email_5@qq.com', 'status' => 1],
],
];
// 向模板引擎设置数据
$view->assign($data);
// 解析显示
$view->display('index');
```
## 模板文件
```
<!DOCTYPE html>
<html>
<head>
<title>列表</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="http://apps.bdimg.com/libs/bootstrap/3.3.4/css/bootstrap.css" />
<script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script type="text/javascript" src="http://apps.bdimg.com/libs/bootstrap/3.3.4/js/bootstrap.min.js"></script>
</head>
<body>
<table class="table table-bordered">
<tr>
<th>编号</th>
<th>用户名</th>
<th>邮箱</th>
<th>状态</th>
<th>操作</th>
</tr>
<tr php-if="$list" php-repeat="$list as $user">
<td>{$user.id}</td>
<td>{$user.name}</td>
<td>{$user.email}</td>
<td>
<php php-switch="$user['status']">
<span php-case="1">正常</span>
<span php-case="0">已禁用</span>
<span php-case="-1">已删除</span>
</php>
</td>
<td>
<a php-show="$user['status'] === 1" php-after="echo ' '" href="javascript:void(0);" class="btn btn-xs btn-warning">禁用</a>
<a php-show="$user['status'] === 0" php-after="echo ' '" href="javascript:void(0);" class="btn btn-xs btn-primary">启用</a>
<a php-show="$user['status'] >= 0" php-after="echo ' '" href="javascript:void(0);" class="btn btn-xs btn-danger">删除</a>
<a php-show="$user['status'] == -1" php-after="echo ' '" href="javascript:void(0);" class="btn btn-xs btn-primary">恢复</a>
</td>
</tr>
<tr php-else="">
<td colspan="3" class="text-center">没有数据</td>
</tr>
</table>
</body>
</html>
```
## 最终效果
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-05_572a316adfe34.png)
无限级菜单生成
最后更新于:2022-04-01 11:04:21
> 无限级菜单和分类也是经常用到的功能, 这里提供一个参考案例, 具体项目可就该对应的dom结构
## 控制器代码
```
<?php
// 树状结构
$menus = [
[
'title' => '菜单1',
'sub' => [
['title' => '菜单1.1'],
['title' => '菜单1.2'],
['title' => '菜单1.3'],
['title' => '菜单1.4'],
]
],
[
'title' => '菜单2',
'sub' => [
['title' => '菜单2.1'],
['title' => '菜单2.2'],
['title' => '菜单2.3'],
['title' => '菜单2.4'],
]
],
[
'title' => '菜单3',
'sub' => [
[
'title' => '菜单3.1',
'sub' => [
['title' => '菜单3.1.1'],
['title' => '菜单3.1.2'],
[
'title' => '菜单3.1.3',
'sub' => [
['title' => '菜单3.1.3.1'],
['title' => '菜单3.1.3.2'],
]
],
]
],
['title' => '菜单3.2'],
['title' => '菜单3.3'],
['title' => '菜单3.4'],
]
],
];
// 赋值给模板
$view->assign('menus', $menus);
$view->display('index');
```
## 模板文件
```
<!DOCTYPE html>
<html>
<head>
<title>无限级菜单</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="http://apps.bdimg.com/libs/bootstrap/3.3.4/css/bootstrap.css" />
<script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script type="text/javascript" src="http://apps.bdimg.com/libs/bootstrap/3.3.4/js/bootstrap.min.js"></script>
</head>
<body>
<ul php-init="echo_menu($menus)" php-function="echo_menu($menus)">
<li php-repeat="$menus as $menu">
{$menu.title}
<ul php-if="isset($menu['sub'])" php-call="echo_menu($menu['sub'])"></ul>
</li>
</ul>
</body>
</html>
```
## 最终效果
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-05_572a316a951fb.png)
分页
最后更新于:2022-04-01 11:04:19
> 分页是数据输出后经常用到的功能, 这里提供一个参考案例, 具体项目可就该对应的dom结构
## 控制器代码
```
// 总页数
$view->assign('pagecount', 100);
// 当前页
$view->assign('p', isset($_GET['p']) ? $_GET['p'] : 1);
// url生成, 可在闭包函数中生成复杂的url
$view->assign('page', function ($p) {
return '/test/index.php?p=' . $p;
});
$view->display('index');
```
## 模板文件
```
<!DOCTYPE html>
<html>
<head>
<title>分页效果</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="http://apps.bdimg.com/libs/bootstrap/3.3.4/css/bootstrap.css" />
<script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script type="text/javascript" src="http://apps.bdimg.com/libs/bootstrap/3.3.4/js/bootstrap.min.js"></script>
</head>
<body>
<!-- 这里可以做成单独的模板文件, 然后用 php-include="common/page" 的方式引入 -->
<nav php-show="$pagecount > 1">
<ul class="pagination">
<li php-show="$p > 1">
<a href="{:$page(1)}">首页</a>
</li>
<li php-show="$p > 1">
<a href="{:$page($p - 1)}">上一页</a>
</li>
<li php-show="$p - 4 > 2">
<!-- 这里是 往前十页, 如果第一页显示了, 就隐藏这个'...' 按钮 -->
<a href="{:$page($p - 10 < 1 ? 1 : $p - 10)}"><span>...</span></a>
</li>
<li
php-for="$i = $p - 4; $i <= $p + 4; $i++"
php-show="$i > 0 && $i <= $pagecount"
class="{$p == $i ?= 'disabled'}">
<a php-show="$p != $i" href="{:$page($i)}">{$i}</a>
<span php-show="$p == $i">{$i}</span>
</li>
<li php-show="$p + 4 < $pagecount">
<!-- 这里是 后十页, 如果最后一页显示了, 就隐藏这个'...' 按钮 -->
<a href="{:$page($p + 10 > $pagecount ? $pagecount : $p + 10)}"><span>...</span></a>
</li>
<li php-show="$p < $pagecount">
<a href="{:$page($p + 1)}">下一页</a>
</li>
<li php-show="$p < $pagecount">
<a href="{:$page($pagecount)}">尾页 {$pagecount}</a>
</li>
</ul>
</nav>
</body>
</html>
```
## 最终效果
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-05_572a316a5979f.png)
常用实例
最后更新于:2022-04-01 11:04:17
[分页](%E5%88%86%E9%A1%B5.md)
[无限级菜单生成](%E6%97%A0%E9%99%90%E7%BA%A7%E8%8F%9C%E5%8D%95%E7%94%9F%E6%88%90.md)
[数据列表输出](%E6%95%B0%E6%8D%AE%E5%88%97%E8%A1%A8%E8%BE%93%E5%87%BA.md)
附录
最后更新于:2022-04-01 11:04:14
[常用实例](%E5%B8%B8%E7%94%A8%E5%AE%9E%E4%BE%8B.md)
[结合框架使用](%E7%BB%93%E5%90%88%E6%A1%86%E6%9E%B6%E4%BD%BF%E7%94%A8.md)
[更新日志](%E6%9B%B4%E6%96%B0%E6%97%A5%E5%BF%97.md)
[代码提示](%E4%BB%A3%E7%A0%81%E6%8F%90%E7%A4%BA.md)
自定义扩展
最后更新于:2022-04-01 11:04:12
> 如果系统自带的解析规则不能满足需求, 可以使用 Angular::extend()方法进行扩展, 此方法有两个参数, 详细请看下面实例.
## 入口文件: /test/index.php
```
<?php
use think\angular\Angular;
require '../src/Angular.php';
// 自定义扩展, 打印变量的值
Angular::extend('dump', function ($content, $param, $angular) {
$old = $param['html'];
$new = '<pre>';
unset($param[0], $param[1], $param[2], $param[3], $param[4], $param[5]);
$new .= '<?php var_dump(' . $param['value'] . '); ?>';
$new .= '<pre>';
return str_replace($old, $new, $content);
});
// 自定义扩展, 变量+1
Angular::extend('inc', function ($content, $param, $angular) {
$old = $param['html'];
$new = '<?php ' . $param['value'] . '++; ?>';
$new .= Angular::removeExp($old, $param['exp']);
return str_replace($old, $new, $content);
});
// 自定义扩展, 变量-1
Angular::extend('dec', function ($content, $param, $angular) {
$old = $param['html'];
$new = '<?php ' . $param['value'] . '--; ?>';
$new .= Angular::removeExp($old, $param['exp']);
return str_replace($old, $new, $content);
});
/ 配置
$config = [
'debug' => true, // 是否开启调试, 开启调试会实时生成缓存
'tpl_path' => './view/', // 模板根目录
'tpl_suffix' => '.html', // 模板后缀
'tpl_cache_path' => './cache/', // 模板缓存目录
'tpl_cache_suffix' => '.php', // 模板缓存后缀
'directive_prefix' => 'php-', // 指令前缀
'directive_max' => 10000, // 指令的最大解析次数
];
// 实例化
$view = new Angular($config);
// 输出解析结果
$view->display('index');
```
## 模板文件: /text/view/index.html
```
<!DOCTYPE html>
<html>
<head>
<title>diy test</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div php-dump="$navs"></div>
<div php-init="$i = 0" php-inc="$i" php-inc="$i">{$i}</div>
<div php-dec="$i">{$i}</div>
</body>
</html>
```
## 解析后
```
<!DOCTYPE html>
<html>
<head>
<title>diy test</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<pre><?php var_dump($navs); ?><pre>
<?php $i = 0; $i++; $i++; ?>
<div><?php echo $i; ?></div>
<?php $i--; ?>
<div><?php echo $i; ?></div>
</body>
</html>
```
model
最后更新于:2022-04-01 11:04:09
> model指令专门用来解决数据在输入框中编辑的问题, 自动转移特殊字符(htmlentities), 保证 input的value正确输出
`版本要求: v1.0.8+`
~~~
// 模版赋值中带有双引号
$view->assign('name', '"php" and "think-angular"');
~~~
## 解析前
~~~
<input type="text" name="name" php-model="$name" />
<input type="submit" value="提交">
~~~
## 解析后
~~~
<input type="text" name="name" value=""thinkphp" vs "angular"" />
<input type="submit" value="提交">
~~~
## 显示
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/6b0728d4a2bda016f5eab0db60932f8c_237x52.png)
checked
最后更新于:2022-04-01 11:04:06
> checked指令专门用来解决复选框和单选的自动选中问题, 可省去多个if判断
~~~
<div
class="form-control"
php-init="$all_hobby = ['html','css','js','php', 'mysql', 'linux']"
php-init="$user_hobby = ['linux','css','js','php']">
技能:
<label class="checkbox-inline" php-repeat="$all_hobby as $hobby">
<input type="checkbox" name="hobby" value="{$hobby}" php-checked="in_array($hobby, $user_hobby)" /> {$hobby}
</label>
</div>
<br />
<div class="form-control" php-init="$user_sex = 1">
性别:
<label class="radio-inline">
<input type="radio" name="sex" value="0" php-checked="$user_sex === 0" /> 女
</label>
<label class="radio-inline">
<input type="radio" name="sex" value="1" php-checked="$user_sex === 1" /> 男
</label>
</div>
~~~
解析后:
~~~
<?php
$all_hobby = ['html','css','js','php', 'mysql', 'linux'];
$user_hobby = ['linux','css','js','php']; ?>
<div class="form-control">
技能:
<?php foreach ($all_hobby as $hobby) { ?>
<label class="checkbox-inline">
<?php if (in_array($hobby, $user_hobby)) { ?>
<input type="checkbox" name="hobby" value="<?php echo $hobby; ?>" checked="checked" />
<?php } else { ?>
<input type="checkbox" name="hobby" value="<?php echo $hobby; ?>" />
<?php } echo $hobby; ?>
</label>
<?php } ?>
</div>
<br />
<?php $user_sex = 1; ?>
<div class="form-control">
性别:
<label class="radio-inline">
<?php if ($user_sex === 0) { ?>
<input type="radio" name="sex" value="0" checked="checked" />
<?php } else { ?>
<input type="radio" name="sex" value="0" />
<?php } ?>
女
</label>
<label class="radio-inline">
<?php if ($user_sex === 1) { ?>
<input type="radio" name="sex" value="1" checked="checked" />
<?php } else { ?>
<input type="radio" name="sex" value="1" />
<?php } ?>
男
</label>
</div>
~~~
selected
最后更新于:2022-04-01 11:04:04
> selected指令专门用来解决选择框的自动选中问题, 可省去多个if判断
~~~
<select class="form-control" php-init="$p = isset($_GET['p']) ? $_GET['p'] : 1">
<option php-for="$i = 1; $i <= 50; $i++" php-selected="$p == $i" value="{$i}">第{$i}页</option>
</select>
~~~
解析后:
~~~
<?php $p = isset($_GET['p']) ? $_GET['p'] : 1; ?>
<select class="form-control">
<?php
for ($i = 1; $i <= 50; $i++) {
if ($p == $i) { ?>
<option selected="selected" value="<?php echo $i; ?>">第<?php echo $i; ?>页</option>
<?php } else { ?>
<option value="<?php echo $i; ?>">第<?php echo $i; ?>页</option>
<?php }
}
?>
</select>
~~~
literal
最后更新于:2022-04-01 11:04:01
> literal指令可以实现代码的原样输出
~~~
<div php-literal="" class="name">{$name}</div>
~~~
解析后:
~~~
<div class="name">{$name}</div>
~~~
如果想输出原始代码,可以使用php-literal="code" , 这样可以在页面上显示div的源代码,其实,只是把左尖括号替换成了实体。
~~~
<div php-literal="code" class="name">{$name}</div>
~~~
解析后:
~~~
<div class="name">{$name}</div>
~~~
extends
最后更新于:2022-04-01 11:03:59
> extends为继承指令,一般项目中, 我们的网页框架是一样的, 比如新闻介绍页, 文章介绍页, 文章列表页, 等等 都是公用的头部底部和侧边栏, 又或者做后台的时候, 都是统一的导航菜单和底部, 这时候我们可以使用模板继承方便的实现代码的重用和结构的划分
## 1. base.html
```
<!DOCTYPE html>
<html>
<head>
<title>base</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div php-block="left">这里是left, 会被替换</div>
<div php-block="right">这里是right, 会被替换</div>
<div php-block="bottom">这里是bottom, 会被替换</div>
</body>
</html>
```
## 2. index.html
```
<div php-extends="common/base"></div>
<div php-block="left">
网页主体
</div>
<div php-block="right">
侧边栏推荐
<ul>
<li php-repeat="[1,2,3,4,5] as $i">列表 {$i}</li>
</ul>
</div>
<div php-block="bottom">
版权所有 {$username}
</div>
```
> 这样模板引擎调用解析 index.html的时候会把对应的block合并到base.html中, 实现模板的继承
## 解析结果
```
<!DOCTYPE html>
<html>
<head>
<title>base</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div >
网页主体
</div>
<div >
侧边栏推荐
<ul>
<?php foreach ([1,2,3,4,5] as $i) { ?><li >列表 <?php echo $i; ?></li><?php } ?>
</ul>
</div>
<div >
版权所有 <?php echo $username; ?>
</div>
</body>
</html>
```
function
最后更新于:2022-04-01 11:03:57
> function指令可以把指定的标签定义为一个函数, 在需要的地方调用
~~~
<div class="menu">
<ul php-function="echo_ul($list)">
<li php-foreach="$list as $cate">
<a href="/category/{$cate.name}">{$cate.title}</a>
<ul php-if="isset($cate['_child'])" php-call="echo_ul($cate['_child'])"></ul>
</li>
</ul>
<ul php-call="echo_ul($list)"></ul>
</div>
~~~
解析后
~~~
<div class="menu">
<?php function echo_ul($list) { ?><ul >
<?php foreach ($list as $cate) { ?><li >
<a href="/category/<?php echo $cate["name"]; ?>"><?php echo $cate["title"]; ?></a>
<?php if (isset($cate['_child'])) { echo_ul($cate['_child']); } ?>
</li><?php } ?>
</ul><?php } echo_ul($list); ?>
</div>
~~~
> 此示例本身就是一个无限级菜单展示的案例, php-call为调用函数传入数据
exec
最后更新于:2022-04-01 11:03:54
> exec目前和init功能相同
~~~
<div class="name" php-exec="$name='shuai'">{$name}</div>
~~~
解析后:
~~~
<?php $name='shuai'; ?><div class="name" ><?php echo $name; ?></div>
~~~