Пхп местами странноватый язык который странновато эволюционирует.
$a = new class { public readonly object $b; public readonly object $c; public function __construct() { $this->b = new class { public function helloworld() { return 'hello world'; } }; } };
Вот если у нас есть объект в котором есть 2 проперти, одно из которых инициализировано, а другое нет.
С инициализированным проперти всё просто и понятно:
echo $a->b?->helloworld(); // hello world
А вот если вы так же сделаете для неинициализированного то оно умрёт:
echo $a->c?->helloworld(); // Typed property class@anonymous::$c must not be accessed before initialization
Неудобно когда умирает поэтому приходится делать дополнительную проверку:
if (isset($a->c)) { echo echo $a->c->helloworld(); }
Ещё более неудобно когда хочешь проверить есть ли какой-то объект и проверить что-то в этом объекте, то начинается…
if (isset($a->c) && $a->c->isValid()) { return true; }
По непонятно причине ?->
умирает если оно неиницилизовано и не заменяет isset()
, а вот ??
не умирает и вполне себе живёт и заменяет isset()
поэтому…
echo ($a->c ?? null)?->helloworld(); if (($a->c ?? null)?->isValid()) { return true; }
Какой же ад, нравится!
2024.12.10 18:01
Допустим у вас есть моделька
class Model { public int $id; public string $title; public function getValue(string $property): mixed { return $this->$property; } }
И вам очень сильно совсем надоело хардкодить проперти и ещё больше сильнее совсем надоело их рефакторить:
$model = new Model(); $model->id = 42; $model->title = 'my title'; $id = $model->getValue('id'); $title = $model->getValue('title'); var_dump($id, $title);
То есть преккрасное убогое решение которое поможет вам обманывать вашу IDE: автодополнение и рефакторинг работают. Но не всегда, конечно, а только в контексте исполнения.
trait PropertyNameTrait { public static function __property(): object { return new class { public function __get(string $property): string { return $property; } }; } } /** @method static Model __property() */ class Model { use PropertyNameTrait; public int $id; public string $title; public function getValue(string $property): mixed { return $this->$property; } } $model = new Model(); $model->id = 42; $model->title = 'my title'; $id = $model->getValue($model::__property()->id); $title = $model->getValue(Model::__property()->title); var_dump($id, $title);
Конечно, можно добавить ещё немного магии, но у вас не получится аккуратно чейнить __get()
в трейте и классе, так что это уже по желанию (мне не очень нравится, но пользоваться этим сильно более красивее). (ну и надо не забыть кидать фатал на 404, но мне лень писать эти проверки).
/** @property-read Model $__property */ class Model { public int $id; public string $title; public function getValue(string $property): mixed { return $this->$property; } public function __get(string $property): mixed { if ($property === '__property') { return new class { public function __get(string $property): string { return $property; } }; } throw new Error("404: {$property}"); } } $model = new Model(); $model->id = 42; $model->title = 'my title'; $id = $model->getValue($model->__property->id); $title = $model->getValue($model->__property->title); var_dump($id, $title);
2021.10.20 13:50
В похапе вводят строгую типизацию, но путь предстоит ещё крайне длинный. Судя по всему идти по нему можно будет всегда.
1. Что больше, единица или массив?
< ?php declare(strict_types = 1); $max = max(1, 2, ['array']); print_r($max); // Array // ( // [0] => array // )
2. Бесконечный цикл это просто и удобно.
< ?php declare(strict_types = 1); for ($i = 0; $i < ['array']; $i++) { echo "$i."; if ($i === 10) { break; } } // 0.1.2.3.4.5.6.7.8.9.10.
Больно.
2021.06.23 13:02
Ничего нового, но до сих пор великолепно
var_dump((bool)'0'); // bool(false) var_dump((bool)0); // bool(false) var_dump((bool)'00'); // bool(true) var_dump((bool)00); // bool(false) var_dump((bool)'0x0'); // bool(true) var_dump((bool)0x0); // bool(false)
сердечко
2021.04.26 15:58
Д – Дизайн
/** * https://github.com/symfony/symfony/blob/5.0/src/Symfony/Component/Security/Core/Authentication/Token/TokenInterface.php#L45-L53 * Returns a user representation. * * @return string|object Can be a UserInterface instance, an object implementing a __toString method, * or the username as a regular string * * @see AbstractToken::setUser() */ public function getUser();
Н – Наслаждение
// Authorized echo get_class($tokenStorage->getToken()->getUser()); // App\Entity\User // Anonymous echo $tokenStorage->getToken()->getUser(); // 'anon.'
О – Очарование
// https://github.com/symfony/symfony/blob/5.0/src/Symfony/Bundle/FrameworkBundle/Controller/AbstractController.php#L361-L377 protected function getUser() { if (!$this->container->has('security.token_storage')) { throw new \LogicException('The SecurityBundle is not registered in your application. Try running "composer require symfony/security-bundle".'); } if (null === $token = $this->container->get('security.token_storage')->getToken()) { return null; } if (!\is_object($user = $token->getUser())) { // e.g. anonymous authentication return null; } return $user; }
2020.02.06 19:59
Я, конечно, понимаю что уже поздновато размораживаться, но, оказывается, существует волшебная штука json-schema
которой можно валидироавть структуру json’а.
Но особенно прекрасно то что оно сущетсвует для php и что ещё более прекрасно — в php оно проверяет не json, а обычный \stdClass
.
То есть если вам нужно проверить структуру сложного объекта, с проверкой типов, возможностью кастинга и использованием дефолтных значений — json-scheme
может спасти вам здоровье, психику и остатки волос.
И оно даже соберет все ошибки, укажет в чем проблема и даст вам путь к неправильному элементу.
2019.10.16 16:58