Этого треда уже нет.
Это копия, сохраненная 21 декабря 2017 года.

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

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

Пожалуйста, пишите один большой пост вместо нескольких маленьких и не флудите не по теме.

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

Предыдущий тред был тут: >>1082507 (OP). Еще предыдущие треды ищутся в гугле по словам "клуб изучающих php" или в архиваче.

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

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

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

С чего начать

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

Устанавливать пока что ничего не требуется, разве что редактор кода вроде 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

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

Также, у нас есть задачи которые позволят тебе изучить или подтянуть до нормального уровня знания 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

Оформляй код аккуратно!!! — например пропусти через 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? — Да, однозначно. Посмотри любую вакансию.
grammar-nazi
56 Кб, 500x644
Напомню #2 #1097441
Код нужно писать не как попало, а аккуратно и по правилам. Почему? Потому, что на неакуратно написанный код не хочется даже смотреть.

Если тебе лень выравнивать код руками, закачай его на http://beta.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
#4 #1097492
Привет. Нужен хелп. Скачал шаблон с расширением .psd, открыл его фотошопом, а там куча горизонтальных и вертикальных линий зеленовато-белого цвета. Как эту хуйню убрать? Чтоб линий не было.Программирую 2 дня.
#5 #1097493
Привет. Нужен хелп. Скачал шаблон с расширением .psd, открыл его фотошопом, а там куча горизонтальных и вертикальных линий зеленовато-белого цвета. Как эту хуйню убрать? Чтоб линий не было.Программирую 2 дня.
#6 #1097494
Привет. Нужен хелп. Скачал шаблон с расширением .psd, открыл его фотошопом, а там куча горизонтальных и вертикальных линий зеленовато-белого цвета. Как эту хуйню убрать? Чтоб линий не было.Программирую 2 дня.
#7 #1097496
Извините, хз как 3 раза отправилось
#8 #1097532
>>1097494

Это направляющие (guides). Погугли по словам "photoshop guides", есть кнопки и пункт меню для их отключения.
#9 #1097541
>>1097438 (OP)
Пишет на этом кто-нибудь?
http://develnext.org/ru/
#10 #1097568
TL;DR: ОТКЛЮЧАЙТЕ ZEND OPCACHE В PHP 7.1, КОТОРЫЙ ИДЕТ ВМЕСТЕ С ПАКЕТОМ PHP71-EXTENSIONS. РАЗРАБОТЧИКИ ИГРАЛИ С ПАМЯТЬЮ И ПРОИГРАЛИ

Есть у меня на обслуживании проект, полностью написанный в стиле php4. Даже html кое-где вперемешку с кодом.
Позавчера вздумалось мне переставить на сервере с этим проектом php, с 5.6 прыгнуть на 7.1. Прочитал все статьи про миграцию с 5.6 на 7.0 и с 7.0 на 7.1 на php.net, убедился, что ничего не сломается, обновил php.
Проверил логи - ничего не сыпется. Потыкал сайт, все работает, красота. Хотя ой. Почему-то пара запросов оборвались - сервер рвет соединение, будто php падает. В логах пусто. Рестарт апача еще раз, потыкал-потыкал, вроде норм. Забегая вперед: не норм, просто код не уходил на ветку, где все падало.

Вчерашний вечер, собираюсь идти домой. Проверяю рабочую почту. А там куча репортов от юзеров, что одна из функций сайта не работает. Ну ебать. И меня ждал удивительный вечер в обнимку с var_dump().
Смотрю, код при заходе на определенную ветку действительно всегда безмолвно падает. В логах пусто совсем. Даже в php.ini прописал директиву error_log со ссылкой на лог апача, но ничего. Ветка длинная, пытаюсь отловить сломанное место с помощью die(), лучшего отладчика легаси кода.
Тут мне на глаза попадается еще один баг, одна из функций стала работать просто некорректно - уходит на ветку else, вместо того, чтобы зайти в один из elseif. Тут хотя бы ничего не падает. Лезу туда. И постепенно глаза лезут на лоб.
В начале скрипта $code это string(3) "304". А около ветки с if - уже string(2) "10". Я в шоке, эту переменную трогать не должен никто. Расставляю var_dump() повсюду. В итоге нахожу зловредное место.
var_dump($code); // string(3) "304"
$someData = file_get_contents('some_config.conf');
var_dump($code); // string(2) "10"

Чего блядь?! Лезу в мануал, fgc завезли сайд-эффект? Да нет, у разработчиков пхп мозги еще на месте.
Копирую $code в $code2, $another_random_var - после вызова file_get_contents все они превращаются в string(2) "10"!!!
Комментирую вызов fgc. Скрипт падает.
У меня опускаются руки, я заказываю платную поддержку у хостера и описываю ситуацию. Утром мне отписываются "закомментировали zend_extension=opcache.so, все заработало".
И правда, всё заработало как раньше, ничего нигде не падает.

Всё это выглядит как переполнение буфера у OpCache, либо какая-то борода с указателями, в общем проблемы с памятью, что серьезный баг.
Слава богу, что это не интернет-магазин, было бы охуенно выставить счет на 304 тысячи, а продать за 10 тысяч, например.
Я не знаю, как зарепортить подобное разработчикам, да и как это воспроизвести - понятия не имею. Могу только включить opcache обратно и дать доступ к серверу.
Такие дела.
#10 #1097568
TL;DR: ОТКЛЮЧАЙТЕ ZEND OPCACHE В PHP 7.1, КОТОРЫЙ ИДЕТ ВМЕСТЕ С ПАКЕТОМ PHP71-EXTENSIONS. РАЗРАБОТЧИКИ ИГРАЛИ С ПАМЯТЬЮ И ПРОИГРАЛИ

Есть у меня на обслуживании проект, полностью написанный в стиле php4. Даже html кое-где вперемешку с кодом.
Позавчера вздумалось мне переставить на сервере с этим проектом php, с 5.6 прыгнуть на 7.1. Прочитал все статьи про миграцию с 5.6 на 7.0 и с 7.0 на 7.1 на php.net, убедился, что ничего не сломается, обновил php.
Проверил логи - ничего не сыпется. Потыкал сайт, все работает, красота. Хотя ой. Почему-то пара запросов оборвались - сервер рвет соединение, будто php падает. В логах пусто. Рестарт апача еще раз, потыкал-потыкал, вроде норм. Забегая вперед: не норм, просто код не уходил на ветку, где все падало.

Вчерашний вечер, собираюсь идти домой. Проверяю рабочую почту. А там куча репортов от юзеров, что одна из функций сайта не работает. Ну ебать. И меня ждал удивительный вечер в обнимку с var_dump().
Смотрю, код при заходе на определенную ветку действительно всегда безмолвно падает. В логах пусто совсем. Даже в php.ini прописал директиву error_log со ссылкой на лог апача, но ничего. Ветка длинная, пытаюсь отловить сломанное место с помощью die(), лучшего отладчика легаси кода.
Тут мне на глаза попадается еще один баг, одна из функций стала работать просто некорректно - уходит на ветку else, вместо того, чтобы зайти в один из elseif. Тут хотя бы ничего не падает. Лезу туда. И постепенно глаза лезут на лоб.
В начале скрипта $code это string(3) "304". А около ветки с if - уже string(2) "10". Я в шоке, эту переменную трогать не должен никто. Расставляю var_dump() повсюду. В итоге нахожу зловредное место.
var_dump($code); // string(3) "304"
$someData = file_get_contents('some_config.conf');
var_dump($code); // string(2) "10"

Чего блядь?! Лезу в мануал, fgc завезли сайд-эффект? Да нет, у разработчиков пхп мозги еще на месте.
Копирую $code в $code2, $another_random_var - после вызова file_get_contents все они превращаются в string(2) "10"!!!
Комментирую вызов fgc. Скрипт падает.
У меня опускаются руки, я заказываю платную поддержку у хостера и описываю ситуацию. Утром мне отписываются "закомментировали zend_extension=opcache.so, все заработало".
И правда, всё заработало как раньше, ничего нигде не падает.

Всё это выглядит как переполнение буфера у OpCache, либо какая-то борода с указателями, в общем проблемы с памятью, что серьезный баг.
Слава богу, что это не интернет-магазин, было бы охуенно выставить счет на 304 тысячи, а продать за 10 тысяч, например.
Я не знаю, как зарепортить подобное разработчикам, да и как это воспроизвести - понятия не имею. Могу только включить opcache обратно и дать доступ к серверу.
Такие дела.
#11 #1097569
>>1097568
Вдогонку: Zend OpCache стоял и до этого, расширением к php5.6. Что-то поломано именно сейчас.
#12 #1097571
>>1097568
Это теперь всегда так будет, Анон.

У меня при обработке текстовых файлов время от времени выскакивает «Unable to allocate 74255 petabytes of memory» и уже довольно давно. Все настройки в пыхопэини крутил, гуглил, да всё без толку. Когда работает, а когда нет.
#13 #1097576
>>1097571
У тебя тоже opcache? А если его выключить и перезапустить апач?
#14 #1097577
>>1097571
Да и к тому же, у меня вообще ничего не выскакивало. display_errors=Off, конечно, но до записи в лог эти краши точно не доходят.
#15 #1097580
>>1097568

Проблемы с оп-кешем на старых проектах (на Zend) я видел еще лет 5 назад во времена PHP5. Все аналогично. Просто какой-то баг.

> В логах пусто совсем.


Ну так если PHP падает, он уже в лог ничего записать не может. Надо смотреть лог Апача, где будет что-то вроде Child xxx unexpectedly terminated.

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

>>1097571

> У меня при обработке текстовых файлов время от времени выскакивает «Unable to allocate 74255 petabytes of memory» и уже довольно давно.


Тут тоже хорошо бы сделать минимальный скрипт, который вызывает эту ошибку и зарепортить.
#16 #1097582
>>1097580

>Надо смотреть лог Апача


Ой, я не знал, что у апача еще свой лог имеется. Да, там килотонны
[Sat Nov 25 10:27:42.445985 2017] [mpm_itk:error] [pid 63118] child died with signal 11
[Sat Nov 25 10:27:44.163616 2017] [mpm_itk:error] [pid 63126] child died with signal 11
[Sat Nov 25 10:27:46.207923 2017] [mpm_itk:error] [pid 63128] child died with signal 11

>надо сделать коредамп упавшего процесса и отладчиком (gdb) смотреть


Не умею ничего из перечисленного, я простая веб-макака.
#17 #1097588
>>1097582

По такому описанию разработчики PHP баг найти просто не смогут. Если бы у меня было время, я бы попробовал поставить такие же версии софта, как у тебя, нагенерировал бы огромных PHP файлов и пробовал бы их запускать, чтобы поймать ошибку - а потом можно отладчиком найти место падения и от него искать истоки ошибки. Но времени у меня, увы, на это нет.
#18 #1097590
>>1097588
Если скажешь, как сделать дамп, могу сделать и выслать.
#19 #1097593
>>1097590

>было бы охуенно выставить счет на 304 тысячи, а продать за 10 тысяч, например.


У вас что, транзакций в MySQL нет?..
Ничего там не сломается, не переживай.
LdJfE9oNG1g
22 Кб, 1343x236
#20 #1097603
Сап, программач. В жс треде никто не помог. Помогите, прошу, необходима ваша помощь

У ВК некоторое время назад сменилось шифрование прямой ссылки на аудиозапись. Нашел на этом форуме новый дешифратор прямой ссылки. Но если брать ссылку из ВК, то он возвращает ее же без дешифровкистарый дешифратор теперь возвращает полную хуйню. набор символов, а не ссылку

вот его код: https://pastebin.com/vvmpKjdw

С ссылками, которые приводились в пример к другим дешифраторам и которые я нашел в интернете он справляется хорошо. Возвращает ссылку типа https://...mp3, но если я сам возьму из HTML кода (или даже через пост запрос к al_audio.php) зашифрованную ссылку типа audio_api_unavailable, то он возвращает ее же.

скриншот консоли пикрелейтед

первый вариант - с той ссылкой, которую я сам взял из HTML разметки ВК
https://vk.com/mp3/audio_api_unavailable.mp3?extra=Adu4mwuXyuPJwfLOqL0WrtfLEdKYBK8XsOfjs10WCgeZy10Ol2eOChz4AOiYvxnIwsOTBI8OnKnbp2qZounYDs44 qNDplxfTDM5Rq2O5lJvLrJGOl3KXDeXOq3bUEM5iuJPyB2q5s1a4BvDYow9jAee1zeG1vJfhA3bJlvvnyLCYAuzZsMjeog1KnKqXthzXwveTyNbwDgD5ovDN x3GOudnJr29on3LSlufSrvzpBxnum2mOnejpq2uOwNPjwdyTl249BMuUEtC#AqS1nZC
второй вариант - с той ссылкой, которую приводили как пример для других дешифраторов
https:\/\/vk.com\/mp3\/audio_api_unavailable.mp3?extra=jtK5pt53yMiUpN5GFJT5yZSMyc4Pi2mJkdLIpxX8yN51Ex98FhH5Dh1OFhL8yYa9FNi0ntK\/lhaInY0CFdL5hcGVpdK3obWxFY9\/lJX1oZOjkX85bYrGgHG+FN54jquPlGn1hbuElcCddJ0gptCbDbqDFrizkH0mixuioYT6jW4FiZT4pauiybKViJW7E3W\/hxGSEYb\/isyEiNGKEZP+nZqzgYW5FIiogGumldCunXS7kX0hhZWvd2aPlaiFaqjG#DGL4cOOjDG
#21 #1097643
Ребята, есть у кого опыт переезда из мухосранска в ДС на работу джуниором?
#22 #1097658
Есть массив внутри которого массивы. Вопрос: как можно добавлять переменные в нужный мне масив?

https://ideone.com/Y2yRSp
#24 #1097661
>>1097660
Спасибо большое.
#25 #1097744
А двойные кавычки это одно и то же, что и две одинарных, которые сразу друг за дружкой идут?
#26 #1097746
>>1097744
Нет, это отдельный символ. Две одинарных кавычки - пустая строка.
#27 #1097748
>>1097744

У меня двойные кавычки (") в русской раскладке пишутся как Shift + 2, а в латинской - есть отдельная кнопка с одиночными (') и двойными (") кавычками около Enter. Проверь свою клавиатуру.

Учти, что еще есть апостроф ` - у меня он на клавише с буквой Ё и тильдой ~.

Есть еще разные Юникодные кавычки и символы дюймов, но их нет на клавиатуре.
#28 #1097829
Суп. К пхпПИ ЭЙЧ ПИ не прикасался вообще не коим образом, сейчас учу хтмл/ксс.
Короче, есть один хеадер, в нем список расположенный горизонтально, 3 элемента в нем - ссылки, 1, последний - поле для ввода. Сделалхотел сделать, чтобы поле для ввода раскрывалось вправо при выделении, но оно раскрывается в обе стороны и сдвигает другие элементы. Как сделать, чтобы оно раскрывалось только вправо? Паддинг не предлагать, потому что тогда текст идет не до конца.
index.html
https://pastebin.com/5njNSUFM
style.css
https://pastebin.com/CC7jaDk
#29 #1097858
>>1097438 (OP)
есть книги по LAMP с новым PHP и Apache. Пытался найти, но всюду пых оброс бородой
#30 #1097860
>>1097438 (OP)
Охуенная картинка с Юкиной <:3
#31 #1097865
>>1097438 (OP)

>2 картинка



Представляю сколько у этих кошатниц глистов
#32 #1097912
В задаче про студентов при сортировке списка тоже должны быть ЧПУ? Я пока только с ссылками такого вида запилил: example.com/?field=surname&direction=desc
#33 #1097920
Нужен хелп. Как в фотошопе в psd-шаблоне скопировать текст? Не вручную же его в html писать? Смотрел видос по верстке, там челик копировал прям из psd текст, однако не объяснил , как это делается.
#34 #1097943
>>1097920

К фотошопу идет официальный мануал, переведенный в том числе на русский, толстенная книга (в PDF) под 1000 страниц. Если ты по каким-то причинам его потерял, его можно найти в сети в формате PDF. Обрати внимание, что надо искать руководство для нужной версии программы.

Более того, я сейчас погуглил и выяснил, что похоже наступил коммунизм, и Адоб выложила руководство по фотошопу на русском (!) под свободной лицензией:

Версия CC2017: https://helpx.adobe.com/ru/photoshop/user-guide.html
Старые версии: https://helpx.adobe.com/ru/photoshop/archive.html

Раздел про текст: https://helpx.adobe.com/ru/photoshop/user-guide.html

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

>>1097912

Можно без ЧПУ, можно с ЧПУ.

>>1097858

Наверно только официальный мануал на англ https://httpd.apache.org/docs/2.4/ (если есть время, можешь перевести статью-другую, и материал выучишь, и другим людям поможешь).

Со стороны PHP подключение PHP как mod_php (модуль Апача) описано тут http://php.net/manual/ru/install.unix.apache2.php (часть про компиляцию Апача смело пропускаем, важна только часть, где надо добавить директивы в конфиг Апача).
#35 #1097944
>>1097829

CSS-файл удален. А так, это делается обычно за счет float, меню флоатится влево, поиск флоатится вправо, и на всю шапку ставится clearfix. Таким образом, правый край поля поиска прикреплен к правому краю шапки.

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

Также есть другие варианты:

- использовать display: table для создания таблицы с 2 ячейками с выравниванием влево и вправо (не получится реализовать перекрытие меню)
- использовать flexbox (то же самое)

Все основные способы позиционирования перечислены (но не описаны) в уроке тут: https://github.com/codedokode/pasta/blob/master/html/positioning.md
#36 #1097948
>>1097590

Судя по описанию здесь, надо заморочиться: https://bugs.php.net/bugs-generating-backtrace.php

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

То есть нужно либо включить коредампы (может они даже уже включены, можно проверить через cat /proc/sys/kernel/core_pattern и ulimit -a ) либо запускать сервер из-под gdb (в однопоточном режиме). Второе наверно даже удобнее, но может быть баг в однопоточном режиме не проявится.

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

При этом надо помнить, что в core dump могут сохраниться куски PHP кода и данных (значения переменных), которые он обрабатывал.

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

Также, я еще кое-что придумал. Ты можешь попробовать запускать код без участия Апача (но с теми же настройками php.ini), используя встроенный в PHP веб-сервер ( http://php.net/manual/ru/features.commandline.webserver.php ). Его можно запустить даже без прав рута, если, есть доступ к командной строке. С помощью него ты можешь проверить: связано ли появление бага с Апачом или нет.

Разумеется, ты можешь также скопилировать отладочную версию PHP у себя на компьютере (если у тебя линукс или виртуальная машина с ним), главное взять ту же самую версию PHP и расширений (версию и параметры, с которыми был собран PHP, можно увидеть в phpinfo()). Это удобнее в том плане, что ты имеешь там все нужные права. Если ты раньше ничего не собирал, то это минимум несколько часов (а может и дней), так как будут возникать ошибки от того, что не хватает какой-то библиотеки или неверно прописан какой-то путь и ты будешь искать их причину.
#36 #1097948
>>1097590

Судя по описанию здесь, надо заморочиться: https://bugs.php.net/bugs-generating-backtrace.php

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

То есть нужно либо включить коредампы (может они даже уже включены, можно проверить через cat /proc/sys/kernel/core_pattern и ulimit -a ) либо запускать сервер из-под gdb (в однопоточном режиме). Второе наверно даже удобнее, но может быть баг в однопоточном режиме не проявится.

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

При этом надо помнить, что в core dump могут сохраниться куски PHP кода и данных (значения переменных), которые он обрабатывал.

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

Также, я еще кое-что придумал. Ты можешь попробовать запускать код без участия Апача (но с теми же настройками php.ini), используя встроенный в PHP веб-сервер ( http://php.net/manual/ru/features.commandline.webserver.php ). Его можно запустить даже без прав рута, если, есть доступ к командной строке. С помощью него ты можешь проверить: связано ли появление бага с Апачом или нет.

Разумеется, ты можешь также скопилировать отладочную версию PHP у себя на компьютере (если у тебя линукс или виртуальная машина с ним), главное взять ту же самую версию PHP и расширений (версию и параметры, с которыми был собран PHP, можно увидеть в phpinfo()). Это удобнее в том плане, что ты имеешь там все нужные права. Если ты раньше ничего не собирал, то это минимум несколько часов (а может и дней), так как будут возникать ошибки от того, что не хватает какой-то библиотеки или неверно прописан какой-то путь и ты будешь искать их причину.
#37 #1097949
>>1097590

Также, что касается поиска багов обращения к памяти, то для этого можно запустить программу под valgrind: http://valgrind.org/ - это не требует сборки какой-то специальной версии PHP (но в неотладочной версии конечно полезной информации будет меньше).

То есть можно запустить встроенный в PHP веб-сервер под valgrind, запустить в нем проблемный скрипт, и если там есть ошибки работы с памятью, valgrind может их обнаружить.
#38 #1097951
>>1097568

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

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

А так да, лет 5 назад я видел такую же проблему на хостинге, тоже с древним приложением, только с другим кешем, вроде бы apc cache или еще какой-то. Замена кеша на другой решила проблему.
#39 #1097954
>>1097949
Также, что касается поиска багов обращения к памяти, то для этого можно запустить программу на другом языке программирования: это не требует сборки какой-то специальной версии PHP (но в неотладочной версии конечно полезной информации будет меньше).

То есть можно взять текстовый редактор, написать в нём заново «проблемный скрипт», и если там есть ошибки работы с памятью, в другом языке программирования их не будет.
#40 #1098026
Аноны, объясните нуфане, что значит "сайт" на PHP, например вк? Это значит, что его серверная логика реализована на PHP?
Ведь делать разные анимации и всё такое можно только на JS, потому что это единственный язык, которой понимает браузер
#41 #1098035
>>1097829
>>1097944

> CSS-файл удален.


Найс. Перезалил https://pastebin.com/NcmGj85e .
#42 #1098043
Реально ли за 2 месяца вкатиться в верстальщика (параллельно учусь на очном, но кроме как ходить на пары ничего не делаю и поэтому в неделю часов 60-80 свободного времени есть) уровня ~15к в месяц. Альтернатива - обычная работка для студента на 15-18к с графиком 3 полных дня в неделю. Мб кто-то расскажет про свои первые попытки вкатиться.
#43 #1098099
>>1098026
Это значит, что бэкенд сделан на Php. То есть ты хочешь посмотреть на сайте сообщения за прошлый год, жмешь кнопку, сайт посылает с фронта http-запрос с нужными параметрами, далее php обрабатывает запрос, лезет в базу и выдает нужные данные, а потом на сайте это реализуется с помощью js или html или неважно как. Также на этот самый бэкенд приходят запросы с мобильной версии сайта, с мобильного приложения, с десктопного (если оно у них есть).
>>1098043
вполне реально, правда я в дс не видел особо много контор, где можно работать неполный день. плюс верстальщик - такая специализация, которая ни туда, ни сюда. знать надо дохуя, а перспектив нет. у нас в конторе вообще нет понятия "верстальщик", есть джуниор-фронт.
#44 #1098105
>>1098099
Ну почему же... перспектив нет. Женитьса на склочной стервозной бабище из хуяр-отдела, очень даже.
https://github.com/kichiweb123/students #45 #1098161
>>1097466
>>1097470

Комменатрий лучше добавить не к таблице, а прямо к колонке (например через ALTER TABLE MODIFY password_hash ... COMMENT ....).

https://github.com/kichiweb123/students/blob/master/model/ConnectDb.php
Здесь не очень понятно, зачем этот класс. Если он для того, чтобы хранить объект mysqli, то что мешает его хранить просто в переменной без всяких ConnectDb? Также, непонятно, зачем в нем поля вроде db_address? Где и как они будут использоваться?

То есть в TDG можно написать так:

> function __construct(mysqli $mysqli) ...



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

>>Лучше использовать DI и убрать с класса TableStudentGateway обязанность соединяться с БД.


> Сделал, но надо проверять


Вроде с DI ты разобрался.

> $err = $this->connect->connect_error;


> $err = mb_convert_encoding($err, 'UTF-8', 'cp1251');


А это зачем? Ошибка соединения с БД возвращается в cp1251? Это конечно плохо, так как под линуксом они будут в utf-8... По-хорошему, это mysqli сама должна преобразовывать информацию об ошибке в заданную в настройках PHP (default_encoding) кодировку, если это не так, то можно собрать подробности, проверить что все верно и зарепортить баг разработчикам PHP (а еще лучше - вместе с исправлением).

> TableStudentsGateway.php


> Класс нужен для соединия с БД,


Для соединения он не нужен, это лучше убрать.

Код оформлен не по PSR. Пропусти код класса через phpformatter.com, и увидишь, как правильно надо его оформлять. Также, смотри второй пост в треде про оформление кода.

> class TableStudentsGateway{


> public $db = null;


Почему поле db сделано public? Как ты выбираешь, что поставить, public или private?

В функции getStudent в SQL запрос вставляется переменная $sort, но нет проверки, что она содержит разрешенное значение, а значит тут может быть SQL инъекция.

> while($row = $result->fetch_array(MYSQLI_ASSOC)){


> $arr[] = $row;


Это можно сделать одной командой вместо цикла.

> for($i = 0; $i<=8; $i++){


Почему не foreach тут? А то придется цифру менять при изменении числа полей.

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

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

Вот я например заметил одну вещь: в базе поле называется second_name, а в коде sname - легко перепутать. И неудобно работать: если ты берешь массив из одной функции и передаешь в другую, получается, надо заменять в нем название поля? Было бы проще если бы для представления одного студента использовался объект.

> if(!$data['name'] and !$data['sname'] and $data['class']){


> $class = "class = ?";


> }elseif(($data['name'] or $data['sname']) and $data['class']){


> $class = ", class = ?";


> }


> if(!$data['name'] and !$data['sname'] and !$data['class'] and $data['email']){


> $email = "email = ?";


> }elseif(($data['name'] or $data['sname'] or $data['class']) and $data['email']){


> $email = ", email = ?";


> }



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

Запрос проще собирать так. Сделать массив кусочков вида ['name = ?', 'email = ?'] и склеить через implode.

> WHERE login = ?


> AND password_hash = ?


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

Методы findPage и getStudent не дублируют друг друга?

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

> function getEmail(){


В этой функции есть нарушение разделения ответственности (принципа, что каждый класс занимается своим делом). Мы вроде бы подразуемваем, что за получение данных из БД отвечает только класс TabsleStudentsGateway, никто другой этим не занимается. Но! Эта функция возвращает объект класса mysqli_result. Не список email, а объект для работы с базой данных. И код, который функцию вызовет, должен получается сам работать с базой данных, а не получить готовый результат.

Приведу простой пример: допустим, мы заменим mysqli на PDO. Если все сделано верно, то нам придется править только класс TableStudentGateway. Но у тебя придется править еще и код, который использует getEmail. То есть то, что должно быть инкапсулировано (спрятано) внутри TableStudentsGateway, "протекает" в этой функции из класса наружу.

Вот еще пример нарушения инкапсуляции:

> Authorisation.php



> function isLogin($login, $pass = false){


> $result = $this->tableStudentGateway->getLoginPass();


> if($login and $pass){


> while($row = $result->fetch_array(MYSQLI_ASSOC)){


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

Должно быть так:

- запрашиваем у TSG данные по студенту с логином login
- если не нашлись, значит логи неправильный
- если такие данные нашлись, сверяем хеш

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

Далее, я вижу в Authorisatin метод isEmailUsed. Какое отношение он имеет к авторизации? Никакого. Этот метод лучше сделать в классе TSG. И сделать его эффективно, чтобы не вытягивались все email из базы, а делался поиск с помощью SQL запроса. Иначе на таблице в миллион пользователей это будет работать очень медленно, а может даже памяти не хватит. То, что база умеет делать сама (поиск одной записи), выгоднее делать в ней.
https://github.com/kichiweb123/students #45 #1098161
>>1097466
>>1097470

Комменатрий лучше добавить не к таблице, а прямо к колонке (например через ALTER TABLE MODIFY password_hash ... COMMENT ....).

https://github.com/kichiweb123/students/blob/master/model/ConnectDb.php
Здесь не очень понятно, зачем этот класс. Если он для того, чтобы хранить объект mysqli, то что мешает его хранить просто в переменной без всяких ConnectDb? Также, непонятно, зачем в нем поля вроде db_address? Где и как они будут использоваться?

То есть в TDG можно написать так:

> function __construct(mysqli $mysqli) ...



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

>>Лучше использовать DI и убрать с класса TableStudentGateway обязанность соединяться с БД.


> Сделал, но надо проверять


Вроде с DI ты разобрался.

> $err = $this->connect->connect_error;


> $err = mb_convert_encoding($err, 'UTF-8', 'cp1251');


А это зачем? Ошибка соединения с БД возвращается в cp1251? Это конечно плохо, так как под линуксом они будут в utf-8... По-хорошему, это mysqli сама должна преобразовывать информацию об ошибке в заданную в настройках PHP (default_encoding) кодировку, если это не так, то можно собрать подробности, проверить что все верно и зарепортить баг разработчикам PHP (а еще лучше - вместе с исправлением).

> TableStudentsGateway.php


> Класс нужен для соединия с БД,


Для соединения он не нужен, это лучше убрать.

Код оформлен не по PSR. Пропусти код класса через phpformatter.com, и увидишь, как правильно надо его оформлять. Также, смотри второй пост в треде про оформление кода.

> class TableStudentsGateway{


> public $db = null;


Почему поле db сделано public? Как ты выбираешь, что поставить, public или private?

В функции getStudent в SQL запрос вставляется переменная $sort, но нет проверки, что она содержит разрешенное значение, а значит тут может быть SQL инъекция.

> while($row = $result->fetch_array(MYSQLI_ASSOC)){


> $arr[] = $row;


Это можно сделать одной командой вместо цикла.

> for($i = 0; $i<=8; $i++){


Почему не foreach тут? А то придется цифру менять при изменении числа полей.

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

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

Вот я например заметил одну вещь: в базе поле называется second_name, а в коде sname - легко перепутать. И неудобно работать: если ты берешь массив из одной функции и передаешь в другую, получается, надо заменять в нем название поля? Было бы проще если бы для представления одного студента использовался объект.

> if(!$data['name'] and !$data['sname'] and $data['class']){


> $class = "class = ?";


> }elseif(($data['name'] or $data['sname']) and $data['class']){


> $class = ", class = ?";


> }


> if(!$data['name'] and !$data['sname'] and !$data['class'] and $data['email']){


> $email = "email = ?";


> }elseif(($data['name'] or $data['sname'] or $data['class']) and $data['email']){


> $email = ", email = ?";


> }



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

Запрос проще собирать так. Сделать массив кусочков вида ['name = ?', 'email = ?'] и склеить через implode.

> WHERE login = ?


> AND password_hash = ?


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

Методы findPage и getStudent не дублируют друг друга?

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

> function getEmail(){


В этой функции есть нарушение разделения ответственности (принципа, что каждый класс занимается своим делом). Мы вроде бы подразуемваем, что за получение данных из БД отвечает только класс TabsleStudentsGateway, никто другой этим не занимается. Но! Эта функция возвращает объект класса mysqli_result. Не список email, а объект для работы с базой данных. И код, который функцию вызовет, должен получается сам работать с базой данных, а не получить готовый результат.

Приведу простой пример: допустим, мы заменим mysqli на PDO. Если все сделано верно, то нам придется править только класс TableStudentGateway. Но у тебя придется править еще и код, который использует getEmail. То есть то, что должно быть инкапсулировано (спрятано) внутри TableStudentsGateway, "протекает" в этой функции из класса наружу.

Вот еще пример нарушения инкапсуляции:

> Authorisation.php



> function isLogin($login, $pass = false){


> $result = $this->tableStudentGateway->getLoginPass();


> if($login and $pass){


> while($row = $result->fetch_array(MYSQLI_ASSOC)){


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

Должно быть так:

- запрашиваем у TSG данные по студенту с логином login
- если не нашлись, значит логи неправильный
- если такие данные нашлись, сверяем хеш

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

Далее, я вижу в Authorisatin метод isEmailUsed. Какое отношение он имеет к авторизации? Никакого. Этот метод лучше сделать в классе TSG. И сделать его эффективно, чтобы не вытягивались все email из базы, а делался поиск с помощью SQL запроса. Иначе на таблице в миллион пользователей это будет работать очень медленно, а может даже памяти не хватит. То, что база умеет делать сама (поиск одной записи), выгоднее делать в ней.
https://github.com/kichiweb123/students #46 #1098164
>>1097466
>>1097470

> setcookie("login", "$login", 0x7FFFFFFF,


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

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

В валидаторе, при проверке поля score, надо проверять, что оно содержит цифры. А то можно ввести "30 cats". Для года надо проверять что там указан реалистичный год.

> if($this->authorisation->isLogin


Лучше isLoginUsed

Также, нужно подумать, как избавиться от повторяющегося кода в методах validateStudent и validateProfile.

> https://github.com/kichiweb123/students/blob/master/public/cfg.ini


зачем ты конфиг с паролями положил в публично доступную папку? Хочешь со всеми поделиться своими секретами?

> function my_autoloader($class){


Тут ошибка. В моем уроке про автозагрузку ( https://github.com/codedokode/pasta/blob/master/php/autoload.md ) было сказано:

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



У тебя нет проверки, что файл ../controller/'.$class.'.php'; существует - следовательно, если написать например код

if (class_exists('TestClass')) {}

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

> header('Location: error.php');


Это неправильно. Допустим у тебя в коде произошла ошибка. Сервер должен отдать ответ с кодом 5xx. А ты отдаешь ответ с кодом 302 (редирект), который значит - страница, которую вы ищете, переехала по другому адресу. Не надо никогда редиректить на страницу ошибки, надо ее показывать.

https://github.com/kichiweb123/students/blob/master/public/index.php
Из этого файла надо убрать полностью HTML код и лишние маркеры <?php

Ты попытался сделать обработчик исключений. Но почему-то ты ловишь только исключения при создании нескольких объектов, а остальной код не проверяешь. Логичнее тогда весь код в файле обернуть в один большой try/catch. Или прочитать про обработчик исключений в моем уроке по исключениям.

> $error = $e->getMessage();


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

Контроллеры Search и Table очень похожи. Их функции можно объединить в один контроллер, ведь поиск - это тоже просмотр списка студентов, только с фильтром по имени.

> Profile.php


> if($_SERVER["REQUEST_METHOD"] == "POST"){


> require_once "../refreshStudent.php";


Зачем из контроллера вынсоить кусок в отдельный файл? Не лучше ли сюда этот код и вписать?

> <form class="form-inline" style="float:right;


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

https://github.com/kichiweb123/students/blob/master/view/login.phtml
В view не должно быть работы с POST/GET. Оно просто отображает то, что дал контроллер.

> elseif(!$container['Authorisation']->isLogin($login, $pass)){


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

> view/pages.phtml


> echo "<a href='?id=search&search=".$search."&p=".($offset-1).


тебе не кажется, что тут длинная и тяжело читаемая смесь из знаков препинания? Лучше сделать функцию или метод где-нибудь в Util, который будет формировать URL из переданных ему параметров. И не забывай про htmlspecialchars.

> view/search.phtml


> Найдены запросы по слову \"$search\":


Прочитай мой урок по XSS на гитхабе.

Также, в шаблонах не должно быть echo, это неудобно, писать HTML в кавычках. Используй <?= ?>.

Если тебе что-то непонятно, спрашивай. Важно не слепо следовать советам, а понимать, зачем это нужно.

>>1097468

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


> Это как?


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

Если у тебя код правильно разделен на части, то это сделать нетрудно.
https://github.com/kichiweb123/students #46 #1098164
>>1097466
>>1097470

> setcookie("login", "$login", 0x7FFFFFFF,


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

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

В валидаторе, при проверке поля score, надо проверять, что оно содержит цифры. А то можно ввести "30 cats". Для года надо проверять что там указан реалистичный год.

> if($this->authorisation->isLogin


Лучше isLoginUsed

Также, нужно подумать, как избавиться от повторяющегося кода в методах validateStudent и validateProfile.

> https://github.com/kichiweb123/students/blob/master/public/cfg.ini


зачем ты конфиг с паролями положил в публично доступную папку? Хочешь со всеми поделиться своими секретами?

> function my_autoloader($class){


Тут ошибка. В моем уроке про автозагрузку ( https://github.com/codedokode/pasta/blob/master/php/autoload.md ) было сказано:

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



У тебя нет проверки, что файл ../controller/'.$class.'.php'; существует - следовательно, если написать например код

if (class_exists('TestClass')) {}

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

> header('Location: error.php');


Это неправильно. Допустим у тебя в коде произошла ошибка. Сервер должен отдать ответ с кодом 5xx. А ты отдаешь ответ с кодом 302 (редирект), который значит - страница, которую вы ищете, переехала по другому адресу. Не надо никогда редиректить на страницу ошибки, надо ее показывать.

https://github.com/kichiweb123/students/blob/master/public/index.php
Из этого файла надо убрать полностью HTML код и лишние маркеры <?php

Ты попытался сделать обработчик исключений. Но почему-то ты ловишь только исключения при создании нескольких объектов, а остальной код не проверяешь. Логичнее тогда весь код в файле обернуть в один большой try/catch. Или прочитать про обработчик исключений в моем уроке по исключениям.

> $error = $e->getMessage();


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

Контроллеры Search и Table очень похожи. Их функции можно объединить в один контроллер, ведь поиск - это тоже просмотр списка студентов, только с фильтром по имени.

> Profile.php


> if($_SERVER["REQUEST_METHOD"] == "POST"){


> require_once "../refreshStudent.php";


Зачем из контроллера вынсоить кусок в отдельный файл? Не лучше ли сюда этот код и вписать?

> <form class="form-inline" style="float:right;


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

https://github.com/kichiweb123/students/blob/master/view/login.phtml
В view не должно быть работы с POST/GET. Оно просто отображает то, что дал контроллер.

> elseif(!$container['Authorisation']->isLogin($login, $pass)){


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

> view/pages.phtml


> echo "<a href='?id=search&search=".$search."&p=".($offset-1).


тебе не кажется, что тут длинная и тяжело читаемая смесь из знаков препинания? Лучше сделать функцию или метод где-нибудь в Util, который будет формировать URL из переданных ему параметров. И не забывай про htmlspecialchars.

> view/search.phtml


> Найдены запросы по слову \"$search\":


Прочитай мой урок по XSS на гитхабе.

Также, в шаблонах не должно быть echo, это неудобно, писать HTML в кавычках. Используй <?= ?>.

Если тебе что-то непонятно, спрашивай. Важно не слепо следовать советам, а понимать, зачем это нужно.

>>1097468

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


> Это как?


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

Если у тебя код правильно разделен на части, то это сделать нетрудно.
#47 #1098226
https://ideone.com/QfGifZ

>ucwords — Преобразует в верхний регистр первый символ каждого слова в строке



Там, где delimiters нужно регулярное выражение? Почему он в верхний регистр отказался преобразовать строку?
#48 #1098251
#49 #1098262
>>1097943
Спасибо большое по поводу фотошопа
https://github.com/someApprentice/chat/ #50 #1098286
>>1087406

Ой, пост пропустил. Потому я обычно и прошу напомнить о себе, потому что в треде на 900 постов можно что-то и упустить.

>>>+offset + +1


>>Немного странное место. Не многовато ли знаков "плюс"?


> Что поделать если js при сложении не преобразует данные в число? Приходиться делать это самому.


Ну это уже вопрос к твоему коду в backend, почему он числа в виде строк возвращает. А так, надо хотя бы скобки ставить для понятности: (+offset) + 1

>>Также, мне кажется, что у тебя в контроллере находится код, относящийся ко view: вызовы jQuery вроде if ($(that.view.moremessages).length) стоило бы перенести во view и писать вместо этого if (that.view.hasMoreMessagesButton()), а еще лучше - if (this.canShowMoreMessages()), так как это довольно коряво, проверять наличие новых сообщений по наличию кнопки на экране. Должно ведь быть наоборот - модель/viewModel сама знает, есть ли новые сообщения.



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


Тут скорее идея в том, что мы изолируем всю работу с DOM в один класс. Это ведь один из принципов ООП - single responsibility. И потому мы должны писать

view.showMessageCount(1);

а не

view.messageCountDiv.text(1);

Видишь разницу между 2 вариантами? Она в наличии/отсутствии инкапсуляции работы с DOM внутри view. Ну и если ты, например, захочешь сделать анимацию при изменении числа, в первом варианте это будет проще. Также, в первом случае код чуть понятнее, на мой взгляд.

Можно конечно не делать инкапсуляцию, но тогда возникает вопрос, а зачем вообще нужен view? Не проще его объединить с контроллером? Такой вариант тоже возможен.

Да, может показаться, что это раздувает код, но это потому, что ты пишешь все руками, не используешь библиотеки для data-binding (knockout, angular, react, vue и тд), которые решают проблему избавления от ручного обновления DOM.

>>Должно ведь быть наоборот - модель/viewModel сама знает, есть ли новые сообщения.


> Должно быть свойство модели/viewModel, например this.canShowMoreMessages = true/false?


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

backend.getMessages(offset) -> [messages, hasMoreMessages]

И просто хранить в переменной. Можно хранить в свойстве контроллера. В переменной удобнее тем, что у нее ограничена область видимости.

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

var hasMore = messageList.hasMoreMessages(offset);

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

Я там еще увидел, что ты решил пойти дальше и переменные начать хранить в DOM:

> var datawith = $('a', that.view.moreMessages).attr('data-with');



А что мешает хранить это в переменной?

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

<div class="hotel-card" data-stars="3" data-city="London" data-price="100"></div>

Более того, давно уже ведутся разговоры по возможности добавления кастомных тегов, чтобы писать <hotel-card stars="3" city="London"></hotel-card>. Например, такое есть в Polymer.js, для этого добавили Shadow DOM. Такой синтаксис используют в Реакте. Почему нет? Вполне соответствует идее семантической (смысловой) разметки.

Но в таком случае обычно "карточка отеля" - это отдельный компонент. Где-то есть скрипт, который читает эти атрибуты и обрабатывает их, есть шаблон и тд. А у тебя не так, у тебя ведь кнопка не оформлена как отдельный компонент. Ты просто используешь DOM атрибуты как поля объекта или переменные, и возникает вопрос - а что мешает данные сразу и хранить в полях или переменных?

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

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


> Разве контроллер не должен "дирижировать" всем этим?


Я не помню, что я имел в виду, но думаю, я хотел сказать о 1) разделении ответственности (например, только вью работает с DOM напрямую) и 2) о преобразовании больших функций с кучей колллбеков (callback hell). Может их надо на части разбить, может их надо писать не вложенно, а последовательно.

Про callback hell, это когда пишут так:

$(...).click(function (e) {
$.ajax({
url: ...,
onsuccess: function (result) {
setTimeout(function () {
$(...).click(function () {
...
});
});
}
})
});

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

Я вот сейчас открыл твой код - и обнаружил там те самые 2 пробела. Как в воду глядел.

Вот это вот код не для человека:

https://github.com/someApprentice/chat/blob/master/public/js/conversation.js#L71

> that.backend.handleError(jqXHR, textStatus);


> }


> );


> }


> }


> }


> }.bind(this));


> };



Я не робот и я не могу в уме посчитать, к чему тут относится bind(this). 8 уровней вложенности! 3-4 хватило бы с лихвой.

Промисы позволяют победить это:

var result = doSmth();
result.catch(...);
result.then(function () {
...
}).then(function () {
...
});

Также, можно выносить код в функции:

$(btn).click(handleClick);
$(btn2).click(this.handleClick.bind(this));

Алсо, кто-то даже сделал сайт по теме http://callbackhell.com/

Или тут: https://github.com/someApprentice/chat/blob/master/public/js/conversation.js#L80 - функция на целых 60 строк. Пока я дойду до конца, я забуду, что было в начале.

И еще, ты-то может это знаешь, но я например не понимаю, за что отвечает каждый класс. Вот conversation.js - это контроллер области сообщений? Контроллер, отвечающий за переписку вообще? Стоит взять за правило писать перед классом, за что он отвечает и зачем нужен. Кроме самых очевидных случаев.

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

if (!...) {
return;
}

Вот попробуем упростить это:

https://github.com/someApprentice/chat/blob/master/public/js/conversation.js#L31

> that.backend.getLastMessages(datawith, offset).then(function(data) {


> проверка, что URL не изменился


> отправка сообщений на расшифровку


> обновление DOM



Я бы сделал так. Все, связанное с расшифровкой, просто вынес бы в функцию. Использовал бы промисы для выполнения асинхронных операций последовательно:

var encryptedPromise = that.backend.getLastMessages(datawith, offset);
var decryptedPromise = encryptedPromise.then(this.decryptMessages.bind(this));
decryptedPromise.then(function (decrypted)) {
если (URL изменился) { выйти; }

this.appendMessages(decrypted);
this.showSomeButton(...);
...
};

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

Иногда ситуация бывает сложнее, чем я написал. Ну например, бекенд возвращает 2 значения, { encryptedMessages, haveMore }, и надо как-то передать haveMore в функцию вывода данных, пропустив этап расшифровки. Я не знаю правильного ответа, попробуем например что-нибудь написать:

var resultPr = that.backend.getLastMessages(datawith, offset);
var viewData = resultPr.then(function (lastMessages) {
var decryptedPr = that.decrypt(lastMessages.encryptedMessages);

// Добавляем haveMore в результат расшифровки
var decryptedAndHaveMorePr = decryptedPr.then(function (decrypted) {
return {
haveMore: lastMessages.haveMore,
decrypted: decrypted
};
});
return decryptedAndHaveMorePr;
});

viewData.then(function (decryptedAndHaveMore) {
// вывод сообщений
}, function () {
// вывод ошибок
});

Не знаю, читабельно ли вышло? Может, ты сможешь красивее записать? Асинхронный код, он такой, на await/async ( https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Operators/await ) это бы наверно компактнее получилось:

var result = await that.backend.getLastMessages(datawith, offset);
var decrypted = await decryptMessages(result.encrypted);
view.showMessages(decrypted);
view.showMoreButton(result.haveMore);

>>Также, твой Crypter является по сути оберткой над openpgp, ничего от себя не добавляя. Непонятно, в чем смысл его существовани


> Вы выше делали замечание что нужно делать обёртку. Я запутан.



Не помню, к сожалению, что я имел в виду. Я просто хотел сказать, что если ты пишешь класс-обертку, он должен добавлять какой-то функционал, иначе можно использовать внутренний класс напрямую. Ну не знаю, давай считать тогда, что добавленный функционал - это запуск воркера (initWorker).
https://github.com/someApprentice/chat/ #50 #1098286
>>1087406

Ой, пост пропустил. Потому я обычно и прошу напомнить о себе, потому что в треде на 900 постов можно что-то и упустить.

>>>+offset + +1


>>Немного странное место. Не многовато ли знаков "плюс"?


> Что поделать если js при сложении не преобразует данные в число? Приходиться делать это самому.


Ну это уже вопрос к твоему коду в backend, почему он числа в виде строк возвращает. А так, надо хотя бы скобки ставить для понятности: (+offset) + 1

>>Также, мне кажется, что у тебя в контроллере находится код, относящийся ко view: вызовы jQuery вроде if ($(that.view.moremessages).length) стоило бы перенести во view и писать вместо этого if (that.view.hasMoreMessagesButton()), а еще лучше - if (this.canShowMoreMessages()), так как это довольно коряво, проверять наличие новых сообщений по наличию кнопки на экране. Должно ведь быть наоборот - модель/viewModel сама знает, есть ли новые сообщения.



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


Тут скорее идея в том, что мы изолируем всю работу с DOM в один класс. Это ведь один из принципов ООП - single responsibility. И потому мы должны писать

view.showMessageCount(1);

а не

view.messageCountDiv.text(1);

Видишь разницу между 2 вариантами? Она в наличии/отсутствии инкапсуляции работы с DOM внутри view. Ну и если ты, например, захочешь сделать анимацию при изменении числа, в первом варианте это будет проще. Также, в первом случае код чуть понятнее, на мой взгляд.

Можно конечно не делать инкапсуляцию, но тогда возникает вопрос, а зачем вообще нужен view? Не проще его объединить с контроллером? Такой вариант тоже возможен.

Да, может показаться, что это раздувает код, но это потому, что ты пишешь все руками, не используешь библиотеки для data-binding (knockout, angular, react, vue и тд), которые решают проблему избавления от ручного обновления DOM.

>>Должно ведь быть наоборот - модель/viewModel сама знает, есть ли новые сообщения.


> Должно быть свойство модели/viewModel, например this.canShowMoreMessages = true/false?


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

backend.getMessages(offset) -> [messages, hasMoreMessages]

И просто хранить в переменной. Можно хранить в свойстве контроллера. В переменной удобнее тем, что у нее ограничена область видимости.

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

var hasMore = messageList.hasMoreMessages(offset);

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

Я там еще увидел, что ты решил пойти дальше и переменные начать хранить в DOM:

> var datawith = $('a', that.view.moreMessages).attr('data-with');



А что мешает хранить это в переменной?

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

<div class="hotel-card" data-stars="3" data-city="London" data-price="100"></div>

Более того, давно уже ведутся разговоры по возможности добавления кастомных тегов, чтобы писать <hotel-card stars="3" city="London"></hotel-card>. Например, такое есть в Polymer.js, для этого добавили Shadow DOM. Такой синтаксис используют в Реакте. Почему нет? Вполне соответствует идее семантической (смысловой) разметки.

Но в таком случае обычно "карточка отеля" - это отдельный компонент. Где-то есть скрипт, который читает эти атрибуты и обрабатывает их, есть шаблон и тд. А у тебя не так, у тебя ведь кнопка не оформлена как отдельный компонент. Ты просто используешь DOM атрибуты как поля объекта или переменные, и возникает вопрос - а что мешает данные сразу и хранить в полях или переменных?

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

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


> Разве контроллер не должен "дирижировать" всем этим?


Я не помню, что я имел в виду, но думаю, я хотел сказать о 1) разделении ответственности (например, только вью работает с DOM напрямую) и 2) о преобразовании больших функций с кучей колллбеков (callback hell). Может их надо на части разбить, может их надо писать не вложенно, а последовательно.

Про callback hell, это когда пишут так:

$(...).click(function (e) {
$.ajax({
url: ...,
onsuccess: function (result) {
setTimeout(function () {
$(...).click(function () {
...
});
});
}
})
});

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

Я вот сейчас открыл твой код - и обнаружил там те самые 2 пробела. Как в воду глядел.

Вот это вот код не для человека:

https://github.com/someApprentice/chat/blob/master/public/js/conversation.js#L71

> that.backend.handleError(jqXHR, textStatus);


> }


> );


> }


> }


> }


> }.bind(this));


> };



Я не робот и я не могу в уме посчитать, к чему тут относится bind(this). 8 уровней вложенности! 3-4 хватило бы с лихвой.

Промисы позволяют победить это:

var result = doSmth();
result.catch(...);
result.then(function () {
...
}).then(function () {
...
});

Также, можно выносить код в функции:

$(btn).click(handleClick);
$(btn2).click(this.handleClick.bind(this));

Алсо, кто-то даже сделал сайт по теме http://callbackhell.com/

Или тут: https://github.com/someApprentice/chat/blob/master/public/js/conversation.js#L80 - функция на целых 60 строк. Пока я дойду до конца, я забуду, что было в начале.

И еще, ты-то может это знаешь, но я например не понимаю, за что отвечает каждый класс. Вот conversation.js - это контроллер области сообщений? Контроллер, отвечающий за переписку вообще? Стоит взять за правило писать перед классом, за что он отвечает и зачем нужен. Кроме самых очевидных случаев.

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

if (!...) {
return;
}

Вот попробуем упростить это:

https://github.com/someApprentice/chat/blob/master/public/js/conversation.js#L31

> that.backend.getLastMessages(datawith, offset).then(function(data) {


> проверка, что URL не изменился


> отправка сообщений на расшифровку


> обновление DOM



Я бы сделал так. Все, связанное с расшифровкой, просто вынес бы в функцию. Использовал бы промисы для выполнения асинхронных операций последовательно:

var encryptedPromise = that.backend.getLastMessages(datawith, offset);
var decryptedPromise = encryptedPromise.then(this.decryptMessages.bind(this));
decryptedPromise.then(function (decrypted)) {
если (URL изменился) { выйти; }

this.appendMessages(decrypted);
this.showSomeButton(...);
...
};

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

Иногда ситуация бывает сложнее, чем я написал. Ну например, бекенд возвращает 2 значения, { encryptedMessages, haveMore }, и надо как-то передать haveMore в функцию вывода данных, пропустив этап расшифровки. Я не знаю правильного ответа, попробуем например что-нибудь написать:

var resultPr = that.backend.getLastMessages(datawith, offset);
var viewData = resultPr.then(function (lastMessages) {
var decryptedPr = that.decrypt(lastMessages.encryptedMessages);

// Добавляем haveMore в результат расшифровки
var decryptedAndHaveMorePr = decryptedPr.then(function (decrypted) {
return {
haveMore: lastMessages.haveMore,
decrypted: decrypted
};
});
return decryptedAndHaveMorePr;
});

viewData.then(function (decryptedAndHaveMore) {
// вывод сообщений
}, function () {
// вывод ошибок
});

Не знаю, читабельно ли вышло? Может, ты сможешь красивее записать? Асинхронный код, он такой, на await/async ( https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Operators/await ) это бы наверно компактнее получилось:

var result = await that.backend.getLastMessages(datawith, offset);
var decrypted = await decryptMessages(result.encrypted);
view.showMessages(decrypted);
view.showMoreButton(result.haveMore);

>>Также, твой Crypter является по сути оберткой над openpgp, ничего от себя не добавляя. Непонятно, в чем смысл его существовани


> Вы выше делали замечание что нужно делать обёртку. Я запутан.



Не помню, к сожалению, что я имел в виду. Я просто хотел сказать, что если ты пишешь класс-обертку, он должен добавлять какой-то функционал, иначе можно использовать внутренний класс напрямую. Ну не знаю, давай считать тогда, что добавленный функционал - это запуск воркера (initWorker).
#51 #1098288
>>1087406

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


Тут главное правильно его спроектировать (интерфейс к нему), с учетом асинхронности почти всех операций.

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


Конечно, будет. Если это делает бекенд. А если бекенд генерирует события пропадения/появления связи или события ошибок, а контроллер/вью на них подписывается и отображает на экране, то разделению соблюдается. То есть паттерн "Observer" решает эту проблему.

Вот так:

// в контроллере
this.backend.onError(function (e) {
that.displayError(e);
});

Просто тут ведь есть такие варианты:

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

И какой лучше - зависит от ситуации. Может ты в углу хочешь выводить ошибки, может менять цвет иконки, а может рядом с сообщением или кнопкой отправки.
#52 #1098306
Если у кого-то из вас, аноны, нет опыта и вы не работали с большими проектами, и любопытно, а как они выглядят, то почему бы не посмотреть большие проекты на PHP?

Движок от Википедии: https://github.com/wikimedia/mediawiki
Магенто 2, движок для интернет-магазинов: https://github.com/magento/magento2

Вот примерно с таким вы можете столкнуться, если устроитесь на работу.
#53 #1098317
>>1087406

И еще. Ты использешь в дампе utf8: https://github.com/someApprentice/chat/blob/master/chat.sql

Это не utf-8, настоящая utf-8 в MySQL называется utf8mb4: https://medium.com/@adamhooper/in-mysql-never-use-utf8-use-utf8mb4-11761243e434

А то в твоем чатике нельзя будет эмодзи пересылать.
#54 #1098323
Проверьте пожалуйста задание на приведение номеров к единому стандарту через регулярки

https://ideone.com/EQhCuF

Репост из предыдущего треда
#55 #1098330
>>1097438 (OP)
Какой популярный фреймворк "более ооп-шный".
Даже не знаю, может мое недовольство не обоснованно, но вот например пробовал laravel, так там по мануалу полно обращений к статическим методам или сам генератор перечисляет поля из бд в массиве. (например protected $fillable = [ 'name', 'email', 'password', ]; )
#56 #1098380
>>1098317

И еще. В дампе ошибка DATETIME(6), в форме регистрации не пропускает логин ivan, из-за кривой регулярки.

В имени нельзя использовать цифры.

При регистрации появляется ошибка, что за 60 секунд ключ не сгенерировало, хотя процесс gpg висит с 0 потреблением CPU все это время. Может конечно, это нехватка энтропии в виртуальной машине виновата.

На c9.io просто появляется надпись generating keys... и ничего не происходит.
#57 #1098414
Не могу установить Xdebug через Babun

вводил здесь
https://xdebug.org/wizard.php
аутпут от php -i

Download php_xdebug-2.5.4-7.1-vc14-nts-x86_64.dll
Move the downloaded file to ext
Edit C:\tools\php71\php.ini and add the line
zend_extension = ext\php_xdebug-2.5.4-7.1-vc14-nts-x86_64.dll

Прописал эту строчку сразу после
;;;;;;;;;;;;;;;;;;;
; About php.ini ;
;;;;;;;;;;;;;;;;;;;

таким образом
;zend_extension = ext\php_xdebug-2.5.4-7.1-vc14-nts-x86_64.dll

после этого снова ввел
pact install xdebug
в Бабуне, но ничего всё равно получил
Package xdebug not found or ambiguous name, exiting
#58 #1098468
Что использовать для разработки на Линуксе?
Скачать Атом ? Или есть достойные альтернативы?
#59 #1098487
>>1098414

Инструкции на сайте xdebug - они для ручной установки. То есть она пишет, какую dll тебе надо скачать, куда положить и что дописать в php.ini. Ты их выполнял?

Что касается pact, он ведь никак с разработчиками xdebug не связан. Это сборка с cygwin. И pact устанавливает не любые программы, а те, что есть в репозитории cygwin.

Что такое cygwin? Это набор библиотек, имитирующих линуксовое АПИ на Windows. За счет этого можно скомпилировать линуксовые программы под cygwin и запускать их под windows.

Если ты ставил php для windows (не для cygwin), то ты должен для него скачать xdebug с сайта, как он тебе советует.

Если вместо этого ты бы предпочел пользоваться cygwin и pact, то тебе надо установить php через pact, и через него же xdebug. И убедиться, что виндовый PHP находится не в PATH, чтобы не запустить его случайно.

> Package xdebug not found or ambiguous name, exiting


Ты ввел неправильнео имя пакета. Делать надо не так:

- найти пакеты по слову xdebug (pact find xdebug)
- просмотреть список и выбрать нужный тебе
- установить его, указав его правильное имя. Скорее всего он называется как-то вроде php7-xdebug. Поиск подскажет.

pact describe xdebug покажет подробную информацию о пакетах, в названии которых есть это слово.

Я кстати сам cygwin использую, ты можешь с его помощью потихоньку привыкать к линуксовой командной строке.
#60 #1098554
>>1097860
Ну ты и быдло.
#61 #1098557
>>1098035
>>1097829
К спеке вообще прикасался? Зачем тебе везде idшники там? Почему не вписал классы для описания элементов? Почему там JS?
#62 #1098571
>>1097829
Короче чот ты много нагородил, мож заработался, у меня такое бывает. Ну в общем:

>text-align: center;


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

> <div id="page-wrapper">


>Внутри него находится твой хаотический список


>Соответственно этот div и является окном


>>1097944
Чот ты нагородил тоже, не проще ли установить его статично и все? Просто в таких случаях лезть во флекс, совет интересный, но не в этом случае смею предположить. Ну ка расскажи где эт флексы так используют, аж интересно стало? Почему так все усложнено?
Смотри што сделал:
https://theknacker.github.io/Test/index.html
#63 #1098576
>>1097944

>А так, это делается обычно за счет float, меню флоатится влево, поиск флоатится вправо, и на всю шапку ставится clearfix. Таким образом, правый край поля поиска прикреплен к правому краю шапки.


https://theknacker.github.io/Test/index2.html - Поиск здорового человека.

>Если ты используешь флоат и поле поиска расширяется так, что перекрывает меню, то по умолчанию оно провалится вниз, так как флоаты не перекрывают друг друга.


https://theknacker.github.io/Test/index3.html - Поиск курильщика.
Все вспомнил, извини ОП за тупость. Но вот табличный способ если чесна первый раз слышу, интересно как он работает?
Я не автор страницы, я просто взял ее на разбор ради интереса.
#64 #1098594
>>1098571

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

Тут https://theknacker.github.io/Test/index.html сделано что-то другое, поле поиска не прижато вправо.

тут https://theknacker.github.io/Test/index2.html поле не наезжает на меню при расширении, а проваливается вниз. Попробуй сделать, чтобы поле расширялось до 200px, а не 120, и увидишь.

https://theknacker.github.io/Test/index3.html та же проблема.

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

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

> Но вот табличный способ если чесна первый раз слышу, интересно как он работает?


display: table/table-row/rable-body/table-cell. Лучше всего про них почитать в спецификации если не боишься, или в какой-нибудь статье. Заставляют элементы позиционироваться как таблицу. Соответственно, можно сделать таблицу из 2 ячеек.

> Чот ты нагородил тоже, не проще ли установить его статично и все?


Что значит статично? position: static? Не вижу логики.

> где эт флексы так используют


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

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

HTML все же, если честно, заточен на оформление именно текста. Когда делаешь сложный интерфейс, флекс может быть полезен. Но у них конечно куча подвохов (например, при неудачном использовании он может картинки делать нулевого размера), поддерживается не везде, было 2 спецификации флекса, то есть нужная, но немного проблемная и сырая технология.
#64 #1098594
>>1098571

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

Тут https://theknacker.github.io/Test/index.html сделано что-то другое, поле поиска не прижато вправо.

тут https://theknacker.github.io/Test/index2.html поле не наезжает на меню при расширении, а проваливается вниз. Попробуй сделать, чтобы поле расширялось до 200px, а не 120, и увидишь.

https://theknacker.github.io/Test/index3.html та же проблема.

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

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

> Но вот табличный способ если чесна первый раз слышу, интересно как он работает?


display: table/table-row/rable-body/table-cell. Лучше всего про них почитать в спецификации если не боишься, или в какой-нибудь статье. Заставляют элементы позиционироваться как таблицу. Соответственно, можно сделать таблицу из 2 ячеек.

> Чот ты нагородил тоже, не проще ли установить его статично и все?


Что значит статично? position: static? Не вижу логики.

> где эт флексы так используют


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

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

HTML все же, если честно, заточен на оформление именно текста. Когда делаешь сложный интерфейс, флекс может быть полезен. Но у них конечно куча подвохов (например, при неудачном использовании он может картинки делать нулевого размера), поддерживается не везде, было 2 спецификации флекса, то есть нужная, но немного проблемная и сырая технология.
#65 #1098595
>>1098571

Причем, когда поле наезжает на меню, нужно, чтобы пункт меню, уходящий под поле поиска, плавно исчезал на протяжении 10-20 пикс. Не резко врезался в поле поиска, а плавно терял яркость. Надеюсь, ты понял идею.
#66 #1098603
>>1098323
https://ideone.com/fSFugG

Немного подправил код
#67 #1098607
>>1098594
Первая ссылка это я автору дал намек на его вопрос, остальные это имплементация слов вот тут написано >>1098576 (Гринтекст - ссылка как работает).

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


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

>display: table/table-row/rable-body/table-cell. Лучше всего про них почитать в спецификации если не боишься, или в какой-нибудь статье. Заставляют элементы позиционироваться как таблицу. Соответственно, можно сделать таблицу из 2 ячеек.


Господи да спеку по CSS3 я уже изнасиловал. Я спросил кто этим пользуется и как оно выглядит. А не про поведение display параметра.

>Что значит статично? position: static? Не вижу логики.


Зафиксировать ширину элемента (Шапки например) чтобы поиск отталкивался просто от нее, не трогая другие элементы, я кстати так и сделал тут: https://theknacker.github.io/Test/index2.html

>HTML все же, если честно, заточен на оформление именно текста.


Изначально да, а потом напичкали всякими API и скриптами.
>>1098595
Вот это я пытался сделать, потом займусь. Типо так?
https://tympanus.net/codrops/
#68 #1098612
>>1098468
ну шторм.
#69 #1098636
пацаны, поясните за композер. я хочу в использовать последнюю стабильную версию библиотеки, поебать какой номер версии. соответственно самый распространенный способ записи require "vendor/package": "1.*" мне не подходит. версия станет 2.0 и мне пизда. как правильно? "vendor/package": "@stable"?
#70 #1098638
>>1097858

>пых оброс бородой


в смысле?
Screenshot1
5 Кб, 471x29
#71 #1098675
>>1097438 (OP)
А зачем в этом примере про регулярные выражения (с этой страницы взято: http://archive-ipq-co.narod.ru/l1/regexp.html ) вначале пишется ([0-9]{3}), а потом ([0-9]{7}) ? Это потому-что система не поймет, если сразу написать ([0-9]{10}) ?
#72 #1098680
Чем отличаются исключения от if exit() ?
#73 #1098684
>>1097438 (OP)
Я сделал регулярное выражение для проверки автомобильного номера.

$regexp = '/([а-яё]{1})([0-9]{3})([а-яё]{2})/'

Все верно сделано?
https://regex101.com/ пишет, что да. Я протестил несколько вариантов, но вдруг что-то упусти.
#74 #1098687
>>1098684

>([а-яё]{1})([0-9]{3})([а-яё]{2})/'



флажки u и i добавь
#75 #1098690
>>1098687
$regexp = '/([а-яё]{1})([0-9]{3})([а-яё]{2})/ui'

Зачтено?
#76 #1098696
>>1098690
Я не ОП, но выглядит правильно.
#77 #1098698
>>1098696
А можешь тогда ещё глянуть на мой вопрос >>1098675 ?
#78 #1098709
Делаю задачу опа про файлообменник на slim и я в некотором отчаянии. В общем, при ajax запросе если в коде fatal error, типа E_PARSE или E_ERROR возвращается пустой ответ без какого либо текста, кода ошибки и прочего, как на первом скриншоте, т.к. в коде синтаксическая ошибка (скрин 2). При этом, c обычным http запросом все нормально, сработает обработчик, выведется 500 ошибка и все ок(скрин 3). И да, я добавил свои кастомные обработчики ошибок отдельно для xhr, отдельно для обычных запросов, но они тут не причем, даже если их отключить ситуация таже.
register_shutdown_function тоже ничего не выводит.
Естественно выставлено:
error_reporting(E_ALL);
ini_set("display_errors", 1);
ini_set('display_startup_errors', 1);

Алсо, варнинги и нотайсы выводятся нормально. Что мне с этим делать?
#79 #1098710
>>1098698
Попробую.

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

Формат номера такой 8(xxx)(xxxxxxx)

Где первая скобка - это код оператора, вторая - оставшийся номер. Благодаря этим скобкам, в учебнике ОП выводит код оператора. Без разделения на ([0-9]{3}) и ([0-9]{7}) этого бы не получилось.

Пример.
https://ideone.com/BV0u8L
434px-VenndiagramshowingGreek,LatinandCyrillicletters.svg
48 Кб, 434x418
#80 #1098711
>>1098684
Если ты про российский госномер, то "яё" в нём нет.

>ГОСТ для использования на знаках разрешены 12 букв кириллицы, имеющие графические аналоги в латинском алфавите — А, В, Е, К, М, Н, О, Р, С, Т, У и Х.


https://ru.wikipedia.org/wiki/Регистрационные_знаки_транспортных_средств_в_России
#81 #1098712
>>1098680
много чем. в первую очередь тем, что если ты используешь if exit, тебя нормальный работодатель пошлет нахуй.

а технологически отличие в том, что исключения можно ловить (т.е. обрабатывать) в одном удобном месте (или в разных для разных компонентов системы), логировать, классифицировать по степени критичности. какие-то, например, можно красиво упаковать и показать пользователю, а какие-то слать на имейл админу и пользователю показывать только заглушку "что-то временно не работает".
#82 #1098714
>>1098710
Кажется я понял. Мой пример подошел бы, если бы все цифры шли сплошняком, а ИРЛ цифры номера телефона перебиваются пробелами/дефисами и нужно сделать уступку для этого.

>>1098711
Оу. Ну, у меня машины никогда не было и я этой тонкости не знал.
#83 #1098719
>>1098709

А ты случайно content-type: application/json в неправильном ответе не получаешь? Это не может быть баг в инструментах разработчика?

Если ты отправляешь AJAX через GET, попробуй открыть этот URL просто в браузере. Если через POST - поменяй временно PHP код, чтобы он принимал GET. И посмотри, что будет - тоже белая страница или нет?

Ну и ты показал вкладку Response, но я не вижу там ни кода ответа HTTP, ни заголовков. Даже если ты в скрипте сделаешь die(), то все равно будет HTTP ответ, с заголовками. Это может быть просто баг в инструментах разработчика.

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

Также, ты можешь отправить HTTP запрос из командной строки программой curl (нужно ее установить сначала). Примерно так:

curl -v 'http://xxx/page.php?a=1'

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

Ну и всегда есть радикальный вариант. Ты можешь посмотреть, какой запрос с какими заголовками отправляет аякс на вкладке Headers, и отправить такой же запрос руками через nc или telnet (описано тут в задачах https://github.com/codedokode/pasta/blob/master/soft/web-server.md )
#84 #1098728
>>1098675

Если бы у меня была задача просто проверить, что номер состоит из 10 цифр, то скобки конечно было бы не нужны. Но у меня другая задача - проверить номер И извлечь из него код города и телефон. Для этого я группирую первые 3 и последние 7 цифр в круглые скобки. После вызова preg_match она положит код города и номер в отдельные элементы массива $m:

if (preg_match($regexp, $string, $m)) {

}

В $m[0] будет номер целиком, то есть все, что совпадает с регуляркой
В $m[1] будет часть исходного текста, которая соответствует первым круглым скобкам, то есть код города
В $m[2] будет то, что соответствует вторым круглым скобкам.
#85 #1098730
>>1098680

exit завершает скрипт. То есть, когда ты пишешь в функции exit то она завершает скрипт. У того, кто вызвал функцию, нет возможности на это повлиять и предложить другой способ обработки ошибки.

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

Подробно про исключения, с самого начала, с нуля: https://github.com/codedokode/pasta/blob/master/php/exceptions.md (нужно знать что такое объекты).
#86 #1098732
>>1098714

Нет, в моей регулярке из учебника нет "уступки" для других символов. Она написана для номеров только из цифр.
#87 #1098742
Делаю задачу с поиском по номерам телефонов.
Два вопроса:

1.Можно ли вместо -?-? ? сделать запись , типа -,(, ,? ?
2.Как вообще запихивать скобки в регулярные выражения?
#88 #1098766
>>1098712
>>1098730
Спасибо.
#89 #1098925
>>1098487

>Инструкции на сайте xdebug - они для ручной установки. То есть она пишет, какую dll тебе надо скачать, куда положить и что дописать в php.ini. Ты их выполнял?


Да

>cygwin


У меня установлен Babun, который является удобной упакованной версией cygwin

>найти пакеты по слову xdebug (pact find xdebug)


Не знаю, он ничего не находит, совсем

>Я кстати сам cygwin использую, ты можешь с его помощью потихоньку привыкать к линуксовой командной строке.


У меня Минт второй системой установлен
#90 #1098942
>>1098925

Я поискал тут https://cygwin.com/cgi-bin2/package-grep.cgi?grep=php&arch=x86_64 - действительно, xdebug нет. Нет, ну и ладно. В линуксоподобных системах должен работать pecl, который умеет скачивать любое стандартное расширение к PHP, собирать его и устанавливать. То есть pecl - это внутрненний менеджер пакетов для расширений PHP.

В cygwin он идет в пакете php-PEAR-1.10.1-1

Тебе нужно поставить этот пакет и выполнить команду, я думаю, pecl search xdebug, а затем pecl install имя-пакета.

Возможно, что пеклу понадобится компилятор и еще что-нибудь для сборки, установишь тогда его через pact.

-----

Или же ты можешь пользоваться виндовым PHP, но надо раскомментировать строку в php.ini, у тебя zend_extension закомментирован.
#91 #1098943
>>1098942
спасибо за помощь
#92 #1099024
>>1098742
Бамп вопросу.
#93 #1099028
>>1097438 (OP)
20лвл-хуй.
Завтра иду в веб студию, вакансия битрикс junior.
Сам битрикс нихуя не знаю, но вообще шарю в пыхапе( знаю такие слова как ООП MVC и даже чутка понимаю что это)
Пилил самопис на php+mysql(pdo) чуть сложнее гостевухи. понимаю jquery. Писал парсеры/грабберы на пхп(подключая либы+импорт в wordpress на кроне) вооот все, нихуя больше... вроде умею гуглить и ваще в пхп вкатился по урокам Попова в 13 лет. + могу настроить LAMP+postfix на вдске.

Требования в вакансии: Требования: Обязательные знания: php5, sql, html, css, js, опыт работы с 1C-Bitrix.
Желательно понимание работы систем контроля версий (если что, научим), опыт работы с Linux-подобными ОС.

Что будут спрашивать на собеседовании? Меня возьмут? Что говорить?
Алсо зп 20к руб хД
#94 #1099032
>>1099028
Ебать, как же торможу, если 27-ой лвл и я только полгода поработал в саппорте CMS-ки.
Аноним #95 #1099042
>>1099032
Чем занимался в саппорте cms'ки?
#96 #1099047
>>1099042
Дрочил хуи Пояснял клиентам за функционал, тестил обнаруженные ими баги, правил их (иногда наши) шаблоны + ИНОГДА (!) помогал им разобраться, что за хуйня у них с серваками.
Типа, у одного было столько бэкапов, что они съели все свободное место на VDS, но вначале юзер пенял на нас.
#97 #1099098
братики, пишу testHub на ларе и ума не приложу, как структурировать бд для него. буду рад любой помощи и продвижению в этом вопросе. ломал голову, но получалась всякая параша.
https://gist.github.com/codedokode/8733007
#98 #1099119
>>1099028

>php5


>1C-Bitrix


>jquery


Тебе 20 лет, тебе развиваться надо, а не копаться в CMS параше, тем более в такой отборной как битрикс. Ищи работу за еду, где тебя научат нормально кодить на нормальных фреймворках. С CMS ты никуда не вырастешь, а лишь научишься профессионально месить говно, которое на более сложных проектах вообще не нужно.
#99 #1099139
Пытаюсь тут понять зачем нужны исключения, есть пару вопросов, напишу их сюда.

1) Перехватывать исключения в теории можно двумя способами: неструктурно и структурно. Неструктурно — это когда мы задаем обработчик исключений в начале программы:

set_exception_handler(function ([Exception $exception) {
// Функция будет вызвана при возникновении исключения
});

То что я выделил жирным - это два тайп хинта?

2)// В try пишется код, в котором мы хотим перехватывать исключения
$users = loadUsersFromFile(...);

Это значит, что в переменную $users будут класться исключения?

3) $e->getMessage() это метод встроенного класса Exception ? И что она выводит?
#100 #1099141
>>1099098
это я. я тут придумал табличку tests, с графой questions, где json имени вопросов, типа и вариантов ответа. но тогда табличка разрастется до вселенских масштабов, нужно как-то это разрешить.
Аноним #101 #1099149
>>1099119
На сайте у этой же компании есть вакансия
Помощник веб-программиста Python
Требования:

Python, SQL, HTML, CSS, JS
Крайне желательно знакомство с framework Django или неутомимое желание его освоить.
Желательно знание Linux. Приветствуется владение системами контроля версий.

Если я завтра приду и скажу, битрикс НИУМЕЮ НИХАЧУ, можно мне ДЖАНГУ? норм тема?
алсо на питоне только говнопарсеры писал
Аноним #102 #1099151
>>1099119
ваще как вести себя на собеседовании? мне деньги нужны за квартиру платить бляяяяяя
#103 #1099153
>>1099149

>Если я завтра приду и скажу, битрикс НИУМЕЮ НИХАЧУ, можно мне ДЖАНГУ? норм тема? алсо на питоне только говнопарсеры писал


Ну да.
#104 #1099154
>>1099151
Тогда иди в сапорт, лол.
#105 #1099156
>>1099149
Зачем говорить, что ты не хочешь заниматься чем-то из вакансии А, если ты подал резюме на вакансию Б?
Если хочешь осваивать питон - осваивай, если хочешь пыху - ищи еще вакансии.
>>1099151
А если деньги нужны вот прям щас, то иди на эту работку, если она тебе эти деньги в ближайшее время гарантирует, а самообразованием тогда отдельно занимайся, только сделать это будет напорядок сложнее, т.к. практику выдумать себе придется самому.
Че ты как малой, тебе еще советов накидать как штаны надевать?
Аноним #106 #1099157
>>1099154
нету в моем городе саппорт вакансий
#107 #1099158
>>1099157
А что за город?
Аноним #108 #1099160
>>1099156
Епта, че у меня завтра спросят? Чем мне выебнуться, чтобы меня взяли джуном? Я просто никогда на собесы не ходил
Аноним #109 #1099161
>>1099158
Челябинск
Аноним #110 #1099164
>>1099160
двач дай советов мудрых
#111 #1099165
>>1099160
Шаблонизаторы знаешь? Как серваки работают?
#112 #1099168
>>1099141

>тут придумал табличку tests, с графой questions, где json имени вопросов, типа и вариантов ответа.



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

Есть тесты, есть вопросы, есть варианты ответов, они все связаны внешними ключами. Как положено.

Полистай этот урок https://github.com/codedokode/pasta/blob/master/db/databases.md#Теория-по-проектированию-БД там среди прочего упомянуты нормализация, разные полезные паттерны и наследование таблиц.

Почитай эти уроки http://jtest.ru/bazyi-dannyix/sql-dlya-nachinayushhix-chast-3.html

Подумай, какие тут есть сущности, какие у них свойства, как они связаны.

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

Ну то есть я предлагаю тебе позаниматься немного проектированием баз данных, так как у тебя тут явно не хватает опыта, и начать с простых тренировочных задачек.
#113 #1099169
>>1099160

>Чем мне выебнуться, чтобы меня взяли джуном?


Не советую делать этого в качестве джуна. Просто расскажи прямо и честно, что умеешь и чего хочешь уметь. Ты же на джуна метишь.
Спросят тебя об элементарных вещах. Почитай про протоколы, алгоритмы, подтяни SQL и самое главное закрой двач.
Аноним #114 #1099170
>>1099165
шаблонизаторы - в первый раз слышу =(
Серваки ну там бля, sudo apt-get instal lamp
POST/GET tcp/ip хуй знает
алсо я накатил тут
#115 #1099174
>>1099170

Так и быть, ОП даст тебе пасту про шаблонизаторы, выучив которую, ты, я думаю, сможешь поразить собеседующих: https://github.com/codedokode/pasta/blob/master/php/templates.md

Также, посмотри другие уроки в моем гитхабе, там полно ценной инфы, которую иначе надо по крупицам извлекать из разных источников.
Аноним #116 #1099176
>>1099174
:*
ОП-спасибо за тред, ты няша :3
#117 #1099189
>>1099170

> я накатил тут


В каком смысле?

А так, тебе может понадобится знать, что такое xslt и tpl.
#118 #1099190
Чем отличается интерфейс от абстрактного класса ? У обоих есть методы и свойства.
#119 #1099199
>>1098742
Ну анон! Ну помоги!
#120 #1099200
>>1098742
>>1099199
Первый вопрос не понял, что ты имеешь в виду. Отвечу на второй.

Скобки можно запихивать в регулярные с помощью квадратных скобок "[]"

https://regex101.com/r/TQIKNp/1/
#121 #1099207
>>1099200
Тогда я не понимаю, почему не работает выражение:
[7-8] ?-?-?[(]?([0-9]{1}) ?-?-?[)]?([0-9]{1}) ?-?-?([0-9]{1}) ?-?-?([0-9]{1}) ?-?-?([0-9]{1}) ?-?-?([0-9]{1}) ?-?-?([0-9]{1}) ?-?-?([0-9]{1}) ?-?-?([0-9]{1}) ?-?-?([0-9]{1})

Для набора:

'84951234567', '+74951234567', '8-495-1-234-567',
' 8 (8122) 56-56-56', '8-911-1234567', '8 (911) 12 345 67',
'8-911 12 345 67', '8 (911) - 123 - 45 - 67', '+ 7 999 123 4567',
'8 ( 999 ) 1234567', '8 999 123 4567'
#122 #1099213
>>1099207
Зачем тебе знаки вопроса?
#123 #1099217
>>1099213
Не, знак вопроса я использовал в контексте "это может быть, а может не быть".
#124 #1099220
>>1099217
У тебя слишком много повторений. Может быть лучше попробовать использовать символ * который может и отсутствовать и повторятся любое количество раз?
#125 #1099221
>>1099220
Может быть лучше попробовать использовать символ * который позволяет предыдущему символу отсутствовать и повторятся любое количество раз. Я исправил.
#126 #1099222
>>1099220
Я хотел максимально расширить регулярное выражение, чтобы в него входили ВСЕ случаи.

Логика была такая:
1)Либо "8", либо "7".
2)Может быть пробел, дефис, минус, скобка, а может и нет.
3)Цифра
4)См. п 2.
5)Повторять до упада.
#127 #1099227
>>1099222

>1)Либо "8", либо "7".


[78]

>2)Может быть пробел, дефис, минус, скобка, а может и нет.



>3)Цифра



>4)См. п 2.



>5)Повторять до упада.



Можно упростить эту задачу. Смотри. После 8 или 7 идет цифра. Перед ней может быть пробел, дефис, минус, скобка, а может и нет. После нее тоже. И так пока цифры номера не закончатся. То есть получается однообразное действие. Может его повторить через {10}? ( десять - это количество цифр после 7 или 8)
#128 #1099228
>>1099227
Если сделать так, то вот, что получится:

https://regex101.com/r/1s0Jab/1
#129 #1099230
>>1099228
Ты сделал просто поиск номера, а я написал вот что " После 8 или 7 идет цифра. Перед ней может быть пробел, дефис, минус, скобка, а может и нет. После нее тоже. И так пока цифры номера не закончатся. То есть получается однообразное действие. Может его повторить через {10}?"

то есть надо изменить это "([0-9]{10})" чтобы возможно был пробел, дефис, минус, скобка перед цифрой и после нее а возможно и нет.
#130 #1099233
>>1099230
Я понял.
https://regex101.com/r/1s0Jab/2

Проблема в том, что я не могу добавить что-то между ] и {10}
#131 #1099236
Аноны, как настроить DOMDocument, чтобы он читал нестандартные(пусть даже заранее известные) теги?
Есть страница с тегами типа <bodyexport>, как её прочесть?

Ошибки типа:
DOMDocument::loadHTML(): Tag noindex invalid in Entity
#132 #1099242
>>1098636
можно я по композеру бампану вопрос, раз тут все собрались
#133 #1099244
>>1099233
Я не могу понять зачем тебе это
?-?-?

Ведь есть символ * . Может попробовать лучше его использовать?
#134 #1099245
PhpUnit тесты после запуска выдают пустую строку, никакой ошибки в консоли. Если запускать из PhpStorm - 255 ошибка.
Анон, как фиксить?
#136 #1099252
>>1099246
Ну это статья про создание такого гемороя на JS, а я хочу распарсить его через DOM.
Или я чего-то не увидел?
#137 #1099254
>>1098636

Это плохая затея. Почитай про semantic versioning: https://semver.org/lang/ru/

Если библиотека обновит мажорную версию то с близкой к 100% вероятностью код сломается.

Конечно, если ты используешь composer.lock, то там само ничего не обновится, так как версии фиксируются в нем.

Что касается версий, я их наизусть не помню, и могу лишь предложить мануал https://getcomposer.org/doc/articles/versions.md

Или ты его уже прочел?

>>1099236

Ну он пишет, но тег-то создает? Ошибки подавляются с помощью libxml функций http://php.net/manual/ru/ref.libxml.php

>>1099245

255 ошибка значит по моему что программа не найдена.

А так, начинай отлаживать. Например, помести в bootstrap-файл строчку die("here\n"); и проверь, выводится она или нет. Если да - помести ее же в первый тест. ЧТобы понять, где падает.

Проверь, что phpunit вообще работает, выполнив команду вроде phpunit --help, phpunit --list-suites

У меня ощущение, что у тебя там die, либо вылетает фатальная ошибка/исключение, но отображение ошибок отключено.
#137 #1099254
>>1098636

Это плохая затея. Почитай про semantic versioning: https://semver.org/lang/ru/

Если библиотека обновит мажорную версию то с близкой к 100% вероятностью код сломается.

Конечно, если ты используешь composer.lock, то там само ничего не обновится, так как версии фиксируются в нем.

Что касается версий, я их наизусть не помню, и могу лишь предложить мануал https://getcomposer.org/doc/articles/versions.md

Или ты его уже прочел?

>>1099236

Ну он пишет, но тег-то создает? Ошибки подавляются с помощью libxml функций http://php.net/manual/ru/ref.libxml.php

>>1099245

255 ошибка значит по моему что программа не найдена.

А так, начинай отлаживать. Например, помести в bootstrap-файл строчку die("here\n"); и проверь, выводится она или нет. Если да - помести ее же в первый тест. ЧТобы понять, где падает.

Проверь, что phpunit вообще работает, выполнив команду вроде phpunit --help, phpunit --list-suites

У меня ощущение, что у тебя там die, либо вылетает фатальная ошибка/исключение, но отображение ошибок отключено.
#138 #1099255
>>1099244
Попробовал https://regex101.com/r/1s0Jab/3
Вообще не работает.
#139 #1099256
>>1098306

>Движок от Википедии: https://github.com/wikimedia/mediawiki



>// Set a dummy $wgTitle, because $wgTitle == null breaks various things


>// In a perfect world this wouldn't be necessary


>$wgTitle = Title::makeTitle( NS_SPECIAL, 'Badtitle/dummy title for API calls set in api.php' );



Лол.
#140 #1099257
>>1099254

> У меня ощущение, что у тебя там die, либо вылетает фатальная ошибка/исключение, но отображение ошибок отключено.


Отображение ошибок включено В конфиге бутстрапа есть переменная неопределенная, так вот если раскомментить эту строчку - тест выдает нотис и после нее 255.
Если тест запускать без бутстрапа и автолоадинга классов, тогда тест успешно проходит, в консоли вижу текст типа " 1 тест запущен, 1 пройден (ок)"

В бутстрапе происходит создание приложения yii 1, где-то там косяк, но не пойму где.
#141 #1099258
>>1099255
Две черточки зачем нужны? У тебя символ читает только самую правую квадратную скобку, если хочешь, чтобы читало все - нужно добавить их в круглые скобки (тут должно быть что-то)
#142 #1099261
>>1099258
Я не совсем понимаю, как это сделать.
И да, в описании статьи говорится только про "предыдущий символ". Т.е. нужно как-то по-особому скормить набор символов злобной звездочке.
#143 #1099262
>>1099254

>Ну он пишет, но тег-то создает?



И правда, спасибо.
#144 #1099264
>>1099261
Тебе нужна рега на телефонные номера? Я тут недавно изъебался, но написал регу для адресов с вариативностью расположения улиц/домов/хуйни, мб могу помочь?
#146 #1099266
>>1099265
Понятно. А как это скомбинировать с дефисами, минусами и пробелами?

>>1099264
Боюсь, это будет сложновато для меня. Я тут пытаюсь выполнить задание из учебника ОП-а с номерами телефонов.
#147 #1099269
>>1099254

>


>Это плохая затея. Почитай про semantic versioning: https://semver.org/lang/ru/


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

да, мануал композера смотрел, там как раз не нашел ответ на вопрос. а в интернетах увидел только варик @stable, что не похоже на best practice.
#148 #1099270
>>1099266

>Понятно. А как это скомбинировать с дефисами, минусами и пробелами?



Попробуй добавить их в квадратные скобки. Пробел если что значит \s
https://regex101.com/r/uhZ7xS/1
#149 #1099272
>>1099257

У phpunit есть опции -vv и --debug ( https://phpunit.de/manual/4.8/en/textui.html#textui.clioptions ) попробуй их добавить.

> создание приложения yii 1, где-то там косяк, но не пойму где.


Идешь в скрипт Юи, ставишь через строчку echo 1, echo 2 и так далее и постепенно ищешь этот exit. Может у тебя, кстати, в конфиге Юи отображение ошибок выключено?
#150 #1099276
С какого фреймворка стоит начать, если еще не было работы с ними? Что стоит почитать?
#151 #1099280
>>1099255

У тебя там написано

--[(]

Это значит пробел, за ним идет 2 минуса подряд, за ним открывающая скобка. И далее ][)]* что значит 0 или больше закрывающих скобок.

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

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

(abc)*

Это соответствует пустой строке, строке abc, abcabc, abcabcabc и так далее.

Что касается ситуации с 10 цифрами, там надо написать так:

- сначала напиши "ровно 1 скобка, минус или пробел"
- затем напиши "любое число минусов, скобок или пробелов"
- затем напиши "любое число минусов, скобок или пробелов, за ними ровно 1 цифра"
- затем возьми это в скобки и припишеи повторение 10 раз: (....){10}

>>1099270

Если уточнить, то \s - это не только пробел, но и любой другой пробельный символ (символ, который не печатается или выгодит как пустое место), например: перевод строки \n, узкий пробел, неразрывный пробел, и тд. В Юникоде штук 10 разных пробелов есть на все случаи жизни: http://jkorpela.fi/chars/spaces.html и символ \s всем им соответствует.
#151 #1099280
>>1099255

У тебя там написано

--[(]

Это значит пробел, за ним идет 2 минуса подряд, за ним открывающая скобка. И далее ][)]* что значит 0 или больше закрывающих скобок.

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

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

(abc)*

Это соответствует пустой строке, строке abc, abcabc, abcabcabc и так далее.

Что касается ситуации с 10 цифрами, там надо написать так:

- сначала напиши "ровно 1 скобка, минус или пробел"
- затем напиши "любое число минусов, скобок или пробелов"
- затем напиши "любое число минусов, скобок или пробелов, за ними ровно 1 цифра"
- затем возьми это в скобки и припишеи повторение 10 раз: (....){10}

>>1099270

Если уточнить, то \s - это не только пробел, но и любой другой пробельный символ (символ, который не печатается или выгодит как пустое место), например: перевод строки \n, узкий пробел, неразрывный пробел, и тд. В Юникоде штук 10 разных пробелов есть на все случаи жизни: http://jkorpela.fi/chars/spaces.html и символ \s всем им соответствует.
#152 #1099281
>>1099276
Читай ООП, выбирай любой фреймворк(всё равно сложно в начале будет), смотри его структуру(MVC чаще всего) и разбирайся. Официальная документация обычно хорошо написана, и гайдики по первому приложению есть.

>>1099280
Господа, я вам настоятельно рекомендую начать экранировать тире и прочие подобные символы, чтобы потом не обосраться где-нибудь. От лишнего бэкслеша ничего не сломается.
#153 #1099284
>>1099276

Может с микрофреймворка Slim или Silex ? Микрофреймворк он простой, ты можешь его код целиком прочитать если надо.

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

Потом можешь брать Юи, Ларавель или Симфони.

>>1099257

Если у тебя есть отладчик (например в IDE) и xdebug, можно попробовать запустить код из-под него и пошагово место завершения, но phpunit, может быть применяет всякие хаки и как бы от них отладчик не сломался.

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

>>1099190

Почитай урок про интерфейсы https://github.com/codedokode/pasta/blob/master/php/interfaces.md

Это вообще разные вещи и даже сравнивать их между собой не очень логично.

Алсо, если это задают на собеседовании, и ты видишь, что проваливаешься, спроси, а есть ли у них в проекте интерфейсы и абстрактные классы и как используются. И затем объясни им, что они просто их используют "чтобы были", не думая, нужны ли они на самом деле, и код от этого не становится лучше. И объясни как на самом деле их надо использовать.
#154 #1099286
Сейчас разбираю исключения и параллельно думаю над задачей о студентах. Вообщем, я решил запилить обработчик, который будет ловить все типы ошибок и исключений и выводить пользователю страницу с сообщением о технической проблеме. Я в правильном направлении думаю?
#155 #1099289
>>1099286

Да, и ведь в уроке про исключения по моему про это в конце написано, как раз про эту страницу. Логгировать только ошибку не забывай.
halp
60 Кб, 1366x768
#156 #1099329
>>1098719
Спасибо за ответ.

>А ты случайно content-type: application/json в неправильном ответе не получаешь? Это не может быть баг в инструментах разработчика?


Нет, text/html, на скрине заголовки типичного пустого ответа.

>Если ты отправляешь AJAX через GET, попробуй открыть этот URL просто в браузере. Если через POST - поменяй временно PHP код, чтобы он принимал GET. И посмотри, что будет - тоже белая страница или нет?



Пробовал отправлять форму через расширение для хрома (RESTED) в разных кодировках json, urlencoded, эффект тот же самый, пробовал разные браузеры и разные сборки (на работе XAMPP + win, дома linunx + nginx). Из всех своих потуг, понял что проблема в middleware, то есть если запрос обрабатывается middleware то ошибка не выводится, неважно где допущена сама ошибка внутри middleware или внутри самого приложения, например прямо в контроллере - выведена она не будет. Допустим мы отправляем json с формой логина, а в контроллере допущена синтаксическая ошибка, если контроллер покрыт миддлварс то получаем пустой ответ, либо если было eсho или другой вывод в middleware он будет выведен, но текста ошибки все-равно не будет. Убираем middleware и получаем нормальный синтакс еррор. Шизняк какой-то. Если будет желание разобраться, то
Вот мой файл с роутами: https://github.com/honeydev/fileshare/blob/master/app/Routes.php
Вот контроллер:
https://github.com/honeydev/fileshare/blob/master/app/Controllers/MainPageController.php
Вот миддлварсы:
https://github.com/honeydev/fileshare/tree/master/app/Middlewares
#157 #1099401
ОП, делаю testhub на yii2. При помощи чего реализовывать перетаскивание вопросов, есть ли готовое решение, для gridview например? Или велосипедить с jqueryUI?
#158 #1099418
>>1099272

> -vv и --debug


Пробую с этими ключами - опять пустая строка
#159 #1099424
>>1097438 (OP)
Сап, почаны! Помогите вникнуть в логику циклов. Третий урок из начальных. Почему, когда я присваиваю в Условии_1 $x=10000, то программа считает, что на счету через год будет та же сумма (10000) https://ideone.com/hNqkv9 ? Когда я выношу команду echo за пределы тела цикла, оно отображает действительную сумму больше миллиона через 49 лет, вкладчику 65 лет (ответ правильный). Получается, что есть разница, где писать echo: если в теле цикла, то echo выводит на экран результаты вычисления до того момента, когда условие выполняется, но почему echo за телом цикла показывает результат, когда условие цикла уже не выполняется? https://ideone.com/juIFDU
Подскажите, где я делаю ошибку?
#160 #1099427
>>1099424
А, всё понял: в первый год нужно тоже добавлять процентную ставку, т.е. в Условие_1 тоже нужно прописать $x=$pay*1.1 . Остаётся вопрос про echo. Почему echo после тела цикла выдаёт значение, при котором условие уже не выполняется?
#161 #1099428
>>1099418
Нашел проблему: у меня все приложение крутится в Докере, там порт для БД 8002 и другой пароль, я же запускал тесты вне докера с другими переменными доступа к БД на 5432 порт. И это фейлилось без ошибок, что странно.

Вообще в Yii много мест, где БД фейлится без ошибок. Уже такое было в системном логгере, когда в одно из полей поступал странный символ в неизвестной кодировке. Просто логгер ничего не логгировал и молчал.
#162 #1099454
>>1097438 (OP)
я тут случайно наткнулся на некоего чувака, который заявляет следующее:
1. заканчивать названия объектов на -er - это анти ооп http://www.yegor256.com/2015/03/09/objects-end-with-er.html

2. составные имена типа textLength - это code smell, т.к. скоуп данной переменной слишком большой http://www.yegor256.com/2015/01/12/compound-name-is-code-smell.html

3. пустые строки - это тоже code smell, т.к. они означают, что метод не соблюдает принцип единой обязанности. http://www.yegor256.com/2014/11/03/empty-line-code-smell.html

он там еще много всего заявляет, притом он вроде не из серии "ооп это грех, покайтесь господу", он там какие-то награды раздает за код, вот например им https://github.com/php-ai/php-ml (я так на него и наткнулся)

что ты думаешь об этих идеях? это полная хуйня или он прав?

просто так-то все это звучит логично, но вот например
public function validateEmail($email)
{
if (!StringUtil::isEmail($email)) {
$message = sprintf('"%s" is not a valid login', $email);
throw new InvalidArgumentException($message);
}

return true;
}
чем тут мешает пустая строка? мне наоборот кажется, они улучшают читаемость кода, а упростить его еще дальше тут хз как.

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

>и если он прав


Кто-то забыл поставить "else".
#164 #1099462
>>1099427
И ещё вопрос про программу с айфоном в кредит из того же урока. Нашёл решение задачи, но оно какое-то кривое и мне не нравится (сука, говнокод уже со старта выходит какой-то) https://ideone.com/8BK2Rq

Правильно ли я решил задачу, и можно ли её оптимизировать? Спасибо.
#165 #1099464
>>1099427
не до конца понял вопрос. что значит "после echo тело цикла выдает значение"? после echo оно уже ничего не выдает, т.к. цикл не выполняется.

если ты спрашивал "почему значение x больше миллиона, хотя в цикле указано условие чтобы икс был меньше миллиона", то у тебя же идет сначала условие выполнения ЦИКЛА x<1000000, а затем этот x умножается на 1.1. цикл поэтому и не выполняется, а значение увеличивается.

также посмотри, что такое пост-инкремент и используй лучше его, чем +1.
#166 #1099465
>>1099456
где поставить else? в примере кода?
#167 #1099467
>>1099464
Немного не в том вопрос. Почему, если echo я вставляю после тела цикла, то программа выполняет его до тех пор, пока на счету не будет больше миллиона и результатом выводит 49 лет, миллион с копейками, а если echo находится внутри цикла, то программа выдаёт 48 лет и сумму, в которой не хватает ещё одного выполнения цикла до выполнения условия х>1000000?
Песдец я криво выражаю мысли
#168 #1099469
>>1099464
А, и ещё: постинкремент- это "++"?
Почему лучше использовать именно его?
#169 #1099480
>>1099467
ты нормально выражаешь мысли, просто я тебе на этот вопрос и ответил. программа выполняет цикл всегда одно и то же количество раз независимо от того, где находится echo. echo просто выводит текущее на данный момент значение переменной, а оно разное 1. до цикла, 2. в каждой новой итерации цикла, 3. после цикла.

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

если же echo лежит внутри цикла, то там никогда не может быть x больше миллиона. соответственно и год - 48, а не 49. чтобы понять, представь, последовательность, с которой выполняется код. можешь там блок-схему нарисовать.

инкремент лучше хотя бы потому, что $y++ короче, чем $y = $y + 1. и еще потому, что это по сути не арифметическое действие, а счетчик, т.е. семантически это более верно.
#170 #1099494
>>1099480
Так получается если echo стоит внутри цикла, то цикл выполняется 10 раз, а если за циклом, то 11, но на 11 раз это уже не цикл, а простой код?
Спасибо, няша, добра тебе.
#171 #1099521
>>1099280
Что касается ситуации с 10 цифрами, там надо написать так:

- сначала напиши "ровно 1 скобка, минус или пробел"
- затем напиши "любое число минусов, скобок или пробелов"
- затем напиши "любое число минусов, скобок или пробелов, за ними ровно 1 цифра"
- затем возьми это в скобки и припишеи повторение 10 раз: (....){10}

Но я не знаю, где может быть, а может и не быть скобка! Подразумевается, что пользователь может быть поехавшим и написать хоть (911) 123 45 67, что (911) (123) (45) (67)!
#172 #1099522
>>1099494
на 11-й уже не цикл, верно.
#173 #1099559
>>1099465
Да, прикинь, возврат из оператора условия из середины функции — это что-то плохое.
Типичный же случай, когда макака начинает учить других макак.
#174 #1099565
>>1099168
братка, виды отношений знаю, работал.
я рассматривал вариант разделения сущностей на : тесты, вопросы, ответы, прописывая внешние ключи.

по поводу json:
табличка tests,
табличка questions со столбиком questions (json данных по вопросу - тип, варианты ответа).
#175 #1099572
Тайпхинты вообще везде нужно ставить, где это можно, или лучше их использовать только, когда код немного "запутанный" и лучше перестраховаться от ошибки?
нуб
#176 #1099612
>>1099454
Спасибо за чтиво. Там в комментах его называют троллем от ООП. Тоже хочу мнение ОПа на его статьи.

Ебать меня понесло из-за тебя. https://ideone.com/DazJGT
#177 #1099629
>>1099565
Во-первых, названия таблиц должны быть в единственном числе и мелкими буквами: "test", "question".
Во-вторых, не храни JSON и XML в таблицах, об этом ещё Андрей Орлов писал, в 90-е уже все грабли посчитаны были.
#178 #1099639
>>1099559
объясни, чем конкретно это плохо
#179 #1099641
>>1099629
табличка tests,
табличка questions,
табличка answers,
табличка tags,
табличка tests_to_tags

только что набросал, так более менее?
#180 #1099643
>>1099639
Тем, что это не удастся редактировать.

>>1099641
По стандарту их надо назвать так:
test
question
answer
tag
test_tag

Чтобы потом написать:
SELECT COUNT(*) FROM test LEFT OUTER JOIN question ...
#181 #1099645
>>1099629

По поводу названий предлагаю ориентироваться на этот гайд http://www.sqlstyle.guide/ru/

> Используйте собирательные имена или, что менее предпочтительно, форму множественного числа. Например, staff и employees (в порядке убывания предпочтения).



>>1099641

Нормально, но ты не учел, что бывают разные типы вопросов и ответов (числовые, текстовые, с выбором). И получается типичное наследование таблиц.
#182 #1099649
>>1099645
спасибо, я в sql почти что ноль, все хотел подтянуть, но руки не доходили. благодарю, что направил и мотивировал.

>разные типы вопросов и ответов



думал проскочить, сделав в type_answer
#183 #1099653
Читаю про шаблонизатор.
https://github.com/codedokode/pasta/blob/master/php/templates.md

Решил опробовать код и выдает ошибку
Parse error: syntax error, unexpected end of file, expecting elseif (T_ELSEIF) or else (T_ELSE) or endif (T_ENDIF) in C:\Apache24\htdocs\student\template.html on line 13

Почему?

Вот шаблон
https://ideone.com/BhgZOK с расширением .html

Вот логика
https://ideone.com/4giVWT с расширением .php
#184 #1099658
В дополнение к вопросу >>1099521
Зачем писать [0-9], если можно просто указать \d ?
#185 #1099663
>>1099653

<?php if ($result): ?>
<?php else: ?>
<?php endif; ?>

короткие теги <? уже не используются и их выключают в настройках php
#186 #1099665
>>1099663
Спасибо большое, помогло.
#187 #1099695
isset($_GET['a']) && is_numeric($_GET['a']) ? $_GET['a'] : 0;

Что означает знак вопроса двоеточие и ноль тут?
#188 #1099697
https://regex101.com/r/1s0Jab/4

У меня указано 10 итераций по принципу "вначале может быть какой-то символ, а потом число", но получается, что каждый символ съедает один подход.
Как указать, что {10} - это не для вас, молодой человек спец. символов и пробелов, а только для чисел?
#189 #1099708
И в добавок к постам >>1099697 и >>1099658 , у меня ещё один вопрос:
'+8 234 5678901', / либо 8 либо +7 /
Мне кажется этот пример из учебника неправильным. Ведь можно просто отбрасывать "+" и получать правильный номер.
#190 #1099710
>>1099708
Если у тебя номеров очень много будет, то ручками придется убирать плюсик, а это очень долго, скучно, нудно, однообразно, верно?
#191 #1099712
>>1099710
Понятно.
А как указать, чтобы без плюса было?
#192 #1099717
>>1099712
Можно заменить плюсик на ничего с помощью preg_replace или в регулярку забить +7 или 8 чтобы искало
#194 #1099723
>>1099721
Спасибо большое.
#195 #1099748
>>1099717

>+7


Просто так низя, ибо ОП сделал вариант "+ 7".
Я записал так (8|\+\ *7) , но регулярка срабатывает на +8.
#196 #1099750
>>1099748

>Просто так низя, ибо ОП сделал вариант "+ 7".



Что мешает искать +,пустое пространство которое возможно много раз или нет, семь или восемь вместо всего этого?
#197 #1099774
>>1099750
Это я уже решил. Единственная проблема - как заставить систему не тригериться на +8?
#198 #1099784
>>1099774
накалякал быстро. что-то типо этого. смотри, там идет +,пустое пространство от 0 до бесконечности, 7 ИЛИ 8 вместо всего что было до
https://regex101.com/r/jGHwK6/1
#199 #1099789
>>1099784
Лол, у тебя не работает, если использовать примеры ОП-а:

'84951234567', '+74951234567', '8-495-1-234-567',
' 8 (8122) 56-56-56', '8-911-1234567', '8 (911) 12 345 67',
'8-911 12 345 67', '8 (911) - 123 - 45 - 67', '+ 7 999 123 4567',
'8 ( 999 ) 1234567', '8 999 123 4567'

incorrectNumbers = [
'02', '84951234567 позвать люсю', '849512345', '849512345678',
'8 (409) 123-123-123', '7900123467', '5005005001', '8888-8888-88',
'84951a234567', '8495123456a',
'+1 234 5678901', / неверный код страны /
'+8 234 5678901', / либо 8 либо +7 /
'7 234 5678901' / нет + /
#200 #1099805
>>1099789
Это понятно, ведь я взял только +7|8
#201 #1099811
>>1099805
А, подожди. У тебя вообще не было варианта +8.
#202 #1099814
>>1099811
Конечно, он ведь неправильный.
#203 #1099819
>>1099814
Хм, может я тогда неправильно выразился.
В общем, мне нужно как-то отсечь вариант +8.
#204 #1099820
>>1099819
preg_match использовать можно.
#205 #1099822
>>1099820
Я на сервисе regex101.com пробую. Или это не лучший вариант?
#206 #1099831
>>1099822
Верный. На нем ты составляешь регулярное выражение. preg_match проверяет, соответствует ли данное значение шаблону, который мы написали и если все окей, то возвращает 1.

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

https://ideone.com/3pTSSD
#207 #1099856
У меня css (бутстрап, подключал не через CDN, а через файлы) на локальном сервере грузится где-то одну-две секунды. Это конечно не такая большая пауза, чтобы она меня бесила, но все же. Это нормально?
#208 #1099864
Как лучше отправлять данные на сервер через get или post ?
#209 #1099866
#210 #1099867
>>1099831
Хм, т.е. ответ от сервиса релевантный.
#211 #1099877
>>1099867
Если я хочу создать две формы, которые считывают числа и выводят их сумму, то что лучше?

формы
https://ideone.com/leEIwL

скрипт
https://ideone.com/vyBa8T
#212 #1099882
>>1099877
Если что я новичок. Сделал задачу про вектор, но ужаснулся студентов и не знаю, что дальше делать
#213 #1099907
У меня тут вопрос.

https://ideone.com/7g7sdm

Почему вызов функции работает до объявления функции?
#214 #1099919
>>1099907
Короткий ответ: Файл не исполняется в лоб построчно. Если функция в этом же файле, PHP ее найдет.
Вот это уже упадет с ошибкой:

<?php
foo();
require_once "file_with_foo.php";
#215 #1099926
>>1097603
Тебе никто не отвечает, потому что ты не сформулировал вопрос. Более того, во всём твоём посте даже знака вопроса нет, шизик )))
#216 #1099927
>>1097643
Есть, у нашего уборщика
#217 #1099928
>>1098043
За два месяца реально вкатиться только в двухмесячного вкатывальщика, нодискасс.
#218 #1099930
>>1098468
Лучше сразу приучить себя к IDE, из бесплатных -- Eclipse, из платных -- phpStorm
IMG20171127195555030
57 Кб, 700x345
#219 #1099934
>>1099139

> 1)


Здесь написано, что параметром функции1 set_exception_handler должно быть имя функции2, в свою очередь принимающей в качестве параметра объект типа 'исключение'

Мануал с примерами: http://php.net/manual/ru/function.set-exception-handler.php

> 2)// В try пишется код, в котором мы хотим перехватывать исключения


> $users = loadUsersFromFile(...);



> Это значит, что в переменную $users будут класться исключения?



Нет. В блоке try { } обычный код твоей программы, который должен выполняться без ошибок. Обработка исключений(ошибок) -- в блоке catch {}

> 3) $e->getMessage() это метод встроенного класса Exception ?


Да

> И что она выводит?


http://php.net/manual/ru/exception.getmessage.php

<?php
try {
throw new Exception("Какое-нибудь сообщение об ошибке");

} catch(Exception $e) {
echo $e->getMessage();

}
IMG20171127195555030
57 Кб, 700x345
#219 #1099934
>>1099139

> 1)


Здесь написано, что параметром функции1 set_exception_handler должно быть имя функции2, в свою очередь принимающей в качестве параметра объект типа 'исключение'

Мануал с примерами: http://php.net/manual/ru/function.set-exception-handler.php

> 2)// В try пишется код, в котором мы хотим перехватывать исключения


> $users = loadUsersFromFile(...);



> Это значит, что в переменную $users будут класться исключения?



Нет. В блоке try { } обычный код твоей программы, который должен выполняться без ошибок. Обработка исключений(ошибок) -- в блоке catch {}

> 3) $e->getMessage() это метод встроенного класса Exception ?


Да

> И что она выводит?


http://php.net/manual/ru/exception.getmessage.php

<?php
try {
throw new Exception("Какое-нибудь сообщение об ошибке");

} catch(Exception $e) {
echo $e->getMessage();

}
#220 #1099935
>>1099454
Выебоны не по делу, важен результат
jGMBMjF3H4
125 Кб, 750x927
#221 #1099938
>>1099934
>>1099139
Короче, блэт,

<?php
try {
//Тут код нашей программы
$a = 2*2;

//Который мы проверяем
if ( $a !== 4 )
throw new Exception("Пиздос!");

} catch(Exception $e) {
//А тут обработка ошибок. Можно показать её, записать в лог, отправить себе на имейл и т.д.
echo $e->getMessage();

//в некоторых случаях можно попытаться её исправить
$a = 4;

//или остановить программу
exit(1);

}
111
6 Кб, 371x271
#222 #1099976
Анончики, расскажите глупому почему это не работает?
#223 #1099992
>>1099976
Тебе нужна функция array_key_exists(). in_array() ищет по значениям, а не по ключу.
#224 #1099993
>>1099992
Спасибо, добрый анон.
#225 #1099994
>>1099831
Понятно.
Так-с, теперь у меня 2 вопроса:

1.Как логически указывается, чтобы пробел/дефис/что-то ещё не считалось за цифру?
2.Как указывать жесткое "или", чтобы не срабатывало на +8?
#226 #1100012
>>1099927
Что за уборщик?
#227 #1100029
>>1100012
Garbage Collector
#228 #1100036
>>1100012
Убирается в офисе, что непонятного?
#229 #1100037
>>1097643
у меня есть опыт работы джуниором в дс без переезда лол. думаю, имеет смысл сначала прокачаться по максимуму (может, что-то на фрилансе поделать), сделать какое-то портфолио на гитхабе, потом приехать в дс, снять комнатку и уже параллельно искать работу. а получить оффер из дс, находясь в мухосранске, мне кажется, очень сложно. надо быть прямо на голову выше местных дсшных студентиков и перекатившихся.
#230 #1100040
>>1097643
плюс в дс есть определенные конторы-потогонки, которые набирают студентов работать по 12 часов в день за гроши и типа их "выращивают". они могут заинтересоваться чуваком, который будет полностью от них зависим. я в такой работал, это на любителя, хотя и прокачивает хорошо.
#231 #1100062
>>1100040
ГОВНОКОДИШЬ ЗА ЕДУ
@
ПО ВЕЧЕРАМ УБЕЖДАЕШЬ СЕБЯ, ЧТО ХОРОШО ПРОКАЧАЛСЯ
#232 #1100074
>>1100062
Будет что внукам рассказать!
#233 #1100075
>>1100062
не то чтобы говнокодишь, там большой проект и нормальный аудит. через год такой работы я пошел на другую за норм бабки
#234 #1100079
>>1100037
У меня денег только на первый месяц проживания в ДС. А перекатиться и слить сразу все накопления на хату и при этом ещё и не получить работу будет уж слишком обидно. Но спасибо за ответ.
>>1100040
Я на большее и не рассчитываю.
изображение
9 Кб, 857x142
#235 #1100089
Назвал переменные логично, но они трудночитаемы. Отличаются только единственным/множественным числом, то-есть маленьким и неприметным символом "s". Как можно было бы сделать лучше
#236 #1100091
>>1100089

Думаю, подойет просто options или names.
#237 #1100092
>>1100089

Алсо, array_diff/array_intersect.
#238 #1100101
>>1099994
Ещё один бамп вопросу
#239 #1100105
>>1099994

>Как логически указывается, чтобы пробел/дефис/что-то ещё не считалось за цифру


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

>Как указывать жесткое "или", чтобы не срабатывало на +8?


(+7|8)
Андвансед левел, чтобы не засорять бэкрефы - (?:+7|8)
Теперь результат совпадения этой подмаски не будет сохранен в массиве $matches.
#240 #1100106
>>1100079
ну пойдешь курьером поработаешь месяц, если не получится. а потом работу джуном в дс не так сложно найти, если знания есть.
#241 #1100110
>>1100105

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


Я написал, может быть херовое, но такое выражение:
[- \(-\(\)\d]{10})
Т.е. вначале может быть, а может и не быть знак, а потом идет число.
Система засчитывает любой символ, как одно из 10-ти значений, которые нужно найти.

Вот скрины. +8 проглатывается.

>>1100079

>У меня денег только на первый месяц проживания в ДС


Ну так иди в какой-нить саппорт по-приличнее, чтобы
1)Опыт работы в ДС появился.
2)Бабло было на поиски.
Но да, может случиться "проклятье острова Баунти".
#242 #1100116
>>1099994
Вдогонку. Чтобы не трахаться с пробелами и дефисами, просто сделай strtr($phoneNumber, [' ' => '', '-' => '', '(' => '', ')' => '']); перед сравнением с регуляркой.
А то я заметил, что + 7 у тебя тоже должно матчится. Да и к тому же, ты не сможешь предугадать, куда твой юзер поставит пробелы, дефисы и даже скобки.

https://ideone.com/uwW1i1
image
44 Кб, 477x652
#243 #1100125
>>1100110
Но если ты хочешь заморочиться и решить все регулярками, то даю подсказку.
image
32 Кб, 268x622
#244 #1100128
>>1100110
Кстати, в реальной жизни может быть так и даже так. ОП как-то не подумал.
#245 #1100148
>>1099559
ага, в симфони наверное тоже пишут и аудируют код макаки
https://github.com/symfony/symfony/blob/ed2222bb855fe3006509d4570ab0bc9f78b5b69d/src/Symfony/Component/Workflow/Workflow.php#L159

только вася с двача знает как правильно.
#246 #1100152
>>1099559
прикинь, возврат и завершение скрипта с помощью throw - это разные вещи
#247 #1100164
>>1097438 (OP)
За месяц учёбы по учебнику ОПа через день по вечерам, только закончил регулярки. Я совсем глупый или это норм?
#248 #1100168
Я правильно понимаю, что фреймворки пишутся в стиле ООП?
изображение
251 Кб, 1940x600
#249 #1100171
Скоро! Очень скоро! https://symfony.com/4
#250 #1100173
>>1100091
Так не получится, ибо у меня есть еще одни опции - опции из файла. Вот и получается $fileOptions и $optionsInComplectationsName
>>1100092
А вот за это спасибо, че-то не вспомнил про них
#251 #1100182
>>1100164
Нормально, просто у тебя нет временных рамок. Если бы ты работал и тебе на работе дали такое же задание с указанием "сделать к вечеру", ты бы скорее всего сделал его к вечеру или к ночи.
#252 #1100188
Как сделать задачу я тебя помню на куки? Я прочитал в мануале, но все равно что-то не понимаю
#254 #1100222
>>1100210

>time() + 6


Твоя кукиса будет жить 6 секунд. А так - правильно.
#255 #1100223
>>1100210
btw будет совсем правильно поставить флаг httpOnly = true. Будет больно, потому что он в самом конце необязательных параметров.
#256 #1100227
>>1099926
>>1097603
В чем проблема? Почему из цикла выходит? Должно же быть все нормально
#257 #1100234
>>1100223

>Будет больно


Подробнее?

>>1100222
Спасибо.
#258 #1100245
>>1100234

>Подробнее?


>потому что он в самом конце необязательных параметров

#259 #1100246
#260 #1100248
>>1100210

Изучи, какие параметры есть у кук.

Ты не указал параметр path. Это значит, что для куки он будет выставлен по умолчанию как путь к скрипту - например, /folder/script.php. Когда у тебя один скрипт, это не проблема, но когда их много, кука будет видна не везде.

Лучше сразу привыкать ставить /, чтобы кука была доступна на всем сайте, а не только в одном скрипте.
#261 #1100251
>>1100248
Спасибо большое. Верно теперь?
https://ideone.com/g14IRt
#262 #1100259
>>1100171
а еще завтра все обновляем прод сервер на 7.2
#263 #1100262
>>1100259
а мы уже...
#264 #1100266
>>1100259
Лол, в треде 7.1 сегфолтится, а вы еще и релиз кандидат накатываете? Храбрые вы парни.
15069364463940
31 Кб, 400x300
#265 #1100274
А-а-а-а-а, задача про гостиницу кажется такой простой, но хрен там плавал. Второй вечер решаю, ни одну возможность еще не реализовал, а кода уже на 400 строк.
#266 #1100276
>>1100266
>>1100262
полёт совершенно нормальный, на кучке из нескольких проектов, как на вирт. хостинге (sprinthost), так и у себя на колокейшнах, нах
#267 #1100279
>>1100274
Реквестирую задачу про гостиницу
#268 #1100280
Двач, так вышло, что нужно за 2 недели осилить приложение реализующее функционал домашней бухгалтерии.
Все бы ничего, но php и web в целом до этого не трогал вообще, сейчас сижу и не понимаю за что хвататься-то, как хоть что-то сделать, помогите советом
#269 #1100281
>>1100276
добавлю: всё писалось изначально на 7,
если на 5 -- может быть, и возможны проблемы, мы не знаем
#270 #1100282
>>1100280
а что трогал?
почему теперь именно РНР?
#271 #1100283
>>1100279
[quote user="codedokode"]
Есть Гостиница, в ней есть Номера. Для каждого Номера известен его номер,

количество Гостей, которое в него влезет, а также цена за сутки. В Гостиницу

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

- получить список свободных номеров на определенную дату
- получить список свободных номеров, которые будут свободны в определенный

диапазон дат (от A до B)
- дан список Гостей и диапазон дат, в которые они хотели бы заселиться. Необходимо

подобрать им самый дешевый и маленький Номер, который их вместит и который

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

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

приехало 3 Гостя, но все 3-местные номера заняты и мы выделяем 2 2-местных, или 3

1-местных или 1-местный + 2-местный.
- зарегистрировать проживание данных Гостей в данных Номерах на данный период
- получить историю заселения Номера (кто в нем когда жил)
- получить историю заселения Гостя (в каких номерах он жил)
- получить статистику доходов Гостиницы за данный диапазон дат (в день A отдель

заработал X тугриков, в день B - Y тугриков и так далее)

-------------------

Сделать достаточно только ООП-модель, то есть классы (но конечно можно для

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

представления даты в PHP есть класс DateTimeImmutable (

http://php.net/manual/ru/class.datetimeimmutable.php ), почему я рекомендую его, а

не DateTime, подумай сам.
[/quote]

Правда, я еще реализую код, проверяющий все это - строящий отель, заселяющий гостей, и т.д.
#271 #1100283
>>1100279
[quote user="codedokode"]
Есть Гостиница, в ней есть Номера. Для каждого Номера известен его номер,

количество Гостей, которое в него влезет, а также цена за сутки. В Гостиницу

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

- получить список свободных номеров на определенную дату
- получить список свободных номеров, которые будут свободны в определенный

диапазон дат (от A до B)
- дан список Гостей и диапазон дат, в которые они хотели бы заселиться. Необходимо

подобрать им самый дешевый и маленький Номер, который их вместит и который

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

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

приехало 3 Гостя, но все 3-местные номера заняты и мы выделяем 2 2-местных, или 3

1-местных или 1-местный + 2-местный.
- зарегистрировать проживание данных Гостей в данных Номерах на данный период
- получить историю заселения Номера (кто в нем когда жил)
- получить историю заселения Гостя (в каких номерах он жил)
- получить статистику доходов Гостиницы за данный диапазон дат (в день A отдель

заработал X тугриков, в день B - Y тугриков и так далее)

-------------------

Сделать достаточно только ООП-модель, то есть классы (но конечно можно для

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

представления даты в PHP есть класс DateTimeImmutable (

http://php.net/manual/ru/class.datetimeimmutable.php ), почему я рекомендую его, а

не DateTime, подумай сам.
[/quote]

Правда, я еще реализую код, проверяющий все это - строящий отель, заселяющий гостей, и т.д.
#272 #1100284
>>1100282
а трогал всякий десктоп, в принципе, подобие того, что просят делал, но на шарпе с wpf-ом.
А PHP потому что пытаюсь податься на стажировку и просят там тестовое именно на PHP
someApprentice #273 #1100285
>>1097368

>Насчет данных с paypal - не знаю, скорее всего нет. Но думаю, они будут доступны для американской разведки.


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

>Авторское право © PayPal, 1999–2017 гг. Все права сохранены. Общество с ограниченной ответственностью Небанковская кредитная организация «ПэйПал РУ». Юридический адрес: Российская Федерация, 125047, Москва, ул. Бутырский Вал, д. 10. Деятельность осуществляется на основании лицензии Центрального банка России № 3517-К.



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

>> Мне видеться использовать JSON-объект с свойствами каждого вложения.


>Скорее всего что-то такое и было.


Я думаю, вот можно было для какой-нибудь сущности иметь колонку temp с типом JSON и сохранять туда какие-нибудь второстепенные/временные/неважные данные. Можно былоо бы гибче обращаться с записями. Как вам идея?

>- кеширование - кеш снижает нагрузку на чтение из БД, при условии, что запросы повторяются, и что обновление данных происходит реже, чем чтение.


Можете посоветовать какой-нибудь софт/библеотеку для этого?

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


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


>


>А так, сохранять стоит все, что есть.


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

Но я только что понял, что такой вопрос нужно решать на стадии миграции.
someApprentice #273 #1100285
>>1097368

>Насчет данных с paypal - не знаю, скорее всего нет. Но думаю, они будут доступны для американской разведки.


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

>Авторское право © PayPal, 1999–2017 гг. Все права сохранены. Общество с ограниченной ответственностью Небанковская кредитная организация «ПэйПал РУ». Юридический адрес: Российская Федерация, 125047, Москва, ул. Бутырский Вал, д. 10. Деятельность осуществляется на основании лицензии Центрального банка России № 3517-К.



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

>> Мне видеться использовать JSON-объект с свойствами каждого вложения.


>Скорее всего что-то такое и было.


Я думаю, вот можно было для какой-нибудь сущности иметь колонку temp с типом JSON и сохранять туда какие-нибудь второстепенные/временные/неважные данные. Можно былоо бы гибче обращаться с записями. Как вам идея?

>- кеширование - кеш снижает нагрузку на чтение из БД, при условии, что запросы повторяются, и что обновление данных происходит реже, чем чтение.


Можете посоветовать какой-нибудь софт/библеотеку для этого?

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


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


>


>А так, сохранять стоит все, что есть.


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

Но я только что понял, что такой вопрос нужно решать на стадии миграции.
#274 #1100286
>>1100283
Спасибо. Я когда вектор говношлепал тоже вышло много строчек а толкового ничего. Переделывал полностью раза три все с горящим пердаком.
#275 #1100287
>>1100284
Для специалиста (но не факт, что тебя, как я понял) по шарпу освоить синтаксис PHP -- не такая уж большая проблема, значит -- кури в первую очередь официальный мануал: http://php.net/manual/en/

Тебе понадобятся азы (переменные, приведение типов, функции, строковые функции, ООП),
и, если просят работу с БД, то раздел PDO.
#276 #1100288
>>1100286
трудна жизнь вкатывальщика-2018, ничего не поделать
#277 #1100291
>>1100288
Не поспоришь. Но ничего. Мой максимализм еще никому не удалось победить!
image
42 Кб, 800x517
#278 #1100297
ОП, хочу уточнить.

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



На данный момент я пренебрегаю ценой, но селю каждую партию гостей в минимально маленький номер.
Допустим, у меня два номер, за 1000 тугриков для двоих, и за 500 для троих. И две группы гостей - двое и трое. Я селю двоих в номер за 1000 и троих за 500. То есть двое могли сэкономить, засели я их в номер для троих, но тогда бы я не смог заселить группу из троих человек.
Я правильно понимаю, что подразумевается, я должен заселить максимальное количество человек, а не экономить им деньги и оставлять кого-то на улице?
#279 #1100303
>>1100297
думай с позиции мкс. прибыли гостишки
#280 #1100305
>>1100303
Тогда я все правильно делаю.

Но есть еще вопрос.
Допустим, у меня есть два трехместных номера, один за 300, другой за 500. И две заявки, номер 0 - на троих персон и номер 1 - на одного. Сейчас я обрабатываю их по порядку, и выходит, что три человека заселятся в номер за 300, а один - за 500. Но по факту мне пофиг, кого куда селить в такой ситуации, бабло я получу, а вот бедный одиночка будет платить 500 тугриков, а троица - по сотне с носа.
Должен ли я проявлять человечность и в таком случае селить одиночку в номер за 300?
1511831055001
5 Кб, 448x357
#281 #1100306
Какие сейчас лучшие сайты по фрилансу? Простой интернет-магазин могу сделать, лендинги и другую хуйню(если пиздить дизайны).
#282 #1100308
>>1100305
Накой ты за них вообще решаешь? Выдавай им варианты, пусть сами думают куда им заселяться.
#283 #1100309
>>1100308
сел писать искусственный интеллект
#284 #1100313
>>1100128
>>1100125
Никак не могу найти, что означает ":" в твоем примере.
#285 #1100314
Играюсь тут с браузерами. Написал js скрипт-приветствие в форму, оно работает, лол. Это имеется в виду, когда говорится, что можно так украсть кукисы и прочие данные? Как можно запретить вводить скрипт в эштиэмэль формы?
#286 #1100322
>>1100313
Я же объяснил в >>1100105.
?: - именно в такой комбинации - не запоминать результат в скобках. Всегда пишется сразу после открывающей скобки. Можешь безболезненно убрать эти символы, тут это лишнее, если тебе нужно просто сравнить строку с регуляркой. У меня просто привычка не засирать массив с результатами, пишу на автомате.
#287 #1100324
>>1100314

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


Да.

>Как можно запретить вводить скрипт в эштиэмэль формы?


Никак, ты должен применять htmlspecialchars($text) при выводе пользовательских текстов.
#288 #1100325
>>1100324
Спасибо за ответ.

> ты должен применять htmlspecialchars($text) при выводе пользовательских текстов.



Можно пример пожалуйста?
#289 #1100326
>>1100322

>бэкрефы


Я честно пытался загуглить, что означает это понятие. Количество итераций?
#290 #1100328
>>1100325

>Можно пример пожалуйста?


echo htmlspecialchars('<script>alert('hi');</script>');
Результат отобразится как простой текст.

>>1100326
Back references, обратные ссылки. В них по умолчанию сохраняется содержимое скобок. Они же кладутся в массив $matches. В регулярке доступны в виде $цифра либо \цифра. Например, ловим парные html-теги: /<(div|a|b)>.*?</$1>/g.
Если не понял, ни ссы, еще поймешь. С регулярками всегда так.
#291 #1100329
>>1100328
Фикс примера: echo htmlspecialchars("<script>alert('hi');</script>");
#292 #1100331
>>1100328

>htmlspecialchars('<script>alert('hi');</script>');



Спасибо. А как сделать если через форму?

Допустим у меня вывод формы echo $_GET["text"];

он все равно выводит нежданный скрипт
спасибо
3 Кб, 340x199
#293 #1100332
>>1100331
Извиняюсь, я понял. Все. Выводит нормально
#294 #1100335
>>1100274
>>1100286

Советую обязательно решить. Ваши мучения не пропадут даром. В большинстве учебников, а тем более в видеокурсах на ютубе, вам никто нормально ООП не объяснит. В лучшем случае вас заставят вызубрить дословно 3 определения принципов ООП (инкапсуляция/наследование/полиморфизм, и может быть, SOLID), которые вы не поймете, и расскажут как объявить класс. А на задачах про Гостиницу и про Продюсерское Агенство вы более-менее сможете увидеть реальное применение ООП, как оно облегчает написание кода за счет разбиения на отдельные классы (если думаете, что не облегчает, попробуйте без классов решить). Научитесь проектировать ООП-модель для задачи.

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

>>1100305

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

> Должен ли я проявлять человечность и в таком случае селить одиночку в номер за 300?


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

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

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

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

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

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

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

Сделать это можно попробовать так:

- берем K заявок
- для каждой заявки находим все варианты заселения. Ну то есть N номеров, куда можно поселить этих гостей.
- для каждой пары (1 заявка - 1 вариант заселения) вычисляем очки. Формула для вычисления очков подбирается так, чтобы можно было численно измерить, какой вариант "лучше", "выгоднее" для нас:
-- при прочих равных, чем меньше плата с группы за номер, тем больше очков (то есть лучше предложить номер за 300, чем за 500)
-- при прочих равных, чем меньше плата с 1 человека, тем лучше (лучше заселить одиночку в номер за 300, а группу в номер за 500, чем наоборот)
-- при прочих равных, чем меньше остается в номере свободных мест, тем лучше (одиночку лучше всего селить в одноместный номер)

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

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

Казалось бы, задача решена.

Но тут, увы, грабли нам подсовывает комбинаторика. https://ru.wikipedia.org/wiki/Комбинаторика

Если у нас K заявок и N номеров, то число возможных распределений (вариантов заселения) - это размещение из N по K : https://ru.wikipedia.org/wiki/Размещение

И так как в формуле использован факториал, то при сотне номеров и десятке заявок числа получаются гигантские (100! / 90! = 100 x 99 x 98 x 97 ... 91 ~ 1 x 10^20).

Потому предлагаю придумать способ попроще. Например, такой:

- берем N заявок
- для каждой заявки находим K подходящих номеров, считаем очки для каждого варианта и получаем отсортированный список, от наилучшего к наихудшему варианту.
- теперь мы имеем N заявок и N отсортированных списков предложений номеров
- берем из каждого списка предложений первый вариант (лучший внутри списка) и ищем среди них лучший по очкам. Находим, заселяем. Убираем эту заявку и список предложений для нее. Удаляем занятый номер из остальных списков (или игнорируем его впредь).
- затем берем из оставшихся первых элементов списков следующий, чуть похуже. Заселяем, удаляем заявку и список.
- и так далее, пока списки не кончатся и все гости не будут заселены (либо пока не закончатся номера и списки предложений не станут пустыми)

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

Что остается сделать тебе:

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

Как, справишься? Заодно поучишься оптимизации.

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

Если тебя вдруг заинтересовала эта тема, и хочется знать еще больше - гугл в помощь: https://www.google.ru/search?q=методы+оптимизации&newwindow=1&dcr=0&gbv=1&sei=JjQfWqvDKoLE6QTwzq-ADw

>>1100309

Тем оптимизации пересекается с машинным обучением, так что ты недалек от истины.
#294 #1100335
>>1100274
>>1100286

Советую обязательно решить. Ваши мучения не пропадут даром. В большинстве учебников, а тем более в видеокурсах на ютубе, вам никто нормально ООП не объяснит. В лучшем случае вас заставят вызубрить дословно 3 определения принципов ООП (инкапсуляция/наследование/полиморфизм, и может быть, SOLID), которые вы не поймете, и расскажут как объявить класс. А на задачах про Гостиницу и про Продюсерское Агенство вы более-менее сможете увидеть реальное применение ООП, как оно облегчает написание кода за счет разбиения на отдельные классы (если думаете, что не облегчает, попробуйте без классов решить). Научитесь проектировать ООП-модель для задачи.

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

>>1100305

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

> Должен ли я проявлять человечность и в таком случае селить одиночку в номер за 300?


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

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

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

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

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

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

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

Сделать это можно попробовать так:

- берем K заявок
- для каждой заявки находим все варианты заселения. Ну то есть N номеров, куда можно поселить этих гостей.
- для каждой пары (1 заявка - 1 вариант заселения) вычисляем очки. Формула для вычисления очков подбирается так, чтобы можно было численно измерить, какой вариант "лучше", "выгоднее" для нас:
-- при прочих равных, чем меньше плата с группы за номер, тем больше очков (то есть лучше предложить номер за 300, чем за 500)
-- при прочих равных, чем меньше плата с 1 человека, тем лучше (лучше заселить одиночку в номер за 300, а группу в номер за 500, чем наоборот)
-- при прочих равных, чем меньше остается в номере свободных мест, тем лучше (одиночку лучше всего селить в одноместный номер)

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

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

Казалось бы, задача решена.

Но тут, увы, грабли нам подсовывает комбинаторика. https://ru.wikipedia.org/wiki/Комбинаторика

Если у нас K заявок и N номеров, то число возможных распределений (вариантов заселения) - это размещение из N по K : https://ru.wikipedia.org/wiki/Размещение

И так как в формуле использован факториал, то при сотне номеров и десятке заявок числа получаются гигантские (100! / 90! = 100 x 99 x 98 x 97 ... 91 ~ 1 x 10^20).

Потому предлагаю придумать способ попроще. Например, такой:

- берем N заявок
- для каждой заявки находим K подходящих номеров, считаем очки для каждого варианта и получаем отсортированный список, от наилучшего к наихудшему варианту.
- теперь мы имеем N заявок и N отсортированных списков предложений номеров
- берем из каждого списка предложений первый вариант (лучший внутри списка) и ищем среди них лучший по очкам. Находим, заселяем. Убираем эту заявку и список предложений для нее. Удаляем занятый номер из остальных списков (или игнорируем его впредь).
- затем берем из оставшихся первых элементов списков следующий, чуть похуже. Заселяем, удаляем заявку и список.
- и так далее, пока списки не кончатся и все гости не будут заселены (либо пока не закончатся номера и списки предложений не станут пустыми)

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

Что остается сделать тебе:

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

Как, справишься? Заодно поучишься оптимизации.

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

Если тебя вдруг заинтересовала эта тема, и хочется знать еще больше - гугл в помощь: https://www.google.ru/search?q=методы+оптимизации&newwindow=1&dcr=0&gbv=1&sei=JjQfWqvDKoLE6QTwzq-ADw

>>1100309

Тем оптимизации пересекается с машинным обучением, так что ты недалек от истины.
#295 #1100336
>>1100314

Я написал урок специально по этой теме https://github.com/codedokode/pasta/blob/master/security/xss.md

Там и теория, и методы защиты.
#296 #1100342
>>1100305

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

Допустим, у нас 10 заявок и 100 номеров.

Наша цель - закрасить 10 клеточек в таблице так, чтобы они дали максимальную сумму.

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

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

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

Так понятнее, надеюсь?
#298 #1100346
>>1100335
Ого, слишком сложно, я все-таки больше ООП хочу выучить.
На данный момент я реализовал:
1. Чтобы всегда заселять максимум народа не дробя группы (дробление еще не сделал).
2. Чтобы мелкие группы получали N-местные номера дешевле, чем N-местные номера для больших групп. То есть двое арендуют трехместный за 300, а трое за 500, и никогда наоборот.

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

Так и сделаю. На глаз тут будет работать принцип Парето - 20% усилий на разработку алгоритма (от системы с баллами) покроет 80% случаев несправедливости.
#299 #1100347
>>1100297

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

Алсо, если ты попробуешь нарисовать таблицу с очками, как я написал выше, то выбор будет очевиден.

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

Эх, математика бы сюда, разбирающегося в методах оптимизации. .. Эй, аноны-математики из /pr/, смотрите, какая у нас задача интересная получилась.
#300 #1100348
>>1100346

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

Ты попробуй нарисовать таблицу, как я предложил, на ней твои ситуации очень наглядно выглядят.
#301 #1100349
>>1100342
Да, понятно. Я уже сейчас сортирую вместимости + оплате, то есть 1 - 100, 1 - 130, 2 - 90, 2 - 100 и так далее, а группы - по количеству. Но при этом вместимость играет ключевую роль. То есть я отправлю человека в одноместный номер, если он один, даже если он стоит 100500 денег.
Как оценивать в баллах вместимость? Я не представляю.
Тут игра на два фронта. Клиент хочет дешевле, а я хочу вселить больше. Разумеется, я и вселяю как можно больше. Но если я могу вселить всех по минимальному прайсу, не оставив никого на улице, я сделаю так в первую очередь. Вот.
Конечно, может случится ситуация, что я вселил одиночку в четырехместный номер за 100, а на улице осталась группа из четырех человек и одноместный номер за 1000. И в таком случае, хм, можно попробовать заселить того, кто на улице в минимально дешевый занятый номер на 4 персоны, жильцов того номера попробовать заселить в пустой номер, если не выходит, то заселить в минимально дешевый занятый номер, а других переселить в пустой номер, но если не выходит... И так далее, пока не заселю всех! Бинго! Спорю, это самый выгодный алгоритм!
#302 #1100352
>>1100349

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

> Как оценивать в баллах вместимость? Я не представляю.


Если остается 0 пустых мест в номере = 1000 баллов
Если одно = 500 баллов
Если два = 250 баллов
...

Или использовать отрицательные баллы: -100 x (число незанятых мест в номере).

> если не выходит, то заселить в минимально дешевый занятый номер, а других переселить в пустой номер, но если не выходит... И так далее, пока не заселю всех!


Так (пробуя менять местами) ты в неудачном случае придешь к полному перебору. То есть будешь перебирать все способы закрасить 10 клеток в описанной выше таблице, а таких комбинаций там порядка 10 ^ 20 как я описал выше.

Так как в варианте "пробуем менять местами" я не вижу какой-то защиты от большого числа таких попыток.
#303 #1100353
>>1098161

>Здесь не очень понятно, зачем этот класс. Если он для того, чтобы хранить объект mysqli, то что мешает его хранить просто в переменной без всяких ConnectDb? Также, непонятно, зачем в нем поля вроде db_address? Где и как они будут использоваться?


Класс для соединения с бд. А где хранить хранить этот объект, как метод в Util? Или как? Как просто переменную, если да то где? Здесь не понятно. db_adress и подобные нужны были для того чтобы держать в них информацию о конфиге, понял, что можно сразу из массива pasre_ini_file пихать в mysqli

>Как ты выбираешь, что поставить, public или private?


Поставил private, паблик для вызова снаружи класса и наследников, приват только для опредленного класса

>Пропусти код класса через phpformatter.com


Сделал

>но нет проверки, что она содержит разрешенное значение, а значит тут может быть SQL инъекция.


Теперь есть

>Это можно сделать одной командой вместо цикла.


Как?

>Почему не foreach тут?


Пофиксил

> у тебя функции в TableDataGateway принимают и возвращают массивы


Теперь объекты по идее

> Не нужно писать 5 однотипных блоков кода, нужно использовать цикл.


Подскажи как тут использовать цикл, я не понял

>Методы findPage и getStudent не дублируют друг друга?


Теперь один метод getStudent

>Далее, я вижу в Authorisatin метод isEmailUsed. Какое отношение он имеет к авторизации? Никакого. Этот метод лучше сделать в классе TSG.


Сделал в TSG isEmailUsed

>- запрашиваем у TSG данные по студенту с логином login


>- если не нашлись, значит логи неправильный


>- если такие данные нашлись, сверяем хеш


Сделал это в TSG метод getLoginPass, как его разделить по частям чтобы вытягивание из БД было в TSG а проверка в Authoristaion ума не приложу, или так нормально?
#303 #1100353
>>1098161

>Здесь не очень понятно, зачем этот класс. Если он для того, чтобы хранить объект mysqli, то что мешает его хранить просто в переменной без всяких ConnectDb? Также, непонятно, зачем в нем поля вроде db_address? Где и как они будут использоваться?


Класс для соединения с бд. А где хранить хранить этот объект, как метод в Util? Или как? Как просто переменную, если да то где? Здесь не понятно. db_adress и подобные нужны были для того чтобы держать в них информацию о конфиге, понял, что можно сразу из массива pasre_ini_file пихать в mysqli

>Как ты выбираешь, что поставить, public или private?


Поставил private, паблик для вызова снаружи класса и наследников, приват только для опредленного класса

>Пропусти код класса через phpformatter.com


Сделал

>но нет проверки, что она содержит разрешенное значение, а значит тут может быть SQL инъекция.


Теперь есть

>Это можно сделать одной командой вместо цикла.


Как?

>Почему не foreach тут?


Пофиксил

> у тебя функции в TableDataGateway принимают и возвращают массивы


Теперь объекты по идее

> Не нужно писать 5 однотипных блоков кода, нужно использовать цикл.


Подскажи как тут использовать цикл, я не понял

>Методы findPage и getStudent не дублируют друг друга?


Теперь один метод getStudent

>Далее, я вижу в Authorisatin метод isEmailUsed. Какое отношение он имеет к авторизации? Никакого. Этот метод лучше сделать в классе TSG.


Сделал в TSG isEmailUsed

>- запрашиваем у TSG данные по студенту с логином login


>- если не нашлись, значит логи неправильный


>- если такие данные нашлись, сверяем хеш


Сделал это в TSG метод getLoginPass, как его разделить по частям чтобы вытягивание из БД было в TSG а проверка в Authoristaion ума не приложу, или так нормально?
#304 #1100356
>>1100352

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


Какая разница, если у меня все равно кто-то на улице, а значит, я продам этот номер в любом случае? А так я могу заселить всех, и выгодно для абсолютного большинства. Мало того, у меня 4 довольных клиента вместо одного. Но в то же время, чем больше клиентов, тем больше толкучка у шведского стола.
Упрощаем: представь, что у меня только одноместные номера разной стоимости, в любом случае придется селить кого-то в самый дорогой.

>Если остается 0 пустых мест в номере = 1000 баллов


Хорошо, а деньги как оценивать в баллах? Раз меньше - это лучше?
Вычитать из стоимости самого дорогого номера? Давай предположим, что у нас есть президентский люкс на одного за 100к тугриков, а остальные номера стоят 1000-2000 тугриков. Все номера получают 98000 баллов. Плохо.
Значит, берем медиану, она будет около 1700, вычитаем баллы из нее. Да, будет логично.
Но пускай медиана 10к и разброс от 2000 до 20000. Что будем делать? Тогда 250 баллов будут погрешностью. Надо делать баллы от пустых мест зависимыми от баллов за деньги. А как?

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


Защита от бесконечного цикла точно есть. Если методом уплотниловки все влезают - задача имеет решение.
Интуитивно мне кажется, что цикл открутится за приемлемое время.
У меня текущая гостиница полностью строится за 2-4 секунды, учитывая, что шанс выбить последнюю комнату 1/640. Просто номер комнаты я даю рандомно, чтобы можно было построить 10 случайных комнат для теста, а не всю гостиницу. В итоге, когда 639 номеров из 640 разобраны, рандому должно хорошо посчастливиться.
#305 #1100357
>>1100352
Вообще, лол, мы можем написать каждый свой алгоритм и сравнить результаты.
#306 #1100362
>>1100356

> Какая разница, если у меня все равно кто-то на улице, а значит, я продам этот номер


Такого условия нет. Заявок может быть ограниченное количество за период времени. Гостиницы и другие предприятия сферы обслуживания вообще редко бывают заняты на 100% (если бы так было, они бы расширялись).

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

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

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

> Все номера получают 98000 баллов. Плохо.


Не плохо. Железяке все равно, что цифры не красивые.

> Тогда 250 баллов будут погрешностью. Надо делать баллы от пустых мест зависимыми от баллов за деньги. А как?


Можно брать маленький вес. Например, за тугрик стоимости вычитаем 1000 баллов. А за незанятое место вычитаем всего 10 баллов. Незанятых мест в 1 номере всяко меньше 100, так что это будет влиять только если цена 2 вариантов одинаковая.

То есть вес стоимости в 1000 раз больше чем вес фактора незанятых мест.

> Интуитивно мне кажется, что цикл открутится за приемлемое время.


А ты посчитать попробуй. Используя комбинаторику. Там почти все формулы с факториалами.

>>1100357

Ой-ой, хочешь заставить ОПа решать учебные задачки для начинающих? Где такое видано? Если Оп пишет задачу, предполагается, что он ее решить может в уме (хотя бы примерно).
#307 #1100367
>>1100353

>Подскажи как тут использовать цикл, я не понял


Сам справился
#308 #1100375
>>1100362
Я наконец-то понял твой принцип!
Можно обойтись без баллов. Сортируем комнаты по возрастанию цены. Сортируем заявки по уменьшению персон. Для каждой заявки пробуем комнаты, первую подходящую заселяем. Всё.

Затем вспоминаем, что у нас еще есть интервал бронирования, и надо бы в некомплектные номера селить тех, кто останавливается на короткий срок. И теряем сознание.
#309 #1100378
>>1100375
Алгоритм, не дающий захватить одному захватить номер для шести на длительный срок:

Сортируем комнаты по возрастанию цены. Сортируем заявки по уменьшению персон, внутри одинакового кол-ва персон по уменьшению срока брони. Для каждой заявки пробуем комнаты, первую подходящую заселяем, при этом подходящей считаем только ту, где вместимость = количество персон, а не >=. Заселенные заявки удаляем. Проходим цикл с оставшимися заявками, с условием вместимость = количество персон + 1. И так далее до исчезновения заявок, либо количество персон + N > вместимостьМаксимальногоНомера === true для каждой заявки, эти заявки заселить невозможно.

Таким образом, 4 человека, приехавшие на месяц, живут в 4-местном номере, а 4 человека, приехавшие на день, занимают, допустим, единственный 6-местный номер всего на день.
В предыдущей версии алгоритма 4 человека, приехавшие на месяц, могли заблокировать возможность принимать 6 человек на целый месяц, заняв 6-местный номер, при том, что 4-местный номер стоял бы пустым спустя день.
#310 #1100380
>>1100378
И еще один полезный бонус: не влезают в нашу гостиницу те, кто собрался вписаться на короткий срок, а долгим стабильно платящим клиентам местечко завсегда найдется.
#311 #1100383
>>1100380

>нашу гостиницу


шлюхи будут?
#312 #1100501
>>1100328
У меня вообще появилась идея перешагнуть через регулярки и потом уже вернуться к этому делу.
Так стоит поступать?
#313 #1100519
>>1100501
Ты уже можешь решить задачу, удалив лишнее через strtr, как я показывал выше. И тогда регулярка будет выглядеть (+7|8)\d{10}. Самое забавное, в свое время я ее вроде так и решил.
Давай добьем загадочное зеленое пятно в скобках. Нам нужно 10 цифр железно, верно? Для начала напишем (\d){10} и вот мы уже матчим первые два примера.
Теперь нам нужно игнорировать пробелы, дефисы и скобки, то есть кушать их и не давиться. Для начала, придумай выражение в квадратных скобках, совпадающее с ними всеми. Затем помести его в скобки перед цифрой и после цифры. Затем поставь нужный квантификатор к квадратным скобкам.
#314 #1100525
>>1100519
Просто то, что ты мне описываешь, подразумевает наличие двух регулярных выражений, что, как мне кажется, нереализуемо в рамках сайта, если только нет "трубы" для перенаправления результата из одного регулярного выражения в другое.

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

'84951234567', '+74951234567', '8-495-1-234-567',
' 8 (8122) 56-56-56', '8-911-1234567', '8 (911) 12 345 67',
'8-911 12 345 67', '8 (911) - 123 - 45 - 67', '+ 7 999 123 4567',
'8 ( 999 ) 1234567', '8 999 123 4567'

а потом удивлялся, с каких таких хуев у меня не все корректно работает И ТОЛЬКО СУКА СЕЙЧАС Я УВИДЕЛ КАК У ТЕБЯ СДЕЛАНО И КАК ДОЛЖЕН БЫЛ СДЕЛАТЬ Я!11
Именно из-за этого у меня не работала херня с ^
#315 #1100526
>>1100525
Регулярки можно комбинировать как угодно. В скобках как раз скрывается подвыражение, которое должно стрельнуть 10 раз подряд.
Да, еще выставь модификатор m, чтобы крышечка и доллар были началом и концом строки, а не всего текста.
#316 #1100771
Если не ошибаюсь, в прошлом треде кто-то спрашивал про абстракцию для файлов, можно ли сделать абстракцию, чтобы представлять локальные и удаленные файлы. Я по моему тогда ответил, что это сложно, и плохо будет работать.

Но тут случайно наткнулся на проект на JS, из gulp, который этим и занимается. Посмотрите, если еще интересно: https://github.com/gulpjs/vinyl

Ну и есть еще Symfony Filesystem, который абстрагирует файловую систему и который наверно тоже можно как-то тут использовать, наверняка что-то есть.

И есть еще Flysystem https://github.com/thephpleague/flysystem

-----------------

Также, напомню, что в прошлом треде были проверены:

https://github.com/Qevg/Student-list , вот тут >>1091604

Ну и все остальные задачи, что там были запощены, там же и проверены.
2017-12-010003
100 Кб, 1164x763
#317 #1100781
И прошу заметить: ни в каком другом треде, кроме РНР, вам не помогут так подробно и по всему web-стеку.

Спасибо ОПу и компании!
#318 #1100790
Если относительный url начинается со знака вопроса, то что это значит?
#319 #1100791
>>1100790
как '?foo=bar&biz=buz' ?

это значит, что в скрипт по адресу '/'
передаются get-параметры

их можно увидеть так:

<?php

echo '<pre>'.printf( $_GET, true ).'</pre>';
nxubJW8xfs
236 Кб, 1120x1600
#320 #1100793
>>1098554
Но она же реально охуенная
#321 #1100794
>>1100791
или print_r
#322 #1100795
Допустим на странице http://example.com:81/some/page.html?a=1&b=2#hash размещены относительные ссылки. Определи полный URL для этих ссылок

/test
?x
//test.example.com
#test
../1.txt
./1.txt

Ответы
http://example.com:81/some/test
http://example.com:81/some/page.html?x
http://test.example.com
http://example.com:81/some/page.html?a=1&b=2#test
http://example.com:81/1.txt
http://example.com:81/some/1.txt
#323 #1100797
>>1100795
Вижу уже, что где-то мимо, но не написав этого сюда бы не заметил, так что извините

//test.example.com
http://test.example.com

Так вернее?
#324 #1100798
>>1100795
Первая неправильно
#326 #1100800
>>1100799
А нет походу. Ведь написано что если с одного слэша, то порт берется.
#327 #1100801
Запиши относительные URL для этих ссылок как можно короче:

1.http://example.com:81/1.txt
2.http://test.example.com/1.txt
3.http://example.com:81/some/page2.html#hash
4.http://example.com:81/some/page.html?x=1

1) /1.txt
2) //1.txt
3) /#hash
4) /?x=1
#328 #1100802
>>1100795

/test полностью замещает path (путь) и все, что дальше. И получается http://example.com:81/test

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

Если относительный URL начинается с ....
http://... - замещает все целиком
//... - замещает все, начиная с host и далее
/.. - замещает path и далее
?... - замещает query и далее
#... - замещает hash

xyzxyz... - замещает последний файл в path и далее (самое сложное место)
./xyzxyz.. - примерно то же самое
../xyzxyz - примерно то же самое, но .. значит подъем на 1 папку вверх

Ты в первом варианте ошибся.
#329 #1100804
>>1100801

Вариант 2) даст при разрещении http://1.txt что явно неправильно.

Вариант 3) даст http://example.com:81/#hash
Ну и с 4) та же проблема.

Смотри правила выше.
#330 #1100810
>>1100802

>/test полностью замещает path (путь) и все, что дальше. И получается...



Вроде теперь правильно понял.

>>1100804

>Вариант 2) даст при разрещении http://1.txt что явно неправильно.



/1.txt

>Вариант 3) даст http://example.com:81/#hash



#hash
?x1

Так верно? Спасибо большое за ответ.
#331 #1100823

>Время бы лучше указать как-то понятнее, вроде текущее + 10 лет, а то не очень понятно, почему именно 7ffff... и сколько это в привычных нам единицах измерения.


Пофиксил

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


Пофиксил

>В валидаторе, при проверке поля score, надо проверять, что оно содержит цифры. А то можно ввести "30 cats". Для года надо проверять что там указан реалистичный год.


Пофиксил

>Также, нужно подумать, как избавиться от повторяющегося кода в методах validateStudent и validateProfile.


Сделал

>зачем ты конфиг с паролями положил в публично доступную папку? Хочешь со всеми поделиться своими секретами?


Перелолил в папку cfg

>У тебя нет проверки, что файл ../controller/'.$class.'.php'; существует


Теперь есть

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


Теперь я её просто подключаю, правильно?

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


Там по всему коду try catch на методах где ловятся исключения, или я что то не понял?

> Лучше писать $e->__toString()


Сделано

>Их функции можно объединить в один контроллер, ведь поиск - это тоже просмотр списка студентов, только с фильтром по имени.


В процессе

>Зачем из контроллера вынсоить кусок в отдельный файл? Не лучше ли сюда этот код и вписать?


Сделал

>В view не должно быть работы с POST/GET. Оно просто отображает то, что дал контроллер.


Убарл по идее

>Лучше сделать функцию или метод где-нибудь в Util, который будет формировать URL из переданных ему параметров. И не забывай про htmlspecialchars.


В процессе

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


Всё равно не понимаю
#331 #1100823

>Время бы лучше указать как-то понятнее, вроде текущее + 10 лет, а то не очень понятно, почему именно 7ffff... и сколько это в привычных нам единицах измерения.


Пофиксил

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


Пофиксил

>В валидаторе, при проверке поля score, надо проверять, что оно содержит цифры. А то можно ввести "30 cats". Для года надо проверять что там указан реалистичный год.


Пофиксил

>Также, нужно подумать, как избавиться от повторяющегося кода в методах validateStudent и validateProfile.


Сделал

>зачем ты конфиг с паролями положил в публично доступную папку? Хочешь со всеми поделиться своими секретами?


Перелолил в папку cfg

>У тебя нет проверки, что файл ../controller/'.$class.'.php'; существует


Теперь есть

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


Теперь я её просто подключаю, правильно?

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


Там по всему коду try catch на методах где ловятся исключения, или я что то не понял?

> Лучше писать $e->__toString()


Сделано

>Их функции можно объединить в один контроллер, ведь поиск - это тоже просмотр списка студентов, только с фильтром по имени.


В процессе

>Зачем из контроллера вынсоить кусок в отдельный файл? Не лучше ли сюда этот код и вписать?


Сделал

>В view не должно быть работы с POST/GET. Оно просто отображает то, что дал контроллер.


Убарл по идее

>Лучше сделать функцию или метод где-нибудь в Util, который будет формировать URL из переданных ему параметров. И не забывай про htmlspecialchars.


В процессе

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


Всё равно не понимаю
#332 #1100824
#333 #1100849
Объясните пожалуйста как это сделать.

Для поиска в одной колонке по части строки в SQL есть оператор LIKE: WHERE x LIKE '%hello%' (% здесь соответствует любым символам). Для поиска по всем колонкам можно применить оператор LIKE к соединенным через пробел значениям столбцов.
#334 #1100917
Ребятки, нужны уютненькие ребусы как у ОПа на базы данных. По другим мурзилкам учить плохо получается - приходится вникать с ходу перепрыгивая важные писечки, это неприемлимо.
#335 #1100926
Алсо как проходят базы и погромирование в целом в учебных заведениях?
#336 #1100946
>>1100771
это я спрашивал. спасибо, посмотрю этот vinyl

ты тогда посоветовал мне задуматься о DI и создании объекта FileSystem. я объект делать не хотел, т.к. он требовал бы в коде библиотеки зависимости от библиотеки виртуальной файловой системы, которая по сути нужна только для тестов (т.е. идет в require-dev). В итоге я так сделал: в классе, который работает с файлами, есть путь по дефолту типа
CONST ROOT_DIR = __DIR__ . '/..';
private $someFilePath = SELF::ROOT_DIR . '/var/file.txt';

и сделал сеттер, который может менять путь для тестов. в тестах подменял ее на путь, который начинается с vfs:// (его генерирует сама либа файловой системы) и все работает ок

единственное, в чем я не разобрался - это как Flysystem работает в плане тестов. поэтому воспользовался вот этой https://github.com/mikey179/vfsStream
она у phpunit указана в документации в кач-ве примера.
#337 #1100979
>>1100926
максимально хуёво, это же РФ + "образование" в IT
#338 #1101030
>>1100979

>это же РФ


Такой себе аргумент. Скинь хоть методичек раз в теме
>>1100917
Бамп!
#339 #1101036
>>1101030
http://exercism.io/ вот шикарный сайт с хорошими задачами и написанными тестами под них. можно смотреть код других участников

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

в то же время у меня есть очень прошаренные знакомые с большим опытом и ВО, но они в момент учебы постоянно что-то писали, где-то работали, что-то сами ковыряли и т.д.
#340 #1101042
Накатил ospanel, создал домен и индекс файлик привет мир в utf8 кодировке. В браузере отображается криво. В чем может быть проблема?
#341 #1101047
>>1100979

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

https://sphere.mail.ru/pages/index/
https://track.mail.ru/pages/about/
https://park.mail.ru/pages/index/

https://academy.yandex.ru/ (там есть список вузов)

В ИТМО (Спб) вроде тоже как IT преподают.

Ну то есть надо хотя бы погуглить.

Если же ты не в одном из таких вузов, то конечно, учить тебя ничему не будут. Препод будет занудно рассказывать на лекциях про GUI на турбопаскале, реляционную алгебру и, если повезет, про PHP4. То есть не те знания, с которыми можно куда-то устроиться.
#342 #1101048
>>1101042

> OpenServer



быстрофикс
#344 #1101052
>>1101042

> header('Content-type: text/html; charset=utf-8');


Решил.
#345 #1101077
>>1101047
Учебников тонет? Вот чтобы прямо учебник, как в школе
#346 #1101084
>>1101077

Учебников по какому предмету? По веб-разработке вообще?

Это малореально, как мне кажется, пока учебник напишут, пока одобрят, выйдет 1 новая версия PHP и 10 новых названий для ноды.
#347 #1101088
>>1101077
как в школе - это учебник по информатике разве что. то, что ты спрашиваешь - это как просить учебник "как чинить форд фокус".
http://php.net/manual/ru/language.variables.external.php #348 #1101094
<?php
if ($_POST) {
echo '<pre>';
echo htmlspecialchars(print_r($_POST, true));
echo '</pre>';
}
?>
<form action="" method="post">
Имя: <input type="text" name="personal[name]" /><br />
Email: <input type="text" name="personal[email]" /><br />
Пиво: <br />
<select multiple name="beer[]">
<option value="warthog">Warthog</option>
<option value="guinness">Guinness</option>
<option value="stuttgarter">Stuttgarter Schwabenbräu</option>
</select><br />
<input type="submit" value="Отправь меня!" />
</form>

Для чего тут нужен параметр true?
#349 #1101096
>>1101094
return
Если вы хотите перехватить вывод print_r(), используйте параметр return. Если его значение равно TRUE, то print_r() вернет результат вывода вместо вывода в браузер (который производится по умолчанию).
http://php.net/manual/ru/function.print-r.php
#350 #1101099
перекатился дома на 7.2, но под него еще нет xdebug и sodium ругается
PHP Warning: Module 'sodium' already loaded in Unknown on line 0
пришлось закомментировать вызов модуля в /etc/php/7.2/mods-available/sodium.ini. warning пропал, а содиум работает ок, т.е. он подгружается еще в каком-то месте помимо конфига, что как-то странно само по себе. зачем тогда было запиливать кривой конфиг по умолчанию
#351 #1101100
>>1101096
Понятно. Спасибо.
#352 #1101261
>>1101099
Почитай список изменений для 7.2:

http://php.net/archive/2017.php#id2017-11-30-1

Конкретно про Sodium - теперь это входит в ядро:
https://wiki.php.net/rfc/libsodium
#353 #1101283
Прохожу урок по Базе данных перед студентами. Там дана таблица с хэшем и солью, что это?
#354 #1101304
>>1100926
>>1101283
>>1100979
примерно вот так, готовятся на двощах
#355 #1101308
>>1101304
хех, на одном курсе повышения квалификации встретил препода какого-то "вузика",

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

но с высоты своего огромного практического опыта ответил на вопросы и дал советов премудрых например, учить SQL хотя бы на Postgre
#356 #1101310
>>1100823

>>Их функции можно объединить в один контроллер, ведь поиск - это тоже просмотр списка студентов, только с фильтром по имени.


Сделал

>>Лучше сделать функцию или метод где-нибудь в Util, который будет формировать URL из переданных ему параметров. И не забывай про htmlspecialchars.


Сделал
#357 #1101317
mariadb, mysql, postgresql - все это не имеет значения для вкатывающегося? Дебиан марию предлагает, например
#358 #1101321
>>1101317
для вкатывальщика-2018 имеет смысл только убить себя как можно быстрее, осознавая свою отсталость;

Тем не менее, mariadb -- это форк mysql, так что это, условно, одно и то же. Практический плюс мускуля в том, что он является самой распространённой СУБД на виртуальных хостингах, то есть, 99% малых и средних проектов. Самая крупная установка мускуля, вроде -- Booking.com

Postgresql круче (больше возможностей, больше объём БД) для больших систем и имеет хорошие перспективы в РФ в рамках импортозамещения как "бесплатный оракл"
#359 #1101324
>>1101321

>для вкатывальщика-2018 имеет смысл только убить себя как можно быстрее, осознавая свою отсталость;


Мне это не подходит.
Значит похуй че ставить?
#360 #1101325
>>1101324
Значит, осознание ещё не наступило.

Нет, не похуй, но из форков mysql можешь выбирать любой, в том числе mariadb.
#361 #1101326
>>1101261
а какой смысл был тогда делать пакет php7.2-sodium?
#362 #1101327
>>1101325
Как же бесит то а, блять
#363 #1101329
>>1101327
привыкай, вкатывальщик
#364 #1101331
>>1101329
Ничего, все ещё охуеют как я могу
#365 #1101332
>>1101331
ха-ханет
photo2017-11-3009-52-12
103 Кб, 1280x819
#366 #1101333
Задам неприличный вопрос:

у кого-нибудь есть хороший, годный (со всеми плюшками) bash-скрипт инсталяции php-fpm + nginx для CentOS?
#367 #1101334
>>1101331
>>1101332
ну зачем ты его обижаешь, чуть-чуть опыта наберётся и лет через 15 всем всё покажет
#368 #1101335
>>1101333
а там прям скрипт нужен? на убунте все работает после apt install php7-fpm nginx
#369 #1101337
>>1101335
Ну как-то работает, да, это не проблема, я имел ввиду прям годную установку с настройкой безопасности, нормально работающих пакетов типа php-fpm-cli, etc.

Олсо, ИМХО бубунты на продакшне точно не должно быть, разве что у тотально выживших из ума хипсторов
#370 #1101344
>>1101337
ну если тебе нужно отвечать за безопасность, все надо делать самому. вот modsec поставить, например https://geekflare.com/install-modsecurity-on-nginx/

опять же на убунте все пакеты нормально работают из коробки после apt install php7.1*.

ну ок, в дебиане те же команды и тоже все работает из коробки (почти) но я впрочем не предлагаю тебе менять дистр на сервере, а просто выебываюсь
#371 #1101347
>>1101333
Да это понятно, у нас на текущих серверах всё очень в порядке, просто пытаюсь найти скрипт (не факт, что он есть), который делал бы на новых установках все кайфуши автоматом.
#372 #1101350
>>1101344
Ну дебиан ещё куда ни шло, сойдёт.

Но так-то все посоны на кошерных дистрибутивах сидят.
#373 #1101351
>>1101350
На каких?
#374 #1101352
>>1101351
RHEL/CentOS, BSD для старообрядцев.

Но Debian, Slackware (раньше) тоже норм.

Олсо, в некоторых отраслях (банки, гос.конторы) в РФ важна сертификация дистрибутива в соответствующих органах.
#375 #1101359
#376 #1101390
Как правильно настроить при установке MySQL?
#377 #1101394
>>1101390
для обучения настройка не нужна
#378 #1101399
>>1101390
>>1101394
в смысле, для просто-установки тебе не нужно ничего настраивать.

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

Развлекательное чтиво по теме: http://www.pvsm.ru/mysql/247358
Выбор1
109 Кб, 972x735
#379 #1101402
>>1101399
А что тут выбирать?
#380 #1101404
На 1-ом пике все верно? Что значит Current root password на 2 пике?
#381 #1101408
>>1101402

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

>>1101404

А ты английский понимаешь?

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

На второй картинке требуют придумать пароль администратора. Current root password - это я думаю, должна быть пустая строка.

Ну и ниже можно еще создать обычные аккаунты, хотя я бы советовал учиться их создавать командой CREATE USER в консоли.
#383 #1101411
>>1101408
Спасибо за ответ. У меня ошибка. Я пытался запустить консоль mysql unicode или как-то так она называлась, она крашилась сразу же.

Я все удалил попробую заново.
................................................
Так. Все установилось. Все открылось. Теперь я могу начать работать с mysql? Спасибо большое за ответ. Он мне очень помог.

Английский плохо знаю, маленький словарный запас.
#384 #1101412
>>1101411
бедняжечка :3
#385 #1101413
тем не менее, несмотря на заслуженный троллинг убогих вкатывальщиков, РНР-тред -- единственное место, где вам помогут и объяснят весб веб-стек
#386 #1101415
>>1101399

Человеку, который пока не разобрался с установкой mysql, рановато читать про архитектуру поиска.

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

Я помню, по моему на хабре читал эту статью и конечно у меня ощущение, что как-то у них все костыльно сделано. Если бы это делали вконтакте, они бы просто на Си написали поисковый демон с хранением данных в RAM и поиском того, что требуется (и это не так сложно, как кажется). Если бы это был я, я бы попробовал в порядке эксперимента сделать то же на Го - может чуть медленнее, но язык приятнее. Не очень понимаю, почему они городят что-то сложное на СУБД общего назначения. На Си пройтись в цикле по 1000 предложений займет меньше миллисекунды, я думаю.

(если кто-то из анонов не верит, давайте сформулируем задание, и вы напишете на Го и померяете).

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

Может, конечно, я чего-то не знаю.

>>1101390

Вообще, MySQL настраивается с помощью редактирования файла конфигурации my.ini и перезапуска сервера. В файле конфигурации можно указать много разных опций, я могу дать только ссылку на англ. мануал, так как их очень много: https://dev.mysql.com/doc/refman/5.7/en/server-options.html

Но тебе скорее всего подойдут настройки по умолчанию.
#387 #1101416
>>1101347

Можно написать playbook для ansible. Ansible - это штука, которая умеет соединяться с сервером по ssh и настраивать его по описанным в конфиге правилам. Ну например, ты можешь сделать playbook, который устанавливает все нужное для веб-сервера или playbook, который добавляет новый virtual host в Апач. Если ты какую-то настройку делаешь больше 1 раза, ее надо автоматизировать.

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

Из недостатков ansible - он не поддерживает винду и его сложно ставить на cygwin (то каких-то заголовочных файлов не хватает, то openssl).

>>1101335

Часто еще надо модули ставить, настройки менять.

>>1101329

Не надо тут устраивать чат пожалуйста. Это тред про программирование.

>>1101326

На линуксе часто расширения идут как отдельные пакеты.

>>1101321

Не знаю, крупная или нет, но mysql еще использовался в фейсбуке, используется в википедии и в Uber недавно на него перешли.

>>1101317

Тебе надо учить стандартный SQL. Там есть отличия у разных БД, но на 80-90% они используют стандартный SQL и 10-20% дополнений к нему.
#387 #1101416
>>1101347

Можно написать playbook для ansible. Ansible - это штука, которая умеет соединяться с сервером по ssh и настраивать его по описанным в конфиге правилам. Ну например, ты можешь сделать playbook, который устанавливает все нужное для веб-сервера или playbook, который добавляет новый virtual host в Апач. Если ты какую-то настройку делаешь больше 1 раза, ее надо автоматизировать.

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

Из недостатков ansible - он не поддерживает винду и его сложно ставить на cygwin (то каких-то заголовочных файлов не хватает, то openssl).

>>1101335

Часто еще надо модули ставить, настройки менять.

>>1101329

Не надо тут устраивать чат пожалуйста. Это тред про программирование.

>>1101326

На линуксе часто расширения идут как отдельные пакеты.

>>1101321

Не знаю, крупная или нет, но mysql еще использовался в фейсбуке, используется в википедии и в Uber недавно на него перешли.

>>1101317

Тебе надо учить стандартный SQL. Там есть отличия у разных БД, но на 80-90% они используют стандартный SQL и 10-20% дополнений к нему.
#388 #1101417
>>1101283

Хеш и соль описаны в уроке про то, как правильно хранить пароли: https://github.com/codedokode/pasta/blob/master/security/password-hashing.md

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

>>1101261

Вообще, у нас тут есть анон, который "пилит" убийцу телеграм, может ему пригодится этот libsodium.

>>1101099

> но под него еще нет xdebug


Через pecl не поставить? Под линуксом вроде не проблема.

> зачем тогда было запиливать кривой конфиг по умолчанию


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

>>1100946

Я думаю, что для тестов там предназначен Memory Adapter: https://github.com/thephpleague/flysystem-memory

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


Это да.

> поэтому воспользовался вот этой https://github.com/mikey179/vfsStream


Тоже вариант.
#388 #1101417
>>1101283

Хеш и соль описаны в уроке про то, как правильно хранить пароли: https://github.com/codedokode/pasta/blob/master/security/password-hashing.md

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

>>1101261

Вообще, у нас тут есть анон, который "пилит" убийцу телеграм, может ему пригодится этот libsodium.

>>1101099

> но под него еще нет xdebug


Через pecl не поставить? Под линуксом вроде не проблема.

> зачем тогда было запиливать кривой конфиг по умолчанию


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

>>1100946

Я думаю, что для тестов там предназначен Memory Adapter: https://github.com/thephpleague/flysystem-memory

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


Это да.

> поэтому воспользовался вот этой https://github.com/mikey179/vfsStream


Тоже вариант.
#389 #1101418
>>1100926

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

На практике наверно потребуют сделать какие-то SQL запросы.

Учебник по SQL будет прочитать куда как полезнее.

У нас в ОП посте кстати есть простые задачки по SQL.

Кстати, кто разбирается в стандартном SQL - они там LIMIT завезли уже?

>>1100849

Соединяем значения столбцов: CONCAT(name, ' ', surname, ' ', email,....)
Добавляем LIKE: WHERE CONCAT(...) LIKE '...'
Дописываем оставшуюся часть запроса (SELECT .. FROM ... ORDER ... LIMIT)

>>1100810

По прежнему неверно. Ссылка /1.txt разрешится в http://example.com:81/1.txt , а надо http://test.example.com/1.txt

> 3) #hash


Там должно быть page2.html, а у тебя будет page.html

> ?x1


Знак равно забыл.

>>1100790

Он замещает в базовом URL query и все, что дальше.

Базовый URL http://x.com/123?aaa
Относительный ?bbb
Результат http://x.com/123?bbb
#389 #1101418
>>1100926

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

На практике наверно потребуют сделать какие-то SQL запросы.

Учебник по SQL будет прочитать куда как полезнее.

У нас в ОП посте кстати есть простые задачки по SQL.

Кстати, кто разбирается в стандартном SQL - они там LIMIT завезли уже?

>>1100849

Соединяем значения столбцов: CONCAT(name, ' ', surname, ' ', email,....)
Добавляем LIKE: WHERE CONCAT(...) LIKE '...'
Дописываем оставшуюся часть запроса (SELECT .. FROM ... ORDER ... LIMIT)

>>1100810

По прежнему неверно. Ссылка /1.txt разрешится в http://example.com:81/1.txt , а надо http://test.example.com/1.txt

> 3) #hash


Там должно быть page2.html, а у тебя будет page.html

> ?x1


Знак равно забыл.

>>1100790

Он замещает в базовом URL query и все, что дальше.

Базовый URL http://x.com/123?aaa
Относительный ?bbb
Результат http://x.com/123?bbb
#390 #1101420
ОП, сегодня попытался обновить symfony 3.4 -> 4.0 в проекте. Поменял версию в composer.json, запустил команду и тут начались пляски: https://pastebin.com/GCSaapBc
Если я пропишу в composer.json "symfony/framework-bundle": "3.0" , то эта проблема уйдёт и появится подобная с другой библой уже. Что-то мне подсказывает, что заполнять это руками неразумно. Я вообще не могу понять (и нагуглить) сути проблемы. Вот содержимое composer.json https://pastebin.com/udYZyZim
#391 #1101449
Оп проверь студентов плз.
Я не понял когда нужно трай/кетч сувать. На каждый чих что ли?
Еще пытался фронконтролер сделать и получилась какая та хуйня.
Так же не делал валидацию очень серьезную.
А еще все это без ксс. Деревянное все.

https://github.com/dsgaljkeguhodgiosetuhsegjposguh/studlist
#393 #1101477
>>1101417

>Через pecl не поставить? Под линуксом вроде не проблема.


пока проблема :(

checking Check for supported PHP versions... configure: error: not supported. Need a PHP version >= 5.5.0 and < 7.2.0 (found 7.2.0-1+ubuntu16.04.1+deb.sury.org+1)

но шторм понимает несколько интерпретаторов, поэтому пока пользуюсь 7.1 для хдебага

>Я думаю, что для тестов там предназначен Memory Adapter: https://github.com/thephpleague/flysystem-memory


о, спасибо
#394 #1101487
>>1101475
Так по этой же инструкции я и пытаюсь обновиться
#395 #1101492
>>1101487
Просто
composer update symfony/symfony
делал?
#396 #1101503
14530140008130
57 Кб, 916x515
#397 #1101517
Опчик, начинаю в качестве дальнейшей тренировки приложение на js карточная игра. Правила придумал. Вдохновляюсь квестами из КР.

План:

1) простейшая реализация правил с выводом в консоль, играешь с рандомом.

2) простейшая графическая часть

3) искусственный интеллект (вот тут хотелось бы твоих советов, хочется сделать его обучающимся в процессе)

Основной смысл: хочу писать маленькие объекты, и сразу покрывать все тестами. Когда по тестам все будет работать как часы, пройдусь пару игр против генератора случайных чисел, если все работает, можно делать AI (самая интересная часть, так как вообще не представляю как тут что делается).

Вопросы:

1) js(знаю) или typescript(не пробовал) или фреймворки(работал с angular)?

2) хороший тестировщик для js(/typescript)?
#398 #1101524
>>1101492
Делал, ситуация такая же что и при composer update symfony/symfony --with-dependencies
и при composer update
#399 #1101561
Опчик почему у тебя нет ничего про ссылки на переменные &$variable оно вообще надо? Часто используется в разработке?
#400 #1101614
>>1101561
В очень редких случая используется при работе с массивами использую его. Работает не со всеми типами, иногда PHP иногда PHP его игнорирует.
#401 #1101619
>>1101561
я не ОП и не знаю, надо ли оно, но часто вижу в коде что-то типа
foreach ($array as &$item) {
$item = ...
}

в том же симфони такого много:
foreach ($namespacedCommands as &$commandsSet) {
ksort($commandsSet);
}

foreach ($namespacedCommands as &$commandsSet) {
ksort($commandsSet);
}

$fileRecorder = function ($extension, $path) use (&$files) {
$files['yaml' === $extension ? 'yml' : $extension][] = $path;
};

и т.д.
#402 #1101657
<?php

$rnd = mt_rand(1, 6)

if ( $rnd == 1) {
echo "Значение1";
} elseif ( $rnd == 2 ) {
echo "Значение2";
} elseif ( $rnd == 3 ) {
echo "Значение3";
} elseif ( $rnd == 4 ) {
echo "Значение4";
} elseif ( $rnd == 5 ) {
echo "Значение5";
} elseif ( $rnd == 6 ) {
echo "Значение6";
}

?>

> Parse error: syntax error, unexpected 'if' (T_IF)



Я перед этим говнокодил на питоне и теперь не могу понять чего оно от меня хочет? Что с if не так?
#403 #1101663
>>1101657

>$rnd = mt_rand(1, 6)


;
#404 #1101665
>>1101657
Алсо поставь нетбинс какойнибудь, чтобы в дальнейшем избежать подобных заёбов
#405 #1101675
>>1101663
Спасибо, никак не привыкну. Юзаю саблайм, странно что никак не подсветил код.
#406 #1101677
>>1101665

>нетбинс


Иди помойся.
>>1101675
Ставь PhpStorm с торентов.
Или VSCode + php-плагин, если хочешь что полегче.
#407 #1101678
>>1101677
Не очень люблю идешки, очень тормозят. Кстати, pycharm для пхп годится?
#408 #1101681
>>1101678
Тогда VSCode или Atom, мне больше первый нравится.

>pycharm


А теперь подумай над своим вопросом и осознай насколько он тупой.
#409 #1101682
>>1101677

>Иди помойся.



>Или VSCode + php-плагин


ага

>>1101657
+ в подобных случаях (много когда elseif) лучше заменять всю конструкцию на switch case
#410 #1101685
>>1101677

>VSCode


Как на i386 ставить?

>Ставь PhpStorm с торентов.


кек
#411 #1101686
Ну так что, какую IDE ставить?
#412 #1101687
>>1101686
Иди нахуй
#413 #1101689
>>1101678
Geany хорош, 4 мегабайта весит
>>1101687
Нет.
#414 #1101696
>>1101682
>>1101681
>>1101689
Добра вам.
#415 #1101698
>>1101686
если у тебя что-то там лагает, то хоть в блокноте пиши. все, кто профессионально пишут код или стремятся к этому, пользуются штормом. это промышленный стандарт. ты придешь в контору работать и тебя там с твоим атомом, нетбинсом и прочим говном пошлют нахуй также, как анон выше.
#416 #1101699
>>1101686
а шторм достаточно долго осваивать со всеми его фишечками, поэтому лучше начинать уже сейчас
#417 #1101700
>>1101698
Я вкатываюсь чтобы одноклассники охуели, зарабатывать этим всем не собираюсь
>>1101699
Хотя посмотреть всетаки стоит
#418 #1101703
>>1101699

>а шторм достаточно долго осваивать со всеми его фишечками


Никогда не пользовался этими комбайнами, можно в двух словах о его преимуществах по сравнения с редакторами которые просто подсвечивают синтаксис?
#419 #1101711
>>1101703
я перечислю то, чем сам пользуюсь постоянно:
тесты - запуск и покрытие (смотреть, что не покрыто)
переход по методу или свойству класса
иерархия классов
контроль версий - порешать конфликты, сравнить файл с какой-то конкретной версией, посмотреть чьи правки
автозаполнение по аннотациям
инспекция кода
рест апи клиент для тестирования запросов
композер - автоапдейт, автоинсталл
консолью из шторма пользуюсь
автодеплой
ну просто запустить файл в кли из интерфейса шторма удобно
икс дебаг конечно же (который в 7.2 еще не завезли)
рефакторинг - это наверное самое ценное, что он умеет

плюс он умеет в автоформат по пср или по кодстайлу твоей конторы, авто неймспейсы по пср0 и 4, авто use, авто аннотации

сложно все вспомнить, может что-то забыл. еще он умеет работать с БД, но я пользуюсь воркбенчем, и всякие штуки с фронтом и версткой (в чем я не шарю).
#420 #1101717
>>1101711
Нихуйственно. Спасибо за инфу.
#421 #1101730
>>1101711
что такое рефакторинг? Он типа сам переписывает говнокод по красоте или как?
#422 #1101737
>>1101682

> switch case


Можно ли под case напихать не много своего говнокода? Скобки "}{" нужны?
#423 #1101755
добрый день. пишу тестхаб и мучаюсь над /new. то есть реализовать переход вопроса из редактируемого в обычное состояние можно за счет средств css, убирая бордеры инпутам и прописывая элементам display: none, потом все отправить формой. вопрос в том, как прописывать name'ы. можно давать question1[например, text](для ответов question1[answers]) , а для каждого раскрываемого вопроса увеличивать номер. также при перезагрузке весь прогресс сбросится. я думал добавлять вопрос в сессии при переходе его в обычное состояние, но тогда нет необходимости в форме. помогите, друзья.
#424 #1101756
>>1101730
почти так. допустим, поменять название метода, чтобы он поменялся во всем проекте, вынести код в другой класс и т.д., захуярить автоматически интрерфейс на основе класса - это все рефакторинг.

>>1101737
можно. по поводу скобок, они там есть, но только в одном месте. лучше посмотри пример http://php.net/manual/ru/control-structures.switch.php
#425 #1101777
>>1101619
не знаю, кстати, как в 7 (кто-нибудт знает?), а раньше это экономило память (при передачи по ссылке значение переменной не копируется)
#426 #1101782
#427 #1101853
Посоветуйте хорошую книгу по верстке, где есть все (адаптивность, флексбоксы, препроцессоры и т. д.).
#428 #1101887
>>1101853
«Web Design for Developers» (Brian Hogan),
«Design Accessible Web Sites» (Jeremy Sydik).
#429 #1101890
у меня вопрос по тестам.

как я понимаю, мы тестируем не весь код втупую, а логику работы приложения, т.е. не тестируем непубличные методы, а тестируем публичные, которые их используют. это вроде логично.
а вот если у нас есть композиция классов (или как тут верно сказать), т.е. допустим есть класс FormHandler и у него в конструкторе создается объект класса FormValidator, который вне этого хендлера больше нигде не будет использоваться, нам его как тестировать? через FormHandlerTest или напрямую через FormValidatorTest? Я сам склоняюсь к первому варианту, но смущает то, что в валидаторе может быть какая-то хитрая логика, которую в таком случае лучше тестить напрямую.
1443175981525861472
49 Кб, 600x450
#430 #1101898
>>1101890

>у него в конструкторе создается объект класса FormValidator


Нет же.
Ему в конструктор передаётся, а тестировать их — отдельно.
#431 #1102021
>>1101898
если бы передавался, то понятно, но не передается, а именно создается:

class FormHandler
{
private $formValidator;

public function __construct()
{
$this->formValidator = new FormValidator();
}

}
#432 #1102027
>>1102021
Сделай, чтобы передавался. Создавать внутри — нельзя.
#433 #1102057
>>1102027
согласно мнению ОПа, в данном случае как раз можно: >>1085287 (смотри по слову "композиция")
#434 #1102107
Аноны, помогайте
Есть задача: написать интернет магазин (фейковый).
Что там должно быть?
Админпанель (разные варианты для админа, продавца, покупателя?).
Корзина (ХЗ как её реализовать).
Главная страница.
Меню с видами продуктов.
Меню с опциями для сортировки продуктов внутри вида (по производителю, цене, ?,?,?).
Страница продукта.
Пагинация страниц результатов (или этот модный скроллинг, но я ХЗ как его реализовать).
?.
?.
?.

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

Еще подводные?
#435 #1102132
>>1102057

>объект API содержит в себе под-объекты, которые независимо от него не используются. Логично потому их создавать в конструкторе.


А пол-года спустя уже используются. Логично потому их не создавать в конструкторе. Ибо нехер плодить зависимости на пустом месте.
#436 #1102136
>>1102107

>Еще подводные?


Не делай тестовые задания, вот в чём подводные.
#437 #1102148
>>1101890
>>1102021
>>1102057
>>1102132

Если что-то можно создать в конструкторе, значит можно это безболезненно поместить в текущий класс. Или боишься файла на 600 строк вместо 300? Так и думать про

>через FormHandlerTest или напрямую через FormValidatorTest?


не придется.

Если хоть мысль пролетит

>А пол-года спустя уже используются.


делай DI.
#438 #1102188
>>1102132

>А пол-года спустя уже используются.



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

плюс, предполагаю, что ты говоришь про mvc, где можно 20 зависимостей передать через контейнер.
#439 #1102206
>>1102136
Это ты к чему вообще высрал?
Не знаешь, что сказать по сабжу - пройди мимо.
#440 #1102208
>>1102148

>Или боишься файла на 600 строк вместо 300?


честно говоря, да. немного побаиваюсь god object

>Если хоть мысль пролетит


>>А пол-года спустя уже используются.


>делай DI.


тут соглашусь
#441 #1102214
>>1102206
Какой вопрос, такой и ответ. Платина.

>>1102188
Я не понимаю, почему если он нигде не используется, он вынесен в отдельный класс??

И MVC тут вообще ни при чем.
Без названия
3 Кб, 252x200
#442 #1102250
Господи какой же абсурд Зачем придумывать велосипеды, когда уже есть CSS с ну очень простым синтаксисом?
https://www.youtube.com/watch?v=w4_1SagLY94
#443 #1102262
Я конечно знаю, что тупой, но...
Как сделать эту задачу?
Просто жопой чую, что можно пройти через дверь, а не лезть через забор
https://ideone.com/dEcffB

Доделай шифрование до нормального уровня
Доделай расшифровку зашифрованного текста. Посказка для глупеньких: тебе поможет array_flip()
#444 #1102307
>>1102214
я не ОП и хочется услышать его мнение. мое мнение: чтобы не нарушать принцип единой ответственности и чтобы не было классов по 1000 строк.
#445 #1102354
Насколько сильно различаются mysql и mysqli?
#446 #1102362
>>1102354
Настолько, что все давно перешли на PDO.
#447 #1102393
>>1102307
Ждем-с тогда.

Мое мнение: если класс создает в конструкторе зависимости, он уже вышел за пределы своей ответственности.

>>1102250
Очередной язык, не хочешь — не бери.

>https://guide.elm-lang.org/error_handling/maybe.html



Ну это так-то гениально!
#448 #1102424
>>1102362

>PDO


А все эти мускли и прочее трудно освоить?
#449 #1102455
>>1102424
mysql - это устаревшая библиотека, ее нельзя использовать. mysqli можно, но нормальные люди пользуются pdo. осваивать одинаково, если ты хоть как-то знаешь ооп, если не знаешь - mysqli будет попроще. но пользоваться им нельзя, также как сейчас нельзя писать процедурный код, поэтому лучше сразу учи pdo.
#450 #1102535
>>1102455
Поцце-дурный код как раз можно. Эх как создам, бывало, просранства имён и в них функций каак насру...
#451 #1102565
Аноны,надеюсь вы не спите.
В задаче про массивы и генерацию имени для питомца
С задачей я справился так:
https://ideone.com/BKUeFG
и вот так:
https://ideone.com/Jt8nm5
Так вот у меня такой вопрос:
$petName = implode(array_rand($letters,4));
echo $petName;
Печатаются ключи ,которые получились при рандоме,а как получить доступ к значениям?
#452 #1102585
>>1102455
>>1102455

>mysqli будет попроще. но пользоваться им нельзя.


Почему нельзя? Религия не позволяет?
#453 #1102620
Народ, как создается страница, ну скажем с товаром. У меня есть корзина, я добавляю туда товар, я правильно понимаю:
На сервак поступает запрос с требованием создать HTML элемент в корзине с данными, формами и т.д в свою очередь в хранилище есть готовый CSS файл со стилем для этих элементов, так?
Т.е запрос создать в HTML доп. элементы с уже готовым стилем в CSS файле который содержит инфу об отступах от первого элемента в корзине, от второго и до бесконечности > выноска с HTML кодом добавляется в пользовательский HTML файл и инфа со стилем не меняется, а остается нетронутой. Правильно?
#454 #1102638
>>1102620
Да, всё правильно. Впрочем при необходимости на php можно генерировать даже CSS файлы.
#455 #1102651
>>1102638
Спасибо.
1imHq8-BKWM
32 Кб, 604x492
#456 #1102727
>>1097438 (OP)
https://ideone.com/cPiQC3
Делаю задачу с опечатками.

Не могу понять в чём проблема. Почему у меня выдаёт только часть слова с ошибкой? Когда я прописываю просто одно слово с ошибкой в виде переменной ($text = "Постaвка";), то всё определяется нормально и выводится как и должно, а после разбивки строки на массив и прохождения по нему циклом выдаёт только кусок слова. Хелп ми.
#457 #1102730
кто шарит, объясните, в чем разница между
$this::staticMethod() и
self::staticMethod()
#458 #1102736
>>1102730
В первом обращение к статичному методу объекта, во втором обращение к классу объекта.
#459 #1102747
Сходил недавно на собеседование, вакансия стажера, дали тестовое задание на верстку макета из psd, уже три дня сижу как еблан и не могу разобраться, 70% того что я запомнил вылетает из головы на следующий день, ну как так блять, неужели я настолько тупой что даже это не могу освоить.
#460 #1102756
>>1102736
в первом обращение к объекту, а во втором к классу, да. но в случае со статическим методом там не может быть состояния, которое привносит созданный объект. то есть, по сути это всегда обращение к классу. так получается, что разницы нет?
#461 #1102757
>>1102747
вакансия стажера-верстальщика?

не парься, первое время все тупые. через полгода будет лучше.
#462 #1102767
>>1102730
Так ты бы поигрался с ними. Например:

https://ideone.com/3c2QaY

Попробуй объяснить, что не так?
#463 #1102795
>>1102767
в случае с
public static function durr() {
$this::staticMethod();
}

идет обращение к $this в контексте статического метода, что нельзя делать, поэтому фатал. это понятно

я спрашивал про
public function yarr() {
$this::staticMethod();
}
и
public function hurr() {
self::staticMethod();
}

которые выводят одинаковый результат. то есть в данном случае разницы нет. так?
#464 #1102805
>>1102767
я понимаю, что так $this::staticMethod() делать не надо, т.к. это идиотская конструкция. но мне непонятно, зачем в языке до сих пор присутствует эта возможность. насколько я понимаю, она там с 5.3. просто руки не дошли выпилить?
#465 #1102819
>>1102756
Порой такая штука удобна, например когда надо вызвать динамичный метод, причем не важно статик он или нет
$this->{$methodName}($arg)

Кстати $this::method() алиас static::method(), а не self::method()
#466 #1102820
>>1102819
>>1102805
промазал
#467 #1102821
>>1102805
>>1102795

Хех... Сложно... Ну смотри тогда такой пример:

https://ideone.com/4FhUeP

И статью:

http://php.net/manual/ru/language.oop5.late-static-bindings.php

Разница есть, и выпиливать нечего.
#468 #1102832
>>1102821
благодарю. про отличие static от self знаю, а про то, что с помощью $this->{$methodName}($arg) можно вызывать в т.ч. статический метод, не знал.
#469 #1102890
>>1102730
self::staticMethod() так правильно,
$this::staticMethod() так не правильно, но все равно работает.
#470 #1102895
Тест
#471 #1102897
А кстати раз такая тема пошла, то спрошу, бывают ли в php статические абстрактные методы?
#472 #1103002
>>1102897
abstract class cA
{
static function A()
{
static::B();
}

abstract static function B();
}

class cB extends cA
{
static function B()
{
echo "ok\n";
}
}

cB::A();
cB::B();

этот код у меня выполняется на 7.1 с error_reporting e_all без ошибок, то есть бывают. но история темная, тут она описана https://stackoverflow.com/questions/999066/why-does-php-5-2-disallow-abstract-static-class-methods/31235907#31235907

получается, что в версии <7 такой код вызывал бы нотис уровня strict, а в 7 все ок.
#473 #1103013
а вот у меня еще один вопрос по тестам.

у нас есть абстрактный класс, как его тестировать?
вижу такие варианты:
1. через существующих наследников
2. через анонимный класс-потомок (начиная с 7)
3. через getMockBuilder в PHPUnit
4. через getMockForAbstractClass в юните же

притом вариантов 1 и 4 сам нигде не нашел (кроме как 4 в мануале). также сам не смог протестировать через getMockForAbstractClass - код в шторме не покрывается. а через getMockBuilder тоже нихуя непонятно - он же подменяет методы класса, почему они тогда отрабатываются.

интересно кто что думает.
#474 #1103047
>>1102897

А где это может понадобиться? По идее, абстрактные нестатические методы используются в ситуации с наследованием: есть базовый класс Base с абстр. методом doSmth() и его наследники X, Y, Z. В коде ниже мы не знаем, объект какого именно класса перед нами, но знаем, что в нем есть метод doSmth (для таких ситуаций и придуманы абстрактные методы):

function test(Base $b)
{
$b->doSmth();
}

Но статические методы вызываются, как правило, с указанием имени класса:

X::doSmth();

Так как мы знаем имя класса, мы можем проверить, какие в нем методы есть, и задавать абстрактный метод в предке (Base) не обязательно. Потому в той же Яве абстрактных статических методов нет.

Тут я нашел такое объяснение: https://stackoverflow.com/questions/370962/why-cant-static-methods-be-abstract-in-java

> Because "abstract" means: "Implements no functionality", and "static" means: "There is functionality even if you don't have an object instance". And that's a logical contradiction.



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

static::doSmth()

в классе Base, когда метод doSmth абстрактный.

https://stackoverflow.com/questions/999066/why-does-php-5-2-disallow-abstract-static-class-methods

Тут пишут, что абстрактных статических методов в PHP нет (выше анон опровергает, эти разработчики там совсем двинулись уже). Напомню еще раз, что мне сама идея с переопределением статических методов и использованием static не очень нравится.

А в какой ситуации они тебе нужны?
#474 #1103047
>>1102897

А где это может понадобиться? По идее, абстрактные нестатические методы используются в ситуации с наследованием: есть базовый класс Base с абстр. методом doSmth() и его наследники X, Y, Z. В коде ниже мы не знаем, объект какого именно класса перед нами, но знаем, что в нем есть метод doSmth (для таких ситуаций и придуманы абстрактные методы):

function test(Base $b)
{
$b->doSmth();
}

Но статические методы вызываются, как правило, с указанием имени класса:

X::doSmth();

Так как мы знаем имя класса, мы можем проверить, какие в нем методы есть, и задавать абстрактный метод в предке (Base) не обязательно. Потому в той же Яве абстрактных статических методов нет.

Тут я нашел такое объяснение: https://stackoverflow.com/questions/370962/why-cant-static-methods-be-abstract-in-java

> Because "abstract" means: "Implements no functionality", and "static" means: "There is functionality even if you don't have an object instance". And that's a logical contradiction.



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

static::doSmth()

в классе Base, когда метод doSmth абстрактный.

https://stackoverflow.com/questions/999066/why-does-php-5-2-disallow-abstract-static-class-methods

Тут пишут, что абстрактных статических методов в PHP нет (выше анон опровергает, эти разработчики там совсем двинулись уже). Напомню еще раз, что мне сама идея с переопределением статических методов и использованием static не очень нравится.

А в какой ситуации они тебе нужны?
#475 #1103053
>>1103013

Для чего нужен абстрактный класс? Как заготовка для создания наследников.

Можно создать тестового наследника и тестировать его. То есть пишешь class TestChild extends Parent { ... }.

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

> через анонимный класс-потомок (начиная с 7)


Можно и так.

Моки, мне кажется, не для этого. Они для подмены существующий конкретных классов.
#476 #1103056
>>1102819

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

Если нужен динамический вызов, имхо, лучше будет написать self::$method(), call_user_func("self::$method") или call_user_func(['self', $method]).

>>1102805

В PHP вообще с ООП много проблем, так как часть разработчиков (по моим ощущениям) сишники и ООП вообще толком не понимают. Ну например, раньше там была такая "фича", что при вызыве из одного класса статического метода другого класса передавалось значение $this:

class A
{
public function a()
{
B::b();
}
}

class B
{
public static function b()
{
// $this указывает на объект класса $a
}
}

$a = new A;
$a->a();

Так что да, делать так ни в коем случае не надо.

>>1102730

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

>>1102727

Скорее всего, в слове больше одной латинской буквы. И твое выражение не захватывает все слово из-за этого. Например: П(о)(с)т(а)вка. Видишь, как хорошо зашифровано, даже твоя программа его не может справиться.

> foreach($piece as $error) {


лучше foreach ($words as $word)
#476 #1103056
>>1102819

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

Если нужен динамический вызов, имхо, лучше будет написать self::$method(), call_user_func("self::$method") или call_user_func(['self', $method]).

>>1102805

В PHP вообще с ООП много проблем, так как часть разработчиков (по моим ощущениям) сишники и ООП вообще толком не понимают. Ну например, раньше там была такая "фича", что при вызыве из одного класса статического метода другого класса передавалось значение $this:

class A
{
public function a()
{
B::b();
}
}

class B
{
public static function b()
{
// $this указывает на объект класса $a
}
}

$a = new A;
$a->a();

Так что да, делать так ни в коем случае не надо.

>>1102730

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

>>1102727

Скорее всего, в слове больше одной латинской буквы. И твое выражение не захватывает все слово из-за этого. Например: П(о)(с)т(а)вка. Видишь, как хорошо зашифровано, даже твоя программа его не может справиться.

> foreach($piece as $error) {


лучше foreach ($words as $word)
#477 #1103060
>>1102620

Я не очень понимаю суть вопроса, но постараюсь прокомментировать.

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



Зачем эта "инфа" об отступах? В HTML/CSS тебе не надо указывать расположение каждого элемента на экране. Ты просто указываешь, что они должны идти, например, вертикально, и задаешь расстояние между ними. Или я тебя не понял, или тебе стоит подучить CSS. То есть ты пишешь что-то вроде "все товары в корзине расположены вертикально c отступом в 10px, текст в них написан черным цветом на белом фоне".

CSS файлы пишет разработчик и в них ничего программно обычно не добавляется.

Ну и не понял, при чем тут HTML файлы. В динамических сайтах HTML файлы не генерируются. Почитай-ка мой урок https://github.com/codedokode/pasta/blob/master/soft/web-server.md#Статические-и-динамические-страницы

>>1102565

Оба варианта правильные. Только переменная названа не очень удачно, не $index, а например $syllable (слог) лучше было назвать.

>>1102585

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

>>1102354

Библиотека mysql удалена в PHP7. Объяснение, почему, на английском https://wiki.php.net/rfc/mysql_deprecation#why
#478 #1103061
>>1102262

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

>>1102107

Может, надо писать не с нуля, а взять готовую CMS? Много работы же получается.

>>1101890

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


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

> т.е. допустим есть класс FormHandler и у него в конструкторе создается объект класса FormValidator, который вне этого хендлера больше нигде не будет использоваться, нам его как тестировать?


> через FormHandlerTest или напрямую через FormValidatorTest? Я сам склоняюсь к первому варианту, но смущает то, что в валидаторе может быть какая-то хитрая логика, которую в таком случае лучше тестить напрямую.



В Яве есть такая штука, как "приватные" классы, то есть вспомогательные классы, объявленные внутри другого класса и недоступные/невидимые снаружи этого класса. Их, конечно, можно не тестировать.

Если твой класс FormValidator по смыслу такой же "вспомогательный", то ты можешь тестирвать только FormHandler. Но на практике, скорее всего, у тебя как-то распределены обязанности между этими 2 классами. И удобнее тестировать их по отдельности.

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

>>1101449

Про исключения почитай урок https://github.com/codedokode/pasta/blob/master/php/exceptions.md

Если ты хочешь как-то специально обработать конкретное исключение, ты пишешь try/catch. Ну например, ты скачиваешь файл, а при ошибке - берешь его с диска:

try {
$file = downloadFile();
} catch (DownloadException $e) {
log("Error downloading file: $e->getMessage()");
$file = loadFromDisk();
}

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

Код на гитхабе недоступен.
#478 #1103061
>>1102262

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

>>1102107

Может, надо писать не с нуля, а взять готовую CMS? Много работы же получается.

>>1101890

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


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

> т.е. допустим есть класс FormHandler и у него в конструкторе создается объект класса FormValidator, который вне этого хендлера больше нигде не будет использоваться, нам его как тестировать?


> через FormHandlerTest или напрямую через FormValidatorTest? Я сам склоняюсь к первому варианту, но смущает то, что в валидаторе может быть какая-то хитрая логика, которую в таком случае лучше тестить напрямую.



В Яве есть такая штука, как "приватные" классы, то есть вспомогательные классы, объявленные внутри другого класса и недоступные/невидимые снаружи этого класса. Их, конечно, можно не тестировать.

Если твой класс FormValidator по смыслу такой же "вспомогательный", то ты можешь тестирвать только FormHandler. Но на практике, скорее всего, у тебя как-то распределены обязанности между этими 2 классами. И удобнее тестировать их по отдельности.

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

>>1101449

Про исключения почитай урок https://github.com/codedokode/pasta/blob/master/php/exceptions.md

Если ты хочешь как-то специально обработать конкретное исключение, ты пишешь try/catch. Ну например, ты скачиваешь файл, а при ошибке - берешь его с диска:

try {
$file = downloadFile();
} catch (DownloadException $e) {
log("Error downloading file: $e->getMessage()");
$file = loadFromDisk();
}

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

Код на гитхабе недоступен.
#479 #1103062
>>1101420

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

Вот смотри, что пишет композер:

> Problem 1


> - stof/doctrine-extensions-bundle v1.2.2 requires symfony/framework-bundle ~2.1|~3.0



Это сторонняя библиотека, не часть Симфони. Открываем эту библиотеку на гитхабе: https://github.com/stof/StofDoctrineExtensionsBundle/blob/master/composer.json

> "require": {


> "symfony/framework-bundle": "~2.1|~3.0",



То есть она не совместима с Symfony 4. Что можно сделать:

- отказаться от нее
- попросить авторов сделать поддержку Symfony 4 (уже: https://github.com/stof/StofDoctrineExtensionsBundle/issues/354 )
- сделать поддержку самому и запушить пулл реквест, а пока он не принят, использовать версию из своего гитхаба (уже сделали: https://github.com/stof/StofDoctrineExtensionsBundle/pull/358 и ты можешь подключить версию из того гитхаба)

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

> Что-то мне подсказывает, что заполнять это руками неразумно. Я вообще не могу понять (и нагуглить) сути проблемы.


Тут сложность в том, что Симфони состоит не из одного, а из множества пакетов. И обновлять их надо синхронно. Проще всего взять стандартное приложение на Симфони и список версий оттуда https://github.com/symfony/symfony-standard

Затем ты пробуешь обновиться и смотришь, что напишет композер. И разбираешься с проблемными библиотеками.

> , то эта проблема уйдёт и появится подобная с другой библой уже.


Без подробностей помочь не могу.
#479 #1103062
>>1101420

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

Вот смотри, что пишет композер:

> Problem 1


> - stof/doctrine-extensions-bundle v1.2.2 requires symfony/framework-bundle ~2.1|~3.0



Это сторонняя библиотека, не часть Симфони. Открываем эту библиотеку на гитхабе: https://github.com/stof/StofDoctrineExtensionsBundle/blob/master/composer.json

> "require": {


> "symfony/framework-bundle": "~2.1|~3.0",



То есть она не совместима с Symfony 4. Что можно сделать:

- отказаться от нее
- попросить авторов сделать поддержку Symfony 4 (уже: https://github.com/stof/StofDoctrineExtensionsBundle/issues/354 )
- сделать поддержку самому и запушить пулл реквест, а пока он не принят, использовать версию из своего гитхаба (уже сделали: https://github.com/stof/StofDoctrineExtensionsBundle/pull/358 и ты можешь подключить версию из того гитхаба)

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

> Что-то мне подсказывает, что заполнять это руками неразумно. Я вообще не могу понять (и нагуглить) сути проблемы.


Тут сложность в том, что Симфони состоит не из одного, а из множества пакетов. И обновлять их надо синхронно. Проще всего взять стандартное приложение на Симфони и список версий оттуда https://github.com/symfony/symfony-standard

Затем ты пробуешь обновиться и смотришь, что напишет композер. И разбираешься с проблемными библиотеками.

> , то эта проблема уйдёт и появится подобная с другой библой уже.


Без подробностей помочь не могу.
#480 #1103063
>>1101337

Ubuntu server (не desktop) вполне адекватная вроде. Разве что у меня в виртуалке логин притормаживает в сравнении с дебианом. А что тебе-то не нравится?

>>1101898

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

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

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

На практике, может показаться, что DI тут использовать удобнее. Ведь скорее всего, у FormValidator есть тоже какие-то зависимости, например, доступ к БД. Его надо как-то передать туда, и получается, что удобнее тут использовать DI и передать ответственность за получение зависимостей DI контейнеру.

Если зависимостей у FormValidator нет, можно не использовать DI.

Есть еще вариант передавать зависимости в FormHandler:

class FormHandler
{
public function __construct($dep1, $dep2, $dep3)
{
$validator = new FormValidator($dep1, $dep2, $dep3);
}

Но тут видна нелогичность: не проще ли передавать сразу $validator вместо 3 зависимостей? Но если мы сделаем DI (будет принимать $validator снаружи), то получается, что мы готовы работать с несколькими вариантами валидатора. Что тоже нелогично. Это говорит о том, что мы не очень удачно сделали разделение ответственности между классами.

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

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

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

>>1102132

Ну когда будут использоваться, тогда можно код переделать. Почитай-ка статью и узнай про YAGNI: https://habrahabr.ru/post/153225/

Напомню всем любителям поломать голову над ООП, что в этом треде есть задача про Гостиницу и Продюсерское Агенство (ищите поиском), и я пока что-то ни одного решения не видел, только обсуждения.
#480 #1103063
>>1101337

Ubuntu server (не desktop) вполне адекватная вроде. Разве что у меня в виртуалке логин притормаживает в сравнении с дебианом. А что тебе-то не нравится?

>>1101898

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

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

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

На практике, может показаться, что DI тут использовать удобнее. Ведь скорее всего, у FormValidator есть тоже какие-то зависимости, например, доступ к БД. Его надо как-то передать туда, и получается, что удобнее тут использовать DI и передать ответственность за получение зависимостей DI контейнеру.

Если зависимостей у FormValidator нет, можно не использовать DI.

Есть еще вариант передавать зависимости в FormHandler:

class FormHandler
{
public function __construct($dep1, $dep2, $dep3)
{
$validator = new FormValidator($dep1, $dep2, $dep3);
}

Но тут видна нелогичность: не проще ли передавать сразу $validator вместо 3 зависимостей? Но если мы сделаем DI (будет принимать $validator снаружи), то получается, что мы готовы работать с несколькими вариантами валидатора. Что тоже нелогично. Это говорит о том, что мы не очень удачно сделали разделение ответственности между классами.

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

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

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

>>1102132

Ну когда будут использоваться, тогда можно код переделать. Почитай-ка статью и узнай про YAGNI: https://habrahabr.ru/post/153225/

Напомню всем любителям поломать голову над ООП, что в этом треде есть задача про Гостиницу и Продюсерское Агенство (ищите поиском), и я пока что-то ни одного решения не видел, только обсуждения.
#481 #1103103
https://ideone.com/Czm6Us
что я делаю не так с таблицой умножения?
Снимок экрана2017-12-0422-07-06
59 Кб, 1167x472
#482 #1103106
Че не так то?
#483 #1103111
>>1103103
Может быть дело в "++"?
#484 #1103114
>>1103103
Как-то так.

https://ideone.com/PMUxzg

$c = $a * $b надо писать в теле цикла.
#486 #1103122
>>1103117
Ну да. Ты прав. Сдаюсь.

Красиво.
#487 #1103124
>>1103117
>>1103122

только что это
1 1 = 1
2
2 = 1
3 3 = 1
4
4 = 1
5 5 = 1
6
6 = 1
7 7 = 1
8
8 = 1
9 * 9 = 1
hqdefault
10 Кб, 480x360
#488 #1103127
Безумие - это точное повторение одного и того же действия, раз за разом, в надежде на изменение. Это есть безумие.

https://ideone.com/KUFAQ8
#489 #1103136
>>1103114
спасибо
#491 #1103139
>>1103127
WINNER!
#492 #1103147
>>1103106
Вот я хлебушек, разобрался.
#493 #1103152
>>1103127

$a < 10, $b < 10

тут ошибка. Учитываться будет только последнее условие. Надо писать с использованием оператора "И", то есть &&:

$a < 10 && $b < 10

Потому что в первой и третьей части ты просто указываешь действия. А в средней части - условие проверки, и тут запятую использовать нельзя.
#494 #1103154
>>1103127

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

То есть $x, $y даст тот же результат что и $y (если $x не выполняет никаких действий, а только что-то проверяет).
#495 #1103249
>>1100823
>>1100353
Опчик проверь
#496 #1103252
>>1103061

>Много работы же получается


Ну так дипломная же.
5791db7e03bbf15611c1643f[1]
235 Кб, 700x700
#497 #1103257
вкатываюсь к вам, слоники
ну вот скачал я ваш netbeans php
настроил всё, не самодельничал
и не могу подключиться к локалхосту
#498 #1103259
>>1101420

Алсо, может тебе помогут такие команды композера:

> prohibits Shows which packages prevent the given package from being installed.


> why Shows which packages cause the given package to be installed.


> why-not Shows which packages prevent the given package from being installed.

#499 #1103265
А что можно простое сделать на js типа задачи на студентов?
#500 #1103278
>>1103265

Игру сапер или другие задания отсюда: https://gist.github.com/codedokode/ce30e7a036f18f416ae0#3-Сапер (прокрути до сапера, там вначале идут простые задачи, а потом поинтереснее)

Слишком просто? Есть игра поинтереснее, Арканоид: https://gist.github.com/codedokode/9933897

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

Еще сложнее? Сделай простой мессенджер.

Слишком просто??? Ну ладно, так и быть, держи задание уровня nightmare (его решило 0 человек): https://github.com/codedokode/pasta/blob/master/js/spa.md Молодец, что ты не ищешь легких путей, и просишь задачи посложнее, это тебе наверняка поможет в будущем.
#501 #1103279
>>1103265

Можешь еще сделать студентов в виде SPA на knockout/react/angular.
#502 #1103281
Хейтера потерли, уря.
#503 #1103304
Сап, обьясните слоупоку профиты от Nosql баз данных? Как так получилось что всех всё устраивало, всё работало идеально, а потом в 2012 все резко поняли что реляционные базы - говно и надо с них срочно мигрировать на NoSql.
#504 #1103339
Сап как сделать мультиплеерную рисовалку ?
#505 #1103353
>>1103304
Если совсем вкратце, то в большом количестве nosql бд, ты жертвуешь фичами и гарантиями современных реляционных бд ради красивых цифр в бенчмарках.
То есть некоторые специализированные nosql вполне ничего, но,например, какую-нибудь монгу не очень понятно зачем вообще использовать в среднем проекте.
#506 #1103367
>>1103257
бывает, чо.

алсо, нетбинс тут не любят.

если ты на винде, ставь openserver - там все сразу работает из коробки. также в шторме есть простой способ запускать вебсервер, который дает пхп. также в пхп есть встроенный вебсервер по php -S, кажется.
someApprentice #507 #1103412
http://phpclub.tech/

Я не совсем уверен, что сказал @kubk по поводу старых тредов, но они скоро появиться
#508 #1103429
Оп, можешь дать подсказку по реализации прохождения тестов? В задании подразумевается, что на каждый вопрос нужна отдельная страница (/question/1, /question/2 и т.д.), но как тогда в таком случае быть с формами? Каждый ответ на вопрос отправлять на сервер? И куда их потом? В таблицу тестов пользователя?
someApprentice #509 #1103435
>>1098742
>>1099200

>2.Как вообще запихивать скобки в регулярные выражения?


Ещё можно экранировать с помощью символа \

https://secure.php.net/manual/ru/regexp.reference.escape.php
#510 #1103441
Посоветуйте учебник или обзор языка пхп для фронтендера, сам пишу на жс, работаю в связке с бэкендером, инб почему у него не спросишь, не спрошу тк ему под 40 уже и он не в курсе актуальных учебников. Нужно просто составить представление о языке и основных операторах.
someApprentice #511 #1103444
>>1103257
Чтобы подключиться к чему-то нужно иметь веб-сервер принимающий HTTP-запросы. К примеру Apache2.

В&О по установке https://github.com/codedokode/pasta/blob/master/soft/apache-install.md
Если хочешь продвинутой информации, вот урок по http-запросам https://github.com/codedokode/pasta/blob/master/network/http.md
#512 #1103450
>>1103441
Если тебе просто пробежаться по синтаксису можешь попробовать какие нибудь ущербные курсы вроде codeacademy пролистать, если серьезно вникать то по php, наверное один нормальный учебник это http://www.phptherightway.com/
#513 #1103469
Анончики, подскажите пожалуйста, почему функция не работает?
https://ideone.com/9fjsix
#514 #1103478
>>1103469
У тебя скобка после return не закрыта, функцию вызываешь уже после вывода, если хочешь вывести переменную в строке используй обратные ковычки `{$var}`.
#515 #1103482
>>1103478
Спасибо большущее, разобрался
#516 #1103564
Посоны, все тот же вкатывальщик в фронтенд. Где нибудь есть хорошие мануалы по верстке сайта по psd шаблону?
Дали тестовое задание, не могу разобраться с позиционированием и актуальными инструментами для верстки, тут фреймворк, там reset.css, тут хуй рассказывает как верстать через костыли актуальные в 2008.
#517 #1103572
>>1103412

Ссылка на /chain/ стоит на значке № и хрен догадаешься, что она там есть. Лучше сделать ее более заметной, например, сделав надпись "цепочка сообщений" или как-то еще.

Также, можно убрать прокрутку у длинных постов - это ведь по идее защита от постеров-шутников, которых в архиве скорее всего нету.
#518 #1103588
>>1103564
я сам не фронт и даже в верстку не умею, но фронты говорили, что самые пиздатые курсы по этой херне у htmlacademy.

>>1103441
ну учебник ОПа по азам - самое то. что тебе еще-то надо?
someApprentice #519 #1103594
>>1103572

>Ссылка на /chain/ стоит на значке № и хрен догадаешься, что она там есть. Лучше сделать ее более заметной, например, сделав надпись "цепочка сообщений" или как-то еще.


Я вообще хочу убрать эту функцию. Я когда проектировал, хотел чтобы обсуждения, которые растягиваются на несколько тредов, вывелись по одному клику. Но вместо этого, если в цепочку попадает ОП-пост или ещё какой-нибудь пост с кучей ответов, то всё превращается в кучу молу.
За место этого, я хочу сделать, чтобы пользователи сами добавляли нужные им посты в "Избранное". Всё равно я планирую прикрутить чатик, поэтому регистрация в любом случае понадобиться.
Нужно обсудить это ещё с моей командой.

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


Что за защита? Если что будет в посте, то это тоже спарситься из активных тредов.
#520 #1103597
>>1103594

Я имею в виду, здесь стоит ограничение на высоту поста для защиты от вайперов, которые могут постить посты на 5000 строк из 1 символа. В архиве в этом нет необходимости и прокрутка только мешает читать сообщение.
someApprentice #521 #1103598
>>1103564
Если тебе тяжело решить тестовое задание, то представь как тяжело будет решить боевое. Лучше подтянуть свои знания. У нас, кстати, есть задача на вёрстку лэндинга(?) из .psd макета https://github.com/codedokode/pasta/blob/master/html/html.md#Главное-задание-на-верстку-макета
И ещё относительно простые задачки по html/css, которые научат тебя базовым трюкам https://github.com/codedokode/pasta/blob/master/html/html.md#Задания
someApprentice #522 #1103601
>>1103597
Ок, я уже добавил это к себе в задачи. Мне тоже не удобно читать посты с прокруткой.
#523 #1103612
Хорошая статья, разработчики виртуальной клавиатуры для айфона случайно открыли доступ к своей монге в Интернет и исследователи выяснили, какие данные с телефона собирало и накапливало приложение (все, до чего смогло дотянуться).
#524 #1103613
>>1103612
Ссылочка https://mackeepersecurity.com/post/virtual-keyboard-developer-leaked-31-million-of-client-records

Какое отношение это имеет к веб-разработке? Прямое. В веб-разработке точно также используется MongoDB.
#525 #1103619
>>1103598
Большое спасибо, попробую разобраться. Проблема в том, что я смотрю в psd шаблон и понимаю как все должно выглядеть и какие должны быть параметры/отступы, в каких блоках какие типы элементов должны распологаться, но когда доходит до верски - то все идет по пизде и я понимаю что все свои мысли для решения не могу перенести в html/css код, буду учиться, еще раз благодарю.
#526 #1103625
>>1103619

Тебе надо изучать позиционирование. У меня есть такой недописанный урок, и в нем картинка со всеми имеющимися видами позиционирования элементов: https://github.com/codedokode/pasta/blob/master/html/positioning.md#Виды-позиционирования

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

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

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

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

Вообще, в большинстве случаев там все просто - обычно сайт собран из вертикально расположенных блоки, которые иногда деляnся на несколько частей или колонок.
#527 #1103653
Что нужно знать по базам данных, чтобы решить студентов ?
someApprentice #528 #1103659
>>1103653
CREATE DATABASE ...
CREATE TABLE ...
INSERT ...
UPDATE ...
SELECT ... ORDER BY/OFFSET/LIMIT
DELETE ...

Но в боевых задачах, практически, всегда нужно будет работать с БД. Поэтому, запросы нужно знать хорошо.
Есть урок и задачи по SQL https://github.com/codedokode/pasta/blob/master/db/databases.md
#529 #1103676
>>1103659
Спасибо.
Я тут еще один вопрос задам. Возможно глупый.
Чтобы подключить базу данных к PHP нужно PDO изучить, да?
#530 #1103688
Вечер добрый, на чем лучше написать чат? Node + socket, php +.socket, RabbitMQ + php? Для меня нет проблемы написать на всех трех, по отдельности я с ними работал либо читал документацию но вот не знаю, на чем остановиться так как скорее всего надо чтобы проект был масштабируемым
#531 #1103725
Анончики. Те из вас, кто проходил мой учебник или изучал регулярки где-то еще, знаком наверно с сайтом https://regex101.com/ где можно вдоволь тестировать регулярку.

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

Они запилили поддержку переводов https://github.com/firasdib/regex101-translations/

Чтобы на сайте появился русский или другой близкий и понятный тебе язык, нужно взять файл вроде https://github.com/firasdib/regex101-translations/blob/master/english.json , и в каждой паре слов справа заменить английские слова на переведенные.

В файле есть специальные конструкции вроде {0}, они обозначают места, куда будет вставлен какой-то дополнительный текст, их надо оставить.

Я бы также советовал параллельно читать мануал http://php.net/manual/ru/pcre.pattern.php и делать перевод, используя одинаковые термины, чтобы не сбить читателя с толку.

Более того, чтобы не делать это руками, запилен сайт для переводов https:// r101 cf / projects/regex101/ (русского там нет). Если перевод уже есть - не беда, можно его проверить и одобрить/предложить исправление.

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

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

>>1103688

Если будешь делать бекенд на PHP, то больше сможешь изучить (reactphp например).
#532 #1103731
Можно ли, и если да, то как, работать в php с массивами байтов напрямую, в виде байтов, т.е. читать их, писать в виде hexString, менять отдельные байты как числа и т.д.?
#533 #1103743
>>1103731
Можно. Так же как и с массивам не в виде байтов.
#534 #1103745
>>1103731

Да. Строка в PHP это и есть массив байтов (не символов).

$s = '12345';
// запись байта в массив
$s[0] = ord(0x35);
// или
$s[0] = "\x35";
// чтение
echo chr($s[1]);
// размер массива
echo strlen($s);
#535 #1103793
>>1103444
>>1103367
Спасибо, слоники
#536 #1103823
>>1103688
Для масштабируемых чатов, я бы волшебный обратил внимание на akka и java/scala или вообще какой-нибудь erlang. Акторная модель многопоточности, которая там и там используется, очень хорошо подходит для чатов
#537 #1103825
>>1103823

>волшебный


вообще*

быстро-фикс
someApprentice #538 #1103836
>>1103676
Да, но там ничего сложного. В задаче о студентах всё написано https://github.com/codedokode/pasta/blob/master/student-list.md#Работа-с-базой-данных-из-php

Не забудь прочитать статью на хабре https://habrahabr.ru/post/137664/ она поможет разобраться в том чем является PDO
#539 #1103849
>>1103823

>волшебный


Надо было и не фиксить, мне приятно.
Знаю только JS/php/sql и начал изучать Golang читаю доки в свободнее от работы и чтения других доков время
Не могу же заказчику заявить, мол я буду делать на незнакомом мне языке чат, поэтому это займет в 3 раза больше времени чем нужно.
#540 #1103852
>>1103849
Кстати, го тоже неплохо пойдет под задачу.

А так я думал, что это для себя пишется. Если для заказчика, то да, надо брать знакомое и проверенное.
#541 #1103888
>>1103429
Оп, ну хоть намекнуть можешь?
#543 #1103927
>>1103926
Это такой троллинг солнышко ммм?
#544 #1103930
>>1103927
В чём троллинг?
#545 #1103934
>>1103930
У тебя все хорошо?
702d986e17d709a84612808fdb6cb63f
3 Кб, 378x112
#546 #1103936
>>1103934
Всё было хорошо да, почему странное поведение такое у гибкого сравнения?
В JS пикрелейтед.
Даже если логически подумать - сравниваются значения с разными типами, почему бы их просто не привести к булевому значению и не сравнить их между собой? 0 => false, не пустая строка => true . Как итог false == true => false
Sc1
27 Кб, 1511x579
#547 #1103939
Опять вкатываюсь с вопросом по фронтенду, по оформлению хедера.
Все эти блоки запихиваю в хедер, телефон, две кнопки в правую часть хедера с помощью списка, логотип по центру который заезжает на слайдер, плюс меню, на которое опять же заезжает логотип, как запихнуть меню в ебучую нижнюю часть хедера стык в стык и при этом вставить пробел между 3 и 4 пунктом? Намекните куда смотреть при чтении позиционирования.
#548 #1103940
>>1103936

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


А ты ожидал от такого сравнения чего? Меня бы архитектор за такое просто обоссал бы.

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


Привести string к булеву значению? Да ты зелёный.
#549 #1103941
>>1103939
<table><table>
702d986e17d709a84612808fdb6cb63f
3 Кб, 378x112
#550 #1103946
>>1103940

>Привести string к булеву значению? Да ты зелёный.


Так это ж PHP
43f2e7b92786ef22113972c4133dcbbf
6 Кб, 491x353
#551 #1103947
>>1103946
Блять, не та картинка
#552 #1103948
Допустим, что есть example.org и он имеет страницу с адресом /123. Можно ли с помощью .htaccess сделать так, чтобы по адресу example.org/abc открывалось то же самое, что и по /123, но при условии, что в адресной строке написано /abc (то есть, редирект просто не пойдёт)? Если да, то что нужно написать?
#553 #1103950
>>1103946
Чел, в 2003 версии MVS net С++ можно было делить на ноль ссылкой (пофиксили в 2012 году). Но это не значит что С++ так был задуман. Как то странно косячить, а потом делать вывод что это язык виноват. Нет чел, ты должен понимать что ты делаешь и зачем.
#554 #1103951
>>1103950
Я не делаю вывод, мне интересно почему такое поведение.
#555 #1103959
>>1103951
Это баг. В 7.2 его пофиксили.
#556 #1103966
>>1103940
я бы тебя тоже обоссал
>>1103926
вот таблица сравнения типов http://php.net/manual/en/types.comparisons.php
также почитай про операторы сравнения http://php.net/manual/en/language.operators.comparison.php
конкретно вот: If you compare a number with a string or the comparison involves numerical strings, then each string is converted to a number and the comparison performed numerically.

также если ты думаешь, почему echo выводит строку, то вот ответ http://php.net/manual/en/language.types.string.php A boolean TRUE value is converted to the string "1". Boolean FALSE is converted to "" (the empty string). This allows conversion back and forth between boolean and string values.
#557 #1103973
>>1103966

>я бы тебя тоже обоссал


Окай, в какой ситуации такое сравнение было бы уместным и при этом не выглядило бы как говнокод?
#558 #1103981
>>1103973
понятно, что это говнокод. сейчас вообще не используют нестрогое сравнение, а если где-то оно необходимо, то скорее всего за этим кроются дикие костыли.

я это к тому, что если явно чувак вкатывается, учится - то помоги ему, поделись своим ценным опытом. к тому же, вполне вероятно, что php после js кажется ебанутым (уж js после php точно кажется).
#559 #1103982
>>1103981
А, тогда сорян. Я просто привык что в тред только зелёные с таким вопросом входял (Вопрос кстати скопирован из лурочки).
someApprentice #560 #1104034
>>1103939
Я не спец по вёрстке, но, по-моему, проще всего сделать

<ul class="menu">
<li>Menu 1</li>
<li>Menu 2</li>
<li>Menu 3</li>
<li class="slider">Slider</li>
<li>Menu 4</li>
<li>Menu 5</li>
<li>Menu 6</li>
</ul>

.menu li {display:inline-block; margin: 0;} .slider {width: 1020px; //??? heaght:1020px; //???}
#561 #1104046
>>1103062
Спасибо, я разобрался. Какие-то либы (от symfony и sensiolab) я просто удалил, т.к. в skeleton-проекте их не было, а значит они уже не нужны. У некоторых обновил версию. Ну а с stof/doctrine-extensions-bundle я так и сделал, форкнул себе форк того чувака, что сделал поддержку 4ой версии и её подрубил.
Один плюс - я за эти дни почитал доки composer'а. Стал лучше его понимать

Еще с парой вещей пришлось повозиться, например, папка web теперь public.
#562 #1104085
>>1103056

>И твое выражение не захватывает все слово из-за этого. Например: П(о)(с)т(а)вка. Видишь, как хорошо зашифровано, даже твоя программа его не может справиться.



Подскажи как для таких слов сделать регулярку, я не совсем понимаю.
15105346750820
41 Кб, 604x453
#563 #1104101
Здарова бандиты.

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

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

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

Если я ошибся тредом дайте мне НАПРАВЛЕНИЕ, ток не пиздите ногами. Спс.

Заодно было бы неплохо получить общие рекомендации о том, что учить дальше, мб что в ближайшем будущем может стать актуальным и стоит начать учить уже сейчас.
#564 #1104106
>>1103982
на лурке статья про php образца начала 2000-х (в плане фраз типа "недавно ввели неймспейсы, но их никто не использует"), у меня до сих пор пиздец как пригорает от нее
#565 #1104114
>>1104101
В воркаче есть тренд про фронт https://2ch.hk/wrk/res/1144163.html (М)
#566 #1104117
>>1104114
Заебись, спасибо
#567 #1104128
>>1104101

В ОП посте есть задачи на HTML/CSS, начиная с простейших и в конце задание на верстку макета.

Если этого мало, гугли free psd templates, но учти что они в большинстве плохого качества и придется отсеивать нормальные.

>>1104085

Если ты хочешь захватить такое слово, то надо писать регулярку в стиле "кириилица - 1 латинская буква - любые буквы".

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

>>1103939

Центральный квадрат - это ведь логотип?

Тут можно поступать по-разному.

1) Можно разбить шапку по горизонтали на 3 части (левая, логотип и правая). Это можно сделать за счет float: right/left, за счет inline-block, за счет display: table, flexbox. Два последних варианта (table, flexbox) позволяют сделать резиновую шапку, в которой левая и правая части будут растягиваться под ширину шапки. Первые 2 варианта - только шапку фиксированных либо процентных размеров (впрочем, с флоатами тоже можно сделать резину, если сделать 2 флоата шириной по 50% и внутри них фиксированный отступ под логотип).

Затем добавить в левую/правую части 2 отдельных куска меню, добавив отступ от верха паддингом или маргином. Телефон и кнопку можно зафиксировать с помощью абс. поз либо сделать обычным блоком.

.header
-- .header__left
---- .header__left-menu
---- .header__phone
-- .header__logo
-- .header__right

а можно, как советуют ниже, сделать логотип частью меню. Например, так: добавить в меню средний пункт, такой же высоты, как и другие, а в него с помощью абс. поз. вставить большой логотип так, что низ логотипа прижат к точке чуть ниже пункта меню (bottom: -10px).

Само меню можно сделать на флоатах с процентами, inline-block, на table или flexbox.

2) Можно сделать 2 отдельных меню, прижатых вправо/влево за счет флоата, а логотип закрепить абс. поз., либо сделать его обычным отцентрированным блоком. Абс. позиционирование хорошо тем, что логотип не будет ничего никуда расталкивать. Флоаты при желании можно сделать как 50% шапки, чтобы все было резиновым.

3) Как тут уже предложили, можно сделать в меню пункт под логотип и в него поместить логотип с помощью абс. поз.

ul.header-menu
-- li
-- li
-- li
-- li.header-menu__center
---- .header-logo
-- li
....

То есть вариантов много.
#567 #1104128
>>1104101

В ОП посте есть задачи на HTML/CSS, начиная с простейших и в конце задание на верстку макета.

Если этого мало, гугли free psd templates, но учти что они в большинстве плохого качества и придется отсеивать нормальные.

>>1104085

Если ты хочешь захватить такое слово, то надо писать регулярку в стиле "кириилица - 1 латинская буква - любые буквы".

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

>>1103939

Центральный квадрат - это ведь логотип?

Тут можно поступать по-разному.

1) Можно разбить шапку по горизонтали на 3 части (левая, логотип и правая). Это можно сделать за счет float: right/left, за счет inline-block, за счет display: table, flexbox. Два последних варианта (table, flexbox) позволяют сделать резиновую шапку, в которой левая и правая части будут растягиваться под ширину шапки. Первые 2 варианта - только шапку фиксированных либо процентных размеров (впрочем, с флоатами тоже можно сделать резину, если сделать 2 флоата шириной по 50% и внутри них фиксированный отступ под логотип).

Затем добавить в левую/правую части 2 отдельных куска меню, добавив отступ от верха паддингом или маргином. Телефон и кнопку можно зафиксировать с помощью абс. поз либо сделать обычным блоком.

.header
-- .header__left
---- .header__left-menu
---- .header__phone
-- .header__logo
-- .header__right

а можно, как советуют ниже, сделать логотип частью меню. Например, так: добавить в меню средний пункт, такой же высоты, как и другие, а в него с помощью абс. поз. вставить большой логотип так, что низ логотипа прижат к точке чуть ниже пункта меню (bottom: -10px).

Само меню можно сделать на флоатах с процентами, inline-block, на table или flexbox.

2) Можно сделать 2 отдельных меню, прижатых вправо/влево за счет флоата, а логотип закрепить абс. поз., либо сделать его обычным отцентрированным блоком. Абс. позиционирование хорошо тем, что логотип не будет ничего никуда расталкивать. Флоаты при желании можно сделать как 50% шапки, чтобы все было резиновым.

3) Как тут уже предложили, можно сделать в меню пункт под логотип и в него поместить логотип с помощью абс. поз.

ul.header-menu
-- li
-- li
-- li
-- li.header-menu__center
---- .header-logo
-- li
....

То есть вариантов много.
#568 #1104129
>>1103948

Да, можно. В случае, если ты используешь апач, нужно изучить mod_rewrite и зарулить такие запросы на один скрипт, если нгинкс то просто зарулить все запросы к PHP на один скрипт index.php.

То есть ты можешь настроить любое соответствие между URL и именем файла. Обычно все запросы, которые не идут к статическим файлам, заруливают на index.php и дальше уже в PHP коде анализируют запрос.

С точки зрения SEO и с точки зрения логики иметь 2 страницы с одинаковым контентом это плохо.

>>1103927

Не надо нервно так относиться к вопросу.

>>1103926

Если ты исопльзуешь == и сравниваешь строку с числом, то PHP преобразует эту строку в число. Используй === вместо ==.

>>1103936

Для любителей похоливорить по поводу языков даю справочник https://habrahabr.ru/post/315152/

>>1104106

Почитай https://habrahabr.ru/post/315152/ и успокойся.
#569 #1104133
>>1103941

Тег table используется только для разметки таблиц. А не меню.
#570 #1104163
>>1104129
Извиняюсь за оффтоп, но:

> https://habrahabr.ru/post/315152/


Статья интересная, но в некоторых местах какая-то странноватая:

> Haskell


> Неприятная система типов.



> Scala


Названы всякие мелочи, основные минусы не сказаны.

>C#


> Продвигает устаревшее (типы вариантов и LINQ, что существенно добавляет беспорядка).


Что хотел сказать автор вообще не понятно.
К тому же жалуются на то, что не компилируются куски совершенно семантически бредового кода типа foreach(var i in ints) { i = i + 1; }

Кстати, php-кун, можешь посоветовать какую-нибудь не сильно долгую задачку на которой можно новую технологию для SPA протестить, а то обычный todoMVC надоел?
#571 #1104181
ОП
я спроектировал продюсерское агентство ну и базу данных для него. Там нет реализации ничего, кроме тех параметров которые как я подумал необходимы. В некоторых функциях возвращаю $this чтобы можно было красиво инициализировать объекты как в шаблоне строитель.

http://sandbox.onlinephpfunctions.com/code/4d9a7a089423b0849ace858480486f55486f9d75
#572 #1104203
>>1104181

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

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

Урок https://github.com/codedokode/pasta/blob/master/php/interfaces.md

Если кому-то интересная задача, то вот она: >>1094213
1390678602689
12 Кб, 604x461
#573 #1104206
>>1104128

>Если ты хочешь захватить такое слово, то надо писать регулярку в стиле "кириилица - 1 латинская буква - любые буквы".



Спасибо большое! Чекни код, пожалуйста.

https://ideone.com/5PP57b
#574 #1104219
Пытаюсь подключиться к базе данных, но не понимаю, что я делаю не так, поэтому попробую описать все свои действия пошагово, но перед этим заранее напишу, что для root при установке MySQL установил пароль "admin".

Я зашел в php.ini и расскоментил extension=php_pdo_mysql.dll
и перезапустил сервер.

Далее я присоединился к БД ( название базы данных 'zoo' в ней есть таблица 'pet')
https://ideone.com/D5iSIK

А дальше у меня ничего не получается. Я пытался читать мануал, я не знаю, что именно делать. Помогите, пожалуйста
#575 #1104240
>>1104219

Напиши или заскриншоть что выводится при запуске скрипта. Проверь, что в php.ini стоит display_errors = 1 (показывать ошибки на экране).
#576 #1104245
>>1104219

Если у тебя все работает, но ты не понял, как пользоваться PDO, что начни с изучения примеров

http://phpfaq.ru/pdo
https://phpdelusions.net/pdo (англ)
https://habrahabr.ru/post/137664/

Запрос без плейсхолдеров на изменение данных делается через exec по моему.

SQL-Запрос на получение данных делается через query либо через prepare + execute.

А, кстати, SQL-то ты знаешь?
#577 #1104254
>>1104203

Тогда я думаю пихать классы специальностей(Модель, Актер и Музыкант) в поле $talants в класс TalantedPerson, убрать у них наследование от Person. Так же добавить в TalantedPerson метод addTalant getTalant. Ну и получается что TalantedPerson будет реализовывать интерфейс с этими методами.
Для талантов же сделать интрефейс с методами getTalantName и getPropitries, setPropirtes.
Просто мне кажется что свойство-массив это плохо, но ничего другого в голову не приходит

http://sandbox.onlinephpfunctions.com/code/0d1f403bd9d989d3d63aa0ae9dbad81ba64a5490
#578 #1104260
Анон, решил начать вкатываться ИТ. Работаю в НИИ, времени свободного много. Одна беда - пекарни на работе без интернета вообще. Какой набор софта посоветуете скачать на флешку? Решил качать netbeans, PHP, MySQL, apache, node.js, sublime text и питон с явой заботливо уже установлены на пеке кем-ьо Прозреваю, надо еще последний VC скачать. Что еще?
Учебник из ОП-поста могу читать с телефона, ну и уже накачал Eloquent JavaScript, Dive into Python, по Яве какую-то книгу, которую в факе яватреда порекомендовали.
#579 #1104263
>>1104260
Может вначале лучше определиться какую-именно технологию хочешь изучать?
#580 #1104267
>>1104254

Использование методов вроде getParams никуда не годится. Вот почему.

Допустим, у тебя есть фукнция такого вида:

function x(TalantInterface $talant) {

}

Что можно сделать с переменной $talant? Можно вызвать единственный метод getParams(), который вернет массив непонятно чего. Пользы от такого интерфейса ноль. Это не ООП.

Более того, название getParams вообще ничего не значит. Оно эквивалентно просто get.

Не нужен тут TalantInterface и метод getparams.

Достаточно просто сделать класс Person и у него массив навыков. Вот и все.
#581 #1104269
>>1104260

Если ты изучаешь PHP, то тебе достаточно самого интерпретатора (php.exe и другие файлы). Он не требует прав админа и ставится в любую папку, в ОП посте есть инструкция по установке.

В PHP встроен простой веб-сервер, потому тебе на первых порах даже не нужен Апач. Поднять локально сайт можно только с помощью PHP.

Если у тебя сложности с установкой MySQL на компьютер, то можно использовать вместо нее расширение PHP под названием sqlite. Это встраиваемая (внутрь интерпретатора PHP) база данных, поддерживающая язык SQL. Диалект там немного отличается от MysQL, но во многом похож.

Также ты можешь скачать мануал по PHP: http://php.net/download-docs.php

В том числе на русском, в том числе в формате chm с поиском.

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

Мой гитхаб https://github.com/codedokode/pasta/ можно скачать в виде zip-архива (правда, уроки будут в формате .md ).

Главная сложность, конечно, в том, что гуглить нельзя.
#582 #1104281
>>1104263
Ну хочу в веб вкатиться, для начала научиться в пхп, sql, сервера. Там в процессе уже пойму, что мне интереснее, фронтенд или бэкенд.
>>1104269

>то тебе достаточно самого интерпретатора (php.exe и другие файлы)


Неудобно же, в netbeans подсветка всей хуйни, контроль скобок и т.п.

>Главная сложность, конечно, в том, что гуглить нельзя.


С телефона можно. Проблема в том, что я нищук с Windows Phone, который, сука, запрещает скачивание .exe, .msi и так далее.

>Мой гитхаб https://github.com/codedokode/pasta/ можно скачать в виде zip-архива (правда, уроки будут в формате .md ).


Вот за это спасибо большое.
#583 #1104308
Анон, существует ли функция, на подобии array_rand(), но чтобы бралось именно случайное значение из массива, а не индекс?
#584 #1104309
А, и да, ОП. У тебя ошибка в третьей задаче на массивы. Если вбить указанную ссылку с шаблоном задачи, то откроется сам ответ.
#585 #1104313
function factor($num)
{
if ($num =0){
return 1;
} else {
$result = 1;

for ($i=2; $i<=$num; $i++) {
$result = $result*$i;
}

return $result;
}
}
почему 1 возвращает?
#586 #1104318
>>1104313
Я понял что вместо проверки присвоил 0 дурачок.
#587 #1104325
>>1104106

>Дата последнего редактирования 27 октября 2017


Давай не будем, ок? Практическая польза от этого выражения нулевая. Теоретическая тоже. И я сомневаюсь что ньюфаг сможет догадаться до такого. Спиздил с лурочки, и припёрся в тред потраллировать.
#588 #1104397
Если я даун 23 лвл, живу в мухосранске, без вышки, работаю на дерьмо работе со средним специальным образованием. Вот вроде прохожу обучение от ОП, мне это интересно, я получаю кайф когда понимаю как что то сделать, делаю студентов, сижу по пару часов в день за этим занятием(мб я бы сидел больше, если бы у меня было время).
И я задумался, раз мне это так нравится, мб стоит потратить силы, сдать егэ и поехать учиться на программиста, в какой то средний институт в мск/питер или любой другой город
Или все же лучше еще учить пхп и все к нему прилагающее. И если сделаю все задачи от ОП нормально и что то свое, раскидать просто резюме на джуна или фриланс попробывать?
#589 #1104423
>>1104163
Ну у автора свое мнение.
#590 #1104424
>>1104397
Да кем бы ты ни стал, хоть программистом, хоть слесарем, хирургом - Все зависит от тебя, результат будет один и тот же, я тебя уверяю.
#591 #1104428
Пожалуйста помогите!
Почему не работает:
<?php
$filename = "json.txt";
$json = file_get_contents($filename);
$data = json_decode($json,true);
echo "<pre>";
print_r ($data);

Если написать echo $json, он выдает содержимое файла, все ок, если напрямую в $json вписать содержимое файла в виде строки ($json = "содержимое файла";), то декодирует и выводит $data нормально.
Но если запустить то что я дал изначально - нихуя не выводит. echo $data выдает NULL.
Не понимаю. Все по отдельности работает, в связке нихуя.
#592 #1104431
>>1104397

>Если я даун 23 лвл, живу в мухосранске, без вышки, работаю на дерьмо работе со средним специальным образованием.


Никогда не поздно начать учиться, порой достаточно лишь желания.

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


У ОПа все задачки специально сделаны с таким раскладом, чтобы было легко, тебе уже подали на блюде то, что нужно решать, я не критикую, для базы вполне сойдет, сам же выполнял эти задачки. (Хотя я бы отталкивался от спецификации и официальных источников, документации и чем больше информации в плане ссылок, источников и полезностей тем лучше). Т.е советую САМОМУ придумывать себе задачи и самостоятельно писать программы, не считай часы, к черту их, учись сколько можешь, хоть 15 минут, главное чтобы в голову лезло.

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


Университет по большей сути ничего тебе не даст, вот серьезно, туда нужно будет идти, отстреливаться и идти на работу джуна. Мой знакомый который учился на матфаке говорил, что когда они программировали их просто запирали и давали кодить, решать задачи, кучу просто, под конец семестра их число превосходило миллион, а у них там C/C++

>Или все же лучше еще учить пхп и все к нему прилагающее. И если сделаю все задачи от ОП нормально и что то свое, раскидать просто резюме на джуна или фриланс попробывать?


Я бы посоветовал параллельно учиться и работать джуном.
#593 #1104455
>>1103061
То есть мне надо сделать во всех функциях/методах проверку и если ошибка кидать исключение. и что бы грузился уже не контролер а страница ошибки. то есть исключения что бы при ошибки, приложение не работало дальше. что бы ничего не поломалось? а перехватывать исключения это уже на усмотрение.

код заработал вроде
https://github.com/dsgaljkeguhodgiosetuhsegjposguh/studlist
#594 #1104488
>>1104428
Разобрался, спасибо за помощь.
someApprentice #595 #1104493
>>1104308
$randomValue = $array[array_rand($array)]
#596 #1104494
>>1104129
У меня суть какая. Я нуб-недофрилансер и от меня хотят страницу с именем вида website.ru/iphone-x, а сайт на какой-то самописной CMS и страницы там создаются с именами вида website.ru/index.php?id=100. Мне бы как-нибудь сделать, чтобы в адресной строке было website.ru/iphone-x, а на деле контент отдавался с адреса website.ru/index.php?id=100. Конкретных файлов как таковых нет.
#597 #1104672
>>1104325
ну в чужую голову не залезешь, так что, да, не будем.
#598 #1104678
Кто подскажет, чем микросервисы отличаются от SOA?

Я на практике сталкивался только с SOA и там все довольно понятно - есть отдельные проекты, для каждого отдельный репозиторий и они общаются по АПИ. А что такое микросервисы?? Читал https://stackoverflow.com/questions/25501098/difference-between-microservices-architecture-and-soa но все формулировки размытые, единственная не размытая - это "в принципе это одно и то же".
#599 #1104692
>>1104494
mod_rewrite для апача или содомировать конфиг nginx. эта хуйня зовётся https://ru.wikipedia.org/wiki/Семантический_URL.
#600 #1104766
Оп посмотри пожалуйста гостиницу. Там еще не все реализовано. Просто чтобы понять я в том направлении двигаюсь или нет.

http://sandbox.onlinephpfunctions.com/code/d2170294a7293a1e73795358d3ebbac14ada7a61
#601 #1104862
>>1104678

Я видел где-то такое определение: микросервис - это приложение, которое пишется маленькой командой (например, 3 человека) за 2 недели. Если приходит новая команда и ничего не может понять в коде, она просто переписывает микросервис с нуля.

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

Также, плюс в возможности распараллеливания и масштабирования проекта на много серверов.

Можно использовать разные языки программирования.

Минусы (в сравнении с монолитом):

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

В общем, видно, что использовать микросервисы не всегда выгодно. С другой стороны, если ты строишь вконтакте, то без этого не обойтись.
omegalul
4 Кб, 200x210
#602 #1104975
>>1104766

>ZZaharovFamily

#603 #1104978
>>1104862
спасибки. то есть, получается, что микросервисы от СОА отличаются размером собственно сервисов.

расскажу как у нас в СОА было:
- основная часть была на php, а сервис чатиков на go
- на условно 10 сервисов, которые составляли приложения, шестью занималась "команда веб-разработки", то есть любой из нее мог шариться в любом сервисе, а еще 4 распределялись между командами, где каждая (мобильники, почта, чатик и т.д.) занималась только одним. притом юмор в том, что там каждый тимлид решал, какие использовать фреймворки и они везде были разные (симфони, зенд, ларавел)
- развроачивать все это локально ни у кого даже мысли не было ввиду сложности всей структуры (там еще было миллион баз с шардированием, сервер очередей и т.д.). просто был дев-сервер и к нему можно было подключиться по впн при необходимости. у каждого была своя папочка на сервере и свой хост
- да, логи везде свои и нужно добавлять какой-нибудь идентификатор для каждого запроса, чтобы отслеживать их во всех сервисах. по идее можно сделать какой-нибудь простой клишный скрипт-клиент, который их все по идентификатору будет собирать, но никто с этим не заморачивался
- проблемы из серии "нашел баг в другом сервисе" у нас почему-то ни разу не было. мы в чужих и не лазили
- проблемы с отладкой есть первое время, потом когда понимаешь точки взаимодействия (их обычно не так много и в основном между двумя сервисами), как-то не замечаешь. единственный нюанс - нужно держать несколько проектов шторма одновременно открытами (тут линуксовые воркспейсы решают)
#604 #1105006
Господи, сейчас посмотрел код простой страницы созданной на WP, в чем его проблема? Почему разработчики им не пользуются?
#605 #1105030
>>1097438 (OP)
https://ideone.com/3zjsI7
Проверьте задание с опечатками.
#606 #1105048
>>1105006
Покажи, что ли.
#607 #1105055
Апач работает только с пхп 5 ?
#608 #1105060
>>1105055
У меня с 7.2 работает.
#609 #1105066
>>1105060
Если я хочу перенести директорию с сайтом из /var в /home, то в конфиге phpmyadmin ее тоже надо менять или он умный и сам догадается?
#610 #1105228
Очень странная ситуация произошла после переноса проекта на другой сервер, буду рад если кто выскажет свои предположения по поводу причин.

Есть базовый класс ApiRequest. У него есть наследники CreateProductRequest и UpdateProductRequest, структура примерно такова:
Request/
- ApiRequest.php
- CreateProductRequest.php - https://ideone.com/vQQA0R (cодержит require_once)
- UpdateProductRequest.php - https://ideone.com/vuJs0A (не содержит require_once)
public/
- api.php - https://ideone.com/hctPzV

При попытке обратиться к api.php просходит ошибка в классе UpdateProductRequest - не удаётся найти класс ApiRequest. Если разобрать порядок подключения файлов в api.php, то должно выйти как-то так:

1) Подключение CreateProductRequest, в котором подключается ApiRequest
2) Подключение UpdateProductRequest

Проблема изчезла после того, как в UpdateProductRequest был добавлен require_once

Нет ни у кого идей? Этот код работал локально и на старом сервере месяца 4, проблемы возникли только на новом сервере. Версии PHP везде 5.5.9
#611 #1105271
https://gist.github.com/codedokode/8733007

>Теги (темы) — можно указать любые, через запятую, при этом все введенные теги собираются в таблицу и используются для автодополнения. Регистр букв в теге не имеет значения, «физика» и «Физика» — один тег (возможно стоит их принудительно переводить в нижний регистр). Если теги различаются только знаками пунктуации, то же самое (теги могут содержать только знаки дефис, запятая, точка (не в конце названия)).



Немного не понял.
Есть в базе тег "мат анал". Юзер вводит "мат.анал". Что нужно из этого сделать?
- Сохранить "мат.анал" и при поиске по любому их этих тегов суммировать результаты по обоим? Тут будет проблема в наличии дубликатов.
- Преобразовать пользовательский тег к "мат анал", что бы не было дубликатов. Тут будет проблема, что юзер вводит одно, а сохраняется другое. Юзер нервничает и материться
- Мой вариант. Разрешить только символы алфавита и пробел. И выводить ошибку валидации, если юзер вводит недопустимые символы. Это решает и первую и вторую проблемы
#612 #1105675
Что за пиздец с задачей про перевод цифр в слово?
Я хуй знает как это решать.
#613 #1105682
ХТМЛ и пхп код могут быть вместе в одном файле.
Как правильней, пхп в хтмл писать иди хтмл внутри пхп?
#614 #1105690
>>1105682

>>ХТМЛ и пхп код могут быть вместе в одном файле.


Они могут быть вместе. Например шаблон страницы с хтмл тэгами внутри которых есть пхп переменные.

>> Как правильней, пхп в хтмл писать иди хтмл внутри пхп?


в файлах пхп писать хтмл тэги.
#615 #1105709
>>1105682

Лучше все же разделять. Урок про шаблоны в помощь https://github.com/codedokode/pasta/blob/master/php/templates.md

>>1105675

Надо разбить задачу на более простые части:

- разбиваем число на группы по 3 цифры
- пишем функцию, которая переводит в строку число от 1 до 999
- пишем функцию, которая выбирает форму слова (миллион/миллиона/миллионов)

>>1105271

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

Дубликаты все равно в любом случае будут, и кому-то придется потом их склеивать.
автозагрузка классов #616 #1105723
Пример функции-автозагрузчика:

spl_autoload_register(function ($class) {
// Получаем путь к файлу из имени класса
$path = __DIR__ . $class . '.php';
// Если в текущей папке есть такой файл, то выполняем код из него
if (file_exists($path)) {
require_once $path;
}
// Если файла нет, то ничего не делаем - может быть, класс
// загрузит какой-то другой автозагрузчик или может быть,
// такого класса нет
});

Немного не понимаю жирный текст.
1)Мы объявляем функцию внутри функции?
2)Например у меня есть класс Cat. Как написать код, чтобы автозагружался класс Cat?
3) Как поступать с абстрактными классами?
#617 #1105728
>>1105723
Дополню.

index.php:
spl_autoload_register(function ($class) {
// Получаем путь к файлу из имени класса
$path = __DIR__ . $class . '.php';
// Если в текущей папке есть такой файл, то выполняем код из него
if (file_exists($path)) {
require_once $path;
}
// Если файла нет, то ничего не делаем - может быть, класс
// загрузит какой-то другой автозагрузчик или может быть,
// такого класса нет
});
spl_autoload_call("Cat");
$pet = new Cat;

Fatal error: Uncaught Error: Class 'Cat' not found in C:\Apache24\htdocs\index.php:19 Stack trace: #0 {main} thrown in C:\Apache24\htdocs\index.php on line 19

Cat.php

<?php

class Cat
{
public $color;
public $paws;
public $tail;
}
#617 #1105728
>>1105723
Дополню.

index.php:
spl_autoload_register(function ($class) {
// Получаем путь к файлу из имени класса
$path = __DIR__ . $class . '.php';
// Если в текущей папке есть такой файл, то выполняем код из него
if (file_exists($path)) {
require_once $path;
}
// Если файла нет, то ничего не делаем - может быть, класс
// загрузит какой-то другой автозагрузчик или может быть,
// такого класса нет
});
spl_autoload_call("Cat");
$pet = new Cat;

Fatal error: Uncaught Error: Class 'Cat' not found in C:\Apache24\htdocs\index.php:19 Stack trace: #0 {main} thrown in C:\Apache24\htdocs\index.php on line 19

Cat.php

<?php

class Cat
{
public $color;
public $paws;
public $tail;
}
#618 #1105805
>>1097438 (OP)
Чем плох NetBeans?
#619 #1105819
>>1105805
Единственная нормальная IDE.
Портативная, бесплатная, гибкая, имеет кучу плагинов, красивая, функциональная.
1c-bitrix-1
10 Кб, 560x349
#620 #1105823
Посоны. Хотят всучить мне пилить проект на битриксе. Я его в глаза не видел и они об этом знают, поэтому дают типа, который поможет если че.

Хотелось бы спросить хотябы какова структура файлов там, че оно вообще такое в общих чертах?

Буду благодарен если кто-то расскажет развернуто по хардкору
#621 #1105832
В чем разница между $x и {$x}? В гугле не гуглится.
#622 #1105833
>>1105832
в фигурных скобках
петросян.жпг

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

echo "Меня зовут $name";

А если нужно допилить например окончание?
echo "Меня зовут $namer";
где "r" - не часть имени переменно, то как быть? Берешь название переменной в фигурные скобки:
echo "Меня зовут {$name}r";
#623 #1105837
>>1105819
>>1105805

>Чем плох NetBeans?


Юзай нетбинс. Сказать то что хотел? Опять стартуешь срачи IDE?
#624 #1105854
>>1105837
Я реально не понимаю. Просто в тредах нет нет, да проскакивают посты о том какое нетбинс гавно и мол phpstorm незаменим. Хотел просто узнать причины и всё.
#625 #1105856
>>1105854
хз, какой-то он странный мне кажется. Был момент когда PHPStorm мне казался отвратительным, а потом они добавили тёмные темы и мне он показался уютненьким и я на него перескочил с какого-то древнего редактора, возможно даже с Notepad. А это вот NetBeans был прямотаки недружелюбен.
#626 #1105857
>>1105854
Запомни одно. Все люди в интернете, с которыми ты споришь, просто повторяют, то, что услышали. Аргументов не имеют. Если тебе нравится и всем устраивает- знач збс.

Я вообще долго писали сейчас часто это делаю все на notepad++, ибо он гибкий имеет кучу нужных плагинов и пр. И постоянно был вынужден ловить необоснованные струи мочи
#627 #1105859
>>1105857
Пишет он в PHP треде. В котором каждый необоснованно (на самом деле иногда обоснованно) ловит струи мочи.
#628 #1105860
>>1105857
Есть у меня один знакомый который пишет на Notepad++ c 2007 года.
Это не ты случаем?
#629 #1105880
Анон, помоги нубу. Установил Apache, настроил его для работы с Symfony, и он вроде как работает, то только на корень. Т.е если я пишу localhost/ и после / еще что нибудь выдает Not Found 404. Что это может быть? Конфигурацию взял тут: https://symfony.com/doc/current/setup/web_server_configuration.html (та, которая без .htaccess) Что может быть не так? По идее он при любом URI (и даже его отсутствии) должен меня на index.php кидать, а делает это только при / .

Что за дела?
#630 #1105881
>>1105880
Система Debian 9, PHP 7.2, Apache 2.4 если это как то поможет :(
#631 #1105917
Привет тредик. У меня опять лабораторная. На этот раз про базы данных. Я хотел сделать такую штуку, чтоб печатала всю базу данных на страницу (при том любую, даже если я не знаю имён полей и прочего).
Нашёл это: https://pastebin.com/2gPL3vBH
Вот только mysql_ модуль же устарел, по крайней мере так на php.net сказано, да и IDE у меня эти команды не понимает. Говорит, малаца, но переделывай под mysqli_. А я не понимаю как. В качестве аналогов функций типа mysql_tablename указаны запросы, которые, по итогу, возвращают не строку, а какой-то совсем другой объект. Что мне этим делать?
#632 #1105918
>>1105917
прошу прощения, вот так
https://pastebin.com/YxJVfmuP
#633 #1106007
#634 #1106078
>>1105823
https://dev.1c-bitrix.ru/learning/course/index.php?COURSE_ID=43&LESSON_ID=2287

госпаде, пробежавшись по началу статьи, я уже нашел три оправдания в духе "bitix не говно, просто так проще вам будет говнокодить". Надеюсь, ты сможешь отмазаться от этого проекта, мен
#635 #1106091
>>1105723

1) Это анонимная функция

http://php.net/manual/ru/functions.anonymous.php
https://habrahabr.ru/post/147620/
https://habrahabr.ru/company/mailru/blog/103983/

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

3)

> Как поступать с абстрактными классами?


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

> $path = __DIR__ . $class . '.php';


Нету разделителя (слеша) между DIR и именем класса.

Для отладки ты можешь поставить в автозагрузчик echo и выводить имя класса и путь к файлу.
#636 #1106143
>>1105917

Еще лучше - PDO, тут, например, объясняется, как с ним работать: https://habrahabr.ru/post/137664/

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

>>1105880

Если ты работаешь без htaccess, то тебе надо приписывать в URL имя скрипта вроде index.php, чтобы было http://localhost/index.php/some/path. Может даже не index.php, а index_dev.php. Надо смотреть, что там у тебя за скрипты.

Также, можно попробовать разобраться с mod_rewrite:

https://habrahabr.ru/company/sprinthost/blog/129560/
http://httpd.apache.org/docs/current/mod/mod_rewrite.html

>>1105832

В мануале написано http://php.net/manual/ru/language.types.string.php#language.types.string.parsing
#637 #1106144
>>1105228

Я бы для начала в UpdateProductRequest.php дописал бы require для ApiRequest, так как ты не должен рассчитывать на то, что какие-то файлы уже кем-то подключены. Либо же сделать все require в api.php и убрать из других мест.

Также, не используются ли неймспейсы?

Также, нет ли проблем из-за перепутанных маленьких/больших букв в имени файла? Из-за русской буквы в имени файла или класса?

Если ты хочешь увидеть, какие файлы подключаются, ты можешь запустить программу из командной строки из-под strace (только в linux):

strace php public/api.php

Предупреждение: выведется много данных.

Также, можно запустить из под strace встроенный веб-сервер:

strace php -S 0.0.0.0:9000 -t public

И зайти браузером на http://ip-адрес:9000/api.php (в случае хостинга порт 9000 может быть у них заблокирован и это не получится) и опять же посмотреть.

strace показывает все системные вызовы (обращения к ОС), которые делает программа, и там будет видно обращение к файлам. Там среди прочих будут строчки с open - это системный вызов для открытия файла.

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

>>1105066

А она прописана в конфиге? Если да, то надо менять.
#637 #1106144
>>1105228

Я бы для начала в UpdateProductRequest.php дописал бы require для ApiRequest, так как ты не должен рассчитывать на то, что какие-то файлы уже кем-то подключены. Либо же сделать все require в api.php и убрать из других мест.

Также, не используются ли неймспейсы?

Также, нет ли проблем из-за перепутанных маленьких/больших букв в имени файла? Из-за русской буквы в имени файла или класса?

Если ты хочешь увидеть, какие файлы подключаются, ты можешь запустить программу из командной строки из-под strace (только в linux):

strace php public/api.php

Предупреждение: выведется много данных.

Также, можно запустить из под strace встроенный веб-сервер:

strace php -S 0.0.0.0:9000 -t public

И зайти браузером на http://ip-адрес:9000/api.php (в случае хостинга порт 9000 может быть у них заблокирован и это не получится) и опять же посмотреть.

strace показывает все системные вызовы (обращения к ОС), которые делает программа, и там будет видно обращение к файлам. Там среди прочих будут строчки с open - это системный вызов для открытия файла.

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

>>1105066

А она прописана в конфиге? Если да, то надо менять.
#638 #1106145
>>1105030

> $word = preg_split


Лучше назвать $words

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

>>1105675

Ты можешь также показать код, который получился, и спросить, что делать дальше. Хотя бы частично-то ты наверно можешь решить?

>>1104766

У тебя вся логика засунута в Hotel, хотя часть ее лучше поместить в другие классы, например:

> if (($value->getExpireDate() <= $date) || ($value->getExpiredDate() == null)) {


Лучше if ($room->isOccupied($date))

> public function isFreeSpecificRoomsNumber($rooms, $date)


Не лучше ли это сделать методов у объекта Number?

Также, тебе надо разобраться, какие есть сущности и какие у них свойства:

> class Hotel


> private $date;


Почему дата - это свойство отеля? Что-то я не понимаю, где тут логика. дата заезда - это свойство заявки на размещение.

Насчет свойства logs - не логичнее ли историю заселения в номер хранить в самом номере? А то у тебя есть там только expireDate, который не отражает историю заселения. Ну и он не позволяет учесть ситуацию, что номер может быть забронирован в будушем с числа X по число Y.

Логичнее по моему сделать объект "бронь" и в номере сделать список броней. Если группа заселяется в несколько номеров, то можно сделать одну бронь с несколькими номерами, а можно привязать к группе несколько броней - тут уж как решишь.

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

Вот какие я сущности вижу:

- Гостиница
- Номер
- Группа гостей
- Гость
- Бронь (то, что связывает 1 Группу и 1..N Номеров - или 1 Группу и 1 Номер - тут есть разные варианты)
- при желании реализма, объект Оплаты (Счет? не силен в бухгалтерии)

Дальше, мы уже можем решить какие у них есть свойства, и какие между ними есть связи (отношения). Например: Группа содержит Гостей, Группа размещает Бронь, Бронь относится к 1 или нескольким Номерам, Номер содержит список относящихся к нему Броней.

Ты можешь даже попытаться нарисовать эти сущности и связи между ними (есть даже язык диаграмм UML для этого).

Вот не знаю, поможет эта статья или нет, тут упоминаются связи между классами: https://habrahabr.ru/post/150041/

И тут https://ru.wikipedia.org/wiki/Диаграмма_классов

А тут рассказывается про ER модель: https://ru.wikipedia.org/wiki/ER-модель

> private $money;


Тоже не очень понятно назначение свойства

> private function getTotalRooms($freeNumbers)


Не очень понятно, зачем эта функция вообще и что она делает.

> if ($this->getTotalRooms($this->getFreeNumbers($checkIn)) >= count($persons)) {


Это трудно читать из-за обилия скобок. Ну и тут

> foreach ($this->numbers as $key => $value) {


Лучше $numbers as $number

> public function createHotel(Number $number)


Лучше назвать addNumber

То есть у тебя не очень удачно спроектированы классы и из-за этого ты громоздишь весь код в один класс Hotel. И получается уже не совсем ООП.
#638 #1106145
>>1105030

> $word = preg_split


Лучше назвать $words

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

>>1105675

Ты можешь также показать код, который получился, и спросить, что делать дальше. Хотя бы частично-то ты наверно можешь решить?

>>1104766

У тебя вся логика засунута в Hotel, хотя часть ее лучше поместить в другие классы, например:

> if (($value->getExpireDate() <= $date) || ($value->getExpiredDate() == null)) {


Лучше if ($room->isOccupied($date))

> public function isFreeSpecificRoomsNumber($rooms, $date)


Не лучше ли это сделать методов у объекта Number?

Также, тебе надо разобраться, какие есть сущности и какие у них свойства:

> class Hotel


> private $date;


Почему дата - это свойство отеля? Что-то я не понимаю, где тут логика. дата заезда - это свойство заявки на размещение.

Насчет свойства logs - не логичнее ли историю заселения в номер хранить в самом номере? А то у тебя есть там только expireDate, который не отражает историю заселения. Ну и он не позволяет учесть ситуацию, что номер может быть забронирован в будушем с числа X по число Y.

Логичнее по моему сделать объект "бронь" и в номере сделать список броней. Если группа заселяется в несколько номеров, то можно сделать одну бронь с несколькими номерами, а можно привязать к группе несколько броней - тут уж как решишь.

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

Вот какие я сущности вижу:

- Гостиница
- Номер
- Группа гостей
- Гость
- Бронь (то, что связывает 1 Группу и 1..N Номеров - или 1 Группу и 1 Номер - тут есть разные варианты)
- при желании реализма, объект Оплаты (Счет? не силен в бухгалтерии)

Дальше, мы уже можем решить какие у них есть свойства, и какие между ними есть связи (отношения). Например: Группа содержит Гостей, Группа размещает Бронь, Бронь относится к 1 или нескольким Номерам, Номер содержит список относящихся к нему Броней.

Ты можешь даже попытаться нарисовать эти сущности и связи между ними (есть даже язык диаграмм UML для этого).

Вот не знаю, поможет эта статья или нет, тут упоминаются связи между классами: https://habrahabr.ru/post/150041/

И тут https://ru.wikipedia.org/wiki/Диаграмма_классов

А тут рассказывается про ER модель: https://ru.wikipedia.org/wiki/ER-модель

> private $money;


Тоже не очень понятно назначение свойства

> private function getTotalRooms($freeNumbers)


Не очень понятно, зачем эта функция вообще и что она делает.

> if ($this->getTotalRooms($this->getFreeNumbers($checkIn)) >= count($persons)) {


Это трудно читать из-за обилия скобок. Ну и тут

> foreach ($this->numbers as $key => $value) {


Лучше $numbers as $number

> public function createHotel(Number $number)


Лучше назвать addNumber

То есть у тебя не очень удачно спроектированы классы и из-за этого ты громоздишь весь код в один класс Hotel. И получается уже не совсем ООП.
#639 #1106146
>>1104455

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


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

> то есть исключения что бы при ошибки, приложение не работало дальше.


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

https://github.com/dsgaljkeguhodgiosetuhsegjposguh/studlist/blob/master/дамп для создания бд

Этот файл лучше назвать dump.sql или students.sql. Из него стоит убрать название БД (tables), чтобы он не был привязан к конкретной базе.

При оформлении SQL кода стоит придерживаться этого руководства по стилю: http://www.sqlstyle.guide/ru/

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

В репозиторий стоит добавить README с кратким описанием проекта и инструкцией по установке. Образцы (можно даже более кратко сделать):

- https://github.com/Al-faqun/Students/blob/master/README.md
- https://github.com/moroz95/StudentList/blob/master/README.md
- https://github.com/TheSidSpears/Students/blob/master/README.md
- https://github.com/foobar1643/student-list/blob/master/README.md
(если нажать Raw то можно увидеть исходный текст с разметкой)

- мнение про то, как писать: http://qaru.site/questions/19638/how-to-write-a-good-readme

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

https://github.com/dsgaljkeguhodgiosetuhsegjposguh/studlist/blob/master/src/CheckForm/CheckForm.php

> preg_match('/[a-zA-Z1-90]{6,32}/iu',


нет привязки к краям строки (^$), также, для пароля стоит разрешить использовать разные символы.

> [а-яА-Яa]{2,32}


Буква ё в Юникоде идет отдельно от алфавита (не входит в а-я) и ее надо указать отдельно.

> class CheckForm


> const REG_FORM_SEX_MAN = "Мужской";


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

Сообщения об ошибках, конечно, лучше делать более понятные.

> (!preg_match('/[1990-9]{4}/iu'


Неправильная регулярка. [1990-9] значит "одна любая цифра" и равносильно [0-9]. [1990] значит "одна любая из цифр 0, 1 или 9".

Методы checkRegForm() и checkProfileInfo() содержат много одинакового кода. Копипаста кода - это зло. Потому что изучать такой код в 2 раза дольше, править в 2 раза дольше.

https://github.com/dsgaljkeguhodgiosetuhsegjposguh/studlist/blob/master/src/Student/Student.php
Функции setStudent и updateStudentInfo можно объединить в одну, которая принимает массив и обновляет присутствующие в нем поля.

Папку лучше назвать не Student, а Entity или Model.

https://github.com/dsgaljkeguhodgiosetuhsegjposguh/studlist/blob/master/src/DbConnect/DbConnect.php
Этот класс не очень-то и нужен, тебе ведь никто не запрещает просто создать PDO через new.

Ну и сам способ использования класса очень странный:

> $dbConnect = new DbConnect;


> $db = $dbConnect->connect;



Тебе не кажется, что это было бы проще записать так:

$db = connectToDb();
$db = DbConnector::connect();
$db = $dbConnector->connect();
$db = new PDO(...);

То есть, возвращать результат через return а не через записть в свойство?

> }catch (PDOException $e) {


> throw new Exception("Database connection error");


не очень понятен смысл catch. Зачем менять тип исключения с конкретного на более общее?

https://github.com/dsgaljkeguhodgiosetuhsegjposguh/studlist/blob/master/src/UsersTableGateway/UsersTableGateway.php
Тут стоит попробовать применить Dependency Injection: https://github.com/codedokode/pasta/blob/master/arch/di.md

> public function checkEmail($email)


Лучше назвать getEmailUsageCount(), а еще лучше сделать функцию isEmailUsed/isEmailUnique.

То же относится к checkLogin.

> public function addToken($login, $token)


лучше updateToken, или setTokenForLogin.

https://github.com/dsgaljkeguhodgiosetuhsegjposguh/studlist/blob/master/src/Table/Table.php
Это странный класс. Почему он с маленькой буквы? почему назывется table? Это ведь параметры отображения таблицы. Логичнее назвать TableViewParameters или TableParameters, или или TableFilter или ViewFilter. И убрать оттуда работу с БД, работу с GET. Взамен можно добавить ключевое слово.

> $this->countStudents = $this->db->getStudentsCount()['COUNT(*)'];


Это странный код, что мешает из функции getStudentsCount возвращать сразу число? Почему такой странный тип результата функции?

Также, ты не должен для каждого класса создавать по папке. Некоторые можно класть просто в корень, если их мало.

> public function SearchStudents($search, table $table)


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

https://github.com/dsgaljkeguhodgiosetuhsegjposguh/studlist/blob/master/controllers/Router/Router.php
лучше анализировать только path из URL, без query string, тогда проверка может быть очень простая, в стиле if ($path == '/list').

> $title = 'Таблица';


> $body = 'view/table.phtml';


> require_once "controllers/table.php";


> require_once 'view/headers.phtml';


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

Вместо exit лучше бы поставить return.

> Меняю имя страницы.и гружу шапку не знаю куда еще затолкать


В соответствующий контроллер.

У тебя есть автозагрузчик, так что в роутере логичнее писать if (class_exists()).

> $title = 'error';


> $body = "view/error404.phtml";


> exit;
Это ничего не выведет.

> header('location: http://localhost:8081/login');


Тут зря ты прописал домен и порт, как перенести код на другой домен?

https://github.com/dsgaljkeguhodgiosetuhsegjposguh/studlist/blob/master/controllers/reg.php

> 'email' => trim(htmlspecialchars($_POST['email'],ENT_QUOTES)),


> 'password' => trim(htmlspecialchars($_POST['password'],ENT_QUOTES)),


> 'name' => trim(htmlspecialchars($_POST['name'],ENT_QUOTES)),


тут можно применить цикл вместо копипасты.

Контроллеры profile и reg наверно можно объединить?
#639 #1106146
>>1104455

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


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

> то есть исключения что бы при ошибки, приложение не работало дальше.


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

https://github.com/dsgaljkeguhodgiosetuhsegjposguh/studlist/blob/master/дамп для создания бд

Этот файл лучше назвать dump.sql или students.sql. Из него стоит убрать название БД (tables), чтобы он не был привязан к конкретной базе.

При оформлении SQL кода стоит придерживаться этого руководства по стилю: http://www.sqlstyle.guide/ru/

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

В репозиторий стоит добавить README с кратким описанием проекта и инструкцией по установке. Образцы (можно даже более кратко сделать):

- https://github.com/Al-faqun/Students/blob/master/README.md
- https://github.com/moroz95/StudentList/blob/master/README.md
- https://github.com/TheSidSpears/Students/blob/master/README.md
- https://github.com/foobar1643/student-list/blob/master/README.md
(если нажать Raw то можно увидеть исходный текст с разметкой)

- мнение про то, как писать: http://qaru.site/questions/19638/how-to-write-a-good-readme

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

https://github.com/dsgaljkeguhodgiosetuhsegjposguh/studlist/blob/master/src/CheckForm/CheckForm.php

> preg_match('/[a-zA-Z1-90]{6,32}/iu',


нет привязки к краям строки (^$), также, для пароля стоит разрешить использовать разные символы.

> [а-яА-Яa]{2,32}


Буква ё в Юникоде идет отдельно от алфавита (не входит в а-я) и ее надо указать отдельно.

> class CheckForm


> const REG_FORM_SEX_MAN = "Мужской";


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

Сообщения об ошибках, конечно, лучше делать более понятные.

> (!preg_match('/[1990-9]{4}/iu'


Неправильная регулярка. [1990-9] значит "одна любая цифра" и равносильно [0-9]. [1990] значит "одна любая из цифр 0, 1 или 9".

Методы checkRegForm() и checkProfileInfo() содержат много одинакового кода. Копипаста кода - это зло. Потому что изучать такой код в 2 раза дольше, править в 2 раза дольше.

https://github.com/dsgaljkeguhodgiosetuhsegjposguh/studlist/blob/master/src/Student/Student.php
Функции setStudent и updateStudentInfo можно объединить в одну, которая принимает массив и обновляет присутствующие в нем поля.

Папку лучше назвать не Student, а Entity или Model.

https://github.com/dsgaljkeguhodgiosetuhsegjposguh/studlist/blob/master/src/DbConnect/DbConnect.php
Этот класс не очень-то и нужен, тебе ведь никто не запрещает просто создать PDO через new.

Ну и сам способ использования класса очень странный:

> $dbConnect = new DbConnect;


> $db = $dbConnect->connect;



Тебе не кажется, что это было бы проще записать так:

$db = connectToDb();
$db = DbConnector::connect();
$db = $dbConnector->connect();
$db = new PDO(...);

То есть, возвращать результат через return а не через записть в свойство?

> }catch (PDOException $e) {


> throw new Exception("Database connection error");


не очень понятен смысл catch. Зачем менять тип исключения с конкретного на более общее?

https://github.com/dsgaljkeguhodgiosetuhsegjposguh/studlist/blob/master/src/UsersTableGateway/UsersTableGateway.php
Тут стоит попробовать применить Dependency Injection: https://github.com/codedokode/pasta/blob/master/arch/di.md

> public function checkEmail($email)


Лучше назвать getEmailUsageCount(), а еще лучше сделать функцию isEmailUsed/isEmailUnique.

То же относится к checkLogin.

> public function addToken($login, $token)


лучше updateToken, или setTokenForLogin.

https://github.com/dsgaljkeguhodgiosetuhsegjposguh/studlist/blob/master/src/Table/Table.php
Это странный класс. Почему он с маленькой буквы? почему назывется table? Это ведь параметры отображения таблицы. Логичнее назвать TableViewParameters или TableParameters, или или TableFilter или ViewFilter. И убрать оттуда работу с БД, работу с GET. Взамен можно добавить ключевое слово.

> $this->countStudents = $this->db->getStudentsCount()['COUNT(*)'];


Это странный код, что мешает из функции getStudentsCount возвращать сразу число? Почему такой странный тип результата функции?

Также, ты не должен для каждого класса создавать по папке. Некоторые можно класть просто в корень, если их мало.

> public function SearchStudents($search, table $table)


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

https://github.com/dsgaljkeguhodgiosetuhsegjposguh/studlist/blob/master/controllers/Router/Router.php
лучше анализировать только path из URL, без query string, тогда проверка может быть очень простая, в стиле if ($path == '/list').

> $title = 'Таблица';


> $body = 'view/table.phtml';


> require_once "controllers/table.php";


> require_once 'view/headers.phtml';


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

Вместо exit лучше бы поставить return.

> Меняю имя страницы.и гружу шапку не знаю куда еще затолкать


В соответствующий контроллер.

У тебя есть автозагрузчик, так что в роутере логичнее писать if (class_exists()).

> $title = 'error';


> $body = "view/error404.phtml";


> exit;
Это ничего не выведет.

> header('location: http://localhost:8081/login');


Тут зря ты прописал домен и порт, как перенести код на другой домен?

https://github.com/dsgaljkeguhodgiosetuhsegjposguh/studlist/blob/master/controllers/reg.php

> 'email' => trim(htmlspecialchars($_POST['email'],ENT_QUOTES)),


> 'password' => trim(htmlspecialchars($_POST['password'],ENT_QUOTES)),


> 'name' => trim(htmlspecialchars($_POST['name'],ENT_QUOTES)),


тут можно применить цикл вместо копипасты.

Контроллеры profile и reg наверно можно объединить?
#640 #1106147
>>1104428

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

>>1104397

Институтов, где тебя реально будут чему-то учить, очень мало, в основном известные ВУЗы в крупных городах. Плюс, есть программы сотрудничества с вузами у Yandex/mail.ru:

https://it.mail.ru/promo/full-time-learning/
https://it.mail.ru/promo/online-learning/
https://academy.yandex.ru/

ИТМО вроде хороший ВУЗ: http://www.ifmo.ru/ru/ - но и то он не только про IT. Вообще, если ты хочешь просто быть средним программистом, тебе ВУЗ не нужен (по идее это в техникуме должны изучать, но не знаю, изучают ли). ВУЗ по идее учит каким-то более сложным вещам, связанным с серьезной математикой, наукой, и тд. Уж точно там не должны учить, как двигать менюшки на сайте.

Но если ты не ищешь простых путей, и хочешь делать что-то сложное, чем сайты (пусть даже и хорошие) то может быть и есть смысл попробовать поступить в какой-нибудь ВУЗ получше. Если такая возможность есть, наверно не стоит от нее отказываться.

Посмотри для начала рейтитнги ВУЗов вроде таких (первое, что нашел):

https://students.superjob.ru/reiting-vuzov/it/

Или посмотри, кто выигрывает олимпиады ACM:

http://finals.snarknews.info/
https://icpc.baylor.edu/worldfinals/results
https://ru.wikipedia.org/wiki/Международная_студенческая_олимпиада_по_программированию#Победители

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

Ну и конечно, обучение в таком ВУЗе предполагает большую нагрузку. Чтобы доказать, что ты сможешь с ней справиться, ты должен получить высокий балл на вступительных экзаменах (сколько именно, написано на сайте).

Есть статьи на хабре вроде таких: https://habrahabr.ru/post/179891/

>>1104309

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

>>1104281

> запрещает скачивание .exe, .msi и так далее.


Наверняка есть сторонние программы-скачивальщики, лишенные этих ограничеий?
#640 #1106147
>>1104428

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

>>1104397

Институтов, где тебя реально будут чему-то учить, очень мало, в основном известные ВУЗы в крупных городах. Плюс, есть программы сотрудничества с вузами у Yandex/mail.ru:

https://it.mail.ru/promo/full-time-learning/
https://it.mail.ru/promo/online-learning/
https://academy.yandex.ru/

ИТМО вроде хороший ВУЗ: http://www.ifmo.ru/ru/ - но и то он не только про IT. Вообще, если ты хочешь просто быть средним программистом, тебе ВУЗ не нужен (по идее это в техникуме должны изучать, но не знаю, изучают ли). ВУЗ по идее учит каким-то более сложным вещам, связанным с серьезной математикой, наукой, и тд. Уж точно там не должны учить, как двигать менюшки на сайте.

Но если ты не ищешь простых путей, и хочешь делать что-то сложное, чем сайты (пусть даже и хорошие) то может быть и есть смысл попробовать поступить в какой-нибудь ВУЗ получше. Если такая возможность есть, наверно не стоит от нее отказываться.

Посмотри для начала рейтитнги ВУЗов вроде таких (первое, что нашел):

https://students.superjob.ru/reiting-vuzov/it/

Или посмотри, кто выигрывает олимпиады ACM:

http://finals.snarknews.info/
https://icpc.baylor.edu/worldfinals/results
https://ru.wikipedia.org/wiki/Международная_студенческая_олимпиада_по_программированию#Победители

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

Ну и конечно, обучение в таком ВУЗе предполагает большую нагрузку. Чтобы доказать, что ты сможешь с ней справиться, ты должен получить высокий балл на вступительных экзаменах (сколько именно, написано на сайте).

Есть статьи на хабре вроде таких: https://habrahabr.ru/post/179891/

>>1104309

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

>>1104281

> запрещает скачивание .exe, .msi и так далее.


Наверняка есть сторонние программы-скачивальщики, лишенные этих ограничеий?
#641 #1106164
ОП, начал делать TestHub. Первая итерация: https://github.com/TheSidSpears/test_hub
Проверь, плиз
вынос за корень #642 #1106178
<VirtualHost :80>
# Имя сервера которое обслуживает этот VirtualHost
ServerName example.com
# Корневая папка сервера
DocumentRoot /var/www/example.com/public
# ....

у меня сервер начинает падать, когда прописываю
<VirtualHost
:80>

что делать?
#643 #1106183
>>1106178

Посмотреть в логе ошибок Апача, почему.
#644 #1106191
>>1106178
Разве не <VirtualHost *:80> нужно писать? Попробуй
#645 #1106211
>>1106145

>>Почему дата - это свойство отеля? Что-то я не понимаю, где тут логика. дата заезда - это свойство заявки на размещение.


Это дата на сегодня.

>>Насчет свойства logs - не логичнее ли историю заселения в номер хранить в самом номере? А то у тебя есть там только expireDate, который не отражает историю заселения. Ну и он не позволяет учесть ситуацию, что номер может быть забронирован в будушем с числа X по число Y.


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

>>- Бронь (то, что связывает 1 Группу и 1..N Номеров - или 1 Группу и 1 Номер - тут есть разные варианты)


По сути это у меня класс logs.

>> private $money;


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

>> private function getTotalRooms($freeNumbers)


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

В любом случае спасибо большое за ревью. Буду переделывать. Сам понимаю что, что-то перезамудрил, когда начал реализовывать методы. Я так понимаю, что когда сложно делать реализацию эта в первую очередь проблема проектирования.
#646 #1106214
Помогите пожалуйста!
https://ideone.com/tPp46M
Вот такой отрывок, мне нужно из условия с isset(_$GET) получить информацию, обработать и получить ответ в виде post, и в условии с isset($_POST) для обработки результатов мне нужна переменная из get, как ее оттуда достать? Подскажите пожалуйста, с сессией не получается. Спасибо заранее.
#647 #1106215
>>1104428
>>1106147
Там оказалось что сгенерированный json лучше не править руками в текстовом рекдакторе, только в этом была проблема.
#648 #1106218
>>1106214
Все работает, это я дурак, сорян за беспокойство.
#649 #1106219
>>1106214
Ты разбираешься как работают POST и GET запросы?
Какая-то у тебя конструкция адовая.

Я бы реализовал так. Приходит GET запрос, формируется страница с тестом исходя из $_GET["testid"]. На странице с тестом есть форма в которой прописан method POST и например указан action скрипт_обработки_POST_запроса.php . На этой же странице c сформированным тестом можно в скрытое поле складывать $_GET["testid"]. Потом обрабатываешь POST в скрипт_обработки_POST_запроса.php и выдаешь результат.

Относительно хранения временных данных, можно использовать COOKIE или LocalStorage если ты можешь в JavaScript.
#650 #1106224
>>1106219
Более-менее разбираюсь, но я же еще учусь.
То что я налепил выше - работает, просто я сессии вписал, а страницу не обновил (точнее жал при обновлении повторить отправку данных), то есть из гета в $_SESSION ничего не было передано.
Что криво и на костылях - я не сомневаюсь, даже на своем уровне я мог бы сделать лучше, недавно шаблонизацию покурил немножко и родил свой первый шаблонизатор (чуть не помер).
Тут просили в рамках одной страницы сделать отображение тестов и обработку.
#651 #1106275
Раз никто не задает вопросы, дам ссылочку на статью про гигантский репозиторий кода в Гугле: https://cacm.acm.org/magazines/2016/7/204032-why-google-stores-billions-of-lines-of-code-in-a-single-repository/fulltext (англ)

> The Google codebase includes approximately one billion files and has a history of approximately 35 million commits spanning Google's entire 18-year existence. The repository contains 86TB of data, including approximately two billion lines of code in nine million unique source files.



> In 2014, approximately 15 million lines of code were changedb in approximately 250,000 files in the Google repository on a weekly basis. The Linux kernel is a prominent example of a large open source software repository containing approximately 15 million lines of code in 40,000 files.



Ну и раз речь зашла про большие репозитории, то можно еще почитать про перенос репозитория кода Windows на Git:

https://habrahabr.ru/company/everydaytools/blog/329878/ (рус)
https://blogs.msdn.microsoft.com/bharry/2017/05/24/the-largest-git-repo-on-the-planet/ (англ)

> кодовая база Windows состоит из 3.5 миллионов файлов; когда заливаешь ее на Git, получается репозиторий размером где-то в 300 гигабайт.

ZDLgLMu10C0
34 Кб, 448x537
#652 #1106281
>>1106145

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



Хорошо, попробую сделать и это.

https://ideone.com/JTdyXo - посмотри ещё задачу с исправлением ошибок.
У тебя там в коде функция, для изменения регистра первой буквы предложения написана одной строчкой, но я так и не понял как это сделать, поэтому вставил код который загуглил. Есть uсfirst() ещё, но он не работает с многобайтной кодировкой.
#653 #1106304
Где можно достать какие-то годные уроки по вебмастерингу?
Все что гуглю выдает либо старье, либо верстка/пхп и прочие вещи.

Интересует какой-то полный развернутый курс по всей этой кухне: настройка линупса как сервера, работа через терминал (ssh), настройка нгинксов и прочих апачей и чтобы все на русском было
#654 #1106325
>>1106304
ясен хер, тебе выпадают курсы по верстке. "вебмастеринг" - это ублюдское понятие из начала 2000-х, которое и означает верстку.

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

по твоим задачам все просто: линукс, если это дебиан, работает из коробки. установить апач - sudo apt install apache2. настраивать его необязательно, т.к. по http://localhost он будет отвечать сразу же. и у ОПа есть урок по настройке апача.
#655 #1106327
>>1106304

Нужно изучать линукс, bash, и тд. Установить себе линукс либо в виртуалку, либо на свою машину. Для виртуалки могу посоветовать Debian Testing либо Ubuntu Server (Не desktop).

Придется немного помучиться, чтобы сделать доступ виртуалки к интернету и доступ с хоста по ssh:

- https://www.google.ru/search?q=настройка+доступа+к+ssh+с+хоста+virtualbox&newwindow=1&dcr=0&gbv=1&sei=6q8uWvi2HuGg6AS2i6PQAQ
- https://gist.github.com/codedokode/420c8c12a1edae25f0ec

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

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

То есть гуглить надо "учебник по линукс", и желательно поновее.

Затем, освоив основы линукс, ты можешь погуглить документацию по Апачу и другим программам, раздел Install and configure, он обычно на английском.
#656 #1106341
>>1106143
sq3 - просто текст запрса
number - число строк.

И, всё же, моя лабораторная предполагает именно вот это вот всё с функциональным стилем, а не PDO. Мне бы конкретно тот код переделать под mysqli или хотя бы найти альтернативу для вывода всех таблиц неизвестной БД
#657 #1106348
>>1106341

Что значит "предполагает"? В требованиях написано использовать устаревшее расширение mysql? Ставь тогда старую версию PHP.

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

Если тебе принципиально использовать mysqli, то используй: http://php.net/manual/ru/mysqli.quickstart.php
#658 #1106422
>>1106348
да, в ходе работы указано именно mysql, но в университете так же стоит новый PHP и, я предполагаю, преподу просто лень было переписывать свой же сборник лаб. Потому он сказал "ну, вы посмотрите и поправьте под mysqli".

>будешь использовать PDO


Да? Когда я открыл руководство мне в ебало полетели всякие мерзкие сишные -> и ::. И я закрыл, не вчитываясь. Значит, там есть функциональная версия? Как и в mysqli?

>Если тебе принципиально использовать mysqli


Я прочитал. Но в качестве альтрнативы функциям типа mysql_tablename там указаны SQL запросы. Которые возвращают странный объект. А раньше функция возвращала массив, с которым, собственно, работал код скинутый выше. Вопрос изначально и заключался в том, как вообще этим пользоваться для поставленной задачи.
#659 #1106455
>>1106422

>Значит, там есть функциональная версия?


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

ты лучше подумай, что ты приобретешь, выполняя ненужные в реальной жизни задания для препода, которому лень обновить под "новый" php (ООП используется в нем как основная методология уже лет 5 как минимум, т.е. с 5.3).

я не особый знаток функционального программирования (это вопрос к тем, кто знает хаскель там), но то, что обычно называют функциональным программированием в php те, кому лень учить ООП - это скорее надо называть простыней из кода.
#660 #1106528
Пилите перекат, а то мы тонем.
#661 #1106578
>>1106455

>что ты приобретешь, выполняя ненужные в реальной жизни задания для препода



Диплом. А так я вообще джаву предпочитаю или питончик, там. Я не против ООП, мне просто надо сдать лабораторную. Очевидно, в том виде, в котором её хочет видеть преподаватель.

Но я не могу, потому, что коды к старой версии не работают, а альтернатива, которую он разрешил использовать, не возвращает массив. Что мне вообще делать с объектом, который возвращает sql запрос?
#662 #1106594
>>1106578
ну современный пхп не то чтобы глобально отличается от джавы или питона (понятно, что отличия есть).

>Что мне вообще делать с объектом, который возвращает sql запрос?



так без кода сложно говорить. смотря что за объект. по идее у него должны быть методы, которые занимаются формированием массива. вот например в пдо есть метод fetch для объекта PDOStatement https://secure.php.net/manual/en/pdostatement.fetch.php и там можно поставить флаг FETCH_ASSOC, который тебе сформирует массив с ключом и значением.

лучше покажи код, где что-то не возвращает массив, который ты ожидаешь (и укажи версию пхп, где все крутится).
#663 #1106595
>>1106578
да, кстати

>Диплом


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

по поводу джавы. если любишь джаву, то в джаве есть jdbc https://en.wikipedia.org/wiki/Java_Database_Connectivity и они с PDO внезапно очень похожи.
111
19 Кб, 2250x1520
#664 #1106603
Привет! Взялся за php. Установил apache, mysql, phpmyAdmin и сам php 7.0. Апач работает, правда пришлось ебаться с портами, т.к. на 80 выдавал ошибку. Поставил 8080. Непонятно почему при установке и ведение логов mysql, они сохраняются в папке data в в папке mysql,а не в той, что мне надо. И при заходе в phpmyAdmin появляется прикрил, а не сама админка.

Новичок-кун
222
78 Кб, 2250x1520
#665 #1106606
Иерархия сервера

Новичок - кун
#666 #1106607
>>1106595

>вообще ни разу не спрашивали


А вдруг меня спросят? Да и вообще, третий курс уже. Бакалавриат-то закончить надо, не долго осталось.

>если любишь джаву, то в джаве есть


Это всё очень здорово, очень. И, наверное, я даже почитаю вскоре. Но лабораторная то по PHP.

Самообразование - это здорово (нет хотя и необходимо) и я, хм, образовываюсь. Но, во-первых, не в сторону PHP (Да не обидит это никого в треде, вам же меньше конкуренции), а во-вторых, конкретно этот вопрос мне нужно решить именно через mysqli, именно в таком виде и всё такое. Как будто тренировка перед безумным заказчиком.

И я попросил помощи, как раз потому, что на PHP.net не нашёл объяснения тому, что за объект и как из него получить массив или, хотя бы, строку. Очень жаль, что как-то не нашлось людей которые смогли бы с этим помочь.

>>1106603
Почему бы не воспользоваться готовыми решениями, типа Denwer худший, наверное, вариант или любой другой сборкой? Вот, например, небольшой их разбор.
https://habrahabr.ru/post/144242/
#667 #1106608
>>1106607
Устанавливал 2 часа, хочется уже на чем есть
#668 #1106609
>>1106608
боюсь, быстрее установить сборку (благо, даже денвер устанавливается в пару кликов и ввода буквы Y), чем дождаться ответа\разобраться с тем, что ты сделал сам.

Впрочем, наверное, если ты разберёшься, ты получишь куда больше знаний, чем просто используя, да.
#669 #1106610
>>1106609
Я 2 часа копался в этом, а мог в один клик сделать все готовое?
#670 #1106611
>>1106610
что-то вроде того
#671 #1106612
>>1106611
вот блядь. хз теперь, мб все нахер снести и поставить open server
#672 #1106632
>>1106607
может и спросят, конечно.

>Очень жаль, что как-то не нашлось людей которые смогли бы с этим помочь



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

так без кода можно привести объект к массиву либо с помощью реализации у класса этого объекта интерфейса ArrayAccess, либо по-простому миллион вариантов, например вот тут: https://stackoverflow.com/questions/4345554/convert-php-object-to-associative-array
#673 #1106644
удалил то, чем занимался 2 часа. Теперь качаю open server

Хотел еще узнать, насколько хорошо надо знать html, css, js, чтобы понять, что готов писать back-end?
Новичок - кун.
#674 #1106664
>>1106644
если хочешь заниматься только бэкендом, то, в теории, можно вообще не знать. но на практике лучше знать основы, чтобы что-то тестировать (отправлять формы или смотреть xhr-запросы, например).
#675 #1106689
>>1106644
Вот хорошая статья по установке апача, пыха и прочего https://hackware.ru/?p=21 В итоге это удобнее чем какой-нибудь xampp. Апач всегда запущен, не надо никаких прог запускать для этого. Когда выходит новая версия php, по этой же инструкции и обновляешься хоть сразу же, а не ждёшь пока разработчики xampp сделают поддержку в своём продукте. Да и опыт полезный, на собеседовании плюсик будет

ОП, ты вот пишешь комментарии к задачам в самом треде. А я тут узнал, что можно комментировать код на github-e, если сделать pull-request. Почему бы не воспользоваться данным методом, ведь это, как мне кажется, удобнее?
#676 #1106695
>>1106689
По такой статье и устанавливал, только по видяшке с юттабчика. Челик не вставил в описание 6. Установка и настройка phpMyAdmin файла. Вот где я проебался( Но я нетерпелив и уже снес нафиг и скачал Open server. Но это был отличный опыт, на собеседование на типичные ошибки отвечу
#677 #1106696
>>1106664
А сам бэкенд это что? Работа на стороне сервера или создание динамичных сайтов, форм добавления статей итд. На бекенде же много работы, скажем, если я сделаю что-то вроде hdrezka.ru?
#678 #1106698
>>1106696
>>1106695
новичок-кун
#679 #1106701
Освоил типы переменных, правила объявления переменных, if, циклы. Двигаюсь дальше

новичок-кун
#680 #1106761
1. Оцените; как убрать пробелы во второй и третьей строчке?; как можно сделать проще? https://ideone.com/Yd5R6H
2. Где-то слышал про codeacademy. Стоит пробовать или неоч? Есть опыт с этим сайтом?
#681 #1106785
>>1106761
preg-replace(' ','',$string);
#682 #1106881
>>1106696
Что такое фронт- и бекэнд ты сможешь нагуглить. Уметь гуглить - очень полезный навык для программиста ^_^
#683 #1106894
Вообщем, я делаю регистрацию и получается так, что у меня страница регистраци index.php ссылается на саму себя при отправке форм. Отправляю я формы; информация добавляется в базу данных. Все бы хорошо, но когда я обновляю страницу у меня информация повторно и повторно в базу заносится. Допустим я ввел в форму имя Sergey и возраст 9. Заносится информация в бд. Нажимаю ф5 - информация снова заносится и уже Sergey 9 не один, а два. Еще раз и будет их уже три.
Как можно это исправить?
#684 #1106898
>>1106894
У тебя action формы должен быть отличным от той страницы, на которой эта форма располагается. Это прям маст-хев правило такое. Где-то у ОПа в статьях это было описано.

Ты можешь сделать action="register.php", на ней будет происходить обработка и валидация формы и в конце она будет редиректить обратно на index.php, опционально с GET-параметром status.
#685 #1106900
А почему документация такая понятная? Имею ввиду php.com
Новичок-кун
#686 #1106923
Есть div с неким контентом. Есть куча кнопок. Нужно чтобы при нажати на кнопку этит div возникал рядом с нажатой кнопкой. Нажали на другую - переместился на новое место.

Не понимаю, как это сделать. Нашёл пока только такой пример:Шарик под баклофеном курсором https://codepen.io/cleric/pen/dIuFj?editors=1111
Но пока не понял, как его адаптировать под мою цель.
#687 #1106930
>>1106898
Понял. Спасибо большое
#688 #1106931
>>1106923
я сам ньюфаг, но псевдокласс :hover может поможет?
#689 #1106947
>>1106923
ты можешь определить в стилях положения которые тебе нужны и просто менять класс у див используя ЖаваСкрипт.
#690 #1106952
>>1106528

Скоро перекатим, просто надо еще тут на вопросы ответить.
#691 #1106957
>>1097438 (OP)
https://ideone.com/oxgLUi - пиздец я тут с йода-стайлом наговнокодил, подскажите немного как и что исправить.
#692 #1106987
>>1106931

>:hover


Не похоже, что это поможет. Это просто вид элемента при наведении.
>>1106947
Теоретически да. Но не получается.
mzl.yclqycst
77 Кб, 1024x1024
#694 #1107066
Пыхари, поясните за regexp'ы.
Cука /[a-zA-Z0-9\.\-_%]+/ срабатывает и на цифирьки, и на букивки, а надо чтобы только на букивки с цифирьками вместе. Где я объебался?
someApprentice #695 #1107067
>>1106923
У нас есть как раз такая задача и советы по её решению https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-12

Причём её решение делается без подключения JS.
#696 #1107069
>>1107066

>/[a-zA-Z0-9\.\-_%]+/


/[a-zA-Z]+[0-9\.\-_%]+/
Бля, сам решил.
Зато побампал.
someApprentice #697 #1107070
>>1107066

>Cука /[a-zA-Z0-9\.\-_%]+/ срабатывает и на цифирьки, и на букивки, а надо чтобы только на букивки с цифирьками вместе.


А можно по понятнее? И примеры хорошо бы.

Наверно что-то такое должно получиться, если я правильно понимаю https://regex101.com/r/qfD5Da/1
#698 #1107072
>>1107003
Анон, ты гений, я с этой хренью сидел сегодня почти весь день и нихрена не получилось. Спасибо!
#699 #1107075
Что я делаю не так?
В одном файле:
setcookie('name', 1, time () + 200, "/");

Дальше идет переадрессация через форму в другой файл

if(isset($_COOKIE['name'])){
echo "it works!";
}

var_dump($_COOKIE);

и в ответ array(0) { }
#700 #1107090
Вопрос по хтмл, не бейте сильно
Есть навбар, в него хочу запихнуть картинки.
Как задать отступ именно на размер навбара? В еденицах не устраивает, т.к. картинки могут быть разных размеров.
#701 #1107124
Пилите перекат, 700 постов уже.
#702 #1107127
>>1107124
в предыдущем вообще под 1000 было, так что все ок
#703 #1107148
>>1100771
Ребят, подскажите! Почему этот код работает:

$true = isset($_COOKIE['notification']);
// if(isset($_COOKIE['notificaton'])){
if($true){
echo '<div class="notification">' . $_COOKIE['notification'] . '</div>';
setcookie('notification', '', time() - 1);
}

А этот - нет:

// $true = isset($_COOKIE['notification']);
if(isset($_COOKIE['notificaton'])){
// if($true){
echo '<div class="notification">' . $_COOKIE['notification'] . '</div>';
setcookie('notification', '', time() - 1);
}

?

Что самое смешное, if(!isset($_COOKIE['notificaton'])) во втором примере работает! Хотя isset при существующих куках же должен true возвращать?

PHP 7.1.12, Apache/2.4.29
#704 #1107169
>>1107148

>echo '<div class="notification">' . $_COOKIE['notification'] . '</div>';


>


посмотри таблицу https://secure.php.net/manual/en/types.comparisons.php

isset равен true для в т.ч. значений 0, '', и других.

а при приведении 0 к булеану (что происходит в условии), он становится false и оно не выполняется.

и про приведение типов почитай https://secure.php.net/manual/ru/language.types.type-juggling.php

в твоем случае можно использовать !empty вместо isset

алсо, называть переменную $true - плохая идея, т.к. насилие это над мозгом других анонов. хорошую альтернативу сходу придумать не могу, т.к. такие значения (иссет что-то там) никто в доп. переменные не кладет, но даже $notificationIsSet будет лучше (хотя это тоже полное говно).
#705 #1107196
>>1107169

Назвать можно $cookieExists, $doesCookieExist
#706 #1107197
>>1106923

Да, там выше написали, это делаектся примерно так.

Кнопка с запоминанием состояния делается из чекбокса. Этот чекбокс можно скрыть средствами CSS и привязать к нему label, который будет реагировать на клики вместо него. В зависимости от состояния чекбокса можно менять вид кнопки, за счет CSS вроде input:checked + .class { ... }.

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

.checkbox1
.checkbox2
.checkbox3
.some-div

То мы можем писать правила вроде .checkbox1:checked ~ .some-div { ... }.

Ну и конечно остается еще вариант использовать яваскрипт.

>>1107090

Я не очень понял, о чем речь, потому придется угадывать, либо тебе надо описать проблему нормально.

Навбар закреплен с помощью position: fixed, имеет неизвестную высоту и надо сделать на body соответствующий ему отступ? Наверно, только JS может помочь. Либо отказ от fixed.

>>1107124

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

>>1107148

Зачем гадать. Попробуй сделать var_dump($true); var_dump($_COOKIE); var_dump(isset(...)); в обоих случаях.
#706 #1107197
>>1106923

Да, там выше написали, это делаектся примерно так.

Кнопка с запоминанием состояния делается из чекбокса. Этот чекбокс можно скрыть средствами CSS и привязать к нему label, который будет реагировать на клики вместо него. В зависимости от состояния чекбокса можно менять вид кнопки, за счет CSS вроде input:checked + .class { ... }.

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

.checkbox1
.checkbox2
.checkbox3
.some-div

То мы можем писать правила вроде .checkbox1:checked ~ .some-div { ... }.

Ну и конечно остается еще вариант использовать яваскрипт.

>>1107090

Я не очень понял, о чем речь, потому придется угадывать, либо тебе надо описать проблему нормально.

Навбар закреплен с помощью position: fixed, имеет неизвестную высоту и надо сделать на body соответствующий ему отступ? Наверно, только JS может помочь. Либо отказ от fixed.

>>1107124

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

>>1107148

Зачем гадать. Попробуй сделать var_dump($true); var_dump($_COOKIE); var_dump(isset(...)); в обоих случаях.
#707 #1107198
>>1107075

Стоит открыть средства разработчика (Ctrl + Shift + I), вкладку Network, и перезагрузить страницу. На вкладке посмотреть заголовки ответа Set-Cookie. Потом посмотреть вкладку Resources, где показываются куки, и посмотреть параметры куки.

>>1107003

Я бы советовал улучшить код:

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

>>1107072

Изучай DOM, затем jQuery и получится. В ОП посте есть задачки в помощь, ну а мануал по jQuery легко гуглится.

>>1106957

Незачем код разбиения текста на предложения копипастить 2 раза. Копипаста - зло, раздувает объем кода, его становится должше читать.

Функцию makeFirstletterUppercase лучше сделать так, чтобы она работала только для одного слова или предложения, и вызывать ее изнутри цикла для каждого предлложения.

> foreach ($splitText as $splits) {


Лучше $sentences as $sentence.

> $clearText = preg_replace("/[,;]/u", "", $splits);


Здесь незачем создавать новую переменную.

> $replace = preg_replace("/\s([.]{1})\s/u", "$1 ", $port);


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

> array_push($yodaText, $result);


$yodaText[] = $result;
#707 #1107198
>>1107075

Стоит открыть средства разработчика (Ctrl + Shift + I), вкладку Network, и перезагрузить страницу. На вкладке посмотреть заголовки ответа Set-Cookie. Потом посмотреть вкладку Resources, где показываются куки, и посмотреть параметры куки.

>>1107003

Я бы советовал улучшить код:

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

>>1107072

Изучай DOM, затем jQuery и получится. В ОП посте есть задачки в помощь, ну а мануал по jQuery легко гуглится.

>>1106957

Незачем код разбиения текста на предложения копипастить 2 раза. Копипаста - зло, раздувает объем кода, его становится должше читать.

Функцию makeFirstletterUppercase лучше сделать так, чтобы она работала только для одного слова или предложения, и вызывать ее изнутри цикла для каждого предлложения.

> foreach ($splitText as $splits) {


Лучше $sentences as $sentence.

> $clearText = preg_replace("/[,;]/u", "", $splits);


Здесь незачем создавать новую переменную.

> $replace = preg_replace("/\s([.]{1})\s/u", "$1 ", $port);


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

> array_push($yodaText, $result);


$yodaText[] = $result;
#708 #1107200
>>1106898

Ты все перепутал и даешь неправильный совет. Вот урок по формам https://github.com/codedokode/pasta/blob/master/forms.md

Подумай сам, как в твоем варианте при ошибке вывести форму с введенными ранее значениями?

>>1106894

> у меня страница регистраци index.php ссылается на саму себя при отправке форм


Так и должно быть.

> Все бы хорошо, но когда я обновляю страницу у меня информация повторно и повторно в базу заносится.


Нужно делать редирект после успешного заполнения формы, читай урок https://github.com/codedokode/pasta/blob/master/forms.md

>>1106761

Ну так попробуйи посмотри, это же вроде бесплатно.

> как убрать пробелы во второй и третьей строчке?


лучше всего их не добавлять туда с самого начала. Например, ты можешь сделать проверку, если текущее "слово" равно "\n", то не выводить пробел.

> for ($i = 0;$i < 4;$i++) {


Тут надо использовать foreach вместо ручного подсчета и указания числа элементов в массиве.

>>1106696

Фронт/бек - это "передняя" и "задняя" часть системы из 2 частей. Бэкенд в данном случае - серверный код, фронтенд - код, работающий в браузере.
#708 #1107200
>>1106898

Ты все перепутал и даешь неправильный совет. Вот урок по формам https://github.com/codedokode/pasta/blob/master/forms.md

Подумай сам, как в твоем варианте при ошибке вывести форму с введенными ранее значениями?

>>1106894

> у меня страница регистраци index.php ссылается на саму себя при отправке форм


Так и должно быть.

> Все бы хорошо, но когда я обновляю страницу у меня информация повторно и повторно в базу заносится.


Нужно делать редирект после успешного заполнения формы, читай урок https://github.com/codedokode/pasta/blob/master/forms.md

>>1106761

Ну так попробуйи посмотри, это же вроде бесплатно.

> как убрать пробелы во второй и третьей строчке?


лучше всего их не добавлять туда с самого начала. Например, ты можешь сделать проверку, если текущее "слово" равно "\n", то не выводить пробел.

> for ($i = 0;$i < 4;$i++) {


Тут надо использовать foreach вместо ручного подсчета и указания числа элементов в массиве.

>>1106696

Фронт/бек - это "передняя" и "задняя" часть системы из 2 частей. Бэкенд в данном случае - серверный код, фронтенд - код, работающий в браузере.
#709 #1107201
>>1106689

Да нифига не удобно. Кто будет делать pull request и куда? pull request ведь делается в существующий репозиторий снаружи.

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

>>1106644

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

>>1106607

> вам же меньше конкуренции


Ты пока не очень похож на конкурента

> на PHP.net не нашёл объяснения тому, что за объект и как из него получить массив или, хотя бы, строку


Чтобы использовать mysqli, строго желательно освоить основы ООП. Если ты хочешь писать на Java, C#, Руби, JS - знание ООП все равно понадобится.

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

Далее, имея понимание ООП, мы открываем мануал и легко находим ответ.

mysqli::query возвращает объект mysqli_result, который представляет собой ответ сервера на SQL запрос (результат запроса). Это написано тут: http://php.net/manual/ru/mysqli.query.php

Открываем мануал по mysqli_result: http://php.net/manual/ru/class.mysqli-result.php

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

>>1106603

> на 80 выдавал ошибку.


Он занят какой-нибудь программой вроде скайпа, надо в настройках это отключить. Посмотреть кто именно занял порт, можно набрав команду netstat -abn в привилегированной консоли с правами админа. Если что, гайд по командной строке в ОП посте.

> Непонятно почему при установке и ведение логов mysql, они сохраняются в папке data в в папке mysql,а не в той, что мне надо.


А где ты прописал папку? В my.ini? А сервер MySQL перезапустил?

> И при заходе в phpmyAdmin появляется прикрил, а не сама админка.


Очевидно, там надо создать конфиг, который ты не создал.

Есть раздел в мануале: https://docs.phpmyadmin.net/en/latest/setup.html#quick-install

Там написано:

> Now you must configure your installation. ...


> Using Setup script


> Next, open your browser and visit the location where you installed phpMyAdmin, with the /setup suffix. The changes are not saved to the server, you need to use the Download button to save them to your computer and then upload to the server.



Надо выполнить то, что тут написано, то есть зайти в /setup и настроить.
#709 #1107201
>>1106689

Да нифига не удобно. Кто будет делать pull request и куда? pull request ведь делается в существующий репозиторий снаружи.

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

>>1106644

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

>>1106607

> вам же меньше конкуренции


Ты пока не очень похож на конкурента

> на PHP.net не нашёл объяснения тому, что за объект и как из него получить массив или, хотя бы, строку


Чтобы использовать mysqli, строго желательно освоить основы ООП. Если ты хочешь писать на Java, C#, Руби, JS - знание ООП все равно понадобится.

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

Далее, имея понимание ООП, мы открываем мануал и легко находим ответ.

mysqli::query возвращает объект mysqli_result, который представляет собой ответ сервера на SQL запрос (результат запроса). Это написано тут: http://php.net/manual/ru/mysqli.query.php

Открываем мануал по mysqli_result: http://php.net/manual/ru/class.mysqli-result.php

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

>>1106603

> на 80 выдавал ошибку.


Он занят какой-нибудь программой вроде скайпа, надо в настройках это отключить. Посмотреть кто именно занял порт, можно набрав команду netstat -abn в привилегированной консоли с правами админа. Если что, гайд по командной строке в ОП посте.

> Непонятно почему при установке и ведение логов mysql, они сохраняются в папке data в в папке mysql,а не в той, что мне надо.


А где ты прописал папку? В my.ini? А сервер MySQL перезапустил?

> И при заходе в phpmyAdmin появляется прикрил, а не сама админка.


Очевидно, там надо создать конфиг, который ты не создал.

Есть раздел в мануале: https://docs.phpmyadmin.net/en/latest/setup.html#quick-install

Там написано:

> Now you must configure your installation. ...


> Using Setup script


> Next, open your browser and visit the location where you installed phpMyAdmin, with the /setup suffix. The changes are not saved to the server, you need to use the Download button to save them to your computer and then upload to the server.



Надо выполнить то, что тут написано, то есть зайти в /setup и настроить.
#710 #1107202
>>1106281

> Есть uсfirst() ещё, но он не работает с многобайтной кодировкой.


Да, не работает.

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


Отрезаешь первую букву с помощью mb_substr, переводишь в верхний регистр с помощью mb_strtoupper, приклеиваешь остаток строки.

> [,:]{1}


{1} тут не нужен. И \s* тоже.

> (?<=[.!?](?![.!?]))


Здесь условия незачем вкладывать друг в друга, и можно просто написать (?<=...)(?!...)

>>1106211

>>>Почему дата - это свойство отеля? Что-то я не понимаю, где тут логика. дата заезда - это свойство заявки на размещение.


> Это дата на сегодня.


Сегодняшняя дата это не свойство Гостиницы, как не крути. Свойства Гостиницы - это, например, список Номеров в ней.

>> private $money;


> Сюда хотел по итогу дня складывать выручку.


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

Это проще вычислять, а не хранить.

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


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

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


А, мы просто не так друг друга поняли. Обычно в англ. языке Номер называется "Room" или "Suit". Вот примеры предложений:

http://context.reverso.net/перевод/русский-английский/Трехместный+номер,
https://www.linguee.ru/русский-английский/перевод/трехместный.html

Вот видишь, как важно выбирать правильные названия полей и переменных.
#710 #1107202
>>1106281

> Есть uсfirst() ещё, но он не работает с многобайтной кодировкой.


Да, не работает.

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


Отрезаешь первую букву с помощью mb_substr, переводишь в верхний регистр с помощью mb_strtoupper, приклеиваешь остаток строки.

> [,:]{1}


{1} тут не нужен. И \s* тоже.

> (?<=[.!?](?![.!?]))


Здесь условия незачем вкладывать друг в друга, и можно просто написать (?<=...)(?!...)

>>1106211

>>>Почему дата - это свойство отеля? Что-то я не понимаю, где тут логика. дата заезда - это свойство заявки на размещение.


> Это дата на сегодня.


Сегодняшняя дата это не свойство Гостиницы, как не крути. Свойства Гостиницы - это, например, список Номеров в ней.

>> private $money;


> Сюда хотел по итогу дня складывать выручку.


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

Это проще вычислять, а не хранить.

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


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

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


А, мы просто не так друг друга поняли. Обычно в англ. языке Номер называется "Room" или "Suit". Вот примеры предложений:

http://context.reverso.net/перевод/русский-английский/Трехместный+номер,
https://www.linguee.ru/русский-английский/перевод/трехместный.html

Вот видишь, как важно выбирать правильные названия полей и переменных.
#711 #1107203
>>1106211

Вот еще про то, в чем разница между room и suit, мне стало любопытно и я погуглил: https://www.yellowpages.ca/tips/what-is-the-difference-between-a-hotel-room-and-suite/
Безымянный
87 Кб, 1035x260
#712 #1107218
>>1107197

>Наверно, только JS может помочь. Либо отказ от fixed


М-м-м. Ясно. Буду думать.
И подскажи пожалуйста еще момент, почему ссылка меняет текст и получает подчеркивание? Там же стоит text-decoration: none;
#713 #1107220
>>1107218
текст
цвет офк
#714 #1107228
>>1107218

Потому что надо еще поставить то же самое для :hover. Иначе встроенное правило браузера

a:hover { ... }

Имеет более высокий приоритет.

https://webref.ru/course/css-basics/priority (псевдокласс вроде :hover имеет тот же вес, что и обычный класс)
https://habrahabr.ru/post/137588/
#715 #1107232
>>1107228
Спасибо.
#716 #1107265
>>1097438 (OP)
есть вопрос, что ты думаешь по поводу этих >1099454 идей? чувак кукухой поехал или он прав?
#717 #1107266
>>1107265
сорян >>1099454 вот ссылка
изображение
19 Кб, 548x450
#718 #1107274
>>1107201

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



А ведь можно оказывается без всяких pull-request'ов создавать issue и в нём описывать проблему: https://github.com/TheSidSpears/test_hub/issues/2
Это ж круто, анон делает pull в мастер, просит проверить код, ты создаешь пачку issue, пишешь в тред "проверяй", анон их решает и закрывает, делает новый pull в мастер и так по кругу
#719 #1107284
>>1107274

Вообще, надо посмотреть, почему бы и нет.

С пулл-реквестами - они ведь вроде только из одного репозитория в другой создаются.

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

Плюс, я быстро печатаю, у меня даже Sublime от такой скорости набора подвисать начинает со временем, а браузер уж точно тормозить будет, я думаю. Хотя это надо еще проверить, может и не будет.
#720 #1107285
Пытаюсь указать папке public корень сервера, но не могу найти <VirtualHost *:80> в httpd.conf. Как же тогда прописать путь корня?
Apache
17 Кб, 747x244
#721 #1107288
>>1107285
Не нашел ни ServerName example.com ни <VirtualHost *:80>, но вроде сделал и работает

Что я делаю не так? Или так? Спасибо.
#722 #1107290
Нубский вопрос про статус коды хттп и функцию header. Я пилю студентов, и сейчас ломаю голову на обработчиком ошибок. Если вбрасывается исключение роутера, то понятно что пользователь не на тот урл зашел и надо редиректить его на 404 через header. А что делать, если например, произошла ошибка в БД, то тоже на 404 редирект нужен? И как лучше сделать страницу с ошибкой? Если я через апач вот так сделаю: RewriteEngine On ErrorDocument 404 /404.html, то это ок?
#723 #1107292
>>1107284
где-то специально учился быстро печатать или оно само?
#724 #1107302
Как сделать, чтоб всплывающий при наведении на линк див не пропадал, когда курсор переходит на див, а пропадал только после ухода с дива?
Примерно так, как в розетке главное меню реализовано.
#725 #1107312
Допустим у меня есть класс с магическим методом __construct

Вопрос: могу ли я в качестве аргумента использовать mysql запрос? Или как по другому загрузить в объект информацю нужную ?
#726 #1107313
>>1107312
Студенты если что. Или может не нужно использовать так классы?
#727 #1107317
>>1107067
>>1107197
>>1107198
Спасибо, посмотрю.
#728 #1107330
Зачем нужен break в 7 версии, если он теперь выдает ошибку в условиях if-else, циклах for, foreach, while ?

'break' not in the 'loop' or 'switch' context
#729 #1107332
>>1107330
Вопрос решен.
#730 #1107359
Анон, что делать? Пилю задачку Grammar Nazi из раздела про регулярные выражения. Там надо вывести ошибку с куском текста. Я запилил регэксп с поиском ошибок через |. Заключил его в скобки и с каждого конца поставил .{10}?
Проблема в том, что если в эти десять символов до или после попадается ошибка, то preg_match_all её не находит. Как это исправить?
someApprentice #731 #1107383
>>1107285
>>1107288
Если погуглить, то можно найти, что настройки с VirtualHost находятся в apache\conf\extra\httpd-vhosts.conf

G: windows apache virtualhost
someApprentice #732 #1107393
>>1107290

>А что делать, если например, произошла ошибка в БД, то тоже на 404 редирект нужен?


Должна быть ошибка 500

>И как лучше сделать страницу с ошибкой?


Ловим ошибку/исключение

https://secure.php.net/manual/ru/function.set-error-handler.php
https://secure.php.net/manual/ru/function.set-exception-handler.php

Для пользователя выводим страницу что что-то сломалось, со статусом 500

Подробности ошибки сохраняем в лог

https://secure.php.net/manual/ru/function.error-log.php

https://secure.php.net/manual/ru/book.errorfunc.php

>Если я через апач вот так сделаю: RewriteEngine On ErrorDocument 404 /404.html, то это ок?


Я не знаю
#733 #1107405
Почему может выдавать неправильные номера символов в строке PREG OFFSET CAPTURE?
someApprentice #734 #1107407
>>1107312
>>1107313
Обычно, конструктор используется для заполнения полей класса и для внедрения зависимостей

Прим.
class User
{
private $id;
private $login;
private $password;

//заполнение полей
public function __construct($id, $login, $password)
{
$this->id = $id;
$this->login = $login;
$this->password = $password;
}
}

class Database
{
public function addUser(User $user)
{
$query = "INSERT INTO users ...";
...
}
...
}

class Controller
{
private $database;

//внедрение зависимостей
public function __construct(Database $database)
{
$this->database = $database;
}

public function run()
{
$user = new User(...);

$this->database->addUser($user);
}
}

>могу ли я в качестве аргумента использовать mysql запрос?


В доктрине есть метод принимающий sql-запрос в качестве аргумента. Такой паттерн, вроде, называется Query Builder, но я не уверен насчет этого.

>Или как по другому загрузить в объект информацю нужную ?


Через конструктор и/или аргументы методов.

Но не стоит передавать в них сам запрос, а только информацию нужную для него.

>function addUser($login, $password)


> {


> $pdo = ...;


> $query = $pdo->prepare("INSERT INTO users (id, login, password) VALUES (NULL, :login, :password)");


> $query->execute(array(


> 'login' => $login,


> 'password' => $password


> ));


> }

someApprentice #734 #1107407
>>1107312
>>1107313
Обычно, конструктор используется для заполнения полей класса и для внедрения зависимостей

Прим.
class User
{
private $id;
private $login;
private $password;

//заполнение полей
public function __construct($id, $login, $password)
{
$this->id = $id;
$this->login = $login;
$this->password = $password;
}
}

class Database
{
public function addUser(User $user)
{
$query = "INSERT INTO users ...";
...
}
...
}

class Controller
{
private $database;

//внедрение зависимостей
public function __construct(Database $database)
{
$this->database = $database;
}

public function run()
{
$user = new User(...);

$this->database->addUser($user);
}
}

>могу ли я в качестве аргумента использовать mysql запрос?


В доктрине есть метод принимающий sql-запрос в качестве аргумента. Такой паттерн, вроде, называется Query Builder, но я не уверен насчет этого.

>Или как по другому загрузить в объект информацю нужную ?


Через конструктор и/или аргументы методов.

Но не стоит передавать в них сам запрос, а только информацию нужную для него.

>function addUser($login, $password)


> {


> $pdo = ...;


> $query = $pdo->prepare("INSERT INTO users (id, login, password) VALUES (NULL, :login, :password)");


> $query->execute(array(


> 'login' => $login,


> 'password' => $password


> ));


> }

someApprentice #735 #1107411
>>1107359
Покажи код
#736 #1107412
>>1107405

Он выдает не номер символа, а номер байта. Ну например, в utf-8 кириллица занимает 2 байта и может быть несовпадение из-за этого. Преобразовать номера байта в номер символа можно хитрыми манипуляциями с substr/mb_strlen.
#737 #1107414
>>1107407

Query Builder это когда строят запрос по кусочкам, обычно из-за наличия if или циклов (если запрос всегда одинаковый, то проще его сразу и написать):

$qb = new QueryBuilder('some_table');
$qb->where('x = ?', $x);
if ($y) {
$qb->andWhere('y = ?', $y);
}

$qb->orderBy('zzz');
$sql = $qb->getSql();
#738 #1107415
>>1107312

По поводу работы c базой данных с использованием ООП- обязательно для начала прочти теорию по этой теме: https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md

Специально сделал обзор и все разжевал.
#739 #1107470
В задании с поиском опечаточников всё сделал отлично, только в квадратных скобках высвечивается последняя английская буква всегда. Регэксп, чтобы была первая, никак не могу придумать. Мой регэксп:
/([а-яёa-z])([a-z]+)([а-яёa-z])/ui
ЧЯДНТ?
#740 #1107475
>>1107470
Сделал, запилив дополнительный регэксп без первой скобки перед реплейсментом. Чувствую, что уебанство, но до универсального регэкспа не догадался.
#741 #1107483
Сап. Нужно получить такой json
https://pastebin.com/P2xhDuMc
Создаю такой вот массив https://pastebin.com/EbKnNubE
но получаю https://pastebin.com/wbrES8pD
Как добавить еще одни скобки вначале?
#742 #1107496
Сап анонам. Делаю задание про список студентов, у меня есть класс StudentGateway, это часть моей модели, которая собсна делает все дела с бд и таблицей студентов, пока что там только 3 метода, но я буду добавлять еще что-то вроде поиска, изменения и мб чего-то еще. https://pastebin.com/M1QDrhjf Я хотел спросить, не сильно ли по ДЫБЫЛЬНОМУ? Я там что-то написал, но у меня нет опыта, и собсна никакой уверенности в правильности моих решений. Из-за этого мне грустно :(
#743 #1107528
>>1107496
У всех сначала не было опыта. Больше пиши и читай чужой код. И не грусти, а то станешь как я.
someApprentice #744 #1107556
>>1107496

>https://pastebin.com/M1QDrhjf


>private $query;


>private $sql;


>


>$this->sql = 'SELECT first_name,last_name,group_num,exam_sum FROM students ORDER BY id DESC LIMIT '. $this->rows .' OFFSET '. $this->offset;


>$this->query = $this->db->getPdo()->prepare($this->sql);


Свойства здесь не нужны, лучше использовать простые переменные, а в свойствах хранить только PDO как зависимость.

>private $db;


>public function __construct(...) {


>$this->db = new Database();


Вот примерно так, только сам класс StudentGataway наследовать от твоего Database, и само PDO передавать в конструктор, и сохранять в свойства.

>public function __construct($p) {


>$this->offset = $p * $this->rows - $this->rows; //сверхформула для высчитывания оффсета, чтобы переходить по страницам вроде page=1, page=2 etc


>}


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

>public function SelectStudent(){


>


>$this->sql = 'SELECT first_name,last_name,group_num,exam_sum FROM students ORDER BY id DESC LIMIT '. $this->rows .' OFFSET '. $this->offset;


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

>public function getTotalRows()


Лучше сделать такую функцию в пагинаторе и передавать в неё количество, а на её прежнем месте сделать функцию getCount().
someApprentice #744 #1107556
>>1107496

>https://pastebin.com/M1QDrhjf


>private $query;


>private $sql;


>


>$this->sql = 'SELECT first_name,last_name,group_num,exam_sum FROM students ORDER BY id DESC LIMIT '. $this->rows .' OFFSET '. $this->offset;


>$this->query = $this->db->getPdo()->prepare($this->sql);


Свойства здесь не нужны, лучше использовать простые переменные, а в свойствах хранить только PDO как зависимость.

>private $db;


>public function __construct(...) {


>$this->db = new Database();


Вот примерно так, только сам класс StudentGataway наследовать от твоего Database, и само PDO передавать в конструктор, и сохранять в свойства.

>public function __construct($p) {


>$this->offset = $p * $this->rows - $this->rows; //сверхформула для высчитывания оффсета, чтобы переходить по страницам вроде page=1, page=2 etc


>}


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

>public function SelectStudent(){


>


>$this->sql = 'SELECT first_name,last_name,group_num,exam_sum FROM students ORDER BY id DESC LIMIT '. $this->rows .' OFFSET '. $this->offset;


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

>public function getTotalRows()


Лучше сделать такую функцию в пагинаторе и передавать в неё количество, а на её прежнем месте сделать функцию getCount().
#745 #1107664
>>1107169
Спасибо за табличку, в моем случае $_COOKIE['notification'] или строка, или NULL (я куки очищаю полностью же, как только получил сообщение). Поэтому как isset, так и !empty должны давать одинаковый результат.

Нуок, сделал так:
if(!empty($_COOKIE['notification'])) {
echo '<div class="notification">' . $_COOKIE['notification'] . '</div>';
setcookie('notification', '', time() - 1);
}
Все равно не работает, хотя var_dump показывает bool(true). Опять же, оборачиваю в переменную либо использую обратное значение (empty без !) - все работает!

Насчет имени переменной - сорян, если изнасиловал кому-то мозг, понимаю, что так нельзя называть, но у меня дико припекало от того, что фактически if(true) не выполняется.

>а при приведении 0 к булеану (что происходит в условии), он становится false и оно не выполняется.


Ничего не понял, как там может появиться 0, если куки пусты?

>>1107197

>Зачем гадать. Попробуй сделать var_dump($true); var_dump($_COOKIE); var_dump(isset(...)); в обоих случаях.



Да в том-то и дело, что в обоих случаях они все либо true (и в массиве 1 строка), либо false (и тогда массив соответственно пустой).

А теперь - внимание!!! Разгадка. Внимательно посмотрите на эти две строчки, и скажите, чем они отличаются:
if(isset($_COOKIE['notificaton']))
if(isset($_COOKIE['notification']))
Больше часа на это убил, еще и анону мозг вынес, г-ди, какой же я тупой)))))
Кстати, как избежать в дальнейшем подобного мозгоебства? Более короткие имена использовать? Может какие-то редакторы/плагины под это дело есть? Сам юзаю саблайм, потихоньку перекатываюсь на VS Code.
#746 #1107669
>>1107284
Я специально занимался слепой 10-и пальцевой печатью, у меня на play.typeracer.com частенько скорость набора переваливает за 120 слов в минуту, печатаю в браузере - ничего не глючит. Может вам следует обновить железо?

>>1107274
Не вариант, в твоём репозитории никто ответы ОПа читать не будет. А в треде удобно то, что объяснения могут увидеть много человек, спросить что не понятно.

>>1107292
10-ю пальцами без практики не научишься. Качай любой тренажёр и тренируйся. Ну и учти, что при написании кода тебе это особо не понадобится, если пишешь не в блокноте, а в нормальной IDE. А вот при переписке с кем-то - очень помогает.
#747 #1107684
>>1107302
bump
Понимаю, что надо использовать mouseover, но не понимаю как его прилепить на всплывающий див.
#748 #1107723
>>1107664

>как избежать в дальнейшем подобного мозгоебства?


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

еще надо ставить error_reporting E_ALL, чтобы при исполнении генерировался notice о том, что такого ключа у массива нет.

также во всяких условиях я пишу примерно так
if (123 === $value), т.е. значение слева и строгое сравнение. потому что если писать как обычно, можно проебаться, написав if ($value = 123) и оно выдаст true и IDE от такого не защитит.

а в целом полностью никак не защититься. и со временем перестанешь удивляться, что так происходит, придет смирение.
#749 #1107728
>>1107292
я счалал прогу stamina (но думаю любая подойдет) и недели за две переучился и по-русски, и по-английски. главное когда учишься, стараться печатать медленно и без ошибок.
#750 #1107744
>>1107664

>Ничего не понял, как там может появиться 0, если куки пусты?


>


я про твои куки ничего не знаю пусты они там или нет. я просто имел в виду что
$var1 = 0;
$var2 = '';
isset($var1); // true
isset($var2); // true
if ($var1 || $var2) {
// не выполнится
}
#751 #1107749
>>1107728

>я счалал


>печатать медленно и без ошибок


обосрался, да
#752 #1107778
Смотрю алгоритм по возврату неправильных значений в форму и немного не понимаю, что там писать.

$values = значения по умолчанию (пустые);
$errors = пустой массив;

Если (форма отправлена) {
Копируем переданные значения полей в $values;
Проверяем значения в $values и записываем найденные ошибки в $errors;

Если (ошибок нет) {
Делаем требуемое действие (например вставляем запись в БД);
Редиректим куда-нибудь;
Завершаем скрипт;
}
}

Выводим форму($values, $errors);

Какой код нужно написать в Выводим форму? Завершаем скрипт?
Screenshot86
46 Кб, 792x418
#753 #1107863
Привет, погромисты. У меня возникла необходимость в создании карты сети. Есть бд со свитчами, их связями и т.д. То есть по базе понятно какой свитч к какому подключен и через какой порт. Нужно реализовать карту сети, на которой
бы динамически отрисовывались все устройства и их подключения. Как это лучше сделать? Мне на ум приходит только вариант с библиотекой GD. То есть тупо рисовать картинку в коде. Может есть получше варианты?
#754 #1107892
>>1107863
Кажись сам разобрался, GraphViz думаю подойдет.
#755 #1107917
>>1107669

> в твоём репозитории никто ответы ОПа читать не будет



ну серьёзно, кому еще нужны ответы ОПа к не своей задаче? Их никто не читает, кроме того, кому они адресованы
#756 #1107920
>>1107917

>Их никто не читает



Я читаю например, если что-то не знаю или не понимаю.
#757 #1107921
>>1107917

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


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

по-моему, если хочешь научиться, логично читать подробные комментарии к чужим задачам. странно, что ты так не делаешь.
#758 #1108017
http://php.net/manual/en/datetime.settime.php

Вот для времени "когда" используется DateTime. (когда заканчивается урок? - в 12:15)
А для времени "сколько" его тоже можно использовать? (сколько длиться урок? - 45 минут)

Так же в MySQL в какой тип использовать для второго?
#759 #1108035
>>1107198

>Незачем код разбиения текста на предложения копипастить 2 раза. Копипаста - зло, раздувает объем кода, его становится должше читать.


> Функцию makeFirstletterUppercase лучше сделать так, чтобы она работала только для одного слова или предложения, и вызывать ее изнутри цикла для каждого предлложения.



https://ideone.com/ga6iPB - исправил свой говнокод с йодастайлом, посмотри, пожалуйста.
#761 #1108057
>>1106761

>codeacademy


вкатывальщики жрат
#762 #1108060
>>1108054
>>1105723

>// Если файла нет, то ничего не делаем - может быть, блаблабла


Враньё, require выдаст фатальную ошибку
asian
2,7 Мб, webm,
1280x720, 0:09
#763 #1108062
Задам неприличный вопрос: есть тут знатоки C++, которые модно молодёжно собирают себе форки php? Поделитесь хотя бы попсовыми хорошими практиками?
#764 #1108066
>>1108060
А, нет, извините, до этого не дойдёт. Заработался.
#765 #1108113
>>1108062

>C++


А зачем плюсплюс? Там же простой C.
123
91 Кб, 1065x564
#766 #1108319
Тред еще жив?
Подскажите почему вот это перестало работать при загрузке на удаленный сервер, на локальном все збс.
#767 #1108324
>>1108319

Короткие теги <? не включены, используй <?php. Кстати, ты мог бы это проверить, открыв исходный код страницы в браузере и проверив, отображаются ли они там.
#768 #1108332
>>1108324
Спасибо тебе милчеловек.
#769 #1108383
>>1107917
Я тоже читаю все ответы опа.
#770 #1108425
Аноны, погодите еще немного с перекатом, еще не на все вопросы ответил.

>>1108062

Я как-то компилировал PHP под Windows. Он по моему на Си, а не Си++, если не путаю. Насчет хороших практик - думаю, подойдут любые "хорошие практики" по Си++.

>>1108017

Это называется "интервал времени". Для него есть класс:

http://php.net/manual/en/class.dateinterval.php
А также http://php.net/manual/en/class.dateperiod.php

В стандарте SQL для этого есть специальный тип INTERVAL, судя по https://www.techrepublic.com/article/sql-basics-datetime-and-interval-data-types/ .

Тут описана его реализация в Postgres: https://postgrespro.ru/docs/postgrespro/9.5/datatype-datetime.html

Тут описана его реализация в Oracle: https://www.toadworld.com/platforms/oracle/w/wiki/2041.interval-datatypes

В MySQL судя по https://dev.mysql.com/worklog/task/?id=831 это пока не реализовано.

Вместо этого для интервала (если он небольшой) можно испоьзовать тип TIME, судя по https://dev.mysql.com/doc/refman/5.7/en/time.html

> MySQL retrieves and displays TIME values in 'HH:MM:SS' format (or 'HHH:MM:SS' format for large hours values). TIME values may range from '-838:59:59' to '838:59:59'. The hours part may be so large because the TIME type can be used not only to represent a time of day (which must be less than 24 hours), but also elapsed time or a time interval between two events (which may be much greater than 24 hours, or even negative).



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

Как напоминание об интервалах, в MySQL есть такая конструкция:

NOW() + INTERVAL 1 MONTH

https://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_date-add
#770 #1108425
Аноны, погодите еще немного с перекатом, еще не на все вопросы ответил.

>>1108062

Я как-то компилировал PHP под Windows. Он по моему на Си, а не Си++, если не путаю. Насчет хороших практик - думаю, подойдут любые "хорошие практики" по Си++.

>>1108017

Это называется "интервал времени". Для него есть класс:

http://php.net/manual/en/class.dateinterval.php
А также http://php.net/manual/en/class.dateperiod.php

В стандарте SQL для этого есть специальный тип INTERVAL, судя по https://www.techrepublic.com/article/sql-basics-datetime-and-interval-data-types/ .

Тут описана его реализация в Postgres: https://postgrespro.ru/docs/postgrespro/9.5/datatype-datetime.html

Тут описана его реализация в Oracle: https://www.toadworld.com/platforms/oracle/w/wiki/2041.interval-datatypes

В MySQL судя по https://dev.mysql.com/worklog/task/?id=831 это пока не реализовано.

Вместо этого для интервала (если он небольшой) можно испоьзовать тип TIME, судя по https://dev.mysql.com/doc/refman/5.7/en/time.html

> MySQL retrieves and displays TIME values in 'HH:MM:SS' format (or 'HHH:MM:SS' format for large hours values). TIME values may range from '-838:59:59' to '838:59:59'. The hours part may be so large because the TIME type can be used not only to represent a time of day (which must be less than 24 hours), but also elapsed time or a time interval between two events (which may be much greater than 24 hours, or even negative).



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

Как напоминание об интервалах, в MySQL есть такая конструкция:

NOW() + INTERVAL 1 MONTH

https://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_date-add
#771 #1108426
>>1107778

> Какой код нужно написать в Выводим форму?


Тот, который выводит страницу с формой. Если ты используешь шаблон, то тот, который вызывает этот шаблон. Шаблоны описаны тут https://github.com/codedokode/pasta/blob/master/php/templates.md

> Завершаем скрипт?


return или exit в зависимости от того, как реализован у тебя контроллер.

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

>>1108054

Код с ошибками.

Замечания:

- неправильно, что ты пытаешься подключить файл без проверки. Во-первых, автозагрузчиков может быть несколько и например библиотека может использовать свой загрузчик из своей папки. Твой же выдаст ошибку в этом случае.
- во-вторых, твой автозагрузчик выдаст ошибку на код вроде if (class_exists('InvalidClassName')) { ... }
- DOCUMENT_ROOT использовать тоже неправильно. Он имеет смысл только внутри веб-сервера (а не при запуске из командной строки например), да и не всегда корректно указывает куда-то (представь например случай php-fpm + nginx).

Алсо, в PHP есть встроенная функция-автозагрузчик, ищущая файл в include_path: http://php.net/manual/ru/function.spl-autoload.php

>>1108035

> foreach ($sentence as $sentences) {


Наоборот должно быть, множественное число идет в начале. $sentences as $sentence. "Из набора предложений взять по очереди каждое предложение".

> $firstUp = mb_strtoupper(mb_substr($text, 0, 1)) . mb_substr($text, 1, null);


> return $firstUp;


Можно сразу писать return mb_strtoupper...

А так, решено верно.
#771 #1108426
>>1107778

> Какой код нужно написать в Выводим форму?


Тот, который выводит страницу с формой. Если ты используешь шаблон, то тот, который вызывает этот шаблон. Шаблоны описаны тут https://github.com/codedokode/pasta/blob/master/php/templates.md

> Завершаем скрипт?


return или exit в зависимости от того, как реализован у тебя контроллер.

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

>>1108054

Код с ошибками.

Замечания:

- неправильно, что ты пытаешься подключить файл без проверки. Во-первых, автозагрузчиков может быть несколько и например библиотека может использовать свой загрузчик из своей папки. Твой же выдаст ошибку в этом случае.
- во-вторых, твой автозагрузчик выдаст ошибку на код вроде if (class_exists('InvalidClassName')) { ... }
- DOCUMENT_ROOT использовать тоже неправильно. Он имеет смысл только внутри веб-сервера (а не при запуске из командной строки например), да и не всегда корректно указывает куда-то (представь например случай php-fpm + nginx).

Алсо, в PHP есть встроенная функция-автозагрузчик, ищущая файл в include_path: http://php.net/manual/ru/function.spl-autoload.php

>>1108035

> foreach ($sentence as $sentences) {


Наоборот должно быть, множественное число идет в начале. $sentences as $sentence. "Из набора предложений взять по очереди каждое предложение".

> $firstUp = mb_strtoupper(mb_substr($text, 0, 1)) . mb_substr($text, 1, null);


> return $firstUp;


Можно сразу писать return mb_strtoupper...

А так, решено верно.
#772 #1108427
>>1107723

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

Еще из полезных возможностей - быстрый переход при вводе части имени файла или класса. Очень полезно, когда большой проект.

Насчет защиты (тут бы не помогло): я стараюсь писать вместо isset($array['field']) или empty просто array_key_exists('field', $array), так как isset/empty промолчит если я опечатаюсь в названии $array. Не люблю такие функции.

Тут бы помогла константа: $_COOKIE[NOITFICATION_COOKIE]. Она же помогла бы сделать нечитаемое название куки вроде nf (Гугл такие названия любит, смотрите любой сервис гугла).

>>1107302

1) Поместить див внутрь ссылки в HTML коде.
2) Использовать JS

3) Также, можно использовать интересный трюк с псевдоэлементом:

<a title="xxx" href="">ссылка</a>

a:before {
content: attr(title);
display: block;
position: absolute;
}

Попробуй-ка так сделать.

>>1107669

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

Раскладку переключаю с помощью левого/правого Ctrl, без этого постоянно ошибки получаются.
#772 #1108427
>>1107723

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

Еще из полезных возможностей - быстрый переход при вводе части имени файла или класса. Очень полезно, когда большой проект.

Насчет защиты (тут бы не помогло): я стараюсь писать вместо isset($array['field']) или empty просто array_key_exists('field', $array), так как isset/empty промолчит если я опечатаюсь в названии $array. Не люблю такие функции.

Тут бы помогла константа: $_COOKIE[NOITFICATION_COOKIE]. Она же помогла бы сделать нечитаемое название куки вроде nf (Гугл такие названия любит, смотрите любой сервис гугла).

>>1107302

1) Поместить див внутрь ссылки в HTML коде.
2) Использовать JS

3) Также, можно использовать интересный трюк с псевдоэлементом:

<a title="xxx" href="">ссылка</a>

a:before {
content: attr(title);
display: block;
position: absolute;
}

Попробуй-ка так сделать.

>>1107669

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

Раскладку переключаю с помощью левого/правого Ctrl, без этого постоянно ошибки получаются.
#773 #1108428
>>1107496

Имена функций/методов пишут с маленькой буквы.

Имена файлов должны быть в едином стиле:

> /Student.php';


> .'/db_connection.php';



В плане ООП, у меня ощущение, что ты не понимаешь, зачем нужны поля и просто натыкал их наугад. Что представляет собой объект StudentGateway? Какие свойства должны быть у этого объекта?

> private $query;


$query - это свойство объекта StudentGateway? Для какой цели оно хранится? Там не нужно поле, а достаточно простой переменной.

> private $sql;


> private $offset;


То же замечание

> public function __construct($p) {


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

Также, я бы советовал убрать работу со страницами из SG, это по идее не его задача. Удобнее и гибче сделать получение данных через offset/limit, а не по номеру страницы.

> $this->db = new Database();


Тут советую почитать урок пр DI https://github.com/codedokode/pasta/blob/master/arch/di.md

> LIMIT '. $this->rows .


Нужно подставлять данные через плейсхолдеры

> while ($row = $this->query->fetch(PDO::FETCH_ASSOC)) {


> $listOfStudents[] = $row;


Это можно сделать одним действием, посмотри мануал по PDOStatement.

> $listOfStudents


Можно просто $students.

> $this->sql = 'SELECT COUNT(id) FROM students';


> $this->query = $this->db->getPdo()->prepare($this->sql);


Если в запросе нет подставляемых параметров, то prepare не требуется, можно сразу выполнять запрос.

> $pages = intval($pages['COUNT(id)']);


> $pages = $pages / $this->rows;


Мне кажется, что функция с названием getTotalRows должна возвращать число строк в таблице.
#773 #1108428
>>1107496

Имена функций/методов пишут с маленькой буквы.

Имена файлов должны быть в едином стиле:

> /Student.php';


> .'/db_connection.php';



В плане ООП, у меня ощущение, что ты не понимаешь, зачем нужны поля и просто натыкал их наугад. Что представляет собой объект StudentGateway? Какие свойства должны быть у этого объекта?

> private $query;


$query - это свойство объекта StudentGateway? Для какой цели оно хранится? Там не нужно поле, а достаточно простой переменной.

> private $sql;


> private $offset;


То же замечание

> public function __construct($p) {


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

Также, я бы советовал убрать работу со страницами из SG, это по идее не его задача. Удобнее и гибче сделать получение данных через offset/limit, а не по номеру страницы.

> $this->db = new Database();


Тут советую почитать урок пр DI https://github.com/codedokode/pasta/blob/master/arch/di.md

> LIMIT '. $this->rows .


Нужно подставлять данные через плейсхолдеры

> while ($row = $this->query->fetch(PDO::FETCH_ASSOC)) {


> $listOfStudents[] = $row;


Это можно сделать одним действием, посмотри мануал по PDOStatement.

> $listOfStudents


Можно просто $students.

> $this->sql = 'SELECT COUNT(id) FROM students';


> $this->query = $this->db->getPdo()->prepare($this->sql);


Если в запросе нет подставляемых параметров, то prepare не требуется, можно сразу выполнять запрос.

> $pages = intval($pages['COUNT(id)']);


> $pages = $pages / $this->rows;


Мне кажется, что функция с названием getTotalRows должна возвращать число строк в таблице.
#774 #1108429
>>1107556

> Вот примерно так, только сам класс StudentGataway наследовать от твоего Database,


Наследование - это отношение A is B (A is an improved version of B), и не уверен, что оно тут годится. Наследовать можно скорее от класса вроде AbstractGateway.

>>1107483

Добавить еще один уровень вложенности массива

'occupancies' => [
[...],
[...]
]

>>1107470

Нужно написать:

только кириллица - латиница - любые буквы

>>1107290

Немного описано тут https://github.com/codedokode/pasta/blob/master/php/exceptions.md#Страница-ошибки-в-веб-приложениях

>>1107359

Да, preg_match не проходит один кусок строки дважды. Исправить это сложно:

- либо получать позицию найденного фрагмента в тексте средствами флага PREG_OFFSET_CAPTURE в preg_match_all и с ее помощью брать подстроку. PREG_OFFSET_CAPTURE возвращает позицию не в символах, а в байтах, потому придется делать преобразование с помощью mb_strlen/substr.
- либо получать позицию найденного фрагмента строки с помощью mb_strpos (не работает, если одинаковых фрагментов там несколько)

Также, можно вместо одного регекспа сделать несколько и искать каждый по отдельности.

>>1107290

Нельзя при 404 ошибке делать редирект. Так как он значит "контент есть, но по другому адресу". Надо сразу выдавать страницу ошибки.

> А что делать, если например, произошла ошибка в БД, то тоже на 404 редирект нужен?


Нужно выдавать код 5xx, почитай список кодов состояния: https://ru.wikipedia.org/wiki/Список_кодов_состояния_HTTP
#774 #1108429
>>1107556

> Вот примерно так, только сам класс StudentGataway наследовать от твоего Database,


Наследование - это отношение A is B (A is an improved version of B), и не уверен, что оно тут годится. Наследовать можно скорее от класса вроде AbstractGateway.

>>1107483

Добавить еще один уровень вложенности массива

'occupancies' => [
[...],
[...]
]

>>1107470

Нужно написать:

только кириллица - латиница - любые буквы

>>1107290

Немного описано тут https://github.com/codedokode/pasta/blob/master/php/exceptions.md#Страница-ошибки-в-веб-приложениях

>>1107359

Да, preg_match не проходит один кусок строки дважды. Исправить это сложно:

- либо получать позицию найденного фрагмента в тексте средствами флага PREG_OFFSET_CAPTURE в preg_match_all и с ее помощью брать подстроку. PREG_OFFSET_CAPTURE возвращает позицию не в символах, а в байтах, потому придется делать преобразование с помощью mb_strlen/substr.
- либо получать позицию найденного фрагмента строки с помощью mb_strpos (не работает, если одинаковых фрагментов там несколько)

Также, можно вместо одного регекспа сделать несколько и искать каждый по отдельности.

>>1107290

Нельзя при 404 ошибке делать редирект. Так как он значит "контент есть, но по другому адресу". Надо сразу выдавать страницу ошибки.

> А что делать, если например, произошла ошибка в БД, то тоже на 404 редирект нужен?


Нужно выдавать код 5xx, почитай список кодов состояния: https://ru.wikipedia.org/wiki/Список_кодов_состояния_HTTP
#775 #1108431
>>1107288

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

>>1107265
>>1107266

Такой интересный вопрос, и никто в треде не комментирует? Что же вы так.

> 1. заканчивать названия объектов на -er - это анти ооп http://www.yegor256.com/2015/03/09/objects-end-with-er.html



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

- если сервис использовал DI, то теперь мы должны передавать зависимости при создании сущности, хотя они, может быть, ей редко когда нужны и выглядят "лишними". То есть в объект User мы должны передавать PDO, и еще какие-то зависимости.
- если сервис создает сущности (StudentGateway->findStudentById(..)), то как этот код перенести в Student?
- мы должны смешивать функционал в одном классе и менять паттерны в угоды этой идее. Например, в соответствии с его идеями, мы должны отказаться от Data Mapper и заменить его на Active Record, которая имеет недостатки (много функционала собрано в одном классе).
- на практике, с одной сущностью часто можно делать очень много вещей. Возьмем Пост в блоге: опубликовать, прокомментировать, лайкнуть, проверить на правильность, сохранить в БД, загрузить из БД, поделиться ссылкой на Пост по почте. Ну или возьмите Товар в интернет-магазине. Или Пользователя в соцсети. Там просто тонна функционала и класс станет огромным, и будет напоминать God object.

Если подумать над решением указанных проблем, "сервисы" как раз помогают их решить. Вот также статья про Service Layer: http://design-pattern.ru/patterns/service-layer.html

Возможно, что это не "чистый ООП". А это где-то описано, каким должен быть "чистый ООП"? Я не знаю.

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

По второму вопросу.

> Isn't it already clear that a single-argument constructor of class CSV expects the name of a file with comma-separated values? I would rename it to file


fileName как раз лучше, так как file у меня ассоциируется с объектом вроде SplFileObject.

> 3. пустые строки - это тоже code smell, т.к. они означают, что метод не соблюдает принцип единой обязанности.


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

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


Почитать такую статью и попробовать составить свое мнение было бы полезно.
#775 #1108431
>>1107288

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

>>1107265
>>1107266

Такой интересный вопрос, и никто в треде не комментирует? Что же вы так.

> 1. заканчивать названия объектов на -er - это анти ооп http://www.yegor256.com/2015/03/09/objects-end-with-er.html



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

- если сервис использовал DI, то теперь мы должны передавать зависимости при создании сущности, хотя они, может быть, ей редко когда нужны и выглядят "лишними". То есть в объект User мы должны передавать PDO, и еще какие-то зависимости.
- если сервис создает сущности (StudentGateway->findStudentById(..)), то как этот код перенести в Student?
- мы должны смешивать функционал в одном классе и менять паттерны в угоды этой идее. Например, в соответствии с его идеями, мы должны отказаться от Data Mapper и заменить его на Active Record, которая имеет недостатки (много функционала собрано в одном классе).
- на практике, с одной сущностью часто можно делать очень много вещей. Возьмем Пост в блоге: опубликовать, прокомментировать, лайкнуть, проверить на правильность, сохранить в БД, загрузить из БД, поделиться ссылкой на Пост по почте. Ну или возьмите Товар в интернет-магазине. Или Пользователя в соцсети. Там просто тонна функционала и класс станет огромным, и будет напоминать God object.

Если подумать над решением указанных проблем, "сервисы" как раз помогают их решить. Вот также статья про Service Layer: http://design-pattern.ru/patterns/service-layer.html

Возможно, что это не "чистый ООП". А это где-то описано, каким должен быть "чистый ООП"? Я не знаю.

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

По второму вопросу.

> Isn't it already clear that a single-argument constructor of class CSV expects the name of a file with comma-separated values? I would rename it to file


fileName как раз лучше, так как file у меня ассоциируется с объектом вроде SplFileObject.

> 3. пустые строки - это тоже code smell, т.к. они означают, что метод не соблюдает принцип единой обязанности.


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

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


Почитать такую статью и попробовать составить свое мнение было бы полезно.
#776 #1108433
>>1099612

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

По коду, ты перестарался, логичнее наверно $e = new Email('[ ^xANUSmeQ;^PUNCTUMcopi"m'); if ($e->isValid()) ... Как бонус, мы получаем специальный тип для email и можем тайп-хинтить его:

public function setEmail(Email $email);

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

>>1106900

Да, считается, что у PHP хорошая документация.
#777 #1108497
>>1108433
Не обращай внимания, это я попробовал написать код используя только объекты и вилку (ну без нее блядь никак же), ориентируясь на то что там этот тип пишет "ООП это объекты и ничего более".

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

<html>
<head>
<?php include 'autoload.php'; ?>
</head>
<body>
...
</body>
</html>

Ничего не выводит, если расширение .html, работает корректно если .php

Здесь якобы работает https://github.com/codedokode/pasta/blob/master/php/templates.md

В процессе поиска наткнулся на

https://habrahabr.ru/post/139154/
где черти в комментах опустили автора небалуй.

ОП, молю, объясни кто прав, кто виноват!
#779 #1108532
Пытаюсь спарсить магазин в .onion при помощи curl, ничего не выходит. Я разобрался, как получить доступ к .onion сайтам через curl (
$proxy = 'http://127.0.0.1:9150/';
curl_setopt($ch, CURLOPT_PROXY, $proxy);
curl_setopt($ch, CURLOPT_PROXYTYPE, 7);
)
и некоторые сайты действительно работают, однако нужный мне - нет. У него на входе стоит каптча и чувствую, что дело в ней.
Возвращает следующие хэдеры:
HTTP/1.1 302 Moved Temporarily Server: nginx Date: Sat, 16 Dec 2017 19:34:23 GMT Content-Type: application/octet-stream Transfer-Encoding: chunked Connection: close Set-Cookie: pregate=1513452863.64191784b0be11457be059be4ad2bcff.3fa8d862745b15a3ff47c669f88a3869 Location: /

При установке curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1) просто входит в бесконечный луп и отваливается на максимальном времени исполнения скрипта.
#780 #1108547
>>1108431
спасибо.

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

>I thought it was obvious that the vast majority of modern software written in modern OO languages is unmaintainable and simply a mess.


http://www.yegor256.com/2016/08/15/what-is-wrong-object-oriented-programming.html

вот достаточно посмотреть на названия статей по ООП http://www.yegor256.com/tag/oop.html
он считает злом ORM, activeRecord, геттеры и сеттеры, try-catch и много чего еще.

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

а по поводу плодить сущности без необходимости у него есть статья про то, что много маленьких классов - это как большой словарный запас, т.е. норм. вот она http://www.yegor256.com/2017/02/28/too-many-classes.html
#781 #1108622
>>1108547
Ты вообще неправильно понял.

>> I thought it was obvious that the vast majority of modern software written in modern OO languages is unmaintainable and simply a mess.



Он говорит о том, что большинство написанного софта на современных ООП языках - неподдерживаямая груда кода, где тут "ООП как на неизбежное зло"? Автор как раз за ООП, только у него своё понимание.

О том, что геттеры/сеттеры это не ООП и нарушают принцип Tell Dont Ask рассказывал даже один из авторов доктрины: https://youtu.be/WW2qPKukoZY?t=8m49s

try-catch тоже нужно избегать. Проблема в том, что большинство PHP-разработчиков не понимают исключения. Исключения нужно выбрасывать в исключительных ситуациях, которые не должны происходить. И ловиться для того, чтобы как-то оповещать разработчика о том, что что-то пошло не так. Я же постоянно в коде натыкаюсь на ситуции, когда исключения используют для валидации пользовательского ввода, что неверно, так как неверный ввод мы как правило ожидаем от пользователя.
#782 #1108634
>>1097438 (OP)
Есть таблица, создаваемая по результату SQL-запроса. В каждой строке в ней добавлено текстовое поле для sumbit для записи текст в SQL через скрипт вроде
$var="\"".$_GET['submit1']."\""
$sql="INSERT into form1 (col1) VALUES (var)";

Как можно сделать, чтобы передавать в скрипт не только данные из поля submit1, но и данные из одной из ячеек в строке, в которой делается submit, и ещё текущее время ?

Можно, наверное, для каждой строки делать своё имя submit+row['id'] (будет submit1, sumbit2) и т.д., а потом из обрабатывающего скрипта/функции, зная, какая это строка, делать ещё один запрос и брать нужное значение и добавлять его к данным из формы, но может как-то попроще можно ?
#783 #1108680
>>1108504

Мне кажется, ты читал невнимательно и все перепутал. Если ты открываешь URL вроде http://localhost/test.html то веб-сервер по расширению видит, что это статический файл и отдает его как есть.

Если ты открываешь URL http://localhost/test.php то сервер с помощью PHP выполняет код из файла.

Это описано тут например https://github.com/codedokode/pasta/blob/master/soft/web-server.md#Встроенный-в-php-сервер

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

Когда ты в PHP коде пишешь require то расширение вообще не имеет значения.

Статья с хабра вообще отношения не имеет к делу. Что касается вставки значений в JS код, то у меня тоже есть урок по теме https://github.com/codedokode/pasta/blob/master/js/pass-values.md

Я тебе настоятельно рекомендую разобраться, как работает веб-сервер, как браузер и веб-сервер взаимодействуют. Не понимая этого, ты нормально дальше двигаться не сможешь. В идеале, хорошо бы было, если бы ты попробовал вручную отправить HTTP запрос, как описано в моем уроке. Это не так и сложно.
#784 #1108692
>>1108547

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

Могу кстати сказать, что в старых версиях ИЕ для хранения HTML была использована не-ООП модель, и из-за этого DOM у них работал медленно и плохо (хотя, может быть и более экономно с точки зрения использования памяти, их модель была заточена на сайты, которые особо не модифицируют DOM, и плохо работала с современными интерактивными SPA приложениями): https://blogs.windows.com/msedgedev/2017/04/19/modernizing-dom-tree-microsoft-edge/

Бывают случаи, когда ООП не нужен - например, если вы пишете программу для обработки данных от какой-нибудь научной установки, там одна математика и структуры сложнее массивов в общем-то не требуются. И бывают случаи, когда люди начинают городить переусложненную архитектуру, как тут: https://habrahabr.ru/post/153225/ (та самая статья про хлеб).

Там есть цитата Линуса про то, что ему не нравится Си++, и отчасти поэтому в ядре линукса используется только Си. Но, например, в МакОСи фреймворк для написания драйверов объектно-ориентированный: https://developer.apple.com/library/content/documentation/DeviceDrivers/Conceptual/IOKitFundamentals/Introduction/Introduction.html - а недостатки Си++ исправлены тем, что там из него убрана часть особо опасных фич.

И действительно, для драйверов ООП хорошо подходит: допустим, у нас есть драйвер USB-флешки. Когда мы втыкаем эту флешку, система создает экземпляр драйвера (на деле чуть сложнее конечно). Втыкаем вторую - создает второй экземпляр. Вынимаем - уничтожает. Аналогии с ООП очевидны. Устройства обычно подключены к шинам (PCI, USB и тд), и эта иерархия тоже хорошо моделируется с помощью ООП. Также, при написании драйвера часто берется какой-то общий шаблон (например, шаблон драйвера звуковой карты) за основу и дополняется кодом работы уже с конкретным устройством. Это иногда можно удачно реализовать с помощью наследования.

Да и вообще, основной язык разработки под Mac/iOS долгое время был Objective-C - ООП-расширение языка Си.

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

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

Если кому-то хочется попробовать свои силы, в треде есть задачи про Гостиницу ( >>1100283 ) и Продюсерское Агенство (запощу отдельным постом ниже). И обратите внимание, это еще примеры простых задач, которые решаются за 30 минут. ООП тем и хорош, что он масштабируется на гораздо более сложные системы, которые пишутся человеко-годами. Потому он и используется.

Тут надо учесть, что я не особо силен в теории ООП. Я хорошо знаю только тот вид (?) ООП, который используется в приложениях на языках вроде Java/C++/скриптовых языков (то есть PHP/Python/Ruby). Я не изучал Simula и Smalltalk, в которых была реализована первоначальная версия ООП ( https://en.wikipedia.org/wiki/Object-oriented_programming#History ).

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

Наверно, один из примеров, где можно увидеть недостатки - это ORM. Объекты не очень хорошо ложатся на SQL-таблицы, ORM часто получаются сложные, с разными костылями вроде "ленивой загрузки" (чтобы не вытягивать всю БД в память) и искуственных языков вроде DQL, но тут уж извините, попробуйте написать лучше. В итоге ORM все же экономит время на написание кода работы с БД. У этого автора же, кстати, про ORM тоже статья есть: http://www.yegor256.com/2014/12/01/orm-offensive-anti-pattern.html (если хотите, и ее можем обсудить).

Также, если посмотрите, статья начинается со слов:

> Recently, I was trying to convince a few of my readers that a better understanding of an object in OOP would help us solve many problems in existing pseudo-object-oriented languages.



То есть автор и не отрицает необходимость ООП, ему просто чем-то не нравится его реализация в языках программирования. И если посмотреть другую его статью ( http://www.yegor256.com/2016/07/14/who-is-object.html ), то тут он топит за инкапсуляцию (хотя это слово в ней ни разу не использовано).

> Java is the most distressing thing to happen to computing since MS-DOS.


А вот тут обидно. На ней весь юзерспейс (не-ядро) Андроида собран и он прекрасно работает.

> он считает злом ORM, activeRecord, геттеры и сеттеры, try-catch и много чего еще.


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

Я всегда готов поучастовать в обсуждении и высказать свое мнение.
#784 #1108692
>>1108547

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

Могу кстати сказать, что в старых версиях ИЕ для хранения HTML была использована не-ООП модель, и из-за этого DOM у них работал медленно и плохо (хотя, может быть и более экономно с точки зрения использования памяти, их модель была заточена на сайты, которые особо не модифицируют DOM, и плохо работала с современными интерактивными SPA приложениями): https://blogs.windows.com/msedgedev/2017/04/19/modernizing-dom-tree-microsoft-edge/

Бывают случаи, когда ООП не нужен - например, если вы пишете программу для обработки данных от какой-нибудь научной установки, там одна математика и структуры сложнее массивов в общем-то не требуются. И бывают случаи, когда люди начинают городить переусложненную архитектуру, как тут: https://habrahabr.ru/post/153225/ (та самая статья про хлеб).

Там есть цитата Линуса про то, что ему не нравится Си++, и отчасти поэтому в ядре линукса используется только Си. Но, например, в МакОСи фреймворк для написания драйверов объектно-ориентированный: https://developer.apple.com/library/content/documentation/DeviceDrivers/Conceptual/IOKitFundamentals/Introduction/Introduction.html - а недостатки Си++ исправлены тем, что там из него убрана часть особо опасных фич.

И действительно, для драйверов ООП хорошо подходит: допустим, у нас есть драйвер USB-флешки. Когда мы втыкаем эту флешку, система создает экземпляр драйвера (на деле чуть сложнее конечно). Втыкаем вторую - создает второй экземпляр. Вынимаем - уничтожает. Аналогии с ООП очевидны. Устройства обычно подключены к шинам (PCI, USB и тд), и эта иерархия тоже хорошо моделируется с помощью ООП. Также, при написании драйвера часто берется какой-то общий шаблон (например, шаблон драйвера звуковой карты) за основу и дополняется кодом работы уже с конкретным устройством. Это иногда можно удачно реализовать с помощью наследования.

Да и вообще, основной язык разработки под Mac/iOS долгое время был Objective-C - ООП-расширение языка Си.

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

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

Если кому-то хочется попробовать свои силы, в треде есть задачи про Гостиницу ( >>1100283 ) и Продюсерское Агенство (запощу отдельным постом ниже). И обратите внимание, это еще примеры простых задач, которые решаются за 30 минут. ООП тем и хорош, что он масштабируется на гораздо более сложные системы, которые пишутся человеко-годами. Потому он и используется.

Тут надо учесть, что я не особо силен в теории ООП. Я хорошо знаю только тот вид (?) ООП, который используется в приложениях на языках вроде Java/C++/скриптовых языков (то есть PHP/Python/Ruby). Я не изучал Simula и Smalltalk, в которых была реализована первоначальная версия ООП ( https://en.wikipedia.org/wiki/Object-oriented_programming#History ).

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

Наверно, один из примеров, где можно увидеть недостатки - это ORM. Объекты не очень хорошо ложатся на SQL-таблицы, ORM часто получаются сложные, с разными костылями вроде "ленивой загрузки" (чтобы не вытягивать всю БД в память) и искуственных языков вроде DQL, но тут уж извините, попробуйте написать лучше. В итоге ORM все же экономит время на написание кода работы с БД. У этого автора же, кстати, про ORM тоже статья есть: http://www.yegor256.com/2014/12/01/orm-offensive-anti-pattern.html (если хотите, и ее можем обсудить).

Также, если посмотрите, статья начинается со слов:

> Recently, I was trying to convince a few of my readers that a better understanding of an object in OOP would help us solve many problems in existing pseudo-object-oriented languages.



То есть автор и не отрицает необходимость ООП, ему просто чем-то не нравится его реализация в языках программирования. И если посмотреть другую его статью ( http://www.yegor256.com/2016/07/14/who-is-object.html ), то тут он топит за инкапсуляцию (хотя это слово в ней ни разу не использовано).

> Java is the most distressing thing to happen to computing since MS-DOS.


А вот тут обидно. На ней весь юзерспейс (не-ядро) Андроида собран и он прекрасно работает.

> он считает злом ORM, activeRecord, геттеры и сеттеры, try-catch и много чего еще.


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

Я всегда готов поучастовать в обсуждении и высказать свое мнение.
#785 #1108693
>>1108622

> О том, что геттеры/сеттеры это не ООП и нарушают принцип Tell Dont Ask


Какая предлагается альтернатива?

Вот он приводит пример плохого класса class User { private $passwordHash; } и видимо намекает, что модель должна быть "умной":

class User {
public function setPassword($password);
public function validate();
}

Но если у нас хешированием паролей занимается отдельный сервис, как его сюда внедрить? Если для валидации необходим доступ к БД? Доктрина не позволяет конструкторы с аргументами (можно решить фабрикой) и остается только вариант вроде

public function setPassword($hashService, $password);
public function validate($userRepository);

так? Не очень тянет на красивое АПИ если честно (в видео он по сути так и делает, используя анонимные функции, но здесь есть недостаток, что их иногда нужно несколько). Остается разве что отказаться от DI вообще. Ну и я высказывался по поводу умных моделей выше: >>1108431

По моему субъективному мнению, так мне нравится больше:

$authService->changePassword($user, $newPass);

Заметьте, в моем варианте легко реализуются уведомления о смене пароля, а также более сложные схемы, с высылкой письма со ссылкой, на которую надо кликнуть для смены, с 2F авторизацией. А что в варианте из видео? Вы утонете в коллбеках. Вообще, коллбеки там это как костыль - объект пользователя не умеет хешировать пароли, потому давайте с помощью коллбека дадим ему эту возможность.

Мне нравится подход, когда у нас есть сервисы, и они образуют внутреннее АПИ приложения. А "глупые" модели используются как аргументы для методов этого API. Да, тут получается меньше инкапсуляци, так как любой может читать/писать данные в модели. Предложите альтернативу. В некоторых языках это решается, например, в Си++, есть "friend classes", которые могут залезать в приватные поля другого класса.

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

> Я же постоянно в коде натыкаюсь на ситуции, когда исключения используют для валидации пользовательского ввода


Здесь легко привести пример, когда это не работает: когда тебе надо сообщить об ошибках в нескольких полях. С другой стороны, исключения представляют ошибку и хочется их использовать. Вообще, валидация интерсная вещь. Вот представьте, что вам для валидации передали объект пользователя, и в нем не указан IP-адрес, с которого произведена регистрация. Что с этим делать? вы же не можете в форме написать пользователю "не указан IP адрес", потому что там нет такого поля.

Я для себя придумал такой компромиссный вариант:

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

Чувствую, впрочем, что решение не идеальное.
#785 #1108693
>>1108622

> О том, что геттеры/сеттеры это не ООП и нарушают принцип Tell Dont Ask


Какая предлагается альтернатива?

Вот он приводит пример плохого класса class User { private $passwordHash; } и видимо намекает, что модель должна быть "умной":

class User {
public function setPassword($password);
public function validate();
}

Но если у нас хешированием паролей занимается отдельный сервис, как его сюда внедрить? Если для валидации необходим доступ к БД? Доктрина не позволяет конструкторы с аргументами (можно решить фабрикой) и остается только вариант вроде

public function setPassword($hashService, $password);
public function validate($userRepository);

так? Не очень тянет на красивое АПИ если честно (в видео он по сути так и делает, используя анонимные функции, но здесь есть недостаток, что их иногда нужно несколько). Остается разве что отказаться от DI вообще. Ну и я высказывался по поводу умных моделей выше: >>1108431

По моему субъективному мнению, так мне нравится больше:

$authService->changePassword($user, $newPass);

Заметьте, в моем варианте легко реализуются уведомления о смене пароля, а также более сложные схемы, с высылкой письма со ссылкой, на которую надо кликнуть для смены, с 2F авторизацией. А что в варианте из видео? Вы утонете в коллбеках. Вообще, коллбеки там это как костыль - объект пользователя не умеет хешировать пароли, потому давайте с помощью коллбека дадим ему эту возможность.

Мне нравится подход, когда у нас есть сервисы, и они образуют внутреннее АПИ приложения. А "глупые" модели используются как аргументы для методов этого API. Да, тут получается меньше инкапсуляци, так как любой может читать/писать данные в модели. Предложите альтернативу. В некоторых языках это решается, например, в Си++, есть "friend classes", которые могут залезать в приватные поля другого класса.

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

> Я же постоянно в коде натыкаюсь на ситуции, когда исключения используют для валидации пользовательского ввода


Здесь легко привести пример, когда это не работает: когда тебе надо сообщить об ошибках в нескольких полях. С другой стороны, исключения представляют ошибку и хочется их использовать. Вообще, валидация интерсная вещь. Вот представьте, что вам для валидации передали объект пользователя, и в нем не указан IP-адрес, с которого произведена регистрация. Что с этим делать? вы же не можете в форме написать пользователю "не указан IP адрес", потому что там нет такого поля.

Я для себя придумал такой компромиссный вариант:

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

Чувствую, впрочем, что решение не идеальное.
#786 #1108694
Для тех, кто хочет попрактиковаться в ООП-проектировании, или, наоборот, показать, как легко решается задача без ООП, повторно даю 2 задачки. В версии без ООП разрешается использовать объекты без методов (только в публиными полями) как структуры для хранения данных. Обратите внимание, что предметная область в этих задачах очень простая и на практике сущностей бывает больше, а связи между ними сложнее.

Задача про Гостиницу

Есть Гостиница, в ней есть Номера. Для каждого Номера известен его номер, количество Гостей, которое в него влезет, а также цена за сутки. В Гостиницу приезжают Гости. Нужно сделать объектную модель Гостиницы с такими возможностями (методами):

- получить список свободных номеров на определенную дату
- получить список свободных номеров, которые будут свободны в определенный диапазон дат (от A до B)
- дан список Гостей и диапазон дат, в которые они хотели бы заселиться. Необходимо подобрать им самый дешевый (а среди номеров с одинаковой ценой - самый маленький) Номер, который их вместит и который свободен в это время.
- то же самое, но при отстутствии одного подходящего номера для Гостей разрешается заселить их в несколько номеров, опять же, начиная с самых дешевых. Например, приехало 3 Гостя, но все 3-местные номера заняты и мы выделяем 2 2-местных, или 3 1-местных или 1-местный + 2-местный.
- зарегистрировать проживание данных Гостей в данных Номерах на данный период
- получить историю заселения Номера (кто в нем когда жил)
- получить историю заселения Гостя (в каких номерах он жил)
- получить статистику доходов Гостиницы за данный диапазон дат (в день A отдель заработал X тугриков, в день B - Y тугриков и так далее)

Задача про Продюсерское Агенство

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

Персоны - это люди, у которых есть какие-то творческие способности. У каждой Персоны есть такие свойства:

- имя
- контактный номер телефона

Кроме того, у них могут быть навыки: Персона может быть Актером, Моделью, Музыкантом, Менеджером.

У Актера в дополнение к обычным свойствам есть свойство: список Фильмов, в которых он снимался
У Музыканта есть свойства: список Групп, в которых он участвует, и список инструментов, на которых он умеет играть
У Модели есть свойства: рост, цвет глаз и цвет волос
У Менеджера (Агент или менеджер по работе с талантами) есть свойство: название Агенства, которое он представляет.

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

Нужно представить информацию о Персонах в виде объектной модели (набора классов), которая бы позволила наиболее удобно представить информацию о них. Соответственно "база Персон" - это просто массив таких объектов. Тебе нужно спроектировать эти классы. Методы тут писать не нужно, хватит только полей.
#786 #1108694
Для тех, кто хочет попрактиковаться в ООП-проектировании, или, наоборот, показать, как легко решается задача без ООП, повторно даю 2 задачки. В версии без ООП разрешается использовать объекты без методов (только в публиными полями) как структуры для хранения данных. Обратите внимание, что предметная область в этих задачах очень простая и на практике сущностей бывает больше, а связи между ними сложнее.

Задача про Гостиницу

Есть Гостиница, в ней есть Номера. Для каждого Номера известен его номер, количество Гостей, которое в него влезет, а также цена за сутки. В Гостиницу приезжают Гости. Нужно сделать объектную модель Гостиницы с такими возможностями (методами):

- получить список свободных номеров на определенную дату
- получить список свободных номеров, которые будут свободны в определенный диапазон дат (от A до B)
- дан список Гостей и диапазон дат, в которые они хотели бы заселиться. Необходимо подобрать им самый дешевый (а среди номеров с одинаковой ценой - самый маленький) Номер, который их вместит и который свободен в это время.
- то же самое, но при отстутствии одного подходящего номера для Гостей разрешается заселить их в несколько номеров, опять же, начиная с самых дешевых. Например, приехало 3 Гостя, но все 3-местные номера заняты и мы выделяем 2 2-местных, или 3 1-местных или 1-местный + 2-местный.
- зарегистрировать проживание данных Гостей в данных Номерах на данный период
- получить историю заселения Номера (кто в нем когда жил)
- получить историю заселения Гостя (в каких номерах он жил)
- получить статистику доходов Гостиницы за данный диапазон дат (в день A отдель заработал X тугриков, в день B - Y тугриков и так далее)

Задача про Продюсерское Агенство

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

Персоны - это люди, у которых есть какие-то творческие способности. У каждой Персоны есть такие свойства:

- имя
- контактный номер телефона

Кроме того, у них могут быть навыки: Персона может быть Актером, Моделью, Музыкантом, Менеджером.

У Актера в дополнение к обычным свойствам есть свойство: список Фильмов, в которых он снимался
У Музыканта есть свойства: список Групп, в которых он участвует, и список инструментов, на которых он умеет играть
У Модели есть свойства: рост, цвет глаз и цвет волос
У Менеджера (Агент или менеджер по работе с талантами) есть свойство: название Агенства, которое он представляет.

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

Нужно представить информацию о Персонах в виде объектной модели (набора классов), которая бы позволила наиболее удобно представить информацию о них. Соответственно "база Персон" - это просто массив таких объектов. Тебе нужно спроектировать эти классы. Методы тут писать не нужно, хватит только полей.
#787 #1108695
>>1108634

У тебя в коде уязвимость - SQL инъекция: https://github.com/codedokode/pasta/blob/master/security/sql-injection.md

Что касается твоего вопроса, дополнительные данные в форме можно передать через скрытый input, проще всего передать только id сущности, а текущее время можно получить и на сервере.
#788 #1108712
>>1108693
Начну с того, что сам я в промышленном коде конечно же использую геттеры/сеттеры, просто потому что у нас так делают все и у меня не те уровень компетенции и положение в команде, чтобы учить кого-то таким спорным вещам. Более того, я считаю что советовать другие подходы нужно только в том случае, если сам на них не одну собаку съел, иначе к моему мнению просто пропадёт доверие.

Ещё я хочу сказать, что в простых приложениях rich domain model не нужна и попросту не оправдывает себя, можно нагенерить код и сопровождать его будет не очень больно. Для более сложных случаев используются репозитории (по сути TDG). Можно делать прям поверх QueryBuilder'а Yii/Laravel, как-то так: https://ideone.com/aYG6ft
И в тех проектах, что я видел на Symfony делают ведь так же само - flush пихают в репозитории, что противоречит persistence ignorance и сводит на нет UnitOfWork доктрины. Однако такой подход решает задачи, только непонятно зачем там доктрина. Кстати, в 3-й доктрине хотят добавить что-то вроде TDG - можно будет сохранить определённую сущность в обход UnitOfWork, не используя flush (не могу нагуглить issue на гитхабе).

Теперь касательно примера с классом User. Нет, там не будет методов setPassword и validate, проверять данные нужно там, где для этого хватает информации (это может быть валидатор, а может быть и AuthService). Проверяются на валидность объекты-пустышки без логики:
- https://stovepipe.systems/post/avoiding-entities-in-forms
- https://stovepipe.systems/post/rethinking-form-development

Rich Domain Model - это не о том, как всё пихать в сущность, это о том, как в коде максимально правдиво отражать требования бизнеса. В сущность не должны добавляться уведомления о смене пароля, нам же нужно SRP соблюдать. Для таких целей есть Domain Events:
- http://enterprisecraftsmanship.com/2017/10/03/domain-events-simple-and-reliable-solution/
- http://udidahan.com/2008/02/29/how-to-create-fully-encapsulated-domain-models/

Мне кажется, что такой подход требует определённых соглашений для распределения файлов по модулям, нужен быстрый способ, позволяющий например найти "всех слушателей события UserRegistered". В системе на ивентах сложно разбираться, для этого думаю нужно не складывать все слушатели в одни папку, а делить систему на модули. Но я пока только изучаю всё это, нужно найти время и написать что-нибудь со сложной логикой (TestHub я не считаю сложным, его просто долго делать, там всё линейно).
#788 #1108712
>>1108693
Начну с того, что сам я в промышленном коде конечно же использую геттеры/сеттеры, просто потому что у нас так делают все и у меня не те уровень компетенции и положение в команде, чтобы учить кого-то таким спорным вещам. Более того, я считаю что советовать другие подходы нужно только в том случае, если сам на них не одну собаку съел, иначе к моему мнению просто пропадёт доверие.

Ещё я хочу сказать, что в простых приложениях rich domain model не нужна и попросту не оправдывает себя, можно нагенерить код и сопровождать его будет не очень больно. Для более сложных случаев используются репозитории (по сути TDG). Можно делать прям поверх QueryBuilder'а Yii/Laravel, как-то так: https://ideone.com/aYG6ft
И в тех проектах, что я видел на Symfony делают ведь так же само - flush пихают в репозитории, что противоречит persistence ignorance и сводит на нет UnitOfWork доктрины. Однако такой подход решает задачи, только непонятно зачем там доктрина. Кстати, в 3-й доктрине хотят добавить что-то вроде TDG - можно будет сохранить определённую сущность в обход UnitOfWork, не используя flush (не могу нагуглить issue на гитхабе).

Теперь касательно примера с классом User. Нет, там не будет методов setPassword и validate, проверять данные нужно там, где для этого хватает информации (это может быть валидатор, а может быть и AuthService). Проверяются на валидность объекты-пустышки без логики:
- https://stovepipe.systems/post/avoiding-entities-in-forms
- https://stovepipe.systems/post/rethinking-form-development

Rich Domain Model - это не о том, как всё пихать в сущность, это о том, как в коде максимально правдиво отражать требования бизнеса. В сущность не должны добавляться уведомления о смене пароля, нам же нужно SRP соблюдать. Для таких целей есть Domain Events:
- http://enterprisecraftsmanship.com/2017/10/03/domain-events-simple-and-reliable-solution/
- http://udidahan.com/2008/02/29/how-to-create-fully-encapsulated-domain-models/

Мне кажется, что такой подход требует определённых соглашений для распределения файлов по модулям, нужен быстрый способ, позволяющий например найти "всех слушателей события UserRegistered". В системе на ивентах сложно разбираться, для этого думаю нужно не складывать все слушатели в одни папку, а делить систему на модули. Но я пока только изучаю всё это, нужно найти время и написать что-нибудь со сложной логикой (TestHub я не считаю сложным, его просто долго делать, там всё линейно).
#789 #1108743
ОП, добавь пожалуйста в шапку треда ссылку на http://phpclub.tech/
Там сейчас треды 1-96 за исключением 14-22. С этими тредами проблема в том, что у них ID пересекаются с ID уже ранне добавленных постов из тредов до 14-го. Мне непонятно, как на старом 2ch.hk вообще такое было возможно.
#790 #1108756
>>1108712

Я противник событий в серверном коде, так как это добавляет неочевидность в порядок выполнения кода. В Симфони события можно определять в куче мест (services.yml, класс Бандла, где-то в бутстрапе) и хрен найдешь так просто, что происходит в том или ином случае. Лучше все же явно вызвать нужные методы.

Я допускаю использование событий для дополнительных проверок, условно, при сохранении пользователя по postPersist проверять, что какие-то служебные поля заполнены, или что файл аватарки существует.

Также могу принять события, если это какая-то CMS и без них не расширить ее функционал.
#791 #1108758
>>1108743

Ок.

Там был то ли вайп, то ли потеряли БД и соответственно последние сообщения были потеряны и номера вернулись на несколько дней назад. Если у тебя id с двача используются как primary key то видимо это не очень удачное решение. Можно сделать искуственные id или использовать пару (id треда, id поста).

Сейчас на главной картинки вверху не видны.
#792 #1108763
>>1108743

Насчет цепочек, там выше писали, что ОП посты мешают, может можно игнорировать ссылки из них? То есть из Оп поста дальше продолжение не идет, и даже сам Оп пост можно не включать.

И тут http://phpclub.tech/pr/chain/1098085/ явно смешались разные цепочки, это наверно из-за моих постов, где я отвечаю на несколько вопросов...
#793 #1108766
>>1108743

И названия картинок теряются...
#794 #1108774
>>1108758

> Если у тебя id с двача используются как primary key то видимо это не очень удачное решение.


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

> Сейчас на главной картинки вверху не видны.


Исправлено.

> явно смешались разные цепочки,


Там же весь граф включается (все достижимые узлы)

> что ОП посты мешают


Да, их наверное нужно исключать.

>>1108766
Уточни пожалуйста где конкретно.
#795 #1108777
>>1108774

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

По поводу картинок - у них стали названия в виде md5 хеша, а на этой борде они выводятся текстом, например, cat-cafe-osaka.jpg

И еще один совет хотел дать, не знаю, как у вас с этим, но советую автоматизировать все операции вроде деплоя или настройки сервера. Очень помогает, когда приходится менять сервера например. Многие используют ансибл, мне он не нравится, я использую bash скрипты. Ну например, у меня есть скрипт, который разворачивает и настраивает OpenVPN на любом ubuntu сервере за пару минут (с генерацией ключей, конфигов и прочего).
#796 #1108780
>>1108777
Понял. Для всех тредов, которые парсятся с 2ch-api присутствуют client provided file names: http://phpclub.tech/pr/res/1097438.html

Треды младше парсятся с архивача и там я просто не предусмотрел функции парсинга оригинальных имён, можно добавить. С парсингом было много проблем и не все решены, это всё нужно выписывать куда-то и исправлять постепенно.

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


Хорошо, нужно сделать.

> советую автоматизировать все операции вроде деплоя


Пока git pull, @foobar писал что поднимет Jenkins, чтобы был автопрогон тестов при пуше в мастер и деплой.
#797 #1108784
>>1108622
про ООП да, базара нет.
а вот

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



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

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

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

вопросы:
1. чем в данном случае плоха реализация через исключения? ты возможно скажешь, что она семантически плоха, мол видя исключения разработчик должен сразу предполагать исключительно критичные ситуации, но если дело только в этом, то это немного религиозный вопрос. или есть еще причины?
2. как бы в случае валидации сделал именно ты?
3. если ты знаком с другими ООП-языками, то как например такие вещи принято реализовывать в джаве? или они тоже неправильно понимают исключения?
#798 #1108789
>>1108693

>Здесь легко привести пример, когда это не работает: когда тебе надо сообщить об ошибках в нескольких полях.


да, это во всей ситуации с исключениями для валидации достаточно кривой момент. вот тут https://habrahabr.ru/post/279501/ есть способ решения, что думаешь о таком?
#799 #1108804
>>1108766
Добавил issue для сбора ошибок в парсере: https://github.com/someApprentice/phpClub/issues/30
#800 #1108817
>>1108780

Если у вас открытый код на гитхабе, можно бесплатно подключить для тестов (не деплоя) Travis CI. Вот у меня подключено: https://github.com/codedokode/task-checker/blob/master/.travis.yml

Он запускает phpunit, и вот как это выглядит: https://travis-ci.org/codedokode/task-checker/jobs/264686025

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

https://github.com/codedokode/task-checker/commits/master

Для тестов под Windows (если вдруг понадобится) есть appveyour. Им например можно делать сборку сишных проектов под винду и автоматически загружать экзешник в releases.

Имена файлов могут быть в архивах, сохраненных с двача, у меня есть и новые треды тоже, могу скинуть.
#801 #1108819
>>1108789

Проще просто сделать объект "коллекция ошибок". Хотя с ходу недостатки предлагаемого в статье решения не могу назвать.
#802 #1108821
Алсо, знаю, где можно взять минималистичный VPS на VMWare (то есть с поддержкой любых модулей ядра и iptables) за 1 евро в месяц по акции, нужно? Сканы документов (пока?) не нужны, Европа.

>>1108784

Ошибки валидации это не исключения (по моему мнению), так как они ожидаемы. Мы ожидаем, что пользователь может ввести что угодно и программа должна при этом работать корректно.

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

В статье на Хабре имхо проще было вернуть ошибку через return чем городить try/catch.

> чем в данном случае плоха реализация через исключения?


Тем, что это замаскированный return

> как бы в случае валидации сделал именно ты?


$errors = validate($data);

> если ты знаком с другими ООП-языками


Это не зависит от языка.
#803 #1108824
От студентов плакать хочется. Тот момент, когда понимаешь, что ничего не понимаешь, лол.
#804 #1108865
>>1108821

>Тем, что это замаскированный return


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

>$errors = validate($data);


можешь привести какие-то примеры из публичного кода? я просто сколько всего не смотрел, такого не видел.
#805 #1108907
Делаю студентов. Почему-то возникает проблема, что меня перенапрвляет на Location:/list.php" хотя я ничего еще не добавил в форму ( приватный режим браузера) и в БД добавляются пустые строчки. Где я ошибся?

....
function query($pdo){
//get name and other infromation about studen as variables

$FN = $_POST['FirstName'];
$LN = $_POST['LastName'];
$SOP = $_POST['points'];
$query =$pdo->query("INSERT INTO students VALUES('$FN','$LN')");

$names = [$FN,$LN,$SOP];

return $names;
}

foreach($_POST as $key=>$var){
if(!isset($var) ){
$error = true;
}
} if(!($error)){
//get the array containing info about a student
$name = query($pdo);

$string = implode($name);
setcookie("student",$string, time() +15);
$_POST = array();
header("Location:/list.php");

}
#805 #1108907
Делаю студентов. Почему-то возникает проблема, что меня перенапрвляет на Location:/list.php" хотя я ничего еще не добавил в форму ( приватный режим браузера) и в БД добавляются пустые строчки. Где я ошибся?

....
function query($pdo){
//get name and other infromation about studen as variables

$FN = $_POST['FirstName'];
$LN = $_POST['LastName'];
$SOP = $_POST['points'];
$query =$pdo->query("INSERT INTO students VALUES('$FN','$LN')");

$names = [$FN,$LN,$SOP];

return $names;
}

foreach($_POST as $key=>$var){
if(!isset($var) ){
$error = true;
}
} if(!($error)){
//get the array containing info about a student
$name = query($pdo);

$string = implode($name);
setcookie("student",$string, time() +15);
$_POST = array();
header("Location:/list.php");

}
#806 #1108917
>>1108907

У тебя там в коде SQL инъекция: https://github.com/codedokode/pasta/blob/master/security/sql-injection.md

По коду, попробуй вывести значения переменных с помощью var_dump (в том числе значение $_POST), а также натыкать echo, чтобы понять, выполняется ли цикл и if.
#807 #1108929
>>1108917
Спасибо. У меня в шаблонн есть скрытые формы для радио кнопок, так как $_POST не добавлял ключа с пустым значением для них, если не выбрать радио значение. Может быть из-за этого?
#808 #1109082
>>1108929

Ты же пишешь, что у тебя проблема появляется, даже если ты не отправил форму. Значит, что у тебя в форме, не имеет значения, а проблема где-то в коде. Потому я и предлагаю натыкать echo и var_dump, чтобы увидеть, что в переменных и в каком порядке выполняется код.
someApprentice #809 #1109155
>>1108763
У меня была такая идея игнорировать ОП-пост, но помимо них могут быть другие посты с несколькими ответами. Заставить кого-то отвечать разными постами было бы не справедливо.
#810 #1109234
Symfony4 уже кто-то смотрел? Пока я понял, что изменилась структура папок, концепция скелета проекта (там теперь нет нихуяшечки, ни аннтотаций, ни твига), сама концепция ушла очень далеко от general purpose framework. Они говорят мол а зачем вам твиг, если у вас например АПИ-приложение. По-моему супер круто.
#811 #1109236
>>1109234
Вообще икогда не понимал нахрена нужен твиг и это вот всё. Как по мне, какое-то пятое колесо.
#812 #1109261
>>1109236
зависит от масштаба проекта и количества сотрудников. шаблоны на твиге может править какой-нибудь верстальщик, который не знает, что происходит на уровне фреймворка и php вообще.

может кто-то назовет другие плюсы шаблонизаторов, потому что я принципиальных плюсов (кроме того, что на мой взгляд это изящное решение) больше не знаю.
#813 #1109262
>>1109236

Ответ написан на главной твига https://twig.symfony.com/

Алсо, урок про шаблонизаторы вообще: https://github.com/codedokode/pasta/blob/master/php/templates.md
#814 #1109343
сап пхпач, тут это js/питон макака чет не может разобраться, в документации есть кусок кода, но он на пхп, я попытался перенести его на пистон, но в силу своего хуевого знакомства с пыхом, чет не выходит возвращается 404 ошибка, хотя не должна по идее
вот код с примера документации к api
https://pastebin.com/pfvyy8pr
можете отправить post запрос на $url_for_post с параметрами $params
и показать что пришло в ответ?
#815 #1109346
>>1109343
просто у меня даж апача не стоит да и настолько хуево знаком с пыхом что минут 20 убил на то, чтоб добавить ключ 'sign' в $params а проверить я ли проебался с переноса примера с php на питон или у них документация к api протухла нужно.
вот как я это вижу на питоне
алсо схуяли у вас хэштейбл объявляется как array? наркоманы...
https://pastebin.com/jEv7C9xD
#816 #1109381
>>1109343

>а $url_for_post с параметрами $params


>и показать что пришло в ответ?



31 $curl=curl_init();
32 curl_setopt($curl,CURLOPT_RETURNTRANSFER, true);
34 curl_setopt($curl,CURLOPT_URL, $url_for_post);
35 curl_setopt($curl,CURLOPT_CUSTOMREQUEST, 'POST');
36 curl_setopt($curl,CURLOPT_POSTFIELDS, json_encode($params));
37 curl_setopt($curl,CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
38 curl_setopt($curl,CURLOPT_HEADER, false);
39 curl_setopt($curl,CURLOPT_SSL_VERIFYPEER, 0);
40 curl_setopt($curl,CURLOPT_SSL_VERIFYHOST, 0);
41 $out=curl_exec($curl);
42 $code=curl_getinfo($curl, CURLINFO_HTTP_CODE);
43
44 var_dump($out);
45 var_dump($code);
говнокод, понимаю, но тем не менее

$ php tmp.php
string(21) "<p>Page not found</p>"
int(404)

аналогично если не делать json_encode для $params, возвращается
$ php tmp.php
string(216) "<html><body><h1>500 Internal Server Error</h1>If you are the administrator of this website, then please read this web application's log file and/or the web server's log file to find out what went wrong.</body></html>"
int(500)

так что там какое-то наебалово, бро.
#816 #1109381
>>1109343

>а $url_for_post с параметрами $params


>и показать что пришло в ответ?



31 $curl=curl_init();
32 curl_setopt($curl,CURLOPT_RETURNTRANSFER, true);
34 curl_setopt($curl,CURLOPT_URL, $url_for_post);
35 curl_setopt($curl,CURLOPT_CUSTOMREQUEST, 'POST');
36 curl_setopt($curl,CURLOPT_POSTFIELDS, json_encode($params));
37 curl_setopt($curl,CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
38 curl_setopt($curl,CURLOPT_HEADER, false);
39 curl_setopt($curl,CURLOPT_SSL_VERIFYPEER, 0);
40 curl_setopt($curl,CURLOPT_SSL_VERIFYHOST, 0);
41 $out=curl_exec($curl);
42 $code=curl_getinfo($curl, CURLINFO_HTTP_CODE);
43
44 var_dump($out);
45 var_dump($code);
говнокод, понимаю, но тем не менее

$ php tmp.php
string(21) "<p>Page not found</p>"
int(404)

аналогично если не делать json_encode для $params, возвращается
$ php tmp.php
string(216) "<html><body><h1>500 Internal Server Error</h1>If you are the administrator of this website, then please read this web application's log file and/or the web server's log file to find out what went wrong.</body></html>"
int(500)

так что там какое-то наебалово, бро.
#817 #1109423
>>1109381
спасибо анончик, пойду до саппорта доебусь
#818 #1109487
ОП, что бы Dependency Injection работал. Нужно объекту, который связан к примеру еще с 3 объектами, передавать эти объекты при создании и что бы он сам их в конструкторе привязывал? Или можно написать что бы он сам создавал в конструкторе их? Но тогда как то неявно будет.
#819 #1109689
>>1109234
Смотрел, testhub делаю на нём. Вот появились уроки для самых маленьких
https://knpuniversity.com/screencast/symfony4-upgrade/sf34-deprecations?utm_content=buffer7e518&utm_medium=social&utm_source=twitter.com&utm_campaign=buffer

Щас читать буду, а то в некоторых моментах туплю
#820 #1109723
>>1109689
о, спасибо. жалко, еще не все дописаны, но сохранил в закладки.
#821 #1109756
Ох блять, выебать бы в срандель того, кто придумал преобразовывать типы в строки в json_decode. Только что час проебался не понимая, почему же у меня is_null($string) показывала false, когда я к серверу отправил жсон {"origin": null}
silex-ajax
229 Кб, 1236x768
аутенфикация Silex + AJAX #822 #1109833
Привет,
пытаюсь разобраться с аутенфикацией Silex + AJAX.

На сервере использую способ аутенф. "form_login" в настройках фаирвола. Из клиентского прилоежения отправляю AJAX запрос с данными _password и _username. Но сервер не аутенфицирует (после отправки формы сервер редиректит на страницу, которая указана в свойстве 'login_path').

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

В пикриле инфа о запросах AJAX и обычной формы, я вижу что в AJAX запросе нет отправки Cookie, очевидно это и есть причина?

Как метод аутенфикации использовать в настройках Silex? Пилить свой? Я думал, что должно быть так: есть адрес api, по которму на сервер можно отправить username/password и получить обратно токен. По остальным адресам api, сервер использует токен-аутенфикацию, и клиент отправляет все запросы с токеном, который он получил раннее. А как это делается в реальной жизни?

Код AJAX запроса:
https://github.com/enotocode/birthday_reminder/blob/23ec142c4dcaf8f881a1b3b4cc67fb5307478e17/src/client/services/apiCall.js#L72

Настройки аутенфикации сервера:
https://github.com/enotocode/birthday_reminder/blob/23ec142c4dcaf8f881a1b3b4cc67fb5307478e17/src/server/public/index.php#L54
#823 #1109845
>>1109833
с отправкой Cookie разобрался, добавив свойство credentials: include в метод fetch.

Но в целом, вопрос как выглядит схема аутенфикации для spa приложения с silex бэк-эндом, остается открытым.
#824 #1109853
>>1109487

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

Но если объект - это не зависимость, а какая-то сущность, используемая классом, то ее можно и создавать в конструкторе. Ну например, класс линии может создавать объект "стартовая точка" сам:

class PolyLine
{
private $points = [];

public function __construct($x, $y)
{
$this->points[] = new Point($x, $y);
}
}

Надеюсь, не запутал.

>>1109261

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

>>1109155

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

Может, строить цепочку только в одну сторону? Ну то есть:

- берем первый пост
- добавляем ответы на него
- для каждого ответа добавляем ответы на них (но не добавляем посты, на которые ссылаются эти посты)

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

>>1108824

Читай комментарии к задаче, пробуй делать хотя бы частично, спрашивай советов в треде.
#824 #1109853
>>1109487

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

Но если объект - это не зависимость, а какая-то сущность, используемая классом, то ее можно и создавать в конструкторе. Ну например, класс линии может создавать объект "стартовая точка" сам:

class PolyLine
{
private $points = [];

public function __construct($x, $y)
{
$this->points[] = new Point($x, $y);
}
}

Надеюсь, не запутал.

>>1109261

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

>>1109155

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

Может, строить цепочку только в одну сторону? Ну то есть:

- берем первый пост
- добавляем ответы на него
- для каждого ответа добавляем ответы на них (но не добавляем посты, на которые ссылаются эти посты)

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

>>1108824

Читай комментарии к задаче, пробуй делать хотя бы частично, спрашивай советов в треде.
#825 #1109854
>>1108865

Та строчка, которую я написал, $errors = validate($data); это первое, что приходит в голову и я даже не понимаю, зачем нужно искать какие-то примеры кода.

Пожалуйста, вот пример https://symfony.com/doc/current/validation.html

> $errors = $validator->validate($author);



>>1108712

> Для более сложных случаев используются репозитории (по сути TDG). Можно делать прям поверх QueryBuilder'а Yii/Laravel, как-то так: https://ideone.com/aYG6ft


В Симфони, как я помню, репозиторий не имеет доступа к контейнеру и ограничен только работой с БД.

> И в тех проектах, что я видел на Symfony делают ведь так же само


Ну тут я прокомментировать чьи-то чужие решения никак не могу.

Вообще, с flush не все так просто. Например, не сделав flush, ты не можешь получить id новой вставленной сущности, а он может быть где-то нужен.

> можно будет сохранить определённую сущность в обход UnitOfWork, не используя flush (не могу нагуглить issue на гитхабе).



Это можно было сделать и раньше, передав ее в flush(). Не знаю, правда, сохранит ли это связанные с ней сущности.

> Нет, там не будет методов setPassword


В видео такой метод есть.

> https://stovepipe.systems/post/avoiding-entities-in-forms


> Entities should always be in a valid state



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

А вот с формами, я не уверен, что есть смысл делать всегда валидные сущности и потом решать возникшие из-за этого проблемы. Вариант с DTO, конечно, работает, но усложняет код. Я бы его использовал только там, где форма сильно не похожа на сущность.

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

> Для таких целей есть Domain Events:


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

>>1108532

Видимо, это защита от парсинга.
#825 #1109854
>>1108865

Та строчка, которую я написал, $errors = validate($data); это первое, что приходит в голову и я даже не понимаю, зачем нужно искать какие-то примеры кода.

Пожалуйста, вот пример https://symfony.com/doc/current/validation.html

> $errors = $validator->validate($author);



>>1108712

> Для более сложных случаев используются репозитории (по сути TDG). Можно делать прям поверх QueryBuilder'а Yii/Laravel, как-то так: https://ideone.com/aYG6ft


В Симфони, как я помню, репозиторий не имеет доступа к контейнеру и ограничен только работой с БД.

> И в тех проектах, что я видел на Symfony делают ведь так же само


Ну тут я прокомментировать чьи-то чужие решения никак не могу.

Вообще, с flush не все так просто. Например, не сделав flush, ты не можешь получить id новой вставленной сущности, а он может быть где-то нужен.

> можно будет сохранить определённую сущность в обход UnitOfWork, не используя flush (не могу нагуглить issue на гитхабе).



Это можно было сделать и раньше, передав ее в flush(). Не знаю, правда, сохранит ли это связанные с ней сущности.

> Нет, там не будет методов setPassword


В видео такой метод есть.

> https://stovepipe.systems/post/avoiding-entities-in-forms


> Entities should always be in a valid state



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

А вот с формами, я не уверен, что есть смысл делать всегда валидные сущности и потом решать возникшие из-за этого проблемы. Вариант с DTO, конечно, работает, но усложняет код. Я бы его использовал только там, где форма сильно не похожа на сущность.

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

> Для таких целей есть Domain Events:


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

>>1108532

Видимо, это защита от парсинга.
https://github.com/TheSidSpears/testhub #826 #1109855
>>1106164

Нету README.

Нету тестов.

Зачем в каждой папке лежит пустой gitignore?

https://github.com/TheSidSpears/test_hub/blob/master/templates/base.html.twig#L21

> {% if app.request.attributes.get('_route') != 'main' %}


Вот это мне не нравится, почему view лезет куда-то в Request?

https://github.com/TheSidSpears/test_hub/blob/master/templates/_testlist.html.twig
Почему имя файла начинается с подчеркивания?

https://github.com/TheSidSpears/test_hub/blob/master/templates/_testlist.html.twig#L16

> "{{ path('tests', {'tag': tag.name}) }}"


Вот это мне не нравится. Разве не лучше было бы написать getTestsByTagUrl(tag)? Так мы собираем код генерации URL в одном месте, а не размазываем по шаблонам, получаем тайп-хинты, можем делать дополнительные проверки. Можем как-то централизованно влиять на генерацию URL.

> https://github.com/TheSidSpears/test_hub/blob/master/templates/tests/list.html.twig#L8


> 'attr': {


> 'value': searchValue


Что-то выглядит как костыль. Значение в форму в контроллере прописать нельзя?

https://github.com/TheSidSpears/test_hub/blob/master/templates/tests/list.html.twig#L29

> {{ tests.getTotalItemCount }} tests total



Нет выбора правильной формы слова в зависимости от числа.

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

https://github.com/TheSidSpears/test_hub/blob/master/config/packages/twig.yaml#L4
Почему strict_variables включены только в режиме debug? Это может быть субъективное мнение, но я считаю, что это неправильно и даже issue по этому поводу создал: https://github.com/twigphp/Twig/issues/2537

То же самое касается strict_requirements в роутере.

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

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

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

https://github.com/TheSidSpears/test_hub/blob/master/src/Controller/TestsController.php#L23

> // only handles data on POST


> $form->handleRequest($request);


Форма поиска должна работать через GET

https://github.com/TheSidSpears/test_hub/blob/master/src/Controller/TestsController.php#L29

> elseif (!$searchString = $request->query->get('tag')) {


Неудачная идея, по моему, делать присваивание внутри if.

https://github.com/TheSidSpears/test_hub/blob/master/src/Migrations/Version20171208191454.php#L18
Тут charset utf8 стоит, а не utf8mb4

https://github.com/TheSidSpears/test_hub/blob/master/src/Migrations/Version20171208231923.php#L19
Тут избыточные индексы у таблицы test_tag

https://github.com/TheSidSpears/test_hub/blob/master/src/Repository/TestRepository.php#L19
Для не меняющегося запроса, наверно короче будет написать его на DQL.
https://github.com/TheSidSpears/testhub #826 #1109855
>>1106164

Нету README.

Нету тестов.

Зачем в каждой папке лежит пустой gitignore?

https://github.com/TheSidSpears/test_hub/blob/master/templates/base.html.twig#L21

> {% if app.request.attributes.get('_route') != 'main' %}


Вот это мне не нравится, почему view лезет куда-то в Request?

https://github.com/TheSidSpears/test_hub/blob/master/templates/_testlist.html.twig
Почему имя файла начинается с подчеркивания?

https://github.com/TheSidSpears/test_hub/blob/master/templates/_testlist.html.twig#L16

> "{{ path('tests', {'tag': tag.name}) }}"


Вот это мне не нравится. Разве не лучше было бы написать getTestsByTagUrl(tag)? Так мы собираем код генерации URL в одном месте, а не размазываем по шаблонам, получаем тайп-хинты, можем делать дополнительные проверки. Можем как-то централизованно влиять на генерацию URL.

> https://github.com/TheSidSpears/test_hub/blob/master/templates/tests/list.html.twig#L8


> 'attr': {


> 'value': searchValue


Что-то выглядит как костыль. Значение в форму в контроллере прописать нельзя?

https://github.com/TheSidSpears/test_hub/blob/master/templates/tests/list.html.twig#L29

> {{ tests.getTotalItemCount }} tests total



Нет выбора правильной формы слова в зависимости от числа.

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

https://github.com/TheSidSpears/test_hub/blob/master/config/packages/twig.yaml#L4
Почему strict_variables включены только в режиме debug? Это может быть субъективное мнение, но я считаю, что это неправильно и даже issue по этому поводу создал: https://github.com/twigphp/Twig/issues/2537

То же самое касается strict_requirements в роутере.

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

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

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

https://github.com/TheSidSpears/test_hub/blob/master/src/Controller/TestsController.php#L23

> // only handles data on POST


> $form->handleRequest($request);


Форма поиска должна работать через GET

https://github.com/TheSidSpears/test_hub/blob/master/src/Controller/TestsController.php#L29

> elseif (!$searchString = $request->query->get('tag')) {


Неудачная идея, по моему, делать присваивание внутри if.

https://github.com/TheSidSpears/test_hub/blob/master/src/Migrations/Version20171208191454.php#L18
Тут charset utf8 стоит, а не utf8mb4

https://github.com/TheSidSpears/test_hub/blob/master/src/Migrations/Version20171208231923.php#L19
Тут избыточные индексы у таблицы test_tag

https://github.com/TheSidSpears/test_hub/blob/master/src/Repository/TestRepository.php#L19
Для не меняющегося запроса, наверно короче будет написать его на DQL.
#827 #1109856
>>1109833

С аякс-запросом куки отправляются точно так же, как и с обычным. Я вижу так же наличие заголовка Authorisation (HTTP авторизация) в обычной форме. Ты случайно не HTTP-авторизацию включил? Она скорее всего не будет работать при отправке аякс-запроса (ну или тебе надо как-то вручную там формировать заголовок Authorisation).

Если что, в мануале также есть совет:

> When a security configuration does not behave as expected, enable logging (with the Monolog extension for instance) as the Security Component logs a lot of interesting information about what it does and why.



> Как метод аутенфикации использовать в настройках Silex? Пилить свой? Я думал, что должно быть так: есть адрес api, по которму на сервер можно отправить username/password и получить обратно токен. По остальным адресам api, сервер использует токен-аутенфикацию, и клиент отправляет все запросы с токеном, который он получил раннее. А как это делается в реальной жизни?



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

Если речь о публичном API, то имхо, проще тут посылать данные авторизации с каждым запросом (следуя правилу stateless из REST).

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

То, что ты предложил, выглядит как усложнение, нам надо следить за этими токенами, продлевать их итд. При этом по сути это то же самое, что токен в куках.
#828 #1109857
Я кстати поймал себя на мысли, что phpclub ведь могли бы использовать и любители других языков, если им хочется иметь архив своих тредов с поиском. Да и вообще кто угодно.
#829 #1109866
Переходите в новый тред >>1109863 (OP) , тут будут только ответы на старые посты. Если вам не ответили - напомните о себе в новом треде. Не пишите тут.
#830 #1110212
>>1109854

> В Симфони, как я помню, репозиторий не имеет доступа к контейнеру и ограничен только работой с БД.



Вот список различных способов регистрировать репозитории: https://www.tomasvotruba.cz/blog/2017/10/16/how-to-use-repository-with-doctrine-as-service-in-symfony/

В SF4 влепили какой-то костыль и теперь можно использовать репозитории как сервисы: https://symfony.com/doc/current/doctrine.html#querying-for-objects-the-repository

> Это можно было сделать и раньше, передав ее в flush().


Это удалят в Doctrine 3 из-за багов: https://github.com/doctrine/doctrine2/issues/6118

Касательно всего остального - мне нужно написать нормальное приложение с таким подходом и тогда я отпишу о результатах.
Тред утонул или удален.
Это копия, сохраненная 21 декабря 2017 года.

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

Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
« /pr/В начало тредаВеб-версияНастройки
/a//b//mu//s//vg/Все доски