Этого треда уже нет.
Это копия, сохраненная 5 июля 2018 года.

Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее

Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
Клуб изучающих PHP и webdev #101 ОП # OP 1174695 В конец треда | Веб
Добро пожаловать. Тут мы изучаем язык PHP (а также JS/CSS/HTML/SQL), решаем задачки и даже делаем простые сайты! Зачем? Кто-то хочет сделать себе блог, кто-то приобрести новую профессию, кому-то просто нечего делать.

Да, в нашем треде отвечают почти на все вопросы, только не сразу.

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

Предыдущий тред был тут: >>1152267 (OP) . Остальные треды есть в архиве: https://phpclub.tech/ (там есть поиск, так что можно легко найти обсуждение какой-то задачи или ответы на свой старый пост) или ищутся в гугле по словам "клуб изучающих php" и в архиваче.

Мейлач лежит? Есть запасной тред на доброчане: /s/res/23225.xhtml#i46467

Что самое главное для программиста? Умение аккуратно оформлять код (как, написано во втором посте).

Правила: ведем себя воспитанно, помогаем новичкам, читаем учебники, решаем задачки, постим ссылки на решения, ОП их проверяет и дает советы и замечания. ОП заходит редко, где-то раз в 2-3 дня, у него мало времени, не жди его, решай задачки дальше. ОП отвечает на все вопросы по его задачкам и учебнику, а вот насчет каких-то других вещей - только если останется время. Но в треде немало анонимных экспертов разного уровня, так что вряд ли вопрос останется без ответа.

С чего начать

У нас есть свои уроки по основам PHP, они собраны и выложены по адресу http://codedokode.github.io/phpbook (вас отредиректит на другой домен, не читайте, не сохраняйте, не запоминайте его, он временный). Это учебник для изучающих с нуля, то есть если ты вообще ничего не знаешь, то можно начать с него. Он простой и понятный. Там есть задачи, их нужно решать (чтобы стать программистом, надо писать код — иначе никак). Пости ссылки на решения в тред, мы их проверим, напишем замечания и дадим советы по улучшению. С другой стороны, если этот учебник тебе не нравится, можно читать любой другой. Или официальный мануал. Или все сразу.

Устанавливать пока что ничего не требуется, разве что редактор кода вроде Sublime Text 3, Notepad++, Visual Studio Code, Netbeans PHP или PhpStorm (с ним будет удобнее).

Если не знаешь как решать, запости код, напиши в каком месте остановился и попроси подсказку.

Ты прошел весь учебник? Молодец, но это были лишь основы языка PHP, этого недостаточно. Вот что в идеале надо изучить еще: ООП, как работает веб-сервер, HTML/CSS, SQL, PDO, работа с таблицами в БД, работа с формами, MVC, git, composer, JS, фреймворки, автоматизированное тестирование.

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

- для начала прочти урок https://github.com/codedokode/pasta/blob/master/soft/web-server.md
- установи Апач + PHP (советы выше и ниже) и читай туториал http://php.net/manual/ru/tutorial.php
- Учи HTML/CSS и SQL, PDO, хотя бы основы
- Далее простая, но полезная задача сделать список студентов, в ней много полезных советов: https://github.com/codedokode/pasta/blob/master/student-list.md
- Более сложная задача сделать файлообменник на микрофреймворке Slim: https://gist.github.com/codedokode/9424217
- Еще более сложная и долгая задача на Yii/Symfony: https://gist.github.com/codedokode/8733007
- После нее можно изучать автоматизированное тестирование https://gist.github.com/codedokode/a455bde7d0748c0a351a
- Если ты все решил, переходи к Symfony 3/Doctrine 2
- Почитать про паттерны http://designpatternsphp.readthedocs.org/ru/latest/README.html (если ты не изучил ни одного фреймворка, то это будет рановато), тут с примерами кода http://designpatternsphp.readthedocs.org/ru/latest/README.html . Имей в виду что без примеров использования их учить бесполезно - не поймешь, хочешь увидеть примеры использования паттернов - ковыряй исходники Симфони, например Symfony Forms. Не заучивай паттерны - смотри код и думай, зачем тут они использованы.

Чтобы делать эти задания, тебе надо установить Апач + PHP (можно заодно сразу и MySQL) на компьютер. Вот полезные инструкции:

https://github.com/codedokode/pasta/blob/master/soft/php-install.md
https://github.com/codedokode/pasta/blob/master/soft/apache-install.md

Может тебе понадобится пользоваться командной строкой, вот гайд https://github.com/codedokode/pasta/blob/master/soft/cli.md

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

Параллельно стоит подучивать английский, на первых порах можно без него, но по мере развития придется все чаще сталкиваться с англоязычными статьями, так что лучше не откладывать. Читать можно news.ycombinator.com - это что-то вроде их хабра. Также можно начинать смотреть фильмы и видео на английском.

Также, у нас есть задачи которые позволят тебе изучить или подтянуть до нормального уровня знания JS/HTML/CSS/SQL. Решай их параллельно с задачами выше.

- HTML/CSS: https://github.com/codedokode/pasta/blob/master/html/html.md
- JS: https://gist.github.com/codedokode/ce30e7a036f18f416ae0
- SPA (сложно): https://github.com/codedokode/pasta/blob/master/js/spa.md
- Проверялка решений на JS: http://dkab.github.io/jasmine-tests/
- MySQL: https://github.com/codedokode/pasta/blob/master/db/databases.md

Что почитать

- Мануал по PHP — http://www.php.net/manual/ru/langref.php
- Сайт phptherightway (перевод на русский: http://getjump.me/ru-php-the-right-way/ )
- По PHP: Профессиональное программирование на PHP Джордж Шлосснейгл
- По PHP: Мэтт Зандстра — PHP: Объекты, шаблоны, методики программирования
- JS: learn.javascript.ru
- Про Git: https://git-scm.com/book/ru/v1
- Новости IT на англ. https://news.ycombinator.com/

Оформляй код аккуратно!!! — например пропусти через phpformatter.com . Также, если ты пользуешься IDE вроде PhpStorm, Netbeans, Eclipse, то в них эта опция встроена, подробнее: https://gist.github.com/codedokode/8759492

У ОПа нет аккаунтов и групп вконтакте, в фейсбуке, в твиттере, все "пхп-треды" там поддельные.

Платиновые вопросы

- Почему PHP? Потому что вакансий море, и учить легко.
- Сайт опять упал!!!!! — Не паникуй, а открой http://rghost.ru/6bfCY9lfl и получи личную немного устаревшую оффлайновую копию сайта (можно читать хоть на андроиде без интернета)
- Что надо знать чтобы найти работу - разработчику: PHP, SQL, HTML/CSS, JS, ООП, Git, композер, MVC, фреймворк. Верстальщику - HTML/CSS, JS, jQuery. У нас в треде были люди, которые практически с нуля учились и смогли найти работу.
- Что будут спрашивать на собеседовании если 0 опыта - гонять по теории, по официальному мануалу PHP, давать дурацкие задачки на переворачивание строк, гонять по SQL (транзакции, внешние ключи, напиши запрос), по JS (как сделать анимацию при нажатии кнопки), ну погугли, не ленись
- Можно подробнее про поиск работы, собеседования - нет, ОП писать не будет, но может кто из анонов захочет рассказать. Поищите тред перезвонивших, а также раздел /wrk/
- Сколько времени надо изучать все это? - все зависит от тебя, но не меньше 6-8 месяцев
- Нужен ли ООП, фреймворки, MVC, git, composer? — Да, однозначно. Посмотри любую вакансию.
Важно ОП 2 1174696
Код важно писать не как попало, а аккуратно и по правилам. Почему? Потому, что на неакуратно написанный код не хочется даже смотреть.

Если тебе лень выравнивать код руками, закачай его на http://www.phpformatter.com/ и нажми «format». Робот исправит выравнивание и отступы в мгновение ока (да, прогресс не стоит на месте). Если ты используешь мощную IDE вроде PhpStorm, там тоже есть функция форматирования кода.

Горячие клавиши для форматирования кода в разных IDE: https://gist.github.com/codedokode/8759492

Вообще, в PHP долгое время не было единого стандарта оформления кода, все писали как попало и было много бардака, но сейчас дело лучше — есть стандарты PSR-1 и 2. Вот как надо оформлять код:

- переменные и функции пишутся с маленькой буквы, подчеркивание не используется, используется camelCase, пример: $x, $numberOfPeople, printResults()
- Название функции начинается с глагола, в стиле «сделайЧтоТо»
- не знаешь английский? Не беда, в 21 веке есть решение этой проблемы. Не пиши транслитом, открой лучше Гугл Транслейт или slovari.yandex.ru и найди название для переменной там
- в именах классов используется CamelCase, первая буква большая, «_» может использоваться
- мы предпочитаем подстановку переменных вместо конкатенации строк: "I am $age years old" — хорошо, 'I am ' . $age . ' years old' — плохо из-за обилия точек и кавычек
- мы используем для отступов 4 пробела (можно настроить редактор, чтобы при нажатии Tab он вставлял 4 пробела)

Вот ссылка на стандарты, где все это описано подробнее и даны примеры оформления:

PSR-1: https://github.com/samdark/fig-standards-ru/blob/master/accepted/ru/PSR-1-basic-coding-standard.md
PSR-2: https://github.com/samdark/fig-standards-ru/blob/master/accepted/ru/PSR-2-coding-style-guide.md
ОП 3 1174698
Если я кому-то не ответил в прошлом треде, напомните о себе тут.

Напомню всем, что у нас есть архив тредов phpclub.tech . Там есть поиск и можно найти, например, все обсуждения задачи про кредит. Или найти свой старый пост и все ответы к нему.
4 1174704
>>174695 (OP)

>Верстальщику - HTML/CSS, JS, jQuery


Я вот не понимаю, что делает верстальщик? Если верстальщик сверстает макет, то всё-равно же придется всё заново переписывать фронетнедеру, который будет на каком-нибудь React'e описывать всё эту верстку.
5 1174705
>>174704
фикс фронтендеру
6 1174706
>>174704
фикс всЮ эту верстку
7 1174778
Задача на массив, застрял: https://ideone.com/NRDJRI
Учебник читал, гуглил, но все равно ничего не понял.
8 1174796
>>174704
Всегда думал, что фронтендер это и верстальщик тоже. Иначе что за отдельный фронтендер? Чем он будет заниматься? Это прослойка между бекендером и верстальщиком зачастую нахуй не нужная, если пишут не на реакте-вью-ангуляре?
9 1174800
>>174796
Это деление было уместно лет 10 назад в полсдений раз (ну и на проектах той эпохи), когда клиенты были тонкими, а не толстыми и на них не было иной логики, кроме как логики отображения.

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

Те же "фронтендеры" что кричат, что они занимаются только логикой отображения, просто ленивые хуеплеты, делающие двойную работу. Сначала верстальщик верстает макет, потом они его переплетают логикой - это дегенратвство. Учитывая то, что значительная часть логики отображения сегодня выносится в тот же css, анимации и прочее. И чтобы заниматься действителньо крупным проектом, нельзя быть в отрыве от верстки. Это все равно, что кричать что бэкендеру не нужно в ьазы данных. Проектировать ему может их не нужно, а дергать эффективно - еще как нужно. И если он в них не умеет, то дальше коленочных поделок пускать его нельзя. То же самое с фронтом.
10 1174852
Есть контроллер с зависимостями. Как лучше посутпить - создавать поля и передавать каждую зависимость отдельно или сразу сделать одно поле и передавать туда сразу весь DI контейнер?
11 1174855
Когда нужно использовать ООП в php? Вижу, что почти все написано в процедурном стиле.
12 1174895
>>174855

" Вижу, что почти все написано в процедурном стиле." - а что ты смотрел? Я например постоянно с Симфони сталкиваюсь, а это ООП.
13 1174967
>>174852

>сразу сделать одно поле и передавать туда сразу весь DI контейнер?


Вот так делать точно не стоит, в чем смысл DI в названии? Почитай комментарии ОПа к задаче о студентах. Если у тебя часто встречаются одинаковые зависимости в разных методах, то можешь их внедрять в конструктор, но лучше, как мне кажется, внедрять зависимости сразу в методы, тогда у тебя точно не будет неиспользуемых объектов. Обычно в крутых контейнерах есть функции вызова нужных тебе методов(например ты разбиваешь юрл и по заранее описанным рутам находишь коллбек), и они сами заполняют методы нужными зависимостями по тайп-хинту или по аннотациям или еще какой-то подпихне
15226146028240.jpg67 Кб, 1000x800
14 1175020
Всё равно ничего не понятно.

> идея примерно такая: мы заводим переменные $result (результат предыдущих действий), $number (число, которое сейчас набирается) и $op (предыдущая операция). Затем разбираем строку посимвольно (циклом for).


Это есть.

>Если это цифра — добавляем ее к числу $number (умножаем на 10 и прибавляем цифру)


Это есть.

>если это операция — то выполняем предыдущую операцию (которую мы храним в $op) над $result и $number, сохраняем итог в $result, а текущую операцию на будущее сохраняем в op. Если это «=», то выполняем предыдущую операцию и выводим $result


Это тоже есть.

При этом если тут оно хоть что-то выдавало https://ideone.com/Tjfbus, то тут я добавил одну переменную и оно умолкло https://ideone.com/PwGd9r .

Если же перенести echo $result в самый конец https://ideone.com/e6qIvF, то он выдаёт набор цифр 0002222488448842662. Они должны быть в результатах вычисления, это правильные цифры, но и не правильные.

Пытался вот так https://ideone.com/niBIBF, всё равно ничего.

Но при этом я не могу понять, где ошибка.
Если попадается операция, то создаётся временная переменная с предыдущей операцией, а текущая сохраняется на будущее. После выполняется вычисление над $result и $number операции, если же операция =, то вычисляется текущая и выводится результат с прекращением дальнейшего выполнения цикла for.
Если же попадается число, то оно складывается в $number.

Пытался разобрать это https://ideone.com/T0AfO, вообще ничего не понял.
15 1175195
>>174695 (OP)
ОП, ответь, пожалуйста, на вопрос - это очень важно. Вопрос без подвоха и не траленк. Ты би или гей?
16 1175205
>>175195
Ты своей нетактичностью даже меня задел, а я за ОП-а и двор стреляю в упор.
Намек понятен?
не-ОП
17 1175237
У нас самый лучший на свете ОП. Спасибо ему за то что он такой молодец и няша. Я бы его чаем угостил или даже не пожалел на наго бутылку лучшего Хеннеси. Если бы конечно имел возможность ирл его встретить.
18 1175238
>>175195
Он тян.
20 1175357
Что делать, если не знаешь с какой стороны начать подходить к задаче?
21 1175371
>>175357
Не подходи, блядь, дебил сука ебаный.
Она тебя сожрет.
22 1175380
Пробую решить упражнение, где надо написать программу, выводящую таблицу умножения чисел от 1 до N на самих себя, используя цикл. Программа должна вывести примерно такой результат:

1×1 = 1
2×2 = 4
...
9×9 = 81

Результат пока такой https://ideone.com/qawxeR

Я понимаю, почему в строке 1 * 1 не выводится решение, но как сделать так чтобы все работало как задумано, не городя кучи всего снаружи цикла, без костылей так сказать.
23 1175412
>>175380
ну ес кароч бля $сум в фигурные скобки перенести всё норм будет)
24 1175413
>>175412
Спасибо, добрый человек.
25 1175435
Пачаны, завасянил задачку по написанию стихов, но у меня такое чувство что это можно сделать как-то пиздаче, дайте советов мудрых.
https://ideone.com/JkebMt
26 1175556
>>175380
Чего такой вариант не устраивает?

for ($a = 1; $a < 10; $a++) {
$sum = $a $a;
echo "$a
$a = $sum\n";
}
27 1175585
28 1175591
29 1175600
Наверное очень тупой вопрос. Как лучше созавать объект, если у него в конструкторе нет зависимостей, со скобками - new Object () или без - new Object?
30 1175619
>>175600
Разницы нет, но по PSR - со скобками, ради единобразия: https://github.com/php-fig/fig-standards/blob/master/proposed/extended-coding-style-guide.md#4-classes-properties-and-methods

> When instantiating a new class, parenthesis MUST always be present even when there are no arguments passed to the constructor.

31 1175625
>>175238
Сука что же ты делаешь, теперь я правда буду думать что там может быть ОП-тян.
32 1175633
>>175625
Это правда.
изображение.png1 Кб, 571x31
33 1175636
>>175633
Просто раньше это казалось шуткой, а теперь обретает больше смысла.
Наверняка уже какой-нибудь ероха написал ОП-тяну и они уже пару лет как встречаются :(
34 1175648
Можно ли высвети сразу ответ при вызове переменных, где есть числа и операция?

Например, есть:
$z = 1;
$q = '+';
$x = 3;

echo $z, $q, $x;

Выводит: "1+3". Как сделать, чтобы оно сразу вычислялось и выводило 4?

Это касательно задачи с калькулятором. Можно же числа определить в один массив, а операции в другой, а когда for дойдёт до "=", по очереди вызвать элементы массивов с числами и операциями, так, чтобы они сложились в пример и сразу вычислялись?
image.png1,2 Мб, 1600x900
35 1175651
Сукаблджад, флуд тут развели.
ОП - это жнец, который вещает нам из глубин космоса.
Ноу дискасс.
36 1175663
>>175648
Гугли eval() для крайне опасного быстрохака, но вообще это задача синтаксического анализа, гугли и читай dragonbook %хотя вряд ли ты его осилишь, тупой и ленивый кусок дерьма%
37 1175740
>>175205

>нетактичностью


>2ch.hk


Туда ли ты зашёл, петушок?
38 1175746
Есть простейшая логин форма следующего содержания- https://pastebin.com/JG0rLWXf, помогите докрутить цикл до следующего функционала: при логине за юзера admin, к примеру, выдает результат 1, а при логине за юзера kek выдает другой результат, такой же кусок html текста.
39 1175749
>>175746
Не поставил пробел после ссылки.
https://pastebin.com/JG0rLWXf
40 1175794
Как DI контейнер "внутри" работает? Каждый раз, когда я обращаюсь к сервису из контейнера, создается новый объект?
41 1175799
>>175794
Как я понял, то часто разные контейнеры имплементируют метод singleton(), по которому возвращается один и тот же, единожды созданный объект, а по get() возвращается новенький. Так что да, по get() ты получаешь новый объект.

Хотя в статье ОПа по DI пример куска кода контейнера, который нужно доработать, имеет функционал как раз обратный, там два массива, в одном готовые к созданию сервисы, а в другом уже созданные объекты сервисов, и get() сначала проверяет массив уже созданных объектов.
42 1175828
Хочу написать студентов на скорость используя свои знания в быдлокодинге на Codeigniter'e, что бы:

1. узнать за сколько примерно в комфортных для меня условиях я смогу справиться с такой вот несложной задачкой, сейчас мне кажется что я написал бы часа за 4 не больше всё это.
2. Что бы на гитхабе был такой вот хэллоу ворлд на игнайтере для собеседований. (не то что бы я хотел на нем работать дальше, просто что бы был если спросят за скилл)
3. Освежить в памяти фреймворк и посмотреть подводные камни какие-никакие.
4. У меня ступор и я хоть и хочу каждый день сесть за задачу, но понимаю что сначала надо прочитать кучу теории по местам в которых у меня дыры, а потом уже садиться и писать сразу нормально с исключениями и паттернами хотя бы для бд. А не просто обертка пдо в свой бд-класс и поперли.

Как вам такая безумная идея, имеет смысл?
ОП 43 1175886
Проверил в старом треде посты с 24 по 29 марта. В частности:

>>1175880 - программа про вывод чисел текстом
>>1175881 - замечания по верстке отдаленно напоминающего ВК сайта
>>1175884 - https://github.com/7Y2RPXK3ETDCNRDD/webpaint

Если я не проверил чей-то пост - напомните о себе здесь.
44 1175988
Как лучше прописать путь к юзеру (в том числе самого себя) в личном кабинете panel.php ?

1. По get запросу и id юзера - panel.php?id=25 и в самой странице поставить проверки, если юзер на которого мы зашли совпадает с залогиненым юзером, то появляются крутилочки для изменения данных

или 2
Страница panel.php будет без get запроса, и все будет выполнятся внутри нее. Правда тогда вопрос: как заходить на чужие аккаунты ?

3. Как лучше поступить с точки зрения безопасности, проверяя пользователя и его привелегии?
Проверка через $_SESSION я так понял довольно уязвима ?

Короче, как лучше запилить логику личного кабинета ?
45 1175997
Q
1524070553291.jpeg2,5 Мб, 2309x1732
46 1176196
Как правильно спроектировать систему уведомления на сайте? (Не email, а внутри сайта)

Есть вариант с тремя таблицами:
-Пользователи
-События
-События+пользователи(many-to-many)

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

Но! Тут есть проблема. Во-первых пользователей очень много, около 20 000, во вторых события тоже будут измеряться тысячами.
Не будет ли тормозить запрос на выборку из третьей таблицы, учитывая, что он будет происходить при каждой загрузке страницы? (Вверху счетчик непрочитанных уведомлений).

Ситуация осложняется тем, что у событий есть права доступа (по нескольким параметрам: регион/представительство/отдел), поэтому запрос на выборку событий будет ещё медленнее.

Ещё есть мысль создать табличку типа:
Айди_пользователя|количество прочитанных уведомлений
Добавлять во второй столбец значение при прочтении уведомлений.
Однако, выглядит этот вариант не очень надежно.

Буду благодарен любым советам и идеям. Спасибо!
47 1176199
>>175988
Get + проверка с сессией.
Сессии вполне себе надежная штука.
48 1176343
Вопрос - есть \MessageFormatter в Intl, которому можно скармливать строку вида {fileCount, plural, one{файл} few{файла} many{файлов} other{файла}} и число, на выходе получим отформатированное сообщение. Я хочу такую строку хранить в файлах переводов в Symfony. Тут http://symfony.com/doc/current/components/intl.html пишут, что "The replacement layer is limited to the locale "en". If you want to use other locales, you should install the intl extension instead."
Выходит, что русский язык работать не будет и мне нужно руками вызывать $messageFormatter->format($translator->translate('files')) ?
49 1176381
>>176196
Решил просто порассуждать и поделиться мыслями,строго не бейте, все равно никто больше непишет ничего, а так глядишь дискач на почве указания на ошибки завяжется.

Как я понял ты хочешь сделать свою систему уведомлений скорее как систему обычных сообщений на сайте, но слегка урезанную. Во первых сами юзеры не смогут слать в ней друг другу сообщения, а во вторых сообщения будут генерироваться самим сайтом внутри во время выполнения некоторых функций. (ну пример наверное когда пользователь пополнил баланс на X рублей и ему прилетело сообщение системное: мол вы пополнили баланс на X рублей, теперь он Y рублей, спасибо бла бла) - для персональных оповещений звучит не так уж и плохо.

Допустим у тебя будет табличка в которой связь юзеров и сообщений. Ну добавилась туда 1 связь - и всё ок. Ничего не разрастается. Причем очевидно, по тому что ты хочешь отслеживать прочитанные сообщения у тебя будет у каждого сообщения некий флаг (readen) и в селектах его тоже будет легко учитывать. Даже можно например сделать переодическую отчистку таблицы, с переносом тех сообщений в которых дата создания больше чем пол года и readen=true в отдельную таблицу-архив, из которой всё будет долго и незаметно для юзера селектится когда он в своих уведомлениях кликнет на кнопку: смотреть давнишние, или что-то в таком духе, но нам то главное, что наша основная табличка не будет тормозить для большинства юзеров.

Ок, но что делать когда нужно разослать сообщения всем пользователям? (У нас в каталоге новая хуета-нейм, ознакомьтесь). Ты же не будешь генерить 20000 записей в эту таблицу с тем что бы каждому юзеру пришло подобное? Это же тупо засерание собственной базы и адуха как на этапе инсерта туда, так и на этапе селекта потом каждым юзером из неё. Лучше уж сделать отдельный функционал немного напоминающий новости - ты просто создаешь новость, и в отдельных полях указываешь группы пользователей для которых она видима например. Если у тебя там пользователи не сильно то и бьются по группам, то можно прямо в таблице завести столбцы с булевыми значениями, и типа указывать что-то типа:
everyone=true - новость для всех пользвателей
everyone=false, admin=true - новость для админов.
everyone=false, admin=false, premUser=true - сообщение сообщение только для каких-то там прем юзеров если у тебя такие есть. Ну надеюсь понятно в целом, и конечно же при такой системе придется продумать как и что ты будешь селектить и как ты будешь себя вести в случае добавления новых групп пользователей.
Либо если у тебя все юзеры разбиты на группы с разными ид, то можно в отдельном поле хранить какой-нибудь json массив с перечислением груп пользователей которым новость доступна.

С тем что бы отслеживать кто и что тут прочитал, а кто не прочитал - уже не получится. Но не придется для небольшого сайта писать хайлоад оптимизацию просто для того что бы следить кто что проситал.
49 1176381
>>176196
Решил просто порассуждать и поделиться мыслями,строго не бейте, все равно никто больше непишет ничего, а так глядишь дискач на почве указания на ошибки завяжется.

Как я понял ты хочешь сделать свою систему уведомлений скорее как систему обычных сообщений на сайте, но слегка урезанную. Во первых сами юзеры не смогут слать в ней друг другу сообщения, а во вторых сообщения будут генерироваться самим сайтом внутри во время выполнения некоторых функций. (ну пример наверное когда пользователь пополнил баланс на X рублей и ему прилетело сообщение системное: мол вы пополнили баланс на X рублей, теперь он Y рублей, спасибо бла бла) - для персональных оповещений звучит не так уж и плохо.

Допустим у тебя будет табличка в которой связь юзеров и сообщений. Ну добавилась туда 1 связь - и всё ок. Ничего не разрастается. Причем очевидно, по тому что ты хочешь отслеживать прочитанные сообщения у тебя будет у каждого сообщения некий флаг (readen) и в селектах его тоже будет легко учитывать. Даже можно например сделать переодическую отчистку таблицы, с переносом тех сообщений в которых дата создания больше чем пол года и readen=true в отдельную таблицу-архив, из которой всё будет долго и незаметно для юзера селектится когда он в своих уведомлениях кликнет на кнопку: смотреть давнишние, или что-то в таком духе, но нам то главное, что наша основная табличка не будет тормозить для большинства юзеров.

Ок, но что делать когда нужно разослать сообщения всем пользователям? (У нас в каталоге новая хуета-нейм, ознакомьтесь). Ты же не будешь генерить 20000 записей в эту таблицу с тем что бы каждому юзеру пришло подобное? Это же тупо засерание собственной базы и адуха как на этапе инсерта туда, так и на этапе селекта потом каждым юзером из неё. Лучше уж сделать отдельный функционал немного напоминающий новости - ты просто создаешь новость, и в отдельных полях указываешь группы пользователей для которых она видима например. Если у тебя там пользователи не сильно то и бьются по группам, то можно прямо в таблице завести столбцы с булевыми значениями, и типа указывать что-то типа:
everyone=true - новость для всех пользвателей
everyone=false, admin=true - новость для админов.
everyone=false, admin=false, premUser=true - сообщение сообщение только для каких-то там прем юзеров если у тебя такие есть. Ну надеюсь понятно в целом, и конечно же при такой системе придется продумать как и что ты будешь селектить и как ты будешь себя вести в случае добавления новых групп пользователей.
Либо если у тебя все юзеры разбиты на группы с разными ид, то можно в отдельном поле хранить какой-нибудь json массив с перечислением груп пользователей которым новость доступна.

С тем что бы отслеживать кто и что тут прочитал, а кто не прочитал - уже не получится. Но не придется для небольшого сайта писать хайлоад оптимизацию просто для того что бы следить кто что проситал.
50 1176388
>>176381
Бро, спасибо, что потратил время.

Сообщениями это не может считаться и не сработает.

Это скорее похоже на описанные тобой новости, однако, как ты сам написал, отслеживать кто что прочитал не получится. А именно это мне и нужно.
51 1176390
>>176381

>генерить 20000 записей



Нет, это не нужно. Просто записываешь в связующую табличку id пользователя и id новости, когда пользователь эту новость прочтет.
Тем самым исключаются проблемы с инсертом.
52 1176395
>>176343
Внимательнее почитал доку - оказалось у Symfony там свой велосипед и Intl они не юзают: http://symfony.com/doc/2.1/book/translation.html#pluralization
Но судя по сорсам - можно сделать свой MessageFormatter: https://github.com/symfony/translation/blob/master/Formatter/MessageFormatter.php
И уже там дёргать \MessageFormatter
53 1176426
>>176388
Ну смотри, у тебя в любом случае получается таблица, которая потенциально содержит в себе число записей = число юзеров x число новостей. Так что готовься что через некоторое время тебя будет ад и погибель.

Если же тебе нужна именно таблица на бэкэнде для каких-то своих целей, то на ум разве что приходит некая оптимизация, что когда у тебя создается новость, то в неё записывается куча записей из id новости и id каждого юзера, но когда например юзер прочитал оповещение, у тебя из этой таблицы запись с id этого юзера и id оповещения удаляется. То есть в идеале на живом сервисе в теории у тебя юзеры и будут поддерживать чистоту в этой таблице. Но на практике если на сайте скажем 20к юзеров, а реально активных из них скажем 5к, то у тебя всё равно будет таблица в перспективе забита на sum(users) x sum(news) x ~0.75, потому что 75% мертвых юзеров никогда ничего не прочитают, и придется например опять же самому писать дополнительную зачистку, что бы из этой основной таблички в какой-нибудь архив тормозной всё что старше даты X, даже если оно не прочитано в случае лагов.

Кстати это даже интересно звучит, ведь можно написать автоматизацию и повесить на крон, которая будет спрашивать из этой таблички какой-нибудь ряд тестовых селектов, и в случае если у тебя среднее время запроса превышает комфортные 0.1 секунду то например начинать чистку на предмет разгребания части самого старья. Ну и повесить всё это циклично на крон, что бы проверялдось само раз в час/три/день.

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

>>176390
Исключается проблема с большим инсертом при создании новости, но не девается никуда проблема с тем, что у тебя юзеры при просмотре новостей эту табличку сделают очень жирной и выведут из работоспособного состояния. У меня на локалке от миллиона записей вроде уже работа с таблицей перестает быть комфортной. при этом просто разовые запросы, никаких даже тестов о том, что бы слать например <10 запросов в секунду. У тебя если 20к юзеров, и пусть даже в среднем из них 5к будут активно что-то читать, то в среднем получается, что через 200 новостей они уже этот миллион записей создадут, ну пусть для вашего сервера комфортно будет ворочать табличку с 10лямами записей - ок. Но ты же говорил о том, что

>события тоже будут измеряться тысячами.


Тебе явно нужен какой-то хитрый механизм отчистки от старого дерьма.
53 1176426
>>176388
Ну смотри, у тебя в любом случае получается таблица, которая потенциально содержит в себе число записей = число юзеров x число новостей. Так что готовься что через некоторое время тебя будет ад и погибель.

Если же тебе нужна именно таблица на бэкэнде для каких-то своих целей, то на ум разве что приходит некая оптимизация, что когда у тебя создается новость, то в неё записывается куча записей из id новости и id каждого юзера, но когда например юзер прочитал оповещение, у тебя из этой таблицы запись с id этого юзера и id оповещения удаляется. То есть в идеале на живом сервисе в теории у тебя юзеры и будут поддерживать чистоту в этой таблице. Но на практике если на сайте скажем 20к юзеров, а реально активных из них скажем 5к, то у тебя всё равно будет таблица в перспективе забита на sum(users) x sum(news) x ~0.75, потому что 75% мертвых юзеров никогда ничего не прочитают, и придется например опять же самому писать дополнительную зачистку, что бы из этой основной таблички в какой-нибудь архив тормозной всё что старше даты X, даже если оно не прочитано в случае лагов.

Кстати это даже интересно звучит, ведь можно написать автоматизацию и повесить на крон, которая будет спрашивать из этой таблички какой-нибудь ряд тестовых селектов, и в случае если у тебя среднее время запроса превышает комфортные 0.1 секунду то например начинать чистку на предмет разгребания части самого старья. Ну и повесить всё это циклично на крон, что бы проверялдось само раз в час/три/день.

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

>>176390
Исключается проблема с большим инсертом при создании новости, но не девается никуда проблема с тем, что у тебя юзеры при просмотре новостей эту табличку сделают очень жирной и выведут из работоспособного состояния. У меня на локалке от миллиона записей вроде уже работа с таблицей перестает быть комфортной. при этом просто разовые запросы, никаких даже тестов о том, что бы слать например <10 запросов в секунду. У тебя если 20к юзеров, и пусть даже в среднем из них 5к будут активно что-то читать, то в среднем получается, что через 200 новостей они уже этот миллион записей создадут, ну пусть для вашего сервера комфортно будет ворочать табличку с 10лямами записей - ок. Но ты же говорил о том, что

>события тоже будут измеряться тысячами.


Тебе явно нужен какой-то хитрый механизм отчистки от старого дерьма.
54 1176459
По задаче со студентами и вообще в дальнейшем, подскажите кто шарит.

1. В какой конкретно кодировке лучше всего создавать базу?
utf8_general_ci
?
2. Движок по дефолту InnoDB, не трогать?

3. Если про классы в пхп всё понятно, то вот таблицы и названия баз данных сейчас как принято писать? Тоже камелкейсом?
students_list
studentsList
StudentsList
?
55 1176462
>>176459
1. Да
2. Да
3. students_list
56 1176478
>>176459
student
это таблица, и так понятно что она лист.
Еще есть холивар на тему student или students.
Оно в принципе не важно. Ну лучше знать о таких срачах на случай случайно детонирующих коллег.
ОП 57 1176480
Проверил в старом треде все оставшиеся задачи и посты, начиная с 30 марта:

- >>1176468 - задача про кредит и задача про вектор https://repl.it/repls/AcclaimedWhirlwindSoftwareengineer
- >>1176469 - почему в задаче про кредит не работает if ($a || $b || $c > $d) ?
- >>1176470 вопрос про ssh agent
- >>1176471 про просмотрщик картинок
- >>1176476 про ООП и https://github.com/mlmn/vector.loc/

Если вы писали в прошлом треде и вам не ответили - напомните о себе тут.
58 1176481
>>176459

По SQL берите за основу sql guide: http://www.sqlstyle.guide/ru/
59 1176482
>>176459

Про движки - погугли отличия InnoDB от MyISAM. Не выбирай бездумно.
60 1176483
>>175357

Задать конкретный вопрос в треде, что не понятно.
3.jpg306 Кб, 1100x1466
61 1176502
Нужно сделать ебучую викторину с вопросами, где за правильные ответы первые n ноунеймов получат купон на скидку товаров.

С викториной проблем нет, интересна схема с купоном.

Пока есть 2 идеи - либо записать в базу n купонов и выдавать каждому, кто прошёл весь Вьетнам, выпиливаясь из базы штукой. Либо, сделать как с капчей, если все ответы верные - выдается рандом код\картинка - ноунейм пишет, и вычитается n число от общей суммы.

Что скажете, мамкины прогеры? Если что, база есть.
harddaybywhitediamondsltd-d4udwjx.jpg77 Кб, 649x681
62 1176742
Хотел бы показать проект ОПу, но постоянно перелопачиваю код до неузнаваемости по желанию левой пятки. Стыдно.
2018-04-1720-16-18.png16 Кб, 920x289
63 1176765
Анончики, подскажите, как сделать это задание. Как поменять шрифт и цвет сердца, если из тегов можно использовать только <em>? А если его использовать, то шрифт не соответствует необходимому результату.
64 1176768
>>176502
Сгенерировать в базу. Либо определить упорядоченное (желательно внешне рандомное) множество значений размерностью n. Ща распишу. я ж у мамы программист
65 1176770
Три
66 1176781
Спасибо за уроки от двача, это довольно фаново и даёт мне мотивацию. Вот только один вопрос, почему не работает \n? Юзаю <br/> вместо него
67 1176830
Собираюсь пилить мини-сайтики, например, сайт визитку по приложению
Не напрягаясь, заскочил сюда. Мне это в ИДЕ удобней будет или с простым редактором можно обойтись? Или в какой лучше все это дело оборачивать? чтобы чекать БД, формочки и т.д.?
мимоАндройдДжуниор
68 1176834
>>176830
А хотя, хули то спрашивать такую фигню.
Ебнул нетБианс.
70 1176840
>>176765
Оборачиваешь сердце в em, делаешь ресет родных для em стилей, меняешь цвет и шрифт. Остальное там через html entities набираешь, в том числе само сердце, юникодным номером.
140b091f13bbd367216daf070018d4c1full.jpg49 Кб, 550x413
71 1176842
Блядь. Что я делаю в пхп-треде? Мискликнул так мискликнул..
72 1176843
>>176842
Может быть это судьба?
73 1176845
>>176842
Перепили под PHP плиз!
python-gpio-534x462.jpg55 Кб, 534x462
74 1176850
>>176845
Я уже забыл его напрочь. Лет 5 не писал на пхп.
Снимок экрана 2018-04-19 в 18.51.09.png82 Кб, 455x546
75 1176853
>>176199
Спасибо

Поставил php7.2 и на ровном месте образовалась ошибка (пикрелейтед), с переменной все ок же! Когда заливаю на хостинг то ошибки нет, подозреваю что там php<7.2

Вот код страницы
https://pastebin.com/Tz9D5kpK
76 1176855
>>176850
Что посоветуешь анону, который хочет быть веб макокой но никак не выберет стул: пхп или питон? плюсы и минусы, заранее спасибо!
image.png107 Кб, 1134x608
77 1176856
Почему такие непонятные версии? Авторы пхп накурились и не смогли в обратную совместимость? Какую качать для самообучения?
78 1176857
>>176853
<?php
$error__test = false;

у тебя переменная неинициализирована
79 1176859
80 1176863
>>176855
Пхп простой, но ограниченный. На пхп можно делать только сайты и то с вебсокетами например будет уже пляска и простые cli приложения. Нет ни многопоточности, ни нормальной асинхронности, много легаси вроде тысяч функций в глобальном пространстве. Насколько помню всё так же хуёво с юникодом. Скудное разнообразие структур данных.

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

Если хочется именно вебмакакой быть, учи лучше жс и ебашь фронтэнды. Голова будет болеть от тысяч фреймворков и дебильной слабой типизации в пхп такая же, но хотя бы заработаешь что-то.
15125844024801.jpg206 Кб, 1280x960
81 1176866
Стоит ли изучать bootstrap в 2018?
82 1176870
>>176863
Большое спасибо, анон!
83 1176873
>>176857
В смысле? Я же ей присвоил true в случае успеха и false в случае провала регистрации.
Вынес в начало перед if, и присвоил $errors__test = 0;
Ошибок нет, так будет правильно?
84 1176874
>>176855
Пхп даже на вебсервер проще положить, он в апаче вообще нативно работает. Можешь сходу прям на голом пхп уже что то клепать, а с питоном так не выйдет, нужна джанга, uswgi и еще костыли на сервак. Но анон >>176863 правильно сказал, я считаю что питон это вклад в будущее, а пхп это быстро и без напрягов срубить бабла уже сейчас.
85 1176879
>>176866
бамп
86 1176904
Сап ПШПач. Как написать смс бомбер на пшп?
Нужно направление, как это всё осуществляется, че куда.
87 1176912
>>176874
а что мешает порубить малость бабла и потом идти большой дорогой?
88 1176929
>>176912
Ничего не мешает, если уже все знаешь в пхп, то можно по вечерам пробовать душить своего питона.
89 1176933
>>176929
А если только начал?
90 1176944
>>176874

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


>Kokoko Kokoko


В последующие лет 5 все будет жить, так что практически нихуя не изменится. Специалисты везде нужны. Очередной флейм разводишь.
91 1176953
>>176944

>В последующие лет 5 все будет жить


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

Я к тому, что если надо быстро освоить и идти работать за деньги то это однозначно пхп.
Если острой необходимости в деньгах нет, то изучение питона в далекой перспективе даст свои профиты. Разве я не прав ?
92 1176961
>>176953

>, то изучение питона в далекой перспективе даст свои профиты. Разве я не прав ?


И почему же?
93 1176962
>>176961
На далекую перспективу изучаешь питон от корки до корки и погружаешься в мир хайлоада и отсоса хиккующих выблядков.
Мимопроходил
94 1176963
>>176962
Питон? Ну а может быть лучше node.js?
95 1176965
>>176963
Я не знаю, я просто мимопроходил. Я вообще думаю, что надо всё на начальном уровне изучить РНР, JS, node.js, Pyhton. Чтобы уметь на всем этом тудулист смастерить. А потом выбрать что-то одно, что больше по душе и по жизненным обстоятельствам.
96 1176967
>>176965
фикс Python
97 1176968
>>176965
Прямо с языка снял.
98 1176970
Ну серьезно? Какого хера я должен ебаться с установкой апачи и другой фигни, если можно скачать тот же WAMP? Что мне это даст, когда я потрачу 2 часа на самостоятельные долбежки?
100 1177006
>>176970
Какие долбежки? Весь стек устанавливается тремя командами, или одной через tasksel. Вообще это полезно как минимум потому что в будущем в виртуальной среде ты сможешь тестить свое говно на разных серверах и версиях пых. если захочешь
101 1177058
>>176768
Попробую и то и то, пока времени хватает. Маме привет.

>>176835
Лол, сейчас бы в пыхетреде выкладывать код на питоне.
Но в принципе, саму идею понял, что-то набросаю, сяб.
sage 102 1177117
>>176999
Регулярки пиздец. (л|ю|н)? Серьёзно? [люн] блядь
103 1177153
Анчоусы, есть ли уже готовое расширение, позволяющее создавать формы динамически?
Например, я создаю в админке новую форму, добавляю туда любые поля, выбираю их тип, задаю правила валидации, возможно назначаю эвенты перед отправкой формы, потом все это дело сохраняется в БД. На фронте эта форма со всеми полями и правилами вытаскивается из БД и генерируется в html/js. Не представляю, как это организовать вообще, чтобы в контроллер прилетали POST-данные, ими заполнять эту динамическую форму, валидировать и сохраняться данные в БД.
104 1177169
>>177058
Ну я на самом деле потом подумал ещё, тебе ведь всё равно нужно учитывать использовался ли купон, так что наверное только в БД тыщу рандомов писать. Единственное проверяй чтобы в кодах не было мата. FUCKBITCHTWAT
105 1177178
Откуда взять символы для задачки с хакерским шифром? Я, честно говоря, не понял зачем она нужна кроме...лулзов?
106 1177210
>>177153
Очевидный JavaScript очевиден: http://www.r-5.org/books/computers/all-js/
QDe84Ga.png81 Кб, 851x1185
107 1177211
>>177117
Через [л-ю-н] задаются диапазоны же? Тогда все буквы между ними попадут в поиск.
108 1177222
>>177178

Из статьи википедии про l33t. Она нужна для изучения функции strtr(), если ты сделал задачу про шифровку, то можно пропустить.
sage 109 1177225
>>177211

>пишешь ему [люн]


>отвечает про [л-ю-н]

изображение.png49 Кб, 885x88
sage 110 1177227
>>177211
Даже на пике написано, дебил блядь
111 1177230
>>177227
Ну не стукай!
112 1177303
>>176929
Нуу, я только вкатываюсь, массивы хуесивы и прочее. Заодно мб как прохать пойму немного. Ы ебать.
113 1177311
114 1177318
Проганон, сколько будет стоить одностраничник, так называемый лендинг, с кнопкой оплаты на электронный кошель, на сайте будет несколько фото картинок и небольшое описание.
115 1177367
>>176873
if (isset($data['do_signup']))
{

даунелло, у тебя не всегда ЭТО исполняется
116 1177400
Поясните про TDD. Его обычно во всяких компаниях используют, где тестировщики в штате есть, или когда просто для себя пишу, то тоже ему стоит следовать? Вот допустим есть задача от ОПа на testhub. Лучше сразу с тестов начать?
117 1177587
Алсо, если в классе есть приватный или протектед метод, но хочется его протестить, то как поступить? Сделать его публичным?
118 1177629
>>177587
А где по-твоему используются такие методы?
121 1177632
>>177587

Обычно, когда мы тестируем класс, мы смотрим на него снаружи и "не видим" приватных или защищенных методов. Мы используем этот класс точно так же, как и его использует код. Ведь цель тестирования - что класс будет вести себя так, как ожидается. Не приватные методы класса, а класс в целом.

Плюс, хорошая идея не закладывать в тесты какие-то внутренние особенности класса, так как при рефакторинге это все сломается. Мы должны тестировать публично доступные методы.

Мы пишем тесты по мотивам требований, которые предъявляются к классу и публичным методам. Если метод должен вести себя так-то - мы это и тестируем.

Соответственно, ответ - тестируй публичные методы. Они ведь вызывают тот приватный метод.

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

Как вариант, можно конечно добавить публичный метод testSomething() но это будет не очень хорошо, так как мы закладываемся на знание внутреннего устройства класса. И этот тест окажется бесполезен после рефакторинга.
122 1177715
>>177222
Сделалъ. Просто там была задача с "шпионским" шифром, а потом с хакерским. Вот я и не понял зачем делать это дважды.
123 1177724
go лучше пхп?
124 1177752
>>177724
В сотню раз, это тупой вопрос ведь, гошечка лучшее решение для хай-лоад сервера.
125 1177755
>>177752
это не тупой вопрос,прост недавно узнал про язык от гугла.
126 1177756
>>177752
это не тупой вопрос,прост недавно узнал про язык от гугла.так на нем можyо клепать сайты на поток?
127 1177758
>>177400
Тесты ебень полная, ты закончишь тем, что тесты будешь писать, а не код.
128 1177837
>>177758
Ты не прав, с тестами проблемы возникают у тех, кто не умеет их писать, делает хрупкими, полагается на внутренности тестируемого кода, что приводит к тому, что изменения в систему вносить очень больно. По моим ощущениям юнит-тесты вообще не добавляют сложности, пишутся быстро и проверяют сразу много всего, с приёмочными тестами возиться приходится больше, особенно если на фронте навороченное SPA, но в целом от таких тестов тоже польза есть. Не надо лезть с такими советами, человек может хорошим специалистом стать, а ты тянешь обратно в болото. У нас есть на работе мануальные тестировщики, но они, к примеру, не могут протестировать REST API, а программист может. Ещё мануальных тестировщиков не получится "запускать" так же часто, а тесты можно запускать на каждый чих.
129 1177856
>>174695 (OP)
Глупый вопрос. Зачем нужно писать в стиле ООП в вебе, если скрипты "живут" очень малое время (получают данные из БД и рисуют шаблоны)? Можно же просто статическими функциями реализовывать все требования к сайту.

Смысл вопроса: не могу понять, куда ООП "присобачить", в какие файлы и функции, в процессе своего говнокодинга. Да, можно создавать экземпляры классов, но для чего? Можно без него обойтись, не скажу, что проще, но они не нужны, лишнее нагромождение
130 1177880
>>177856

>спойлер


Никуда, но Web-макаки не изучают компьютерную науку же.
131 1178091
>>176999
Переделал решение, заранее спасибо.
https://ideone.com/QBsXdT
132 1178190
Привет. Нужна помощь в задачке на палиндром. Выводится пустота. Я ковыряюсь уже не первый час и запутался пздц.
http://sandbox.onlinephpfunctions.com/code/63cf89da69bab8ce6434556101059c96e78d3b8c
133 1178200
Привет ОП. Делаю генератор стихов. Памаги, почему из массива выводится только последний массив? А именно word5.
https://ideone.com/aoUwEY

Ps. сделол вот так, без массивов.

$word10 = array_flip($word1);
$word11 = array_rand($word10);

$word20 = array_flip($word2);
$word22 = array_rand($word20);
$finalWord = $word11 . " " . $word22;
echo $finalWord;

Но мне кажется это не очень правильно, к тому же, пытаюсь понять ту ситуацию с выводом сверху.
134 1178203
>>174695 (OP)
Решил нахерачить логин форму отсюда: https://www.tutorialspoint.com/php/php_mysql_login.htm. И меня не редиректит на страницу welcome.php, хотя он проверяет по базе данных логин и пароль, то есть конект есть, редиректа нету. Не могу понять что не так, на 10 раз пересмотрел все исходники
135 1178229
Починили
136 1178230
>>178190

>http://sandbox.onlinephpfunctions.com/code/63cf89da69bab8ce6434556101059c96e78d3b8cC


Строка 18: $halfLength == $count. Это условие всегда неверно. Соответственно, скрипт даже не заходит внутрь цикла. Нужно переписать на выполнять пока $i (в твоем случае $count) меньше $halfCount.
28: elseif($halfLength == $count) {
echo "$result";
}
Это условие никогда не проверится. Ты ждешь третьего результата, там где возможно только 2 (true, false).
26: Замени на $result = "Не палиндром"; Выводи $result после цикла.
С этого момента все должно работать.

Как все заработало, время рефакторинга:

$zero = 0;
$minusone = -1;
$count = 0;
Лишние переменные. Достаточно использовать $i. С позициями при копировании символов ты все сделал верно (много анонов тут со старта ошибаются).
Условие в цикле можно сократить до одного if, когда не нужно будет обновлять эти переменные.
14885356640560.jpg36 Кб, 604x453
137 1178242
>>174695 (OP)
На проверку, задача про мошеннические опечатки.

Вариант только с русским текстом:
https://ideone.com/sz1DCU
Вариант с русским и английским текстом: https://ideone.com/IjnjLz
138 1178254
Есть строка с названием файла. Задача вынуть оттуда расширение - jpg, txt и т. д., а если у имени файла вообще нет расширения вернуть null. Я сделал регулярку '/.([^\.]+$)/i'. Но когда я ввошу preg_match('/.([^\.]+$)/i', 'test', $arr) и делаю return $arr[1], то получаю est. Что я делаю не так?
139 1178258
Привет.

Ситуация: чиню/дополняю сайт на пхп, и вижу: все запросы к бд обернуты минимум в рид локи.

Судя по общему качеству исполнения сайта делаю вывод, что они скорее всего не нужны.

Но какие нужны? Понимаю, довольно абстрактный вопрос. Но судя по объяснениям которые я видел - большинство операций и так лочат всё как требуется.

КАПЧА НЕВАЛИДНА BAD GATEWAY
140 1178262
>>178254
Я так делою
$ext = array_pop(explode('.', basename($filePath)));
141 1178265
>>178254
Точку экранируй, умник.
142 1178274
>>178242
>>174695 (OP)
Еще на проверку, автоматическое исправление опечаток.

Версия с проверкой на опечатки до и после исправления https://ideone.com/A7cHmQ

Урезанная версия с просто исправлением
https://ideone.com/WzIbPY

Заранее спасибо!
143 1178312
>>178203
mysql старье.
дрочи pdo
144 1178329
>>174695 (OP)
Делать обращения к базе в цикле это плохо или похуй? Антипаттерн или норм?
изображение.png22 Кб, 856x155
145 1178330
>>178203
20 секунд уделил твоему вопросу, сам код не копировал и у себя на компе не запускал.

Так что на вскидку два возможных варианта, предполагая что сам код там рабочий и предельно просто всё там по схеме:
1. Если пост запрос то смотрим что в нем
2. Взяли с пост-запроса логин пароль
3. Спросили у базы строчку where логин и пароль
4. Посмотрели ответ базы, посчитали сколько в нем строк
5. Если строк == 1 (а не 0, ведь если в базе нет юзера с таким логином и паролем, то стало быть что-то неверно), то поставить куку юзернейма и редиректнуть на траницу которая как раз уже требует эту куку.

Во первых как с таким говном работать новичку:

Берешь и построчно вардампишь свой код.
После

>$result = mysqli_query($db,$sql);


пишешь
var_dump($result);
exit;
Смотришь что там в ответе, что коннект есть и всё ок.

Идешь дальше:
Смотришь что там прилетело в:

> $row = mysqli_fetch_array($result,MYSQLI_ASSOC);


var_dump($row);
exit;
...

var_dump($count);

Дальше у тебя будет 2 варианта - либо в $count лежит 0 - значит проблема с базой, потому что нет такого юзера и ты накасячил в самой таблице и пытаешься залогиниться под неверныю юзером или с неверным паролем или еще что-то такое.

Либо в $count лежит единичка и должно бы редиректить, но ничего не работает, тут ты должен знать что пикрил. Значит ты что-то не так скопировал и у тебя какая-нибудь херня пои копипасте или ты забил пробелов перед <?php тегами и прочее.
изображение.png22 Кб, 856x155
145 1178330
>>178203
20 секунд уделил твоему вопросу, сам код не копировал и у себя на компе не запускал.

Так что на вскидку два возможных варианта, предполагая что сам код там рабочий и предельно просто всё там по схеме:
1. Если пост запрос то смотрим что в нем
2. Взяли с пост-запроса логин пароль
3. Спросили у базы строчку where логин и пароль
4. Посмотрели ответ базы, посчитали сколько в нем строк
5. Если строк == 1 (а не 0, ведь если в базе нет юзера с таким логином и паролем, то стало быть что-то неверно), то поставить куку юзернейма и редиректнуть на траницу которая как раз уже требует эту куку.

Во первых как с таким говном работать новичку:

Берешь и построчно вардампишь свой код.
После

>$result = mysqli_query($db,$sql);


пишешь
var_dump($result);
exit;
Смотришь что там в ответе, что коннект есть и всё ок.

Идешь дальше:
Смотришь что там прилетело в:

> $row = mysqli_fetch_array($result,MYSQLI_ASSOC);


var_dump($row);
exit;
...

var_dump($count);

Дальше у тебя будет 2 варианта - либо в $count лежит 0 - значит проблема с базой, потому что нет такого юзера и ты накасячил в самой таблице и пытаешься залогиниться под неверныю юзером или с неверным паролем или еще что-то такое.

Либо в $count лежит единичка и должно бы редиректить, но ничего не работает, тут ты должен знать что пикрил. Значит ты что-то не так скопировал и у тебя какая-нибудь херня пои копипасте или ты забил пробелов перед <?php тегами и прочее.
146 1178339
>>178329
Не можешь справится со сложным запросом и хочешь селать много мелких? Если можно за 1 запрос вытянуть что-то, то наверное лучше за 1 дернуть. Хотя знаешь, я на самом деле не уверен, иногда лучше потестить например, поделав оба варианта по несколько десятков/сотен/тысяч раз и справнив среднее время за сколько ты в итоге получаешь свои данные.

Сам часто делал в продакшене хуйню уровня: дернуть несколько простых запросов и их уже средствами пхп обработать всё в нужный блок данных, потому что знания мускуля не на таком уровне, и вместо того что бы 4 часа сидеть гуглить и учиться составить этот хитровыебанный запрос с условиями и подзапросами средствами мускуля, проще реально дернуть несколько разных отдельных запросов и их перелопатить вируозно на пхп. К тому же начальник прямым текстом еще на тебя налегает что давай сириусли ебош хуяк-хуяк и в продакшен.
147 1178342
>>178339

>Не можешь справится со сложным запросом и хочешь селать много мелких?


Нет. У меня есть таблица user_info, куда я вставляю id разных сущностей. Их много - user_agent_id, phone_id, ip_address_id и т.д.
То есть перед тем как вставить запись в эту таблицу, мне нужно получить id всех необходимых сущностей (или если их нет - добавить сущность и потом вернуть её id).
148 1178347
>>178265
>>178262
Спасибо, про точку и функцию basename забыл.
149 1178350
>>178347
'/\.(\w+$)/iu'
someApprentice 150 1178355
>>1176471

>Какие ты видишь решения проблемы?


Я ещё не освоился с JS, но пока могу сказать, что это нужно разделить либо на отдельные функции, либо разбить на два класса - Helper и Handler, который вешает обработчики (к примеру, Handler.prototype.handleClickOnImg...).

>> var fullsize = $('.fullsize');


>Не лучше ли сохранять ссылку в переменной, а не искать каждый раз этот класс по всему дереву DOM?



>> Этот элемент нужно искать именно каждый раз когда мы делаем клик, потому что, при каждом открытии, он, каждый раз, создаётся новый.


ну все равно, можно сохранять ссылку на него, а не искать в DOM.

Разве эта переменная и так не ссылка на объект jQuery?

>Что-то мне кажется, для добавления обертки надо опять откатываться к яваскрипту. Либо добить решение с флексбоксом. Вот такой вот он, CSS. Предлагай свои идеи.


У меня идеи закончились когда не получилось отцентировать картинку. Мне нравится вариант с высчитом размеров картинки и центрирования с помощью double translate, потому что мы, в любом случае, обращаемся к js чтобы вывести popup - ничего страшного если с его помощью и размеры посчитать.
1333366373208.jpg131 Кб, 658x658
151 1178627
У кого какие лайфхаки с обучением? Заметил за собой, что у меня чем дальше изучение, тем оно медленее, и не потому что темы сложнее, а скорее потому что большими объемами данных нужно ворочать. Если на первых парах ты брал маленькую задачу и решал её скажем за час, то с какими-нибудь студентами сидишь месяц и подступиться не можешь, постоянно откладываешь, не знаешь как разбить на мелкие подзадачи и т.д. Вот думаю мб разбавлять решение задач какими-нибудь другими практиками, что бы время не так сильно тратилось в никуда? Сидеть css или js ковырять по часу в день хотя бы и решать те же задачи от ОП-тян на верстку например.

Так же вот думая об этом, понимаешь зачем в итоге ооп было придумано. Ну не могут просто люди брать и в голове держать программу написанную без какой либо модульности на 300 и более строк кода, где тупо идет поток лапши. Скажем надо что-то где-то переписать и тут же понимаешь как всё плохо с этим всем, когда у тебя из-за одной переменной может в нескольких местах может всё сломаться и нужно весь код из-за такой вот мелочи перелопачивать. А так вроде как всё разбито по модулям, и ты даже можешь с этим легко работать, главное научиться их выделять логически и связывать, а сами микрозадачи решать - это легко и уже давно к этому адаптировался.
152 1178643
>>178342
Поясни поподробнее схему? Ты когда юзера создаешь, ты всю инфу не в 1 таблицу кладешь, а раскидываешь всякую сопутствующую инфу по типу его телефона и емейла по отдельным таблицам, а юзеру собственно вносишь id для связи? В чем вообще профит? Я искренне не понимаю подобного подхода.
ОП 153 1178654
Проверка времени поста.
154 1178659
>>178230

>$halfCount



Ты имел ввиду $halfLength (половина длины текста без пробелов)? $i заменить $count?

>Ты ждешь третьего результата, там где возможно только 2 (true, false).



Но ($halfLength == $count) либо равно, либо не равно?

>>178627
Я вот не могу понять как кто-то решает задачу за час. Я уже месяц сижу на основах пхп из учебника ОПа. Впрочем реального времени на учебу потрачено может неделя от силы. Когда дело доходит до задач дропаю на несколько дней, пока жду тут ответа. От чтения справочника ситуация не меняется, даже наоборот - появляется еще больше вопросов.
155 1178660
>>178659
Да и задачи я "решил" скопировав решения анонов, которые выкладывали их в тред. Копировал, впрочем не полностью. Используя их как примеры пришло понимание того, как это можно использовать тему урока.
Я придерживаюсь мнения что перед тем как давать задачи, нужно дать пример использования теории на практике. Этот момент в учебнике упущен.
Как было в школьных учебниках: дается теория, формула. Потом идут примеры как их применяют. Потому примеры уже с задачей. Далее идут непосредственно задачи, которые решают самостоятельно.
Очень не хватает примеров применения на практике материала. Я ведь даже предположить как можно, а как нельзя.
Может с таким ущербным майндсетом мне сразу в биореактор, совсем уже заебался
156 1178678
>>178643
Не имейл и телефон, а разные данные о посещении сайта. Статистика - версия браузера, версия оs, ip адрес, название модели устройства, тип устройства и т.д. Телефон не юзера, а некий, который на сайте юзеру показывается, в зависимости от параметра url. Естественно мне эти данные нужно связать с id юзера.

>ты всю инфу не в 1 таблицу кладешь, а раскидываешь всякую сопутствующую инфу по типу его телефона и емейла по отдельным таблицам, а юзеру собственно вносишь id для связи?


>В чем вообще профит?


В нормализации базы данных.
157 1178686
>>178660
Вроде довольно реалистичные задачи, вон типа списка студентов, файлообменника etc - дохрена же сайтов примерно такой структуры, вполне реалистично выходит.
158 1178688
>>178686
Я не про задачи, а про пример применения темы урока на практике. Именно как и куда это можно вставить. Потому что когда я вижу решения анона у меня возникает только одна мысль "а так можно было?", потому как я не знаю как можно и как нельзя.
15090918220400.jpg105 Кб, 800x800
159 1178715
>>178678
Вот почему ты теперь мне кажешься высокомерным пидорасом? Еще хотел же приписать к вопросу про твою оптимизацию:
inbifo: не слышал про нормализацию?
Но подумал, что это будет лишнее, а в итоге следовало бы.
сам надумал себе - сам обиделся

Кароче ты парсишь $_SERVER, и например видишь что там юзер зашел с какого-нибудь альфа-фаерфокс 60 версии, идешь значит в таблицу user_agents, смотришь что там ничего нету подобного, заходишь в неё, добавляешь туда себе этот новый неизведанный агент, забираешь его айдишечку, потом херачишь так по нескольким таблицам которые у тебя чисто под такие вот "сущности" выделены и содержат 2 столбца из id и значения, и обойдя в итоге все таблицы и убедившись что везде всё есть ты завозишь наконец с чистой совестью в user_info тупо наконец-то запись с кучкой айдишников? Я правильно понял? У тебя так при каждом обращении юзера к сайту происходит? Ну и я не уловил в итоге, в чем профит такого усложнения перед тем что бы просто занести все нужные тебе куски информации в одну таблицу 1 инсертом за 1 обращение? Инбифо: для нормализации.
160 1178727
>>178715

>Вот почему ты теперь мне кажешься высокомерным пидорасом?


Пиздец ты ебанутый. Пропало желание тебе отвечать.
Подожду опа.
161 1178730
>>178727
Что обиделся то сразу? Ну блэээт.
Или я был прав:?
Вебмастеринг 162 1178737
Долго ждал сего урока. Поделюсь с аноном годнотой:
http://nnm-club.me/forum/viewtopic.php?t=1220587
163 1178744
>>178688

А можешь пожалуйста написать один или несколько примеров, о чем именно, что должно бы быть написано в уроках?
164 1178754
>>178715

>Ну и я не уловил в итоге, в чем профит такого усложнения перед тем что бы просто занести все нужные тебе куски информации в одну таблицу 1 инсертом за 1 обращение? Инбифо: для нормализации.


Денормализация ИНОГДА, ДОВОЛЬНО РЕДКО, бывает оправдана, но это явно не тот случай. За денормализованные данные по ебалу бьют в нормальных конторах.
Но если ты индус Кумар Ебалнасрал то, действительно, профиты могут быть неочевидны. Можешь дальше хуячить данные в базу as is.
165 1178760
>>178330
Дампнул - вывод пикрил. Пробелов не видать - https://pastebin.com/F2CChrQw Еще раз проверил все файлы хотя я до сих пор могу не видеть какую-нибудь очевидную ошибку При успешном логине он крашит body, пикрил. Собсна что делать, по-другому можно редирект сделать? Пробывал локейшен заменить на echo - тот же эффект.
NORMALIZACIYA.jpg173 Кб, 1280x720
166 1178769
>>178754
Вспоминается анекодот про макак и бананы. Вот я захожу к вам ща в камеру, кидаю ненормализованную таблицу на пол, и вы на меня набрасываетесь, а пояснить то можешь на конкретном примере? А не высрать: НУ ТАК ПРИНИТА.

Мне вот видится, что нормализация нужна реже чем нужна, потому что в небольших проектах она скорее всего будет только усложнять базу и увеличивать количество кода которое её обслуживает, что нахуй не нужно. И на каком-нибудь условном хайлоаде ты тоже будешь херачить 10 записей в 10 таблиц вместо 1? Может тогда у тебя маня-нормализация и дыры в проектировании базы, а не нормализация?

Жду пояснения на конкретном примере, с обоснованием хотя бы в духе: ну кароче у меня к этой таблице селектов 99%, поэтому тут всё нормализованно и проиндексированно по айдишникам, шоб быстрее, а инсерты 1% оче редко и похуй что там 10 запросов за раз идет.

У слившегося челика как я понял юзер при каждом клике создает в десятки таблиц по запросу только что бы проверить есть ли там то, что юзер с собой принес, потом еще потенциально по десятку инсертов может прилетать туда же, если вся инфа- свежачок, зато нормализацию базы поддерживает)))
167 1178774
>>178769
Деньги вперед.
168 1178775
>>178760
А я то думал мы тут ща обсуждать будем и рождать в споре истину.

https://www.youtube.com/watch?v=AQqiUusn04k
169 1178776
>>178775 мимо
>>178774 сюда
170 1178779
>>178760
Смотри, а попробуй в начале welcome.php
написать перед include('session.php');
написать:
echo 123;
exit;

Вдруг у тебя всё нормально редиректит, просто я смотрю, что в session.php тоже при какой-то ошибке редиректит назад на login.php, вдруг у тебя проблема как раз в том, что прохоидт целый круг редиректов и назад тебя на login.php возвращает.
4214dfdsdaw3.png34 Кб, 552x311
171 1178782
>>178779
Думал об этом. Написал - тот же эффект.
172 1178787
>>178782
И не заходит в этот файл получается?

Значит проблема в этих 3 строчках - пикрил 1.

Заходим в мануал: http://php.net/manual/ru/function.session-register.php

Видим корень зла - пикрил 2.

И вообще, напиши ка error_reporting(-1); в начале своего кода - почему еще не сделал и не посмотрел что тебе пишет твой пхп?
173 1178794
Прохожу практику в одной компании. Завтра будет первый день в офисе. Пхп почти совсем не знаю. Что я могу сегодня выучить чтобы не очень сильно ударить в грязь лицом?
321dsatst.png103 Кб, 960x633
174 1178803
>>178787
Я тупой, возможно. Вставил вот как на пике и самой первой строкой после <?php - никакого эффекта, так же пустой экран.
175 1178804
Тут люди спорят про нормализацию.
Я конечно не гуру, даже не нуб.
Но почти любой адекват скажет что этот топик впринципе настолько сильно зависит от обстоятельств что спорить о нём нет смысла без полного их описания.
Нет никаких чётких конвенций.

Поэтому использовать нужно коммон сенс.
Вот пара высосанных из жопы примеров:

Например, если содержимое столбца никогда не используется отдельно от сущности таблицы, скорее всего нет смысла её нормализовать.
Пример: posts [ id, author_id, content ] - нет смысла нормализовать [ content ], он полностью входит в сущность поста и от неё не отрывен.

Но если мы вдруг понимаем, что в ней в итоге придется при этом держать больше одного значения, значит лучше все-же нормализовать.
Пример: posts [ id, authors_ids, content ] - имеет смысл добавить таблицу posts_authors [ post_id, author_id ]. Такое может произойти если вдруг захотелось возможность писать коллективные посты.

Если есть несколько столбцов которые всегда содержат соответствующие значения, логично нормализовать их в отдельную таблицу.
Пример: posts [ id, author_id, content, category_title, category_image ] - логично вынести данные в таблицу categories [ id, title, image ], наша таблица станет такой: posts [ id, author_id, category_id, content ].

Однако, пример: posts [ id, author_id, content, category_title ] - не факт что такая структура требует нормализации.

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

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

Пойдем дальше. Пример: requests [ user_id, ip, agent, date ].

Например, поле ip - содержит четыре числа через точку. Это-же очевидный массив. Почему бы не нормализовать его разделить его на четыре столбца, по одному на октет? А потом вынести их в отдельные таблицы: /0 [ id, octet ], /8 [ id, octet ], /16 [ id, octet], /24 [ id, octet] и получить таблицу request [ user_id, agent, date, /0_id, /8_id, /16_id, /24_id ].

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

Далее, поле agent. Ну тут уж никто не поспорит совешенно очевидно что это массив жостко огранниченных по значениям полей! Первая мысль конечно же разнести его на столбцы [ .., browser, browser_version, os, os_version, device, .. ] и так далее. Потом мы сразу же захотим выделить все эти метаданные в таблицы: browsers [ id, name, version ], osses [ id, name, version ], devices [ id, name, revision, company_id, ... ], companies [ id, title, trademark_id ... ], trademarks [ id, title, image_id, ... ], images [ id, path, svg_path, icon_id, ... ] icons [ id, СТОЙ ЧТО ЖЕ ТЫ ДЕЛАЕШЬ ТЕБЕ ПРОСТО НУЖНО ПОФИЛТРОВАТЬ РЕКВЕСТЫ!!!

Просто берешь и select * from requests where agent like "%firefox%".
Хочешь знать с каких устройств заходит твой юзер? SELECT DISTINCT reqiests.agent ...
Невероятно просто.
У себя в аппликейшене можешь просто держать мап "browser" => "wildcard" / "regex"

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

Прежде чем это делать нужно очень четко представлять себе конечную цель твоей работы. Возможно, это реально требуется. Но даже в таком случае, почти наверняка тебе не нужно нормализовать эти столбцы в отдельные таблицы, потому что почти наверняка, отдельно от сущности реквеста эти данные тебе не нужны. Берешь какую-то из библиотек по вычислению браузера/ос/чепухи, у нормальных они будут индексированны. В таблицу вставляешь уже индексированные значения. В приложении селектишь по этим-же индексам. Как пример. Если потом захочешь поменять библу, можно замапить новые индексы на старые, или сразу сделать свой мап если живешь в режиме паранойи.

Мимо проходил в надежде стать более лучше одеваться.
175 1178804
Тут люди спорят про нормализацию.
Я конечно не гуру, даже не нуб.
Но почти любой адекват скажет что этот топик впринципе настолько сильно зависит от обстоятельств что спорить о нём нет смысла без полного их описания.
Нет никаких чётких конвенций.

Поэтому использовать нужно коммон сенс.
Вот пара высосанных из жопы примеров:

Например, если содержимое столбца никогда не используется отдельно от сущности таблицы, скорее всего нет смысла её нормализовать.
Пример: posts [ id, author_id, content ] - нет смысла нормализовать [ content ], он полностью входит в сущность поста и от неё не отрывен.

Но если мы вдруг понимаем, что в ней в итоге придется при этом держать больше одного значения, значит лучше все-же нормализовать.
Пример: posts [ id, authors_ids, content ] - имеет смысл добавить таблицу posts_authors [ post_id, author_id ]. Такое может произойти если вдруг захотелось возможность писать коллективные посты.

Если есть несколько столбцов которые всегда содержат соответствующие значения, логично нормализовать их в отдельную таблицу.
Пример: posts [ id, author_id, content, category_title, category_image ] - логично вынести данные в таблицу categories [ id, title, image ], наша таблица станет такой: posts [ id, author_id, category_id, content ].

Однако, пример: posts [ id, author_id, content, category_title ] - не факт что такая структура требует нормализации.

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

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

Пойдем дальше. Пример: requests [ user_id, ip, agent, date ].

Например, поле ip - содержит четыре числа через точку. Это-же очевидный массив. Почему бы не нормализовать его разделить его на четыре столбца, по одному на октет? А потом вынести их в отдельные таблицы: /0 [ id, octet ], /8 [ id, octet ], /16 [ id, octet], /24 [ id, octet] и получить таблицу request [ user_id, agent, date, /0_id, /8_id, /16_id, /24_id ].

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

Далее, поле agent. Ну тут уж никто не поспорит совешенно очевидно что это массив жостко огранниченных по значениям полей! Первая мысль конечно же разнести его на столбцы [ .., browser, browser_version, os, os_version, device, .. ] и так далее. Потом мы сразу же захотим выделить все эти метаданные в таблицы: browsers [ id, name, version ], osses [ id, name, version ], devices [ id, name, revision, company_id, ... ], companies [ id, title, trademark_id ... ], trademarks [ id, title, image_id, ... ], images [ id, path, svg_path, icon_id, ... ] icons [ id, СТОЙ ЧТО ЖЕ ТЫ ДЕЛАЕШЬ ТЕБЕ ПРОСТО НУЖНО ПОФИЛТРОВАТЬ РЕКВЕСТЫ!!!

Просто берешь и select * from requests where agent like "%firefox%".
Хочешь знать с каких устройств заходит твой юзер? SELECT DISTINCT reqiests.agent ...
Невероятно просто.
У себя в аппликейшене можешь просто держать мап "browser" => "wildcard" / "regex"

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

Прежде чем это делать нужно очень четко представлять себе конечную цель твоей работы. Возможно, это реально требуется. Но даже в таком случае, почти наверняка тебе не нужно нормализовать эти столбцы в отдельные таблицы, потому что почти наверняка, отдельно от сущности реквеста эти данные тебе не нужны. Берешь какую-то из библиотек по вычислению браузера/ос/чепухи, у нормальных они будут индексированны. В таблицу вставляешь уже индексированные значения. В приложении селектишь по этим-же индексам. Как пример. Если потом захочешь поменять библу, можно замапить новые индексы на старые, или сразу сделать свой мап если живешь в режиме паранойи.

Мимо проходил в надежде стать более лучше одеваться.
176 1178805
Что такое Middleware?
177 1178806
>>178803
Перед include('config.php);

А вообще, идея в том, что даже если тебе твой пхп и не покажет эрор на использовании этой функции, то ты сам её замени на то, как в мануале показано.
4324.png8 Кб, 320x168
178 1178808
>>178806
Бляяять, костыль действительно работает. Анон, я бы тебя расцеловал во все места, в которые можно расцеловать. Счастья тебе, здоровья, жену красавицу или трапа красивого, в общем всего всего. Спасибо, что на меня дауна потратил свое время!
179 1178809
нахуя углубленно учить пхп,если во вреймворках синтаксис отличается на 80% ?
изображение.png720 Кб, 584x587
180 1178813
>>178804

>Поэтому использовать нужно коммон сенс.


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



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

Так вот глядя на подобные высеры

>За денормализованные данные по ебалу бьют в нормальных конторах.


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

Вот уж точно орнул, когда представил, что устраиваешься например в фейсбук, и там блядь вся эта ваша бигдата нормализованна и юзер размазан по милиону таблиц, ну а хуле, John - популярное имя, нехуй дублироваться, го отдельную таблицу под имена)))
181 1178814
>>178809

>нахуя учить


не учи
182 1178815
>>178744
После того как осилю учебник. Навскидку - тело цикла, например, рассматривать подробнее, что в нем может находиться.
183 1178817
какой топ фреймворк наиболее простой?
184 1178819
>>178817
Bootstrap
185 1178822
>>178815
Во первых перестань писать под спойлером - это адово тупо и бесит.

Во вторых если хочешь упражнений на циклы, то вот тебе на вскидку 3 для того что бы лучше разобраться.

1. Напиши кусок кода который умеет считать факториалы.
Пусть выводит факториалы от 1! до 10! например.

2. То же самое но с числами фибоначи.

3. Условия знаешь? Тогда напиши физз-базз:
Напишите программу, которая выводит на экран числа от 1 до 100. При этом вместо чисел, кратных трем, программа должна выводить слово «Fizz», а вместо чисел, кратных пяти — слово «Buzz». Если число кратно и 3, и 5, то программа должна выводить слово «FizzBuzz»
а
186 1178823
>>178819
не траллируй.
cake пойдет?
187 1178825
>>178230

>Условие в цикле можно сократить до одного if, когда не нужно будет обновлять эти переменные.



Снова 2 часа перебирания. Почему бы тебе не сказать что это за условия, ибо я, откровенно говоря - идиот или необучаемый.
188 1178828
как реализовать такое,я двигаю шар из одного угла в другой,остальные пользователи видят это перемещение
189 1178832
>>178822
Я в этом треде уже много насрал - вот и скрываю. Да и кому нужны эти претензии пока я не составил конкретные пояснения что/где/куда? Пока еще рано.
Спасибо за задачи, я и правда не до конца понял как работает цикл. С пониманием остального материала таких проблем не возникало. Просмотр решения других анонов + чтения учебника + учебник ОПа в моем случае сработали.
>>178825
>>178659
>>178190
Видишь - много ненужного флуда. Надо выражать мысль лаконичнее. Горю я сильно от своей ограниченности, анон, контролировать получается не очень.
190 1178841
>>178805
Применимо к PHP это, например, вот что:
https://github.com/idealo/php-middleware-stack

по крайней мере к этому идет.
191 1178843
>>178825
вот:
http://sandbox.onlinephpfunctions.com/code/ee8b5691bf732bd63333003f7425003db2fdee7f

>идиот или необучаемый


Терпение, труд и регулярные занятия решат эти проблемы.
192 1178845
>>178813
Ебать тебя порвало, братишка. Сразу скатился в ad hominem и скобочки подключил с боевыми картиночками.
Но вот только нубас ты, ведь сам в этом расписался:
>>178339

>Сам часто делал в продакшене хуйню уровня


>не можешь справиться со сложными запросами


То есть в базах данных ты хуй простой, но мнение имеешь.
193 1178847
>>178845
С высокомерным пидрилой я всё же в точку попал видимо.
14846769968690.png45 Кб, 532x495
194 1178848
привет всем!я снова здесь!
195 1178854
>>178823
Cock.
Шапку и задачки читай.
Оп рекомендует slim
196 1178856
>>178854
слим это микрофреймворк.
а нужен серьезный
197 1178858
Делаю файлообменник, и возник вопрос, как адекватно прикрутить eloquent к слиму. Я засунул \Capsule\Manager в контейнер, как советуют в документации слима, но почти ничего не работает, нельзя например через фасад модели запрос к бд делать как в ларавеле. На стаковерфлоу советуют не заворачивать подключение в контейнер, а просто его объявить глобально. Так все фишки eloquent-а работают, но мне кажется эта идея слишком сомнительной из за глобальной переменной в коде.
198 1178873
>>178854
по нему мало инфы
199 1178874
>>178856
Выбор фреймворка от проекта зависит
200 1178880
>>178856
Зачем тебе серьезный, если ты будешь 10% от возможностей юзать?
201 1178881
>>178880
для работы на дядю
202 1178885
>>178847

>С высокомерным пидрилой


Я не он, но ты так говоришь, как будто это плохо. Высокомерным быть лучше, чем тупым и самоуверенным, как ты.
203 1178890
Анончики, хочу использовать для проекта сложного магазина laravel.
Какие подводные?
До этого работал с yii2
204 1178891
>>176196
Бамп
205 1178922
Сап анонимусы, работодатель на интервью подкинул задачку на алгоритмы, пытался написать на пыхе, но ничего дельного не вышло:
Расстояние между А и В 18 км, первая заправка находится от А на расстоянии 9 км, расстояние от первой до след. заправки 4 км, от второй до B 5 км. Нужно оптимально разместить три новые заправки (помимо этих трех, эти три перемещать нельзя) чтобы минимизировать максимальное расстояние между двумя заправками подряд (на всем маршруте).
Т.е. имеем массив [9,4,5] и количество заправок k = 3, нужно конкретно для этой задачи получить массив [3,3,3,4,2.5,2.5], но как это сделать алгоритмически и для любых данных, ума не приложу..
пс может вопрос тупой, сори, но если кто сталкивался или сообразит хелп плз! Всем мир!
206 1178943
>>178922
Братик, у тебя почерк неровный. Из твоего поста вытекает, что уже существует всего 2 заправки
207 1178960
>>178943
Да есть такое, изначально заправки две, затем над добавить еще 3 в оптимальных местах (т.е. k = 3 это новые заправки).
ОП 208 1178973
>>178858

> но почти ничего не работает, нельзя например через фасад модели запрос к бд делать как в ларавеле.


А ты уверен, что эта возможность - это особенность eloquent, а не самого Ларавеля? Я сам не в курсе, если что.

Но вообще, эти фасады - это скорее вредная штука, так как это статические методы, они работают в обход DI. Хотя что-то я сейчас не могу вспомнить, чем именно они вредны.

> Так все фишки eloquent-а работают, но мне кажется эта идея слишком сомнительной из за глобальной переменной в коде.



Ну да, это уже не DI.

>>178805

Смотря в каком контексте. В веб-фреймворках middleware (посредник) - это обертка, в которую можно обернуть процесс обработки запроса. Ну то есть функция, которая получает на вход Request, может что-то с ним сделать, затем вызывает обработчик запроса, получает ответ (Response), опять же может с ним что-то сделать перед тем, как он будет отдан клиенту (браузеру).

Выглядеть это может так:

$middleware = function (Request $req, callable $next): Response
{
...
$response = $next($req);
...
return $response;
};

middleware может быть несколько, и они вкладываются друг в дружку.

Предвосхищая вопрос, зачем это нужно, вот несколько применений:

- ограничение доступа к определенным URL
- сжатие или кеширование ответов по определенным правилам
- шифрование кук: middleware может расшифровывать приходящие куки до обработки запроса, а после зашифровывать установленные куки до отдачи клиенту
- организация сессий
- защита от CSRF
- добавление/обработка каких-то заголовков
ОП 208 1178973
>>178858

> но почти ничего не работает, нельзя например через фасад модели запрос к бд делать как в ларавеле.


А ты уверен, что эта возможность - это особенность eloquent, а не самого Ларавеля? Я сам не в курсе, если что.

Но вообще, эти фасады - это скорее вредная штука, так как это статические методы, они работают в обход DI. Хотя что-то я сейчас не могу вспомнить, чем именно они вредны.

> Так все фишки eloquent-а работают, но мне кажется эта идея слишком сомнительной из за глобальной переменной в коде.



Ну да, это уже не DI.

>>178805

Смотря в каком контексте. В веб-фреймворках middleware (посредник) - это обертка, в которую можно обернуть процесс обработки запроса. Ну то есть функция, которая получает на вход Request, может что-то с ним сделать, затем вызывает обработчик запроса, получает ответ (Response), опять же может с ним что-то сделать перед тем, как он будет отдан клиенту (браузеру).

Выглядеть это может так:

$middleware = function (Request $req, callable $next): Response
{
...
$response = $next($req);
...
return $response;
};

middleware может быть несколько, и они вкладываются друг в дружку.

Предвосхищая вопрос, зачем это нужно, вот несколько применений:

- ограничение доступа к определенным URL
- сжатие или кеширование ответов по определенным правилам
- шифрование кук: middleware может расшифровывать приходящие куки до обработки запроса, а после зашифровывать установленные куки до отдачи клиенту
- организация сессий
- защита от CSRF
- добавление/обработка каких-то заголовков
ОП 209 1178975
>>178828

Передаешь данные о перемещении на сервер по вебсокету, пользователи по какому-нибудь вебсокету подписываются на изменения и получают информацию о перемещении. На сервере нужен демон, который будет поддерживать вебсокет-соединения и ретранслировать сообщения. Ключевые слова: javascript, websocket, Websocket Application Message Protocol, php websocket server, php multiplexor.

>>178813

> го отдельную таблицу под имена


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

Если что, урок https://github.com/codedokode/pasta/blob/master/db/normalization.md

>>178809

Так а фреймворки не на PHP написаны? Как ты собрался изучать их, если PHP не понимаешь?

>>178804

Про нормализацию я попытался написать простыми словами тут https://github.com/codedokode/pasta/blob/master/db/normalization.md

> Однако, пример: posts [ id, author_id, content, category_title ] - не факт что такая структура требует нормализации.



Лучше сделать, так как 1) если надо обновить название категории, то придется обновлять кучу записей (а там окажется, что оно еще в нескольких таблицах используется) 2) если у категории надо добавить какие-то свойства, то тоже будет неудобно.

> Предположим, при написании поста автор может вообще что угодно придумать для категории, а поиск постов по ней осуществляется через вайлдкард - в таком случае смысла в нормализации нет.



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

> Например, поле ip - содержит четыре числа через точку. Это-же очевидный массив.


Вообще, конечно, нет. для IP удобно использовать BINARY и в СУБД обычно есть функции преобразования между текстовым и бинарным форматами.
ОП 209 1178975
>>178828

Передаешь данные о перемещении на сервер по вебсокету, пользователи по какому-нибудь вебсокету подписываются на изменения и получают информацию о перемещении. На сервере нужен демон, который будет поддерживать вебсокет-соединения и ретранслировать сообщения. Ключевые слова: javascript, websocket, Websocket Application Message Protocol, php websocket server, php multiplexor.

>>178813

> го отдельную таблицу под имена


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

Если что, урок https://github.com/codedokode/pasta/blob/master/db/normalization.md

>>178809

Так а фреймворки не на PHP написаны? Как ты собрался изучать их, если PHP не понимаешь?

>>178804

Про нормализацию я попытался написать простыми словами тут https://github.com/codedokode/pasta/blob/master/db/normalization.md

> Однако, пример: posts [ id, author_id, content, category_title ] - не факт что такая структура требует нормализации.



Лучше сделать, так как 1) если надо обновить название категории, то придется обновлять кучу записей (а там окажется, что оно еще в нескольких таблицах используется) 2) если у категории надо добавить какие-то свойства, то тоже будет неудобно.

> Предположим, при написании поста автор может вообще что угодно придумать для категории, а поиск постов по ней осуществляется через вайлдкард - в таком случае смысла в нормализации нет.



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

> Например, поле ip - содержит четыре числа через точку. Это-же очевидный массив.


Вообще, конечно, нет. для IP удобно использовать BINARY и в СУБД обычно есть функции преобразования между текстовым и бинарным форматами.
ОП 210 1178976
>>178803

Не храни пароли в открытом виде, читай урок https://github.com/codedokode/pasta/blob/master/security/password-hashing.md

После header Location надо завершать скрипт. зачем ты продолжаешь его выполнять и выводишь страницу?

Вместо error_reporting в коде лучше на своем локальном сервере прописать это в php.ini вместе с display_errors=1, но не делай так на боевом сервере.

>>178769

> что нормализация нужна реже чем нужна, потому что в небольших проектах она скорее всего будет только усложнять базу



Наоборот. Отсутствие нормализации усложняет работу с БД. Усложняет таким образом:

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

Ну возьмем простой пример. Умник решил хранить теги к посту в одной колонке:

text | tags

Пост 1| php , js
Пост 2| уроки php ,photoshop

Удобно ли тут искать записи с тегом php? Легко ли добавить тег, удалить тег SQL-запросом? Можно ли сделать индекс для быстрого поиска по тегу? Если мы захотим каждому тегу добавить атрибут "скрытый", легко ли это сделать?

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

> ну кароче у меня к этой таблице селектов 99%, поэтому тут всё нормализованно и проиндексированно по айдишникам, шоб быстрее,


Ты же не понимаешь, в чем суть нормализации. Она не для того, чтобы ускорить какой-то поиск. А чтобы данные хранить в наиболее удобном для работы с ними виде.
ОП 210 1178976
>>178803

Не храни пароли в открытом виде, читай урок https://github.com/codedokode/pasta/blob/master/security/password-hashing.md

После header Location надо завершать скрипт. зачем ты продолжаешь его выполнять и выводишь страницу?

Вместо error_reporting в коде лучше на своем локальном сервере прописать это в php.ini вместе с display_errors=1, но не делай так на боевом сервере.

>>178769

> что нормализация нужна реже чем нужна, потому что в небольших проектах она скорее всего будет только усложнять базу



Наоборот. Отсутствие нормализации усложняет работу с БД. Усложняет таким образом:

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

Ну возьмем простой пример. Умник решил хранить теги к посту в одной колонке:

text | tags

Пост 1| php , js
Пост 2| уроки php ,photoshop

Удобно ли тут искать записи с тегом php? Легко ли добавить тег, удалить тег SQL-запросом? Можно ли сделать индекс для быстрого поиска по тегу? Если мы захотим каждому тегу добавить атрибут "скрытый", легко ли это сделать?

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

> ну кароче у меня к этой таблице селектов 99%, поэтому тут всё нормализованно и проиндексированно по айдишникам, шоб быстрее,


Ты же не понимаешь, в чем суть нормализации. Она не для того, чтобы ускорить какой-то поиск. А чтобы данные хранить в наиболее удобном для работы с ними виде.
ОП 211 1178978
>>178329

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

>>178342

> user_agent_id, phone_id, ip_address_id


Ip адрес может быть отдельной сущностью, а может и не быть в зависимости от ситуации. Если у тебя с IP-адресом связаны какие-то данные, например, "репутация", то это отдельная сущность. Вместо искуственного ключа тут можно использовать естественный - сам IP адрес в бинарной форме (BINARY(4)), благо он весит всего 4 байта, а в СУБД есть функции преобразования из текстового в бинарный формат.

То же относится к phone_id и тд.

Нормализация не требует каждое поле выносить в отдельную таблицу.

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

time | user_id | device_id

Урок https://github.com/codedokode/pasta/blob/master/db/normalization.md

>>178660

Ну общая идея такая:

- программа это последовательность команд, после каждой ставится точка с запятой:

команда 1;
команда 2;

- команда - это например echo 2 + 2; или $x = 3 + 3;
- программа по умолчанию выполняется сверху вниз
- блоком называют последовательность команд, заключенных в фигурные скобки:

{
команда 1;
команда 2;
}

блоки используются не сами по себе, а как часть операторов вроде if, for, foreach.

- специальная команда if позволяет выполнять действия в определенном блоке или пропускать блок в зависимости от условия
- циклы for, foreach, while, do позволяют выполнить блок несколько раз подряд в зависимости от условий

- в программе могут содержаться функции, они начинаются со слова function, за которой идет имя:

function x()
{
команда 1;
команда 2;
}

Слово function только создает функцию, но пока не выполняет команды в ней. Также, есть анонимные функции, у них нет имени и потому указатель для их вызова сохраняется в переменную:

$x = function () { ... };

- в программе можно вызвать функцию, указав ее имя и круглые скобки: echo x(); Анонимная функция вызывается через переменную, в которой хранится указатель на нее: echo $x();

Вот краткое описание синтаксиса PHP и того, что можно делать.

Ты бы спрашивал вопросы, если что-то непонятно.
ОП 211 1178978
>>178329

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

>>178342

> user_agent_id, phone_id, ip_address_id


Ip адрес может быть отдельной сущностью, а может и не быть в зависимости от ситуации. Если у тебя с IP-адресом связаны какие-то данные, например, "репутация", то это отдельная сущность. Вместо искуственного ключа тут можно использовать естественный - сам IP адрес в бинарной форме (BINARY(4)), благо он весит всего 4 байта, а в СУБД есть функции преобразования из текстового в бинарный формат.

То же относится к phone_id и тд.

Нормализация не требует каждое поле выносить в отдельную таблицу.

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

time | user_id | device_id

Урок https://github.com/codedokode/pasta/blob/master/db/normalization.md

>>178660

Ну общая идея такая:

- программа это последовательность команд, после каждой ставится точка с запятой:

команда 1;
команда 2;

- команда - это например echo 2 + 2; или $x = 3 + 3;
- программа по умолчанию выполняется сверху вниз
- блоком называют последовательность команд, заключенных в фигурные скобки:

{
команда 1;
команда 2;
}

блоки используются не сами по себе, а как часть операторов вроде if, for, foreach.

- специальная команда if позволяет выполнять действия в определенном блоке или пропускать блок в зависимости от условия
- циклы for, foreach, while, do позволяют выполнить блок несколько раз подряд в зависимости от условий

- в программе могут содержаться функции, они начинаются со слова function, за которой идет имя:

function x()
{
команда 1;
команда 2;
}

Слово function только создает функцию, но пока не выполняет команды в ней. Также, есть анонимные функции, у них нет имени и потому указатель для их вызова сохраняется в переменную:

$x = function () { ... };

- в программе можно вызвать функцию, указав ее имя и круглые скобки: echo x(); Анонимная функция вызывается через переменную, в которой хранится указатель на нее: echo $x();

Вот краткое описание синтаксиса PHP и того, что можно делать.

Ты бы спрашивал вопросы, если что-то непонятно.
ОП 212 1178979
>>178659

Пока ждешь, пробуй смотреть другие задачи, читать урок дальше, поискать информацию сам, а вдруг найдешь понятное объяснение.

>>178190

> $zero = 0;


Это плохое название для переменной, так как далее ты ее увеличиваешь и там уже не zero. Надо писать, что хранится в переменной, для чего она нужна. В данном случае переменная указывает на позицию символа слева и ее можно назвать $leftPosition, $leftPos, $leftCharPos.

> for ($i = 1; $halfLength == $count; $i++) {


Цикл написан с ошибкой. Второй компонент в заголовке - это условие продолжения цикла. Пока оно верно, цикл выполняется, как только становится неверно - цикл завершается. У тебя в начале $count равно нулю, $halfLength - половина длины строки, которая больше нуля. Условие равенства не выполняется, цикл не выполняется ни разу.

Надо писать

$i < $halfCount

то есть, выполнять, пока $i меньше, чем $halfCount.

> } elseif($halfLength == $count) {


Это можно было не делать, а просто поставить echo $result после цикла. Так как цикл должен завершиться, когда перестанет выполняться условие $i < $halfCount, и начнет выполняться код за ним.

>>178627

И еще одна причина появления ООП - это то, что многие вещи удобно представлять именно в виде объектов, у которых есть свойства (поля), и действия над ними (методы).
ОП 213 1178980
>>178274

> $before = checkForTypos($text);


Функция же ничего не возвращает.

> } else {


> echo "Текст успешно исправлен, опечаток больше нет!";


> exit();


exit это плохо, так как ты когда пишешь функцию, не знаешь, кто и когда ее будет вызывать (даже если ты пишешь один, притворись, что не знаешь, и не видишь код снаружи функции). Соответственно ты можешь кому-то этим exit нарушить логику работы программы, код после вызова функции не выполнится. Функция не должна самовольно завершать всю программу.

Также, твоя программа видит в латинских словах опечатки в каждой букве: https://ideone.com/LqT9UN

Надо искать только слова из смеси двух алфавитов.

> Урезанная версия с просто исправлением


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

>>178258

read lock запрещает запись в таблицу, но не запрещает добавление блокировок к ней. Это излишняя мера (она снижает производительность, так как другие скрипты ждут снятия блокировки), но блокировка отдельных строк может быть полезна для согласованного чтения или обновления. Представь такую ситуацию:

- мы банк
- у пользователя есть в нем 2 аккаунта
- нам надо взять деньги с аккаунта 1, аккаунта 2 и найти сумму денег пользователя

Мы пишем код:

$sum1 = getValue("SELECT ... WHERE account = 1");
$sum2 = getValue("SELECT ... WHERE account = 2");
$sum = $sum1 + $sum2;

Корректен ли он?

Ну конечно нет. В промежутке между получением $sum1 и $sum2 могли произойти переводы денег с аккаунта 1 на аккаунт 2 и сумма получится больше фактической. Для предотвращения этого мы можем заблокировать строчку с первым аккаунтом:

BEGIN
SELECT ... WHERE account = 1 FOR SHARE
...
COMMIT

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

Там еще есть опция получения эксклюзивной блокировки на строчку - FOR UPDATE.

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

Теперь второй вопрос. Мы пишем перевод денег со счета 1 на счет 2. Какие тут есть подвохи?

UPDATE ... SET value = value - 100 WHERE account = 1
UPDATE ... SET value = value + 100 WHERE account = 2

Я вижу минимум два:

- скрипт может упасть на полпути, и деньги не дойдут. Или отключится электричество.
- другая транзакция может читать записи между 1-й и 2-й строчкой и увидит меньшую сумму денег, чем есть

Обе этих проблемы решаются заворачиванием в транзакцию:

BEGIN
UPDATE ... SET value = value - 100 WHERE account = 1
UPDATE ... SET value = value + 100 WHERE account = 2
COMMIT

Изменения, вносимые внутри транзакции, не видны другим до выполнения COMMIT.

Теперь вопрос: если же нам надо снять с 2 счетов по 100 тугриков с каждого и положить на третий, то что мы делаем?

Мануалы:

- https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html
- https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html#innodb-shared-exclusive-locks
- https://ru.wikipedia.org/wiki/Уровень_изолированности_транзакций
ОП 213 1178980
>>178274

> $before = checkForTypos($text);


Функция же ничего не возвращает.

> } else {


> echo "Текст успешно исправлен, опечаток больше нет!";


> exit();


exit это плохо, так как ты когда пишешь функцию, не знаешь, кто и когда ее будет вызывать (даже если ты пишешь один, притворись, что не знаешь, и не видишь код снаружи функции). Соответственно ты можешь кому-то этим exit нарушить логику работы программы, код после вызова функции не выполнится. Функция не должна самовольно завершать всю программу.

Также, твоя программа видит в латинских словах опечатки в каждой букве: https://ideone.com/LqT9UN

Надо искать только слова из смеси двух алфавитов.

> Урезанная версия с просто исправлением


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

>>178258

read lock запрещает запись в таблицу, но не запрещает добавление блокировок к ней. Это излишняя мера (она снижает производительность, так как другие скрипты ждут снятия блокировки), но блокировка отдельных строк может быть полезна для согласованного чтения или обновления. Представь такую ситуацию:

- мы банк
- у пользователя есть в нем 2 аккаунта
- нам надо взять деньги с аккаунта 1, аккаунта 2 и найти сумму денег пользователя

Мы пишем код:

$sum1 = getValue("SELECT ... WHERE account = 1");
$sum2 = getValue("SELECT ... WHERE account = 2");
$sum = $sum1 + $sum2;

Корректен ли он?

Ну конечно нет. В промежутке между получением $sum1 и $sum2 могли произойти переводы денег с аккаунта 1 на аккаунт 2 и сумма получится больше фактической. Для предотвращения этого мы можем заблокировать строчку с первым аккаунтом:

BEGIN
SELECT ... WHERE account = 1 FOR SHARE
...
COMMIT

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

Там еще есть опция получения эксклюзивной блокировки на строчку - FOR UPDATE.

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

Теперь второй вопрос. Мы пишем перевод денег со счета 1 на счет 2. Какие тут есть подвохи?

UPDATE ... SET value = value - 100 WHERE account = 1
UPDATE ... SET value = value + 100 WHERE account = 2

Я вижу минимум два:

- скрипт может упасть на полпути, и деньги не дойдут. Или отключится электричество.
- другая транзакция может читать записи между 1-й и 2-й строчкой и увидит меньшую сумму денег, чем есть

Обе этих проблемы решаются заворачиванием в транзакцию:

BEGIN
UPDATE ... SET value = value - 100 WHERE account = 1
UPDATE ... SET value = value + 100 WHERE account = 2
COMMIT

Изменения, вносимые внутри транзакции, не видны другим до выполнения COMMIT.

Теперь вопрос: если же нам надо снять с 2 счетов по 100 тугриков с каждого и положить на третий, то что мы делаем?

Мануалы:

- https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html
- https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html#innodb-shared-exclusive-locks
- https://ru.wikipedia.org/wiki/Уровень_изолированности_транзакций
214 1178981
>>178975
так вроде в пхп с сокетами все хуево
ОП 215 1178982
>>178242

> ([а-яёА-ЯЁ]+)?


+ и ? можно заменить на звездочку.

> (([а-яёА-ЯЁ]+)?([a-zA-Z])([а-яёА-ЯЁ]+)?){1,}


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

Хотя программа как-то и работает, регулярки, думаю, надо улучшить.

>>178200

Так ты только его и выводишь командой var_dump. Выполняются несколько раз только действия внутри цикла (блока фигурных скобок), а var_dump стоит после и выполняется один раз.
216 1178984
>>178981
те только через костыли
217 1178985
>>178922
Смотри как тебе такое универсальное решение
На вход берешь массив сегментов и количество разделений которые нужно добавить.

Делишь 18 (общая длинна) / 5 (общее количество разделителей) = 3.6 - best т.е. в идеальном мире если бы заправки можно было двигать... заодно если у тебя всего один сегмент то ответ уже готов.

Вычисляешь
9 4 5 - наш массив ; 3 - остаток бюджета делителей
5.4 0.4 1.4 - отклонения сегментов от идеального; 2.4 - среднее отклонение

Берешь первый отрезок с самым большим отклонением и делаешь вот что: делишь его по очереди на разное количество сегментов в бюджете и считаешь среднее отклонение. Лучший разрез даст наименьшее отклонение.

4.5 4.5 4 5 ; 2
0.9 0.9 0.4 1.4 ; 0.9

3 3 3 4 5 ; 1
0.6 0.6 0.6 0.4 1.4 ; 0.72

2.25 2.25 2.25 2.25 4 5 ; 0
1.35 1.35 1.35 1.35 0.4 1.4 ; 1.2

Выбираем разрез на 3 части, в бюджете остается еще разрез. Повторим алгоритм, теперь резать будем 5, но так как вариант порезать сегмент всего один (у нас один разрез) то сразу получаем конечный результат:

3, 3, 3, 4, 2.5, 2.5 ; 0
0.6, 0.6, 0.6, 0.4, 1.1, 1.1 ; 0.88

Предположим другие входные данные:
50 22 2 9; 5; ( 10.375 )
Поехали:
25 25 22 2 9; 4; 10.125
16.66 16.66 16.66 22 2 9; 3; 6.7
12.5 12.5 12.5 12.5 22 2 9; 2; 4.26
10 10 10 10 10 22 2 9; 1; 2.9
8.33 8.33 8.33 8.33 8.33 8.33 22 2 9; 0; 3.73
Выбираем вариант с разделением на пять частей (тратим 4 делителя):
10 10 10 10 10 22 2 9; 1; 2.9
Ну думаю уже догадался что мы поделим и что получится.

На вскидку кажется нет узких мест.

Теперь давай попробуем прикинуть алгоритмическую сложность:
Первое: перед каждым разрезом мы проходимся по массиву для поиска самого большого куска, это N. Операцию выбора большого куска придется также повторить до тех пор пока k не кончится - N k, но так как k уменьшается то N log( k )
Второе: чтобы найти лучший разрез мы делим наш кусок на k..1 и каждый раздел расчитываем, это еще раз k, так что k ^ 2, но так как k уменьшается то log ( k ^ 2 )

Вторую операцию мы повторяем столько раз сколько дает первая, т.е.: N log( k ) log ( k ^ 2 )
Алгоритмическая сложность если я правильно понимаю O( N log( k ) log ( k ^ 2 ) )
Надеюсь если будет кто шарящий читать поправит.

Пойду устраиваться вместо тебя
217 1178985
>>178922
Смотри как тебе такое универсальное решение
На вход берешь массив сегментов и количество разделений которые нужно добавить.

Делишь 18 (общая длинна) / 5 (общее количество разделителей) = 3.6 - best т.е. в идеальном мире если бы заправки можно было двигать... заодно если у тебя всего один сегмент то ответ уже готов.

Вычисляешь
9 4 5 - наш массив ; 3 - остаток бюджета делителей
5.4 0.4 1.4 - отклонения сегментов от идеального; 2.4 - среднее отклонение

Берешь первый отрезок с самым большим отклонением и делаешь вот что: делишь его по очереди на разное количество сегментов в бюджете и считаешь среднее отклонение. Лучший разрез даст наименьшее отклонение.

4.5 4.5 4 5 ; 2
0.9 0.9 0.4 1.4 ; 0.9

3 3 3 4 5 ; 1
0.6 0.6 0.6 0.4 1.4 ; 0.72

2.25 2.25 2.25 2.25 4 5 ; 0
1.35 1.35 1.35 1.35 0.4 1.4 ; 1.2

Выбираем разрез на 3 части, в бюджете остается еще разрез. Повторим алгоритм, теперь резать будем 5, но так как вариант порезать сегмент всего один (у нас один разрез) то сразу получаем конечный результат:

3, 3, 3, 4, 2.5, 2.5 ; 0
0.6, 0.6, 0.6, 0.4, 1.1, 1.1 ; 0.88

Предположим другие входные данные:
50 22 2 9; 5; ( 10.375 )
Поехали:
25 25 22 2 9; 4; 10.125
16.66 16.66 16.66 22 2 9; 3; 6.7
12.5 12.5 12.5 12.5 22 2 9; 2; 4.26
10 10 10 10 10 22 2 9; 1; 2.9
8.33 8.33 8.33 8.33 8.33 8.33 22 2 9; 0; 3.73
Выбираем вариант с разделением на пять частей (тратим 4 делителя):
10 10 10 10 10 22 2 9; 1; 2.9
Ну думаю уже догадался что мы поделим и что получится.

На вскидку кажется нет узких мест.

Теперь давай попробуем прикинуть алгоритмическую сложность:
Первое: перед каждым разрезом мы проходимся по массиву для поиска самого большого куска, это N. Операцию выбора большого куска придется также повторить до тех пор пока k не кончится - N k, но так как k уменьшается то N log( k )
Второе: чтобы найти лучший разрез мы делим наш кусок на k..1 и каждый раздел расчитываем, это еще раз k, так что k ^ 2, но так как k уменьшается то log ( k ^ 2 )

Вторую операцию мы повторяем столько раз сколько дает первая, т.е.: N log( k ) log ( k ^ 2 )
Алгоритмическая сложность если я правильно понимаю O( N log( k ) log ( k ^ 2 ) )
Надеюсь если будет кто шарящий читать поправит.

Пойду устраиваться вместо тебя
218 1178993
>>178975 >>178976

Про теги я знаю допустим, не случайно уточнил что примеры из жопы, а последние специально доведены до абсурда. Мысль то была не в этом, а в том что думать нужно, не просто делить всё подряд...
219 1179015
>>178980
А как будут работать локи строк с myisam таблицами? Если я правильно понял там в любом случае при DML запросах она блочится целиком. И заодно суб-вопрос, зафигом там вообще myisam если даже текста нет...

И как думаешь нужен ли мне лок всей таблицы вот для чего:
есть основная допустим main: | id | ... |
и много разных:
main_secondary: | main_id | secondary_id |
Мне нужно удалить запись из основной, предварительно почистив все остальные. Но есть вероятность, что пока я буду их чистить и дойду до удаления основной, в какую-то из них опять что-то добавят.
В то-же время не хотелось бы лочить их все. И не хотелось бы получить висяки.
Я так понимаю, если добавить констрейнты foreign key, то мне просто не даст удалить запись если в процессе кто-то что-то опять добавит, но такой вариант мне тоже не нравится - просто inconvinient для пользователя.

Что если дописать там поле допустим QUEUED_FOR_DELETION, и во всех местах приложения не давать добавлять связи для таких сущностей, а потом когда-нибудь их удалить. Можно было бы конечно вообще не удалять в таком случае но таблица будет расти и место там не резиновое.
220 1179124
>>178922
У меня как то так вышло: http://sandbox.onlinephpfunctions.com/code/0494c1a1d92e3584993a9514f8e60459c33c57b5
Тут конечно еще нужно допиливать. Надо бы больше тестов. Проверка входящих значений, имена поправить и т.д. Хотя я собой доволен. Когда твой пост прочитал, вообще не понимал как подступиться.
221 1179162
>>179124
Как же лаконично и алгоритмически более эффективно.
А казалось бы просто представь сегмент как что-то самостоятельное, пиздец я еще тупой, рановато мне пытаться помогать кому-то.
222 1179167
>>178885
Для чего лучше? Оба варианта хуевы для взаимодействия, что первый долбоеб которому ничего не докажешь, но он окукливается при первой же угрозе и будет тебя скрыто хейтить, иногда попердывая при удобном для него случае, как и второй, который будет стоять на своей неправоте и считать что спор выигран тем, за кем было последнее слово или тот кто громче крикнул.
224 1179252
продублирую сюда из бд-треда
Вопрос по постгресу. Уменя есть колонка в таблице с варчар данными, которые есть обычный json. Типа:
{"Lat":"123","Lon":"231"}
Суть в том, что мне нужно сделать из неё jsonb, но так, чтобы значения были нумерик, а не текст. Обычный alter, который set type jsonb using col::jsonb переводит в обычный текст (значения в кавычках), а мне нужно от этих кавычек избавиться. Как быть?
225 1179282
Ощущаю себя тупым. Сколько времени у вам заняло изучение html+css?только без толстоты плс
226 1179285
>>178979
Меня почему - то ступор на самых простых вещах, каждый раз. В голову не пришла мысль, что если цикл не ломается - значит все совпало. И что считать не надо, так как уже все считается.
А по поводу условия в цикле - это уже просто невнимательность. Много раз переделывал, "глаз замылился".
http://sandbox.onlinephpfunctions.com/code/ce073838ae8fa5753fef60ff8c5018ca95a65de4
Так верно?
227 1179304
>>179282
я вообще изучал этот кал. это же фронтэнед, а мы тут учим php sql ООП фреймворки линуху
228 1179309
>>179252
Покажи как ты сохраняешь
229 1179390
>>179252

Сделать бекап. Добавить новую колонку типа JSON. Сделать UPDATE и сконвертировать значения из старой колонки в новую. Проверить, что все ок. Дропнуть старую колонку.
Стикер512x512
230 1179478
Планирую начать изучать PHP, но сначала надо определиться с web-сервером. Когда то работал немного на OpenServer.
Какой посоветуете? Мало ли, может придется использовать сервер в будущем и я уже буду знаком со всеми настройками
231 1179617
Привет анонам. Настроил тут у себя ОЧЕРЕДЬ файлообменника, теперь могу конвертировать видео и сжимать картинки без регистрации и смс. У меня вопрос. Заресайзить картинку в пхп это не дело одной команды, ffmpeg пока еще не трогал. Я вот подумал, а почему бы не написать все эти дела на каком-то питоне(я его не знаю, но пример ресайза на питоне в 2-3 раза меньше чем на пхп), ну и может как-то наладить общение между ними типа ВСЕ_ОК или там ПРАВА_ЗАПИЛИ(понятия не имею как).
232 1179730
>>179617
Умные люди ресайзят картинки на клиенте.
233 1179739
>>179617
Я опять выхожу на связь. До меня дошло что я не знаю статус выполнения задач, и как я понял то beanstalkd мне ничего не скажет. Мне теперь надо запилить еще таблицу статуса задач в бд, и к ней при реквесте обращаться? Не ну это уже некрасиво.
234 1179828
>>174695 (OP)
на 3 трап?
235 1179830
>>179828
Это ОП.
236 1179846
Аноны, установил на laravel npm, запустил npm run watch, но когда я делаю изменения в любом vue компоненте, изменения проявляются в браузере спустя где то пол часа. Иногда все работает сразу, но обычно такая фигня. Как фиксить?
Всегда пишется что build successful
237 1179875
>>179478
1 стул-xampp
2 стул-сразу перенести разработку на VPS
238 1179898
Поясните, как вы мониторите доступность и нормальную работу своих сайтов?
Есть идея запилить скрипт, который будет чекать определённый элемент на странице сайта. Простой чек по коду 200 не подходит, потому что сайт может отдавать такой код и при этом, например, быть пустой страницей или если оплата вовремя не внесена была домен всё равно будет доступен только будет редиректить на скрипт хостера.
Норм идея так делать? Сайты мои, поэтому можно не париться, что элемент, наличие которого чекаю, исчезнет.
someApprentice 239 1180024
>>178355

>>Какие ты видишь решения проблемы?


>Я ещё не освоился с JS, но пока могу сказать, что это нужно разделить либо на отдельные функции, либо разбить на два класса - Helper и Handler, который вешает обработчики (к примеру, Handler.prototype.handleClickOnImg...).


Я ещё подумал, что можно разить ещё на отдельные классы, например PopUp и поместить в него все методы связанные с PopUp'ом. Например, PopUp.handle(); или PopUp.resize() и т.д.

Я только не знаю насколько это будет читабельно https://codepen.io/anon/pen/YLGNRY?editors=0010
Мне лично нравится такое решение.
Я 240 1180063
Вкатываюсь в вашу парашу. Почти полный ноль, знаком только с основными терминами разработочки, так что надеюсь вы тут не уёбки и будете хоть иногда отвечать на мои вопросы.

1) Сразу ставить линупс и привыкать к нему или всякие апачи и на окнах нормально функционируют? Если на окнах придрочусь, не будет такого что в линупсе по другому всё работает? На каких осях кодят во всяких кампаниях, куда меня потенциально могут взять джуном? люблю вас
241 1180066
>>180063
Ну смотри, с линуксом ты в любом случае столкнешься, так что выбор не между натуралом и геем, а между натуралом и бисексуалом.
С такой точки зрения может даже лучше быть бисексуалом - ты будешь знать много всяких тонкостей о которых натуралы даже не задумываются.
Минус же в том что обычный традиционный секс тебя уже не будет удовлетворять.
242 1180072
У меня дежат на впс два сайта, один на 8080м порту, другой на 8081, однако корректный сервернэйм апач отдает только для одного, на втором (8081) он отдает IP вместо домена. Пробовал уже прописывать ServerName в sites-enabled/000-default.conf, не помогло. В чем затык? Заранее благодарен за помощь.
243 1180074
>>180072
Если что, сервак на дебиане 8, апач 2.4, пыха 7.2.
244 1180081
Привет всем.
Вопрос к про, задали сегодня на собеседование.
Написать семафор для доступа к абстрактному ресурсу на 7 строк кода PHP.
Я чет тормазнул на этом, вообще все реализации что были в голове и то что я знаю о семафорах подразумевало много больше кода.
Чего от меня хотели?
Сможет кто решить это?
245 1180084
>>180081

>Чего от меня хотели?


Ну, меня например, неделю назад на улице остановили и сказали сюда иди сюка. Потом избили, прошлись по мне ногами, но не обоссали, а достали свои мужыцкие достоинства и давай трясти ими.
А тебе велели семафор... семафор для доступа... для доступа к абстрактному ресурсу на 7 строк кода... на PHP.
sage 246 1180085
>>180072
Отбой, разобрался. В апаче поменял, а про nginx забыл.
247 1180097
>>180081
Может, от тебя хотели просто знание библиотечных функций: http://php.net/manual/en/book.sem.php
248 1180132
ОП и компания Решил задачу "Генератор имени" через конкатенацию строк и через имплод все работает верно. Для эксперемента попробовал искать рандомный слог через mt_rand,а не как делал ранее через array_rand. И тут столкнулся с проблемой - программа ни в какую не хочет видеть последний слог в массиве, правильно высчитывает его положение , а через echo выводит пустое место. Пробовал решать в phpstorm - Notice: Undefined offset: 16 in и тд.
В чем проблема? По идее все должно работать правильно =(
Для наглядности увеличил число слогов до 40 https://ideone.com/xxWWWY
249 1180140
>>180132
Индексы в массивах в php начинаются с 0, а не единицы. Поэтому лучше сделать так

>$random = mt_rand(0, count($letters)-1);

250 1180141
>>174695 (OP)
Дайте пожалуйста убер-краткий гайд с примерами для даунского вката в sql на уровне "решить задачу на собеседовании". САМЫЕ основы - как добавлять, удалять, изменять данные знаю. Но вот промежуточные таблицы в запросе, функции всякие, объединения/соединения таблиц, вычитания, переменные в запросе - я вообще ноль. Памахити, братишки.
252 1180151
>>180143
Так там тесты, а не гайды. Или ты вот это
http://www.sql-tutorial.ru
имел ввиду?
Там дохуя очень, я за полдня не успею прошариться. Так бы на офф-сайте доки, может, читал с гуглопереводчиком, если бы времени было вагон.
253 1180165
Устроился PHP джуном. У вас в пхп да и вообще в бекенде есть хоть что-нибудь интересное? Или вы целыми днями пишете обработчики для форм? Прошла всего неделя, а меня уже заебало работать
254 1180172
Объясните как на apache быстро открывать сайт php, чтобы не писать каждый раз в поисковой строке http:\\localhost
На openserver это делалось в разы интуитивней
255 1180174
>>180165
Бекенд же ведь он разный бывает. Если просто сайты делать, то действительно немного интересного. А так иногда приходится и базы настраивать и проектировать, репликацию, веб-сокеты.
256 1180179
>>180172
Быстро решительно добавляешь ссылку на сайт на панель закладок. Сайт теперь открывается в один клик.
257 1180181
>>180179
Я об этом не подумал. Спасибо
А почему во всех туториалах по началу работы с php советуют брать связку apache+MySQL+PHP7, а не OpenServer, где все это есть и работа происходит чисто интуитивно?
258 1180182
>>180181
Потому что openserver это чисто виндовая хуйня. Следоваетльно чуть более чем полностью бесполезная. Ты когда будешь сайт на хостинг переносить столкнёшься с линухом куда будешь накатывать apache/nginx + mysql + php
259 1180184
>>180182
Хмм, понятно. А есть какой нибудь туториал по apache? Я имею ввиду вот зачем мне Apache Service monitor? У меня там даже start не горит. Вдруг есть какая то инфа, про которую стоило бы узнать заранее? Был бы благодарен
260 1180185
>>180184
Накати лучше линух в виртуалку хотя бы и играйся там с установкой и настройкой окружения. Там это всё приятней и быстрее делается, чем в винде.
На винду не случайно запилили все эти комбайны типа опенсервера и xammp ибо устанавливать все эти компоненты по отдельности тот ещё гемор под винду.
261 1180187
Как сильно надо знать пхп чтобы на божественные 15к рупий в месяц выйти? Срок по времени?
262 1180188
>>180185
Да... Практика в линуксе определенно нужна, но в любом случае пока что в планах - это осилить PHP. Думаю это еще не скоро будет
263 1180189
>>180188
Тогда забей и работай как удобно пока. Хоть в опенсервере.
264 1180190
>>180187
Нихуя не надо знать. Прям завтра идёшь и устраиваешься.
265 1180191
>>180189
Хорошо. Спасибо за ответ анончик.
Хотя у меня последний вопрос остался. Как определять, например, что нужно выполнять на js, а что на php?
266 1180193
>>180191
Cлишком общий вопрос. Зависит от задачи, очевидно. Нельзя ответить коротко и однозначно.
267 1180197
>>174695 (OP)
Как в задаче с "Сумма прописью" числам придать женский род?
268 1180208
>>180197
Хуяришь массив. Цифор всего десять.
269 1180214
>>180190

>устраиваешься.


Там то все понятно, требования везде примерно одинаковые по шаблону, абстрактное знание php, mysql, html, js , jquery.

А вот как быстро спасти себя от голодной смерти с помощью пхп с помощью фриланса - не известно.
270 1180220
Сап, Антошки!
Задачка с выводом email-адресов из текста:
https://ideone.com/0ZiZMs

Вроде я её и решил, но мне не нравится такое решение, ибо я хотел бы, чтоб мне выводились только имэйл адреса, а не то, что получается у меня (у меня тоже адреса, но они делятся по частям регулярного выражения в массив)

Подскажите, как можно вывести только название адреса.
Спасибо!
271 1180223
>>180141
Бамп вопросу
273 1180230
>>180223
В оп-посте же есть. Пока ты бампаешь уже успел бы весь http://sql-tutorial.ru/ прочитать.
274 1180259
>>180230
Шутишь? Он огромный, а в оп-посте самые азы. Ладно, спасибо.
275 1180307
>>180165

>устроился хуесосом в говноконтору ковырять лендинги


>мам у вас в пхп так скучно, где интересное то?


Чому ты такой тупой?
Я, да Я 276 1180308
Ладно, с дикой тоской в глазах дошел до генератора leet шифра и пошел спатки.

Кому заняться нечем, можете рейтануть, раскритиковать мой код. Советы тоже норм
Обмен валют - https://ideone.com/GxnpIE
Игра в кубики - https://ideone.com/fpmVXk
Таблица умножения - https://ideone.com/XIc2VN
Процент вклада - https://ideone.com/v9dwvI
Расчет кредита - https://ideone.com/UOy1TU
Средний балл - https://ideone.com/Wu7ve0
Сравнение роста - https://ideone.com/0iNujR
РулетОчка - https://ideone.com/akfHyX
Генератор имён - https://ideone.com/qTV2wH
Шифровка - https://ideone.com/M9ebqb

Люблю вас
sage 277 1180331
>>180165
А формы от csrf защитил? А как быть с формой, если страница кэшируется? А валидацию с сохранением промежуточных значений в сессию сделал? А что, если для записи данных нужно двадцать таблиц из трёх бд дёрнуть, как вон выше у анона с ёба-нормализованной бд, а клиент хочет сразу ответ получить? И так далее, и так далее
278 1180355
>>180331
Жаль тот челик с нормализованной бд окуклился и не ответил в чем таки профит его подхода.
279 1180464
>>180308
Что там критиковать-то, кек, три строчки.
280 1180470
Задачка "Кредит на айпад". Пока что пробую создать функцию для 2 из 3 банков. Выводится пустота, ошибку самостоятельно не нашел.
https://ideone.com/2ZrJCa
281 1180471
>>180470

>Выводится пустота


Потому что у тебя функция ничего не возвращает. Где return?
282 1180472
Держу двач на втором мониторе - он немного старый и с разрешением 1280*1024, и в общем хотел немного поковырять пользовательские css, но что-то не работает ничего. Например решил начать с простого и немного уменьшить марджины у постов, что бы влезало больше текста и полоса прокрутки текста в посте тоже уехала на край. Но ничего не работает, в юзер css пытался лепить как правило вида:
post-message { margin: 5px; }
так и
blockquote { margin: 1em 5px;}
Не подхватывается, кто-нибудь сталкивался?
283 1180473
>>180472

>.post-message { margin: 5px; }


.post-message { margin: 5px; }
284 1180474
>>180473
Что ты хочешь мне сказать?
И вообще сори, отбой - всё заработало, я забыл галочку в настройках поставить собственно, которая активирует всё это.
Я, да Я 285 1180475
>>180474

>Что ты хочешь мне сказать?


Что перед классами нужна точка.
286 1180478
Чятик, где про простейший роутинг почитать. Ночью гуглил, но все какое то на базе ООП и считаю что для начала слишком сложно.
Хочу чет на безе GET, как описывалось в пасте про MVC, но загуглить не смог.
287 1180479
>>180478
Ну так это, берёшь какой-нибудь известный микрофреймворк типа Slim (или Fat Free Framework) и смотришь как там устроен роутинг.
288 1180480
>>180479
так они все достаточно громоздкие, хотелось бы чет простое. Чисто для понимания как такое написать и собственно написать.
289 1180489
>>180478
Я бы начал такое вот васянить: допустим хочу что бы мои урлы были вида:
site/controller/method/argument

На примере студентов это бы выглядело:
student.list/Student/show/123
Student - это контроллер тут
show - это метод контроллера
123 - это аргумент который мы ему передаем ( id студента которого мы хотим посмотреть )

Ну и вот тебе надо смотреть в $_SERVER там смотреть в какое-нибудь ["PATH_INFO"]
дергать оттуда все эти куски урла
далее отдавать специальной функции, которая будет как-то так всё это обрабатывать:

$test = new $controller; //в $test ляжет новый объект класса Student;
$test->$method($argument); //тут она вызовет метод show и передаст ему аргумент 123 в примере

Ну и для начала норм как по мне.
Untitled.png171 Кб, 604x739
290 1180495
>>180478
Вот простая поэтапная инструкция
изображение.png84 Кб, 1280x1024
291 1180519
>>180475
Спасибо энивей за помощь и молниеносный отклик, настроил себе окошко двача так, что вообще ничего лишнего и легко и приятно стало читать большие посты на мелком монике, ну и форма ответа теперь внезапно наменого менее мешающая.
292 1180520
Еще с лету вот такой вопрос. Вот например есть твои посты - посты которые подсвечены красным, есть посты которые содержать ответ на твой поста - подсвечены пунктиром. А есть возможность как-то внутри этого поста как-то обозначить какая часть ответа тебе? Например что бы когда человек цитирует твой пост - то его номер:
>>180475
Скажем выводился жирным. Или тут нужно уже кастомный js подрубать что бы высчитывать подобное? И проще сразу идти писать абу что бы вводили?
293 1180523
>>180520
Да, нужно скрипт писать, ибо сообщения в самом хтмл ничем не выделяются для каждого юзера, да и с жс ты вряд ли найдешь универсальный способ определения того куска текста, который именно для тебя писался. Потому что я могу так сделать

>1


>2


текст
Могу так
текст

>1


Могу даже те>1кст
изображение.png45 Кб, 1321x882
294 1180526
>>180523
Вот пример маломальский того что я хотел бы на пикриле.

Хотя бы сам номер поста который мой - выделяеся жирным, помню пару тредов назад кто-то вкидывал как можно кастом js какой-то через закладки браузера активировать на страницах. Есть идеи как можно по простому и быстро такое налепить?
295 1180527
>>180526
А, ну это легко сделать наверно. Делаешь массив ТВОИХ ответов с треда, потом смотришь в пунктирных постах ответы и проверяешь со своим массивом, если true то делаешь жирным.
296 1180530
>>180526
тест, что будет если отвечать самому себе.
Я, да Я 297 1180531
mb_strtolower в ideone уже не работает? В ошибке пишет что неизвестный метод
298 1180533
>>180531
Там mb_* функции не работают, не подключили модуль в пхп.
изображение.png3 Кб, 262x87
299 1180542
>>180533
Блядь в учебнике же написано, что нужно перекатываться на ideone
300 1180545
>>180527
Вопрос в том, что как это прикрутить к двачу со стороны клиента. Нашел уже тот пост с костылем, но во первых что-то это в лисе не работает, а во вторых надо же кнопку нажимать, а хочется автоматизировать и забыть.

>>180542
Учебник года 3 назад писался, а на идеоне прост забыли при перекате на новую версию пыхи подключить библиотеку в ini файле, напиши им в поддержку если хочешь. cont^9{actANUSiL<4deonePUNCTUMc9^Vom
301 1180547
Если кто не слышал про букмарклеты, то расскажу. Это закладки в браузере, в которых вместо URL указан скрипт на JS. Ну например, вот как можно сделать букмарклет, который подсвечивает посты в треде без ответов.

Щелкните правой кнопкой на панели закладок (чтобы показать ее в Хроме, используйте Ctrl + Shift + B) или найдите в меню пункт "добавить закладку". В поле "название" введите что хотите, в поле URL введите:

javascript:var t = document.querySelectorAll('.post-wrapper:not(.watched-posts-marker)');Array.prototype.map.call(t, function (el) { var ref = el.querySelectorAll('.ABU-refmap a'); if (!ref.length) { var bg = el.querySelector('.post'); bg.style.backgroundColor = '#fbfb9d'; } });

(проверьте, что на сайте латинские буквы не заменены на кирилицу).

После этого сохраните закладку. Теперь при нажатии на эту кнопку запустится скрипт в контексте страницы и подсветит неотвеченные посты желтым.
302 1180548
>>180545

>Нашел уже тот пост с костылем, но во первых что-то это в лисе не работает, а во вторых надо же кнопку нажимать, а хочется автоматизировать и забыть.


Переделой
303 1180564
>>176196
Бамп, опчик, я надеюсь ты посоветуешь что-то, когда будет время :3
304 1180670
Нужна хелпа, попробовал решить задачу про Льва Толстого через перебор общего массива - в итоге заблудился в трех соснах и не могу вывести текст на экран. И вообще есть способ решить эту задачу с помощью foreach не используя is_array???
https://ideone.com/l7OcfA
305 1180681
>>180670
Зачем там implode вообще?
307 1180913
>>180545

Букмарклет работает только по нажатию кнопки. Также, в него не запихнешь много кода.

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

Расширение пишется на HTML/CSS/JS. Оно может содержать:

- фоновую страницу. Это HTML + JS код, который работает в своем, отдельном окружении (то есть можешь представить, что в браузере открывается невидимая вкладка и в нее загружается твой код и что-то там делает)
- кнопку, добавляемую на панель браузера или в адресную строку (browser action/page action). Она может показывать HTML страницу при нажатии или реагировать на это как-то еще.
- также оно может взаимодействовать с другими вкладками и внедрять в них JS скрипты (content scripts). Эти скрипты могут взаимодействовать с DOM страницы, например, находить посты и что-то с ними делать.

Собственно, тебе хватит простого расширения из кнопки в адресной строке (просто чтобы показать, что оно запущено, жать на нее не надо) и контентного скрипта, который будет автоматически внедряться во все вкладки с двачем.

В расширении делается специальный файл - манифест - который содержит информацию о расширении. Через него ты можешь указать иконку для кнопки, путь к контентному скрипту и URL страниц, в которые его надо внедрять.

Стандартный формат расширений - Chrome Extension. Этот формат разработан Гуглом и позже его адаптировали разработчики всех современных браузеров под названием WebExtension, включая Opera, Firefox и Edge. А я помню, как когда-то делал слои абстракции, чтобы сделать расширение и для chrome, и для firefox.

Я тебе советую не заморачиваться и делать как можно проще, для твоего расширения хватит манифеста, иконки и 1 скрипта.

Я бы советовал для облегчения кода не использовать jQuery, если это не замедляет разработку, так как расширение будет работать только в современных браузерах, где есть querySelector, classList и другие современные DOM методы. Там, где их нет, нет и поддержки таких расширений. Или использовать облегченный аналог jQuery вроде zepto.js (для сайтов, я бы его не рекомендовал, из-за совместимости только с новыми браузерами).

Ссылки:

- пример написания расширения (рус) https://canonium.com/articles/briefly-about-building-a-chrome-
- офиц туториал (англ) https://developer.chrome.com/extensions
- офиц док (англ) https://developer.chrome.com/extensions/devguide
- док. по совместимости с фаерфоксом (англ) https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Porting_a_Google_Chrome_extension
- про content scripts (рус) http://chrome-ext.blogspot.ru/2014/02/content-scripts.html

Задавай вопросы, если что.
307 1180913
>>180545

Букмарклет работает только по нажатию кнопки. Также, в него не запихнешь много кода.

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

Расширение пишется на HTML/CSS/JS. Оно может содержать:

- фоновую страницу. Это HTML + JS код, который работает в своем, отдельном окружении (то есть можешь представить, что в браузере открывается невидимая вкладка и в нее загружается твой код и что-то там делает)
- кнопку, добавляемую на панель браузера или в адресную строку (browser action/page action). Она может показывать HTML страницу при нажатии или реагировать на это как-то еще.
- также оно может взаимодействовать с другими вкладками и внедрять в них JS скрипты (content scripts). Эти скрипты могут взаимодействовать с DOM страницы, например, находить посты и что-то с ними делать.

Собственно, тебе хватит простого расширения из кнопки в адресной строке (просто чтобы показать, что оно запущено, жать на нее не надо) и контентного скрипта, который будет автоматически внедряться во все вкладки с двачем.

В расширении делается специальный файл - манифест - который содержит информацию о расширении. Через него ты можешь указать иконку для кнопки, путь к контентному скрипту и URL страниц, в которые его надо внедрять.

Стандартный формат расширений - Chrome Extension. Этот формат разработан Гуглом и позже его адаптировали разработчики всех современных браузеров под названием WebExtension, включая Opera, Firefox и Edge. А я помню, как когда-то делал слои абстракции, чтобы сделать расширение и для chrome, и для firefox.

Я тебе советую не заморачиваться и делать как можно проще, для твоего расширения хватит манифеста, иконки и 1 скрипта.

Я бы советовал для облегчения кода не использовать jQuery, если это не замедляет разработку, так как расширение будет работать только в современных браузерах, где есть querySelector, classList и другие современные DOM методы. Там, где их нет, нет и поддержки таких расширений. Или использовать облегченный аналог jQuery вроде zepto.js (для сайтов, я бы его не рекомендовал, из-за совместимости только с новыми браузерами).

Ссылки:

- пример написания расширения (рус) https://canonium.com/articles/briefly-about-building-a-chrome-
- офиц туториал (англ) https://developer.chrome.com/extensions
- офиц док (англ) https://developer.chrome.com/extensions/devguide
- док. по совместимости с фаерфоксом (англ) https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Porting_a_Google_Chrome_extension
- про content scripts (рус) http://chrome-ext.blogspot.ru/2014/02/content-scripts.html

Задавай вопросы, если что.
308 1180921
Поставил сервер на LAMP, установил Drupal, но PHP не знаю, хотя говорят надо бы, или необязательно для простого интернет магазина?
Как вообще знающие PHP используют CMS, пишете свои модули?
Я собирался начать учить, но немножечко время поджимает, со всех сторон в плане учебы, просто как бы я не прогадал.
309 1180922
>>180921
Еще спрошу: планирую ставить разные хостинги, на Nginx с Joomla, правда времени наверное много уйдет, кто нибудь занимался этим? Какая база нужна?
310 1180952
Пример переусложнения кода: https://habr.com/company/superjob/blog/354388/

Для отделения логики от представления не нужно делать второе приложение на JS (как я понял, у них на сервере 2 приложения - одно на JS/ReactJS, и оно обращается к другому на PHP). И цифры пугающие - 10 запросов к API на страницу.

Подумайте сами, все это можно было сделать на PHP:

- шаблонизаторы - есть, например, twig, они лучше чем React
- API - есть, вызываешь нужные функции напрямую вместо использования REST API и затрат на HTTP. Внутреннее API в 100 раз лучше чем REST.

Что интересно, в фронтенде у них используется еще и Angular.

Такое ощущение, что там просто набралась критическая масса яваскриптщиков, которые не хотят писать на PHP. Или может они тайно грезят о замене бекенда на PHP на что-нибудь другое, кто знает.
311 1180976
>>180921
>>180922
Почитал западных профи, в общем нечего с апачем делать без опыта серверника.
312 1180977
>>180952
Согласен, в Symfony например есть мощный компонент форм, позволяющий избегать дублирования кода на фронте и бекенде, ну и в целом только бекенд писать проще, чем бекенд + фронтенд. Но что делать если нужна интерактивность, например в задаче тестхаб было бы гораздо удобнее, если бы создание/редактирование теста было на одной странице, так же как и прохождение тестов (мне нравится как сделали на Duolingo, Lingualeo - там всё без перезагрузки). C jQuery начинается дикая каша, я пробовал, и цена внедрения функционала растёт с каждым новым изменением. А вот SPA на реакте подошло хорошо и существенно облегчило разработку там, где нам была нужна интерактивность.
313 1180978
>>180952
но на реакте моднее и реактивнее
314 1180979
>>180977
зато на жс страницу перезагружать не нужно. чем больше логики переносится на жс, тем меньше ее остается для пхп. скоро пхп будут использовать только для запросов к базе.
315 1180980
>>180977

Так у них реакт на сервере, как я понял. То есть там сервис на ноде рендерит страницы через реакт, а данные запрашивает с PHP-бекенда. Может в расчете перейти на какой-нибудь Го или Ноду и на бекенде.

Так-то я не спорю, что в SPA это пригодится.

В задаче на тестхаб, по моим ощущениям, хватило бы и jQuer, но если хочется, можно и реакт/ангулар использовать. Для прохождения теста, не думаю, что что-то сложное нужно, там же всего лишь выбрать опцию или ввести текст вопроса.
316 1180981
>>180979

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

Реакт - для интерактивных приложений скорее.
317 1181006
>>180981
аяксом эти запросы к апи быстро делаются. а пока данные не получены можно поставить заставку. в итоге получается удобный и красивый фронт. да и проще один раз запрос к апи сделать, получить все данные и обрабатывать их на клиенте, чем перегружать страницу и делать запросы к базе каждый раз.
318 1181019
>>181006
Господа, аяк и xhr это одно и то же по сути?
319 1181030
>>181006

Ты можешь написать сколь угодно крутой фронтенд, но загрузить HTML с данными всегда быстрее чем загрузить HTML + мегабайт яваскрипта + сделать запрос к API. А если ты используешь REST, то тебе скорее придется делать несколько запросов.

А если произойдет хоть одна ошибка в JS коде, будет просто белая страница. В отличие от классического HTML. Плюс, такой сайт будет наверно плохо индексироваться гуглом, так как ему не понравится, что надо запускать полноценный браузер и ждать пока там все загрузится. Статический HTML парсить быстрее.

Зачем мне смотреть на заставку если я могу смотреть сразу на нужные мне данные? Да, это скорее подходит к эпохе из 2000, но почему меня это должно беспокоить.

Если у тебя тяжелый сайт с кучей рекламы и тебя беспокоит перезагрузка страницы, то можно использовать pjax. Он загружает классическую HTML страницу аяксом и обновляет DOM. Не нужен реакт, не нужно делать REST API. Не нужна перезагрузка страницы. не нужно ничего дорабатывать на сервере. Как тебе?
320 1181061
Чет не догоняю как работает __clone и что мне нужно, что бы скажем склонировать организацию, в которой лежит куча департаментов с кучей сотрудников внутри.

Допустим есть объект внутри которого лежит другой объект - https://ideone.com/QgS6gL
Но что делать если у меня там массив департмаментов, и в каждом департаменте еще и массив рабочих. Просто массив непоклонируешь особо, там ошибка.
321 1181064
>>181061
$this->inside = clone $this->inside;
Вот эта строчка немного голову ломает если честно :(
322 1181066
>>181030

>А если произойдет хоть одна ошибка в JS коде, будет просто белая страница


Что ты несешь.
323 1181079
>>181061

Массив не объект и "клонируется" при копировании:

$a = [];
$b = $a; // независимая копия массива

При этом содержимое массива - объекты - не клонируются. Это надо сделать руками. Ты должен создать новый массив, заполнить его клонами, поместить в поле объекта.

Для понимая, представь что в переменной хранится не объект, а его порядковый номер:

$a = new X; // создаем объект #1 и кладем в $a
$b = $a; // копируем номер #1 в $b

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

То же самое при копировании массива с объектами:

$a = [new X, new X, new X];
// можно представить как $a = [#1, #2, #3];

$b = $a; // создается копия массива, но в ней лежат указатели на те же объекты #1, #2, #3

> как работает __clone



PHP создает неглубокую копию объекта и вызывает на копии метод __clone, который может что-то сделать. В примере кода с $inside:

$clone = clone $base;

Это создает "неглубокий" клон $base, когда поля (включая inside) не клонируются, а копируются обычным образом. И в $clone->inside лежит указатель на тот же объект что и в $base. затем PHP вызывает магический метод __clone, который берет объект из $inside, создает его клон и помещает указатель на него назад в этом поле.
323 1181079
>>181061

Массив не объект и "клонируется" при копировании:

$a = [];
$b = $a; // независимая копия массива

При этом содержимое массива - объекты - не клонируются. Это надо сделать руками. Ты должен создать новый массив, заполнить его клонами, поместить в поле объекта.

Для понимая, представь что в переменной хранится не объект, а его порядковый номер:

$a = new X; // создаем объект #1 и кладем в $a
$b = $a; // копируем номер #1 в $b

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

То же самое при копировании массива с объектами:

$a = [new X, new X, new X];
// можно представить как $a = [#1, #2, #3];

$b = $a; // создается копия массива, но в ней лежат указатели на те же объекты #1, #2, #3

> как работает __clone



PHP создает неглубокую копию объекта и вызывает на копии метод __clone, который может что-то сделать. В примере кода с $inside:

$clone = clone $base;

Это создает "неглубокий" клон $base, когда поля (включая inside) не клонируются, а копируются обычным образом. И в $clone->inside лежит указатель на тот же объект что и в $base. затем PHP вызывает магический метод __clone, который берет объект из $inside, создает его клон и помещает указатель на него назад в этом поле.
324 1181081
>>181066

Расскажи нам, что будет при ошибке в JS коде в SPA? По моему так и останется страница с прелоадером. Или например если код написан с использованием ES6, а браузер его не поддерживает - что будет?
325 1181082
Перекатился в жс и фронтенд, платят норм, востребованно, ваш похапе не нужен.
изображение.png5 Кб, 506x191
326 1181087
>>181079
Осилил уже с помощью стаковерфлоу вот так вот сделать.
Еще был вариант там с помощью array_map это делать, но чет нахрапом не смог осилить принцип и быстро еще к себе адаптировать.
327 1181088
>>181082
Рассказал бы стори хоть, что на пхп делал и сколько платили, как докатился до фронтэнда и что теперь там делаешь и что там платят собственно.
328 1181089
>>181082

Так не нужен, что ты не поленился найти наш тред и сказать об этом? Ничего, проходи, устраивайся поудобнее.
329 1181109
Как тестируется верстка? Руками? Или все таки можна как то автоматизировать? Вообщем, есть одна страничка с динамическим контентом. Как можно проверить, что ее не распидорасит, если там будет много текста или картинки большие, видео и т. д.?
330 1181127
>>181109

>После нее можно изучать автоматизированное тестирование https://gist.github.com/codedokode/a455bde7d0748c0a351a

331 1181169
>>181088
да просто маньки пхпшники не нужны уже на фоне такого обилия всяких цмс. манек пхпшников это настолько рассатривает, что они даже делают бложики из велосиедов на всяких уии и зендах вместо того, чтобы взять готовую цмс.
А вот js на острие хайповых технологий щас, все больше логики переносится на жс, приложение начинают различаться лишь интерфейсом тк в плане функциональности все давно изобретено и переизобретено под типовые нужды.
собсно меня всегда и брали пилить фронтенд там, где на бэке пхп (вордпресс или уии), потому что я в довесок знаю похапе.
и вот я пришел сказать, как человек, который в рановй степени учил и пхп и жс, что жс гораздо более востребован и оплачивается.
332 1181233
Аноны, спасибо за картинку с роутингом.
Такой тупой вопросец. Зачем использовать {скобки} при вписывании переменной в строку вида --- echo "Привет аноны я, {$username}";
334 1181292
>>181169
Куда устроился в итоге и сколько платят? И что за город?
335 1181304
>>181169
Ну я изчую пхп. Но я не нацелен на гавно цмс, разве когда я изучу симфони, мне с такими знаниями придется клепать хрень на цмс? Я думал там, интереснее есть задачи для бэкэнда.
336 1181307
Интересные задачи начинаются когда тебе уже всё равно на чём писать.
337 1181329
>>181109

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

Также можно проверить, что если скрыть какой-то блок (сайдбар например), страница не разваливается.

Не забудь тестировать страницу на разной ширине окна браузера, чтобы проверить адаптивность.

Также, ты можешь использовать вставку php-кода в HTML, чтобы скрипт генерировал контент по заданным параметрам.

У меня был скрипт, чтобы в верстке добавлять пункты меню и удлинять тексты, но я не помню, где он.
338 1181338
>>181304
нахуй не нужны фреймворки, все можно сделать на цмс в пхп.
а на фреймворках любят костылять байтоебы-велосипедчики, в итоге костыляют ту же цмс только долго и плохо
339 1181347
>>181109
Может будет полезно
https://habr.com/company/2gis/blog/246831/
340 1181356
>>180063
опен сервер поставь и забей на сервер и разбирание в том, что такое апач, хуяч.

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

Мимо по своему опыту
341 1181357
>>180081

>семафор


шо это ха хуйня, чем знаменита?
342 1181358
>>180141
внезапно были годные уроки от webformyself
там вся кухня блядь была, давно смотрел, но помню ахуел от того как дохуя можно рассказать по теме
343 1181359
>>180165
тож устроился джуном на пхп. С сайтами вообще почти не работаю.
Пишу ботов, хуйотов, парсеры, спамеры лол и много всякой подобной хуйни, работа с сайтом часто заключается в том, чтобы я просто набросал какой нибудь интерфейс чтобы кликать можно было и управлять настройками бота
344 1181361
>>180478
Тебе без ЧПУ?
Хуле там учить тогда? Принимаешь ?page=hyi, на странице пишешь include $_GET['page'].'.php'; сверху/снизу шапка/футер. Обмазывание свистоперделками - дело индивидуальное
345 1181362
>>181307
подрбней?
346 1181364
>>181304
Откуда это распространённое мнение, что работа на симфони как-то сильно отличается от остальной работы на PHP? Плохой код пишут везде, я по работе сталкиваюсь с проектами на Laravel/Symfony/Yii и скажу, что всё зависит не от фреймворка, а от разработчиков.

>>181019
Да. https://learn.javascript.ru/ajax

>>181030

> мегабайт яваскрипта


Есть tree shaking, мы будем заморачиваться с этим: https://medium.com/netscape/webpack-3-react-production-build-tips-d20507dba99a

> + сделать запрос к API.


Ну нет же, при первой загрузке страницы данные из бекенда передаются куда-нибудь в window.INITIAL_STATE и уже оттуда подхватываются фреймворком, без дополнительного запроса. Про "несколько запросов" тоже не понял, ничего мне не мешает передавать сразу дерево объектов на фронт.

> Плюс, такой сайт будет наверно плохо индексироваться гуглом,


Ну не всегда нужна индексация, может быть продукт закрытый для определённого круга лиц. И уже 2018-й на дворе, тут пишут, что гугл индексирует SPA: https://medium.com/@l.mugnaini/spa-and-seo-is-googlebot-able-to-render-a-single-page-application-1f74e706ab11

> Не нужен реакт, не нужно делать REST API


А потом бизнес скажет, что нужно API для мобилок (было 2 раза). И дешевле было сразу делать API. И на страницах всё больше логики и jQuery лапша становится всё запутаннее, а пилить свой очередной MVC велосипед не хочется, нужно чтобы новые разработчики быстро вникали в проект.
347 1181424
>>180471
Проверьте решение - кредит на айпад.
https://ideone.com/HW6Jad

И еще: объясните что происходит с переменной $payed после того, как я ее "вернул" максимально простым языком, пожалуйста.
348 1181472
Анончики, стоит ли перекатываться на линукс для разработки?
Есть ли в этом профиты?
Под чем работаете вы?

В принципе пердолинг меня увлекает и я не против, если есть плюсы
349 1181496
>>181424

> объясните что происходит с переменной $payed после того, как я ее "вернул" максимально простым языком, пожалуйста.



Когда ты выходишь из функции, ты можешь "вернуть" какое-то значение (не переменную! локальные переменные уничтожаются после выхода из функции) с помощью return, например:

return 100;
return "Yes";
return [1, 2, 3];
$x = 1;
return $x;

Важно помнить, что ты возвращаешь не переменную, а берешь ее значение и возвращаешь его. Переменные не возвращаются и не передаются - передаются только значения - числа, строки, массивы. Переменная - это просто хранилище для значения. Надо различать эти 2 понятия.

Значение, которое было указано в return, будет возвращено в место вызова функции. То есть, если ты пишешь

echo x();

И функция x() возвращает 10, то получится echo 10 и это число выведется на экран. Или, если ты напишешь

$y = x();

То результат, который вернет x(), скопируется в переменную $y.

Можно использовать функции и в более сложных выражениях, например:

$a = x() + y() + z();

Здесь происходит вызов 3 функций, их результаты складываются и сохраняются в переменную $a. Или так:

echo x(y());

Здесь вызывается функция y(), ее результат запоминается, затем вызывается функция x(), при этом ей передается результат функции y(), и то, что вернет x(), выводится на экран.

Если в функции нет return, то она возвращает значение по умолчанию - null. Если ты никуда не сохраняешь результат вызова функции, он отбрасывается, например:

w();

Здесь результат вызова функции никак не используется и отбрасывается.

По решению:

Код надо правильно выравнивать. Смотри второй пост треда. Ты можешь либо с самого начала ставить отступы правильно, либо использовать сайт для форматирования, либо писать код в IDE, где есть функция выравнивания кода. В твоем коде отступы нарушены и тяжело понять, где начинается и заканчивается тот же if.

> $credit = 39999;


> $payPerMonth = 5000;



Это можно было сделать аргументами функции, чтобы можно она была универсальнее и можно было делать расчет кредита с любыми параметрами. Это не ошибка, просто так было бы чуть лучше.

if можно было бы заменить на функцию min/max:

выплата = меньшее из (стандартная выплата, остаток кредита);

Расчет программа делает правильно.
349 1181496
>>181424

> объясните что происходит с переменной $payed после того, как я ее "вернул" максимально простым языком, пожалуйста.



Когда ты выходишь из функции, ты можешь "вернуть" какое-то значение (не переменную! локальные переменные уничтожаются после выхода из функции) с помощью return, например:

return 100;
return "Yes";
return [1, 2, 3];
$x = 1;
return $x;

Важно помнить, что ты возвращаешь не переменную, а берешь ее значение и возвращаешь его. Переменные не возвращаются и не передаются - передаются только значения - числа, строки, массивы. Переменная - это просто хранилище для значения. Надо различать эти 2 понятия.

Значение, которое было указано в return, будет возвращено в место вызова функции. То есть, если ты пишешь

echo x();

И функция x() возвращает 10, то получится echo 10 и это число выведется на экран. Или, если ты напишешь

$y = x();

То результат, который вернет x(), скопируется в переменную $y.

Можно использовать функции и в более сложных выражениях, например:

$a = x() + y() + z();

Здесь происходит вызов 3 функций, их результаты складываются и сохраняются в переменную $a. Или так:

echo x(y());

Здесь вызывается функция y(), ее результат запоминается, затем вызывается функция x(), при этом ей передается результат функции y(), и то, что вернет x(), выводится на экран.

Если в функции нет return, то она возвращает значение по умолчанию - null. Если ты никуда не сохраняешь результат вызова функции, он отбрасывается, например:

w();

Здесь результат вызова функции никак не используется и отбрасывается.

По решению:

Код надо правильно выравнивать. Смотри второй пост треда. Ты можешь либо с самого начала ставить отступы правильно, либо использовать сайт для форматирования, либо писать код в IDE, где есть функция выравнивания кода. В твоем коде отступы нарушены и тяжело понять, где начинается и заканчивается тот же if.

> $credit = 39999;


> $payPerMonth = 5000;



Это можно было сделать аргументами функции, чтобы можно она была универсальнее и можно было делать расчет кредита с любыми параметрами. Это не ошибка, просто так было бы чуть лучше.

if можно было бы заменить на функцию min/max:

выплата = меньшее из (стандартная выплата, остаток кредита);

Расчет программа делает правильно.
350 1181498
>>181364

> Есть tree shaking, мы будем заморачиваться с этим:



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

> Ну нет же, при первой загрузке страницы данные из бекенда передаются куда-нибудь в window.INITIAL_STATE и уже оттуда подхватываются фреймворком, без дополнительного запроса. Про "несколько запросов" тоже не понял, ничего мне не мешает передавать сразу дерево объектов на фронт.



Ну так с таким же успехом можно передавать уже отрендеренный HTML. Я напомню, что речь в статье о сайте с вакансиями.

> Про "несколько запросов" тоже не понял,


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

> Ну не всегда нужна индексация, может быть продукт закрытый для определённого круга лиц


Сайт с вакансиями.

> гугл индексирует SPA


Это требует больше процессорного времени в сравнении со статическим сайтом. Бюджет времени на 1 сайт может быть ограничен. Значит, Гугл будет индексировать меньше страниц или делать это медленее. Плюс, увеличивается вероятность каких-то ошибок. Из-за ошибки JS загрузится белая страница - ухудшение рейтинга. Напомню, что на сервере можно отдать код 5xx и робот повторит попытку позже.

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

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

> А потом бизнес скажет, что нужно API для мобилок (было 2 раза).


И для мобильного приложения нужен ровно такой де API, как для сайта (нет). В любом случае, добавить только REST API гораздо быстрее чем заморачиваться со всем, что ты описал.

> а пилить свой очередной MVC велосипед не хочется, нужно чтобы новые разработчики быстро вникали в проект.



А он и не нужен для показа вакансий.
350 1181498
>>181364

> Есть tree shaking, мы будем заморачиваться с этим:



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

> Ну нет же, при первой загрузке страницы данные из бекенда передаются куда-нибудь в window.INITIAL_STATE и уже оттуда подхватываются фреймворком, без дополнительного запроса. Про "несколько запросов" тоже не понял, ничего мне не мешает передавать сразу дерево объектов на фронт.



Ну так с таким же успехом можно передавать уже отрендеренный HTML. Я напомню, что речь в статье о сайте с вакансиями.

> Про "несколько запросов" тоже не понял,


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

> Ну не всегда нужна индексация, может быть продукт закрытый для определённого круга лиц


Сайт с вакансиями.

> гугл индексирует SPA


Это требует больше процессорного времени в сравнении со статическим сайтом. Бюджет времени на 1 сайт может быть ограничен. Значит, Гугл будет индексировать меньше страниц или делать это медленее. Плюс, увеличивается вероятность каких-то ошибок. Из-за ошибки JS загрузится белая страница - ухудшение рейтинга. Напомню, что на сервере можно отдать код 5xx и робот повторит попытку позже.

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

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

> А потом бизнес скажет, что нужно API для мобилок (было 2 раза).


И для мобильного приложения нужен ровно такой де API, как для сайта (нет). В любом случае, добавить только REST API гораздо быстрее чем заморачиваться со всем, что ты описал.

> а пилить свой очередной MVC велосипед не хочется, нужно чтобы новые разработчики быстро вникали в проект.



А он и не нужен для показа вакансий.
351 1181499
>>181361

> include $_GET['page'].'.php';



Не делай так. Это уязвимость, позволяющая запустить любой php-файл на сервере. Значение из page надо проверять по белому списку разрешенных значений.

>>180081

Читаем https://ru.wikipedia.org/wiki/Семафор_(информатика)

Затем гуглим http://php.net/manual/ru/book.sem.php и пишем код на нем. В задаче не сказано, что нельзя его использовать.

Допустим, это не прокатило. Тогда нам нужны 2 вещи:

- где-то нам нужно хранить счетчик, доступный из всех потоков (или скорее процессов). Если речь именно о потоках, то хватит переменной, если о процессах, то нужен файл или примитив ОС (разделяемая память итд)
- для реализации enter()/leave() нам нужен примитив для атомарного изменения счетчика, а также для ожидания, пока счетчик не станет более 0

Так как в задаче про это не написано, просто представим, что такие функции уже есть (atomic_inc(), atomic_dec(), wait()). Если и это не прокатывает, то есть 2 варианта:

- если речь о потоках, то храним счетчик в переменной, а wait() делаем на основе sleep(). Минус - я не уверен, что увеличение переменной атомарно даже через $x++ - есть шанс, что эта операция реализована не атомарно (и кстати, ты понимаешь, что значит "атомарно"). Это сомнительный вариант
- иначе, реализуем их на основе файла, в котором мы храним число и который блокируем на время операции увеличения/уменьшения, чтобы реализовать атомарность:

- http://php.net/manual/en/function.flock.php

Напишешь, или нужна еще помощь? Если напишешь, давай код, я придумаю, как можно протестировать, что он реально работает. Ну или придумай сам.

>>181357

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

Почитай вики https://ru.wikipedia.org/wiki/Семафор_(информатика)

>>181356

Не надо так. Лучше уж встроенный в PHP сервер.
351 1181499
>>181361

> include $_GET['page'].'.php';



Не делай так. Это уязвимость, позволяющая запустить любой php-файл на сервере. Значение из page надо проверять по белому списку разрешенных значений.

>>180081

Читаем https://ru.wikipedia.org/wiki/Семафор_(информатика)

Затем гуглим http://php.net/manual/ru/book.sem.php и пишем код на нем. В задаче не сказано, что нельзя его использовать.

Допустим, это не прокатило. Тогда нам нужны 2 вещи:

- где-то нам нужно хранить счетчик, доступный из всех потоков (или скорее процессов). Если речь именно о потоках, то хватит переменной, если о процессах, то нужен файл или примитив ОС (разделяемая память итд)
- для реализации enter()/leave() нам нужен примитив для атомарного изменения счетчика, а также для ожидания, пока счетчик не станет более 0

Так как в задаче про это не написано, просто представим, что такие функции уже есть (atomic_inc(), atomic_dec(), wait()). Если и это не прокатывает, то есть 2 варианта:

- если речь о потоках, то храним счетчик в переменной, а wait() делаем на основе sleep(). Минус - я не уверен, что увеличение переменной атомарно даже через $x++ - есть шанс, что эта операция реализована не атомарно (и кстати, ты понимаешь, что значит "атомарно"). Это сомнительный вариант
- иначе, реализуем их на основе файла, в котором мы храним число и который блокируем на время операции увеличения/уменьшения, чтобы реализовать атомарность:

- http://php.net/manual/en/function.flock.php

Напишешь, или нужна еще помощь? Если напишешь, давай код, я придумаю, как можно протестировать, что он реально работает. Ну или придумай сам.

>>181357

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

Почитай вики https://ru.wikipedia.org/wiki/Семафор_(информатика)

>>181356

Не надо так. Лучше уж встроенный в PHP сервер.
352 1181500

>>181338



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

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

>>181169

Сайты вакансий подтверждают твою мысль?

>>180921

Писать кастомные модули, дорабатывать их, писать шаблоны ты не сможешь. Только использовать стандартные.

>>180670

> echo $a = implode(" ", $word[array_rand($word)]);


Здесь не очень понятно, зачем использовать $a = ... если можно писать сразу echo implode(...).

implode склеивает значения из массива в строку. Но $word[array_rand($word)] - это не массив, а строка (одно слово), и склеивать в ней ничего не требуется. implode лишний.

>>180685

тут все верно
353 1181501
>>176196
>>180564
>>178891

Давай начнем с нормализованного подхода, а потом прикинем, что с нормализацией. Не очень понятно, что имеется в виду по "событиями"? Один из стандартных текстов, который рассылается массе людей? Или произвольный, индивидуальный для каждого текст (Вася поделился 5 фото и получил 3 лайка)?

Допустим, произвольный текст. Тогда получается как-то так:

userId | eventType | time | isRead | text

Тут конечно все выходит немного печально, текст может быть большой, и таблица потому тяжелая. Допустим, текст весит 200 байт (100 русских букв), инты весят 8 байт в x64, получается примерно 230 байт на строку, и всего 20000 польз. x 1000 событий x 230 = 4.6Gb - это только данные. Индексы, впрочем, будут меньше из-за того, что в них не включен текст. MySQL конечно может работать с такой таблицей, но тяжеловато и надо очень тщательно писать запросы. И она ведь расти будет. В такой ситуации можно посоветовать выделить на сервер MySQL заведомо больше памяти, чем весит эта таблица.

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

Теперь рассмотрим более простые варианты. Допустим, "событие" одинаково для всех пользователей. Ну например, опубликована новая интересная статья на сайте. Это намного проще. Делаем так:

events: id | time | text
notifications: userId | eventId | isRead

Здесь все не так печально. В таблице notifications строчка весит 8 + 8 + 1 = 17 байт, 17 x 20M = 340M, терпимо. Минус - time у нас в events, и нельзя выбрать записи из notifications отсортированными. Потому придется перенести time туда для оптимизации (индекс по (userId, time) для выборки N последних событий).

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

Наконец, предположим, что нам не нужны прочтенные уведомления. Тогда еще проще - вместо поля isRead можно просто удалять записи. Хотя, тут надо мерять, может выгоднее удалять их отложенно, по крону.

Если события рассылаются всем, то можно еще рассмотреть вариант хранить не список непрочтенных нотификаций, а наоборот, прочтенных.

Наконец, поговорим про "ленты". На некоторых сайтах ты можешь "подписываться" на сущности (например, группы) и получать персонализированные новости из них.

Реализация такой системы "в лоб" непроста. Ну допустим, мы сделаем так:

subscriptions: userId | groupId - кто на что подписан

И при выводе ленты делаем примерно так:

SELECT FROM posts p JOIN subscriptions s ON ... WHERE s.userId = ? ORDER BY p.time DESC;

Это конечно ни в какие индексы не ляжет и уронит твою БД. Потому, можно попробовать другой вариант:

subscriptions: userId | groupId
news: userId | postId | time | isRead - time для оптимизации

При добавлении нового поста в группу ищем, кто на нее подписан, и кидаем им в news ссылку на пост. Если подписчиков много, вставка поста начнет тормозить, и придется делать ее отложенно через крон или gearman. Можно также использовать комбинированный подход - смотреть, сколько подписичков, если мало, вставлять напрямую, если много - отложенно.

Можно еще чуть оптимизировать таблицу news, если убрать поле isRead и для пользователя просто хранить дату последнего открытия ленты новостей.

Тут небольшой минус - в постоянно растущей таблице news. В ней 3 поля по 8 байт + isRead, и на большом числе пользователей и новостей она опять же будет расти. Значит, надо либо ограничить длину ленты, либо срок хранения, либо архивировать старые записи в ней.

Ну и еще небольшая оптимизация: если у пользователя мало подписок (3-5), то таким пользователям можно не использовать таблицу news, а запрашивать новые посты несколькими SELECT. Хотя это может усложнить код.

В любом случае, я советую:

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

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



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

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


Если ему надо обойти 5 строк по индексу - нет. Если сотни - то на большой нагрузке. Если десятки тысяч - то всегда.

> Ситуация осложняется тем, что у событий есть права доступа (по нескольким параметрам: регион/представительство/отдел), поэтому запрос на выборку событий будет ещё медленнее.



Это плохо. Для быстрой выборки запрос должен использовать индекс.

> Добавлять во второй столбец значение при прочтении уведомлений.



Это называется денормализация, но тут есть подвох. У тебя уведомления зависят от региона - значит при смене региона ты должен как-то пересчитать эту цифру.
353 1181501
>>176196
>>180564
>>178891

Давай начнем с нормализованного подхода, а потом прикинем, что с нормализацией. Не очень понятно, что имеется в виду по "событиями"? Один из стандартных текстов, который рассылается массе людей? Или произвольный, индивидуальный для каждого текст (Вася поделился 5 фото и получил 3 лайка)?

Допустим, произвольный текст. Тогда получается как-то так:

userId | eventType | time | isRead | text

Тут конечно все выходит немного печально, текст может быть большой, и таблица потому тяжелая. Допустим, текст весит 200 байт (100 русских букв), инты весят 8 байт в x64, получается примерно 230 байт на строку, и всего 20000 польз. x 1000 событий x 230 = 4.6Gb - это только данные. Индексы, впрочем, будут меньше из-за того, что в них не включен текст. MySQL конечно может работать с такой таблицей, но тяжеловато и надо очень тщательно писать запросы. И она ведь расти будет. В такой ситуации можно посоветовать выделить на сервер MySQL заведомо больше памяти, чем весит эта таблица.

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

Теперь рассмотрим более простые варианты. Допустим, "событие" одинаково для всех пользователей. Ну например, опубликована новая интересная статья на сайте. Это намного проще. Делаем так:

events: id | time | text
notifications: userId | eventId | isRead

Здесь все не так печально. В таблице notifications строчка весит 8 + 8 + 1 = 17 байт, 17 x 20M = 340M, терпимо. Минус - time у нас в events, и нельзя выбрать записи из notifications отсортированными. Потому придется перенести time туда для оптимизации (индекс по (userId, time) для выборки N последних событий).

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

Наконец, предположим, что нам не нужны прочтенные уведомления. Тогда еще проще - вместо поля isRead можно просто удалять записи. Хотя, тут надо мерять, может выгоднее удалять их отложенно, по крону.

Если события рассылаются всем, то можно еще рассмотреть вариант хранить не список непрочтенных нотификаций, а наоборот, прочтенных.

Наконец, поговорим про "ленты". На некоторых сайтах ты можешь "подписываться" на сущности (например, группы) и получать персонализированные новости из них.

Реализация такой системы "в лоб" непроста. Ну допустим, мы сделаем так:

subscriptions: userId | groupId - кто на что подписан

И при выводе ленты делаем примерно так:

SELECT FROM posts p JOIN subscriptions s ON ... WHERE s.userId = ? ORDER BY p.time DESC;

Это конечно ни в какие индексы не ляжет и уронит твою БД. Потому, можно попробовать другой вариант:

subscriptions: userId | groupId
news: userId | postId | time | isRead - time для оптимизации

При добавлении нового поста в группу ищем, кто на нее подписан, и кидаем им в news ссылку на пост. Если подписчиков много, вставка поста начнет тормозить, и придется делать ее отложенно через крон или gearman. Можно также использовать комбинированный подход - смотреть, сколько подписичков, если мало, вставлять напрямую, если много - отложенно.

Можно еще чуть оптимизировать таблицу news, если убрать поле isRead и для пользователя просто хранить дату последнего открытия ленты новостей.

Тут небольшой минус - в постоянно растущей таблице news. В ней 3 поля по 8 байт + isRead, и на большом числе пользователей и новостей она опять же будет расти. Значит, надо либо ограничить длину ленты, либо срок хранения, либо архивировать старые записи в ней.

Ну и еще небольшая оптимизация: если у пользователя мало подписок (3-5), то таким пользователям можно не использовать таблицу news, а запрашивать новые посты несколькими SELECT. Хотя это может усложнить код.

В любом случае, я советую:

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

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



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

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


Если ему надо обойти 5 строк по индексу - нет. Если сотни - то на большой нагрузке. Если десятки тысяч - то всегда.

> Ситуация осложняется тем, что у событий есть права доступа (по нескольким параметрам: регион/представительство/отдел), поэтому запрос на выборку событий будет ещё медленнее.



Это плохо. Для быстрой выборки запрос должен использовать индекс.

> Добавлять во второй столбец значение при прочтении уведомлений.



Это называется денормализация, но тут есть подвох. У тебя уведомления зависят от региона - значит при смене региона ты должен как-то пересчитать эту цифру.
354 1181513
>>181501
Спасибо, я как раз разбираюсь с фейкером, буду пробовать как лучше в моем случае.

Ещё придумал хранить где-то в сессии количество уведомлений и изначально в счетчике непрочитанных вверху отображать данные из сессии. А уже потом, когда страничка обновится - отправлять аякс запрос на обновление счетчика и данных в сессии.
355 1181566
>>181513

И в чем смысл? Что мешает получить число сразу?
356 1181594
>>181513
Тут где то пропал мой пост. Напишу что помню. Вообщем я померял для:
user_table
user_id, name
(20000 rows)

message_table
message_id, text(varcahr(128)), add_time
(5e6+ rows)

user_message_map
user_id(index), message_id, is_read, read_time
(5e6+ rows)

1 ядро (i5 6500) 1 Gb

Мускуль держит:
4000-6000 вставок в секунду. Мессага всем пользователям вставляется 3.7 секунды.
1300 выборок в секунду для count() непрочитанных.
Это для сообщений к юзерам 1<->1.

Для такой базы я бы не давал основным таблицам расти дальше 5е6 записей (дальше производительность резво начинает падать) и не больше 100-150 записей на одного пользователя (иначе нужно мутить хитрую пагинацию внутри БД).

А еще вспомнил. Выбор 1000 непрочитанных при 2e7 записей в БД. 0.5-0.6 секунды.
357 1181647
>>181594

> 4000-6000 вставок в секунду.



Под нагрузкой эта цифра просядет. Плюс, число пользователей будет только расти в дальнейшем. Но если вставку делать из крона по ночам, то ок.

> Для такой базы я бы не давал основным таблицам расти дальше 5е6 записей (дальше производительность резво начинает падать) и



А в посте упоминалось 20К пользователей и 1000 событий. Тесты надо было делать на соотв. объемах.

> Выбор 1000 непрочитанных



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

> user_id(index), message_id, is_read, read_time


Если ты выбираешь с сортировкой по времени, то индекс надо было делать по (user_id, time)
image.png936 Кб, 894x921
358 1181764
Я так понял нет смысла кидать сюда задания.
Кстати есть вопрос. Можно ли в пыхе через echo выводить сразу результат деления/умножения/вычитания/etc, а не создавать отдельную переменную, записывать туда результат вычисления и потом только вставлять её в echo ?
359 1181771
>>181764

>Я так понял нет смысла кидать сюда задания.


Решенные из учебника ОПа? Есть конечно. Просто у нас тут может быть большой пинг на проверки (иногда и 3 недели для больших задач).
Тут со всем помогут. Если ты конечно не притащишь откровенный фриланс или криминал.

>Можно ли в пыхе через echo выводить ...


Да. Там вообще можно отрываться по полной:

echo '$' . ($x = function($a) {return $a;})(1) (10 * 6) . PHP_EOL;
//1000000
Screenshot.png21 Кб, 634x180
360 1181775
>>181771
Вот задача

Я просто не совсем понял задачи ОПа. Он указал, что Школьник не может заплатить в месяц больше, чем 5000 рублей. Т.е. школьник чисто гипотетически может может отдать в месяц и 4000 рублей? Иными словами ОП, я так понял, не указал конкретное сумму сколько школьник отдает в банк. Я делал задачу так, что школьник отдает в банк каждый месяц 5000 рублей.

результат все равно не совпадает

Ссыль на код: https://ideone.com/47k5fR

Задача: http://phpbooktest.ga/l1/loops.html
361 1181778
>>181472
Стоит. Сам долго ругался и пытался в итоге остался на кубунте - годнота, удобно и приятно
362 1181782
>>181775

>https://ideone.com/47k5fR


Ты переусложнил расчет баланса кредита. Как результат у тебя сначала школьник платит 5000, а потом считается новый баланс. Евросеть конечно, себя так обижать не станет и начислит проценты в 00:00, а деньги примет не раньше 9:00.

В последний месяц, когда баланс кредита меньше 5000 у тебя все равно платит всю сумму, это нужно проверять.
363 1181811
>>181778
А можешь, пожалуйста, рассказать какие преимущества дает такой переход
364 1181813
>>181811
Как перекатиться на убунту если на винде у тебя пубг и прочая стимохуйня? Перекатиться на месяцок что бы отработать консольку и прочее, а потом как возьмут на работу снова установить себе дома лпмповый опен сервер?
sage 365 1181816
>>181813
дуалбут
366 1181826
Аноны, подскажите пожалуйста, поставил сокс для телеграма на убунту https://github.com/Lozy/danted
Как еще полностью выключить логи на сервере?
367 1181846
>>181826

В файле https://github.com/Lozy/danted/blob/master/install_debian.sh

(или install_centos.sh в зависимости от ОС) находим строчку

> logoutput: /var/log/sockd.log



И меняем ее на

logoutput: /dev/null

После установки проверяем файл /etc/danted/sockd.conf и убеждаемся, что там прописан /dev/null.

Это отключает логи сокс-демона.
368 1181850
>>181846
Спасибо. Попробую.
369 1181858
>>181826
Не слушай этого >>181846 пиздуй в /s/
Для того чтобы отключить логи, нужно не logoutput: /dev/null вписывать в конфиг, а удалить эту строчку из конфига.
Внезапно, да?
370 1181871
>>181858
О, как хорошо, что я решил еще подождать ответов, да, ты логичнее.
371 1181880
Пачаны, пытаюсь сделать загрузку на сервер нескольких фоточек. Но что-то не получатся.

html:
<b>Фотография</b><input type='file' multiple name='image[]'>

php:

$uploaddir = 'resource/photos/';
for ($i=0; $i<count($_FILES['photo']['name']); $i++)
{
$uploadfile = $uploaddir . basename($_FILES['photo']['name'][$i]);
if (move_uploaded_file($_FILES['photo']['tmp_name'][$i], $uploadfile)) {
echo "Файл успешно загружен.\n";
} else {
echo "Ошибка!\n";
}
}

Раньше загружал только один файл и норм было. А так почему-то не работает
372 1181882
>>181880
Пачаны, нашел где объебался.
Все работает
373 1181934
>>181813
Дуалбут ставится поверх винды и норм.
Заодно рабочее и игровое пространство разграничиваешь.

Только ставь не убунту, лучше дебиан, иначе смысла нет, она как шиндовс, даже с консолькой работать толком не нужно
!.png16 Кб, 415x368
374 1181982
>>181813

>отработать консольку

375 1181989
>>181934

>даже с консолькой работать толком не нужно


Не нужно но можно, да и главное же не пердолинг ради пердоинга, а изучение среды работа с правами и прочее что нужно для работы разрабом на линуксе. Мне же нужно что бы я при устройстве на работу имел навык сесть за бубунту рабочую и не сосать хуй неделю пока разбираюсь с ней.
376 1182070
подписался на тред
someApprentice 377 1182086
>>180024
Обновил код https://github.com/richBlueElephant/phpClub/blob/master/public/media/js/script.js

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

Ответьте пожалуйста на пару вопросов выше >>180024 >>178355

Спасибо.
Я, да Я 378 1182092
Критично ли, что я в проверке палиндрома прохожусь по всей длине строки вместо длины\2? Так же в 2 раза больше итераций получается.

Вот код если что https://repl.it/@2chGray/Palindrom
ideone уёбки не отвечают на моё письмо с просьбой подключить mbstring библиотеку
379 1182120
>>181989
Всё же советую попробовать что-то другое. Далеко не факт что на работе будет убунта.
380 1182122
>>179898
Бамп
381 1182135
>>182092
А зачем тебе вся длина строки?

Давай порассуждаем. Допустим у тебя четное число символов в строке - тут всё просто и ты должен совершить 2 итерации цикла если у тебя 4 символоа, 3 если 6, 4 если 8 и так далее.
Простое деление на 2 работает для этого.

Далее допустим у тебя нечетная строка, средний символ в такой строке равен сам себе, поэтому в строке скажем из 5 символов тебе достаточно лишь сравнить первые два с последними двумя. Для строки в 5 символов нужно лишь 2 итерации, из 7 сиволов - 3 итерации, и так далее.

Значит тебе надо просто высчитывать длину строки, далее из длины строки с помощью целочисленого деления высчитывать то, сколько итераций тебе нужно для проверки на палиандром. Ща загуглил и в php 7 появилась такая штука как intdiv(); - то что нужно для тебя как раз.

Ну и в теле цикла сравнивать первый с последним, первый + 1 с последним -1 и так далее до окончания цикла.

А по поводу письма, ты же им на английском написал? Есть мнение, что сервис всё же забугорный, хоть для нас у них и русская морда.
382 1182144
>>182135

>ты же им на английском написал?


Да, письмо даже как прочитанное не отметилось.
383 1182336
Господа, почему когда я добавляю первый пик (с мануала bootstrap) у меня в перестают сабмитится формы, но когда добавляю 2 пик(из одного тутора с ютуба), то формы работают, но не работает dropdown menu. В первом случае меню отображается по клику как надо.
image.png34 Кб, 1194x126
384 1182337
>>182336
первый пик*
385 1182353
>>182336
Подключать бутстрап через cdn плохая практика. Вдруг какой нибудь ркн заблочит cdn или еще какая то неведомая хуйня произойдет. Файлы лучше иметь у себя на сервере.
sage 386 1182372
>>174695 (OP)
ОП, у тебя в уроке какая-то хрень.

>Также, при наследовании есть правило: класс-предок не должен ничего знать о своих наследниках. Он не имеет права обращаться к полям или методам, которые появляются только в наследниках и которых нет в нем самом. Это логично: ведь кто-то сделать еще одного наследника и не добавить туда эти поля.



В тексте про объекты.
http://phpbooktest.ga/l1/pasta.html

Сразу вопрос: как можно создать проверку на актуальность сохраненных кук?
387 1182377
>>182372

>Сразу вопрос: как можно создать проверку на актуальность сохраненных кук?


if (isset($_COOKIE["your cookie name"])) {
...
}
sage 388 1182378
>>182377
А если куки сохраняются в отдельном файле и не удаляются автоматически по истечению годности?
tumblrm6adw5blXV1r87tiqo11280.jpg343 Кб, 1217x1772
389 1182387
Вечерочка доброго!
А не подскажет ли кто-нибудь, где можно почитать описание такой вот не хитрой конструкции в статическом методе (его части, там несколько подобных конструкций следуют одна за другой):
if ( something true or false) { return; }
Этот метод вызывается через Paamayim Nekudotayim и в принципе понятно, что он делает, он возвращает вычисленное выражение от if всё дальше и дальше накапливая вычисления...Но описания такого подхода, что прос то return; и всё, я нигде не нашёл, подскажите, будьте любезны.
390 1182389
>>182372

Поясни пожалуйста, почему ты думаешь, что это хрень? Это один из принципов ООП.

Ну смотри:

class Parent
{
public function test()
{
echo $this->something; // обращение к полю, которого нет в классе
}
}

class Child extends Parent
{
public $something = "yes";
}

$child = new Child();
$child->test();

Этот код содержит проблему: мы можем написать $p = new Parent(); $p->test(); и это вызовет ошибку (обращение к несуществущему полю). Мы можем защититься от нее, написав перед class Parent слово abstract и тем самым запретив создавать объекты Parent. Но это все равно оставляет возможность для ошибки:

class OtherChild extends Parent {}
$o = new OtherChild();
$o->test(); // обращение к несуществующему полю

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

Я хочу, чтобы неправильный код было писать нельзя в принципе. И ООП это позволяет - при соблюдении определенных правил. Одно из которых приведено в уроке, про обращение только к доступным полям и методам. В языках со статической типизацией (Ява, C#) это правило проверяется при компиляции программы и компилятор выдаст ошибку. В PHP, увы, нет.

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

abstract class Parent
{
abstract public function getSomething(); // это должен реализовать наследник
public function test()
{
echo $this->getSomething();
}
}

class Child extends Parent
{
public function getSomething()
{
return "yes";
}
}

$child = new Child();
$child->test();

Этот код не получится использовать как-то неправильно.

ООП тем и хорош, что позволяет писать код, который в принципе нельзя использовать неправильно. Вот тебе еще пример:

1) ООП позволяет запретить присваивать неправильные значения. Допустим, мы делаем класс ЖурналОценок и в нем есть метод поставитьОценку. Очевидно, оценка ставится Ученику за Урок и может быть от 1 до 5. Мы можем написать такой метод:

class Register
{
public function addScore(Lesson $lesson, Student $student, int $score)
{
if ($score < 1 || $score > 5) {
throw new \InvaldiArgumentException("Score must be 1 to 5, $score given");
}
....
}
}

Как видишь, этот метод не позволяет поставить неправильную оценку.

Ты должен стараться писать код так, чтобы его нельзя было неправильно использовать. И ООП дает возможности для этого:

- закрытие внутренних полей и методов от доступа снаружи с помощью private/protected
- закрытие всех полей от доступа снаружи; разрешаем изменение значений только через методы
- проверка передаваемых значений
- указание в конструкторе всех значений, которые нужны для работы класса
- не полагаемся на то, что методы будут вызываться в определенном порядке
390 1182389
>>182372

Поясни пожалуйста, почему ты думаешь, что это хрень? Это один из принципов ООП.

Ну смотри:

class Parent
{
public function test()
{
echo $this->something; // обращение к полю, которого нет в классе
}
}

class Child extends Parent
{
public $something = "yes";
}

$child = new Child();
$child->test();

Этот код содержит проблему: мы можем написать $p = new Parent(); $p->test(); и это вызовет ошибку (обращение к несуществущему полю). Мы можем защититься от нее, написав перед class Parent слово abstract и тем самым запретив создавать объекты Parent. Но это все равно оставляет возможность для ошибки:

class OtherChild extends Parent {}
$o = new OtherChild();
$o->test(); // обращение к несуществующему полю

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

Я хочу, чтобы неправильный код было писать нельзя в принципе. И ООП это позволяет - при соблюдении определенных правил. Одно из которых приведено в уроке, про обращение только к доступным полям и методам. В языках со статической типизацией (Ява, C#) это правило проверяется при компиляции программы и компилятор выдаст ошибку. В PHP, увы, нет.

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

abstract class Parent
{
abstract public function getSomething(); // это должен реализовать наследник
public function test()
{
echo $this->getSomething();
}
}

class Child extends Parent
{
public function getSomething()
{
return "yes";
}
}

$child = new Child();
$child->test();

Этот код не получится использовать как-то неправильно.

ООП тем и хорош, что позволяет писать код, который в принципе нельзя использовать неправильно. Вот тебе еще пример:

1) ООП позволяет запретить присваивать неправильные значения. Допустим, мы делаем класс ЖурналОценок и в нем есть метод поставитьОценку. Очевидно, оценка ставится Ученику за Урок и может быть от 1 до 5. Мы можем написать такой метод:

class Register
{
public function addScore(Lesson $lesson, Student $student, int $score)
{
if ($score < 1 || $score > 5) {
throw new \InvaldiArgumentException("Score must be 1 to 5, $score given");
}
....
}
}

Как видишь, этот метод не позволяет поставить неправильную оценку.

Ты должен стараться писать код так, чтобы его нельзя было неправильно использовать. И ООП дает возможности для этого:

- закрытие внутренних полей и методов от доступа снаружи с помощью private/protected
- закрытие всех полей от доступа снаружи; разрешаем изменение значений только через методы
- проверка передаваемых значений
- указание в конструкторе всех значений, которые нужны для работы класса
- не полагаемся на то, что методы будут вызываться в определенном порядке
391 1182391
>>182387

return; это выход из функции без возврата значения. В такой ситуации, если попытаться получить значение, которое вернула функция, ты получишь null:

function test() { return; }
$a = test(); // null
392 1182401
Кампухтерных дел мастера, HALP! Хочу с 10 на 7 перейти обратно, но не робит привод. Есть диск с лицензионным ключом, но с офф. сайта не грузит ISO файл для создания загрузочной флешки. Я скинул содержимое диска с 7 виндой SP1 Home Premium на флешку с другого компа и хочу перенести на ПК и тупо запустить setup, такое будет работать?
393 1182402
>>182401
В /s/ в виндотреде наверно быстрей помогут. Я уже не вспомню особенности пердолинга с win7, но помоему твой план не взлетит.
394 1182403
>>182402
Эх, и на том спасибо
395 1182405
>>180495
я быдлокодер и я хочу возразить в оправдание своего непрофессионализма.

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

касаемо всех случаев на картинке я не увидел что будет если мы вызовем не GET, а хотя бы POST. не говоря уже о HEAD, не говоря уже о PROPFIND, OPTIONS, и других даже невалидных методах, что если вместо HTTP к нам придёт каша, а веб-сервер её пропустит до PHP-интерпретатора!?

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

// более гибкий парсер строки чем умеет сам PHP
мы не сделаем,
// это как в статье про шаблоны -- больше чем умеет сам PHP мы не реализуем.
// поэтому каждую страничку чекаем в каждом if, elseif, else 404
if (strpos($_SERVER['REQUEST_URI'], '/home/') === 0) {

// и уже потом проверяем методы
switch ($_SERVER['REQUEST_METHOD']) {
case 'GET':
case 'POST':
break; // если GET или POST, мы счастливы
case 'HEAD':
exit; // HEAD не требует отдачи контента, выходим
default:
http_response_code(405);
exit; // если неизвестный метод тоже выходим
}

include(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'home.php');
}

мы не ограничиваемся возможностями нашего личного парсера маршрута REQUEST_URI,
мы также задаём действия по-умолчанию для популярных методов GET|POST|HEAD, при случае если потребуется реализовать дополнительный метод, мы это так же учтём и добавим уже для какого-то конкретного контроллера.

а не так, что обрабатываем маршрут, передаём контроллеру, а что там было -- GET|POST|HEAD|другая параша -- хер её знает, кому это важно?
395 1182405
>>180495
я быдлокодер и я хочу возразить в оправдание своего непрофессионализма.

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

касаемо всех случаев на картинке я не увидел что будет если мы вызовем не GET, а хотя бы POST. не говоря уже о HEAD, не говоря уже о PROPFIND, OPTIONS, и других даже невалидных методах, что если вместо HTTP к нам придёт каша, а веб-сервер её пропустит до PHP-интерпретатора!?

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

// более гибкий парсер строки чем умеет сам PHP
мы не сделаем,
// это как в статье про шаблоны -- больше чем умеет сам PHP мы не реализуем.
// поэтому каждую страничку чекаем в каждом if, elseif, else 404
if (strpos($_SERVER['REQUEST_URI'], '/home/') === 0) {

// и уже потом проверяем методы
switch ($_SERVER['REQUEST_METHOD']) {
case 'GET':
case 'POST':
break; // если GET или POST, мы счастливы
case 'HEAD':
exit; // HEAD не требует отдачи контента, выходим
default:
http_response_code(405);
exit; // если неизвестный метод тоже выходим
}

include(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'home.php');
}

мы не ограничиваемся возможностями нашего личного парсера маршрута REQUEST_URI,
мы также задаём действия по-умолчанию для популярных методов GET|POST|HEAD, при случае если потребуется реализовать дополнительный метод, мы это так же учтём и добавим уже для какого-то конкретного контроллера.

а не так, что обрабатываем маршрут, передаём контроллеру, а что там было -- GET|POST|HEAD|другая параша -- хер её знает, кому это важно?
396 1182447
Поясните почему кто-то торгует доменными именами? Это наебалово со стороны хостингов? И вот допустим я хочу сайт с адресом .by - мне не обязательно садить его у белорусского хостера? Чет не могу понять как вся эта система устроена с тем где сайт физически лежит, какое доменное имя имеет и вообще за что при этом нужно платить мне как человеку который хочет всем этим начать пользоваться.
397 1182449
>>182391
https://codeshare.io/jGzQ9
Вот образец метода, каким-то образом все переменные доходят до конца и отправляются, как аргументы функции wp_mail
Ничего тогда не понимаю, что за магия такая.
398 1182453
>>182449
Хм, или это потому что до return и не доходит дело, просто происходит вызов функции. Совсем чёт худо дело у меня с соображениями на этот счёт.
sage 399 1182524
>>182389

>ведь кто-то сделать


Мне показалось, что тут отсутствует слово "мог".
400 1182525
>>182447

>И вот допустим я хочу сайт с адресом .by - мне не обязательно садить его у белорусского хостера?


Тут особенности местного законодательства нужно гуглить. По моему для интернет магазинов (хз что у них считается интернет магазином сейчас) домен должен быть в .by и хостер только местный.
401 1182528
>>182405
Кажется ты настроен на конструктив, поэтому отвечу развернуто - насколько смогу.
Во первых, картинка - шутка, мем такой есть, поэтому воспринимать её буквально не стоит.
Во вторых, человек хотел именно пример как вообще в принципе делается роутинг, насчет этого чуть дальше.

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

Насчет методов: так как картинка - шутливый псевдокод, то учтены не все нюансы жизни. Популярные же роутеры, однако, имеют в параметрах тип запроса, как пример, объявление роута в klein:

$klein->respond('GET', '/hello-world', function () {
return 'Hello World!';
});

Так-же, пример с Request и далее подразумевают, что тип запроса и соответствующие данные разбираются этим классом самостоятельно и передаются в контроллер уже в "красивом" виде (третий пример подразумевает использование dependency injection container, где это делается автоматически, четвертый - ioc контейнера на рефлексии).

Перейдем к такому примеру, основанному на твоём (не очень честно потому что я не знаю как бы именно ты это написал):

if (strpos($_SERVER['REQUEST_URI'], '/forum/') === 0) {
_ switch ($_SERVER['REQUEST_METHOD']) {
_ _ case 'GET':
_ _ _ break;
_ _ case 'POST':
_ _ _ break;
_ _ case 'HEAD':
_ _ _ exit();
_ _ default:
_ _ _ http_response_code(405);
_ _ _ exit();
_ }
_ include( dirname(__FILE__) . DIRECTORY_SEPARATOR . 'forum.php' );
}

Теперь давай пройдемся по изъянам.

Пропустили запросы GET/POST - хорошо. Но в самом forum.php тебе в итоге придется опять делать ту-же проверку, чтобы выяснить - постит юзер или хочет прочитать страницу. Если же ты проверишь это сразу, то передать в инклюд данные о проверке сможешь только через статический класс или глоаблки, постепенно превращая код в лапшу.

Если тебе понадобится валидация для HEAD (чтобы для несуществующих разделов ответить кодом 404), тебе придется пихать туда эту логику, хотя она УЖЕ будет в контроллере/где-то еще, т.к. там ТОЖЕ нужна эта валидация.

strpos - сматчит все роуты, где в начале есть /forum/. Скорее всего, в вебе будут ссылки только на реальные разделы. Не считая удаленных тредов например. И тогда тебе придется в контроллере опять проверять есть ли такой тред, рендерить другой шаблон - в общем куча работы по валидации URI в контроллере, который по идее должен лишь раскидать данные в модель и отрендерить шаблон.

Что если ты хочешь иметь подраздел, например /forum/admin/ ? С таким подходом твой URI будет отвечать сразу двумя контролами, и тебе придется опять наворачивать лапшу.

Поэтому есть смысл использовать, например, регулярки. Популярные роутеры имеют свой синтаксис вместо регулярок например. Но суть в том что /\/forum\/(.+\/)/ сматчит только то, что ты действительно хочешь. Это конечно не отменяет промежуточный слой валидации, но дополняет его.

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

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

Теперь о картинке.

Первый и второй пример очень простые и логика в них похожа на твою.

Третий пример и четвертый пример похожи. Подход, похожий на четвертый используется в очень популярном фреймворке Laravel (не буквально, опять же, а на основе того). Почему он вообще существует? Потому что есть такие люди которые любят тестировать код прежде чем пушить в продакшен. Для этого классы делают на основе интерфейсов; При тестировании какого-то класса, ему вместо реальных зависимостей даются мок-имплементации интерфейсов зависимостей; В продакшене IoC контейнер имеет конфигурацию с указанием реализаций интерфейсов.

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

Почему третий "хуже" четвертого? Потому что любой скажет тебе что строковые идентификаторы - зло. По сути, почти то-же самое.

Почему они "лучше" первых двух? Потому что в кавычках. С одной стороны, увеличивается гибкость, всё делается автоматически, уменьшается количество рутины. С другой - ломается тайп-хинтинг, и для меня это отменяет все плюсы например...

Полностью я не смогу охватить эту тему, да и зачем, ведь если ты заинтересуешься - найдешь всё сам. Лишь предложу тебе попробовать написать сайт/сервис с использованием роутера, а роутер написать самому.
401 1182528
>>182405
Кажется ты настроен на конструктив, поэтому отвечу развернуто - насколько смогу.
Во первых, картинка - шутка, мем такой есть, поэтому воспринимать её буквально не стоит.
Во вторых, человек хотел именно пример как вообще в принципе делается роутинг, насчет этого чуть дальше.

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

Насчет методов: так как картинка - шутливый псевдокод, то учтены не все нюансы жизни. Популярные же роутеры, однако, имеют в параметрах тип запроса, как пример, объявление роута в klein:

$klein->respond('GET', '/hello-world', function () {
return 'Hello World!';
});

Так-же, пример с Request и далее подразумевают, что тип запроса и соответствующие данные разбираются этим классом самостоятельно и передаются в контроллер уже в "красивом" виде (третий пример подразумевает использование dependency injection container, где это делается автоматически, четвертый - ioc контейнера на рефлексии).

Перейдем к такому примеру, основанному на твоём (не очень честно потому что я не знаю как бы именно ты это написал):

if (strpos($_SERVER['REQUEST_URI'], '/forum/') === 0) {
_ switch ($_SERVER['REQUEST_METHOD']) {
_ _ case 'GET':
_ _ _ break;
_ _ case 'POST':
_ _ _ break;
_ _ case 'HEAD':
_ _ _ exit();
_ _ default:
_ _ _ http_response_code(405);
_ _ _ exit();
_ }
_ include( dirname(__FILE__) . DIRECTORY_SEPARATOR . 'forum.php' );
}

Теперь давай пройдемся по изъянам.

Пропустили запросы GET/POST - хорошо. Но в самом forum.php тебе в итоге придется опять делать ту-же проверку, чтобы выяснить - постит юзер или хочет прочитать страницу. Если же ты проверишь это сразу, то передать в инклюд данные о проверке сможешь только через статический класс или глоаблки, постепенно превращая код в лапшу.

Если тебе понадобится валидация для HEAD (чтобы для несуществующих разделов ответить кодом 404), тебе придется пихать туда эту логику, хотя она УЖЕ будет в контроллере/где-то еще, т.к. там ТОЖЕ нужна эта валидация.

strpos - сматчит все роуты, где в начале есть /forum/. Скорее всего, в вебе будут ссылки только на реальные разделы. Не считая удаленных тредов например. И тогда тебе придется в контроллере опять проверять есть ли такой тред, рендерить другой шаблон - в общем куча работы по валидации URI в контроллере, который по идее должен лишь раскидать данные в модель и отрендерить шаблон.

Что если ты хочешь иметь подраздел, например /forum/admin/ ? С таким подходом твой URI будет отвечать сразу двумя контролами, и тебе придется опять наворачивать лапшу.

Поэтому есть смысл использовать, например, регулярки. Популярные роутеры имеют свой синтаксис вместо регулярок например. Но суть в том что /\/forum\/(.+\/)/ сматчит только то, что ты действительно хочешь. Это конечно не отменяет промежуточный слой валидации, но дополняет его.

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

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

Теперь о картинке.

Первый и второй пример очень простые и логика в них похожа на твою.

Третий пример и четвертый пример похожи. Подход, похожий на четвертый используется в очень популярном фреймворке Laravel (не буквально, опять же, а на основе того). Почему он вообще существует? Потому что есть такие люди которые любят тестировать код прежде чем пушить в продакшен. Для этого классы делают на основе интерфейсов; При тестировании какого-то класса, ему вместо реальных зависимостей даются мок-имплементации интерфейсов зависимостей; В продакшене IoC контейнер имеет конфигурацию с указанием реализаций интерфейсов.

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

Почему третий "хуже" четвертого? Потому что любой скажет тебе что строковые идентификаторы - зло. По сути, почти то-же самое.

Почему они "лучше" первых двух? Потому что в кавычках. С одной стороны, увеличивается гибкость, всё делается автоматически, уменьшается количество рутины. С другой - ломается тайп-хинтинг, и для меня это отменяет все плюсы например...

Полностью я не смогу охватить эту тему, да и зачем, ведь если ты заинтересуешься - найдешь всё сам. Лишь предложу тебе попробовать написать сайт/сервис с использованием роутера, а роутер написать самому.
https://github.com/mlmn/vector.loc 402 1182534
>>1176476
1. Вывод шаблонов в конструкторе и деструкторе убрал, сделал обычные методы.

2.

>А зачем нужно OrgInfo? Нельзя ли в организации сделать методы для вычислений этих чисел? Просто у меня ощущение, что этот класс заточен только под вывод таблицы, и тогда код getOrgInfo() желательно вынести из компании куда-нибудь, хотя бы в ту же OrgInfo. Или вообще ликвидировать этот метод.


Класс OrgInfo - выпилил, перенес вычисления общих и средних показателей по организации в отдельные методы. Теперь поясню почему я так держался за это с самого начала. Изначально очень удобно и просто было высчитывать всё это за 1 цикл, тупо прокручивая все департаменты в нем 1 раз, и складывая всю инфу в 1 выходной объект, поэтому в итоге это и выросло в такую вот шизу как отдельный класс для хранения этой информации на выходе этого метода. Мне и сейчас решение с вынесением всех вычислений в разные методы не кажется хорошим, просто потому что, во первых они почти все повторяют друг друга и у них отличается только переменная на входе, выходе и название соответственно, а во вторых всё это вместо одного компактного цикла использует каждый раз по циклу на метод и опять же перебирает снова и снова департаменты. В общем я сделал как рекомендовано, но остались сомнения с точки зрения оптимизации.

3. Тайп хинты расставил везде где нашел возможным.

4. try/catch выпилил, самому не нравилась идея оборачивать каждый код с exeptionon'ом внутри в эту конструкцию. А если я например чужой класс ипользую - мне нужно идти смотреть получается нет ли там внутри выброса исключений и на методы внутри которых есть рисовать try/catch каждый раз? Звучит тупо, так что только рад что это всё не нужно.

5.

>> public function promoteStuff(array $promotionList) {


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


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

6.

>По моему было бы гораздо удачнее сделать так:


>if ($employeeSelector->matches($employee)) ...


>Это позволило бы поместить логику отбора в класс-фильтра, где ей и место. Ну и еще есть такой вариант с коллбеком:


Перенес из департамента метод фильтрации сотрудников в сам класс EmployeeSelector, сделал там метод match который принимает на вход сотрудника и выдает булево значение - подходит сотрудник под текущие параметры или нет.

> new EmployeeSelector('Engineer', [1, 2, 3], [true, false]);


>лучше сделать возможность указать "не важно" для ранга. null, например, передать.


При этом сам способ фильтрации почти не изменился, разве что добавил возможность передавать в конструктор null как вариант "не важно"

7.

> return round($pageCost, 3);


>Не надо делать тут round, так как это нужно только для вывода в таблицу и должно быть там, где делается вывод, а не тут. Тут должен быть метод, который возвращает точное значение.


Ок, округление теперь во вьюхах

8.

> $vectorSecondAC = clone $vectorVanilla;


>В клонировании у тебя допущена ошибка. Этот метод не создает глубокую копию компании. он делает клон компании, но в него помещает ссылки на те же самые департаменты с теми же самыми работниками - они по умолчанию не клонируются, а просто копируются ссылки. Изучи магический метод __clone().


Переделал, теперь при клонировании организации должны клонироваться еще и объекты департаменты, а не просто ссылки на них, и при клонировании департамента соответственно объекты сотрудников

9.

> $this->organisation->setTitle("после антикризисных мер #1");


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


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

10.

>Сортировку лучше делать в одной функции, так:


>Также, есть еще такой трюк, вычисляем "вес" и сравниваем его:


Выбрал вариант с вычислением веса, так как он мне понятнее.

11.

>По view: в идеале, надо использовать htmlspecialchars при вставке текста в HTML. Иначе может быть уязвимость XS


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

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

>> abstract protected function setDefaults();


>Это не очень хорошо, так как непонятно, что эта функция должна делать. Это никак не описано и никак не проверяется. Мне непонятно, что в ней надо написать. По моему так лучше сделать функции getStartingSalary(), getStartingCoffee() и тд, с которыми все проще и понятнее.


>> В общем тут у меня проблема и не понимание как из этого слабого места выкрутиться. [про абстрактные методы]


>Сделать абс. методы вроде getStartingSalary():float { return 500; } для каждого значения.


Я вообще не понимаю что тут от меня нужно.

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

Но потом когда я начал решать антикризисные меры, там вы первых написано:

>Пришло время проверить, соответствует ли твой код принципам ООП? Гибок ли он и легко ли поддается изменениям?


В во вторых в одном методе там есть условие:

>Увеличить в целях стимуляции умственной деятельности базовую ставку аналитика с 800 до 1100 тугриков, а количество выпиваемого им кофе с 50 до 75 литров.


И тут становится понятно, что просто ретернить захардкоженные значения уже не работает. Ведь их придется менять, а что бы менять - их нужно где-то хранить (в полях и храним, а значит всё предельно удачно теперь встает на свои места и зменяемов с помощью опять же сеттеров и геттеры не просто хардкод а берут то, что в текущий момент в объекте установлено. Я опять же легко могу кому-угодно что угодно поменять, а как всё это провернуть с методами вроде этого:

>getStartingSalary():float { return 500; }


- я просто НЕ ПОНИМАЮ. Если у меня снова будут в сотруднике такие методы - то как я смогу вот эти вот 800 заменить на 1100 в коде?

13. Так же добавил свистелку в виде методов setTimePoint() и benchMark() - прошу оценить реализацию. Саму идею я уже где-то видел, но вот как обычно называется это под капотом и как раскидано по коду я не ковырял пока.

14.

>Кстати, у нас еще есть задача про Гостиницу. Не хочешь отточить навыки ООП?


Да хочу, лучше было сразу просто условие скинуть.

В итоге 2 главных проблемы так и не решил - OrgInfo ращбил на кучу копипастных методов, которые пусть и удобные, но само их существование мне не нравится и они дублируются и лишь загромождают код, и вообще ничего не понял как нужно сделать абстрактные методы в сотрудниках по типу: getStartingSalary():float { return 500; }
https://github.com/mlmn/vector.loc 402 1182534
>>1176476
1. Вывод шаблонов в конструкторе и деструкторе убрал, сделал обычные методы.

2.

>А зачем нужно OrgInfo? Нельзя ли в организации сделать методы для вычислений этих чисел? Просто у меня ощущение, что этот класс заточен только под вывод таблицы, и тогда код getOrgInfo() желательно вынести из компании куда-нибудь, хотя бы в ту же OrgInfo. Или вообще ликвидировать этот метод.


Класс OrgInfo - выпилил, перенес вычисления общих и средних показателей по организации в отдельные методы. Теперь поясню почему я так держался за это с самого начала. Изначально очень удобно и просто было высчитывать всё это за 1 цикл, тупо прокручивая все департаменты в нем 1 раз, и складывая всю инфу в 1 выходной объект, поэтому в итоге это и выросло в такую вот шизу как отдельный класс для хранения этой информации на выходе этого метода. Мне и сейчас решение с вынесением всех вычислений в разные методы не кажется хорошим, просто потому что, во первых они почти все повторяют друг друга и у них отличается только переменная на входе, выходе и название соответственно, а во вторых всё это вместо одного компактного цикла использует каждый раз по циклу на метод и опять же перебирает снова и снова департаменты. В общем я сделал как рекомендовано, но остались сомнения с точки зрения оптимизации.

3. Тайп хинты расставил везде где нашел возможным.

4. try/catch выпилил, самому не нравилась идея оборачивать каждый код с exeptionon'ом внутри в эту конструкцию. А если я например чужой класс ипользую - мне нужно идти смотреть получается нет ли там внутри выброса исключений и на методы внутри которых есть рисовать try/catch каждый раз? Звучит тупо, так что только рад что это всё не нужно.

5.

>> public function promoteStuff(array $promotionList) {


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


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

6.

>По моему было бы гораздо удачнее сделать так:


>if ($employeeSelector->matches($employee)) ...


>Это позволило бы поместить логику отбора в класс-фильтра, где ей и место. Ну и еще есть такой вариант с коллбеком:


Перенес из департамента метод фильтрации сотрудников в сам класс EmployeeSelector, сделал там метод match который принимает на вход сотрудника и выдает булево значение - подходит сотрудник под текущие параметры или нет.

> new EmployeeSelector('Engineer', [1, 2, 3], [true, false]);


>лучше сделать возможность указать "не важно" для ранга. null, например, передать.


При этом сам способ фильтрации почти не изменился, разве что добавил возможность передавать в конструктор null как вариант "не важно"

7.

> return round($pageCost, 3);


>Не надо делать тут round, так как это нужно только для вывода в таблицу и должно быть там, где делается вывод, а не тут. Тут должен быть метод, который возвращает точное значение.


Ок, округление теперь во вьюхах

8.

> $vectorSecondAC = clone $vectorVanilla;


>В клонировании у тебя допущена ошибка. Этот метод не создает глубокую копию компании. он делает клон компании, но в него помещает ссылки на те же самые департаменты с теми же самыми работниками - они по умолчанию не клонируются, а просто копируются ссылки. Изучи магический метод __clone().


Переделал, теперь при клонировании организации должны клонироваться еще и объекты департаменты, а не просто ссылки на них, и при клонировании департамента соответственно объекты сотрудников

9.

> $this->organisation->setTitle("после антикризисных мер #1");


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


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

10.

>Сортировку лучше делать в одной функции, так:


>Также, есть еще такой трюк, вычисляем "вес" и сравниваем его:


Выбрал вариант с вычислением веса, так как он мне понятнее.

11.

>По view: в идеале, надо использовать htmlspecialchars при вставке текста в HTML. Иначе может быть уязвимость XS


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

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

>> abstract protected function setDefaults();


>Это не очень хорошо, так как непонятно, что эта функция должна делать. Это никак не описано и никак не проверяется. Мне непонятно, что в ней надо написать. По моему так лучше сделать функции getStartingSalary(), getStartingCoffee() и тд, с которыми все проще и понятнее.


>> В общем тут у меня проблема и не понимание как из этого слабого места выкрутиться. [про абстрактные методы]


>Сделать абс. методы вроде getStartingSalary():float { return 500; } для каждого значения.


Я вообще не понимаю что тут от меня нужно.

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

Но потом когда я начал решать антикризисные меры, там вы первых написано:

>Пришло время проверить, соответствует ли твой код принципам ООП? Гибок ли он и легко ли поддается изменениям?


В во вторых в одном методе там есть условие:

>Увеличить в целях стимуляции умственной деятельности базовую ставку аналитика с 800 до 1100 тугриков, а количество выпиваемого им кофе с 50 до 75 литров.


И тут становится понятно, что просто ретернить захардкоженные значения уже не работает. Ведь их придется менять, а что бы менять - их нужно где-то хранить (в полях и храним, а значит всё предельно удачно теперь встает на свои места и зменяемов с помощью опять же сеттеров и геттеры не просто хардкод а берут то, что в текущий момент в объекте установлено. Я опять же легко могу кому-угодно что угодно поменять, а как всё это провернуть с методами вроде этого:

>getStartingSalary():float { return 500; }


- я просто НЕ ПОНИМАЮ. Если у меня снова будут в сотруднике такие методы - то как я смогу вот эти вот 800 заменить на 1100 в коде?

13. Так же добавил свистелку в виде методов setTimePoint() и benchMark() - прошу оценить реализацию. Саму идею я уже где-то видел, но вот как обычно называется это под капотом и как раскидано по коду я не ковырял пока.

14.

>Кстати, у нас еще есть задача про Гостиницу. Не хочешь отточить навыки ООП?


Да хочу, лучше было сразу просто условие скинуть.

В итоге 2 главных проблемы так и не решил - OrgInfo ращбил на кучу копипастных методов, которые пусть и удобные, но само их существование мне не нравится и они дублируются и лишь загромождают код, и вообще ничего не понял как нужно сделать абстрактные методы в сотрудниках по типу: getStartingSalary():float { return 500; }
sage 403 1182544
ОП, пока ты здесь, скажи, где можно почитать о проверки перед авторизацией?!
>>182372 - кун
404 1182595
Мне надо установить videojs. Я скачал ноду, и установил его через npm, но помимо videojs и его зависимостей, накачалась куча всякой хуиты типа документации, примеров кода, минифицированный video.js, и не минифицированный и т. д. Я правильно понял, что на продакшене подразумевается, что надо все это удалить руками? Или может есть какой то флаг для npm, чтобы он это сам это сделал и осталось только нужное. Я просто ввел npm install video.js. В жс и фронтенде пока еще плохо разбираюсь, так что сорри за нубский вопрос.
405 1182598
>>182595
Хахахаххаха, лох ебаный блядь. Зашел в гугол, нашел оф сайт этой либы, скончал ее и подключил в своем проекте. Нахуй ноду с ее ебаным npmч
406 1182632
>>182598
Обновлять зависимости тоже будешь вручную через гугол?
407 1182636
>>182595

>Я правильно понял, что на продакшене подразумевается, что надо все это удалить руками? Или может есть какой то флаг для npm, чтобы он это сам это сделал и осталось только нужное.


Обычно используют системы сборки типа webpack для такого.
На продакшене у тебя будет только минифицированный файл. А на деве полезно иметь документацию и не аглифицированные-минифицированные сорцы, чтобы можно было в случае чего обратиться к справке либы прямо из ide своей или посмотреть как там внутри код работает.
408 1182647
>>182632
Да нет, блядь, буду держать для зависимостей сраный ноде.
409 1182659
Как почитать mp3 теги (id3 или как они правильно называются?)?
410 1182675
>>182659
Через pecl поставь либу id3 (вроде так называется) и там уже готовых функций...
411 1182700
>>182647
Допустим у тебя 10 сайтов по 10 сторонних либ в каждом. Ты это руками будешь обновлять? Или при разворачивании проекта на другой машине ты будешь всё это руками качать? Какую-то хуйню пишешь. Вангую у тебя ничего сложнее сайта-визитки не было, где в зависимостях только джиквери.
412 1182714
>>182700

> Допустим у тебя 10 сайтов по 10 сторонних либ в каждом.



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

Каждый сайт свой набор инструментов, один хуй надо будет читать чэенджлог, что убрали, что добавили. Ну и уж не такая это и частая процедура обновлять раз в год, а то и 2, библиотеки.

Из пальца высасываешь.
413 1182722
Ананасы, кто тут умеет джаваскрипт? Почему на пхп так легко дизайнить разные классы, сценарий работы приложения легко выстраивается в голове, код понятный, идет четкое разделение обязанностей и вот это все. Я на жс хочу загрузчик файлов написать для файлообменника, и вообще понятия не имею как должен выглядеть "чтобы красиво" объект в жс. Я должен и отправлять формдату через аякс, и вызывать нужные функции при разных состояниях, которые изменяют дом(включают/выключают надписи), на каждый чих я добавляю и удаляю классы у разных нод, и в итоге у меня намешано куча разного всего, и мой класс FileUploading это вообще херня а не файл аплоадинг. А еще вот этот selectElementById(), благодаря бутстрапу у меня куча врапперов для врапперов, и я туда верх-вниз езжу по этим нодам как циган.
414 1182742
>>182722
Некоторых людей это не беспокоит.
Некоторым даже нравится, да.
Те, кого такая ситуация не устраивает, либо берут чужую практику, либо делают свою. В итоге получается что-то типа React. Вот про него и почитай.
415 1182778
Поясните почему пхп так ругают? Чем он хуже того же пиздона? Взялся учить пайтон - хуита же... когда дошел до ООП и увидел что объект необходимо постоянно передавать в метод - дропнул
416 1182784
>>182778
Какие-то у тебя школярские проблемы. Ты хоть бы на рынок труда смотрел и выбирал где больше платят и меньше заебывают, больше свободного времени на развитие. Пхп - это мелкие галеры с потогоной системой. Будешь медленно делать пректы, тебя будут всякую фигню заставлять выполнять. Будешь быстро делать - придется говнокодить и прменять примитивные технологии в ущерб своему развитию.
417 1182786
>>182784
ну я работаю пхп макакой и не жалуюсь. Меня не интересует метод оценки быдла хде больше плотють я хочу для себя выучить какойто более серьезный язык чем пхп. Пробовал ноду - дно. Взялся вот за пайтон - разочаровуюсь по мере изучения и возникла мысль чем же так хуйов пхп?
sage 418 1182788
>>182778

>когда дошел до ООП и увидел что объект необходимо постоянно передавать в метод - дропнул


лол ребёнок
419 1182789
>>182786
Я работаю пхп макакой и жалуюсь на то что продуктовые компании, в которых пхп основной язык разработки по пальцам одной руки пересчитать. На счет быдла: ты конечно выбрал пхп потому, что у тебя серьезный математический (или инженерный) бэкграунд
420 1182790
>>182788

>пук


ясно
421 1182796
>>182789

>продуктовые компании


>язык разработки


чево блядь?
Я не выбирал пхп, я случайно в него вкатился, просто потомучто надо было сделать для себя пару сайтов
422 1182815
>>182778
А кто ругает то? Самый лучший язык как по мне, вкатился только из-за того что наоборот все любят и язык идет вперед, пока всякие руби адово загнивают
423 1182819
>>182815

>А кто ругает то?


попробуй упомянут в любом месте, что ты пишешь на пхп
424 1182823
>>182815

>язык идет вперед


сказал анон и пошел писать лендинг на версии 5.3
425 1182826
>>182823
Хз пишу на семерке, всё норм. А вообще ща товарищ попросил сайт ему простой сделать, а я не знаю никаких цмс толком. Думаю вот что надо бы свой первый сайт на вордпрессе сварганить уже как раз.
426 1182831
>>182826
Вот тут не поспоришь: если делаешь что-то для себя или нанимаешь макак в свою студию - пхп замечательный. Если же сам макака, то вступает в действие колесо сансары из которого не выбраться. Из макаки в следующей жизни человеком не переродишься.
sage 427 1182882
>>182790
Вам в /b/ загон, животное.
428 1182900
>>182882
но ведь это тебе туда, долбоебушек. Что сказать то хотел?
sage 429 1182904
>>182900
Что ты малолетний ебанат-максималист с мемами вместо головы)
430 1182906
>>182831

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


Поясни ка немного о чем ты? Готов поспорить, что ты нихуя не понимаешь просто, но предвзят к тому, что мол если ты разработчик на пхп, то у тебя одна лишь дорога - клепать лендосы на цмс.
431 1182910
Ребята, старайтесь быть конструктивне, в тематике-то.
На любых языках пишется как важный софт так и бесполезное говно.
Так-же как и на любых человеческих языках можно вести полезный диалог, а можно пиздеть без толку.
432 1182912
>>182778
Пыха хорошая, пыха замечательная. Только вот со временем ты вырастешь и захочешь писать более быстрый софт - и не сможешь, потому что она жестко прикручена к запуску отдельного скрипта на каждый процесс. Захочешь писать более надежный софт и увидишь, что это невозможно, посколько вместо числа или строки в функцию может придти прокисший борщ. Захочешь использовать крутые библиотеки - и помощи ни от языка, ни от сообщества не дождешься. Захочешь нанять кодеров себе в помощь - у тебя в коридоре будет вонь как в конюшне и толпа кидающихся какахами макак-соискателей. Карочи, пыха со временем просто перестает доставлять.
433 1182913
>>182906
Я и в правду нихуя не понимаю ,но все вакансии пхп либо студии с однодневными проектами на одно рыло (а значит дядя будет присваивать весь твой труд себе, с нулевым вкладом со своей стороны), либо какая-нибудь часть проекта работающая с фронтендом на удаленке/фрилансе (и тут ты должен быть фулстак разрабом). У тебя просто не будет ни времени, ни возможности специализироваться глубоко в чем-нибудь одном, или изучить что-то новое. Дядя специально выбрал php для своего проекта, чтобы было быстро и дешево.
434 1182916
>>182904
Всеравно непонятно. Попробуй хуй изо рта вынуть и повторить еще раз
sage 435 1182921
Анон, а как можно написать проверку для парсинга, удается ли залогироваться?
436 1182924
>>182921
if (залогирование === true) {
// залогирован
}

хуй изо рта так и не высунул, смотрю
437 1182959
Пацаны доставьте мемасик где гопарь, начав программировать на PHP сразу стал успешным, а все остальные языки это сторчавшиеся нарики.
438 1183002
>>182722
Пишешь на https://www.typescriptlang.org/docs/handbook/classes.html
компилируешь в JS атоматом webpack-ом.
sage 439 1183128
>>182916
Рвись ещё, ребёночек)

>эти шаблоны про хуй во рту


>эти стрелочки


Тебе 15?
440 1183171
>>183128

>залогироваться


>мне больше 15ти и хуя во рту нет

sage 441 1183190
>>183128
Ссу на жлоба. Наверно, ты еще и алкоголик.
442 1183204
>>183128
вообще то ты первый начал писать оскорбления вроде "ребенок". так что уебывай отсюда и сагу свою забери
изображение.png11 Кб, 698x339
sage 443 1183220
>>183171

>залогироваться


Хуя ты {'даунёнок' => 'глупнький'})0)
Рвись ниже, пажалуста, веселите меня всем тредом.
444 1183227
>>179846
По итогу все не работает только в долбаном хроме, а в остальных браузерах все и всегда нормально работает. Кто то знает как это фиксить?
445 1183233
>>183227
Хром любит кешировать?
446 1183234
>>183233
ага. я чищу кеш после каждого изменения но это неудобно.
447 1183237
>>183234
Disable cache в настройках Devtool
mLvnYDI[1].png5 Кб, 209x230
448 1183287
Поясните за ехидные колобки колбэки в php. Как мне сделать нечто вроде такого: pic1

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

$obj->bob = function () {return "YOBA"}
449 1183288
>>183220
Ты аут? Нахуя ты скрин куска треда кинул?
450 1183290
>>183287
Сам ответ написал, лол.
Возьми и сделай публичное поле.
Ctl3S0L[1].png6 Кб, 217x269
451 1183296
>>183287
Не работает. ЧЯДНТ?

Суть в том, что есть класс, который работает с html-кодом. И этот самый html-код может получаться разными способами, которые никак не унифицировать. То есть, у каждого объекта своя версия функции, которая генерирует html. По умолчанию он будет генерироваться по определенному алгоритму из переданных в скрипт параметров, но может быть результатом обращения к API, file_get_contents, генерацией по совершенно другому алгоритму и т. д.
UnKmyvJ[1].png6 Кб, 231x272
452 1183297
>>183296
Я ёбаный наркоман и закомментировал run, но раскомментирование не помогает.
453 1183306
>>183297
$this->tst() в run? Для поля tst можешь сделать хитрый setter, кторый будет выполнять колбэк, мне лень писать
LJHgYdw[1].png9 Кб, 263x394
454 1183312
Эта ёбанная наркомания - самое близкое к тому, чего я хочу. По умолчанию значение свойства - результат выполнения метода, при этом нужным объектам я могу прописать свои анонимные функции.

Не знаю, насколько это всрато, но мою задачу решает.

>>183306
Не работает.
Доделал Student List 455 1183323
>>174695 (OP)
Доделал Student List вот ссылка на проверку
https://github.com/levneedscoffee/Student-List
Оп, я никак не могу понять зачем нужен отдельный класс Студент?
456 1183325
>>183312
$оbj->tst = 20;

Зачем городить лишнее?
458 1183357
>>183354
конечно
public $_tst;
public $_cb;
--->
private $_tst;
private $_cb;

очепятка
459 1183383
>>183297
У тебя tst не в this, чем ты занимаешься там вообще?
jShfcT4[1].png10 Кб, 629x290
460 1183401
>>183325
Затем, что это пример, а на практике там будут функции в не один десяток строк.
>>183354
Спасибо, Анон. Я слишком сонный и пока нихуя не понял особо, но выглядит похожим на правду. Завтра разберусь.
>>183383
Наркоман что ли? С чего вдруг оно не в $this?
sage 461 1183426
>>183401

>С чего вдруг оно не в $this?


>Объявляет public tst


>Потом в функции вызывает this->tst


Как он по твоему должен в this переселиться?

https://stackoverflow.com/questions/1981375/setting-public-class-variables
462 1183434
>>183426
На скриншоте всё работает, тебя это не смущает?
463 1183438
>>183426
Я только въезжаю в ООП, но, по-моему, ты несёшь какую-то хуйню, анон.
$this - используется для доступа к объекту изнутри класса. Я в классе объявляю tst. Объект этого класса тоже будет иметь tst. Чё не так то? Тем более, на скриншоте всё работает.
Вдвойне тем более - ты сам по своей ссылке переходил? Там написано, что да, это работает, но лучше обмазываться инкапсуляцией (или как это называется). Это архитектурный дроч, сейчас вопрос не в этом.
1-129 ОП 464 1183545
>>174778

> echo "Ответ $answers[$answer[1]]\n";


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

Мануал по подстановке переменных в строки: http://php.net/manual/ru/language.types.string.php#language.types.string.parsing

array_rand возвращает массив только если требуется вернуть более 1 ключа, иначе она возвращает сам ключ, не в массиве.

Первый элемент массива имеет индекс 0, а не 1.

>>174852

Есть 2 подхода - внедрять сервисы по одному либо забить и внедрить сразу контейнер.

>>174967

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

> но лучше, как мне кажется, внедрять зависимости сразу в методы,



Для этого вызывающий код должен это поддерживать, то есть анализировать аргументы методов и подбирать сервисы. Плюс, это не работает, если у тебя для одного класса есть несколько сервисов.
ОП 465 1183547
>>175020

Для отладки кода поставь везде echo, которые показывают, какие места кода выполняются и чему равны переменные в этой точке. Например, если if не выполняется, выведи, чему равны переменные перед ним и увидишь, почему.

> elseif($timeOP == '=') {


Это неправильно, так как $timeOp - это предыдущая (а не текущая) увиденная операция, а после = уже других операций нет и это условие никогда не сработает.

> то он выдаёт набор цифр 0002222488448842662. Они должны быть в результатах вычисления, это правильные цифры, но и не правильные.


Потому что надо сбрасывать number после выполнения операции.

>>175435

>https://ideone.com/JkebMt



Короче можно сделать, если использовать функцию array_rand - подробности в мануале.

Еще короче - если составить массив, в котором каждый элемент - это массив, содержащий варианты слов:

[
['я', 'ты', 'он'],
['видел', 'слышал', 'знал'],
...
];

И обходить его в цикле.

>>175648

Через if/else: если операция это плюс, то сложить; если операция это минус, то вычесть и тд.

> Можно же числа определить в один массив, а операции в другой, а когда for дойдёт до "=", по очереди вызвать элементы массивов с числами и операциями, так, чтобы они сложились в пример и сразу вычислялись?



Можно попробовать. Но тогда наверно проще сделать единый массив и с числами, и с операциями, и идти по нему последовательно.
ОП 465 1183547
>>175020

Для отладки кода поставь везде echo, которые показывают, какие места кода выполняются и чему равны переменные в этой точке. Например, если if не выполняется, выведи, чему равны переменные перед ним и увидишь, почему.

> elseif($timeOP == '=') {


Это неправильно, так как $timeOp - это предыдущая (а не текущая) увиденная операция, а после = уже других операций нет и это условие никогда не сработает.

> то он выдаёт набор цифр 0002222488448842662. Они должны быть в результатах вычисления, это правильные цифры, но и не правильные.


Потому что надо сбрасывать number после выполнения операции.

>>175435

>https://ideone.com/JkebMt



Короче можно сделать, если использовать функцию array_rand - подробности в мануале.

Еще короче - если составить массив, в котором каждый элемент - это массив, содержащий варианты слов:

[
['я', 'ты', 'он'],
['видел', 'слышал', 'знал'],
...
];

И обходить его в цикле.

>>175648

Через if/else: если операция это плюс, то сложить; если операция это минус, то вычесть и тд.

> Можно же числа определить в один массив, а операции в другой, а когда for дойдёт до "=", по очереди вызвать элементы массивов с числами и операциями, так, чтобы они сложились в пример и сразу вычислялись?



Можно попробовать. Но тогда наверно проще сделать единый массив и с числами, и с операциями, и идти по нему последовательно.
466 1183548
>>175794

Зависит от реализации и от настроек. Обычно можно указать - хотим ли мы каждый раз создавать новый объект или переиспользовать старый.

Если твой объект не становится хуже в процессе использования, то его логично переиспользовать, чтобы не создавать новые. Более того, если объект в себе кеширует какие-то значения, то переиспользование позволяет задействовать этот кеш.

>>175799

Задается это обычно при настройке контейнера. Для каждого сервиса индивидуально.

>>175828

Не советую. Этот фреймворк очень старый и даже по тем временам он выглядел весьма сомнительно. Он переполнен дурными приемами написания кода.

Бери лучше Юи, он по стилю поход, но современнее. Но конечно, для такой простой задачи, как студенты, это наверно перебор и лучше брать микрофреймворк вроде Slim.

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



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

>>175988

Если у тебя можно смотреть только свой профиль, то не надо указывать id. Если можно смореть любой профиль, то надо указывать.

> Проверка через $_SESSION я так понял довольно уязвима ?



А при чем тут вообще сессия?

> По get запросу и id юзера - panel.php?id=25 и в самой странице поставить проверки, если юзер на которого мы зашли совпадает с залогиненым юзером, то появляются крутилочки для изменения данных



Проверять надо не тут. Проверять надо в первую очередь в том обработчике, в котором эти изменения сохраняются. Перед сохранением надо проверить, что у пользователя есть права на изменение.
466 1183548
>>175794

Зависит от реализации и от настроек. Обычно можно указать - хотим ли мы каждый раз создавать новый объект или переиспользовать старый.

Если твой объект не становится хуже в процессе использования, то его логично переиспользовать, чтобы не создавать новые. Более того, если объект в себе кеширует какие-то значения, то переиспользование позволяет задействовать этот кеш.

>>175799

Задается это обычно при настройке контейнера. Для каждого сервиса индивидуально.

>>175828

Не советую. Этот фреймворк очень старый и даже по тем временам он выглядел весьма сомнительно. Он переполнен дурными приемами написания кода.

Бери лучше Юи, он по стилю поход, но современнее. Но конечно, для такой простой задачи, как студенты, это наверно перебор и лучше брать микрофреймворк вроде Slim.

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



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

>>175988

Если у тебя можно смотреть только свой профиль, то не надо указывать id. Если можно смореть любой профиль, то надо указывать.

> Проверка через $_SESSION я так понял довольно уязвима ?



А при чем тут вообще сессия?

> По get запросу и id юзера - panel.php?id=25 и в самой странице поставить проверки, если юзер на которого мы зашли совпадает с залогиненым юзером, то появляются крутилочки для изменения данных



Проверять надо не тут. Проверять надо в первую очередь в том обработчике, в котором эти изменения сохраняются. Перед сохранением надо проверить, что у пользователя есть права на изменение.
467 1183549
>>176343

pluralisation в Симфони 2.1 сделан максимально бездарно. Так как transChoice() не предполагает, что может быть несколько слов, зависящих от нескольких чисел. А также там нет поддержки зависимости от пола. Пример:

"{user} (расшарил|расшарила) {pictures} (картинка|картинки|картинок) для {friends} (друга|друзей)"

Что я могу посоветовать:

- посмотреть, можно ли сделать свой наследник сервиса Translator
- в нем сделать вызов Intl с полноценным форматированием + свои методы по вкусу
- если нельзя, сделать свой сервис и использовать его, добавить свои теги для перевода в Твиг
- посмотреть в issues компонента Translation, есть ли там жалобы
- если нет, подробно объяснить недостатки существующей системы (я уже создал issue)

> Но судя по сорсам - можно сделать свой MessageFormatter:



Так и стоит поступить. Не забудь это задокументировать в своем проекте, а то догадаться, что ты подменил форматтер, будет невозможно.

>>176742

Зря. Может, у тебя глаз замылился, а ОП с анонами что-то увидят, что ты сам не видишь.

>>176781

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

Чтобы переносы строк нормально работали и в браузере и в ideone (и в консоли), можно использовать для этого \n, а в начале программы поставить

header("Content-Type: text/plain; charset=utf-8");

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

Иначе перенос строки будет в исходном коде страницы (его можно увидеть нажав Ctrl + U), но на самой странице его не будет.

>>176853

На хостинге может быть отключен вывод ошибок на экран (правильно), и их надо смотреть в логах.
467 1183549
>>176343

pluralisation в Симфони 2.1 сделан максимально бездарно. Так как transChoice() не предполагает, что может быть несколько слов, зависящих от нескольких чисел. А также там нет поддержки зависимости от пола. Пример:

"{user} (расшарил|расшарила) {pictures} (картинка|картинки|картинок) для {friends} (друга|друзей)"

Что я могу посоветовать:

- посмотреть, можно ли сделать свой наследник сервиса Translator
- в нем сделать вызов Intl с полноценным форматированием + свои методы по вкусу
- если нельзя, сделать свой сервис и использовать его, добавить свои теги для перевода в Твиг
- посмотреть в issues компонента Translation, есть ли там жалобы
- если нет, подробно объяснить недостатки существующей системы (я уже создал issue)

> Но судя по сорсам - можно сделать свой MessageFormatter:



Так и стоит поступить. Не забудь это задокументировать в своем проекте, а то догадаться, что ты подменил форматтер, будет невозможно.

>>176742

Зря. Может, у тебя глаз замылился, а ОП с анонами что-то увидят, что ты сам не видишь.

>>176781

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

Чтобы переносы строк нормально работали и в браузере и в ideone (и в консоли), можно использовать для этого \n, а в начале программы поставить

header("Content-Type: text/plain; charset=utf-8");

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

Иначе перенос строки будет в исходном коде страницы (его можно увидеть нажав Ctrl + U), но на самой странице его не будет.

>>176853

На хостинге может быть отключен вывод ошибок на экран (правильно), и их надо смотреть в логах.
468 1183550
>>176863

В PHP есть проверка типов и нормальные классы, а в Питоне нет. Код типичного проекта на Питоне ничем не читабельнее PHP, например https://github.com/rg3/youtube-dl/blob/master/youtube_dl/utils.py (обрати внимание на объем файла, количество комментариев и число подчеркиваний).

>>176866

Для админок и не требущих особого дизайна страничек подойдет.

>>176970

Даст понимание, из чего состоит веб-сервер.

>>176999

> з(дела(л|ю|н)


Еще есть "зделаем" и "зделанный".

> (\w+)\sа\s/


Пробелов может быть более одного. После "а" может идти не пробел, а другая запятая. Лучше использовать \b

> '/\b((,)|(\.)|(;)|(:)|(!)|(\?))[^\s]\b/' Хоспаде, ну почему ты не работаешь?! //



А зачем там \b в начале? И у тебя теряется [^\s].

>>177153

Может попробовать что-то сделать на основе Symfony Forms?

>>177318

Спроси на сайтах фриланса.
468 1183550
>>176863

В PHP есть проверка типов и нормальные классы, а в Питоне нет. Код типичного проекта на Питоне ничем не читабельнее PHP, например https://github.com/rg3/youtube-dl/blob/master/youtube_dl/utils.py (обрати внимание на объем файла, количество комментариев и число подчеркиваний).

>>176866

Для админок и не требущих особого дизайна страничек подойдет.

>>176970

Даст понимание, из чего состоит веб-сервер.

>>176999

> з(дела(л|ю|н)


Еще есть "зделаем" и "зделанный".

> (\w+)\sа\s/


Пробелов может быть более одного. После "а" может идти не пробел, а другая запятая. Лучше использовать \b

> '/\b((,)|(\.)|(;)|(:)|(!)|(\?))[^\s]\b/' Хоспаде, ну почему ты не работаешь?! //



А зачем там \b в начале? И у тебя теряется [^\s].

>>177153

Может попробовать что-то сделать на основе Symfony Forms?

>>177318

Спроси на сайтах фриланса.
469 1183551
>>177400

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

>>177630

> 1 http://jsbin.com/mofepusiko/edit?html,css,output



Ок, верно. Для вертикального выравнивания одной строки есть трюк - сделать line-height равной высоте блока.

> 2 http://jsbin.com/zofidemusi/edit?html,css,output


Ок, верно, хотя стоило бы учесть еще ширину border - он тоже место занимает.

> 3 http://jsbin.com/nofuwotoka/edit?html,css,output


Вместо цифр лучше использовать слова, например:

&lt ;

Полный список HTML-мнемоник: https://dev.w3.org/html5/html-author/charref

Попробуй там найти свои символы. А то цифры человеку читать очень трудно.

> 4 http://jsbin.com/nadevedose/2/edit?html,css,output


Верно.

> 5 http://jsbin.com/civowoweye/edit?html,css,output


Все правильно.

>>177715

Повторение - мать учения.

>>177756

Да, но придется изучить Си, и написать свой веб-фреймворк.
469 1183551
>>177400

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

>>177630

> 1 http://jsbin.com/mofepusiko/edit?html,css,output



Ок, верно. Для вертикального выравнивания одной строки есть трюк - сделать line-height равной высоте блока.

> 2 http://jsbin.com/zofidemusi/edit?html,css,output


Ок, верно, хотя стоило бы учесть еще ширину border - он тоже место занимает.

> 3 http://jsbin.com/nofuwotoka/edit?html,css,output


Вместо цифр лучше использовать слова, например:

&lt ;

Полный список HTML-мнемоник: https://dev.w3.org/html5/html-author/charref

Попробуй там найти свои символы. А то цифры человеку читать очень трудно.

> 4 http://jsbin.com/nadevedose/2/edit?html,css,output


Верно.

> 5 http://jsbin.com/civowoweye/edit?html,css,output


Все правильно.

>>177715

Повторение - мать учения.

>>177756

Да, но придется изучить Си, и написать свой веб-фреймворк.
470 1183552
>>177856

Во-первых, ООП не надо "присобачивать", если ты не видишь, где он нужен, то не надо использовать.

Во-вторых, странно, что ты не видишь, где можно применить ООП. ООП позволяет представлять всякие сущности в виде объектов, и в вебе этого предостаточно - Пользователь, Пост, Комментарий например - прекрасно представляются в виде объектов. Также в виде объектов можно представлять сервисы, которые что-то делают с этими сущностяями. Ну например, ты можешь сделать класс СервисПостов с методами:

- найтиПостПоid(id)
- найтиВсеПостыПоУсловию(сортировка, offset, limit)
- найтиПостыПоТегу(тег)
- получитьЧислоКомментариевКПосту(пост)
- удалитьПост(пост)
- сохранитьПост(пост)

И так далее.

Пример ООП кода есть например в моем уроке по MVC: https://github.com/codedokode/pasta/blob/master/arch/mvc.md - изучи его.

> Можно же просто статическими функциями реализовывать все требования к сайту.



Статические методы ничем в принципе не отличаются от обычных функций. И соответсвенно получается такой же спутанный воедино код. Ты можешь почитать урок https://github.com/codedokode/pasta/blob/master/arch/di.md где описаны некоторые недостатки этого подхода.

Главный недостаток - весь код становится намертво спутан и ты не можешь вынести какие-то функции для использования в другом проекте. Не можешь их тестировать.

Пример, у тебя есть метод конвертации валюты:

public static function convertDollarToRouble(float $dollars): float { ... }

В нем идет обращение к внешнему сервису, с которого скачивается текущий курс. А как протестировать этот метод без обращения к тому сервису?

Чтобы иметь возможность подменять ответ от внешнего сервиса, мы должны вынести "скачивальщик курса" из кода функции и сделать его отдельной сущностью: либо анонимной функцией

function ($currency): float {}

либо интерфейсом:

interface RateDownloader()
{
public function downloadRate($currency);
}

Эта функция или объект становятся "зависимостью" метода convertDollarToRouble (зависимость - это то, от чего зависит работа функции). Теперь, когда мы выделили зависимость, мы должны как-то ее передать ("внедрить"). Это можно тоже сделать по-разному, например, передать как аргумент:

convertDollarToRouble(RateDownloader $rateDownloader, float $dollars): float { ... }

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

class Converter
{
public function __construct(RateDownloader $rateDownloader) {}
public function convertDollarToRouble(...) ..;
}

Вот мы и получили ООП с DI. Прочитай урок по DI, там подробнее описано.
470 1183552
>>177856

Во-первых, ООП не надо "присобачивать", если ты не видишь, где он нужен, то не надо использовать.

Во-вторых, странно, что ты не видишь, где можно применить ООП. ООП позволяет представлять всякие сущности в виде объектов, и в вебе этого предостаточно - Пользователь, Пост, Комментарий например - прекрасно представляются в виде объектов. Также в виде объектов можно представлять сервисы, которые что-то делают с этими сущностяями. Ну например, ты можешь сделать класс СервисПостов с методами:

- найтиПостПоid(id)
- найтиВсеПостыПоУсловию(сортировка, offset, limit)
- найтиПостыПоТегу(тег)
- получитьЧислоКомментариевКПосту(пост)
- удалитьПост(пост)
- сохранитьПост(пост)

И так далее.

Пример ООП кода есть например в моем уроке по MVC: https://github.com/codedokode/pasta/blob/master/arch/mvc.md - изучи его.

> Можно же просто статическими функциями реализовывать все требования к сайту.



Статические методы ничем в принципе не отличаются от обычных функций. И соответсвенно получается такой же спутанный воедино код. Ты можешь почитать урок https://github.com/codedokode/pasta/blob/master/arch/di.md где описаны некоторые недостатки этого подхода.

Главный недостаток - весь код становится намертво спутан и ты не можешь вынести какие-то функции для использования в другом проекте. Не можешь их тестировать.

Пример, у тебя есть метод конвертации валюты:

public static function convertDollarToRouble(float $dollars): float { ... }

В нем идет обращение к внешнему сервису, с которого скачивается текущий курс. А как протестировать этот метод без обращения к тому сервису?

Чтобы иметь возможность подменять ответ от внешнего сервиса, мы должны вынести "скачивальщик курса" из кода функции и сделать его отдельной сущностью: либо анонимной функцией

function ($currency): float {}

либо интерфейсом:

interface RateDownloader()
{
public function downloadRate($currency);
}

Эта функция или объект становятся "зависимостью" метода convertDollarToRouble (зависимость - это то, от чего зависит работа функции). Теперь, когда мы выделили зависимость, мы должны как-то ее передать ("внедрить"). Это можно тоже сделать по-разному, например, передать как аргумент:

convertDollarToRouble(RateDownloader $rateDownloader, float $dollars): float { ... }

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

class Converter
{
public function __construct(RateDownloader $rateDownloader) {}
public function convertDollarToRouble(...) ..;
}

Вот мы и получили ООП с DI. Прочитай урок по DI, там подробнее описано.
471 1183558
>>183550

>Код типичного проекта на Питоне ничем не читабельнее PHP, например https://github.com/rg3/youtube-dl/blob/master/youtube_dl/utils.py



https://www.youtube.com/watch?v=RE0G2b3-QsA
472 1183570
Не знаю где спросить про CMS. Кто нибудь пробовал использовать вместе с разработкой?
Или смысла нет какой из них использовать, мол они все одинаковые по сути?
473 1183614
>>183570
Знаю точно что есть modx - там больше ориентированности на код, нужно все шаблончики и сущности в ручную прописывать, что бы потом юзер смог типовую сущность в админке создать и заполнить например накликиванием. В каком-нибудь wordpress же знаю что для тебе заранее заготовлены некие сущности такие как page, posts ну и так далее, и админка заранее под все это заточена. Там вообще всё сделано так, что простой бложек или сайт о компании из нескольких страничек можно накликать по сути в админке и подцепить поверх понравившуюся тему там же.
474 1183621
>>183614
Сейчас под WP есть куча писек, которые и интернет-магазин в пару кликов помогают создать. Многие макаки умудряются зарабатывать на создании сайтов никак не залезая в код, на любой чих есть плагины. Другой вопрос, конечно, в том, что если плагина на чих всё-таки нет и нужно слегка что-то изменить, то макак обделается. Да и на производительности это сказывается не очень хорошо, конечно же.
А modx да, он как CMF позиционируется. Еще Drupal вроде ёба в этом смысле, но не знаю, жив ли он еще.
475 1183636
>>183621
Друпал вроде как жив, там новая версия выкатилась вроде как год назад с ооп-ориентацией. У нас в городе есть галера которая чисто на друпале ориентируется и они периодически проводят даже обучалки что бы новых макакичей рекрутировать.

>Другой вопрос, конечно, в том, что если плагина на чих всё-таки нет и нужно слегка что-то изменить, то макак обделается.



Мне кажется, что это стереотип из той же оперы что и на пхп одни макаки работают и вообще это язык хуевый. Я вот вчера скачал себе wp, и там заходишь в их кодекс и там везде в документации вплетены гайды о том что писать в коде для чего и думаю что многие обучалки тоже расскажут о том как и что писать, так что любая макака спустя пару недель будет просто вынуждена хотя бы в шаблонах покопаться, а там уже и впшные функции надо знать и так далее.
476 1183674
Есть такая функция переворота UTF8 строки

function utf8_strrev($str){
preg_match_all('/./us', $str, $ar);
return implode(array_reverse($ar[0]));
}

Что значит якорь us в регулярки? Это все не ASCII символы?
Как вообще распутывать чужие регулярки.
160507.jpg138 Кб, 620x408
477 1183696
>>183550

>А зачем там \b в начале?


Регулярка уровня Б
478 1183699
>>183614
>>183621
>>183636
Спасибо товарищиъ, попробую WP еще, неплохие вещи тоже на нем делают.
Да я писал на Drupal, худая документация пока.
479 1183700
Как вам наовый принцип программирования: DRYOLO
расшифровывается как: Do Repeat YOLO
Состоит в дублировании кода везде, где это возможно, каждый инстанс должен иметь уникальные изменения.
481 1183746
>>182636

>Обычно используют системы сборки типа webpack для такого.


А можно как нибудь без вебпака обойтись? У меня из жс-а просто только плеер нужен. Например устанавливать через композер или npm, и затем баш скриптом необходимые для продакшена файлы в публичную папку перетаскивать.
15213995942770.jpg121 Кб, 890x892
482 1183769
Сап анонимусы, возник интересный вопрос.

У нас есть статическая страница c подключенным jquery. После заполнения формы мы делаем ajax-запрос с параметрами к php, а оттуда по прошествии некоторого времени приходит ответ выстраиваемый в хтмл таблицу.

Как я понял php-файл при работе с ajax работает сам по себе, без участия браузера пользователя. Если он покинет страницу, то выполнение скрипта на сервере продолжится и без него?

Если моя теория верна даем печеньки посетителю, пусть он уходит. Результат выполнения скрипта мы отправляем в БД с привязкой к кукам посетителя. При возвращении, показываем из БД результат выполнения по кукам. Это вообще возможно?
483 1183776
>>183636
Ты просто начитался всяких ВЫЕБУ ТВОЙ РОТ ЗА ТАКОЙ СТИЛЬ КОДА и не представляешь, какой ад творится в днищесегменте фриланса. Некоторые петухи вообще на одних конструкторах живут, а ты удивляешься тому, что они сайты на визуальных письках вроде visual composer делают абсолютно не вникая в код.
484 1183777
>>183776

>Некоторые петухи вообще на одних конструкторах живут.



Сначала подумал что они вместо функций создают под каждую функцию класс, в котором есть только конструктор, и потом уже этим говном оперируют в коде.

Потом таки допер в чем дело.
485 1184055
>>175636
Наркоманы. Не понимают очевидной шутки. НО БОЛЕЕ ТОГО, УЖЕ МАНЯФАНТАЗИЙ СЕБЕ ПРИДУМАЛИ ГДЕ ОП С ЕРОХОЙ ВСТРЕЧАЕТСЯ!
486 1184180
>>184055
Ты наверное не очень умный
В каждой шутке есть доля шутки
1377758402688.jpg184 Кб, 1280x1432
487 1184213
>>174695 (OP)
Привет.

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

Что нужно знать джуну пхп? Какой базис? Что уметь делать?
488 1184214
>>184213

>за ответов на вопросо



за ответом на вопрос

быстро фикс
489 1184218
Как можно проверить, актуальные ли у меня куки или нет?
Это через curl делается?
490 1184223
>>184213
Для начала: ВСЕ из онлайн-учебника ОП-а - НЕОБХОДИМО
491 1184225
>>184213
Двигайся дальше и углубляйся в JS, зачем тебе пхп макакинг?
492 1184228
>>184225
А если человек не хочет каждый год учить новый фреймворк?
493 1184241
>>184228
А что плохого в новых фреймворках?
494 1184265
>>184055
Пацаны, ероха подкатывающий к ОП-тян детектед, ибо очевидно пытается выставить нашу теорию в безмуном свете, что бы замести следы. Типа как когда вор громче всех кричит: "лови вора!".
495 1184424
Как то похуй какого ты пола или царства, я кот например, хули, попытайтесь доказать обратное.
496 1184427
>>183769

>Если он покинет страницу, то выполнение скрипта на сервере продолжится и без него?


Да

>Это вообще возможно?


Да
497 1184429
Друзья, нет желания у кого-то вкатиться вместе с 0 по сути.
Или взять меня так скажем, под крыло и помочь начать. Хорошо умею в математику, вроде не туп
498 1184514

>1184429


Можно было бы. Я вот начинал и продолжаю без ментора, всё сам, ахах, а было бы гораздо быстрее, если бы можно было спросить кого-то. Иногда тупо не знал как у гугла спросить даже.
499 1184515
Отличный тред, остаюсь тут, ребятки :d
500 1184516
>>184429

>Хорошо умею в математику


Но при чём здесь PHP?
ДВАЧ 501 1184517
Хм, кто поопытней, может подскажете, какую архитектуру использует двач? Просто заметил, что страницы по старому принципу подключаются и везде есть .html . Было бы интересно почитать.
502 1184519
>>184517

>страницы по старому принципу подключаются и везде есть .html


Я могу настроить mod_rewrite так, что все урлы на моём сайте будут иметь вид /page.html а под капотом будет какой-нибудь моднявый Yii.
503 1184520
Господа, есть у кого-то код решения задачи на регулярки, которая разбирает телефонные номера?
504 1184521
>>184519
а, ну хотя, я забыл про .htaccess XD
505 1184523
>>184225
В JS треде настолько токсичные аноны, что за полтора года и наверное сотню вопросов, я получил только посылы на три буквы. Так что нет.
506 1184526
>>184523
Мне кажется, что тут так во всех тредах. Только на SO всё хорошо, ибо модерация.
Собеседование 507 1184535
Кто подскажет, какие вопросы/тесты на собеседованиях чаще всего бывают по php? Скажем, на джуниора.
508 1184538
>>184520
Не нужно, написал сам.
https://regex101.com/r/i60sEK/1
509 1184543
Аноны, а нормально ли отправлять изображения по http, читая их в строку, преобразуя, например, в base64, затем отправляя как обычный текст, на том конце расшифровывая и опять собирая в изображение?
Разбирал свой старый проект и нашёл там такое странное решение. Почему я вообще так сделал - непонятно. Видимо, была причина.
510 1184544
>>184535
Вопросы как правило связаны со знанием синтаксиса, ооп, шаблонами. Если попадется мудак с матаном головного мозга, то заебет вопросами математического характера. Будет самоутверждаться и потом всем говорить, что ты говно итебя взяли только потому что кто то должен набирать код.

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

Говорят, остались еще пидоры, которые ебут мозги загадками на внимательность и сообразительность. Забыл как это точно называется что то типа тест на когнитивные возможности. Вопрос про бейсбольную биту и мяч за 1 доллар и 10 центов и прочие пидорские загадки.

А, ну будь еще готов к приколам, дадут тестовое задание и ты его должен будешь решать на листочке. Типа напишите нам функцию парсинга входных данных с такими то критериями. Не ссы и говори, чтобы дали комп с ИДЕ для решения, ибо вентел на хую работать в конторе, которая заставляет писать код на листочке.
511 1184547
>>184535
https://github.com/codedokode/pasta/blob/master/interview-tasks.md
Ну и ты отличай, что PHP-разработка бывает разной, в веб-студиях у тебя будут спрашивать опыт работы с CMS и умение верстать, в нормальных конторах - фреймворки, вопросы по БД по алгоритмам. Вот этот >>184544 в каких-то днищеконторах собеседовался, надеюсь ты в такие не попадёшь.
512 1184548
>>184535
https://drive.google.com/file/d/0B8VvT_dbtrYMN1NKSUZXRlo4QUk/view

Вот тестовое задание одной фирмы из моей мухосрани. Я на самом деле не пойму даже обязательного задания, просто блять не представляю как это должно выглядеть. в виде таблицы, карточек, еще какого-то говна
513 1184553
>>184547
Пошел на хуй, пидор. А если серьёзно, то я с этой ебалой сталкивался в середине 00-х и до ~2010 года, потом перекатился в другую сферу, тк заебало. Сейчас уже может все по другому, ибо рыночек порешал и квалификация не так важна. Сечёшь, всегда найдется обезьянка готовая работать чуть ли не за еду.
514 1184683
>>184228
Будто на пхп не надо каждый год учить фреймворк.
515 1184685
Просто хочу спросить, нужно ли разрабу на PHP знать паттерны проектирования? Всякие синглтоны и прочий матан.
516 1184686
>>184519

> моднявый Yii.


Оооо, так иии моднявый.
Вообще же есть ларавел, щас он модный.
Уайии уже лет 6
517 1184687
>>184685
Да, ещё как, лол.
Хотя паттерны взаимодействия с БД посмотри.
518 1184689
>>184225
намек на ноду?
519 1184690
>>184685
ОЧЕНЬ! Современный сайт без паттернов - каша.
520 1184691
>>184548

>https://drive.google.com/file/d/0B8VvT_dbtrYMN1NKSUZXRlo4QUk/view


Посмотрел, чет дохуя хотят. Эту залупу в полном виде неделю минимум писать.
Это норма?
Плюс важнее, мне кажется, не что, а как. Тот же фронт лучше бы замутить на SPA, а не на голом хтмл с jquery-аякс-запросами. Но причем тут ебаный пхп, лол?
521 1184692
>>184690
Нет, просто если раньше ты писал говно с минимумом знаний - это был эдакий сайт.
А сейчас это просто паттерн такой KISS называется.
Ну и тоже самое с остальным. Фабрики и прочее.
522 1184697
>>184692
>>184690
Окей, но если скажем я пишу плагин под вордпресс или сайт на laravel мне всё ещё нужны паттерны?
К тому же, много ли сейчас чего вообще делается на чистом похапе? Я думал чаще всего просто юзают фреймворки
523 1184699
>>184697

>мне всё ещё нужны паттерны?


Да.

>много ли сейчас чего вообще делается на чистом похапе? Я думал чаще всего просто юзают фреймворки


И то юзают и то. Тут тебе не JS, где можно вообще фрэймворк выучить без знаний JS, тут надо знать PHP чтобы порой исходники вордпресса править.
524 1184700
>>184697
Вордпресс - лютейший говнокод.
Если пишешь на фреймворке, то да, он нехуево так задает тебе архитектуру, как правильно прогать. Но лучше таки иметь представление, хотя бы.

Если что-то разрабатывается с нуля, то без паттернов у тебя получится лапша, не поддающаяся дальнейшим улучшениям и хуй пойми как работающая
525 1184705
>>184700

>Вордпресс - лютейший говнокод.


Пруфы? Ты что, все его исходники отмониторил лол? Да, он ебануться какой тормозной. Но весь PHP такой, разве нет?
526 1184708
>>184705

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


Че еще пизданешь?
527 1184714
>>184708
Что я такого спизданул, еблан? Я тебя спросил, почему ты считаешь его говнокодом.

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


Вот твои еблано-аргументы, значит. Но блять почему если код не июзает неймспейсы, то это сразу говнокод? И блять PHP по дефолту был не строго типизорованым, что же получается PHP по роду своему вынуждает писать говнокод, так выходит?
528 1184716
>>184714

> PHP по роду своему вынуждает писать говнокод


Да, прикинь?
На языке без строгой типизации очень сложно, если сказать невозможно, что-то большое и сложное написать.
Даже js-дауничи начали что-то подозревать и выкатили typescript.

А еще в пхп есть такие штуки, как fatal error'ы (вместо исключений)(и даже появление исключений не привело к отказу от тонн старого говна, в итоге современные методы кидают исключения, а старые ерроры и предупреждения).
А еще функция в пыхе, ВНЕЗАПНО, из-за его нестрогой типизации может вернуть тебе совершенно любое говно вместо того, что ты ожидаешь.
Например, повсеместно используемая PDO:fetch() вернет тебе FALSE вместо массива, если запись не найдена.
То есть ждешь ты такой массив, а тебе фолс ебаный прилетел в ебало.
Как было бы сделано в норм языке: или пустой массив или исключение.
Но это же похапе.
И такое дерьмище там чуть ли не в каждой стандартной функции.
Хоть и стараются в новых версиях return одного типа делать.

И еще есть вещи, вынуждающие писать на пхп говно-код.
Например, там нет нормальных структур данных. Только массив.

мимо пхп-фрилансер
529 1184719
>>184716
А еще многопоточность только вчера завезли
530 1184721
>>184716

>повсеместно используемая PDO:fetch() вернет тебе FALSE вместо массива, если запись не найдена. То есть ждешь ты такой массив, а тебе фолс ебаный прилетел в ебало. Как было бы сделано в норм языке: или пустой массив или исключение. Но это же похапе. И такое дерьмище там чуть ли не в каждой стандартной функции. Хоть и стараются в новых версиях return одного типа делать.


Что мещает юзать if (!PDO::fetch()) die()?
Типо это нормально, наоборот более юзабельно, нет?

>там нет нормальных структур данных. Только массив.


Лол что? PHP насколько я знаю позволяет оперировать любыми данными. Там же есть ассоциативные массивы аки словари в питоне. ЧТо же тебе ещё надо?
531 1184722
>>184721

>Что мещает юзать костыли?


>Вот дед говно ел и ты ешь. Что тебе еще надо? Не жили богато - неча и начинать

532 1184723
>>184722
Ты дурачек что ли? Какие костыли ебать? Это старинное условие ещё со времен Си.
image.png5 Кб, 186x202
533 1184730
https://ideone.com/aP0F3B

Почему не срабатывает цикл, если свойство у json-объекта есть?
534 1184733
>>184705

> Но весь PHP такой, разве нет?


Нет.
535 1184734
>>184708
Если ты используешь нэймспейсы - ты говнокодер. И неважно какой язык. Просто смирись.
536 1184737
>>184719
Где ты в PHP будешь её использовать? Если ты в многопоточные расчёты хочешь, ты не совсем ту платформу выбрал.
537 1184739
>>184734
Я вот на Хекслет когда сидел видел лекцию про неймспейсы и нихуя не понял, что это за говно.

Может кто-нибудь объяснить, что это?
538 1184740
>>184733
Ну в смысле нет? Это интерпретируемый язык. И такой хуйни как у питона -- PyPy, насколько я знаю у PHP нет. Ну и с какого тогда хуя PHP -- не тормоз?
539 1184741
>>184716

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


>Я написал функцию, а она не работает ряяяя


Про тестирование не слышал?

>На языке без строгой типизации очень сложно, если сказать невозможно, что-то большое и сложное написать.


Джависты не жалуются (Именно Java, а не JS).

>Например, повсеместно используемая PDO:fetch() вернет тебе FALSE вместо массива, если запись не найдена.


Тоесть по твоему она должна вернуть запись если её нет? Наркоман штоле? Правильное поведение.

>Как было бы сделано в норм языке: или пустой массив или исключение.


С чего вдруг? Код то работает. Это не проблемы программы что у тебя руки кривые и ты ищешь то, чего нет. Исключение ты можешь сам повесить.
Короче как я понял ты просто неопытный ньюфаг который не понимает зачем он вообще в программисты понаехал.
540 1184742
>>184722
Что ещё спизданёшь? Что автотест костыли? Что try catch костыли? if у него костыль. Одна история ахуительнее другой просто.
541 1184743
>>184741

>Тоесть по твоему она должна вернуть запись если её нет? Наркоман штоле? Правильное поведение.


Нет, он видимо имеет ввиду что если записи нет то функция сама должна раисить исключение. Ленивый он, ебать.
542 1184746
>>184740
Он не торможной. Если у тебя в коде рекурсия через рекурсию - да. А если говнокода нет, всё отлично работает. МОжешь даже тесты погуглить на последние версии. А то, что вордпресс тупит - ну вообще хз, стандартно на него навешают аддонов, плагинов, потом "Ну это PHP тупит". Ну конечно. Чёж у меня 10 лет сайт висит, даже не упал ни разу. А у вас тупит всё. Руки кривые растут из жопы.
543 1184749
>>184739
Говно самое настоящее. Вроде как ты используешь переменную Vasya. А какой-то чел уже в своём фрэймворке использует переменную Vasya. Ну вот подрубил ты фрэймворк, и стало у тебя 2 васи. Чтобы конфликта небыло, надо нэймспэйсы использовать. Это типа говнокодерский выход. А на самом деле надо
1 Нормально именовать переменные.
2 Определять область их видимости. Если у тебя счётчик i используется в 1 функции, а видит его вся прога - это очень плохо.
544 1184750
>>184746

>Он не торможной.


Нет братан, PHP -- нацеленный на веб исключительно тормозной язык(ибо интерпретируемый). Ну в сравении с Си или с Питоном это так.
545 1184752
>>184749
Лол, а разве такие однотипные переменные не в массивы запихивать или там в объекты?
546 1184753
>>184749

>Определять область их видимости. Если у тебя счётчик i используется в 1 функции, а видит его вся прога - это очень плохо.


Бля а что ты определить область видимости что мы юзаем? Правильно, класс, функции и неймспейсы блять. Неймспейсы нам помогают определить облать.
547 1184754
>>184730
Бамп вопросу!
548 1184756
>>184743
Так этож не её обязаность. Странный какой-то. Там же суть в том, чтобы либо вернуть порцию данных, либо сообщить что данных нет. Возвращать массив нулевых значений - это как-то вообще тупость. Вот тебе вернули false, ну сам массив нулевых значений создай. Делов то.
549 1184760
>>184750

>тормозной язык


Если что, интерпретатор 7 пхп - самый быстрый интерпретатор из существующих, дебил.
550 1184761
>>184752
Всмысле? Зависит от задачи. Откуда я знаю что ты хочешь.
>>184753

>Неймспейсы нам помогают определить облать.


Только когда обосрамс произошёл. Класс и функции должны справляться без неймспэйсов.
551 1184762
>>184750

>Ну в сравении с Си или с Питоном это так.


Ты видимо на серьёзных проектах с питоном не работал. Питон для веба - тот ещё тормоз. В своё время перевёл контору на PHP с Питона (2013 год примерно), и билинговая система ускорилась в 7 раз.
552 1184763
>>184760
Лол что? Ну окей может быть я не знаю. Но факт остается фактом PHP интерпретируется. Следовательно это тормоз тот ещё. .
553 1184765
>>184763
Прочитай про HHVM например, который почему-то медленнее 7 PHP. Хотя казалось бы C++ и все дела.
554 1184766
>>184762
Братан я вообще новичек-теоретик.
Только скажи - ты юзал PyPy?
555 1184768
>>184766
Нет, банально потому, что когда я с ним работал, никто его не юзал, ибо был он в бета версии. Но веб сервера на C++ и на C в 2007 ещё писал. Годнота. Если не считать что можно сервер положить в даун одном лёгким движением руки.
556 1184773
Я вот не очень-то люблю PHP. Python куда лучше. Пишу на PHP только потому что кушать очень хочется.
557 1184777
>>184773
Обожаю PHP, сейчас решил JS изучить - вот где говна полон чан.
558 1184779
>>184777
Сложение строк как конкатенация, но вычитание КАК МАТ ОПЕРАЦИЯ! За что, господи за что?
Каждая переменная - ГЛОБАЛЬНАЯ
559 1184781
>>184779

>Каждая переменная - ГЛОБАЛЬНАЯ


Это где это такая поебень? В жс? Там же вроде замыкания и вся хуйня
560 1184782
>>184781
>>184779

>Это где это такая поебень? В жс?


Вы там поехали? Из переменные без var и let объявляете?
561 1184783
>>184742

>if у него костыль.


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

Как ты додумался вообще про if говорить, ты на нулевом уровне абстракции мыслишь?
562 1184784
>>184782

>Другие языки "Обьяви специально что переменная глобальная"


>JS "Обьяви специально что переменная НЕ глобальная"

563 1184785
>>184783

>на нулевом уровне абстракции мыслишь?


Ты еблан совсем братуха? О чем ты блять? Ифы это часть языка. Ты типо не юзаешь их когда проектируешь алгоритм? Нулевой уровень абстракции блять. Лол
564 1184786
>>184783

>Как ты додумался вообще про if говорить


Это ты говоришь. Я поэтому и упомянул, что у тебя увидел и удивился.

>Маняконструкции, обходящие эту проблему - костыли.


Потому-что нет никакой проблемы. То, что ты не способен додуматься, до того что для всех очевидно и само собой - твои проблемы.
565 1184788
>>184783

>if это абстракция


Золотой фонд цитат PHP треда.
566 1184790
Аноны, у меня тут вопрос по АРХЕТИКТУРЕ. Все еще делаю файлообменник. Сейчас опишу немного весь сценарий, чтобы было проще.
- У меня есть сущность Файл(базовая сущность), и наследующие ее Изображение, Видео, и Аудио. (Сделано это для того чтобы рендерить разные шаблоны под видео, аудио и "обычный" файл)
- Создаю конкретные сущности фабрикой на лету.
- Дальше мне нужно отправить в очередь сообщение, если это медиа файл, чтобы потом этот файл расковырять, сконвертировать, да что я захочу.

И вот тут у меня вопрос, я могу все еще свитчом вызывать нужные методы в зависимости от типа сущности, или, как я думал, использовать ПОЛИМОРФИЗМ, сделать интерфейс например Queueable с каким-то handle методом, мои сущности будут его имплементировать, и потом одной строчкой отправлять в очередь сообщение, в котором буду передавать например id, воркер будет вызывать handle метод. Но тут проблема, моя сущность это domain object, в ней не должно быть никакой логики вроде как, да и вообще в любой точке программы мне не нужен метод handle, который по сути выполняется всего один раз после загрузки файла. Не ебать мозг и использовать свитч/ifelse ?
567 1184792
>>184734
Вы тут совсем поехавшие? Говорить что неймспейсы нинужны - это какой-то новый уровень долбоёбизма.
>>184737
Ещё один с мантрой про "нинужно".
>>184741

>Джависты не жалуются (Именно Java, а не JS).


>Java - самый строготипизированный язык из популярных, с таким уровнем типизации, что пыху снится только во влажных мечтах


Что, мать твою, ты такое несёшь?

Долбоёбов полон тред.
568 1184795
>>184788
Это не я сказал, а ты придумал.
Речь шла про то, что сам факт того, что метод может вернуть разные типы данных - это хуево.
Затем чел запостил говнокод, который "обходит" эту проблему в виде конструкции if.
На что я ответил, что подобные конструкции (любые, которые пытаются проверять, какой тип данных вернул метод это должно было быть сделано на этапе объявления возвращаемого типа данных этого метода) - костыли.
Затем пришел очередной довен в виде тебя с охуительной "цитатой" собственного сочинения.
569 1184801

>На языке без строгой типизации очень сложно, если сказать невозможно, что-то большое и сложное написать.



Тайпхинты в пхп не решают эту проблему? Кроме переменных можно на любой пердежь поставить тип принимаемых и возвращаемых значений. На переменные и так смысла нет их ставить особо, все равно через конструктор их заполняешь. осталось только перенести весь код в интернете на пхп7 и переписать с тайп хинтами
570 1184807
>>184801

> Тайпхинты в пхп не решают эту проблему?


Отчасти решают. Тайп-хинтинг - это большой шаг вперёд для php.
Но один хуй, не вся стандартная либа на них переписана.
Да и продвинутых конструкций вида HashMap $map = new HashMap<ArrayList<String>>() один хуй нет, ибо нет ни нужного уровня типизации, ни самих структур данных, лол
571 1184824
>>184807

>HashMap $map = new HashMap<ArrayList<String>>()


Что-то на эльфийском, не могу прочитать. Можно это как-то реализовать через интерфейсы? Да и вообще, зачем из пхп делать худшую версию джавы?
2018-05-0605-45-28.png168 Кб, 352x251
572 1184833
Аноны, как с помощью figure и figcaption сделать такую подпись?
1525555746151.jpg8 Кб, 446x136
573 1184865
574 1184901
>>184743
Я думаю, что имелось ввиду, что функции, от которой ожидаешь массив, логично было бы вернуть массив, а не false.
Если записи не были найдены - возвращается пустой массив.

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

Просто заебало каждый раз проверять результат. А если этого не делать, то, передай ты это дело в какой-нибудь foreach, получишь предупреждение о том, что invalid argument suplied for foreach.

А если функция возвращает пустой массив, то таких проблем нет, предупреждений нет. Профит.
575 1184915
>>184901
Не логичнее возвращать null если записи не были найдены? Отсутствие записей = отсутствие данных = null.
fetchAll кстати возвращает пустой массив, хуй их поймешь.
576 1184925
>>184915
Походу я не прав. Перечитал своё сообщение и подумал, что ведь действительно правильно возвращать false вместо массива.
Ты когда заказываешь бургер в пиццерии, получаешь ответ о том, что бургеров у них нет, а не пустую коробку, верно? Это правильно поведение.
Да и сувать непонятную переменную в цикл, без проверки, тоже неправильно, наверное.

Хотя, в моём любимом C++, языке со статической типизацией, таких проблем нет, т.к. если функция должна вернуть int, то она его вернёт. Обосрётся, но вернёт int ну или выкинет исключение, но это другая история.
577 1184954
нахуя люди используют этот говно язык?и продолжают вешать на него всякие функции без изменения всей структуры?
20!8 год на дворе
578 1184963
>>184954

>без изменения всей структуры?


Как там в 2008?
579 1184996
>>184963
в тот же уебищный синтаксис и семантика
580 1184999
>>184996

>уебищный синтаксис


>C like


Нахуй послан, школьник.
581 1185002
>>184999
ну и хуле почти от него плюются?
582 1185003
>>185002
От кого плюются? Количество языков с таким синтаксисом настолько огромно, что проще перечислить кто не с ткаим синтаксисом. Критика синтаксиса - это просто сразу нахуй. Сразу видно что ты из b к нам потраллить понаехзал, а приграммированием и не занимался ни разу. Синтаксис у него, ахуеть вообще.
583 1185005
>>185003

>От кого плюются?


от его устарелости и говна мамонта,который он тащит с собой из начала 00
584 1185007
>>185005

>из начала 00


Не кормите троля.
585 1185011
>>185007
почему сразу троль?
image.png19 Кб, 471x163
586 1185034
хехехе, кто-то еще ждёт JIT-компилятор в версии PHP8, чтобы начать юзать тайпхинтинг? Кстати, в 2018м же должен выйти PHP7.3
587 1185036

>>начать юзать тайпхинтинг


Имею в виду, что будет больше смысла в нём, т.к. сейчас он не даёт особого прироста к производительности.
588 1185044
>>185034
Кто говорит такую ересь, походу совсем не понимает зачем PHP нужен. JIT он профиты даёт не для веба, зачем он тут? Какую задачу он решает?
image.png70 Кб, 579x215
589 1185049
>>185044
Да потому что, PHP интерпретируемый, что по определению уже снижает производительность. JIT-компиляция должна принести трансляцию кода в двоичный, соответственно можно нормально работать с системой, нет посредников. Тут уже будут иметь смысл строготипизированные программы. Потому что сейчас юзать тайпхинтинг смысла не особо-то много.
590 1185051
>>185044
JSники что-то не жалуются на уже введенный JIT
591 1185066
>>185051
>>185049
Какую задачу это решает?
592 1185068
>>185007
давай пример доказательства?
593 1185074
>>185066
Задачу повышения производительности медленного слоника, как минимум, внося смысл в тайпхинтинг для php.
Почитай, может поймешь
https://stackoverflow.com/questions/32940170/are-scalar-and-strict-types-in-php7-a-performance-enhancing-feature
594 1185103
>>184901
Хоть один нормальный человек в треде
595 1185107
>>185049

>JIT-компиляция


>в двоичный


>сейчас юзать тайпхинтинг смысла не особо-то много


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


Какие же конченые дауны в этом треде, я просто в ахуе
596 1185122
>>184901

>что функции, от которой ожидаешь массив, логично было бы вернуть массив, а не false.


Если ты ожидаешь от неё массив, ты чего-то не понимаешь в программировании.
597 1185124
>>185107
Тайпхинтинг есть в PHP7 и старше.
598 1185129
>>184901

>заебало каждый раз проверять результат.


Всмысле каждый раз. Написал функцию или вообще в MVC пропустил. 1 раз написал и забыл про это. Ты вообще о чём? Какой каждый раз то?
599 1185131
>>185074
Ясно. Пытаешься решить то, сам не знаешь что. Тоесть JIt типа нужон но ты сам не знаешь зачем.
>>185068
Какую задачу это решает?
600 1185136
>>185107
А не ты ли даун? Компиляция подразумевает трансляцию высокоуровневого кода в машинный язык, для того, чтобы блять твой компьютер понял что делать. А PHP интерпретируемый на данный момент. ПОЧИТАЙ ЧТО ЭТО ТАКОЕ.

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


Я и сказал "причин не особо много". Только ради структурированного кода и стоит использовать. Больше тебе он ничего принесет.
Посмотри тесты или проведи их сам. ПОЭТОМУ Я И ОСВЕТИЛ ТЕМУ JIT'а. Который и даст буст к пёрфоменсу, сука.
601 1185137
>>185131
Вот по-твоему, зачем ВК разработали KittenPHP?? ПОДУМАЙ, КАКУЮ ЗАДАЧУ ОНИ РЕШИЛИ, МММММ?
602 1185138
>>185136

>даст буст к пёрфоменсу, сука.


Опять какой-то буст. А текущей производительности мало? Какой тебе буст нужен? И так уже быстрее некуда.
603 1185139
>>185131
Тебе же сказали, это решает ПРОБЛЕМЫ С ПРОИЗВОДИТЕЛЬНОСТЬЮ.
604 1185141
>>185138
А ты проект побольше сделай и узнаешь :D
605 1185142
>>185137
Тоесть ты ответить на вопрос не можешь, а про Jit сказал пушо васян из 11 класса тебе говорил что это круто.
606 1185143
>>185139
У кого проблемы? Где? Пруфы, графики, скрины где именно PHP что-то там вешет. Почему у меня за 10 лет проблем с производительностью базы на 600 миллионов записей и PHP нет, а у залётного анона с laba1.php они вдруг есть?
607 1185144
>>185141

>пук


Ясно.
608 1185147
>>185143
омг, ты слишком консервативен. То есть, ты считаешь, что дальше некуда? Так? А что если я тебе скажу, что всё еще быстрее работать будет? :3
610 1185149
611 1185153
Здесь есть кто-то с опытом? Было бы неплохо иметь ментора, чтобы иногда можно было задать вопросик. Кто-то хочет взять ученика? XD
470-611 612 1185215
>>185044

> JIT он профиты даёт не для веба


В том числе и для веба, почему нет? Если у нас долгоживущее приложение. Или если разработчики смогут сделать кеш для JIT-кода в короткоживущих приложениях.

>>185066

Поясню для любопытствующих анонов.

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

Именно потому и нужна JIT - just-in-time (а не AOT - ahead-of-time) компиляция - он во время выполнения кода определяет типы значений в переменных, которые нельзя определить до выполнения, только методом статического анализа кода.

Машинный код - это команды, которые "понимает" и выполняет процессор (по факту это просто числа, которые хранятся в памяти и каждое число обозначает отдельную примитивную команду вроде сложения содержимого 2 ячеек памяти). Программы на строго типизированных языках вроде Си, Го, компилируются в машинный код.

Байт-код - это команды, которые "понимает" и выполняет интерпретатор PHP. Обычно PHP-программа превращается в байт-код, и его выполняет интепретатор. AOT или JIT-компиляция - это преобразование программы в машинный код для выполнения на процесссоре напрямую. AOT компиляция делается до выполнения программы, JIT - в процессе выполнения.

Например, если у нас есть PHP-функция:

function x($a, $b) { return $a + $b; }

То не зная типы $a и $b - сложно для нее написать оптимальный машинный код. Так как для сложения целых чисел в машинном коде нужна одна команда, для сложения дробных другая, для сложения массивов - нужно вызвать отдельную подрограмму. В случае, если один из аргументов - строка, ее надо сначала преобразовать в число. Плюс, есть еще варианты, что в переменных может быть null или false/true. И функция выше превращается в такую сложную последовательность команд:

если ($a или $b - массив), то { использовать функцию сложения массивов; }

если ($a - это строка), то { преобразовать ее в число; }
если ($a это null, false или true), { преобразовать их в число; }

если ($b - это строка) { то преобразовать ее в число; }
если ($b это null, false или true), { преобразовать их в число; }

если ($a это int, а $b это float) { преобразовать $a в float; }
если ($b это int, а $a это float) { преобразовать $b в float; }

если ($a и $b - типа float) { использовать операцию сложения дробных чисел; }
если ($a и $b - типа int) { использовать операцию сложения целых чисел; }

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

Теперь допустим, у нас есть вариант функции, где указаны типы данных:

function x(int $a, int $b) { return $a + $b; }

Здесь на первый взгляд типы заданы жестко, но это не так. PHP позволяет передать в качестве $a или $b также float, если в нем целое число, или string, строку с целым числом, и автоматически сконвертируем их в int (мануал ). Потому код получается такой:

если $a - это строка, то { попытаться преобразовать ее в int }
иначе если $a - это float, то { попытаться преобразовать ее в int }
иначе если $a не int, то { выдать ошибку }

то же самое для $b
использовать команду сложения целых чисел;

Это лучше, чем в прошлый раз, но не идеально. Указание declare(strict_types=1) в начале файла отключает эту конвертацию и позволяет сократить код до:

если $a не int, то { выдать ошибку }
если $b не int, то { выдать ошибку }
использовать команду сложения целых чисел;

JIT позволяет определить типы переменных. Во время выполнения кода он "запоминает" типы переданных переменных, а потом компилирует оптимизированную под эти типы версию функции в машинном коде. При этом в начале ставится проверка: если переданы переменные других типов, то вместо оптимизированной функции используется медленный, но универсальный неоптимизированный вариант.

JIT не бесплатен. Анализ и компиляция требуют времени. Потому обычно JIT применяется только к "горячим" функциям, которые вызываются больше определенного числа раз. JIT используется, например, в интерпретаторе JS, v8, который используется в Chrome.
470-611 612 1185215
>>185044

> JIT он профиты даёт не для веба


В том числе и для веба, почему нет? Если у нас долгоживущее приложение. Или если разработчики смогут сделать кеш для JIT-кода в короткоживущих приложениях.

>>185066

Поясню для любопытствующих анонов.

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

Именно потому и нужна JIT - just-in-time (а не AOT - ahead-of-time) компиляция - он во время выполнения кода определяет типы значений в переменных, которые нельзя определить до выполнения, только методом статического анализа кода.

Машинный код - это команды, которые "понимает" и выполняет процессор (по факту это просто числа, которые хранятся в памяти и каждое число обозначает отдельную примитивную команду вроде сложения содержимого 2 ячеек памяти). Программы на строго типизированных языках вроде Си, Го, компилируются в машинный код.

Байт-код - это команды, которые "понимает" и выполняет интерпретатор PHP. Обычно PHP-программа превращается в байт-код, и его выполняет интепретатор. AOT или JIT-компиляция - это преобразование программы в машинный код для выполнения на процесссоре напрямую. AOT компиляция делается до выполнения программы, JIT - в процессе выполнения.

Например, если у нас есть PHP-функция:

function x($a, $b) { return $a + $b; }

То не зная типы $a и $b - сложно для нее написать оптимальный машинный код. Так как для сложения целых чисел в машинном коде нужна одна команда, для сложения дробных другая, для сложения массивов - нужно вызвать отдельную подрограмму. В случае, если один из аргументов - строка, ее надо сначала преобразовать в число. Плюс, есть еще варианты, что в переменных может быть null или false/true. И функция выше превращается в такую сложную последовательность команд:

если ($a или $b - массив), то { использовать функцию сложения массивов; }

если ($a - это строка), то { преобразовать ее в число; }
если ($a это null, false или true), { преобразовать их в число; }

если ($b - это строка) { то преобразовать ее в число; }
если ($b это null, false или true), { преобразовать их в число; }

если ($a это int, а $b это float) { преобразовать $a в float; }
если ($b это int, а $a это float) { преобразовать $b в float; }

если ($a и $b - типа float) { использовать операцию сложения дробных чисел; }
если ($a и $b - типа int) { использовать операцию сложения целых чисел; }

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

Теперь допустим, у нас есть вариант функции, где указаны типы данных:

function x(int $a, int $b) { return $a + $b; }

Здесь на первый взгляд типы заданы жестко, но это не так. PHP позволяет передать в качестве $a или $b также float, если в нем целое число, или string, строку с целым числом, и автоматически сконвертируем их в int (мануал ). Потому код получается такой:

если $a - это строка, то { попытаться преобразовать ее в int }
иначе если $a - это float, то { попытаться преобразовать ее в int }
иначе если $a не int, то { выдать ошибку }

то же самое для $b
использовать команду сложения целых чисел;

Это лучше, чем в прошлый раз, но не идеально. Указание declare(strict_types=1) в начале файла отключает эту конвертацию и позволяет сократить код до:

если $a не int, то { выдать ошибку }
если $b не int, то { выдать ошибку }
использовать команду сложения целых чисел;

JIT позволяет определить типы переменных. Во время выполнения кода он "запоминает" типы переданных переменных, а потом компилирует оптимизированную под эти типы версию функции в машинном коде. При этом в начале ставится проверка: если переданы переменные других типов, то вместо оптимизированной функции используется медленный, но универсальный неоптимизированный вариант.

JIT не бесплатен. Анализ и компиляция требуют времени. Потому обычно JIT применяется только к "горячим" функциям, которые вызываются больше определенного числа раз. JIT используется, например, в интерпретаторе JS, v8, который используется в Chrome.
613 1185217
>>185107

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

>>185136

Не нервничай.

>>184954

Ну иди и пиши на том языке, который тебе нравится. Алсо, твой язык тоже отстой: https://habr.com/post/315152/

Это тред изучения PHP, а не тред для обсуждения вашей тонкой душевной организации, которой видите ли синтаксис не нравится. Валите на любой другой язык, если вам этот не нравится. Что вы тут забыли, флудеры? Мы тут делом вообще-то занимаемся.

>>184901

Да, логичнее всегда исопльзовать один тип возвращаемого значения. Как вариант - для объектов можно возвращать null. Так проще использовать результат функции, не добавляя лишние ифы.

>>184915

Если ты возвращаешь массив записей, то логичнее пустой массив. Если одну запись - то null.

>>184925

Нет, возвращать false как раз плохая идея так как ты теперь везде обязан будешь писать проверку на false. Лучше возвращать значения только одного типа. Также, можно использовать исключение - оно бы подошло в твоем примере с пиццерией. Так как ожидаемое поведение пиццерии - то, что бургеры она всегда может приготовить.
614 1185218
>>184833

<figure>
<img>
<figcaption>...</figcaption>
</figure>

Закрепляешь figcaption за счет абс. поз. относительно figure.

>>184824

Нет, тут нужны именно generic types, то есть обобщенные типы вроде "Коллекция объектов типа T" - Collection<T>. В примере выше надо читать так:

ArrayList<String> - список строк (на основе массива)
HashMap<ArrayList<String>> - хеш-таблица, содержащая списки строк.

Без generic тебе придется делать кучу одинаковых классов вроде IntCollection, StringCollection, SomeObjectCollection, итд.

>>184790

> У меня есть сущность Файл(базовая сущность), и наследующие ее Изображение, Видео, и Аудио. (Сделано это для того чтобы рендерить разные шаблоны под видео, аудио и "обычный" файл)



Есть еще альтернативный вариант - сделать сущность Файл с полем media, а в него класть МедиаОбъект - Изображение, Видео или Аудио.

> И вот тут у меня вопрос, я могу все еще свитчом вызывать нужные методы в зависимости от типа сущности, или, как я думал, использовать ПОЛИМОРФИЗМ, сделать интерфейс например Queueable с каким-то handle методом, мои сущности будут его имплементировать



Вот по моим ощущениям, это не очень хорошая идея. У нас есть принцип single responsibility - каждый класс занимается своим делом. Класс File представляет данные о файле в БД и наверно это не его задача, вычислять размер изображения или генерировать превьюшки, или выполнять какие-то фоновые задачи. Это лучше поручить отдельному сервису (а может даже нескольким):

медиаОбъект = сервис->распарситьФайл(путьКФайлу);
превьюшка = сервис->сгенерироватьПревьюшку(видеоФайл); или превьюшка = сервис->сгенерироватьПревьюшку(путьКФайлу);
сервисФоновыхЗадач->запланировать(ЗадачуКонвертацииВидео);

При таком подходе мы можем вызывать функцию анализа в любом месте кода. А при твоем - тебе нужен объект Файл с кучей полей для этого. То есть я предлагаю для чистоты кода изолировать друг от друга отдельно хранение данных о загруженных файлах и анализ медиафайлов. А у тебя все выглядит спутанно и связано друг с другом намертво.

А ты ведь еще пытаешься в класс Файл и засунуть взаимодействие с очередью задач. Зачем? Задача - это отдельная сущность и можно либо: использовать в Задаче switch, либо вообще сделать разные типы задач:

обработатьМедиаФайл(файл) {

если (тип == видеофайл) {
запланировать ЗадачуГенерацииПревьюшки;
запланировать ЗадачуКонвертацииВидео;
} иначе ...
...
}

Задачи можно представить либо объектами, либо функциями.

Наследование имело бы смысл применять, если бы можно было добавлять новые типы файлов, не трогая код. Но это в твоем случае вряд ли возможно. Не стоит использовать наследование просто ради того, чтобы оно было. То есть задавай себе вопрос, а зачем мне это? Какая мне от этого выгода?
614 1185218
>>184833

<figure>
<img>
<figcaption>...</figcaption>
</figure>

Закрепляешь figcaption за счет абс. поз. относительно figure.

>>184824

Нет, тут нужны именно generic types, то есть обобщенные типы вроде "Коллекция объектов типа T" - Collection<T>. В примере выше надо читать так:

ArrayList<String> - список строк (на основе массива)
HashMap<ArrayList<String>> - хеш-таблица, содержащая списки строк.

Без generic тебе придется делать кучу одинаковых классов вроде IntCollection, StringCollection, SomeObjectCollection, итд.

>>184790

> У меня есть сущность Файл(базовая сущность), и наследующие ее Изображение, Видео, и Аудио. (Сделано это для того чтобы рендерить разные шаблоны под видео, аудио и "обычный" файл)



Есть еще альтернативный вариант - сделать сущность Файл с полем media, а в него класть МедиаОбъект - Изображение, Видео или Аудио.

> И вот тут у меня вопрос, я могу все еще свитчом вызывать нужные методы в зависимости от типа сущности, или, как я думал, использовать ПОЛИМОРФИЗМ, сделать интерфейс например Queueable с каким-то handle методом, мои сущности будут его имплементировать



Вот по моим ощущениям, это не очень хорошая идея. У нас есть принцип single responsibility - каждый класс занимается своим делом. Класс File представляет данные о файле в БД и наверно это не его задача, вычислять размер изображения или генерировать превьюшки, или выполнять какие-то фоновые задачи. Это лучше поручить отдельному сервису (а может даже нескольким):

медиаОбъект = сервис->распарситьФайл(путьКФайлу);
превьюшка = сервис->сгенерироватьПревьюшку(видеоФайл); или превьюшка = сервис->сгенерироватьПревьюшку(путьКФайлу);
сервисФоновыхЗадач->запланировать(ЗадачуКонвертацииВидео);

При таком подходе мы можем вызывать функцию анализа в любом месте кода. А при твоем - тебе нужен объект Файл с кучей полей для этого. То есть я предлагаю для чистоты кода изолировать друг от друга отдельно хранение данных о загруженных файлах и анализ медиафайлов. А у тебя все выглядит спутанно и связано друг с другом намертво.

А ты ведь еще пытаешься в класс Файл и засунуть взаимодействие с очередью задач. Зачем? Задача - это отдельная сущность и можно либо: использовать в Задаче switch, либо вообще сделать разные типы задач:

обработатьМедиаФайл(файл) {

если (тип == видеофайл) {
запланировать ЗадачуГенерацииПревьюшки;
запланировать ЗадачуКонвертацииВидео;
} иначе ...
...
}

Задачи можно представить либо объектами, либо функциями.

Наследование имело бы смысл применять, если бы можно было добавлять новые типы файлов, не трогая код. Но это в твоем случае вряд ли возможно. Не стоит использовать наследование просто ради того, чтобы оно было. То есть задавай себе вопрос, а зачем мне это? Какая мне от этого выгода?
615 1185219
>>184750

> Ну в сравении с ... Питоном это так.



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

> Ну в сравении с Си



Да, Си компилируется в машинный код и он быстрый, но ты пробовал на нем писать что-то сложнее сложения матриц в лабораторной работе? Вот смотри, код на PHP:

$userIds = array_unique(array_column($users, 'id'));

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

Плюс, в PHP в разы удобнее отладка, пишешь просто var_dump() и смотришь результат, а при исключении видишь нормальный стек трейс.

Конечно, есть компилируемые языки с большей скоростью написания кода - C++, D, Rust, Go - но она все равно ниже чем на PHP, плюс в них все плохо с веб-фреймворками, насколько я знаю.

>>184766

Если ты новичок-теоретик, зачем про производительность рассуждаешь?

>>184762

Вообще, это странно конечно. Не думаю, что он настолько медленнее, наверно что-то в алгоритмах поменялось.

>>184756

Возвращать нужно данные одного типа, чтобы не писать потом ифы.

> Вот тебе вернули false, ну сам массив нулевых значений создай. Делов то.


Там был разговор про другое, про функцию, которая возвращает список записей.
615 1185219
>>184750

> Ну в сравении с ... Питоном это так.



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

> Ну в сравении с Си



Да, Си компилируется в машинный код и он быстрый, но ты пробовал на нем писать что-то сложнее сложения матриц в лабораторной работе? Вот смотри, код на PHP:

$userIds = array_unique(array_column($users, 'id'));

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

Плюс, в PHP в разы удобнее отладка, пишешь просто var_dump() и смотришь результат, а при исключении видишь нормальный стек трейс.

Конечно, есть компилируемые языки с большей скоростью написания кода - C++, D, Rust, Go - но она все равно ниже чем на PHP, плюс в них все плохо с веб-фреймворками, насколько я знаю.

>>184766

Если ты новичок-теоретик, зачем про производительность рассуждаешь?

>>184762

Вообще, это странно конечно. Не думаю, что он настолько медленнее, наверно что-то в алгоритмах поменялось.

>>184756

Возвращать нужно данные одного типа, чтобы не писать потом ифы.

> Вот тебе вернули false, ну сам массив нулевых значений создай. Делов то.


Там был разговор про другое, про функцию, которая возвращает список записей.
616 1185220
>>184730
>>184754

> https://ideone.com/aP0F3B



curl_exec возвращает строку. И вообще, откуда там возьмется объект? JSON это массивы (списки и словари), в нем полноценных объектов все равно нет.

>>184753

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

\MegaForum\Entity\Post

Но в коде использовать короткое имя Post. Урок https://github.com/codedokode/pasta/blob/master/php/autoload.md

Область видимости - это где будет видна переменная, например, переменная созданная в функции, видна только внутри нее.

>>184749

Нет, фреймворк или библиотека вообще не должны создавать глобальные переменные. Плюс, на них неймспейсы не распространяются.

> Нормально именовать переменные.


Если ты про классы и функции, то это приводит к тому, что получаются длинные имена вроде Zend_Db_Table_abstract. Неймспейсы позволяют использовать уникальные имена, но при этом в коде исопльзовать более короткие синонимы: https://github.com/codedokode/pasta/blob/master/php/autoload.md

Вот зачем ты спешишь критиковать, не разобравшись в теме?

>>184739

У меня есть простой урок https://github.com/codedokode/pasta/blob/master/php/autoload.md

>>184716

fetch сделан логично: он возвращает или запись или false. Пустой массив как раз нелогично, так как он выглядит как пустая запись из базы данных без единственной ячейки.
616 1185220
>>184730
>>184754

> https://ideone.com/aP0F3B



curl_exec возвращает строку. И вообще, откуда там возьмется объект? JSON это массивы (списки и словари), в нем полноценных объектов все равно нет.

>>184753

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

\MegaForum\Entity\Post

Но в коде использовать короткое имя Post. Урок https://github.com/codedokode/pasta/blob/master/php/autoload.md

Область видимости - это где будет видна переменная, например, переменная созданная в функции, видна только внутри нее.

>>184749

Нет, фреймворк или библиотека вообще не должны создавать глобальные переменные. Плюс, на них неймспейсы не распространяются.

> Нормально именовать переменные.


Если ты про классы и функции, то это приводит к тому, что получаются длинные имена вроде Zend_Db_Table_abstract. Неймспейсы позволяют использовать уникальные имена, но при этом в коде исопльзовать более короткие синонимы: https://github.com/codedokode/pasta/blob/master/php/autoload.md

Вот зачем ты спешишь критиковать, не разобравшись в теме?

>>184739

У меня есть простой урок https://github.com/codedokode/pasta/blob/master/php/autoload.md

>>184716

fetch сделан логично: он возвращает или запись или false. Пустой массив как раз нелогично, так как он выглядит как пустая запись из базы данных без единственной ячейки.
617 1185221
>>184548

Первая часть элементарная и решается на Симфони за несколько часов, если ты хорошо с ней знаком. Тут правда подвох в количестве сотрудников - если ты попробуешь загрузить в память 50 000 объектов Доктрины, то скрипт упадет. Ну правильно, надо отсеивать тех, кто поленился изучить особенности работы Доктрины.

> не представляю как это должно выглядеть.



Написано же:

> Создайте веб страницу, которая будет выводить иерархию сотрудников в


древовидной ​форме.

Заходишь на страницу, а там дерево вроде дерева папок, только с сотрудниками. Вроде такого например https://www.jstree.com/demo/

Что такое дерево: https://ru.wikipedia.org/wiki/Дерево_(структура_данных)

>>184691

> Тот же фронт лучше бы замутить на SPA


Зачем? Ты предлагаешь писать 2 приложения (клиентское и серверное), замедлять время загрузки страницы, и повышать затраты на разработку, ради чего?

>>184538

Не годится, слишком длинно и слишком много копипасты.

Даю хинт. Допустим, тебе надо найти последовательность из слов, не менее 5 слов, где первое слово это "большой", а последнее - "кот". Вот регулярка:

большой\s(\w+\s){5,}кот
617 1185221
>>184548

Первая часть элементарная и решается на Симфони за несколько часов, если ты хорошо с ней знаком. Тут правда подвох в количестве сотрудников - если ты попробуешь загрузить в память 50 000 объектов Доктрины, то скрипт упадет. Ну правильно, надо отсеивать тех, кто поленился изучить особенности работы Доктрины.

> не представляю как это должно выглядеть.



Написано же:

> Создайте веб страницу, которая будет выводить иерархию сотрудников в


древовидной ​форме.

Заходишь на страницу, а там дерево вроде дерева папок, только с сотрудниками. Вроде такого например https://www.jstree.com/demo/

Что такое дерево: https://ru.wikipedia.org/wiki/Дерево_(структура_данных)

>>184691

> Тот же фронт лучше бы замутить на SPA


Зачем? Ты предлагаешь писать 2 приложения (клиентское и серверное), замедлять время загрузки страницы, и повышать затраты на разработку, ради чего?

>>184538

Не годится, слишком длинно и слишком много копипасты.

Даю хинт. Допустим, тебе надо найти последовательность из слов, не менее 5 слов, где первое слово это "большой", а последнее - "кот". Вот регулярка:

большой\s(\w+\s){5,}кот
618 1185222
>>184517

Ты можешь посмотреть исходники phpclub.tech, если интересно: https://github.com/richBlueElephant/phpClub

>>183769

Не факт. При разрыве соединения скрипт может завершиться. Там есть опция, чтобы игнорировать это.

>>184218

Не понятно, о чем речь. Какие еще куки? Просто отркываешь сайт в браузере, если ты залогинен, то актуальные.

>>184213

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

- SQL
- ООП
- какой-нибудь фреймворк
- git

>>183746

Можно конечно. Вебпак - это склейщик и загрузчик JS/CSS файлов, если тебе он не нужен, то не надо его и использовать.

Конечно, можно копировать и скриптом. Можно на bash, можно на PHP, если хочется кроссплатформенности.

Также, в фреймворках вроде Симфони могут быть свои методы для этого.

>>182636

Ну так проблема, что на dev папка vendor обычно не видна из public. Хотя, ... можно ее отобразить туда симлинком, на дев можно, а на продакшен я не уверен, что это безопасно и что там нет какого-то php скрипта, который можно использовать не по назначению. Лучше не стоит на продакшене так делать.
618 1185222
>>184517

Ты можешь посмотреть исходники phpclub.tech, если интересно: https://github.com/richBlueElephant/phpClub

>>183769

Не факт. При разрыве соединения скрипт может завершиться. Там есть опция, чтобы игнорировать это.

>>184218

Не понятно, о чем речь. Какие еще куки? Просто отркываешь сайт в браузере, если ты залогинен, то актуальные.

>>184213

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

- SQL
- ООП
- какой-нибудь фреймворк
- git

>>183746

Можно конечно. Вебпак - это склейщик и загрузчик JS/CSS файлов, если тебе он не нужен, то не надо его и использовать.

Конечно, можно копировать и скриптом. Можно на bash, можно на PHP, если хочется кроссплатформенности.

Также, в фреймворках вроде Симфони могут быть свои методы для этого.

>>182636

Ну так проблема, что на dev папка vendor обычно не видна из public. Хотя, ... можно ее отобразить туда симлинком, на дев можно, а на продакшен я не уверен, что это безопасно и что там нет какого-то php скрипта, который можно использовать не по назначению. Лучше не стоит на продакшене так делать.
619 1185224
>>182595

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

А так, ничего страшного, если ты вывалишь лишние файлы в public, я думаю, нет, если только там нет PHP скриптов, которые можно использовать в целях атаки на сервер.

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

Обрати внимание, что там есть 2 варианта - dev и production. Если ты ставишь dev версию, то получишь гору зависимостей, потому npm лучше было вызывать с опцией production. Она описана тут https://docs.npmjs.com/cli/install

Так что варианты такие:

- устанавливать в public как есть
- устанавливать не в public, а потом как-то копировать или создавать симлинки на те файлы, которые нужно сделать доступными

В том же video.js есть файл .npmignore и он по идее должен игнорировать лишние файлы: https://github.com/videojs/video.js/blob/master/.npmignore

>>183674

Строка в памяти хранится как последовательность байтов. При этом в utf-8 1 буква может кодироваться комбинацией из нескольких байтов. Если ты не указываешь флаг u, то PCRE будет считать что у тебя 1-байтовая кодировка и точка будет соответствовать не символу, а одному байту. И он разобьет строку на отдельные байты, перевернет их и поменяет их комбинации и строка перестанет вообще раскодироваться. Флаг u заставляет его интепретировать строку как последовательность utf-8 символов.

Подробнее про байты и кодировки https://github.com/codedokode/pasta/blob/master/cs/strings.md
620 1185232
>>185215
Ну вот создали HHVM например, создали под него даже мод PHP с типизацией. А он оказался медленнее чем PHP 7, не говоря уже про PHP 7.1. Тоесть вроде и производительность должны были поднять, ну и получили в скорости по сравнению с 5.4, но с другой стороны задачу "Надо выполнять код быстрее" это не решило.

>Если у нас долгоживущее приложение.


Как по мне - PHP для долгоживущих приложений не совсем подходит. Читал множество статей на stack о том что всё равно в районе 2-3 суток случается либо переполнение буфера, либо затыки с процессором.
621 1185241
>>185232

Думаю, это зависит от того, как писать код. То есть проблема не в PHP, а где-то допущена в коде утечка. Хотя я сам не очень представляю, как ее искать без каких-то инструментов для этого.
622 1185258
Какой язык лучше использовать в проектах и почему?
XHTML или HTML5?
623 1185260
>>185218
Спасибо большое за советы. У меня есть еще один вопросик. Когда, например, видео конвертируется, я хочу быть в курсе этого, чтобы выводить стандартный шаблон для загрузки файла. То есть наверное у записи в бд должна быть колонка в стиле state = (new, proccessing, finished, failed) или что-то в таком духе. Я думал что если я использую бд, то может мне и beanstalk и не нужен (для задачки на обучение), но beanstalk будет стучать в базу только после того как получит новое сообщение, а скрипт на бд будет стучать каждое n время. Хорошая ли практика использовать сервер очередей И базу, чтобы быть в курсе состояния моего файла?
624 1185270
>>185258
пятерку
625 1185334
Котятки, а что, NetBeans не может в PSR? Попробовал отформатить с его помощью код, так он мне какой-то хурмы наделал.
Фигурная скобочка в определении классов и методов на той же строке стоит, как, например в if/else.
Это вообще почему так? При помощи чего вы это делаете? Ну не руками же, идеально никто не пишет, а вручную исправлять всё - так себе идея.
626 1185335
>>185217

>самоутверждайся за счет обучающихся.


Вовсе нет. Но очень многие в треде несут полную хуйню с умным видом, тем самым мешая реально обучающимся.
627 1185337
>>185136
Ты сука знаешь, чем JIT-компилятор отличается от обычного компилятора?
628 1185340
Можно ли как-нибудь встроенный в пхп веб сервер открыть без окошка cmd? Положить в автозагрузку? Или обязательно нужен апачи? Надоело прописывать одно и тоже каждый день, да и окно это мешает, а закроешь его - все, сдох процесс. Халп!
629 1185348
>>185153
И нахуя такое счастье кому-то нужно?
630 1185353
>>185221

> Зачем? Ты предлагаешь писать 2 приложения (клиентское и серверное), замедлять время загрузки страницы, и повышать затраты на разработку, ради чего?


Затем что потом заказчику захочется внести новый функционал, сделать мобильное приложение или ещё что.
А ты не предусмотрел возможностей для роста
631 1185354
>>185340
& в конце добавь
632 1185357
>>185334
NetBeans в 2018-м уже никто не юзает. PHPStorm из коробки нормально форматирует код и умеет ещё кучу всего: https://www.youtube.com/watch?v=pP9jw3fgrCU

> а вручную исправлять всё - так себе идея.


Верно, поэтому придумали PHP CS Fixer
633 1185397
>>185357
Спасибо
634 1185421
>>185354
В уконце чего?
635 1185502
>>185353

Когда захочется, тогда и сделаем. Не вижу также прямой связи между SPA и мобильным приложением. С большой вероятностью там понадобится отдельный API.
636 1185504
>>185353

>ты не предусмотрел возможностей для роста


А ещё надо написать версию без js и под ie6. Заказчик может тебя попросить написать, а ты не предусмотрел возможностей для роста.
637 1185508
>>184514
ну летс го, пиши тг или почту
638 1185751
>>185508
s61748RJ401ANUSmainYXlPUNCTUMr7K&u
639 1185781
Аноны, влияет ли использование подобной нотации на скорость работы?
\Name\Space\Class::...

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

И вообще, нормально ли использовать такой способ записи? Или нужно обязательно везде писать use \Name\Space\Class::... ?
640 1185830
>>185421
Тебе нужно разобраться как запускать процессы в фоне. В линуксе это делается добавлением символа & в конец консольной команды, на винде - не знаю, погугли "windows run process in background": https://superuser.com/a/591084

>>185504
Ты утрируешь, IE6 очень старый. Максимум, что просят в 2018-м - это поддержку IE 9-10. Сейчас заказчикам поголовно нужны SPA, а 0.2% маргиналов без JS никого не интересуют. Такова реальность, не то чтобы мне это нравилось.

>>185781
Если я тебя правильно понял, то нет никакой разницы - использовать use или всегда указывать полный неймспейс. Но использовать use - хорошая практика, которая делает код более лаконичным. Прописывать самому us'ы не нужно - IDE сами неймспейс прописывают.

> И вообще, нормально ли использовать такой способ


При возникновении подобных вопросов можешь просто открыть исходники популярного фреймворка, например Symfony, и посмотреть - делают там так или нет.
641 1185854
>>185830
Читал про '&' что процесс открывется в том же треде что и сам инстанс php и так-же останется висеть до завершения, со всеми сопутствующими импликейшнами, и поэтому лучше через посредника, демона или что-то еще открывать его в отдельном. Соответствует ли это действительности, или я что-то не так понял?

просто сижу тют в тредже.
642 1185884
>>185830
а, он же не из пхп запускает
643 1185962
Поделитесь ссылкой на пхп конфу треда, пожалуйста?
pr - Клуб изучающих PHP и webdev #101 - Google Chrome 2018-[...].jpg73 Кб, 542x399
644 1185965
>>185962
Абу, прекрати хуйню городить на вакабе.
645 1185971
>>185965

Дополню только, что это сторонняя и неофициальная конфа, созданная кем-то из посетителей треда. Заходите туда на свой страх и риск!
646 1185972
>>185971
Дополню что в конфе 2-3 сообщения в неделю.
647 1186007
Начал задачу про файлообменник.
Какие столбцы должны быть в БД в таблице относящейся к файлу?
648 1186281
Пишу парсер, но возникла проблема, так как на сайте у пары блоков один class , но мне нужен только один блок
Как это сделать ?
Использую DiDom
649 1186383
Решил по хардкору решать задачку с айфоном в кредит и искренне не понимаю почему данный код ничего не выводит на экран.

<?php

for ( $i = -40000; $i >= 0; $i = ($i + ($i * 0.03) + 1000) - 5000 )
{
echo $i . ' <br>';
}
650 1186431
>>186383
Проебал что начал с отрицательного числа, переделал формулу

for ( $i = -40000; $i >= 0; $i = (($i + ($i * 0.03) + (-1000)) + 5000) )
{
echo $i . ' <br>';
}

Все равно выводит пустую страницу.
651 1186448
>>185508
У тебя большой опыт?
652 1186577
А что влияет на быстродействие скрипта? Насколько сильно влияет количество переменных, объектов, всяких процедур на быстродействие? Я недавно где то на хабре видел таблицу, где сравнивалась скорость фреймворков, и выходило, что микрофреймворки самые быстрые, и среди них луший по этим показателям слим. То есть получается, что чем меньше кода, тем быстрее, если не учитывать всякие взаимодействия с субд?
653 1186614
>>186577
Ну очевидно. В тяжелых фреймворках больше уровней абстракций и прочего говна. Там например путь при наследовании из 10 дочерних классов у какого-нибудь контроллера, потом еще всякие ди-контейнеры, в которые складываются всякие db, конфиг и прочее, объявляется куча переменных и зависимостей с константами, еще всякие десятки инклудов других файлов и прочее, и всё это для того, что бы ты просто мог увидеть стартовую страницу сайта. Самый быстрый скрипт - тот в котором написано только то, что от него требуется, без всяких классов и абстракций. Тупо на базовых типах, функциях и с использованием шустреньких алгоритмов с наименьшей сложностью.
654 1186686
Поясните как в WP принято подключать в тему картинки?
655 1186712
>>186614
поэтому я пишу на чистом пхп
656 1186715

>и среди них луший по этим показателям слим


а хуй там было
https://habr.com/company/nixsolutions/blog/329718/
657 1186730
>>186715

>Время выполнения


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


>php 7.1


>slim-3.0 0.662


>никого больше до секунды



ну сам же макнул себя.
658 1186733
>>186730
там разбор идет по всем показателям
659 1186873
>>186730

Так там 0,662 мс а не 0,662 с.
660 1186885
>>186715

А вообще, этот тест сам по себе мало полезен. Если ты хочешь высокую производительность, бери Си++, Rust, Go, D, а не PHP. Задача фреймворка - облегчать разработку. Фреймворки там разные и может быть, что в более быстром не будет каких-то нужных тебе классов и тебе придется больше писать самому.
661 1186912
>>186885
кони в вакууме
662 1186941
Насколько близки андроид разработка и веб? сложно ли перекатиться из одного в другое?
663 1186975
>>186431
Потому что ты долбоёб и пишешь хуйню. Покури ещё как работает цикл for в php.
1467132416-z-jh0mvqa.jpg43 Кб, 786x438
664 1187145
>>186431

>$i = -40000;


>$i >= 0;

665 1187361
>>186431

В цикле пишется условие продолжение цикла. Оно проверяется перед каждым шагом. У тебя условие $i >= 0 не выполняется уже на первом шаге и цикл не выполняется ни разу.
666 1187366
Помогите пожалуйста, есть такое задание - Написать функцию которая выводит расттояние между двумя символами в сроке, например дана строка "string" и две буквы "t" и "n" вывести 2
но надо не забывать что буквы могут оказаться в обратном порядке например строка "string"

Я так понял, вызываем функции и вводим 2 цифры - это два номера букв в строке, между которым надо отсчитать расстояние.
Далее цикл, который будет длится пока не закончатся все буквы в строках ( узнаем предварительно сколько букв в строке)
Далее, при условии, что если счетчик равен первой цифре, которую мы оказали, мы запоминаем эту цифру, и так же со второй цифрой.
А далее просто от второй отнимаем первую цифру. Это так?

Или стойте, это же БУКВЫ.
Есть переменная со строкой, мы вызываем функцию, куда записываем буквы из этих строк. И делаем тоже самое, только предварительно надо узнать под какой буквой какая цифра. Океей.
Я правильно мыслю? Тогда такой вопрос, скажите пожалуйста - вот допустим есть строка, есть буквы. Как мне узнать, за какой буквой какая цифра? Ну, т.е.
$a = "abvgd";
Я ввел strlen ($а);, знал что в той строке 5 букв, узнал.
Я ввел далее g, и... Погодите. Я запутался.
В общем обьясните, умоляю. Я максимально гуглить старался, но это пока выше моих познаний.

Учусь по базовому курсу для нулевых из шапки.
667 1187416
>>187366
Не осилил твой поток мысли, но я бы делал по такому алгоритму:

1. Предполагаем из условия, что в строке как начальная, так и конечная буква встречаются только в единичном экземпляре.
2. Берем искомую строку, превращаем её в массив символов как учила оп-тян это намек, что если не знаешь как превратить, то смотри её уроки по строкам http://archive-ipq-co.narod.ru/l1/strings.html
3. Далее перебираем наш массив в цикле, когда нам встречается начальная буква, мы запоминаем её номер в какую-нибудь переменную, например $start, когда встречается наша конечная, её номер тоже запоминаем в другую переменную, например $finish.
4. Высчитываем искомое число отняв $start от $finish.
5. Возвращаем значение.

На примере без кода ты будешь примерно такими значениями оперировать:

$string = 'qwerty';
допустим ищем разницу между w и t
2...
$array = [0=>'q', 1=>'w', 2=>'e', 3=>'r', 4=>'t', 5=>'y'];
3...
$start = 1;
$finish = 4;
4...
$interval = 3;
5...
return 3;
668 1187491
Хочу понять, что мыслю в верном направлении.
Задача: написать вью каунтер в 2018 году.
Решение: каждый раз при отдаче отрендеренной страницы инкрементим редис по ключу с названием и id объекта. Объединяем всё в тэг, каждый раз считаем сумму и, по достижению суммы всех просмотров, скажем, сотни, ставим таск на инсерт в базу. В базу инсертим просмотры с нужными параметрами, временем и тд в отдельную таблицу, с которой морфичечски соединяем все объекты с вью-каунтерами. При просмотре объекта юзеру отдаём каунт из бд + значение из редиса.
Все правильно делаю? Какие тут могут быть подводные?
669 1187492
>>187491
А, ещё второй вариант: каждый раз ставить таск с дилеем, скажем, в 5 минут, который собирает просмотры из редиса и заносит в бд. Если таск стоит в очереди, то не ставим. По сути типа крон, но "по запросу".
670 1187590
Ебаные ЧПУ.
Куча бесполезного кода для их обработки и формирования.
Ни одного явного доказательства влияния на ранг при поиске.
Полтора человека которые пишут или читают урлы в адресной строке.
671 1187604
>>187590

Почему же куча кода? Банально добавляешь в таблицу поле slug + делаешь одну универсальную функцию генерации слуга.
672 1187609
>>187604
Да это чепуха. А вот когда начинается "а вот если у нас такой раздел то пусть будут такие а если этот раздел то в обратном порядке, а в этом разделе кароче вообще по другому вот здорово то а!"...
673 1187710
А http://phpclub.tech/ временно не работает или проект накрылся?
674 1187713
Стажировался в конторке с нуля(за два дня до собеседования начал учить язык, до этого программировал на андроид немного и бота на ноде делал), проработал полтора месяца за 10к в месяц и уволился (не нравилось начальство и цмска на которой пилили (Битрикс)), месяц уже не работаю, вот хз искать ли новую, как вообще проверить уровень, достоин ли я Джуна?
675 1187720
>>187713
Ну ты и мраааазь. Любой новичек мечтает о таком, работать за еду чтоб учили.
676 1187725
>>187720
Ты думаешь меня там кто-то учил? Первый месяц, кстати, бесплатно работал, а следующую прибавку через пол года обещали
someApprentice 678 1187947
>>187710

http://phpclub.tech/ временно не работает или проект накрылся?


Нам хостинг отключили, предположительно за NSFW картинки, которые были спаршены с 2ч. Скоро восстановим.
679 1187979
>>187947

>NSFW


Ого, кто-то за этим следит? Хуясе вахтеры.

У меня проблема! В жаваскрипте:

let x = 0;
setInterval(()=>{ x += (10 / 100 2) }, 1000}

выдает значения 1.2 1.4 а затем бред — 1.599999999 1.79999999998 и т.д.

Штоэта? Как бороться?

Пробовал
x += Number((10 / 100
2).toFixed(2))
но не помогает.
680 1187981
>>187979
Ну вы поняли, там *
681 1188015
>>187979

Тебе надо обязательно почитать про тип float и представление в компьютере дробных чисел (стандарт IEEE754).

Представь, что у тебя есть фиксированное число ячеек памяти (например, 10 ячеек), в каждую из которых можно поместить ровно одну цифру. И ты хочешь с помощью этих 10 ячеек представить как можно больший диапазон чисел, включая дробные. Как это можно сделать?

Самое простое - это число с фиксированной запятой. Пусть у нас между 5-й и 6-й ячейкой стоит воображаемая запятая. И если у нас есть последовательность 12345 67890, то мы интерпретируем ее как число

12345,67890

Этот подход имеет свои плюсы (простота), но и минусы: мы не можем представить таким образом числа меньше 0,00001 или больше 99999,99999 (чуть менее 100 000). Для расширения диапазона необходимо выделять больше ячеек памяти. Однако, такой подход использовался в древних калькуляторах и компьютерах. Конечно, там могло быть не 10 ячеек, или запятая могла стоять в другом месте, но принцип тот же.

Потому был придуман другой способ: число с плавающей запятой. Разобьем наши 10 ячеек на 2 группы, допустим группу из 2 и из 7 ячеек, а в оставшуюся 10-ю ячейку мы будем класть знак - плюс или минус:

+ 12 3456789

Назовем первую группу + 12 "экспонентой", а вторую 3456789 - "мантиссой". Пусть перед мантиссой стоит воображаемая запятая. И договоримся, что экспонента показывает, на сколько разрядов надо сдвинуть запятую вправо относительно начального положения (если экспонента отрицательная, со знаком минус, то запятая сдвигается влево, а не вправо). Например, +12 значит, что запятую надо сдвинуть на 12 символов вправо, дополняя число нулями при нехватке цифр:

имеем мантиссу 0,3456789 и экспоненту 12, сдвигаем запятую и получаем итоговое число:

345678900000,0

А в таком числе:

-02 1234567

Запятая сдвигается на 2 символа влево, дополняя пустые места нулями, и получается

0,001234567

Если обозначить экспоненту как E, а мантиссу как M, то мы можем записать правило восстановления числа в виде формулы N = 0,M x (10 ^ E).

При таком подходе минимальное число, которое мы можем представить, будет -99 0000001 = 0, ... 99 нулей ... 0000001, а максимальное x 99 9999999 = 999 999 900 ... и еще 90 нулей. Как видишь, используя те же 10 ячеек, мы смогли представить огромный диапазон чисел, примерно от ~10^-106 (10 в минус 106 степени, очень крошечное число) до ~10^100 (очень огромное число).

Но этот подход имеет и недостаток - так как у нас под мантиссу выделено всего 7 цифр, то оставшиеся цифры теряются. Например, число 123456789 будет сохранено как

+09 1234568

И при восстановлении получится 123456800,0 что отличается на 11 от исходного числа. Сохраняются только несколько первых значащих цифр. То есть наш формат сохраняет числа не точно, а с погрешностью.

Единственное отличие чисел стандарта IEEE754 от описанного мной варианта отличается в том, что там используются двоичные числа (состоящие только из цифр 0 или 1) и 32 ячейки. То есть 32 бита, каждый из которых равен 0 или 1.

Это и ответ на твой вопрос. 1,4 + 0,2 дает 1,6 которое при переводе в двоичную систему счисления представляет бесконечную дробь: 1,6 = 1,1 0011 0011 0011 0011.... Из-за того, что дробь бесконечная, а размер мантиссы конечный - 24 бита, получается не ровно 1,6, а 1,5999999 что отличается от 1,6 совсем немного (примерно на 0,00000001) и в принципе является тем же числом.

Сконвертировать число из 10-ного вида в формат IEEE754: https://www.h-schmidt.net/FloatConverter/IEEE754.html

Почитать про дробные числа:

- https://habr.com/post/112953/

Кстати, из-за этой особенности (погрешность при сохранении) нельзя сравнивать дробные числа с помощью a == b. Не хочешь подумать, над "правильным" алгоритмом сравнения дробных чисел, с учетом того, что они хранятся неточно и в результате операций может накапливаться небольшая погрешность в последнем разряде?
681 1188015
>>187979

Тебе надо обязательно почитать про тип float и представление в компьютере дробных чисел (стандарт IEEE754).

Представь, что у тебя есть фиксированное число ячеек памяти (например, 10 ячеек), в каждую из которых можно поместить ровно одну цифру. И ты хочешь с помощью этих 10 ячеек представить как можно больший диапазон чисел, включая дробные. Как это можно сделать?

Самое простое - это число с фиксированной запятой. Пусть у нас между 5-й и 6-й ячейкой стоит воображаемая запятая. И если у нас есть последовательность 12345 67890, то мы интерпретируем ее как число

12345,67890

Этот подход имеет свои плюсы (простота), но и минусы: мы не можем представить таким образом числа меньше 0,00001 или больше 99999,99999 (чуть менее 100 000). Для расширения диапазона необходимо выделять больше ячеек памяти. Однако, такой подход использовался в древних калькуляторах и компьютерах. Конечно, там могло быть не 10 ячеек, или запятая могла стоять в другом месте, но принцип тот же.

Потому был придуман другой способ: число с плавающей запятой. Разобьем наши 10 ячеек на 2 группы, допустим группу из 2 и из 7 ячеек, а в оставшуюся 10-ю ячейку мы будем класть знак - плюс или минус:

+ 12 3456789

Назовем первую группу + 12 "экспонентой", а вторую 3456789 - "мантиссой". Пусть перед мантиссой стоит воображаемая запятая. И договоримся, что экспонента показывает, на сколько разрядов надо сдвинуть запятую вправо относительно начального положения (если экспонента отрицательная, со знаком минус, то запятая сдвигается влево, а не вправо). Например, +12 значит, что запятую надо сдвинуть на 12 символов вправо, дополняя число нулями при нехватке цифр:

имеем мантиссу 0,3456789 и экспоненту 12, сдвигаем запятую и получаем итоговое число:

345678900000,0

А в таком числе:

-02 1234567

Запятая сдвигается на 2 символа влево, дополняя пустые места нулями, и получается

0,001234567

Если обозначить экспоненту как E, а мантиссу как M, то мы можем записать правило восстановления числа в виде формулы N = 0,M x (10 ^ E).

При таком подходе минимальное число, которое мы можем представить, будет -99 0000001 = 0, ... 99 нулей ... 0000001, а максимальное x 99 9999999 = 999 999 900 ... и еще 90 нулей. Как видишь, используя те же 10 ячеек, мы смогли представить огромный диапазон чисел, примерно от ~10^-106 (10 в минус 106 степени, очень крошечное число) до ~10^100 (очень огромное число).

Но этот подход имеет и недостаток - так как у нас под мантиссу выделено всего 7 цифр, то оставшиеся цифры теряются. Например, число 123456789 будет сохранено как

+09 1234568

И при восстановлении получится 123456800,0 что отличается на 11 от исходного числа. Сохраняются только несколько первых значащих цифр. То есть наш формат сохраняет числа не точно, а с погрешностью.

Единственное отличие чисел стандарта IEEE754 от описанного мной варианта отличается в том, что там используются двоичные числа (состоящие только из цифр 0 или 1) и 32 ячейки. То есть 32 бита, каждый из которых равен 0 или 1.

Это и ответ на твой вопрос. 1,4 + 0,2 дает 1,6 которое при переводе в двоичную систему счисления представляет бесконечную дробь: 1,6 = 1,1 0011 0011 0011 0011.... Из-за того, что дробь бесконечная, а размер мантиссы конечный - 24 бита, получается не ровно 1,6, а 1,5999999 что отличается от 1,6 совсем немного (примерно на 0,00000001) и в принципе является тем же числом.

Сконвертировать число из 10-ного вида в формат IEEE754: https://www.h-schmidt.net/FloatConverter/IEEE754.html

Почитать про дробные числа:

- https://habr.com/post/112953/

Кстати, из-за этой особенности (погрешность при сохранении) нельзя сравнивать дробные числа с помощью a == b. Не хочешь подумать, над "правильным" алгоритмом сравнения дробных чисел, с учетом того, что они хранятся неточно и в результате операций может накапливаться небольшая погрешность в последнем разряде?
682 1188051
Я все правильно сделал?
683 1188054
>>188051
Мне кажется, нет. Было бы правильно создать отдельный метод setQuestion для заполнения массива вопросов, а в него уже передавать вопросы в виде многомерного массива и создать метод getQuestions, который возвращает все массивы. Таким образом, происходит разделение данных и логики (я имею в виду, что данные не вводятся вручную, а передаются в специальную функцию обработчик, который является прослойкой для них. Чем это лучше? Тем, что мы абстрагируемся от способа хранения) и уменьшается количество повторяемого кода.
Но это имхо.
684 1188055
>>188054
Я ничего не понял, но благодарю сильно за ответ. Тут другое дело пока. Я сейчас делаю по гайду

>http://codedokode.github.io/phpbook


Основы ООП. Я пытаюсь создать класс с вопросами и ответами, но у меня ничего не получается. https://ideone.com/D3eBq8
Откуда взялся $letter ?
Уже три часа бьюсь над загадкой. То ругается что Notice: Undefined variable: text in M:\Soft\xampp\htdocs\test.php on line 15
на строках где функцией создаю вопросы, то циклом не показывает варианты ответов.
685 1188060
>>188055
Я долбоеб, ошибка найдена, прошу прощения.
686 1188063
>>188054

В какой класс ты предлагаешь добавить метод setQuestion?
687 1188193
>>187979
Решил в итоге так:

https://learn.javascript.ru/number#неточные-вычисления

let x = 0;
setInterval(()=>{
x = (+(x + (10 / 100 • 2)).toFixed(2));
}, 1000);

>>188015

Говорили, не нужна математика программировании, ага...

Это конец, всегда еле вытягивал матишу, а она и тут достала, эх.

>Это и ответ на твой вопрос



Вопрос был в том числе "Как бороться?" :) Ответа я не нашел.

>"правильным" алгоритмом сравнения дробных чисел



В голову приходит только превратить обе части в строки и сравнить их. Но тут тоже могут быть какие-нибудь подводные камни.
688 1188200
>>188193
При обучении программированию и в очень редких случаях математика нужна. На математической основе построено много обучающих задач по программированию. При этом математика выступает в роли чего то сверхпростого и тривиального а сложность в создании логического алгоритма.
7911d51e20705af676e2c6f98fadd36299ae9992a5d0ed915d54396219b[...].png22 Кб, 364x150
689 1188215
>>188015
Алсо:

>Поэтому в IEEE754 применяется правило округления до четного. Так, 12,5 будет округлено до 12, а 13,5 – до 14.



ОК. А как это обходят в ЯП? Используют округление от нуля?
https://ru.wikipedia.org/wiki/IEEE_754-2008#Округление_до_ближайшего

Раньше казалось, что математические операции и в программировании железобетонны и бесконечно надежны. Это же ужас:

>Деньги нельзя хранить в виде числа с плавающей запятой, т.к. в этом случае нельзя выделить значимые разряды. Если в языке программирования нет типов данных с фиксированной запятой, можно выйти из положения и хранить деньги в виде целого числа, подразумевая копейки (иногда доли копеек)



Можно поподробнее, пожалуйста? Я думаю подразумевается нечто вроде decimal(9,2) из sql? Тут явно указано 2 знака за запятой. А если хранишь все число, то потом сам выделяешь запятую с конца чтобы получить копейки?

Капча намекает на неточность.
690 1188232
>>188215

Тред не читал, о чем речь не знаю, в почти всех задачах на округление нужно использовать % остаток от деления на 10 с цикличным умножением или делением с последующим округлением на 10
691 1188255
>>188063
Не знаю, создай что-то вроде обыкновенной фабрики, но той, которая не возвращает объекты, а сохраняет их. Хотя, это больше похоже на шаблон Приспособленец.

interface QuestionFactory
{
public function setQuestion(string $name, int $points, array $answerd);
public function getQuestions() : array;
}

А использовать как-то так:
$factory = new QuestionFactory();

$factory->setQuestion("Вопрос", 666, array("Да", "Нет"));
$factory->setQuestion("Вопрос2", 666, array("Да", "Нет"));
$factory->setQuestion("Вопроc3", 666, array("Да", "Нет"));

$questions = $factory->getQuestions();
foreach($questions as $question) {

echo $question->text;
...
}

Хотя, использовать 3 параметра, это уже эребор и говорит о неправильной архитектуре.
Я, если что, не профи. Сам только познаю дзен. Пускай придет гуру и разрулит всё это.
692 1188278
>>188255
Ой да зачем тут целую фабрику городить. Это если бы вопросы разных классов были тогда ладно еще.

Щас тут насоветуют начитанные знатоки велосипедеры.
693 1188326
Нужно вставить пикчу:
При попытке сделать это через echo "<img src="../upload/$_GET[id].jpg">"; появляется ошибка, мол, что у тебя там за точки стоят придурок.
При попытке сделать это через echo '<img src="../upload/$_GET[id].jpg">'; ошибка исчезает, но уже ищется файл $_GET[id].jpg, т.к. из-за других кавычек переменная читается как текст.
Чо, собсна, делать?
694 1188340
>>188255
Ебать ты тупой
695 1188343
>>188326

Во-первых, так делать нельзя, $_GET прямо в HTML-код, это уязвимость, читай урок про XSS https://github.com/codedokode/pasta/blob/master/security/xss.md

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

Во-вторых, насчет кавычек, почитай правила обработки строк в кавычках в PHP внимательно и целиком http://php.net/manual/ru/language.types.string.php
696 1188345
>>188326

В третьих, для расширения кругозора почитай еще про шаблоны: https://github.com/codedokode/pasta/blob/master/php/templates.md

Это гораздо лучше чем мучаться с echo и кавычками.
697 1188350
>>188326

>echo "<img src="../upload/$_GET[id].jpg">";


как вариант обозначить для интерпретатора где точно начинается и заканчивается сложная переменная (массивы и объекты надо обмазывать в {} )
echo "<img src="../upload/{$_GET[id]}.jpg">";

>echo '<img src="../upload/$_GET[id].jpg">';


как вариант сделать через склеивание строк через точку
echo '<img src="../upload/' . $_GET[id]. '.jpg">';

>$_GET[id]


Еще у тебя тут скорее всего ошибка, и нужно будет выводить через
$_GET['id']

Если ты обращаешься к числовому ключу массива, то без кавычек - всё ок:
$test[1]
$test[0]
$test['234]

Но если он сам по себе строка, то через кавычки
$user['name']
$user['age']
...

А еще ты можешь не эхать весь html с помощью пхп, а писать обычный html код, а где нужно уже вставлять переменные с помощью пхп тегов: <?=$var?>

Например:
...
<div class="img>
<img src="../upload/<?=$_GET['id']?>.jpg">
</div>
...
697 1188350
>>188326

>echo "<img src="../upload/$_GET[id].jpg">";


как вариант обозначить для интерпретатора где точно начинается и заканчивается сложная переменная (массивы и объекты надо обмазывать в {} )
echo "<img src="../upload/{$_GET[id]}.jpg">";

>echo '<img src="../upload/$_GET[id].jpg">';


как вариант сделать через склеивание строк через точку
echo '<img src="../upload/' . $_GET[id]. '.jpg">';

>$_GET[id]


Еще у тебя тут скорее всего ошибка, и нужно будет выводить через
$_GET['id']

Если ты обращаешься к числовому ключу массива, то без кавычек - всё ок:
$test[1]
$test[0]
$test['234]

Но если он сам по себе строка, то через кавычки
$user['name']
$user['age']
...

А еще ты можешь не эхать весь html с помощью пхп, а писать обычный html код, а где нужно уже вставлять переменные с помощью пхп тегов: <?=$var?>

Например:
...
<div class="img>
<img src="../upload/<?=$_GET['id']?>.jpg">
</div>
...
698 1188354
>>188350

> echo '<img src="../upload/' . $_GET[id]. '.jpg">';


вот этот вариант рабочий.

> echo "<img src="../upload/{$_GET[id]}.jpg">";



а этот не рабочий

Но я бы сделал так:
?> <img src="../<?= $_GET['id'] ?>.jpg" /><?
699 1188355
>>188354
Просто на практике выводить строку с хтмл часто геморно. Проще закрыть пхп, дальше писать хтмл с микро вставками пхп с выводом переменных, а затем снова открыть пхп.
700 1188356
>>188350

>А еще ты можешь не эхать весь html с помощью пхп, а писать обычный html код, а где нужно уже вставлять переменные с помощью пхп тегов: <?=$var?>


Вот за это открытие большое человеческое спасибо. И в этой ситуации реально удобно, и ещё в паре мест лишние костыли выкину.
701 1188481
Тс
Какую библиотеку посоветуешь для написание парсера
702 1188492
>>188481
я на SimpleXML делал
703 1188528
Вопросы по тестхабу: https://gist.github.com/codedokode/8733007

> Сама информация в вопросах сохраняется в видимых или скрытых полях и отправляется на сервер как обычная форма. Проверку правильности надо сделать как на клиенте, яваскриптом, так и на сервере. Желательно, чтобы описания полей брались из одного источника, а не дублировались.



Как это сделать, есть какие-то готовые решения? Например для вопросов с одним вариантом ответа мне нужно сделать проверку, что хотя бы у одного из вариантов выставлено is_correct = true, как такую проверку не дублировать на фронте и бекенде? Формы симфони мне только дадут возможность использовать HTML5 валидацию, а как насчёт более сложных случаем? Я читал про JSON Schema, но не нашёл готовых пакетов. Велосипедить не хочу, такой велосипед потянет на отдельный пакет/бандл.

ОП, что посоветуешь для админки?
704 1188533
>>188528
Если тебе нужно и там и там то не дублировать не получится.

JSON это просто яваскрипт объект. Тоесть ты можешь из пхп выводить хтмл а можешь выводить яваскрипт.

Например

<script>
var question = <?= json_encode($question) ?>;
</script>

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

Но в твоей задаче сказано что надо хранить данные в полях а не в json, тоесть тебе нужно при выводе страницы сделать hidden инпуты. Например скрытый инпут с номером правильного ответа.

Единственный смысл проверки на клиенте, это юзабилити. Чтобы пользователю быстрей показать результат. Но без такой же проверки на сервере было бы неправильно, т.к. все что на клиенте можно подменить. Хотя в данной задаче было бы нелепо показывать юзеру результат до проверки на сервере и ответа. Поэтому самое юзабильное решение это аякс.
705 1188550
>>188340
Поясни
706 1188984
>>180308
Аккуратненько.
707 1189014
Нужно вставить в заголовок страницы переменную, значение которой объявляется в самой странице. Использую код:
<title>
<?php echo $title; ?>
</title>
Но вместо заголовка, содержащего значение переменной, появляется ошибка, мол $title не объявлена, хотя тот же самый <?php echo $title; ?> в самом body работает. Мне кажется, проблема в том, что <title> грузится раньше <body>, в котором объявляется переменная. Можно ли как-то устранить проблему? Объявить переменную не в <body> никак не получится.
708 1189016
>>189014

Просто если немножко подумать то ты поймешь что переменную нельзя использовать до того как она объявлена. Это было бы не логично.
709 1189032
>>189014
Хочется конечно взять и..., но я сдержусь, смотри дружище, тебе никто не мешает твой пхп код вставить вообще перед открывающим <html>
<?php
$title='ti';
$var1='pidor';
$closeHtml='</body></html>';
?>

<html>
<head>
....
<?=$title?>
</head>
<body>
<?=$var1?>
...
<?$closeHtml>

но на самом деле это всё залупа и хуйня, потому что лучше делай вот так - сначала в файле index.php, ты собственно пишешь пхп код и собираешь все переменные которые тебе нужны, потом ты пишешь в коде прям include "view.php"; в которой у тебя собственно лежит весь html с вставками переменных из пхп, это ты таким образом на самом простом уровне реализуешь подключение html шаблона в котором будет отделение, как бы выразиться попроще что бы тебе было яснее, фронтэнда от бэкэнда. Или отделение движка от отображения, или бизнес-логики от логики-представления - как тебе удобнее будет, так это и представляй.

Попробуй вот прям ща накидать себе два файла примерно таких index.php, view.php

index.php
<?
$title = "ti-huy";
$name = "naprimer";
$string = "ne pishi translitom v kode, ya delayu eto dla skorosti, no eto zashkvar";
include "view.php";
//end of index.php

view.php

<html>
<head>
<title><?=$title?></title>
</head>
<body>
<?=$string?>
</body>
</html>

и да, как ты мог заметить, вместо
<?php echo $title; ?>
лучше и быстрее использовать
<?=$title?>
Это компактная и удобная запись
709 1189032
>>189014
Хочется конечно взять и..., но я сдержусь, смотри дружище, тебе никто не мешает твой пхп код вставить вообще перед открывающим <html>
<?php
$title='ti';
$var1='pidor';
$closeHtml='</body></html>';
?>

<html>
<head>
....
<?=$title?>
</head>
<body>
<?=$var1?>
...
<?$closeHtml>

но на самом деле это всё залупа и хуйня, потому что лучше делай вот так - сначала в файле index.php, ты собственно пишешь пхп код и собираешь все переменные которые тебе нужны, потом ты пишешь в коде прям include "view.php"; в которой у тебя собственно лежит весь html с вставками переменных из пхп, это ты таким образом на самом простом уровне реализуешь подключение html шаблона в котором будет отделение, как бы выразиться попроще что бы тебе было яснее, фронтэнда от бэкэнда. Или отделение движка от отображения, или бизнес-логики от логики-представления - как тебе удобнее будет, так это и представляй.

Попробуй вот прям ща накидать себе два файла примерно таких index.php, view.php

index.php
<?
$title = "ti-huy";
$name = "naprimer";
$string = "ne pishi translitom v kode, ya delayu eto dla skorosti, no eto zashkvar";
include "view.php";
//end of index.php

view.php

<html>
<head>
<title><?=$title?></title>
</head>
<body>
<?=$string?>
</body>
</html>

и да, как ты мог заметить, вместо
<?php echo $title; ?>
лучше и быстрее использовать
<?=$title?>
Это компактная и удобная запись
710 1189035
>>189032

>Хочется конечно взять и..., но я сдержусь


А у меня как то гантеля в монитор прилетела.
711 1189036
>>189032
Да, все подтверждаю, лучше разделять, чтоб сначала вся бизнеслогика шла, а потом уже вывод с переменными. Но для начала если совсем нуб, то можно и в одном файле. Вверху логика, внизу вывод всей страницы.
712 1189037
>>189035
Я год назад телефон разъебал, пусть это и была звонилка за тясячу, но всё равно жалко, он у меня долго был и много где с ним путешествовал, в общем хороший телефон, и до сих пор жалко, похуй что он дешевый, ведь не в цене дело, помню на работе когда ходил срать в толчек бизнес центра играл на нем в змейку, охуенно было отдохнуть от всей этой суеты и на 15 минут отвлечься.
713 1189038
>>189037
А я не хотел отвлекаться. Я ебашил кислоту прям во время разработки. Код светился так охуенно.
714 1189039
>>189038
Я тогда эникеем работал, это я ща уже 3 года на пхп хуярю всякое говно и не могу решить до сих пор решить как организовать взаиодействие классов в кошках-мышках и дубрировать ли переменные координат или нет, но вангую это не по моей тупости, а потому что передо мной в этой задаче стоят на самом деле одни из базовых вопросов геймдева, и если об этом думать, то сильно голова закипает, так о чем это я. Эникеем я обслуживал контору из 3 этащей в БЦ и сотней человек штата, и постоянно кому-то было что-то нужно и на ногах был 90% времени поэтому, и вот как раз съебать подальше ото всех было иногда прост необходимо.
715 1189040
>>189039
Эйбля, представляю, я бы слабительное пил чтоб в параше весь день сидеть.
image.png446 Кб, 1920x1080
716 1189118
Почему вместо xml открывается html ?
Как это фиксить ?
717 1189119
>>189118
Скорее всего это браузер перестраивает, уже после получения.
718 1189120
>>189118
Попробуй сделать
$a = file_get_contents("brling.ru/sitemap.xml");
var_dump($a);
719 1189125
>>189120
то же самое будет.

Браузер сам закоментил первую строку xml и проставил критические html теги.

Надо гуглить настройки браузера в этом плане.
720 1189139
>>189120
>>189119
Я много способов попробовал, но все они тоже самое выводят.

$doc = new DOMDocument();
$doc->load('./sitemap.xml');
echo $doc->saveXML();

Остановился на этом.

В хроме, мозиле как на моем скриншоте. В Explorer 11 - все окей.
721 1189145
>>189139
Хедеры?
722 1189147
>>189139
Этот >>189145 анон, скорее всего, прав. По-умолчанию, браузер воспринимает документы как text/html, поэтому тебе нужно обязательно перед выводом передать клиенту заголовок

header("Content-Type: text/xml");
723 1189148
Если PHP обращается к приложению в консоле (через proc_open/close), то это приложение будет использовать системные переменные окружения или те что заданны в PHP в переменной $_ENV?

К примеру, если я в системе создам переменную окружения FOO='foo', а в PHP задам $_ENV['FOO']='bar'; то какое значение получит консольное приложение запущенное с помощью PHP?
724 1189281
>>189148
Нашел ответ проверив экспериментально:

Изменение переменной $_ENV - никак не отразилось на изменение переменных окружения.
Изменение глобальных переменных с помощью putenv("FOO=bar"); передалось и в консольное приложение, которое мы вызываем с помощь PHP.

В мануале по этой функции сказано:

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



Из чего можно сделать вывод, что у каждого "консольного клиента", в том числе и PHP, свой набор переменных окружения.
chat someApprentice 725 1189311
https://github.com/someApprentice/chat

В моем приложении есть серьёзная проблема.

Обновление сообщений и контактов происходит вызовом скрипта c определённым интервалом и возвратом времени когда этот скрипт был вызван, чтобы получать из БД только новые на текущий момент сообщения. Если сообщения были отправлены как раз в этот интервал (т.е. между вызовами скрипта), то эти сообщения не обновятся.

К тому же, ещё есть большая проблема с потреблением памяти, со временем, если оставить приложение открытом, то, спустя какое-то время, вызов скриптов загрузит всю память. У меня дошло до ~1.4Гб за менее чем пол часа.

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

Как можно добиться подобного поведения в PHP? Мне приходит на ум, что это асинхронное получение результатов из БД... То есть, если в БД появились новые сообщения, то скрипт триггерется.
726 1189376
>>189311
Пхп не предназначен для постоянной работы.
Сделай чтобы при запросе сообщений передавалось не время ответа а время последнего полученного сообщения. Тогда ты сможешь отдать все сообщения после последнего отданного.
727 1189397
>>189147

>header("Content-Type: text/xml");


Все окей, все заработало. Спасибо Анон
someApprentice 728 1189406
>>189376
Good call

Сделал https://github.com/someApprentice/chat/commit/9bf70b7215bb924f508249fd347be3b6e1b4bfef
Теперь сообщения перестали пропадать

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

Спасибо
729 1189418
методы Eloquent типа create защищены от sql инъекций?
730 1189465
Лол, сейчас игрался с css-transform, и обнаружил интересную штуку:

https://jsfiddle.net/e0Lk2a6v/

Скроллбар переместился вверх, но теперь можно скроллить влево-вправо колесиком мышки! Без JS. Без Shift-а.

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

У меня вот нашлось сразу идеальное место, куда применить. Мб кому полезно будет.
731 1189471
>>189465
хуя ты бешеный
732 1189476
>>189471
Попрошу Вас объясниться, мистер!
733 1189478
>>189465
Это ты еще до паралакса не дошел
734 1189484
>>189465

>https://jsfiddle.net/e0Lk2a6v/


Уж лучше не джээс сделать - проматывать на ширину блока при прокрутке колёсика. Так неудобно, так как приходится туда-сюда крутить, чтобы на страничку попасть.
7.jpg593 Кб, 1026x1002
735 1189509
>>174695 (OP)
>>187793
Задачка Yoda speak на проверку

http://sandbox.onlinephpfunctions.com/code/bd50ad5b1ba78da4cac28247e93a098a77a1713e

К сожалению на ideone функции с приставкой mb_ не хотят исполняться.
736 1189575
Аноны, а зачем нужны фигурные скобки внутри echo? Делаю задачку на кубики и там "У анона выпало {$anonDice1} и {$anonDice2}". Зачем здесь {}?
737 1189647
>>189575
В данном случае не обязательно. Нужны если выводишь элемент массива или свойство объекта.

Но лично я ставлю всегда, чтобы было везде одинаково
738 1189665
что будет в 8 версии пхп?
739 1189685
>>189665
кнопка "сделать сайт"
740 1189690
Скажите, пожалуйста, что я сделал не так? Где я обосрался?
https://ideone.com/5QSOQE
На сайте написано: Правильный ответ: чуть больше миллиона накопится примерно за 49 лет, соответственно вкладчику исполнится 65.
Но у меня к 65-летию у него ток 970к, а миллион будет на 66 лет.
741 1189696
>>189690
А все, нашел ошибку. Пиздец я тупой.
742 1189784
>>189465
Либо муисам гавно, либо я дебил.

Как может быть что
SELECT .. LIKE 'cat'
находит что нужно а
SELECT .. AGAINST ( 'cat' IN NATURAL LANGUAGE MODE )
или
SELECT .. AGAINST ( '+cat' IN BOOLEAN MODE )
НИЧЕГО?
SELECT .. AGAINST ( '"cat"' IN BOOLEAN MODE )
Ничего.
SELECT .. AGAINST ( 'cat*' IN BOOLEAN MODE )
что угодно кроме 'cat'.

Там где отрабатывает - порой крайне странно ранжирует.

Может он просто не рассчитан на текст из одного-двух слов?

p.s.: какие шансы уебать базу при апгрейде с MDB 5.5 на десятку?
743 1189816
Как через пхп можно сделать скриншот? Может библиотека какая то есть. Я гуглил, но ничего вразумительного не нашел, мне это для бота надо.
744 1189827
>>189816
Если ты о скриншоте страницы, то это javascript и html5 canvas.
745 1189829
>>189827
Хотя зачем я сказал про canvas
746 1189862
>>189827

>Если ты о скриншоте страницы, то это javascript и html5 canvas.


Да, я о странице. Я думал отправить запрос на сервер, получить html и как то сэмулировать браузер, но вот как это сделать, не знаю.
747 1189884
>>189862

>Симулировать браузер на пхп.


Поверь, оно того не стоит.

Но, возможно есть какойнибуь сервис который это делает. Шлешь туда хтмл, получаешь в ответ картинку, теоритически. Ну для этого curl нужно юзать.
748 1189930
>>189884

>есть какойнибуь сервис


Есть, анон, есть http://browsershots.org/
749 1189942
Я как то на пыхе вот с этим взаимодействовал
https://www.betaface.com/wpa/
716-749 750 1190029
>>189827
>>189816

Канвас никак не позволяет делать скриншоты страниц. Для этого надо либо запускать управляемый браузер (headless/selenium), либо использовать сторонний сервис создания скриншотов.

>>189784

А ты можешь тут на http://sqlfiddle.com/ воссоздать ситуацию? Создать таблицу с парой-тройкой записей и проверить?

А то так трудно понять.

>>189690

10 000 р будет не в 17, а в 16 лет.

>>189575

Подробно объяснено в мануале http://php.net/manual/ru/language.types.string.php#language.types.string.parsing

Тут они не обязательны, но и вреда особого от них нет.

>>189509

> mb_convert_case($text, MB_CASE_LOWER, $encoding)


Можно просто mb_strtolower

Функция makeFirstletterUppercase читается не очень хорошо из-за обилия скобок. Лучше наверно так:

$firstLetter = mb_substr(...);
...

Кроме \K, можно было еще использовать assertions ( http://php.net/manual/en/regexp.reference.assertions.php ) которые не захватывают символы, вроде (?=[...])

Название переменной $word неудачное, можно подумать, что там всего одно слово, а там массив слов.

В остальном верно.
716-749 750 1190029
>>189827
>>189816

Канвас никак не позволяет делать скриншоты страниц. Для этого надо либо запускать управляемый браузер (headless/selenium), либо использовать сторонний сервис создания скриншотов.

>>189784

А ты можешь тут на http://sqlfiddle.com/ воссоздать ситуацию? Создать таблицу с парой-тройкой записей и проверить?

А то так трудно понять.

>>189690

10 000 р будет не в 17, а в 16 лет.

>>189575

Подробно объяснено в мануале http://php.net/manual/ru/language.types.string.php#language.types.string.parsing

Тут они не обязательны, но и вреда особого от них нет.

>>189509

> mb_convert_case($text, MB_CASE_LOWER, $encoding)


Можно просто mb_strtolower

Функция makeFirstletterUppercase читается не очень хорошо из-за обилия скобок. Лучше наверно так:

$firstLetter = mb_substr(...);
...

Кроме \K, можно было еще использовать assertions ( http://php.net/manual/en/regexp.reference.assertions.php ) которые не захватывают символы, вроде (?=[...])

Название переменной $word неудачное, можно подумать, что там всего одно слово, а там массив слов.

В остальном верно.
751 1190030
>>189465

Интересное решение. Хотя у меня на тачпаде например и так есть горизонтальная прокрутка, жаль, не все программы ее поддерживают и в линуксе ее нет.

>>189418

Надо смотреть сначала в документацию, потом в код.

Обрати внимание, что при использовании mass assignment из данных пользователя надо контролировать, каким полям можно присваивать значения, а каким - нет, иначе пользователь может изменить какие-то служебные поля: https://laravel.com/docs/5.6/eloquent#mass-assignment

В документации ничего не сказано, посмотрим в код метода create():

- https://github.com/illuminate/database/blob/master/Eloquent/Model.php#L1514
- https://github.com/illuminate/database/blob/master/Eloquent/Builder.php#L788

Он вызывает $this->newModelInstance($attributes); и затем $instance->save();

которая вызывает model->newInstance($attributes)

- https://github.com/illuminate/database/blob/master/Eloquent/Model.php#L282

Эта функция передает атрибуты в конструктор, а тот передает их в fill():

- https://github.com/illuminate/database/blob/master/Eloquent/Model.php#L212

Далее вызывается:

> $key = $this->removeTableFromKey($key);


> ...


> $this->setAttribute($key, $value);



removeTableFromKey() удаляет все, что идет до точки, если она есть: https://github.com/illuminate/database/blob/master/Eloquent/Model.php#L271

setAttribute() описана тут: https://github.com/illuminate/database/blob/master/Eloquent/Concerns/HasAttributes.php#L533

Она сохраняет переданные данные:

> $this->attributes[$key] = $value;



Вернемся к save(). Она вызывает в итоге https://github.com/illuminate/database/blob/master/Eloquent/Model.php#L666

А та уже https://github.com/illuminate/database/blob/master/Query/Builder.php#L2336

В общем, я думаю, что значения элементов массива экранируются. Насчет ключей - на 100% не уверен, что там нет чего-нибудь этакого.
751 1190030
>>189465

Интересное решение. Хотя у меня на тачпаде например и так есть горизонтальная прокрутка, жаль, не все программы ее поддерживают и в линуксе ее нет.

>>189418

Надо смотреть сначала в документацию, потом в код.

Обрати внимание, что при использовании mass assignment из данных пользователя надо контролировать, каким полям можно присваивать значения, а каким - нет, иначе пользователь может изменить какие-то служебные поля: https://laravel.com/docs/5.6/eloquent#mass-assignment

В документации ничего не сказано, посмотрим в код метода create():

- https://github.com/illuminate/database/blob/master/Eloquent/Model.php#L1514
- https://github.com/illuminate/database/blob/master/Eloquent/Builder.php#L788

Он вызывает $this->newModelInstance($attributes); и затем $instance->save();

которая вызывает model->newInstance($attributes)

- https://github.com/illuminate/database/blob/master/Eloquent/Model.php#L282

Эта функция передает атрибуты в конструктор, а тот передает их в fill():

- https://github.com/illuminate/database/blob/master/Eloquent/Model.php#L212

Далее вызывается:

> $key = $this->removeTableFromKey($key);


> ...


> $this->setAttribute($key, $value);



removeTableFromKey() удаляет все, что идет до точки, если она есть: https://github.com/illuminate/database/blob/master/Eloquent/Model.php#L271

setAttribute() описана тут: https://github.com/illuminate/database/blob/master/Eloquent/Concerns/HasAttributes.php#L533

Она сохраняет переданные данные:

> $this->attributes[$key] = $value;



Вернемся к save(). Она вызывает в итоге https://github.com/illuminate/database/blob/master/Eloquent/Model.php#L666

А та уже https://github.com/illuminate/database/blob/master/Query/Builder.php#L2336

В общем, я думаю, что значения элементов массива экранируются. Насчет ключей - на 100% не уверен, что там нет чего-нибудь этакого.
752 1190031
>>189311

> К тому же, ещё есть большая проблема с потреблением памяти, со временем, если оставить приложение открытом, то, спустя какое-то время, вызов скриптов загрузит всю память. У меня дошло до ~1.4Гб за менее чем пол часа.



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

Гугление находит:

1) https://github.com/BitOne/php-meminfo

2) Использовать режим trace в xdebug, который пишет в лог каждый вызов функции и потребление памяти в этот момент. Как-то проанализировать лог в поисках функций, при вызове которых потребление только растет.

Что-то еще я нагуглил тут: https://stackoverflow.com/questions/16068301/how-to-find-which-php-script-is-leaking-memory/36288686#36288686

> Обновление сообщений и контактов происходит вызовом скрипта c определённым интервалом и возвратом времени когда этот скрипт был вызван, чтобы получать из БД только новые на текущий момент сообщения.



Скрипт на сервере должен возвращать время для следующего запроса. Тут стоит еще помнить, что время может быть разным на клиенте/сервере и лучше использовать в запросе полученное от сервера же время.

> В популярной соц.сете, эта проблема решается следующим образом, добавляется параметр wait и ответ поступает только спустя это время. Но, если собеседник отправляет сообщение, то этот скрипт вызывается мгновенно.


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



Это так называемый long polling - когда скрипт "подвисает" до наступления события (или до таймаута). Это вариант для случаев, когда недоступен или не хочется использовать вебсокет. Возможно соцсеть использует его потому, что этот метод более устойчив в случае разрывов связи, но я не уверен, это надо делать тесты. Или может, потому что он кросс-браузерней и не требует вебсокета. Или потому, что не все прокси (в организациях) пропускают вебсокет.

Таймаут нужен, так как браузер, а также промежуточные прокси или NAT-сервера могут прибивать "подвисшие" соединения, по которым ничего не передается. Потому обычно его ставят в пределах 20-60 секунд.

Опишем задачу: у нас есть один процесс (или поток) на сервере, который обрабатывает соединение от клиента (wait.php) и "висит" в ожидании уведомлений для него или в ожидании таймаута - subscriber. И есть второй процесс/поток, который добавляет новое сообщение в БД и хочет как-то уведомить все ждущие потоки первого типа о появлении нового сообщения - publisher. Такая архитектура еще называется publish/subscribe (pub/sub) - есть те, кто "публикует" сообщения, и есть те, кто "подписывается" на их получение.

Чтобы понять, кто какое уведомление ждет, введем "идентификатор канала" - channelId. Подписчик подписывается на сообщения с определенным channelId. Наша система лишь уведомляет об изменениях, она не передает их содержание, подписчик должен сам извлечь новые сообщения из базы данных.

channelId может, например, просто равняться userId пользователя, которому предназначено сообщение.

Реализуется это в общем за счет межпроцессного (межпоточного) взаимодействия, IPC: https://ru.wikipedia.org/wiki/Межпроцессное_взаимодействие

Это набор "примитивов", которые реализуются по-разному в зависимости от ситуации, используемой ОС и тд. При этом не очень принципиально, о чем идет речь - о потоках, о "зеленых" тредах (асинхронное программирование), о процессах или даже о запущенных на разных машинах процессах. Я буду писать просто "поток".

Если посмотреть на примитивы IPC, то для нашей задачи подошли бы, например, семафоры ( https://ru.wikipedia.org/wiki/Семафор_(информатика) ). Семафор умеет блокироваться до того, как его "отпустят". Вот, как может выглядеть код:

// Создаем доступную всем потокам таблицу семафоров. Она имеет структуру
//
// {
// channel1: [ semaphore1, semaphore2, semaphore3 ],
// channel2: [ semaphore ],
// ....
// }
//
// Каждый подписчик создает и кладет в таблицу свой семафор под нужным ему channelId.
// На одном канале может быть несколько подписчиков.
//
var semaphores = {};

// Функция для потока-подписчика, она ждет публикации
// сообщения с данным channelId неограниченное время
function waitForMessages(channelId) {

// создаем семафор, который блокируется при попытке захвата
var semaphore = initSemaphore(0);

// добавляем его в список
if (!semaphores[channelId]) {
semaphores[channelId] = [];
}

semaphores[channelId].push(semaphore);

// блокируемся до появления события
// (так как семафор имеет значение 0)
semaphore.enter();

// получено новое сообщение, удаляем не нужный более семафор
// из массива
removeFromArray(semaphores[channelId], semaphore);
semaphore.destroy();
}

// Функция для издателя, "будит" все потоки, ждущие сообщения
// с данным channelId
function publishMessage(channelId) {
// Находим все ждущие семафоры и "отпускаем" их
if (!semaphores[channelId]) {
return;
}

semaphores[channelId].forEach(function (semaphore) {
// Отпускаем семафор и позволяем ждущему на нем потоку
// захватить его в enter()
semaphore.leave();
});
}

В этом коде я использовал особенность Node.JS, что она однопоточная и функция выполняется целиком, потому нам не надо беспокоиться о гонках между потоками (например, в процессе выполнения forEach никто не добавляет или удаляет элементы из массива). В других языках могут потребоваться дополнительные блокировки во время работы с разделяемым массивом semaphores.

Также, я не реализовал таймаут ожидания уведомления - оставим это как домашнее задание читателю, например, можно "отпускать" семафор в подписчике примерно таким кодом:

setTimeout(function () {
semaphore.leave();
}, timeout);

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

Также, приведенный выше код требует, чтобы из всех потоков была доступна переменная semaphores и потому работает только внутри одного процесса Node.JS. Это лишь демонстрация архитектуры pub/sub.

Если ты хочешь реализовать pubsub между разными процессами, или тем более, разными машинами, этот подход не подойдет и проще использовать брокер (брокер = посредник при сделке) - специальный процесс, реализующий паттерн pubsub. Брокер является сервером (например, TCP-сервером), к нему подсоединяются клиенты-подписчики, ждущие новых сообщений, и клиенты-издатели, желающие уведомлять подписчиков.

Например, есть такие варианты:

- pubsub встроен в сервер redis: https://redis.io/topics/pubsub который может служить брокером
- самописный брокер на ReactPHP, в котором есть поддержка WAMP (Websocket App. Messaging Protocol), в котором есть в том числе и подписки, а также поддержка и websocket, и long polling. Это работает внутри одного процесса PHP.
- написать свой брокер на Node.JS с использованием готовых библиотек
- написать на Го
- сервер очередей RabbitMQ: https://ru.wikipedia.org/wiki/RabbitMQ - он, кстати, поддерживает HTTP и возможно, подписчик может подсоединяться напрямую с клиента
- сервер очередей ZeroMQ

Есть и другие брокеры. Есть так же более-менее стандартные протоколы MQTT и AMPQ, чтобы для разных брокеров можно было использовать общие клиентские библиотеки.

Ты можешь использовать pubsub внутри одного процесса (например, иметь единый процесс на ReactPHP, который обслуживает все соединения и который внутри содержит брокер, например, встроенный в WAMP) или использовать отдельный, внешний брокер. В этом варианте подписчики соединяются с брокером в ожидании уведомлений, а издатели подсоединяются к брокеру для публикации уведомления.

В случае внешнего брокера, есть опять же 2 варианта:

- браузер подсоеиняется к процессу PHP, который соединяется с брокером
- браузер напрямую подсоединяется к брокеру, если он поддерживает HTTP и такой режим доступа

Браузер может использовать long polling или websocket в зависимости от условий и реализации. Если используется websocket и протокол WAMP, то в него уже встроена возможность подписываться на каналы, и клиентская JS-библиотека с нужными функциями - сервер должен ее только реализовать. Вот пример такой клиентской библиотеки: https://github.com/crossbario/autobahn-js

В плане масштабирования есть такие варианты:

- использовать единый внешний брокер сообщений (готовый или самописный) - это годится для маленьких масштабов.
- использовать много брокеров, составить соответствие между channelId и IP/портом брокера и подсоединяться к нужному - это неограниченно масштабируемая схема.

Надеюсь, я не слишком запутал? Задавай уточняющие вопросы тогда.
752 1190031
>>189311

> К тому же, ещё есть большая проблема с потреблением памяти, со временем, если оставить приложение открытом, то, спустя какое-то время, вызов скриптов загрузит всю память. У меня дошло до ~1.4Гб за менее чем пол часа.



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

Гугление находит:

1) https://github.com/BitOne/php-meminfo

2) Использовать режим trace в xdebug, который пишет в лог каждый вызов функции и потребление памяти в этот момент. Как-то проанализировать лог в поисках функций, при вызове которых потребление только растет.

Что-то еще я нагуглил тут: https://stackoverflow.com/questions/16068301/how-to-find-which-php-script-is-leaking-memory/36288686#36288686

> Обновление сообщений и контактов происходит вызовом скрипта c определённым интервалом и возвратом времени когда этот скрипт был вызван, чтобы получать из БД только новые на текущий момент сообщения.



Скрипт на сервере должен возвращать время для следующего запроса. Тут стоит еще помнить, что время может быть разным на клиенте/сервере и лучше использовать в запросе полученное от сервера же время.

> В популярной соц.сете, эта проблема решается следующим образом, добавляется параметр wait и ответ поступает только спустя это время. Но, если собеседник отправляет сообщение, то этот скрипт вызывается мгновенно.


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



Это так называемый long polling - когда скрипт "подвисает" до наступления события (или до таймаута). Это вариант для случаев, когда недоступен или не хочется использовать вебсокет. Возможно соцсеть использует его потому, что этот метод более устойчив в случае разрывов связи, но я не уверен, это надо делать тесты. Или может, потому что он кросс-браузерней и не требует вебсокета. Или потому, что не все прокси (в организациях) пропускают вебсокет.

Таймаут нужен, так как браузер, а также промежуточные прокси или NAT-сервера могут прибивать "подвисшие" соединения, по которым ничего не передается. Потому обычно его ставят в пределах 20-60 секунд.

Опишем задачу: у нас есть один процесс (или поток) на сервере, который обрабатывает соединение от клиента (wait.php) и "висит" в ожидании уведомлений для него или в ожидании таймаута - subscriber. И есть второй процесс/поток, который добавляет новое сообщение в БД и хочет как-то уведомить все ждущие потоки первого типа о появлении нового сообщения - publisher. Такая архитектура еще называется publish/subscribe (pub/sub) - есть те, кто "публикует" сообщения, и есть те, кто "подписывается" на их получение.

Чтобы понять, кто какое уведомление ждет, введем "идентификатор канала" - channelId. Подписчик подписывается на сообщения с определенным channelId. Наша система лишь уведомляет об изменениях, она не передает их содержание, подписчик должен сам извлечь новые сообщения из базы данных.

channelId может, например, просто равняться userId пользователя, которому предназначено сообщение.

Реализуется это в общем за счет межпроцессного (межпоточного) взаимодействия, IPC: https://ru.wikipedia.org/wiki/Межпроцессное_взаимодействие

Это набор "примитивов", которые реализуются по-разному в зависимости от ситуации, используемой ОС и тд. При этом не очень принципиально, о чем идет речь - о потоках, о "зеленых" тредах (асинхронное программирование), о процессах или даже о запущенных на разных машинах процессах. Я буду писать просто "поток".

Если посмотреть на примитивы IPC, то для нашей задачи подошли бы, например, семафоры ( https://ru.wikipedia.org/wiki/Семафор_(информатика) ). Семафор умеет блокироваться до того, как его "отпустят". Вот, как может выглядеть код:

// Создаем доступную всем потокам таблицу семафоров. Она имеет структуру
//
// {
// channel1: [ semaphore1, semaphore2, semaphore3 ],
// channel2: [ semaphore ],
// ....
// }
//
// Каждый подписчик создает и кладет в таблицу свой семафор под нужным ему channelId.
// На одном канале может быть несколько подписчиков.
//
var semaphores = {};

// Функция для потока-подписчика, она ждет публикации
// сообщения с данным channelId неограниченное время
function waitForMessages(channelId) {

// создаем семафор, который блокируется при попытке захвата
var semaphore = initSemaphore(0);

// добавляем его в список
if (!semaphores[channelId]) {
semaphores[channelId] = [];
}

semaphores[channelId].push(semaphore);

// блокируемся до появления события
// (так как семафор имеет значение 0)
semaphore.enter();

// получено новое сообщение, удаляем не нужный более семафор
// из массива
removeFromArray(semaphores[channelId], semaphore);
semaphore.destroy();
}

// Функция для издателя, "будит" все потоки, ждущие сообщения
// с данным channelId
function publishMessage(channelId) {
// Находим все ждущие семафоры и "отпускаем" их
if (!semaphores[channelId]) {
return;
}

semaphores[channelId].forEach(function (semaphore) {
// Отпускаем семафор и позволяем ждущему на нем потоку
// захватить его в enter()
semaphore.leave();
});
}

В этом коде я использовал особенность Node.JS, что она однопоточная и функция выполняется целиком, потому нам не надо беспокоиться о гонках между потоками (например, в процессе выполнения forEach никто не добавляет или удаляет элементы из массива). В других языках могут потребоваться дополнительные блокировки во время работы с разделяемым массивом semaphores.

Также, я не реализовал таймаут ожидания уведомления - оставим это как домашнее задание читателю, например, можно "отпускать" семафор в подписчике примерно таким кодом:

setTimeout(function () {
semaphore.leave();
}, timeout);

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

Также, приведенный выше код требует, чтобы из всех потоков была доступна переменная semaphores и потому работает только внутри одного процесса Node.JS. Это лишь демонстрация архитектуры pub/sub.

Если ты хочешь реализовать pubsub между разными процессами, или тем более, разными машинами, этот подход не подойдет и проще использовать брокер (брокер = посредник при сделке) - специальный процесс, реализующий паттерн pubsub. Брокер является сервером (например, TCP-сервером), к нему подсоединяются клиенты-подписчики, ждущие новых сообщений, и клиенты-издатели, желающие уведомлять подписчиков.

Например, есть такие варианты:

- pubsub встроен в сервер redis: https://redis.io/topics/pubsub который может служить брокером
- самописный брокер на ReactPHP, в котором есть поддержка WAMP (Websocket App. Messaging Protocol), в котором есть в том числе и подписки, а также поддержка и websocket, и long polling. Это работает внутри одного процесса PHP.
- написать свой брокер на Node.JS с использованием готовых библиотек
- написать на Го
- сервер очередей RabbitMQ: https://ru.wikipedia.org/wiki/RabbitMQ - он, кстати, поддерживает HTTP и возможно, подписчик может подсоединяться напрямую с клиента
- сервер очередей ZeroMQ

Есть и другие брокеры. Есть так же более-менее стандартные протоколы MQTT и AMPQ, чтобы для разных брокеров можно было использовать общие клиентские библиотеки.

Ты можешь использовать pubsub внутри одного процесса (например, иметь единый процесс на ReactPHP, который обслуживает все соединения и который внутри содержит брокер, например, встроенный в WAMP) или использовать отдельный, внешний брокер. В этом варианте подписчики соединяются с брокером в ожидании уведомлений, а издатели подсоединяются к брокеру для публикации уведомления.

В случае внешнего брокера, есть опять же 2 варианта:

- браузер подсоеиняется к процессу PHP, который соединяется с брокером
- браузер напрямую подсоединяется к брокеру, если он поддерживает HTTP и такой режим доступа

Браузер может использовать long polling или websocket в зависимости от условий и реализации. Если используется websocket и протокол WAMP, то в него уже встроена возможность подписываться на каналы, и клиентская JS-библиотека с нужными функциями - сервер должен ее только реализовать. Вот пример такой клиентской библиотеки: https://github.com/crossbario/autobahn-js

В плане масштабирования есть такие варианты:

- использовать единый внешний брокер сообщений (готовый или самописный) - это годится для маленьких масштабов.
- использовать много брокеров, составить соответствие между channelId и IP/портом брокера и подсоединяться к нужному - это неограниченно масштабируемая схема.

Надеюсь, я не слишком запутал? Задавай уточняющие вопросы тогда.
753 1190032
>>189376

Вполне себе предназначен - ReactPHP.

>>189406

Я бы не советовал вообще вычислять время на сервере PHP, чтобы не сталкиваться с проблемами расхождения времени на клиенте, сервере, особенно если их несколько. Лучше пусть клиент присылает время последнего доступного ему сообщения, или, может, id (чтобы он был уникальным).

>>189281

Массив $_ENV это лишь копия переменных, доступных в момент запуска PHP скрипта. Его изменение ни на что не влияет. Ты можешь изменить переменные окружения процесса (для текущего процесса, которые будут наследоваться запущенными из него процессами) с помощью putenv(). А получить текущие значения с помощью getenv().

Кстати, в некоторых конфигурациях $_ENV вообще пуст. Его заполнение включается где-то в php.ini.

> Из чего можно сделать вывод, что у каждого "консольного клиента", в том числе и PHP, свой набор переменных окружения.



У каждого процесса в ОС своя копия переменных. Она копируется от родителя в момент создания процесса, но это именно независимая копия.

>>189148

Она унаследует переменные процесса PHP в момент запуска внешней программы. $_ENV ни на что не влияет.
754 1190039
>>190029
Неапрва. Я когдато гуглил. Канвас нужен чтобы получить достутп к графическому апи html5 на странице, а с его помощью можно сделать снимок внутри произвольной области внутри любого элемента.
755 1190040

>ReactPHP



Ебать извращение.
756 1190041
>>190039

Это работает с большими ограничениями, если верить статье https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Drawing_DOM_objects_into_a_canvas и не получится это использовать для рендеринга произвольного стороннего сайта.
757 1190042
>>190032
Пыха изначально разрабатывалась для http.
Тоесть: Запрос -> Выполнение -> Ответ.

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

А так конечно, я даже видел среду разработки десктоп-приложений на php.
758 1190043

>>>1190032


>Я бы не советовал вообще вычислять время на сервере PHP, чтобы не сталкиваться с проблемами расхождения времени на клиенте, сервере, особенно если их несколько. Лучше пусть клиент присылает время последнего доступного ему сообщения, или, может, id (чтобы он был уникальным)



Ебашишь простыни и не видишь что то же самое уже предложено. Мамкин умник.
759 1190045
>>190042

Тебе именно что кажется. По твоей логике, JS разрабатывался для использования в браузере и на сервере ему делать нечего.
760 1190046
>>190045
Нет, яваскрипт разрабатывался не для браузера.
изображение.png2 Кб, 817x82
761 1190213
>>189509
Кстати по поводу библиотеки mbstring в ideone, я же им писал две недели назад.
762 1190234
>>190213
Видимо у них пока нет времени на это. А тебе спасибо за доброе дело!

Благодаря ошибкам на ideone я наконец разобрался с openserver, теперь гораздо удобнее проверять свои поделки. Но судя по треду лучшее решение это установить lamp на сервер и подключаться к нему, что скажете?
763 1190271
>>190234
Open server достаточно. 7 лет на нем, никаких проблем.
someApprentice 764 1190295
>>190031

>> К тому же, ещё есть большая проблема с потреблением памяти, со временем, если оставить приложение открытом, то, спустя какое-то время, вызов скриптов загрузит всю память. У меня дошло до ~1.4Гб за менее чем пол часа.


>


>Нужно искать место утечки памяти. В идеале, должен быть какой-то инструмент, который меряет число выделений/освобождений памяти, находит неосвобожденные куски и пишет стектрейсы, где они были выделены.


>


>Гугление находит:


>


>1) https://github.com/BitOne/php-meminfo


>


>2) Использовать режим trace в xdebug, который пишет в лог каждый вызов функции и потребление памяти в этот момент. Как-то проанализировать лог в поисках функций, при вызове которых потребление только растет.


>


>Что-то еще я нагуглил тут: https://stackoverflow.com/questions/16068301/how-to-find-which-php-script-is-leaking-memory/36288686#36288686


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

>> Обновление сообщений и контактов происходит вызовом скрипта c определённым интервалом и возвратом времени когда этот скрипт был вызван, чтобы получать из БД только новые на текущий момент сообщения.


>


>Скрипт на сервере должен возвращать время для следующего запроса. Тут стоит еще помнить, что время может быть разным на клиенте/сервере и лучше использовать в запросе полученное от сервера же время.


Или таймстамп. Но зачем возвращать время для следующего запроса, в клиенте можно же самому выставить интервал?

>> В популярной соц.сете, эта проблема решается следующим образом, добавляется параметр wait и ответ поступает только спустя это время. Но, если собеседник отправляет сообщение, то этот скрипт вызывается мгновенно.


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


>


>Это так называемый long polling - когда скрипт "подвисает" до наступления события (или до таймаута). Это вариант для случаев, когда недоступен или не хочется использовать вебсокет. Возможно соцсеть использует его потому, что этот метод более устойчив в случае разрывов связи, но я не уверен, это надо делать тесты. Или может, потому что он кросс-браузерней и не требует вебсокета. Или потому, что не все прокси (в организациях) пропускают вебсокет.


Значит нужно поскорей переходить на вебсокет...

>Надеюсь, я не слишком запутал? Задавай уточняющие вопросы тогда.


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

Виртуальный сервер к которому приходят запросы это один единственный процесс или на каждый запрос создается свой собственный?

Если виртуальный сервер, это один единственный процесс, то я могу предположить, что значит уже сам PHP создает "дерево" из нескольких процессов, это так?

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

Чтобы понять как работает паттерн pub/sub, я заглянул на вики и там обнаружил, что

>Шаблон издатель-подписчик представляет собой расширение шаблона наблюдатель, в который добавлено описание канала событий (англ. event channel), специально предназначенного для оповещения о событиях.


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

>>190032

>Я бы не советовал вообще вычислять время на сервере PHP, чтобы не сталкиваться с проблемами расхождения времени на клиенте, сервере, особенно если их несколько. Лучше пусть клиент присылает время последнего доступного ему сообщения, или, может, id (чтобы он был уникальным).


А клиент не пользуется этим временем, он просто пересылает его обратно PHP. Однако, я вижу аргумент за использование ID вместо даты - так надёжнее.
someApprentice 764 1190295
>>190031

>> К тому же, ещё есть большая проблема с потреблением памяти, со временем, если оставить приложение открытом, то, спустя какое-то время, вызов скриптов загрузит всю память. У меня дошло до ~1.4Гб за менее чем пол часа.


>


>Нужно искать место утечки памяти. В идеале, должен быть какой-то инструмент, который меряет число выделений/освобождений памяти, находит неосвобожденные куски и пишет стектрейсы, где они были выделены.


>


>Гугление находит:


>


>1) https://github.com/BitOne/php-meminfo


>


>2) Использовать режим trace в xdebug, который пишет в лог каждый вызов функции и потребление памяти в этот момент. Как-то проанализировать лог в поисках функций, при вызове которых потребление только растет.


>


>Что-то еще я нагуглил тут: https://stackoverflow.com/questions/16068301/how-to-find-which-php-script-is-leaking-memory/36288686#36288686


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

>> Обновление сообщений и контактов происходит вызовом скрипта c определённым интервалом и возвратом времени когда этот скрипт был вызван, чтобы получать из БД только новые на текущий момент сообщения.


>


>Скрипт на сервере должен возвращать время для следующего запроса. Тут стоит еще помнить, что время может быть разным на клиенте/сервере и лучше использовать в запросе полученное от сервера же время.


Или таймстамп. Но зачем возвращать время для следующего запроса, в клиенте можно же самому выставить интервал?

>> В популярной соц.сете, эта проблема решается следующим образом, добавляется параметр wait и ответ поступает только спустя это время. Но, если собеседник отправляет сообщение, то этот скрипт вызывается мгновенно.


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


>


>Это так называемый long polling - когда скрипт "подвисает" до наступления события (или до таймаута). Это вариант для случаев, когда недоступен или не хочется использовать вебсокет. Возможно соцсеть использует его потому, что этот метод более устойчив в случае разрывов связи, но я не уверен, это надо делать тесты. Или может, потому что он кросс-браузерней и не требует вебсокета. Или потому, что не все прокси (в организациях) пропускают вебсокет.


Значит нужно поскорей переходить на вебсокет...

>Надеюсь, я не слишком запутал? Задавай уточняющие вопросы тогда.


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

Виртуальный сервер к которому приходят запросы это один единственный процесс или на каждый запрос создается свой собственный?

Если виртуальный сервер, это один единственный процесс, то я могу предположить, что значит уже сам PHP создает "дерево" из нескольких процессов, это так?

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

Чтобы понять как работает паттерн pub/sub, я заглянул на вики и там обнаружил, что

>Шаблон издатель-подписчик представляет собой расширение шаблона наблюдатель, в который добавлено описание канала событий (англ. event channel), специально предназначенного для оповещения о событиях.


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

>>190032

>Я бы не советовал вообще вычислять время на сервере PHP, чтобы не сталкиваться с проблемами расхождения времени на клиенте, сервере, особенно если их несколько. Лучше пусть клиент присылает время последнего доступного ему сообщения, или, может, id (чтобы он был уникальным).


А клиент не пользуется этим временем, он просто пересылает его обратно PHP. Однако, я вижу аргумент за использование ID вместо даты - так надёжнее.
765 1190415
>>190295

Если в браузере - попробуй использовать средства разработчика, вкладка Profiles, опции Take Heap Snapshot и Record Heap Allocations. Такое потребление абсолютно ненормально и скорее всего вызвано ошибками в коде.

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

> Или таймстамп. Но зачем возвращать время для следующего запроса, в клиенте можно же самому выставить интервал?



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

/new-messages?from=0

получает какие-то сообщения и новое значение для from (или вычисляет его сам из максимального времени у последнего сообщения). И использует это значение в следующем запросе.

> Значит нужно поскорей переходить на вебсокет...



Тут лучше сделать сравнение. Кто знает, может при неустойчивой связи как раз long polling надежнее работает.

> Прежде чем разобраться межпроцессным взаимодействием, нужно разобраться как работают процессы.



Процесс - это, условно, говоря абстрактная сущность, которая соответствует выполняющейся программе и под которую ОС выделяет ресурсы, в первую очередь память и процессорное время. Ты можешь увидеть список процессов командами вроде ps lax или top.

Процесс в ядре имеет уникальный номер (PID = process id, а также TGID = thread group id), который ты можешь увидеть в выводе команды top или ps lax в колонке с заголовком PID. Ресурсы - в первую очередь это изолированная область памяти (плюс еще кое-что по мелочи: набор переменных окружения, таблица открытых файлов и тд). Когда ты запускаешь какую-то команду (например, ls), ядро ОС создает новый "процесс", добавляет его в список процессов, выделяет кусок памяти, мапит (отображает) туда исполняемый файл /bin/ls и создает внутри процесса "поток", который будет выполнять двоичный код из этого файла.

"Поток" (тред, поток выполнения кода) это абстрактная штука, которая может выполнять код. В каждом живом процессе есть минимум один поток. В ядре ОС есть планировщик потоков, который постоянно переключает имеющиеся процессоры между потоками, создавая иллюзию параллельного выполнения всех потоков. Код может порождать новые потоки внутри того же процесса, также, потоки могут завершаться, если они выполнили свой код и больше не нужны. В линуксе потоки еще называются Light Weight Processes, они идентифицируются уникальным номером TID (thread id). Чтобы увидеть отдельные потоки, надо добавить к команде ps lax опцию -T, она выводит идентификатор потока (тот, что TID) под заголовком SPID, а идентификатор процесса под заголовком PID. Путаница вызвана историческими причинами, в первую очередь тем, что современные потоки появлились где-то в районе linux 2.4, а до этого была другая система ( https://unix.stackexchange.com/questions/364660/are-threads-implemented-as-processes-on-linux ).

Мануал по функции clone(), порождающей процессы и потоки в Линуксе, описывает названия TID, PID и TGID: http://man7.org/linux/man-pages/man2/clone.2.html Можно считать, что PID/TGID совпадает с TID самого первого потока в процессе.

> Виртуальный сервер к которому приходят запросы это один единственный процесс или на каждый запрос создается свой собственный?



Ты про HTTP сервер? Это зависит от используемого веб-сервера и ОС. Если ты используешь mod_php, как плагин к Апачу, то по умолчанию под Линуксом Апач создает N процессов-рабочих и 1 процесс-диспетчер, который принимает и раскидывает приходящие HTTP-запросы между рабочими. Он также следит за рабочими, создает новые при росте нагрузки, или при их аварийном завершении, или прибивает ненужные. Код интерпретатора PHP подгружается как библиотека внутрь процесса-рабочего Апача и выполняется внутри него. У Апача есть специальное API, ты пишешь код на Си, компилируешь в библиотеку, подключаешь ее в конфиге и Апач вызывает твой код при обращении к определенному типу файла. Разработчики PHP поставляют интерпретатор в виде плагина к Апачу. Соответственно, при обращении к php-файлу Апач вызывает функцию из плагина, которая выполняет файл как PHP код.

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

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

Такого, что на каждый входящий запрос запускается новый процесс, обычно не делают, это неэффективно. Так когда-то давно было в протоколе CGI - веб-сервер при поступлении запроса просто запускал приложение и оно выводило на стандартный вывод HTML-код, который сервер оборачивал в HTTP-заголовки и отправлял клиенту.

Хотя процесс интепретатора PHP обычно не завершается, но контекст, в котором выполняется PHP-скрипт (список созданных PHP-переменных, функций, классов) обычно очищается после обработки одного HTTP-запроса. То есть приходит HTTP-запрос, создается новый пустой "контекст", php-скрипт работает, подгружает файлы, создает переменные, потом завершается и "контекст" уничтожается и следующий PHP-скрипт запускается в чистом, пустом окружении, как будто предыдущего скрипта и не было.

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

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

// Открываем TCP-порт
$socket = createListeningSocket(9001);
while (true) {
// Принимаем новое соединение от клиента
$connection = acceptConnection($socket);
handleConnection($connection);
}

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

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



Издателем тут будет скрипт, который добавляет в базу новое сообщение, а подписчиком - скрипт, который ждет новых сообщений в схеме с long polling либо поток, обслуживающий websocket-соединение.

В общем случае это могут быть процессы даже на разных машинах (если у нас много серверов). Ну например, пусть у нас при отправке сообщения вызывается скрипт /send.php, он может выглядеть так:

...
$msg = new Message();
...
saveMessageToDb($msg);
notifyUser($toUser); // эта функция должна как-то вызвать функционал издателя

> Я представлял, что приложение по цепочке вызывает все зависимости и в итоге становиться одним целым, т.е. я не думал что на каждую зависимость создаётся свой процесс. Неужели это действительно так?



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

Я описывал архитектуры серверов (не только веб-, а вообще любых работающих по схеме клиент-сервер приложений) вот тут вот: https://gist.github.com/codedokode/ffd520440a970c07c1c6 - есть самые разные варианты.

> То есть описание канала событий это обёртка над методами межпроцессных взаимодействиями, в нашем случае семафором?



Да. Семафор - это примитив, низкоуровневая сущность. Во многих ОС есть системные вызовы для создания и управления семафорами. pub/sub это штука, которая гораздо на более высоком уровне и она реализуется поверх примитивов ОС. То есть обычно для pub/sub нужна или библиотека или отдельное приложение-брокер. Отдельное приложение-брокер 100% нужно для распределенных систем, так как примитивы IPC работают только внутри одной машины.
765 1190415
>>190295

Если в браузере - попробуй использовать средства разработчика, вкладка Profiles, опции Take Heap Snapshot и Record Heap Allocations. Такое потребление абсолютно ненормально и скорее всего вызвано ошибками в коде.

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

> Или таймстамп. Но зачем возвращать время для следующего запроса, в клиенте можно же самому выставить интервал?



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

/new-messages?from=0

получает какие-то сообщения и новое значение для from (или вычисляет его сам из максимального времени у последнего сообщения). И использует это значение в следующем запросе.

> Значит нужно поскорей переходить на вебсокет...



Тут лучше сделать сравнение. Кто знает, может при неустойчивой связи как раз long polling надежнее работает.

> Прежде чем разобраться межпроцессным взаимодействием, нужно разобраться как работают процессы.



Процесс - это, условно, говоря абстрактная сущность, которая соответствует выполняющейся программе и под которую ОС выделяет ресурсы, в первую очередь память и процессорное время. Ты можешь увидеть список процессов командами вроде ps lax или top.

Процесс в ядре имеет уникальный номер (PID = process id, а также TGID = thread group id), который ты можешь увидеть в выводе команды top или ps lax в колонке с заголовком PID. Ресурсы - в первую очередь это изолированная область памяти (плюс еще кое-что по мелочи: набор переменных окружения, таблица открытых файлов и тд). Когда ты запускаешь какую-то команду (например, ls), ядро ОС создает новый "процесс", добавляет его в список процессов, выделяет кусок памяти, мапит (отображает) туда исполняемый файл /bin/ls и создает внутри процесса "поток", который будет выполнять двоичный код из этого файла.

"Поток" (тред, поток выполнения кода) это абстрактная штука, которая может выполнять код. В каждом живом процессе есть минимум один поток. В ядре ОС есть планировщик потоков, который постоянно переключает имеющиеся процессоры между потоками, создавая иллюзию параллельного выполнения всех потоков. Код может порождать новые потоки внутри того же процесса, также, потоки могут завершаться, если они выполнили свой код и больше не нужны. В линуксе потоки еще называются Light Weight Processes, они идентифицируются уникальным номером TID (thread id). Чтобы увидеть отдельные потоки, надо добавить к команде ps lax опцию -T, она выводит идентификатор потока (тот, что TID) под заголовком SPID, а идентификатор процесса под заголовком PID. Путаница вызвана историческими причинами, в первую очередь тем, что современные потоки появлились где-то в районе linux 2.4, а до этого была другая система ( https://unix.stackexchange.com/questions/364660/are-threads-implemented-as-processes-on-linux ).

Мануал по функции clone(), порождающей процессы и потоки в Линуксе, описывает названия TID, PID и TGID: http://man7.org/linux/man-pages/man2/clone.2.html Можно считать, что PID/TGID совпадает с TID самого первого потока в процессе.

> Виртуальный сервер к которому приходят запросы это один единственный процесс или на каждый запрос создается свой собственный?



Ты про HTTP сервер? Это зависит от используемого веб-сервера и ОС. Если ты используешь mod_php, как плагин к Апачу, то по умолчанию под Линуксом Апач создает N процессов-рабочих и 1 процесс-диспетчер, который принимает и раскидывает приходящие HTTP-запросы между рабочими. Он также следит за рабочими, создает новые при росте нагрузки, или при их аварийном завершении, или прибивает ненужные. Код интерпретатора PHP подгружается как библиотека внутрь процесса-рабочего Апача и выполняется внутри него. У Апача есть специальное API, ты пишешь код на Си, компилируешь в библиотеку, подключаешь ее в конфиге и Апач вызывает твой код при обращении к определенному типу файла. Разработчики PHP поставляют интерпретатор в виде плагина к Апачу. Соответственно, при обращении к php-файлу Апач вызывает функцию из плагина, которая выполняет файл как PHP код.

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

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

Такого, что на каждый входящий запрос запускается новый процесс, обычно не делают, это неэффективно. Так когда-то давно было в протоколе CGI - веб-сервер при поступлении запроса просто запускал приложение и оно выводило на стандартный вывод HTML-код, который сервер оборачивал в HTTP-заголовки и отправлял клиенту.

Хотя процесс интепретатора PHP обычно не завершается, но контекст, в котором выполняется PHP-скрипт (список созданных PHP-переменных, функций, классов) обычно очищается после обработки одного HTTP-запроса. То есть приходит HTTP-запрос, создается новый пустой "контекст", php-скрипт работает, подгружает файлы, создает переменные, потом завершается и "контекст" уничтожается и следующий PHP-скрипт запускается в чистом, пустом окружении, как будто предыдущего скрипта и не было.

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

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

// Открываем TCP-порт
$socket = createListeningSocket(9001);
while (true) {
// Принимаем новое соединение от клиента
$connection = acceptConnection($socket);
handleConnection($connection);
}

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

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



Издателем тут будет скрипт, который добавляет в базу новое сообщение, а подписчиком - скрипт, который ждет новых сообщений в схеме с long polling либо поток, обслуживающий websocket-соединение.

В общем случае это могут быть процессы даже на разных машинах (если у нас много серверов). Ну например, пусть у нас при отправке сообщения вызывается скрипт /send.php, он может выглядеть так:

...
$msg = new Message();
...
saveMessageToDb($msg);
notifyUser($toUser); // эта функция должна как-то вызвать функционал издателя

> Я представлял, что приложение по цепочке вызывает все зависимости и в итоге становиться одним целым, т.е. я не думал что на каждую зависимость создаётся свой процесс. Неужели это действительно так?



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

Я описывал архитектуры серверов (не только веб-, а вообще любых работающих по схеме клиент-сервер приложений) вот тут вот: https://gist.github.com/codedokode/ffd520440a970c07c1c6 - есть самые разные варианты.

> То есть описание канала событий это обёртка над методами межпроцессных взаимодействиями, в нашем случае семафором?



Да. Семафор - это примитив, низкоуровневая сущность. Во многих ОС есть системные вызовы для создания и управления семафорами. pub/sub это штука, которая гораздо на более высоком уровне и она реализуется поверх примитивов ОС. То есть обычно для pub/sub нужна или библиотека или отдельное приложение-брокер. Отдельное приложение-брокер 100% нужно для распределенных систем, так как примитивы IPC работают только внутри одной машины.
766 1190582
Нужно сделать совсем примитивный жаваскрипт обработчик: кликаешь по ссылке - открывается окошко. Как сделать лучше: просто написать функцию и в html объявить через атрибут обработчик или прямо в жс-е задать его для кнопки через addeventlistener. И еще, нужно ли весь жс код для такой примитивной фичи оборачивать в самоисполняющуюся функцию? Сорри, если вопрос очень банальный, я только начинаю в фронтенде разбираться.
767 1190587
Очень-очень тупой вопрос от только вкатившегося. Более-менее знаю HTML и CSS, подключал готовые JS к сайту, там всё в принципе просто. А вот как с PHP? Я что-то ни в какую не понимаю. Почему нигде про это не говорится для начинающих? Про IDE и онлайн площадки для этого много чего (Text Sublime юзаю вообще), но как сохранять файлы Пыхи и как их запускать, подключать к сайту или как это вообще работает что-то не могу понять. Пока не разобрался прохожу курс с ОП-поста и сам язык осваиваю используя Ideon и пару аналогичных площадок, странно ещё, что на разных один и тот же код порой даёт разный результат, это проблемно.
768 1190589
Приветствую. Вкатываюсь в пхп. Назрел вопрос: есть ли какие-либо годные курсы\лекции\т.п.? Желательно на русском, но можно и ангельский.
769 1190590
>>190589
Я про видео-курсы.
770 1190617
>>190587
Задачу от ОП-а на список студентов или файлобменник сделай, сразу поймешь как все работает.
771 1190645
>>190582
Никогда не пиши обработчик в хтмл теге.
Если у тебя тестовый проект из одной страницы, который нахуй никому не нужен, тогда напиши обработчких в теге скрипт.

Если это сайт с несколькими страницамии js скриптами, тогда пиши обработчик в файле скрипта и подключай через src
772 1190652
>>190587
ЕСТЬ ОЧЕНЬ ДРЕВНИЙ СПРАВОЧНИК ДЛЯ НУБОВ, ЗДЕСЬ ВСЕ ПО ВЕБУ, В ТОМ ЧИСЛЕ ОБЪЯСНЯЕТСЯ ПРИНЦИП РАБОТЫ СЕРВЕРНЫХ СКРИПТОВ. ДОБАВТЕ В ШАПКУ.

https://starcat.dp.ua/doc/wdh/
773 1190665
>>190645

Обработчик писать не стоит, а вызов функции вполне можно, как мне кажется, если это проблем не приносит. Это же проще и короче. И, кстати, в реакте и ангуларе именно так и делают.

>>190582

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

Насчет вызова в атрибуте onclick - почему бы и нет, я проблем не вижу. Это удобно тем, что можно в один клик в IDE перейти к определению функции.

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

$(document).ready(function() {
$('.somebutton').click(...);
...
});

У такого подхода есть плюсы, он во многих уроках и статьях упоминается, но есть и минусы:

- нереально найти обработчик из HTML кода, не понятно даже есть он или нет у данной кнопки
- в файле с JS непонятно, на каких страницах используется тот или иной блок кода, и используется ли он вообще? Никто не решается удалять код, его только дописывают, и в итоге там получается огромная длинная функция инициализации, в которой часть кода работает "вхолостую", и в которой никто не разберется.
- не тратится время на поиск элементов и навешивание обработчиков
- файл JS инициализируется только после события ready, хотя в случае с атрибутами обработчик доступен сразу

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

<скрипт>
var widget = $('.js-some-widget');
initSomeWidget(someWidget);
</скрипт>

Этот подход требует загружать скрипты синхронно в шапке (а почему бы и нет, если их немного), но при желании переделывается на асинхронную загрузку скриптов через тот же require.js:

<скрипт>
когдаЗагрузится('some-script.js и jquery', function () {
var widget = $('.js-some-widget');
initSomeWidget(someWidget);
});

Алсо, хоть это и не имеет отношения к вопросу, но мне не нравится jQuery, он не модульный и мне не нравится его интерфейс, например, использование одних и тех же функций как геттеров и сеттеров, скрытие ошибок.
773 1190665
>>190645

Обработчик писать не стоит, а вызов функции вполне можно, как мне кажется, если это проблем не приносит. Это же проще и короче. И, кстати, в реакте и ангуларе именно так и делают.

>>190582

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

Насчет вызова в атрибуте onclick - почему бы и нет, я проблем не вижу. Это удобно тем, что можно в один клик в IDE перейти к определению функции.

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

$(document).ready(function() {
$('.somebutton').click(...);
...
});

У такого подхода есть плюсы, он во многих уроках и статьях упоминается, но есть и минусы:

- нереально найти обработчик из HTML кода, не понятно даже есть он или нет у данной кнопки
- в файле с JS непонятно, на каких страницах используется тот или иной блок кода, и используется ли он вообще? Никто не решается удалять код, его только дописывают, и в итоге там получается огромная длинная функция инициализации, в которой часть кода работает "вхолостую", и в которой никто не разберется.
- не тратится время на поиск элементов и навешивание обработчиков
- файл JS инициализируется только после события ready, хотя в случае с атрибутами обработчик доступен сразу

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

<скрипт>
var widget = $('.js-some-widget');
initSomeWidget(someWidget);
</скрипт>

Этот подход требует загружать скрипты синхронно в шапке (а почему бы и нет, если их немного), но при желании переделывается на асинхронную загрузку скриптов через тот же require.js:

<скрипт>
когдаЗагрузится('some-script.js и jquery', function () {
var widget = $('.js-some-widget');
initSomeWidget(someWidget);
});

Алсо, хоть это и не имеет отношения к вопросу, но мне не нравится jQuery, он не модульный и мне не нравится его интерфейс, например, использование одних и тех же функций как геттеров и сеттеров, скрытие ошибок.
774 1190672
>>190665
Нет вешать обработчик на onclick в теге супер хуево. Это подход 2000 года. Правильно добавлять только через addEventListener.

Написание любого кода вроде onclick в теге в дальнейшем приведет к невообразимой путанице. Исключение очень маленькие одно-двухстраничные проекты.

А ангуляр дермо сделанное для дебилов, чтоб они хоть как то кодить могли.
775 1190679
>>190672

Каким образом это приводит к путанице?

<button onclick="openSomePopup()"></button>

Вот тут я могу в один клик в IDE перейти к функции. А в твоем подходе, как мне искать обработчик кнопки в горах JS кода?

Аргумент про 2000 год это вообще не аргумент.

Алсо, открой HTML-код Ютуба или своей любимой соцсети и сделай поиск по ' on'.
776 1190687
>>190679
Хтмл код ютуба не аргумент. Допустим у тебя сайт из 10-20 страниц с кучей js финтифлюшек. Хороший разраб сделал несколько js файлов в ктоторых сгрупировал фукнции и обработчики по смыслу. Потом в проект взяли тебя и ты на одной из страниц вписал обработчик в onclick тега. А через неделю этот обработчик понадобился еще в нескольких местах.

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

Ты отстаиваешь устаревший и менее эфефективный подход.
777 1190694
>>190687

Ты прочитал мой пост? >>190665

На сайте из 10-20 разделов твой JS файл превратится в большую свалку кода такого вида:

$('.class-1').click(...
....
...
);

if ($('.class2').length) {
$('.class2')....
.....
...
);

if ($(window).widh() > 800) {
...
}

И так еще строк 300.

Этот подход работает только для маленьких сайтов.

И ты не ответил на вопрос, как при таком подходе искать обработчик для какой-то кнопки?

> Во вторых при отладке js в браузере проще выполнять по шагам js файл


При отладке ты просто ставишь брейкпойнт в начале нужной тебе функции и тебе не надо по шагам проходить описанные выше 300 строк инициализации.

> Ты отстаиваешь устаревший и менее эфефективный подход.



Я привел в посте аргументы, почему мой подход лучше. Все твои аргументы сводятся к "устаревший". Кто его объявил устаревшим? Покажи мне стандарт W3C, в котором это написано. Или хотя бы страницу MDN.
777 1190694
>>190687

Ты прочитал мой пост? >>190665

На сайте из 10-20 разделов твой JS файл превратится в большую свалку кода такого вида:

$('.class-1').click(...
....
...
);

if ($('.class2').length) {
$('.class2')....
.....
...
);

if ($(window).widh() > 800) {
...
}

И так еще строк 300.

Этот подход работает только для маленьких сайтов.

И ты не ответил на вопрос, как при таком подходе искать обработчик для какой-то кнопки?

> Во вторых при отладке js в браузере проще выполнять по шагам js файл


При отладке ты просто ставишь брейкпойнт в начале нужной тебе функции и тебе не надо по шагам проходить описанные выше 300 строк инициализации.

> Ты отстаиваешь устаревший и менее эфефективный подход.



Я привел в посте аргументы, почему мой подход лучше. Все твои аргументы сводятся к "устаревший". Кто его объявил устаревшим? Покажи мне стандарт W3C, в котором это написано. Или хотя бы страницу MDN.
778 1190714
>>190694
Ладно убедил, сука.
779 1190716
>>190714
Что-то ты быстро сдался. Эх ты, а я болел за тебя...
780 1190722
>>190716
Не ну тут он прав, мне доводилось работать со свалками кода в js файлах, это тот еще гемор.

В целом js файл выглядет аккуратнее чем html js мешанина, наверное поэтому этот подход я считаю лучше.

Но это не особо решает.

Единственное что могу еще добавить в пользу addEventListener, таким способом можно к одной кнопке привязать несколько событий, в html это не возможно.
781 1190828
>>190722

>можно к одной кнопке привязать несколько событий



В смысле? https://jsfiddle.net/baqu460z/
782 1190839
Три задачки, в правильности решения которых я не особо уверен. Проверьте, пожалуйста.
https://ideone.com/vCJosI
Со стихами смог сделать только через shuffle, иначе первые две строки были абсолютно одинаковыми.
https://ideone.com/IPaXhH
С палиндромом ебался часа 3, написал хуеты, но главное работает.
http://sandbox.onlinephpfunctions.com/code/1eed5a0bfc43968f61079d0dd36a84d9d66c2b2c
783 1190840
>>190828
Несколько обрабочиков, сорян за неточность.
784 1190851
>>190828
Да я знал что ты скажешь что можно в один onlcick вписать несколько функций. Но что если обработчики нужно вешать по условию, или даже например удалять в определенных ситуациях? Сам хуй.
785 1190996
>>190839
Все, нашел ошибку во второй. Шел по улице и понял, где я обосрался.
786 1191029
>>190029

http://sqlfiddle.com/#!9/beb4c/3
Такой же результат как у меня, хотя тут мускл а не мариа

На иннодб поиске такой проблемы нет, но чтобы мне поставить иннодб фуллтекст придется сначала апдейтнуть марию на 10+ версию.

Я проверил стандартный список стоп-слов муисам и там кошки нет, возможно в той дистрибуции сентос которая на впске стоит свой особый конфиг но я уже не знаю как это быстро чекнуть.
787 1191036
>>174695 (OP)

>https://phpclub.tech/


Анон, что с ссылкой на учебник?
788 1191078
>>191029

Ок, погуглил мануал: https://dev.mysql.com/doc/refman/8.0/en/fulltext-boolean.html

> The minimum and maximum word length full-text parameters apply to FULLTEXT indexes created using the built-in FULLTEXT parser and MeCab parser plugin. innodb_ft_min_token_size and innodb_ft_max_token_size are used for InnoDB search indexes. ft_min_word_len and ft_max_word_len are used for MyISAM search indexes.



Проверил значение параметра: http://sqlfiddle.com/#!9/beb4c/4

> ft_min_word_len4

789 1191081
>>191029

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

Кстати, через SET они не меняются.
790 1191131
Господа, как правильно хранить стоимость в базе?
Сойдет ли для этого decimal длинной 10 и 2 знаками после запятой?
MySQL, если что.
791 1191135
как создать личный аккаунт на пхп пускай выводит только имя пользователя после регистрации в красивой форме?
792 1191212
>>191131
Зависит от того, что твоя система будет делать. Если у тебя тупо каталог с ценой за продукт в рубль.копейка то хватит. Иначе врядли.
Например 1 евроцент это ~ 0.0000014 биткоина.

Для магазов вроде нужно делать decimal 10.4 (это стандарт установленный регулятором) при операциях с деньгами, ну и показывать пользователю 10.2.
793 1191244
>>191081
Спасибо тебе, поменял настройку и поехало..
Только в итоге все равно задачу решает не лучше like с вайлдкартой :(
794 1191462
У меня тупняк, помогите пожалуйста.
У меня есть путь:
D:/Progs/openserver/OSPanel/domains/uppu/files/2018/7413527a15526a76bf354a78520ad2b5ba1a19d5.JPG

Если я ее подставляю в браузер, то файл открывается, а если подставляю эту строку в <a href="..."> или <img src="..." то ничего не работает
Почему не работает?
795 1191471
>>191462
Это обсолютный путь на диске. Браузер когда такое видит сразу запрашавает файл прямо с жесткого диска не подключаясь к веб-серверу.
Сервер работает с URL. Ссылки и сорцы картинок должны тоже соответсвовать.
Я не знаю настроены ли у тебя виртуальные хосты, но твоя ссылка должна выглядеть как то так:
Если у тебя корень сайта (где лежит твой html файл)
D:/Progs/openserver/OSPanel/domains/uppu/
и в браузере ты октрываешь его через:
http://localhost/
то ссылка на картинку будет:
http://localhost/files/2018/7413527a15526a76bf354a78520ad2b5ba1a19d5.JPG
796 1191516
>>191471
спасибо
изображение.png6 Кб, 444x209
797 1191542
Ок, вроде разобрался как написать автолоадер для студентов, но осталась пара вопросов.

Допустим у меня код автолоадера: пикрил

И файл Student.php с Описанием класса Student лежит соотственно в /Classes/Entities/

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

Так вот - я теперь всегда обязан буду так создавать новый класс?
$a = new Classes\Entities\Student();

Либо например написать где-то
use Classes\Entities\Student;
Что пхп будет воспринято как
use Classes\Entities\Student as Student;

и можно будет писать
$a = new Student();

Это всё всё равно не решает никак проблему автоматизации подгрузки классов, нужно будет либо в ручную постоянно писать use c полным именем класса (в котором зашита по сути папка в которой он лежит), либо написать какой-то отдельный инициализатор, которому скармливать например какой-нибудь массив со всеми классами в приложении, и что бы он за тебя писал в цикле этот самый use Classes\Entities\Student;

Это нормальная практика? На этом всё? Просто сначала автолоадер воспринимался как нечто что само должно находить и подгружать тебе всё что ты захочешь, но в итоге как я посмотрю всё равно он будет подгружать только то, что четко задокументировано самим программистом.
798 1191575
>>191542

>нужно будет либо в ручную постоянно писать use c полным именем класса


IDE делают это автоматически.
799 1191585
>>191542
Суть неймспейсов в том что у тебя может быть несколько классов Student. Поэтому всегда надо уточнять.
800 1191609
>>191575
При чем тут иде? Суть в том, что это должно быть в коде, а дальше уже не важно ты в ручную это пишешь или иде за тебя. Речь о том, что бы вообще обойти написание этих юзов.
>>191585
Да это то понятно, вы не поняли немного что я собственно спрашивал. У меня возник вопрос о том как собственно писать автолоадер когда у тебя гора классов в разных папках.

Пришло на ум три варианта.
1. ты пишешь хитровыебанный древовидный поиск по папкам, в духе:
заглянуть в каждую папку в корне, там есть вызываемый класс? да - подгрузить, нет - в папке есть еще папки? да - посмотреть каждую папку ... и так далее

2. Хардкодишь в автолоадер все возможные пути в которых у тебя могут сидеть классы и пусть пребором ищет по ним.

3. Вот так зашивать путь к классу в неймспейс, и при попытке вызывать класс придется сообщать собственно этот путь и указывать, либо 1 раз писать use Namespace\Classname; где-то что бы потом можно было просто везде потом спокойно вызывать этот самый $obj = new Classname;

Еще кстати вопрос по поводу заглавных букв в названии папок возник.
Лучше в итоге всё всё писать с большой буквы? И неймспейс и названия папок? Вроде и когда мешанина из мелких и больших все работает, но что бы 1 раз уяснить для себя и не тупить больше с этим.

https://github.com/codedokode/pasta/blob/master/php/autoload.md прочитал если что, но вдруг что-то упустил.
801 1191615
>>191609

>заглянуть в каждую папку в корне, там есть вызываемый класс? да - подгрузить, нет - в папке есть еще папки



сосешь в производительности.
802 1191621
>>191609
Можно сделать один файл с массивом где каждому классу сопоставлен путь к нему.

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

Так что лучше смириться с use и не париться.

К тому же это практика многих языков, не только php. Все так делают.
803 1191640
>>191542

Автолоадер помогает избежать записи путей к файлам в коде. Ты ведь будешь не только писать свои классы, а еще и использовать сторонние библиотеки. И за счет автолоадера ты убираешь из кода пути к ним, а просто пишешь: "мне нужен класс Symfony\Routing\Router". Не указывая, где находится библиотека.

До автолоадинга делали так: библиотеки клали в отдельную папку вроде /usr/share/pear (pear = php extension and application repository) и прописывали путь к ней в set_include_path(). А в коде писали что-то вроде require 'Net/Util/Dns.php'; для класса с названием Net_Util_Dns из сторонней библиотеки.

Это вариант до сих пор работает, кстати.

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

В некоторых других языках, например, в node.js, модули подключаются по пути относительно текущего файла:

var module = require('some/module');
var object = new module.SomeClass(); (или new module(), если модуль экспортирует единственный класс)

Отличие от PHP в том, что в JS классы и функции не создаются в глобальной области видимости, а только в переменной module. Это позволяет например иметь функции с одинаковыми названиями в разных модулях без использования неймспейсов (неймспейсом по сути становится путь к модулю).

Теперь про неймспейсы. Длинные имена классов были и до них, например, Zend_Db_Table_Abstract. Неймспейсы лишь поменяли _ на \ и позволили за счет use использовать к коде короткое имя и сделать код более читаемым. use по задумке может вставлять в код IDE.

----

Теперь вернемся к твоему примеру.

> Classes\Entities\Student



Classes здесь не нужен. Он ничего не говорит. В начале пути либо пишу название приложения, либо ничего. То есть либо StudentList\Entity\Student, либо Entity\Student. Если классов совсем мало (в пределах 10-20), можно писать просто Student или StudentList\Student. Если все классы находятся в одном неймспейсе, то use писать не придетися.

Почему нужны длинные имена классов? В PHP не может быть 2 класса с совпадающим именем и все приложения и библиотеки должны использовать уникальные имена классов. Отсюда нужда в неймспейсах. Чтобы твой Student не совпал с именем класса в какой-то библиотеке.

Урок, если ты не читал https://github.com/codedokode/pasta/blob/master/php/autoload.md
803 1191640
>>191542

Автолоадер помогает избежать записи путей к файлам в коде. Ты ведь будешь не только писать свои классы, а еще и использовать сторонние библиотеки. И за счет автолоадера ты убираешь из кода пути к ним, а просто пишешь: "мне нужен класс Symfony\Routing\Router". Не указывая, где находится библиотека.

До автолоадинга делали так: библиотеки клали в отдельную папку вроде /usr/share/pear (pear = php extension and application repository) и прописывали путь к ней в set_include_path(). А в коде писали что-то вроде require 'Net/Util/Dns.php'; для класса с названием Net_Util_Dns из сторонней библиотеки.

Это вариант до сих пор работает, кстати.

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

В некоторых других языках, например, в node.js, модули подключаются по пути относительно текущего файла:

var module = require('some/module');
var object = new module.SomeClass(); (или new module(), если модуль экспортирует единственный класс)

Отличие от PHP в том, что в JS классы и функции не создаются в глобальной области видимости, а только в переменной module. Это позволяет например иметь функции с одинаковыми названиями в разных модулях без использования неймспейсов (неймспейсом по сути становится путь к модулю).

Теперь про неймспейсы. Длинные имена классов были и до них, например, Zend_Db_Table_Abstract. Неймспейсы лишь поменяли _ на \ и позволили за счет use использовать к коде короткое имя и сделать код более читаемым. use по задумке может вставлять в код IDE.

----

Теперь вернемся к твоему примеру.

> Classes\Entities\Student



Classes здесь не нужен. Он ничего не говорит. В начале пути либо пишу название приложения, либо ничего. То есть либо StudentList\Entity\Student, либо Entity\Student. Если классов совсем мало (в пределах 10-20), можно писать просто Student или StudentList\Student. Если все классы находятся в одном неймспейсе, то use писать не придетися.

Почему нужны длинные имена классов? В PHP не может быть 2 класса с совпадающим именем и все приложения и библиотеки должны использовать уникальные имена классов. Отсюда нужда в неймспейсах. Чтобы твой Student не совпал с именем класса в какой-то библиотеке.

Урок, если ты не читал https://github.com/codedokode/pasta/blob/master/php/autoload.md
804 1191652
>>191621

Такой файл умеет генерировать композер с опцией --optimize-autoloader: https://getcomposer.org/doc/articles/autoloader-optimization.md

Учтите, что обязательно нужен кеш php-кода вроде opcache, чтобы эта оптимизация была эффективна и PHP не перечитывал этот гигантский массив при каждом запуске скрипта.

> On PHP 5.6+, the class map is also cached in opcache which improves the initialization time greatly. If you make sure opcache is enabled, then the class map should load almost instantly and then class loading is fast.



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

>>191609

> У меня возник вопрос о том как собственно писать автолоадер когда у тебя гора классов в разных папках.



Если ты используешь композер, то он умеет генерировать автозагрузчик и там есть 2 готовых варианта:

1) описать каждую папку, прописав путь к папке и неймспейс находящихся в ней классов
2) заставить композер обойти все файлы и сгенерировать список, какой класс в каком файле (classmap)

> Лучше в итоге всё всё писать с большой буквы? И неймспейс и названия папок?



Да. Имена классов и так пишутся с большой буквы, логично и неймспейсы так же. В папках регистр должен совпадать, так как на линукс файловая система и имена файлов чувствительны к регистру.

>>191542

>я как бы сообщаю автолоадеру полное имя класса, которое совпадает с папкой в которой он лежит



Не полное, а относительное. Потому Classes писать не надо.

> Просто сначала автолоадер воспринимался как нечто что само должно находить и подгружать тебе всё что ты захочешь, но в итоге как я посмотрю всё равно он будет подгружать только то, что четко задокументировано самим программистом.



Правила, как называть и располагать классы (PSR-4) нужны, так как без них каждый начнет придумывать свою систему и ты при работе в команде или с чужим кодом будешь ломать голову, как найти тот или иной класс, куда поместить новый класс? Без правил как раз будет свалка, а с правилами все единообразно.

Посмотри на пример чужого проекта, как там сделаны пути и имена классов:

- совсем маленький проект https://github.com/symfony/filesystem
- проект побольше https://github.com/slimphp/Slim
- https://github.com/twigphp/Twig

Заодно обрати внимание на оформление и все остальное. От тебя хотелось бы в итоге (после проверок и исправления кода) получить код такого же качества или лучше. Разумеется, язык в ридми и комментариях можно использовать русский.
804 1191652
>>191621

Такой файл умеет генерировать композер с опцией --optimize-autoloader: https://getcomposer.org/doc/articles/autoloader-optimization.md

Учтите, что обязательно нужен кеш php-кода вроде opcache, чтобы эта оптимизация была эффективна и PHP не перечитывал этот гигантский массив при каждом запуске скрипта.

> On PHP 5.6+, the class map is also cached in opcache which improves the initialization time greatly. If you make sure opcache is enabled, then the class map should load almost instantly and then class loading is fast.



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

>>191609

> У меня возник вопрос о том как собственно писать автолоадер когда у тебя гора классов в разных папках.



Если ты используешь композер, то он умеет генерировать автозагрузчик и там есть 2 готовых варианта:

1) описать каждую папку, прописав путь к папке и неймспейс находящихся в ней классов
2) заставить композер обойти все файлы и сгенерировать список, какой класс в каком файле (classmap)

> Лучше в итоге всё всё писать с большой буквы? И неймспейс и названия папок?



Да. Имена классов и так пишутся с большой буквы, логично и неймспейсы так же. В папках регистр должен совпадать, так как на линукс файловая система и имена файлов чувствительны к регистру.

>>191542

>я как бы сообщаю автолоадеру полное имя класса, которое совпадает с папкой в которой он лежит



Не полное, а относительное. Потому Classes писать не надо.

> Просто сначала автолоадер воспринимался как нечто что само должно находить и подгружать тебе всё что ты захочешь, но в итоге как я посмотрю всё равно он будет подгружать только то, что четко задокументировано самим программистом.



Правила, как называть и располагать классы (PSR-4) нужны, так как без них каждый начнет придумывать свою систему и ты при работе в команде или с чужим кодом будешь ломать голову, как найти тот или иной класс, куда поместить новый класс? Без правил как раз будет свалка, а с правилами все единообразно.

Посмотри на пример чужого проекта, как там сделаны пути и имена классов:

- совсем маленький проект https://github.com/symfony/filesystem
- проект побольше https://github.com/slimphp/Slim
- https://github.com/twigphp/Twig

Заодно обрати внимание на оформление и все остальное. От тебя хотелось бы в итоге (после проверок и исправления кода) получить код такого же качества или лучше. Разумеется, язык в ридми и комментариях можно использовать русский.
805 1191654
>>191542

В проектах, на которые я выше дал ссылки, правила автозагрузки прописаны в файле composer.json. Там используется автозагрузчик, который генерирует композер на основе правил из этого файла.
806 1191657
>>191652

>Такой файл умеет генерировать композер с опцией --optimize-autoloader



Ну так одно дело когда это автоматически.
807 1191660
>>191462

Путь с d:/... указывать неправильно, так как этот путь и диск d: виден только на твоем компьютере. Если на твой сайт зайдет человек с другого компьютера, у него может вообще не быть диска d:, и тем более, там не будет нужной картинки.

В вебе пути указываются относительно корневой папки веб-сервера (так как веб-сервер раздает только файлы внутри нее и не отдает файлы за ее пределами).

Как написал анон выше, надо писать /files/....

Алсо, имена из md5 на мой взгляд это не самая лучшая идея, так как они не воспринимаются человеком, их неудобно перепечатывать и при отладке тебя будет сбивать с толку большое количество таких файлов в папке.
808 1191665
>>191462

> Почему не работает?



Потому что в src/href указывается URL, и путь d:/... - это не URL. Структура URL описана в моем уроке https://github.com/codedokode/pasta/blob/master/network/urls.md

>>191244

Почему? По идее LIKE использует индекс только при поиске по началу строки, если в начале не стоит % или _, а MATCH - умеет искать слово в любом месте строки по индексу.

>>191131

Наверно с 2-4 знаками после запятой. Не забудь поле для валюты, если у тебя что-то международное.

>>190851

Навешивание обработчика полезно, когда надо передать ему контекст в виде переменных из замыкания или значение this:

var x = ...;
button.addEventListener('click', function (e) {
console.log(x);
});

var someObject = ...;
button.addEventListener('click', e => someObject.handleClick(e);
});

В случае навешивания обработчика снаружи надо использовать addEventListener, а не button.onclick = ..., чтобы не затереть обработчик в атрибуте. Через JS трогать on-атрибуты вообще не стоит.
808 1191665
>>191462

> Почему не работает?



Потому что в src/href указывается URL, и путь d:/... - это не URL. Структура URL описана в моем уроке https://github.com/codedokode/pasta/blob/master/network/urls.md

>>191244

Почему? По идее LIKE использует индекс только при поиске по началу строки, если в начале не стоит % или _, а MATCH - умеет искать слово в любом месте строки по индексу.

>>191131

Наверно с 2-4 знаками после запятой. Не забудь поле для валюты, если у тебя что-то международное.

>>190851

Навешивание обработчика полезно, когда надо передать ему контекст в виде переменных из замыкания или значение this:

var x = ...;
button.addEventListener('click', function (e) {
console.log(x);
});

var someObject = ...;
button.addEventListener('click', e => someObject.handleClick(e);
});

В случае навешивания обработчика снаружи надо использовать addEventListener, а не button.onclick = ..., чтобы не затереть обработчик в атрибуте. Через JS трогать on-атрибуты вообще не стоит.
809 1191666
>>190828

В коде ошибка

document.log = log;

Это ни на что не влияет. Глобальные переменные создаются в объекте window, а не document.
810 1191724
>>191652

>Не полное, а относительное. Потому Classes писать не надо.


Ну это если у меня нет папки Classes в корне в которой и лежат все классы. Если я её уберу из пути, то у меня тупо будет ошибка что по указаному пути ничего не найдено.

Вообще я не понял особо по поводу относительного пути.
Допустим я дампаю __DIR__ - он показывает папку с виртуальным хостом у меня.

Соответственно поэтому я и навасянил . '\\' . себе в путь класса в отличие от примера ОП-а, потому что если это убрать, то не будет хватать одного бекслеша.

В общем пикрилы всё демонстрируют.
811 1191747
>>191666
Похуй.
812 1191765
Можно ли как-то при создании второй мышки заставить ее сопровождать и охранять предыдущую? Или придется всё-таки давать им ID? Код:

this.world.locations = [
new Location(
"Яма арены",
[{text:"в клетку", id:"Клетка арены"}],
[
new creatures.Mouse({}).go("Клетка арены"),
new creatures.Mouse({}).guard(?).follow(?)
]
),
new Location(
"Клетка арены",
[{text:"выйти", id:"Яма арены"}],
[]
)
];
813 1191775
>>191724
У тебя все классы лежать в папке Classes, поэтому эту папку можно жестко вписать в путь в автолоадере, а классы именовать без этой папки.
814 1191786
>>191775
Спасибо, наконец-то понял о чем речь.
815 1191811
>>191724

У тебя еще ошибка: ты должен заменять бекслеши в имени класса на прямые, так как в Linux обратные бекслеши в путях не поддерживаются, а прямые работают во всех ОС.

Classes писать не надо. Неймспейс это не путь к файлу, а группировка классов вместе по назначению. В твоем варианте, если классов всего несколько, логичнее их кинуть в общий неймспейс StudentList. Папку под него можно создавать, можно не создавать.

Я же вроде писал в уроке, что PSR-4 допускает установку правил вроде "Все классы в неймспейсе X лежат в папке Y". То есть, например, "класс StudentList\X" лежит в src/X.php.

Я вообще не советую использовать папку classes, так как в ООП приложении 99% файлов это классы. Просто назови ее src или StudentList.
816 1191813
>>191765

Думаю, что можно, почему нет?

var mouse1 = new Mouse();
var mouse2 = new Mouse();
mouse2.follow(mouse1);

id не стоит вводить, если и без них все работает. Объекты сами по себе уникальны и не требуют идентификаторов.
817 1191990
>>191813
Без переменных, как я понимаю, не получится? У меня там намечается 1000 локаций и ~700 "мышек", я потеряюсь в переменных. %%Как и в ID."
818 1191995
>>191990
массив локаций и массив мышек = 2 переменные
819 1192023
>>191995
>>191813
Всё же без идентификаторов не получится: нужно сохранять игру, а как сохранить (в JSОN, например) связи между объектами и потом восстановить их?
820 1192025
>>192023
Массивы имеют ключи. Используй их вместо id.
821 1192098
>>191660

>так как веб-сервер раздает только файлы внутри нее и не отдает файлы за ее пределами



В задаче про студентов писалось, что нужно выносить все файлы за корень, и оставить там только css, js и index.php

так где же все-таки должен находиться каталог с файлами загруженными на сервер?
822 1192103
>>192098

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

Если файл должен быть доступен из браузера то конечно он должен быть в публичной папке по определению.
823 1192187
>>192103 >>192098
с апачем и НЖИНКС любые файлы могут находиться где угодно, уточняйте окружение.
824 1192191
>>192187

Это если специально менять конфигурацию. По умолчанию они раздают файлы из публичной папки.
15171000203201.png272 Кб, 600x550
825 1192226
Я вот тред почитал, но так и не понял: если я выучу этот ваш РНР, деньги-то можно будет зарабатывать? Или это чисто хобби по фану, как лабание на гитаре и вышивка?
826 1192374
>>192226
Одно дело выучить пыху, другое научиться программировать.

Большая часть вакансий основана на пыхе, это самое популярное говно, так еще будет долго.
827 1192387
Анонимы, нужна помощь. Я использую библиотеку PDO для работы с базой данных. У меня возникает такая ошибка.
В базу данных, естественно, всё залетает, но экзепшн все равно выкидывает. 2031 ошибка, как сказано в документации,
это неправильное формирование данных для execute(). Но выглядит всё правильно, вроде как. Ах да, пробовал ключи типа ":name", вместо "name". Не помогло.
828 1192395
>>192387
Попробуй в массиве поменять ключи типа name на :name.
829 1192396
>>192395
Пробовал, все то же, не выходит
830 1192402
>>192387
>>192395
Не прочитал до конца твой пост. сук Должно работать же. Можешь попробовать использовать ? плейсхолдеры, и передавать массив без ключей, или через BindValue байндить. Но все равно как-то странно что не работает :thinking:
А зачем ты поля таблицы в кавычки берешь? Я бы по ПРИКОЛУ попробовал без них затестить и с ключами :name
831 1192407
>>192402
спасибо, за попытку помощи. Я НАШЕЛ В ЧЕМ ДЕЛО. У меня строчка была в методе модели, которая кидала записи в базу, которая ссылалась на метод для SELECT-запросов, что и вызывало ошибку формирования данных, мать вашу, как всегда. Я весь stackoverflow перерыл уже XD
2018-05-1911-33-48.png4 Кб, 435x147
832 1192517
Аноны, ОП, подкиньте какую-нибудь статью, мануал (кроме вот этой https://habr.com/post/154719), чтобы понять, как сделать эти кнопки.
835 1192799
Задача про Shift. Анончики, не понимаю, как с помощью preg_replace пробелы расставить или убрать. Помогите!
836 1192972
>>192799
Конкретно один пробел " "
Один или больше пробелов " +"
Один любой пробельный символ (табуляция например) "\h"
Один или больше любых пробельных символов "\h+"

Незнаю чо там в задаче, но если в preg_replace заменить "\h+" на " ", то везде будет ровно 1 пробел.
838 1193013
>>192374
Ну так это, я могу, выучив пыху, идти зарабатывать на хлебушек и попутно вкатываться в ТО САМОЕ программирование, где 30000кккк/наносекунду?
839 1193045
>>193013
Да. Пара тройка лет работы на пыхе и ты уже понимаешь как не надо писать код. Какую инфу по теории программирования надо знать и т.д. Изучаешь какой нибудь C++, C# или яву, пишешь в резюме что ты ахуевший кодер со стажем и опаньки ты в многоэтажном офисе с бассейном ебешь гусей своей мечты.
840 1193050
>>193045
Кайф, спасибо.
841 1193051
>>193050
Нет это не кайф. Тут нужно ебашить как на заводе, чтобы чего то достичь с нуля.
842 1193052
>>193051
Ну так ебашить по жизни энивей придется, и я так-то считаю что ебашить головой и иметь в будущем перспективы это намного радужнее чем ебашить лапками и не иметь перспектив.
843 1193057
>>193052
Все верно. Просто знаю человек сто, которые хотели стать программистами чтоб не работать на заводе и купаться в деньгах, но дико обломились когда головушки заболели.
844 1193058
До сих пор ору с них всех.
845 1193067
Сап, пхпач. Я дебек, не могу понять чому не получатся. Скорее всего я проебланил в чем-то, но почему тогда доллары не отображаются?..
846 1193071
>>193067

Во-первых, зачем тебе переменная $exchangeRate, если ты её не используешь?

Во-вторых, строка "$dollars" выведет значение переменной $dollars без знака доллара.

Чтобы вывести со знаком доллара нужно выводить так: "${$dollars}" или так "$ $dollars" или так "$dollars$"
847 1193074
>>193071
Просто читал гайдик данный в шапке, делал все как там описано
848 1193075
>>193074
Если для чего то введена переменная, нужно везде вместо её значения подставлять её.

Потому что, если в переменной значение поменяется, то оно должно поменяться везде.
849 1193076
>>193074
Строчку error_reporting(-1) добавляй после того как убедился что все работает, чтобы видеть ошибки выполнения пока решаешь задачу.
850 1193079
>>193075
>>193076
>>193071
Пасиб, парни. В самом начале вводил значениями, но тогда чому-то появлялась ошибка, после этого начал пробовать вбивать значения сразу, сейчас же все как надо, хы. ^^
851 1193081
>>193079
вбивать цифры сразу*
фикс
852 1193292
>>193057
Ну, хули, пока не попробую - не узнаю. А вдруг не обосрусь и через десяток лет буду получать тонны денег и нюхать кокаин с задниц латиноамериканских шлюх.
853 1193314
>>193292
пол года на кокаине и ты из гениального прогера превращаешься в тупорылого дауна
854 1193331
>>193314
После полугода на кокаине и умереть не жалко.
image.png69 Кб, 843x282
855 1193402
>>174695 (OP)
Почему ссылки не подсвечиваются и некликабельны.
856 1193454
>>192972
>>192973
Спасибо большое. Стоило ещё пояснить точнее - не просто заменить, а именно расставить, чтоб запятая превратилась не в пробел, а в запятую с пробелом.

Там выше у анончика есть пример кода, он использует $1 и $2. Я погуглил, выяснил, что это подмаски. Но как их юзать, так и не разобрался. А тупо копипастить не хочу, хочу понять.
857 1193474
>>193454
если в своей регулярке какуюто часть ты берешь в скобки, то часть строки соотвествующая этой части в скобках запоминается в $1. $2 - это то что совпало со вторыми скобками и т.д. Часть строки совпавшая со всей регуляркой целиком это $0.

Используя скобки в регулярке ты можешь потом производить замену совпавшей части строки при этом сохраняя конкретные совпавшие подчасти.

Например есть предложение с запятой посередине, ты хочешь заменть запятую на точку с запятой но чтобы все остальное осталось как было:

preg_replace("/(.+),(.+)/", "$1;$2", "слово1, слово2")
858 1193480
>>193454
В регулярке обрамляется скобочками нужный объект, например /(пидорашка) (любит) пыню/ui

пидорашка это $1
любит $2

а так /((пидорашка) (любит)) пыню/ui

$1 пидорашка любит
$2 пидорашка
$3 любит

Понятно?
859 1193508
>>193480
>>193474
Спасибо! Теперь прояснилось.
860 1193525
>>193508
Кстати, вместо $1 можно написать так \\1.
861 1193739
Сап, есть ли возможность писать бэк на PHP не для WEB, а для онлайн игры?
862 1193741
>>193739
Только для запрос-ответ. Все постоянные длительные серверные вычисления лучше делать на с++
863 1193743
>>193741
Например если помимо игроков сервер должен постоянно просчитывать действия мобов то пхп для этого херовый.
864 1193744
>>193739
Если есть идея игры и умеешь рисовать я с тобой.
865 1193747
>>193743
Почему? Моб я так понимаю по сути функция на PHP. >>193744
Я PHP не умею. А идея простая, изометрия на изометрии и рпг погоняет.
866 1193749
>>193747
Мобы могут чтото делать независимо от того есть игроки или нет. Нет игроков = нет запросов = нет запусков скрипта. Если вычисления для мобов простые и короткие по времени можно использовать переодические вызовы скриптов кроном.

>изометрия на изометрии и рпг погоняет



Ну так это то что надо. Я много раз хотел чтото подобное, но нихуя не умею рисовать. зато знаю пхп.
image.png1 Мб, 1037x901
867 1193750
Я вообще в эту хуищу ебашу. А тут даже не изометрия а просто кнопки с картинками.
868 1193751
>>193749

>Мобы могут чтото делать независимо от того есть игроки или нет.


Судя по исходникам которые я смотрел, делается так. "Если игрок достиг ячейки карты, запустить действия моба". "Если на карте нет игрока, не использовать функцию." Как-то так.
869 1193761
>>193751
Да такой вариант возможен. Эмуляция прошедших действий моба только при наблюении. Но мобы это только один пример. Я имел в виду вообще любые процессы которые могут происходить даже если никто не онлайн. В некоторых случаях делать просчеты только когда "кто-то смотрит" не получится из-за большого фактора энтропии.

Например нужно оповестить игрока о том что где то в мире произошло какое то событие, которое зависит от множества факторов. При этом нельзя посадить это на рандом и оповестить нужно именно в момент когда событие произошло. В такой ситуации на сервере должна происходить движуха независимо от запросов игроков.
870 1193764
>>193761
Интересно, а как с этим в WOW обстоит дело, там вроде по расписанию всё. И все события в основном генерируются именно по времени и заранее описаны скриптами.
871 1193769
>>193764
В вов все просто. У каждого моба есть четкое расписание действий. Нет энтропии.

Но что если бы мобы могли вести себя рандомно (как в майнкрафте например). Скажим есть у тебя хата, пришли в любой момент криперы проели дыру в стене позврывали все нахуй.
872 1193770
>>193769
Ну то есть у пхп очень ограниченный предел возможностей в плане игр. Но простую игровую механию сваять нехуй делать.
873 1193783
>>193770
Побегу делать наброски, если будет получаться что-то больше чем "У меня есть идея", ты же в треде будешь? спишемся.
874 1193790
>>193783
ага
875 1193839
Вопрос по Twig.
как обрезать длинную строку, чтобы показывалась начало и конец, а в середине было "..." ?
изображение.png243x24
876 1193850
Помогите с регуляркой, какая-то мистическая хуйня с ней происходит. Не пропускает половину слов. Например если скормить ей:
"Список",
"Список 3"
- то всё ок
но если:
"йцуйываыапыв"
какое-нибудь, то чет сосалово.
Алсо когда стояла просто регулярка:
/^[\w]+$/
То вообще русские символы не пропускало.
877 1193852
>>193850
Если у тебя юникод, поставиь в конце аттрибут u, поиграйся с ним.
878 1193867
Поясните во что лучше во вьюхе оборачивать всякие юзернеймы и прочее для защиты от xss? На этапе ввода в базу это всё эскейпится средствами фреймворка если что.
879 1193882
>>193852
Спасибо большое, теперь всё ок. Видимо без u пропускало некоторые русские символы, которые умещаются в 1 байт или что-то такое, поэтому такой рандом был.
880 1193908
>>193867

В htmlspecialchars или аналоги как описано тут: https://github.com/codedokode/pasta/blob/master/security/xss.md

Некоторые шаблонизаторы поддерживают автоматическое экранирование при выводе.
881 1193959
Делаю тестовое, в принципе с пхп частью справляюсь легко.

Но дошел до момента, где нужно создавать некий список. Допустим это название и пункты и вот надо что бы всё это создавалось / редактировалось без перезагрузки страницы. Чет завис на этом моменте, с чего начать гуглить, что бы это воплотить?

Под аякс запросы обычно другой метод контроллера пишут или в тот же всё летит?

Допустим есть у меня /someController/editList/123
Захожу я в него, там во вьюхе список обычный
<ul>
<li></li>
...
<li></li>
</ul>

в каждый <li> обернут по сути элемент из базы, в общем наверное нужно весь этот список превратить в js объект сначала? А дальше с ним манипуляции проводить? И если что бы по заполнению некого поля и клику по кнопке Добавить еще могу представить себе как этот список что-то будет добавляться или по клику какой-нибудь иконки что бы пункт удалялся, то как только устроить редактирование отдельных пунктов чет ума не приложу.
882 1193973
Аноны. Вот я вроде немного разобрался с php. Сделал студентов, файлообменик. Уже что то понимаю в симфони. Делаю тест хаб. Знаю начальный html, css, js. И я вроде хочу джуном устроится, но в моей мухосрани 50к нету вариантов. И я смотрю в сторону фриланса, а там везде цмс, цмс, цмс. Так вот смысл от этого фреимворка. Вон учишь цмс и хоть работа какая-никакая. Или я не прав?
883 1193980
>>193959
Можно выдавать json объект и строить элементы яваскриптом, а можно выдавать кусок html и заменить яваскриптом содержимое блока.

Все зависит от того нужно ли тебе использовать данные в яваскрипте или нет. Если нет, то html кусок лучше чем json.

Если логика в обработке аякс и обычного запроса сильно не отличается то вполне можно использовать тот же экшн контроллера. Просто ставишь в нем проверку на аякс чтобы не выдавать всю страницу а только часть или json.
884 1193981
>>193959
Щас увидел что у тебя на странице будет редактирование. В этом случае json нормальное решение, но и тут в принципе можно обойтись без него ведь есть же data аттрибуты у тегов.
885 1193983
>>193973
Работа на цмс более востребована, обычно это мелкие конторы с низким порогом оплаты. Фреймы как правило используются для более серьезных проектов чем "хатет сайт продават", соответственно в более крупных компаниях и более крупной оплатой.

Стартовать лучше с цмс.
886 1193985
>>193973
Ну и если стает вопрос пилить обычный сайт (блог, магаз, несколькостраничник) на цмс или фрейме то цмс в этом плане лидирует так как имеет уже готовую админку и огромный набор плагинов.

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

Так что фрейм нужно юзать для особых нестандартных проектов, например таже биржа фриланса или соцсеть.
887 1194055
>>193983
А не подскажешь какую выбрать цмс. ЧТо бы я мог на удаленке найти работу. Ну я конечно её пощупаю, попробую написать пару модулей. Этого же хватит? Хотя бы что бы в месяц тысяч 7 получать.
888 1194075
>>194055
Самая популярная это вордпресс
889 1194077
>>194055
В любой цмс нужно уметь делать модули и темы.
1.PNG10 Кб, 386x347
890 1194105
Где я обосрался?
891 1194109
>>194105
Знак доллара перед цифрами.
892 1194114
>>194105
да и надо было написать:
$random = mt_rand(1,6);
что бы функция mt_rand сложила в переменную $random число от 1 до 6.
893 1194123
>>194109
>>194114
спасибо :)
894 1194199
>>193980
Пасиб, сижу сейчас читаю вот это
https://learn.javascript.ru/ajax-xmlhttprequest

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

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


как эту проверку в пхп реализовать?
895 1194353
>>194199
xmlhttprequest добавляет в http запрос какойто особый заголовок, который можно увидеть в пхп в массиве $_SERVER
896 1194546
https://ideone.com/e.js/c62h6E

Как-то так, предыдущие не скинул, ибо делал в другой IDE т.к. IDEOne не работала.
897 1194616
https://ideone.com/e.js/cZSPyB и вот ещё, но вот тут я действительно не уверен в правильности своих действий, без понятия, можно ли сделать всё так, чтобы $i в условиях цикла и $i в теле цикла влияли друг на друга только в одностороннем порядке. То есть только из условия в тело, но не наоборот.
899 1194619
>>194616
Ты можешь даже присваивать $i произвольные значения внутри цикла. Например чтобы сбросить счетчик, или перескочить несколько итераций сразу.
900 1194686
>>194618
Там вообще какая-то хуйня с ней творится начинает, может IDE тупит. Сейчас проверю где-нибудь ещё.
901 1194690
>>194618
Эм... Фиг знает почему, но теперь всё работает. Сделал как ты написал, спасибо!
902 1194754
https://ideone.com/e.js/2aUPAC

Вроде бы работает как надо, но вот хуй знает, что делать с этими копейками.
903 1194860
>>194075
А как в вордпресс и вообще в цмски вкатиться? Я не представляю, как писать модули. И нужны ли ООП, продуманная архитектура, или можно все в трешовом стиле цмс писать. Мне кажется, что аккуратный код плагина особой роли не сыграет, если сам код цмс выглядит как говно.
904 1194861
>>194860
Судя по архитектуре вордпреса, его клепали умельцы не особо шарящие в высокоуровневом программировании. Там есть несколько классов но в основном все построено на глобальных функциях.

Что касается модулей то тут больше свободы, можешь весь модуль делать на функциях можешь на ооп.
905 1194862
>>194860
Ну а в катываться начинать надо с чтения документации, желательно официальной, желательно на англиском.
906 1195280
for ($mouth = 0;$credit > 0;$mouth++) {
if ($credit < 5000) {

break;
}
}

Если я так сделаю, то прерывание затронет весь цикл ли только конструкцию if?
907 1195286
>>195280
break и continue влияет только на циклы, независимо от того насколько глубоко внутри цикла он находится.
908 1195434
>>195280
причем тут вообще break к if. это вообще разные вещи. перечитай мануал
909 1195447
http://symfony.com.ua/doc/current/introduction/from_flat_php_to_symfony2.html
Нужна помощь с симфони. По ссылке выше говорится, что фронт-контроллер каким-то образом должен обрабатывать каждый запрос, но как заставить его это делать не написаноили я жопой читал. Если фронт-контроллер имеет вот такой код
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
if ('/index.php' === $uri) {
list_action();
} elseif ('/index.php/show' === $uri && isset($_GET['id'])) {
show_action($_GET['id']);
} else {
header('HTTP/1.1 404 Not Found');
echo '<html><body><h1>Page Not Found</h1></body></html>';
}
как можно перенаправить запрос с лист.пхп сюда?
910 1195464
>>195447
Этим занимается веб сервер. Процесс называется rewrite.
https://symfony.com/doc/current/setup/web_server_configuration.html
911 1195634
>>195286
Спасибо!
>>195434
Почитал, признаю, что был невнимателен. Там эта же конструкция мельком демонстрируется.
912 1195721
https://ideone.com/eUZzCl

Так блять, вроде работает. Вопрос такой. Я писал расчёт с процентами и комиссией в 2 строки:

$credit = $credit* $percent;
$credit = $credit + $comission;

И у меня был проёб в расчётах на некоторую сумму, с чем это может быть связано? Проёб такой, что айфон обходился в ~55к
913 1196291
>>193739
а на питон?
914 1196298
какое же непонятное руководство у слима,это пиздц
915 1196350
>>196291
Поидее питон более универсальный язык.

Я бы запрос-ответ сделал на пыхе, а все постоянные процессы игры на с++
916 1196353
>>196350
Вот кто эталонный образец для сайта govnokod.ru. Уж если србрался бек писать для онлайна, то пиши его уеликом на крестах, ибо сокеты там и всякое такое будет безопаснее и быстрее. Пых для бека... ну разве только для блогов и форумов.
917 1196356
>>196353
Кресты - смазливая хуйня.
918 1196473
>>196356
С и асм наше фсйо?
919 1196480
>>196473
Плюсы то что надо.
920 1196494
а что бы сделать Rest API. Мне нужно сделать по сылке доступ к методу, который отдает json или что то подобное?
И это все?
921 1196497
>>196298
https://www.youtube.com/watch?v=YRHqSsKYDJo
самый внятный видеокурс на русском, который нашёл, правда он по slim2
922 1196529
https://2ch.hk/pr/res/1192401.html#1196527 (М)

Нужна помощь, знаю что тут есть мастера не только по бекэнду
923 1196534
>>196298
оно написано для тех, кто шарит прост. типа ты работал на чем-то похожем раньше.
советую тебе просто смотреть обучающие видео на ютубе, как кто-то делает сайт.
924 1196608
>>196534
охуеть,а ОП говорил что с него надо начинать,а руководство-гавно.вот у YII оно норм
925 1196614
>>196608
двачую, сам 3 года назад вкатился в Yii2. сейчас подумываю переходить на ларавел из-за его большей популярности.
926 1196618
>>196614
да ,лаварел крут,но и самый НЕ производительный фр
927 1196619
>>196618
есть пруфы?
928 1196623
>>196619
да
https://habr.com/company/nixsolutions/blog/329718/
но ради справедливости добавлю что это сферическое тестирование в вакууме
929 1196624
По архитектуре шо то шо это одно и тоже. Но в ларавел длиннее цепочки наследований и жирнее классы. Это то что первое бросилось в глаза.
930 1196625
>>196624
правильнее говорить уровень абстракции выше))
931 1196626
>>196625
Блять, подловил))
130-450 932 1196643
>>178091

Формы вроде "зделаешь" не учтены, но в общем, решено правильно.

>>178355

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

Начнем с вопроса, как можно инициализировать код и подключать обработчики.

1) "классический" вариант: подключаем скрипты в шапке документа, содержащие функции, а в коде прописываем обработчики в атрибутах вроде <button onclick="..">, которые вызывают эти функции.

Плюс:

- простота и понятность, можно в один клик перейти к функции
- обработчики работают в момент появления элемента на странице (браузер парсит HTML по мере получения и отображает частично загруженную страницу), нет промежутка времени, когда они "мертвые"
- нет проблем с навешиванием обработчиков на динамически доабвляемый на страницу контент

Минус:

- скрипты в шапке блокируют разбор HTML до их загрузку и нешуточно замедляют загрузку страницы на мобильном соединении если их много (с HTTP/2 это чуть улучшилось, но все равно мешает загрузке)

2) вешаем обработчики через функции вроде $(document).ready() в внешних файлах. Этот подход описан довольно давно (статья 2006 года http://alistapart.com/article/behavioralseparation ).

Плюс:

- достигается полное отделение JS от HTML (некоторые вообще против inline-скриптов и атрибутов onxxx)
- это подается под соусом progressive enhancement
- скрипт не требуется загружать заранее в шапке, его можно загрузить асинхронно уже после загрузки страницы

Минус:

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

Особенно неявно все сделано в bootstrap. Там часто наличие определенного класса или атрибута на элементе вызывает появление на нем обработчика. Это очень неочевидная схема.

- код инициализации может разрастаться со временем и часто работать вхолостую (опять же, грамотное разделение на небольшие файлы может помочь)
- не всегда получается навесить обработчик для динамически добавляемого контента (отчасти решается навешиванием обработчика не на каждый элемент, а на уровень выше в DOM)
- кнопка "мертвая" с момента появления до момента загрузки скрипта и срабатывания события docuemnt ready (решение: либо делаем graceful degradation, чтобы до загрузки скрипта кнопка работала без JS, либо скрываем кнопку до инициализации, например, прописав ей класс с visibility: hidden и снимая этот класс при инициализации). Кстати, про "мертвые" кнопки по моему нигде не пишут, неужели я один знаю про эту особенность?

3) смешанные варианты

Например, вариант 1, но с асинхронной загрузкой кода или вариант 2, с инициализацией не во внешнем файле, а в inline-скрипте.

Проблемы, встречающиеся на больших сайтах:

Проблема: большой объем кода. Трудно разобраться, надо грузить много лишнего кода, который не нужен на странице.
Решение: разбиваем код на файлы. Критерии разбиения могут быть разные, например: один класс на файл, один файл на страницу или раздел, один файл на каждый виджет. Главное, чтобы там была какая-то логика.

Например, в идеологии БЭМ мы можем каждый виджет (элемент страницы) делать независимым и класть в свою папку, где лежит его шаблон, его стили, управляющие скрипты: https://ru.bem.info/methodology/filestructure/ . Ну например, мы можем сделать отдельную папку для виджета просмотра и добавления комментариев, после чего легко добавлять его на любую страницу.

Разбиение на компоненты используется и в Angular, и в React, но делать его можно и без этих библиотек.

Проблема: синхронные скрипты блокируют загрузку страницы
Решение: используем progressive enhancement и асинхронную загрузку. То есть загружается просто базовая HTML версия страницы, затем асинхронно грузятся скрипты и обогащают страницу.

Проблема: асинхронно загруженный скрипт не знает, есть ли уже в дереве DOM нужные ему элементы или нет
Решение: либо используем document.ready, либо пишем после кода виджета inline-скрипт, который вызывает фукнцию инициализации явно. Во втором случае элемент инициализируется раньше, чем если бы мы ждали события ready.

Проблема: скрипты могут иметь зависимости и их требуется грузить в определенном порядке. Например, скрипт, использующий jQuery, можно запускать только после загрузки этой библиотеки.
Решение: модули, ES6 модули, AMD, загрузчики вроде require.js. Они позволяют указать зависимости модулей друг от друга.

Проблема: элементы не реагируют на события до загрузки управляющего скрипта
Решение: либо используем graceful degradation (например, ссылка до загрузки скрипта работает как ссылка, а после - как кнопка) либо скрываем элементы. При скрытии желательно использовать visibility: hidden или opcaity, чтобы верстка не прыгала при появлении элемента.

Проблема: в разных скриптах может оказаться функция или переменная с одинаковым именем.
Решение: префиксы в именах функций или модули.

Ответы на вопросы:

> Я ещё не освоился с JS, но пока могу сказать, что это нужно разделить либо на отдельные функции, либо разбить на два класса - Helper и Handler, который вешает обработчики (к примеру, Handler.prototype.handleClickOnImg...).



Не уверен, что в этом есть смысл, разбивать код одного виджета на 2 части.

Кстати, по поводу закрытия при клике на фон - видел такую реализацию, что при наведении на фон (за пределами попапа) курсор превращается в крестик. Чтобы намекнуть, что он закрывает попап. А при наведении на превьюшку курсор можно превращать в лупу.

По коду: https://codepen.io/anon/pen/YLGNRY?editors=0010

Не очень понятно, зачем там строка this.fullsize = $('.fullsize') встречается 2 раза.

> var content = $('<img/>', {class: 'fullsize', src: src});


> $(content).on('load', function() {



Нет ли тут риска, что событие load может произойти до навешивания обработчика? Я не уверен, как все это работает, но по моему src было бы безопаснее задавать после навешивания обработчика.

Нет индикации того, что идет загрузка.

В коде очень глубокая вложенность. 3-4 уровня это максимум.

Это сделано очень неудачно:

> много строк...


> this.visible = true;


> }


> }.bind(this));



Непонятно, к чему вообще относится bind(this). Не надо так писать, огромную функцию и после нее сразу же bind. Вообще, это плохая идея делать гигантские анонимные функции. Ее надо разбить на функции поменьше. Зачем вообще вкладывать несколько функций друг в друга, когда можно их писать просто вертикально друг над другом?

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

По коду https://github.com/richBlueElephant/phpClub/blob/master/public/media/js/script.js

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

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

Это конечно скорее проблема плохого дизайна обработчиков событий в браузере, что нам приходится дергать JS скрипт на каждое событие прокрутки или движения мыши. Причем они еще и синхронные - пока обработчик не отработает, браузер ждет и ничего не делает.

Тут в коде та же проблема- огромная вложенность и стремление писать стены кода вместо разделения на функици.

При отправке запроса желательно сделать индикатор. На доброчане, например, яблочко крутится, как я помню, при наведении на ссылку.

Если код состоит из отдельных независимых классов, может стоит разбить его на отдельные файлы.

Если пост есть на странице, возможно не требуется дергать API.

jQuery по умолчанию отключает кеширование в GET-запросе добавлением случайного параметра в URL. Если посты редко меняются, имеет смысл включить кеширование и на сервере отдавать заголовки для безусловного кеширования на небольшое время. А может, еще и поддерживать кеширование через if-modified-since.

В обработчике scroll уменьшение частоты вызовов лучше сделать отдельной функцией, можно даже найти готовую, они называются вроде debounce ( https://davidwalsh.name/javascript-debounce-function ). Это явно стоит вынести в отдельную функцию.

В обработчике попапа, возможно, стоит реагировать на $(window).resize и обновлять позицию попапа, опять же, с применением debounce.
130-450 932 1196643
>>178091

Формы вроде "зделаешь" не учтены, но в общем, решено правильно.

>>178355

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

Начнем с вопроса, как можно инициализировать код и подключать обработчики.

1) "классический" вариант: подключаем скрипты в шапке документа, содержащие функции, а в коде прописываем обработчики в атрибутах вроде <button onclick="..">, которые вызывают эти функции.

Плюс:

- простота и понятность, можно в один клик перейти к функции
- обработчики работают в момент появления элемента на странице (браузер парсит HTML по мере получения и отображает частично загруженную страницу), нет промежутка времени, когда они "мертвые"
- нет проблем с навешиванием обработчиков на динамически доабвляемый на страницу контент

Минус:

- скрипты в шапке блокируют разбор HTML до их загрузку и нешуточно замедляют загрузку страницы на мобильном соединении если их много (с HTTP/2 это чуть улучшилось, но все равно мешает загрузке)

2) вешаем обработчики через функции вроде $(document).ready() в внешних файлах. Этот подход описан довольно давно (статья 2006 года http://alistapart.com/article/behavioralseparation ).

Плюс:

- достигается полное отделение JS от HTML (некоторые вообще против inline-скриптов и атрибутов onxxx)
- это подается под соусом progressive enhancement
- скрипт не требуется загружать заранее в шапке, его можно загрузить асинхронно уже после загрузки страницы

Минус:

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

Особенно неявно все сделано в bootstrap. Там часто наличие определенного класса или атрибута на элементе вызывает появление на нем обработчика. Это очень неочевидная схема.

- код инициализации может разрастаться со временем и часто работать вхолостую (опять же, грамотное разделение на небольшие файлы может помочь)
- не всегда получается навесить обработчик для динамически добавляемого контента (отчасти решается навешиванием обработчика не на каждый элемент, а на уровень выше в DOM)
- кнопка "мертвая" с момента появления до момента загрузки скрипта и срабатывания события docuemnt ready (решение: либо делаем graceful degradation, чтобы до загрузки скрипта кнопка работала без JS, либо скрываем кнопку до инициализации, например, прописав ей класс с visibility: hidden и снимая этот класс при инициализации). Кстати, про "мертвые" кнопки по моему нигде не пишут, неужели я один знаю про эту особенность?

3) смешанные варианты

Например, вариант 1, но с асинхронной загрузкой кода или вариант 2, с инициализацией не во внешнем файле, а в inline-скрипте.

Проблемы, встречающиеся на больших сайтах:

Проблема: большой объем кода. Трудно разобраться, надо грузить много лишнего кода, который не нужен на странице.
Решение: разбиваем код на файлы. Критерии разбиения могут быть разные, например: один класс на файл, один файл на страницу или раздел, один файл на каждый виджет. Главное, чтобы там была какая-то логика.

Например, в идеологии БЭМ мы можем каждый виджет (элемент страницы) делать независимым и класть в свою папку, где лежит его шаблон, его стили, управляющие скрипты: https://ru.bem.info/methodology/filestructure/ . Ну например, мы можем сделать отдельную папку для виджета просмотра и добавления комментариев, после чего легко добавлять его на любую страницу.

Разбиение на компоненты используется и в Angular, и в React, но делать его можно и без этих библиотек.

Проблема: синхронные скрипты блокируют загрузку страницы
Решение: используем progressive enhancement и асинхронную загрузку. То есть загружается просто базовая HTML версия страницы, затем асинхронно грузятся скрипты и обогащают страницу.

Проблема: асинхронно загруженный скрипт не знает, есть ли уже в дереве DOM нужные ему элементы или нет
Решение: либо используем document.ready, либо пишем после кода виджета inline-скрипт, который вызывает фукнцию инициализации явно. Во втором случае элемент инициализируется раньше, чем если бы мы ждали события ready.

Проблема: скрипты могут иметь зависимости и их требуется грузить в определенном порядке. Например, скрипт, использующий jQuery, можно запускать только после загрузки этой библиотеки.
Решение: модули, ES6 модули, AMD, загрузчики вроде require.js. Они позволяют указать зависимости модулей друг от друга.

Проблема: элементы не реагируют на события до загрузки управляющего скрипта
Решение: либо используем graceful degradation (например, ссылка до загрузки скрипта работает как ссылка, а после - как кнопка) либо скрываем элементы. При скрытии желательно использовать visibility: hidden или opcaity, чтобы верстка не прыгала при появлении элемента.

Проблема: в разных скриптах может оказаться функция или переменная с одинаковым именем.
Решение: префиксы в именах функций или модули.

Ответы на вопросы:

> Я ещё не освоился с JS, но пока могу сказать, что это нужно разделить либо на отдельные функции, либо разбить на два класса - Helper и Handler, который вешает обработчики (к примеру, Handler.prototype.handleClickOnImg...).



Не уверен, что в этом есть смысл, разбивать код одного виджета на 2 части.

Кстати, по поводу закрытия при клике на фон - видел такую реализацию, что при наведении на фон (за пределами попапа) курсор превращается в крестик. Чтобы намекнуть, что он закрывает попап. А при наведении на превьюшку курсор можно превращать в лупу.

По коду: https://codepen.io/anon/pen/YLGNRY?editors=0010

Не очень понятно, зачем там строка this.fullsize = $('.fullsize') встречается 2 раза.

> var content = $('<img/>', {class: 'fullsize', src: src});


> $(content).on('load', function() {



Нет ли тут риска, что событие load может произойти до навешивания обработчика? Я не уверен, как все это работает, но по моему src было бы безопаснее задавать после навешивания обработчика.

Нет индикации того, что идет загрузка.

В коде очень глубокая вложенность. 3-4 уровня это максимум.

Это сделано очень неудачно:

> много строк...


> this.visible = true;


> }


> }.bind(this));



Непонятно, к чему вообще относится bind(this). Не надо так писать, огромную функцию и после нее сразу же bind. Вообще, это плохая идея делать гигантские анонимные функции. Ее надо разбить на функции поменьше. Зачем вообще вкладывать несколько функций друг в друга, когда можно их писать просто вертикально друг над другом?

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

По коду https://github.com/richBlueElephant/phpClub/blob/master/public/media/js/script.js

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

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

Это конечно скорее проблема плохого дизайна обработчиков событий в браузере, что нам приходится дергать JS скрипт на каждое событие прокрутки или движения мыши. Причем они еще и синхронные - пока обработчик не отработает, браузер ждет и ничего не делает.

Тут в коде та же проблема- огромная вложенность и стремление писать стены кода вместо разделения на функици.

При отправке запроса желательно сделать индикатор. На доброчане, например, яблочко крутится, как я помню, при наведении на ссылку.

Если код состоит из отдельных независимых классов, может стоит разбить его на отдельные файлы.

Если пост есть на странице, возможно не требуется дергать API.

jQuery по умолчанию отключает кеширование в GET-запросе добавлением случайного параметра в URL. Если посты редко меняются, имеет смысл включить кеширование и на сервере отдавать заголовки для безусловного кеширования на небольшое время. А может, еще и поддерживать кеширование через if-modified-since.

В обработчике scroll уменьшение частоты вызовов лучше сделать отдельной функцией, можно даже найти готовую, они называются вроде debounce ( https://davidwalsh.name/javascript-debounce-function ). Это явно стоит вынести в отдельную функцию.

В обработчике попапа, возможно, стоит реагировать на $(window).resize и обновлять позицию попапа, опять же, с применением debounce.
933 1196645
>>179015

В MyISAM нельзя заблокировать одну строку, только таблицу целиком. Подозреваю, что будет либо ошибка, либо mysql молча проигнорирует требование блокировки.

> Мне нужно удалить запись из основной, предварительно почистив все остальные. Но есть вероятность, что пока я буду их чистить и дойду до удаления основной, в какую-то из них опять что-то добавят.



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

> В то-же время не хотелось бы лочить их все. И не хотелось бы получить висяки.


Это необходимо. Вряд ли у тебя куча транзакций обращается в один момент времени к одной и той же строке.

> Я так понимаю, если добавить констрейнты foreign key, то мне просто не даст удалить запись если в процессе кто-то что-то опять добавит, но такой вариант мне тоже не нравится - просто inconvinient для пользователя.


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

> Что если дописать там поле допустим QUEUED_FOR_DELETION, и во всех местах приложения не давать добавлять связи для таких сущностей, а потом когда-нибудь их удалить. Можно было бы конечно вообще не удалять в таком случае но таблица будет расти и место там не резиновое.


По моему ты изобретаешь велосипед и это здесь не нужно.

>>179285

Нет, неправильно. Ты не меняешь значения firstletter и lastletter и они всегда одинаковые, на каждом шаге цикла.

>>179478

Апач и нгинкс изучи.

>>179617

По моему это усложнение. Вызов внешней команды это сложнее и медленнее, чем вызов библиотечной функции. Для ресайза в PHP можно найти готовую библиотеку или написать несложный код на gd.

>>179739

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

Надо учесть, что задача генерации превьюшки или видео может провалиться. Возможно, стоит предусмотреть несколько попыток конвертации. И ручной запуск переконвертации проблемных файлов.
933 1196645
>>179015

В MyISAM нельзя заблокировать одну строку, только таблицу целиком. Подозреваю, что будет либо ошибка, либо mysql молча проигнорирует требование блокировки.

> Мне нужно удалить запись из основной, предварительно почистив все остальные. Но есть вероятность, что пока я буду их чистить и дойду до удаления основной, в какую-то из них опять что-то добавят.



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

> В то-же время не хотелось бы лочить их все. И не хотелось бы получить висяки.


Это необходимо. Вряд ли у тебя куча транзакций обращается в один момент времени к одной и той же строке.

> Я так понимаю, если добавить констрейнты foreign key, то мне просто не даст удалить запись если в процессе кто-то что-то опять добавит, но такой вариант мне тоже не нравится - просто inconvinient для пользователя.


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

> Что если дописать там поле допустим QUEUED_FOR_DELETION, и во всех местах приложения не давать добавлять связи для таких сущностей, а потом когда-нибудь их удалить. Можно было бы конечно вообще не удалять в таком случае но таблица будет расти и место там не резиновое.


По моему ты изобретаешь велосипед и это здесь не нужно.

>>179285

Нет, неправильно. Ты не меняешь значения firstletter и lastletter и они всегда одинаковые, на каждом шаге цикла.

>>179478

Апач и нгинкс изучи.

>>179617

По моему это усложнение. Вызов внешней команды это сложнее и медленнее, чем вызов библиотечной функции. Для ресайза в PHP можно найти готовую библиотеку или написать несложный код на gd.

>>179739

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

Надо учесть, что задача генерации превьюшки или видео может провалиться. Возможно, стоит предусмотреть несколько попыток конвертации. И ручной запуск переконвертации проблемных файлов.
934 1196646
>>179846

Проверь заголовки кеширования, которые отдаются со статикой. Ты уверен, что у тебя не включено принудительное кеширование всего в браузере?

Алсо, эти watch скрипты часто едят процессор, хотя по логике не должны бы.

>>179898
>>182122

Есть готовые сервисы вроде ping-admin, погугли.

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

>>180220

Не найдет адрес вроде xOJYyzANUS000M.O0PUNCTUMc;GRom

До символа @ могут встретиться символы +, точка, процент и наверно еще куча символов.

Вывыодить надо не массив с кучей лишних элементов, а только список email.

>>180308

> Обмен валют - https://ideone.com/GxnpIE


Верно.

> Игра в кубики - https://ideone.com/fpmVXk


Вместо $humanFRand лучше было сделать humanRand1 - цифра читается лучше, чем S или F.

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

> Таблица умножения - https://ideone.com/XIc2VN


Верно.

> Процент вклада - https://ideone.com/v9dwvI


Правильно.

> Расчет кредита - https://ideone.com/UOy1TU


> Можно было через for, в котором сделать проверки if sumCredit < 5000 и т.д.


Так наверно и стоило ради простоты кода. А то тут трудно проверить, правильно ли все считается.

> Средний балл - https://ideone.com/Wu7ve0


Правильно.

> Сравнение роста - https://ideone.com/0iNujR


Верно.

> РулетОчка - https://ideone.com/akfHyX


Правильно.

> Генератор имён - https://ideone.com/qTV2wH


> $name[$i]


Можно просто писать $name[] = ..., чтобы индексы вычислялись автоматически. А так, верно.

> Шифровка - https://ideone.com/M9ebqb


Праивльно.
934 1196646
>>179846

Проверь заголовки кеширования, которые отдаются со статикой. Ты уверен, что у тебя не включено принудительное кеширование всего в браузере?

Алсо, эти watch скрипты часто едят процессор, хотя по логике не должны бы.

>>179898
>>182122

Есть готовые сервисы вроде ping-admin, погугли.

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

>>180220

Не найдет адрес вроде xOJYyzANUS000M.O0PUNCTUMc;GRom

До символа @ могут встретиться символы +, точка, процент и наверно еще куча символов.

Вывыодить надо не массив с кучей лишних элементов, а только список email.

>>180308

> Обмен валют - https://ideone.com/GxnpIE


Верно.

> Игра в кубики - https://ideone.com/fpmVXk


Вместо $humanFRand лучше было сделать humanRand1 - цифра читается лучше, чем S или F.

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

> Таблица умножения - https://ideone.com/XIc2VN


Верно.

> Процент вклада - https://ideone.com/v9dwvI


Правильно.

> Расчет кредита - https://ideone.com/UOy1TU


> Можно было через for, в котором сделать проверки if sumCredit < 5000 и т.д.


Так наверно и стоило ради простоты кода. А то тут трудно проверить, правильно ли все считается.

> Средний балл - https://ideone.com/Wu7ve0


Правильно.

> Сравнение роста - https://ideone.com/0iNujR


Верно.

> РулетОчка - https://ideone.com/akfHyX


Правильно.

> Генератор имён - https://ideone.com/qTV2wH


> $name[$i]


Можно просто писать $name[] = ..., чтобы индексы вычислялись автоматически. А так, верно.

> Шифровка - https://ideone.com/M9ebqb


Праивльно.
935 1196647
>>180542

Увы, ideone теперь тоже сломан, перекатывайтесь куда-нибудь еще.

>>181775

Школьник может платить от 0 до 5000 р в месяц. Он платит как можно больше, чтобы быстрее выплатить кредит и меньше платить процентов. То есть он платит меньшее из чисел (5000, остаток долга).

Код выглядит примерно так:

- прибавляем проценты и комиссию к остатку долга (!не вычитаем ничего пока!)
- если остаток маленький, выплачиваем сколько осталось и уходим
- иначе платим 5000

«Платим» здесь значит уменьшаем долг и увеличиваем общую сумму выплаченного.

Ответ тогда получится правильный.

Также, там сначала добавляются проценты, а потом школьник платит. У тебя наоборот.

>>182086

Вот кстати по чату, очень бы хотелось, чтобы ты для себя сделал первым приоритетом простой, понятный код. Чтобы в нем было легко разбираться. Мы же в PHP разделяем код на классы, соблюдаем правила оформления, пишем комментарии - хотелось бы и в JS то же самое.

Сторонние скрипты лучше положить в отдельную папку от своих.

>>182092

А какой в этом смысл? Достаточно проверить половину символов.

А так, решено верно.

>>182336

Посмотри в инструментах разработчика (Ctrl + Shift + I), нет ли ошибок на вкладке Network и Console. Не надо гадать.
935 1196647
>>180542

Увы, ideone теперь тоже сломан, перекатывайтесь куда-нибудь еще.

>>181775

Школьник может платить от 0 до 5000 р в месяц. Он платит как можно больше, чтобы быстрее выплатить кредит и меньше платить процентов. То есть он платит меньшее из чисел (5000, остаток долга).

Код выглядит примерно так:

- прибавляем проценты и комиссию к остатку долга (!не вычитаем ничего пока!)
- если остаток маленький, выплачиваем сколько осталось и уходим
- иначе платим 5000

«Платим» здесь значит уменьшаем долг и увеличиваем общую сумму выплаченного.

Ответ тогда получится правильный.

Также, там сначала добавляются проценты, а потом школьник платит. У тебя наоборот.

>>182086

Вот кстати по чату, очень бы хотелось, чтобы ты для себя сделал первым приоритетом простой, понятный код. Чтобы в нем было легко разбираться. Мы же в PHP разделяем код на классы, соблюдаем правила оформления, пишем комментарии - хотелось бы и в JS то же самое.

Сторонние скрипты лучше положить в отдельную папку от своих.

>>182092

А какой в этом смысл? Достаточно проверить половину символов.

А так, решено верно.

>>182336

Посмотри в инструментах разработчика (Ctrl + Shift + I), нет ли ошибок на вкладке Network и Console. Не надо гадать.
936 1196648
>>182524

Спасибо за сообщение, что-то я сразу не понял.

>>182378

А зачем их сохранять в файле? непонятно. Используй что-то стандартное, например, сессии или храни данные в БД. Ну или пиши свой код для проверки и обновления данных в файле.

>>182405

Насчет нестандартных методов - некоторые роутеры умеют проверять методы и указывать, для каких роутов какие методы разрешены. Symfony Routing это умеет.

> if (strpos($_SERVER['REQUEST_URI'], '/home/') === 0) {


Это плохой подход, так как у тебя дял страницы есть огромное число URL вроде /home/1, /home/2 и тд. А с точки зрения логики и SEO у каждой страницы должен быть 1 URL.

> case 'HEAD':


> exit; // HEAD не требует отдачи контента, выходим


это неправильная реализация, так как HEAD должен отдать ровно те же заголовки, что и GET, только без тела. У тебя это не реализовано. Например, в твоем коде для страницы с 404 HEAD отдаст код 200, а это неправильно. HEAD проще всего реализовать, делая GET и отрезая от него тело.

Смысл роутера - чтобы не писать лапшу из if, а просто сделать конфиг.
https://github.com/mlmn/vector.loc 937 1196649
>>182534

> try/catch выпилил, самому не нравилась идея оборачивать каждый код с exeptionon'ом внутри в эту конструкцию. А если я например чужой класс ипользую - мне нужно идти смотреть получается нет ли там внутри выброса исключений и на методы внутри которых есть рисовать try/catch каждый раз? Звучит тупо, так что только рад что это всё не нужно.



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

> Убрал, но как в другом месте это выводить или впиливать - не понял.


Просто прописать во вью либо сделать массив вида ['name' => ..., 'company' => ...] либо такой же объект.

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


Лучше сразу привыкать делать правильно. Плюс, если у тебя в названии компании будет <s> то без htmlspecialchars оно вставится как тег.

> >> abstract protected function setDefaults();


> Я вообще не понимаю что тут от меня нужно.


У тебя, чтобы объект Employee правильно работал, в нем надо задать зарплату, кофе и тд. Это можно сделать по-разному:

- сделать такие аргументы в конструкторе Employee, чтобы нельзя было создать объект без их задания
- сделать абстрактные методы, чтобы нельзя было объявить класс-наследник без указания зарплаты и потребл. кофе

> И тут становится понятно, что просто ретернить захардкоженные значения уже не работает. Ведь их придется менять, а что бы менять - их нужно где-то хранить



Можно ввести 3 разных понятия:

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

Либо можно при создании объекта требовать указать стартовую зарплату в конструкторе.

В твоем коде никак не проверяется, что стартовая зарплата задана. Легко забыть это сделать при написании класса-наследника.

> Так же добавил свистелку в виде методов setTimePoint() и benchMark()


Почитай мануал по microtime - explode давно уже не нужен. Также, а зачем это нужно, если можно с помощью расширения xdebug записать трейс и в нем посмотреть, какие функции когда вызвались и сколько времени заняли? Погугли xdebug tracing.

> В итоге 2 главных проблемы так и не решил - OrgInfo ращбил на кучу копипастных методов, которые пусть и удобные, но само их существование мне не нравится и они дублируются и лишь загромождают код,


Тут наверно ничего не сделать, благо методы крошечные. Сложные классы могут содержать и по 1000, и по 2000 строк, так что ничего. Ну либо придется выносить это в обертку, которой мы передаем компанию и в которой есть методы для вычисления суммы и среднего.

Можно было еще как-то заморочиться с такой штукой, где один метод умеет считать сумму любого показателя:

public function getTotal($type) {
...
}

По коду:

Для методов, которые ничего не возвращают, можно писать тайп-хинт void.

> public function getDepartments(): array {


> if ($this->countDepartments() == 0) {


> throw new Exception('Пустая организация, нечего выводить.');


Я думаю, логичнее возвращать пустой массив. Разве это ошибка - запросить список департаментов, если их пока не добавили?

> $classMatch = (get_class($employee) == $this->getClass());


Может быть лучше instanceof, чтобы искались бы и наследники класса? По правилу подстановки Лисков наследник класса может использоваться вместо него.

> if ($classMatch and $rangMatch and $leaderMatch) {


> return true;


Можно писать return $classMatch && $rangMatch && $leaderMatch;

> if (in_array($employee, $fireList)) {


Тут наверно нужен еще true

> abstract protected function setDefaults();


Недостаток твоего решения тут в том, что этот метод не обязывает нас что-то делать. И не документирует, что он должен делать. Мы можем просто сделать пустой метод или забыть что-то в нем задать. Потому тут лучше было бы сделать 3 отдельных абстрактных метода вроде

abstract protected function getDefalutSalary(): float

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

> new EmployeeSelector('Engineer', null, null);


имя класса лучше писать как Engineer::class - тогда при опечатке будет выдана ошибка.

> $engineersList = $employeeSelector->filterEmployees($dep->getEmployees());


Тут еще можно было сделать вариант $dep->findEmployees($selector); но твой вариант тоже годится конечно.

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

$selector = new Selector;
$selector->setMinRang(2);
$selector->setMinExperience(2);
$selector->setSalaryRange(100, 500);

Также, есть еще интересный вариант, когда селектор выражается анонимной функцией, возвращающей true/false:

$list = $dep->findEmployees(function (Employee $e) {
return $e->getRank() == 2 && $e instanceof Engineer;
});

Если в PHP добавят стрелочные функции ( https://wiki.php.net/rfc/arrow_functions ), этот код будет еще короче:

$list = $dep->findEmployees(fn($e) => $e->getRank() == 2 && $e instanceof Engineer);

Более того, в объектах есть метод __invoke, который позволяет "вызывать" их как функцию: http://php.net/manual/ru/language.oop5.magic.php#object.invoke

Если твой Selector реализует этот метод, то его можно будет передавать в ту же самую функцию вместо анонимной функции.

В общем, сделано верно. Надеюсь, ты смог увидеть преимущества ООП в этой задаче, как ООП позволяет организовать большой и сложный код, разбив его на отдельные классы. Если хочется еще потренироваться с ООП, могу посоветовать задачу про Гостиницу: https://phpclub.tech/pr/res/1082507.html#1097078
https://github.com/mlmn/vector.loc 937 1196649
>>182534

> try/catch выпилил, самому не нравилась идея оборачивать каждый код с exeptionon'ом внутри в эту конструкцию. А если я например чужой класс ипользую - мне нужно идти смотреть получается нет ли там внутри выброса исключений и на методы внутри которых есть рисовать try/catch каждый раз? Звучит тупо, так что только рад что это всё не нужно.



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

> Убрал, но как в другом месте это выводить или впиливать - не понял.


Просто прописать во вью либо сделать массив вида ['name' => ..., 'company' => ...] либо такой же объект.

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


Лучше сразу привыкать делать правильно. Плюс, если у тебя в названии компании будет <s> то без htmlspecialchars оно вставится как тег.

> >> abstract protected function setDefaults();


> Я вообще не понимаю что тут от меня нужно.


У тебя, чтобы объект Employee правильно работал, в нем надо задать зарплату, кофе и тд. Это можно сделать по-разному:

- сделать такие аргументы в конструкторе Employee, чтобы нельзя было создать объект без их задания
- сделать абстрактные методы, чтобы нельзя было объявить класс-наследник без указания зарплаты и потребл. кофе

> И тут становится понятно, что просто ретернить захардкоженные значения уже не работает. Ведь их придется менять, а что бы менять - их нужно где-то хранить



Можно ввести 3 разных понятия:

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

Либо можно при создании объекта требовать указать стартовую зарплату в конструкторе.

В твоем коде никак не проверяется, что стартовая зарплата задана. Легко забыть это сделать при написании класса-наследника.

> Так же добавил свистелку в виде методов setTimePoint() и benchMark()


Почитай мануал по microtime - explode давно уже не нужен. Также, а зачем это нужно, если можно с помощью расширения xdebug записать трейс и в нем посмотреть, какие функции когда вызвались и сколько времени заняли? Погугли xdebug tracing.

> В итоге 2 главных проблемы так и не решил - OrgInfo ращбил на кучу копипастных методов, которые пусть и удобные, но само их существование мне не нравится и они дублируются и лишь загромождают код,


Тут наверно ничего не сделать, благо методы крошечные. Сложные классы могут содержать и по 1000, и по 2000 строк, так что ничего. Ну либо придется выносить это в обертку, которой мы передаем компанию и в которой есть методы для вычисления суммы и среднего.

Можно было еще как-то заморочиться с такой штукой, где один метод умеет считать сумму любого показателя:

public function getTotal($type) {
...
}

По коду:

Для методов, которые ничего не возвращают, можно писать тайп-хинт void.

> public function getDepartments(): array {


> if ($this->countDepartments() == 0) {


> throw new Exception('Пустая организация, нечего выводить.');


Я думаю, логичнее возвращать пустой массив. Разве это ошибка - запросить список департаментов, если их пока не добавили?

> $classMatch = (get_class($employee) == $this->getClass());


Может быть лучше instanceof, чтобы искались бы и наследники класса? По правилу подстановки Лисков наследник класса может использоваться вместо него.

> if ($classMatch and $rangMatch and $leaderMatch) {


> return true;


Можно писать return $classMatch && $rangMatch && $leaderMatch;

> if (in_array($employee, $fireList)) {


Тут наверно нужен еще true

> abstract protected function setDefaults();


Недостаток твоего решения тут в том, что этот метод не обязывает нас что-то делать. И не документирует, что он должен делать. Мы можем просто сделать пустой метод или забыть что-то в нем задать. Потому тут лучше было бы сделать 3 отдельных абстрактных метода вроде

abstract protected function getDefalutSalary(): float

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

> new EmployeeSelector('Engineer', null, null);


имя класса лучше писать как Engineer::class - тогда при опечатке будет выдана ошибка.

> $engineersList = $employeeSelector->filterEmployees($dep->getEmployees());


Тут еще можно было сделать вариант $dep->findEmployees($selector); но твой вариант тоже годится конечно.

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

$selector = new Selector;
$selector->setMinRang(2);
$selector->setMinExperience(2);
$selector->setSalaryRange(100, 500);

Также, есть еще интересный вариант, когда селектор выражается анонимной функцией, возвращающей true/false:

$list = $dep->findEmployees(function (Employee $e) {
return $e->getRank() == 2 && $e instanceof Engineer;
});

Если в PHP добавят стрелочные функции ( https://wiki.php.net/rfc/arrow_functions ), этот код будет еще короче:

$list = $dep->findEmployees(fn($e) => $e->getRank() == 2 && $e instanceof Engineer);

Более того, в объектах есть метод __invoke, который позволяет "вызывать" их как функцию: http://php.net/manual/ru/language.oop5.magic.php#object.invoke

Если твой Selector реализует этот метод, то его можно будет передавать в ту же самую функцию вместо анонимной функции.

В общем, сделано верно. Надеюсь, ты смог увидеть преимущества ООП в этой задаче, как ООП позволяет организовать большой и сложный код, разбив его на отдельные классы. Если хочется еще потренироваться с ООП, могу посоветовать задачу про Гостиницу: https://phpclub.tech/pr/res/1082507.html#1097078
938 1196650
>>182544

А какие проверки тебе нужны? Я не понимаю вопрос.

Могу только дать ссылку на определение слова авторизация: https://ru.wikipedia.org/wiki/Авторизация

>>182659

Библиотека getId3 по моему.

>>182598

Библиотекам часто нужны зависимости. Удобнее по моему иметь небольшой списочек библиотек в файле, чем вручную их все качать, искать их зависимости, при обновлении все это заново делать итд

В чем недостаток bower? То, что ты его не осилил, это не аргумент.

>>182722

Ну так JS код надо точно так же организовать, как PHP: отделить логику от интерфейса, разбить на функции, прокомментировать, соблюдать стиль написания кода.

У тебя явно можно разнести логику загрузчика файла и логику отображения. Например:

var form = $('#upload-form');
form.on('submit', function () {
lockSubmitButton(form);
showProgress();
uploader.uploadForm(form, function (response) {
unlockSubmitButton(form);
hideProgress();
showMessage('Success');
}, function (reason) {
unlockSubmitButton(form);
hideProgress();
showMessage('Error: '+ reason);
});
});

Или то же, но с промисами:

form.on('submit', function () {
lockSubmitButton(form);
showProgress();
var response = uploader.uploadForm(form);

response.success(function (response) {
unlockSubmitButton(form);
hideProgress();
showMessage('Success');
});

response.error(function (reason) {
unlockSubmitButton(form);
hideProgress();
showMessage('Error: '+ reason);
});
});

Чтобы не ездить по нодам, возьми библиотеку для DOM traversing или jQuery.

>>182742

Простую форму загрузки файла можно сделать без React. Более того, React довольно тяжелый и там по моему Hello World под мегабайт весит.

>>183002

Typescript неплохая вещь, но к вопросу он мало отношения имеет. Да и не очень удобно, постоянно перекомпилировать вместо того, чтобы просто обновить страницу.
938 1196650
>>182544

А какие проверки тебе нужны? Я не понимаю вопрос.

Могу только дать ссылку на определение слова авторизация: https://ru.wikipedia.org/wiki/Авторизация

>>182659

Библиотека getId3 по моему.

>>182598

Библиотекам часто нужны зависимости. Удобнее по моему иметь небольшой списочек библиотек в файле, чем вручную их все качать, искать их зависимости, при обновлении все это заново делать итд

В чем недостаток bower? То, что ты его не осилил, это не аргумент.

>>182722

Ну так JS код надо точно так же организовать, как PHP: отделить логику от интерфейса, разбить на функции, прокомментировать, соблюдать стиль написания кода.

У тебя явно можно разнести логику загрузчика файла и логику отображения. Например:

var form = $('#upload-form');
form.on('submit', function () {
lockSubmitButton(form);
showProgress();
uploader.uploadForm(form, function (response) {
unlockSubmitButton(form);
hideProgress();
showMessage('Success');
}, function (reason) {
unlockSubmitButton(form);
hideProgress();
showMessage('Error: '+ reason);
});
});

Или то же, но с промисами:

form.on('submit', function () {
lockSubmitButton(form);
showProgress();
var response = uploader.uploadForm(form);

response.success(function (response) {
unlockSubmitButton(form);
hideProgress();
showMessage('Success');
});

response.error(function (reason) {
unlockSubmitButton(form);
hideProgress();
showMessage('Error: '+ reason);
});
});

Чтобы не ездить по нодам, возьми библиотеку для DOM traversing или jQuery.

>>182742

Простую форму загрузки файла можно сделать без React. Более того, React довольно тяжелый и там по моему Hello World под мегабайт весит.

>>183002

Typescript неплохая вещь, но к вопросу он мало отношения имеет. Да и не очень удобно, постоянно перекомпилировать вместо того, чтобы просто обновить страницу.
939 1196651
>>183233

Хром подчиняется правилам, заданным в HTTP заголовкам ответа. Кто-то криворуко настроил эти заголовки, а виноват Хром.

>>183287

Вызывать функцию надо как call_user_func($this->x, ...) и тогда все будет работать. Но судя по твоему описанию, у тебя может быть неудачная архитектура и ты лепишь костыли вместо решения проблемы.

> Суть в том, что есть класс, который работает с html-кодом. И этот самый html-код может получаться разными способами, которые никак не унифицировать. То есть, у каждого объекта своя версия функции, которая генерирует html.



Это только подтверждает мою мысль.
940 1196705
>>187793
Бамп
941 1196711
Господа, есть регулярка находящая одну латинскую букву в окружении двух возможных на кириллице, которых может не быть.

/[а-яёА-ЯЁ]?[a-zA-Z][а-яёА-ЯЁ]?/ui

Как сделать, чтобы она находила латинскую букву с обязательной кириллической буквой рядом или с обоих сторон?
942 1196769
>>196711
/([А-Яа-я]([A-Za-z]))|(([A-Za-z])[А-Яа-я])|([А-Яа-я]([A-Za-z])[А-Яа-я])/ui

Но это не точно.
943 1196778
>>196769
Выглядит как хуй, но спасибо.
944 1196796
стоит ли сильно задрачивать чистый пхп и его технологии,если есть фреймворки?
в Б меня обоссали за попытку пилить сайт на чистом языке
945 1196798
>>196796
Как ты поймешь фреймворки не зная основ языка на котором они написаны?
946 1196799
>>196796
Работая в компании мне приходилась иметь дело с самописными двиками.

Незная чистого языка ты постоянно будешь биться об нипонимание что делает тот или иной код в недрах фрейма.
947 1196805
>>196798
мне сказали,что там высокая абстракция ,и сильные знания чистого не нужны
450px-Multithreadedprocess.svg.png24 Кб, 450x425
someApprentice 948 1196856
>>190031
>>190415
Прошу прощения за столь долгий ответ - пришлось набираться сил чтобы погрузитья глубже в изучение, но, каким-то чудом, я, вроде, всё понял. Даже вопросов нет, почти.

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

Технологии, которые я буду использовать:
Redis Pub/Sub https://redis.io/topics/pubsub
phpredis https://github.com/phpredis/phpredis
ReactPHP EventLoop (для реализации таймаута ожидания) https://reactphp.org/event-loop/

subscribe.php
<?php

$redis = new Redis();
$redis->open(...); // соеденяемся

// Каналами может быть всё что угодно - id переписок, пользователей, всё на что мы хотим подписаться
// В нашем случае можно опустить только до сообщений для простоты
$channels = [...];

$message = new Message();

$loop = React\EventLoop\Factory::create();

$loop->addTimer($interval = 30, function () use ($redis) {

//unsubscribe
$redis->close();

//возвращаем пустое сообщение
});

$loop->run();

$message = $redis->subscribe($channels, function($r, $c, $m) use ($message) {

return $message->set($m);

});

//возвращаем получившиеся сообщение (либо пустое, либо то что вернул брокер)
return $message;

?>

publish.php
<?php

$database = new Database(...);

$redis = new Redis();
$redis->open(...);

$channels = [...];

$message = new Message($_POST['message']);

$message = $database->add($message);

foreach ($channels as $channel) {

$redis->publish($channel, $message); // перевод объекта Сообщения в строку опустим для простоты

}

// возвращаем сообщение назад в случае успеха
return $message;

?>

Получилось довольно всё просто, не смотря на такую трудную для меня задачу.

Однако, у меня, всё же, появились вопросы пока я писал этот пост, и я вынжден попрасить вас ответить на них.

https://github.com/phpredis/phpredis#subscribe
Я не знаю языка C, поэтому я не могу разобраться, ассинхронная ли это функция? Должно быть, ассинхронная. То есть, её возврат и присваиванее в переменную $message, в моём коде, не произойдет, если никакое сообщение так и не прийдёт?
Если это так, то можно сначала подписаться, а потом уже поставить таймайут ожидания.

https://github.com/phpredis/phpredis#publish
Опять же, из-за незнания C, я не знаю, что эта функция вернет? Как всегда, true/false в случае успеха/неудачи?

Приемлимо для обмена сообщений между клиентами Redis использовать строку в виде данных json? Или есть какая-то другая договрённость для обмена большого количества информации?
К примеру, в моём коде, я хотел опубликовать весь объект Сообщения, включая id, само сообщение, дату и так далее.

Как я и раньше, брал в пример поведение одной популярной соц.сети, так и сейчас хотелось бы рассмотреть одно из её поведений: Когда происходит одно из уведомлений (не важно, приходит ли сообщение или собеседник набирает сообщение, или кто-то подписывается) всегда выполняется один и тот же запрос.
Мне кажется, это эффективно - меньше дёрганий на обращение к БД на обнавление сообщений/контактов/проверки набора сообщений.
А что вы думаете?

И кстати, в моём примере, при подписке, я не где не обращаюсь к БД, а жду что ко мне придёт уже готовое сообщение. В этом нет ничего плохого?

Спасибо большое.
450px-Multithreadedprocess.svg.png24 Кб, 450x425
someApprentice 948 1196856
>>190031
>>190415
Прошу прощения за столь долгий ответ - пришлось набираться сил чтобы погрузитья глубже в изучение, но, каким-то чудом, я, вроде, всё понял. Даже вопросов нет, почти.

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

Технологии, которые я буду использовать:
Redis Pub/Sub https://redis.io/topics/pubsub
phpredis https://github.com/phpredis/phpredis
ReactPHP EventLoop (для реализации таймаута ожидания) https://reactphp.org/event-loop/

subscribe.php
<?php

$redis = new Redis();
$redis->open(...); // соеденяемся

// Каналами может быть всё что угодно - id переписок, пользователей, всё на что мы хотим подписаться
// В нашем случае можно опустить только до сообщений для простоты
$channels = [...];

$message = new Message();

$loop = React\EventLoop\Factory::create();

$loop->addTimer($interval = 30, function () use ($redis) {

//unsubscribe
$redis->close();

//возвращаем пустое сообщение
});

$loop->run();

$message = $redis->subscribe($channels, function($r, $c, $m) use ($message) {

return $message->set($m);

});

//возвращаем получившиеся сообщение (либо пустое, либо то что вернул брокер)
return $message;

?>

publish.php
<?php

$database = new Database(...);

$redis = new Redis();
$redis->open(...);

$channels = [...];

$message = new Message($_POST['message']);

$message = $database->add($message);

foreach ($channels as $channel) {

$redis->publish($channel, $message); // перевод объекта Сообщения в строку опустим для простоты

}

// возвращаем сообщение назад в случае успеха
return $message;

?>

Получилось довольно всё просто, не смотря на такую трудную для меня задачу.

Однако, у меня, всё же, появились вопросы пока я писал этот пост, и я вынжден попрасить вас ответить на них.

https://github.com/phpredis/phpredis#subscribe
Я не знаю языка C, поэтому я не могу разобраться, ассинхронная ли это функция? Должно быть, ассинхронная. То есть, её возврат и присваиванее в переменную $message, в моём коде, не произойдет, если никакое сообщение так и не прийдёт?
Если это так, то можно сначала подписаться, а потом уже поставить таймайут ожидания.

https://github.com/phpredis/phpredis#publish
Опять же, из-за незнания C, я не знаю, что эта функция вернет? Как всегда, true/false в случае успеха/неудачи?

Приемлимо для обмена сообщений между клиентами Redis использовать строку в виде данных json? Или есть какая-то другая договрённость для обмена большого количества информации?
К примеру, в моём коде, я хотел опубликовать весь объект Сообщения, включая id, само сообщение, дату и так далее.

Как я и раньше, брал в пример поведение одной популярной соц.сети, так и сейчас хотелось бы рассмотреть одно из её поведений: Когда происходит одно из уведомлений (не важно, приходит ли сообщение или собеседник набирает сообщение, или кто-то подписывается) всегда выполняется один и тот же запрос.
Мне кажется, это эффективно - меньше дёрганий на обращение к БД на обнавление сообщений/контактов/проверки набора сообщений.
А что вы думаете?

И кстати, в моём примере, при подписке, я не где не обращаюсь к БД, а жду что ко мне придёт уже готовое сообщение. В этом нет ничего плохого?

Спасибо большое.
949 1196865
>>196805
Всё равно, что учить некий диалект русского языка не зная русского языка. Разумеется в том же блатняке дохуя абстракций и даже более-менее зная язык всё равно не поймёшь особо, но тебе русский нужен всё равно, иначе будешь как макака.
image.png527 Кб, 700x992
950 1196873
Уважаемый, ОП. Что думаешь об этой книжке?
951 1196876
>>196873
хуевый справочник
952 1196887
>>196876
Спасибо... а ты точно ОП?
953 1196894
>>196887
А какая разница? Книга - плохой пересказ документации. Просто авторы докатали пару глав для новый buzzwords: psr, nginx, fpm и тд для переиздачи, а так все тот же треш из 2004 года. Нет смысла возится с этим толмудом. Лучше сразу топить задачу про студентов из ОП поста и все с ней связанное.
954 1196897
>>196894

>Лучше сразу топить задачу про студентов из ОП поста и все с ней связанное.


А если я программирую первый раз в жизни? Стоит ли проходить основы из оп-учебника?
955 1196907
>>196894
Основы SQL я вроде знаю, что это огромная язык позволяющий ебашить двумерные таблицы (может и трёхмерные, хуй знает, читал пару лет назад) и генерировать всякие запросы с фильтрами для получения нужных данных из базы. А вот ООП... сука, где? Я знаю, что его придумал какой-то мужик, но написал ли он о нём гайд? Да и опять на этом ебучем английском читать.
image.png423 Кб, 1038x873
956 1196910
>>196907

>огромная язык

957 1196911
>>196910

>ебола управляемая через


проебалась где-то между. Эта хуйня конечно полезна, когда тебя зовут помочь, ибо тыжпрограммист, а там в 1С нужно ебашить отчёты.
958 1196912
>>196911
эта хуйня необходима когда ты пиздуешь сайты на пхп
959 1196914
>>196912
Да знаю я. Шапки от начала и до конца зачитывать — золотое правило в любом тематическом разделе.
960 1196915
Слушай, ОП. Такой вот вопрос. Я погляжу, ты тут дохуя чего заготовил и всё годнота. Вопрос таков, за сколько всё это учится?
961 1196916
>>196915

>Примерно


отклеилось.
962 1196938
>>196897
Конечно. ОП поясняет за основы.
963 1196972
>>196915
неОП Если примерно то от 6 месяцев до года в обычном темпе для обычного человека. Есть конечно истории как чуваки за 2-3 месяца полностью вкатывались, но лично я не умею грамотно декомпозировать проблему, приходиться медленно учиться на своих ошибках
964 1196979
>>196873
Я и 5 покупал, и 7 купил. Валяются ;-)

Котеров слишком заумно пишет. Излишняя, чрезмерная, надменная подача информации. Вроде как живое общение с читателем, на равных.

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

Для новичка в мире программирования лучше начать с какой-нибудь онлайн обучалки. Потом уже переходить на чтиво сего талмуда.
965 1197001
>>196979
А старцы из мира программирования хейтят Котерова и его книги. Говорят, мол, говнокода много в примерах, нелогично он выстроен и несвязанно, нет единого стиля, используются устаревшие решения и прочее.
Сам не читал, слышал мнение где-то (тут же на дваче, кажется).
966 1197017
>>196915
У меня есть знакомый, который пол года пытался научится в группе, а потом три года сидя дома. Но так и не стал кодером. Потому что учился на расслабоне, например включает видос и валяется с попкорном а там чтото приятно бубнят. Или читает текст без вдумывания, инфа проходит через мозг и не осознается. То есть он думает что если водить глазами по буквам то чему то можно научиться.

Так что тут все зависит от упорства памяти и внимательности.
967 1197026
>>197001

> говнокода много в примерах



Там ещё беда в том, что примеры кода были написаны в эпоху рнр 5.0.21(!!!) и из 5 книги перккочевали в 7, но с небольшими поправками под современные реалии. И все бы ничего, но стиль примеров действительно остался из середины 00-х.

Там столько исходников, что переписывоть все под 7 рнр у них заняло кучу времени.

Лично мне почему 7 понравилась, тем что в книге они уже пишут про композер, как некоторые технологии юзать. Мне как любителю писать скрипты для души это ценная инфа.

В js с появлением ноды появились всякие бабели и прочие штуки типа вебпака. Была бы полезна некая книга с описанием что и для чего, конечно же в полном цикле с изучением js. Я вот лично из-за объема не собранного вместе материала теряюсь. По отдельности нде то выискивать и читать не очень хочется. Хотелось бы чтобы доходчиво в 1 книге расписали чо к чему.
968 1197032
А пхп программисту нужно учить JS фреймворки? Или нужно просто обычный жс знать и все?
969 1197034
>>197032
По обстоятельствам. Я не проф программист, пишу исклбчительно дома для души. Жс юзаю по мере, но в основном библы, так как с нэтив надо слишком дохуя нюансов этой пердольноц затычки знать.
970 1197035
>>197032
js + jquery необходимая база.
971 1197036
>>197032
Не слушай >>197035 этого. Нэтив жс желательно знать, а вот либы конкретно под проект стоит изучать. Их там такой зоопарк шо пиздец просто. Сейчас vue, angular в почете, jquery это все свистоперделки, которые можно заменить бутстрапом и другими либами.
972 1197037
>>197032

Не слушай >>197036 этого. Зная js + jquery легче начать работать чем с js + vue.

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

Так что если ты только вкатываешься то делай упор на js + jquery. В большинстве вебкомпаний этого достаточно.
973 1197039
>>197037

> делай упор на js + jquery.


Советы уровня /pr. Пиздец, с кем ч на одной борде сижу, лол.
974 1197041
>>197039
Нахуй пошел. Я дело советую.

Допустим ты полнуй нуб только вкатился только начал искать работу. Тебе ничего кроме вордпреса не доверят. И скажи мне нахуй там vue ?
image.jpeg387 Кб, 1024x1024
975 1197043
>>197041
Азаххахаха а нахуй на ворде жкуэри? Что ты несешь дебил? Ты ни дня не работая даешь советы) лол кек чебурек. Катись колбаской сукин сын.
976 1197044
>>197043
Ебать ты даунЖ, ворпрес и жквери не раздельны и у меня 6 лет стажа как на говнокоде так и на фреймах, так шо сосни и жалуйся мамке дите.
image.jpeg744 Кб, 1213x1280
977 1197045
>>197044
Эти маняфантазии.

> 6 лет стажа


На харкаче в /pr проиграммируешь?
978 1197046
>>197045
Какие фантазии? На чем бы ты писал на чистом js? Аргументируй, пизделка.
979 1197047
>>197046
*На чем бы ты писал в WP
980 1197048
>>197046
>>197047
Вот ты и сдулся петух ебаный. Вся твоя гнилая суть проявилась. Хуета чсвшная. Поясняю тебе за щеку. Ты еще бы мутулз посоветовал или иной древгий нахуй ненужный фреймворк для изучения, лалка сосалка ты дурная. Дура безтрусая ты, я тебе еще раз повторяю, ты окромя как в /pr нигде строчки не писал.
981 1197049
>>197048
А тебе вопрос задал. А ты продолжаешь кукарекать. Нечего больше сказать. Лалка.
982 1197050
>>197049
Идиота кусок, что ты собрался в WP на jQuery писать? Ты совсем ебанат натрия что ли?
983 1197051
>>197050
Да любые свистелки пирделки блять. Любая js логика. Любые манипуляции со страницей после загрузки. Да тот же аякс блять.
984 1197053
>>197051
Всё с тобой ясно. Ты понятия не имеешь, о чём ты пишешь. Другой анон правильно про тебя написал, что ты кроме как в /pr нигде больше строчки кода не написал.

мимо другой анон
985 1197063
ТАк стоп. Как я понял из срача выше.
Нужно знать чистый js. А остальное под проект уже учить, но вообще если что от еще хочется, то ангуляр, вуе или реакт. Так?
986 1197069
>>197063
Так
987 1197071
>>197017
Спасибо. Понял.
988 1197072
>>197063
Да в идеале под проект, но хуйня в том что тебе, так как ты нуб, ничего сложного не доверят. А в простых проектах нужен jquery.
989 1197073
>>197053
Другой анон это ты. А я прав.
Проблема с регистрацией 990 1197110
сделал регистрацию,но выдает ошибки,помогите пожалуйста,пых только начал учить
КОД https://pastebin.com/MBXEwHGJ
Ошибка и бд на пике
991 1197111
>>197110
написано же, не то что надо передал в mysqli_real_escape_string
992 1197114
>>197073
Ты меня на шизика то не тяни. Я тебе не билли миллиган, не традаю я множественными личностями.
993 1197116
>>197114
Похер вообще.
994 1197120
>>197116
Хоть в чём-то с тобой солидарен, но ты всё же не мимикрируй под программиста. Человек пришёл за помощью, а ты его траллить начал.
995 1197123
>>197120
Я все верно сказал. Если ты чего то не понимаешь, не списывай это на траллинг.
996 1197182
>>196873
щас бы учить кодить по книжкам
997 1197266
>>197182
я с этого начинал
13.PNG2 Кб, 185x125
998 1197592
Как все это вписать в одну строку?
999 1197599
ОП расскажи пожалуйста, что значит в вакансии знание REST API
1000 1197608
>>197599
Ты должен знать правила работы серверной части в веб приложениях и веб сервисах. Где клиент запрашивает не страницы как это происходит в обычных веб сайтах, а идет чисто технический обмен данными.
1001 1197610
>>197599
Основные отличия это формат ответа и авторизация.

Обычно в ответ приходит json, jsonp или xml. Авторизация не всегда на основе кукисов а чаще на основе токенов.
1002 1197643
>>197599

Изучи статью википедии про принципы REST, и разбери пару примеров API, например API Яндекс Диска и API Youtube. Этого хватит.
1003 1198151
Здраститя, с платиновым вопросом к вам можно? Подскажите, за какой срок жс-макаке можно освоить пхп и какой-нибудь фреймворк до уровня уметь хоть что-то?
1004 1198160
>>198151
За какой срок макака освоила js? Макаке еще нужно освоить SQL лучше MySQL
1005 1198161
>>198160
Макака освоила месяца за 4, но тогда в погромировании никаких знаний не было от слова совсем.

> Макаке еще нужно освоить SQL


Казалось, что это просто. На самом деле нет?
image.png423 Кб, 1038x873
1006 1198176
>>198161
В основном да, но бывают сложности.
1007 1198177
>>198160
JS пипец сложный. Я чот вообще года два не могу в него. Хотя за плечами PHP (fullstack), Delphi, C++, Swift, даже 20 лет как мёртвый PROLOGUE, даже руби. А работаю я C# макакой! А вот JS не могу. Какой-то он нелогичный весь. Вот не поддаётся он анализу. Смотрю на код макакенов, вижу прямо лютый говнокод. А им норм. Даже какие-то конференции устраивают дже хвастают друг перед другом. Вообще не могу понять этот движ. Для меня те кто освоил JS - вообще не люди, это какие-то эльфы сверхразумы.
1008 1198178
>>198177
JS выглядит не так ровно как код других языков. А еще объект это функция и класс и конструктор объектов. Наследование через анал жирафа.

Но когда я вкатился в js я понял что на нем мне писать удобней и быстрей чем на чем-то другом. С++, С#, php, sql, верстка кун
1009 1198180
>>198177
с шарпов то на js конечно тяжко. Сложно понять где что как.
1010 1198183
>>198178
>>198180
У меня ступор. ПРЯМ СТУПОР И ПАРАЛИЧЬ наступает когда
var x=4;
var y=2;
z=x+y;
c=x-y;
И ТУТ ТАКОЙ z=42,c =2;
WAAAAAAAAAAAAAAT
1011 1198185
>>198183
Ну так привык же к строгой типизации
1012 1198186
>>198185
Настолько строгая, что JS не может int от String отличить.
1013 1198187
>>198183
У него есть некоторое количество роялей в шкафу, которые нужно просто держать в голове и все проверять, когда появляется вероятность этого рояля.
1014 1198188
>>198186
А откуда он знает "4" число это или символ и что тебе надо.

Просто надо читануть как что и во что конвертируется автоматом.
1015 1198190
>>198176
Ух ты, какой замечательный хурр дурр!
1016 1198191
>>198176
8 джойнов. Вспомнил как меня Админ центробанка хотел отпиздить за применение 3 джойнов в 2008 году. Потому-что серваки нагружаю. А база там с миллиардами записей.
1017 1198195
>>198191
ну это запрос для магаза с посещямостью 100 человек в день
1018 1198198
>>198195
Ну ты помни что такое возможно. Сегодня ты магаз делаешь, а зватра положил финансовую систему области.
1019 1198200
>>198198
Да я в курсе. Когда работаешь в системе финансовой области и получаешь в разы больше денег, так что можешь спокойно втулить в несколько раз больше таблиц и делать еще кучу всякой сложной херни для оптимизации.
451-880 https://github.com/levneedscoffee/Student-List ОП 1020 1198353
>>183323

Сразу же замечание по интерфейсу - плохо смешивать в интерфейсе 2 разных языка (русский и английский), это выглядит, как будто проект начали переводить, но не доделали. Лучше все делать на одном языке.

В httpd.conf желательно было добавить комментарии, указывающие, что там надо поменять.

В репозиторий не надо добавлять config.json, так как он у каждого члена команды разный, они будут перезаписывать конфиги друг друга и потому этот файл надо убрать из репозитория и добавить в .gitignore. Понятно, что ты делаешь проект один, но полезно учиться работать в команде. А так, даже если кто-то тебе пулл-реквест захочет с исправлениями предложить, он твой config.json перезапишет своим.

path в конфиге можно было не указывать, так как путь к папке со скриптом легко определить по php-константе __DIR__.

В базе данных нужно соблюдать единый стиль наименования полей. У тебя student_id и groupNum написаны в разном стиле. Да и не стоило сокращать, пиши лучше groupNumber.

В таблице желательно использовать комментарии, например, в поле password желательно указать, что там хранится, какой вид хеша.

composer.lock не надо добавлять в gitignore для приложений. Его лучше добавить в репозиторий. Он содержит точные версии библиотек, которые использует разработчик и которые гарантированно работают. Соответственно тот, кто разворачивает проект, установит эти проверенные версии.

> ini_set('display_errors', 1);


Это лучше бы не писать в коде, так как эта настройка должна быть отключена на продакшене. Ее лучше задавать в php.ini

> $string = file_get_contents('/var/www/project/config.json');


Тут лучше не прописывать путь, а использовать __DIR__ .

У тебя в коде во многих местах прописан этот путь и из-за этого твой проект нельзя развернуть в другой папке. Это очень неудобно. Вместо того, чтобы 20 раз прописывать путь, его нужно было определить в boostrap-скрипте, загрузить по нему конфиги и передать в те классы, которым путь или конфиг нужен.

> "StudentList\\Controllers\\": "app/controllers/",


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

> https://github.com/levneedscoffee/Student-List/blob/master/app/controllers/FrontController.php


> $uriControllerName = explode("?",$uri)[0];



Лучше использовать parse_url для этого.

> if(!empty($_SERVER['REQUEST_URI'])){


> $uri = trim($_SERVER['REQUEST_URI'], '/');


> }


Зачем тут !empty? Если этого элемента нет, то у тебя не будет создана переменная $uri и дальше пойдут ошибки.

> if(file_exists($path)){


> include_once($path);


> }else{


> FrontController::http404();


> }


> $controllerName= 'StudentList\\Controllers\\'.$controllerName;


Ты тут при ошибке 404 выдаешь заголовок 404, но не завершаешь на этом скрипт, а продолжаешь выполнять.

> https://github.com/levneedscoffee/Student-List/blob/master/app/controllers/MainController.php


> const CONTROLLER_VIEW = 'mainView.html';


Нет особого смысла использовать тут константу.

> private function pagination($pageNum, $search, $sort)


Имена функций принято начинать с глагола, сделайЧтоТо().

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

А так, у тебя в контроллере какие-то непонятные массивы куда-то передаются и преобразуются и тяжело в этом разбираться. Код должен быть простой, например:

пагинатор = создатьПагинатор();
студенты = сервисСтудентов->найтиВсехСтудентов(страница);

и так далее. Без оперирования сложными массивами с непонятными полями.

> $values = $paginator->returnPageValues($pageNum, $search, $sort);


Плохое название для переменной, так как values ничего не значит. Любая переменная хранит какое-то значение.

> $this->wrapSearchStr($val, $search);


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

> "arr" => $val["arr"],


Непонятно, что значит val, и что значит arr. Переменным и полям надо давать понятные названия, чтобы код было легко читать.

> https://github.com/levneedscoffee/Student-List/blob/master/app/services/Paginator.php



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

> $db = new StudentDataGateway(new DatabaseMySql());


Зависимости лучше внедрять с использованием DI: https://github.com/codedokode/pasta/blob/master/arch/di.md

Тем более, что у тебя там подключен pimple.

> returnIterableArr


Лучше было назвать getAllPageNumbers() или getVisiblePageNumbers().

Вместо 0 логичнее возвращать пустой массив.

> public function returnPageValues($page, $search=null, $sort = null)


У результатов функций и их аргументов надо расставлять тайп-хинты: http://php.net/manual/ru/functions.arguments.php#functions.arguments.type-declaration

Они делают код понятнее и защищают от ошибок.

https://github.com/levneedscoffee/Student-List/blob/master/app/controllers/Controller.php#L22
Плохо, что твиг-функция сама что-то берет из $_GET. Если смотреть на место вызова, это ведь не очевидно, что она может откуда-то сама брать данные. Не надо так делать, все, что нужно функции, лучше передавать ей явно.

https://github.com/levneedscoffee/Student-List/blob/master/app/controllers/EditController.php#L33
Здесь после отправки заголовка для редиректа выполнение скрипта продолжается зачем-то.

> $val->validate($studentObject, $userEmail);


> $errors = $val->returnErrors();



Во многих случаях значения лучше сразу возвращать через return, а не таким косвенным образом. Это делает код более надежным и не позволяет вызвать методы в неправильном порядке (не позволяет вызвать returnErrors до валидации, например).

Если надо вернуть несколько значений, то тут есть варианты:

- вернуть нумерованный массив: list($errors, $values) = validate(....);
- вернуть ассоциативный массив
- вернуть объект с несколькими полями или методами
- сделать отдельно метод преобразования значений, а отдельно метод валидации

Еще, плохо что ты вызываешь рендеринг одного и того же шаблона, передавая туда разные наборы переменных. Как можно надежно писать код, если ты не знаешь, будет такая переменная передана или нет?

Удалять пользователя при смене email - плохая идея. В дальнейшем могут появляться новые таблицы, которые ссылаются на таблицу пользователей. При смене email эти связи у тебя будут потеряны. Также, если в таблицу добавить поля, которых нет в форме, то они тоже будут потеряны при смене email. Лучше использовать id в качестве идентификатора.

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

Редактирование лучше делать не созданием нового объекта, а загрузкой объекта из БД, изменением его полей и сохранением в БД - так надежнее. Например, если в объекте есть поля, которых нет в форме, то их значения не потеряются.

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

https://github.com/levneedscoffee/Student-List/blob/master/app/entity/User.php

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

https://github.com/levneedscoffee/Student-List/blob/master/app/models/DataInterface.php
В таких случаях надо писать комментарии, так как непонятно, зачем этот интерфейс и какой характеристике класса он соответствует.
451-880 https://github.com/levneedscoffee/Student-List ОП 1020 1198353
>>183323

Сразу же замечание по интерфейсу - плохо смешивать в интерфейсе 2 разных языка (русский и английский), это выглядит, как будто проект начали переводить, но не доделали. Лучше все делать на одном языке.

В httpd.conf желательно было добавить комментарии, указывающие, что там надо поменять.

В репозиторий не надо добавлять config.json, так как он у каждого члена команды разный, они будут перезаписывать конфиги друг друга и потому этот файл надо убрать из репозитория и добавить в .gitignore. Понятно, что ты делаешь проект один, но полезно учиться работать в команде. А так, даже если кто-то тебе пулл-реквест захочет с исправлениями предложить, он твой config.json перезапишет своим.

path в конфиге можно было не указывать, так как путь к папке со скриптом легко определить по php-константе __DIR__.

В базе данных нужно соблюдать единый стиль наименования полей. У тебя student_id и groupNum написаны в разном стиле. Да и не стоило сокращать, пиши лучше groupNumber.

В таблице желательно использовать комментарии, например, в поле password желательно указать, что там хранится, какой вид хеша.

composer.lock не надо добавлять в gitignore для приложений. Его лучше добавить в репозиторий. Он содержит точные версии библиотек, которые использует разработчик и которые гарантированно работают. Соответственно тот, кто разворачивает проект, установит эти проверенные версии.

> ini_set('display_errors', 1);


Это лучше бы не писать в коде, так как эта настройка должна быть отключена на продакшене. Ее лучше задавать в php.ini

> $string = file_get_contents('/var/www/project/config.json');


Тут лучше не прописывать путь, а использовать __DIR__ .

У тебя в коде во многих местах прописан этот путь и из-за этого твой проект нельзя развернуть в другой папке. Это очень неудобно. Вместо того, чтобы 20 раз прописывать путь, его нужно было определить в boostrap-скрипте, загрузить по нему конфиги и передать в те классы, которым путь или конфиг нужен.

> "StudentList\\Controllers\\": "app/controllers/",


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

> https://github.com/levneedscoffee/Student-List/blob/master/app/controllers/FrontController.php


> $uriControllerName = explode("?",$uri)[0];



Лучше использовать parse_url для этого.

> if(!empty($_SERVER['REQUEST_URI'])){


> $uri = trim($_SERVER['REQUEST_URI'], '/');


> }


Зачем тут !empty? Если этого элемента нет, то у тебя не будет создана переменная $uri и дальше пойдут ошибки.

> if(file_exists($path)){


> include_once($path);


> }else{


> FrontController::http404();


> }


> $controllerName= 'StudentList\\Controllers\\'.$controllerName;


Ты тут при ошибке 404 выдаешь заголовок 404, но не завершаешь на этом скрипт, а продолжаешь выполнять.

> https://github.com/levneedscoffee/Student-List/blob/master/app/controllers/MainController.php


> const CONTROLLER_VIEW = 'mainView.html';


Нет особого смысла использовать тут константу.

> private function pagination($pageNum, $search, $sort)


Имена функций принято начинать с глагола, сделайЧтоТо().

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

А так, у тебя в контроллере какие-то непонятные массивы куда-то передаются и преобразуются и тяжело в этом разбираться. Код должен быть простой, например:

пагинатор = создатьПагинатор();
студенты = сервисСтудентов->найтиВсехСтудентов(страница);

и так далее. Без оперирования сложными массивами с непонятными полями.

> $values = $paginator->returnPageValues($pageNum, $search, $sort);


Плохое название для переменной, так как values ничего не значит. Любая переменная хранит какое-то значение.

> $this->wrapSearchStr($val, $search);


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

> "arr" => $val["arr"],


Непонятно, что значит val, и что значит arr. Переменным и полям надо давать понятные названия, чтобы код было легко читать.

> https://github.com/levneedscoffee/Student-List/blob/master/app/services/Paginator.php



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

> $db = new StudentDataGateway(new DatabaseMySql());


Зависимости лучше внедрять с использованием DI: https://github.com/codedokode/pasta/blob/master/arch/di.md

Тем более, что у тебя там подключен pimple.

> returnIterableArr


Лучше было назвать getAllPageNumbers() или getVisiblePageNumbers().

Вместо 0 логичнее возвращать пустой массив.

> public function returnPageValues($page, $search=null, $sort = null)


У результатов функций и их аргументов надо расставлять тайп-хинты: http://php.net/manual/ru/functions.arguments.php#functions.arguments.type-declaration

Они делают код понятнее и защищают от ошибок.

https://github.com/levneedscoffee/Student-List/blob/master/app/controllers/Controller.php#L22
Плохо, что твиг-функция сама что-то берет из $_GET. Если смотреть на место вызова, это ведь не очевидно, что она может откуда-то сама брать данные. Не надо так делать, все, что нужно функции, лучше передавать ей явно.

https://github.com/levneedscoffee/Student-List/blob/master/app/controllers/EditController.php#L33
Здесь после отправки заголовка для редиректа выполнение скрипта продолжается зачем-то.

> $val->validate($studentObject, $userEmail);


> $errors = $val->returnErrors();



Во многих случаях значения лучше сразу возвращать через return, а не таким косвенным образом. Это делает код более надежным и не позволяет вызвать методы в неправильном порядке (не позволяет вызвать returnErrors до валидации, например).

Если надо вернуть несколько значений, то тут есть варианты:

- вернуть нумерованный массив: list($errors, $values) = validate(....);
- вернуть ассоциативный массив
- вернуть объект с несколькими полями или методами
- сделать отдельно метод преобразования значений, а отдельно метод валидации

Еще, плохо что ты вызываешь рендеринг одного и того же шаблона, передавая туда разные наборы переменных. Как можно надежно писать код, если ты не знаешь, будет такая переменная передана или нет?

Удалять пользователя при смене email - плохая идея. В дальнейшем могут появляться новые таблицы, которые ссылаются на таблицу пользователей. При смене email эти связи у тебя будут потеряны. Также, если в таблицу добавить поля, которых нет в форме, то они тоже будут потеряны при смене email. Лучше использовать id в качестве идентификатора.

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

Редактирование лучше делать не созданием нового объекта, а загрузкой объекта из БД, изменением его полей и сохранением в БД - так надежнее. Например, если в объекте есть поля, которых нет в форме, то их значения не потеряются.

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

https://github.com/levneedscoffee/Student-List/blob/master/app/entity/User.php

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

https://github.com/levneedscoffee/Student-List/blob/master/app/models/DataInterface.php
В таких случаях надо писать комментарии, так как непонятно, зачем этот интерфейс и какой характеристике класса он соответствует.
https://github.com/levneedscoffee/Student-List ОП 1021 1198354
>>183323

https://github.com/levneedscoffee/Student-List/blob/master/app/models/DatabaseMySql.php
У тебя во многих местах идет чтение JSON конфига. Это дублирование кода и это надо вынести отдельно. Удобнее всего применить здесь DI и требовать передавать параметры соединения в класс DatabaseMySql. Хотя тогда становится непонятно, зачем он вообще нужен.

> } catch (\PDOException $e) {


> echo "Connection failed: " . $e->getMessage();


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

> https://github.com/levneedscoffee/Student-List/blob/master/app/models/StudentDataGateway.php


> public function __construct(DataInterface $obj)


Почему не передавать сюда сразу объект PDO? Зачем класс-посредник?

https://github.com/levneedscoffee/Student-List/blob/master/app/models/StudentDataGateway.php#L23

> $stmt = $this->pdo->query('SELECT * FROM students ORDER by '.$sort.' LIMIT '.$page.','.$limit);


Нет защиты от SQL инъекции.

> return $stmt->fetch()[0];


Есть метод в PDO для получения только одного значения.

https://github.com/levneedscoffee/Student-List/blob/master/app/services/Security.php#L18

> if(isset($_COOKIE['token']) && isset($_POST['token']) && $_COOKIE['token'] === $_POST['token']){


Если кука есть, но пустая (''), и в форме пустой токен, то проверка пройдет. Проверка не должна срабатывать, если токены пустые.

> if (!preg_match("/^[А-ЯЁA-Z][-а-яёa-zА-ЯЁA-Z\\s]{1,".$strLength."}$/u", $name)) {


Вместо подстановки переменной в регулярку было бы лучше просто проверить длину через mb_strlen. А то появляется вопрос, а нет ли тут возможности инъекции произвольного выражения в регулярку и не создаст ли это новой уязвимости?

> public function validateEmail($email)


В email до знака @ может встретиться намного больше символов, например: минус, плюс, процент.

Статьи по теме валидации email:

- https://habr.com/post/274985/
- https://habr.com/post/55820/

Зачастую проще проверять email по упрощенной модели:

- есть знак @
- нет пробелов
- есть точка справа, и вокруг точки есть хотя бы еще 1 символ (технически домен в email может быть и без точки, но такие домены не доступны в глобальном интернете, а только во внутренних сетях)

Вроде как такая модель используется в браузере для поля с типом email.

> const MAX_points = 300;


Константы пишут большими буквами.

> const MIN_BIRTHDAY = 1985-01-01;


Дискриминация по возрасту

> https://github.com/levneedscoffee/Student-List/blob/master/app/view/mainView.html


> <td>{{ row.name|raw }}</td>


Что с защитой от XSS? Ты ведь отключил экранирование.

https://github.com/levneedscoffee/Student-List/blob/master/app/view/editView.html
Тут желательно настроить HTML5 валидацию для проверки данных до отправки.

> <input class="form-control" type="text" name="email"


В HTML5 есть тип поля email. Изучи типы полей input в HTML5.

https://github.com/levneedscoffee/Student-List/blob/master/app/view/registerView.html
По яваскрипт-коду:

- на время отправки запроса желательно блокировать форму или кнопку отправки
- перед отправкой запроса стоит очистить поле с информацией об ошибках, так как оно более неактуально и может сбить с толку пользователя
- желательно показать, что идет отправка запроса

Про это написано в моем уроке про использование аякса: https://github.com/codedokode/pasta/blob/master/js/ajax.md

Так, вообще, сделано хорошо для первого раза, но код, конечно, стоит доработать.
https://github.com/levneedscoffee/Student-List ОП 1021 1198354
>>183323

https://github.com/levneedscoffee/Student-List/blob/master/app/models/DatabaseMySql.php
У тебя во многих местах идет чтение JSON конфига. Это дублирование кода и это надо вынести отдельно. Удобнее всего применить здесь DI и требовать передавать параметры соединения в класс DatabaseMySql. Хотя тогда становится непонятно, зачем он вообще нужен.

> } catch (\PDOException $e) {


> echo "Connection failed: " . $e->getMessage();


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

> https://github.com/levneedscoffee/Student-List/blob/master/app/models/StudentDataGateway.php


> public function __construct(DataInterface $obj)


Почему не передавать сюда сразу объект PDO? Зачем класс-посредник?

https://github.com/levneedscoffee/Student-List/blob/master/app/models/StudentDataGateway.php#L23

> $stmt = $this->pdo->query('SELECT * FROM students ORDER by '.$sort.' LIMIT '.$page.','.$limit);


Нет защиты от SQL инъекции.

> return $stmt->fetch()[0];


Есть метод в PDO для получения только одного значения.

https://github.com/levneedscoffee/Student-List/blob/master/app/services/Security.php#L18

> if(isset($_COOKIE['token']) && isset($_POST['token']) && $_COOKIE['token'] === $_POST['token']){


Если кука есть, но пустая (''), и в форме пустой токен, то проверка пройдет. Проверка не должна срабатывать, если токены пустые.

> if (!preg_match("/^[А-ЯЁA-Z][-а-яёa-zА-ЯЁA-Z\\s]{1,".$strLength."}$/u", $name)) {


Вместо подстановки переменной в регулярку было бы лучше просто проверить длину через mb_strlen. А то появляется вопрос, а нет ли тут возможности инъекции произвольного выражения в регулярку и не создаст ли это новой уязвимости?

> public function validateEmail($email)


В email до знака @ может встретиться намного больше символов, например: минус, плюс, процент.

Статьи по теме валидации email:

- https://habr.com/post/274985/
- https://habr.com/post/55820/

Зачастую проще проверять email по упрощенной модели:

- есть знак @
- нет пробелов
- есть точка справа, и вокруг точки есть хотя бы еще 1 символ (технически домен в email может быть и без точки, но такие домены не доступны в глобальном интернете, а только во внутренних сетях)

Вроде как такая модель используется в браузере для поля с типом email.

> const MAX_points = 300;


Константы пишут большими буквами.

> const MIN_BIRTHDAY = 1985-01-01;


Дискриминация по возрасту

> https://github.com/levneedscoffee/Student-List/blob/master/app/view/mainView.html


> <td>{{ row.name|raw }}</td>


Что с защитой от XSS? Ты ведь отключил экранирование.

https://github.com/levneedscoffee/Student-List/blob/master/app/view/editView.html
Тут желательно настроить HTML5 валидацию для проверки данных до отправки.

> <input class="form-control" type="text" name="email"


В HTML5 есть тип поля email. Изучи типы полей input в HTML5.

https://github.com/levneedscoffee/Student-List/blob/master/app/view/registerView.html
По яваскрипт-коду:

- на время отправки запроса желательно блокировать форму или кнопку отправки
- перед отправкой запроса стоит очистить поле с информацией об ошибках, так как оно более неактуально и может сбить с толку пользователя
- желательно показать, что идет отправка запроса

Про это написано в моем уроке про использование аякса: https://github.com/codedokode/pasta/blob/master/js/ajax.md

Так, вообще, сделано хорошо для первого раза, но код, конечно, стоит доработать.
ОП 1022 1198355
>>184543

Мне тоже непонятно. думаю, что особо нет смысла. В JS в новых браузерах есть FormData для отправки данных форм аяксом, и туда можно прикладывать файлы.

>>185260

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

БД и сервер очередей выполняют разные задачи. БД - хранит данные. Сервер очередей - уведомляет о появлении новой задачи в БД.

>>185334

Думаю, надо залезть в настройки форматирования и поправить их.

>>185854

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

В этом плане конечно из-под веб скрипта лучше длительные процессы не запускать.

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

Плюс, в случае с очередью задач ты можешь сделать систему распределенной - на одном сервере обслуживать запросы, на другом - выполнять фоновые задачи. Масштабирование!

> Читал про '&' что процесс открывется в том же треде что и сам инстанс php


Это неправда.

>>186007

А подумай, какую информацию ты хотел бы хранить о файле.

>>186281

Не знаю. Ищи какие-то отличительные признаки.
ОП 1022 1198355
>>184543

Мне тоже непонятно. думаю, что особо нет смысла. В JS в новых браузерах есть FormData для отправки данных форм аяксом, и туда можно прикладывать файлы.

>>185260

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

БД и сервер очередей выполняют разные задачи. БД - хранит данные. Сервер очередей - уведомляет о появлении новой задачи в БД.

>>185334

Думаю, надо залезть в настройки форматирования и поправить их.

>>185854

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

В этом плане конечно из-под веб скрипта лучше длительные процессы не запускать.

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

Плюс, в случае с очередью задач ты можешь сделать систему распределенной - на одном сервере обслуживать запросы, на другом - выполнять фоновые задачи. Масштабирование!

> Читал про '&' что процесс открывется в том же треде что и сам инстанс php


Это неправда.

>>186007

А подумай, какую информацию ты хотел бы хранить о файле.

>>186281

Не знаю. Ищи какие-то отличительные признаки.
ОП 1023 1198356
>>186686

Надо смотреть документацию по созданию тем.

>>186941

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

>>187366

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

Только используй mb-функции, так как strlen не работает с кириллицей.

>>187491

Если у тебя маленькая посещаемость, то можно фигачить все прямо в базу. Если большая то почитай статью от мейл ру https://habr.com/company/mailru/blog/206494/ (текст куда-то потерялся, копия: http://savepearlharbor.com/?p=206494 )

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

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

> каждый раз ставить таск с дилеем, скажем, в 5 минут, который собирает просмотры из редиса и заносит в бд. Если таск стоит в очереди, то не ставим


Имхо проще использовать крон.

>>187793
>>196705

> return mb_strtoupper(mb_substr($text, 0, 1, 'UTF-8'), 'UTF-8') . mb_substr(mb_convert_case($text, MB_CASE_LOWER, 'UTF-8'), 1, mb_strlen($text), 'UTF-8');


Очень длинно и тяжело читать, надо вынести часть выражения в переменные и разбить на несколько действий.

Сделано верно.
ОП 1023 1198356
>>186686

Надо смотреть документацию по созданию тем.

>>186941

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

>>187366

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

Только используй mb-функции, так как strlen не работает с кириллицей.

>>187491

Если у тебя маленькая посещаемость, то можно фигачить все прямо в базу. Если большая то почитай статью от мейл ру https://habr.com/company/mailru/blog/206494/ (текст куда-то потерялся, копия: http://savepearlharbor.com/?p=206494 )

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

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

> каждый раз ставить таск с дилеем, скажем, в 5 минут, который собирает просмотры из редиса и заносит в бд. Если таск стоит в очереди, то не ставим


Имхо проще использовать крон.

>>187793
>>196705

> return mb_strtoupper(mb_substr($text, 0, 1, 'UTF-8'), 'UTF-8') . mb_substr(mb_convert_case($text, MB_CASE_LOWER, 'UTF-8'), 1, mb_strlen($text), 'UTF-8');


Очень длинно и тяжело читать, надо вынести часть выражения в переменные и разбить на несколько действий.

Сделано верно.
ОП 1024 1198357
>>188193

Сравнение дробных чисел делается путем их вычитания и сравнения разницы с малым числом:

function isEqual(a, b)
{
var diff = Math.abs(a - b);
var epsilon = ...; // маленькое число
return diff < epsilon;
}

Как выбрать epsilon? Зависит от ситуации. Если ты сравниваешь вес товаров, можно взять например 1 грамм. Если напряжение - берешь с учетом погрешности вольтметра.

В общем случае, epsilon вычисляется исходя из самих чисел и известной погрешности формата float. Этой теме посвящен отдельный сайт: http://floating-point-gui.de/errors/comparison/

> Вопрос был в том числе "Как бороться?" :) Ответа я не нашел.


Использовать правильные алгоритмы сравнения чисел с учетом погрешности. То есть надо понимать, что точно хранятся только первые N знаков числа и исходить из этого.

> В голову приходит только превратить обе части в строки и сравнить их. Но тут тоже могут быть какие-нибудь подводные камни.


Это никак не решает проблему так как в этом случае '1.99999999' != '2'.

>>188215

> ОК. А как это обходят в ЯП? Используют округление от нуля?



В ЯП применяется округление по тем правилам, которые заданы в языке. То есть см. мануал.

> Можно поподробнее, пожалуйста?


Да, можно хранить деньги как int в копейках или сотых копейки. То есть 3 рубля = 30000 сотых копейки. Преобразовывать туда-обратно.

Если использовать float, у тебя балансы не будут сходиться.
ОП 1024 1198357
>>188193

Сравнение дробных чисел делается путем их вычитания и сравнения разницы с малым числом:

function isEqual(a, b)
{
var diff = Math.abs(a - b);
var epsilon = ...; // маленькое число
return diff < epsilon;
}

Как выбрать epsilon? Зависит от ситуации. Если ты сравниваешь вес товаров, можно взять например 1 грамм. Если напряжение - берешь с учетом погрешности вольтметра.

В общем случае, epsilon вычисляется исходя из самих чисел и известной погрешности формата float. Этой теме посвящен отдельный сайт: http://floating-point-gui.de/errors/comparison/

> Вопрос был в том числе "Как бороться?" :) Ответа я не нашел.


Использовать правильные алгоритмы сравнения чисел с учетом погрешности. То есть надо понимать, что точно хранятся только первые N знаков числа и исходить из этого.

> В голову приходит только превратить обе части в строки и сравнить их. Но тут тоже могут быть какие-нибудь подводные камни.


Это никак не решает проблему так как в этом случае '1.99999999' != '2'.

>>188215

> ОК. А как это обходят в ЯП? Используют округление от нуля?



В ЯП применяется округление по тем правилам, которые заданы в языке. То есть см. мануал.

> Можно поподробнее, пожалуйста?


Да, можно хранить деньги как int в копейках или сотых копейки. То есть 3 рубля = 30000 сотых копейки. Преобразовывать туда-обратно.

Если использовать float, у тебя балансы не будут сходиться.
1025 1198358
>>188051

Да, верно.

>>188255

Ты переусложнил. Ты мог бы сделать объект "коллекция вопросов", QuestionsCollection, но я не вижу особого смысла его делать, когда можно просто взять массив.

Ни фабрика, ни "приспособленец" не имеют к этому отношения и предназначены для других целей.

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

>>188528

> Формы симфони мне только дадут возможность использовать HTML5 валидацию, а как насчёт более сложных случаем?


Надо искать или писать библиотеку, конвертирующую правила Симфони в правила для JS-валидатора. Задача нетривиальная, так как даже диалекты регулярок в JS и PHP в мелочах различаются.

Варианты реализации разные. Давай начнем с самой формулировки задачи:

- есть форма редактирования теста
- надо на клиенте динамически добавлять и удалять вопросы
- надо переставлять вопросы местами
- надо менять тип вопросов, в зависимости от типа там доступны разные поля
- надо добавлять и удалять варианты вопросов
- в идеале еще и валидировать на клиенте

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

Переключение типов вопросов можно сделать по аналогии с табами - просто сделать несколько форм, но показывать только одну.

Получается такая огромная форма, которую можно модицифировать динамически.

При желании можно добавить сохранение по таймеру на сервер, и аякс-отправку данных для валидации без перезагрузки страницы.

Второй вариант - делать мини-приложение (мини-SPA) для редактирования теста. Выбор богатый: Angular, knockout, React, vue.js. Скорее всего, получится решение потяжелее и посложнее, но зато будет больше возможностей. В соответствие с идеологией MVC ты делаешь модель данных, которая хранит информацию о редактируемом тесте, и с помощью view отображаешь эту модель на странице в виде формы. При изменениях в форме ты меняешь модель данных и view обновляет представление теста на экране.

В такой схеме ты можешь писать как клиентскую валидацию для модели данных, так и аякс-валидацию через отправку модели на сервер. Ну и опять же, периодическое сохранение тоже можно прикрутить.
1025 1198358
>>188051

Да, верно.

>>188255

Ты переусложнил. Ты мог бы сделать объект "коллекция вопросов", QuestionsCollection, но я не вижу особого смысла его делать, когда можно просто взять массив.

Ни фабрика, ни "приспособленец" не имеют к этому отношения и предназначены для других целей.

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

>>188528

> Формы симфони мне только дадут возможность использовать HTML5 валидацию, а как насчёт более сложных случаем?


Надо искать или писать библиотеку, конвертирующую правила Симфони в правила для JS-валидатора. Задача нетривиальная, так как даже диалекты регулярок в JS и PHP в мелочах различаются.

Варианты реализации разные. Давай начнем с самой формулировки задачи:

- есть форма редактирования теста
- надо на клиенте динамически добавлять и удалять вопросы
- надо переставлять вопросы местами
- надо менять тип вопросов, в зависимости от типа там доступны разные поля
- надо добавлять и удалять варианты вопросов
- в идеале еще и валидировать на клиенте

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

Переключение типов вопросов можно сделать по аналогии с табами - просто сделать несколько форм, но показывать только одну.

Получается такая огромная форма, которую можно модицифировать динамически.

При желании можно добавить сохранение по таймеру на сервер, и аякс-отправку данных для валидации без перезагрузки страницы.

Второй вариант - делать мини-приложение (мини-SPA) для редактирования теста. Выбор богатый: Angular, knockout, React, vue.js. Скорее всего, получится решение потяжелее и посложнее, но зато будет больше возможностей. В соответствие с идеологией MVC ты делаешь модель данных, которая хранит информацию о редактируемом тесте, и с помощью view отображаешь эту модель на странице в виде формы. При изменениях в форме ты меняешь модель данных и view обновляет представление теста на экране.

В такой схеме ты можешь писать как клиентскую валидацию для модели данных, так и аякс-валидацию через отправку модели на сервер. Ну и опять же, периодическое сохранение тоже можно прикрутить.
1026 1198359
>>190652

Что-то он древний такой...

>>190839

> https://ideone.com/vCJosI



тут можно было бы избавиться от дублирования кода в ветках if, если сделать так:

текущая выплата = меньшее из (5000, остаток долга);

По стихам - надо было случайные индексы генерировать внутри цикла, а не один раз до цикла.

> палиндром


> http://sandbox.onlinephpfunctions.com/code/1eed5a0bfc43968f61079d0dd36a84d9d66c2b2c



Много переменных с неудачными названиями. Вместо countOne лучше было написать leftLetter или letter1.

Не очень удачно, что $i начинается с -1.

>>191135

Быстро не объяснить. Обычно используют куки или сессии. Например, в куках можно хранить id пользователя и специальный код, индивидуальный для каждого пользователя, для защиты от подделки.

>>192517

Если тебя интересует механизм переключения, то он такой. Чтобы у кнопки было состояние, мы используем элементы формы - чекбоксы или радиокнопки, у которых оно есть. Скрываем их с экрана, чтобы не мешались. Поскольку кликнуть по скрытому элементу трудно, то добавляем лейблы (label) - тут 2 варианта:

- либо привязать label к input по id
- либо засунуть input внутрь label, тогда id не нужен и не надо следить за их уникальностью
- также есть еще вариант как-то сделать инпут прозрачным, растянуть на размер кнопки и повесить над ней, чтобы обойтись без label

label позиционируем так, чтобы его размер охватывал всю кнопку. Можно, например, кнопку как раз и сделать этим тегом.

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

.buttons input:checked + .buttons__bg { background: red; }

Вот и все.

Дальше остается только поработать с клавиатурной навигацией.
1026 1198359
>>190652

Что-то он древний такой...

>>190839

> https://ideone.com/vCJosI



тут можно было бы избавиться от дублирования кода в ветках if, если сделать так:

текущая выплата = меньшее из (5000, остаток долга);

По стихам - надо было случайные индексы генерировать внутри цикла, а не один раз до цикла.

> палиндром


> http://sandbox.onlinephpfunctions.com/code/1eed5a0bfc43968f61079d0dd36a84d9d66c2b2c



Много переменных с неудачными названиями. Вместо countOne лучше было написать leftLetter или letter1.

Не очень удачно, что $i начинается с -1.

>>191135

Быстро не объяснить. Обычно используют куки или сессии. Например, в куках можно хранить id пользователя и специальный код, индивидуальный для каждого пользователя, для защиты от подделки.

>>192517

Если тебя интересует механизм переключения, то он такой. Чтобы у кнопки было состояние, мы используем элементы формы - чекбоксы или радиокнопки, у которых оно есть. Скрываем их с экрана, чтобы не мешались. Поскольку кликнуть по скрытому элементу трудно, то добавляем лейблы (label) - тут 2 варианта:

- либо привязать label к input по id
- либо засунуть input внутрь label, тогда id не нужен и не надо следить за их уникальностью
- также есть еще вариант как-то сделать инпут прозрачным, растянуть на размер кнопки и повесить над ней, чтобы обойтись без label

label позиционируем так, чтобы его размер охватывал всю кнопку. Можно, например, кнопку как раз и сделать этим тегом.

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

.buttons input:checked + .buttons__bg { background: red; }

Вот и все.

Дальше остается только поработать с клавиатурной навигацией.
1027 1198360
>>193402

Это вопросы к администрации учреждения.

>>193839

http://twig-extensions.readthedocs.io/en/latest/text.html - это не годится? Если нет, то писать функцию для Твига самому (в Твиг можно добавлять функции).

>>193882

Без u PCRE думает, что буквы занимают ровно 1 байт и воспринимают 1 букву кириллицы как 2 обычные недобуквы. И от этого все ломается. Например, [аб] воспринимается как набор из 4 недобукв [а1а2б1б2] (а1 и а2 - это обозначение байтов, которыми кодируется буква "а") и совпадает со всем попало.

\w вообще без флага u кириллицу может не видеть (еще бы, если она занимает 2 байта, а \w ищет один).
14117756309560.jpg96 Кб, 500x732
1028 1198366
Давайте рассмотрим ситуацию в вакууме.

Допустим есть посты. У постов есть всякие стандартные атрибуты как id, author_id, time, body и т д.

Далее у постов могут быть картинки, допустим как на дваче, до 8 картинок к посту. Картинки лежат соответственно в отдельной таблице и там id, post_id, file_name например.

Далее есть теги, теги тоже лежат в отдельной таблице: id, tag_name
Ну и так как тегов у поста может быть много, и 1 тег может быть у нескольких постов, то есть еще таблица связей вида: id?, tag_id, post_id где свалка many_to_many организована.

Что бы еще такого приплести, допустим у постов есть комментарии - пусть просто нечто вроде урезанных постов без картинок и тегов, но у комментариев есть авторы, то есть в таблице с комментариями всё выглядит как-то так: id, post_id, author_id, body.

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

Но что делать, когда у нужен допустим список постов какого-нибудь автора со всей вот этой сопутствующей мишурой (теги, картинки, ответы), тут уже просто невозможно выкрутиться подобным способом: не будешь же потом в цикле для каждого поста слать по 3 дополнительных селекта? Если у тебя постов скажем много?
Как с подобными вещами работают? Как вообще с такой базой подружиться?
1029 1198376
>>198366
Для списка постов все лучше делать одним большим запросом.

Самая длительная операция - установление соединения с бд.

Вторая по длительности передача запроса и получение ответа.

Выполнение запроса базой даже с кучей джоинов, сортировок и т.д. обычно происходит быстрее.

Для каждого запроса, кроме непосредственно выборки данных бд делает парсинг текста запроса, анализ наличия индексов и кеша, определение наиболее рационального способа выборки. Уверен там дохрена еще всякого говна.
1030 1198378
>>198366
Если это высоконагруженный новостной портал, то просто делаются дополнительные таблицы, базы данных, сервера баз данных, с кешем наиболее востребованных записей.

Например первые 5 страниц постов храняться в основновной и дополнительной базе.

Связи с картинками можно вообще не хранить в базе а просто условится что картинки поста с id 382 будут лежать в папке 382 которая лежит в папке соответсвующей дате создания поста. В крайнем случае в таблице постов можно добавить поле с количеством картинок у каждого поста, чтобы знать есть ли они и сколько их.
1031 1198411
>>198376
Как подобные запросы делаются? Там картинки и прочие теги делаются подзапросом и возвращаются склеенными и просто джойнятся в итоге к основному?
>>198378

>Связи с картинками можно вообще не хранить в базе а просто условится что картинки поста с id 382 будут лежать в папке 382 которая лежит в папке соответсвующей дате создания поста.


Да, спасибо за свежую идею, да только на каком-нибудь дваче с кучей постов и малым количеством просмотров каждого вряд ли имеет смысл. На сайте где 1 новость в день и десятки тысяч просмотров - офк отлично зайдет.
1032 1198561
>>198411
Если только джоинами то инфа о кадом посте будет дублироваться для каждой картинки, и при разборе ответа чтобы преобразовать это все в объекты тебе надобудет кучу циклов городить которые для разной хуйни выбирают разные поля игнорируя те что дублируются.

Можно поиграться с GROUP BY и CONCAT попробовать вместо нескольких строк с одним и тем же постом получить одну с дополнительным поле содержащим названия картинок через запятую.

С тегами таже ситуация.
1033 1198565
>>198411
Как то мне довелось детально изучить внутреннию механику построенния запросов для связанных таблиц в yii2.

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

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

Сначала были извлечены записи постов. Затем фрейм собрал их id и выбрал все картинки которые принадлежат этим постам по условию WHERE `image`.`post_id` IN (.....).

Затем все эти картинки были перебраны в цикле и растасованы по нужным постам.

Затем точно также один запрос на все теги которые связаны только с выбранными постами.

Так же с комментами.

Почему то только сейчас вспомнил про этот вариант.
881-1033 1034 1198630
>>193959

> Под аякс запросы обычно другой метод контроллера пишут или в тот же всё летит?



Если он делает что-то другое, то конечно другой.

> в каждый <li> обернут по сути элемент из базы, в общем наверное нужно весь этот список превратить в js объект сначала?



А зачем?

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



Ну самый просто вариант - поместить список внутрь формы и сделать название каждого пункта инпутом (при желании можно через CSS оформить все так, чтобы он выглядел как обычный текст, а только при клике выглядел как инпут). При удалении добавлять в форму скрытое поле с id удаленного пункта. При добавлении - опять же, добавлять в форму новый инпут.

При нажатии кнопки "Сохранить" отправлять всю форму аяксом на сервер. Элементарно же. Желательно также подсвечивать измененные, но еще не сохраненные поля.

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

По моему, тут все реализуется на простом jQuery, без использования SPA-фреймворков.

>>193973

А что сложного в CMS? CMS это программы для разработки и управления сайтом преимущественно через админку. Иногда к этому добавляется необходисость дописывать кастомный код - "темы оформления" (шаблоны) и "плагины" (для реализации отсуствующего функционала).

Если ты в фреймворках разбираешься, ты CMS освоишь легко и быстро. Без проблем сможешь написать тему или плагин, используя документацию. Найди любой курс "как сделать сайт на CMS x" и увидишь, что там все довольно просто.

> Вон учишь цмс и хоть работа какая-никакая.



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

Алсо, ты на hh.ru заходил? Я набрал "php удаленно", выбрал "Вся Россия, без опыта", и там 30 вакансий вываливается: https://hh.ru/search/vacancy?text=php&schedule=remote&clusters=true&enable_snippets=true&experience=noExperience&from=cluster_experience

А если не ставить галочку "без опыта", то вообще 300. Плюс, можно еще на фрилансе поискать задачи.
881-1033 1034 1198630
>>193959

> Под аякс запросы обычно другой метод контроллера пишут или в тот же всё летит?



Если он делает что-то другое, то конечно другой.

> в каждый <li> обернут по сути элемент из базы, в общем наверное нужно весь этот список превратить в js объект сначала?



А зачем?

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



Ну самый просто вариант - поместить список внутрь формы и сделать название каждого пункта инпутом (при желании можно через CSS оформить все так, чтобы он выглядел как обычный текст, а только при клике выглядел как инпут). При удалении добавлять в форму скрытое поле с id удаленного пункта. При добавлении - опять же, добавлять в форму новый инпут.

При нажатии кнопки "Сохранить" отправлять всю форму аяксом на сервер. Элементарно же. Желательно также подсвечивать измененные, но еще не сохраненные поля.

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

По моему, тут все реализуется на простом jQuery, без использования SPA-фреймворков.

>>193973

А что сложного в CMS? CMS это программы для разработки и управления сайтом преимущественно через админку. Иногда к этому добавляется необходисость дописывать кастомный код - "темы оформления" (шаблоны) и "плагины" (для реализации отсуствующего функционала).

Если ты в фреймворках разбираешься, ты CMS освоишь легко и быстро. Без проблем сможешь написать тему или плагин, используя документацию. Найди любой курс "как сделать сайт на CMS x" и увидишь, что там все довольно просто.

> Вон учишь цмс и хоть работа какая-никакая.



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

Алсо, ты на hh.ru заходил? Я набрал "php удаленно", выбрал "Вся Россия, без опыта", и там 30 вакансий вываливается: https://hh.ru/search/vacancy?text=php&schedule=remote&clusters=true&enable_snippets=true&experience=noExperience&from=cluster_experience

А если не ставить галочку "без опыта", то вообще 300. Плюс, можно еще на фрилансе поискать задачи.
1035 1198631
>>193980

Тут можно без json, просто форму сделать и отправлять аяксом. Формально это соответствует поставленным требованиям.

>>194055

Изучи список вакансий и задач на фрилансе.

>>194199

Лучше всего указывать это явно, например параметром в URL. Не стоит полагаться на заголовок, так как это потом усложнит отладку. Явное (указание, что тебе нужен аякс-ответ) лучше неявного.

>>194353

Не добавляет. Это делает библиотека jQuery, например. И лучше явно указывать в URL, что тебе нужен аякс.

>>194546

Там еще есть условие, что если у обоих даблы, то это тоже ничья. В остальном верно.

>>194616

Не требуется писать $x = $i, ты можешь сразу использовать $i.

> можно ли сделать всё так, чтобы $i в условиях цикла и $i в теле цикла влияли друг на друга только в одностороннем порядке.



Нет, если я правильно понял. $i это просто обычная переменная и никакой защиты от ее изменения нету. Если ты поменяешь $i внутри цикла, это естественно повлияет на его выполнение. Потому $i стоит использовать "только для чтения", то есть не изменять ее значение внутри цикла.
1035 1198631
>>193980

Тут можно без json, просто форму сделать и отправлять аяксом. Формально это соответствует поставленным требованиям.

>>194055

Изучи список вакансий и задач на фрилансе.

>>194199

Лучше всего указывать это явно, например параметром в URL. Не стоит полагаться на заголовок, так как это потом усложнит отладку. Явное (указание, что тебе нужен аякс-ответ) лучше неявного.

>>194353

Не добавляет. Это делает библиотека jQuery, например. И лучше явно указывать в URL, что тебе нужен аякс.

>>194546

Там еще есть условие, что если у обоих даблы, то это тоже ничья. В остальном верно.

>>194616

Не требуется писать $x = $i, ты можешь сразу использовать $i.

> можно ли сделать всё так, чтобы $i в условиях цикла и $i в теле цикла влияли друг на друга только в одностороннем порядке.



Нет, если я правильно понял. $i это просто обычная переменная и никакой защиты от ее изменения нету. Если ты поменяешь $i внутри цикла, это естественно повлияет на его выполнение. Потому $i стоит использовать "только для чтения", то есть не изменять ее значение внутри цикла.
1036 1198632
>>194619

Но это усложнит понимание логики работы кода и лучше такого избегать.

>>194754

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

>>194860

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

>>194861

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

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

Давай для примера разберем какую-нибудь функцию внутреннего API для плагинов. Ну, например, wp_repote_post, которая отправляет POST-запрос: https://codex.wordpress.org/Function_Reference/wp_remote_post

Мы видим, что там активно используются массивы как аргументы и как результат функции. Хорошо, что формат этих массивов хотя бы описан в документации. Причем, функция не выбрасывет исключения, но может вместо массива вернуть объект WP_Error (а вот и объекты появились), потому после ее вызова мы должны будем сами написать проверку. К сожалению, WP_Error не реализует интерфейс Throwable и потому не может быть использован как объект-исключение в конструкции throw.

$result = wp_remote_post('https://example.com', [...]);
if (is_wp_error($result)) {
throw new \Exception($result->get_error_message());
}

$contentType = wp_remote_retrieve_header($result, 'content-type');

Вот, как это могло бы выглядеть в ООП-стиле:

$httpClient = new HttpClient();
$response = $httpClient->post('https://example.com', [...]);
$contentType = $response->headers->get('Content-Type');

Мне конечно симпатичнее второй вариант, тем более, что он дает меньше возможностей для ошибок. Ну например, ты не можешь вызывать метод $response->headers->get до выполнения запроса, так как у тебя нет объекта $response. Ну то есть само собой очевидно, что ты сначала должен сделать запрос, а потом что-то делать с результатом.

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

Если мы возьмем более классическое API, то оно документировано куда как хуже. Вот, например, древняя функция get_posts(): https://developer.wordpress.org/reference/functions/get_posts/

В документации написано, что она возвращает массив, но не описано, что в нем содержится. То есть она возвращает массив непонятно чего. Ну и много ссылок на класс WP_Query, видимо, рекомендуется использовать его.

Если мы посмотрим примеры использования в get_posts() и в WP_Query, то увидим, что они полагаются на использование глобальных переменных и глобального состояния:

// The Query
$query1 = new WP_Query( $args );

// The Loop
while ( $query1->have_posts() ) {
$query1->the_post();
echo '<li>' . get_the_title() . '</li>';
}

На мой взгляд, тут неочевидно, откуда get_the_title() берет данные. Гораздо лучше было бы

foreach ($query1->getPosts() as $post) {
echo get_the_title($post);
}

Как плюс, могу отметить, что в коде WP соблюдается определенный стиль, много комемнтариев. Есть документация. То есть при написании небольшого плагина будет вполне комфортно.
1036 1198632
>>194619

Но это усложнит понимание логики работы кода и лучше такого избегать.

>>194754

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

>>194860

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

>>194861

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

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

Давай для примера разберем какую-нибудь функцию внутреннего API для плагинов. Ну, например, wp_repote_post, которая отправляет POST-запрос: https://codex.wordpress.org/Function_Reference/wp_remote_post

Мы видим, что там активно используются массивы как аргументы и как результат функции. Хорошо, что формат этих массивов хотя бы описан в документации. Причем, функция не выбрасывет исключения, но может вместо массива вернуть объект WP_Error (а вот и объекты появились), потому после ее вызова мы должны будем сами написать проверку. К сожалению, WP_Error не реализует интерфейс Throwable и потому не может быть использован как объект-исключение в конструкции throw.

$result = wp_remote_post('https://example.com', [...]);
if (is_wp_error($result)) {
throw new \Exception($result->get_error_message());
}

$contentType = wp_remote_retrieve_header($result, 'content-type');

Вот, как это могло бы выглядеть в ООП-стиле:

$httpClient = new HttpClient();
$response = $httpClient->post('https://example.com', [...]);
$contentType = $response->headers->get('Content-Type');

Мне конечно симпатичнее второй вариант, тем более, что он дает меньше возможностей для ошибок. Ну например, ты не можешь вызывать метод $response->headers->get до выполнения запроса, так как у тебя нет объекта $response. Ну то есть само собой очевидно, что ты сначала должен сделать запрос, а потом что-то делать с результатом.

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

Если мы возьмем более классическое API, то оно документировано куда как хуже. Вот, например, древняя функция get_posts(): https://developer.wordpress.org/reference/functions/get_posts/

В документации написано, что она возвращает массив, но не описано, что в нем содержится. То есть она возвращает массив непонятно чего. Ну и много ссылок на класс WP_Query, видимо, рекомендуется использовать его.

Если мы посмотрим примеры использования в get_posts() и в WP_Query, то увидим, что они полагаются на использование глобальных переменных и глобального состояния:

// The Query
$query1 = new WP_Query( $args );

// The Loop
while ( $query1->have_posts() ) {
$query1->the_post();
echo '<li>' . get_the_title() . '</li>';
}

На мой взгляд, тут неочевидно, откуда get_the_title() берет данные. Гораздо лучше было бы

foreach ($query1->getPosts() as $post) {
echo get_the_title($post);
}

Как плюс, могу отметить, что в коде WP соблюдается определенный стиль, много комемнтариев. Есть документация. То есть при написании небольшого плагина будет вполне комфортно.
1037 1198633
>>195447

Зависит от веб-сервера. В Апаче это делается с помощью mod_rewrite, в нгинксе с помощью указания в конфиге правил роутинга, в встроенном в PHP веб-сервере - с помощью роутинг-скрипта.

>>195721

Ответ должен быть 61270. Скорее всего, проблема в этой лишней строке

$credit = $credit * $percent;

>>196298

А что именно непонятно? Оно наверно предполагает наличие каких-то начальных знаний.

Вот например я тут читаю https://www.slimframework.com/docs/

> At its core, Slim is a dispatcher that receives an HTTP request, invokes an appropriate callback routine, and returns an HTTP response. That’s it.



Вроде как довольно понятно.

>>193739

Да. Если ты захочешь сделать "долгоживущее" приложение, которое обрабатывает много запросов не умирая, то есть ReactPHP для этого.

>>196494

Почитай статью в википедии про принципы REST. Изучи документацию по примерам REST API - API яндекс Диска и API Youtube. Тогда ты будешь лучше ориентироваться.

> Мне нужно сделать по сылке доступ к методу, который отдает json или что то подобное?


Формулируешь плохо. Тебе надо сделать на сервере обработчик, который возвращает ответ в формате вроде JSON (или XML например) по определенному URL.

>>1196527
>>196529

Во-первых, ресайзить с 1000 до 150 - плохая идея, так как пользователь зря грузит огромную картинку. Ресайзят обычно в небольших пределах.

Во-вторых, изучи такие свойства: max-width, max-height у картинок, background-cover, object-cover. И может тут в посте про методы центрирования что-то полезное есть: https://2ch.hk/pr/res/1152267.html#1172048 (М)
1037 1198633
>>195447

Зависит от веб-сервера. В Апаче это делается с помощью mod_rewrite, в нгинксе с помощью указания в конфиге правил роутинга, в встроенном в PHP веб-сервере - с помощью роутинг-скрипта.

>>195721

Ответ должен быть 61270. Скорее всего, проблема в этой лишней строке

$credit = $credit * $percent;

>>196298

А что именно непонятно? Оно наверно предполагает наличие каких-то начальных знаний.

Вот например я тут читаю https://www.slimframework.com/docs/

> At its core, Slim is a dispatcher that receives an HTTP request, invokes an appropriate callback routine, and returns an HTTP response. That’s it.



Вроде как довольно понятно.

>>193739

Да. Если ты захочешь сделать "долгоживущее" приложение, которое обрабатывает много запросов не умирая, то есть ReactPHP для этого.

>>196494

Почитай статью в википедии про принципы REST. Изучи документацию по примерам REST API - API яндекс Диска и API Youtube. Тогда ты будешь лучше ориентироваться.

> Мне нужно сделать по сылке доступ к методу, который отдает json или что то подобное?


Формулируешь плохо. Тебе надо сделать на сервере обработчик, который возвращает ответ в формате вроде JSON (или XML например) по определенному URL.

>>1196527
>>196529

Во-первых, ресайзить с 1000 до 150 - плохая идея, так как пользователь зря грузит огромную картинку. Ресайзят обычно в небольших пределах.

Во-вторых, изучи такие свойства: max-width, max-height у картинок, background-cover, object-cover. И может тут в посте про методы центрирования что-то полезное есть: https://2ch.hk/pr/res/1152267.html#1172048 (М)
1038 1198634
>>196769

Упрощение:

(рус)(лат)(рус)?|(лат)(рус)

>>196805

Это неправда. Фреймворки нельзя изучать, не зная языка, в том числе концепций ООП.

>>196856

> https://github.com/phpredis/phpredis


Обрати внимание, что эта библиотека не использует исключения и ты должен проверять результат каждого вызова, при ошибке сам получать подробности ошибки. Игнорировать ошибки, естественно, не дело.

Насчет метода subscribe - я не уверен, что тут подойдет ReactPHP. Разве метод subscribe() работает асинхронно? Увы, документация по phpredis это никак не освещает (если у тебя есть время, можешь допилить ее), примеров использования я тоже в репозитории не нашел. Как я понимаю, клиент redis при выдаче команды SUBSCRIBE начинает просто ждать сообщений от redis, блокируя тред. То есть вызов $redis->subscribe() блокирующий. И до $loop->run выполнение просто не дойдет.

Для таймаута, судя по https://github.com/phpredis/phpredis/issues/634 можно использовать опцию задания таймаута.

Возможно, правильнее использовать pubsub не для передачи самих сообщений, а для передачи уведомления о том, что что-то изменилось. А за обновлениями лезть в БД.

Также, нужна защита от ошибок. Что, если твой PHP скрипт получил из redis сообщение и умер? Клиент отправляет новый запрос, но сообщение-то уже забрано из redis. Защититься от этого можно такой логикой:

- проверить изменения в БД, если есть, вернуть клиенту
- ждать событий в redis с таймаутом
- проверить изменения в БД, если есть, вернуть клиенту

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

> https://github.com/phpredis/phpredis#subscribe


> Я не знаю языка C, поэтому я не могу разобраться, ассинхронная ли это функция?


Думаю, нет. Вот ее код:

- https://github.com/phpredis/phpredis/blob/4533920fde608e12fe763cf2c977ed711c77e120/redis.c#L2491
- https://github.com/phpredis/phpredis/blob/4533920fde608e12fe763cf2c977ed711c77e120/redis_commands.c#L755 (генерирует текст команды subscribe)
- https://github.com/phpredis/phpredis/blob/2828c2f187900a5ddc450ce857b467d9e0b483ac/library.c#L272 (обрабатывает ответ на нее)

Код не особо понятный, но я вижу там

> / Multibulk response, {[pattern], type, channel, payload } /


> while(1) {


> if (!redis_sock_read_multibulk_reply_zval(


> INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, &z_resp)) break;


> ....


> if(zend_call_function(&(sctx->cb), &(sctx->cb_cache) TSRMLS_CC)


> ==FAILURE) ...


> }



То есть блокирующий цикл.

> https://github.com/phpredis/phpredis#publish


> Опять же, из-за незнания C, я не знаю, что эта функция вернет? Как всегда, true/false в случае успеха/неудачи?



Судя по коду

- https://github.com/phpredis/phpredis/blob/4533920fde608e12fe763cf2c977ed711c77e120/redis.c#L2477
- https://github.com/phpredis/phpredis/blob/2828c2f187900a5ddc450ce857b467d9e0b483ac/library.c#L1040

> if(ret > LONG_MAX) { / overflow /


> RETVAL_STRINGL(response + 1, response_len - 1);


> } else {


> RETVAL_LONG((long)ret);


> }


> ...


> if (IS_ATOMIC(redis_sock)) {


> RETVAL_FALSE;



Есть такие варианты:

- целое число (long - это 32-битное целое)
- строка с числом, если оно большое
- false

Что это за число - надо смотреть документацию по PUBLISH в redis, что она вернет.

> Приемлимо для обмена сообщений между клиентами Redis использовать строку в виде данных json? Или есть какая-то другая договрённость для обмена большого количества информации?


Приемлемо. Есть и много других форматов конечно - BSON, Protocol Buffers и тд.

> К примеру, в моём коде, я хотел опубликовать весь объект Сообщения, включая id, само сообщение, дату и так далее.



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

> Мне кажется, это эффективно - меньше дёрганий на обращение к БД на обнавление сообщений/контактов/проверки набора сообщений.


> А что вы думаете?



Не знаю. Зависит от ситуации наверно.

> И кстати, в моём примере, при подписке, я не где не обращаюсь к БД, а жду что ко мне придёт уже готовое сообщение. В этом нет ничего плохого?



Надо учитывать возможность устаревания данных или их потерь.
1038 1198634
>>196769

Упрощение:

(рус)(лат)(рус)?|(лат)(рус)

>>196805

Это неправда. Фреймворки нельзя изучать, не зная языка, в том числе концепций ООП.

>>196856

> https://github.com/phpredis/phpredis


Обрати внимание, что эта библиотека не использует исключения и ты должен проверять результат каждого вызова, при ошибке сам получать подробности ошибки. Игнорировать ошибки, естественно, не дело.

Насчет метода subscribe - я не уверен, что тут подойдет ReactPHP. Разве метод subscribe() работает асинхронно? Увы, документация по phpredis это никак не освещает (если у тебя есть время, можешь допилить ее), примеров использования я тоже в репозитории не нашел. Как я понимаю, клиент redis при выдаче команды SUBSCRIBE начинает просто ждать сообщений от redis, блокируя тред. То есть вызов $redis->subscribe() блокирующий. И до $loop->run выполнение просто не дойдет.

Для таймаута, судя по https://github.com/phpredis/phpredis/issues/634 можно использовать опцию задания таймаута.

Возможно, правильнее использовать pubsub не для передачи самих сообщений, а для передачи уведомления о том, что что-то изменилось. А за обновлениями лезть в БД.

Также, нужна защита от ошибок. Что, если твой PHP скрипт получил из redis сообщение и умер? Клиент отправляет новый запрос, но сообщение-то уже забрано из redis. Защититься от этого можно такой логикой:

- проверить изменения в БД, если есть, вернуть клиенту
- ждать событий в redis с таймаутом
- проверить изменения в БД, если есть, вернуть клиенту

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

> https://github.com/phpredis/phpredis#subscribe


> Я не знаю языка C, поэтому я не могу разобраться, ассинхронная ли это функция?


Думаю, нет. Вот ее код:

- https://github.com/phpredis/phpredis/blob/4533920fde608e12fe763cf2c977ed711c77e120/redis.c#L2491
- https://github.com/phpredis/phpredis/blob/4533920fde608e12fe763cf2c977ed711c77e120/redis_commands.c#L755 (генерирует текст команды subscribe)
- https://github.com/phpredis/phpredis/blob/2828c2f187900a5ddc450ce857b467d9e0b483ac/library.c#L272 (обрабатывает ответ на нее)

Код не особо понятный, но я вижу там

> / Multibulk response, {[pattern], type, channel, payload } /


> while(1) {


> if (!redis_sock_read_multibulk_reply_zval(


> INTERNAL_FUNCTION_PARAM_PASSTHRU, redis_sock, &z_resp)) break;


> ....


> if(zend_call_function(&(sctx->cb), &(sctx->cb_cache) TSRMLS_CC)


> ==FAILURE) ...


> }



То есть блокирующий цикл.

> https://github.com/phpredis/phpredis#publish


> Опять же, из-за незнания C, я не знаю, что эта функция вернет? Как всегда, true/false в случае успеха/неудачи?



Судя по коду

- https://github.com/phpredis/phpredis/blob/4533920fde608e12fe763cf2c977ed711c77e120/redis.c#L2477
- https://github.com/phpredis/phpredis/blob/2828c2f187900a5ddc450ce857b467d9e0b483ac/library.c#L1040

> if(ret > LONG_MAX) { / overflow /


> RETVAL_STRINGL(response + 1, response_len - 1);


> } else {


> RETVAL_LONG((long)ret);


> }


> ...


> if (IS_ATOMIC(redis_sock)) {


> RETVAL_FALSE;



Есть такие варианты:

- целое число (long - это 32-битное целое)
- строка с числом, если оно большое
- false

Что это за число - надо смотреть документацию по PUBLISH в redis, что она вернет.

> Приемлимо для обмена сообщений между клиентами Redis использовать строку в виде данных json? Или есть какая-то другая договрённость для обмена большого количества информации?


Приемлемо. Есть и много других форматов конечно - BSON, Protocol Buffers и тд.

> К примеру, в моём коде, я хотел опубликовать весь объект Сообщения, включая id, само сообщение, дату и так далее.



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

> Мне кажется, это эффективно - меньше дёрганий на обращение к БД на обнавление сообщений/контактов/проверки набора сообщений.


> А что вы думаете?



Не знаю. Зависит от ситуации наверно.

> И кстати, в моём примере, при подписке, я не где не обращаюсь к БД, а жду что ко мне придёт уже готовое сообщение. В этом нет ничего плохого?



Надо учитывать возможность устаревания данных или их потерь.
1039 1198635
>>196873

Не читал.

>>197592

Используй точку для склеивания строк. Или конструкции вроде \xff внутри строки.

>>198177

Трудно поверить. Ты наверно просто основы пропустил и берешься сразу за сложное. Порешай-ка наши задачи на JS из ОП-поста, может быть поможет разобраться.

>>198191

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

SELECT comments.*
FROM comments
JOIN posts ON ...
JOIN users ON comments.author_id = users.id
JOIN users AS post_author ON post_author.id = posts.author_id
LEFT JOIN tags_to_posts ...
WHERE comment.date BETWEEN x AND y

Тут все просто: СУБД выбирает комментарии по дате (в идеале по индексу), и затем к ним приджойнивает посты, авторов и тд. Все будет работать относительно быстро.

Пример страшных джойнов:

SELECT products.*
FROM products
JOIN products_colors ...
JOIN products_categories ...
WHERE products_colors.color_id = ?
AND products_categories.category_id = ?
AND products.price < 1000

Здесь СУБД придется выбрать сначала огромный список id товаров определенного цвета, потом огромный список товаров определенной категории, потом пересечь их, если она умеет это делать, потом приджойнить огромные список товаров и отсеять их по цене.
1039 1198635
>>196873

Не читал.

>>197592

Используй точку для склеивания строк. Или конструкции вроде \xff внутри строки.

>>198177

Трудно поверить. Ты наверно просто основы пропустил и берешься сразу за сложное. Порешай-ка наши задачи на JS из ОП-поста, может быть поможет разобраться.

>>198191

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

SELECT comments.*
FROM comments
JOIN posts ON ...
JOIN users ON comments.author_id = users.id
JOIN users AS post_author ON post_author.id = posts.author_id
LEFT JOIN tags_to_posts ...
WHERE comment.date BETWEEN x AND y

Тут все просто: СУБД выбирает комментарии по дате (в идеале по индексу), и затем к ним приджойнивает посты, авторов и тд. Все будет работать относительно быстро.

Пример страшных джойнов:

SELECT products.*
FROM products
JOIN products_colors ...
JOIN products_categories ...
WHERE products_colors.color_id = ?
AND products_categories.category_id = ?
AND products.price < 1000

Здесь СУБД придется выбрать сначала огромный список id товаров определенного цвета, потом огромный список товаров определенной категории, потом пересечь их, если она умеет это делать, потом приджойнить огромные список товаров и отсеять их по цене.
1040 1198636
>>198366

> Теперь собственно вопрос, желательно для опытных ребят, как бы вы организовали запросы в такую базу?


Самый простой (но не самый быстрый) вариант - использовать ORM вроде Доктрины. Смотри, как я выбираю пост по id:

$id = 123;
$post = $em->find(Post::class, $id);
printf("Название: %s, Автор: %s, Комментариев: %s\n",
$post->getTitle(),
$post->getAuthor()->getName(),
count($post->getComments())
);

$tagNames = array_map($post->getTags(), function ($tag) { return $tag->getTitle(); });
printf("Теги: %s\n", implode(', ', $tagNames));

В SQL ты можешь сделать это через несколько запросов или одним запросом с джойнами:

SELECT p.title, a.name, COUNT(DISTINCT com.id) AS commentCount,
GROUP_CONCAT(DISTINCT tag.title) AS tags
FROM posts p ON ...
JOIN users a ON ...
LEFT JOIN comments com ON ...
...
GROUP BY p.id

> Но что делать, когда у нужен допустим список постов какого-нибудь автора со всей вот этой сопутствующей мишурой (теги, картинки, ответы), тут уже просто невозможно выкрутиться подобным способом: не будешь же потом в цикле для каждого поста слать по 3 дополнительных селекта? Если у тебя постов скажем много?



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

SELECT FROM images WHERE post_id IN (1,2,3,4,5);

>>198376

Вообще, нет. Запросы бывают тяжелые, зависит от ситуации.

>>198378

> Связи с картинками можно вообще не хранить в базе а просто условится что картинки поста с id 382 будут лежать в папке 382 которая лежит в папке соответсвующей дате создания поста.



Это имеет недостатки:

- надо проверять, есть ли картинка или нет, через file_exists()
- при замене картинки имя не меняется и браузер может использовать старую кешированную картинку, если используется HTTP кеширование
- нельзя быстро получить размеры картинки, информацию о размерах и параметрах превьюшек
- если ты хранишь картинки в CDN, то быстро проверить их наличие и параметры вообще нельзя, надо делать запрос к CDN
- нельзя проверить, все ли картинки на месте

На практике, почти всегда, если нагрузки не гигантские, выгоднее всегда хранить информацию о картинках и превьюшках в БД. Это решает описанные выше проблемы.

>>198561

Удобнее делать групповые запросы. Первый запрос - выбрать все посты, второй - все картинки к ним. третий - все комментарии итд.
1040 1198636
>>198366

> Теперь собственно вопрос, желательно для опытных ребят, как бы вы организовали запросы в такую базу?


Самый простой (но не самый быстрый) вариант - использовать ORM вроде Доктрины. Смотри, как я выбираю пост по id:

$id = 123;
$post = $em->find(Post::class, $id);
printf("Название: %s, Автор: %s, Комментариев: %s\n",
$post->getTitle(),
$post->getAuthor()->getName(),
count($post->getComments())
);

$tagNames = array_map($post->getTags(), function ($tag) { return $tag->getTitle(); });
printf("Теги: %s\n", implode(', ', $tagNames));

В SQL ты можешь сделать это через несколько запросов или одним запросом с джойнами:

SELECT p.title, a.name, COUNT(DISTINCT com.id) AS commentCount,
GROUP_CONCAT(DISTINCT tag.title) AS tags
FROM posts p ON ...
JOIN users a ON ...
LEFT JOIN comments com ON ...
...
GROUP BY p.id

> Но что делать, когда у нужен допустим список постов какого-нибудь автора со всей вот этой сопутствующей мишурой (теги, картинки, ответы), тут уже просто невозможно выкрутиться подобным способом: не будешь же потом в цикле для каждого поста слать по 3 дополнительных селекта? Если у тебя постов скажем много?



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

SELECT FROM images WHERE post_id IN (1,2,3,4,5);

>>198376

Вообще, нет. Запросы бывают тяжелые, зависит от ситуации.

>>198378

> Связи с картинками можно вообще не хранить в базе а просто условится что картинки поста с id 382 будут лежать в папке 382 которая лежит в папке соответсвующей дате создания поста.



Это имеет недостатки:

- надо проверять, есть ли картинка или нет, через file_exists()
- при замене картинки имя не меняется и браузер может использовать старую кешированную картинку, если используется HTTP кеширование
- нельзя быстро получить размеры картинки, информацию о размерах и параметрах превьюшек
- если ты хранишь картинки в CDN, то быстро проверить их наличие и параметры вообще нельзя, надо делать запрос к CDN
- нельзя проверить, все ли картинки на месте

На практике, почти всегда, если нагрузки не гигантские, выгоднее всегда хранить информацию о картинках и превьюшках в БД. Это решает описанные выше проблемы.

>>198561

Удобнее делать групповые запросы. Первый запрос - выбрать все посты, второй - все картинки к ним. третий - все комментарии итд.
1041 1199090
Сап. Пытаюсь решить задачу по регуляркам с номером телефона, где регулярка должна помимо чисел воспринимать ещё и пробелы, скобки, тире.
Я сделал такую:

>$regexp = '/^8([()\s-]([0-9]{10}))$/';


И конечно же ничего не работает, не понимаю, как быть.
В примерах всё только с началом кода и концом, а тут надо именно чтоб между числами были эти символы.
1042 1199113
>>199090
^8[(\s-]?[0-9]{3}[) -]?[0-9]{3}[ -]?[0-9]{2}[ -]?[0-9]{2}$
1043 1199114
>>199113
Но это не точно
1044 1199115
\s в начале замени на один пробел а то оно и табуляцию пропустит
1045 1199123
>>199115
>>199113
>>199114
Спасибо большое, анон! А то я долго тупил над структурой.
1046 1199160
ОП, привет, начал делать задачу SPA и первое с чем столкнулся и уверен многие сталкиваются так это то, что не знаю с какой стороны начать.

Вообще есть ли есть какая либо задача есть ли какой-то определенный алгортим как делать какой-то большой проект?

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

Как вообще правильно планировать разработку и может какую-то хорошую литературу подскажете?
1047 1199174
Доделал Йобу-тексто-генератор:
http://sandbox.onlinephpfunctions.com/code/420e0d6e51382e49251f9e1411329c06f51c505f

И просто исправление текста:
http://sandbox.onlinephpfunctions.com/code/516d35fe23ee0c43c6038af65693aa25e1bd231e

Задачки отсюда, есличе
https://phpbooktest2.ga/l1/finals.html
1048 1199210
Начал делать er диаграмму (задача SPA) и не совсем понимаю некоторые вещи, при создании занятия для указывания предмета используется текстовое поле, получается таблица с предметами мне не нужна или все-таки нужна?

%%походу все-таки нужна%

анон - >>199160
1049 1199212
>>199210
хотя нет, по интерфейсу видно, что учитель может редактировать отметки с разных предметов, получается у каждой группы свой учитель, но это уже не для вуза, а для начальной школы получается приложение
image.png30 Кб, 714x448
1050 1199216
>>199210
добавлю еще диаграмму ERD
someApprentice 1051 1199240
>>198634
То что phpredis работает не асинхронно, это вызывает сомнения в использовании этой библиотеки. Да и ваши справедливые замечания, по поводу документации и обработки ошибок, подливают масла в огонь. Слишком много у неё недостатков. Дальше только будет больше проблем с ней.
Подумав над этим, я решил написать что-то подобное на ReactPHP, без участия Redis:

subscribe.php
<?php

// Каналы опустим для простоты (если они вообще нужны)

$database = new Database(...);

$message = new Message();

// Проверяем изменения
$message = $database->check(...);

// Если сообщение пустое ждем событий
if (empty(array_filter(get_object_vars($object)))) {

$loop = React\EventLoop\Factory::create();
$socket = new React\Socket\Server('127.0.0.1:8080', $loop);

$socket->on('connection', function (ConnectionInterface $c) {

$c->on('data', function ($data) use ($c) {
// пришло уведомление, проверяем сообщение в БД и возвращаем его
$message = $database->check(...);
$c->close();
});

});

$loop->addTimer($interval = 30, function () use ($socket) {
$socket->close(); // unsubscribe
});

$loop->run()

}

return $message; // дойдет ли выполнение досюда до окончания таймера?

?>

publish.php
<?php

$database = new Database(...);

$message = new Message($_POST['message']);

$message = $database->add($message);

$loop = React\EventLoop\Factory::create();
$connector = new Connector($loop);

// обработка Reject опущена для простоты
$connector->connect('127.0.0.1:8080')->then(function (ConnectionInterface $c) {

$c->write(...); // передаем либо уведомление, либо само сообщение целиком
$c->end();

});

$loop->run();

// возвращаем сообщение назад в случае успеха
return $message;

?>

Пара очень быстрых вопросов:

Когда создается сервер, ему передается адрес, который он будет слушать, и при соединении конектора, передается адрес, по которому оно создается. Т.е. для нескольких серверов, сначала нужно иметь роутер(?), который будет распределять соединения, как это делается при шардинге БД?
И зачем при соединении указывать адрес? Неужели не достаточно того что сервер уже слушает его?

>- самописный брокер на ReactPHP, в котором есть поддержка WAMP (Websocket App. Messaging Protocol), в котором есть в том числе и подписки, а также поддержка и websocket, и long polling. Это работает внутри одного процесса PHP.


Такой брокер уже написан кем-то другим и указан на странице ReactPHP - https://github.com/voryx/Thruway . Только документация совсем не написана. Может попробовать придумать что-нибудь на нём?
someApprentice 1051 1199240
>>198634
То что phpredis работает не асинхронно, это вызывает сомнения в использовании этой библиотеки. Да и ваши справедливые замечания, по поводу документации и обработки ошибок, подливают масла в огонь. Слишком много у неё недостатков. Дальше только будет больше проблем с ней.
Подумав над этим, я решил написать что-то подобное на ReactPHP, без участия Redis:

subscribe.php
<?php

// Каналы опустим для простоты (если они вообще нужны)

$database = new Database(...);

$message = new Message();

// Проверяем изменения
$message = $database->check(...);

// Если сообщение пустое ждем событий
if (empty(array_filter(get_object_vars($object)))) {

$loop = React\EventLoop\Factory::create();
$socket = new React\Socket\Server('127.0.0.1:8080', $loop);

$socket->on('connection', function (ConnectionInterface $c) {

$c->on('data', function ($data) use ($c) {
// пришло уведомление, проверяем сообщение в БД и возвращаем его
$message = $database->check(...);
$c->close();
});

});

$loop->addTimer($interval = 30, function () use ($socket) {
$socket->close(); // unsubscribe
});

$loop->run()

}

return $message; // дойдет ли выполнение досюда до окончания таймера?

?>

publish.php
<?php

$database = new Database(...);

$message = new Message($_POST['message']);

$message = $database->add($message);

$loop = React\EventLoop\Factory::create();
$connector = new Connector($loop);

// обработка Reject опущена для простоты
$connector->connect('127.0.0.1:8080')->then(function (ConnectionInterface $c) {

$c->write(...); // передаем либо уведомление, либо само сообщение целиком
$c->end();

});

$loop->run();

// возвращаем сообщение назад в случае успеха
return $message;

?>

Пара очень быстрых вопросов:

Когда создается сервер, ему передается адрес, который он будет слушать, и при соединении конектора, передается адрес, по которому оно создается. Т.е. для нескольких серверов, сначала нужно иметь роутер(?), который будет распределять соединения, как это делается при шардинге БД?
И зачем при соединении указывать адрес? Неужели не достаточно того что сервер уже слушает его?

>- самописный брокер на ReactPHP, в котором есть поддержка WAMP (Websocket App. Messaging Protocol), в котором есть в том числе и подписки, а также поддержка и websocket, и long polling. Это работает внутри одного процесса PHP.


Такой брокер уже написан кем-то другим и указан на странице ReactPHP - https://github.com/voryx/Thruway . Только документация совсем не написана. Может попробовать придумать что-нибудь на нём?
someApprentice 1052 1199241
>>199240

>if (empty(array_filter(get_object_vars($message*)))) {

1053 1199257
>>199160
Сначала нужно определить с какими данными оперирует пользователь.

Данные могут быть входящими и производными.

Затем делишь данные на группы (данные студента, данные предмета и т.д.)

Каждая группа данных это своя таблица, свой класс. А дальше определяешь в каком классе какие будут методы просто по смыслу.
1054 1199307
>>199257
а дальше? Начать с апи, фронта или может быть с админки?

И что по этому >>199210 >>199212 поводу?
1055 1199332
>>199307
Я всегда с админки начинаю. Работаю на yii2.
Делаю общие модели данных с общей логикой, затем от них параллельно модели админки и модели фронта.

Сначала это выглядело круто охуенно, но потом я понял что почти во всех проектах этого не нужно было делать, так как модели ничем не отличались.
1056 1199334
>>199332
С другой стороны в любой момент может понадобится добавить такое отличие.
1057 1199374
>>199210

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

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

>>199160

Есть разные версии, с чего начинать. Я предпочитаю начинать с модели данных, какие у нас есть данные, как они связаны.

Тут по сути надо сделать 2 приложения:

- серверное, управляющее данными и предоставляющее API для этого (по сути это будет MVC почти без V).
- клиентское, обеспечивающее отображение данных и их изменение пользователем (а тут уже MVC)

Самый сложный момент тут синхронизация данных. На сервере есть БД, на клиенте есть копия части БД, и данные в них могут независимо изменяться. Как обеспечить их согласованность?

Для начала можно попробовать обойтись без этого и просто на каждый чих делать запросы на сервер.

> Вообще есть ли есть какая либо задача есть ли какой-то определенный алгортим как делать какой-то большой проект?



Изучать, как делают другие. В вебе ничего уникального нет и все давно придумано.
1058 1199376
>>199240

Я погуглил "redis reactphp" и вижу, что есть асинхронные клиенты для редиса. Ты их не смотрел?

Ты, как я вижу, попытался написать свою реализауию pubsub, но она явно не работающая. Ты в subscribe.php открываешь порт на прослушивание на 30 секунд. Но порт в один момент времени может слушать только один процесс (есть возможность открыть порт нескольким процессам, если указать опцию расшаривания порта в linux, но тогда соединение получит один случайно выбранный из этих процессов, а не все).

То есть у тебя не может быть больше одного подписчика. Это не pubsub.

Как я понимаю, реализовать pubsub напрямую на примитивах ОС для IPC (вроде сокетов, которые ты пытался использовать) сложно, если вообще возможно. Проще реализовать его внутри процесса-брокера, и сделать возможность присоединения клиентов-издателей и подписчиков к нему. Я где-то в предыдущем посте предлагал даже пример кода на семафорах: https://phpclub.tech/pr/res/1174695.html#1190031 - сейчас я подумал, что в асинхронном однопоточном коде (Node.JS или ReactPHP) семафоры ведь и не нужны (так как один поток), можно без них это сделать, примерно так (пример сильно упрощен, убрана обработка сетевых ошибок, отсоединений клиентов итд):

// Мы делаем словарь, в котором индексом является номер канала,
// а содержимым - массив сокетов, заинтересованных в сообщениях.
// При поступлении сообщения в канал оно ретранслируется всем
// ждущим его сокетам клиентов.
//
// channelId: [ socket1, socket2, socket3 ]
//
// При отсоединении клиента надо удалять его сокет, это не сделано.

var listeners = {};

// Вызывается из клиента-подписчика, добавляет коллбек в массив коллбеков
// при появлении сообщения в канале оно посылается по TCP соединению
// подписчику
function subscribeForMessages(clientSocket, channelId) {
listeners[channelId].push(clientSocket);
}

// Вызывается из клиента-издателя, отправляет сообщение всем
// подписчикам канала
function publishMessage(channelId, message) {
var clients = sockets[channelId] || [];

// делаем копию для защиты от добавления/удаления
// сокетов в массив в процессе расылки
clients = clients.slice();
clients.forEach(function (socket) {
// В теории, если клиент не принимает сообщения, то они
// буферизуются и буфер будет расти неограниченно. Защита
// от этого не предусмотрена.
socket.write(message);
});
}

// Поднимаем TCP-сервер. Когда приходит соединение, мы читаем из
// него команду в текстовом виде. Подписчик посылает команду вида
// subscribe 1234, а издатель - publish 1234 message
//
// Если подписчик подписался на канал, ему в сокет приходят сообщения
// от издателей как строки текста. Отписка не предусмотрена.
//
// Нагло стырено с https://gist.github.com/creationix/707146

var net = require('net');
var serverSocket = net.createServer(function (socket) {

var lineReader = carrier.carry(socket);
lineReader.on('line', function(line) {

// Пришла строка от клиента
var [_, command, channelId, _, message] = /^(\w+)\s+(\d+)(\s+\S.*)?$/.exec(line);
if (command == 'subscribe') {
subscribeForMessages(socket, channelId);
} elseif (command == 'publish') {
publishMessage(channelId, message);
} else {
console.log("Invalid command: " + line);
}
});

socket.on('error', ...);
socket.on('close', ...);
});

serverSocket.on('error', ...);
serverSocket.listen(9001, '0.0.0.0');

Если ты так хочешь написать свой pubSub брокер, можешь переписать этот пример на PHP и допилить до работающего состояния. В качестве клиента используется telnet или netcat.

Тут разбирается реализация брокера в redis: https://making.pusher.com/redis-pubsub-under-the-hood/

> // дойдет ли выполнение досюда до окончания таймера?


Не знаю, вроде как event loop должен завершиться при закрытии всех сокетов и истечению всех таймаутов. Если нет, то можно (надежнее так) в таймауте явно вызвать команду завершения event loop.

> Т.е. для нескольких серверов, сначала нужно иметь роутер(?), который будет распределять соединения, как это делается при шардинге БД?



Да, если серверов несколько, то нужно "балансировать" клиентов между ними. Это можно сделать несколькими способами:

- на клиенте: клиент имеет массив адресов серверов и выбирает один случайно для соединения
- на сервере: делаем прокси, к которому подсоединяется клиент и который далее проксирует его соединение к одному из серверов

> И зачем при соединении указывать адрес? Неужели не достаточно того что сервер уже слушает его?



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

> Такой брокер уже написан кем-то другим и указан на странице ReactPHP - https://github.com/voryx/Thruway . Только документация совсем не написана. Может попробовать придумать что-нибудь на нём?



Можно.
1058 1199376
>>199240

Я погуглил "redis reactphp" и вижу, что есть асинхронные клиенты для редиса. Ты их не смотрел?

Ты, как я вижу, попытался написать свою реализауию pubsub, но она явно не работающая. Ты в subscribe.php открываешь порт на прослушивание на 30 секунд. Но порт в один момент времени может слушать только один процесс (есть возможность открыть порт нескольким процессам, если указать опцию расшаривания порта в linux, но тогда соединение получит один случайно выбранный из этих процессов, а не все).

То есть у тебя не может быть больше одного подписчика. Это не pubsub.

Как я понимаю, реализовать pubsub напрямую на примитивах ОС для IPC (вроде сокетов, которые ты пытался использовать) сложно, если вообще возможно. Проще реализовать его внутри процесса-брокера, и сделать возможность присоединения клиентов-издателей и подписчиков к нему. Я где-то в предыдущем посте предлагал даже пример кода на семафорах: https://phpclub.tech/pr/res/1174695.html#1190031 - сейчас я подумал, что в асинхронном однопоточном коде (Node.JS или ReactPHP) семафоры ведь и не нужны (так как один поток), можно без них это сделать, примерно так (пример сильно упрощен, убрана обработка сетевых ошибок, отсоединений клиентов итд):

// Мы делаем словарь, в котором индексом является номер канала,
// а содержимым - массив сокетов, заинтересованных в сообщениях.
// При поступлении сообщения в канал оно ретранслируется всем
// ждущим его сокетам клиентов.
//
// channelId: [ socket1, socket2, socket3 ]
//
// При отсоединении клиента надо удалять его сокет, это не сделано.

var listeners = {};

// Вызывается из клиента-подписчика, добавляет коллбек в массив коллбеков
// при появлении сообщения в канале оно посылается по TCP соединению
// подписчику
function subscribeForMessages(clientSocket, channelId) {
listeners[channelId].push(clientSocket);
}

// Вызывается из клиента-издателя, отправляет сообщение всем
// подписчикам канала
function publishMessage(channelId, message) {
var clients = sockets[channelId] || [];

// делаем копию для защиты от добавления/удаления
// сокетов в массив в процессе расылки
clients = clients.slice();
clients.forEach(function (socket) {
// В теории, если клиент не принимает сообщения, то они
// буферизуются и буфер будет расти неограниченно. Защита
// от этого не предусмотрена.
socket.write(message);
});
}

// Поднимаем TCP-сервер. Когда приходит соединение, мы читаем из
// него команду в текстовом виде. Подписчик посылает команду вида
// subscribe 1234, а издатель - publish 1234 message
//
// Если подписчик подписался на канал, ему в сокет приходят сообщения
// от издателей как строки текста. Отписка не предусмотрена.
//
// Нагло стырено с https://gist.github.com/creationix/707146

var net = require('net');
var serverSocket = net.createServer(function (socket) {

var lineReader = carrier.carry(socket);
lineReader.on('line', function(line) {

// Пришла строка от клиента
var [_, command, channelId, _, message] = /^(\w+)\s+(\d+)(\s+\S.*)?$/.exec(line);
if (command == 'subscribe') {
subscribeForMessages(socket, channelId);
} elseif (command == 'publish') {
publishMessage(channelId, message);
} else {
console.log("Invalid command: " + line);
}
});

socket.on('error', ...);
socket.on('close', ...);
});

serverSocket.on('error', ...);
serverSocket.listen(9001, '0.0.0.0');

Если ты так хочешь написать свой pubSub брокер, можешь переписать этот пример на PHP и допилить до работающего состояния. В качестве клиента используется telnet или netcat.

Тут разбирается реализация брокера в redis: https://making.pusher.com/redis-pubsub-under-the-hood/

> // дойдет ли выполнение досюда до окончания таймера?


Не знаю, вроде как event loop должен завершиться при закрытии всех сокетов и истечению всех таймаутов. Если нет, то можно (надежнее так) в таймауте явно вызвать команду завершения event loop.

> Т.е. для нескольких серверов, сначала нужно иметь роутер(?), который будет распределять соединения, как это делается при шардинге БД?



Да, если серверов несколько, то нужно "балансировать" клиентов между ними. Это можно сделать несколькими способами:

- на клиенте: клиент имеет массив адресов серверов и выбирает один случайно для соединения
- на сервере: делаем прокси, к которому подсоединяется клиент и который далее проксирует его соединение к одному из серверов

> И зачем при соединении указывать адрес? Неужели не достаточно того что сервер уже слушает его?



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

> Такой брокер уже написан кем-то другим и указан на странице ReactPHP - https://github.com/voryx/Thruway . Только документация совсем не написана. Может попробовать придумать что-нибудь на нём?



Можно.
1059 1199377
>>199307

Тут админка не особо нужна.

>>199113
>>199123

Не, это плохое решение. ЛУчше сделать так:

- пишем выражение вида "ровно одна цифра, за ней любое число минусов, скобок, пробелов"
- обрачиваем это выражение в (...){10}

>>199174

> $fixText


> $fixPunctuation


> $addDot =


тут лучше использовать одну и ту же переменную ($sentence), а не заводить новую на каждом шаге

> $wordsSeparation


лучше просто words

> $createNewSentence


newSentence

А так, верно.

> \\s{2,99}


Лучше \\s{2,} - так нельзя?

> $reg


Непонятное название.

А так, решено верно.

>>199216

lesson - это занятие в конкретный день или в общем название предмета? Наверно еще стоит сделать таблицу предметов.

Выглядит верно.
1059 1199377
>>199307

Тут админка не особо нужна.

>>199113
>>199123

Не, это плохое решение. ЛУчше сделать так:

- пишем выражение вида "ровно одна цифра, за ней любое число минусов, скобок, пробелов"
- обрачиваем это выражение в (...){10}

>>199174

> $fixText


> $fixPunctuation


> $addDot =


тут лучше использовать одну и ту же переменную ($sentence), а не заводить новую на каждом шаге

> $wordsSeparation


лучше просто words

> $createNewSentence


newSentence

А так, верно.

> \\s{2,99}


Лучше \\s{2,} - так нельзя?

> $reg


Непонятное название.

А так, решено верно.

>>199216

lesson - это занятие в конкретный день или в общем название предмета? Наверно еще стоит сделать таблицу предметов.

Выглядит верно.
1060 1199378
>>199212

Ну по идее преподаватель может вести разные предметы же. И у разных групп.

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

>>199332

Вообще, немного странная идея. По идее модель соответствует одной сущности и не может быть 2 модели для одной и той же сущности. Точнее, не очень понятно, в чем смысл.
1061 1199389
Я своим студентам в академии эту же задачу выдумал. Двое взялись никто до ума не довел. 2 года отучились блять. Тупые лентяи.
Тред закрыт 1062 1199394
Я проверил все задачи, ответил на все вопросы. Тред закрыт. Переходите пожалуйста в новый тред >>1199390 (OP)

Если я кого-то пропустил, то, пожалуйста, напомните о себе в новом треде.
1063 1199424
>>199377
Благодарю!

>тут лучше использовать одну и ту же переменную ($sentence), а не заводить новую на каждом шаге


Да, тоже хотел, но где-то читал жопой и не узнал, как их объединить. Подозреваю, что это самые основы, но если можно, то ткните, пожалуйста.
someApprentice 1064 1199822
>>199376

>Я погуглил "redis reactphp" и вижу, что есть асинхронные клиенты для редиса. Ты их не смотрел?


Я смотрел некоторые клиенты предлагаемые самим редисом (https://redis.io/clients#php) и предлагаемый ReactPHP (https://github.com/nrk/predis-async). Все они плохо задокументированы. Я разрываюсь между изучением их кода и написанием своего собственного брокера.
Изучу и то и то, так буду точно уверен что из этого выбрать.

Библиотеки на которые я обращу внимание:
https://github.com/clue/php-redis-react
https://github.com/shumkov/rediska //может быть не асинхронная
https://github.com/nrk/predis-async // заброшена с 2016
https://github.com/voryx/Thruway

>Ты, как я вижу, попытался написать свою реализауию pubsub, но она явно не работающая. Ты в subscribe.php открываешь порт на прослушивание на 30 секунд. Но порт в один момент времени может слушать только один процесс (есть возможность открыть порт нескольким процессам, если указать опцию расшаривания порта в linux, но тогда соединение получит один случайно выбранный из этих процессов, а не все).


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

>Если ты так хочешь написать свой pubSub брокер, можешь переписать этот пример на PHP и допилить до работающего состояния. В качестве клиента используется telnet или netcat.


>В качестве клиента используется telnet или netcat.


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

>> // дойдет ли выполнение досюда до окончания таймера?


>Не знаю, вроде как event loop должен завершиться при закрытии всех сокетов и истечению всех таймаутов. Если нет, то можно (надежнее так) в таймауте явно вызвать команду завершения event loop.


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

setTimeout($t = 3, function() {echo "TIMEOUT"});

echo "AFTER TIMEOUT";

Выдаст результат сначала "AFTER TIMOUT", а потом уже "TIMEOUT".

Т.е. если мы вызовем return после таймаута, то он вернет что-то до его истечения?

>> И зачем при соединении указывать адрес? Неужели не достаточно того что сервер уже слушает его?


>Так сервер это один процесс, а клиент - другой. Как клиент узнает, к кому подсоединяться? Твой вопрос звучит как "а зачем в браузере вводить адрес сайта в адресной строке, разве не достаточно что где-то есть сервер и он слушает порт".


Я плохо знаю низкоуровневые устройства сети, но разве сервер слушает все адреса в интернете?

https://reactphp.org/socket/#server

>As above, the $uri parameter can consist of only a port, in which case the server will default to listening on the localhost address 127.0.0.1, which means it will not be reachable from outside of this system.


>which means it will not be reachable from outside of this system.


То есть, если я задам, например, $uri = "google.com:8080", то сервер будет до бесконечности слушать этот адрес, пока google сам не создаст соединение по адресу сервера (что никогда не произойдет). В чем смысл слушать адрес, а не только свой порт, если от клиента зависит создастся ли соединение или нет?

Или это нужно чтобы соединение устанавливалось только когда указанные адреса в сервере и клиенте совпадают? Если подумать, то это имеет смысл, чтобы злоумышленник не создал свое соединение, и не стал присылать свои уведомления... Всё равно ничего не понятно.

Спасибо
someApprentice 1064 1199822
>>199376

>Я погуглил "redis reactphp" и вижу, что есть асинхронные клиенты для редиса. Ты их не смотрел?


Я смотрел некоторые клиенты предлагаемые самим редисом (https://redis.io/clients#php) и предлагаемый ReactPHP (https://github.com/nrk/predis-async). Все они плохо задокументированы. Я разрываюсь между изучением их кода и написанием своего собственного брокера.
Изучу и то и то, так буду точно уверен что из этого выбрать.

Библиотеки на которые я обращу внимание:
https://github.com/clue/php-redis-react
https://github.com/shumkov/rediska //может быть не асинхронная
https://github.com/nrk/predis-async // заброшена с 2016
https://github.com/voryx/Thruway

>Ты, как я вижу, попытался написать свою реализауию pubsub, но она явно не работающая. Ты в subscribe.php открываешь порт на прослушивание на 30 секунд. Но порт в один момент времени может слушать только один процесс (есть возможность открыть порт нескольким процессам, если указать опцию расшаривания порта в linux, но тогда соединение получит один случайно выбранный из этих процессов, а не все).


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

>Если ты так хочешь написать свой pubSub брокер, можешь переписать этот пример на PHP и допилить до работающего состояния. В качестве клиента используется telnet или netcat.


>В качестве клиента используется telnet или netcat.


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

>> // дойдет ли выполнение досюда до окончания таймера?


>Не знаю, вроде как event loop должен завершиться при закрытии всех сокетов и истечению всех таймаутов. Если нет, то можно (надежнее так) в таймауте явно вызвать команду завершения event loop.


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

setTimeout($t = 3, function() {echo "TIMEOUT"});

echo "AFTER TIMEOUT";

Выдаст результат сначала "AFTER TIMOUT", а потом уже "TIMEOUT".

Т.е. если мы вызовем return после таймаута, то он вернет что-то до его истечения?

>> И зачем при соединении указывать адрес? Неужели не достаточно того что сервер уже слушает его?


>Так сервер это один процесс, а клиент - другой. Как клиент узнает, к кому подсоединяться? Твой вопрос звучит как "а зачем в браузере вводить адрес сайта в адресной строке, разве не достаточно что где-то есть сервер и он слушает порт".


Я плохо знаю низкоуровневые устройства сети, но разве сервер слушает все адреса в интернете?

https://reactphp.org/socket/#server

>As above, the $uri parameter can consist of only a port, in which case the server will default to listening on the localhost address 127.0.0.1, which means it will not be reachable from outside of this system.


>which means it will not be reachable from outside of this system.


То есть, если я задам, например, $uri = "google.com:8080", то сервер будет до бесконечности слушать этот адрес, пока google сам не создаст соединение по адресу сервера (что никогда не произойдет). В чем смысл слушать адрес, а не только свой порт, если от клиента зависит создастся ли соединение или нет?

Или это нужно чтобы соединение устанавливалось только когда указанные адреса в сервере и клиенте совпадают? Если подумать, то это имеет смысл, чтобы злоумышленник не создал свое соединение, и не стал присылать свои уведомления... Всё равно ничего не понятно.

Спасибо
1065 1204935
>>174695 (OP)
Оппушка и все.
Насколько сильно нужно знать алгоритмы и матеш на самом деле? Нужно ли быть одаренным гением или хватает базовых знаний?
И как на данный момент обстоят дела с вакансиями PHP программиста. На superjob нашел только 4 вакансии, которые не требовали опыт работы. Все, лавочка закрыта?
1066 1204954
>>204935
И еще, сложно ли научиться оптимизации и рефакторингу существующего кода?
1067 1210254
Опчик! Помоги! Есть ли возможность ебашить условную функцию проверки по времени. Типа если сейчас меньше 5 вечера, то возвращает 1, если меньше, то возвращает 0? Вне зависимости от даты, то есть в любой день.
1068 1210263
>>210254
Блять, если больше, то возвращает 0.
1069 1215823
>>204954
Поддерживаю реквест
1070 1215825
Bump
1071 1215826
Bump
1072 1215828
Bump
1073 1215830
Bump
1074 1215832
Bump
1075 1215833
Bump
1076 1215834
Bump
Тред утонул или удален.
Это копия, сохраненная 5 июля 2018 года.

Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее

Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
« /pr/В начало тредаВеб-версияНастройки
/a//b//mu//s//vg/Все доски