Whoops \ Exception \ ErrorException (E_WARNING) Invalid argument supplied for foreach()

Can’t remember exactly after what it happened, but getting this error:

Whoops \ Exception \ ErrorException (E_WARNING)

Invalid argument supplied for foreach()

<?php foreach($websites as $p): ?>

Maybe some changes in server, but what I did is probably not connected with this.

Also if I remove controller with code:

<?php

return function ($page, $pages) {

  $websites = $pages->listed()->filterBy('template', 'website');
  
  if(param("sort") == "hearts") {
    $websites = $websites->sortBy(function($page) {
      return $page->likeCount();
    }, 'desc');
  }
  elseif(param("sort") == "alpha") {
    $websites = $websites->sortBy(function($page) {
      return preg_replace('#^https?://#', '', $page->content()->url());
    }, 'asc');
  }

  return [
    'websites' => $websites,
    'sort' => param("sort")
  ];

};

and change foreach to:

<?php foreach($pages->listed()->filterBy('template', 'website') as $p): ?>

then it works, but of course, not solution, as I need those settings

What does $websites after sorting spit out when you dump() the var? It should be a collection of Pages

I hunch is that the variable isn’t traversable anymore.

Sorry, didn’t understand your question

If you do a dump($websites) or var_dump($websites) just before the controller returns, what type of result is returned? It should be a Pages object.

Your error indicates that whatever is returned isn’t traversable, so it might not be a Pages object.

Thank you, can you explain a bit more what I should do?

Set whoops to false in your config and then add the var_dump() statement:

<?php

return function ($page, $pages) {

  $websites = $pages->listed()->filterBy('template', 'website');
  
  if(param("sort") == "hearts") {
    $websites = $websites->sortBy(function($page) {
      return $page->likeCount();
    }, 'desc');
  }
  elseif(param("sort") == "alpha") {
    $websites = $websites->sortBy(function($page) {
      return preg_replace('#^https?://#', '', $page->content()->url());
    }, 'asc');
  }
var_dump($websites);

  return [
    'websites' => $websites,
    'sort' => param("sort")
  ];

};

$websites should actually return a pages collection (even if an empty one), but I wonder if you redefine $websites somewhere.

Thanks, if I put var_dump($websites), error is the same. $websites is defined in controller and then displayed in one template.

How to set whoops to false? Never did it and didn’t find how.

It’s explained in the docs:

Do your template and controller match?

Ah, so easy :slight_smile: ok, after disabling whoops and with or without var_dump($websites); this foreach shows nothing, only other parts of website - header, footer etc.

Yes, it’s home.php page and home.php controller, with websites snippet

So var_dump($websites) says NULL? This debug statement is not supposed to change anything, it is there to find out what is in your $website variable.

No, not NULL, just empty, nothing - when in controller. In template, yes, says NULL

It cannot possibly be that var_dump() doesn’t show anything. Unless your controller doesn’t work. But in that case, $websites would be undefined.

Please post your template as well.

Yes, it was very strange. I tried to replace entire /site/ folder and now it works again, should have done it 3 hours ago :sob: Hovewer template and controller - they are the same, maybe I deleted some other file by accident. Really no idea what was wrong. Thanks everyone for help.

Template is this, but it was the same too before replacing /site/ folder:

<main class="websites">

	<?php foreach($websites as $p): ?>
		<div class="website" id="<?= $p->uid() ?>">

			<div class="screenshot">

				<div class="front_back">
					
					<?php if ($p->images()->isNotEmpty()): ?>

					
					<?php $frontend = $p->images()->template("backend")->sortBy('sort', 'asc')->first() ?>
					<?php $panels = $p->images()->template("backend")->sortBy('sort', 'asc') ?>
					<a class="frontend" href="<?= $panels->first()->url() ?>">
						<img class="lazy" data-src="<?= $frontend->focusCrop(400, 300)->url() ?>" alt="<?= $p->title() ?>">
					</a>
					<div class="backend">
						<img class="lazy" data-src="<?= $panels->first()->resize(1600)->url() ?>" alt="<?= $p->title() ?>">
						<?php foreach($panels as $panel): ?>
							<img class="popup" data-src="<?= $panel->url() ?>" data-size="<?= $panel->width() ?>x<?= $panel->height() ?>">
						<?php endforeach ?>
					</div>
					
					<?php endif ?>
					
				</div>

			</div>

			<div class="title">
				<div>
					<div class="smaller">
				<?= $p->title() ?></div>
<div>
				<a class="frontend bold" title="<?= $p->title() ?>" href="<?= $p->url() ?>"><?= $p->heading() ?></a></div>
				<div class="smaller">
				<?= $p->school() ?><br>
				<?= $p->class() ?> class<br>
				</div>
				</div>
				<div class="heart-block">
				 <a title="Vote" class="heart  <?php e($p->hasLiked(), 'has_liked') ?>" href="<?= $p->url() ?>/like/toggle"">
					
					
					<span>
					<?= $p->likeCount() ?></span><?= svg('assets/images/heart.svg') ?>
					
					 </a>
				</div>

			 </div>
							 <div class="small"><?= $p->desc() ?></div>

		</div>
	<?php endforeach ?>

</main>

Well, there is no issue regarding $websites in there. It sometimes happens that we inadvertently overwrite variables which can result in such NULL issues, but that’s not the case here.

Nevertheless, this piece of code should be hardened because it can potentially cause errors if these is no first panel. Never call a class method without making sure you have an object of that class: