如何从 CakePHP 中的字符串 load/execute 视图模板
How to load/execute a view template from a string in CakePHP
我开发了一个 CakePHP 插件,允许站点管理员将自定义报告定义为执行的 SQL 查询列表,并通过 .ctp 模板显示结果。
现在我需要允许管理员编辑模板,与报告一起存储在数据库中。
因此,我需要呈现一个位于字符串内部而不是 .ctp 文件中的模板,我在核心中找不到任何有用的东西。
我最初考虑过在 .ctp 文件中编写模板并从那里加载它们的方法,但我怀疑这个解决方案存在缺陷:文件的位置和相关权限。
更好的解决方案似乎是覆盖视图 class 并添加一个方法来执行此操作。
谁能提出更好的方法?
P.S。安全在这里不是问题,因为管理员基本上是无法访问代码的开发人员。
Hmmm.. 也许创建一个变量来存储生成的代码,并且只是 'echo' 这个变量在 ctp 文件中。
我有类似的问题 (cakephp 3)
控制器方法:
public function preview($id = null) {
$this->loadModel('Templates');
$tempate = $this
->Templates
->findById($id)
->first();
if(is_null($template)) {
$this->Flash->error(__('Template not found'));
return $this->redirect($this->referer());
}
$html = $template->html_content;
$this->set(compact('html'));
}
而 preview.ctp 只是:
<?= $html
在 CakePHP 2.0 中:
View::render()
方法使用
导入模板文件
include
The include
statement includes and evaluates the specified file.
已评估的模板会立即在它包含的任何范围内执行。要复制此功能,您需要使用
eval()
Caution: The eval()
language construct is very dangerous because it
allows execution of arbitrary PHP code. Its use thus is discouraged.
If you have carefully verified that there is no other option than to
use this construct, pay special attention not to pass any user
provided data into it without properly validating it beforehand.
(这个警告是专门对你说的)
...如果您希望继续...这是您如何实现这一目标的基本示例:
$name = 'world';
$template = 'Hello <?php echo $name ?>... <br />';
echo $template;
// Output: Hello ...
eval(' ?>' . $template . '<?php ');
// Output: Hello world...
这(几乎)完全相同:
$name = 'world';
$template = 'Hello <?php echo $name ?>... <br />';
file_put_contents('path/to/template.php', $template);
include 'path/to/template.php';
除非人们不会因为使用 eval()
而对你大吼大叫
在您的 CakePHP 应用程序中:
app/View/EvaluatorView.php
class EvaluatorView extends View
{
public function renderRaw($template, $data = [])
{
if (empty($data)) {
$data = $this->viewVars;
}
extract($data, EXTR_SKIP);
ob_start();
eval(' ?>' . $template . '<?php ');
$output = ob_get_clean();
return $output;
}
}
app/Controller/ReportsController.php
class ReportsController extends AppController
{
public function report()
{
$this->set('name', 'John Galt');
$this->set('template', 'Who is <?php echo $name; ?>?');
$this->viewClass = 'Evaluator';
}
}
app/View/Reports/report.ctp
// Content ...
$this->renderRaw($template);
我开发了一个 CakePHP 插件,允许站点管理员将自定义报告定义为执行的 SQL 查询列表,并通过 .ctp 模板显示结果。
现在我需要允许管理员编辑模板,与报告一起存储在数据库中。 因此,我需要呈现一个位于字符串内部而不是 .ctp 文件中的模板,我在核心中找不到任何有用的东西。
我最初考虑过在 .ctp 文件中编写模板并从那里加载它们的方法,但我怀疑这个解决方案存在缺陷:文件的位置和相关权限。
更好的解决方案似乎是覆盖视图 class 并添加一个方法来执行此操作。
谁能提出更好的方法?
P.S。安全在这里不是问题,因为管理员基本上是无法访问代码的开发人员。
Hmmm.. 也许创建一个变量来存储生成的代码,并且只是 'echo' 这个变量在 ctp 文件中。
我有类似的问题 (cakephp 3) 控制器方法:
public function preview($id = null) {
$this->loadModel('Templates');
$tempate = $this
->Templates
->findById($id)
->first();
if(is_null($template)) {
$this->Flash->error(__('Template not found'));
return $this->redirect($this->referer());
}
$html = $template->html_content;
$this->set(compact('html'));
}
而 preview.ctp 只是:
<?= $html
在 CakePHP 2.0 中:
View::render()
方法使用
include
The
include
statement includes and evaluates the specified file.
已评估的模板会立即在它包含的任何范围内执行。要复制此功能,您需要使用
eval()
Caution: The
eval()
language construct is very dangerous because it allows execution of arbitrary PHP code. Its use thus is discouraged. If you have carefully verified that there is no other option than to use this construct, pay special attention not to pass any user provided data into it without properly validating it beforehand.
(这个警告是专门对你说的)
...如果您希望继续...这是您如何实现这一目标的基本示例:
$name = 'world';
$template = 'Hello <?php echo $name ?>... <br />';
echo $template;
// Output: Hello ...
eval(' ?>' . $template . '<?php ');
// Output: Hello world...
这(几乎)完全相同:
$name = 'world';
$template = 'Hello <?php echo $name ?>... <br />';
file_put_contents('path/to/template.php', $template);
include 'path/to/template.php';
除非人们不会因为使用 eval()
在您的 CakePHP 应用程序中:
app/View/EvaluatorView.php
class EvaluatorView extends View
{
public function renderRaw($template, $data = [])
{
if (empty($data)) {
$data = $this->viewVars;
}
extract($data, EXTR_SKIP);
ob_start();
eval(' ?>' . $template . '<?php ');
$output = ob_get_clean();
return $output;
}
}
app/Controller/ReportsController.php
class ReportsController extends AppController
{
public function report()
{
$this->set('name', 'John Galt');
$this->set('template', 'Who is <?php echo $name; ?>?');
$this->viewClass = 'Evaluator';
}
}
app/View/Reports/report.ctp
// Content ...
$this->renderRaw($template);