Jump to content

How to resolve Trying to access array offset on value of type null error?


slotegraafd

Recommended Posts

Hi,

WHAT:

So I cannot for the life of me figure out why I'm getting this error. I'm trying to create a function that will display the user information from the database in a table but I have like a ton of these errors on the page and I don't know whats wrong.

STEPS TO RESOLVE:

So I've gone over my code a bunch of types to make sure that all the variables and what not were spelled correctly and as far as I can tell they are.

I've also googled this issue to see if I can find a solution but none of them are very helpful.

I honestly don't know whats wrong so kinda hard to find ways to resolve an issue, I don't even really know what this error means.

THE CODE:

This is where I put the function into action

 <?php
   display_table(
     array(
      "id" => "Id",
      "emailaddress" => "Email",
      "firstname" => "First Name",
      "lastname" => "Last Name",
      "salesperson" => "Salesperson",
      "phonenumber" => "Phone Number",
      "extension" => "Extension",
      "type" => "Type"
    )
  );
   ?>
//This is the function
<?php
function display_table($fields, $data, $rows, $page){
  if(isset($_GET['page'])){
    $page = $_GET['page'];
  } else {
    $page = 1;
  }
  $firstRecord = ($page - 1) * ROWS_PER_PAGE;
  $pageNumbers = ceil($rows / ROWS_PER_PAGE);

  echo '<div class="table-responsive w-75 mx-auto py-3">
  <table class="table table-dark table-bordered table-sm">
  <thead>
  <tr>';

  foreach($fields as $key){
    echo '<th class="py-2">' . $key . '</th>';
  }

  echo '</tr>
  </thead>
  </tbody>';

  $keys = array_keys($fields);

  for($record = $firstRecord; $record < $firstRecord + ROWS_PER_PAGE; $record++){
    $row = $data[$record];
    echo '<tr>';

    for($recordCount = 0; $recordCount < count($keys); $recordCount++){
      $column = $keys[$recordCount];
      echo '<td class="py-2">' . $row[$column] . '</td>';
    }

    echo '</tr>';
  }

  echo '</tbody>
  </table';

  for($pages = 1; $pages <= $pageNumbers; $pages++){
    echo '<a class="btn btn-dark mx-1" href=?page=' . $pages . '</a>';
  }
}
?>

Any help/advice would be really appreciated

Link to comment
Share on other sites

I know it would mean basically starting over, but something like this is screaming pagination. 

Here's a small cms example using pagination for my website:

/*
 * Pagination Code
 */
$current_page = htmlspecialchars($_GET['page'] ?? 1); // Current Page Location:
$per_page = 3; // Total articles per page
$total_count = $journal::countAll(); // Totoal articles in database table:
$pagination = new Pagination($current_page, $per_page, $total_count);

 

Here's the Pagination Class:

<?php

namespace Miniature;

use PDO;
use Miniature\Database as DB;

class Pagination extends Journal {

    public $currentPage;
    public $perPage;
    public $totalCount;
    public $result = \NULL;
    protected $query = \NULL;
    protected $stmt = \NULL;

    public function __construct($currentPage = 1, $perPage = 20, $totalCount = 0) {
        $this->currentPage = (int) $currentPage;
        $this->perPage = (int) $perPage;
        $this->totalCount = (int) $totalCount;
    }

    public function offset() {
        return $this->perPage * ($this->currentPage - 1);
    }

    public function totalPages() {
        return ceil($this->totalCount / $this->perPage);
    }

    public function previousPage() {
        $prev = $this->currentPage - 1;
        return ($prev > 0) ? $prev : false;
    }

    public function nextPage() {
        $next = $this->currentPage + 1;
        return ($next <= $this->totalPages()) ? $next : false;
    }

    public function previousLink($url = "") {
        $link = "";
        if ($this->previousPage() != false) {
            $link .= "<a class=\"menuExit\" href=\"{$url}?page={$this->previousPage()}\">";
            $link .= "&laquo; Previous</a>";
        }
        return $link;
    }

    public function nextLink($url = "") {
        $link = "";
        if ($this->nextPage() != false) {
            $link .= "<a class=\"menuExit\" href=\"{$url}?page={$this->nextPage()}\">";
            $link .= "Next &raquo;</a>";
        }
        return $link;
    }

    public function numberLinks($url = "") {
        $output = "";
        for ($i = 1; $i <= $this->totalPages(); $i++) {
            if ($i == $this->currentPage) {
                $output .= "<span class=\"selected\">{$i}</span>";
            } else {
                $output .= "<a class=\"menuExit\" href=\"{$url}?page={$i}\">{$i}</a>";
            }
        }
        return $output;
    }

    public function pageLinks($url) {
        $output = "";
        if ($this->totalPages() > 1) {
            $output .= "<div class=\"pagination\">";
            $output .= $this->previousLink($url);
            $output .= $this->numberLinks($url);
            $output .= $this->nextLink($url);
            $output .= "</div>";
        }
        return $output;
    }

