«phpClub» — архив тем ("тредов"), посвящённых изучению PHP и веб-технологий.
Аноним 2019/05/03 10:11:50  №1393386 1
Объясните пожалуйста.
1) Как реализовать конструктор в классе, который реализует паттерн TableDataGateway? В примере ОП использует PDO и конструктор выглядит так:
public function __construct(PDO $pdo) { ... }
а я использую mysqli могу ли я написать
public function __construct($conn) { ... }?
Так же не понятно, что мне писать в самом конструкторе? Подключение к базе данных или что?
2)С исключениями я тоже не понял. Могу ли я их не использовать, а писать просто
$conn = new mysqli ($hn, $un, $pw, $db);
if($conn->connect_error) die($conn->connect_error);
?
Аноним 2019/05/03 10:26:27  №1393396 2
>>1393386
>а я использую mysqli
зачем? Юзай pdo
>Подключение к базе данных или что?
не смотрел пример ОПа, но в классе PDO коннекшн уже же будет установлен?
>С исключениями я тоже не понял. Могу ли я их не использовать, а писать просто
можешь. Зачем тебе только это? Твой die() выйдет из программы и всё, а исключение можно обработать и продолжать работать дальше.

Привыкай к ним, die и exit в реальном коде не встретишь
Ответы: >>1393514 >>1393514
Аноним 2019/05/03 16:24:09  №1393514 3
>>1393396
>>1393396
>Юзай pdo
В книге, которую я читаю, используют mysqli. Мне его использовать удобней.
>PDO коннекшн уже же будет установлен?
Не понял
>Зачем тебе только это?
Да вот собственно вопрос. Оп пишет что исключение сокращает код, только у меня чет наоборот. Ну и нигде нормального объяснения про исключения не могу найти.
Так же видел, что нельзя использовать класс Exception. С классом Exception вопросы. Мне нужно создать свой класс, который унаследует Exception? А что в нем писать?
Ну и не понятно зачем отлавливать ошибку если можно вместо die
отправить HTML страницу с ошибкой. Но в задании этого нет, так что делать я этого не буду.

>>1393429
Во во, тоже вопрос. ОП вроде тоже писал про обертку mysqli или не он. Что это значит? Зачем нужно? Как реализовать я даже не спрашиваю. И что так mysqli не любят?
Аноним 2019/05/03 17:21:33  №1393541 4
>>1393514
>про обертку mysqli
>Что это значит?
То и значит - оберни в класс функционал mysqli, который тебе нужен.
>Зачем нужно?
Банально удобнее работать с такими вещами через объекты.
Ну и по ТЗ нужен ООП.
>Как реализовать я даже не спрашиваю
Объяснять дольше чем класс писать. С этой хренью любой ждун за 10 минут справится. Гугл подоёбывай по этой теме.
Аноним 2019/05/03 20:41:28  №1393617 5
>>1393400
>Что по английскому у тебя
с англ ок, на русском тех литру не читаю в принципе
>А на 140 к какие вопросы на собесе были
очень много вопросов по sql и по безумным джоинам. В остальном вопросы разные, от логических задачек в яндексе (не взяли) до вопросов про то, как реализован массив в ядре пхп
>>1393402
>Как вообще рынок пыхи оцениваешь
в рашке большой, но разный, серьёзное погромирование только на симфони и немножко лара, его мало, в остальном пхп рынок это дно уровня вордпресса и битрикса, это путь в никуда и дерьмо полное, не тратьте время. В европе он побольше, но всё равно так себе, слишком дурная слава у пыхи. Хотя язык хороший
>>1393456
не понял

>>1393514
>которую я читаю, используют mysqli
и что блядь, я говорю тебе, это дерьмо в приличном обществе даже не упоминают, а ты
>Мне его использовать удобней.
Просто погугли mysqli vs pdo php и почитай тонны текста.
>Оп пишет что исключение сокращает код
оп всё правильно пишет, любой новичок поначалу не понимает, зачем нужны исключения. Я тебе дал пищу для размышлений по поводу того, что die безусловно заканчивает работу программы.
>Ну и нигде нормального объяснения про исключения не могу найти.
exception почти в неизменном виде есть в Java/Php/C++/C#/js, написаны килотонны паст и разбито много копий, а ты не можешь найти объяснения. Главное качество погромиста - умение гуглить, запомни.
>зачем отлавливать ошибку если можно вместо die
вот прям так и загугли. Только не на русском, конечно

Аноним 2019/05/03 20:55:28  №1393623 6
>>1393617
на чём пишешь? Перспективно учить ларавел сейчас для пыхи?
Ответы: >>1393628
Аноним 2019/05/03 21:06:55  №1393628 7
>>1393623
пишу на симфони.
>Перспективно
да. Спрос есть и разработка на ларе зачастую попадает под категорию "серьёзное программирование". Но если есть выбор, делай в сторону симфони.
Ответы: >>1393714 >>1393724
Аноним 2019/05/04 06:59:58  №1393714 8
>>1393628
Сколько часов в неделю уходит на работу + обучение не считая обедов и прочего отдыха?
Ответы: >>1393737
Аноним 2019/05/04 07:32:59  №1393724 9
15531687310600.png (157, 680x753)
753x680
>>1393628
А какой фронт? Это нормально когда я пришёл на джуна по ларке, а меня спрашивают кроме ларки ещё по реакт/вью и бутстрап? Что бы ты посоветовал, углубляться в бэк или распыляться на фронт, чтобы найти работу?
Ответы: >>1393737
Аноним 2019/05/04 07:46:43  №1393729 10
>>1393617
>от логических задачек в яндексе
Что за задачи хоть были? Такие которые не решаются обычными смертными без анало-математического мышления или все таки к ним можно было подготовиться?
Че вообще думаешь? Это же получается ты не попадешь на верхушку ITяндекса ЛОЛ, как переживешь?
Ответы: >>1393737 >>1394571
Аноним 2019/05/04 08:08:44  №1393737 11
>>1393714
если интересный проект на работе, то работаю все рабочее время (7 часов примерно), а дома отдыхаю. Если проект так себе, то половину времени на работе прокрастинирую. Дома сейчас мини проект на расте пишу ради фана + один пупен-сорс на пыхе. Пару часов вечером, иногда 0.

