«phpClub» — архив тем ("тредов"), посвящённых изучению PHP и веб-технологий.
Аноним 2017/04/17 18:54:31  №975137 1
Аноны, что означает подобная запись?
public function get(): StringReverseWorker
{
код
}
Интересует именно двоеточие
Ответы: >>975144
Аноним 2017/04/17 19:01:44  №975144 2
>>975137
>: StringReverseWorker
Возвращаемый тип.
Гугли: тайпхинтинг в пхп.
Ответы: >>975149
Аноним 2017/04/17 19:09:38  №975149 3
>>975144
Да, оно, спасибо. Впервые вообще такое вижу. Откуда ты об этом узнал?
Ответы: >>975158 >>975159
Аноним 2017/04/17 19:19:58  №975158 4
>>975149
Это в седьмой пыхе завезли. Strict Mode, все дела
Аноним 2017/04/17 19:20:14  №975159 5
>>975149
Это супер новая фитча пхп7.
Ответы: >>976106
Аноним 2017/04/19 01:41:40  №976106 6
>>975191

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

Также у тебя там 2 свитча для математических действий, попробуй объединить в один.

>>975183

Сам ты сталкер. Query Builder используется для сборки запроса из кусков с условиями, если запрос всегда одинаковый, то смысла его использовать нет.

То же касается и DQL, смысл тут его использовать если можно без него обойтись.

Ты вместо аккуратного запроса нагородил кучу скобок и стрелок и наверно думаешь что Query Builder придумали как замену SQL.

>>975159

Очень полезная фича. Раньше тип указывали через phpdoc вроде @return SomeClass, а теперь можно нормально на уровне языка указать.

>>975117

Во-первых, я не советую исплоьзоваь NativeSQL с маппингом. Если тебе нужен маппинг - используй DQL или Query Builder , если тебе нужно посчитать количество то можно выполнить обычный SQL запрос без маппинга, напрямую через DBAL.

Во-вторых, ассоциации в доктрине загружаются лениво. То есть они не загружаются из БД пока к ним не обратишься (если только ты не указал для них жадную загрузку).

Соответственно запрос вида

$em->find('Thread', $threadId);

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

Для подсчета числа постов ты можешь использовать

SELECT COUNT(*) FROM posts WHERE thread_id = ?

Но еще эффективнее будет просто в треде сделать поле "число постов" и брать данные из него. Это назвается денормализация - добавление избыточных данных в базу ради повышения производительности.

Далее, тебе надо для треда получить 3 последних поста. Тут есть много вариантов:

1) через DQL делаем запрос вида

SELECT p FROM posts WHERE IDENTITY(posts.thread) = ? ORDER BY postedTime DESC
с опцией setMaxResults(3)

Это будет преобразовано в SQL запрос вида SELECT .. ORDER BY postedTime DESC LIMIT 3

Разумеется, нужен индекс по (thread_id, postedTime) для оптимальной выборки.

Этот метод позволяет выбрать 3 последних поста оптимально, но только для 1 треда. Нужно для 10 тредов - нужно 10 запросов.

2) потому можно при желании применить денормализацию и хранить в БД ссылки на 3 последних поста каждого треда. Либо в самой таблице тредов в виде id, либо в виде таблицы связи многие-ко-многим треды <-> посты. В Доктрине она оформляется как ассоциация hasMany по моему.

Это позволяет одним запросом выбрать 3 последних поста для N тредов сразу.

Тебе важно разобраться, как именно работает Доктрина. Какие она может генерировать запросы в разных случаях.

Ну например в такой ситуации:

1: $thread = $em->find('Thread', $threadId);
2: $posts = $thread->getPosts();
3: foreach ($posts as $post)

делается 2 SQL запроса:

В строчке 1 - SELECT FROM threads WHERE id = ?
В строчке 3 (да, в 3, а не в 2, так как у нас ленивая коллекция) - SELECT FROM posts WHERE thread_id = ?

Если понимать, как работает Доктрина,то станет видно что любые обращения к коллекции $posts вызовут загрузку всех постов треда в память. даже если они все нам не нужны.

>>975117

>>Тогда будет один запрос. Но на мой взгляд, это только утяжелит таблицу, и приведет к дублированию данных без особой выгоды
> Это действительно так плохо? Это решение решило бы проблему.

Ну давай взвесим:

1) если не дублировать данные. таблица будет раза в 2 меньше, но надо сделать 2 запроса которые можно объединить в 1 с помощью UNION
2) если дублировать данные, таблица будет больше, при добавлении поста надо делать больше вставок, зато мы делаем 1 запрос вместо 2.

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

