$a=0; if ($a == 'string') { è vero

Come mai accade questo?

<?php
<?
//attention about this case!

$a=0;

if($a=="some string..."){ /* (...) -> true! */ }
if($a==="some string..."){ /* (...) -> false */ }
?>

Stavo andando al manicomio poi ho visto sul manuale un tipo che diceva di stare attenti a questo caso.

Nel mio caso infatti c'è un controllo sulla chiave di un array.

il controllo è:

if ($key == 'chiave')

visto però che $key = 0;

 il controllo passa lo stesso!!!

assurdo!

inviato 10 anni fa
arjuna
modificato 10 anni fa
X 0 X

se ho capito bene tu fai una cosa tipo:

$a = 0;
if($a == "0") 
 echo "uguale";

giusto?

Se il problema è questo, l'operatore di confronto che devi usare "===".

L'operatore "===" a differenza di "==" controlla che i due dati che stai confrontando abbiano lo stesso valore e che siano dello stesso tipo (interi,stringhe,ecc..).

Facendo così quando confronti $a con "0" (in formato stringa) ti restituirà false,non passando il controllo.

risposto 10 anni fa
ice
ice
1
modificato 10 anni fa
X 0 X

no,

l'esempio che faccio io è:

$a=0;

if ($a = "stringa")

  echo "uguale";

stringa puè essere 'hello word' o qualsiasi altra cosa oggettivamente non uguale ad uno 0 sia reso come 0 che come '0'!!!

il fatto è che qualsiasi cosa metta al posto di stringa, l'if è sempre vera!!!

vedere qui:

http://www.php.net/manual/it/language.operators.comparison.php#61879

risposto 10 anni fa
arjuna
X 0 X

Ah urka, non avevo capito cosa intendevi.

Comunque questa cosa mi è nuova, se ne scopri il motivo di questo comportamento strano facci sapere.  ;)

risposto 10 anni fa
ice
ice
1
X 0 X

Il PHP ha due operatori per il confronto: == e ===

L'operatore === confronta sia il tipo di dato che il suo contenuto. Quindi se gli operandi confrontati non sono perfattamente identici, cioè dello stesso tipo (2 interi, due stringhe, due booleani, due float) e con lo stesso valore allora restituisce false.

L'operatore == invece è meno restrittivo nel confronto, infatti non vincola gli operandi ad essere dello stesso tipo. E' possibile quindi confrontare operandi di tipi diversi ma ciò necessita delle regole per cambiare ad esempio una stringa in un numero o in un float o in un booleano.

Quando vengono confrontati interi con stringhe è la stringa ad essere convertita in intero prima che venga effettuato il confronto dei valori. In questa conversione se la stringa non inizia con dei numeri ma con delle lettere oppure se è vuota viene covertita in 0

 :bye:

risposto 10 anni fa
Gianni Tomasicchio
modificato 10 anni fa
X 0 X

ora è tutto chiaro... che strano però...

perchè 'stringa' convertita in numero deve  fare 0? secondo quale oscena logica?

risposto 10 anni fa
arjuna
X 0 X

Anche farla diventare 1 quando non contiene nessun numero sarebbe abbastanza illogico  :dunno:

risposto 10 anni fa
Gianni Tomasicchio
X 0 X

Semplicemente perché il PHP ha una tipizzazione debole delle variabili.

Avendolo voluto mantenere semplice, in PHP non esistono le stringhe, gli interi, le virgole mobili eccetera.

Ma dei valori che possono assumere l'essere considerati stringhe e/o numeri.

0 è un intero di valore zero, ma '0' in PHP è una stringa, insomma il valore per te è lo stesso ma per il PHP una volta è un numero e una volta una stringa, dipende dal contesto di potrebbe dire.

Se noti, ci sono un'infinità di operatori di confronto, proprio perché il problem è sentito.

risposto 10 anni fa
Marco Grazia
X 0 X

adesso capisco... però cmq non mi torna...

se php legge 0 e lo interpreta come numero, perchè una stringa la deve vedere come uno 0?

non sarebbe più sensato FALSE come risultato?

risposto 10 anni fa
arjuna
X 0 X

false è un booleano mentre il confronto è fra un intero e una stringa. Ecco perché la stringa diventa 0

Se invece la stringa deve essere convertita in booleano allora diveta false se è vuota o se contiene il carattere 0, altrimenti diventa true

 :bye:

risposto 10 anni fa
Gianni Tomasicchio
X 0 X

Be veramente non è vero, false e true sono due valori interi che valgono 1 e 0.