>>1393724
>Это нормально
in the grand scheme of things это хуёво, тк нормально, когда есть деление: бекендеры, фронты (у нас есть алсо отдельные верстальщики, то есть фронты только js пилят). Я, например, вообще не разбираюсь в современном js и не особо хочу разбираться. И не страдаю.

Но очень часто (вот прям очень) конторы берут себе фуллстеков, и на дуде игрецов и жнецов и швецов (экономят). Ясное дело, что один человек не может (ну просто не хватит сил у него и нервов) разбираться хорошо и в беке, и в бд, и в продвинутом современном js. Так что экономия выходит боком.
Сам начинал в подобном месте. Начинать там нормально, но как решишься работу менять, уже ищи внимательнее. И всегда на собесах прямо спрашивай, не придётся ли ковырять фронт.

>Что бы ты посоветовал
только углубляться. Хороший фронт/бек всем нужен. Фуллстек - ни рыба ни мясо, нужен только рогам и копытам для экономии.

>>1393729
логические, не относящиеся к матеше. Чисто как из мы-вам-перезвоним-тредов про лампочки и переворачивания монеток.
>как переживешь?
ну сейчас не попал, но тоже оч хорошее место нашёл. Через год примерно снова буду искать и опять в яндех попробую, хули нет. Подготовлюсь получше, всё в наших руках
Ответы: >>1393751
Аноним 2019/05/04 09:04:32  №1393751 12
Ответы: >>1393756
Аноним 2019/05/04 09:19:00  №1393756 13
Аноним 2019/05/05 11:12:49  №1394459 14
image.png (102, 1064x569)
569x1064
>>1393617
Не хотел засорять, но с исключениями остались вопросы
>и что блядь, я говорю тебе, это дерьмо в приличном обществе даже не упоминают, а ты
Ну так я это прочитал в бестселлере, который имеет 4 издание. Тебя в яндекс не взяли так что не знаю про какое общество ты говоришь. Но так как я не считаю яндекс каким то топовым местом и перейти на PDO мне не трудно

>оп всё правильно пишет, любой новичок поначалу не понимает, зачем нужны исключения.
Вот смотри как выглядит задача, которую я программирую(задача ОПа). Есть список студентов в БД. Мы должны к нему подключится. Если подключение не удалось я НИЧЕГО НЕ ДЕЛАЮ. Все, прога завершает свою работу. Естественно на боевом сервере нужно было бы вывести красивую ошибку, но сейчас не про это. Мой вопрос заключается вот в чем. Зачем использовать исключения, если:
1) Этот код занимает больше места чем тот вариант который я написал;
Сравни
try {
$dbh = new PDO('mysql:host=localhost;dbname=""', $user, $pass);
} catch (PDOException $e) {
print "Error!: " . $e->getMessage() . "<br/>";
die();
}

и

$conn = new mysqli ($hn, $un, $pw, $db);
if($conn->connect_error) die($conn->connect_error);

Ну кстати первый вариант с pdo, а второй с mysqli. Я просто не знаю как можно сокращено написать с pdo. Где то их вооб
2) Так еще вместо die() если это нужно конечно можно было бы подключить файл с выводом той красочной страницы с ошибкой, мол НЕ УДАЛОСЬ ПОДКЛЮЧИТЬСЯ С БАЗОЙ ДАННЫХ, ПРИНОСИМ ИЗВИНЕНИЯ.

Короче, суть в этих словах: если не знаешь, как обрабатывать - не обрабатывай никак. РНР прекрасно справляется с базовой обработкой и сам.
Ловить исключение только ради того чтобы поймать - бессмысленно.
Поэтому лучше оставить всё как есть, а ловить исключение только тогда, когда точно знаешь, что хочешь сделать, поймав.


Я это все пишу не для того чтобы поспорить. Просто мне кажется так мы сокращаем строчки кода вроде бы без ущерба.
Ответы: >>1394511 >>1394569
Аноним 2019/05/05 13:08:13  №1394511 15
>>1394460

Ошибки должны писаться в логи, если только ты их не отключил. Логи в линуксе находятся в /var/log, а также читаются утилитой journalctl. Изучи, как устроено логгирование.

>>1394459

Можно использовать mysqli, она тоже поддерживает исключения, только их надо включить. Без них тебе придется после каждой команды ставить if и проверять результат, что утомляет. Про исключения у меня есть урок, прочти, если еще не читал: https://github.com/codedokode/pasta/blob/master/php/exceptions.md и после этого можешь задавать уточняющие вопросы.