Ответы: >>976188
Аноним 2017/04/19 10:24:58  №976188 7
>>976106
>Если понимать, как работает Доктрина,то станет видно что любые обращения к коллекции $posts вызовут загрузку всех постов треда в память. даже если они все нам не нужны.
Такое поведение будет и при getRepository()?

>По моему пункт 1 выгоднее. У нас ведь была цель избавиться от потенциально большого числа запросов (если цепочка постов длинная), а два запроса или один - разницы особой нет.
Но нужно сделать не два запроса, а ещё столько же сколько детей. Получается мы делаем эти запросы либо при вставке либо при получении. Только есть разница, что мы вставляем только один раз при добавлении поста, а получаем каждый раз когда пользователь получает цепочку. С такой перспективы кажется лучше 2-ой вариант.
Ответы: >>976350
Аноним 2017/04/19 15:56:12  №976350 8
>>976188

getRepository возвращает объект репозитория и ничего не загружает из базы вообще.

> Но нужно сделать не два запроса, а ещё столько же сколько детей.
Нет, я говорил про вариант, где для построения цепочки нужно ровно 2 запроса:

1) для постов, до которых можно дойти по стрелкам в графе WHERE post = A (на которые ссылается A)
2) для постов, до которых можно дойти, идя против направления стрелок в графе WHERE reference = A (которые ссылаются на A)

Посмотри на граф со стрелками и может быть станет понятнее.

Я предлагаю сделать таблицу, где мы для каждого поста (узла в графе) указываем все посты, в которые можно дойти по стрелкам из него.

Ответы: >>976361
Аноним 2017/04/19 16:29:57  №976361 9
>>976350
>2) для постов, до которых можно дойти, идя против направления стрелок в графе WHERE reference = A (которые ссылаются на A)
Но если пост A ссылается на пост B то нужно будет сделать запрос WHERE reference = B, и так далее.

При условии что структура такая:

>post | reference | depth
>A | B | 1
>A | C | 1
>A | D | 2
>A | E | 2
>B | D | 1
>B | E | 1
Ответы: >>976687
Аноним 2017/04/20 04:04:53  №976687 10
>>976518

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

>>976403

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

>>976391

Можно, она для этого и придумана, но неудобно. Прямой слеш поддерживается и в Линуксе, и в винде, проще использовать его.

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

Вот примеры таких библиотек (нашел на packagist.org по слову path):

- https://github.com/donutclub/php-path
- https://github.com/vweevers/php-path
- https://github.com/webmozart/path-util

>>976361

Кажется, я понял, что ты имел в виду.

Тебе надо получить все узлы в графе, которые достижимы из заданного, если идти по стрелкам в любом направлении? Тогда да, для ускорения выборки надо заранее строить их списки для каждого поста, и списки могут быть огромные. Там у тебя легко могут сотни постов набраться (нужно конечно делать тесты чтобы узнать).

> Получается мы делаем эти запросы либо при вставке либо при получении. Только есть разница, что мы вставляем только один раз при добавлении поста, а получаем каждый раз когда пользователь получает цепочку.
Ну да, либо мы строим полный список заранее, либо делаем много запросов.
Ответы: >>977026
Аноним 2017/04/20 20:00:55  №977026 11
>>976687
>А зачем ты вообще присылаешь ссылку на почту? Попробуй начать рассуждать с этого.
Чтобы удостовериться что почта существует, конечно же. В таком ключе становиться очевидно, что не так важно что должно содержаться в ссылке. Просто я часто видел в таких ссылках содержится какой-то хэш-код.
Ответы: >>979512
Аноним 2017/04/25 02:19:47  №979512 12
>>977716

ок, верно.

>>977633

