Czy konieczne jest zadeklarowanie tablicy PHP przed dodaniem wartości z []?

84
$arr = array(); // is this line needed?
$arr[] = 5;

Wiem, że działa bez pierwszej linii, ale często jest to uwzględnione w praktyce.

Jaki jest powód? Czy bez niej jest to niebezpieczne?

Wiem, że możesz też to zrobić:

 $arr = array(5);

ale mówię o przypadkach, w których trzeba dodawać elementy jeden po drugim.

ryanve
źródło
2
Jeśli nie lubisz powiadomień o niezadeklarowanych zmiennych, polecam zainicjowanie. Poza tym po prostu tworzy czytelny kod (jasne jest, że $foo = array()i że nie był to ciąg zamieniony na tablicę itp.).
Brad Christie
6
@Brad Christie: Tyle że to nie powoduje takiego powiadomienia.
BoltClock
3
@BoltClock: Zależy od wersji, nad którą pracujesz .
Brad Christie

Odpowiedzi:

92

Jeśli nie zadeklarujesz nowej tablicy, a dane, które tworzą / aktualizują tablicę, zawiodą z jakiegokolwiek powodu, to każdy przyszły kod, który będzie próbował użyć tablicy, będzie działać, E_FATALponieważ tablica nie istnieje.

Na przykład foreach()zgłosi błąd, jeśli tablica nie została zadeklarowana i nie dodano do niej żadnych wartości. Jednak żadne błędy nie wystąpią, jeśli tablica jest po prostu pusta, jak miałoby to miejsce w przypadku jej zadeklarowania.

djdy
źródło
Zaopiniowano, ponieważ foreachprzykład i fakt, że wywoływany jest błąd, są najwyraźniej zależne od używanej wersji PHP.
Charles Sprayberry
1
Nie rozumiem tej odpowiedzi. Nie zadeklarowane i nie dodane coś oznacza, że ​​nie wpisałem w kodzie źródłowym.
Gordon
2
@Gordon, przykład czegoś, co nie zadziała poprawnie, jeśli $ coś nie jest równe 1: if ($ coś == 1) {$ rows [] = "a"; $ wiersze [] = "b"; } foreach ($ rows as $ row) {} Błędu można było uniknąć, gdyby $ wiersze zadeklarowano jako $ wiersze = tablica (); przed stwierdzeniem if.
djdy
1
Zgadzam się (oddałem głos), ale życie jest zbyt krótkie, aby deklarować wszystko przez cały czas, mimo że wiemy, że jest to „właściwe” postępowanie. Alternatywnie, zgaduję, że możesz użyć is_array (), jeśli martwisz się o niezadeklarowane tablice. Jak większość rzeczy, zależy od szczegółów.
PJ Brunet
25

Chciałem tylko zaznaczyć, że dokumentacja PHParrays faktycznie mówi o tym w dokumentacji.

Ze strony PHP, z towarzyszącym fragmentem kodu:

$arr[key] = value;
$arr[] = value;
// key may be an integer or string
// value may be any value of any type

„Jeśli $arrjeszcze nie istnieje, zostanie utworzony, więc jest to również alternatywny sposób tworzenia tablicy”.

Ale, jak stwierdzono w innych odpowiedziach ... naprawdę powinieneś zadeklarować wartość swoich zmiennych, ponieważ jeśli tego nie zrobisz, mogą się wydarzyć wszelkiego rodzaju złe rzeczy.

Charles Sprayberry
źródło
14

PHP to język o luźnej typie. Jest to całkowicie do przyjęcia. Biorąc to pod uwagę, prawdziwi programiści zawsze deklarują swoje vars.

AlienWebguy
źródło
1
@Gordon dokładnie to, o czym myślałem;)
AlienWebguy
Przepraszamy, ale "prawdziwe" programy kodują w taki sposób, że w 99% przypadków nie muszą deklarować vars. I zwykle używaj obiektu, który obsługuje potencjalne puste dane, takie jak null
James
Świetna historia stary.
AlienWebguy
7

Pomyśl o koderach, którzy cię ścigają! Jeśli po prostu zobaczysz $arr[] = 5, nie masz pojęcia, co $arrmogłoby być bez przeczytania całego poprzedniego kodu w zakresie. Wyraźna $arr = array()linia wyjaśnia to.

Rob Agar
źródło
2
W PHP 5.4.x - 5.6.x: $ arr = [] też działa.
Anthony Rutledge,
4