Per comodità, hanno introdotto le costanti false e true, che prima non c'erano in PHP, ma i loro valori "interni" sono sempre due numeri.

Ora se fai un classico confronto del tipo if ($variabile) il PHP si aspetta di ritorno o uno zero o un uno. Per questo i confronti tra valori booleani dovrebbero essere sempre fatti così; per un controllo interno, PHP sa che un confronto del genere deve sempre dare 1 o 0.

Il problema arriva se $variabile contiene un valore arbitrario, per esempio una stringa o un numero diverso da 0 e 1, se leggi il manuale, trovi spesso che alcune funzioni, che ritornano un valore, come per esempio la fopen, viene sconsigliato di usarle per il controllo true o false, perché possono verificarsi dei falsi positivi.

Ad esempio if($fp = fopen(pippo)) per scoprire se $fp è l'handle valido di un file o se c'è un problema, può dare dei problemi, perché zero, che è il valore per false (ovvero handle non generato), potrebbe essere invece proprio l'handle del file, che è comunque un valore numerico esadecimale e 0, cioè zero, è un handle esadecimale valido. Tutti i manuali poi ne sconsigliano l'uso nel controllo delle query ai database, proprio perché può capitare che zero, debba essere proprio il valore cercato e non già un errore.

Insomma True e False sono due valori imposti per necessità stilistica, ma che vanno usati con accortezza e nel giusto modo.

In un confronto, se proprio non si volesse usare il classico ($boolean) è meglio confrontarli con il triplo uguale ($boolean === true) o ($boolean !== false) per evitare ambiguità con le stringhe.

Mentre: $boolean = '0'; if ($boolean == false) è verificato ma non è vero!

risposto 10 anni fa
Marco Grazia
X 0 X

Il fatto che il PHP utilizzi gli interi 0 e 1 all'interno dello Zend Engine per gestire i tipi booleani non significa che a livello dello script non ci sia differenza tra true/false e 1/0. PHP è pienamente consapevole della differenza, basta fare qualche test:

<?php
$array = array(1,1.234,'test',true,null);
var_dump($array);
?>
risultato:
array(5) {
  [0]=>
  int(1)
  [1]=>
  float(1.234)
  [2]=>
  string(4) "test"
  [3]=>
  bool(true)
  [4]=>
  NULL
}

Anche i confronti restituiscono un valore booleano:

<?php
var_dump(1 == '1');
?>
restituisce:
bool(true)

Il problema dei valori restituiti dalle funzioni che possono alterare il comportamento di costrutti quali l'IF deriva proprio dal fatto che in certe condizioni PHP vuole un booleano, non un intero 1/0. Tant'è che se non gli viene fornito provvede lui stesso ad effettuare il cast, in booleano appunto.

Ed infatti:

<?php
if('test') echo 1;
if((int)'test') echo 2;
if((bool)'test') echo 3;
?>
risultato:
13

che conferma che la stringa subisce una conversione in booleano, non in intero. Infatti una stringa non nulla e diversa da '0' diventa true, mentre la sua conversione in intero produce 0 che in booleano diventa false.

 :bye:

risposto 10 anni fa
Gianni Tomasicchio
X 0 X

ma tu hai mai provato a fare ciò che ho inserito io?

risposto 10 anni fa
Marco Grazia
X 0 X
ma tu hai mai provato a fare ciò che ho inserito io?

cioè?

risposto 10 anni fa
Gianni Tomasicchio
X 0 X
ma tu hai mai provato a fare ciò che ho inserito io?

cioè?

Vedere i risultati tra $boolean = '0'; ($boolean == true) e ($boolean === true) e vedere che risultati ti da

risposto 10 anni fa
Marco Grazia
X 0 X

Se si fa un confronto tra un booleano (true) e una stringa '0', la stringa viene prima convertita in booleano. La stringa '0' in booleano vale false pertanto ($boolean == true) vale false.

<?php
$boolean = '0';
var_dump($boolean == true); // false
var_dump($boolean === true); // false

$boolean = 'a';
var_dump($boolean == true); // true
var_dump($boolean === true); // false
?>

 :bye:

risposto 10 anni fa
Gianni Tomasicchio
X 0 X

Ma è proprio su valori errati o comunque non booleani che da errore.

Infatti (a) non può essere false e nemmeno true, ma da true se usi solo l'operatore == proprio perché non è zero.

risposto 10 anni fa
Marco Grazia
X 0 X
Effettua l'accesso o registrati per rispondere a questa domanda