Muhammad Kamran
Muhammad Kamran

Reputation: 25

invalid argument supplied for foreach() laravel 8

I'm learning Laravel, so not know much about that. I am developing a blog and facing an issue. I am not using the database yet, just working on hard-coded files for practice. The issue is when I click on a link to open the posts, the page shows "invalid argument supplied for foreach() (View: C:\wamp64\www\blogapp\resources\views\posts.blade.php)". On the Home page, I checked that if the post is not an array, but it shows that your post is an array. Here are my codes: web.php

Route::get('/', function () {
    $files = File::files(resource_path("posts"));
    $posts = [];
    foreach ($files as $file) {
        $document = YamlFrontMatter::parseFile($file);
        $posts[] = new Post(
            $document->title,
            $document->excerpt,
            $document->date,
            $document->body(),
            $document->slug
        );
    }
    return view('posts', [
        'posts' => $posts,
    ]);
});

Route::get('posts/{post}', function ($slug) {
    return view('posts', [
        'posts' => Post::find($slug),
    ]);
})->where('posts', '[A-z\-]+');

Post Model: Post.php

<?php
namespace App\Models;

use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Support\Facades\File;

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;
    }

    public static function all()
    {
        $files = File::files(resource_path("posts/"));

        return array_map(fn($file) => $file->getContents(), $files);
    }
    public static function find($slug)
    {
        if (!file_exists($path = resource_path("posts/{$slug}.html"))) {
            // return redirect('/');
            throw new ModelNotFoundException();
        }
        return cache()->remember("posts.{$slug}", 5, fn() => file_get_contents($path));
    }

}

My View: posts.blade.php


<body>
    @if (is_array($posts) || is_object($posts))
    @foreach ($posts as $post)
        <article>
            <h1>
                <a href="/posts/{!! $post->slug !!}">
                    {!! $post->title !!}
                </a>
            </h1>
            <div>{!! $post->excerpt !!}</div>
        </article>
    @endforeach
    @else
    <h3>
        {{ 'Not An Array or Object' }}
        <br>
    </h3>
    @endif
</body>

In the resources folder, I have a folder named posts which consist of 4 HTML files, the HTML code is: my-first-post.html

---
title: My First Post
slug: my-first-post
excerpt: Lorem ipsum dolor sit amet consectetur adipisicing elit.
date: 2021-10-06
---

<p>
    1. Lorem ipsum dolor sit amet consectetur adipisicing elit. Libero
    blanditiis hic, fugiat molestias nostrum at autem ipsam minima sint, earum
    explicabo accusamus magni quasi. Laborum dignissimos voluptas ea deserunt
    voluptatum.
</p>

I don't know Where is the Problem, Please Help

Upvotes: 0

Views: 2078

Answers (1)

Mah Es
Mah Es

Reputation: 630

The problem is your $posts array is either null or empty, or not being sent to view.

You can send $posts to your blade like this too:

return view('posts', ['posts'])

Also, before returning the view, check what is inside your $posts with:

dd($posts)

If it shows null or empty, then that's your problem. You should check in your blade to execute the foreach if the $posts is not empty nor null.

Also, your $posts has to be an array or a collection.

One more thing about the code is that you can just fill $posts like a normal array in PHP and in your case you don't really need to create an instance of Post model for each $post.

Upvotes: 1

Related Questions