Пхп местами странноватый язык который странновато эволюционирует.
$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