Raketenmechaniker: Deprecated: Array and string offset access syntax with curly braces is deprecated in php

In PHP 7.4 wirft etwas wie das hier die Fehlermeldung "Deprecated: Array and string offset access syntax with curly braces is deprecated in php"

<?php
$bar="Hallo";
$i=3;
$tok=1;

$foo = $bar{1};
$foo = $bar{ 1 };
$foo = $bar{ 1+3 };

$foo = $bar{ $tok + 3 }; $foo = $bar{$i};

Das will man natürlich ggf. nicht von Hand umschreiben, ein Ein- bis Dreizeiler (Wofür, bittschön, habe ich denn sonst Linux?) muss also her. Ein Test mit

/tmp> sed --in-place="-`date +%Y%m%d_%I%M`" -E -e 's/\$([a-zA-Z0-9_]+)\{([^\}]*)\}/\$\1[\2]/g' test.php

führt scheinbar erfolgreich zum richtigen Ergebnis:

<?php
$bar="Hallo";
$i=3;
$tok=1;

$foo = $bar[1];
$foo = $bar[ 1 ];
$foo = $bar[ 1+3 ];

$foo = $bar[ $tok + 3 ]; $foo = $bar[$i];

Frage: Bevor ich das jetzt mit

find --name '*.php' -exec sed --in-place="-`date +%Y%m%d_%I%M`" -E -e 's/\$([a-zA-Z0-9_]+)\{([^\}]*)\}/\$\1[\2]/g' {} \;;

würde ich nur zu gern wissen, welche Schäden andere an meinen Skripten erwarten würden.

  1. Hallo Raketenmechaniker,

    ich würde annehmen, dass Objekteigenschaften nicht als variablenartige Elemente erkannt werden. Verschachtelte Indexausdrücke $a{2+$b{$c}} dürften gelingen, aber nur in 2 Durchläufen. Zuerst $a[2+$b{$c]}, danach $a[2+$b[$c]].

    Indexzugriffe auf Funktionsergebnisse werden wohl auch ignoriert, aber so was ist selten und kann von Hand passieren.

    Whitespace zwischen Variable und { führt ebenso zur Nichterkennung, das ist aber je nach deinem Coding Style irrelevant.

    Rolf

    --
    sumpsi - posui - clusi
    1. Verschachtelte Indexausdrücke $a{2+$b{$c}} dürften gelingen, aber nur in 2 Durchläufen.

      Jau. Genau das ist mir bei weiteren Tests aufgefallen… Sogar die Idee mit dem zweiten Durchlauf kam auch mir.

      Das folgende behebt dieses Problem und führt mit den Resultaten einen Syntax-Test durch, bevor diese übernommen werden. Ein Backup wird dennoch erzeugt.

      (Soweit zum "Ein- bis Drei-Zeiler" …)

      #!/bin/bash
      ### php73to74.sh
      
      ### Diese Zeile muss angepasst werden!
      phpcli='/usr/bin/php74/bin/php-cli';
      ###
      
      file=$1;
      
      if [ -z "${file}" ]; then
      	echo "Keine Datei angegeben. Exit!" 2>&1; 
      	exit 1;
      
      elif [ -f "${file}]" ]; then
      	echo "'${file}' ist keine Datei. Exit!" 2>&1;
      	exit 2;
      
      elif [ ! -r "${file}" ]; then
      	echo "'${file}' ist nicht lesbar. Exit!" 2>&1;
          exit 4;
      
      elif [ ! -w "${file}" ]; then
          echo "Keine Schreibrechte an '${file}' Exit!" 2>&1;
          exit 8;
      fi
      
      if [ ! -f "${phpcli}" ] && [ ! -x "${phpcli}" ]; then
      	echo "phpcli ('${phpcli}') ist falsch. Exit!" 2>&1;
          exit 8;
      fi
      
      tmpfile1=`mktemp`;
      tmpfile2=`mktemp`;
      backupfile="${file}-`date +%Y%m%d_%H%M`";
      
      
      sed -E -e 's/\$([a-zA-Z0-9_]+)\{([^\}]*)\}/\$\1[\2]/g' "${file}" > "${tmpfile1}";
      $phpcli -l "${tmpfile1}" 1>/dev/null 2>/dev/null;
      if [ 0 -eq $? ]; then
      	cp "${file}" "${backupfile}";
      	cp "${tmpfile1}" "${file}";
      	echo "Erfolg: '${file}' umgewandelt. Backup in '${backupfile}'."  2>&1;
      	rm -f "${tmpfile1}" "${tmpfile2}";
      	exit 0;
      else
      	sed -E -e 's/\$([a-zA-Z0-9_]+)\{([^\}]*)\}/\$\1[\2]/g' "${tmpfile1}" > "${tmpfile2}";
      	$phpcli -l "${tmpfile2}" 1>/dev/null 2>/dev/null;
      	if [ 0 -eq $? ]; then
      	    cp "${file}" "${backupfile}";
              cp "${tmpfile2}" "${file}";
              echo "Erfolg: '${file}' umgewandelt. Backup in '${backupfile}'."  2>&1;
      		rm -f "${tmpfile1}" "${tmpfile2}";
      		exit 0;
      	fi
      fi
      echo "Misserfolg: '${file}' konnte nicht erfolgreich umgewandelt werden.";
      echo "Grund:";
      err=`$phpcli -l "${file}" 1>/dev/null 2>&1`;
      if [ 0 -ne $? ]; then
      	echo "'${file}' enthält folgenden Fehler:";
      	echo $err;
      	rm -f "${tmpfile1}" "${tmpfile2}";
      	exit 16;
      fi
      err=`$phpcli -l "${tmpfile1}" 2>&1`;
      if [ 0 -ne $? ]; then
          echo "Erster Umwandlungsversuch führte zu folgendem Fehler:";
          echo $err;
      fi
      err=`$phpcli -l "${tmpfile2}" 2>&1`;
      if [ 0 -ne $? ]; then
          echo "'Zweiter Umwandlungsversuch führte zu folgenden Fehler:";
          echo $err;
      fi
      rm -f "${tmpfile1}" "${tmpfile2}";
      exit 16;
      

      Zu exekutieren mit:

      find -name *.php -print0 | xargs -0 /PFAD/ZU/php73to74.sh > php73to74.log
      

      Es verbleiben:

      Indexzugriffe auf Funktionsergebnisse werden wohl auch ignoriert, aber so was ist selten und kann von Hand passieren.

      und:

      Whitespace zwischen Variable und { führt ebenso zur Nichterkennung, das ist aber je nach deinem Coding Style irrelevant.

      Von beiden lass ich (vorerst) die Finger, weil ich befürchte, da mehr einzureißen als zu reparieren. Ich hab ja das Logfile...

      1. Hallo Raketenmechaniker,

        1-3 Zeiler

        Ja, so eskaliert das... 😀

        Rolf

        --
        sumpsi - posui - clusi
        1. 1-3 Zeiler

          Ja, so eskaliert das... 😀

          Dafür "wallt" jetzt aber auch der Luxus.

  2. Die (wie immer: vorläufige) Endversion des Skripts zum Beheben der obigen Deprecated-Meldung in PHP 7.4 habe ich veröffentlicht.

    Neue Futures:

    • Kaputte Skripte werden gar nicht erst angefasst.
    • Es werden für jedes Skript die Anderungen ausgegeben (diff)
    • backups werden erzeugt.
    • Rolfs Hinweise habe ich (teils) beachtet.
    • Nicht lauffähige Resultate werden nicht gespeichert.