Но я должен предупредить, в некоторых книгах эту библиотеку используют только потому, что она похожа на более старую библиотеку mysql, и авторы, чтобы не переделывать код, написанный для mysql, просто добавили в функции букву i (mysql_query -> mysqli_query). Но зачастую код, писавшийся для mysql, некачественный, и лучше бы они его переписали с нуля. Да и mysqli имеет некоторые отличия и авторам книг лучше было бы код переделать с нуля, а не механически заменить названия функций (например, mysqli поддерживает плейсхолдеры, а mysql - нет. И авторам стоило бы перевести свой код на их использование, а не подставлять данные в запрос вручную, как это делалось в mysql).

То есть, полезно пролистать официальный мануал по mysqli, чтобы правильно ее использовать.

> Я это все пишу не для того чтобы поспорить. Просто мне кажется так мы сокращаем строчки кода вроде бы без ущерба.

Как раз хорошо, что ты задаешь вопросы. В программировании, как и в других инженерных науках, все решения принято обосновывать. Что касается сокращения кода - я тут его не вижу. Выбросить исключение - это одна строчка. Написать свой класс исключений - 3 строки (class X extends \Exception {}).

Если библиотека поддерживает выброс исключений (mysqli и PDO поддерживают), то их использование экономит строчки, так как тебе не надо руками писать if() после каждой функции работы с БД, которая может вернуть ошибку. Это упомянуто в моем уроке.
Аноним 2019/05/05 13:09:08  №1394513 16
>>1393386

> а я использую mysqli могу ли я написать
> public function __construct($conn) { ... }?

А ты читал урок про DI? Прочти, если не читал: https://github.com/codedokode/pasta/blob/master/arch/di.md А то я не вижу смысла пересказывать уже написанное там.

В ООП мы используем разделение ответственности, каждый класс отвечает за что-то свое. Соответственно, устанавливать соединение с БД - это не задача класса TableGateway, потому мы передаем ему уже готовое соединение в конструктор, примерно как ты написал, только стоит еще тайп-хинт добавить.

> С исключениями я тоже не понял. Могу ли я их не использовать, а писать просто
> $conn = new mysqli ($hn, $un, $pw, $db);
> if($conn->connect_error) die($conn->connect_error);

Прочти урок про исключения и там написано, чем это плохо. Ну как минимум у тебя проблема в том, что ты пользователю показываешь ошибку, которая ему нафиг не нужна, так как он не программист, при этом ты (разработчик) об этой ошибке не узнаешь, так как она не пишется в лог. Потому стоит почитать про существующие решения в моем уроке: https://github.com/codedokode/pasta/blob/master/php/exceptions.md

Альтернатива исключениям - это возвращать код ошибки. Его придется проверять после вызова каждой функции, где может произойти ошибка.

>>1393514

> Ну и не понятно зачем отлавливать ошибку

В случае выброса исключения тот, кто вызвал функцию, решает, что делать в случае исключения. В случае die() он решить ничего не может. Плюс, тут нарушается разделение ответственности. С какой стати класс для работы с БД может показывать HTML страницу? Ему никто этого не разрешал.

Если в программе есть разделение ответственности, то класс работы с БД лишь сообщает об ошибке, но не решает, как ее обрабатывать. Показ страницы ошибки - это не его зона ответственности. Ты пока воспринимаешь программу как одно целое и не разделяешь ее на слабосвязанные части.

>>1393617

В твоем посте избыток категоричности стоило бы заменить на изобильность пояснений.
Ответы: >>1394643
Аноним 2019/05/05 15:26:47  №1394569 17
170-312

>>1394459

Твой код с try/catch написан неправильно. try/catch если и ставят, то только 1 раз, в самом начале программы, а не вокруг каждого вызова функции. Потому код там будет выглядеть так:

$dbh = new PDO('mysql:host=localhost;dbname=""', $user, $pass);

Что, очевидно, короче, чем если бы мы еще писали после него if с проверкой результата.

Глобальный обработчик исключений ставят либо с помощью set_exception_handler, либо с помощью try/catch в самом начале программы.

>>1394386

У тебя какая-то ошибка синтаксиса - какой-то лишний символ (например: неразрывный пробел), или какая-то слишком старая версия PHP, или какое-нибудь двоеточие вместо точки с запятой, или русская буква вместо латинской.

Попробуй этот файл вставить в ideone и проверить, будет такая же ошибка или же другая. Если такая же - то дело именно в символах.

>>1394269

array_slice. Не ленись, открой раздел про функции работы с массивами и прочитай список с краткими описаниями. Это все равно на собеседовании могут спросить.

Вот, читай список тут: https://www.php.net/manual/ru/ref.array.php

>>1394228

Так это учебный тред для начинающих с нуля. Ты подожди, пока анончик прочтет все уроки и решит все мои задачи, и твоя самооценка зашатается.

>>1394166

Для демонизации там есть php-fpm. Зачем нужна "асинхронность", если синхронный код писать проще и он понятнее, я не понял. Но если тебе хочется мучаться с промисами и евент-лупами, то ReactPHP к твоим услугам.

Синхронность это плюс: синхронный код проще. В отличие от языков вроде ноды, где код писать тяжело. То, что PHP умирает после каждого запроса, это плюс: у нас нет утечек памяти. В отличие от языков вроде ноды или руби, где (вроде бы) нет профайлеров памяти, по крайней мере бесплатных, и при утечке люди просто тупо прибивают приложение по крону, чтобы оно не отъедало всю память, так как не могут найти эту утечку.

Хотя есть ситуации, где нужен именно асинхронный код. Тут, конечно, все корявенько, но сама возможность есть.

