Создание блога

firep91613

Новичок
Плохо ли использовать try catch в методе модели-репозитория и в методе контроллера одновременно? Допустим, удаление же это несколько связанных операций. Я сделал в модели-репозитории транзакцию с try catch. В контроллере, в случае успешного удаления надо сделать редирект с одним флеш сообщеним, а в случае ошибки удаления - с другим сообщением. Ну и исключение тоже надо перехватить.
 

AmdY

Пью пиво
Команда форума
Плохо ли использовать try catch в методе модели-репозитория и в методе контроллера одновременно? Допустим, удаление же это несколько связанных операций. Я сделал в модели-репозитории транзакцию с try catch. В контроллере, в случае успешного удаления надо сделать редирект с одним флеш сообщеним, а в случае ошибки удаления - с другим сообщением. Ну и исключение тоже надо перехватить.
Можно использовать. Но тебе стоит рассмотреть вариант с глобальной ловлей исключений на уровне выше контроллера. Посмотри как делают в Laravel https://laravel.com/docs/master/errors
 

firep91613

Новичок
Как по людски идентифицировать исключение? Бросается, к примеру, такой эксепшен:
PHP:
throw new CategoryException("Ошибка при удалении категории {$e->getMessage()}", $id);
Нужно узнать, что это именно была ошибка при удалении. Я сделал, пока что так:
PHP:
public function isDeleteError(): bool
{
    return str_contains($this->getMessage(), 'Ошибка при удалении категории');
}
Есть ощущение, что это говно-код.
 

AmdY

Пью пиво
Команда форума
Почитай документацию. Исключения проверяются по типу прямо в catch или внутри него через instanceof
Код:
try {
...
    throw new CategoryException("Ошибка при удалении категории", $id);
} catch(CategoryException $e) {
    echo "Исключение CategoryException с текстом:  {$e->getMessage()}";
} catch(\Throwable $e) {
    echo "Это НЕ CategoryException с текстом:  {$e->getMessage()}";
}
Код:
try {
...
    throw new CategoryException("Ошибка при удалении категории", $id);
} catch(\Throwable $e) {
    if ($e instanceof CategoryException) {
        echo "Это CategoryException с текстом:  {$e->getMessage()}";
    } else {
        echo "Это НЕ CategoryException с текстом:  {$e->getMessage()}";
    }
}
 

firep91613

Новичок
Почитай документацию. Исключения проверяются по типу прямо в catch или внутри него через instanceof
Я наверно не правильно выразился. Там же в Laravel исключения можно ловить в bootstrap/app.php или в самом классе в методе render. И ошибки могут быть разные. При удалении, обновлении, создании, к примеру. Я так пока что сделал, это работает. Но сам подход очень сомнительный.
PHP:
<?php

namespace App\Exceptions;

class CategoryException extends \Exception
{
    public function __construct(string $message, protected ?int $categoryId = null)
    {
        parent::__construct($message);
    }

    public function getCategoryId(): int
    {
        return $this->categoryId;
    }

    public function isDeletionError(): bool
    {
        return str_contains($this->getMessage(), 'Ошибка при удалении категории');
    }

    public function isUpdateError(): bool
    {
        return str_contains($this->getMessage(), 'Ошибка при обновлении категории');
    }

    public function isCreateError(): bool
    {
        return str_contains($this->getMessage(), 'Ошибка при создании категории');
    }
}
PHP:
->withExceptions(function (Exceptions $exceptions) {
    $exceptions->render(function (CategoryException $e) {
        if ($e->isDeletionError()) {
            return redirect()->route('admin.categories.show', $e->getCategoryId())->with('error', $e->getMessage());
        }

        if ($e->isUpdateError()) {
            return redirect()->route('admin.categories.edit', $e->getCategoryId())->with('error', $e->getMessage());
        }

        if ($e->isCreateError()) {
            return redirect()->route('admin.categories.create')->with('error', $e->getMessage());
        }

        return false;
    });
})
 

AmdY

Пью пиво
Команда форума
Зачему ты так делаешь? Сразу же видно дублирование.
Ты можешь например завести отдельный тип исключений RedirectException и тогда делать общую логику

