Laravel 8出现invalid argument supplied for foreach()报错如何解决?
问题根因
- Post模型
find()方法返回值类型错误:当前方法直接返回file_get_contents()读取的HTML字符串,没有解析YAML前置元数据,也没有返回Post类实例,你将字符串赋值给视图的$posts变量,无法被foreach遍历。 - 单篇文章路由与列表页共用视图逻辑错误:列表页视图
posts.blade.php是为遍历多篇文章设计的,你直接将单篇文章数据传给该视图,即使返回Post实例,遍历逻辑也不符合需求。 - 路由参数约束无效:路由参数名为
{post},但where方法中写的参数是posts,正则约束未生效。 - 列表页查询逻辑与单页查询逻辑不统一:首页手动解析YAML生成Post实例,
find()方法无对应解析逻辑,导致数据结构不一致。
修复方案
1. 修正Post模型的查询方法
统一列表和单篇的查询逻辑,修改Post.php代码如下:
<?php namespace App\Models; use Illuminate\Database\Eloquent\ModelNotFoundException; use Illuminate\Support\Facades\File; use Spatie\YamlFrontMatter\YamlFrontMatter; class Post { public $title; public $excerpt; public $date; public $body; public $slug; public function __construct($title, $excerpt, $date, $body, $slug) { $this->title = $title; $this->excerpt = $excerpt; $this->date = $date; $this->body = $body; $this->slug = $slug; } // 修复all方法,返回Post实例数组 public static function all() { $files = File::files(resource_path("posts/")); return array_map(fn($file) => self::parsePostFromFile($file), $files); } // 修复find方法,返回Post实例 public static function find($slug) { if (!file_exists($path = resource_path("posts/{$slug}.html"))) { throw new ModelNotFoundException(); } return cache()->remember("posts.{$slug}", 3600, fn() => self::parsePostFromFile($path)); } // 抽离公共的文件解析逻辑 protected static function parsePostFromFile($path) { $document = YamlFrontMatter::parseFile($path); return new self( $document->title, $document->excerpt, $document->date, $document->body(), $document->slug ); } }
2. 新建单篇文章详情视图
在resources/views目录下新建post.blade.php,用于展示单篇文章内容:
<!DOCTYPE html> <html> <body> <article> <h1>{{ $post->title }}</h1> <p>发布日期:{{ $post->date }}</p> <p>{{ $post->excerpt }}</p> <div>{!! $post->body !!}</div> <a href="/">返回文章列表</a> </article> </body> </html>
3. 修正路由配置
修改web.php代码,简化首页逻辑,修复单篇路由的参数约束和视图返回逻辑:
use App\Models\Post; Route::get('/', function () { return view('posts', [ 'posts' => Post::all(), ]); }); Route::get('posts/{post}', function ($slug) { return view('post', [ 'post' => Post::find($slug), ]); })->where('post', '[A-z\-]+');
内容的提问来源于stack exchange,提问作者Muhammad Kamran
相关产品推荐
相关产品推荐