И я не считаю, что нода это что-то плохое, но есть ситуации, где PHP просто удобнее использовать.

А еще, PHP хорошо оптимизирован, есть типизация и у нас готовят JIT.
Ответы: >>1394581 >>1394643
Аноним 2019/05/05 15:28:30  №1394571 18
>>1394247

Я тоже такой термин не слышал никогда.

>>1394148

Сделай foreach'ем либо через intersect_key.

>>1393471

Очень плохо. Идея ООП в том, что ты можешь в наследнике заменить или обернуть метод, а если тебе понадобился instanceof, то ты делаешь что-то неправильно. Плюс, предок не должен знать о своих наследниках. Как автор кода может знать, кто именно в будущем будет наследовать его класс, а? В ООП принцип открытости для расширения - любой может в будущем унаследовать твой класс и ты не знаешь даже, сколько у него будет наследников.

Ты в предке пишешь название класса-наследника. Это неправильно.

Тебе надо правильно проектировать классы, думать о том, какая у каждого зона ответственности. Конкретный совет дать не могу, так как пример у тебя абстрактный. Можно попробовать вынести дублирующийся код в отдельный метод.

>>1393729

Задачи из яндекса легко гуглятся. Мне в общем они нравятся, интересные и есть над чем поломать голову. Я вообще люблю задачи, которые не могу решить сразу.

Ответы: >>1394590
Аноним 2019/05/05 15:31:07  №1394575 19
>>1393636

Обычно есть несколько отдельных рабочих процессов PHP и оба запроса будут обрабатываться параллельно. Для получения id записи в MySQL надо использовать LAST_INSERT_ID() или одноименную функцию в PDO или mysqli, не надо делать кривой велосипед. В Postgres надо использовать сиквенсы (генераторы уникальных значений) для этого.

Описанные тобой способы неправильные и могут давать ошибки.

>>1393551

Подучи HTML/CSS/JS. Вряд ли ты сможешь осилить фронтенд-фреймворки не зная толком JS. Ну и мне кажется, тебе надо дальше проходить собеседования, есть шанс, что куда-нибудь возьмут.

Заодно можно поизучать теорию по БД, виды связей, нормализация, древовидные данные, индексы. оптимизация и тд.

>>1393514

Наследования исключения делается в простейшем варианте так:

class SomeException extends \Exception {}

Далее при желании можно добавлять поля и методы.

>>1393429

Я думаю, что если стоит задача сделать что-то более универсальное, то можно взять готовую библиотеку вроде Doctrine DBAL, где уже есть все нужные обертки.

>>1393389

Это тайп-хинт (контроль типов). Изучи его и используй по возможности везде.

>>1393036

Если твой скрипт может выполнить задачу за 5 минут, то да, можно так. Если не может, то надо запускать реже.
Ответы: >>1394600
Аноним 2019/05/05 15:37:44  №1394581 20
>>1394569
>Твой код с try/catch написан неправильно. try/catch если и ставят, то только 1 раз, в самом начале программы, а не вокруг каждого вызова функции. Потому код там будет выглядеть так:
ну, кстати, тут я бы поспорил. Разные мнения на этот счёт, моё таково, что в try catch надо оборачивать каждый (в разумных пределах) вызов функции, где возможен выброс исключения, и которое ты планируешь обработать.
Ответы: >>1394582 >>1394733
Аноним 2019/05/05 15:38:38  №1394582 21
>>1394581
то есть несколько try/catch в одном коде это ок, особенно если разные исключения ловятся и они в разных местах возникают
Ответы: >>1394733
Аноним 2019/05/05 15:50:38  №1394590 22
>>1394571
> Конкретный совет дать не могу, так как пример у тебя абстрактный.
Спасибо за ответ. Всегда приятно читать твои объяснения.

Реальный код такой. Есть класс WebReader, который удобная для меня обертка над file_get_contents, контекстами стримов и $http_response_header.
В нем есть метод doRequest(), внутри которого while и try-catch, и идет запрос через file_get_contents, собственно. В catch обрабатываются исключения, которые кидает file_get_contents. Если исключение такое, что это просто сбой http-запроса - крутим while снова (отправляем новый запрос). Если что-то другое, пробрасываем исключение наружу, конец.
Он не абстрактный, готовый класс для запрос в интернет. Но от него я наследуюсь, если конкретному сайту нужны специфические заголовки, или сохранить-отдать специфические куки. TheSiteWebReader, например. Я все это закладывал при проектировании, поэтому работает замечательно.

И вот пришла беда: на одном из сайтов, на который я лезу через TheSiteWebReader, file_get_contents выдает такую ошибку, которую я могу починить немного починив запрос конкретно для этого сайта, но ни для какого другого. Единственное место, где я могу это починить - глубокие кишки WebReader->doRequest(). И мне нужно проверять, что я TheSiteWebReader, потому что для других сайтов чинить эту ошибку нельзя.

Что делать? Выделить содержимое catch во вспомогательный метод типа WebReader->tryToRepairTheRequest(), а затем при необходимости переопределять этот метод в классах-наследниках? Это будет нормально - передать ему исключение, на основе которого он либо изменит свойства класса (модифицирует запрос), либо кинется переданным исключением, если он не может починить запрос?
Ответы: >>1394733
Аноним 2019/05/05 16:15:40  №1394600 23
>>1394575
Просто сразу не мог додуматься до того, что в ларавеле после $var->save(), смогу взять из неё же id =)
Аноним 2019/05/05 18:32:37  №1394643 24
>>1394569
>Твой код с try/catch написан неправильно. try/catch если и ставят, то только 1 раз, в самом начале программы, а не вокруг каждого вызова функции. Потому код там будет выглядеть так:
Так стойте, что это значит? А что тогда должен ловить try/catch?

