What is the best way for testing if a foreach element is the last element?

I have read that the way this should be done is with testing for: ($row === end($stmt))

However, when I test for this it is not detecting that the last result is the end.

Is there a better (more accurate way) of checking for the last result?

I also tried with !next, but it still does not work.

$sql="(My Query)";
$stmt = $pdo->query($sql);
foreach ($stmt as $row) {
  if ($row === end($stmt)) {
    echo '<div class="newsLine_noBottom">';
  }
  else {
    echo '<div class="newsLine_bottom">';
  }
  echo $row['stuff'];
  echo '</div>';
}

What I am trying to do:
For every row of data, show the data and place a line underneath each row, except for the last.

Any ideas why this is not working? In my example above, only 3 rows of data are returned, however all 3 are getting the same div class (newsLine_bottom) applied to them, where-as the last one should be getting the alternate div class (newsLine_noBottom).

<?php declare (strict_types = 1);

$arr = ['One', 'Two', 'Three'];
$end = end($arr);

foreach ($arr as $v) {

    if ($v == $end) {
        echo $v;
        break;
    }
    echo $v;
    echo '<hr>';
}

I’m getting an error when I try to use the reference to strict types:

Fatal error: strict_types declaration must be the very first statement in the script in /myurl/index.php on line 418

Line 418 is where I used:

<?php declare (strict_types = 1);

My guess is that maybe this is supposed to go on Line 1? However on Line 1 is where I have: session_start();

To my understanding for sessions, that has to be first on Line 1.

Put the session start under it or delete the strict types.

<?php declare(strict_types=1);
session_start();

* session_start needs to come before any output. It doesnt matter what line it is on.

I thought session_start() has to be the very first thing that follows php? I’ve read this several times in different sources – is this not the case?

Your sources are wrong, it is not the case

session_start needs to come before any output. It doesnt matter what line it is on.

Okay. I will trust you on that then. I was taught nothing could be between the “<?php” and then the reference to session. It does make sense to me though that it just needs to come before any output.

Keep in mind I am a newbie coder here:

I think I have tracked down the issue.

when I try: echo array_values($stmt);

I get the following error:
Warning : array_values() expects parameter 1 to be array, object given in /home/cabox/workspace/minisgallery/Live_Files/index.php on line 425

Why would my above query not be returning the results as an array?

I thought $stmt = $pdo->query($sql); would generate an array of the results? Or is that not what this does?

Take a look at this PDO tutorial.

$sql = 'Your Query';
foreach ($pdo->query($sql) as $row)
{
//Do Stuff
}

You will want to learn how to use var_dump. It will show you details of what a value is and contains.

https://www.php.net/manual/en/pdo.query.php

The manual is your friend. It even gives an example of how to use query method.

Good job on starting your journey with PDO. It was the right decision. :+1:

Well to say I have much confusion in this area is an understatement. I originally began doing queries as per the manual, however then I was shown the delusions manual and the query format there is different. I now do all my queries as per the delusions examples.

I have now spent 3 hours today trying to get this simple @#$#ing query to work. I’ve read the manuals so many times, that they no longer make sense to me.

Thank you for the “var_dump” method… I spent 20 minutes Googling how to get the value for my array and none of the results mentioned var_dump.

I have restructured my query now and it appears to be working fine:

$sql="(My Query)";
$stmt = $pdo->prepare($sql);
$stmt->execute();
$result = $stmt->fetchAll();

foreach ($result as $row) {
  if ($row === end($result)) {
    echo '<div class="newsLine_noBottom">';
  }
  else {
    echo '<div class="newsLine_bottom">';
  }
  echo $row['stuff'];
  echo '</div>';
}

Thank you for your help – I know it must be frustrating helping us newbies :slight_smile:

Now see what you can do to refactor it to clean it up. Notice any duplicate code? Hint: Get rid of the else.

It’s all a Journey. Just keep at it.
Some of us ( me :innocent: ) can be rather direct. Don’t take it personal.

1 Like

Incidentally - the answer to your problem is actually probably better solved with a better targetted CSS rule than using code to give it a different class.

.newsLine:not(:last-child) {
   margin-bottom: 2px;
}
1 Like

Thank you for mentioning this option. I’m not overly familiar with CSS and I thought last-child could only be used on things such as lists that are contained within tags.

:last-child refers to the last element inside any container. <html> is a container (and usually, the <body> tag is its last child)… anything that has an opening and closing tag and contains other elements will have a :last-child match.

Keep in mind that :last-child matches the last CHILD, not necessarily the last matching element.

<div>
   <div class='a'></div>
   <div class='a'></div>
   <div class='a'></div>
   <div class='a'></div>
   <div class='b'></div>
</div>

.a:last-child will not match anything here; none of the ‘a’ divs is the last child.