Главная | Настройки | NSFW
Тема:
Доски


[Ответить в тред] Ответить в тред

[Назад] [Обновить тред] [Вниз] [Каталог] [ Автообновление ] 20 / 3 / 2

PHP HTML CSS Anonymous No.3525
schiza3.png (1023 KB, 1654x871)
В этом треде станем изучать PHP, можете вбрасывать статьи и книги.
Пока что попробую спросить советов у анонимуса, у меня есть контроллеры (MVC https://ru.wikipedia.org/wiki/Model-View-Controller) у которых часто повторяются некоторые блоки кода (csrf-защита, требование подтвердить операцию, проверка прав), мне хочется сделать код компактным, для этого создаю в базовом контроллере что-то на уровне:
public function csrf() {
//код csrf защиты
}
и вставляю в контроллер
public function pageAction() {
try {
isAdmin();
csrf();
superDuperProverka();
} catch(\Exception $e) {
$this->response->error($e);
}
}

хочется сделать что-то ещё более компактное, тогда можно прямо в csrf() делать выброс ошибки (а не исключения!) с exit(). Какой способ самый лучший? И, да, этот вопрос не является для меня важным, так, для затравки, чтобы получился тред. Я могу в этих блоки кода добавлять только выбросы Exception, но тогда их нужно вылавливать, чтобы отобразить ошибку стильно или вообще страницу с кнопкой "подтвердить операцию". У меня есть повторяющиеся блоки кода, с которыми не знаю, что делать, какие метод лучше для сокращения. Может перемудрил? Проще будет найти где там Exception отображается в Symfony и изменить стандартную страницу ошибки? Так мне нужно сделать такое изменение конкретно для своих ошибок. Кнопку "подтвердите операцию" разве можно считать за Exception? Не знаю...
Вот ещё вопрос для примера: у меня есть сервис repsonse, через который делаю в контроллере return $this->response->error(текст ошибки); $this->repsonse->ok(шаблон, массив с данными). Потом обратил внимание, что само Symfony такое делает через свой базовый контроллер (тот же $this->render()), может и мне лучше упразднить этот response и перенести методы в свой базовый контроллер с целью сокращению кода? Тогда получится $this->error(), $this->ok(), но с response лучше соблюдается правило с пространством имён.
Пост отредактировал Anonymous
Anonymous No.3526
>у которых часто повторяются некоторые блоки кода
Если они много где используются, стоит вынести их в отдельные сервисы и пробрасывать в контроллер через dependency injection.

>может и мне лучше упразднить этот response и перенести методы в свой базовый контроллер с целью сокращению кода?
Да, лучше. Вообще можешь поковырять проекты на symfony, посмотреть, как сделано там и делать так же.
Anonymous No.3527
>>3526
Я не уверен, что это такие сервисы, есть банальное:
if($this->auth->isAdmin()) {
//зашибись.
} else {
//нет, ты чо!
}

Такие блоки хочется сделать ещё короче! Сервис auth уже имеется, я даже не знаю какое название придумать для такого дополнительного сервиса, который должен:
$this->isAdmin();
просто сразу же выбрасывать ошибку.
Пост отредактировал Anonymous
Anonymous No.3528
>>3527
Делай так тогда и все.

public function controller_name()
{
//Если не админ
if(! $this->auth->isAdmin()) {
return $this->error403();
}

//Какая-то логика
return $this->answer('ololo');
}
Anonymous No.3529
>>3528
ну да, может так правильно, мне хотелось сделать что-то на уровне:
$this->checkAdmin();
которое сразу выдаёт ошибку без всяких if, но по-моему такое недостаточно интуитивно понятно, когда читаешь код (что оно вообще завершает выполнения скрипта в некоторых случаях).
Пост отредактировал Anonymous
Anonymous No.3530
Есть какие-то новые прикольные книги? Я изучал PHP где-то в 18 лет, сейчас мне 28 лет, на деле мои знания особо не продвигались. Я изучал после парочки книг PHP в 18 лет уже на практике и через документацию. Забыл указать в заголовке, что ещё хочется здесь javascript обсуждать, веб-разработку саму по себе.
Пост отредактировал Anonymous
Anonymous No.3531
2537798_detail[...].jpg (240 KB, 497x699)
>>3530
>Я изучал PHP где-то в 18 лет, сейчас мне 28 лет, на деле мои знания особо не продвигались.
Тогда твои знания безнадежно устарели. PHP теперь это совсем не тот язык, что был 10 лет назад.
Книгу если прям по самому языку, по синтаксису ищешь, то ищи php7 Дмитрия Котерова, она вроде как самая подробная по современным возможностям языка.
Anonymous No.3532
>>3531
ну, тогда уже было ООП, базарю. Помню, когда в PHP переменные переданные методом GET или POST ебашились прямо так: $охуенная_переменная_переданная_через_строку_браузера. Потом оно стало deprecated, но почему вообще так сделали? Лол, та ещё была идея.
Пост отредактировал Anonymous
Anonymous No.3533
>>3532
Тогда php был преимущественно функциональным языком и многого из современной версии там не было. Плюс php сегодня эта не только сам язык, но и экосистема из psr стандартов и composer пакетов.

>Помню, когда в PHP переменные переданные методом GET или POST ебашились прямо так: $охуенная_переменная_переданная_через_строку_браузера
Во ты вспомнил, это уже в php4 было выключено по умолчанию.
Пост отредактировал Anonymous
Anonymous No.3534
>>3533
>Во ты вспомнил, это уже в php4 было выключено по умолчанию.
mysql_query('SELECT * FROM `table` WHERE `id` = ' . какая-то_функция_защищающая_от_sql_инъекций($_GET['id']) .';');
В PHP до сих пор есть одна интересная фича связанная с foreach: https://bugs.php.net/bug.php?id=29992
Пост отредактировал Anonymous
Anonymous No.3536
>>3534
>mysql_query
>какая-то_функция_защищающая_от_sql_инъекций
Так в 2021 году никто не делает. Для составленея sql запросов используется или PDO с подготовленными запросами, или orm.

>В PHP до сих пор есть одна интересная фича связанная с foreach:
Сталкивался с этим лично. Странный баг, проявляющийся иногда, если передавать в foreach ссылку.
Anonymous No.3537
>>3536
> Для составленея sql запросов используется или PDO с подготовленными запросами, или orm.
Я знаю.
Anonymous No.3544
Я придумал "не знаю куда относящиеся" блоки кода уводить в методы, которые содержат в своём названии "trait", эти методы могут выводить содержимое и завершать работу программы.
типа:
$this->csrfTrait();
выводит ошибку и завершает работу программу, если csrf-токена нету или неправильный. Да, можно выбрасывать исключение, но это не совсем то, мне нужно html+json+xml выводить, исключение у меня выбрасывает:
$this->csrfProtection();
Мне бы с вылавливанием Exception в Symfony конечно разбираться, но это такая же марока, чтобы они с правильным оформлением отображались в зависимости от каждого конкретного случая.
Вот пример:
/** Выбрасывает исключение, если метод отправки не является указанным в параметре $method. */
public function methodProtection($method) {
if($this->request->isMethod($method) == false) {
throw new \Exception($this->translator->trans('Метод отправки не является ') . $method . '.');
}
return true;
}

/** Выбрасывает исключение, если метод отправки не является POST. */
public function confirmationProtection() {
return $this->methodProtection('POST');
}

/** Страница с требование подтвердить операцию с помощью нажатия на кнопку (некоторые операции недостаточно безопасно выполнять методом GET, могут скинуть ссылку типа /profile/removeMyAccaunt.php). */
public function confirmationRequest() {
return $this->ok('confirmation.html.twig');
}

и тут нужен confirmationTrait, чтобы выловил исключение confirmationProtection() и выполнил confirmationRequest().
типа такого будет (не проверял код):
public function confirmationTrait() {
try {
$this->confirmationProtection();
} catch(\Exception $e) {
print $this->confirmationRequest();
exit();
}
}
Пост отредактировал Anonymous
Anonymous No.3546
image.png (31 KB, 748x694)
>>3544
>Выбрасывает исключение, если метод отправки не является POST
Документацию читать не пробовал?
https://symfony.com/doc/current/routing.html#matching-http-methods
Anonymous No.3547
>>3546
А, блин, ты ж не на symfony. Спутал тебя с тем чуваком, который борду на symfony пишет. Извиняюсь.
Anonymous No.3548
>>3546
Ты ничего не понял, если метод отправки не является POST, нужно вывести страницу с кнопкой "подтвердить операцию". Да, на Symfony. Вот есть страница: /user/delete.html, если дать ссылку скрытую на страницу, пользователь удалит свой аккаунт, поэтому нужно подтверждение нажатием на кнопку. Нет, конечно, можно запретить методом GET доступ к странице, но мне так удобней, контролирую случайные нажатия на ту же ссылку "удалить всю бд" + пока не умею менять стандартные ошибки Symfony, вот что выдадет, если метод отправки не является POST? Мне нужно кастомизировать, подозреваю, что ничего, потому что этот контроллер вообще не запустится, он только для POST доступен. Да, вот сейчас поразмышлял, можно делать два контроллера на одну страницу, один отвечает на метод POST, а другой на метод GET, но у меня тогда код начнёт увеличиваться в размере! На каждую страницу с подтверждение такое надо будет делать! Впрочем, конечно, такой способ выглядит правильным.
Пост отредактировал Anonymous
Anonymous No.3549
>>3548
>да, вот сейчас поразмышлял, можно делать два контроллера на одну страницу, один отвечает на метод POST, а другой на метод GET
Именно так.

>вот что выдадет, если метод отправки не является POST
404 ошибку, если контроллер для пути не описан, либо 405, если контроллер по данному пути описан для POST, а ты стучишься на него методом GET.

>пока не умею менять стандартные ошибки Symfony (вот что выдадет, если метод отправки не является POST? мне нужно кастомизировать!
Если ты про http ошибки 404, 500, и т.д, то они не меняются в dev окружении. А в prod окружении меняются очень просто, нужно положить файл с шаблоном по следующему пути: templates/bundles/TwigBundle/Exception/error404.html.twig, где 404 - это код ошибки, которую ты хочешь кастомизировать. TwigBundle к проекту должен быть подключен.
Anonymous No.3550
>>3549
>templates/bundles/TwigBundle/Exception/error404.html.twig
Если мне память не изменяет, никакой реакции на подобное не последовало, документацию то читаю, там про такое было (у меня своя реализация получилась). Впрочем, может забыл в prod окружении проверить.
Пост отредактировал Anonymous
Anonymous No.3551
Лол, в этот раз так же не получилось с помощью templates/bundles/TwigBundle/Exception/error404.html.twig изменить что-то, умудрённый долгим опытом кэширования в Symfony почистил каталог /cache/prod и оно заработало. Когда только начинал в Symfony разбираться не задумывался о каталоге с кэшем, поэтому всегда нулевой результат был на попытку кастомизировать страницы ошибок стандартным методом.
Пост отредактировал Anonymous
Anonymous No.3556
чо творю:
/** CSRF-защита. */
public function ifCsrfWrongThrowException($method = 'POST', $var = 'token') {
$method = strtoupper($method);
if($this->config->get('csrf') == true) {
switch($method) {
case "POST":
if(!isset($_POST[$var])) {
throw $this->tokenNotSent();
}
if (!$this->isCsrfTokenValid($var, $_POST[$var])) {
throw $this->wrongToken();
}
break;
case "GET":
if(!isset($_GET[$var])) {
throw $this->tokenNotSent();
}
if (!$this->isCsrfTokenValid($var, $_GET[$var])) {
throw $this->wrongToken();
}
break;
}
}
}

/** Выбрасывает исключение, если метод отправки не является указанным в параметре $method. */
public function ifMethodWrongThrowException($method) {
if($this->request->isMethod($method) == false) {
throw $this->methodNotAllowed(array($method), $this->translator->trans('Метод отправки не является ') . $method . '.');
}
}

/** Выбрасывает исключение, если метод отправки не является POST */
public function ifMethodNotPOSTThrowException() {
if($this->request->isMethod('POST') == false) {
throw $this->confirmationRequest();
}
}

/** Капча. */
public function ifCaptchaWrongThrowException() {
/** Если капчу не надо проверять, тогда сразу возвращает true. */
if($this->config->get('captcha') == false) {
return true;
}
/** Проверка капчи. */
if(!isset($_POST['gregwar_captcha_value'])) {
throw $this->captchaNotSent();
}
if ($this->captchaSession->check($_POST['gregwar_captcha_value']) == true) {
$this->captchaSession->delete();
} else {
if($this->captchaSession->isActive() == true and $this->captchaSession->isCurrent($_POST['captcha_id']) == true) {
throw $this->wrongCaptcha();
} else {
throw $this->captchaIsOutOfDate();
}
}
return true;
}

/** Выбрасывает исключение, если нету прав администратора. */
public function ifNotAdminThrowException() {
if($this->auth->getAdmin() == false) {
throw $this->notAdmin();
}
}

/** Выбрасывает исключение, если нету прав администратора или модератора. */
public function ifNotAdminAndNotModThrowException($sectionId) {
if($this->auth->getAdmin() == false and $this->auth->getMod($sectionId) == false) {
throw $this->notAdminAndNotMod();
}
}

С функциями-трейтами пока завязал, теперь интереснее названия. Хочется сократить код, но при этом оставить читабельным...
Кстати, насчёт требования подтвердить операцию так решил этот вопрос (error405.html.twig):
{% extends "base.html.twig" %}

{% block body %}
{% if app.request.method == 'GET' %}
{{ include('include/confirmation.html.twig') }}
{% else %}
{{ exception.getMessage }}
{% endif %}
{% endblock %}

пока ничего ещё не тестировал.

подробности:
/** 400 */

/** Плохой запрос. */
public function badRequest($message = null) {
if($message == null) {
$message = $this->translator->trans('Плохой запрос.');
}
return new Exception\BadRequestHttpException($message);
}

/** Неправильно введена капча. */
public function wrongCaptcha() {
return $this->badRequest($this->translator->trans('Неправильно введена капча.'));
}

/** Капча устарела. */
public function captchaIsOutOfDate() {
return $this->badRequest($this->translator->trans('Капча устарела.'));
}

/** Капча не отправлена. */
public function captchaNotSent() {
return $this->badRequest($this->translator->trans('Капча не отправлена.'));
}

public function wrongToken() {
return $this->badRequest($this->translator->trans('Неправильный токен.'));
}

public function tokenNotSent() {
return $this->badRequest($this->translator->trans('Токен не отправлен.'));
}

/** 403 */

/** Доступ запрещён. */
public function forbidden($message = null) {
if($message == null) {
$message = $this->translator->trans('Доступ запрещён.');
}
return new Exception\HttpException(403, $message);
}

/** Доступ запрещён. */
public function error403($message = null) {
return $this->forbidden($message);
}

/** Недостаточно прав. */
public function permissionDenied($message = null) {
if($message == null) {
$message = $this->translator->trans("Недостаточно прав.");
}
return $this->forbidden($message);
}

/** Требуются права администратора. */
public function notAdmin($message = null) {
if($message == null) {
$message = $this->translator->trans("Для выполнения операции требуются права администратора.");
}
return $this->permissionDenied($message);
}

/** Требуются права модератора. */
public function notAdminAndNotMod($message = null) {
if($message == null) {
$message = $this->translator->trans("Для выполнения операции требуются права модератора или администратора.");
}
return $this->permissionDenied($message);
}
/** 405 */

/** Метод не поддерживается. */
public function methodNotAllowed($allow = array(), $message = null) {
if($message == null) {
$message = $this->translator->trans('Метод не поддерживается.');
}
return new Exception\MethodNotAllowedHttpException($allow, $message);
}

/** Метод не поддерживается. */
public function error405($allow = array(), $message = null) {
return $this->methodNotAllowed($allow, $message);
}

/** Требование подтвердите операцию отправив данные методом POST. */
public function confirmationRequest($message = null) {
if($message == null) {
$message = $this->translator->trans('Подтвердите операцию отправив данные методом POST.');
}
return $this->methodNotAllowed(array('POST'), $message);
}
Пост отредактировал Anonymous

[Назад] [Обновить тред] [Вверх] [Каталог] [ Автообновление ]
20 / 3 / 2

[Ответить в тред] Ответить в тред

15000

Ответ в тред No.3525
Настройки
Избранное
Топ тредов