>>1394513
Вот посмотри мой код, пожалуйста. Где тут ошибки. Мне нужно оборачивать запрос $dbh->query($query); в try/catch? Если да, то какую ошибку функция query() может выбрасывать? Тоже PDOException?

<?php
require_once __DIR__ . '/login.php';
try {
$dbh = new PDO('mysql:host=localhost;dbname=', $un, $pw);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
echo 'Подключение не удалось: ' . $e->getMessage(); //$e->getMessage() не нужно писать, получается?
}

$query = "CREATE TABLE student (
id SMALLINT NOT NULL AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
surname VARCHAR(50) NOT NULL,
gender ENUM('male', 'female') NOT NULL,
groupNumber VARCHAR(5) NOT NULL,
email VARCHAR(30) NOT NULL UNIQUE,
totalPoints SMALLINT UNSIGNED NOT NULL,
yearOfBirth YEAR NOT NULL,
localOrNonresident ENUM('local', 'nonresident') NOT NULL,
PRIMARY KEY (id)
)";

$dbh->query($query);
$dbh = null;
?>
Ответы: >>1394656 >>1394732
Аноним 2019/05/05 19:41:31  №1394656 25
>>1394643
Я не оп.
Популярное решение - это централизованный обработчик исключений в ядре твоего фреймворка, как можно ближе к точке входа. В зависимости от режима DEVELOPMENT/ PRODUCTION ты можешь выводить ошибки на экран или молча логировать в файл Собственно единая точка входа и для этого тоже нужна.
>>1394607
Я не оп.
Под хелперами обычно понимают методы/функции шаблонизатора, хотя зависит о терминологии конкретного фремворка.

Сервисы обычно имеют отношения к Dependency Inversion https://ru.wikipedia.org/wiki/Принцип_инверсии_зависимостей фреймворка. Предполанается что ты пишешь в ооп стиле. У тебя куча классов зависящих друг от друга наследованием и композицией (когда один инстанс класса содержит ссылку на инстанс другого класса). Чтобы инстанцировать класс тебе нужно, предварительно инстанцировать кучу других классов, от которых он зависит путем композиции. DI во фреймворке:
1 позволяет обобщеным образом описать зависимости между классами (иногда автоматически интроспекцией получается инстанцировать класс)
2 позволяет осуществлять замену классов зависящих от друг друга наследованием или наследующих один интерфейс

Ты дожен понять что DI это не дополнительный улучшизм, а основной метод содания объектов во фрейймворке. Сервисы это классы твоей бизнес модели как ты выразился. Если твой класс ниотчего не зависит то тебе ненужно вставлять его в DI Собственно ты приходишь к утилитам.
Аноним 2019/05/06 05:52:34  №1394732 26
>>1394643

> А что тогда должен ловить try/catch?

Ты урок про исключения прочел? Смысл исключений как раз в том, чтобы не писать кучу if или кучу try/catch.

> Вот посмотри мой код, пожалуйста. Где тут ошибки

- пользователю не показывается красивая страница ошибки
- информация об ошибке не попадает в лог ошибок
- для показа страницы ошибки try/catch пишут один раз в начале программы, а не вокруг каждого вызова функции

В твоем случае надо либо использовать set_exception_handler, либо оборачивать все в огромный try/catch.

> Если да, то какую ошибку функция query() может выбрасывать? Тоже PDOException?

А в мануале ответа нету? Тут например: https://www.php.net/manual/ru/pdo.error-handling.php

Ошибки естественно могут быть: ошибка в SQL-запросе, ошибка связи с БД.

> Мне нужно оборачивать запрос $dbh->query($query); в try/catch?

Не нужно.

Что использовать: PDO или mysqli - не принципиально, они оба поддерживают исключения.

>>1394604

Померяй или погугли тесты.

Ответы: >>1394743
Аноним 2019/05/06 05:54:58  №1394733 27
>>1394590

> Есть класс WebReader

Это называется обычно HttpClient. И есть уже готовые клиенты, например, Guzzle.

Тебе надо переделать архитектуру и выбрасывать исключение наверх, а в классе-наследнике ловить его и обрабатывать как нужно, либо сделать в базовом классе опцию для включения этого кода, и выставлять ее в true в наследнике, либо вынести решение вопроса "что делать при ошибке" в отдельный метод, и тогда наследник может его переопределить.

А вообще, если речь идет о сккрейпинге, там не стоит сильно заморачиваться с архитектурой, это обычно одноразовые скрипты, которые постепенно приходят в негодность и переписывают или выкидывают.

> Это будет нормально - передать ему исключение, на основе которого он либо изменит свойства класса (модифицирует запрос)

Непонятно, кстати, почему у тебя параметры запроса хранятся в свойствах класса. У тебя объект представляет один запрос и для нового запроса создается новый объект? Если нет, то это может быть ошибкой в архитектуре. Ну например: что, если ты в процессе обработки одного запроса попытаешься через этот класс сделать другой? Свойства второго запроса затрут первый?

>>1394581

Он не может обработать ошибку соединения с БД. У него нет резервной БД или чего-то такого. Потому ему не нужен отдельный обработчик для именно этой ошибки, а нужен один общий обработчик для любых ошибок и для показа страницы ошибки.

