es
Feedback
KRUHLYK 🇺🇦

KRUHLYK 🇺🇦

Ir al canal en Telegram
1 203
Suscriptores
+224 horas
-17 días
+7930 días
Archivo de publicaciones
Mensaje de video00:53

Стрімимо завтра о 15:00. Почнемо будувати мобільну апку для Комуналки з самого початку. Чекатиму всіх! https://youtube.com/live/o2j68J2JONU

Mensaje de video01:00

Тут ще й YouTube подгончик накинув. Тепер можу вам на коментарі голосом відповідати. Ну кайф же ж. Доречі, завтра стрімимо?
Тут ще й YouTube подгончик накинув. Тепер можу вам на коментарі голосом відповідати. Ну кайф же ж. Доречі, завтра стрімимо?

А тим часом мою бібліотечку по роботі з платіжкою WayForPay для C# та .NET прям качають. Приємно. Значить вчився і тренувався
А тим часом мою бібліотечку по роботі з платіжкою WayForPay для C# та .NET прям качають. Приємно. Значить вчився і тренувався не дарма. А що зараз вчите ви? Які нові навички в собі тренуєте? 😉

Хана. Я тепер з дивану не встану.

Вінду не люблю, але тут майки молодці. Кому треба сенйор, щоб вчитися? Пишіть в особисті! 😎
Вінду не люблю, але тут майки молодці. Кому треба сенйор, щоб вчитися? Пишіть в особисті! 😎

sticker.webp0.51 KB

Така відповідь Claude Code мені подобається (блядь!)
Така відповідь Claude Code мені подобається (блядь!)

Ви мабуть вже зрозуміли, що я дуже люблю творчість Митця Леся Подервʼянського. Так от чувак написав ІМБІЩУ для Claude Code. Д
Ви мабуть вже зрозуміли, що я дуже люблю творчість Митця Леся Подервʼянського. Так от чувак написав ІМБІЩУ для Claude Code. Дуже раджу! https://dev.ua/news/mytets-plugin-1771839543

Шо по кавусі?
Шо по кавусі?

А поки анонс на завтрашні заплановані пости
А поки анонс на завтрашні заплановані пости

Claude треба українізувати. Відправлю до своєї вчительки української. Перебілдю... 🙄
Claude треба українізувати. Відправлю до своєї вчительки української. Перебілдю... 🙄

Тут якраз корисні тіпси як обмеження в 5 годин обійти запостили на DOU. Користуйтесь! https://dou.ua/forums/topic/58050/?from=tg

Mensaje de video00:46

Repost from N/a
#випитали Отже, що таке PHP атрибути? Атрибути — це метадані, які ти можеш навішувати на класи, методи, властивості та аргументи. По суті — "анотації нового покоління" (як у Java або C#), але повністю типізовані. PHP вже обросло багатьма корисними нативними атрибутами. До прикладу, чи не щодня я користуюсь #[Deprecated]. Але, як створити кастомний атрибут? Давайте розберемо на простому прикладі. Нам потрібен атрибут, який буде перевіряти роль юзера (через пакет від Spatie чи кастомну логіку. Тут неважливо). Створюєш клас-атрибут. Він обов’язково має бути позначений #[Attribute].
<?php

namespace App\Attributes;

use Attribute;

#[Attribute(Attribute::TARGET_METHOD)]
class RequiresRole
{
    public function __construct(
        public string $role
    ) {}
}
#[Attribute] робить цей клас атрибутом. `TARGET_METHOD`― наш атрибут можна вішати лише на методи. В конструктор передаємо дані (role), і вони доступні в Reflection. Можеш також вказати:
Attribute::TARGET_CLASS
Attribute::TARGET_PROPERTY
Attribute::TARGET_PARAMETER
Attribute::TARGET_FUNCTION
Attribute::IS_REPEATABLE
Використання атрибуту. Припустимо, у контролері:
use App\Attributes\RequiresRole;

class UserController
{
    #[RequiresRole('admin')]
    public function destroy(int $id): void
    {
        // ...
    }
}
Або загадаємо минулу тему. Зчитування атрибуту через Reflection. Десь у middleware або сервісі авторизації:
$controller = app(UserController::class);
$method     = new \ReflectionMethod($controller, 'destroy');