to po prostu dobra praktyka. Załóżmy, że dołączałeś do tablicy wewnątrz pętli (dość powszechna praktyka), a następnie uzyskujesz dostęp do tablicy poza wspomnianą pętlą. Bez deklaracji tablicy Twój kod zgłosiłby błędy, gdybyś nigdy nie trafił do pętli.

Julien
źródło
3

Zdecydowanie zalecamy zadeklarowanie tablicy przed dodaniem wartości. Poza wszystkim wymienionym powyżej, jeśli tablica jest wewnątrz pętli, możesz niechcący wepchnąć elementy do swojej tablicy. Właśnie zauważyłem, że tworzy to kosztowny błąd.

//Example code    
foreach ($mailboxes as $mailbox){
       //loop creating email list to get
       foreach ($emails as $email){
          $arr[] = $email;
       }
       //loop to get emails
       foreach ($arr as $email){
       //oops now we're getting other peoples emails
       //in other mailboxes because we didn't initialize the array
       }
}
ykay, mówi Przywróć Monikę
źródło
Nie rób czego?
ryanve
1

Nie zadeklarowanie tablicy przed jej użyciem może naprawdę spowodować problemy. Jedno doświadczenie, które właśnie znalazłem, nazwałem ten skrypt testowy w ten sposób: indextest.php? File = 1STLSPGTGUS Działa to zgodnie z oczekiwaniami.

//indextest.php?file=1STLSPGTGUS
$path['templates']     = './mytemplates/';
$file['template']      = 'myindex.tpl.php';
$file['otherthing']      = 'otherthing';
$file['iamempty']    = '';

print ("path['templates'] = " . $path['templates'] . "<br>");
print ("file['template'] = " . $file['template'] . "<br>");
print ("file['otherthing'] = " . $file['otherthing'] . "<br>");
print ("file['iamempty'] = " . $file['iamempty'] . "<br>");

print ("file['file'] = " . $file['file'] . "<br>");// should give: "Notice: Undefined index: file"
print ("file = " . $file);// should give: "Notice: Undefined index: file"

//the Output is:
/*
path['templates'] = ./mytemplates/
file['template'] = myindex.tpl.php
file['otherthing'] = otherthing
file['iamempty'] =

Notice: Undefined index: file in D:\Server\Apache24\htdocs\DeliverText\indextest.php on line 14
file['file'] =

Notice: Array to string conversion in D:\Server\Apache24\htdocs\DeliverText\indextest.php on line 15
file = Array
*/

Teraz będę potrzebował tylko pliku z innego kupionego przeze mnie skryptu, na górze mojego i możemy zobaczyć, jak wartości są całkowicie błędne dla tablicy $ file, podczas gdy tablica $ ścieżka jest OK: "checkgroup.php" jest winny.

//indextest.php?file=1STLSPGTGUS
require_once($_SERVER['DOCUMENT_ROOT']."/IniConfig.php");
$access = "PUBLIC";
require_once(CONFPATH . "include_secure/checkgroup.php");
$path['templates']     = './mytemplates/';
$file['template']      = 'myindex.tpl.php';
$file['otherthing']      = 'otherthing.php';
$file['iamempty']    = '';

print ("path['templates'] = " . $path['templates'] . "<br>");
print ("file['template'] = " . $file['template'] . "<br>");
print ("file['otherthing'] = " . $file['otherthing'] . "<br>");
print ("file['iamempty'] = " . $file['iamempty'] . "<br>");

print ("file['file'] = " . $file['file'] . "<br>");
print ("file = " . $file);

//the Output is:
/*
path['templates'] = ./mytemplates/
file['template'] = o
file['otherthing'] = o
file['iamempty'] = o
file['file'] = o
file = oSTLSPGTGUS
*/

Inicjalizacja macierzy wcześniej, to żaden problem!

//indextest.php?file=1STLSPGTGUS
require_once($_SERVER['DOCUMENT_ROOT']."/IniConfig.php");
$access = "PUBLIC";
require_once(CONFPATH . "include_secure/checkgroup.php");

$path = array();
$file = array();

$path['templates']     = './mytemplates/';
$file['template']      = 'myindex.tpl.php';
$file['otherthing']      = 'otherthing.php';
$file['iamempty']    = '';

print ("path['templates'] = " . $path['templates'] . "<br>");
print ("file['template'] = " . $file['template'] . "<br>");
print ("file['otherthing'] = " . $file['otherthing'] . "<br>");
print ("file['iamempty'] = " . $file['iamempty'] . "<br>");