А что у тебя там за связи? Многие-ко-многим между categories и executor? Ты не пробовал сделать как тут описано ( http://symfony.com/doc/2.7/form/form_collections.html )? В частности, посмотри пункт "Doctrine: Ensuring the database persistence" в конце.

Также, в Доктрине прописаны связи между category и executor как многие-ко-многим?

>>977180

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

(?<=[.,])(?![.,]) - соответствует позиции после точкой или запятой, за которой нет другой точки или запятой.

Решено верно.

>>977068

Можно включать, можно не включать.

>>977026

А зачем нужен хеш? Чтобы доказать, что пользователь действительно получил ссылку, а не пытается подтвердить несуществующий ящик, мы генерируем сложный случайный код (не хеш, с чего ты решил, что это результат хеш-функции?), и просим пользователя его предъявить как подтверждение владения почтовым ящиком. Злоумышленник не может угадать код.
Ответы: >>979545
Аноним 2017/04/25 06:58:11  №979545 13
>>979512
>А зачем нужен хеш? Чтобы доказать, что пользователь действительно получил ссылку, а не пытается подтвердить несуществующий ящик, мы генерируем сложный случайный код (не хеш, с чего ты решил, что это результат хеш-функции?), и просим пользователя его предъявить как подтверждение владения почтовым ящиком. Злоумышленник не может угадать код.
Было бы удобно не создавать новых полей или таблиц которые содержат этот код, а просто отправить хеш тот самый который получаем из пароля.
Ответы: >>980992
Аноним 2017/04/27 14:40:32  №980992 14
>>979545

Ну так этот хеш может сгенерировать и злоумышленник, так как он знает свой пароль.

>>980038

А какое именно условие надо поправить?

>>980278

> join seans s2 on s2.start > s.start
Тут должно быть >=

> список фильмов, для каждого указано общее число посетителей за все время, среднее число зрителей за сеанс и общая сумма сбора по каждому, отсортированные по убыванию прибыли.
А любопытно, для подведения итога тут не подойдет GROUP BY WITH ROLLUP вместо UNION?

> число посетителей и кассовые сборы, сгруппированные по времени начала фильма:
Тут можно сделать так:

SELECT CASE
WHEN HOUR(start) BETWEEN 9 AND 14 THEN '9-15'
WHEN HOUR(start) BETWEEN 15 AND 17 THEN '15-18'
END CASE as group,
...
GROUP BY group

Также, можно заджойниться на созданную на лету таблицу:

SELECT ...
FROM seans
JOIN (
SELECT '9:00' AS start, '15:00' AS end
UNION
SELECT '15:00' AS start, '18:00' AS end
) AS periods ON seans.start >= period.start AND seans.start < period.end
...
GROUP BY periods.start

Так, в общем, верно решено. Только названия стоит получше придумывать и ключевые слова писать большими буквами.
Ответы: >>981086 >>981349
Аноним 2017/04/27 17:59:50  №981086 15
>>980992
Да, WITH ROLLUP подошёл и помог избавиться от лишнего запроса с джойном:
http://sqlfiddle.com/#!9/3935de
https://pastebin.com/BFvfR3U8

Правда в мануале написано, что ORDER BY и WITH ROLLUP взаимно исключающие: https://dev.mysql.com/doc/refman/5.7/en/group-by-modifiers.html
Поэтому для сортировки нужно оборачивать запрос с ROLLUP в ещё один запрос вида SELECT * FROM (...) ORDER BY column
Однако такой подход будет при сортировке также учитывать строку 'Итого'.
Ответы: >>981471
Аноним 2017/04/28 02:10:22  №981349 16
>>980992
>Ну так этот хеш может сгенерировать и злоумышленник, так как он знает свой пароль.
Не может, так как он не знает соль. Но если мы позволяем не активированному пользователю логиниться и сохраняем хэш в куки, тогда злоумышленник может получить его от туда. Значит остается только вариант с созданием дополнительных таблиц/колонок?
Ответы: >>981471
Аноним 2017/04/28 13:59:01  №981471 17
>>981007

Нет, не любой. Ты все путаешь.

Во-первых, 2ch.hk - это не URL. Прочти мой урок про URL, это будет полезно: https://github.com/codedokode/pasta/blob/master/network/urls.md

Во-вторых, PHP не поддерживает любые URL, а поддерживает "потоки", за счет чего в некоторых функциях можно вместо имени файла указать похожий на URL идентификатор:

http://php.net/manual/ru/intro.stream.php
http://php.net/manual/ru/wrappers.php

То, что ты указал, для PHP - это просто имя файла.

>>981024

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

>>981063

На ideone не включили почему-то нужное расширение. Используй альтернативы, например 3v4l.org

>>981086

Ага, значит тут он не очень подходит. Но зато ты теперь знаешь про эту возможность.

Конечно можно было извернуться как-то так

ORDER BY IF(id = 'Итого', 1, 0) ASC, ...

но наверно это уже лишнее усложнение.

>>981348

Нужна программа на PHP, которая будет брать данные из базы и генерировать на их основе HTML код, а также обрабатывать запросы на изменение данных.

>>981349

Лучше сделать отдельное случайное число, чтобы не создавать потенциальных уязвимостей. Если тебе жалко места, можно сделать отдельную таблицу кодов подтверждений и чистить в ней старые записи.
Ответы: >>981482
Аноним 2017/04/28 14:12:00  №981482 18
>>981471
>Локально у себя может быть проще поставить Апач вместо того, чтобы возиться с настройкой нгинксов.
Зачем ты об этом говоришь, если изначальный вопрос только про быстродействие сайта был?