„Uwaga: Niezdefiniowana zmienna”, „Uwaga: Niezdefiniowany indeks” i „Uwaga: Niezdefiniowane przesunięcie” za pomocą PHP

1173

Korzystam ze skryptu PHP i nadal otrzymuję błędy, takie jak:

Uwaga: Niezdefiniowana zmienna: moja_nazwa_zmiennej w C: \ wamp \ www \ mypath \ index.php w linii 10

Uwaga: Niezdefiniowany indeks: mój_indeks C: \ wamp \ www \ mypath \ index.php w linii 11

Linia 10 i 11 wygląda następująco:

echo "My variable value is: " . $my_variable_name;
echo "My index value is: " . $my_array["my_index"];

Co oznaczają te komunikaty o błędach?

Dlaczego pojawiają się nagle? Używałem tego skryptu od lat i nigdy nie miałem żadnych problemów.

Jak je naprawić?


To jest ogólne pytanie referencyjne dla osób, które należy połączyć jako duplikat, bez konieczności ciągłego wyjaśniania problemu. Uważam, że jest to konieczne, ponieważ większość rzeczywistych odpowiedzi na ten temat jest bardzo konkretna.

Powiązana meta dyskusja:

Pekka 웃
źródło
3
zmienna mogła nie zostać zainicjowana. Czy inicjujesz zmienną z posta, geta czy tablicy? W takim przypadku możesz nie mieć pola w tej tablicy. To twój dostęp.
Anish Silwal,
3
@Pekka 웃 - Zauważyłem edycję, dodając „i” Uwaga: Nieokreślone przesunięcie ”” - Czy nie ma większego sensu przy użyciu „PHP:„ Niezdefiniowana zmienna ”,„ Niezdefiniowany indeks ”,„ Niezdefiniowane przesunięcie ”powiadomienia” (nawet weź poza PHP, ponieważ jest on oznaczony jako „php”. Ponadto adres URL zostaje odcięty and-notice-undef, tylko sugestia, aby adres URL nie został odcięty. Może nawet usunięcie (zbyt wielu) cytatów. LubPHP: “Undefined variable/index/offset” notices
Funk Forty Niner,
2
@Fred Myślę, że można argumentować dla obu wariantów. Istnieje szansa, że ​​nowicjusze wprowadzą całą linię, łącznie z „Uwaga:” do zapytania, które, jestem pewien, jest głównym generatorem ruchu dla tego pytania. Jeśli wiadomości są w całości, prawdopodobnie poprawi to widoczność w wyszukiwarkach
Pekka
2
@Pekka 웃 Rozumiem. Powiedziałem to tylko dlatego, że adres URL nie był wcześniej odcinany, a teraz robi to o and-notice-undef. To była tylko (kilka) sugestia. To po prostu się powtarza Notice: Undefined.
Funk Forty Niner,

Odpowiedzi:

1066

Uwaga: Niezdefiniowana zmienna

Z ogromnej mądrości podręcznika PHP :

Poleganie na domyślnej wartości niezainicjowanej zmiennej jest problematyczne w przypadku włączenia jednego pliku do innego, który używa tej samej nazwy zmiennej. Jest to także poważne zagrożenie bezpieczeństwa przy włączonym register_globals . Błąd poziomu E_NOTICE jest generowany w przypadku pracy z niezainicjowanymi zmiennymi, ale nie w przypadku dołączania elementów do niezainicjowanej tablicy. Konstrukcja języka isset () może być używana do wykrywania, czy zmienna została już zainicjowana. Dodatkowo, bardziej idealne jest rozwiązanie empty (), ponieważ nie generuje ostrzeżenia ani komunikatu o błędzie, jeśli zmienna nie zostanie zainicjowana.

Z dokumentacji PHP :

Jeśli zmienna nie istnieje, nie jest generowane ostrzeżenie. Oznacza to, że empty () jest w istocie zwięzłym odpowiednikiem ! Isset ($ var) || $ var == false .

Oznacza to, że można użyć wyłącznie empty()w celu określenia, czy zmienna jest ustawiona, a ponadto sprawdza zmienną przed Poniżej 0, 0.0, "", "0", null, falselub [].

Przykład:

$o = [];
@$var = ["",0,null,1,2,3,$foo,$o['myIndex']];
array_walk($var, function($v) {
    echo (!isset($v) || $v == false) ? 'true ' : 'false';
    echo ' ' . (empty($v) ? 'true' : 'false');
    echo "\n";
});

Przetestuj powyższy fragment kodu w internetowym edytorze PHP 3v4l.org

Chociaż PHP nie wymaga deklaracji zmiennej, zaleca się ją, aby uniknąć niektórych luk w zabezpieczeniach lub błędów, w których zapomniałby podać wartość zmiennej, która będzie używana później w skrypcie. To, co PHP robi w przypadku niezadeklarowanych zmiennych, powoduje błąd o bardzo niskim poziomie E_NOTICE, który nie jest nawet domyślnie zgłaszany, ale Podręcznik zaleca, aby zezwolić na to podczas programowania.

Sposoby rozwiązania problemu:

  1. Zalecane: zadeklaruj zmienne, na przykład, gdy próbujesz dołączyć ciąg do niezdefiniowanej zmiennej. Lub użyj isset()/, !empty() aby sprawdzić, czy zostały zadeklarowane przed odwołaniem się do nich, jak w:

    //Initializing variable
    $value = ""; //Initialization value; Examples
                 //"" When you want to append stuff later
                 //0  When you want to add numbers later
    //isset()
    $value = isset($_POST['value']) ? $_POST['value'] : '';
    //empty()
    $value = !empty($_POST['value']) ? $_POST['value'] : '';
    

    To stało się znacznie czystsze od PHP 7.0, teraz możesz użyć operatora zerowania koalesce :

    // Null coalesce operator - No need to explicitly initialize the variable.
    $value = $_POST['value'] ?? '';
    
  2. Ustaw niestandardową procedurę obsługi błędów dla E_NOTICE i przekieruj wiadomości poza standardowe wyjście (być może do pliku dziennika):

    set_error_handler('myHandlerForMinorErrors', E_NOTICE | E_STRICT)
  3. Wyłącz E_NOTICE z raportowania. Szybki sposób na wykluczenie E_NOTICEto:

    error_reporting( error_reporting() & ~E_NOTICE )
  4. Pomiń błąd za pomocą operatora @ .

Uwaga: Zdecydowanie zaleca się wdrożenie tylko punktu 1.

Uwaga: Niezdefiniowany indeks / Niezdefiniowane przesunięcie

To powiadomienie pojawia się, gdy Ty (lub PHP) próbujesz uzyskać dostęp do niezdefiniowanego indeksu tablicy.

Sposoby rozwiązania problemu:

  1. Sprawdź, czy indeks istnieje, zanim uzyskasz do niego dostęp. W tym celu możesz użyć isset()lub array_key_exists():

    //isset()
    $value = isset($array['my_index']) ? $array['my_index'] : '';
    //array_key_exists()
    $value = array_key_exists('my_index', $array) ? $array['my_index'] : '';
    
  2. Konstrukcja języka list()może to wygenerować, gdy próbuje uzyskać dostęp do nieistniejącego indeksu tablicowego:

    list($a, $b) = array(0 => 'a');
    //or
    list($one, $two) = explode(',', 'test string');
    

Dwie zmienne są używane do uzyskania dostępu do dwóch elementów tablicy, jednak istnieje tylko jeden element tablicy, indeks 0, więc to wygeneruje:

Uwaga: Nieokreślone przesunięcie: 1

$_POST/ $_GET/ $_SESSIONzmienna

Powyższe uwagi pojawiają się często podczas pracy z $_POST, $_GETlub $_SESSION. Na $_POSTi $_GETpo prostu trzeba sprawdzić, czy indeks istnieje lub przed ich użyciem nie. Dla $_SESSIONtrzeba upewnić się, że sesja rozpoczęła się session_start()i że indeks istnieje również.

Zauważ też, że wszystkie 3 zmienne są superglobalami i są dużymi literami.

Związane z:

Rizier123
źródło
7
@ dieselpower44 Kilka przemyśleń: „Operator zamykający” ( @) ma pewne problemy z wydajnością. Ponadto, ponieważ pomija wszystkie błędy w określonym zakresie, używanie go bez ostrożności może maskować wiadomości, które chciałbyś widzieć.
IMSoP
6
Ukrywanie problemów NIE jest sposobem na rozwiązanie problemów. Przedmiotów # 2 ... # 4 można używać tylko na serwerach produkcyjnych, a nie ogólnie.
Salman A
1
Czy możliwe jest zamknięcie wbudowanego komunikatu (nie w module obsługi), gdy używana jest również niestandardowa procedura obsługi błędów? $var = @$_GET['nonexisting'];wciąż powoduje zawiadomienie ..
Alph.Dev,
18
Dlaczego zaleca się stosowanie 1. $value = isset($_POST['value']) ? $_POST['value'] : '';zamiast używania 4. $value = @$_POST['value'];?
forsvunnet
@twistedpixel Te 4 sposoby są niezależne, to nie jest czterostopniowy przewodnik. Więc jeśli wybrałeś sposób 4, oznacza to, że nie wdrożyłeś pierwszych 3 sposobów, więc nie ukryłeś jeszcze żadnych błędów.
Aycan Yaşıt
141

Spróbuj tych

P1: ta notatka oznacza, że ​​$ varname nie jest zdefiniowany w bieżącym zakresie skryptu.

Q2: Zastosowanie warunków isset (), empty () przed użyciem jakiejkolwiek podejrzanej zmiennej działa dobrze.

// recommended solution for recent PHP versions
$user_name = $_SESSION['user_name'] ?? '';

// pre-7 PHP versions
$user_name = '';
if (!empty($_SESSION['user_name'])) {
     $user_name = $_SESSION['user_name'];
}

Lub jako szybkie i brudne rozwiązanie:

// not the best solution, but works
// in your php setting use, it helps hiding site wide notices
error_reporting(E_ALL ^ E_NOTICE);

Uwaga na temat sesji:

Ish
źródło
Jeśli używasz E_NOTICEz php.inipliku konfiguracyjnego, wykonajerror_reporting = (E_ALL & ~E_NOTICE)
ahmd0
Z powyższej odpowiedzi próbowałem isset, array_key_exists, ale te nie działały. Próbowałem twojej odpowiedzi, .empty () i działa. Dziękuję Ci bardzo!
ewef
63

Błąd wyświetlania @operatora

W przypadku niepożądanych i nadmiarowych powiadomień można użyć @operatora dedykowanego , aby » ukryć « niezdefiniowane komunikaty zmiennych / indeksów.

$var = @($_GET["optional_param"]);
  • Zazwyczaj jest to odradzane. Nowo przybyli często go nadużywają.
  • Jest to bardzo nieodpowiednie dla kodu głęboko w logice aplikacji (ignorowanie niezadeklarowanych zmiennych tam, gdzie nie powinieneś), np. Dla parametrów funkcji lub w pętlach.
  • Jest jednak jedna zaleta w stosunku do supresji isset?:lub ??supresji. Powiadomienia nadal mogą być rejestrowane. I można wskrzesić @ukryte powiadomienia za pomocą:set_error_handler("var_dump");
    • Dodatkowo nie powinieneś zwykle używać / polecać if (isset($_POST["shubmit"]))w swoim początkowym kodzie.
    • Nowo przybyli nie zauważą takich literówek. Po prostu pozbawia cię powiadomień PHP w tych przypadkach. Dodaj @lub issetdopiero po zweryfikowaniu funkcjonalności.
    • Najpierw napraw przyczynę. Nie powiadomienia.

  • @jest głównie akceptowalny dla $_GET/ $_POSTparametrów wejściowych, szczególnie jeśli są one opcjonalne .

A ponieważ obejmuje to większość takich pytań, omówmy najczęstsze przyczyny:

$_GET/ $_POST/ $_REQUESTniezdefiniowane wejście

  • Pierwszą rzeczą, jaką robisz, gdy napotykasz niezdefiniowany indeks / offset, jest sprawdzanie literówek:
    $count = $_GET["whatnow?"];

    • Czy to oczekiwana nazwa klucza obecna na każdym żądaniu strony?
    • W nazwach zmiennych i oznaczeniach tablic rozróżniana jest wielkość liter w PHP.
  • Po drugie, jeśli zawiadomienie nie ma oczywistej przyczyny, użyj var_dumplub print_rzweryfikuj wszystkie tablice wejściowe pod kątem ich bieżącej zawartości:

    var_dump($_GET);
    var_dump($_POST);
    //print_r($_REQUEST);
    

    Oba ujawnią, czy skrypt został wywołany z właściwymi parametrami lub w ogóle.

  • Alternatywnie lub dodatkowo użyj devtools przeglądarki ( F12) i sprawdź kartę sieci pod kątem żądań i parametrów:

    narzędzia programistyczne przeglądarki / karta sieciowa

    Parametry POST i GET zostaną wyświetlone osobno.

  • Dla $_GETparametrów można również zerknąć na QUERY_STRINGIN

    print_r($_SERVER);

    PHP ma pewne zasady łączenia niestandardowych nazw parametrów w superglobale. Apache może również trochę przepisać. Możesz także w ten sposób spojrzeć na dostarczone nieprzetworzone $_COOKIESi inne nagłówki żądań HTTP.

  • Bardziej oczywiście spójrz na pasek adresu przeglądarki, aby uzyskać parametry GET :

    http://example.org/script.php?id=5&sort=desc

    Do name=valuepary po ?znakiem zapytania są zapytania (GET) parametry. Tak więc ten adres URL może tylko przynieść $_GET["id"]i $_GET["sort"].

  • Na koniec sprawdź swoje <form>i<input> deklaracje, jeśli oczekujesz parametru, ale go nie otrzymujesz.

    • Upewnij się, że każde wymagane wejście ma <input name=FOO>
    • id=Lub title=atrybut nie wystarczyć.
    • method=POSTFormularz powinien wypełnić $_POST.
    • Natomiast a method=GET(lub pominięcie go) dałoby $_GETzmienne.
    • Możliwe jest również dostarczenie formularza action=script.php?get=paramza pomocą $ _GET i pozostałych method=POSTpól w $ _POST obok.
    • Dzięki nowoczesnym konfiguracjom PHP (≥ 5.6) stało się możliwe (niemodne) $_REQUEST['vars']ponowne użycie , które łączy parametry GET i POST.
  • Jeśli korzystasz z mod_rewrite, powinieneś sprawdzić zarówno, access.logjak i umożliwić RewriteLogwykrycie nieobecnych parametrów.

$_FILES

  • Te same testy poprawności dotyczą przesyłania plików i $_FILES["formname"].
  • Ponadto sprawdź enctype=multipart/form-data
  • Jak również method=POSTw <form>deklaracji.
  • Zobacz także: Błąd indeksu niezdefiniowanego PHP $ _FILES?

$_COOKIE

  • $_COOKIETablica nie jest wypełniana tuż po setcookie(), ale tylko na każde żądanie nawiązanie HTTP.
  • Dodatkowo upłynął limit czasu ich ważności, mogą one stanowić ograniczenie do poddomen lub pojedynczych ścieżek, a użytkownik i przeglądarka mogą je po prostu odrzucić lub usunąć.
Mario
źródło
2
Jeśli jesteś ciekawy, jaki jest wpływ na wydajność, ten artykuł dobrze to podsumowuje, derickrethans.nl/… .
Gajus
@GajusKuizinas Od 2009 roku wprowadzono kilka zmian, w szczególności php.net/ChangeLog-5.php#5.4.0 drastycznie zmienia wynik (patrz „Silnik Zend, wydajność” i „(cisza)”).
mario
Dzięki @mario, ciekawe. Teraz, jeśli ktoś był wystarczająco dobry, aby przeprowadzić analizę porównawczą dwóch ... 3v4l.org/CYVOn/perf#tabs 3v4l.org/FLp3D/perf#tabs Według tego testu wydaje się być identyczny (zauważ, że zmienia się skala).
Gajus,
47

Zasadniczo z powodu „złego programowania” i możliwości popełnienia błędów teraz lub później.

  1. Jeśli to pomyłka, najpierw wykonaj prawidłowe przypisanie do zmiennej: $ varname = 0;
  2. Jeśli tak naprawdę jest czasami definiowany, przetestuj go: if (isset($varname))przed użyciem
  3. Jeśli to dlatego, że źle to przeliterowałeś, popraw to
  4. Może nawet odwrócenie ostrzeżeń w ustawieniach PHP
Erik
źródło
5
Nie wyłączaj ostrzeżeń. W bardziej rygorystycznych językach często oznaczają „może występować błąd, lepiej sprawdź tę linię dwa razy” - w języku tak tolerancyjnym jak PHP, często oznaczają „ten kod jest gówniany i prawdopodobnie pełen błędów; Spróbuję zrobić trochę tego rozumiem, ale lepiej jak najszybciej to naprawić ”.
5
Chociaż zgadzam się z pierwszymi trzema punktami, punkt 4 jest po prostu błędny. Ukrywanie problemu nie sprawi, że zniknie, a może nawet spowodować więcej problemów na drodze.
Valentin Flachsel
1
@ Frere absolutnie prawda, ale w niektórych scenariuszach (kupiony skrypt, zero wiedzy technicznej, trzeba go uruchomić do jutra ...) jest to rozwiązanie z taśmą klejącą - naprawdę złe, które zawsze wymaga podkreślenia, ale opcja
Pekka
Taśma klejąca jest dobra ... czasami. Historycznie ostrzeżenia zostały wyłączone w standardowych ustawieniach PHP, ale ustawienia odrzucania stały się bardziej surowe. Szkoda, że ​​wielu wraca do starych ustawień, aby nie drażnić klientów.
Erik
41

Oznacza to, że testujesz, oceniasz lub drukujesz zmienną, do której jeszcze niczego nie przypisałeś. Oznacza to, że albo masz literówkę, albo musisz najpierw sprawdzić, czy zmienna została zainicjowana. Sprawdź ścieżki logiczne, może być ustawione w jednej ścieżce, ale nie w innej.

DGM
źródło
34

Nie chciałem wyłączać powiadomienia, ponieważ jest to pomocne, ale chciałem unikać zbyt częstego pisania.

Moim rozwiązaniem była ta funkcja:

function ifexists($varname)
{
  return(isset($$varname)?$varname:null);
}

Więc jeśli chcę odwoływać się do $ name i echo, jeśli istnieje, po prostu piszę:

<?=ifexists('name')?>

W przypadku elementów tablicy:

function ifexistsidx($var,$index)
{
  return(isset($var[$index])?$var[$index]:null);
}

Na stronie, jeśli chcę odwoływać się do $ _REQUEST ['name']:

<?=ifexistsidx($_REQUEST,'name')?>
Ferenci Zoltán László
źródło
2
Twoja funkcja ifexists () nie działa dla mnie w PHP 5.3. Zmienne wywołujące nie są dostępne w lokalnym zasięgu funkcji (patrz Zakres zmiennej ), chyba że są to superglobale lub nie masz nic przeciwko $ GLOBALS , więc $foo = "BABAR"; ifexists('foo');ogólnie zwróci wartość null. (Kursywa to rozdziały
php.net
teraz dostaniesz „cześć z” ... o co chodzi? po prostu sprawdź wartośćif( !empty($user) and !empty($location) ) echo "hello $user ..."
gcb
27

Najlepszym sposobem na uzyskanie ciągu wejściowego jest:

$value = filter_input(INPUT_POST, 'value');

Ten jednowarstwowy jest prawie równoważny z:

if (!isset($_POST['value'])) {
    $value = null;
} elseif (is_array($_POST['value'])) {
    $value = false;
} else {
    $value = $_POST['value'];
}

Jeśli absolutnie chcesz wartość ciągu , podobnie jak:

$value = (string)filter_input(INPUT_POST, 'value');
mpyw
źródło
25

Jest tak, ponieważ zmienna „$ user_location” nie jest definiowana. Jeśli używasz dowolnej pętli if, w której deklarujesz zmienną „$ user_location”, musisz także mieć pętlę else i zdefiniować ją. Na przykład:

$a=10;
if($a==5) { $user_location='Paris';} else { }
echo $user_location;

Powyższy kod spowoduje błąd, ponieważ Pętla if nie jest spełniona, aw pętli else „$ user_location” nie został zdefiniowany. Nadal poproszono PHP o echo zmiennej. Aby zmodyfikować kod, musisz wykonać następujące czynności:

$a=10;
if($a==5) { $user_location='Paris';} else { $user_location='SOMETHING OR BLANK'; }
echo $user_location;
Roger
źródło
25

W odpowiedzi na „” Dlaczego nagle się pojawiają? Używałem tego skryptu od lat i nigdy nie miałem żadnych problemów ”.

Bardzo często w większości witryn działa „domyślne” raportowanie błędów „Pokaż wszystkie błędy, ale nie„ powiadomienia ”i„ przestarzałe ”. Zostanie to ustawione w php.ini i będzie dotyczyć wszystkich stron na serwerze. Oznacza to, że te „powiadomienia” użyte w przykładach zostaną ukryte (ukryte), podczas gdy inne błędy, uważane za bardziej krytyczne, zostaną pokazane / zarejestrowane.

Innym krytycznym ustawieniem jest to, że błędy mogą być ukryte (tj. display_errorsUstawione na „off” lub „syslog”).

W tym przypadku wydarzy się to, że albo error_reportingzostały zmienione, aby wyświetlały również powiadomienia (jak w przykładach) i / lub ustawienia zostały zmienione display_errorsna ekran (w przeciwieństwie do ich pomijania / rejestrowania).

Dlaczego się zmienili?

Oczywistą / najprostszą odpowiedzią jest to, że ktoś zmienił którekolwiek z tych ustawień w php.ini lub ulepszona wersja PHP używa teraz innego php.ini niż wcześniej. To pierwsze miejsce do obejrzenia.

Można jednak również zastąpić te ustawienia w

  • .htconf (konfiguracja serwera WWW, w tym vhosty i podkonfiguracje) *
  • .htaccess
  • w samym kodzie php

i każdy z nich mógł również zostać zmieniony.

Istnieje również dodatkowa komplikacja polegająca na tym, że konfiguracja serwera WWW może włączać / wyłączać dyrektywy .htaccess, więc jeśli masz dyrektywy w .htaccess, które nagle zaczynają / kończą działanie, musisz to sprawdzić.

(.htconf / .htaccess zakłada, że ​​działasz jako apache. Jeśli uruchomisz wiersz poleceń, to nie będzie miało zastosowania; jeśli uruchomisz IIS lub inny serwer WWW, musisz odpowiednio sprawdzić te konfiguracje)

Podsumowanie

  • Dyrektywy Check error_reportingi display_errorsphp w php.ini nie uległy zmianie lub nie używasz innej wersji php.ini niż wcześniej.
  • Dyrektywy Check error_reportingi display_errorsphp w .htconf (lub vhosts itp.) Nie uległy zmianie
  • Dyrektywy Check error_reportingi display_errorsphp w .htaccess nie uległy zmianie
  • Jeśli masz dyrektywę w .htaccess, sprawdź, czy są one nadal dozwolone w pliku .htconf
  • Na koniec sprawdź swój kod; prawdopodobnie niepowiązana biblioteka; aby sprawdzić, czy error_reportingi display_errorsdyrektyw php zostały tam ustawione.
Robbie
źródło
20

szybka poprawka polega na przypisaniu zmiennej do wartości null u góry kodu

$user_location = null;
Shahin Mammadzada
źródło
16

Kiedyś przeklinałem ten błąd, ale pomocne może być przypomnienie, abyś uniknął wprowadzania danych przez użytkownika.

Na przykład, jeśli uważasz, że to sprytne, skróć kod:

// Echo whatever the hell this is
<?=$_POST['something']?>

... Pomyśl jeszcze raz! Lepszym rozwiązaniem jest:

// If this is set, echo a filtered version
<?=isset($_POST['something']) ? html($_POST['something']) : ''?>

(Używam niestandardowej html()funkcji do ucieczki znaków, twój przebieg może się różnić)

rybo111
źródło
15

W PHP 7.0 można teraz używać operatora koalescencji Null:

echo "My index value is: " . ($my_array["my_index"] ?? '');

Równa:

echo "My index value is: " . (isset($my_array["my_index"]) ? $my_array["my_index"] : '');

Podręcznik PHP PHP 7.0

elpiel
źródło
Działa to również dobrze w instrukcjach if. if (is_array($my_array['idontexist'] ?? '')) { dosomething(); }
programista
Twój kod jest właściwie niezauważonym błędem: ?? - sprawdza tylko isset(), jeśli zdasz is_array()- co jest wartością logiczną, nastąpi nieoczekiwane zachowanie.
elpiel
14

Używam zawsze własnej przydatnej funkcji exst (), która automatycznie deklaruje zmienne.

Twój kod będzie -

$greeting = "Hello, ".exst($user_name, 'Visitor')." from ".exst($user_location);


/** 
 * Function exst() - Checks if the variable has been set 
 * (copy/paste it in any place of your code)
 * 
 * If the variable is set and not empty returns the variable (no transformation)
 * If the variable is not set or empty, returns the $default value
 *
 * @param  mixed $var
 * @param  mixed $default
 * 
 * @return mixed 
 */

function exst( & $var, $default = "")
{
    $t = "";
    if ( !isset($var)  || !$var ) {
        if (isset($default) && $default != "") $t = $default;
    }
    else  {  
        $t = $var;
    }
    if (is_string($t)) $t = trim($t);
    return $t;
}
user2253362
źródło
14

W bardzo prostym języku .
Błąd polega na tym, że używasz zmiennej, $user_locationktóra nie została wcześniej zdefiniowana i nie ma żadnej wartości. Zalecam więc zadeklarowanie tej zmiennej przed użyciem , na przykład:


$user_location = '';
Lub
$user_location = 'Los Angles';
Jest to bardzo częsty błąd, z którym możesz się spotkać. Nie martw się, po prostu zadeklaruj zmienną i ciesz się kodowaniem .

Rishabh Seth
źródło
8

dlaczego nie uprościć sprawy?

<?php
error_reporting(E_ALL); // making sure all notices are on

function idxVal(&$var, $default = null) {
         return empty($var) ? $var = $default : $var;
  }

echo idxVal($arr['test']);         // returns null without any notice
echo idxVal($arr['hey ho'], 'yo'); // returns yo and assigns it to array index, nice

?>
gts
źródło
8

DLACZEGO TO SIĘ DZIEJE?

Z czasem PHP stało się językiem bardziej skoncentrowanym na bezpieczeństwie. Ustawienia, które wcześniej były domyślnie wyłączone, teraz są domyślnie włączone. Doskonałym tego przykładem jest E_STRICT, który został domyślnie włączony od wersji PHP 5.4.0 .

Ponadto, zgodnie z dokumentacją PHP, domyślnie E_NOTICEjest wyłączona w php.ini. Dokumenty PHP zalecają włączenie go w celu debugowania . Jednak gdy pobieram PHP z repozytorium Ubuntu - i ze stosu Windows BitNami - widzę coś innego.

; Common Values:
;   E_ALL (Show all errors, warnings and notices including coding standards.)
;   E_ALL & ~E_NOTICE  (Show all errors, except for notices)
;   E_ALL & ~E_NOTICE & ~E_STRICT  (Show all errors, except for notices and coding standards warnings.)
;   E_COMPILE_ERROR|E_RECOVERABLE_ERROR|E_ERROR|E_CORE_ERROR  (Show only errors)
; Default Value: E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED
; Development Value: E_ALL
; Production Value: E_ALL & ~E_DEPRECATED & ~E_STRICT
; http://php.net/error-reporting
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT

Zauważ, że error_reportingtak naprawdę domyślnie jest ustawiona wartość produkcyjna, a nie domyślna wartość „domyślna”. Jest to nieco mylące i nie jest udokumentowane poza php.ini, więc nie sprawdziłem tego w innych dystrybucjach.

Aby odpowiedzieć na twoje pytanie, ten błąd pojawia się teraz, gdy nie pojawiał się wcześniej, ponieważ:

  1. Zainstalowałeś PHP i nowe ustawienia domyślne są nieco słabo udokumentowane, ale nie wykluczają E_NOTICE.

  2. E_NOTICEostrzeżenia takie jak niezdefiniowane zmienne i niezdefiniowane indeksy faktycznie pomagają uczynić kod czystszym i bezpieczniejszym. Mogę ci powiedzieć, że lata temu utrzymywanie E_NOTICEwłączone zmusiło mnie do zadeklarowania moich zmiennych. Dzięki temu dużo łatwiej było nauczyć się C, ponieważ nie deklarowanie zmiennych jest znacznie bardziej uciążliwe.

CO MOGĘ Z TYM ZROBIĆ?

  1. Wyłącz E_NOTICE, kopiując „Wartość domyślną” E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATEDi zastępując ją tym, co jest obecnie niezakomentowane po zalogowaniu do znaku równości error_reporting =. Uruchom ponownie Apache lub PHP, jeśli używasz CGI lub FPM. Upewnij się, że edytujesz „właściwy” plik php.ini. Prawidłowym będzie Apache, jeśli używasz PHP z Apache, fpm lub php-fpm, jeśli używasz PHP-FPM, cgi, jeśli uruchamiasz PHP-CGI itp. To nie jest zalecana metoda, ale jeśli masz starszy kod, który będzie być wyjątkowo trudnym do edycji, to może być twój najlepszy zakład.

  2. Wyłącz E_NOTICEna poziomie pliku lub folderu. Może to być lepsze, jeśli masz jakiś starszy kod, ale chcesz robić rzeczy „we właściwy” sposób. Aby to zrobić, powinieneś skonsultować się z Apache2, Nginx lub jakimkolwiek innym wybranym serwerem. W Apache można użyć php_valuewewnątrz <Directory>.

  3. Przepisz kod, aby był czystszy. Jeśli musisz to zrobić podczas przenoszenia do środowiska produkcyjnego lub nie chcesz, aby ktoś zobaczył Twoje błędy, upewnij się, że wyłączasz wyświetlanie błędów i rejestrujesz tylko błędy (zobacz display_errorsi log_errorsw php.ini i ustawieniach serwera) .

Aby rozwinąć opcję 3: Jest to ideał. Jeśli możesz wybrać tę trasę, powinieneś. Jeśli początkowo nie wybierasz tej trasy, rozważ przemieszczenie tej trasy, testując kod w środowisku programistycznym. Gdy już to robisz, pozbądź się ~E_STRICTi ~E_DEPRECATEDzobacz, co może pójść nie tak w przyszłości. Zobaczysz Mnóstwo nieznanych błędów, ale powstrzyma Cię to od nieprzyjemnych problemów, kiedy będziesz musiał zaktualizować PHP w przyszłości.

CO OZNACZAJĄ BŁĘDY?

Undefined variable: my_variable_name- Dzieje się tak, gdy zmienna nie została zdefiniowana przed użyciem. Kiedy skrypt PHP jest wykonywany, wewnętrznie przyjmuje po prostu wartość zerową. Jednak w jakim scenariuszu trzeba by sprawdzić zmienną przed jej zdefiniowaniem? Ostatecznie jest to argument za „niechlujnym kodem”. Jako programista mogę powiedzieć, że uwielbiam, gdy widzę projekt typu open source, w którym zmienne są zdefiniowane tak wysoko, jak to możliwe. Ułatwia określenie, które zmienne będą się pojawiać w przyszłości, oraz ułatwia czytanie / uczenie się kodu.

function foo()
{
    $my_variable_name = '';

    //....

    if ($my_variable_name) {
        // perform some logic
    }
}

Undefined index: my_index- Dzieje się tak, gdy próbujesz uzyskać dostęp do wartości w tablicy i nie istnieje ona. Aby zapobiec temu błędowi, wykonaj sprawdzenie warunkowe.

// verbose way - generally better
if (isset($my_array['my_index'])) {
    echo "My index value is: " . $my_array['my_index'];
}

// non-verbose ternary example - I use this sometimes for small rules.
$my_index_val = isset($my_array['my_index'])?$my_array['my_index']:'(undefined)';
echo "My index value is: " . $my_index_val;   

Inną opcją jest zadeklarowanie pustej tablicy u góry funkcji. Nie zawsze jest to możliwe.

$my_array = array(
    'my_index' => ''
);

//...

$my_array['my_index'] = 'new string';

(dodatkowa wskazówka)

  • Kiedy napotykałem te i inne problemy, korzystałem z NetBeans IDE (darmowy), co dało mi wiele ostrzeżeń i uwag. Niektóre z nich oferują bardzo pomocne wskazówki. Nie jest to wymagane i nie używam już IDE, z wyjątkiem dużych projektów. W vimdzisiejszych czasach jestem bardziej osobą :).
smcjones
źródło
6

niezdefiniowany indeks oznacza na przykład w tablicy, o którą prosiłeś o niedostępny indeks tablicy

<?php 

$newArray[] = {1,2,3,4,5};
print_r($newArray[5]);

?>

niezdefiniowana zmienna oznacza, że ​​użyto całkowicie nieistniejącej zmiennej lub która nie jest zdefiniowana lub zainicjowana na przykład przez tę nazwę

<?php print_r($myvar); ?>

niezdefiniowane przesunięcie oznacza w tablicy, o którą prosiłeś o nieistniejący klucz. A rozwiązaniem tego jest sprawdzenie przed użyciem

php> echo array_key_exists(1, $myarray);
Sintayehu Abaynhe
źródło
4

W odniesieniu do tej części pytania:

Dlaczego pojawiają się nagle? Używałem tego skryptu od lat i nigdy nie miałem żadnych problemów.

Brak jednoznacznych odpowiedzi, ale oto kilka możliwych wyjaśnień, dlaczego ustawienia mogą „nagle” zmienić:

  1. Zaktualizowałeś PHP do nowszej wersji, która może mieć inne ustawienia domyślne dla raportowania błędów, błędów wyświetlania lub innych odpowiednich ustawień.

  2. Usunąłeś lub wprowadziłeś jakiś kod (być może zależny), który ustawia odpowiednie ustawienia w czasie wykonywania, używając ini_set()lub error_reporting()(wyszukaj je w kodzie)

  3. Zmieniłeś konfigurację serwera WWW (zakładając tutaj apache): .htaccesspliki i konfiguracje vhostów mogą również manipulować ustawieniami php.

  4. Zwykle powiadomienia nie są wyświetlane / zgłaszane (patrz instrukcja PHP ), więc możliwe jest, że podczas konfigurowania serwera plik php.ini nie mógł zostać załadowany z jakiegoś powodu (uprawnienia do pliku?) I masz ustawienia domyślne . Później „błąd” został rozwiązany (przez przypadek), a teraz MOŻE załadować poprawny plik php.ini z zestawem raportowania błędów wyświetlającym powiadomienia.

Wouter de Winter
źródło
3

Jeśli pracujesz z klasami, musisz upewnić się, że odwołujesz się do zmiennych członka za pomocą $this:

class Person
{
    protected $firstName;
    protected $lastName;

    public function setFullName($first, $last)
    {
        // Correct
        $this->firstName = $first;

        // Incorrect
        $lastName = $last;

        // Incorrect
        $this->$lastName = $last;
    }
}
John Conde
źródło
3

Innym powodem, dla którego zostanie wyświetlone niezdefiniowane powiadomienie o indeksie, jest pominięcie kolumny w zapytaniu do bazy danych.

To znaczy:

$query = "SELECT col1 FROM table WHERE col_x = ?";

Następnie próbuje uzyskać dostęp do większej liczby kolumn / wierszy w pętli.

To znaczy:

print_r($row['col1']);
print_r($row['col2']); // undefined index thrown

lub w whilepętli:

while( $row = fetching_function($query) ) {

    echo $row['col1'];
    echo "<br>";
    echo $row['col2']; // undefined index thrown
    echo "<br>";
    echo $row['col3']; // undefined index thrown

}

Należy również zauważyć, że w systemach * NIX OS i Mac OS X rozróżniana jest wielkość liter.

Zapoznaj się z poniższymi pytaniami i odpowiedziami na stosie:

Fred -ii-
źródło
3

Używanie trójki jest proste, czytelne i czyste:

Przed PHP 7
Przypisz zmienną do wartości innej zmiennej, jeśli jest ustawiona, w przeciwnym razie przypisznull(lub dowolnąinną domyślną wartość):

$newVariable = isset($thePotentialData) ? $thePotentialData : null;

PHP 7+
To samo, z wyjątkiem korzystania z Null Coalescing Operator . Nie ma już potrzeby wywoływania, isset()ponieważ jest ono wbudowane, i nie trzeba podawać zmiennej do zwrócenia, ponieważ zakłada się, że zwróci wartość sprawdzanej zmiennej:

$newVariable = $thePotentialData ?? null;

Oba zatrzymają powiadomienia od pytania PO i oba są dokładnym odpowiednikiem:

if (isset($thePotentialData)) {
    $newVariable = $thePotentialData;
} else {
    $newVariable = null;
}

 
Jeśli nie potrzebujesz ustawiać nowej zmiennej, możesz bezpośrednio użyć zwróconej wartości trójki, takiej jak echoargumenty funkcji, itd:

Echo:

echo 'Your name is: ' . isset($name) ? $name : 'You did not provide one';

Funkcjonować:

$foreName = getForeName(isset($userId) ? $userId : null);

function getForeName($userId)
{
    if ($userId === null) {
        // Etc
    }
}

Powyższe będzie działać tak samo z tablicami, w tym sesjami itp., Zamieniając sprawdzaną zmienną na np .:
$_SESSION['checkMe']
lub jak wiele poziomów potrzebujesz, np .:
$clients['personal']['address']['postcode']


 

Tłumienie:

Możliwe jest pomijanie powiadomień PHP za pomocą @lub zmniejszanie poziomu zgłaszania błędów, ale to nie rozwiązuje problemu , po prostu przestaje być zgłaszane w dzienniku błędów. Oznacza to, że Twój kod nadal próbował użyć zmiennej, która nie została ustawiona, co może oznaczać, że coś nie działa zgodnie z przeznaczeniem - w zależności od tego, jak istotna jest brakująca wartość.

Naprawdę powinieneś sprawdzić ten problem i odpowiednio go obsłużyć, albo dostarczając inny komunikat, albo nawet zwracając wartość zerową dla wszystkiego innego, aby zidentyfikować dokładny stan.

Jeśli zależy Ci tylko na tym, aby Powiadomienie nie było w dzienniku błędów, możesz po prostu zignorować dziennik błędów.

James
źródło
1

Jedną z częstych przyczyn zmiennej nieistniejącej po przesłaniu formularza HTML jest to, że element formularza nie jest zawarty w <form>znaczniku:

Przykład: element nie zawarty w <form>

<form action="example.php" method="post">
    <p>
        <input type="text" name="name" />
        <input type="submit" value="Submit" />
    </p>
</form>

<select name="choice">
    <option value="choice1">choice 1</option>
    <option value="choice2">choice 2</option>
    <option value="choice3">choice 3</option>
    <option value="choice4">choice 4</option>
</select>

Przykład: element zawarty w <form>

<form action="example.php" method="post">
    <select name="choice">
        <option value="choice1">choice 1</option>
        <option value="choice2">choice 2</option>
        <option value="choice3">choice 3</option>
        <option value="choice4">choice 4</option>
    </select>
    <p>
        <input type="text" name="name" />
        <input type="submit" value="Submit" />
    </p>
</form>
John Conde
źródło
0

Prawdopodobnie korzystałeś ze starej wersji PHP do tej pory, a teraz zaktualizowałeś PHP, dlatego od lat działa bezbłędnie. do PHP4 nie było błędu, jeśli używasz zmiennej bez jej zdefiniowania, ale od PHP5 wyrzuca ona błędy dla kodów takich jak wspomniane w pytaniu.

phvish
źródło
0

Podczas pracy z plikami wymagany jest odpowiedni kod i metoda POST, która wyzwoli niezdefiniowane powiadomienie o indeksie, jeśli którekolwiek z nich nie zostanie zawarte w formularzu.

Podręcznik zawiera następującą podstawową składnię:

HTML

<!-- The data encoding type, enctype, MUST be specified as below -->
<form enctype="multipart/form-data" action="__URL__" method="POST">
    <!-- MAX_FILE_SIZE must precede the file input field -->
    <input type="hidden" name="MAX_FILE_SIZE" value="30000" />
    <!-- Name of input element determines name in $_FILES array -->
    Send this file: <input name="userfile" type="file" />
    <input type="submit" value="Send File" />
</form>

PHP

<?php
// In PHP versions earlier than 4.1.0, $HTTP_POST_FILES should be used instead
// of $_FILES.

$uploaddir = '/var/www/uploads/';
$uploadfile = $uploaddir . basename($_FILES['userfile']['name']);

echo '<pre>';
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
    echo "File is valid, and was successfully uploaded.\n";
} else {
    echo "Possible file upload attack!\n";
}

