PHP message: PHP Fatal error: Uncaught TypeError: Cannot access offset of type string on string [duplicate]
Asked Answered
D

4

24

I get following error:

PHP message: PHP Fatal error: Uncaught TypeError: Cannot access offset of type string on string

on this line:

if ($uploadZoneData[1]['size'] != 0) {

On php 7.4 i had any troube but with php 8 i have.

What can be the problem?

EDIT: Full code of the related functions:

function uploadSingleFile($zoneImage, $fileMoveTo, $fileAllowedExtensions, $fileAllowedSize, $zoneCustomer, $zone)
{
    global $config;

    // define file upload settings
    $errors = array();
    $fileName = $zoneImage['name'];
    $fileSize = $zoneImage['size'];
    $fileTmp = $zoneImage['tmp_name'];
    $fileType = $zoneImage['type'];
    $fileExt = strtolower(end(explode('.', $zoneImage['name'])));
    $MBtoByte = $fileAllowedSize * 1048576;
    $extensions= $fileAllowedExtensions;

    // define errors
    if (in_array($fileExt, $extensions) === false) {
        $errors[] = "Dieser Datei-Typ ist nicht erlaubt";
    }

    if ($fileSize > $MBtoByte) {
        $errors[] = 'Die Datei ist zu gross';
    }

    // finally try to upload the file
    if (empty($errors) == true) {
        $temp = explode(".", $zoneImage["name"]);
        $newfilename = $zoneCustomer . '-' . strtoupper($zone) . '-' . uniqid() . '.' . end($temp);

        move_uploaded_file($fileTmp, $_SERVER["DOCUMENT_ROOT"] . $fileMoveTo . $newfilename);
        $status = '1';
    } else {
        $status = '0';
    }

    // build array of the different outputs
    $uploadStatus = array($status, $newfilename, $errors);

    return $uploadStatus;
}

function updateZoneData($zoneFile, $zoneCustomer, $zone, $zoneLink, $maxWidth, $bannerID)
{
    global $db;

    // get customer values
    $getCustomerValues = getColumnValue('customers', "WHERE `customerNr` = '" . $zoneCustomer . "'");

    // define redirect url
    switch ($zone) {
      case "a1":
        $redirectZone = "zones.php#zones-overview-a1-overview";
      break;
      case "a2":
        $redirectZone = "zones.php#zones-overview-a2-overview";
      break;
      case "b1":
        $redirectZone = "zones.php#zones-overview-b1-overview";
      break;
      case "b2":
        $redirectZone = "zones.php#zones-overview-b2-overview";
      break;
      case "b3":
        $redirectZone = "zones.php#zones-overview-b3-overview";
      break;
      case "b4":
        $redirectZone = "zones.php#zones-overview-b4-overview";
      break;
      case "a9":
        $redirectZone = "zones.php#zones-overview-a9-overview";
      break;
      case "a9-1":
        $redirectZone = "zones.php#zones-overview-a9-1-overview";
      break;
      case "a11":
        $redirectZone = "zones.php#zones-overview-a11-overview";
      break;
      default:
        $redirectZone = "zones.php";
      }

    // upload file to the server
    $uploadZoneData = uploadSingleFile($zoneFile, '/adserver/banners/', array("jpg", "jpeg", "png", "gif"), '3', $zoneCustomer, $zone);

    if ($uploadZoneData[1]['size'] != 0) {
        if ($uploadZoneData[0] == '1') {

            // create ZIP-Backup (zone-banners) from '/adserver/banners' to '/cp/includes/files/zip-backups'
            createZipBackup('/adserver/banners', '/cp/includes/files/zip-backups', 'adserver-banners.zip');

            // get zone values & delete old bannerImg from file-system
            $getZoneDeleteValues = getColumnValue('zones', "WHERE `customerNr` = '" . $zoneCustomer . "' AND `zone` = '" . $zone . "' AND `id` = '" . $bannerID . "'");
            unlink($_SERVER["DOCUMENT_ROOT"] . '/adserver/banners/' . $getZoneDeleteValues['0']['bannerImg']);

            // execute action
            $updateZoneData = $db->update("zones", [
                                                   "customerNr" => $zoneCustomer,
                                                   "customer" => $getCustomerValues['0']['customer'],
                                                   "zone" => $zone,
                                                   "bannerImg" => $uploadZoneData[1],
                                                   "bannerLink" => $zoneLink,
                                                   "maxWidth" => $maxWidth,
                                                   "changeDate" => date("Y-m-d H:i:s")
                                                   ], [
                                                      "id" => $bannerID
                                                      ]);

            redirectTo($redirectZone, 1, "« " . strtoupper($zone) . "-Banner (" . $getCustomerValues['0']['customer'] . " [K. N°: " . $zoneCustomer . "]) » wurde erfolgreich aktualisiert.", 'ZONES');
        } else {

        // collect and save errors (file-upload)
            $collectedErrors = array_flatten($uploadZoneData[2]);
            setcookie("collectedErrors", '1', time() + (1 * 5), "/"); // expire in 5 seconds
            $_SESSION["collectedErrors"] = $collectedErrors;

            redirectTo($redirectZone, 0, "« " . strtoupper($zone) . "-Banner (" . $getCustomerValues['0']['customer'] . " [K. N°: " . $zoneCustomer . "]) » konnte nicht aktualisiert werden.", 'ZONES');
        }
    } else {

        // execute action
        $updateZoneData = $db->update("zones", [
                                               "customerNr" => $zoneCustomer,
                                               "customer" => $getCustomerValues['0']['customer'],
                                               "zone" => $zone,
                                               "bannerLink" => $zoneLink,
                                               "maxWidth" => $maxWidth,
                                               "changeDate" => date("Y-m-d H:i:s")
                                               ], [
                                                  "id" => $bannerID
                                                  ]);

        redirectTo($redirectZone, 1, "« " . strtoupper($zone) . "-Banner (" . $getCustomerValues['0']['customer'] . " [K. N°: " . $zoneCustomer . "]) » wurde erfolgreich aktualisiert.", 'ZONES');
    }
}
Deadly answered 10/3, 2021 at 5:38 Comment(7)
Does this answer your question? Cannot use string offset as an array in phpRelated
Unfortunately not don't know what I need to change here on the affected line since it had worked under php 7.4 :/Deadly
Shouldn't you be comparing with == instead of assigning with = in your if statement? -> if ($uploadZoneData[1]['size'] != 0) { ?Specialism
No because the If query checks if the file size is not 0, but that is not the problem according to the error message.Deadly
$uploadZoneData[1] is a string containing the value from $newfilename or null and not an array with the index of size If you are attempting to determine if the string is empty you would need to use strlen($uploadZoneData[1]) or empty(($uploadZoneData[1]) instead. The issue is that in PHP 7.4 it was a warning in 8 it is now a fatal errorPhototonus
See PHP 8 incompatibility changes "A number of warnings have been converted into Error exceptions: Attempting to use an invalid type (array or object) as an array key or string offset." for more details.Phototonus
You can apply a condition check to see if you are actually trying to access an array, in the first place: if(is_array($uploadZoneData))Unprovided
A
21

First of all, welcome to Stack Overflow!

This error means that you are trying to access the index [1]['size'] of the string, which is not valid. Be sure to check that uploadSingleFile(...) is returning you an array and not a string.

I checked your code and I saw that the returned array of uploadSingleFile have these three items:

$uploadStatus = array($status, $newfilename, $errors);

$newfilename is not an array. It is a string, as you defined here:

$newfilename = $zoneCustomer . '-' . strtoupper($zone) . '-' . uniqid() . '.' . end($temp);
Armentrout answered 10/3, 2021 at 6:39 Comment(3)
Thanks for the explanation, I see now, in php7.4 it was an warning and now an error, so to check it was no empty I need to replace "if ($uploadZoneData[1]['size'] != 0) {" with "!empty(($uploadZoneData[1])", correct?Deadly
@Deadly Exactly! With !empty(($uploadZoneData[1]['size']) you certify that the array contains the proper index before using it. Note, however, that strings can also have indexes, but they are just numeric, and used to access and modify characters of the string.Armentrout
That case when the answer is too localized for the opening poster and of VERY little use for the 30k+ visitors from Google. Basically it just paraphrases the error message.Lawrence
M
5

Since this error appears because this key is not set in the dictionnary '$uploadZoneData', you can use:

if(isset(...))

that is an usual PHP 8 error (in previous versions, it was set as 0...)

Malapert answered 29/5, 2022 at 6:22 Comment(3)
Yes they can. But this answer doesn't explain what and where should be chckedLawrence
And is's not a "usual PHP 8 error". It's a usual bad code meets PHP 8 error. The code that is trying to treat a string as associative array makes no sense in any version. PHP 8 just took time to point that out.Lawrence
This solution worked best for me.. While other mentioned !empty, that logic fails if values are zero, while still valid. Thank you!Loam
D
1

Thanks for your answers the solution to my problem is.

Replace this

if ($uploadZoneData[1]['size'] != 0) {

with the following:

if (!empty($uploadZoneData[1])) {
Deadly answered 10/3, 2021 at 9:2 Comment(1)
but it will return wrong result if $uploadZoneData[1]['size'] = 0Lawrence
D
0

I'm not a techie, so I find myself on StackOverflow quite often looking for answers. I had this problem and came here in search of an answer. I had already defined the array ($CA = []; in my case), but it was failing on levels deeper than 1 into the array. At its deepest, my array would look like this:

$CA[$row[2]][$row[3]][$row[4]][$row[5]]

The simplest way I can find to put this answer is that EVERY level of the array must be defined, so I ended up with this for each loop through my dataset: (Note: If $row[x] is not null, all $row[any number less than x] won't be null.)

WHILE ($row = $result->fetch_row()) {
    if ( !is_null($row[2]) && !is_array($CA[$row[2]]) ) { $CA[$row[2]] = []; }
    if ( !is_null($row[3]) && !is_array($CA[$row[2]][$row[3]]) ) { $CA[$row[2]][$row[3]] = []; }
    if ( !is_null($row[4]) && !is_array($CA[$row[2]][$row[3]][$row[4]]) ) { $CA[$row[2]][$row[3]][$row[4]] = []; }
    if ( !is_null($row[5]) && !is_array($CA[$row[2]][$row[3]][$row[4]][$row[5]]) ) { $CA[$row[2]][$row[3]][$row[4]][$row[5]] = []; }
  ... Code to set the array elements below ...

PHP no longer automatically creates the array depth you need; you must set it explicitly to avoid the error. Hope this makes it clearer for other non-techies on this page. I'm interested in any better ways to do it (I like to keep my code concise!)

Disbursement answered 1/11, 2021 at 14:19 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.