我打算将网站转换为使用MVC和php。 我打算使用Twig模板引擎,以便我可以从页面模板中删除所有代码,但我遇到了一个问题,那就是我的菜单。我只希望某个级别的用户访问每个菜单项。
我有一个我调用的函数,如果允许某个级别,则返回true。 因此,例如,如果您有购买级别,您将被允许查看菜单项1,但不允许查看菜单项2.例如,销售将无法看到前两个菜单项。
我知道你不能在Twig中调用函数或类。
例如(我的函数属于一个名为logon的类,但这不重要)
<?php if ($logon->user_access('purchase','accountant','poweruser')):?>
Menu Item 1
<?php endif;?>
<?php if ($logon->user_access('accountant','poweruser')):?>
Menu Item 2
<?php endif;?>
<?php if ($logon->user_access('sales')):?>
Menu Item 2
<?php endif;?>
问题是如何在不使用php的情况下使用此功能在树枝中制作模板? 我完全不熟悉使用模板引擎。
...编辑 @Yoshi
好的,我在index.php中加入了
的twigrequire_once dirname(__DIR__).'/vendor/Twig/vendor/autoload.php';
然后每当我想渲染页面时,我都会从我的核心/视图中调用一个函数
public static function renderTwig($template,$args =[])
{
static $twig = null;
if($twig === null){
$loader = new \Twig_Loader_Filesystem('../App/Views');
$twig = new \Twig_Environment($loader);
echo $twig->render($template, $args);
}
}
然后在我的控制器中我打电话
View::renderTwig('Home/index.html',[
'css'=> $css,
'name' => 'Dave',
'colours' => ['red','green','blue']
]);
我将这一切都从我一直关注的教程中设置为&#34;从头开始创建php mvc项目&#34;。
PS。我想在我的renderTwig函数中,我可以发送在每个页面上使用的变量并将其添加到页面的arg数组中。这样我就不需要为每个页面添加身份验证。
编辑: 我在这里做一个小修正案。尽管Yoshi的回答是正确的。我有一个小问题,我现在已经解决了,我想我会分享这个。 在twig模板中,我正在使用它
{% if user_access('sales','purchase') %}Do something{% endif %}
问题是我不知道进入的项目数量,所以我需要使用args,这导致我一个小问题,因为下面一行将字符串发送到我的函数,但只是一件事。
return $this->logon->user_access($roles);
func_get_args的问题是你无法将它传递给另一个函数。它只能在您发送给它的函数中读取。所以我的小修正案是这样的。
return $this->logon->user_access($args = func_get_args());
现在问题在于它发送了一个数组,但我的php例程设置为使用args,我想在php中使用与twig中相同的函数。所以我做的是检查一个数组是否进来,我只是循环通过数组,但如果一个非数组进来我检查了args。例如
public function user_access($levels)
{
$bool=false;
if(is_array($levels)):
foreach($levels as $item):
if($this->userlevel($item)==true $bool=true;
endforeach;
else:
foreach(func_get_args() as $arg):
if($this->userlevel($arg)==true $bool=true;
endforeach;
endif;
return $bool;
}
所以,谢谢Yoshi
答案 0 :(得分:1)
以下是将功能(或对象)添加到视图的一些方法。
免责声明:我认为设置树枝的做法非常糟糕
View
的静态方法中的环境。我只是一起去 有了它,所以不要在这里复杂化。但如果你对此感兴趣 在如何做得更好。阅读dependency injection。
<?php
require_once dirname(__DIR__).'/vendor/Twig/vendor/autoload.php';
// only as an example example
class AccessChecker
{
public function user_access(...$levels)
{
return true;
}
}
class YourTwigExtension extends \Twig_Extension
{
/**
* @var AccessChecker
*/
private $logon;
/**
* @param AccessChecker $logon
*/
public function __construct(AccessChecker $logon)
{
$this->logon = $logon;
}
/**
* @inheritdoc
*/
public function getFunctions()
{
return [
new Twig_Function('user_access', [$this, 'checkUserAccess']),
];
}
/**
* @param array ...$roles
*
* @return mixed
*/
public function checkUserAccess(...$roles)
{
return $this->logon->user_access(...$roles);
}
}
class View
{
public static function renderTwig($template, $args =[])
{
static $twig = null;
if($twig === null) {
$loader = new \Twig_Loader_Filesystem('../App/Views');
$twig = new \Twig_Environment($loader);
// the extras:
$logon = new AccessChecker();
// with globals:
$twig->addGlobal('logon', $logon);
/*
* {% if logon.user_access('purchase','accountant','poweruser') %}
* ...
* {% endif %}
*/
// with functions:
$twig->addFunction(new Twig_Function('user_access', [$logon, 'user_access']));
/*
* {% if user_access('purchase','accountant','poweruser') %}
* ...
* {% endif %}
*/
// with an extension
$twig->addExtension(new YourTwigExtension($logon));
/*
* {% if checkUserAccess('purchase','accountant','poweruser') %}
* ...
* {% endif %}
*/
}
echo $twig->render($template, $args);
}
}
注意:您显然只需要选择一种添加功能的方法。我建议去扩展。这样,以后的添加可以在同一个地方发生,而无需更改接线代码。