WP actions hooks and filter hooks

There are two types of hooks: Actions and Filters.

Actions allow you to add data or change how WordPress operates.

Filters give you the ability to change data during the execution of WordPress Core, plugins, and themes.

function add_action( $hook_name, $callback, $priority = 10, $accepted_args = 1 ) {
    return add_filter( $hook_name, $callback, $priority, $accepted_args );
}

function has_action( $hook_name, $callback = false ) {
	return has_filter( $hook_name, $callback );
}
public function has_filters() {
    foreach ($this->callbacks as $callbacks) {
        if ($callbacks) {
            return true;
        }
    }

    return false;
}

#php #wordpress #why

2025.11.27 12:17

php & Typed property $var must not be accessed before initialization

Пхп местами странноватый язык который странновато эволюционирует.

$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;
}

Какой же ад, нравится!

#php

english version

2024.12.10 18:01

php: get property name as string

Допустим у вас есть моделька

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);

#php #magic

2021.10.20 13:50

php.strict_types = 1

В похапе вводят строгую типизацию, но путь предстоит ещё крайне длинный. Судя по всему идти по нему можно будет всегда.

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.

Больно.

#php

2021.06.23 13:02

php autocast

Ничего нового, но до сих пор великолепно

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)

сердечко

#php

2021.04.26 15:58

php.symfony.getCurrentUser()

Д – Дизайн

/**
 * 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;
}

#php #symfony #vostorg

2020.02.06 19:59

php + json-schema

Я, конечно, понимаю что уже поздновато размораживаться, но, оказывается, существует волшебная штука json-schema которой можно валидироавть структуру json’а.

Но особенно прекрасно то что оно сущетсвует для php и что ещё более прекрасно — в php оно проверяет не json, а обычный \stdClass.

То есть если вам нужно проверить структуру сложного объекта, с проверкой типов, возможностью кастинга и использованием дефолтных значений — json-scheme может спасти вам здоровье, психику и остатки волос.

И оно даже соберет все ошибки, укажет в чем проблема и даст вам путь к неправильному элементу.

  1. https://mamchenkov.net/wordpress/2017/03/11/validating-json-against-schema-in-php/
  2. https://github.com/justinrainbow/json-schema
  3. http://json-schema.org/understanding-json-schema/

#php #json #vostorg

2019.10.16 16:58