>>1394582

Несколько try/catch пишется, если ты знаешь, как обработать конкретную ошибку. Иначе пишется один общий обработчик ошибок на все случаи жизни.

>>1388385

В нем ничего не заменено, просто QUERY_STRING - это то, что идет ПОСЛЕ знака вопроса в URL (потому знака вопроса в ней нету) и она вообще может отсутствовать. Открой мануал и проверь: https://www.php.net/manual/ru/reserved.variables.server.php

Также, можешь прочитать урок про структуру URL на всякий случай: https://github.com/codedokode/pasta/blob/master/network/urls.md - там написано, что такое query string

>>1387384

Урок по MVC https://github.com/codedokode/pasta/blob/master/arch/mvc.md
Ответы: >>1394909
Аноним 2019/05/06 06:46:42  №1394743 28
image.png (119, 1250x796)
796x1250
>>1394732
>чтобы не писать кучу if или кучу try/catch.
В смысле? На той же яве и в C++ try/catch нужно было на каждый чих ОТДЕЛЬНО устанавливать, а в PHP он как то по другому действует? Тип как try/catch может выглядеть ОДИН на всю программу?

>В твоем случае надо либо использовать set_exception_handler, либо оборачивать все в огромный try/catch
Я чет не понимаю. try/catch должен оборачивать что? ??

>А в мануале ответа нету? Тут например
Там написано, для того чтобы получить ошибку нужно вызвать какую то функцию. И я не увидел какую именно ошибку выбрасывает запрос. Мне же нужно знать, какую именно ошибку выбрасывает запрос, чтобы поймать ее.

Ответы: >>1394746 >>1394747
Аноним 2019/05/06 07:01:29  №1394746 29
>>1394743
Короче, вот если так сделать, то что будет. Это кстати разработка БД, мне не нужно выдавать ошибку


<?php
set_exception_handler(function (Throwable $exception) {
//Код из мануала ОПа
error_log($e->__toString());

header("HTTP/1.0 503 Temporary unavailable");
header("Content-type: text/plain; charset=utf-8");

});
require_once __DIR__ . '/login.php';

$dbh = new PDO('mysql:host=localhost;dbname=', $un, $pw);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); //И куда теперь эту штуку девать?
$query = "CREATE TABLE student (
id SMALLINT NOT NULL AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
surname VARCHAR(50) NOT NULL,
gender ENUM('male', 'female') NOT NULL,
groupNumber VARCHAR(5) NOT NULL,
email VARCHAR(30) NOT NULL UNIQUE,
totalPoints SMALLINT UNSIGNED NOT NULL,
yearOfBirth YEAR NOT NULL,
localOrNonresident ENUM('local', 'nonresident') NOT NULL,
PRIMARY KEY (id)
)";

$dbh->query($query);
$dbh
Ответы: >>1394749
Аноним 2019/05/06 07:01:39  №1394747 30
>>1394743

Пусть у тебя все запросы идут через index.php. Тогда можно написать в нем:

require_once '....error_handler.php';
initErrorHandler();

try {
require_once 'bootstrap.php';
$fc = new FrontContrller();
$fc->handleRequest();
} catch (Throwable $e) {
handleException($e);
}

Альтернатива:

require_once '....error_handler.php';
initErrorHandler();
set_exception_handler('handleException');
$fc = new FrontContrller();
$fc->handleRequest();

Соответственно, во всех остальных местах кода try/catch не нужен, так как исключение будет поймано в index.php. Объясни теперь, откуда у тебя идея, что его надо писать много раз?

В мануале специально дан такой пример, чтобы с помощью расположения try/catch показать, в каком месте выбрасывается исключение. Это не значит, что ты его должен копировать строка в строку. Более того, там объясняется, как отключить выброс исключений и использовать ERRMODE_WARNING, потому и try/catch так поставлен, чтобы исключение не вылетело наружу из кода. А у тебя цели "отключать" исключения нету. То есть ты нашел в мануале пример, который вообще отношения к твоей ситуации не имеет.

В яве и Си++ то же самое, не требуется везде ставить try/catch.

Видимо, я плохо в уроке про исключения это объясняю. Но тебе определенно надо изучить исключения получше.
Ответы: >>1394765
Аноним 2019/05/06 07:04:56  №1394749 31
>>1394746

Если это скрипт, который запускается вручную из консоли (командной строки), то вообще писать try/catch не нужно, так как PHP в этой ситуации при исключении выведет информацию о нем и завершит скрипт. И соответственно, header в консоли не имеет никакого смысла.

Если это не скрипт в консоли, а для веба, то надо делать, как я описал выше, либо set_exception_handler, либо все завернуть в единственный try/catch.
Ответы: >>1394772
Аноним 2019/05/06 08:09:22  №1394765 32
>>1394747
Еще больше запутался.
require_once '....error_handler.php';
Что это за многоточие и что это подключаем тут?

initErrorHandler();
И эта функция что делает?? Не гуглится