print ("file['file'] = " . $file['file'] . "<br>");
print ("file = " . $file);

//the Output is:
/*
path['templates'] = ./mytemplates/
file['template'] = myindex.tpl.php
file['otherthing'] = otherthing.php
file['iamempty'] =
file['file'] =
file = Array
*/

W ten sposób zdałem sobie sprawę, jak ważne jest zainicjowanie zmiennych, ponieważ nigdy nie wiemy, z jakim problemem możemy się później spotkać, a po prostu chcąc zaoszczędzić czas, możemy ostatecznie stracić jeszcze więcej. Mam nadzieję, że będzie to pomocne dla osób takich jak ja, które nie są profesjonalistami.

Dan Bon
źródło
1

Stare pytanie, ale podzielam to, ponieważ jest to jeden przypadek użycia, w którym kod jest prostszy, jeśli tablice nie są zadeklarowane.

Załóżmy, że masz listę obiektów, które chcesz zindeksować w jednej z ich właściwości.

// $list is array of objects, all having $key property.
$index = [];
foreach ($list as $item)
    $index[$item->key][] = $item; // Dont care if $index[$item->key] already exists or not.
jaisson
źródło
0

To zależy od sprawdzania błędów. Jeśli masz raportowanie błędów w trybie ścisłym, otrzymasz powiadomienie, ale technicznie powinno nadal działać bez niego.

brenjt
źródło
0

Jest to dobre w przypadku, gdy potrzebujesz jej jako zmiennej globalnej lub chcesz wielokrotnie używać tej samej tablicy w różnych funkcjach

Vinit
źródło
0

To jest twój kod

$var[]  = 2;
print_r($var)

Działa w porządku! dopóki ktoś nie zadeklaruje tej samej nazwy zmiennej przed Twoim uroczym kodem

$var = 3; 

$var[]  = 2;
print_r($var)

Ostrzeżenie: nie można użyć wartości skalarnej jako tablicy

Ups!

Jest to jeden możliwy (czasami nieprzewidywalny) przypadek, więc tak $var = array()jest potrzebne

$var = 3;
$var = array();
$var[]  = 2;
print_r($var)

Wynik

Array
(
    [0] => 2
)
Deszcz
źródło
0

W przypadku foreachpętli, jeśli nie masz pewności co do danych, możesz to zrobić:

foreach($users ?? [] as $user) {
    // Do things with $user
}

Jeśli $usersnie jest ustawiona (null coalesce robi isset($users)), otrzymasz pustą tablicę, []a zatem PHP nie zapętli jej, foreachponieważ nie ma nic do zapętlenia - żadnych błędów, ostrzeżeń ani powiadomień.

Nie zgadzam się z niektórymi w komentarzach / odpowiedziach, nie sądzę, abyś po prostu deklarował puste tablice lub inicjalizował zmienne tylko ze względu na to, jako rodzaj siatki bezpieczeństwa. Moim zdaniem takie podejście to złe programowanie. Zrób to wyraźnie, gdy jest to konieczne.

I szczerze mówiąc, jeśli musisz zainicjować pustą tablicę, zastanów się, czy kod nie mógłby mieć lepszej struktury, w jaki sposób będziesz sprawdzać dane później lub cokolwiek innego.

Poniższy kod jest bezcelowy, nie pokazuje "zamiaru", może po prostu zmylić ludzi co do tego, dlaczego został zainicjowany (w najlepszym przypadku jest to po prostu coś bez sensu do czytania i przetwarzania):

$user = [];
$user['name'] = ['bob'];

Druga linia również deklaruje nową tablicę i nigdy nie zawiedzie.

James
źródło
-3

Zgadzam się z @djdy, tylko jedna alternatywa, którą chciałbym opublikować:

<?php

// Passed array is empty, so we'll never have $items variable available.
foreach (array() AS $item)
    $items[] = $item;

isset($items) OR $items = array(); // Declare $items variable if it doesn't exist

?>
Otar
źródło
1
Jaki jest sens tego wszystkiego? Wydaje się dużo hałasu, dosłownie nic.
BoltClock
Zamiast wstępnie deklarować zmienną $ items, sprawdzisz istnienie pętli, to wszystko.
Otar
array()jest pustą tablicą, foreachnigdy nic nie zrobi?
James,