    public function readPage() {

        $this->query = 'SELECT id, user_id, author, page, thumb_path, path, post, page, Model, ExposureTime, Aperture, ISO, FocalLength, heading, content, DATE_FORMAT(date_added, "%M %e, %Y") as date_added, date_added as myDate FROM cms ORDER BY myDate DESC LIMIT :perPage OFFSET :blogOffset';
        $this->stmt = static::pdo()->prepare($this->query); // Prepare the query:
        $this->stmt->execute([':perPage' => $this->perPage, ':blogOffset' => $this->offset()]); // Execute the query with the supplied data:
        $this->result = $this->stmt->fetchAll(PDO::FETCH_OBJ);
        return $this->result;
    }

}

Just some food for thought or maybe some ideas on how to fix the code? 

Link to comment
Share on other sites

52 minutes ago, slotegraafd said:

What do you mean?

Not sure how to say it with any more clarity.

Your definition of the function has 4 parameters, namely $fields, $data, $rows and $page

When you call the function you provide only the "$fields" parameter. There are no values provided for the other three.

image.png.80da842f1d02a7121f5252d371a735e9.png

Link to comment
Share on other sites

17 minutes ago, Barand said:

Not sure how to say it with any more clarity.

Your definition of the function has 4 parameters, namely $fields, $data, $rows and $page

When you call the function you provide only the "$fields" parameter. There are no values provided for the other three.

image.png.80da842f1d02a7121f5252d371a735e9.png

display_table(
     array(
      "id" => "Id",
      "emailaddress" => "Email",
      "firstname" => "First Name",
      "lastname" => "Last Name",
      "salesperson" => "Salesperson",
      "phonenumber" => "Phone Number",
      "extension" => "Extension",
      "type" => "Type"
    ),
    client_select_all(),
    client_count(),
    1
  );

I forgot to add the last part of this, I have those two as other functions to for the data and rows and such

 

Link to comment
Share on other sites

What do client_select_all() and client_count() return?  Move them out of the function call and assign them to a variable, then var_dump that variable.

$data = client_select_all();
var_dump($data);
$rows = client_count();
var_dump($rows);

display_table(
     array(
      "id" => "Id",
      "emailaddress" => "Email",
      "firstname" => "First Name",
      "lastname" => "Last Name",
      "salesperson" => "Salesperson",
      "phonenumber" => "Phone Number",
      "extension" => "Extension",
      "type" => "Type"
    ),
    $data,
    $rows,
    1
  );

They probably are not returning what you're expecting them too.

Link to comment
Share on other sites

Your data array only contains 2 rows, but your function is written to expect a minimum of ROWS_PER_PAGE rows.   Once the loop passes the end of your data array,

$row = $data[$record];

Will result in $row being NULL because the index it's trying to access doesn't exist.

What you need to do is change your function to only loop until the end of the array if there are not enough rows available.  So you want the end of your loop to be either

$firstRecord + ROWS_PER_PAGE

or

$rows

which ever is smallest.  This can be easily determined by using the min() function.

So change your for loop to

  $lastRecord = min($firstRecord + ROWS_PER_PAGE, $rows);
  for($record = $firstRecord; $record < $lastRecord; $record++){

 

Additionally, the function currently generates invalid HTML due to various errors in the HTML strings.  You'll want to address those as well.

Edited by kicken
Link to comment
Share on other sites

48 minutes ago, kicken said:

Your data array only contains 2 rows, but your function is written to expect a minimum of ROWS_PER_PAGE rows.   Once the loop passes the end of your data array,


$row = $data[$record];

Will result in $row being NULL because the index it's trying to access doesn't exist.

What you need to do is change your function to only loop until the end of the array if there are not enough rows available.  So you want the end of your loop to be either


$firstRecord + ROWS_PER_PAGE

or


$rows

which ever is smallest.  This can be easily determined by using the min() function.

So change your for loop to


  $lastRecord = min($firstRecord + ROWS_PER_PAGE, $rows);
  for($record = $firstRecord; $record < $lastRecord; $record++){

 

Additionally, the function currently generates invalid HTML due to various errors in the HTML strings.  You'll want to address those as well.

Okay so that didnt in fact get rid of the errors I was getting but now it doesnt show any of the data

Link to comment
Share on other sites

37 minutes ago, kicken said:

@slotegraafd then perhaps you have an additional problem or did not make the correct changes.  Provide the updated code after you've made the changes.

I copied your function from the original post and tested it with the sample data and changes and it works just fine for me.

 

Is this how you did it. Idk what im missing


  $lastRecord = min($firstRecord + ROWS_PER_PAGE, $rows);
  
  for($record = $firstRecord; $record < $lastRecord; $record++){
    $row = $data[$firstRecord + ROWS_PER_PAGE];
    echo '<tr>';

    for($recordCount = 0; $recordCount < count($keys); $recordCount++){
      $column = $keys[$recordCount];
      echo '<td class="py-2">' . $row[$column] . '</td>';
    }

    echo '</tr>';
  }

 

Link to comment
Share on other sites

if you are trying to paginate an array of data, just use array_slice(). it takes the same offset and length values as the LIMIT clause in an sql query would. this would eliminate all this 'glue' logic. you would just foreach(){} loop over the array of data returned. this will also work correctly for a partial last slice or an initial slice with less than ROWS_PER_PAGE elements in it.

if this data is coming from an sql query, why aren't you just getting the requested page of data directly in the query?

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.