Hodnota 0 se tváří jako null
- ForestCZE
- Člen | 209
Ahoj, mám metodu v modelu:
public function getEmployees(?int $jobGrade, ?string $search)
{
if(!$jobGrade && !$search)
return $this->database->getCharacters()->where('job = ? OR job1 = ? OR job2 = ?', self::JOB, self::JOB, self::JOB);
if($jobGrade)
return $this->database->getCharacters()->where('(job = ? AND job_grade = ?) OR (job1 = ? AND job_grade1 = ?) OR (job2 = ? AND job_grade2 = ?)', self::JOB, $jobGrade, self::JOB, $jobGrade, self::JOB, $jobGrade)->fetchAll();
if($search)
{
$s = explode(" ", $search);
if(count($s) == 1)
return $this->database->getCharacters()->where('(job = ? OR job1 = ? OR job2 = ?) AND (LOWER(lastname) LIKE ? OR LOWER(firstname) LIKE ?)', self::JOB, self::JOB, self::JOB, '%' . strtolower($s[0]) . '%', '%' . strtolower($s[0]) . '%')->fetchAll();
else
return $this->database->getCharacters()->where('(job = ? OR job1 = ? OR job2 = ?) AND (LOWER(lastname) LIKE ? AND LOWER(firstname) LIKE ?) OR (LOWER(lastname) LIKE ? AND LOWER(firstname) LIKE ?)', self::JOB, self::JOB, self::JOB, '%' . strtolower($s[0]) . '%', '%' . strtolower($s[1]) . '%', '%' . strtolower($s[1]) . '%', '%' . strtolower($s[0]) . '%')->fetchAll();
}
}
Poté podmínku a zavolání v presentru:
public function actionEmployees($jg, $search, $page = 1): void
{
if(!$jg && !$search)
$this->employees = $this->character->getEmployees(intval($jg), $search)->page($page, 20, $this->employeesLastPage);
else
$this->employees = $this->character->getEmployees(intval($jg), $search);
}
Když mám v url jg=0
, tak to bere jako že se podmínka
splnila a neskočí to do else. Jenže !$jg
přeci není to samé
jako jg=0
.
Co dělám špatně?
Editoval ForestCZE (15. 6. 2021 22:31)
- Marek Bartoš
- Nette Blogger | 1280
Doporučuju prostudovat tyto zdroje: https://www.php.net/…parisons.php a https://www.php.net/….boolean.php#…
Vykřičník funguje tak, že hodnotu zkonvertuje na bool a zneguje.
V podstatě tedy (bool) $jg === false
. PHP při konverzi hodnot
používá loose comparisons, což v praxi znamená, že při konverzi na bool
se z jakékoli „prázdné“ hodnoty stane false – false, null, prázdný
string, prázdné pole, nula a překvapivě i prázdný SimpleXML element.
Abys na to, kde zrovna konverze je bezpečná nebo není nemusel myslet, je lepší se jí vyhnout úplně. Vykřičník by se měl používat pouze na bool (s přivřenýma očima bool|null) a místo dvojitého provnávání (==, !=, <=, atd) použít trojité (===, !==, <==)
V tvém případě bys tedy napsal $jg !== null
.
Takovéhle problémy ti umí podchytit phpstan, tenhle konkrétní problém myslím řeší balíček phpstan-strict-rules. Doporučuju si na to udělat čas, phpstan používat a doplnit si všude datové typy. Umí to ušetřit hodně starostí.
- ForestCZE
- Člen | 209
Marek Bartoš napsal(a):
Doporučuju prostudovat tyto zdroje: https://www.php.net/…parisons.php a https://www.php.net/….boolean.php#…
Vykřičník funguje tak, že hodnotu zkonvertuje na bool a zneguje. V podstatě tedy
(bool) $jg === false
. PHP při konverzi hodnot používá loose comparisons, což v praxi znamená, že při konverzi na bool se z jakékoli „prázdné“ hodnoty stane false – false, null, prázdný string, prázdné pole, nula a překvapivě i prázdný SimpleXML element.Abys na to, kde zrovna konverze je bezpečná nebo není nemusel myslet, je lepší se jí vyhnout úplně. Vykřičník by se měl používat pouze na bool (s přivřenýma očima bool|null) a místo dvojitého provnávání (==, !=, <=, atd) použít trojité (===, !==, <==)
V tvém případě bys tedy napsal
$jg !== null
.Takovéhle problémy ti umí podchytit phpstan, tenhle konkrétní problém myslím řeší balíček phpstan-strict-rules. Doporučuju si na to udělat čas, phpstan používat a doplnit si všude datové typy. Umí to ušetřit hodně starostí.
Jestli jsem to pochopil správně, tak by mělo pomoct upravit podmínku
if(!$jobGrade && !$search)
na
if($jg === null && !$search)
pak to do else skočí, ale databáze zavolá:
SELECT * FROM `users` WHERE (`job` = 'ambulance' OR `job1` = 'ambulance' OR `job2` = 'ambulance')
místo:
SELECT * FROM `users` WHERE ((`job` = 'ambulance' AND `job_grade` = 0) OR (`job1` = 'ambulance' AND `job_grade1` = 0) OR (`job2` = 'ambulance' AND `job_grade2` = 0))
takže metoda vrátí první return, nikoliv druhý. I v té metodě ve třídě musím nějak upravit ty podmínky?
Editoval ForestCZE (15. 6. 2021 23:22)
- Marek Znojil
- Člen | 90
Na yt kanále Nette je fajn přednáška ohledně tohoto tématu:
https://www.youtube.com/watch?…