22 677 Монеток
Сегодня была выпущена вторая мажорная версия PHPStan — популярного статического анализатора кода для PHP, который помогает находить ошибки до выполнения, проверяя типы данных и структуру.
Первая версия была выпущена чуть больше трех лет назад, и теперь, с выходом второй мажорной версии, нас ожидают новые возможности и улучшения 🚀
Ранее последним уровнем быть 9-й который проверял только явное использование типа mixed
, но пропускал случаи, когда тип данных не указан вообще. Новый уровень исправляет это, проверяя также неявно типизированные значения.
Для более точной работы с массивами теперь можно указывать новый тип данных — list
. Это массив с целочисленными ключами, начиная с 0, без пропусков. Пример:
/** @param list<int> $listOfIntegers */
public function doFoo(array $listOfIntegers): void
{
}
Свежая версия теперь использует на 50–70% меньше памяти при анализе крупных проектов, что значительно улучшает производительность, особенно в условиях CI.
@var
Улучшили проверку типов, указанных в комментариях @var
. Это помогает избежать ситуаций, когда тип в комментарии не совпадает с фактическим типом переменной в коде.
Пример:
/** @var string|null $a */
$a = doFoo();
// PHPStan сообщит, что тип string|null не совпадает с типом string в реальной переменной.
@phpstan-pure
для чистых функцийДля чистых функций теперь доступна аннотация @phpstan-pure
. Она указывает, что функция должна всегда возвращать одно и то же значение при одинаковых входных данных и не должна иметь побочных эффектов.
В версии 2.0 улучшена работа с кешем — старые элементы теперь удаляются 😊 и, как результат, экономится дисковое пространство!
Заметки о выпуске впечатляют — более 180 изменений! 😲 Так что если вы не фанат Psalm (его конкурента), переходите по ссылке на инструкцию по обновлению для подробностей 😊
22 677 Монеток
Атрибуты в PHP — это отличный способ добавлять метаданные к вашим классам, методам и свойствам. Laravel предоставляет множество готовых атрибутов, которые можно использовать для улучшения структуры и читаемости вашего кода.
(ObservedBy)
Атрибут ObservedBy
позволяет указать наблюдателя для модели. Это помогает держать код модели чистым, перенося логику наблюдателя в отдельный класс.
use App\Observers\UserObserver;
use Illuminate\Database\Eloquent\Attributes\ObservedBy;
#[ObservedBy([UserObserver::class])]
class User extends Authenticatable
{
// ...
}
(ScopedBy)
Атрибут ScopedBy
позволяет назначить глобальные условия для модели. Это полезно, когда нужно применять общие ограничения к запросам для конкретной модели.
namespace App\Models;
use App\Models\Scopes\ActiveScope;
use Illuminate\Database\Eloquent\Attributes\ScopedBy;
#[ScopedBy([ActiveScope::class])]
class User extends Model
{
// ...
}
Laravel упрощает процесс внедрения зависимостей в зависимости от контекста, например, для внедрения драйверов или настроек. Вместо того чтобы вручную настраивать такие зависимости в сервис-провайдерах, Laravel предлагает ряд контекстных атрибутов, которые облегчают эту задачу.
Пример:
namespace App\Http\Controllers;
use Illuminate\Container\Attributes\Auth;
use Illuminate\Container\Attributes\Cache;
use Illuminate\Container\Attributes\Config;
use Illuminate\Container\Attributes\DB;
use Illuminate\Container\Attributes\Log;
use Illuminate\Container\Attributes\Tag;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Contracts\Cache\Repository;
use Illuminate\Contracts\Database\Connection;
use Psr\Log\LoggerInterface;
class PhotoController extends Controller
{
public function __construct(
#[Auth('web')] protected Guard $auth,
#[Cache('redis')] protected Repository $cache,
#[Config('app.timezone')] protected string $timezone,
#[DB('mysql')] protected Connection $connection,
#[Log('daily')] protected LoggerInterface $log,
#[Tag('reports')] protected iterable $reports,
)
{
// ...
}
}
Laravel также поддерживает автоматическое внедрение текущего пользователя в маршруты:
use App\Models\User;
use Illuminate\Container\Attributes\CurrentUser;
Route::get('/user', function (#[CurrentUser] User $user) {
return $user;
})->middleware('auth');
(DeleteWhenMissingModels)
При использовании моделей в заданиях вы можете добавить атрибут DeleteWhenMissingModels
, чтобы задание автоматически удалялось, если указанная модель отсутствует в базе данных.
namespace Acme;
use Illuminate\Queue\Attributes\DeleteWhenMissingModels;
#[DeleteWhenMissingModels]
class ProcessPodcastJob
{
public function __construct(
public Podcast $podcast,
) {}
}
(WithoutRelations)
Атрибут WithoutRelations
позволяет загрузить модель без её связей. Это удобно, если вам не нужны связанные данные в фоновых задачах.
class ProcessPodcastJob
{
public function __construct(
#[WithoutRelations]
public Podcast $podcast,
) {}
}
Новые атрибуты постепенно появляются, что бы упростить работу с кодом.
А какие атрибуты хотели бы видеть вы? 💡
{message}