$attributes = $method->getAttributes(RequiresRole::class);

if (!empty($attributes)) {
    $instance = $attributes[0]->newInstance();

    $requiredRole = $instance->role;

    // Далі робиш свою логіку
    if (auth()->user()->role !== $requiredRole) {
        abort(403);
    }
}
$instance->role — це значення, яке ми передали у #[RequiresRole('admin')]. Куди це інтегрується в Laravel? - Middleware (авторизація) Підтягує controlled method → читає атрибути → вирішує, пускати чи ні. - Кастомні роутери Можна зробити систему маршрутизації через атрибути замість Route::get(). - Генерація документації Типу OpenAPI через атрибути на методах. - Валідація Можна робити:
#[MinLength(10)]
public string $name;
Маленький лайфхак. Хочеш, щоб атрибут можна було повторювати? Наприклад:
#[Tag('admin')]
#[Tag('billing')]
Пиши так:
#[Attribute(Attribute::IS_REPEATABLE | Attribute::TARGET_METHOD)]
class Tag
{
    public function __construct(public string $name) {}
}

Repost from N/a
<?php

namespace App\Http\Controllers;

use App\Attributes\Permission;
use App\Models\User;
use Illuminate\Http\RedirectResponse;
use Illuminate\View\View;

class UserController extends Controller
{
    #[Permission('users.delete')]
    public function destroy(User $user): RedirectResponse
    {
        // Якщо ми сюди дійшли — значить permission пройшов перевірку
        $user->delete();

        return redirect()
            ->route('users.index')
            ->with('status', 'User deleted');
    }

    #[Permission('users.view')]
    public function show(User $user): View
    {
        return view('users.show', compact('user'));
    }
}
Тут логіка проста: - На метод destroy навішено #[Permission('users.delete')] - Middleware це прочитає й перевірить. - Якщо користувач не має permission users.delete — 403. Підключаємо middleware до route. У routes/web.php:
use App\Http\Controllers\UserController;
use Illuminate\Support\Facades\Route;

Route::middleware(['auth', 'permission.attribute'])
    ->group(function () {
        Route::delete('/users/{user}', [UserController::class, 'destroy'])
            ->name('users.destroy');

        Route::get('/users/{user}', [UserController::class, 'show'])
            ->name('users.show');
    });
Тут важливий момент: Middleware викликається, а вже всередині він дивиться, чи є атрибут у поточного методу. Мінімальний метод hasPermission для юзера в моделі.
<?php

namespace App\Models;

use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    // ...

    public function hasPermission(string $permission): bool
    {
        // Дуже примітивно: припустимо, у нас є json-поле permissions
        // в БД і там масив прав типу ['users.view', 'users.delete']

        $permissions = $this->permissions ?? [];

        if (is_string($permissions)) {
            $permissions = json_decode($permissions, true) ?: [];
        }

        return in_array($permission, $permissions, true);
    }
}
У реальному житті ти, звісно, скоріше за все: - або прикрутиш Spatie Permissions, - або політики (policy), - або ролі/групи. Що ти з цього маєш зрозуміти: 1. Атрибут — просто клас з #[Attribute], який вішається над методом. 2. Reflection — дає змогу прочитати цей атрибут під час виконання. 3. Middleware — хороше місце, щоб інтерпретувати атрибути контролера перед тим, як виконати метод. 4. Логіка вийшла: роут → middleware permission.attribute → дивиться атрибути на методі → перевіряє права → або 403, або пускає.

Repost from N/a
А тепер розберемо більш практичні приклади. Зробимо реальний робочий приклад під Laravel: атрибут Permission, Middleware, реєстрація і використання в контролері. Буду йти крок за кроком, щоб ти міг це повторити в реальному проєкті. 1. Створюємо атрибут Permission
<?php

namespace App\Attributes;

use Attribute;

#[Attribute(Attribute::TARGET_METHOD)]
class Permission
{
    public function __construct(
        public string $name
    ) {}
}
Що тут відбувається: #[Attribute(...)] — позначає, що це PHP-атрибут. TARGET_METHOD — цей атрибут можна вішати тільки на методи (наприклад, методи контролера). public string $name `— сюди ми передаємо назву права доступу, типу: 'users.delete'`. 2. Створюємо middleware, який читає атрибут
<?php