echo 'Here is some more debugging info:';
print_r($_FILES);

print "</pre>";

?>

Odniesienie:

Funk Forty Niner
źródło
0

Zadałem pytanie na ten temat i zostałem skierowany do tego postu z komunikatem:

To pytanie ma już odpowiedź tutaj:

„Uwaga: Niezdefiniowana zmienna”, „Uwaga: Niezdefiniowany indeks” i „Uwaga: Niezdefiniowane przesunięcie” za pomocą PHP

Tutaj dzielę się moim pytaniem i rozwiązaniem:

To jest błąd:

wprowadź opis zdjęcia tutaj

Problem stanowi linia 154. Oto co mam w linii 154:

153    foreach($cities as $key => $city){
154        if(($city != 'London') && ($city != 'Madrid') && ($citiesCounterArray[$key] >= 1)){

Myślę, że problem polega na tym, że piszę, jeśli warunki dla zmiennej $city, która nie jest kluczem, ale wartością w $key => $city. Po pierwsze, czy możesz potwierdzić, czy to jest przyczyną ostrzeżenia? Po drugie, jeśli to jest problem, dlaczego nie mogę napisać warunku na podstawie wartości? Czy to musi być klucz, który muszę napisać warunek?

AKTUALIZACJA 1: Problem polega na tym, że podczas wykonywania $citiesCounterArray[$key]czasami $keyodpowiada on kluczowi, który nie istnieje w $citiesCounterArraytablicy, ale nie zawsze tak jest w oparciu o dane mojej pętli. Potrzebuję ustawić warunek, aby jeśli $keyistnieje w tablicy, uruchom kod, w przeciwnym razie pomiń go.

AKTUALIZACJA 2: Tak to naprawiłem, używając array_key_exists():

foreach($cities as $key => $city){
    if(array_key_exists($key, $citiesCounterArray)){
        if(($city != 'London') && ($city != 'Madrid') && ($citiesCounterArray[$key] >= 1)){
Jaime Montoya
źródło
0

Błędy te występują zawsze, gdy używamy zmiennej, która nie jest ustawiona.

Najlepszym sposobem radzenia sobie z nimi jest ustawianie raportowania błędów podczas programowania.

Aby ustawić raportowanie błędów:

ini_set('error_reporting', 'on');
ini_set('display_errors', 'on');
error_reporting(E_ALL);

Na serwerach produkcyjnych raportowanie błędów jest wyłączone, dlatego nie otrzymujemy tych błędów.

Na serwerze deweloperskim możemy jednak ustawić raportowanie błędów.

Aby pozbyć się tego błędu, widzimy następujący przykład:

if ($my == 9) {
 $test = 'yes';  // Will produce error as $my is not 9.
}
echo $test;

Możemy zainicjować zmienne NULLprzed przypisaniem ich wartości lub użyciem.

Możemy więc zmodyfikować kod jako:

$test = NULL;
if ($my == 9) {
 $test = 'yes';  // Will produce error as $my is not 9.
}
echo $test;

Nie zakłóci to żadnej logiki programu i nie wygeneruje Powiadomienia, nawet jeśli $testnie ma wartości.

Zasadniczo zawsze lepiej jest WŁĄCZYĆ raportowanie błędów w celu opracowania.

I napraw wszystkie błędy.

W przypadku produkcji raportowanie błędów powinno być wyłączone.

Uczeń
źródło
-1

Te powiadomienia są spowodowane tym, że nie masz użytej zmiennej, defineda my_indexklucz nie był obecny w $my_arrayzmiennej.

Te powiadomienia były uruchamiane za każdym razem, ponieważ Twoje dane codenie są poprawne, ale prawdopodobnie nie masz włączonego raportowania powiadomień.

Rozwiąż błędy:

$my_variable_name = "Variable name"; // defining variable
echo "My variable value is: " . $my_variable_name;

if(isset($my_array["my_index"])){
    echo "My index value is: " . $my_array["my_index"]; // check if my_index is set 
}

Innym sposobem na uzyskanie tego:

ini_set("error_reporting", false)
Andrei Todorut
źródło
-2

W PHP potrzebujesz pięści, aby zdefiniować zmienną, po której możesz jej użyć.
Możemy sprawdzić, czy zmienna jest zdefiniowana lub nie w bardzo wydajny sposób!

//If you only want to check variable has value and value has true and false value.
//But variable must be defined first.

if($my_variable_name){

}

//If you want to check variable is define or undefine
//Isset() does not check that variable has true or false value
//But it check null value of variable
if(isset($my_variable_name)){

}

Proste objaśnienie

//It will work with :- true,false,NULL
$defineVarialbe = false;
if($defineVarialbe){
    echo "true";
}else{
    echo "false";
}

//It will check variable is define or not and variable has null value.
if(isset($unDefineVarialbe)){
    echo "true";
}else{
    echo "false";
}
Manish Goswami
źródło