Laravel 9 Blade用@标签报Undefined variable $__env错误求助
Laravel 9 Blade「Undefined variable $__env」错误原因与解决办法
问题原因
你在Blade模板里用原生PHP定义了buildCategory递归函数,而Blade的指令(比如@foreach、@isset)依赖Laravel视图编译时的$__env环境变量才能正常工作。这个自定义函数处于原生PHP的独立作用域中,内部无法自动访问到Blade的$__env变量,所以使用Blade指令就会触发「Undefined variable $__env」错误;而原生PHP的foreach不依赖这个环境变量,因此能正常运行。
解决办法
方案1:使用视图组件重构递归逻辑(推荐)
将分类树的递归生成逻辑移到Laravel视图组件中,脱离原生PHP函数的作用域限制,更符合Laravel的开发规范:
- 创建组件类
app/View/Components/CategoryTree.php:
namespace App\View\Components; use Illuminate\View\Component; class CategoryTree extends Component { public $category; public function __construct($category) { $this->category = $category; } public function render() { return view('components.category-tree'); } public function buildCategory($parent) { if (!isset($this->category['parent_cats'][$parent])) { return ''; } $html = '<ul>'; foreach ($this->category['parent_cats'][$parent] as $cat_id) { foreach ($this->category['userPagePerms'] as $userPagePerm) { $selected = $userPagePerm->backend_page_permission_id == $cat_id ? 'true' : 'false'; $cat = $this->category['categories'][$cat_id]; if (!isset($this->category['parent_cats'][$cat_id])) { $html .= "<li data-jstree='{\"selected\":{$selected},\"opened\":true}'> <a href='{$cat->id}'>{$cat->name}</a> </li>"; } else { $html .= "<li data-jstree='{\"selected\":{$selected},\"opened\":true}'> <a href='{$cat->id}'>{$cat->name}</a> {$this->buildCategory($cat_id)} </li>"; } } } $html .= '</ul>'; return $html; } }
- 创建组件视图
resources/views/components/category-tree.blade.php:
{!! $component->buildCategory(0) !!}
- 在原模板中调用组件:
<x-category-tree :category="$category" />
方案2:手动传递$__env变量到自定义函数
如果不想重构代码,可以在定义函数时手动传入$__env,让函数内部能访问Blade环境:
<?php function buildCategory($parent, $category, $__env){ ?> @isset($category['parent_cats'][$parent]) <ul> @foreach ($category['parent_cats'][$parent] as $cat_id) @foreach ($category['userPagePerms'] as $userPagePerm) @if (!isset($category['parent_cats'][$cat_id])) <li data-jstree='{"selected":{{ ($userPagePerm->backend_page_permission_id == $cat_id) ? 'true' : 'false' }},"opened":true}'> <a href='{{$category['categories'][$cat_id]->id }}'> {{ $category['categories'][$cat_id]->name}}</a> </li> @endif @if (isset($category['parent_cats'][$cat_id])) <li data-jstree='{"selected":{{ ($userPagePerm->backend_page_permission_id == $cat_id) ? 'true' : 'false' }},"opened":true}'> <a href='{{ $category['categories'][$cat_id]->id }}'>{{$category['categories'][$cat_id]->name }}</a> <?php buildCategory($cat_id, $category, $__env); ?> </li> @endif @endforeach @endforeach </ul> @endisset <?php } buildCategory(0, $category, $__env); ?>
⚠️ 此方法仅作临时修复,不符合Laravel最佳实践,不推荐长期使用。
方案3:完全使用原生PHP实现递归
将所有Blade指令替换为原生PHP代码,彻底避开对$__env的依赖:
<?php function buildCategory($parent, $category){ if(isset($category['parent_cats'][$parent])){ ?> <ul> <?php foreach ($category['parent_cats'][$parent] as $cat_id) { foreach ($category['userPagePerms'] as $userPagePerm) { ?> <?php if (!isset($category['parent_cats'][$cat_id])) { ?> <li data-jstree='{"selected":<?php echo ($userPagePerm->backend_page_permission_id == $cat_id) ? 'true' : 'false'; ?>,"opened":true}'> <a href='<?php echo $category['categories'][$cat_id]->id; ?>'> <?php echo $category['categories'][$cat_id]->name; ?></a> </li> <?php } ?> <?php if (isset($category['parent_cats'][$cat_id])) { ?> <li data-jstree='{"selected":<?php echo ($userPagePerm->backend_page_permission_id == $cat_id) ? 'true' : 'false'; ?>,"opened":true}'> <a href='<?php echo $category['categories'][$cat_id]->id; ?>'><?php echo $category['categories'][$cat_id]->name; ?></a> <?php buildCategory($cat_id, $category); ?> </li> <?php } ?> <?php } } ?> </ul> <?php } } buildCategory(0, $category); ?>
内容的提问来源于stack exchange,提问作者Mustafa Bayram
相关产品推荐
相关产品推荐