namespace App\Http\Middleware;

use App\Attributes\Permission;
use Closure;
use Illuminate\Http\Request;
use ReflectionMethod;
use Symfony\Component\HttpFoundation\Response;

class CheckPermissionAttribute
{
    public function handle(Request $request, Closure $next): Response
    {
        $route = $request->route();

        // Якщо раптом route без контролера (closure і т.п.)
        if (! $route) {
            return $next($request);
        }

        $controller = $route->getController();
        $methodName = $route->getActionMethod();

        // Якщо це не контролерний метод — не чіпаємо
        if (! $controller || ! $methodName) {
            return $next($request);
        }

        $reflectionMethod = new ReflectionMethod($controller, $methodName);

        // Дістаємо всі атрибути типу Permission
        $attributes = $reflectionMethod->getAttributes(Permission::class);

        // Якщо атрибутів нема — просто пропускаємо далі
        if (empty($attributes)) {
            return $next($request);
        }

        /** @var Permission $permissionAttributeInstance */
        $permissionAttributeInstance = $attributes[0]->newInstance();

        $permissionName = $permissionAttributeInstance->name;

        // Тут вже твоя логіка перевірки прав
        // Можна через Spatie Permission, через policy,
        // або просто поле role/permissions у юзера

        $user = $request->user();

        if (! $user) {
            abort(401); // неавторизований
        }

        // Варіант 1: якби був Spatie:
        // if (! $user->can($permissionName)) { ... }

        // Для простоти: припустимо в юзера є метод hasPermission(string $name)
        if (! method_exists($user, 'hasPermission') || ! $user->hasPermission($permissionName)) {
            abort(403, 'Forbidden');
        }

        return $next($request);
    }
}
Ключове тут: - Дістаємо контролер та метод з $request->route(). - Через ReflectionMethod читаємо атрибут Permission. - Якщо атрибут є — витягуємо назву права і перевіряємо користувача. - Якщо користувач не має права → abort(403). Реєструємо middleware в bootstrap/app.php:
return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        api: __DIR__.'/../routes/api.php',
        // ...
    )
    ->withMiddleware(function (Middleware $middleware) {
        $middleware->alias([
            'permission.attribute' => \App\Http\Middleware\CheckPermissionAttribute::class,
        ]);
    })
    ->create();
Тепер у роутів є middleware з назвою permission.attribute. Використання в контролері.

Repost from N/a
5. Автоматична генерація документації / OpenAPI Багато бібліотек (Swagger Generator, Blueprint) використовують Reflection, щоб: - читати типи параметрів - генерувати схеми моделей - документувати ендпоінти згідно з атрибутами Тобто документування на основі коду — це повністю Reflection. 6. Validation Rules: автоматичний аналіз моделей Уяви випадок: ти хочеш створити форму CRUD, і на основі моделі автоматично будувати rules.
$model = new User();
$reflection = new ReflectionClass($model);

foreach ($reflection->getProperties() as $property) {
    // Можна аналізувати типи, атрибути і генерувати правила
}
Такі штуки роблять адмін-панелі типу Laravel Nova або Fillament. 7. Тестування — мокінг приватних методів (коли дуже треба) По-перше, якщо тобі треба тестувати приватні методи, то задай собі питання "що зі мною не так?". По-друге, якщо ну ОТ ПРЯМ ДУУУУУЖЕ треба, то: Reflection дозволяє отримати доступ навіть до приватних методів:
$method = new ReflectionMethod(MyService::class, 'calculateInternal');
$method->setAccessible(true);
$result = $method->invoke(new MyService(), 10);
Так — це милиця, але інколи потрібно для складної логіки. Підсумую просто: Reflection реально потрібна коли ти хочеш: - автоматично реєструвати класи (Route, Command, Providers) - читати атрибути (PHP Attributes) - реалізувати власний DI-container або розширити Laravel-івський - будувати код, базуючись на структурі інших класів - генерувати документацію - створювати фреймворк-подібні компоненти Коли НЕ треба використовувати Reflection? Коли ти можеш просто написати код руками — пиши руками. Reflection повільніший і ускладнює дебаг. Його місце — у фреймворках, інструментах, генераторах, а не у кожному другому контролері.