PHP:
->withExceptions(function (Exceptions $exceptions) {
    $exceptions->render(function (RedirectException $e) {
            return redirect()->route($e->getRoute(), ...$e->getParams())->with('error', $e->getMessage());
    });
})
 

AnrDaemon

Продвинутый новичок
Вишенка.
PHP:
        set_exception_handler(function (\Throwable $e) use ($ex_log) {
            if (\PHP_SAPI !== 'cli') header("Content-Type: application/json; charset=UTF-8");
            $ex_log($e);
            try {
                throw $e;
            } catch (\mysqli_sql_exception | \PDOException $e) {
                die(json_encode(["result" => -1, "error" => "Database operation failed, see logs"]));
            } catch (PlatformException $e) {
                if ($e->getCode() > 99 && \PHP_SAPI !== 'cli') {
                    http_response_code($e->getCode());
                }
                die(json_encode($e->__toApiResponse()));
            } catch (\Throwable $e) { // Catch-all fallback
                $code = $e->getCode() ?: (strpos($e->getMessage(), "logout") ? -2 : -1);
                die(json_encode(["result" => $code, "error" => $e->getMessage()]));
            }
        });
 

firep91613

Новичок
Как в админке в DashboardController выводить статистику всякую (кол-во постов, кол-во юзеров, последних зареганых и т.д.)? Квери билдеры за пределами слоя стораджа использовать плохо. Репозиторий под этот контроллер тоже видимо не нужен, это же не таблица.
 

firep91613

Новичок
Хорошая ли практика создавать сервисный слой и передавать его в контроллер? К примеру:
PHP:
class UserService
{
    public function __construct(
        protected UserRepository $userRepository,
        protected RoleRepository $roleRepository
    ) {}
}
Еще вопрос: у какой CMS на Laravel можно поизучать код? OctoberCMS, к примеру, норм? Просто я пытался найти на гитхабе элитный код, так и не нашел...
 

AmdY

Пью пиво
Команда форума
Публичные CMS решают весьма специфические задачи, они должны быть расширяемыми по принципу - нельзя трогать код ядра.Из-за этого требуется делать доп абстракции, евенты и хуки. Поэтому их код далеко не самый чистый. Насколько помню OctoberCMS весьма страная, но я смотрел её ещё во времена 4-5 ларавела. Погуглил, вот вроде адекватный список https://worksolutions.ru/useful/administrativnaya-panel-dlya-laravel-kakuyu-luchshe-vybrat/
Мне в свой время Insolita советовал https://filamentphp.com/
Можешь почитать её бложик, заодно в коментах вроде были обсуждения других вариантов https://donnainsolita.medium.com/
 

firep91613

Новичок
Как запретить браузеру кэшировать страницы в админке? Вот у меня разлогивание перекидывает на маршрут авторизации.
PHP:
public function logout(Request $request): RedirectResponse
{
    $this->auth->guard()->logout();
    $request->session()->invalidate();
    $request->session()->regenerateToken();

    return $this->redirector->route('admin.login');
}
Оно выходит, но если нажать на кнопку "Назад" в браузере, то он показывает страницу админки. Я пробовал посылать заголовки Cache-Control: no-cache, no-store, must-revalidate, Pragma: no-cache. Но он все равно кэширует.

Вот Middleware, я его прицепил ко всем маршрутам в админке, кроме авторизации и разлогивания.
PHP:
public function handle(Request $request, Closure $next): Response
{
    $user = $request->user();

    if (!$user || $user->role_id !== 1) {
        return redirect()->route('admin.login');
    }

    return $next($request);
}
 

miketomlin

Новичок
Админка может не раздувать историю (см. location.replace() или history.replaceState()), либо контролировать контент при помощи события popstate (при этом историю надо формировать pushState'ом).

Но пока можно не париться по этому поводу. Во многих ЛК, сделанных якобы для людей, над этим не парились. Там приоритет – не париться и чтобы везде работало. JS/HistoryAPI не везде работает. А «полифил» – это сложно. Даже у нас «полифил» далеко не во всех админках/ЛК используется, хотя попариться любят по моим наблюдениям :)
 
Последнее редактирование:
Сверху