Скажи я правильно понял или нет, пожалуйста.
Берем главный файл index.php. В него входят две первые строчки, которые я не понял и дальше включаем try. В try идет подключение файла bootstrap. А bootstrap это толи модель, толи просто инициализатор в MVC. Там хранятся файлы:
1) Класс, который описывает сущность студент
2) Класс, который работает с базой данных(паттерн TableDataGateway)
3) Класс, который проверяет правильность ввода данных.
Так вот в тех классах исключения писать не надо? Мне не нужно в классе, который реализует паттерн TableDataGateway использовать отлов ошибок/исключение/try/catch?
Подключение к БД в каком месте идет? В TableDataGateway или в index?
Просто если в index, то что мне делать в конструкторе public function __construct(PDO $pdo) { ... } класса TableDataGateway? Взять данные из базы данных в массив?
И где мне тогда подключаться к базе данных? В try/catch до bootstrap?

$fc = new FrontContrller();
$fc->handleRequest();
Это я тоже не понял. Это шаблоны?

И почему в альтернативе не описана функция set_exception_handler('handleException')? Ты подразумевал, что она где то описана?
Ответы: >>1394771 >>1415600
Аноним 2019/05/06 08:26:49  №1394771 33
>>1394765
>А bootstrap это толи модель, толи просто инициализатор в MVC.
Это прелоадер называется. Там инициализируются зависимости, окружение и тд.
Аноним 2019/05/06 08:32:56  №1394772 34
>>1394749
Кстати я подразумевал, что этот скриgn будет использован один раз. То есть он нужен был для GITHub, чтобы можно было включить один раз и все. Он создал бы базу данных и больше не понадобился.
Ответы: >>1394785
Аноним 2019/05/06 09:05:23  №1394785 35
>>1394772

Лучше использовать для этого SQL-дамп. Просто создаем файл с расширением .sql и в него пишем нужные SQL-команды, с точкой с запятой в конце каждой. Дампы можно генерировать программами вроде mysqldump или phpmyadmin, но можно и писать руками (заодно поучишься SQL).

Загружается дамп через программу-клиент БД или через командную строку.

- http://www.mysql.ru/docs/man/mysqldump.html
- пример первого попавшегося, найденного в гугле, дампа: https://github.com/cymitty/Student-list/blob/master/studentlist.sql

Полезно писать дамп руками, чтобы освоить SQL и работу с дампами из командной строки.

Если же тебе надо что-то посложнее загрузки дампа, то надо сделать скрипт для командной строки. При этом делать страницу ошибки не требуется, и писать try/catch тоже, так как по умолчанию PHP выведет подробности ошибки сам.

Почитать про командную строку простыми словами: https://github.com/codedokode/pasta/blob/master/soft/cli.md
Аноним 2019/05/06 19:18:00  №1394909 36
>>1394733
> вынести решение вопроса "что делать при ошибке" в отдельный метод
Вот это мне нравится. Вытащу тогда содержимое catch во вспомогательный метод типа tryToRepairTheRequest().
В родителе будет
protected function tryToRepairTheRequest(\ErrorException $e) {
// можем что-то сделать? если нет, throw $e;
}
В наследниках буду делать
private function tryToRepairTheRequest(\ErrorException $e) {
try { parent::tryToRepairTheRequest($e); }
catch (\ErrorException $e) { // специальный код для наследника, а если не вышло то опять же throw $e; }
}

>У тебя объект представляет один запрос и для нового запроса создается новый объект?
Нет. Запросы могут идти через один объект, а вот ответы - уже новые объекты.
$reader = new WebReader($defaultStreamContext, $maxQtyAttempts); // контекст стрима, который будет использован, если в get() никакой не указан, и кол-во попыток перезапросить при сбоях
$response = $reader->get('https://google.com'[, $streamContext]); // $response - объект класса WebResponse, содержащий ответ
$response2 = $reader->get('https://yandex.ru');

> что, если ты в процессе обработки одного запроса попытаешься через этот класс сделать другой?
Не понял. У меня нет никакой асинхронности и тредов. Вызвал get() - получи WebResponse или эксепшен.
>Свойства второго запроса затрут первый?
Ну, каждый запрос плодит по совершенно независимому WebResponse. WebReader при этом может оставаться один. Все, что он знает - какие хттп-заголовки и параметры стрима выставлять. $url нигде не запоминается и живет только внутри get(), который под капотом вызывает return $this->doRequest($url, $streamContext, $this->qtyAttempts), если ему нравятся переданные параметры. А doRequest() возвращает new WebResponse($http_response_header, $content), куда кладет всё полученное, если запрос удался.
Ответы: >>1398391 >>1402423 >>1402834
Аноним 2019/05/12 13:29:03  №1398391 37
ОПчик, ответь, пожалуйста, нормальная ли архетиктура в >>1394909
Аноним 2019/05/18 10:41:34  №1402423 38
>>1402419
Хочу узнать, нормальное ли у меня ООП в >>1394909
Аноним 2019/05/19 03:51:23  №1402834 39
>>1402686

Вообще, проще оставить все как есть, так как установка делается не так часто. Но если тебе хочется to go deeper ....

В composer на события можно повесить вызов функции или статического метода: https://getcomposer.org/doc/articles/scripts.md#package-events

При этом он получит объект события. Из него как-то можно попробовать выковырять название пакета: https://getcomposer.org/doc/articles/scripts.md#event-classes

Подробности придется искать в коде композера или в Гугле.

Также, хочу заметить, что твои скрипт не кросс-платформенны и работают только под Linux/Mac. Правильнее было бы повесить кроссплатформенный PHP-скрипт.

>>1394909

Ты как-то что-то усложнил. Давай спроектируем все с нуля:

Задача: дать возможность при ошибке поменять реквест и отправить запрос заново. Значит, нужна функция. Она может получать объект ошибки (не ErrorException, который соответствует PHP-ошибке, а например, HttpException) и объект Request. Она может вернуть либо null - не повторять запрос, либо вернуть тот же или модифицированный Request для повтора запроса, либо выбросить какое-то новое исключение:

function handleError(HttpException $e, Request $r): ?Response { ... }

Реализация по умолчанию, естественно, будет возвращать null.

Но тут есть подвох. Что, если мы хотим, например, в ответ на ошибку 503 сделать паузу в 5 секунд и сделать до 3 повторов запроса? Как нам хранить счетчик запросов? В данном случае - хранить его негде (если мы только не предусмотрели это в базовом классе).

Потому можно попробовать другой подход. Делаем переопределяемым сам метод отправки запроса - sendRequest(Request $req): Response. В наследнике просто оборачиваем его:

function sendRequest(...): ...
{
// любой код
parent::sendRequest()
// любой код
}

Это получается более универсальным подходом, как мне кажется.

А еще более универсально будет обернуть выполнение запроса без наследования, обернув вызов метода get().

Также, можно посмотреть на архитектуру питоновской библиотеки urllib, где есть плагины (openers), но она наверно сложновата для твоего случая: https://docs.python.org/3/library/urllib.request.html#module-urllib.request

У тебя в коде ошибки:

- указан слишком общий класс для отлова исключений
- нет реализации по умолчанию

Вообще, подход с оборачиванием проще, чем с обработчиком ошибок, как мне кажется.
Ответы: >>1402868
Аноним 2019/05/19 07:21:38  №1402868 40
>>1402834
> скрипт не кросс-платформенны и работают только под Linux/Mac.
Я не автор того скрипта, но не понял зачем давать такой совет. Под виндой бекенд обычно не разрабатывают, во многих компаниях наоборот распространена практика пересаживания всех на мак/убунту, чтобы проекты можно было быстрее поднимать по инструкции. Никогда не видел, чтобы в проекте было несколько параллельных инструкций для разных ОС. Зато часто видел древние проекты, которые не то что на винде запустить нельзя, их нужно запускать только под определённой версией PHP и только под апачем, так как на его rewrite правилах и includ'ах завязан весь код.
Ответы: >>1402920 >>1405044
Аноним 2019/05/19 09:35:10  №1402920 41
>>1402868
> бекенд обычно не разрабатывают
Net Core
Аноним 2019/05/22 23:52:06  №1405044 42
>>1403996

Ты ищешь сложное решение вместо простого. В случае использования элемента display: block и задания ему ширины, маргины вычисляются автоматически. Достаточно задать левый маргин, ширину и поставить auto для правого маргина.

Как плюс, это работает вообще во всех браузерах, в отличие от calc(), который пришел только с CSS3 и внедрен с ~2013 года: https://caniuse.com/#feat=calc

Обрати также внимание, что в части старых бразеров calc доступен только с вендорным префиксом. Изучи эту тему, и добавь нужные префиксы, если ты хочешь использовать calc(). Также, добавь в закладки или запомни сайт caniuse, он наверняка еще пригодится.

В CSS полезно знать, как работают значения по умолчанию, чтобы меньше писать кода и меньше менять при правках.

>>1403678

Вообще, я бы советовал просто прочитать цикл статей "создаем приложение на фреймворке X". Вот, например, например, первый попавшийся туториал по Symfony: https://auth0.com/blog/symfony-tutorial-building-a-blog-part-1/

А так, пожалуйста, сложное облачное хранилище файлов nextcloud: https://github.com/nextcloud/server

CMS Интернет-магазина Magento: https://github.com/magento/magento2

>>1402868

Я довольно долгое время под виндой работал, PHP и Апач там вполне работают.

На винду поставить несколько версий PHP проще простого - скачиваем zip-архивы и распаковываем в разные папки. А под линукс? Либо заморачиваться со сторонними репозиториями, которые перезапишут тебе libssl, либо использовать работающие с переменныем успехом скрипты вроде phpenv.
170 - 590 Аноним 2019/06/13 04:11:39  №1415600 43
>>1394765

> require_once '....error_handler.php';
> Что это за многоточие и что это подключаем тут?

Многоточие - это путь к файлу, если он в какой-то папке. Файл содержит обработчик ошибок.

> initErrorHandler();
> И эта функция что делает??

Ее надо написать самому, это функция из error_handler.php. Она, как следует из названия, задает обработчик ошибок.

> А bootstrap это толи модель, толи просто инициализатор в MVC.

Это файл, который подготавливает код: например, задает автозагрузчик, создает нужные объекты (или описывает из в DI контейнере). Если он тебе не нужен, то можно его не использовать.

> Так вот в тех классах исключения писать не надо? Мне не нужно в классе, который реализует паттерн TableDataGateway использовать отлов ошибок/исключение/try/catch?

Да, не надо.

> Подключение к БД в каком месте идет? В TableDataGateway или в index?

Можно создавать объект PDO в bootstrap.php, можно в index. Это не очень важно, где именно. Объект PDO создается там же, где и другие нужные для работы кода объекты.

> Просто если в index, то что мне делать в конструкторе public function __construct(PDO $pdo) { ... } класса TableDataGateway? Взять данные из базы данных в массив?

Это DI. Прочитай урок по DI: https://github.com/codedokode/pasta/blob/master/arch/di.md

> Это я тоже не понял. Это шаблоны?

Это Front Controlller, погугли.

> Ты подразумевал, что она где то описана?

В мануале.

Если есть еще какие-то вопросы, уточняй.