Вы видите копию треда, сохраненную 26 сентября 2018 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
Да, в нашем треде отвечают почти на все вопросы, только бампайте каждые 5 дней. И не разводите флуд, если вам скучно, сходите погуляйте, например. Может вас побьет какой-нибудь хороший человек и вы перестанете флудить в нашем треде.
Это тред для начинающих. Не написал за свою жизнь ни одной программы и имеешь тройку по математике? Ты наш человек.
Предыдущий тред был тут: >>1199390 (OP) . Остальные треды есть в архиве: https://phpclub.tech/ (там есть поиск, так что можно легко найти обсуждение какой-то задачи или ответы на свой старый пост) или ищутся в гугле по словам "клуб изучающих php" и в архиваче.
Мейлач лежит, модератор зверствует? Есть запасной тред на доброчане: /s/res/23225.xhtml#i46467
Форматируй свой код, если хочешь, чтобы его читали (как, написано во втором посте).
Правила: ведем себя воспитанно, помогаем новичкам, читаем учебники, решаем задачки, постим ссылки на решения, ОП их проверяет и дает советы и замечания. ОП заходит редко, где-то раз в 2-3 дня, у него мало времени, не жди его, решай задачки дальше. ОП отвечает на все вопросы по его задачкам и учебнику, а вот насчет каких-то других вещей - только если останется время. Но в треде немало анонимных экспертов разного уровня, так что вряд ли вопрос останется без ответа.
С чего начать
У нас есть свои уроки по основам PHP, они собраны и выложены по адресу http://codedokode.github.io/phpbook (вас отредиректит на другой домен, не читайте, не сохраняйте, не запоминайте его, он временный). Это учебник для изучающих с нуля, то есть если ты вообще ничего не знаешь, то можно начать с него. Он простой и понятный. Там есть задачи, их нужно решать (чтобы стать программистом, надо писать код — иначе никак). Пости ссылки на решения в тред, мы их проверим, напишем замечания и дадим советы по улучшению. С другой стороны, если этот учебник тебе не нравится, можно читать любой другой. Или официальный мануал. Или все сразу.
Устанавливать пока что ничего не требуется, разве что редактор кода вроде Sublime Text 3, Notepad++, Visual Studio Code, Netbeans PHP или PhpStorm (с ним будет удобнее).
Если не знаешь как решать, запости код, напиши в каком месте остановился и попроси подсказку.
Ты прошел весь учебник? Молодец, но это были лишь основы языка PHP, этого недостаточно. Вот что в идеале надо изучить еще: ООП, как работает веб-сервер, HTML/CSS, SQL, PDO, работа с таблицами в БД, работа с формами, MVC, git, composer, JS, фреймворки, автоматизированное тестирование.
Надо переходить к более серьезным задачкам, которые научат тебя всему этому.
- для начала прочти урок https://github.com/codedokode/pasta/blob/master/soft/web-server.md
- установи Апач + PHP (советы выше и ниже) и читай туториал http://php.net/manual/ru/tutorial.php
- Учи HTML/CSS и SQL, PDO, хотя бы основы
- Далее простая, но полезная задача сделать список студентов, в ней много полезных советов: https://github.com/codedokode/pasta/blob/master/student-list.md
- Более сложная задача сделать файлообменник на микрофреймворке Slim: https://gist.github.com/codedokode/9424217
- Еще более сложная и долгая задача на Yii/Symfony: https://gist.github.com/codedokode/8733007
- После нее можно изучать автоматизированное тестирование https://gist.github.com/codedokode/a455bde7d0748c0a351a
- Если ты все решил, переходи к Symfony 3/Doctrine 2
- Почитать про паттерны http://designpatternsphp.readthedocs.org/ru/latest/README.html (если ты не изучил ни одного фреймворка, то это будет рановато), тут с примерами кода http://designpatternsphp.readthedocs.org/ru/latest/README.html . Имей в виду что без примеров использования их учить бесполезно - не поймешь, хочешь увидеть примеры использования паттернов - ковыряй исходники Симфони, например Symfony Forms. Не заучивай паттерны - смотри код и думай, зачем тут они использованы.
Чтобы делать эти задания, тебе надо установить Апач + PHP (можно заодно сразу и MySQL) на компьютер. Вот полезные инструкции:
https://github.com/codedokode/pasta/blob/master/soft/php-install.md
https://github.com/codedokode/pasta/blob/master/soft/apache-install.md
Может тебе понадобится пользоваться командной строкой, вот гайд https://github.com/codedokode/pasta/blob/master/soft/cli.md
Решения задач лучше показать мне, особенно на ООП,так как сам ты вряд ли увидишь все ошибки. Пости свой код на гитхаб и вкидывай ссылку в тред по мере решения. Я прокомментирую и укажу на ошибки.
Параллельно стоит подучивать английский, на первых порах можно без него, но по мере развития придется все чаще сталкиваться с англоязычными статьями, так что лучше не откладывать. Читать можно news.ycombinator.com - это что-то вроде их хабра. Также можно начинать смотреть фильмы и видео на английском.
Также, у нас есть задачи которые позволят тебе изучить или подтянуть до нормального уровня знания JS/HTML/CSS/SQL. Решай их параллельно с задачами выше.
- HTML/CSS: https://github.com/codedokode/pasta/blob/master/html/html.md
- JS: https://gist.github.com/codedokode/ce30e7a036f18f416ae0
- SPA (сложно): https://github.com/codedokode/pasta/blob/master/js/spa.md
- Проверялка решений на JS: http://dkab.github.io/jasmine-tests/
- MySQL: https://github.com/codedokode/pasta/blob/master/db/databases.md
Что почитать
- Мануал по PHP — http://www.php.net/manual/ru/langref.php
- Сайт phptherightway (перевод на русский: http://getjump.me/ru-php-the-right-way/ )
- По PHP: Профессиональное программирование на PHP Джордж Шлосснейгл
- По PHP: Мэтт Зандстра — PHP: Объекты, шаблоны, методики программирования
- JS: learn.javascript.ru
- Про Git: https://git-scm.com/book/ru/v1
- Новости IT на англ. https://news.ycombinator.com/
- какой-то древний, устаревший, но большой и на русском справочник по веб-разработке, посоветованный аноном: https://starcat.dp.ua/doc/wdh/
Оформляй код аккуратно!!! — например пропусти через 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? — Да, однозначно. Посмотри любую вакансию.
---
Код нужно писать не как попало, а аккуратно и по правилам. Почему? Потому, что на неакуратно написанный код не хочется даже смотреть. Если каждый будет оформлять код как хочет, будет бардак.
Если тебе лень выравнивать код руками, закачай его на 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
А телега у вас есть? Мимо junior-middle php
Как к пхпшнику.
Спасибо за ответ ОП. Очень прошу тебя прочетсь пост целиком:
> В чем смысл такого кеша? Я не понимаю из описания, что кешируется и куда.
Имеется ввиду, пишутся на диск из php но читаются только файловым сервером.
> Это непрактично. Попробуй поработать с кешем на миллион файлов с большим количеством папок, и у тебя "траверсенье" может занять полчаса.
В планах была только одна папка с парой тысяч файлов примерно.
> Практичнее сделать неумирающее приложение и держать список файлов в памяти. Если надо, дампить его на диск и при запуске читать дамп. Также, это лучше писать не на PHP, а на Го, так как тут критична производительность.
Я никак не могу пихать его в рам потому что её мало. Файлы могут весить по 1-2 мегабайта, а память там общая на несколько сайтов. Сейчас в среднем свободно меньше гига и даже тот в "эвейлебл" а не фри. Плюс иногда память сильно нужна на всякие процессинги. Получается, под это дело нужно выделять пару гигов хотябы и всё-равно часть системы отвечающая за частоту запросов оставить, чтобы в памяти лежали самые популярные файлы.
> То, что у тебя, скорее всего будет работать плохо.
Вполне возможно.
> Альтернативный простой вариант - просто складывать файлы на диск и раз в сутки запускать штуку, которая обходит файлы, считает их объем и удаляет лишнее. Старайся использовать минимум подпапок, так как их обход при большом количестве будет знатно тормозить.
Это если сделать прямо так может быстро убить диск, чуть позже в посте объясню детали.
> Надо помнить, что дисковый трафик не бесконечный. Возможно, что хранить файлы в памяти выгоднее. Мне кажется, для нгикса что-то такое было.
Как выше объяснил рам не годится (хотя я не спец, может быть можно там всё как то ужимать но есть ли смысл). ИОПСы конечно не резиновые, но в том и фишка, ниже чуть чуть еще объясню свою позицию.
> В общем, у меня есть ощущение, что ты можешь написать что-то бесполезное. То есть в твоем воображении это крутой кеш, а на деле с ним может все будет работать медленее, чем без кеша. Чтобы этого не произошло, надо обязательно провести тесты, которые подтвердят, что с кешем все работает быстрее.
Нет, я не думаю что придумал какой то крутой кеш иначе бы сразу побежал его делать а не думал сперва. Пожалуйста прочти дальше.
> Также, у меня ощущение, что я слышал про что-то такое для нгинкса.
Я похожего на то что нужно не нашел, если ты вспомнишь как эта приблуда называется буду очень благодарен.
Теперь попробую дополнить факторами по которым я решил что так будет лучше и для чего вообще кеш нужен:
1. Кеш для картинок, не помню указывал ли это раньше. Грубо говоря, есть оригинал в 5к, кеш - для его версий в 4к, 2к, телефонном и так далее. Хочу отдельно отметить что это не относится к тамбнейлам, для них отдельная системка и весят они ничтожно мало и проблем нет.
2. Картинок очень много и потенциально есть вероятность запроса их в любом порядке и любом разрешении.
3. Мало рам, диск ограничен.
4. Почему вообще кажется что нужен кеш: ресайз картинок, особенно крупных - занятие небыстрое. Я почему-то думаю, что одно чтение файла с диска быстрее чем чтение более крупного файла с диска, его декодировка, ресайз, кодировка и отдача.
5. "аналитически" (аналитика не моя) считается что в основном будет спрос только на ряд файлов в определнных разрешениях. Что это значит: допустим, какое то изображение в определеном разрешении запросили один раз в месяц - нет смысла даже думать о его кешированнии. Но на главной (лендинг типа) странице есть как минимум несколько изображений которые показываются всем посетителям - очевидно что их есть смысл закешировать в размере в котором они для лендинга юзаются. Так-же есть такие разделы где часто показываются одни и те-же картинки, и ориентировочно большинство пользователей имеют fhd мониторы - следовательно, вероятность что они будут эти именно эти картинки просить в именно таком разрешении выше.
6. Таким образом это не традиционный кеш, а кеш по частоте обращений, т.е. кешировать в принципе нужно только то что чаще всего запрашивают пользователи.
7. Использование отдельного "реестра" для частоты обращений (внутри мемкешд например) как раз позволяет минимизировать бесполезные иопсы и писать только то что реально нужно.
8. Нужна возможность именно вручную контролировать кап на дисковое пространство кеша, чтобы случайно не забить диск и прочие радости.
Конечно в "индустрии" как я видел по множеству конференций и презентаций серьезные дядьки юзают для такого специальные прослойки в структуре с кешированием, распределением нагрузки и т.д.
Но тут проект на одного частника и нет вообще никаких гарантий что он будет иметь нагрузку требующую таких сложных архитектур. Поэтому и лишний раз платить за облачные решения или дополнительные серверные ресурсы он не горит желанием. Я так вообще думаю что этот сайт и одного уника в день не факт что даст.
Но и в то же время не хочется чтобы парочка любопытных листальщиков галерей завалила сайт по рам или диску.
Спасибо за ответ ОП. Очень прошу тебя прочетсь пост целиком:
> В чем смысл такого кеша? Я не понимаю из описания, что кешируется и куда.
Имеется ввиду, пишутся на диск из php но читаются только файловым сервером.
> Это непрактично. Попробуй поработать с кешем на миллион файлов с большим количеством папок, и у тебя "траверсенье" может занять полчаса.
В планах была только одна папка с парой тысяч файлов примерно.
> Практичнее сделать неумирающее приложение и держать список файлов в памяти. Если надо, дампить его на диск и при запуске читать дамп. Также, это лучше писать не на PHP, а на Го, так как тут критична производительность.
Я никак не могу пихать его в рам потому что её мало. Файлы могут весить по 1-2 мегабайта, а память там общая на несколько сайтов. Сейчас в среднем свободно меньше гига и даже тот в "эвейлебл" а не фри. Плюс иногда память сильно нужна на всякие процессинги. Получается, под это дело нужно выделять пару гигов хотябы и всё-равно часть системы отвечающая за частоту запросов оставить, чтобы в памяти лежали самые популярные файлы.
> То, что у тебя, скорее всего будет работать плохо.
Вполне возможно.
> Альтернативный простой вариант - просто складывать файлы на диск и раз в сутки запускать штуку, которая обходит файлы, считает их объем и удаляет лишнее. Старайся использовать минимум подпапок, так как их обход при большом количестве будет знатно тормозить.
Это если сделать прямо так может быстро убить диск, чуть позже в посте объясню детали.
> Надо помнить, что дисковый трафик не бесконечный. Возможно, что хранить файлы в памяти выгоднее. Мне кажется, для нгикса что-то такое было.
Как выше объяснил рам не годится (хотя я не спец, может быть можно там всё как то ужимать но есть ли смысл). ИОПСы конечно не резиновые, но в том и фишка, ниже чуть чуть еще объясню свою позицию.
> В общем, у меня есть ощущение, что ты можешь написать что-то бесполезное. То есть в твоем воображении это крутой кеш, а на деле с ним может все будет работать медленее, чем без кеша. Чтобы этого не произошло, надо обязательно провести тесты, которые подтвердят, что с кешем все работает быстрее.
Нет, я не думаю что придумал какой то крутой кеш иначе бы сразу побежал его делать а не думал сперва. Пожалуйста прочти дальше.
> Также, у меня ощущение, что я слышал про что-то такое для нгинкса.
Я похожего на то что нужно не нашел, если ты вспомнишь как эта приблуда называется буду очень благодарен.
Теперь попробую дополнить факторами по которым я решил что так будет лучше и для чего вообще кеш нужен:
1. Кеш для картинок, не помню указывал ли это раньше. Грубо говоря, есть оригинал в 5к, кеш - для его версий в 4к, 2к, телефонном и так далее. Хочу отдельно отметить что это не относится к тамбнейлам, для них отдельная системка и весят они ничтожно мало и проблем нет.
2. Картинок очень много и потенциально есть вероятность запроса их в любом порядке и любом разрешении.
3. Мало рам, диск ограничен.
4. Почему вообще кажется что нужен кеш: ресайз картинок, особенно крупных - занятие небыстрое. Я почему-то думаю, что одно чтение файла с диска быстрее чем чтение более крупного файла с диска, его декодировка, ресайз, кодировка и отдача.
5. "аналитически" (аналитика не моя) считается что в основном будет спрос только на ряд файлов в определнных разрешениях. Что это значит: допустим, какое то изображение в определеном разрешении запросили один раз в месяц - нет смысла даже думать о его кешированнии. Но на главной (лендинг типа) странице есть как минимум несколько изображений которые показываются всем посетителям - очевидно что их есть смысл закешировать в размере в котором они для лендинга юзаются. Так-же есть такие разделы где часто показываются одни и те-же картинки, и ориентировочно большинство пользователей имеют fhd мониторы - следовательно, вероятность что они будут эти именно эти картинки просить в именно таком разрешении выше.
6. Таким образом это не традиционный кеш, а кеш по частоте обращений, т.е. кешировать в принципе нужно только то что чаще всего запрашивают пользователи.
7. Использование отдельного "реестра" для частоты обращений (внутри мемкешд например) как раз позволяет минимизировать бесполезные иопсы и писать только то что реально нужно.
8. Нужна возможность именно вручную контролировать кап на дисковое пространство кеша, чтобы случайно не забить диск и прочие радости.
Конечно в "индустрии" как я видел по множеству конференций и презентаций серьезные дядьки юзают для такого специальные прослойки в структуре с кешированием, распределением нагрузки и т.д.
Но тут проект на одного частника и нет вообще никаких гарантий что он будет иметь нагрузку требующую таких сложных архитектур. Поэтому и лишний раз платить за облачные решения или дополнительные серверные ресурсы он не горит желанием. Я так вообще думаю что этот сайт и одного уника в день не факт что даст.
Но и в то же время не хочется чтобы парочка любопытных листальщиков галерей завалила сайт по рам или диску.
Запустил сервер регистрации в docker-контейнере.
Опасно так делать, за яйца не возьмут?
нет, сюда заходят смеяться пять минут
Ах ты змеюка подколодная.
Дело в том, что сайтики клепать меня не очень привлекает, хотя и полезная штука. Начинал с сайтоделия, сейчас пишу в основном разных ботов на похапе. Хочу ушуршать, на что-то более взрослое в этом плане.
Посматриваю уроки по этому вашему питону - с одной стороны прикольно, с другой стороны - какой-то он кастрат. Посматриваю в сторону руби и сейчас предлагают посмотреть в сторону го.
Что посоветует анон?
Как с помощью пхп приносить дяде больше бабла?
Из всего тобой перечисленного внимания заслуживает только питон.
Руби-хайп закончился, и с него давно все уже перекатываются, кто куда, а го - это вообще несерьёзно.
>го - это вообще несерьёзно
поясни. Я тож скептически отношусь ибо похож на хайповую неустоявшуюся хуиту, но почитал о нем немного и судя по описаниям прям сказка и прям все из коробки есть и фреймворки ненужны и либы и пр.
Checking Domain Name
Domain Name: cabinet.laravel.com
Top Level Domain: COM (Commercial TLD)
DNS Lookup
IP Address: 159.203.176.43
И как теперь быть? съебать из этой страны не предлагать
и по ней определишь какой язык стоит учить?
ну попробуй же курлом через прокси
Посоны, на рутракере PHPStorm без вирусов лежит или с вирусами, самые популярные раздачи? Стоит ли его пиратский вообще качать для ознакомления пока дома сижу без работы. И комп 2 гига 2 ядра вин7
А я этот номер постановления скоро наизусть выучу - он почти по всех блокировках из-за Телеграма, и как основание там используют постановление об обнаружении на этом IP запрещенного контента Тебе надо либо купить/настроить на иностранном сервере прокси или настроить VPN на сервере, либо арендовать сервер в стране, где меньше проблем со связностью Интернета. Последнее наверно даже выйдет дешевле и не потребует возни с настройками.
Прокси в линуксе обычно задается переменной окружения HTTP_PROXY.
сам phpstorm можно просто оффициально триальный с сайта скачать, и потом активировать уже
А вообще там вроде недавно бесплатную комьюнити версию завезли, если я ничего не путаю
>Прокси в линуксе обычно задается переменной окружения HTTP_PROXY.
насколько помню socks прокси так не задать
Я тут организовал сборник ссылок и полезных материалов по PHP и не только, возможно кому-то будет полезно или сможете что-то посоветовать или дополнить.
https://github.com/NotBadCode/TheKnowledgeBase
>На что съебаться с PHP?
Зачем?
>Хочу ушуршать, на что-то более взрослое в этом плане.
В плане чего?
Для веба за первое место сейчас дерутся PHP и JS.
Остальное сильно позади.
Ну ещё очень модно использовать GO.
Веб это не только 'сайтики' и боты, но ещё и целый пласт разные веб-приложений, сервисов автоматизации, всяких СРМ, ERP, B2B и т.д.
Если ты хочешь уйти из веба, то можешь смотреть в сторону мобилок и соответственно их технологий/языков, тоже модно-молодёжно.
>сервисов автоматизации
WinCC и прочие.
, всяких СРМ, ERP, B2B и т.д.
Решено в рамках уже существующих ERP, одножоп в случае СНГ и САП в случае остального мира.
>
>то можешь смотреть в сторону мобилок и соответственно их технологий/языков, тоже модно-молодёжно.
А вот там как раз веб через кордову сейчас актуален. Потому что на жабе боль, на qt можно делать тяжелый быстрософт, но его еще большая боль писать, а серьезными задачами, где требуется быстродействие плюсов один хер на мобилах работать не удобно и софт не популярен. Там веб самое то. Кроме игорь, но их пишут на готовых движках.
> Коданы, скажите, годная книга? Сейчас на пару дней без пеки и инторнетов останусь, стоит ли почитать?
Ну, если у тебя есть машина времени, у тебя горит сентябрь, яга недопита и ты хочешь вернуть себе 2007 - то вперед.
Как сейчас вспоминаю, этот html4, ебля с браузерами и их несовместимостью, робкие попытки внедрить jQuery, смешивание пыха и html в нечитаемую write-only лапшу на стопицот файлов, SQL инъекции, XSS-инъекуции, magicquotesgpc который не помогает и самопальный парсер.
>у тебя горит сентябрь, яга недопита и ты хочешь вернуть себе 2007 - то вперед.
Было бы неплохо, конечно. А по сабжу устаревшая книга? Что, тогда, из нового почитать? Я только начинаю учить, если что. Для новичков что-то вменяемое есть?
>Решено в рамках уже существующих
Конечно, всё уже изобрели и придумали, но почему то спрос на индивидуальные решения всё равно высок
>>34010
>веб через кордову сейчас актуален
Последний раз, когда я брался за кордову, это было очень сырое решение для энтузиастов, не думаю что сейчас что-то изменилось и оно реально конкурентно.
>на qt можно делать тяжелый быстрософт
>быстродействие плюсов один хер на мобилах работать не удобно и софт не популярен
Мне кажется, у тебя какая-то жуткая каша в голове и ты сам не совсем понимаешь о чем говоришь.
Тебе стоит более подробно изучить рынок и технологии, а потому уже говорить о востребованности и происходящим.
Прежде чем к фреймворку приступать, надо хотя бы на уровне джуна PHP знать, разве нет?
>Тебе стоит более подробно изучить рынок и технологии, а потому уже говорить о востребованности и происходящим.
А что там изучать? 80% - жаба, 20% - плюсы + QT (как правило тот самый непопулярный ёба-софт в котором можно чотополезноесложноеделать или портировано с десктопа переверсткой). Геймдев 90% сисярп на юньке, остальные 10 - ноунейм двадэ движки.
А что ты на пыхе будеш без фреймворка в 2018 году писать? Консольные хеллоуворлды и "прочитать файл" в репле?
На практике ничего. Но без знания синего зелёного слоника, я смогу только установить фреймворк по гайдам зайти и охуеть. Я только-только функции начал учить, до ООП ещё как до луны на тракторе.
@coshauni
>>34249
Обновленная ссылка на неофициальный чат треда, милости прошу к нашему шалашу!
https://t-do.ru/joinchat/Eh8Gzg94NT7LDHFpw4iZ7g
>Если ты хочешь уйти из веба
ноуп
Я люблю сервер и хочу подальше отдалиться от клиентского говна с верстками и пр. цмс. Последней каплей был битрикс.
Хочу язык, чтобы если меня брали на работу, то не воспринимали как человека, который им сейчас будет верстку натягивать, верстать или клепать магазины. Хотя к пхп, как языку, претензий особых нет.
При этом хотелось бы, чтобы возможность написать сайт тоже была. Я так понял - питон идеальный вариант
го как кор язык не кому нужен не будет , алсо большие проекты на го будут не поддерживаемые ввиду его не полного ООП , как доп язык норм , по серьёзнее кровавый терпрайз C# Java тд
раннюю не стабильные версии раздавали , но тоже с триалом
К говноедству высокая терпимость. К какой платформе присмотреться, чтоб побольше денег и ближайшие 5-6 лет не остаться без работы? Magento/woo/laravel/symfony/codeigniter/zf2? Кто может пояснить?
Рынок не СНГ есличо
Задача: https://pastebin.com/jwPp3di5
Есть форма которая пишет введенное значение в файл. Но!, при нажатии кнопки обновить в браузере запрос повторяется и значение знаешь? опять пишутся в файл. Нужно ей запретить.
Пикрилейтед 2 - кнопка обновить
Пикрилейтед 3 - 5 нажатий
Я хочу собрать варианты решения и чем больше, тем лучше. И примеры. Гуру, не поленитесь написать решение иначе это придется делать мне.
Я решаю это так: https://pastebin.com/8ERUtNbx
Добавляю заголовок:
header("Location:$_SERVER[PHP_SELF]");
Но есть и минусы. Если файл что-то выводит до этой строки - будет ошибка:
Warning: Cannot modify header information - headers already sent by (output started at C:\Web\Apache2.2\htdocs\3.php:2) in C:\Web\Apache2.2\htdocs\3.php on line 18
Для того чтобы не контролировать весь вывод до заголовка, нужно в PHP.ini включить буфер
output_buffering = On
И использовать функции буфера ob_start(); и ob_end_flush();
Результат: https://pastebin.com/x9Np8tPb
Минус тоже в том что не во всех серверах буфер будет включен.
Так а что за задача? Тебе нужно с каждого нового запроса новый фал создавать или дописывать в один?
Задача НЕ дописывать в файл (файл тут для удобства, тоже самое происходить при добавлении в БД) пр обновлении страницы.
Мне показали пример ссессий и метки но я нихуйя пока не могу понять. Когда и как ставить.
Вот сделали в похапе удобные классы для работы с датой, ай как хорошо.
Сколько будет 31 января плюс 1 месяц? ТРЕТЬЕ МАРТА, СУКА, ТРЕТЬЕ МАРТА, ААААААААААААААААААААААААААААААААААААААААААААААААА
Это говно просто увеличивает месяц на единицу, и если дней че-т многовато, увеличивает месяц еще на единицу и щедро ссыпает остаток туда. Сука!
Ладно, возьмем класс DatePeriod.
Запустим его с интервалом в месяц от 31 января. Сколько будет 31 января плюс 2 месяца. Че, 31 марта? ХУЙ ТАМ, ТРЕТЬЕ АПРЕЛЯ АААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААА
ИДИТЕ НАХУЙ
СУКА
БЛЯДЬ
>эти исповеди говноеда
Этот дурачок начинает что-то подозревать, какая прелесть.
>>32710 (OP)
Ты гнида, кстати.
>ОП
Гнида, активно распространяющая омерзительное говно среди безмозглого быдла.
Впрочем, не говорю это как что-то плохое.
>дегенераты уровня /зк высирающие этот ваш пыхыпы обосрались с датами как школьники
>Неосиляторы
О да, конечно.
Молодец, опустил тут всех гринтекстом и картиночками, можешь уебывать в свою ламповую фронт помойку, серьёзно, уходи
магазинчики пилят в основном на Magento
остальной булшит на WP Drupal(ибо он нынче CMF)
laravel - хайповая штука по типа RoR есть какой то процент его на рынке но не велик
symfony - хороший интерпрайз фрейм с кучей слоёв абстракций (его бы и брал под большие проекты) довольно большой процент рынка как у нас так и гейропке
yii2 - как по мне очень не плох для средней руки проектов так как у них есть божественный gii потому таблицы с фильтрами и тд очень быстро накидываются в отличии от SF LR
>$dt = new DateTime("2018-01-31");
>$dt->add(new DateInterval("P1M")); // 2016-03-02
Ясно.
>эти говнокостыли из говна в этом говнотреде
Понятно.
костыль не мой , как бы написан ниже на оф сайте пхп
http://php.net/manual/ru/datetime.add.php#118342
Чтобы форма не отправлялась 2 раза, надо использовать паттерн Post/Redirect/Get. Почитай мой урок про обработку форм https://github.com/codedokode/pasta/blob/master/forms.md
> Но есть и минусы. Если файл что-то выводит до этой строки - будет ошибка:
Надо в начало файла поместить всю логику, а весь вывод делать в конце. Если ты сначала выводишь шапку, а только потом обрабатываешь форму, то ты делаешь большую глупость.
Также, надо сохранять файл в utf-8 без BOM (byte order mark).
Не надо искать сложные решения там, где есть простые.
Да, действительно. С другой стороны, если бы 31 января + 1 месяц давало 28 февраля, возникли бы другие проблемы: а сколько например должно давать 30 января + 1 месяц?
Но я дам тебе хинт, как решить проблему: возьми 1-е число месяца, прибавь нужное число месяцев и отними 1 день.
$start->add(...P1M)->sub(...P1D);
>а сколько например должно давать 30 января + 1 месяц?
28 или 29 февраля, олигофрен.
>этот давно запощенный говнокостыль
Оно еще и с замедленным развитием.
http://jsfiddle.net/rLjQx/96508
Вот как жээсеры решили, смотрится логично, даже с учётом високосного года.
https://github.com/moment/moment/issues/854
И к этому пришли намеренно.
"логично" это субъективное мнение. И это сторонняя библиотека со специальной функцией прибавления месяца, а не встроенный JS объект Date. Я думаю, в PHP можно при желании тоже найти такую стороннюю библиотеку (или написать, если вдруг ее нет).
>"логично" это субъективное мнение.
То есть вот это правильно:
>$dt = new DateTime("2018-01-31");
>$dt->add(new DateInterval("P1M")); // 2016-03-02
Фиксирую.
>>36038
Это тред для изучения PHP и webdev. Любители похоливарить и люди, которым скучно и хочется пофлудить, могут пройти в любой другой тред.
Если вам не нравится PHP, просто не используйте его и проходите мимо. Алсо, https://habr.com/post/315152/
На коленях умоляй, олигофрен по кличке ОП.
Спс, буду иметь в виду.
>Чтобы форма не отправлялась 2 раза, надо использовать паттерн Post/Redirect/Get.
Где про это можно прочитать/посмотреть реализацию?
ОП, прошу твое внимания, так как всем похуй.
Я сам реализовал. Логика такова:
1. Создаем переменную метку и генерируем её случайное значение. Вставляем эту метку в форму чтобы отправить её методом POST.
2. Есть условие добавления информации в файл (в БД/не важно). К этому условию добавляем то, что переменная $_SESSION['token'] != $_POST['tonek']. В конце добавления данных в файл/БД/куда угодно устанавливаем $_SESSION['token'] = $_POST['tonek']. И все работает.
Логика такова:
Случайное число (например 666), передается формой ($_POST['token'] = 666), сравнивается с $_SESSION['token'] (коротая, пустая "" != 666) и условие выполняется. Присваиваем $_SESSION['token'] = $_POST['tonek'] (Это 666 = 666). Но когда мы нажимаем обновить (F5) $_POST['token'] не генерирует новое число, а отправляет старое. А его значение уже присвоено $_SESSION['token']. Теперь условие не выполняется. А выполнится оно только при новом отправлении формы.
https://pastebin.com/GjEUKt4y
Но мне типа успешные люди сказали что код хуевый. 2. Так ли это?
>Надо в начало файла поместить всю логику, а весь вывод делать в конце. Если ты сначала выводишь шапку, а только потом обрабатываешь форму, то ты делаешь большую глупость.
3. Можешь исправить мой код так как ты его видишь?
> Где про это можно прочитать/посмотреть реализацию?
Это описано в уроке на который я давал ссылку: https://github.com/codedokode/pasta/blob/master/forms.md
> Если все данные введены правильно, то мы после их обработки делаем редирект на какую-то другую страницу, например на страницу просмотра введенной информации, страницу благодарности, и т.д. Редирект необходим, чтобы при обновлении страницы форма не отправлялась повторно (если ты не знаешь, что такое редирект, то это выдача заголовка вроде Location: /thankyou.php. В php для этого используется функция header()).
> Этот подход (редирект после успешной обработки формы) называется Post/Redirect/Get.
У тебя какое-то переусложненное решение с сессиями.
Советую прочитать урок внимательно.
> 3. Можешь исправить мой код так как ты его видишь?
Ты можешь сделать это и сам. Что сложного в том, чтобы убрать весь вывод из начала скрипта и перенести в конец?
Должно быть так:
<?php
проверка данных формы;
определение значений переменных
?>
HTML код с подстановкой переменных
> Где про это можно прочитать/посмотреть реализацию?
Это описано в уроке на который я давал ссылку: https://github.com/codedokode/pasta/blob/master/forms.md
> Если все данные введены правильно, то мы после их обработки делаем редирект на какую-то другую страницу, например на страницу просмотра введенной информации, страницу благодарности, и т.д. Редирект необходим, чтобы при обновлении страницы форма не отправлялась повторно (если ты не знаешь, что такое редирект, то это выдача заголовка вроде Location: /thankyou.php. В php для этого используется функция header()).
> Этот подход (редирект после успешной обработки формы) называется Post/Redirect/Get.
У тебя какое-то переусложненное решение с сессиями.
Советую прочитать урок внимательно.
> 3. Можешь исправить мой код так как ты его видишь?
Ты можешь сделать это и сам. Что сложного в том, чтобы убрать весь вывод из начала скрипта и перенести в конец?
Должно быть так:
<?php
проверка данных формы;
определение значений переменных
?>
HTML код с подстановкой переменных
Благодарю. Прости я не читал твоих уроков. По книге как-бы ебашу.
Пасиба за ссыль!
только начал писать на пхп, иде phpStorm, когда клацаю на значок гугола кидает на сайт, на котором написано 502 bad gateway.
как проверять работоспособность программы?
держу в курсе: разобрался и пофиксил, не тратьте время зря, если хотели.
хочу изучать php по книжкам, но до сих многие вроде как годные книжки даже на английском под пятую версию. насколько большая разница между 5 и 7 с точки зрения синтаксиса? какие-нибудь базовые вещи одинаковы? потому что в питоне между 2 и 3 разница прямо в базовых структурах есть разница.
А нахуй нужны и интерфейсы и абстрактные классы, если есть просто классы?
Это вопрос из серии, зачем нужен молоток, если есть ножовка. Это разные инструменты для разных целей.
Сделал выборку по тегам. как получить содержимое конкретного элемента? Могу получить содержимое с помощью foreach($tmp as $v).
pq($v)->text() (так работает).
А так
pq($tmp[1])->text() нихрена не выводит
че за херня?
Есть страница с формой. https://ideone.com/BA8klI
Есть скрипт отправки: https://ideone.com/XV6tAU
Есть PHP для обработки отправленных данных будет много допиливаться, это пока тест просто: https://ideone.com/EMpowl
Теперь проблема. Картинки-то загружаются. Но в ответ, вместо вывода php echo 'success' или echo 'error' мне приходит ВСЯ страница от хэдера до футера, весь html-код. В итоге, у меня в диве .divResults появляется копия вёрстки. Как мне выводить то, что получается на выходе PHP-скрипта? Уже кучу всего прогуглил, всё равно никак не могу въехать. Выручайте, аноны.
Допустим, в туторе ОПа есть бросок кубиков, и я хочу сделать так, чтобы кубики бросались только после нажатия кнопки.
Конечно. Пили форму, по которой будет отправляться какое-нибудь значение. Если кнопка нажата, значение существует, выполняем скрипт.
Вот так это выглядит визуально. Если написать вместо ($('#divResults').html(data)); alert(data), то весь код страницы выдаёт в алерте. Не понимаю, как мой php скрипт может выдавать весь код. Если что, я совсем ньюфаг, только учусь, так что, не бейте за очевидные вопросы, тупые ошибки и быдлокод.
подскажите, пожалуйста.
в общем, в форму можно ввести сумму денег, но как сделать так, чтобы эта сумма вычиталась из нынешнего баланса, а затем умножалась или удалялась навсегда в случае победы/поражения?
1) name и id у инпутов должны быть разными.
2) Ты отправляешь две формы одним методом. Либо заключай всё в одну форму, либо записывай деньги в переменную. Лучше в одну форму вида:
Ваша ставка: input class='bet' и т.д.
<button type='submit' name='roll'>Бросить кубики</button>
3) в if у тебя странная конструкция. Проще if (isset($_POST['roll']) {
//код
}
4) Для вычета-прибавления денег используй switch case http://php.net/manual/ru/control-structures.switch.php
Да, забыл дописать в <button> нужен value="". Неважно что будет в значении, потому что если ты будешь использовать isset, как в моём примере, то тебе важен только сам факт наличия этой переменной.
огромное спасибо, анон! сейчас буду разбираться, просто это мой второй день знакомства с пхп, нихуя не знаю...
Только я не на фреймворке планирую это делать, если что.
Как с тобой связаться можно? Лучше фэйкомыльце.
Похоже, что нужна какая-нибудь конфочка для кооперации.
Это такая ерунда, по сравнению с разработкой движка.
Бро, как-то не очень сходится
Вакансий на ларавель и проектов на апворке в разы больше, чем на симфони, и уж тем более yii
У laravel тоже есть команд лайн тул, который умеет все то же, что и gli, и даже больше
Про магенто тоже мимо, вторая версия судя по форумам магенто это фейл, на первой делать уже не так хотят, в итоге магента сдаёт позиции
В целом твой ответ актуален для 2015 года примерно, тогда так и было, ларавель без работы, yii/symfony/magento в тренде
я больше сужу про офлайн работу , ссылки на его gii от лары можно ? последний раз чекал было всё было не очень , проверю.
Я блеать понятия не имею что писать в этот долбаный htaccess :(
Посмотри логи на сервере, няша. 500 ошибка это что угодно может быть. И какая у тебя БД? MySQL? Ее нельзя просто так перекинуть, надо импорты-экспорты творить.
Создание веб-приложения для регистрации и авторизации на php, html, css, js/jquery.
Форма регистрации:
1) Поля:
- login (unique)
- password
- confirm_password
- email (unique)
- name
2) Функционал:
После заполнения формы, уходит запрос на создание пользователя, поля проверяются на валидность (не пустые), уникальные поля проверяются на уникальность в БД, password и confirm_password сравниваются (должны быть одинаковыми). Если что-то не так - выдается ошибка.
В случае ошибки, возвращаем текст с ошибками.
В случае успеха шифруем пароль ("соль"+md5 или "соль"+sha1) и заносим данные в нашу базу.
Форма авторизации:
1) Поля:
- login
- password
2) Функционал:
После заполнения формы уходит запрос:
- проверяется наличие пользователя в бд;
- сверяется пароль.
В случае ошибки, возвращаем текст с ошибками.
В случае успеха происходит процесс авторизации (создание необходимых связей cookies + session + db). Обратите внимание, что в db тоже должна быть связь с сессией и cookies.
В случае авторизации мы должны видеть сообщение 'Hello [имя пользователя]', формы в таком случае не отображаем.
Внешний вид значения не имеет.
Основные требования:
- Вместо базы данных используем файл XML.
- Пароль не должен хранится в открытом виде.
- Связь авторизации - cookies + session + db (xml).
- Формы должны отрправляться используя технологию ajax, ответ в формате json.
- Если js отключён, то форма отправиться не может.
- Все поля форм - обязательные.
- Все формы реализуются через <form>.
- Результаты залить на github/bitbucket. Сделать репозиторий публичным. Ссылку прислать по почте.
Дополнительные требования
- защита от инъекций при получении параметров через get- или post;
- осмысленное название полей в бд;
- разумное оформление кода – имена переменных, функций, отступы, комментарии;
- код должен быть - прост в поддержке;
- отсутствие дублирование кода. копипаст – признак низкой культуры разработки;
- разделение логики работы и представления – некрасиво писать html и php вперемешку;
- css/js в отдельных файлах;
- осмысленное использование css.
Создание веб-приложения для регистрации и авторизации на php, html, css, js/jquery.
Форма регистрации:
1) Поля:
- login (unique)
- password
- confirm_password
- email (unique)
- name
2) Функционал:
После заполнения формы, уходит запрос на создание пользователя, поля проверяются на валидность (не пустые), уникальные поля проверяются на уникальность в БД, password и confirm_password сравниваются (должны быть одинаковыми). Если что-то не так - выдается ошибка.
В случае ошибки, возвращаем текст с ошибками.
В случае успеха шифруем пароль ("соль"+md5 или "соль"+sha1) и заносим данные в нашу базу.
Форма авторизации:
1) Поля:
- login
- password
2) Функционал:
После заполнения формы уходит запрос:
- проверяется наличие пользователя в бд;
- сверяется пароль.
В случае ошибки, возвращаем текст с ошибками.
В случае успеха происходит процесс авторизации (создание необходимых связей cookies + session + db). Обратите внимание, что в db тоже должна быть связь с сессией и cookies.
В случае авторизации мы должны видеть сообщение 'Hello [имя пользователя]', формы в таком случае не отображаем.
Внешний вид значения не имеет.
Основные требования:
- Вместо базы данных используем файл XML.
- Пароль не должен хранится в открытом виде.
- Связь авторизации - cookies + session + db (xml).
- Формы должны отрправляться используя технологию ajax, ответ в формате json.
- Если js отключён, то форма отправиться не может.
- Все поля форм - обязательные.
- Все формы реализуются через <form>.
- Результаты залить на github/bitbucket. Сделать репозиторий публичным. Ссылку прислать по почте.
Дополнительные требования
- защита от инъекций при получении параметров через get- или post;
- осмысленное название полей в бд;
- разумное оформление кода – имена переменных, функций, отступы, комментарии;
- код должен быть - прост в поддержке;
- отсутствие дублирование кода. копипаст – признак низкой культуры разработки;
- разделение логики работы и представления – некрасиво писать html и php вперемешку;
- css/js в отдельных файлах;
- осмысленное использование css.
сорри мой промах , не угараю по АСАШАЙ потому ищу работу больше в европке , 4 года перекатился в пшекарню и с этого делаю выводы.
Джун должен знать хотя бы один фреймворк и уметь создать самостоятельно приложение простое (уровня магазина или форума), а ты детские задачи даешь.
Бро, я сам в Польше уже 4 года, но работаю с США, в Европе денег нет, и айти отсталое
Реально прочекал - локальные польские вакансии - это реально срез США уровня 2015-2016 года
Я импортировал все как надо, sql еще сначала ругался что логин-пароль для доступа к бд неверные, не поменял я их в dbconfig, а как поменял - 500.
В журнале только вот это: [29/Jul/2018:16:31:35 +0300] 0.113 0.113 500 95...74 f.xsph.ru GET / HTTP/1.1 "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36" "-" 314 141.8.195.34 f
Говно, ты?
согласен , няш, не кинь плиз на лара gii , хочу опробовать , вполне возможно дальше буду двигаться в сторону лары
Называется artisan
Можно писать свои команды, но есть встроенные, вот чит шит https://gist.github.com/42antoine/8822851
Ты смотришь access.log, журнал обращений к сайту. Нужно смотреть лог ошибок. Он часто называется error.log, php-errors.log, php-fom.log и тд. На линуксе они обычно в /var/log, но на хостинге могут быть свои особенности, другая папка или просмотр через админку. выясни, где на хостинге логи ошибок.
Не хочу рекламировать свои же уроки, но если взять задачу про студентов из шапки, то там есть подробные комментарии, и многие из них подойдут и к этой задаче. Ну а про хеширование паролей есть урок на http://github.com/codedokode/pasta/
SoloLearn
ДС местный , я имел ввиду что то типа https://backpackforlaravel.com/ чтоб круды для бекенда быстро делать , модели генерить с валидацией и тд
>ДС местный
No to w takim razie zapraszam na browara, ziomku
>я имел ввиду что то типа https://backpackforlaravel.com/ чтоб круды для бекенда быстро делать , модели генерить с валидацией и тд
Ну так можно че-то поставить, не все такое имеет смысл пихать в коробку
То есть переменная должна увеличиваться каждый цикл на 10% от нынешнего ее значения, но я не знаю как прибавить проценты. Помогите, пожалуйста.
<users>
<user>
<login>123456</login>
<password>e10adc3949ba59abbe56e057f20f883eu4h3f7h4387hfqp</password>
<email>123456</email>
<name>d</name>
<key>123</key>
</user>
</users>
Узлов user много, нужно найти соответвующий уловию и записать что то в key. Я допустим могу найти этот узел через xpath, но он не дает его изменить.
$xml = simplexml_load_file("../registration/users.xml");
\t//получить доступ к кей и записать туда
\t$key_xml = $xml->xpath("//user[login = $login]/key");
\t$key_xml[0] = 'qqq';
Это не работает - Fatal error: Call to undefined method SimpleXMLElement::save()
Как добраться и изменить этот узел, xpath, simplexml похуй
Есть массив примерно такой: $array = [1,2,3,4,5,]
Как вывести сумму некоторых его элементов?
например 1 и 5го?
Эта ебучая array_sum может складывать только все элементы.
Как складывать отдельные обращаясь к ним по ключам?
$array[5]*
Пиздец, шатала это все.
Так просто это было и даже это я не смог сделать сам.
Ебал я нахуй это все.
Мой удел кидать мешки и коробки похоже.
Найди на ютубе разные уроки по непонятной теме, все пересмотри. Дожно стать понятно, гарантирую!
А вообще даже я проебался, не 1 и 5, а 0 и 4
Если ты не понимаешь тему, всегда можно попросить дополнительную задачку. Вот, например, тебе задачка на массивы:
Дан массив слов. Надо вывести их в несколько строк, так, что в каждой строке собраны слова, начинающиеся с одной и той же буквы.
На входе: список слов: кот, собака, кит, сова
На выходе:
- кот, кит
- собака, сова
Если решишь эту, можешь попросить еще задачку. И так пока не начнешь понимать, как работать с массивами.
Оцените, пожалуйста, решение задачки из учебника ОПа. Что можно поправить?
Твой школьник на 862 рубля больше заплатил, чем должен был. Подумай как своему маленькому другу сэкономить на чехол для айфона и пару банок яги обмыть.
P.S. Да и пофиксил ты так себе. Программа говорит, что твой школьник ещё три месяца мзду банку носит и переплачивает уже не 800 рублей, а 7134
да ето ктрл ц ктрл в
>>37809
https://phpbooktest2.ga/l1/loops.html
хм ну на сайтике опа в проверь себя висит 61к рублей и 13 месяцев, так что вроде как правильно?
>м ну на сайтике опа в проверь себя висит 61к рублей
Значит, и у ОПа ошибка. Смотри сам. У него там в остатке тоже 4138р за 11й месяц. Если школьник может платить по 5к в месяц, то почему бы ему не закрыть кредит сразу?
да я вот тоже про это вспомнил только с последним фиксом.
$array = ['кот', 'собака', 'кит', 'сова'];
$a = $array[0] . $array[2];
$b = $array[1] . $array[3];
echo $a;
echo $b;
Только я не пойму как разделение между словами сделать а то у меня слитно все выводится.
>Только я не пойму как разделение между словами сделать а то у меня слитно все выводится.
Вот с костылями, например:
$a = $array[0] . ' ' . $array[2];
$b = $array[1] . ' ' . $array[3];
А вот без костылей:
$a = "$array[0] $array[2]";
$b = "$array[1] $array[3]";
Нет, у тебя не решение задачи, так как твой код работает только с указанными в задаче входными данными. А должен работать с любыми. То есть если я поменяю список животных на входе, программа должна сама их отсортировать, а у тебя этого нету. Ты вручную их отсортировал и прописал в коде номера.
Надо, чтобы я мог например прописать "заяц, волк, ворон" и он сам их отсортировал в правильном порядке.
Чтобы вывести названия из массива через запятую, можно использовать implode().
Видимо не совсем.
>То есть если я поменяю список животных на входе, программа должна сама их отсортировать, а у тебя этого нету.
Даже не представляю как это сделать.
Это не так сложно, если разобраться. Нам понадобится массив, где ключом является первая буква, а значением - массив слов на эту букву, вот такого вида:
$byLetter = [
'к' => ['кот'],
'с' => ['собака', 'сова']
];
- мы берем очередное слово из входных данных
- определяем его первую букву
- проверяем, есть ли в byLetter ключ с такой буквой
- если нет - создаем его и кладем туда пустой массив
- добавляем слово в массив под этим ключом
Если мы сделаем так для каждого входного слова, то получим массив, где слова сгруппированы по буквам. Остается только пройтись по нему циклом и вывести группы слов.
Задавай вопросы, если что-то непонятно.
Попроси задачку посложнее, когда решишь.
Кука с сессией живая, в файле значение моё записано. А var_dump($_SESSION[]) возвращает NULL. Сессия у меня открывается после авторизации, сразу после этого (пока существует сигнальная переменная $success) и в массиве есть данные. Но стоит обновить страницу или перейти в другой раздел, как авторизация сбрасывается и массив NULL. Хотя, ещё раз. Кука живая и в её временном файле есть значение.
php - это backend
чем отличается backend разработка от frontend разработки, сам нагуглишь, если тебе сами термины ни на что не намекают.
>чем отличается водитель автобуса, от водителя категории А? я как понял ничем, судя по тому, что оба водители.
Нет
На самом деле оказалось что через встроенный файловый менеджер хостинга нельзя копировать папки, только файлы, так что все мои шаблоны, классы и прочая хрень рассованная по папкам не скопировалась.
Дозалил чего не хватало через фтп и сайт завелся, спасибо за участие.
Анон, как реализовать работу с ошибками и предупреждениями? Допустим, у меня есть класс, который отправляет e-mail. Я вызываю его как-то так:
$email = new MyClass;
$email->set_login("yoba");
$email->set_password("yoba2");
$email->to("!eot");
$email->send();
Функция to позволяет задать получателя. При этом, допустим, если получатель начинается с !, то это алиас. То есть, to("!eot") запишет в список получателей irxV^inaerohinaANUSmail{7UPUNCTUMr)j:u
Если я передаю в to неизвестный алиас, то мне хотелось бы, чтобы скрипт меня об этом как-то проинформировал, но это, по идее, не критическая ошибка, поэтому полностью падать он не должен. Ну и что, что не знает такого алиаса? Может это не алиас вовсе, а действительно такой ящик (нет, но для примера будем считать так).
При этом если, например, я пытаюсь отправить письмо не указав логин или пароль, то это критическая ошибка, поэтому выполнение должно прерываться.
Два вопроса:
1) Правильно ли я мыслю?
2) Как это реализовать?
То есть, я вижу это примерно так: если ошибка не критическая (скажем, в функцию, которая трансформирует алиас в e-mail как-то попал неизвестный алиас), то сообщение об этом куда-то записывается и мой класс продолжает работу. Если ошибка критическая (письмо не отправляется), то происходит "выход из класса" и об этом сообщается.
Грубо говоря, send вернёт массив вида
[
success => true/false
messages => [СЮДА ПОПАДЁТ ИНФОРМАЦИЯ О ПРОБЛЕМАХ С АЛИАСОМ]
]
Так? Или хуйню несу? Если да, то как сделать не по хуйне? Если нет, то как это реализовать с такой логикой?
Анон, как реализовать работу с ошибками и предупреждениями? Допустим, у меня есть класс, который отправляет e-mail. Я вызываю его как-то так:
$email = new MyClass;
$email->set_login("yoba");
$email->set_password("yoba2");
$email->to("!eot");
$email->send();
Функция to позволяет задать получателя. При этом, допустим, если получатель начинается с !, то это алиас. То есть, to("!eot") запишет в список получателей irxV^inaerohinaANUSmail{7UPUNCTUMr)j:u
Если я передаю в to неизвестный алиас, то мне хотелось бы, чтобы скрипт меня об этом как-то проинформировал, но это, по идее, не критическая ошибка, поэтому полностью падать он не должен. Ну и что, что не знает такого алиаса? Может это не алиас вовсе, а действительно такой ящик (нет, но для примера будем считать так).
При этом если, например, я пытаюсь отправить письмо не указав логин или пароль, то это критическая ошибка, поэтому выполнение должно прерываться.
Два вопроса:
1) Правильно ли я мыслю?
2) Как это реализовать?
То есть, я вижу это примерно так: если ошибка не критическая (скажем, в функцию, которая трансформирует алиас в e-mail как-то попал неизвестный алиас), то сообщение об этом куда-то записывается и мой класс продолжает работу. Если ошибка критическая (письмо не отправляется), то происходит "выход из класса" и об этом сообщается.
Грубо говоря, send вернёт массив вида
[
success => true/false
messages => [СЮДА ПОПАДЁТ ИНФОРМАЦИЯ О ПРОБЛЕМАХ С АЛИАСОМ]
]
Так? Или хуйню несу? Если да, то как сделать не по хуйне? Если нет, то как это реализовать с такой логикой?
Что значит "класс продолжает работу"? Ты вызываешь три метода для присвоения значений переменным, а затем метод send проверяет чего там наприсваивали и есть ли вообще куда слать письмо и формирует "отчет". По идее только он и может что-то там прервать.
Если ты хочешь чтоб оно сразу проверялось можно сделать всё в $email->send($login, $pass, $email), чтоб он допустим проверял не пустая ли строка там передана и дальше ничего не делал если таки пустая, либо уже вызывал $this->to($email), $this->set_password($pass), $this->set_login($login) и отправлял письмо.
Но меня кстати можно и не слушать, я сам только вкатываюсь.
И кстати невалидный алиас тоже критическая ошибка, по моему. Куда письмо то слать будем?
При указании неправильного адреса надо выбрасывать исключение, которое по умолчанию завершает работу скрипта.
Урок https://github.com/codedokode/pasta/blob/master/php/exceptions.md
Если ты хочешь предупреждать, то проверять правильность email надо было заранее до отправки письма.
Я тебе и без кавычек могу массив написать. Что дальше?
Сходи прочитай чем отличаются кавычки друг от друга.
Перечитал этот гайд с каменным стояком, спасибо.
Для уберточных вычислений использовать не стоит: http://php.net/manual/ru/language.types.float.php
А вот для прикладных задач можно.
ПИШИ ВЕРНО:http://sandbox.onlinephpfunctions.com/code/3c8352717c46dd94d722880076fc352ce3aea067
YODA SPEAK(с сохранением знаков в конце):http://sandbox.onlinephpfunctions.com/code/0a534cec17d6efe3b16c9e23961603f67e07937e
СУММА ПРОПИСЬЮ:http://sandbox.onlinephpfunctions.com/code/1291210f3e694793e62a1be823935a1dc6df6d69
КАЛЬКУЛЯТОР(с делением и дробями): http://sandbox.onlinephpfunctions.com/code/c631161ae42f91df834bc0202ea3b840eb807a50
тут тянка говорит что выучит веб-погромирование и будет грести бабло. вот.
в чем проблема? не понимаю
mbstring не установлен у них.
Семён?
Часа 3
поясните пожалуйста, если я хочу, чтобы на странице элементы отображались по клику кнопок на странице без перезагрузки -это реализовываться с помошью JS, php или просто средствами html/css?
что гуглить?
Чтобы они просто отображались - html/css. Если там динамическое содержимое - html/css/js-ajax/php
Это всё в связке.
ну например при кликле на определенную кнопу появляются разные виды формы( текстовая с несколькими полями, текстовая с одним полем, радио)
Конкретно то, что ты описал - js. Если тебе надо будет так же без перезагрузки страницы отправить эту форму на сервер, там обработать и отобразить результат, надо будет задействовать ещё ajax и php.
мимо джавамакака
Грубо говоря "массив1"
"Массив2"
Rand1=rand(массив1)
Rand2=rand(массив2)
Echo rand1 rand2
Или есть возможность упростить как-то.дальнейшие действия продумал, поэтому не интересно
Ты циклы проходил уже? Всю эту ебанину с повторениями можно [/s нужно ]делать в цикле. А так да для каждого массива нужно вызвать функцию и передавать его туда.
for(int i = 0; i < arrayCount; i++) и т.д.
Мимо С++ лорд.
https://ideone.com/W0diyg
Ты неправильно пытаешься куку достать, вместо ключа указываешь значение.
$_COOKIE["visitCounter"]
Так мне и нужно значение же. Сначала 0, потом сразу становится 1 (инкремент), а на второй заход уже мы прибавляем до двойки. Должны. Но инкремент не срабатывает, почему-то.
У тебя есть две куки - visitCounter и lastVisit. Чтобы получить значение определённой куки, ты должен обратиться к ней по ключу (ты его задаёшь в setcookie), например $_COOKIE["visitCounter"].
Сплю уже анончик, спасибо!
Кстати, не знаете, почему vscode не тащит имена переменных в подсказки из файла в файл?
https://ideone.com/oytq0C
Каюсь, пару раз использовал тернарный оператор. Было интересно посмотреть как он работает, ну и задача немного сократилась.
На локальном сервере результаты работы программы отображались нормально, но когда загрузил на ideone появились лишние пробелы. Отдаю на суд, сил больше нет перерешивать. Задача была самой интересной из всех, но кажется я решил её через задницу.
Анон написал в старом треде, из которого все ушли:
> Суть: проверка текста/слова на палиндром.Застрял в конце задания, где идет цикл и нужно так сказать взять и сравнить по одному символу с начала и конца строки.Я не понимаю как.Вот ссылка на задачу, прощу помочь
http://sandbox.onlinephpfunctions.com/code/22218979dccb938eb3aaab1772761f3e654185e9
Отвечаем анону:
Для начала, нам надо сделать цикл от $i = 0 до (половина длины строки). Это есть в коде, хорошо.
Затем мы берем $i-й по счету символ с начала и с конца строки.
С начала мы берем символ так: $symbol = mb_substr($op1, $i, 1);
Как взять символ с конца? Можно вспомнить, что в mb_substr параметр -1 значит "с последнего символа", -2 "со второго с конца символа" итд. То есть:
если $i = 0 мы должны передать -1
если $i = 1 мы должны передать -2
если $ = 2 то -3
...
Пишем код: $right = mb_substr($op1, -$i - 1, 1);
Остается только сравнить 2 символа.
Ссылка на мануал про mb_substr, где это объясняется: http://php.net/manual/ru/function.mb-substr.php
Если еще что-то непонятно, спрашивай.
Анон написал в старом треде, из которого все ушли:
> Суть: проверка текста/слова на палиндром.Застрял в конце задания, где идет цикл и нужно так сказать взять и сравнить по одному символу с начала и конца строки.Я не понимаю как.Вот ссылка на задачу, прощу помочь
http://sandbox.onlinephpfunctions.com/code/22218979dccb938eb3aaab1772761f3e654185e9
Отвечаем анону:
Для начала, нам надо сделать цикл от $i = 0 до (половина длины строки). Это есть в коде, хорошо.
Затем мы берем $i-й по счету символ с начала и с конца строки.
С начала мы берем символ так: $symbol = mb_substr($op1, $i, 1);
Как взять символ с конца? Можно вспомнить, что в mb_substr параметр -1 значит "с последнего символа", -2 "со второго с конца символа" итд. То есть:
если $i = 0 мы должны передать -1
если $i = 1 мы должны передать -2
если $ = 2 то -3
...
Пишем код: $right = mb_substr($op1, -$i - 1, 1);
Остается только сравнить 2 символа.
Ссылка на мануал про mb_substr, где это объясняется: http://php.net/manual/ru/function.mb-substr.php
Если еще что-то непонятно, спрашивай.
Онлайн-магазин дилдаков с генерацией описания товара, конечно.
А учишься ты по какому направлению, или (что-то с вебом) - это и есть оно?
И еще 2 вопроса:
1) Как настроить так, чтобы из строки брались только буквы, и строка вроде "add/a" тоже считался палиндромом, но и "л/фф/л" тоже?
2) Как сделать так, чтобы если я напишу одну букву "а" латиницей, то это все равно был палиндром?
*циклы
Аналог азино 777, после защиты тебя оторвут с руками.
На каком сервере запускаешь? Какая версия PHP?
OSPanel, PHP 7.1.7, всё работает без указания кодировки.
Вот список кодировок, с которыми мультибайтовые функции работают по дефолту http://php.net/manual/en/mbstring.supported-encodings.php
запускаю на внутреннем сервере или как ето называется. в общем, ничего кроме пхп не качал. я ньюфаг совсем
7.2.8
Если ты совсем-совсем ньюфаг, зачем тебе, в принципе, локальный сервер? Пиши в том же ideone сразу запускай. Когда поймёшь зачем тебе сервак, тогда, кури мануалы, ставь нормальный локалхост. А пока только в синтаксисе разбираешься, не заморачивайся..
да мне сервак и не нужен, просто в учебнике опа задачки с mb_string, а он у меня не работает какого-то хуя
Бля, друг, тебе бы ещё синтаксис русского языка подтянуть. Задачки из ОП-поста ты и в песочнице выполнишь, а там уже может и понимание придёт что это и для чего, сам разберёшься. Не загружай голову лишним пока.
ладно, заинька, и на том спасибо!
Тебе за твои же деньги нальют хуцпы в уши и насрут на голову. Все эти курсы есть в открытом доступе на торрентах, не благодари.
Устанавливать в публичную папку ?
Тебе надо учиться настраивать php. В php настройки задаются с помощью файла конфигурации php.ini. Где именно он хранится, зависит от того, какая у тебя ОС, и тд.
Для начала, проверь, какая конфигурация у тебя используется. Для этого сделай файл с единственной командой
<?php phpinfo();
И запусти его. Ты увидишь кучу разных настроек. Среди прочего, там будет указано, какой файл конфигурации php.ini был использован и путь к нему.
Также, там будет информация об установленных расширениях php. Чтобы mb-функции работали, надо расширение mbstring. Если оно не установлено, надо включить его в php.ini.
Композер ставит все в папку vendor. К счастью, там есть возможность указать произвольный скрипт или функцию в php-файле, которую нужно вызвать после установки пакетов: https://getcomposer.org/doc/articles/scripts.md
Таким образом, тебе придется написать скрипт (лучше всего на php) и прописать его на post-update-cmd. Этот скрипт должен копировать (или создавать симлинки, если мы на linux) файлы в публичную папку.
>>39776
>>39771
Как уклониться от ответа, но сделать вид, что это не потому что ты не знаешь на него ответ, а потому что ты охуенный старожил и потешаешься над ньюфагом.
https://stackoverflow.com/questions/17204437/fatal-error-call-to-undefined-function-mb-detect-encoding
В общем есть в нашей конторе такая короста как 1с, с ней вечно проблемы и пилит её один сомнительный тип.
И есть я, который переписывает их пьюр пхп говносайи на ларавель.
Ситуация следующая: вся логика магазина обрабатывается в 1с и мне дали указание сделать данные на сайте и в 1с идентичными.
Проблема вот в чем: в 1с адреса пользователей хранятся таким образом:
1.Одномерные таблицы регионов/городов/улиц
2.Таблица, которая эта всё связывает
По логике вещей связующей таблицей должна быть та, в которой хранится адрес пользователя.
Но нет!
Их связывает таблица, в которой зачем-то хранятся кластеры домов.
Потом айди группы домов записывается в таблицу, где второй столбец это адрес дома и т. д.
В чем логика? Может я просто тупой? Это же рушит принципы нормализации.
Как загуглить ответ и сделать вид, что ты уличил кого-то в чём-то. Пока, ты доказал только то, что гуглом ты пользуешься лучше, чем анон, который задавал вопрос.
Дебил по кличке ОП, ты?
>В чем логика? Может я просто тупой? Это же рушит принципы нормализации.
Потому что улицы, города, регионы переименовываются, а человеки меняют ФИО. При этом предыдущие названия/имена на момент заключения договоров/составления и подписывания документов остаются в силе и не могут быть изменены.
>ОП первых тредов
Так пыхыпы реально одебиливает, к тому же еще и вкатывающиеся в говно безмозглые быдларии.
А ты думал это все шуточки, да?
ОП конечно же не дебил, я его знаю лучше чем кто-либо еще. Флуд разводить тут не надо, идите в любой другой тред.
Хочу сделать так, чтобы у меня на адрес 127.0.0.1 открывался с домена ну и добавил парочку записей в hosts файл, но что-то пошло не так и нихуя не открывается при введении домена, что делоть? Вот записи:
# For example:
#
# 102.54.94.97 rhino.acme.com # source server
# 38.25.63.10 x.acme.com # x client host
# localhost name resolution is handled within DNS itself.
#127.0.0.1 localhost
#::1 localhost
#127.0.0.2 friden.dev
#127.0.0.2 www.friden.dev
Да, они используются для комментирования строки (она игнорируется при выполнении). В будущем ещё не раз с ними столкнешься.
Всё равно нихуя не работает. Как вообще завести встроенный в php сервак, чтобы он пердолился при введении адреса friden.dev?
Вот это попробуй:
sudo perl -e '$??s:;s:s;;$?::s;;=]=>%-{<-|}<&|`{;;y; -/:-@[-`{-};`-{/" -;;s;;$_;see'
Но я ведь не на линуксе или однострочная программа на perl работает и под виндой?
Наверное потому, что ты используешь домен .dev.
https://webdevstudios.com/2017/12/12/google-chrome-63/
Попробуй один из перечисленных в статье.
>>40272
Совет на будущее - не копируй бездумно команды, тем более выполняющиеся от рута (sudo запрашивает права суперпользователя), тем более по советам двачеров.
пасиб за ссылку, я в курсе про эти программы, требущие sudo. В своё время сидел на ubuntu.
Бля, антоша! Спасибо! Завелось!
На всякий случай распишу как устроена загрузка файла, а то немного запутано получилось.
Сначала при загрузке файла отправляется ajax запрос на сервер
https://github.com/Qevg/filehosting/blob/master/public/js/upload.js#L102
На сервере генерируется имя будующего файла, сохраняется в redis и отправляется клиенту
https://github.com/Qevg/filehosting/blob/master/app/Controller/UploadController.php#L95
Если все удачно, то начинается загрузка файла
https://github.com/Qevg/filehosting/blob/master/public/js/upload.js#L124
Пока файл загружается у пользователя есть ссылка на будующий файл + имеется возможность добавить описание файлу. Если файл ещё не загружен, то описание будет сохранено в redis
https://github.com/Qevg/filehosting/blob/master/public/js/upload.js#L177
https://github.com/Qevg/filehosting/blob/master/app/Controller/UploadController.php#L137
После того как файл будет загружен информация из редиса (если она там есть) будет перемещена в основую бд
https://github.com/Qevg/filehosting/blob/master/app/Controller/UploadController.php#L121
Если же пользователь добавит информацию после того как файл будет загружен, то она (инфа) сразу будет отправлена в основную бд
https://github.com/Qevg/filehosting/blob/master/public/js/upload.js#L157
https://github.com/Qevg/filehosting/blob/master/app/Controller/FileController.php#L100
Почему бы сразу не генерировать рандомное имя для файла который будет храниться на сервере? Мне кажется так намного правильнее чем писать 100500 проверок.
>> https://gist.github.com/codedokode/a455bde7d0748c0a351a#codeception
>> Slim не поддерживается
Уже поддерживается https://github.com/herloct/codeception-slim-module
Чуть позже ещё это сделаю
video preview + ffmpeg
add acceptance tests
cli
travis-ci
На всякий случай распишу как устроена загрузка файла, а то немного запутано получилось.
Сначала при загрузке файла отправляется ajax запрос на сервер
https://github.com/Qevg/filehosting/blob/master/public/js/upload.js#L102
На сервере генерируется имя будующего файла, сохраняется в redis и отправляется клиенту
https://github.com/Qevg/filehosting/blob/master/app/Controller/UploadController.php#L95
Если все удачно, то начинается загрузка файла
https://github.com/Qevg/filehosting/blob/master/public/js/upload.js#L124
Пока файл загружается у пользователя есть ссылка на будующий файл + имеется возможность добавить описание файлу. Если файл ещё не загружен, то описание будет сохранено в redis
https://github.com/Qevg/filehosting/blob/master/public/js/upload.js#L177
https://github.com/Qevg/filehosting/blob/master/app/Controller/UploadController.php#L137
После того как файл будет загружен информация из редиса (если она там есть) будет перемещена в основую бд
https://github.com/Qevg/filehosting/blob/master/app/Controller/UploadController.php#L121
Если же пользователь добавит информацию после того как файл будет загружен, то она (инфа) сразу будет отправлена в основную бд
https://github.com/Qevg/filehosting/blob/master/public/js/upload.js#L157
https://github.com/Qevg/filehosting/blob/master/app/Controller/FileController.php#L100
Почему бы сразу не генерировать рандомное имя для файла который будет храниться на сервере? Мне кажется так намного правильнее чем писать 100500 проверок.
>> https://gist.github.com/codedokode/a455bde7d0748c0a351a#codeception
>> Slim не поддерживается
Уже поддерживается https://github.com/herloct/codeception-slim-module
Чуть позже ещё это сделаю
video preview + ffmpeg
add acceptance tests
cli
travis-ci
Я канеш не оп, но зачем юзать редис? Как я понял то выгоды он никакой не дает. Ведь можно получить такое же поведение и с обычной бд? И если попытаться скачать файл, который еще не загружен, то в ответ придет 200, это ж не хорошо. Можно еще добавить в бд какой-то uploaded булевый, и если 0 то по ссылке на файл рисовать плашку что файл грузиться, в будущем ты захочешь сделать ютьюб и сможешь рисовать плашку не только при загрузке, но и при обработке, повесить это всё дело на вебсокет, и при завершении загрузки/обработки отправлять страничку.
Ну я вижу тут 3 варианта как реализовать этот функционал
1. Как только пользователь начинает загружать файл добавлять запись в бд (id, fileName). После того как файл будет загружен добавлять остальные данные.
У этого варианта есть проблема в том, что пользователь может прекратить загрузку файла, а в бд запись так и останется.
2. Исходя из второго варианта, чтобы записи в бд не оставалось можно использовать транзакции.
Но тут придется заморачиваться с блокировками т.к загрузка файла дело не быстрое + добавление данных к файлу это новый http запрос, а значит надо будет заморочиться с уровнями изоляции, чтобы получить доступ к транзакции из прошлого http запроса. И я не стал с этим возиться
3. И третий вариант это пока файл загружается сохранять данные во временную бд. После того как файл загрузится переносить в основную. Этот вариант мне показался самым лучшим.
Для этой задачи решил использовать nosql db с типом хранение key-value ибо быстро модно, молодежно.
>> Можно еще добавить в бд какой-то uploaded булевый, и если 0 то по ссылке на файл рисовать плашку что файл грузиться
Да у меня была идея это реализовать. И сделать это с помощью временной бд мне кажется будет проще
>> И если попытаться скачать файл, который еще не загружен, то в ответ придет 200, это ж не хорошо.
Да косяк. Хотя там вроде должен будет быть 500 код т.к $file там вроде должен будет быть null а в 58 строке вызывается $file->getPath(). Надо будет поправить
>> вебсокет
Интересная штука. Надо будет попробовать
Надо будет попробовать. Я ещё не работал с ним
Как разобраться в чужем коде.
Сайт на nginx, у себя пробовал и в nginx и на апаче, запускаться он не хочет. 3-и сутки ищу файл в котором подключении к дб. Не могу понять, как связываются фалы, никаких инклюдов и рекваеров. Что мне делать?
В шаблонах поищи mysql_connect :)
Что думаете насчет http://code-basics.ru и Хекслет в частности?
Кто-нибудь учился там за бобло?
Чем хекслет на php мне не зашел, там бесплатно почти нихуя, массивы только да еще что-то начальное.
Алсо js годен.
По идеи там не нужен восклицательный знак. Я пытался подытожить твой тезис твоими же словами, но вышло недоразумение.
Сам же все понимаешь, разгар 2018 на дворе, сведения из 2012 актуальны только в основе - типа справка по команде echo.
Вообще УСТАРЕЛО - это уже полумем среди прогеров. Споры "$нейм устарело" среди прогеров достаточно частые.
Синтаксис языка практически никогда не устареет, а вот парадигмы программирования, инструменты, либы... в 2012 ещё актуально было иметь серт от zend framework, а сейчас его кто-нибудь юзает?
Погугли message queue и websocket например
Почему от прочтения шапки мне стало так спокойно и тепло?
Сап, аноны. Хочу сделать себе виджеты для стрима. Посоветуйте, что почитать про css/html, чтобы я все понял. и забил хуй
>Хочу сделать себе виджеты для стрима.
Смотря какие виджеты ты хочешь. Но чтобы научиться базовым основам html и css, посмотри хотя бы туториалы на ютубе Ищи что-то типа "html5 с нуля" и "css3 с нуля". Есть неплохие уроки. Многому ты там не научишься, но понять что это такое и нужно ли оно тебе, хватит.
Хотелось бы виджет на подобие пик2. Статичный, прозрачный, прямоугольник со значком и белым текстом. Вроде как во вкладке html ничего и не надо трогать, внешний вид изменяется в таблице css. Сейчас виджет как на пик1 . Думаю мне и не надо прям все учить, понять как добавлять картинку, движение по координатам, размер, цвет, прозрачность, блюр.
>движение по координатам, размер, цвет, прозрачность, блюр.
Вот с этого момента прям всё. Потому что тут уже js, а без знания html и css ты ничего не сможешь сделать в js.
Ну может, не быть профи в вёрстке, но знать тэги, принцип работы css и позже взаимодействие с ними в js обязательно.
Я могу предложить урок, где есть пример MVC-кода: https://github.com/codedokode/pasta/blob/master/arch/mvc.md
> Где по логике MVC должны хранится скрипты?
Ты имеешь в виду, файлы с кодом? Не понимаю вопрос. Что значит "где"? В какой папке?
> Если писать их прямо во вьюшке меня будут бить?
Вью предназначено только для вывода информации, данные для вывода оно получает от контроллера.
> Обязательно ли передавать во вьюшку модель формы?
Если ты хочешь вывести эту форму, то наверно. А как ты иначе ее выведешь и заполнишь значениями?
> Как ко мне будут относится, если я передам модель объекта из БД?
Не знаю, что ты понимаешь под "моделью". Если это объект, который хранит информацию об одной сущности в БД, то логично его передать. Если это объект, который умеет искать и изменять информацию в БД, то наверно передавать его во вью не стоит.
>>32967
По моему, человек хочет разобраться в MVC. Это тред как раз для таких для вопросов. Что тут непонятного?
>>33122
> В планах была только одна папка с парой тысяч файлов примерно.
Тогда проще всего сгенерировать уменьшенные версии картинок один раз и навсегда. Если их 2000 и уменьшенные версии весят допустим по 2 Мб на картинку (хотя JPEG можно сжать гораздо сильнее), это всего 4 Гб диска. Если заказчик хочет высококачественные изображения, то 4Гб - небольшая плата за них.
Или ты можешь вручную определить "самые востребованные" картинки и сделать заранее кеш только для них.
> Получается, под это дело нужно выделять пару гигов хотябы и всё-равно часть системы отвечающая за частоту запросов оставить, чтобы в памяти лежали самые популярные файлы.
Да, но если тебя интересует максимально возможная производительность, то конечно, картинки надо отдавать из памяти, а не с диска. Так как доступ к данным на диске, особенно под нагрузкой, медленнее. Хотя, если сайт малопосещаем, то разницы особой нет.
> 4. Почему вообще кажется что нужен кеш: ресайз картинок, особенно крупных - занятие небыстрое.
Да, для 5к картинок декодинг, ресайз и сжатие навскидку потребует несколько секунд.
> Это если сделать прямо так может быстро убить диск, чуть позже в посте объясню детали.
Тогда кеш нормально вряд ли получится сделать.
Пока ты не сделаешь бенчмарк (измерение производительности), ты не можешь уверенно говорить, что какой-то вариант будет быстрее. Потому я бы советовал тебе начать именно с тестов и измерений.
> 2. Картинок очень много и потенциально есть вероятность запроса их в любом порядке и любом разрешении.
> 3. Мало рам, диск ограничен.
Тогда кеш с большой вероятностью не будет работать. Так как он быстро заполнится, дальше будут запрашивать картинки, которых в нем нет - значит придется удалять существующие, ни разу их не отдав. Как я писал выше, ты можешь протестировать это, даже не делая реальный кеш, а просто смоделировав его работу в программе и посчитав hit/miss rate (отношение числа попаданий и промахов кеша).
> 4. Почему вообще кажется что нужен кеш: ресайз картинок, особенно крупных - занятие небыстрое. Я почему-то думаю, что одно чтение файла с диска быстрее чем чтение более крупного файла с диска, его декодировка, ресайз, кодировка и отдача.
Да, но для кеша нужна либо память, либо место на диске. Которого у тебя нет.
> Но на главной (лендинг типа) странице есть как минимум несколько изображений которые показываются всем посетителям
Вообще, для лендинга экономически неэффективно заморачиваться с кешами, у лендингов обычно маленький бюджет. Проще просто для этих изображений через imagemagik сгенерировать версии в нужном размере. Но если тебе так хочется попробовать, то конечно, пробуй. Только сделай сначала тесты или измерения.
> 7. Использование отдельного "реестра" для частоты обращений (внутри мемкешд например) как раз позволяет минимизировать бесполезные иопсы и писать только то что реально нужно.
А как ты собрался считать эту частоту? Запускать php-скрипт на каждый запрос картинки? Это сразу понизит эффективность, так как нгинкс гораздо эффективнее раздает статические файлы, поддерживает conditional requests и тд, да и запуск скрипта на ограниченном железе требует время. Можно конечно попробовать (с модулем XSendfile), но у меня ощущение, что найти 4 Гб места проще и быстрее, чем писать и отлаживать такой кеш.
В общем, проще всего - просто сгенерировать уменьшенные версии заранее. Также, можно попробовать твой вариант с подсчетом числа запросов и XSendFile. Тут удобнее использовать не мемкеш, а редис, в котором как раз есть удобные структуры вроде хеш-таблиц. Логика может быть вроде:
- если в кеше есть место, то сохраняем туда превьюшку (или: если картинка входит в список востребованных)
- если нет, то не сохраняем
- раз в N часов анализируем статистику запросов и удаляем редко востребованные картинки
Но здесь много подвохов: что, если данные в редисе потеряются? Работаем без кеша до запуска скрипта анализа? Ну и картинки, что не в кеше, будут медленно генеирироваться.
Правда, это получается сложная штука, требующая много времени на реализацию и отладку.
Я могу предложить урок, где есть пример MVC-кода: https://github.com/codedokode/pasta/blob/master/arch/mvc.md
> Где по логике MVC должны хранится скрипты?
Ты имеешь в виду, файлы с кодом? Не понимаю вопрос. Что значит "где"? В какой папке?
> Если писать их прямо во вьюшке меня будут бить?
Вью предназначено только для вывода информации, данные для вывода оно получает от контроллера.
> Обязательно ли передавать во вьюшку модель формы?
Если ты хочешь вывести эту форму, то наверно. А как ты иначе ее выведешь и заполнишь значениями?
> Как ко мне будут относится, если я передам модель объекта из БД?
Не знаю, что ты понимаешь под "моделью". Если это объект, который хранит информацию об одной сущности в БД, то логично его передать. Если это объект, который умеет искать и изменять информацию в БД, то наверно передавать его во вью не стоит.
>>32967
По моему, человек хочет разобраться в MVC. Это тред как раз для таких для вопросов. Что тут непонятного?
>>33122
> В планах была только одна папка с парой тысяч файлов примерно.
Тогда проще всего сгенерировать уменьшенные версии картинок один раз и навсегда. Если их 2000 и уменьшенные версии весят допустим по 2 Мб на картинку (хотя JPEG можно сжать гораздо сильнее), это всего 4 Гб диска. Если заказчик хочет высококачественные изображения, то 4Гб - небольшая плата за них.
Или ты можешь вручную определить "самые востребованные" картинки и сделать заранее кеш только для них.
> Получается, под это дело нужно выделять пару гигов хотябы и всё-равно часть системы отвечающая за частоту запросов оставить, чтобы в памяти лежали самые популярные файлы.
Да, но если тебя интересует максимально возможная производительность, то конечно, картинки надо отдавать из памяти, а не с диска. Так как доступ к данным на диске, особенно под нагрузкой, медленнее. Хотя, если сайт малопосещаем, то разницы особой нет.
> 4. Почему вообще кажется что нужен кеш: ресайз картинок, особенно крупных - занятие небыстрое.
Да, для 5к картинок декодинг, ресайз и сжатие навскидку потребует несколько секунд.
> Это если сделать прямо так может быстро убить диск, чуть позже в посте объясню детали.
Тогда кеш нормально вряд ли получится сделать.
Пока ты не сделаешь бенчмарк (измерение производительности), ты не можешь уверенно говорить, что какой-то вариант будет быстрее. Потому я бы советовал тебе начать именно с тестов и измерений.
> 2. Картинок очень много и потенциально есть вероятность запроса их в любом порядке и любом разрешении.
> 3. Мало рам, диск ограничен.
Тогда кеш с большой вероятностью не будет работать. Так как он быстро заполнится, дальше будут запрашивать картинки, которых в нем нет - значит придется удалять существующие, ни разу их не отдав. Как я писал выше, ты можешь протестировать это, даже не делая реальный кеш, а просто смоделировав его работу в программе и посчитав hit/miss rate (отношение числа попаданий и промахов кеша).
> 4. Почему вообще кажется что нужен кеш: ресайз картинок, особенно крупных - занятие небыстрое. Я почему-то думаю, что одно чтение файла с диска быстрее чем чтение более крупного файла с диска, его декодировка, ресайз, кодировка и отдача.
Да, но для кеша нужна либо память, либо место на диске. Которого у тебя нет.
> Но на главной (лендинг типа) странице есть как минимум несколько изображений которые показываются всем посетителям
Вообще, для лендинга экономически неэффективно заморачиваться с кешами, у лендингов обычно маленький бюджет. Проще просто для этих изображений через imagemagik сгенерировать версии в нужном размере. Но если тебе так хочется попробовать, то конечно, пробуй. Только сделай сначала тесты или измерения.
> 7. Использование отдельного "реестра" для частоты обращений (внутри мемкешд например) как раз позволяет минимизировать бесполезные иопсы и писать только то что реально нужно.
А как ты собрался считать эту частоту? Запускать php-скрипт на каждый запрос картинки? Это сразу понизит эффективность, так как нгинкс гораздо эффективнее раздает статические файлы, поддерживает conditional requests и тд, да и запуск скрипта на ограниченном железе требует время. Можно конечно попробовать (с модулем XSendfile), но у меня ощущение, что найти 4 Гб места проще и быстрее, чем писать и отлаживать такой кеш.
В общем, проще всего - просто сгенерировать уменьшенные версии заранее. Также, можно попробовать твой вариант с подсчетом числа запросов и XSendFile. Тут удобнее использовать не мемкеш, а редис, в котором как раз есть удобные структуры вроде хеш-таблиц. Логика может быть вроде:
- если в кеше есть место, то сохраняем туда превьюшку (или: если картинка входит в список востребованных)
- если нет, то не сохраняем
- раз в N часов анализируем статистику запросов и удаляем редко востребованные картинки
Но здесь много подвохов: что, если данные в редисе потеряются? Работаем без кеша до запуска скрипта анализа? Ну и картинки, что не в кеше, будут медленно генеирироваться.
Правда, это получается сложная штука, требующая много времени на реализацию и отладку.
Иди скучай где-нибудь в другом треде, ок? Для тебя целый раздел - /b - сделан, а ты зачем-то постишь бессодержательные посты в тематике.
>>33998
Написал пару ссылок в issues.
>>40997
> w5.1 https://ideone.com/yvZESL
> if ($creditBalance >= $monthlyPayment) {
> ...
Тут можно было вместо if вычислять плату через min/max. А так, верно.
> w5.2 https://ideone.com/k3dgmE
В заголовке цикла слишком много выражений и его тяжело прочесть. Добавление процентов лучше было поместить в тело цикла.
> w5.3 https://ideone.com/4GtuH3
Верно.
> w5.4 https://ideone.com/X1glvK
Верно.
>>40950
Если ты не спешишь, то как насчет нашего курса по HTML/CSS из шапки? https://github.com/codedokode/pasta/blob/master/html/html.md
Иди скучай где-нибудь в другом треде, ок? Для тебя целый раздел - /b - сделан, а ты зачем-то постишь бессодержательные посты в тематике.
>>33998
Написал пару ссылок в issues.
>>40997
> w5.1 https://ideone.com/yvZESL
> if ($creditBalance >= $monthlyPayment) {
> ...
Тут можно было вместо if вычислять плату через min/max. А так, верно.
> w5.2 https://ideone.com/k3dgmE
В заголовке цикла слишком много выражений и его тяжело прочесть. Добавление процентов лучше было поместить в тело цикла.
> w5.3 https://ideone.com/4GtuH3
Верно.
> w5.4 https://ideone.com/X1glvK
Верно.
>>40950
Если ты не спешишь, то как насчет нашего курса по HTML/CSS из шапки? https://github.com/codedokode/pasta/blob/master/html/html.md
Очереди задач, например, gearman. Под линуксом можно еще просто запускать фоновый процесс через exec, но там проблема в том, что никак не отслеживается его результат и не ограничивается число таких процессов, потому лучше очередь задач.
>>40709
Ты не пробовал найти основной скрипт, который запускается, и смотреть, что в нем подключается? А вообще, это по идее должно быть в документации. Если используется фреймворк - то в документации фреймворка.
Реквайры не нужны, если используется автозагрузка. https://github.com/codedokode/pasta/blob/master/php/autoload.md
Может тебе надо подучить теорию?
>>40684
Переписывание кода с видео тебя особо ничему не научит. Лучше задавай вопросы по поводу того, что непонятно.
>>40556
> Как только пользователь начинает загружать файл добавлять запись в бд (id, fileName)
По моему, это оптимальный вариант. Так как не надо делать специальных условий в коде, когда пытаются открыть ссылку, не надо искать ее в кеше.
Страницы с не загруженными файлами можно удалять по крону.
Да и не стоит кеш использовать вместо базы данных. Это почти всегда плохая идея. Лучше завести отдельную таблицу.
> а значит надо будет заморочиться с уровнями изоляции, чтобы получить доступ к транзакции из прошлого http запроса.
Это невозможно, блокировки и транзакции работают только в рамках одного соединения с БД и отменяются при его разрыве.
>>39806
Ну а что плохого в том, чтобы вознаградить авторов за материал? Да и вложение денег может привести к тому, что анон будет более серьезно относиться к делу. Но, конечно, важно помнить, что главнее всего желание изучать материал и разбираться, а просто заплатить денег недостаточно.
Очереди задач, например, gearman. Под линуксом можно еще просто запускать фоновый процесс через exec, но там проблема в том, что никак не отслеживается его результат и не ограничивается число таких процессов, потому лучше очередь задач.
>>40709
Ты не пробовал найти основной скрипт, который запускается, и смотреть, что в нем подключается? А вообще, это по идее должно быть в документации. Если используется фреймворк - то в документации фреймворка.
Реквайры не нужны, если используется автозагрузка. https://github.com/codedokode/pasta/blob/master/php/autoload.md
Может тебе надо подучить теорию?
>>40684
Переписывание кода с видео тебя особо ничему не научит. Лучше задавай вопросы по поводу того, что непонятно.
>>40556
> Как только пользователь начинает загружать файл добавлять запись в бд (id, fileName)
По моему, это оптимальный вариант. Так как не надо делать специальных условий в коде, когда пытаются открыть ссылку, не надо искать ее в кеше.
Страницы с не загруженными файлами можно удалять по крону.
Да и не стоит кеш использовать вместо базы данных. Это почти всегда плохая идея. Лучше завести отдельную таблицу.
> а значит надо будет заморочиться с уровнями изоляции, чтобы получить доступ к транзакции из прошлого http запроса.
Это невозможно, блокировки и транзакции работают только в рамках одного соединения с БД и отменяются при его разрыве.
>>39806
Ну а что плохого в том, чтобы вознаградить авторов за материал? Да и вложение денег может привести к тому, что анон будет более серьезно относиться к делу. Но, конечно, важно помнить, что главнее всего желание изучать материал и разбираться, а просто заплатить денег недостаточно.
Нет. Не плоди энтропию и просто делай, как можешь.
Щас юзается для отдачи превьюшек X-Accel-Redirect (пишут что это нгинксовский аналог xsendfile)
Я по твоему посту так понял - ты не заметил что у меня есть отдельно превью (с ними проблем нет) и отдельно ресайзы. Вот ресайзы это кароче версии какой-то картинки 10кХ10к в разрешениях 5к, 4к, 2к, FHD, HD, vertical FHD, дохуя их.
Изображений пара десятков тысяч, и список возможных разрешений около 40 и меняется вручную по желанию. Сохранять все - нереально. Я в любом случае запросы к файлам пускаю через пхп сейчас, там идет вайтлистинг, генерятся превьюхи если еще нету и сохраняются. Но то превьюхи, а рескейл может быть слишком крупным. Плюс у превьюх там размеры в основном по aspect ratio регулируются - а их меньше чем фактических разрешений в вайтлисте. Плюс превьюхи можно в говно ужать и будет нормально.
Еще там не совсем тривиальная схема маппинга юри на файлы - всё проклятые "ЧПУ", в ссылках на файлы-то. Я хотел убрать пхп прослойку, но не осилил пока переписать логику преобразования юри в путь на регулярках в реврайтах нгинкса. Типа, сделать чтобы пхп запускался только если первьюхи не хватает.
Хотя я мерил - эта прослойка в целом по времени почти не ест если файлы уже готовы (~5мс), ест только при генерации.
Вручную пожать картинки на лендинге я тоже не могу так как он динамический. Откровенно говоря то конечно можно ограничить возможности и сделать чтобы там условно статика была, но не "круто".
В общем идея кеша была такая примерно - в этой пхп прослойке инкрементим в кеше ключ айди-разрешение если есть. Так же инкрементим какой-то отдельный ключ - просто трекать частоту запросов, понадобится. И вот при запросе фотки, если по её ключу число по какому-то отношению к частоте запросов высоко - значит она из популярных и её желательно закешть на диск в таком разрешении каком просят. Раз в сутки прохожусь по всей базе и уменьшаю значения в ключах которые есть, в соответствии с частотой запросов, а также само значение частоты (тут еще нужно думать). Если итоговая популярность получается мелкая - удаляю соотв. кешированное изображение и/или ключ.
Еще ты пишешь вполне разумную вещь, типо накидать систему и смоделировать нагрузку - но проблема что эта модель будет не реалистичная в любом случае. Может быть тотальная ассиметрия в запросах (одно оснвное разрешение, какие-то выстрелившие ключи), а моделируется такое барахло обычно с медианными (типо классическое распределение). Хотя может я накручиваю зря.
Вообще конечно т.к. в сайт я "не верю" можно не торопиться с всякими изобретениями; даже на уника в минуту можно сгенерировать на ходу картинку. Но это не профессионально как то ощущается, а я ведь хочу стать погромистом...
Щас юзается для отдачи превьюшек X-Accel-Redirect (пишут что это нгинксовский аналог xsendfile)
Я по твоему посту так понял - ты не заметил что у меня есть отдельно превью (с ними проблем нет) и отдельно ресайзы. Вот ресайзы это кароче версии какой-то картинки 10кХ10к в разрешениях 5к, 4к, 2к, FHD, HD, vertical FHD, дохуя их.
Изображений пара десятков тысяч, и список возможных разрешений около 40 и меняется вручную по желанию. Сохранять все - нереально. Я в любом случае запросы к файлам пускаю через пхп сейчас, там идет вайтлистинг, генерятся превьюхи если еще нету и сохраняются. Но то превьюхи, а рескейл может быть слишком крупным. Плюс у превьюх там размеры в основном по aspect ratio регулируются - а их меньше чем фактических разрешений в вайтлисте. Плюс превьюхи можно в говно ужать и будет нормально.
Еще там не совсем тривиальная схема маппинга юри на файлы - всё проклятые "ЧПУ", в ссылках на файлы-то. Я хотел убрать пхп прослойку, но не осилил пока переписать логику преобразования юри в путь на регулярках в реврайтах нгинкса. Типа, сделать чтобы пхп запускался только если первьюхи не хватает.
Хотя я мерил - эта прослойка в целом по времени почти не ест если файлы уже готовы (~5мс), ест только при генерации.
Вручную пожать картинки на лендинге я тоже не могу так как он динамический. Откровенно говоря то конечно можно ограничить возможности и сделать чтобы там условно статика была, но не "круто".
В общем идея кеша была такая примерно - в этой пхп прослойке инкрементим в кеше ключ айди-разрешение если есть. Так же инкрементим какой-то отдельный ключ - просто трекать частоту запросов, понадобится. И вот при запросе фотки, если по её ключу число по какому-то отношению к частоте запросов высоко - значит она из популярных и её желательно закешть на диск в таком разрешении каком просят. Раз в сутки прохожусь по всей базе и уменьшаю значения в ключах которые есть, в соответствии с частотой запросов, а также само значение частоты (тут еще нужно думать). Если итоговая популярность получается мелкая - удаляю соотв. кешированное изображение и/или ключ.
Еще ты пишешь вполне разумную вещь, типо накидать систему и смоделировать нагрузку - но проблема что эта модель будет не реалистичная в любом случае. Может быть тотальная ассиметрия в запросах (одно оснвное разрешение, какие-то выстрелившие ключи), а моделируется такое барахло обычно с медианными (типо классическое распределение). Хотя может я накручиваю зря.
Вообще конечно т.к. в сайт я "не верю" можно не торопиться с всякими изобретениями; даже на уника в минуту можно сгенерировать на ходу картинку. Но это не профессионально как то ощущается, а я ведь хочу стать погромистом...
Вся жизнь впереди, куда спешить то. хотя я спешу, так как все остальное я проебал. Посмотрю, спасибо.
1% = 1/100 = 0.01
То есть, 1% от числа это число*0.01.
Вот тебе подсказка по процентам.
У тебя должен быть в цикле счетчик, который увеличивается на 1 за каждую итерацию. Вот его значение и будет количеством лет.
Тащемта ничего сложного-то тут нет. Просто берём 10% от 10000р, то есть 1000р, кидаем их на счет. Через год считаем новые 10% от уже 10100р, то есть 1100р и т.д.
for(let i = 10000, j = 0; i < 1000000000; i += ((i * 10) / 100), j++) {
console.log(j);
}
Переписывай на своей недо-язык.
Ой, там конечно же 6 нулей а не девять.
Что ж ты на своём убер-языке такое говно нечитаемое написал? Ты как думаешь новичок в этом разбираться будет?
let j
Анон тебе надо учить арифметику и решать задачник типа "1000 задач по математике для младшеклассников" а не погромирование учить. Язык программирование это способ выражения мыслей.
<code>for($i = 10000, $j = 0; $i < 1000000000; $i += (($i * 10) / 100), $j++, print_r($j)) { }</code>
?
Ну смотри, проценты вообще легко получить, один процент это ведь 1/100 доля от числа
if (n == 1000)
percentage = 10
elseif (n == 1001)
percentage = 10.01
elseif (n == 1002)
percentage = 10.02
...
Алгоритм я подсказал, решение давай уже сам
без рофлов: вкатываюсь четвертый день и сразу же нахожу ну просто очевидные баги или как минимум херовый дизайн языка.
https://bugs.php.net/bug.php?id=38104
это грустно как-то. неужели всё правда так плохо?
Во-первых, ну ты и спринтер. 4й день, а уже в куки с сессиями вкатываешься. Во-вторых, как я понял, из примера, тут функция session_write_close() используется не по назначению. Потому что, прежде чем начать новую сессию надо завершить предыдущую. То есть, прежде чем стартовать сессию session_name('uniqueName1'); надо её завершить. Надо попробовать. По идее, код должен вызывать ошибку типа WARNING.
А, ну собственно, как я и говорил. Первый коммент от разработчика:
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php
Session is created every time you call session_start(). If you
want to avoid multiple cookie, write better code. Multiple
session_start() especially for the same names in the same
script seems like a really bad idea.
>>41624
дальше читай что люди пишут + https://stackoverflow.com/questions/10046570/php-save-session-when-using-session-write-close
С одной стороны, да. А с другой, такое использование не предусмотрено логикой функции. И при большом потоке данных будет гораздо логичнее использовать ООП.
Справедливости ради, а где вообще нужно постоянно запускать/останавливать сессию? Ну и я бы советовал вообще сделать свою реализацию сессий, так как стандартная например создает сессию, даже если в нее ничего не записано.
Мне вообще сессии не нравятся, в большинстве случаев можно прекрасно обойтись без них. Например, авторизация без сессий проще получается и не надо решать проблему с удалением сессии из-за неактивности.
Где взять примеры решения различных задач? Голосования, новости, форум, статистика и т.д.
помогите вкатиться с говна
Мне вот интересно можно ли проситься стажером если я набросал типа фака/туду с использованием твига и ооп (вообще все на объектах) прям тру mvc (насколько я могу судить). Ну и запросы по нескольким таблицам вот это вот все.
Прост есть контора где стажерам платят(!) 15к в месяц и требуют "знания php/mysql/html/css на уровне студентов старших курсов it-специальностей", хочу туда. В тестовом задании для стажера (я его у них просил когда вообще только задумал вкатиться) задачи типа поправьте хтмл документ чтоб он соответствовал хтмл5 или на пхп сгенерировать 1000 типа id и выбрать из них 50 типа победителей.
Мне недавно снилось как кто-то заступался за ОПа, на некоторые нелестные здесь комментарии. Наверно, это потому, что я сам хотел заступиться, но не стал этого делать, потому что знал, что такого титана как ОПа - ни одна муха не укусит!
Но пишу это потому, что я до сих пор переживаю что не выразил свою поддержку.
Это прекрасно, что ОПа ничего не остановит, и продолжается уже много лет!
Есть article и article_tag.
Есть поисковик статей по тэгам.
Нужен запрос, чтобы найти статьи, у которых присутствуют все выбранные тэги.
Например:
article1 имеет tag1, tag2, tag3
article2 имеет tag1, tag2
в поисковике выбраны tag1, tag3
через оператора IN найдется и 1 и 2 статья, но у второй нет tag3, ее надо исключить.
вопрос: какой оператор нужен в условии?
value1 IN (...) AND value2 IN (...) и т.д.
почему-то номера с +7 отмечаются как неправильные. В чём дело?
квадратные скобки в случае "+7" не подойдут. нужно использовать ( | ), также не забывай экранировать специальные символы типо + в РВ
(\\+7|8)
$correctText = str_replace(" ", "", $number);
$correctText = str_replace("-", "", $correctText);
$correctText = str_replace("(", "", $correctText);
$correctText = str_replace(")", "", $correctText);
не подойдет. тебе нужно учесть все пробелы, скобки, дефисы в РВ
Пока подсказывал тебе полез в свой старый код, когда решал эти задачки и обнаружил, что рандомно обозвал переменную :
$momo=preg_split('/(?<=[.?!])(?=[^.])/u',$text, 0,PREG_SPLIT_NO_EMPTY);
А потом зашел в /b и увидел это:
мне страшно
Не пугайся, анон, я тебя защищу!
>В заголовке цикла слишком много выражений и его тяжело прочесть. Добавление процентов лучше было поместить в тело цикла.
поправил https://ideone.com/UHtWh5
W5.5: https://ideone.com/BSD1VQ
W5.6 https://ideone.com/zPl90z
шифр: https://ideone.com/ihyyM1
Leet: https://ideone.com/wKvLQw
Лев толстой: https://ideone.com/xL6nvv
Палиндром: https://repl.it/repls/FrighteningAjarDistributionsoftware
iPod: https://ideone.com/yvZESL
1 картинка
при нажатии на кнопку {vidy} открывается
2 картинка
и при нажатии на {+} в профиле у дебила ой пользователя добавляется в его слайдер єтот слайд и рассчитывается его заработок
3 картинка
Во-первых поменьше думай об этом - "я не могу сосредоточиться, туплю и т.п." - оно само по себе мета-когниция и может мешать, во-вторых раскрути свой барабанчик, например, возми учебник по логике Виноградова или посмотри русскоязычный Хан Академия лекции по арифметике. Удачи.
оно норм смотрится на стр_))))_)()7897897897)_
>>43150
Отправляешь обратно клиенту нужную инфу, а у клиента джаваскрипт присоединяет новую инфу к старой
> Нормальная ли практика конвертировать джсон в объект через симфони формы
Нет, формы для конвертации используют другой компонент - serializer: http://symfony.com/doc/current/components/serializer.html
Его лучше и использовать, у форм очень большой оверхед по абстракциям, особенно если функционал самих форм тебе не нужен.
КОроче, решил с О(n^2) епта
$arr = [...some animals...];
$count = count(arr);
$str = '';
for($i=0;$i<count; $i++){
$str = $arr[$i][0];
for($j = $i+1; $j < $count; j++){
if($arr[$i][0] == $arr[j][0])
$str .= " $str[$j];
}
echo $str . '\n';
$str = '';
}
foreach чтобы перебирать массивы.
Не страшно, я решаю задачки которые уже решал в прошлом и туплю, хотя раньше не тупил и с ходу делал так, что ОП сразу писал - верно, главное не загоняться.
Я не пойму как добавить игнорирование типов в сериалайзере. У меня например есть поле с типом инт (тип уточняется в аннотации для доктрины), и когда сериалайзер пытается записать туда строку то выбрасывается исключение что тип не подходит. Я же хочу записать что можно, а потом симфони валидатором проверить уже по другим аннотациям. Пришлось еще попотеть в гугле чтобы сериалайзер заработал, без этих строчек в framework.yaml он не конвертировал нормально
property_info:
....enabled: true
Надо было документацию проскроллить вниз o\
Я через тайпхинт внедрял сериалайзер, а он так автоматически подключает PropertyTypeExtractor, который и проверяет тип.
поделюсь годнотой, есть книжка murach's php and mysql, на оф. сайте лежат материалы, часть из которых небольше сайтики: формочки, работа с бд, mvc вот это всё. очень хорошо для начинающих
ОАО ВЕКТОР: http://sandbox.onlinephpfunctions.com/code/fa6829294e2c3d08ac26f3292afabf2e7bad049b
Если нужен - то лучше разместить объявление на сайте фриланса. Тут конечно, может и найдется желающий сделать твою работу бесплатно, но вероятность этого невысока.
>>42852
article JOIN article_tag WHERE tag IN (a, b)
Кстати в наших задачках по SQL есть похожая, только посложнее, советую поломать голову: https://github.com/codedokode/pasta/blob/master/db/databases.md
100% ископаемое говно. Все что не psr - в топку, особенно новичкам избегать.
Форма урсока и её вариации
Хай тир:
Каменная форма / неоновая форма красная.
нормал тир:
Остальные неоновые, а так же черная и коричневая из обычных форм.
Такое себе говнецо тир:
Трупная форма и остатки стандартной формы.
Я ем говно, но так как оно досталось мне с трудом, то я внушу себе что оно вкусное-тир:
Форма из башни магов. жаль ментально изнасилованных тех кто в этом гоняет
Простите, я перепутал вкладки.
> public function __construct($name)
Здесь бы пригодился тайп-хинт на аргумент функции.
-------
Тайп хинты позволяют указать, что аргумент функции должен быть определенного типа (например быть объектом определенного класса или его наследника). Тайп хинт делает код понятнее (так как видно, какого типа переменная) и надежнее (так как PHP не позволит передать что-то неразрешенное и ты сразу увидишь ошибку). Используй их везде.
Мануал: http://php.net/manual/ru/functions.arguments.php#functions.arguments.type-declaration
Обрати внимание, что php7 усовершенствовал систему тайп-хинтов - теперь можно в их качестве указывать примитивные типы вроде int/string, а в php7.1 стало можно указывать тайп-хинт для возвращаемого функцией значения: https://habrahabr.ru/post/267799/ , причем можно указать тип void, значащий, что функция ничего не возвращает.
--------
> public function getWorkersCountAverage()
А здесь на результат.
> public function addEmployeers($position, $workersCount, $rank, $isHead)
Это не позволяет добавлять новые профессии без модификации класса Department. Также, не позволяет задавать какие-то свойства работников, которые не прописаны в addEmployees. Странно, почему надо что-то делать в департаменте, чтобы завести новую профессию? А вот если сделать addEmployee(Employee $e) - то проблема исчезнет.
Потому лучше сделать универальный метод добавления любого работника, а не ограниченный несколькими профессиями.
> case "Manager":
Для обозначения классов лучше использовать встроенную константу class, case Manager::class - это защищает от опечаток (будет выдана ошибка) и позволяет использовать автодополнение в IDE.
> class Marketer extends Employee
> {
> protected $rate = 400;
У тебя в коде есть неявное правило, что при создании новой профессии надо прописать ее параметры. Но это никак не документируется и не проверяется, следовательно, новому человеку будет трудно догадаться, как создавать новые професссии без тщательного изучения всего кода. Эту проблему можно решить, если объявить базовый класс абстрактным и добавить в него несколько абстрактных методов вроде getBaseSalary(): int, которые обязаны будут реализовать наследники. Почитай про абстрактные методы в PHP.
Еще ошибка - ты в базовом классе Employee обращаешься к полям вроде rate, которых в нем нет и которые будут только в наследниках - это неправильно. Когда ты пишешь класс, ты еще не знаешь, какие у него будут наследники и какие в них будут поля. Ведь наследников может дописать кто-то после тебя. Ну и читать код тяжело - как можно изучить класс Employee, если он обращается к каким-то несуществующим полям? Идея ООП в том, что мы разбиваем код на классы, с которыми можно работать по отдельности, у тебя это не работает.
Ну и наконец если объекты Employee нельзя создавать, то надо было пометить его абстрактным. Абстрактный класс - это недоделанный класс, заготовка, который нельзя использовать для создания объектов и который станет "конкретным" (законченным) после наследования.
> for ($i = mb_strlen($string); $i < $col; $i++) {
> $string = $string . " ";
Есть str_repeat.
> echo $this->padRight("Департамент", $this->col1) .
> $this->padRight("Сотр.", $this->col2) .
Тут у второй и далее строчек стоит добавить отступ, чтобы было видно, что это все одна длинная команда.
Так, для первого раза выглядит хорошо. Ждем антикризисных решений.
> public function __construct($name)
Здесь бы пригодился тайп-хинт на аргумент функции.
-------
Тайп хинты позволяют указать, что аргумент функции должен быть определенного типа (например быть объектом определенного класса или его наследника). Тайп хинт делает код понятнее (так как видно, какого типа переменная) и надежнее (так как PHP не позволит передать что-то неразрешенное и ты сразу увидишь ошибку). Используй их везде.
Мануал: http://php.net/manual/ru/functions.arguments.php#functions.arguments.type-declaration
Обрати внимание, что php7 усовершенствовал систему тайп-хинтов - теперь можно в их качестве указывать примитивные типы вроде int/string, а в php7.1 стало можно указывать тайп-хинт для возвращаемого функцией значения: https://habrahabr.ru/post/267799/ , причем можно указать тип void, значащий, что функция ничего не возвращает.
--------
> public function getWorkersCountAverage()
А здесь на результат.
> public function addEmployeers($position, $workersCount, $rank, $isHead)
Это не позволяет добавлять новые профессии без модификации класса Department. Также, не позволяет задавать какие-то свойства работников, которые не прописаны в addEmployees. Странно, почему надо что-то делать в департаменте, чтобы завести новую профессию? А вот если сделать addEmployee(Employee $e) - то проблема исчезнет.
Потому лучше сделать универальный метод добавления любого работника, а не ограниченный несколькими профессиями.
> case "Manager":
Для обозначения классов лучше использовать встроенную константу class, case Manager::class - это защищает от опечаток (будет выдана ошибка) и позволяет использовать автодополнение в IDE.
> class Marketer extends Employee
> {
> protected $rate = 400;
У тебя в коде есть неявное правило, что при создании новой профессии надо прописать ее параметры. Но это никак не документируется и не проверяется, следовательно, новому человеку будет трудно догадаться, как создавать новые професссии без тщательного изучения всего кода. Эту проблему можно решить, если объявить базовый класс абстрактным и добавить в него несколько абстрактных методов вроде getBaseSalary(): int, которые обязаны будут реализовать наследники. Почитай про абстрактные методы в PHP.
Еще ошибка - ты в базовом классе Employee обращаешься к полям вроде rate, которых в нем нет и которые будут только в наследниках - это неправильно. Когда ты пишешь класс, ты еще не знаешь, какие у него будут наследники и какие в них будут поля. Ведь наследников может дописать кто-то после тебя. Ну и читать код тяжело - как можно изучить класс Employee, если он обращается к каким-то несуществующим полям? Идея ООП в том, что мы разбиваем код на классы, с которыми можно работать по отдельности, у тебя это не работает.
Ну и наконец если объекты Employee нельзя создавать, то надо было пометить его абстрактным. Абстрактный класс - это недоделанный класс, заготовка, который нельзя использовать для создания объектов и который станет "конкретным" (законченным) после наследования.
> for ($i = mb_strlen($string); $i < $col; $i++) {
> $string = $string . " ";
Есть str_repeat.
> echo $this->padRight("Департамент", $this->col1) .
> $this->padRight("Сотр.", $this->col2) .
Тут у второй и далее строчек стоит добавить отступ, чтобы было видно, что это все одна длинная команда.
Так, для первого раза выглядит хорошо. Ждем антикризисных решений.
Нет, конечно. Формы предназначены для работы с HTML формами. Тебе нужен сериализатор/десериализатор JSON.
Когда у меня была обратная задача - преобразовать объект в JSON - я нашел сериализаторы неудобными. Они, например, по умолчанию экспортируют все поля сущности, и можно помечать те, что экспортирвать не надо. Но это плохой подход, так как легко забыть пометить поле и отдать какие-то приватные данные через API. Должно быть наоборот. Также, они заточены на сценарий, когда тебе надо преобазовать сущность в JSON целиком, но на практике часто нужна только часть полей, плюс какие-то дополниетельные свойства, которые вычисляются через методы. По факту было проще вручную их разобрать.
>>43273
Если поле имеет тип int, то естественно, строки в него записывать нельзя.
>>43270
> $correctText = str_replace(" ", "", $number);
> $correctText = str_replace("-", "", $correctText);
> $correctText = str_replace("(", "", $correctText);
тут стоит использовать единственный preg_replace либо strtr с массивом.
> "(\\+7)"
Скобки не нужны
> (-|\\s|\\(|\\)
Можно было написать короче как "[\\-\\s()]"
А так, верно.
>>43210
Тут не нужно O(N^2), хватит O(N).
> for($i=0;$i<count; $i++){
> $str = $arr[$i][0];
Смотри, как тут много скобок и знаков доллара. Это тяжело читать. Надо использовать в такой ситуации цикл foreach. Если ты изучал другой язык и там был for, то забудь про него, в PHP есть foreach для обхода массива.
Не надо называть переменные $arr, так как это ничего не значит. Называй animals или words.
> $arr[$i][0]
Это не вернет первую букву, а первый байт в слове. Строка в PHP - это набор байт, а не символов и $str[0] не вернет тебе первый символ. Почитай урок https://github.com/codedokode/pasta/blob/master/php/strings-utf8.md
Наконец, твой алгоритм можно упростить. Нужно обойти слова и создать их них массив вида:
[
'а' => [...],
'б' => [...],
...
]
То есть массив, где ключ - это первая буква, а значение - это массив слов на эту букву. Тогда хватит O(N).
Нет, конечно. Формы предназначены для работы с HTML формами. Тебе нужен сериализатор/десериализатор JSON.
Когда у меня была обратная задача - преобразовать объект в JSON - я нашел сериализаторы неудобными. Они, например, по умолчанию экспортируют все поля сущности, и можно помечать те, что экспортирвать не надо. Но это плохой подход, так как легко забыть пометить поле и отдать какие-то приватные данные через API. Должно быть наоборот. Также, они заточены на сценарий, когда тебе надо преобазовать сущность в JSON целиком, но на практике часто нужна только часть полей, плюс какие-то дополниетельные свойства, которые вычисляются через методы. По факту было проще вручную их разобрать.
>>43273
Если поле имеет тип int, то естественно, строки в него записывать нельзя.
>>43270
> $correctText = str_replace(" ", "", $number);
> $correctText = str_replace("-", "", $correctText);
> $correctText = str_replace("(", "", $correctText);
тут стоит использовать единственный preg_replace либо strtr с массивом.
> "(\\+7)"
Скобки не нужны
> (-|\\s|\\(|\\)
Можно было написать короче как "[\\-\\s()]"
А так, верно.
>>43210
Тут не нужно O(N^2), хватит O(N).
> for($i=0;$i<count; $i++){
> $str = $arr[$i][0];
Смотри, как тут много скобок и знаков доллара. Это тяжело читать. Надо использовать в такой ситуации цикл foreach. Если ты изучал другой язык и там был for, то забудь про него, в PHP есть foreach для обхода массива.
Не надо называть переменные $arr, так как это ничего не значит. Называй animals или words.
> $arr[$i][0]
Это не вернет первую букву, а первый байт в слове. Строка в PHP - это набор байт, а не символов и $str[0] не вернет тебе первый символ. Почитай урок https://github.com/codedokode/pasta/blob/master/php/strings-utf8.md
Наконец, твой алгоритм можно упростить. Нужно обойти слова и создать их них массив вида:
[
'а' => [...],
'б' => [...],
...
]
То есть массив, где ключ - это первая буква, а значение - это массив слов на эту букву. Тогда хватит O(N).
Ок, хорошо.
> W5.5: https://ideone.com/BSD1VQ
Верно.
> W5.6 https://ideone.com/zPl90z
Ок, верно, имей в виду, что есть функция array_rand.
> шифр: https://ideone.com/ihyyM1
Правильно.
> Leet: https://ideone.com/wKvLQw
Ок, хорошо.
> Лев толстой: https://ideone.com/xL6nvv
Ок, верно.
> Палиндром: https://repl.it/repls/FrighteningAjarDistributionsoftware
> ($i + 1) * (-1)
Наверно, лучше было написать -($i + 1) или -$i - 1. Минус и плюс в PHP может использоваться не только как бинарный оператор, так и как унарный (с одним аругментом). Например: $y = -$x.
А так, верно.
> iPod: https://ideone.com/yvZESL
Верно, хотя вместо if можно использовать min/max и укоротить код.
>>42416
Если ты изучишь ООП, MVC и фреймворки, то для тебя это будут довольно банальные задачи. Настраиваешь схему базы данных, сущности в той же Доктрине и пишешь контроллеры/сервисы для выполнения действий над ними.
Если нет - то готовые примеры тебе мало помогут. Ну и для форума проще взять готовый движок.
Если тебе так нужны готовые примеры, поищи CMS или движки для этого, но предупреждаю, без базовых знаний там ковыряться очень тяжело.
Ок, хорошо.
> W5.5: https://ideone.com/BSD1VQ
Верно.
> W5.6 https://ideone.com/zPl90z
Ок, верно, имей в виду, что есть функция array_rand.
> шифр: https://ideone.com/ihyyM1
Правильно.
> Leet: https://ideone.com/wKvLQw
Ок, хорошо.
> Лев толстой: https://ideone.com/xL6nvv
Ок, верно.
> Палиндром: https://repl.it/repls/FrighteningAjarDistributionsoftware
> ($i + 1) * (-1)
Наверно, лучше было написать -($i + 1) или -$i - 1. Минус и плюс в PHP может использоваться не только как бинарный оператор, так и как унарный (с одним аругментом). Например: $y = -$x.
А так, верно.
> iPod: https://ideone.com/yvZESL
Верно, хотя вместо if можно использовать min/max и укоротить код.
>>42416
Если ты изучишь ООП, MVC и фреймворки, то для тебя это будут довольно банальные задачи. Настраиваешь схему базы данных, сущности в той же Доктрине и пишешь контроллеры/сервисы для выполнения действий над ними.
Если нет - то готовые примеры тебе мало помогут. Ну и для форума проще взять готовый движок.
Если тебе так нужны готовые примеры, поищи CMS или движки для этого, но предупреждаю, без базовых знаний там ковыряться очень тяжело.
>>41891
> function inclineWord($numbers, $isFemale, $key) {
Мне кажется, было бы лучше передавать не непонятный номер, а варианты формы слов, а функция бы из них выбирала. Так получилась бы универсальная функция, которая работает с любыми словами.
> if (arrayCheck($numbers)) {
Непонятно, зачем это. Не лучше ли обязать передавать в функцию просто число? Зачем туда передавать целый массив? Почему функция выбора формы числа должна ковыряться в каких-то непонятных массивах? Ты явно код разбора массива поместил не туда. Это не задача этой функции.
Вдобавок ты не добавил никаких пояснений перед функцией, в каком формате ей надо передавать массив чисел. Как это понять? Каждая функция в идеале должна быть понятной сама по себе, без разбора остального кода. В реальных приложениях десятки и сотни тысяч строк кода, их все читать просто нет времени.
Код тут должен быть разбит на функции, и по каждой функции должно быть понятно, что она делает, в каком формате принимает входные данные и что выдает на выходе. Каждая функция должна быть понятна без изучения остального кода. Я поймал себя на мысли, что в моем учебнике это не объясняется - надо будет потом дописать и может даже дать примеры разбиения кода на функции.
В функцию inclineWord проще всего просто передавать число, для которого надо подобрать форму слова.
> Соединяет особенные числа
> function combineNumbers($numbers) {
Я абсолютно не понимаю, что делает эта функция. И комментарий тоже ничего не говорит. Код должен быть простой и понятный, а не такой. Подумай, если кто-то работает с твоим кодом, сколько времени придется ему потратить на разбор? Почему он или она должны решать ребусы? Так не должно быть.
> $multiplierAndKey = (count($numbers) == 3) ? [100, 3] : ((count($numbers) == 2) ? (($length == 4) ? [100, 2] : [10, 2]) : [1, 1]);
Это тоже трудно понять. Я смутно догадываюсь, что это как-то связано с сотнями и единицами, но не до конца понимаю.
> for ($key = 0, $min = 0, $max = 3; $max <= 9; $key++, $min += 3, $max += 3) {
Это тоже непонятно.
К сожалению, логику алгоритма я в первого взгляда понять не смог, и увидеть, есть ли в нем ошибки, не могу. Разбирать его по строкам у меня времени, увы, нету. Код должен читаться гораздо легче.
Мне кажется, код надо переделывать почти полностью. Ты можешь сделать как-то по своему, но один из вариантов это:
- функция, которая выбирает подходящую форму слова рубль/тысяча/миллион
- функция, которая получает число от 0 до 999 и возвращает его прописью
- функция, которая разбивает число на группы по 3, используя функции выше, для каждой группы получает слова и склеивает их
Будет гораздо проще.
>>41891
> function inclineWord($numbers, $isFemale, $key) {
Мне кажется, было бы лучше передавать не непонятный номер, а варианты формы слов, а функция бы из них выбирала. Так получилась бы универсальная функция, которая работает с любыми словами.
> if (arrayCheck($numbers)) {
Непонятно, зачем это. Не лучше ли обязать передавать в функцию просто число? Зачем туда передавать целый массив? Почему функция выбора формы числа должна ковыряться в каких-то непонятных массивах? Ты явно код разбора массива поместил не туда. Это не задача этой функции.
Вдобавок ты не добавил никаких пояснений перед функцией, в каком формате ей надо передавать массив чисел. Как это понять? Каждая функция в идеале должна быть понятной сама по себе, без разбора остального кода. В реальных приложениях десятки и сотни тысяч строк кода, их все читать просто нет времени.
Код тут должен быть разбит на функции, и по каждой функции должно быть понятно, что она делает, в каком формате принимает входные данные и что выдает на выходе. Каждая функция должна быть понятна без изучения остального кода. Я поймал себя на мысли, что в моем учебнике это не объясняется - надо будет потом дописать и может даже дать примеры разбиения кода на функции.
В функцию inclineWord проще всего просто передавать число, для которого надо подобрать форму слова.
> Соединяет особенные числа
> function combineNumbers($numbers) {
Я абсолютно не понимаю, что делает эта функция. И комментарий тоже ничего не говорит. Код должен быть простой и понятный, а не такой. Подумай, если кто-то работает с твоим кодом, сколько времени придется ему потратить на разбор? Почему он или она должны решать ребусы? Так не должно быть.
> $multiplierAndKey = (count($numbers) == 3) ? [100, 3] : ((count($numbers) == 2) ? (($length == 4) ? [100, 2] : [10, 2]) : [1, 1]);
Это тоже трудно понять. Я смутно догадываюсь, что это как-то связано с сотнями и единицами, но не до конца понимаю.
> for ($key = 0, $min = 0, $max = 3; $max <= 9; $key++, $min += 3, $max += 3) {
Это тоже непонятно.
К сожалению, логику алгоритма я в первого взгляда понять не смог, и увидеть, есть ли в нем ошибки, не могу. Разбирать его по строкам у меня времени, увы, нету. Код должен читаться гораздо легче.
Мне кажется, код надо переделывать почти полностью. Ты можешь сделать как-то по своему, но один из вариантов это:
- функция, которая выбирает подходящую форму слова рубль/тысяча/миллион
- функция, которая получает число от 0 до 999 и возвращает его прописью
- функция, которая разбивает число на группы по 3, используя функции выше, для каждой группы получает слова и склеивает их
Будет гораздо проще.
>>38591
> ПИШИ ВЕРНО:http://sandbox.onlinephpfunctions.com/code/3c8352717c46dd94d722880076fc352ce3aea067
> function makeFirstLetterUppercase($textArray) {
Логичнее сделать функцию, которая делает что-то одно и обрабатывает одно предложение за раз. И вызывать ее в цикле, ведь цикл у тебя уже есть. А ты зачем-то добавил в нее еще склеивание массива в строку.
> [?]|[!]|[.]
Короче [?!.]
> (\\.+|\\?+|!
А почему после ! не стоит +? А лучше было бы написать как [?!.,;:]+ - чтобы проходили любые сочетания знаков.
Решено верно.
> YODA SPEAK(с сохранением знаков в конце):http://sandbox.onlinephpfunctions.com/code/0a534cec17d6efe3b16c9e23961603f67e07937e
> foreach ($sentencesArray as $sentence) {
Лучше ($sentences as $sentence). Не надо писать array.
> $firstWord = mb_strtolower($firstWord) . mb_substr($lastWord,mb_strlen($lastWord) - 1, 1) . ' ';
> $lastWord = mb_strtoupper(mb_substr($lastWord, 0, 1)) . mb_substr($lastWord, 1, mb_strlen($lastWord) - 2);
Здесь может быть стоило сделать отдельную функцию upcaseFirst, ради читаемости. Ну и отделение знака от предложения стоило сделать отдельно от изменения регистра.
> mb_substr($lastWord,mb_strlen($lastWord) - 1, 1)
Короче mb_substr($lastWord, -1), подробности в мануале.
То, что знаки сохраняются - это хорошо, но конечно код мог бы быть чуть читаемее.
> СУММА ПРОПИСЬЮ:http://sandbox.onlinephpfunctions.com/code/1291210f3e694793e62a1be823935a1dc6df6d69
Неправильно выводит:
> На вашем счету: двадцать один миллионов двадцать две тысяч тридцать три (21022033) рублей.
> $words = array(
> 'рубль',
> 'рубля',
> 'рублей',
лучше сделать 2-мерный массив вида
[
[рубль, рубля, ..],
[тысяча, тысяч, ...],
...
]
Тогда не понадобятся магические цифры вроде $i += 3 или ($i == 6).
Еще вариант в таких случаях - сделать вместо цикла 3 вызова функции:
$part1 = spellNumber($number1, 'рубля', 'рублей', ...);
$part2 = spellNumber($number2, 'тысяча', 'тысячи', ...);
...
> $text .= $spelling[$digit] . ' ';
Часто проще складывать слова в массив, чтобы не мучаться с лишними пробелами.
> if (($number > 9) && ($number % 100 > 9)) {
Первое условие не лишнее?
КАЛЬКУЛЯТОР(с делением и дробями): http://sandbox.onlinephpfunctions.com/code/c631161ae42f91df834bc0202ea3b840eb807a50
А, я-то думал, тут дроби вроде 1/2 + 3/4 = 5/4.
> $number = floatval(strval($number) . $char);
> $number = strval($number) . $char;
Это плохо, что у тебя переменная постоянно меняет тип, так как трудно понять, где она имеет какой тип и как с ней работать. Лучше было копить символы как строку, а только перед выполнением операции преобразовать в число.
Работает верно.
>>38591
> ПИШИ ВЕРНО:http://sandbox.onlinephpfunctions.com/code/3c8352717c46dd94d722880076fc352ce3aea067
> function makeFirstLetterUppercase($textArray) {
Логичнее сделать функцию, которая делает что-то одно и обрабатывает одно предложение за раз. И вызывать ее в цикле, ведь цикл у тебя уже есть. А ты зачем-то добавил в нее еще склеивание массива в строку.
> [?]|[!]|[.]
Короче [?!.]
> (\\.+|\\?+|!
А почему после ! не стоит +? А лучше было бы написать как [?!.,;:]+ - чтобы проходили любые сочетания знаков.
Решено верно.
> YODA SPEAK(с сохранением знаков в конце):http://sandbox.onlinephpfunctions.com/code/0a534cec17d6efe3b16c9e23961603f67e07937e
> foreach ($sentencesArray as $sentence) {
Лучше ($sentences as $sentence). Не надо писать array.
> $firstWord = mb_strtolower($firstWord) . mb_substr($lastWord,mb_strlen($lastWord) - 1, 1) . ' ';
> $lastWord = mb_strtoupper(mb_substr($lastWord, 0, 1)) . mb_substr($lastWord, 1, mb_strlen($lastWord) - 2);
Здесь может быть стоило сделать отдельную функцию upcaseFirst, ради читаемости. Ну и отделение знака от предложения стоило сделать отдельно от изменения регистра.
> mb_substr($lastWord,mb_strlen($lastWord) - 1, 1)
Короче mb_substr($lastWord, -1), подробности в мануале.
То, что знаки сохраняются - это хорошо, но конечно код мог бы быть чуть читаемее.
> СУММА ПРОПИСЬЮ:http://sandbox.onlinephpfunctions.com/code/1291210f3e694793e62a1be823935a1dc6df6d69
Неправильно выводит:
> На вашем счету: двадцать один миллионов двадцать две тысяч тридцать три (21022033) рублей.
> $words = array(
> 'рубль',
> 'рубля',
> 'рублей',
лучше сделать 2-мерный массив вида
[
[рубль, рубля, ..],
[тысяча, тысяч, ...],
...
]
Тогда не понадобятся магические цифры вроде $i += 3 или ($i == 6).
Еще вариант в таких случаях - сделать вместо цикла 3 вызова функции:
$part1 = spellNumber($number1, 'рубля', 'рублей', ...);
$part2 = spellNumber($number2, 'тысяча', 'тысячи', ...);
...
> $text .= $spelling[$digit] . ' ';
Часто проще складывать слова в массив, чтобы не мучаться с лишними пробелами.
> if (($number > 9) && ($number % 100 > 9)) {
Первое условие не лишнее?
КАЛЬКУЛЯТОР(с делением и дробями): http://sandbox.onlinephpfunctions.com/code/c631161ae42f91df834bc0202ea3b840eb807a50
А, я-то думал, тут дроби вроде 1/2 + 3/4 = 5/4.
> $number = floatval(strval($number) . $char);
> $number = strval($number) . $char;
Это плохо, что у тебя переменная постоянно меняет тип, так как трудно понять, где она имеет какой тип и как с ней работать. Лучше было копить символы как строку, а только перед выполнением операции преобразовать в число.
Работает верно.
Процент это 1/1000 числа. Увеличить на 10% - значит поделить число на 100 частей, взять 10 и прибавить к этому же числу. Ну или умножить число на 1,1.
>>41102
Ну попробуй сделать, если хочешь, но я бы делал как можно проще. Если у тебя 1 уник в день, проще генерировать на лету.
> Еще там не совсем тривиальная схема маппинга юри на файлы - всё проклятые "ЧПУ", в ссылках на файлы-то.
Ты делаешь URL = путь к картинке на диске (/images/download/2000x3000/sunshine-123.jpg) и добавляешь в нгинксе правило, что если в папке /images/download/ нет файла, то вызывается PHP вместо отдачи 404.
> Может быть тотальная ассиметрия в запросах (одно оснвное разрешение, какие-то выстрелившие ключи), а моделируется такое барахло обычно с медианными (типо классическое распределение). Хотя может я накручиваю зря.
Ну даже это позволит увидеть какие-то косяки. Плюс, ты можешь смоделировать ведь любое распределение.
>>40997
> w5.1 https://ideone.com/yvZESL
> $creditBalance != 0;
Лучше писать условие $x > 0, чтобы при уходе в минус программа не зациклилась.
Верно, хотя вместо if можно было использовать min/max.
> w5.2 https://ideone.com/k3dgmE
> for ($pct = 10, $sumOfDream = 1000000, $dep = 10000, $clientAge = 16; ; $dep += ($dep / 100) * 10, $clientAge++)
Не надо писать такую длинную шапку цикла, ее трудно читать. Стоит оставить вверху только 1 переменную.
Так, верно.
> w5.3 https://ideone.com/4GtuH3
Верно.
> w5.4 https://ideone.com/X1glvK
Правильно.
Процент это 1/1000 числа. Увеличить на 10% - значит поделить число на 100 частей, взять 10 и прибавить к этому же числу. Ну или умножить число на 1,1.
>>41102
Ну попробуй сделать, если хочешь, но я бы делал как можно проще. Если у тебя 1 уник в день, проще генерировать на лету.
> Еще там не совсем тривиальная схема маппинга юри на файлы - всё проклятые "ЧПУ", в ссылках на файлы-то.
Ты делаешь URL = путь к картинке на диске (/images/download/2000x3000/sunshine-123.jpg) и добавляешь в нгинксе правило, что если в папке /images/download/ нет файла, то вызывается PHP вместо отдачи 404.
> Может быть тотальная ассиметрия в запросах (одно оснвное разрешение, какие-то выстрелившие ключи), а моделируется такое барахло обычно с медианными (типо классическое распределение). Хотя может я накручиваю зря.
Ну даже это позволит увидеть какие-то косяки. Плюс, ты можешь смоделировать ведь любое распределение.
>>40997
> w5.1 https://ideone.com/yvZESL
> $creditBalance != 0;
Лучше писать условие $x > 0, чтобы при уходе в минус программа не зациклилась.
Верно, хотя вместо if можно было использовать min/max.
> w5.2 https://ideone.com/k3dgmE
> for ($pct = 10, $sumOfDream = 1000000, $dep = 10000, $clientAge = 16; ; $dep += ($dep / 100) * 10, $clientAge++)
Не надо писать такую длинную шапку цикла, ее трудно читать. Стоит оставить вверху только 1 переменную.
Так, верно.
> w5.3 https://ideone.com/4GtuH3
Верно.
> w5.4 https://ideone.com/X1glvK
Правильно.
А что ето такое?
OP, есть ещё вопрос здесь, который я так и не понял.
Изначально в дочерних классах работника (менеджер, инженер, ..) свойство $rate было запривачено и когда я вызывал метод
getSalaryEmployee(), то пхп выдавал ошибку, $rate запривачен и доступа нет. Но ведь я вызываю этот метод в том классе, где заприваченое свойство и находится, manager наследовал метод же, он в нем вызываться и должен и брать спокойно $rate. Пришлось ставить protected.
Приватный метод принадлежит классу и не виден в других классах, даже в наследниках или предках.
"Видимость" определяется тем, где в коде расположен метод. Не важно, откуда он вызван. Чтобы обращаться к приватному свойству, код должен быть расположен в пределах того же самого класса, между class { и }. Это так сделано неспроста, есть же принцип разделения ответственности. Представь, что каждый класс пишет отдельный человек. Приватные поля и методы принадлежат только этому человеку и никто другой не может ими пользоваться. Только он их видит и может вызывать. А, например, protected поля принадлежат автору класса, но он делится доступом с владельцами классов-наследников (но не предков).
Класс-наследник не включает в себя содержимое предка, это все же отдельные классы, хоть и связанные довольно тесным отношением наследования.
Добавлю еще, что в предке и наследнике могут быть приватные поля с одним и тем же именем, и это будет 2 разных поля. Если ты представишь мою аналогию, что каждый класс пишет отдельный человек, то поймешь, почему это работает: потому что об этих полях знает только их создатель, а другие их даже не видят и потому никакого конфликта нет.
вместо того, чтобы изучить конкретные технологии под конкретные вакансии и устоится наконец на работу вы блять читаете Мэтт Зандстра и решаете задачи типа ебаного калькулятора
А что ты предлагаешь конкретно?
А вообще зачем годами учить это? Я 2 недели как начал учить, уже понял ооп более менее с абстрактными классами и интерфейсами, решил вот задачу опа на ооп. Следующая будет список студентов, которая и представляет собой пример реальной задачи-формошлепства.
>Когда у меня была обратная задача - преобразовать объект в JSON - я нашел сериализаторы неудобными. Они, например, по умолчанию экспортируют все поля сущности, и можно помечать те, что экспортирвать не надо. Но это плохой подход, так как легко забыть пометить поле и отдать какие-то приватные данные через API. Должно быть наоборот. Также, они заточены на сценарий, когда тебе надо преобазовать сущность в JSON целиком, но на практике часто нужна только часть полей, плюс какие-то дополниетельные свойства, которые вычисляются через методы. По факту было проще вручную их разобрать.
Ну у меня и такая задача тоже есть. Взять тот же тестхаб, есть тест как сущность для админа или создателя (с указанием правильных ответов) и тест как сущность для участвующего или студента (без указания правильных ответов). Я думаю просто потом по группам раскидать.
Я еще встречал в ларавел вот такую штуку:
https://fractal.thephpleague.com/transformers/
она вроде бы удобная, но я её не применял на практике. Можно ведь самому сделать некий сервис, который будет принимать параметром сущность, и возвращать массив с данными, которые уже нужно преобразовать в джсон, то есть то что ты и говорил, мы не добавляем в "черный" список например пароль, а добавляем все кроем пароля в "белый" список
>addEmployee(Employee $e)
ОП, извини, что вопросов много задают тупых, но никак не могу вкурить, что ты имел ввиду под этим.
Очень приятно, что кто-то проверяет мои поделки. Большое человеческое спасибо!
Переделал и максимально закомментировал код. Надеюсь я исправился, пожалуйста оцените :3
https://ideone.com/QKJaY8
Какая-то устаревшая информация по сериалайзеру.
> Они, например, по умолчанию экспортируют все поля сущности, и можно помечать те, что экспортирвать не надо.
Группы в сериалайзере были давным давно: https://symfony.com/blog/new-in-symfony-2-7-serialization-groups
А до этого было принятно использовать JMS Serializer c их @ExclusionPolicy и @Expose: https://jmsyst.com/libs/serializer/master/cookbook/exclusion_strategies
> Также, они заточены на сценарий, когда тебе надо преобазовать сущность в JSON целиком, но на практике часто нужна только часть полей, плюс какие-то дополниетельные свойства, которые вычисляются через методы.
Можно сделать свой нормалайзер и вычислять там то, что нужно: -
- http://mickadoo.github.io/symfony/2016/05/18/custom-symfony-normalizers.html
- https://thomas.jarrand.fr/blog/serialization/
>>44310
> Можно ведь самому сделать некий сервис, который будет принимать параметром сущность, и возвращать массив с данными
В терминах symfony/serializer это называется нормализация и делается через кастомные нормалайзеры (ссылки выше).
Fractal тоже норм.
>>44073
> Дрочите всякие инкапсуляции, абстрактные методы, интерфейсы,
Всё правильно делают, это позволит им устроится в хорошую контору с толковыми спецами и интересным стеком.
В @media (max-width: 1200px) убрать флоаты и сделать маргин-авто на блоках.
Не использовать флоаты, а использовать флексы.
Сделать блоки инлайн-блоками, а у родителя сделать центрование текста.
Использовать css column (require прямые руки).
Спасибо.
Виктор Зинченко набери в ютабе, там чувак сначала пилит инет магаз, потом типа мини-инстаграмм
Звук ужасен конечно. А так спасибо.
640x640, 0:18
1. Стоит ли вкатываться?
2. Сколько платят человеку, который уже может приступить к работе за еду?
3. Сильно тяжёло?
4. Троечник-гуманитарий осилит?
Заранее спасибо всем отписавшимся.
Очевидно последнюю
Идешь на фреланс и вбиваешь PHP, все просто, а там далее думаешь сам.
просто, на хостах часто видел 5.7. А так понятно, что надо разбираться с последней.
книжки и практика. html не такое уж и сложное нечто. Верстка разве что.
https://t-do.ru/joinchat/Eh8Gzg94NT7LDHFpw4iZ7g
Присоединяйся няша, мы тебя ждем!
https://ideone.com/ygXoIg
Твоя мамка путешествовала по индии, до твоего рождения?
Я не понял.
Тебе нужна помощь как это короче решить с меньшей вычислительной сложностью или ты просто шутки ради код запостил?
Сначала сделать валидацию для всех значений questions,answers вложенным циклом, а затем уже записывать значения в БД еще одним вложенным циклом, я правильно понимаю?
шутки ради код запостил
Для этого тебе надо понять идею промисов. Промис представляет собой результат будущего вычисления. Промисы удобны тем, что из них можно делать цепочки и более сложные графы. Например:
A --> B --> C
Так я условно нарисовал промис A, из которого мы преобразованием (then()) получаем промис B, а из того - промис C. Будет ли преобразование удачным или нет - в любом случае промис C будет либо разрезолвлен, либо отрежекчен. Преобразование - это функция, которая возвращает либо результат, либо промис с будущим результатом.
Там можно делать более сложные конструкции, ветвить и объединять цепочки вычислений, но нам это пока не надо.
Теперь подумаем, как это применить к твоей задаче. К сожалению, ты не написал, что за библиотеку ты используешь и как работает метод transaction(). Я предположу, что это WebSQL, а там метод t.executeSql() добавляет запрос в очередь на выполнение (они выполняются по одному). Описание https://www.w3.org/TR/webdatabase/#sqltransactioncallback
Проблема, которая есть в твоем коде - что ты завернул в промис вызов transaction(). Не надо этого делать, он должен быть вне промиса, а в промис надо обернуть только вызов executeSql:
function runQuery(t: SQLTransaction, q: string, args: []): Promise<result> {
return new Promise(...);
}
Эта функция добавляет запрос в транзакцию и возвращает промис с результатом или ошибкой.
Остается только придумать, как сделать цепочку из запросов? Очевидно, путем преобразования результата первого запроса с помощью then():
var r1 = runQuery(t, ....);
var r2 = r1.then(function (data) {
//... обработка data
return runQuery(t, ...);
});
var r3 = r2.then(...);
Вот так мы и получаем выполнение нескольких зависящих друг от друга запросов. Когда первый запрос выполнится успешно, r1 разрезолвится и будет вызван коллбек внутри r1.then. Он добавит в очередь второй SQL запрос и вернет промис с результатом. r2 разрезолвится как только будет разрезолвлен этот промис.
Если же r1 будет отрежекчен, то r2 и r3 тоже отрежектятся, другие запросы выполняться не будут.
Разумеется метод transaction можно точно так же обернуть в промис:
function runTransaction(callback) {
return new Promise(...) {
database.transaction(callback, function (..) { resolve(); }, function { reject(); } );
}
}
Но мне не нравится идея передавать коллбек, я вместо этого напишу функцию, которая возвращает SQLTransaction:
function getTransaction(): Promise<SQLTransaction> {
return new Promise(function (res, rej) {
database.transaction(
function (t) { res(t); },
function (e) { rej(e); }
);
});
}
Его можно использовать для построения такой цепочки:
получить транзакцию -> выполнить 1-й запрос -> выполнить 2-й запрос
var tr = getTransaction();
tr.then(function (t) {
return [t, runQuery(t, sql1...)];
}).then(function ([t, data]) {
return [t, runQuery(t, sql2...)];
});
Здесь получается некоторая корявость из-за необходимости передавать пару [транзакция, результат]. Это можно решить, если научить функцию runQuery принимать промис транзакции вместо транзакции:
var t = getTransaction();
var r1 = runQuery(t, ....);
var r2 = r1.then(function (data) {
//... обработка data
return runQuery(t, ...);
});
var r3 = r2.then(...);
Единственное, что меня беспокоит, это вот эта строчка из спецификации (в 4.3.2 Processing model):
> While there are any statements queued up in the transaction, perform the following steps for each queued up statement in the transaction, oldest first.
Не получится ли так, что когда один запрос будет выполнен, а второй еще не добавлен в очередь, что транзакция закончится?
Задавай вопросы, если что-то непонятно. Тема промисов сложная, и надо с ней разобраться.
Для этого тебе надо понять идею промисов. Промис представляет собой результат будущего вычисления. Промисы удобны тем, что из них можно делать цепочки и более сложные графы. Например:
A --> B --> C
Так я условно нарисовал промис A, из которого мы преобразованием (then()) получаем промис B, а из того - промис C. Будет ли преобразование удачным или нет - в любом случае промис C будет либо разрезолвлен, либо отрежекчен. Преобразование - это функция, которая возвращает либо результат, либо промис с будущим результатом.
Там можно делать более сложные конструкции, ветвить и объединять цепочки вычислений, но нам это пока не надо.
Теперь подумаем, как это применить к твоей задаче. К сожалению, ты не написал, что за библиотеку ты используешь и как работает метод transaction(). Я предположу, что это WebSQL, а там метод t.executeSql() добавляет запрос в очередь на выполнение (они выполняются по одному). Описание https://www.w3.org/TR/webdatabase/#sqltransactioncallback
Проблема, которая есть в твоем коде - что ты завернул в промис вызов transaction(). Не надо этого делать, он должен быть вне промиса, а в промис надо обернуть только вызов executeSql:
function runQuery(t: SQLTransaction, q: string, args: []): Promise<result> {
return new Promise(...);
}
Эта функция добавляет запрос в транзакцию и возвращает промис с результатом или ошибкой.
Остается только придумать, как сделать цепочку из запросов? Очевидно, путем преобразования результата первого запроса с помощью then():
var r1 = runQuery(t, ....);
var r2 = r1.then(function (data) {
//... обработка data
return runQuery(t, ...);
});
var r3 = r2.then(...);
Вот так мы и получаем выполнение нескольких зависящих друг от друга запросов. Когда первый запрос выполнится успешно, r1 разрезолвится и будет вызван коллбек внутри r1.then. Он добавит в очередь второй SQL запрос и вернет промис с результатом. r2 разрезолвится как только будет разрезолвлен этот промис.
Если же r1 будет отрежекчен, то r2 и r3 тоже отрежектятся, другие запросы выполняться не будут.
Разумеется метод transaction можно точно так же обернуть в промис:
function runTransaction(callback) {
return new Promise(...) {
database.transaction(callback, function (..) { resolve(); }, function { reject(); } );
}
}
Но мне не нравится идея передавать коллбек, я вместо этого напишу функцию, которая возвращает SQLTransaction:
function getTransaction(): Promise<SQLTransaction> {
return new Promise(function (res, rej) {
database.transaction(
function (t) { res(t); },
function (e) { rej(e); }
);
});
}
Его можно использовать для построения такой цепочки:
получить транзакцию -> выполнить 1-й запрос -> выполнить 2-й запрос
var tr = getTransaction();
tr.then(function (t) {
return [t, runQuery(t, sql1...)];
}).then(function ([t, data]) {
return [t, runQuery(t, sql2...)];
});
Здесь получается некоторая корявость из-за необходимости передавать пару [транзакция, результат]. Это можно решить, если научить функцию runQuery принимать промис транзакции вместо транзакции:
var t = getTransaction();
var r1 = runQuery(t, ....);
var r2 = r1.then(function (data) {
//... обработка data
return runQuery(t, ...);
});
var r3 = r2.then(...);
Единственное, что меня беспокоит, это вот эта строчка из спецификации (в 4.3.2 Processing model):
> While there are any statements queued up in the transaction, perform the following steps for each queued up statement in the transaction, oldest first.
Не получится ли так, что когда один запрос будет выполнен, а второй еще не добавлен в очередь, что транзакция закончится?
Задавай вопросы, если что-то непонятно. Тема промисов сложная, и надо с ней разобраться.
Да, сейчас пытаюсь разобраться с TypeScript и WebSQL (все мечтаю первым сделать твою задачу на SPA). WebSQL хоть и мертвая, но использует синтаксис SQLite, что не будет вредно изучить.
Сейчас уже спать хочу, но вот что сегодня нашел:
https://github.com/oskarer/websql-promisified
https://github.com/oskarer/websql-promisified/blob/master/src/index.js
Не могу понять что тут вообще происходит, но использование, согласись, лаконичное (вот прям идеальное для меня где async await).
Уже в голове промис промисом погоняет.
Спасибо что отвечаешь всегда на мои бешеные вопросы :3
А он тебе точно нужен? Или тебя просто будет согревать мысль, что у твоего бати большой хер, даже если у тебя самого мелкий стручок?
Есть форма, которой можно добавлять поля.
Как сделать чтобы в коде:
<input type="radio" name="correct[]" value=" ">
в значие value попадал ключ массива correct
<input type="radio" name="correct[1]" value="1">
<input type="radio" name="correct[2]" value="2">
<input type="radio" name="correct[3]" value="3">
Можно сделать массив на i элементов
Которые будут генерировать эти инпуты
Типо:
For ($i = 0; $i < correct.size(); $++)
хтмл.create = "<input name='correct [$i]'>"
написал с телефона
Да
https://ideone.com/Aa5oVU
Ну давай разберем по частям все тобою написанное.
Задача функций - избегать дублирования кода. У тебя один и тот же кусок кода 3 раза. А если банков будет 50 штук? Это нужно собрать в одну функцию.
Имена функциям принято начинать с глагола. Например calculateTotalAmount() и т.п.
>Можно ли модифицировать код так, чтобы каждый раз не передавать в функцию идентичные аргументы $credit и $pay???
Можно. Плохой вариант: использовать глобальные переменные (https://www.w3schools.com/php/php_superglobals.asp). За это бьют по рукам.
Вариант получше: использовать значения по умолчанию.
function doSomething($var = 100) {}
В этой задаче так делать смысла я не вижу.
а подскажешь сервис где можно найти крестьянина который бы реализовал это в жзн
>>44539
Переосмысление задачи "сумма прописью", алгоритм работы множителя расписан в более понятных if - else.
Пожалуйста, проверьте.
https://ideone.com/ycLXlo
Хочу джсон в объект трансформировать, ошибки обратно отправить если есть, этот сериалайзер проверяет тип поля, тип вроде бы он забирает из аннотаций для доктрин, выбрасывает исключение если тип неправильный, искал пол часа как отключить проверку типа, вроде бы нашел. Но суть в том что он все равно вызывает свой validateAndDenormalize метод, в конце которого просто есть проверка на этот ключ(на скрине) в массиве, и исключение игнорируется. После всего этого я еще раз делаю проверку через симфони валидатор, собираю ошибки если есть и отправляю ответ.
Это же вроде ОЧЕНЬ тупо, зачем делать валидацию клиентского инпута в сериалайзере, у всех же и так стоят свои правила типа пароль не меньше 6 символов, которые будут прогоняться через другой валидатор.
Или просто при исключении отправлять плохой ответ, и не париться? Это при условии что на клиенте у меня джаваскрипт не даст ничего плохого отправить 100%
Я почитал тут (ты не написал, что ты используешь, потому я предположил что этот компонент) https://symfony.com/doc/current/components/serializer.html и не вижу там каких-то упоминаний валидации.
> Это же вроде ОЧЕНЬ тупо, зачем делать валидацию клиентского инпута в сериалайзере
А надо разделять валидацию и проверку типов. Валидация - это проверка данных, которые имеют нужный тип (строка), но не соответствуют бизнес-правилам (вроде пароль должен быть не короче 6 символов). А проверка типов нужна хотя бы для того, чтобы десериалайзер при вызове метода:
public function setName(string $name)
не словил бы ошибку. Ну и что бы у поля с типом
... @var string ...
private $name;
аннотация бы соблюдалась.
Естественно, при десериализации типы должны проверяться. Чтобы соблюдался контроль типов и в поле не могли оказаться данные не предусмотренного типа. А валидацией занимается валидатор, позже. И вполне возможно, что проверки типов он как раз не делает.
Кстати, порылся в исходниках сериализатора и узнал про компонент https://symfony.com/doc/current/components/property_info.html где и описано, как извлекается информация о типах (если что-то там сложно и непонятно, можешь спросить).
Вот место в исходниках: https://github.com/symfony/serializer/blob/master/Normalizer/AbstractObjectNormalizer.php#L295
Метод validateAndDenormalize() проверяет соответствие переданного значения типу поля в классе (тип определяется с помощью PropertyInfo) и выбрасывает исключение при ошибке. А при успехе - возвращает это значение (иногда слегка подправленное, например int может автоматически конвертироваться в float).
Тебе не надо отключать проверку типов. Так как значение нестандартного типа может вызвать ошибки в самых разных местах кода. А может даже уязвимости. Если ты хочешь обрабатывать ошибку типа, ты можешь ловить NotNormalizableValueException и что-то делать, например, выдавать ошибку HTTP 4xx (предоставлены некорректные JSON-данные).
То есть десериалайзер и должен проверять типы, так и задумано, и надо этим пользоваться.
> Это при условии что на клиенте у меня джаваскрипт не даст ничего плохого отправить 100%
Злоумышленника это не остановит. Он может слать данные напрямую на сервер без джаваскрипта. А ты зачем-то отключаешь защиту от этого.
Я почитал тут (ты не написал, что ты используешь, потому я предположил что этот компонент) https://symfony.com/doc/current/components/serializer.html и не вижу там каких-то упоминаний валидации.
> Это же вроде ОЧЕНЬ тупо, зачем делать валидацию клиентского инпута в сериалайзере
А надо разделять валидацию и проверку типов. Валидация - это проверка данных, которые имеют нужный тип (строка), но не соответствуют бизнес-правилам (вроде пароль должен быть не короче 6 символов). А проверка типов нужна хотя бы для того, чтобы десериалайзер при вызове метода:
public function setName(string $name)
не словил бы ошибку. Ну и что бы у поля с типом
... @var string ...
private $name;
аннотация бы соблюдалась.
Естественно, при десериализации типы должны проверяться. Чтобы соблюдался контроль типов и в поле не могли оказаться данные не предусмотренного типа. А валидацией занимается валидатор, позже. И вполне возможно, что проверки типов он как раз не делает.
Кстати, порылся в исходниках сериализатора и узнал про компонент https://symfony.com/doc/current/components/property_info.html где и описано, как извлекается информация о типах (если что-то там сложно и непонятно, можешь спросить).
Вот место в исходниках: https://github.com/symfony/serializer/blob/master/Normalizer/AbstractObjectNormalizer.php#L295
Метод validateAndDenormalize() проверяет соответствие переданного значения типу поля в классе (тип определяется с помощью PropertyInfo) и выбрасывает исключение при ошибке. А при успехе - возвращает это значение (иногда слегка подправленное, например int может автоматически конвертироваться в float).
Тебе не надо отключать проверку типов. Так как значение нестандартного типа может вызвать ошибки в самых разных местах кода. А может даже уязвимости. Если ты хочешь обрабатывать ошибку типа, ты можешь ловить NotNormalizableValueException и что-то делать, например, выдавать ошибку HTTP 4xx (предоставлены некорректные JSON-данные).
То есть десериалайзер и должен проверять типы, так и задумано, и надо этим пользоваться.
> Это при условии что на клиенте у меня джаваскрипт не даст ничего плохого отправить 100%
Злоумышленника это не остановит. Он может слать данные напрямую на сервер без джаваскрипта. А ты зачем-то отключаешь защиту от этого.
У меня есть класс для работы с конфигом, класс приложения с инициализацией сессии, конфига и бд, и автолоад.
Я подключаю автолоад, он загружает классы, в том числе и конфиг. Потом я подключаю отдельно приложение - оно инициализирует сессию и... вылетает при попытке инициализации конфига (Uncaught Error: Class 'classes\Config' not found). Но автолоад же уже подключил этот класс!
Как оно вообще должно работать?
Бамп.
Я ещё подолбился и таки нашёл проблему. Очень странные ошибки, лучше бы самостоятельно с вами аутировал, а не с этими курсами платными.
Курс профит?
>Злоумышленника это не остановит. Он может слать данные напрямую на сервер без джаваскрипта. А ты зачем-то отключаешь защиту от этого.
Я думал проверять тип валидатором, там же есть Assert\Type() класс для этих вещей, а у валидатора еще можно ошибки отправить со своим сообщением. А с сериалайзером мне остается только ловить исключение и отправлять например 422 код, потому что сообщение исключения тоже особо смысла не несет для пользователя. Можно представить что кто-то сделает мобильное приложение и будет регистрировать созданные там тесты на моем сайте через какое-то апи, и например у них нет клиентской валидации, я поэтому и хотел отправлять нормально ошибки независимо от фронтэнда. Но я сейчас так подумал что мне это не особо нужно, у меня всего пару аякс запросов а все остальное это шаблоны на сервере.
Сообщения нужны только для ошибок пользователя, если он ввел что-то неправильно.
По идее фронтенд должен слать данные корректной структуры и типа и ошибок проверки типа не должно быть. Они могут появиться только если в коде где-то ошибка (бекенд обновился, а фронтенд шлет данные в старом формате) или кто-то специально передает некорректные данные. Потому детальные сообщения для них не нужны.
> Можно представить что кто-то сделает мобильное приложение и будет регистрировать созданные там тесты на моем сайте через какое-то апи, и например у них нет клиентской валидации, я поэтому и хотел отправлять нормально ошибки независимо от фронтэнда.
Тогда можно извлекать подробности ошибки из исключения которое бросает десериалайзер и возвращать их. Вот это исключение:
https://github.com/symfony/serializer/blob/master/Normalizer/AbstractObjectNormalizer.php#L357
throw new NotNormalizableValueException(sprintf('The type of the "%s" attribute for class "%s" must be one of "%s" ("%s" given).', $attribute, $currentClass, implode('", "', array_keys($expectedTypes)), \gettype($data)));
Также, если ты будешь делать АПИ, можно еще как-то сгенерировать JSON schema и проверять приходящие данные по ней. И даже выложить эту схему, чтобы пользователи АПИ могли самостоятельно по ней проверять данные. Если ты будешь документировать свое АПИ с помощью Swagger, то там как раз нужно описать структуру данных с помощью схемы.
Для этого решил создать клоны вектора:
$companyClone = clone $vector;
В родительском классе прописал это, чтобы и департаменты внутри компании тоже клонировались:
public function __clone()
{
foreach ($this->departaments as $departament) {
$departament = clone $departament;
}
}
Но при проверке оказалось, что клонировался только объект компания, а департаменты так и остались ссылкой на одни объекты, что я не так делаю?
Ты клонировал департамент, но клон никуда не сохранил. В поле осталась ссылка на старый департамент.
Вроде разобрался уже, надо создать новый массив пустой, заполнить его клонами департаментов, а потом присвоить этот массив массиву департаментов. Для работников также.
Ща пройду ваш учебник, ебну задачи на фреймворке и вкачусь в IT НАХОЙ. Сначала на буду 120 к в мемсяц иметь, а потом амазон открою. Вот так вот.
https://www.youtube.com/watch?v=WemFf9i2JEo
>ебну задачи и вкачусь в IT НАХОЙ
>Сначала на буду 120 к в мемсяц иметь
Не, братан, это не так работает. Сначала тебя жизнь головой об косяк ёбнет. А потом как начнёшь что-то понимать в этой сфере, начнёшь зарабатывать свои первые 500 баксов в месяц.
анончик, ты вроде уже прошел период зарабатывания 500 баксов в месяц. подскажи, сколько тебе времени понадобилось чтобы на программировании зарабатывать первые деньги?
>Учи HTML/CSS и SQL, PDO, хотя бы основы
По поводу SQL и PDO - это где уроки? Или типа самому читнуть надо? Если самому, посоветуйте материал с расчетом на выполнение более серьезных задач, ну то есть когда учебник прошел.
И да, кстати, пофиксите дизайн сайта, он вообще нихуя не респонсив, с ноута, а тем паче мобилы сидеть НЕПРИЯТНО.
Ты прав, анончик. У меня уже наверно полгода лежит адаптивная верстка с выезжающим меню, которую я начал делать и даже успел лично протестировать на смартфоне и планшете. Но, увы, все руки не доходят доделать ее и выложить для тестирования анонами.
В уроке про работу со строками вроде есть ответ: https://github.com/codedokode/pasta/blob/master/php/strings-utf8.md
Через mb_substr работает нормально. Но почему по индексу не работает? Мне че каждый раз функцию вызывать? Это ж пиздец! Это точно должно так работать?
Если у тебя не работает, то ты русские буквы в строку запихал.
Для начала валидирую код страны пока что в виде 8 онли + 9 и 2 любых на выбор:
"/89[0-9]{2}/u"
Однако он мне признает валидным номер типа 89117772018.
Як? Я ж укозал 2 повторения!
Все дошло, это типа два И БОЛЕЕ, ну логика.
Твоя регулярка не проверяет, что строка целиком соответствует выражению. Она лишь ищет, есть ли в в строке такое выражение или нет.
Няши привет. Никогда не упарывался по бекенду, но тут срочненько нужно написать подключение к бд и обернуть это http get запросом, чтобы это потом каким-то способом закинуть вообще не понимаю как это делать на простой сервак и дергать данные.
Сам джун и знаком с кодингом и работой с sql. По синтаксису php разберусь в работе, так вот, с какой либой это максимально просто и без напрягов сделать? Расширять вообще не планирую, ну мб еще пост запросы прикрутить и т.д.
pdo
>строка целиком соответствует выражению
А как мне проверить строгое соответствие? Крышечкой вначале и долларом в конце, да?
https://github.com/Awesome-Kirill/fukingStudent
>Сколько пилил её?
Больше месяца. Это моя 3 попытка довести задачу до конца.
>И что до неё выучил?
Учил много чего. Но учить !== уметь. Я хронический вкатвальщик-прокрастинатор.Уже год учу.
Крч не ровняйся на меня
Тот же tampermonkey опенсорсный: https://github.com/Tampermonkey/tampermonkey
Ставить юзерскрипты можно в один клик.
А чтобы работали юзерскрипты, расширения устанавливать не надо? Более того, мое расширение не требует фоновой страницы и не запускается, пока ты не зайдешь в профиль.
Если у тебя есть идея, как можно поменять код, чтобы он работал и в составе расширения, и как юзерскрипт, то можешь написать. Я не пользуюсь юзерскриптами и не знаю, как они пишутся.
Не та картинка
http://sandbox.onlinephpfunctions.com/code/b030e2374845be468830adbc0958f58023b83028
Юзают те, кому и так норм. Ты удивишься, но ещё прилично сайтов, особенно в США, где можно встретить такую эзотерику как, например, mootools.
А вот по пхп вакансий и правда полно.
Подскажите какой фрэймворк мне использовать, который максимум быстро позволит делать лэндинги, сайты-визитки и простенькие приложения с логикой?
%%опять же я мог бы бы делать это на node/express, но зачем это мухосранскому заказчику?
В пхп основной подход - это шаблонизация.
А еще, я как человек который хочет в вэб - чувстую себя однобоко без знания пхп. Может я на нем работать и не буду, но по моему php + js разработчик занть обязан.
Допустим в laravel уже встроен функционал к примеру админской панели? Интрефейсы к бд? Ну и вообще всякие плюшки?
В node все это счастье ищется и впихивается самостоятельно (что в принципе не сложно, но у новичка разбегутся глаза от обилия вариантов).
>>В пхп основной подход - это шаблонизация.
Не правильно сформулировал
В пхп основной подход - это шаблонизация? Я о среднегородском уровне.
В мухах популярен Yii2.
http://sandbox.onlinephpfunctions.com/code/13dd69c45baf6239448f6cf4f104365e29663936
Привет, ОП!
Я правильно решил эту мини-задачку из ООПа?
Нашёл чей «курс» обсуждать итт. Конечно устарел его курс, то что он релизнут в 2016 не говорит о его актуальности.
Я просто вкатывальщик, и совсем не знаю, какие курсы хорошие, а какие плохие. Можешь ли посоветовать хорошие курсы, анон?
Курс профит. В чате треда, человек посмотревший оба курса, говорит что этот на порядок круче.
> Можешь ли посоветовать хорошие курсы, анон?
ШАПКУ ТРЕДА НЕ ЧИТАЙ
@
ВОПРОСЫ ЗАДАВАЙ
Для таких как ты @нон писал шапку, старался, а ты - мудло ленивое, даже не в состоянии шапку осилить.
нет-нет, я прочитал всю шапку и даже весь учебник милейшего человека - ОПа, но может я в глаза ебусь, но инфы по поводу курсов я там не вижу.
В учебнике опа для новичка как раз все что нужно. Дальше тебе нербходимо определиться - либо ты испольщуешь фреймворки, либо сам разрабатываешь фреймворки, лучше первый вариант для начала выбери, со временем, возможно, но маловероятно, дойдешь до второго варианта.
Хорошо, спасибо, анон!!
Чем ярче и пестрее креативят зазывая на работу — там тотальная пизда. Если есть время на такой пиздец, значит работы будет очень много, а платить за неё будут очень мало. Овердохуя дружелюбия, все такие без пафоса.
Я рабоал в похожих местах и это пизда просто.
Не слушай этого
>>48586
>>48594
петуха ебаного. Тебе не нужен пробел после <<<DIO_BRANDO — это heredoc называется. Есть nowdoc — <<<'DIO_BRANDO'
Подробнее про строки в мане http://php.net/manual/ru/language.types.string.php#language.types.string.syntax.nowdoc
Нашёл. Проблема в отступах, которые я ставил.
Ну хуй знает. Вроде по-дефолту OpenSans.
у меня например так работает:
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
из документации
Note: Don't use php_value to set boolean values. php_flag (see below) should be used instead.
Может так попробовать?
У тебя нет ошибки. Поэтому нихуя и не выводится. Можешь посмотреть выхлоп в рнр консоле.
Всмысле блять нет? А где $user объявляется? PHP хоть и не строго типизированный, но объявить-то переменную нужно, а тут она не объявлена.
Я и в php.ini эти настроечки на вывод сменил, но чот нифига.
Есть тут ошибка, хуя ты напердолил, довен
массивы это так, мусор завалявшийся
Заебись, завелось вроде.
Если есть желающие позаниматься вместе, проверить домашку, обсудить какие-то вещи типа вката на позицию июня - рад вас видеть, пилите свою тележку.
Ах, да. Если есть анон с навыком дизайна и верстки, пусть даже особо не чухающий в PHP, но который хочет этому научиться параллельно запиливаю какой-нибудь проектик на ОБЩЕСТВЕННЫХ НАЧАЛАХ (с прицелом на озвездение своего гитхаба) - вообще заебись.
Итак! Код этого мастера >>46359 с гитхаба мне не понравился.
Перечитал несколько раз спецификацию и твой пост и получил пикрелейтед реализацию. Довольно неплохо выглядит. Если дальше подумать, с промисами можно было бы даже что-то типа микро-ORM написать, хотя я хочу остановиться на TDG-паттерне. Еще раз спасибо за детальное разъяснение.
Promise и async/await - checked!
Я просто мимо проходил и не знаю, что у тебя за задача, но для проверки балансировки скобок обычно используют стек. Стек - это структура данных, которая хранит цепочку значений, и их можно добавлять или вынимать из стека только с одной стороны. То есть, для стека определены две операции:
- добавить значение в конец списка
- снять значение из конца списка
И если у тебя есть задача проверить баланс скобок в выражении вроде [({}, {}), {}] то она решается стеком. Ты проходишь по строке и, встречая открывающую скобку, кладешь ее в стек. А когда встречаешь закрывающую, вынимаешь значение из стека и проверяешь, что открывающая скобка из стека соответствует встреченной в строке закрывающей.
Насчет дизайна - если не найдешь анона-фронтендщика, ты можешь сделать дизайн на CSS-фреймворке Bootstrap - там уже есть набор готовых стилей для форм, таблиц, создания колонок, и тд.
>>49334
А мне не очень нравится твой код. Вот, что не так:
- ты используешь try/catch в том же месте, где выбрасывается исключение. Это не имеет никакого смысла. try/catch предназначен для ловли исключения при вызове какой-то функции, то есть:
try {
something();
}
В такой ситуации try не нужен:
try {
...thow new Error()...
}
- идея пропускать не сработавшие запросы выглядит как минимум странно. Исключение может быть выброшено по многим причинам: соединение с БД разорвалось, ошибка в тексте запроса, проблемы на стороне БД, нарушение внешних ключей при вставке. Очевидно, что разные случаи требуют разной реакции и объединять их вместе нельзя. Более того, в 99% случаев никакой необходимости обрабатывать такие ошибки нет, а нужно аварийно завершать программу и исправлять ее код.
- ты смешиваешь await и коллбеки, говорящие о готовности (в вызове transaction), что тоже странно выглядит, так как коллбеки и await - это 2 разных подхода к написанию асинхронного кода. Логичнее было бы видеть код в стиле:
a = await something();
b = await something_else(a);
Не знаю, правда, можно ли так сделать тут.
- непонятно, зачем ты обернул весь код в анонимную функцию и сразу же вызвал ее.
И еще. Если ты будешь использовать отступы по 4 пробела, а не 2, то проблемы со слишком большой вложенностью кода будут гораздо заметнее. Мне не нравится идея использовать 2 пробела, так как она используется, чтобы не замечать излишнюю вложенность.
Я просто мимо проходил и не знаю, что у тебя за задача, но для проверки балансировки скобок обычно используют стек. Стек - это структура данных, которая хранит цепочку значений, и их можно добавлять или вынимать из стека только с одной стороны. То есть, для стека определены две операции:
- добавить значение в конец списка
- снять значение из конца списка
И если у тебя есть задача проверить баланс скобок в выражении вроде [({}, {}), {}] то она решается стеком. Ты проходишь по строке и, встречая открывающую скобку, кладешь ее в стек. А когда встречаешь закрывающую, вынимаешь значение из стека и проверяешь, что открывающая скобка из стека соответствует встреченной в строке закрывающей.
Насчет дизайна - если не найдешь анона-фронтендщика, ты можешь сделать дизайн на CSS-фреймворке Bootstrap - там уже есть набор готовых стилей для форм, таблиц, создания колонок, и тд.
>>49334
А мне не очень нравится твой код. Вот, что не так:
- ты используешь try/catch в том же месте, где выбрасывается исключение. Это не имеет никакого смысла. try/catch предназначен для ловли исключения при вызове какой-то функции, то есть:
try {
something();
}
В такой ситуации try не нужен:
try {
...thow new Error()...
}
- идея пропускать не сработавшие запросы выглядит как минимум странно. Исключение может быть выброшено по многим причинам: соединение с БД разорвалось, ошибка в тексте запроса, проблемы на стороне БД, нарушение внешних ключей при вставке. Очевидно, что разные случаи требуют разной реакции и объединять их вместе нельзя. Более того, в 99% случаев никакой необходимости обрабатывать такие ошибки нет, а нужно аварийно завершать программу и исправлять ее код.
- ты смешиваешь await и коллбеки, говорящие о готовности (в вызове transaction), что тоже странно выглядит, так как коллбеки и await - это 2 разных подхода к написанию асинхронного кода. Логичнее было бы видеть код в стиле:
a = await something();
b = await something_else(a);
Не знаю, правда, можно ли так сделать тут.
- непонятно, зачем ты обернул весь код в анонимную функцию и сразу же вызвал ее.
И еще. Если ты будешь использовать отступы по 4 пробела, а не 2, то проблемы со слишком большой вложенностью кода будут гораздо заметнее. Мне не нравится идея использовать 2 пробела, так как она используется, чтобы не замечать излишнюю вложенность.
Не стоит работать с числами как со строками. Это только все усложняет. Надо использовать математические операции.
Функцию inclineWord стоит переписать на работу с числами.
Также, в ней стоит последний elseif заменить просто на else чтобы не надо было гадать, что, если ни одно условие не выполнится.
То же касается и smallNumberToText - оттуда нужна убрать гору preg_match.
Разбить число на миллионы/тысячи/единицы можно делением.
Проблема работы со строками, например в том, что PHP может представить большое число в виде 1e20 и все твои алгоритмы начнут давать ошибки. Ну а также, в более общем случае, числа могут быть отрицательными или дробными.
Код там можно записать так:
- если в числе есть сотни, добавляем слово для сотен
- если число заканчивается на 11-19, добавляем слово для них
- иначе, добавляем десятки и единицы
У тебя слишком большая глубина вложенности if и такой код тяжело читать. Тяжело понять, насколько он правильный.
Вместо этой длинной команды:
$total2 = smallNumberToText($imploded3, null) .' '. inclineWord($imploded3, ' миллион', ' миллиона', ' миллионов') .' '. smallNumberToText($imploded2, $isFemale) .' '. inclineWord($imploded2, ' тысяча', ' тысячи', ' тысяч') .' '. smallNumberToText($imploded1, null) .' '. inclineWord($number, ' рубль', ' рубля', ' рублей')." ($number)";
Лучше собирать строку по частям: если есть миллионы, добавить слово для миллионов, и тд.
Сейчас в коде трудно разобраться и трудно проверить правильность. Сидеть разбирать его построчно и проверять все возможные ситуации слишком долго. Код нужно упростить.
Не стоит работать с числами как со строками. Это только все усложняет. Надо использовать математические операции.
Функцию inclineWord стоит переписать на работу с числами.
Также, в ней стоит последний elseif заменить просто на else чтобы не надо было гадать, что, если ни одно условие не выполнится.
То же касается и smallNumberToText - оттуда нужна убрать гору preg_match.
Разбить число на миллионы/тысячи/единицы можно делением.
Проблема работы со строками, например в том, что PHP может представить большое число в виде 1e20 и все твои алгоритмы начнут давать ошибки. Ну а также, в более общем случае, числа могут быть отрицательными или дробными.
Код там можно записать так:
- если в числе есть сотни, добавляем слово для сотен
- если число заканчивается на 11-19, добавляем слово для них
- иначе, добавляем десятки и единицы
У тебя слишком большая глубина вложенности if и такой код тяжело читать. Тяжело понять, насколько он правильный.
Вместо этой длинной команды:
$total2 = smallNumberToText($imploded3, null) .' '. inclineWord($imploded3, ' миллион', ' миллиона', ' миллионов') .' '. smallNumberToText($imploded2, $isFemale) .' '. inclineWord($imploded2, ' тысяча', ' тысячи', ' тысяч') .' '. smallNumberToText($imploded1, null) .' '. inclineWord($number, ' рубль', ' рубля', ' рублей')." ($number)";
Лучше собирать строку по частям: если есть миллионы, добавить слово для миллионов, и тд.
Сейчас в коде трудно разобраться и трудно проверить правильность. Сидеть разбирать его построчно и проверять все возможные ситуации слишком долго. Код нужно упростить.
В MySQL есть функция BENCHMARK, но надо понимать, что MySQL многопоточная и повесить ты можешь в лучшем случае одно ядро процессора, в то время как другие потоки будут работать. Лучший способ "подвесить" базу данных - имея права администратора, послать процессам mysql сигнал SIGSTOP, который остановит их выполнение, а через несколько секунд - SIGCONT, который их разморозит.
Также, можно попробовать заджойнить несколько больших таблиц: SELECT .. FROM a, b, c LIMIT 1000000, 1 - хотя там MySQL может немного соптимизировать запрос.
>>49060
А ты задачи по SQL из ОП-поста уже все решил? Вот еще задача тогда. Есть таблица со списком прихода и расхода товара на склад, в которой 3 колонки: время, id товара и изменение его количества. Например:
2018-01-01 12:00:01 | 101 | 3
2018-01-01 12:00:02 | 101 | -2
2018-01-01 12:00:03 | 102 | 1
2018-01-01 12:00:04 | 102 | -2
Это значит, что на склад пришло 3 единицы товара 101, затем было забрано 2 единицы, затем пришла 1 единица товара 102 итд.
Задача: найди остаток каждого товара на данный момент. То есть тебе нужно вывести таблицу, где показано текущее количество каждого вида товара. Изначально склад пуст.
>>48866
Вижу, что уже ответили, но я напишу объяснение, чтобы было понятно.
У тебя для PHP стоят настройки для продакшена, а не для разработки (dev). То есть ошибки пишутся в лог где-то в /var/log/... но не выводятся на экран. Это неудобно для разработки.
Настройки меняются в файле php.ini где-то в /etc/php/... (в линуксе все общесистемные настройки хранятся в /etc) - нужны права администратора для редактирования. После смены настроек надо перезапустить php-fpm или apache, в зависимости от того, что используется:
service php-fpm restart
xdebug можно установить, он будет делать сообщения об ошибках более подробными и позволит отлаживать код через IDE вроде Netbeans или PhpStorm. Отладке тоже стоит научиться - она позволяет ставить в программе точки остановка, смотреть значения переменных в них, проходить код по шагам.
Сразу советую почитать про управление сервисами в systemd (команды вроде service xxx start/stop/restart, команда systemctl) - это пригодится. Я набрал "ubuntu systemd управление сервисами" - и выдало кучу ссылок на русском. Сервисы, кстати, - это программы, работающие в фоновом режиме, которые могут запускаться при загрузке ОС или по какому-то событию.
Также, для разработки тебе может быть удобнее использовать встроенный в PHP веб-сервер. Его плюс в том, что не надо настраивать nginx - просто переходишь в папку с проектом и запускаешь одной командой: https://github.com/codedokode/pasta/blob/master/soft/web-server.md
В MySQL есть функция BENCHMARK, но надо понимать, что MySQL многопоточная и повесить ты можешь в лучшем случае одно ядро процессора, в то время как другие потоки будут работать. Лучший способ "подвесить" базу данных - имея права администратора, послать процессам mysql сигнал SIGSTOP, который остановит их выполнение, а через несколько секунд - SIGCONT, который их разморозит.
Также, можно попробовать заджойнить несколько больших таблиц: SELECT .. FROM a, b, c LIMIT 1000000, 1 - хотя там MySQL может немного соптимизировать запрос.
>>49060
А ты задачи по SQL из ОП-поста уже все решил? Вот еще задача тогда. Есть таблица со списком прихода и расхода товара на склад, в которой 3 колонки: время, id товара и изменение его количества. Например:
2018-01-01 12:00:01 | 101 | 3
2018-01-01 12:00:02 | 101 | -2
2018-01-01 12:00:03 | 102 | 1
2018-01-01 12:00:04 | 102 | -2
Это значит, что на склад пришло 3 единицы товара 101, затем было забрано 2 единицы, затем пришла 1 единица товара 102 итд.
Задача: найди остаток каждого товара на данный момент. То есть тебе нужно вывести таблицу, где показано текущее количество каждого вида товара. Изначально склад пуст.
>>48866
Вижу, что уже ответили, но я напишу объяснение, чтобы было понятно.
У тебя для PHP стоят настройки для продакшена, а не для разработки (dev). То есть ошибки пишутся в лог где-то в /var/log/... но не выводятся на экран. Это неудобно для разработки.
Настройки меняются в файле php.ini где-то в /etc/php/... (в линуксе все общесистемные настройки хранятся в /etc) - нужны права администратора для редактирования. После смены настроек надо перезапустить php-fpm или apache, в зависимости от того, что используется:
service php-fpm restart
xdebug можно установить, он будет делать сообщения об ошибках более подробными и позволит отлаживать код через IDE вроде Netbeans или PhpStorm. Отладке тоже стоит научиться - она позволяет ставить в программе точки остановка, смотреть значения переменных в них, проходить код по шагам.
Сразу советую почитать про управление сервисами в systemd (команды вроде service xxx start/stop/restart, команда systemctl) - это пригодится. Я набрал "ubuntu systemd управление сервисами" - и выдало кучу ссылок на русском. Сервисы, кстати, - это программы, работающие в фоновом режиме, которые могут запускаться при загрузке ОС или по какому-то событию.
Также, для разработки тебе может быть удобнее использовать встроенный в PHP веб-сервер. Его плюс в том, что не надо настраивать nginx - просто переходишь в папку с проектом и запускаешь одной командой: https://github.com/codedokode/pasta/blob/master/soft/web-server.md
>>48597
Да, в линукс используется немного другой механизм рендеринга шрифтов для улучшения отображения в мелком размере. Экран монитора состоит из квадратных пикселей и они раньше были довольно крупные - у меня например пиксель имеет ширину где-то 0.5мм и его прекрасно видно, а если приблизить глаза к экрану, то видно пиксельную сетку и крошечные красные, зеленые и синие точки.
Пиксель может гореть только целиком. Потому, если например буква при рендеринге закрывает пиксель частично, то он в итоге загорается серым цветом, яркость пропорциональна площади попавшего в пиксель куска буквы (это называется анти-алиасинг, алиасинг - это эффект появления "ступенек" и "зубцов", которые видны на букве, состоящей только из белых и черных точек). Если например у нас есть буква I, и ее ширина равна допустим 1,5 пикселя, то она займет 2 вертикальных колонки пикселей, просто в правой колонке пиксели будут гореть вполсилы.
На экранах с крупными пикселями это (лишняя закрашенная область) может выглядеть как серые или белые пятна на буквах (грязь вокруг букв). Если у монитора неправильно настроена гамма (то есть он неточно передает оттенки серого, делая их темнее или светлее, чем нужно), эти пятна становятся более заметны. Без антиалиасинга будет еще хуже, у букв будут "заусенцы". Особенно они портят буквы с засечками вроде Times New Roman. Хотя это дело вкуса.
В Windows для решения этой проблемы сделали две вещи:
- для стандартных шрифтов на маленьких размерах вручную сделан хинтинг, то есть вручную изменены формы и пропорции букв, чтобы они укладывались ровно в границы пикселей. В примере с буквой I, ее могли бы сузить до 1 пикселя или расширить до двух. Если я не путаю, это запатентовано. Инструкции для хинтинга зашиты в соответствующих файлах шрифтов, и, если я не путаю, представляют собой микропрограмму на каком-то примитивном специально для этого сделанном языке. Библиотека freetype на линуксе умеет их интерпретировать, если это включить.
Минус в том, что это искажает пропорции и форму букв, также, хинитинг делается вручную и работает только для стандартных шрифтов только в определенных размерах (это может работать в размере 8 и 10, но не работать для размера 9 или 9.5), это заметно например на сайтах с кастомными шрифтами - там шрифты выглядят "как в линуксе".
Плюс в том, что мелкий стандартный шрифт выглядит более четким.
На Mac, насколько я знаю, хинтинг не используется и буквы выглядят "как в линуксе".
- на LCD мониторах используется субпиксельный антиалиасинг. Во многих LCD мониторах квадратный пиксель состоит из 3 идущих горизонтально узких субпикселей - красного, зеленого и синего. Буква рендерится по ним, что позволяет повысить горизонтальное разрешение в 3 раза. Минус - это может выглядеть как появление крошечных цветных полосок справа/слева от линий букв.
Тут подвох в том, что такие буквы нельзя масштабировать и поворачивать - появятся цветные пятна, потому, если на сайте используется CSS-трансформация (масштабирование элемента, или вывод текста под углом), то для таких элементов браузер отключает эту функцию. Также подвох в том, что если сделать скриншот и просмотреть на мониторе с другим расположением субпикселей, то тоже появятся цветные пятна.
Используемая в линуксе библиотека freetype содержит различные опции для ручного и автоматического хинтинга на мелких размерах. Вот нагугленные статьи с картинками:
- https://www.freetype.org/autohinting/hinter.html
- https://www.freetype.org/freetype2/docs/subpixel-hinting.html (здесь много подробностей)
- https://www.freetype.org/freetype2/docs/text-rendering-general.html
Обратите внимание, что картинки в статьях уменьшены и вам надо открыть их в отдельной вкладке в полном размере, чтобы оценивать качество рендеринга.
То есть, в линуксе можно поиграться с настройками freetype и настроить хинтинг и антиалиасинг индивидуально. Также, честно предупрежу, придется еще немного помучаться, чтобы программы на разных движках (Qt, GTK, Java, отдельные программы вроде Chromium) "увидели" эти настройки.
Замечу, что это все теряет актуальность на экранах с высокой плотностью пикселей и точной передачей оттенков серого. У меня, например, на смартфоне с IPS матрицей, мелкие буквы выглядят очень гладко, почти как напечатанные на бумаге, а пиксели с расстояния не видны, если поставить рядом экран смартфона и ноутбука, чувствуется, что они из разных поколений. При этом андроид использует ту же самую библиотеку freetype.
>>48597
Да, в линукс используется немного другой механизм рендеринга шрифтов для улучшения отображения в мелком размере. Экран монитора состоит из квадратных пикселей и они раньше были довольно крупные - у меня например пиксель имеет ширину где-то 0.5мм и его прекрасно видно, а если приблизить глаза к экрану, то видно пиксельную сетку и крошечные красные, зеленые и синие точки.
Пиксель может гореть только целиком. Потому, если например буква при рендеринге закрывает пиксель частично, то он в итоге загорается серым цветом, яркость пропорциональна площади попавшего в пиксель куска буквы (это называется анти-алиасинг, алиасинг - это эффект появления "ступенек" и "зубцов", которые видны на букве, состоящей только из белых и черных точек). Если например у нас есть буква I, и ее ширина равна допустим 1,5 пикселя, то она займет 2 вертикальных колонки пикселей, просто в правой колонке пиксели будут гореть вполсилы.
На экранах с крупными пикселями это (лишняя закрашенная область) может выглядеть как серые или белые пятна на буквах (грязь вокруг букв). Если у монитора неправильно настроена гамма (то есть он неточно передает оттенки серого, делая их темнее или светлее, чем нужно), эти пятна становятся более заметны. Без антиалиасинга будет еще хуже, у букв будут "заусенцы". Особенно они портят буквы с засечками вроде Times New Roman. Хотя это дело вкуса.
В Windows для решения этой проблемы сделали две вещи:
- для стандартных шрифтов на маленьких размерах вручную сделан хинтинг, то есть вручную изменены формы и пропорции букв, чтобы они укладывались ровно в границы пикселей. В примере с буквой I, ее могли бы сузить до 1 пикселя или расширить до двух. Если я не путаю, это запатентовано. Инструкции для хинтинга зашиты в соответствующих файлах шрифтов, и, если я не путаю, представляют собой микропрограмму на каком-то примитивном специально для этого сделанном языке. Библиотека freetype на линуксе умеет их интерпретировать, если это включить.
Минус в том, что это искажает пропорции и форму букв, также, хинитинг делается вручную и работает только для стандартных шрифтов только в определенных размерах (это может работать в размере 8 и 10, но не работать для размера 9 или 9.5), это заметно например на сайтах с кастомными шрифтами - там шрифты выглядят "как в линуксе".
Плюс в том, что мелкий стандартный шрифт выглядит более четким.
На Mac, насколько я знаю, хинтинг не используется и буквы выглядят "как в линуксе".
- на LCD мониторах используется субпиксельный антиалиасинг. Во многих LCD мониторах квадратный пиксель состоит из 3 идущих горизонтально узких субпикселей - красного, зеленого и синего. Буква рендерится по ним, что позволяет повысить горизонтальное разрешение в 3 раза. Минус - это может выглядеть как появление крошечных цветных полосок справа/слева от линий букв.
Тут подвох в том, что такие буквы нельзя масштабировать и поворачивать - появятся цветные пятна, потому, если на сайте используется CSS-трансформация (масштабирование элемента, или вывод текста под углом), то для таких элементов браузер отключает эту функцию. Также подвох в том, что если сделать скриншот и просмотреть на мониторе с другим расположением субпикселей, то тоже появятся цветные пятна.
Используемая в линуксе библиотека freetype содержит различные опции для ручного и автоматического хинтинга на мелких размерах. Вот нагугленные статьи с картинками:
- https://www.freetype.org/autohinting/hinter.html
- https://www.freetype.org/freetype2/docs/subpixel-hinting.html (здесь много подробностей)
- https://www.freetype.org/freetype2/docs/text-rendering-general.html
Обратите внимание, что картинки в статьях уменьшены и вам надо открыть их в отдельной вкладке в полном размере, чтобы оценивать качество рендеринга.
То есть, в линуксе можно поиграться с настройками freetype и настроить хинтинг и антиалиасинг индивидуально. Также, честно предупрежу, придется еще немного помучаться, чтобы программы на разных движках (Qt, GTK, Java, отдельные программы вроде Chromium) "увидели" эти настройки.
Замечу, что это все теряет актуальность на экранах с высокой плотностью пикселей и точной передачей оттенков серого. У меня, например, на смартфоне с IPS матрицей, мелкие буквы выглядят очень гладко, почти как напечатанные на бумаге, а пиксели с расстояния не видны, если поставить рядом экран смартфона и ноутбука, чувствуется, что они из разных поколений. При этом андроид использует ту же самую библиотеку freetype.
Эмм. Ну это javascript же!
>try/catch в том же месте, где выбрасывается исключение. Это не имеет никакого смысла. try/catch предназначен для ловли исключения при вызове какой-то функции
не очень понял, что ты имеешь в виду. to.execute(); это и есть функция. transaction(); это тоже функция.
>идея пропускать не сработавшие запросы
тут я просто перенес идеологию из спецификации:
If the error callback returns false, then move on to the next statement, if any, or onto the next overall step otherwise.
Otherwise, the error callback did not return false, or there was no error callback. Jump to the last step in the overall steps.
Все фатальные ошибки ловятся в catch.
>ты смешиваешь await и коллбеки, говорящие о готовности (в вызове transaction)
>a = await something();
>b = await something_else(a);
Но на скриншоте все именно так! Я не понимаю...
>непонятно, зачем ты обернул весь код в анонимную функцию и сразу же вызвал ее.
await работает только внутри async-функции. А анонимная она тут просто для примера (это кусок тестового кода). В реальном коде это будет async-метод класса, с аргументами.
>отступы по 4 пробела
Уже привык к 2, потому что везде так пишут. Как в PHP везде 4, тоже привык.
Чет я разочарован немного.
Эмм. Ну это javascript же!
>try/catch в том же месте, где выбрасывается исключение. Это не имеет никакого смысла. try/catch предназначен для ловли исключения при вызове какой-то функции
не очень понял, что ты имеешь в виду. to.execute(); это и есть функция. transaction(); это тоже функция.
>идея пропускать не сработавшие запросы
тут я просто перенес идеологию из спецификации:
If the error callback returns false, then move on to the next statement, if any, or onto the next overall step otherwise.
Otherwise, the error callback did not return false, or there was no error callback. Jump to the last step in the overall steps.
Все фатальные ошибки ловятся в catch.
>ты смешиваешь await и коллбеки, говорящие о готовности (в вызове transaction)
>a = await something();
>b = await something_else(a);
Но на скриншоте все именно так! Я не понимаю...
>непонятно, зачем ты обернул весь код в анонимную функцию и сразу же вызвал ее.
await работает только внутри async-функции. А анонимная она тут просто для примера (это кусок тестового кода). В реальном коде это будет async-метод класса, с аргументами.
>отступы по 4 пробела
Уже привык к 2, потому что везде так пишут. Как в PHP везде 4, тоже привык.
Чет я разочарован немного.
>2018-01-01 12:00:01 | 101 | 3
>2018-01-01 12:00:02 | 101 | -2
>2018-01-01 12:00:03 | 102 | 1
>2018-01-01 12:00:04 | 102 | -2
Если взять поля как date,id_product,count
То я бы написал типа такого
select id_product,sum(count) as sum from my_table order by id_product;
>о
>select id_product,sum(count) as sum from my_table order by id_product;
group by конечно же
В задаче на изображении, подразумевается доработка кода теста, из самого начала раздела ООП?
https://ideone.com/U4MsQ0
Тестовое Fora Soft'а, да ? :)
Пацаны что скажете по поводу кода:
http://sandbox.onlinephpfunctions.com/code/916f7aeeb90f7daaa93f4b509669cf93865168c7
Это говнокод или нормально вообще так делать? Как по мне это жопа, я бы так никогда не сделал.
Не, тут вообще ебанина какая-то. Он начинает цикл (1 строка), его не заканчивает, оставив открытой фигурную скобку, но PHP-вставку закрывает. Дальше выводит собственно элемент массива, который перебирает, ставит hr (уже в html, тэг php закрыт) и открывает php для того, чтобы поставить ту самую закрывающую фигурную скобку.
Отсюда вопрос, нахуя так делать, если можно просто внутри цикла:
echo $record . '<hr>';
- Еще более сложная и долгая задача на Yii/Symfony: https://gist.github.com/codedokode/8733007
Можно ли заменить симфони ларавелом?
>Еще более сложная и долгая задача на Yii/Symfony: https://gist.github.com/codedokode/8733007
быстрофикс*
А ты дальше не читал?
> Предлагаемые технологии: фреймворк (Symfony 3-4 (сложнее, но интереснее), Yii2, Laravel), MySQL или Postgres, шаблонизатор Twig, ORM Doctrine
большое спасибо за советы! вот https://ideone.com/BNdQnj , переделал код, вроде меньше строк и более понятно получилось. Заранее скажу, что все те хитрые номера по типу 0, 1, 7000000 и т.д. работают у меня правильно, вопрос стоит опять же в правильности написания самого кода
Ну там выпендрёж просто - школяр какой балуется. Такие вещи в самом начале проходят - конпелятор тутошний. Понятно, что код нечитаем чуть более чем.
Думаю во время пользования пекой включать скрипт и пусть себе делает дело, даже хостинг не нужен. И я пока только php учу, так бы, наверное, питон использовал. Парсер пишу.
А что от скрипта хочешь вообще?
>я пока только php учу
Я тоже его учу. Но что с одним им делоть-то? Лучше сразу и соседние технологии окучивать. Просто для понимания. Да и не сказать, чтобы сложный язык был.
>так бы, наверное, питон использовал
Питон интересно, да.
Мощно! Хорошие комменты. Кто тут следит за ОП постом, доставьте в ФАК. Что-то типа как делать гостевуху.
>Тестовое Fora Soft'а, да ? :)
хз что это, я тестхаб от опа делаю, пытаюсь пройденные тесты засабмитить.
По твоему коду скажу что это всё вообще насрать, я на фрилансе видел в шаблонах код как у тебя и в коде альтернативный if/foreach etc через : и endforeach, когда один скрипт в 20 строк кода проходит несколько итераций от разных "разрабов", то он превращается вообще в кiсмос. Хотя есть такая тема что твоя сущность по геттеру отдает ридонли массив и mah oop, но я сейчас бухой и мне кажется что это дрочево полное, т. к. симфони формы для работы из коробки заствляют делать геттеры и сеттеры на все поля твоей сущности, поэтому это сразу мимо ddd, чуваки на джаваскрипте по сути без какой-либо типизации и инкапсуляции пишут фреймворки, вон ларавер вообще, весь фреймворк это магия, и всем нормно там тоже немного дрочева поэтому не особо считается.
Мне кажется тебе лучше это сделать как сервис, просто в бэкграунде запускать, если закроешь терминал, то у тебя убьется процесс, или еще вариант в кроне это сделать, кажду минуту запускать скрипт
Что за сервис? Крона? Я чет думал, что nohup запустит процесс и он вне терминала будет работать.
Вообще, у нас есть урок и по MVC и по шаблонам, так что это не требуется:
- https://github.com/codedokode/pasta/blob/master/arch/mvc.md
- https://github.com/codedokode/pasta/blob/master/php/templates.md
В примере кода по ссылке никак не обосновано добавление RecordView, там код будет прекрасно работать без него.
Плюс, нет экранирования спецсимволов при выводе.
>>49955
Если ты запускаешь скрипт локально, то проще всего запускать его через команду
php script.php аргументы
А уже в скрипте while и sleep().
nohup нужен для запуска на удаленном сервере, чтобы скрипт "открепился" от консоли и при отсоединении от сервера не завершался бы (по умолчанию при разрыве ssh-соединения демон ssh посылает всем запущенным в сессии программам сигнал SIGHUP, который их убивает. nohup его перехватывает. Также, nohup перенаправляет потоки ввода/вывода в файл. Ну и может еще что-то делает, стоит посмотреть man nohup).
Если ты хочешь запускать скрипт как сервис, чтобы он работал в фоне и запускался автоматически при загрузке ОС, то его можно оформить как сервис systemd.
Также, можно еще настроить запуск в кроне.
>>49949
Это можно реализовать практически на любом языке, ты ошибаешься.
>>49939
Нет, пока не все хорошо. Например, в inclineWord ты по-прежнему зачем-то преобразуешь числа в строку вместо того, чтобы использовать математические операции.
> $forDecades = preg_match('/\d\d$/', $number, $decades);
> $decades = intval(implode('', $decades));
Тут ты используешь implode, и это говорит о том, что ты скорее всего не понимаешь, в каком формате preg_match возвращает массив совпадений. Так как для того, чтобы вытащить совпадение, достатоно писать $decades[0]. Советую почитать мануал по preg_match.
Опять же, тут лучше было бы использовать математические операции.
> if (($number / 100) >= 1) {
Проще $number >= 100
> $intoWords .= ' '.$spelling[$roundHundreds];
Удобнее может быть собирать слова в массив, чтобы не беспокоиться о лишних пробелах между ними.
> if (array_key_exists($decades, $spelling) >= 10
Это неправильный код, так как array_key_exists() возвращает false или true, и ты пытаешься сделать бессмысленное сравнение true >= 10, которое не сработает, так как в такой ситуации false преобразуется в 0, а true в 1.
> !$decades == 0
Этот код тоже сомнительный, так как он воспринимается как (!$decades) == 0. Оператор ! выдает на выходе false или true, и ты пытаешься нестрого их сравнивать с 0. Нужно написать $decades != 0.
Если ты не знал, что такое false/true, то можешь почитать про булев тип. Эти значения обозначают "истина" и "ложь" и их возвращают, например, операции сравнения: 5 < 3 вернет false. Мануал: http://php.net/manual/ru/language.types.boolean.php
Вообще, у нас есть урок и по MVC и по шаблонам, так что это не требуется:
- https://github.com/codedokode/pasta/blob/master/arch/mvc.md
- https://github.com/codedokode/pasta/blob/master/php/templates.md
В примере кода по ссылке никак не обосновано добавление RecordView, там код будет прекрасно работать без него.
Плюс, нет экранирования спецсимволов при выводе.
>>49955
Если ты запускаешь скрипт локально, то проще всего запускать его через команду
php script.php аргументы
А уже в скрипте while и sleep().
nohup нужен для запуска на удаленном сервере, чтобы скрипт "открепился" от консоли и при отсоединении от сервера не завершался бы (по умолчанию при разрыве ssh-соединения демон ssh посылает всем запущенным в сессии программам сигнал SIGHUP, который их убивает. nohup его перехватывает. Также, nohup перенаправляет потоки ввода/вывода в файл. Ну и может еще что-то делает, стоит посмотреть man nohup).
Если ты хочешь запускать скрипт как сервис, чтобы он работал в фоне и запускался автоматически при загрузке ОС, то его можно оформить как сервис systemd.
Также, можно еще настроить запуск в кроне.
>>49949
Это можно реализовать практически на любом языке, ты ошибаешься.
>>49939
Нет, пока не все хорошо. Например, в inclineWord ты по-прежнему зачем-то преобразуешь числа в строку вместо того, чтобы использовать математические операции.
> $forDecades = preg_match('/\d\d$/', $number, $decades);
> $decades = intval(implode('', $decades));
Тут ты используешь implode, и это говорит о том, что ты скорее всего не понимаешь, в каком формате preg_match возвращает массив совпадений. Так как для того, чтобы вытащить совпадение, достатоно писать $decades[0]. Советую почитать мануал по preg_match.
Опять же, тут лучше было бы использовать математические операции.
> if (($number / 100) >= 1) {
Проще $number >= 100
> $intoWords .= ' '.$spelling[$roundHundreds];
Удобнее может быть собирать слова в массив, чтобы не беспокоиться о лишних пробелах между ними.
> if (array_key_exists($decades, $spelling) >= 10
Это неправильный код, так как array_key_exists() возвращает false или true, и ты пытаешься сделать бессмысленное сравнение true >= 10, которое не сработает, так как в такой ситуации false преобразуется в 0, а true в 1.
> !$decades == 0
Этот код тоже сомнительный, так как он воспринимается как (!$decades) == 0. Оператор ! выдает на выходе false или true, и ты пытаешься нестрого их сравнивать с 0. Нужно написать $decades != 0.
Если ты не знал, что такое false/true, то можешь почитать про булев тип. Эти значения обозначают "истина" и "ложь" и их возвращают, например, операции сравнения: 5 < 3 вернет false. Мануал: http://php.net/manual/ru/language.types.boolean.php
Это может быть не очень удачная идея. Там, видимо, $record - это то ли кусок HTML разметки, который соответствует одной записи, либо объект с магическим методом __toString(), который вызвается при выполнении echo и генерирует HTML разметку.
Вопрос в том, как она генерируется. Если там есть отдельный шаблон - ок, почему бы и нет. Минус правда в том, что если мы на каждый элемент страницы будем делать по шаблону, то их станет очень много, но если их грамотно организовать, то это допустимо.
Если же HTML там генерируется без шаблонов, то это плохо.
Магический метод __toString я не люблю и предпочел бы явный вызов $record->getHtml().
Вызывать метод получения данных (getGuestBookRecords) из шаблона имхо плохая идея. Так как это не задача шаблона - получать данные.
>>49815
Да, все верно.
>>49789
Ты бы сформулировал задачу. А то непонятно, что ты хочешь.
По коду - код, конечно, ужасен.
Например, неправильное использование исключений. Ты не понимаешь, как с ними работать, и я советую начать с урока https://github.com/codedokode/pasta/blob/master/php/exceptions.md . Ты почему-то решил, что исключение может быть выброшено только в случеае отстутсвия ключа в массиве, но это не так. При этом ты не логгируешь ошибку и разработчики о ней никогда из-за твоего кода не узнают. То есть ошибки логгируются по умолчанию и ты из-за незнания отключил этот полезный механизм.
Если тебе надо проверить, что ключ есть в массиве, есть метод array_key_exists(). Непонятно, зачем использовать обходные пути определения этого.
Далее, ты не следуешь принципам ООП, а относишься к объектам как к массивам, с которыми можно работать через стрелочки и анонимные функции.
В данном случае стоит применить инкапсуляуию. Вместо лапши с кучей стрелок гораздо лучше сделать метод $question->findOptionById();
Это может быть не очень удачная идея. Там, видимо, $record - это то ли кусок HTML разметки, который соответствует одной записи, либо объект с магическим методом __toString(), который вызвается при выполнении echo и генерирует HTML разметку.
Вопрос в том, как она генерируется. Если там есть отдельный шаблон - ок, почему бы и нет. Минус правда в том, что если мы на каждый элемент страницы будем делать по шаблону, то их станет очень много, но если их грамотно организовать, то это допустимо.
Если же HTML там генерируется без шаблонов, то это плохо.
Магический метод __toString я не люблю и предпочел бы явный вызов $record->getHtml().
Вызывать метод получения данных (getGuestBookRecords) из шаблона имхо плохая идея. Так как это не задача шаблона - получать данные.
>>49815
Да, все верно.
>>49789
Ты бы сформулировал задачу. А то непонятно, что ты хочешь.
По коду - код, конечно, ужасен.
Например, неправильное использование исключений. Ты не понимаешь, как с ними работать, и я советую начать с урока https://github.com/codedokode/pasta/blob/master/php/exceptions.md . Ты почему-то решил, что исключение может быть выброшено только в случеае отстутсвия ключа в массиве, но это не так. При этом ты не логгируешь ошибку и разработчики о ней никогда из-за твоего кода не узнают. То есть ошибки логгируются по умолчанию и ты из-за незнания отключил этот полезный механизм.
Если тебе надо проверить, что ключ есть в массиве, есть метод array_key_exists(). Непонятно, зачем использовать обходные пути определения этого.
Далее, ты не следуешь принципам ООП, а относишься к объектам как к массивам, с которыми можно работать через стрелочки и анонимные функции.
В данном случае стоит применить инкапсуляуию. Вместо лапши с кучей стрелок гораздо лучше сделать метод $question->findOptionById();
Ну да, верно.
>>46427
> if (preg_match_all('/\d+\.?\d|[\+\-\\/\=]/', $input, $numbersAndOperations)) {
if тут не нужен. Можно по умолчанию положить в $numbersAndOperations пустой массив и тогда никаких проблем не будет, если ничего не найдется.
Небольшой минус твоего кода - он игнорирует все некорректные символы вместо того, чтобы сообщить об ошибке.
Знаки плюс, звездочка, равно не требуют экранирования в квадратных скобках.
Считает программа неправильно, попробуй найди причину: https://ideone.com/Gb1WFg - для выражения 2-2x4 выдает ответ 8 вместо 0 (или -6).
> Определяет переменную с десятичной дробью и задает ей тип double, остальным integer
Вообще, integer - это не любые целые числа, а только небольшие целые числа (от PHP_INT_MIN дл PHP_INT_MAX), предел описан в мануале:
- http://php.net/manual/ru/reserved.constants.php
- http://php.net/manual/ru/language.types.integer.php
Так что всегда использовать float будет безопаснее.
>>46798
В inclineWord можно было сделать проще:
если (число от 11 до 19) {
сразу вернуть вариант word3;
}
смотреть на последнюю цифру...;
Вместо последнего длинного ifelse можно было написать просто else.
> smallNumberToText($number, $isFemale, $lengthOfNumber) {
lengthOfNumber избыточна и не нужна, так как размер числа можно определить по $number. Или это что-то другое?
В smallNumberToText слишком много кода. В моем понимании, там хватит 5 веток:
- если число равно нулю, то ...
- если в числе есть сотни, то ...
- если число оканчивается на 11-19, то ...
- если число оканчивается на 20-99, то ...
- если в числе есть единицы, то ...
У тебя же сложная структура ифов и 7 мест с $words[] = .... Есть куда упрощать.
> $isFemale = ($x == 1 and $numbers[1] % 10 == 1 or $x == 1 and $numbers[1] % 10 == 2) ? 1 : 0;
По моему, так все проще: в женском роде только слово "тысяча" и условие должно быть $isFemale = ($x == 1); А SmallNumberToText на основе этого выбирает формы "один" или "одна".
В функции numberToText внутри if ($x == 0) многовато кода и было бы хорошо упростить.
Ну да, верно.
>>46427
> if (preg_match_all('/\d+\.?\d|[\+\-\\/\=]/', $input, $numbersAndOperations)) {
if тут не нужен. Можно по умолчанию положить в $numbersAndOperations пустой массив и тогда никаких проблем не будет, если ничего не найдется.
Небольшой минус твоего кода - он игнорирует все некорректные символы вместо того, чтобы сообщить об ошибке.
Знаки плюс, звездочка, равно не требуют экранирования в квадратных скобках.
Считает программа неправильно, попробуй найди причину: https://ideone.com/Gb1WFg - для выражения 2-2x4 выдает ответ 8 вместо 0 (или -6).
> Определяет переменную с десятичной дробью и задает ей тип double, остальным integer
Вообще, integer - это не любые целые числа, а только небольшие целые числа (от PHP_INT_MIN дл PHP_INT_MAX), предел описан в мануале:
- http://php.net/manual/ru/reserved.constants.php
- http://php.net/manual/ru/language.types.integer.php
Так что всегда использовать float будет безопаснее.
>>46798
В inclineWord можно было сделать проще:
если (число от 11 до 19) {
сразу вернуть вариант word3;
}
смотреть на последнюю цифру...;
Вместо последнего длинного ifelse можно было написать просто else.
> smallNumberToText($number, $isFemale, $lengthOfNumber) {
lengthOfNumber избыточна и не нужна, так как размер числа можно определить по $number. Или это что-то другое?
В smallNumberToText слишком много кода. В моем понимании, там хватит 5 веток:
- если число равно нулю, то ...
- если в числе есть сотни, то ...
- если число оканчивается на 11-19, то ...
- если число оканчивается на 20-99, то ...
- если в числе есть единицы, то ...
У тебя же сложная структура ифов и 7 мест с $words[] = .... Есть куда упрощать.
> $isFemale = ($x == 1 and $numbers[1] % 10 == 1 or $x == 1 and $numbers[1] % 10 == 2) ? 1 : 0;
По моему, так все проще: в женском роде только слово "тысяча" и условие должно быть $isFemale = ($x == 1); А SmallNumberToText на основе этого выбирает формы "один" или "одна".
В функции numberToText внутри if ($x == 0) многовато кода и было бы хорошо упростить.
Я не очень понимаю, будет ли это работать. В моем понимании, транзакция в WebSQL - это такая штука, в которую ты заранее добавляешь все запросы и она их по очереди выполняет (немного странная логика, ну да ладно). А у тебя не так. Ты добавляешь один запрос, и когда он выполнится и она вроде как завершена, пытаешься добавить второй. Не окажется ли что после первого запроса транзакция завершится и второй будет не добавить.
И если ты используешь промисы и асинки, зачем тебе этот коллбек в transaction? Коллбеки - это альтернатива промисам. Логичнее так:
var t = await createTransaction(db);
var res1 = await t.execute('SELECT ...');
Разве нет?
Если ты будешь писать TDG, то try/catch не нужен. Логичнее будет возвращать промис с результатом или ошибкой:
// @return {Promise<>}
function async updateSomething(a, b, c)
{
var t = this.createTransaction(db);
var result = await t.execute(...);
return result;
}
>>50086
А на локалхосте это и надо, закрыл консоль (или нажал Ctrl + C) и скрипт завершился.
Я не очень понимаю, будет ли это работать. В моем понимании, транзакция в WebSQL - это такая штука, в которую ты заранее добавляешь все запросы и она их по очереди выполняет (немного странная логика, ну да ладно). А у тебя не так. Ты добавляешь один запрос, и когда он выполнится и она вроде как завершена, пытаешься добавить второй. Не окажется ли что после первого запроса транзакция завершится и второй будет не добавить.
И если ты используешь промисы и асинки, зачем тебе этот коллбек в transaction? Коллбеки - это альтернатива промисам. Логичнее так:
var t = await createTransaction(db);
var res1 = await t.execute('SELECT ...');
Разве нет?
Если ты будешь писать TDG, то try/catch не нужен. Логичнее будет возвращать промис с результатом или ошибкой:
// @return {Promise<>}
function async updateSomething(a, b, c)
{
var t = this.createTransaction(db);
var result = await t.execute(...);
return result;
}
>>50086
А на локалхосте это и надо, закрыл консоль (или нажал Ctrl + C) и скрипт завершился.
nohup это типа скрина что ль?
>Если ты запускаешь скрипт локально, то проще всего запускать его через команду php script.php аргументы
Чет он даже без while не работает, как надо. Даже через sudo. Один скрипт не видит класс, другой, как я понял, не отправляет запросы по curl. Хуйня какая-то. Нужны какие-то особые аргументы?
Я имел ввиду прописать его в /etc/cron.d/твоёрасписание
а там каждую минуту его запускать /1 * root твой_скрипт_команды или просто команду туда
Так в браузере все отлично работает.
Не нужно от рута запускать. Зачем вредные советы даешь? Запускать от непривилегированного пользователя, иначе при ошибке он тебе может полсистемы разломать.
К сожалению, так не работает (транзакция закроется сразу с 0 запросов и будет ошибка "can't add expression to the queue"), а то да, было бы хорошо. Вся проблема в том что за один вызов в транзакцию там нужно добавить СРАЗУ все query, и условные (основанные на результатах) добавляются только в коллбэках от основных, поэтому так трудно прикрутить асинхронность. Я покажу весь TDG класс, когда напишу его, хорошо?
> Ты бы сформулировал задачу. А то непонятно, что ты хочешь.
Это тестхаб, а конкретнее момент, когда пользователь уже прошел тест, и загружает свои данные на сервер. Я хочу из полученных данных создать массив объектов UserChoice, сам объект просто хранит другие объекты вопрос и ответ. Тут беда в том что я не знаю как лучше обойти входной массив, еще я не уверен в том как входной массив должен выглядеть, но мне показалось удобнее всего иметь массив не очень красивого вида [ question_id => answer_id ], потом я начинаю проходить по коллекции вопросов теста, и на каждой итерации пытаюсь получить айди ответа подставив айди вопроса в массив. Но это как будто я верх ногами все делаю.
Я ведь объект Тест изначально загружаю, поэтому была еще мысль проходить как раз таки входной массив, и доктриной забирать вопросы и ответы из бд, на уже загруженные объекты она просто даст ссылку, и можно потом проверять через collection::contains метод что объект нужный, иначе выбрасывать исключение. У меня просто такое чувство что это всё делается намного проще и я что-то упускаю
["sizes"]=>
array(9) {
[0]=>
array(4) {
["type"]=> string(1) "m"
["url"]=> string(63) ""
["width"]=> int(130)
["height"]=> int(97)
}
Мне нужно сравнить его type, но не знаю, как приравнять строки к числам и сравнивать их.
Либо сравнивать его width/height. Как мне найти самое большое значение массива, а сам подмассив переместить на [0] место в массиве sizes?
Есть еще вариант - записать номер подмассива с самым большим значением в переменную и использовать её потом. Но чет такой вариант не очень.
<?php
if ((pass1||pass2||pass3)==$_POST['password'])
{
?>
Auth complete.
<?php
}
else echo ('Auth failed.');
?>
>Мне нужно сравнить его type,
С чем сравнить?
>переместить на [0] место в массиве sizes
http://php.net/manual/ru/function.array-unshift.php
Так. Хотел тебе дальше ссылки на функции кидать, но смотрю ты даже не пытался искать в списке то что тебе нужно.
Вот. Тут ты найдёшь функции для всего о чем ты спрашиваешь. http://php.net/manual/ru/ref.array.php
Насколько я понимаю, в коде они вообще не объявлены, но почему тогда фраза password работает.
Мне просто нужен вход на страницу с одним паролем.
сделай сравнение ===
Еще как искал.
>array-unshift
Создает, но не перемещает же. Все массивы я получаю по api и не могу знать тот же url заранее. И sort тоже не пойдет, мне надо сравнивать значения из разных массивов. Потому и обратился, не понимаю, как проще всего реализовать это. У меня есть вариант, но он делает от ~8 до 30 проверок на один массив.
>С чем сравнить?
Друг с другом. Тип 'w' больше 'y', а 'y' больше 'z', например. Я мог бы просто брать тип w сразу, но его может не существовать.
Может, взять все значения width в отдельный массив, выполнить asort и взять ключ от значения в переменную? Хотя стоп, мне же нужен... Я в самом деле запутался, дело даже не в знаниях и поиске.
Можешь в usort засунуть что-то вроде function($a, $b) return strcmp($a['type'], $b['type'])
>Создает, но не перемещает же.
array_unshift, а потом просто удаляешь тот элемент, который только что отправил наверх.
>>50673
>И sort тоже не пойдет, мне надо сравнивать значения из разных массивов. Потому и обратился, не понимаю, как проще всего реализовать это. У меня есть вариант, но он делает от ~8 до 30 проверок на один массив.
Тебе нужно конкретнее описывать задачу. Слишком много додумывать надо. И решения разные для каждого варианта.
>>50673
>Тип 'w' больше 'y', а 'y' больше 'z', например. Я мог бы просто брать тип w сразу, но его может не существовать.
if ( 'w' || 'y' || 'z') {
//код
}
В таком случае, код выполнится если придёт w или y или z ровно в таком порядке.
Позволь поспорить насчет кода по ссылке, надеюсь прочитаешь и ответишь.
ViewRecord - это зеркало Record для view, т.к. view и шаблону не требуются все возможности модели. В то-же время он наделяет сущность необходимыми для view качествами - getSomething() внутри ескейпит содержимое, т.о. ты можешь во view и шаблоне больше не думать об этом вовсе. Так-же туда можно пихать форматирование даты, дефолтные значения и прочую view-related требуху. Очевидно что в оригинальном модельном классе это не нужно, иначе получается смешивание ответственности.
Получается чистое разделение модели (Record) и её отображения (ViewRecord), у них разные методы и общая только часть данных необходимая для вывода. И при этом сами шаблоны всё еще отдельны. Получается значение (модель), его отображение (вью) и его внешний вид (шаблон) полностью разделены и могут быть полностью типизированы, что не только упрощает разработку (в теории) но и автоматическое тестирование.
Что скажешь?
>if ( 'w' || 'y' || 'z')
Бля. А я думал, что он возьмет любой из 3 вариантов, какой первым найдет. Если ты прав, то мне в общем-то этого достаточно, спасибо.
> $forDecades = preg_match('/\d\d$/', $number, $decades);
>$decades = intval(implode('', $decades));
>Тут ты используешь implode, и это говорит о том, что ты скорее всего не понимаешь, в каком формате >preg_match возвращает массив совпадений. Так как для того, чтобы вытащить совпадение, достатоно >писать $decades[0]. Советую почитать мануал по preg_match.
Окей, я действительно ступил и забыл что preg_match выдает на выходе, но если сделать как ты сказал, к примеру, то для некоторых чисел выдаёт undefined offset. Выход в браузере получаю правильный, опять же. Я просто заебался это гавно разбирать, на самом деле. (с implode всё норм работает).
> Например, в inclineWord ты по-прежнему зачем-то преобразуешь числа в строку вместо того, чтобы >использовать математические операции.
посуди сам: эта функция в любом из случаев берёт на вход не более чем трёхзначное число и далее окончание слова для числа уже зависит от его последних одной или двух цифер. Как мне качественно заменить в этой функции мои 2 строки регулярок, которые предусматривают всевозможные случаи, математическими операциями? я просто не понимаю. Если учесть то, что на вход могут попасться вообще отрицательные числа и прочие нечисти, то в моём коде вообще переписывать много чего нужно, лол.
Положительные целые числа, вот на что я опирался, когда писал этот код.
> $intoWords .= ' '.$spelling[$roundHundreds];
>Удобнее может быть собирать слова в массив, чтобы не беспокоиться о лишних пробелах между ними.
исправил, но разницы не вижу, честно говоря. в том плане, что легче код не стал, разве что мне показалось, что собирание массива со стороны выглядит более понятно, нежели строку дополнять.
В остальном ещё раз спасибо!
Экранировать не в шаблоне - плохая идея. Так как не видно, экранированы данные или нет. Плюс, если ты например, попытаешься в шаблоне обрезать данные:
<?= mb_substr($rec->getName(), 0, 20) ?>
То тут mb_substr может разрезать экранированные данные и получить что-нибудь вроде Hello &a (&a - кусок от & amp;).
Самое удобное - это автоэкранирование выводимых данных, как в твиге.
Если без экранирования, то RecordView использовать можно. Но я не уверен, оправданны ли тут расходы времени на его написание, и какой новый функционал он дает. На практике форматирование даты может быть проще делать отдельной функцией. То есть создавать такие классы стоит, когда есть какая-то выгода.
И из-за RecordView у нас получается разделение view на 2 части: класс и шаблон. В этом конечно ничего плохого нет.
Ну и мне не нравится магический __toString (он был в примере с echo $record). Так как он скрывает ошибки, которые бы выскочили при неправильном использовании объекта:
// Хотели написать $recView->getId()
echo "itemId = " . $recView;
Вообще, я сталкивался с примером, когда подобный объект View был бы полезен. Я в одном проекте в твиге решил сделать отдельные шаблоны для каждого виджета, например, для блока комментариев или блока с картой с расчетом, чтобы такой вижджет легко бы подключался к любой странице. Комментарии к статье, комментарии к каталогу и вообще к чему угодно.
Для вызова виджета нужно было передать ему довольно много параметров, порядка 6-8. Ну например, для комментариев нужно было получить список числа лайков у них и список лайков, которые поставил текущий пользователь и еще что-то, для карты - список точек и итд. И в каждом контроллере приходилось дублировать вызовы для получения этих данных вроде:
$comments = $commentsService->getCommentsForPage(...);
$commentLikes = $likesService->getLikesForComments(...);
$commentLikesSet = $likesService->getLikesSetForCommentsByUser(...);
И я поймал себя на мысли, что стоило бы сделать класс, который сам бы все это искал:
$commentsView = new CommentView($comments, $likeService);
// В шаблоне
echo $commentsView->getLikeCount($commentId);
// Если пользователь уже лайкнул комментарий
if ($commentsView->hasVoted($commentId)) { ... }
Или даже так:
$commentsView = CommentView::forPage($pageId, $commentService, $likesService);
Руки до реализации, правда не дошли. Там еще неудобство в том, что Symfony Container не поддерживает создание объекта с не фиксированными параметрами в конструкторе, и пришлось бы как-то усложнять все, например, задавая список комментариев не через конструктор:
$commentsView = $container->get('comment_view');
$commentsView->loadForPage($pageId);
Или делая фабрику:
$commentsViewFactory = $container->get('comment_view_factory');
$commentsView = $commentsViewFactory->createForPage($pageId);
Не знаю, можно ли такой объект, который сам умеет получать данные, назвать ViewModel? Мне кажется, что можно. Заметь, что у меня другой объект, который не генерирует HTML.
То, что у тебя в примере - это конечно же, аналог React, яваскрипт-фреймворк, где страница разбивается на компоненты и каждый представлен отдельным классом. И каждый объект умеет рендерить себя.
Такие вещи конечно лучше проверять на проектах посложнее, тогда вылезут преимущества и недостатки. Если какой-то анон захочет, например, сделать файлообменник или TestHub на таком View, было бы интересно посмотреть.
Ты еще пишешь, что это упрощает тестирование, это в общем верно, если в классе есть какая-то логика, которую можно тестировать.
Если у тебя есть статья, с более сложными примерами, можешь вкинуть, посмотрим. На гостевой книге увидеть преимущества и недостатки трудно.
Экранировать не в шаблоне - плохая идея. Так как не видно, экранированы данные или нет. Плюс, если ты например, попытаешься в шаблоне обрезать данные:
<?= mb_substr($rec->getName(), 0, 20) ?>
То тут mb_substr может разрезать экранированные данные и получить что-нибудь вроде Hello &a (&a - кусок от & amp;).
Самое удобное - это автоэкранирование выводимых данных, как в твиге.
Если без экранирования, то RecordView использовать можно. Но я не уверен, оправданны ли тут расходы времени на его написание, и какой новый функционал он дает. На практике форматирование даты может быть проще делать отдельной функцией. То есть создавать такие классы стоит, когда есть какая-то выгода.
И из-за RecordView у нас получается разделение view на 2 части: класс и шаблон. В этом конечно ничего плохого нет.
Ну и мне не нравится магический __toString (он был в примере с echo $record). Так как он скрывает ошибки, которые бы выскочили при неправильном использовании объекта:
// Хотели написать $recView->getId()
echo "itemId = " . $recView;
Вообще, я сталкивался с примером, когда подобный объект View был бы полезен. Я в одном проекте в твиге решил сделать отдельные шаблоны для каждого виджета, например, для блока комментариев или блока с картой с расчетом, чтобы такой вижджет легко бы подключался к любой странице. Комментарии к статье, комментарии к каталогу и вообще к чему угодно.
Для вызова виджета нужно было передать ему довольно много параметров, порядка 6-8. Ну например, для комментариев нужно было получить список числа лайков у них и список лайков, которые поставил текущий пользователь и еще что-то, для карты - список точек и итд. И в каждом контроллере приходилось дублировать вызовы для получения этих данных вроде:
$comments = $commentsService->getCommentsForPage(...);
$commentLikes = $likesService->getLikesForComments(...);
$commentLikesSet = $likesService->getLikesSetForCommentsByUser(...);
И я поймал себя на мысли, что стоило бы сделать класс, который сам бы все это искал:
$commentsView = new CommentView($comments, $likeService);
// В шаблоне
echo $commentsView->getLikeCount($commentId);
// Если пользователь уже лайкнул комментарий
if ($commentsView->hasVoted($commentId)) { ... }
Или даже так:
$commentsView = CommentView::forPage($pageId, $commentService, $likesService);
Руки до реализации, правда не дошли. Там еще неудобство в том, что Symfony Container не поддерживает создание объекта с не фиксированными параметрами в конструкторе, и пришлось бы как-то усложнять все, например, задавая список комментариев не через конструктор:
$commentsView = $container->get('comment_view');
$commentsView->loadForPage($pageId);
Или делая фабрику:
$commentsViewFactory = $container->get('comment_view_factory');
$commentsView = $commentsViewFactory->createForPage($pageId);
Не знаю, можно ли такой объект, который сам умеет получать данные, назвать ViewModel? Мне кажется, что можно. Заметь, что у меня другой объект, который не генерирует HTML.
То, что у тебя в примере - это конечно же, аналог React, яваскрипт-фреймворк, где страница разбивается на компоненты и каждый представлен отдельным классом. И каждый объект умеет рендерить себя.
Такие вещи конечно лучше проверять на проектах посложнее, тогда вылезут преимущества и недостатки. Если какой-то анон захочет, например, сделать файлообменник или TestHub на таком View, было бы интересно посмотреть.
Ты еще пишешь, что это упрощает тестирование, это в общем верно, если в классе есть какая-то логика, которую можно тестировать.
Если у тебя есть статья, с более сложными примерами, можешь вкинуть, посмотрим. На гостевой книге увидеть преимущества и недостатки трудно.
У тебя ошибки в коде, и видимо, отключен вывод предупреждений (display_errors = On) на экран, потому ты их не видишь. Начни с включения вывода ошибок.
Строки надо заключать в кавычки. Нельзя писать просто pass1.
Если ты пропустил основы, то я советую сначала почитать мой учебник из шапки или любой аналогичный.
|| это не "или" (это работает как "или" только при перечислении условий). Он предназначен для использования в таком стиле:
$a == 1 || $a == 2
Это работает так: условие вроде $a == 1 и $a == 2 проверяется и возвращается булево значение true или false. А оператор || принимает 2 булевых значения и выдает итоговое.
Потому писать "$a равно 1 или 2" нельзя. У тебя "pass1" || "pass2" просто вернет true.
Ты можешь также написать if (in_array($pass, ['p1', 'p2', 'p3'])).
>>50638
Тебе надо изучать язык последовательно, а не пропускать основы и брать готовые примеры. Так у тебя ничего не получится.
>>50399
> как приравнять строки к числам и сравнивать их
Сделать массив сопоставлений, какой букве соответствует какое число.
> Как мне найти самое большое значение массива, а сам подмассив переместить на [0] место в массиве sizes?
Тебе надо отсортировать массив с помощью usort.
> Есть еще вариант - записать номер подмассива с самым большим значением в переменную и использовать её потом. Но чет такой вариант не очень.
Вполне годный вариант.
У тебя ошибки в коде, и видимо, отключен вывод предупреждений (display_errors = On) на экран, потому ты их не видишь. Начни с включения вывода ошибок.
Строки надо заключать в кавычки. Нельзя писать просто pass1.
Если ты пропустил основы, то я советую сначала почитать мой учебник из шапки или любой аналогичный.
|| это не "или" (это работает как "или" только при перечислении условий). Он предназначен для использования в таком стиле:
$a == 1 || $a == 2
Это работает так: условие вроде $a == 1 и $a == 2 проверяется и возвращается булево значение true или false. А оператор || принимает 2 булевых значения и выдает итоговое.
Потому писать "$a равно 1 или 2" нельзя. У тебя "pass1" || "pass2" просто вернет true.
Ты можешь также написать if (in_array($pass, ['p1', 'p2', 'p3'])).
>>50638
Тебе надо изучать язык последовательно, а не пропускать основы и брать готовые примеры. Так у тебя ничего не получится.
>>50399
> как приравнять строки к числам и сравнивать их
Сделать массив сопоставлений, какой букве соответствует какое число.
> Как мне найти самое большое значение массива, а сам подмассив переместить на [0] место в массиве sizes?
Тебе надо отсортировать массив с помощью usort.
> Есть еще вариант - записать номер подмассива с самым большим значением в переменную и использовать её потом. Но чет такой вариант не очень.
Вполне годный вариант.
> Окей, я действительно ступил и забыл что preg_match выдает на выходе, но если сделать как ты сказал, к примеру, то для некоторых чисел выдаёт undefined offset
Я предлагаю вообще не использовать preg_match и строковые функции в этой задаче.
Ошибка скорее всего получается, если вообще не было совпадений с регуляркой. Ты должен понимать, как что работает, а не ставить команды наугад.
> посуди сам: эта функция в любом из случаев берёт на вход не более чем трёхзначное число и далее окончание слова для числа уже зависит от его последних одной или двух цифер. Как мне качественно заменить в этой функции мои 2 строки регулярок, которые предусматривают всевозможные случаи, математическими операциями?
Элементарно:
$lastDigit = $number % 10;
$last2Digits = $number % 100;
> исправил, но разницы не вижу, честно говоря
Не надо думать, как не поставить лишний пробел.
Переделал "цифры прописью":
https://ideone.com/i4Ktf9
Переделал калькулятор:
https://ideone.com/MZjuzH
Я полный аутист, если потратил на цифры прописью 1,5 месяца или это норма? Можно мне перейти на второй лвл?
https://ideone.com/dnOx6X такс, я сделал, правда объёмно получилось со стороны, может мне не стоило переменные так называть в последней функции
>$lastDigit = $number % 10;
>$last2Digits = $number % 100
чёрт, я до самого последнего момента был уверен в том, что в случае если у меня будет $number == 1, к примеру, то получится что я поделю 1 на 10 и остатка в виде целого числа как такового не будет и соответствия к числу тоже, откуда ведь взяться целому остатку, если при делении выходит число меньше единицы, а оказывается я просто не помню столь простой приём в математике, по итогу я даже не стал писать код, построенный на подобной схеме, но позже увидел его у другого анона, внедрил в свой код, проверил на всякий, а вдруг работает? по итогу он работает, ы
под приёмом в математике я подрозумеваю то, когда делишь меньшее число (делимое) на большее(делитель) с остатком, то остатком будет являться делимое число
А я последнее время проценты умножением считаю. Совсем поехал наверное.
if находится в цикле. При каждом прохождении даже с break будет перезаписываться же, нет? А break 2; сломает весь цикл, чего мне не нужно.
Но у меня нет массивов.
В общем, раньше я брал значение при первом прохождении цикла for.
if ($i === 0) {$one = $two;}
Но оказалось, что такой вариант не всегда подходит.
Запости весть кусок кода - я понять логики не могу. У тебя там либо с циклом не то, либо ещё что.
Ну или начинай с конца цикл. Хотя велосипедно выйдет.
Заведи массив и все попадания копируй туда по счётчику. Должно сработать.
Примерно так было:
for($u=0; $u<10; $u++) {
тут я получаю разные значения $two
if ($u === 0) {$one = $two; } }
использую $one вне цикла
Но потом оказалось, что мне нужно не первое значение $two, а первое не пустое значение.
1. Можно простой выйти из цикла при первом же присвоении.
2. Просто заводишь массив и добавляешь туда новые значения. И будет у тебя первый if в этом $digits[1].
Из цикла нельзя выходить, он должен до конца отслужить. А вот массив вроде подойдет, спасибо.
Еще спрошу, а если парсер нужен с авторизацией, или прокси, или юзерагентом, то нужно использовать cURL. Есть какие-то библиотеки, которые с ним нормально работают или только через регулярки поиск делать? Пробовал как-то DiDOM примирить с ним, так не получилось.
Прокрастинация не дает жить.
может кто-нибудь объяснить, как нужно реализовать функцию makeFirstLetterUppercase
Имеем переменную с необработанным текстом.
1. Взять первую букву.
2. Сделать эту букву заглавной.
3. Сделать все буквы прописными (Результат пишем в другую переменную).
4. Убрать первую букву, от предыдущей переменной.
5. Соединить переменные из пункта 2 и 4.
Готово!
function curl_get_contents($page_url) {
$curl = curl_init();
......
curl_setopt($curl, CURLOPT_URL, $page_url);
$curlname = curl_exec($curl);
return $curlname; }
И есть элемент массива $match[0][0].
echo $match[0][0]; - выводит ссылку.
$w = curl_get_contents('https://ссылка');
echo $w; - выводит содержимое сайта.
$w = curl_get_contents($match[0][0]);
echo $w; - нихуя не выводит. А var_dump выводит пустую string.
В чем причина?
так я смог сделать первую букву заглавной, но там ведь несколько предложений в переменной.
Подумой каким знаком разделяются предложения и как строку можно разбить на массив подстрок.
Сделал море проверок, не работает, только если я вставляю этот ебаный элемент из массива. Если вставить переменную с ссылкой - ок. Если просто ссылку - ок. Если переменной присвоить значение $match[0][0] и вставить - не работает! Если перебирать foreach ($match[0], $m) {echo curl_get_contents($m;} - опять нихуя. Что за магия?
сделать это не было проблемой, проблемой стало как подстроки изменять.
вот над этим я голову целый день и ломаю
Ладно, забыл про функцию, весь код из неё вынес.
foreach ($match[0] as $m) {
echo $m; - выводит ссылку, всё отлично.
..............
curl_setopt($curl, CURLOPT_URL, $m);
echo curl_exec($curl); } - снова нихуя! Да как, блядь, так? Прописываю ссылку вручную - работает! Вставляю что-то динамическое - не работает! А
Допустим, что у нас предложения разделяются знаком "равно".
Разбиваем текст на массив предложений:
$sentences = explode('=', $text);
Делаем в каждом предложении по очереди букву заглавной:
$fixed = [];
foreach ($sentences as $sentence) {
$fixed[] = uppercaseFirst($sentence);
}
Имеем в $fixed массив преобразованных предложений.
Конечно, в реальности предложения могут разделяться разными символами - точками, знаками вопроса итд. Тут можно применить preg_split.
Есть конечно и более продвинутые способы. Например, написать регулярку для нахождения первых букв в предложении и заменять их на заглавные с помощью preg_replace_callback:
$result = preg_replace_callback(регулярка, function ($letter) {
return mb_strtoupper($letter);
}, текст);
Чтобы понять этот код, надо знать про анонимные функции: http://php.net/manual/ru/functions.anonymous.php и прочесть мануал по preg_replace_callback.
Сделал предВекторную задачу, буду благодарен за проверку!
https://ideone.com/fzfbYB
Что сделано?
Запилил два класса: один для тестового типа вопросов, второй для вопросов с числовым ответом. Оба наследники абстрактного класса, который содержит базовые свойства и два абстрактных метода.
Программа не полагается на то, что существует всего два вида вопросов. Позволяет добавлять новые виды вопросов, не трогая существующие классы.
Не стал делать общую нумерацию и общие итоговые результаты, т. к. в условии об этом ничего не сказано.
Вобщем я стандартный гуманитарий который проебал 5 лет на говно-специальность по которой не нашел работу, потом еще 1 год поработал в забегаловке у клоуна. Решил изменить свою жизнь и стать прогером (в основном изза шанса имигрировать). Итак мой план:
1) Есть материальная база для того чтобы пол года учиться по 12 часов, дальше я должен буду устроиться версталой/пхп-макакой/фрилансером.
2) Думаю параллельно поступить на самое дешевую заочку для корки (я слышал без нее имигрировать никак)
3) Учить английский, чтобы перекатываться на анг-материалы для учебы.
Норм план? С чего начать? Есть ли норм бесплтные курсы по HTML/СSS в русском интернете ?
>Шапку читай
HTML/CSS там тоже есть, я просто треда не нашел ?
>забудь про 12 часов каждый день
Почему?
https://2ch.hk/web/res/116059.html (М)
Вот вёрстка тред и у опа в шапке есть ряд задач по ней и что откуда учить.
Ты не сможешь по 12 часов учить физически и это будет не эффективно очень. Лучше стабильно не спеша идти без наполеоновских планов. Иначе велик шанс забросить и забить голову не дав ей время на обработку.
раскоментил extension=mysqli и скопировал libmySQL.dll в папку windows
Не работает
Для apache2.2/php5 это работало, только там было mysql вместо mysqli
Добавил в конец регулярки любое число возможных пробелов \s. Вроде работает, пробуй.
$text = preg_split("/(?<=[\.!?])\s/ui", $text);
Спасибо! А еще такой вопрос в регулярках для поиска пробела лучше пользоваться [ ] или \s. Знаю что \s означает не только пробел, но и перенос строки. Но может есть какой нибудь единый программистский стандарт. Или кашу маслом не испортишь и везде лучше бахать \s
Я выполняю это
file_get_contents('http://www.google.com/?var1=1&var2=2')
Но ебаная & автоматически меняется на & www.google.com/?var1=1&var2=2
И нихуя естественно не работает.
Я пробовал через curl, нихуя.
Я гуглил, пробовал другие методы.
Ни-ХУ-Я.
Что за хуйня? Я первый раз такое гавно встречаю.
Если я верно понял, ты думаешь, что file_get_contents что-то делает с переданным тобой URL?
Поясни, почему ты так решил?
я смотрю error лог.
Я вижу url до использования и после. Он нормальный, с нормальной &.
А когда использую file_get_contents("url");, то в error логе вижу этот url, но вместо & там & и естественно ошибку.
а) Создавать в SQL таблицу для каждой группы, тип группы указывать в названии таблицы: "котики_table" | "пёсики_table"
б) Создать одну таблицу и добавить колонку "тип": котики | пёсики | нёх и т.д.
в) Что-то еще?..
2) Задача та же, но: набор аттрибутов у каждой группы может отличаться.
а) Создавать в SQL таблицу для каждой группы, тип группы указывать в названии таблицы: "котики_table" | "пёсики_table"
б) Создать одну таблицу со всеми возможными аттрибутами и добавить колонку "тип": котики | пёсики | нёх и т.д.
в) Что-то еще?..
Пожалуйста, дискасс.
хз
Вот выхлоп моего курла
curl -ILv "http://www.google.com/?var1=1&var2=2"
Trying 64.233.165.147...
Connected to www.google.com (64.233.165.147) port 80 (#0)
> HEAD /?var1=1&var2=2 HTTP/1.1
> Host: www.google.com
> User-Agent: curl/7.47.0
> Accept: /
>
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
Нихуя он не меняет
Ну так это говорит только о том, что данные экранируются при записи в error_log, но не значит, что это делает функция file_get_contents. Открой мануал по ней и проверь сам.
Можно просто пробел без всего: /hello world/u
\s обычно удобнее тем, что он позволяет ловить и другие похожие на пробел символы вроде табуляции \t и перевода строки \n.
Более того, в Юникоде есть огромное число пробелов, о которых начинающие разработчики и не слышали:
видимые пробелы https://habr.com/post/23250/
невидимые https://habr.com/post/311518/
Невнимательно читал урок. Надо добавлять флаг u для поддержки utf-8, иначе нелатинские символы ломаются.
Большое спасибо, впредь буду внимательнее.
В общем, ошибки curl никакие не выводит, возвращает только NULL. Может, у меня аналогичная проблема: >>52722 ? Может, url каким-то образом видоизменяется, когда он подаётся через foreach?
Url выглядит так: сайт/index.php?page=post&s=view&id=437
Дело в пост-запросе и его нужно через CURLOPT_POSTFIELDS отправлять?
Думал, дело в прокси, но нет - без прокси просто выводится заглушка роскомнадзора, с прокси - null.
Пробовал ставить задержку и использовать multicurl. Тоже нихуя.
Сделай так же, как я и посмотри error лог в корневой папке
file_get_contents('http://www.google.com/?var1=1&var2=2');
Свой url только вставь.
Вообще можешь новый чистый файл создать test.php
Вставить код этот и пройти на файл, а потом глянь error
У меня там сразу показывает ошибку и url, в котором & заменена &
Я до сих пор не могу эту хуйню решить
>>51700
Никакой магии там нет и быть не может.
Тебе надо, когда ты используешь curl, проверять, не вернул ли он ошибку. А именно, использовать функцию curl_error, посмотри пример в мануале: http://php.net/manual/ru/function.curl-error.php
Также, переменные лучше дампить с помощью var_dump(), чтобы был виден тип.
Также, надо включить отображение ошибок (display_errors) в php.ini. Это конечно нужно делать только на локальном сервере, а на продакшене надо смотреть логи.
Я подозреваю, что ты что-то там не учел. Например, ты пытаешься использовать повторно уже использованный CURL handle, или меняешь переменную или еще что-то не то делаешь. Или какие-то посторонние символы в URL могут быть
>>53039
Это называется "наследование таблиц". Вот паттерны для решения этой задачи:
- http://design-pattern.ru/patterns/class-table-inheritance.html
- http://design-pattern.ru/patterns/single-table-inheritance.html
- http://design-pattern.ru/patterns/concrete-table-inheritance.html
Также, на случай, когда есть много характеристик, которые могут присутствовать или отсутствовать, есть Entity-Attribute-Value.
>>52337
Проблема, которую ты упомянул, бывает из-за того, что при запуске PHP в составе Апача Windows ищет библиотеки dll в папке Апача, а не PHP, и естественно не находит. Потому приходится их копировать либо в папку Апача, либо в одну из папок в переменной окружения PATH (например, папку Windows). Порядок поиска dll описан тут: https://msdn.microsoft.com/ru-ru/library/7d83bc18.aspx
Я бы советовал использовать программу вроде dependency walker, которая показвыает зависимости для exe- и dll-файлов. С ее помощью ты можешь определить, какие dll нужны тому или иному расширению, в том числе расширению mysqli.
Еще один вариант - добавить папку PHP (где хранятся зависимости) в PATH и перезалогиниться в систему. Про PATH можно почитать в интернете или в моем уроке https://github.com/codedokode/pasta/blob/master/soft/cli.md
>>52267
Если ты всерьез будешь полгода учиться по 12 часов, а также, не будешь бояться задавать вопросы и просить дополнительные задачки в нашем треде, из тебя выйдет зверский программист. Хотя я не очень уверен в том, что у тебя хватит сил столько трудиться.
Английский, конечно, пригодится.
>>51700
Никакой магии там нет и быть не может.
Тебе надо, когда ты используешь curl, проверять, не вернул ли он ошибку. А именно, использовать функцию curl_error, посмотри пример в мануале: http://php.net/manual/ru/function.curl-error.php
Также, переменные лучше дампить с помощью var_dump(), чтобы был виден тип.
Также, надо включить отображение ошибок (display_errors) в php.ini. Это конечно нужно делать только на локальном сервере, а на продакшене надо смотреть логи.
Я подозреваю, что ты что-то там не учел. Например, ты пытаешься использовать повторно уже использованный CURL handle, или меняешь переменную или еще что-то не то делаешь. Или какие-то посторонние символы в URL могут быть
>>53039
Это называется "наследование таблиц". Вот паттерны для решения этой задачи:
- http://design-pattern.ru/patterns/class-table-inheritance.html
- http://design-pattern.ru/patterns/single-table-inheritance.html
- http://design-pattern.ru/patterns/concrete-table-inheritance.html
Также, на случай, когда есть много характеристик, которые могут присутствовать или отсутствовать, есть Entity-Attribute-Value.
>>52337
Проблема, которую ты упомянул, бывает из-за того, что при запуске PHP в составе Апача Windows ищет библиотеки dll в папке Апача, а не PHP, и естественно не находит. Потому приходится их копировать либо в папку Апача, либо в одну из папок в переменной окружения PATH (например, папку Windows). Порядок поиска dll описан тут: https://msdn.microsoft.com/ru-ru/library/7d83bc18.aspx
Я бы советовал использовать программу вроде dependency walker, которая показвыает зависимости для exe- и dll-файлов. С ее помощью ты можешь определить, какие dll нужны тому или иному расширению, в том числе расширению mysqli.
Еще один вариант - добавить папку PHP (где хранятся зависимости) в PATH и перезалогиниться в систему. Про PATH можно почитать в интернете или в моем уроке https://github.com/codedokode/pasta/blob/master/soft/cli.md
>>52267
Если ты всерьез будешь полгода учиться по 12 часов, а также, не будешь бояться задавать вопросы и просить дополнительные задачки в нашем треде, из тебя выйдет зверский программист. Хотя я не очень уверен в том, что у тебя хватит сил столько трудиться.
Английский, конечно, пригодится.
Спроектированы классы не очень удачно. А именно, ты по сути сделал две похожих копии кода и у тебя полпрограммы отвечает за вопросы с выбором и вторая половина - за числовые. При этом общего кода, который бы работал с обоими типами вопросов, по сути нет.
Ну например, у тебя сделан отдельно вывод вопросов с выбором и отдельно - числовых. Но почему их нельзя выводить в общем списке? Вот, как это может выглядеть:
// на входе - массив, содержит объекты-вопросы обоих типов
function printAllQuestions($questions)
{
foreach ($questions as $question) {
$question->print();
}
}
Проблема тут в неправильном проектировании класса. Посмотри на базовый класс вопроса:
abstract class AbstractQuestion
{
abstract function printQuestions($questions);
...
Один объект представляет один вопрос. Логично, чтобы каждый объект умел бы выводить "свой" вопрос на экран. Но у тебя такого нет - у тебя только метод вывода всех вопросов, причем их надо передавать отдельно. Стоило бы сделать так:
abstract function print(); // выводит себя на экран
Или, что лучше, сделать метод getAsString(), чтобы он не выводил себя, а лишь возвращал текст с вариантами ответов, чтобы вызывающий этот метод сам решал, что с ним дальше делать - вывести, записать в файл или сделать что-то еще.
То же касается проверки ответа. Логичнее, чтобы объект вопроса проверял только ответ на "свой" вопрос, а именно:
abstract function checkAnswer($answer)
Это позволит избавиться от существующей копипасты в методах checkAnswers и printQuestions.
Тебе придется продумать, что должна возвращать checkAnswer и как корректно считать баллы. Дополнительное усложнение: представь, что у нас в вопросе с выбором кроме варианта "правильный ответ" и "неправильный ответ" возможен еще "почти правильный ответ", за который дается половина от указанного числа баллов. Попробуй добавить такую возможность.
Также, у тебя не используется deviation (допустимое отклонение) в числовых вопросах.
Также, есть еще один трюк. Сейчас у тебя при создании вопроса можно забыть заполнить одно из полей. Если же указать обязательные поля в конструкторе, то забыть о них не получится:
class NumericalQuestion
{
public function __construct($text, $correctAnswer, $deviation)
{
....
}
...
$q = new NumericalQuestion('Чему равно Пи?', 3.14, 0.01);
Попробуй переделать код с учетом этого.
Спроектированы классы не очень удачно. А именно, ты по сути сделал две похожих копии кода и у тебя полпрограммы отвечает за вопросы с выбором и вторая половина - за числовые. При этом общего кода, который бы работал с обоими типами вопросов, по сути нет.
Ну например, у тебя сделан отдельно вывод вопросов с выбором и отдельно - числовых. Но почему их нельзя выводить в общем списке? Вот, как это может выглядеть:
// на входе - массив, содержит объекты-вопросы обоих типов
function printAllQuestions($questions)
{
foreach ($questions as $question) {
$question->print();
}
}
Проблема тут в неправильном проектировании класса. Посмотри на базовый класс вопроса:
abstract class AbstractQuestion
{
abstract function printQuestions($questions);
...
Один объект представляет один вопрос. Логично, чтобы каждый объект умел бы выводить "свой" вопрос на экран. Но у тебя такого нет - у тебя только метод вывода всех вопросов, причем их надо передавать отдельно. Стоило бы сделать так:
abstract function print(); // выводит себя на экран
Или, что лучше, сделать метод getAsString(), чтобы он не выводил себя, а лишь возвращал текст с вариантами ответов, чтобы вызывающий этот метод сам решал, что с ним дальше делать - вывести, записать в файл или сделать что-то еще.
То же касается проверки ответа. Логичнее, чтобы объект вопроса проверял только ответ на "свой" вопрос, а именно:
abstract function checkAnswer($answer)
Это позволит избавиться от существующей копипасты в методах checkAnswers и printQuestions.
Тебе придется продумать, что должна возвращать checkAnswer и как корректно считать баллы. Дополнительное усложнение: представь, что у нас в вопросе с выбором кроме варианта "правильный ответ" и "неправильный ответ" возможен еще "почти правильный ответ", за который дается половина от указанного числа баллов. Попробуй добавить такую возможность.
Также, у тебя не используется deviation (допустимое отклонение) в числовых вопросах.
Также, есть еще один трюк. Сейчас у тебя при создании вопроса можно забыть заполнить одно из полей. Если же указать обязательные поля в конструкторе, то забыть о них не получится:
class NumericalQuestion
{
public function __construct($text, $correctAnswer, $deviation)
{
....
}
...
$q = new NumericalQuestion('Чему равно Пи?', 3.14, 0.01);
Попробуй переделать код с учетом этого.
Она там специально стоит, чтобы парсеры не работали. А так, можешь попробовать куки из браузера скопировать.
>>51212
Плохо пробовал, по моему так скачивание HTML файла и его разбор никак не пересекаются.
>>51129
Мне кажется, этот код не надо было 2 раза копировать:
$decades = $number % 100;
} elseif (array_key_exists($decades, $spelling)) {
array_push($words, $spelling[$hundreds], $spelling[$decades]);
Это можно было сделать так:
если (в числе есть сотни) {
добавляем слово для сотен
}
если (число заканчивается на 11-19) {
добавляем слово для них;
} иначе {
если (число заканчивается на 2x-9x) {
...
}
если (в числе есть единицы) {
..
}
}
В numberToText не очень понятно, зачем заводить несколько переменных для одного и того же: $thousandsForMillions, $thousandsForThousands. Можно тут использовать одну переменную и считать ее в любом случае. Если число меньше 1000, там просто будет 0.
Тогда функция numberToText станет гораздо меньше.
>>50963
> Переделал "цифры прописью": https://ideone.com/i4Ktf9
>if ($number % 100 == 10 or $number % 100 >= 20 and $number % 100 <= 99) {
Тут надо ставить скобки, чтобы не было сомнений в том, как понимать условия: a or (b and c) или (a or b) and c.
> // Обработка нуля
> if ($numberToText == 'ноль' and $lengthOfNumber > 0) {
Лучше просто писать if ($numbers[$i] == 0), то есть проверять исходное число, а не строку, которую вернула функция.
А так, верно.
> Переделал калькулятор: https://ideone.com/MZjuzH
Ок, верно, хотя не очень хорошо, что он пропускает посторонние символы вместо вывода ошибки. Хотя в задаче это и не требовалось.
Она там специально стоит, чтобы парсеры не работали. А так, можешь попробовать куки из браузера скопировать.
>>51212
Плохо пробовал, по моему так скачивание HTML файла и его разбор никак не пересекаются.
>>51129
Мне кажется, этот код не надо было 2 раза копировать:
$decades = $number % 100;
} elseif (array_key_exists($decades, $spelling)) {
array_push($words, $spelling[$hundreds], $spelling[$decades]);
Это можно было сделать так:
если (в числе есть сотни) {
добавляем слово для сотен
}
если (число заканчивается на 11-19) {
добавляем слово для них;
} иначе {
если (число заканчивается на 2x-9x) {
...
}
если (в числе есть единицы) {
..
}
}
В numberToText не очень понятно, зачем заводить несколько переменных для одного и того же: $thousandsForMillions, $thousandsForThousands. Можно тут использовать одну переменную и считать ее в любом случае. Если число меньше 1000, там просто будет 0.
Тогда функция numberToText станет гораздо меньше.
>>50963
> Переделал "цифры прописью": https://ideone.com/i4Ktf9
>if ($number % 100 == 10 or $number % 100 >= 20 and $number % 100 <= 99) {
Тут надо ставить скобки, чтобы не было сомнений в том, как понимать условия: a or (b and c) или (a or b) and c.
> // Обработка нуля
> if ($numberToText == 'ноль' and $lengthOfNumber > 0) {
Лучше просто писать if ($numbers[$i] == 0), то есть проверять исходное число, а не строку, которую вернула функция.
А так, верно.
> Переделал калькулятор: https://ideone.com/MZjuzH
Ок, верно, хотя не очень хорошо, что он пропускает посторонние символы вместо вывода ошибки. Хотя в задаче это и не требовалось.
> Тут беда в том что я не знаю как лучше обойти входной массив, еще я не уверен в том как входной массив должен выглядеть,
Можно так, как у тебя, можно набором пар вопрос-ответ:
[
{"question": 123, "answer": "345"},
{"question": 567, "answer": "890"},
]
Лучше выбирать формат так, чтобы его было проще проверить. К примеру, если ты указываешь id вопросов, нам надо проверять, а существуют ли такие вопросы, а относятся ли они к этому тесту и тд. А если есть возможность указать номер вопроса, то все упрощается - достаточно проверить, что он меньше максимального. Но это требует хранить порядковые номера вопросов и имеет недостаток, что при редактировании теста в процессе прохождения (согласен, такое лучше не допускать) номера вопросов изменятся.
> Я ведь объект Тест изначально загружаю, поэтому была еще мысль проходить как раз таки входной массив, и доктриной забирать вопросы и ответы из бд,
Наверно, имеет смысл в объекте Test сделать поиск вопроса по id, а в вопросе - поиск варианта ответа по id. Тогда пользователь не сможет подсунуть id вопроса из другого теста.
>>50233
Конечно, показывай.
>>50223
>>48379
http://sandbox.onlinephpfunctions.com/code/b030e2374845be468830adbc0958f58023b83028
> public function getSalaryTotal()
Тут можно использовать тайп-хинт:
function getSalaryTotal(): float
float вроде по умолчанию (при отсутствии strict_types) позволяет возвращать int.
> addEmployeesToDepartment
Можно не писать toDepartment, так как это очевидно из названия класса.
> getNameDepartment
И тут тоже.
> public function addEmployeesToDepartment(Employee $employee, int $count)
Здесь ошибка. Ты добавляешь в массив не N разных объектов, а N указателей на один и тот же объект. Если ты поменяешь этом работнику ранг, то это будет выглядеть, как будто всем работникам его поменяли.
А для антикризисных мер надо менять характеристики индивидуально.
> public function getEmployeesByRankAndPosition(string $position, array $rankForIncrease = NULL)
> if (get_class($employeer) == $position) {
Лучше наверно использовать $x instanceof Class, потому что он заодно будет искать и наследников класса Class. А наследники обычно считаются совместимыми с предками. Хотя тут можно поспорить, конечно.
В этом методе можно было сделать единственный цикл вместо двух и упростить код. Кстати, вот, как можно сделать метод поиска работников по любому условию:
$result = $dep->pickEmployees(function ($e) {
return $e->getRank() == 2 && $e instanceof Manager;
});
> public function replaceEmployees(string $position, array $employeesForAdd)
Мне кажется, это не очень удачная функция и логичнее было бы сделать метод fireEmployees(array $employees), то есть явно указать, кого надо уволить, а не убрать всех и часть добавить обратно.
Код сделан не удачно, так как ты там модифицируешь массив, который обходишь. Это позволяет легко сделать ошибку, и так лучше не делать вообще. Было бы логичнее, например, собрать ключи элементов, которые надо удалить, и после цикла удалить их. Либо сделать новый массив работников и после цикла сохранить его в $this->employees.
> public function __construct($rank, $isHead)
Тут не помешали бы тайп-хинты для аргументов.
> public function setIsHead(int $isHead)
Можно было бы использовать булев тип (да, он не описан в учебнике, но какая разница): http://php.net/manual/ru/language.types.boolean.php
> class Manager extends Employee
> public function getBaseSalary() : int
Тут проще было сделать так, без полей:
public function getInitialBaseSalary() : int
{
return 200;
}
А в Employee сделать эти поля и в конструкторе инициализировать их:
public function __construct(...)
{
$this->baseSalary = $this->getInitialBaseSalary();
}
Это позволяет нам в дальнейшем менять базовую ставку. И избежать повторения кода.
В твоем варианте нет гарантии, что в наследниках Employee всегда будет метод вроде setBaseSalary() так как он не упомянут в базовом классе.
> private function cmp($a, $b)
Тут бы не помешал краткий комментарий, что это и что оно сравнивает и как.
Кстати, для документирования кода есть общепринятый синтаксис: phpDoc (скопированный с Явы):
- http://omurashov.ru/docblock-in-php-documentation/
- https://docs.phpdoc.org/
- его пытаются стандартизовать как PSR-5: https://github.com/phpDocumentor/fig-standards/blob/master/proposed/phpdoc.md
phpDoc парсится IDE, а также из него можно сгенерировать документацию вот такого вида: https://api.symfony.com/2.8/Symfony/Component/HttpFoundation/Request.html
Замену руководителя логичнее делать методом в Department:
$dep->appointHead($newHead);
Во-первых, знать, кто руководитель - это явно зона ответственности Департамента. Во-вторых, так гораздо проще и если где-то еще надо назначить главу, то достаточно вызвать один метод, а не писать портянку кода.
Ты по сути здесь обходишь инкапсуляцию (сокрытие данных внутри объекта), извлекаешь список работников и в обход Департамента меняешь им признак босса.
Мы бы могли также запретить замену руководителя в обход Департамента, если бы сделали приватное поле "глава" в Департаменте вместо общедоступного поля "руководитель" в работнике. Но это может значительно усложнить код (но если хочешь, можешь попробовать сделать).
В остальном верно. Если интересно, есть еще задача на ООП про Гостиницу: https://phpclub.tech/pr/res/1082507.html#1097078
> Тут беда в том что я не знаю как лучше обойти входной массив, еще я не уверен в том как входной массив должен выглядеть,
Можно так, как у тебя, можно набором пар вопрос-ответ:
[
{"question": 123, "answer": "345"},
{"question": 567, "answer": "890"},
]
Лучше выбирать формат так, чтобы его было проще проверить. К примеру, если ты указываешь id вопросов, нам надо проверять, а существуют ли такие вопросы, а относятся ли они к этому тесту и тд. А если есть возможность указать номер вопроса, то все упрощается - достаточно проверить, что он меньше максимального. Но это требует хранить порядковые номера вопросов и имеет недостаток, что при редактировании теста в процессе прохождения (согласен, такое лучше не допускать) номера вопросов изменятся.
> Я ведь объект Тест изначально загружаю, поэтому была еще мысль проходить как раз таки входной массив, и доктриной забирать вопросы и ответы из бд,
Наверно, имеет смысл в объекте Test сделать поиск вопроса по id, а в вопросе - поиск варианта ответа по id. Тогда пользователь не сможет подсунуть id вопроса из другого теста.
>>50233
Конечно, показывай.
>>50223
>>48379
http://sandbox.onlinephpfunctions.com/code/b030e2374845be468830adbc0958f58023b83028
> public function getSalaryTotal()
Тут можно использовать тайп-хинт:
function getSalaryTotal(): float
float вроде по умолчанию (при отсутствии strict_types) позволяет возвращать int.
> addEmployeesToDepartment
Можно не писать toDepartment, так как это очевидно из названия класса.
> getNameDepartment
И тут тоже.
> public function addEmployeesToDepartment(Employee $employee, int $count)
Здесь ошибка. Ты добавляешь в массив не N разных объектов, а N указателей на один и тот же объект. Если ты поменяешь этом работнику ранг, то это будет выглядеть, как будто всем работникам его поменяли.
А для антикризисных мер надо менять характеристики индивидуально.
> public function getEmployeesByRankAndPosition(string $position, array $rankForIncrease = NULL)
> if (get_class($employeer) == $position) {
Лучше наверно использовать $x instanceof Class, потому что он заодно будет искать и наследников класса Class. А наследники обычно считаются совместимыми с предками. Хотя тут можно поспорить, конечно.
В этом методе можно было сделать единственный цикл вместо двух и упростить код. Кстати, вот, как можно сделать метод поиска работников по любому условию:
$result = $dep->pickEmployees(function ($e) {
return $e->getRank() == 2 && $e instanceof Manager;
});
> public function replaceEmployees(string $position, array $employeesForAdd)
Мне кажется, это не очень удачная функция и логичнее было бы сделать метод fireEmployees(array $employees), то есть явно указать, кого надо уволить, а не убрать всех и часть добавить обратно.
Код сделан не удачно, так как ты там модифицируешь массив, который обходишь. Это позволяет легко сделать ошибку, и так лучше не делать вообще. Было бы логичнее, например, собрать ключи элементов, которые надо удалить, и после цикла удалить их. Либо сделать новый массив работников и после цикла сохранить его в $this->employees.
> public function __construct($rank, $isHead)
Тут не помешали бы тайп-хинты для аргументов.
> public function setIsHead(int $isHead)
Можно было бы использовать булев тип (да, он не описан в учебнике, но какая разница): http://php.net/manual/ru/language.types.boolean.php
> class Manager extends Employee
> public function getBaseSalary() : int
Тут проще было сделать так, без полей:
public function getInitialBaseSalary() : int
{
return 200;
}
А в Employee сделать эти поля и в конструкторе инициализировать их:
public function __construct(...)
{
$this->baseSalary = $this->getInitialBaseSalary();
}
Это позволяет нам в дальнейшем менять базовую ставку. И избежать повторения кода.
В твоем варианте нет гарантии, что в наследниках Employee всегда будет метод вроде setBaseSalary() так как он не упомянут в базовом классе.
> private function cmp($a, $b)
Тут бы не помешал краткий комментарий, что это и что оно сравнивает и как.
Кстати, для документирования кода есть общепринятый синтаксис: phpDoc (скопированный с Явы):
- http://omurashov.ru/docblock-in-php-documentation/
- https://docs.phpdoc.org/
- его пытаются стандартизовать как PSR-5: https://github.com/phpDocumentor/fig-standards/blob/master/proposed/phpdoc.md
phpDoc парсится IDE, а также из него можно сгенерировать документацию вот такого вида: https://api.symfony.com/2.8/Symfony/Component/HttpFoundation/Request.html
Замену руководителя логичнее делать методом в Department:
$dep->appointHead($newHead);
Во-первых, знать, кто руководитель - это явно зона ответственности Департамента. Во-вторых, так гораздо проще и если где-то еще надо назначить главу, то достаточно вызвать один метод, а не писать портянку кода.
Ты по сути здесь обходишь инкапсуляцию (сокрытие данных внутри объекта), извлекаешь список работников и в обход Департамента меняешь им признак босса.
Мы бы могли также запретить замену руководителя в обход Департамента, если бы сделали приватное поле "глава" в Департаменте вместо общедоступного поля "руководитель" в работнике. Но это может значительно усложнить код (но если хочешь, можешь попробовать сделать).
В остальном верно. Если интересно, есть еще задача на ООП про Гостиницу: https://phpclub.tech/pr/res/1082507.html#1097078
Ты можешь сделать минимальный пример кода, который по-твоему работает с ошибкой? Убрать все, что к ней не относится. Тогда я или другой анон мог бы запустить код у себя и проверить.
Вот есть такой сайт, который тебе в ответ на HTTP-запрос отдает параметры этого запроса в JSON: http://httpbin.org/#/HTTP_Methods/get_get
Вот я делаю файл test.php такого вида:
<?php
$r = file_get_contents('http://httpbin.org/get?a=1&b=2');
var_dump($r);
echo "\n";
И запускаю в командной строке: php /tmp/test.php
Выводится:
string(198) "{
"args": {
"a": "1",
"b": "2"
},
"headers": {
"Connection": "close",
"Host": "httpbin.org"
},
"origin": "185.141.61.117",
"url": "http://httpbin.org/get?a=1&b=2"
}
"
То есть сервер "видит" URL точно так же, как я указал. Ничего не заменяется.
Наконец, ты можешь сделать свой "сервер" на коленке, установив утилиту вроде netcat, которая умеет "слушать" TCP-порт: https://ru.wikipedia.org/wiki/Netcat
Ее можно запустить после установки под Линуксом командой:
nc -v -l -p 8001
Она не сможет ответить на запрос от PHP-кода, но она покажет, что было прислано. Меняем URL в PHP-коде выше на http://127.0.0.1:8001/?a=1&b=2 (127.0.0.1 значит соединяться с своим же компьютером, 8001 - номер порта, на котором мы подняли сервер). Запускаем в одной консоли netcat, в другой PHP код.
Вот, что выводит netcat у меня:
GET /get?a=1&b=2 HTTP/1.0
Host: 127.0.0.1:8001
Connection: close
Как видишь, HTTP запрос содержит правильный URL.
Может быть, ты что-то путаешь. Например, ты скачиваешь страницу с Гугла и извлекаешь URL из ее тела, где он выводится в экранированном Гуглом виде.
Попробуй поэкспериментировать, как я описал. Если ты используешь Windows, то есть версия netcat для нее: https://github.com/diegocr/netcat или https://eternallybored.org/misc/netcat/
Если ты не умеешь пользоваться командной строкой, относительно простой гайд: https://github.com/codedokode/pasta/blob/master/soft/cli.md
Хватит искать проблему вслепую. Надо разобраться, в чем дело.
Ты можешь сделать минимальный пример кода, который по-твоему работает с ошибкой? Убрать все, что к ней не относится. Тогда я или другой анон мог бы запустить код у себя и проверить.
Вот есть такой сайт, который тебе в ответ на HTTP-запрос отдает параметры этого запроса в JSON: http://httpbin.org/#/HTTP_Methods/get_get
Вот я делаю файл test.php такого вида:
<?php
$r = file_get_contents('http://httpbin.org/get?a=1&b=2');
var_dump($r);
echo "\n";
И запускаю в командной строке: php /tmp/test.php
Выводится:
string(198) "{
"args": {
"a": "1",
"b": "2"
},
"headers": {
"Connection": "close",
"Host": "httpbin.org"
},
"origin": "185.141.61.117",
"url": "http://httpbin.org/get?a=1&b=2"
}
"
То есть сервер "видит" URL точно так же, как я указал. Ничего не заменяется.
Наконец, ты можешь сделать свой "сервер" на коленке, установив утилиту вроде netcat, которая умеет "слушать" TCP-порт: https://ru.wikipedia.org/wiki/Netcat
Ее можно запустить после установки под Линуксом командой:
nc -v -l -p 8001
Она не сможет ответить на запрос от PHP-кода, но она покажет, что было прислано. Меняем URL в PHP-коде выше на http://127.0.0.1:8001/?a=1&b=2 (127.0.0.1 значит соединяться с своим же компьютером, 8001 - номер порта, на котором мы подняли сервер). Запускаем в одной консоли netcat, в другой PHP код.
Вот, что выводит netcat у меня:
GET /get?a=1&b=2 HTTP/1.0
Host: 127.0.0.1:8001
Connection: close
Как видишь, HTTP запрос содержит правильный URL.
Может быть, ты что-то путаешь. Например, ты скачиваешь страницу с Гугла и извлекаешь URL из ее тела, где он выводится в экранированном Гуглом виде.
Попробуй поэкспериментировать, как я описал. Если ты используешь Windows, то есть версия netcat для нее: https://github.com/diegocr/netcat или https://eternallybored.org/misc/netcat/
Если ты не умеешь пользоваться командной строкой, относительно простой гайд: https://github.com/codedokode/pasta/blob/master/soft/cli.md
Хватит искать проблему вслепую. Надо разобраться, в чем дело.
Прогресс. Сначала выводило ошибку 301, а теперь выводит bool(true). Но только не ебучий контент сайта. Я реально не понимаю, в чем дело - пробовал делать аналогичный массив вручную и перебирать его foreach-ем в тестовом файле - всё работает! Подставляю массив, который заполняется ссылками, полученными по curl - ничего не работает!
>>53600
У меня включены логи, я отображаю всё вардампом и вывожу ошибки curl_error. Говорю же, магия!
Я тут не вижу, чтобы он мог вернуть null: http://php.net/manual/ru/function.curl-exec.php
Он может вернуть false, true и "контент", я предполагаю, в виде строки.
> В остальном верно.
Спасибо, ОП, каждый раз, когда кидаю тебе решение думаю, что на этот раз все идеально и ошибок просто не может быть, а ты разносишь и даёшь мотивации.
>Если интересно, есть еще задача на ООП про Гостиницу
Про Гостиницу решу на днях обязательно, правда, пока не понимаю, как с датами все сделать красиво.
Для представления дат есть \DateTmimeImmutable, или тебе что-то другое надо?
Если ты про хранение дат бронирования, то даю хинт:
бронь тоже может быть объектом
Точно. Выводил null другой код, а curl-exec возвращает или 301 ошибку, или, если url вида 'google.com/?var1=1&var2=2' превратить в 'https://google.com/?var1=1&var2=2/', bool(true) без контента.
Попробуй изучить все опции курла, и подобрать правильные: http://php.net/manual/ru/function.curl-setopt.php
Так как описанное тобой как раз от этих опций сильно зависит.
Их там миллион и все описаны совершенно непонятным языком. Я уже пробовал это изучать.
Так. Допилил тестовый код, теперь он возвращает то же, что и тот код, с которого я начинал: string(0) ""
Все опции:
curl_setopt($curl, CURLOPT_PROXY, "127.0.0.1:9050");
curl_setopt($curl, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);
curl_setopt($curl, CURLOPT_USERAGENT, $agent);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($curl, CURLOPT_HEADER, 0);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($curl, CURLOPT_URL, 'https://'.$url.'/');
Сделал как ты
><?php
$r = file_get_contents('http://httpbin.org/get?a=1&b=2');
var_dump($r);
echo "\n";
И запускаю в командной строке: php /tmp/test.php
Выводится:
string(198) "{
"args": {
"a": "1",
"b": "2"
},
"headers": {
"Connection": "close",
"Host": "httpbin.org"
},
"origin": "185.141.61.117",
"url": "http://httpbin.org/get?a=1&b=2"
}
У меня все тоже вывело абсолютно нормально. Так же, как у тебя.
Но, если я делаю его на свой домен, то в error идет ошибка и опять замена символа
То есть, если я делаю
<?php
file_get_contents('https://МОЙДОМЕН/get?a=1&b=2');
>?
То опять замена.
Тут еще одна вещь, я делаю на httpS. Это может влиять?
Я попробовал сделать file_get_contents на другой домен, он тоже работает без ошибок. Но тот домен http. Там нет сертификатов.
А когда я отправляю на нужный мне домен, который https, то выходит ошибка.
"
Сделал как ты
><?php
$r = file_get_contents('http://httpbin.org/get?a=1&b=2');
var_dump($r);
echo "\n";
И запускаю в командной строке: php /tmp/test.php
Выводится:
string(198) "{
"args": {
"a": "1",
"b": "2"
},
"headers": {
"Connection": "close",
"Host": "httpbin.org"
},
"origin": "185.141.61.117",
"url": "http://httpbin.org/get?a=1&b=2"
}
У меня все тоже вывело абсолютно нормально. Так же, как у тебя.
Но, если я делаю его на свой домен, то в error идет ошибка и опять замена символа
То есть, если я делаю
<?php
file_get_contents('https://МОЙДОМЕН/get?a=1&b=2');
>?
То опять замена.
Тут еще одна вещь, я делаю на httpS. Это может влиять?
Я попробовал сделать file_get_contents на другой домен, он тоже работает без ошибок. Но тот домен http. Там нет сертификатов.
А когда я отправляю на нужный мне домен, который https, то выходит ошибка.
"
1. Создаем задачу с данными
2. Первый Consumer создает запись в БД и Продюсит следующую задачу с обработкой
3. Второй Consumer обрабатывает данные и Продюсит следующую задачу
4. Третий Consumer получает обработанные данные и создает ещё одну задачу
5. Четвертый Consumer делает реквест с отправкой данных конечному адресату
Или можно как-то по другому всё сделать? Нельзя чтобы на каком нибудь из этапов потерялись данные.
Ещё думаю над таким вариантом
1. Получаем данные и создаем тут же запись в БД (молимся чтобы БД была доступна, сеть работала и запись создалась успешно), тут же создаем задачу в RabbitMQ
2. Первый Consumer Обрабатывает данные и продюсит следующую задачу
3. Получаем данные вторым Consumer, обновляем БД (снова молимся) и отправляем данные конечному получателю
ОП и другие небезразличные помогайте
ПИЗДЕЦ! Спасибо тебе! Каким-то образом эти ссылки у меня кодировались, как и у тебя. Используй htmlspecialchars_decode.
>>53628
curl_setopt($curl, CURLOPT_URL, htmlspecialchars_decode('https://'.$url));
И теперь всё работает!
Ссылки кодируются в HTML коде. Если ты берешь их оттуда, естественно, их надо декодировать. Или использовать библиотеку, которая это делает.
Если это так естественно, что же мне никто не помог? Как сам нашел проблему, так все сразу умными такими стали.
Вкатывайся, но учти, что для фулстак джуна требования ниже чем для джуна симфони/ларавеля/йи. Даже джуны/мидлы парой лет опыта пердолинга на фулстаке с CMS часто не могут вкатиться в чистый бэкенд так как засрали уже мозги хуевой архитектурой CMSок
Зависит от фирмы, мелкие фирмы берут кого угодно, большие галеры могут уже выебываться. Я в мелкой фирме работаю без вышки не то что профильной, а вообще без любой вышки. В мелкой фирме могут меньше платить, зато когда получишь опыт - галеры закрывают глаза на образование в 90% случаев если у тебя есть охуенное портфолио за спиной
Рассказал бы мне кто это лет 5 назад, когда я нахуй бросил прогу и пошел в админы.
Сижу, пержу за компами, нихуя не делаю.
>Это называется "наследование таблиц". Вот паттерны
А можно попонятнее, ОПовским языком для самых маленьких? По ссылкам удручающая информация, в википедии и того хуже...
elseif ($isFemale == 1 && $number % 10 == (1 || 2) {
$array[] = $femaleSpelling[$number % 10];
}
Вроде выглядит все правильно, а считаться правильно не хочет. Я канешь поменяю ==(1|2), на >= и <= , но прям интересно че ему не нравится то. Возможно есть какой то более красивый вариант все это записать???
Типо строго равно означает СТРОГО и не подразумевает никаких ИЛИ????
Интерпретатор PHP работает не так как ты думаешь.
Ты думаешь, можно написать "x равно 1 или 2", а PHP так не может. Он может только сравнить 2 числа:
$x == 1
Оператор || - это "логическое ИЛИ", он принимает на вход значения true/false и возвращает тоже true/false. 1 || 2 возвращает true, и у тебя получается сравнение вроде
$x == true
Почитай про булев тип: http://php.net/manual/ru/language.types.boolean.php
Булев тип - это тип, который обозначает ложность или истинность некоторого условия. Операторы сравнения вроде >, <, == возвращают true или false. А логические операторы вроде ||, !, && преобразуют эти значения.
Я чувствую, что это надо в учебник добавить, а то не первый раз уже такую ошибку делают.
Благодарю! А может кто "Сумма прописью" проверить полностью?
Проблема следующая - не могу одновременно сохранить рубли и избавится от слова ноль. Либо удаляю условие попадания нуля в массив в 1 функции и радуюсь решению ценой одного лишнего пробела, который появляется вместо того самого слова ноль. Либо в последней функции меняю условие для слова рубли на $number%1000 > 0 и все вроде бы работает, кроме чисел оканчивающихся на 000 т.е чистых тысяч. в таких ответах теряется слово рубль. Есть способы решить это все сохранив оригинальное условие ОПа и получить нормальный ответ чтоб рубли были всегда и ничего лишнего.
Ложная тревога. Нашел что нужно добавить
Для начала, если ты учишь совсем с нуля, ты можешь глянуть раздел про ООП в моем учебнике в ОП посте. Слишком просто? Реши тогда задачу про Вектор из того учебника либо задачу про Гостиницу ( https://phpclub.tech/pr/res/1082507.html#1097078 ), и сдай на проверку, тогда и освоишь основы ООП. Я уверен, что это поможет разобраться.
Или тебя какие-то более сложные вещи интересуют? Я сам не видел где-то нормального объяснения ООП (по крайней мере в сочетании с PHP), и по моему опыту, разработчики сами его толком не знают и знают только синтаксис (как создать класс и вызвать метод), но не концепции (разделение ответственности, инкапсуляция итд).
Если ты выучил синтаксис и хочешь именно концепции, то погугли такие слова как SOLID, YAGNI и далее гугли слова оттуда. И опять же, реши мою задачу про Гостиницу.
Спрашивай еще вопросы, если что-то в ООП тебе непонятно. Сама по себе идея ООП в разделении кода программы на отдельные классы, каждый из которых решает свою задачу. Объект объединяет в себе данные и методы для работы с ними. Объект может быть моделью какой-то сущности, либо сервисом - объектом, который делает операции над другими сущностями.
Я профильный студент. Прогать умею. ООП, SOLID, DRY и тд знаю. Хочу полный мануал по синтаксису PHP.
>>54399
>все там есть
https://secure.php.net/manual/en/internals2.classes.php
Спасибо чел. Я хз просто, мне нравится пхп, нравится бэк(хотя я и не очень разбираюсь пока), и стоит ли пытаться такой тупой макаке как я вкатиться в это, или лучше поплакать и идти в эльдорадо работать.
Не комментируешь код чтоле? А диздок чего?
Там вообще задание немного странное, буквально написано вывести иерархию в древовидной форме, а потом что в бд должно быть минимум 50к. А в самом конце как доп.задание реализовать ленивую загрузку на клиенте, и через аякс забирать детей какого-то элемента. Разве 50к записей в память поместятся? И пагинацию не сделаешь, этож дерево. Буду сразу наверное делать ленивую загрузку
Тут имеется в виду то, что ты не должен выводить на странице 50 000 записей сразу, а показать только топ-менеджеров и по нажатию на них подгружать их подчиненных. Ну и естественно для этого тебе все 50 000 не нужно грузить в память на стороне сервера.
В той библиотеке, которую ты упомянул (забыл название) уже есть функции для этого (взять только топ-менеджеров, загрузить список детей и тд).
xmlhttprequest/ajax
Я с треда начинал, но мне просто нравилось кодить, я не ставил целью заработок денег, просто онлайн дрочильни уже все надоели на тот момент. Работу я вообще случайно нашел.
Ну как я понимаю value object это объект, который отражает некоторое значение (строку или число, или еще что-то), при этом может или не может содержать некую логику. Например это может быть Money или Date. Для money можно прописать логику работы с разными типами валют например, ну ты понял. А дто как я понял это что-то вроде массива, он просто переносит данные. Например можно делать кастомные юзер реквесты (доставать поля из форм), заполнять ими дто, проверять его на валидность, и потом из дто заполнять свои сущности, так у тебя точно не будет момента в программе где сущность может быть невалидной. Можно во вью передавать рид онли объект (тот же дто), чтобы убрать возможность в шаблонах как-то изменять сущность.
class Money
{
private $amount;
...
}
$payment = new Money(1000);
$hotel->pay($payment);
Другой пример Value Object - это класс для представления даты-времени:
$t = new \DateTimeImmutable('2018-01-01 12:00:00');
echo $t->format('H:i:s');
Подумай, в чем плюсы и минусы Value Object в сравнении с числами и строками, а потом сравни свой ответ с тем что под спойлером (кстати, такой вопрос хорошо бы подошел для собеседования).
Кстати, Value Object бывают 2 видов - изменяемые и неизменяемые (иммутабельные). В иммутабельном объекте сумму денег поменять нельзя. Опять же можешь подумать о плюсах и минусах каждого подхода.
Строгое определение из Википедии: In computer science, a value object is a small object that represents a simple entity whose equality is not based on identity: i.e. two value objects are equal when they have the same value, not necessarily being the same object.
Мои мысли:
Минусы: для класса надо писать больше кода.
Плюсы:
- доступна проверка типов (можно определить функцию как function pay(Money $money) и в нее не получится передать что-то другое). Это защищает от ошибок и делает код более понятным.
- можно делать полезные методы для работы с данными, см. класс DateTime
- можно добавить дополнительные поля, например поле типа валюты для Денег
- мы контролируем операции над данными. Если деньги представлены в виде числа, их можно умножить или сложить с чем угодно, а с классом - мы определяем список допустимых операций и проверяем аргументы. Например, позволяем складывать деньги только с деньгами в той же валюте.
DTO - это класс без логики, представляет какую-то сущность (работник, заказ, товар), обычно используется, как следует из названия, для передачи данных между разными частями приложения.
Определение из Википедии: Data Transfer Object (DTO) — один из шаблонов проектирования, используется для передачи данных между подсистемами приложения. Data Transfer Object, в отличие от business object или data access object не должен содержать какого-либо поведения.
Тут http://design-pattern.ru/patterns/data-transfer-object.html описано такое использование DTO:
> При работе с удалённым интерфейсом, таким как, например, Remote Facade, каждый запрос к нему достаточно затратен. В результате, приходится уменьшать количество вызовов, что означает необходимость передачи большего количества данных за один вызов. Чтобы реализовать это, как вариант, можно использовать множество параметров. Однако, при этом зачастую код получается неуклюжим и неудобным. Также это часто невозможно в таких языках, как Java, которые возвращают лишь одно значение.
То есть вместо функции с кучей параметров
addProduct($id, $name, $price, $discount, $material, $color, ...)
мы можем сделать
addProduct(ProductDto $product)
Я с ними не сталкивался, так что адекватный пример не предложу. Тут вот есть, на мой взгляд, хороший пример его использования: https://ru.stackoverflow.com/questions/456623/Наглядный-пример-различия-dto-poco-pojo-и-value-object - там Java, но код похож на PHP по виду.
class Money
{
private $amount;
...
}
$payment = new Money(1000);
$hotel->pay($payment);
Другой пример Value Object - это класс для представления даты-времени:
$t = new \DateTimeImmutable('2018-01-01 12:00:00');
echo $t->format('H:i:s');
Подумай, в чем плюсы и минусы Value Object в сравнении с числами и строками, а потом сравни свой ответ с тем что под спойлером (кстати, такой вопрос хорошо бы подошел для собеседования).
Кстати, Value Object бывают 2 видов - изменяемые и неизменяемые (иммутабельные). В иммутабельном объекте сумму денег поменять нельзя. Опять же можешь подумать о плюсах и минусах каждого подхода.
Строгое определение из Википедии: In computer science, a value object is a small object that represents a simple entity whose equality is not based on identity: i.e. two value objects are equal when they have the same value, not necessarily being the same object.
Мои мысли:
Минусы: для класса надо писать больше кода.
Плюсы:
- доступна проверка типов (можно определить функцию как function pay(Money $money) и в нее не получится передать что-то другое). Это защищает от ошибок и делает код более понятным.
- можно делать полезные методы для работы с данными, см. класс DateTime
- можно добавить дополнительные поля, например поле типа валюты для Денег
- мы контролируем операции над данными. Если деньги представлены в виде числа, их можно умножить или сложить с чем угодно, а с классом - мы определяем список допустимых операций и проверяем аргументы. Например, позволяем складывать деньги только с деньгами в той же валюте.
DTO - это класс без логики, представляет какую-то сущность (работник, заказ, товар), обычно используется, как следует из названия, для передачи данных между разными частями приложения.
Определение из Википедии: Data Transfer Object (DTO) — один из шаблонов проектирования, используется для передачи данных между подсистемами приложения. Data Transfer Object, в отличие от business object или data access object не должен содержать какого-либо поведения.
Тут http://design-pattern.ru/patterns/data-transfer-object.html описано такое использование DTO:
> При работе с удалённым интерфейсом, таким как, например, Remote Facade, каждый запрос к нему достаточно затратен. В результате, приходится уменьшать количество вызовов, что означает необходимость передачи большего количества данных за один вызов. Чтобы реализовать это, как вариант, можно использовать множество параметров. Однако, при этом зачастую код получается неуклюжим и неудобным. Также это часто невозможно в таких языках, как Java, которые возвращают лишь одно значение.
То есть вместо функции с кучей параметров
addProduct($id, $name, $price, $discount, $material, $color, ...)
мы можем сделать
addProduct(ProductDto $product)
Я с ними не сталкивался, так что адекватный пример не предложу. Тут вот есть, на мой взгляд, хороший пример его использования: https://ru.stackoverflow.com/questions/456623/Наглядный-пример-различия-dto-poco-pojo-и-value-object - там Java, но код похож на PHP по виду.
Value Object. Так как это объект, представляющий количество денег. И 2 объекта с одинаковыми значениями полей эквивалентны.
DTO - не часто встречаются, и посмотри еще раз пример, для чего они используются. Тут важно предназначение. DTO нужен для переноса данных между 2 частями приложения или системами, а Value Object представляет значение. Это совсем разные вещи, у которых и общего-то ничего нет.
Я ошибку допустил, все понял.
благодарю!
$app->get('/old', function () use ($app) {
//some code
});
Вопрос, что означает конструкция use(app) применительно к функции? Я знаю, что слово use применяется при использовании пространства имён.
Всё, нагуглил наконец. Оказывается, это в пыхе так замыкания реализуются, благо с ними знаком по Javascript.ru.
Там же изи все, посиди и подумай/погугли.
Это ж самое весёлое в программировании, когда ты только в начале обучения и пишешь такую хрень с мыслью - ебать я программист уже. Потом начнётся более абстрактное говно.
Там ведь нет математики особо, там нужно скорее правильно организовать код, чтобы все точно считалось и ничего не терялось. Так что рекомендую решить и сверить ответы.
Короч есть такой код.
<?php
require "../dbconnect.php";
$res=mysql_query("SELECT ido, nameo FROM `otdel`");
while($res_id=mysql_fetch_row($res))
{
echo " <center> <table> <tr>
<td width='45' class='tz'> $res_id[0] </td>
<td width='250' class='tz'> $res_id[1] </td>
<td width='45' class=''><form method='post' name='userpr' action='udal.php'>
<INPUT TYPE='hidden' NAME='userpr' VALUE='$res_id[0]'>
<input type='image' src='../image/delete.png' TITLE='Удалить отдел' WIDTH='30' HEIGHT='30' >
</form>
</td>
</tr> </table>\n";
}
?>
Мне таки надо, чтобы по нажатию на инпут имейдж по значеню скрытого инпута userpr удялялась строка из бд. Знаю, что не секьюрно, но тут на это конкретно поебать.
Вот вам няшу.
Аноны, что делать, если я хочу свои говноподелия просматривать с мобилки/планшета, но именно через локальный сервер? Есть какой-то не слишком заебистый способ поднять локальный сервер для всех своих девайсов сразу?ip динамический
Спасибо, анон, так и знал, что есть какое-то адекватное решение, а то перед тем как спросить, погуглил и охуел от того, что в выдаче сплошные темы на форумах, где рекомендуют прошить роутер, запустить свой спутник и все в этом духе.
Для общего развития можешь решить, это не математика, а хуйня собачья. Там дальше ОП предлагает решить задачки на размен денег и на поиск пути, вот где молодость и хардкор.
Регулярные выражения, \n (или \r\n бывает) - перевод строки.
Стоит, я обосрался с задачами, психанул и посмотрел решение от ОПа, многое стало понятно.
Так и есть. Это старый сраный кривой код. Даже я местами ужасаюсь тому говну, которое там написано.
Вынеси 31 и 32 строку как у меня за ифы, ибо у тебя в каждом ифе $op меняется и заново может идти по другим.
composer install делал в корне проекта?
>но не меньше 6-8 месяцев
Это если с нуля или с опытом в других языках?
Ибо для первого чет мало, а для второго долго.
Информацию совсем не обрабатываешь? Написано же до этого, что тред для совсем нулевых, то есть с опытом отпадают. А для нулевых и сказано, что >= 6-8 мес,а не просто =.
Читаю с конца.
За 6 месяцев, лениво дошел до ООПа + html/css. Наверное автор подразумевает минимальный срок для обучения.
нет. эта дроч не нужна веб-разраработчику. это классическое обучение ненужной хуйне от ОПа. прямо как в универчиках и школах.
Для ОБЩЕВА РАЗВИТЕЯ
Выкати свой гайд, друг.
Подскажите в каком направлении плыть чтобы ввести в него поддержку десятичных знаков.
Он же закрыл массив array(); Оставил его пустым. Почему данные вышли?
fix Пикча другая.
В массив можно после создания добавлять элементы и можно их удалять.
array(); // создает пустой массив и ничего с ним не делает
$marks = array(); // создает пустой массив и записывает его в переменную $marks
$marks['x] = 2; добавляет в массив элемент с значением "2" и с индексом "x". Если в массиве уже был элемент с индексом "x" то он заменяется.
unset($marks["x"]); удаляет из массива элемент с индексом "x", если он там был
Все все, я понял спасибо анончик.
Я бы сделал вычисление number через конкатенацию строк, и оставлял бы его строчным до вычислений. Если точка-просто слияние с number и все.
Если спрашиваешь, значит недостаточно.
У меня программа из while true не выходит, сколько отступов должно быть перед break? Как выходить из цикла чётко?
php чихал на отступы, пробелы и переносы строк. Запости код куда-нибудь.
http://sandbox.onlinephpfunctions.com/ например.
Чем фиксить?
Чтобы посмотреть проект твой на винде, мне просто докер скачать?
>Мета тегом запрещающим кэшерование страницы.
Это?
meta http-equiv="Cache-Control" content="no-cache"
Спасибо.
Про порядок записи и вывода данных знаю, хэши умею использовать, чего ещё надо знать?
Это понятно, но есть ли смысл учить обработку, не зная как написать саму форму и ,например, хэдер и футер к ней?
Что ты имеешь ввиду под обработкой форм?
Хидер и футер к форме это что-то новенькое. Да и само написание формы проше простого. Тег form читай на htmlbook.ru. На рнр обработка проста до безобразия. Как на ноде/змее не знаю
>Хидер и футер к форме это что-то новенькое.
Есть задание сделать пикрелейтед страничку, используя include() для подключения хедера и футера.
Это задание придумал червь-пидор. Для такого используется шаблонизатор, если велосипедостроительством промышляешь. Лучше используй include_once().
Для начала, посмотри эти уроки и проверь, знаешь ли ты эти уязвимости:
https://github.com/codedokode/pasta/tree/master/security
Дальше, на сайте OWASP (с очень неудобной навигацией) собран список уязвимостей в веб-приложениях, вот например, ТОП-10 из 2017: https://www.owasp.org/index.php/Top_10-2017_Top_10
include_once для подключения шаблонов как раз не годится (так как там нет ограничения на число подключеий). Он используется для подключения файлов с функциями или классами.
Ну да, стоит прочитать про HTML-формы хотя бы тут http://htmlbook.ru/samhtml5/formy
Обрати внимание, что в HTML5 в сравнении с HTML4 было добавлено много новых типов полей, а также возможности для валидации (проверки) формы перед отправкой. Стоит про них почитать.
И после этого можно почитать мой урок про обработку форм https://github.com/codedokode/pasta/blob/master/forms.md
По идее, если ты жмешь "обновить" или Ctrl + R в браузере, то страница должна перезагружаться. Браузеры по умолчанию не должны ее кешировать и показывать устаревшую версию.
Во-первых, я тебе советую развиваться и побыстрее уходить из написания парсеров, возни много, платят мало.
Во-вторых, сделай скрипт для командной строки, а как его запускать - не твоя проблема, можно вручную, можно из под программы-супервизора, можно как сервис в systemd.
Мало? Да я постоянно встречаю парсеры, который пишутся за день максимум и стоят ~3к рублей. Это по крайней мере больше, чем получают верстальщики.
Я просто уже общаюсь с заказчиком и вдруг понял, что просто сделать скрипт мало, надо будет еще и всё объяснить заказчику. А я тут и сам не понимаю, что и как.
>скрипт для командной строки
Это просто запуск в терминале php /path/parser.php ?
Может быть они пишутся за день, потом отлаживаются и дорабатываются. Ну и бекенд-разработчики за полный день больше зарабатывают.
Мне хотя бы такие копейки зарабатывать начать.
Так как делается автозапуск? Читаю про всякие кроны и ничего не понимаю. Еще попробовал запустить скрипт через консоль, там та даже curl не видит.
Создал утюг на ООПе, это слабо относится к учебнику, но если будет время оцените пожалуйста.
https://ideone.com/dZTw1Q
Спасибо, анон.
Пиши подробнее: какую команду ты набрал, что вывелось, какая ошибка. Тут экстрасенсов нету.
"Автозапуск" в linux делается добавлением скрипта в systemd (лучше не напрямую, а через супервизор, который может перезапускать скрипт при падении), но я не очень понимаю, зачем он нужен. Ведь парсер обычно запускается, скачивает данные, сохраняет их и завершается.
Крон это сервис для запуска скриптов в определенное время.
Вообще, конечно, утюг брать для изучения ООП можно, но это не очень похоже на реальные задачи. Так как ты вряд ли будешь когда-то писать эмуляторы утюга. Объекты в ООП могут моделировать реальные предметы, но часто они моделируют довольно абстрактные вещи - например, объект может представлять "заказ" в магазине или "бронь" в гостинице, или "маршрут" в расписании автобусов. Или объект может быть "менеджером" и управлять другими объектами.
ООП код пишется для решения задачи. Например, мы пишем объект, представляющий заказ, чтобы можно было делать покупки в интернет-магазине. От поставленной задачи зависит, какой код мы напишем. У тебя задача не сформулирована из-за этого трудно понять, нужно ли то или иное поле.
У тебя не хватает инкапсуляции. Свойство temp публичное - значит, кто угодно может задать любую температуру твоему утюгу даже не включая. Логичнее сделать это свойство закрытым (private), чтобы только код в классе мог бы менять температуру. И вообще, сделать все свойства закрытыми.
Паста:
------------
Инкапсуляция. У этого слова есть разные определения, в том числе такие что ничего не понять, потому объясню простыми словами.
Суть инкапсуляции в том, что класс скрывает (инкапслирует) в себе логику работы с данными и сами данные, а наружу выставляет только методы. Пользователю этих методов не важно, как класс устроен внутри, как он хранит данные, какие у него есть поля, ему достаточно вызвать нужный метод чтобы получить результат.
Кроме нескольких публичных методов, остальные методы и свойства закрываются от доступа снаружи модификаторами private или protected. То есть с объектом снаружи ничего нельзя сделать, кроме вызова публичных методов.
Это упрощает понимание кода: тебе не надо читать и разбирать код класса, достаточно прочитать название публичных методов (и может быть комментарии к ним). Также, это упрощает изменение кода: если какое-то свойство имеет уровень private, то доступ к нему возможен только из того же класса и тебе не надо бегать по всему коду и смотреть что там с этим свойством делается, тебе достаточно просмотреть один файл с этим классом.
При инкапсуляции автор класса таким образом задает ограничения, что можно делать с объектом.
Как плюс, мы можем поставить какие-то проверки в методах, и запретить установку неправильных значений свойств. Таким образом, снаружи записать неправильное значение в объект будет нельзя и автор класса может гарантировать его корректную работу в любой ситуации. Если у нас есть публичные свойства, то в них можно записывать что угодно, а приватные свойства изменять снаружи нельзя, можно только вызвать методы, которые что-то делают.
Инкапсуляция это хорошо. Так как весь код, который занимается одной задачей, оказывается заключен внутри одного класса. Противоположный случай это когда код (или знание о его внутреннем устройстве) вылезает из класса и размазывается по всей программе.
Если проводить аналогии, то можно представить кофе-машину. Ты нажимаешь кнопку (=вызываешь публичный метод) и получаешь кофе (=результат вызова этого метода), при этом ты не видишь что происходит внутри нее и тебе не надо в этом разбираться.
Вот пример класса с использованием инкапсуляции:
// Объект представляет собой ломаную линию из нескольких сегментов
// Показаны только публичные методы, остальное скрыто
class PolyLine
{
public function __construct(float $x, float $y) { ... }
// Добавляет еще одну точку к ломаной
public function addPoint(float $x, float $y): void { ... }
// Посчитать общую длину линии
public function calculateLength(): float { ... }
...
}
В нем всего 3 публичных метода, включая конструктор, и мы видим, что с объектом можно сделать только три действия:
- создать ломаную, указав начальную точку
- добавить к ломаной еще одну точку
- посчитать длину ломаной
Вот пример использования этого класса:
$line = new PolyLine(1, 1);
$line->addPoint(2, 2);
$line->addPoint(4, 7);
echo $line->calculateLength();
При этом код может проверять передаваемые значения, например, не разрешать 2 раза добавлять одну и ту же точку. Здесь не приведен код методов и мы не видим приватные поля и методы, но нам это и не требуется - и так понятно, как использовать класс.
--------------------------
Далее, не очень понятно, зачем признак наличия "питания" передается в конструктор. Мы создаем утюги уже включенными? В принипе, это допустимо, если например, нам часто нужно создать именно включенный утюг. Но вообще, в конструктор обычно передают параметры, которые обязательны для работы объекта. Таким образом мы не даем возможность создать объект без указания этих параметров. Например, если бы у нас были утюги разной мощности, мы бы могли мощность передавать в конструктор.
У тебя почему-то обязательными параметрами выбраны признак наличия питания и объем воды. Объем воды - ладно, это имеет смысл, но зачем требовать указать наличие питания, если без него утюг даже рабоать не будет? Видишь, из-за того, что ты не сформулировал задачу, непонятно, нужно это поле или нет.
Ты пишешь много вложенных if. Лучше переделать код, чтобы вложенность была меньше, вот так:
if (!$this->powerSupply) {
echo "Отсутствует питание\n\n";
return;
}
if ($this->toggle) {
echo "Утюг уже был включён\n\n";
return;
}
Так код будет проще и понятнее.
> while ($this->temp < 90) {
> $this->temp++;
> }
Этот код нужно заменить одной строчкой $this->temp = 90. Если бы ты на каждом шаге писал температуру - тогда цикл имел бы смысл, но в твоем случае он бесполезен. Вообще, в ООП мы моделируем только те вещи, которые нужны в нашей задаче. Например, если время разогрева нам не важно, то мы не имитируем последовательный разогрев, а сразу ставим нужную температуру. Ты забыл, что ООП код пишется для решения какой-то задачи, а не просто для имитации настоящего утюга. Даже более того, мне кажется, это вредно, пытаться в подробностях имитировать реальные объекты, забыв о сути задачи.
Предлагаю тебе попробовать решить нашу задачу про Гостиницу с помощью ООП. Там ты сможешь использовать ООП по назначению: https://phpclub.tech/pr/res/1082507.html#1097078
Вообще, конечно, утюг брать для изучения ООП можно, но это не очень похоже на реальные задачи. Так как ты вряд ли будешь когда-то писать эмуляторы утюга. Объекты в ООП могут моделировать реальные предметы, но часто они моделируют довольно абстрактные вещи - например, объект может представлять "заказ" в магазине или "бронь" в гостинице, или "маршрут" в расписании автобусов. Или объект может быть "менеджером" и управлять другими объектами.
ООП код пишется для решения задачи. Например, мы пишем объект, представляющий заказ, чтобы можно было делать покупки в интернет-магазине. От поставленной задачи зависит, какой код мы напишем. У тебя задача не сформулирована из-за этого трудно понять, нужно ли то или иное поле.
У тебя не хватает инкапсуляции. Свойство temp публичное - значит, кто угодно может задать любую температуру твоему утюгу даже не включая. Логичнее сделать это свойство закрытым (private), чтобы только код в классе мог бы менять температуру. И вообще, сделать все свойства закрытыми.
Паста:
------------
Инкапсуляция. У этого слова есть разные определения, в том числе такие что ничего не понять, потому объясню простыми словами.
Суть инкапсуляции в том, что класс скрывает (инкапслирует) в себе логику работы с данными и сами данные, а наружу выставляет только методы. Пользователю этих методов не важно, как класс устроен внутри, как он хранит данные, какие у него есть поля, ему достаточно вызвать нужный метод чтобы получить результат.
Кроме нескольких публичных методов, остальные методы и свойства закрываются от доступа снаружи модификаторами private или protected. То есть с объектом снаружи ничего нельзя сделать, кроме вызова публичных методов.
Это упрощает понимание кода: тебе не надо читать и разбирать код класса, достаточно прочитать название публичных методов (и может быть комментарии к ним). Также, это упрощает изменение кода: если какое-то свойство имеет уровень private, то доступ к нему возможен только из того же класса и тебе не надо бегать по всему коду и смотреть что там с этим свойством делается, тебе достаточно просмотреть один файл с этим классом.
При инкапсуляции автор класса таким образом задает ограничения, что можно делать с объектом.
Как плюс, мы можем поставить какие-то проверки в методах, и запретить установку неправильных значений свойств. Таким образом, снаружи записать неправильное значение в объект будет нельзя и автор класса может гарантировать его корректную работу в любой ситуации. Если у нас есть публичные свойства, то в них можно записывать что угодно, а приватные свойства изменять снаружи нельзя, можно только вызвать методы, которые что-то делают.
Инкапсуляция это хорошо. Так как весь код, который занимается одной задачей, оказывается заключен внутри одного класса. Противоположный случай это когда код (или знание о его внутреннем устройстве) вылезает из класса и размазывается по всей программе.
Если проводить аналогии, то можно представить кофе-машину. Ты нажимаешь кнопку (=вызываешь публичный метод) и получаешь кофе (=результат вызова этого метода), при этом ты не видишь что происходит внутри нее и тебе не надо в этом разбираться.
Вот пример класса с использованием инкапсуляции:
// Объект представляет собой ломаную линию из нескольких сегментов
// Показаны только публичные методы, остальное скрыто
class PolyLine
{
public function __construct(float $x, float $y) { ... }
// Добавляет еще одну точку к ломаной
public function addPoint(float $x, float $y): void { ... }
// Посчитать общую длину линии
public function calculateLength(): float { ... }
...
}
В нем всего 3 публичных метода, включая конструктор, и мы видим, что с объектом можно сделать только три действия:
- создать ломаную, указав начальную точку
- добавить к ломаной еще одну точку
- посчитать длину ломаной
Вот пример использования этого класса:
$line = new PolyLine(1, 1);
$line->addPoint(2, 2);
$line->addPoint(4, 7);
echo $line->calculateLength();
При этом код может проверять передаваемые значения, например, не разрешать 2 раза добавлять одну и ту же точку. Здесь не приведен код методов и мы не видим приватные поля и методы, но нам это и не требуется - и так понятно, как использовать класс.
--------------------------
Далее, не очень понятно, зачем признак наличия "питания" передается в конструктор. Мы создаем утюги уже включенными? В принипе, это допустимо, если например, нам часто нужно создать именно включенный утюг. Но вообще, в конструктор обычно передают параметры, которые обязательны для работы объекта. Таким образом мы не даем возможность создать объект без указания этих параметров. Например, если бы у нас были утюги разной мощности, мы бы могли мощность передавать в конструктор.
У тебя почему-то обязательными параметрами выбраны признак наличия питания и объем воды. Объем воды - ладно, это имеет смысл, но зачем требовать указать наличие питания, если без него утюг даже рабоать не будет? Видишь, из-за того, что ты не сформулировал задачу, непонятно, нужно это поле или нет.
Ты пишешь много вложенных if. Лучше переделать код, чтобы вложенность была меньше, вот так:
if (!$this->powerSupply) {
echo "Отсутствует питание\n\n";
return;
}
if ($this->toggle) {
echo "Утюг уже был включён\n\n";
return;
}
Так код будет проще и понятнее.
> while ($this->temp < 90) {
> $this->temp++;
> }
Этот код нужно заменить одной строчкой $this->temp = 90. Если бы ты на каждом шаге писал температуру - тогда цикл имел бы смысл, но в твоем случае он бесполезен. Вообще, в ООП мы моделируем только те вещи, которые нужны в нашей задаче. Например, если время разогрева нам не важно, то мы не имитируем последовательный разогрев, а сразу ставим нужную температуру. Ты забыл, что ООП код пишется для решения какой-то задачи, а не просто для имитации настоящего утюга. Даже более того, мне кажется, это вредно, пытаться в подробностях имитировать реальные объекты, забыв о сути задачи.
Предлагаю тебе попробовать решить нашу задачу про Гостиницу с помощью ООП. Там ты сможешь использовать ООП по назначению: https://phpclub.tech/pr/res/1082507.html#1097078
Немного поспешил задавать вопросы. php.ini для консоли и для локального сервера были разными.
Ошибка говорит, что нет curl. Может, взамен изменений ini установить curl в папку через composer? Так же даже правильнее должно быть, да?
composer require curlyc/curl ?
Решение > https://ideone.com/ZdgItc
Через композер ставятся библиотеки. А curl это расширение, его нельзя так поставить. Оно ставится либо через apt-get install (в линуксе) либо через pecl install (в линуксе). Но скорее оно просто у тебя в конфиге не включено.
Ах, вот оно что. Спасибо. Огромное. Реально помогаешь и не отвечаешь даже на тупые вопросы. Если я такой код буду кому-то передавать (заказчику, например), ответственность за установку расширений придется перекладывать на него?
И тут ты такой соснул хуйца, дурачек. И ты получаешь ошибки в случае одинаковых названий классов и пробуешь найти в каком из подклбчаемых файлов вызывается ошибка.
Ты невнимательно прочел пост.
Для подключения файлов с классами или функциями (без автозагрузки вручную) используем require_once
Для подключения шаблонов, футеров, шапок - require.
Спасибо за проверку и критику!
Решение https://ideone.com/8sXAP4
Я - днищефрилансер. То есть, фрилансер, но на данный момент конкурирую со школьниками, домохозяйками и прочим скамом. Пытаюсь превозмочь этот уровень, поэтому в отличии от скама пишу для себя всякие ололо-библиотеки, которые позволяют оптимизировать типовые задачи. И мне бы хотелось, чтобы всякие школьники не могли спиздить мою библиотеку. То есть, я хочу каким-либо образом сделать код не читаемым.
Я понимаю, что DRM - зло, что если мой код захочет спиздить человек, который хотя бы пару месяцев посидел в php-треде, то он сделает это, понимаю, что скорее всего мой код никому нахуй не нужен. Но тем не менее, мне хотелось бы защититься от совсем уж долбоёбов, которые занимаются тем, что копируют чужие сайты, во всю демпингуют и т. д.
Есть ли какой-нибудь бесплатныйшвабодный php-обфускатор или что-то в этом роде?
1. обфусцируя ты ухудшишь читаемость но код все равно будет работать
2. более "продвинутая" обфускация чем скрембл и сжатие - просаживает производительность
2.а. разве кроме компиляции в байткод, у этого свои импликации
3. обфускация усложняет тебе жизнь в случае почитать логи на проде, усложнаяется деплой
4. долбоебы не могут скопировать твой php код _снаружи_
Бесплатных тулы все говно полное. Ищи "ентерпрайзные" ломанные.
Все они контрятся другим платным софтом (у которого такие же шансы быть ломанным), при этом некоторые требуют ставить на стороне клиента дополнительно говно.
Эффективнее переписать либы на си например, собрать в дллки и сделать расширение для пхп с ними, либо собрать бинарник и обращаться к нему из кода. Все дрм-фичи в таком случае уже только полноценный хаксор сломает.
Лушче опубликуй как опенсорс не со свободной лицензией, заодно можешь хвастаться какой у тебя репозиторий.
Недавно решил перейти на ооп и наткнулся на экземпляр моего однокурсника, мы с ним поспорили что я смогу обьяснить все 1:1, двач помоги разобрать этот код и расскажите что и как работает в нем
пхп код делать нечитаемым бессмысленно, его надо делать некопируемым, а для этого пхп вообще плохо подходит. либо переписывать на другой (компилируемый) язык, либо смысла нет, т.к. быть уверенным в том, что его не скопируют, ты не можешь.
>>Лушче опубликуй как опенсорс не со свободной лицензией, заодно можешь хвастаться какой у тебя репозиторий
вот это здравая мысль, а то ты пишешь, что пытаешься превозмочь этот уровень, но майндсет у тебя немного отстает от как бы духа времени. щас бесплатных библиотек жопой жуй, они все поддерживаются, обновляются и часто классно написаны. даже если ты пишешь узкоспециализированные либы к каким-нибудь цмс, однажды кто-то напишет свой опенсорс вариант и выложит, короче так себе варик для развития.
другой разговор если ты пишешь тырпрайзные решения или типа того, но тут самое оптимальное - эт saas.
я когда локальный сервер использовал как бэкенд для мобильного приложения, прописал компу статичный айпи внутри сети и указал в нжинксе для локалхоста proxy_pass до нужного локального домена.
в итоге с мобилки стучимся на внутренний айпи компа (192.168.0.43, например), а он отдает нужный сайт из конфига нжинкса
работает только внутри сети и только с ОДНИМ сайтом за раз, но не надо ебаться с роутерами и условно-бесплантыми решениями типа ngrok. если задачи выйдут за рамки одного проекта и надо будет быстро между ними прыгать, тогда можно поебаться, а так не вижу смысла.
хуита, не будет работать. класс human имплементит интерфейс organic, но не реализует метод suck(), в итоге при объявлении ловим фатал.
смысла что-то объянсть в этом коде нет, честно говоря, вам обоим рекомендую почитать мануал пхп по теме ООП, там по всем ключевым словами (интерфейс, трейт, класс, имплемент-экстенд) все очень хорошо и понятно написано.
твоему другу также рекомендую обзакнмиться с PSR.
также throw new ('...') работать не будет, если там внутри кавычек не полный неймспейс эксепшна
>>также throw new ('...') работать не будет, если там внутри кавычек не полный неймспейс эксепшна
напиздел, даже в таком случае не будет работать.
это некрасивый код, показывающий проблемы в понимании ООП: смысл использовать трейт, если в родительском классе вручную прописан тот же метод? переопделеять реализацию метода таким образом плохо - это неявно и плохо читается.
хорошим выходом было бы либо перенести трейт в родительский класс, либо имплементить интерфейс в дочернем, но у вас неоптимально разделены сущности и непонятно почему в интерфейсе organic метод suck. все в кучу, разделение чисто по приколу, названия классов-интрефейсов неаккуратные и неинформативные. короче ООП как раз про это - хорошее понятное разделение на сущности, уместное наследование логичное поведение объектов.
читайте мануал, пасту ОПа и решайте его задачи, они хорошие
я понимаю, что как бы докапываюсь до хуйни, но если изначальная задача была показать знания ООП и сделать пример использования, то это не удалось и обсуждать по изначальному вопросу "объяснить как это работает" тут особого смысла нет.
сделайте корректный пример, поделите например людей на мужчин и женщин, мужчин разделите на натуралов и геев, женщинам присвойте отдельный интерфейс, для женщин и геев сделайте трейт SuckTrait и напишите SuckableInterface, например. для suck вынесите nullable аргумент Money $money, где Money - это value object. каждому реализующему SuckableInterface классу поставьте свою константу кол-ва денег, за которые он сосет, запилите разную логику (кто-то сосет за доллары, кто-то за айфон, ...).
ебаните логирование и понятную систему исключений и их ловли. а так это несерьезно все (а тут серьезные аноны же сидят)
То, что извне не спиздишь - я знаю, речь о макакенах, которые могут потом работать над проектами, над которыми работал я.
>Лушче опубликуй как опенсорс не со свободной лицензией, заодно можешь хвастаться какой у тебя репозиторий.
Да кого ебёт лицензия на этом дне? Сайты целиком пиздят, а тут лицензия не швабодная, можно подумать.
>>57140
В общем и целом, повторю, я сам любитель швабоды и опенсорса, но сейчас вращаюсь в днище-нише, в которой моя либа очень упрощает жизнь.
У меня была такая идея - куда-нибудь глубоко во внутренности засунуть ололо-секретный ключ, который является чем-то типа md5 SERVER_NAME. На уровень дебилов хватит. Но тут проблема в том, что тогда при переезде сайта всё сломается и так подставлять заказчика я не хочу.
Эх, ладно, придётся забить, видимо. Наверное, нужно не думать как успешно конкурировать с днищемакаками, а как сделать так, чтобы мы находились на разных уровнях и меня вообще не волновало, что они там пиздят.
>Так как делается автозапуск?
Чем тебе cron не понравился? Просто устанавливаешь время срабатывания и указываешь скрипт, предварительно дав ему права на выполнение. Проще некуда ведь.
Лучше готовый движок возьми. Учить разработку для разового проекта идея не очень.
Хуясе ты чсв.
любые манипуляции с кодом на предмет запрятывания туда хэшей и прочего - это конечно анти опенсорс. то есть ты это делаешь для лучшей востребованности в будущем,но уверенным в этой востребованности быть не можешь, т.к. любой школьник со штормом за два клика проищет по проекту твой мд5 и выпилит его.
есть опять же варик привязать бинарник к пхп-коду и в нем что-то генерить (что-то подобное делает битрикс вроде), но это легко можно выключить даже в нем, просто потеряешь возможность обновляться. а если у твоей либы обновлений нет, то хацкер ничего не потеряет.
а подскажи какого рода библиотека у тебя? просто интересно
кстати насчет "чем крон не понравился". а какая альтернатива у крона для бэкенда на пхп? не в супервизоре же кли-скрипты запускать
Это не ООП, а пародия на него.
Суть ООП не в том, что мы пишем смешные классы. Мы решаем какую-то задачу и в рамках ее решения делает ООП-модель, объекты, которые имитируют объекты из задачи.
Тут просто бессмысленный код. Непонятно, какую задачу он решает, непонятно, зачем тут классы, да еще и несколько, если задачу вывода текста на экран легко решить без них.
Увы, это типичная проблема, когда люди знают синтаксис (как написать класс, как вызвать метод), но не понимают концепций (для чего это нужно).
Это еще хуже, чем модель утюга несколькими постами выше.
Я бы тебе советовал:
1) открыть учебник из ОП поста, там раздел про ООП. Решить задачи про ООО Вектор
2) решить задачу про ООП-Гостиницу https://phpclub.tech/pr/res/1082507.html#1097078
Я сталкивался с системами с закрытым кодом, в том числе коммерческими CMS. Это полный отстой. Если там что-то не так работает, ты не можешь даже посмотреть, почему. Не говоря уж об отладке кода.
Закрытый код это дрянь. Его нельзя изучать, нельзя отлаживать, исправить, естественно, тоже нельзя. Он сломается при выходе новой версии PHP и его будет не починить. С открытым кодом (независимо от лицензий) работать в разы удобнее.
Более того, обычно в вебе код особо повторно не используешь. Вот я беру фреймворк, и делаю поверх него модели, контроллеры и шаблоны для интернет-магазина. При этом весь код, что я пишу, он специфичный для задачи, он нужен только в этом магазине и как-то еще его использовать трудно.
Я тебе советую к этому стремиться.
Вопрос по исключениям, с правильностью использования которых у меня проблемы.
Вот абстрактный код на пике.
Стоит ли делать такой if внутри которого я делаю throw
или же стоит это оформить иначе, если да то, как и почему?
В такой конструкции мне нравится то что return и обработка ошибка только в конце функции.
Проверьте, пожалуйста, задачу с палиндромами.
http://sandbox.onlinephpfunctions.com/code/75e94cacefd198240501dfac4cc93cdca0ac29a3
Спасибо!
Тоже хочется увидеть ответ на этот вопрос.
Обычно обработчик стараются делать один, какой-нибудь глобальный, в самом коде просто выбрасывают исключения которые потом проходят через глобальный эксепшн хендлер, так проще всего, так как если тебе захочется поменять логику обработки исключений - то меняешь в одном месте, а в твоем случае когда ты в методе прописываешь обработку - тебе придется в каждом месте менять.
Хотя не исключены и случаи когда нужен именно отдельный обработчик здесь и сейчас.
Для начала, что ты будешь использовать для распознавания команд? Какой-то сторонний сервис? input с микрофончиком?
Ну вот здесь, как раз откат транзакции в обработчике нужен.
Естественно сторонний.
Вопрос снят, не умею пользоваться гуглом...
>Я - днищефрилансер. То есть, фрилансер, но на данный момент конкурирую со школьниками, домохозяйками и прочим скамом.
Расскажи подробнее плес, что делаешь обычно например, на какой площадке и сколько зарабатываешь.
Вот что я хотел написать, а потом просто поставил это все, разобрался за вечер и теперь доволен как слон. Велосипед свой выбросил. Вот прям хочется начинать с тестов и потихоньку заполнять их функционалом, это просто...перевернуло весь мой мир. ОПчик, что про тесты можешь рассказать? Я понимаю, что статей всяких немерено и гугл, но все же.
А статью ОПа про тесты читал (кстати, по запросу "автоматизированное тестирование" в Гугле они идет сразу после википедии): https://gist.github.com/codedokode/a455bde7d0748c0a351a
Увы, там не все идеально, я давно уже хочу исправить и дополнить.
Ну например, важный момент: тесты не тестируют какую-то страницу или какую-то функцию. Они не ищут новые баги. Они лишь проверяют выполнение требований к программе, например "при выборе 2 товаров и оформлении заказа клиент получает скидку 100р".
Справшивай конкрентные вопросы, если что-то непонятно.
Не видел этот урок, ушел читать, вопросы будут обязательно.
Двачую вопрос.
Окей, пришла в голову идея составлять документацию к коду не по самому коду, а по тестам. Как реализовать? Плюсы: документация обновляется только когда проходят все тесты, написание тестов дополнительно мотивируется желанием иметь развернутую документацию.
Тесты можно использовать как примеры кода (в том числе как-то подставлять их в документацию), но документацией они не являются. Документация это ведь текстовое описание, а не код.
Хотя, есть такая штука как Gherkin, но это язык для описания сценариев тестирования.
Тесты по большому счету - это код для проверки, выполняются поставленные требования или нет. То есть если ты, например, старший программист, и поручаешь джуниору сделать задачу, то ты можешь, чтобы проверить, сделал он ее или нет, записать свои требования в виде тестов, и сказать ему, чтобы не приходи,л пока все тесты не пройдут.
В Питоне есть возможность вставлять что-то вроде тестов в комментарии в коде. То есть ты в комментарии пишешь примеры использования функции, а специальная утилита проверяет их корректность и сравнивает получившийся результат: https://docs.python.org/2/library/doctest.html
Fatal error: Call to undefined function createQuestions();
Код:
https://ideone.com/fmZWBe
То же самое и с printQuestions.
PHP 5.5
Я немного ворвусь в чужой разговор с нахуй никому не нужным замечанием.
Запомни, Анон, ты занимаешься не тем, что пишешь код, а тем, что решаешь задачи. Соответственно, по части
>ответственность за установку расширений придется перекладывать на него
нужно быть довольно адаптивным, иначе успеха тебе не сыскать. Кому-то, возможно, нужно будет объяснить, кому-то нет.
Фриланс (речь о нём же?) это не чистое программирование, а программирование + умение вести бизнес + техподдержка + хуй_знает_что.
Если ты элитный погромист 300кк/наносек и работаешь в качестве эдакого субподрядчика у других погромистов, то в этом плане всё проще. Если ты макака-инвалид только начинающий свой путь как я, то среди твоих заказчиков будет много интересных личностей, скорее всего, и там может потребоваться объяснять то, к чему ты вообще не особо причастен. Тут главное уметь балансировать и понимать, когда человека можно нахуй послать, когда лучше ему объяснить, хоть он и пидор, потому что если он будет чувствовать себя ОБСЛУЖЕННОЙ ПО КРАСОТЕ ВИП ПЕРСОНОЙ ПЕРСОНОЙ, то он отвалит много денег и т. д.
у тебя createQuestions это метод класса Question
Необходимо сперва создать объект этого класса например $q = new Question();
А далее вызывать $questions = $q->createQuestions();
Есть html код:
<div class="background">
<div class="box></div>
</div>
Можно ли при наведении курсора (:hover) на box изменить фон родителя?
Код условный, приведён для примера, так что менять его не вариант.
Пока что нельзя в родителя выходить, увы. Придумывай что-то другое.
И да, если $email = null, текст для false тоже выводится.
Спасибо.
Нет, тебе. Это тред для изучающих PHP, а не для любителей самоутверждаться.
>>59589
== это нестрогое сравение. При сравнении данных разных типов оно преобразует их к одному типу и только потом сравнивает.
Сравнивать с false, true, null, надо через ===
Мануал:
http://php.net/manual/ru/language.operators.comparison.php
Ага, спасибо. Сам до этого дошел, когда поставил вместо NULL 0, а потом 1.
До этого вечно думал, что двойное равно и есть тождественное равенство.
Здравствуйте. Иду по гайду для самых маленьких и вот трабл. В чем ошибка?
https://ideone.com/lrRQLg#stdin
братюнь, так он же тебе написал PHP Parse error: syntax error, unexpected '\' (T_NS_SEPARATOR), expecting ',' or ';' in /home/2jRht2/prog.php on line 11
не ожидает \, а ждет или запятую или точку с запятой. рекомендую работать в IDE типа шторма или хотя бы в атоме каком.
echo "У анона выпало {$anonDice1} и {$anonDice2}\n И у компютера выпало {$compDice1} и {$compDice2}\n";
https://ideone.com/6Sqe87
Не расставлены точки с запятой после некоторых команд, \n был за пределами " " в 11 строке, => больше либо равно пишется не так, а >= так, нельзя использовать else (..), для этого есть elseif().
А если на логику смотреть, то нужно ставить просто больше либо меньше, равно тут ни к чему.
>>60043
Спасиб. Вроде разобрался. Однако всплыли следующие вещи.
1. Изначально я писал в ideone, но он решил внезапно стереть все что было и тогда я пошел в Notepad++. Однако он не запускает почему то скрипты(программу) или как это называется, тогда я скопировал написанный в нем код и вставил в ideone. Бум. Чет все поплыло и не стало не на своих местах. Пробелы куда то уехали и тд.
2. После надписей оказывается нужно ставить ( ; ) это наверно идет завершением команды echo?
3. Пока до сих пор не понимаю else, только если ни одно из предыдущих не выполнилось?
1. Скрипты запускаются не в блокноте, это лишь способ их написать. Для запуска надо установить сам php на компуктер и настроить локальный сервер у себя. Php ведь серверный язык. Это все есть в уроках в шапке, но тебе пока что лучше в Ideone исполнять все, а ещё лучше http://sandbox.onlinephpfunctions.com, а писать в каком-нибудь простом sublime,про нотпад забудь. Сервер для учебника опа не нужен.
2. В конце любой команды в php требуется ; ставить, как и перед каждой переменной $. Это стоит просто принять и запомнить, потом на автомате будет у тебя.
3. Else - иначе. Да, все, что не попадает в условие if или elseif попадает в else. Вообще, в учебнике это вроде хорошо все поясняется, почитай ещё мануал официальный.
Вообще я сам только задачу про гостиницу на ооп делаю, так что могу ошибаться в пояснениях.
Грац, все понятно. Поеду дальше)
У тебя переменные объявлены внутри метода, а не класса. Они будут видны только в самом методе.
http://sandbox.onlinephpfunctions.com/code/acbb9ed84500fa0a74c80a5cd85250d74feefb69 вот говнопример. Лучше потратить время и немного подучить. У тебя просто функции завернутые в классы, это не ООП конечно.
Шапку читай
Решил заново, https://ideone.com/RSUyZe
Прошу прощения за мой английский, ну и за утюг тоже стыдно.
Что сделано?
1. Инкапсуляция.
Теперь свойства нельзя изменять вне методов, логически подумав что кто-то захочет унаследовать один из наших классов, я выставил область видимости protected.
Также, в методах объявлены типы передаваемых параметров. Как вы советовали, добавил создание свойств через конструктор, как я понял это относится к инкапсуляции.
2. Вопросы разных типов создаются через одну функцию createQuestions();
3. Методы checkAnswer() и getAsString(), отвечают только за себя и выполняют только свою задачу.
4. getAsString() отдает строку с данными теста, а пользователь сам решает что с этим делать (вывести на экран или добавить в файл)
5. Реализована возможность "почти правильного" ответа. Под неё в классе MultipleChoiceQuestion, создано свойство и отдельный метод для её добавления, думаю это удобно так как по задумке опция не обязательная и будет не у всех вопросов.
6. Реализована возможность отклонения от правильного значения, в вопросах с числовым ответом.
Программа позволяет добавлять новые виды вопросов не трогая существующие классы.
Заранее спасибо!
Если не понимаешь ООП то не используй. Зачем запутывать код и портить жизнь тем, кто будет его поддерживать? Пиши процедурный код на функциях.
Если хочешь разобраться, то могу предложить:
- учебник из ОП поста, глава про ООП, решить задачи из нее
- решить задачу про Гостиницу https://phpclub.tech/pr/res/1082507.html#1097078
- если ты работаешь с БД, то почитать про работу с БД с использованием ООП: https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md
1 http://jsbin.com/kekujufima/1/edit?html,css,output
2 http://jsbin.com/lazejimuju/edit?html,css,output
3 http://jsbin.com/geciyoyice/edit?html,css,output
4 http://jsbin.com/zexisokahe/1/edit?html,css,output
5 http://jsbin.com/yiheyujixa/edit?html,css,output
6 http://jsbin.com/mekayuxeqe/1/edit?html,css,output
7 http://jsbin.com/runubaseko/edit?html,css,output
8 http://jsbin.com/hilohopasa/edit?html,css,output
9 http://jsbin.com/fesitopubu/edit?html,css,output
10 http://jsbin.com/powayifete/edit?html,css,output
11 http://jsbin.com/jilekupapa/edit?html,css,output
12 http://jsbin.com/movadezoyu/1/edit?html,css,output
Что вообще делать, если что-то знаю, но не уверен в том, что смогу устроиться на работу и не накосячу.
Какие сольные проекты могут быть, пусть даже и без дохода?
>я сам только задачу про гостиницу
Это какая такая задача про гостиницу? Там про зарплаты и кошки-мышки задачи, чет про гостиницу не помню ничего.
Можно даже без пхп.
Спяси.
https://ideone.com/438IOu
Есть ли хоть какой либо смысл записываться на платные онлайн курсы по обучению php? Или лучше и проще обучаться самому по гайдам ОПа?
>онлайн курсы
Лол.
>платные
Дабл лол.
Бесплатные курсы по php + гайды ОПа + официальный мануал php
Вопрос по "Вектору":
>(у Сотрудника есть ранг, базовая ставка, профессия, является ли боссом).
>Потребление кофе или зарплата не являются свойствами так как они вычисляются из других свойств и хранить их не надо.
Что значит кофе и зарплата не являются свойствами? Из каких других свойств они вычисляются?
Ниче не понял.
Сам себе ОП противоречит:
>Менеджер получает 500 тугриков в месяц, выпивает 20 литров кофе и производит 200 страниц отчетов в месяц
Даны же по условию! Откуда ты там че вычисляешь?
У менеджера есть базовая ставка 500, выпивает базово кофе 20,по если он станет руководителем, то зарплата будет уже 750, а кофе будет пить 40, различай базовую ставку-дано и зарплату-вычислено.
>если он станет руководителем
Если он станет руководителем, он больше не будет менеджером. Как бэ. То есть мы создадим в памяти новый объект класса руководитель, который унаследует базовые свойства, имя к примеру. Или стаж работы.
А старый мы удалим, высвободив память, в которой он был записан.
Нет, руководитель это как раз свойство любого работника булевое, 0-не босс, 1-босс
Спс. Я вот щас че думаю, как лучше по уму хранить массивы со ставками и множителями? Я пока под это дело класс создал и обращаюсь к его статическим свойствам обращаюсь. Это норма? Или как лучше сделать?
Ты походу суть ооп пока не уловил. У тебя должен быть класс работник, лучше всего абстрактный и от него наследоваться классы менеджер и тд. У работника есть свойства базовая ставка и тд. Также есть метод получить зп работника, где базовая ставка, например, увеличивается на 50 процентов, если работник - босс, если нет, зп = базовая ставка. Есть класс департамент и у него есть метод получить зп всех работников департамента, в этом методе будет вызываться метод работника получить зп и складываться в общую зп департамента в цикле.
А массивы нужны будут только, чтобы хранить объекты, например у департамента будет массив с объектами работниками. Как-то так.
>Также есть метод получить зп работника, где базовая ставка, например, увеличивается на 50 процентов, если работник - босс, если нет, зп = базовая ставка.
Братан, это походу ты суть задания не уловил. Там не только начальник/дурак, а еще есть РАНГИ, их 3 штуки. То, что ты предлагаешь это проверка if и внутри каждого свитч кейс из 3 условий? Некрасиво выглядит, как на мой взгляд. Теперь смотри братан, то что ты предложил уже хуйня. А теперь представим, что ввели новый ранг - 4.
Что ты будешь делать? Ты будешь лазить по КАЖДОМУ классу и вписывать туда свитчкейс новый. Третье - свитч кейсы в принципе хуйня, потому что если ты хоть где-то забудешь break, у тебя потечет прога, як бачок у Ярiка.
Добавлю в метод абстрактного родительского класса ещё один elseif, остальные классы наследуют его ж, моё решение оп проверил уже пару недель назад, так что, я думаю, что я уловил. Свитчей у меня не было никаких, 1 иф на ранг и 1 на босса.
Вот, можешь глянуть, тут сразу с антикризисными мерами, не помню только, исправленный ли это вариант после замечаний опа.
>1 иф на ранг и 1 на босса.
Как блядь у тебя один иф и на ранг и на босса, если рангов 3? Как может быть один иф? Ты обезумел что ли?
Мог бы и сам глянуть, прежде чем бомбить тут, вот метод получения зп. Вот тебе два ифа в нем, что не так?
Хорошо остановимся на твоем коде, я беру оттуда функцию getSalaryEmployee ("получить Зарплатного Сотрудника" - правильно будет getEmployeeSalary) - это у тебя 316 строка я его в отдельный сэндбокс вынес.
http://sandbox.onlinephpfunctions.com/code/eb4bc5c5819053ed5147ab11fa4292ea77ef17c8
Хорошо, сейчас пока рангов три, ты выкрутился. А если их будет 23? Что ты будешь делать? Ты будешь 23 if'а писать?
Про setBaseSalary отдельный разговор. Ты ее прописываешь в абстрактном классе, а потом реализуешь ОТДЕЛЬНУЮ ФУНКЦИЮ в каждом дочернем классе. Причем функцию, которая буквальным образом просто возвращает одно число. Нахуя? Допустим произошла индексация з/п (ПЛОТИ НОЛОГИ), ты будешь лазить по всем классам и менять цифры. Нахуй это нужно?
По заданию было понятно, что рангов будет не 23, надо же адекватно оценивать задание, а не быть машиной. Да и на массив легко поменять,если уж так потребуется.
Set как раз и будет менять ставку, не позволяя лезть в сам класс(антикризисные меры), а гет нужен для начальной инициализации, чтобы пользователь класса не смог создать новый вид работника без ввода начальных ставок(абстрактный метод get должен быть обязательно реализован). Это все инкапсуляция как бы, хочешь ввести новую должность - обязательно укажи ставки, хочешь поменять - обязательно через сет, а не в класс мой лезть. Это все описывал оп много раз.
В абстрактном классе нельзя описывать НЕабстрактные методы?
Например https://ideone.com/dXoRFM
>По заданию было понятно, что рангов будет не 23
А откуда ты знаешь, что будет в следующем задании? Ты ж не шкальник.
По твоей логике ставок может быть и миллиард, тут массива уже не хватит, это тоже придумывать надо было мне? Надо адекватно смотреть на задачи, тупой робот на работе никому не нужен.
>По твоей логике ставок может быть и миллиард
Да хоть сто миллиардов, петушина. За кликхаус слышал че-нть? Или в вашей вордпресной такими приемами не пользуются?
Еще один 300кк врывается в тред. Тут учебные задачи, для которых такое не требуется. Многие, кто делают это задание, ещё об sql не слышали даже.
>9×ме1, 3×ме2, 2×ме3, 2×ма1 + руководитель департамента ме2
Я так понимаю мне нужно создать по одному инстансу каждого типа (ме1, ме2 и т.д.), а потом сложить это все в ассоциативный массив типа:
marketingDept = [
'ме1' => 9,
'ме2' => 3,
...//more coming up next
];
Мне показалось такое решение удобным, потому что я легко могу дернуть любой ключ, вызвать его метод getSalary, а потом помножить на значение, т.е. количество.
Или каким-то другим образом это сделать?
>Многие, кто делают это задание, ещё об sql не слышали даже.
Ну тогда вместо вешания им на уши хуйни про абстрахтные классы и тайп-хинтинг может лучше рассказать про SQL? а потом уже, когда появится PDO научить ООП? На реальном примере общения скрипта с сервером БД, а не на шкальной задачке, решающейся в один скрипт в процедурном стиле.
Предложи это опу, я сам вкатывальщик, но у него сразу после этого идёт как раз sql, гит, post get, небольшой фреймворк и более менее задание реальное-список студентов.
>Предложи это опу,
Ну и как бы в задачке "Вектор" мне вот кажется непонятным мотивация к использованию абстрактного класса. Типа показать что вот есть такое? Ну реально же, я все равно буду четыре класса создавать и во всех переопределение методов методов. Суть? Учебник ОПа не дает внятного ответа на вопрос.
Ну я тоже не понял сразу как лучше и было ясно, что учебник для ознакомления, полез по совету опа из этого же учебника в Зандстру, там все ясно стало.
640x640, 0:16
Оп целую тебя в писю. Твои уроки просто ахуенны.
И давайте без лишней агрессии. Это учебный тред, и здесь приветствуются разные рассуждения, в том числе ошибочные, так как сам процесс рассуждения помогает освоить "инженерное мышление", умение сравнивать плюс/минусы и выбирать один из вариантов решения задачи.
>>62117
Создавать абстрактный класс не требуется. Можно вообще сделать всех работников одним классом, можно сделать один класс работника и несколько не связанных с ним классов-профессий. На ваше усмотрение.
>>62086
Изучение или неизучение ООП никак не мешает изучать SQL.Увы, по SQL отдельного курса просто нет, все что есть это https://github.com/codedokode/pasta/blob/master/db/databases.md
Тайп-хинитинг нужен везде, в том числе в описываемых тобой "скриптах". Но вообще это плохой подход, проблемы потом обязательно вылезут, если не придерживаться какой-то организации кода. Ну например, нельзя будет повторно использовать написанный тобой код, так как он не разбит на функции.
И конечно есть урок по использованию БД вместе с ООП: https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md
>>62085
Можно массивом строк: ['ma1x9', 'en2x3', ...]. Можно массивом массивов:
[
[Manager::class, 1, 9],
[Engineer::class, 2, 3],
...
]
Делать один объект для группы однотипных работчих не очень выгодно, так как нельзя потом например повышать зарплату отдельным работникам в группе.
И давайте без лишней агрессии. Это учебный тред, и здесь приветствуются разные рассуждения, в том числе ошибочные, так как сам процесс рассуждения помогает освоить "инженерное мышление", умение сравнивать плюс/минусы и выбирать один из вариантов решения задачи.
>>62117
Создавать абстрактный класс не требуется. Можно вообще сделать всех работников одним классом, можно сделать один класс работника и несколько не связанных с ним классов-профессий. На ваше усмотрение.
>>62086
Изучение или неизучение ООП никак не мешает изучать SQL.Увы, по SQL отдельного курса просто нет, все что есть это https://github.com/codedokode/pasta/blob/master/db/databases.md
Тайп-хинитинг нужен везде, в том числе в описываемых тобой "скриптах". Но вообще это плохой подход, проблемы потом обязательно вылезут, если не придерживаться какой-то организации кода. Ну например, нельзя будет повторно использовать написанный тобой код, так как он не разбит на функции.
И конечно есть урок по использованию БД вместе с ООП: https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md
>>62085
Можно массивом строк: ['ma1x9', 'en2x3', ...]. Можно массивом массивов:
[
[Manager::class, 1, 9],
[Engineer::class, 2, 3],
...
]
Делать один объект для группы однотипных работчих не очень выгодно, так как нельзя потом например повышать зарплату отдельным работникам в группе.
Можно.
>>62035
Хочу прокомментировать "что делать когда будет 1000 рангов". Вот когда будет - тогда и будем решать. У нас архитектура намертво не завязана на количество рангов и много кода переделывать не придется. Это называется YAGNI. Статья по теме (про программистов пекущих хлеб): https://habr.com/post/153225/
Иначе мы можем нагородить космолет, сделать отдельный класс Value Object для представления ранга, и это нам в итоге не понадобится. Если не уверен, что нужно - не делай. А возможность расширения в архитектуру закладывать можно, если это не космолет.
> Ты ее прописываешь в абстрактном классе, а потом реализуешь ОТДЕЛЬНУЮ ФУНКЦИЮ в каждом дочернем классе. Причем функцию, которая буквальным образом просто возвращает одно число. Нахуя?
Это нужно, чтобы:
1) задокументировать факт, что при создании новой профессии разработчик обязан определить для нее ставку з/п
2) принудить разработчика делать это и не позволить ему забыть об этом
>>61986
Наследование использовать не обязательно. Другие подходы тоже допустимы, если они хорошо решают задачу.
>>61974
Статические свойства это не норма, так как они могут существовать только в одном экземпляре. То есть ты пишешь SomeClass::$something и это единственная переменная. А суть ООП в том, что у нас объекты, и у каждого свои переменные. Ну, например, есть объект Работник и у каждого Работника свой собственный Ранг.
>>61951
Есть кстати еще альтернативная идея - хранить указатель на объект-руководитель в поле head в Депараменте. Так мы гарантированно защищаемся от 2 боссов в одном департаменте, но получаем взамен другие проблемы.
Можно.
>>62035
Хочу прокомментировать "что делать когда будет 1000 рангов". Вот когда будет - тогда и будем решать. У нас архитектура намертво не завязана на количество рангов и много кода переделывать не придется. Это называется YAGNI. Статья по теме (про программистов пекущих хлеб): https://habr.com/post/153225/
Иначе мы можем нагородить космолет, сделать отдельный класс Value Object для представления ранга, и это нам в итоге не понадобится. Если не уверен, что нужно - не делай. А возможность расширения в архитектуру закладывать можно, если это не космолет.
> Ты ее прописываешь в абстрактном классе, а потом реализуешь ОТДЕЛЬНУЮ ФУНКЦИЮ в каждом дочернем классе. Причем функцию, которая буквальным образом просто возвращает одно число. Нахуя?
Это нужно, чтобы:
1) задокументировать факт, что при создании новой профессии разработчик обязан определить для нее ставку з/п
2) принудить разработчика делать это и не позволить ему забыть об этом
>>61986
Наследование использовать не обязательно. Другие подходы тоже допустимы, если они хорошо решают задачу.
>>61974
Статические свойства это не норма, так как они могут существовать только в одном экземпляре. То есть ты пишешь SomeClass::$something и это единственная переменная. А суть ООП в том, что у нас объекты, и у каждого свои переменные. Ну, например, есть объект Работник и у каждого Работника свой собственный Ранг.
>>61951
Есть кстати еще альтернативная идея - хранить указатель на объект-руководитель в поле head в Депараменте. Так мы гарантированно защищаемся от 2 боссов в одном департаменте, но получаем взамен другие проблемы.
В общем идея при изменениях пересоздавать объекты не очень хорошая. Так как:
1) мы должны копировать свойства, в том числе приватные. Значит, копировать объект можно только изнутри, его методом.
2) при добавлении нового свойства мы должны найти код копирования и не забыть добавить копирование этого свойства. А забыть легко.
Хотя, есть концепция иммутабельных значений, которые создаются и никогда больше не меняются. Для изменения пересоздаются новые объекты. Там есть свои плюсы и минусы. Плюс например, что если мы ссылаемся на объект, записали куда-то ссылку на него:
$x = $someObject;
То значение $x никогда не изменится. То есть мы сохраняем в $x неизменяемый "снимок" состояния объекта. Обычные же объекты естественно могут и будут меняться.
>>61834
Есть базовая ставка (менеджер 1 ранга зарабатывает X), А из нее считается зарплата с учетом рангов. То есть отдельно у нас базовая ставка и отдельно итоговая зарплата. Это разные вещи. И я пишу, что проще не хранить производные свойства вроде итоговой зарплаты вообще.
>>60939
Зря ты с HTML смешиваешь логику, прочти про шаблоны: https://github.com/codedokode/pasta/blob/master/php/templates.md
> function __construct( string $n )
Пробелы поставлены не по стандартам PSR-1,PSR-2. Надо:
function __construct(string $n)
Скобки пробелами в общем не отделяем, кроме случаев повышения читабельности.
> public function getEmployee( int $n ) : Employee
Это неучдачно спроектированный метод. Так как непонятно, где брать номер. Более того, объектам не нужны номера. Каждый объект уникален (обладает идентичностью). И их идентичность можно сравнивать:
if ($a === $b) {
// a и b указывают на один и тот же объект
} else {
// a и b указывают на разные объекты
}
> foreach( $emp as $value ) { $this -> employees[] = $value ; }
Надо писать в три строки.
> public function salaryDocumentRatio
Имена функций принято начинать с глагола (хотя есть и другие подходы, где глагол не используют, например в jQuery).
> private $ishead ;
Надо isHead для читабельности (либо is_head)
> bool $i
Лучше назвать так же, как и поле. Одинаковые вещи лучше называть одинаково.
Хорошо, что ты попробовал применить альтернативный подход и не стал делать классы-наследники для профессий. Так интереснее, и дает нам возможность, не прилагая усилий, сравнить разные подходы на чужом опыте.
Код хорош, ждем вторую часть про антикризис.
В общем идея при изменениях пересоздавать объекты не очень хорошая. Так как:
1) мы должны копировать свойства, в том числе приватные. Значит, копировать объект можно только изнутри, его методом.
2) при добавлении нового свойства мы должны найти код копирования и не забыть добавить копирование этого свойства. А забыть легко.
Хотя, есть концепция иммутабельных значений, которые создаются и никогда больше не меняются. Для изменения пересоздаются новые объекты. Там есть свои плюсы и минусы. Плюс например, что если мы ссылаемся на объект, записали куда-то ссылку на него:
$x = $someObject;
То значение $x никогда не изменится. То есть мы сохраняем в $x неизменяемый "снимок" состояния объекта. Обычные же объекты естественно могут и будут меняться.
>>61834
Есть базовая ставка (менеджер 1 ранга зарабатывает X), А из нее считается зарплата с учетом рангов. То есть отдельно у нас базовая ставка и отдельно итоговая зарплата. Это разные вещи. И я пишу, что проще не хранить производные свойства вроде итоговой зарплаты вообще.
>>60939
Зря ты с HTML смешиваешь логику, прочти про шаблоны: https://github.com/codedokode/pasta/blob/master/php/templates.md
> function __construct( string $n )
Пробелы поставлены не по стандартам PSR-1,PSR-2. Надо:
function __construct(string $n)
Скобки пробелами в общем не отделяем, кроме случаев повышения читабельности.
> public function getEmployee( int $n ) : Employee
Это неучдачно спроектированный метод. Так как непонятно, где брать номер. Более того, объектам не нужны номера. Каждый объект уникален (обладает идентичностью). И их идентичность можно сравнивать:
if ($a === $b) {
// a и b указывают на один и тот же объект
} else {
// a и b указывают на разные объекты
}
> foreach( $emp as $value ) { $this -> employees[] = $value ; }
Надо писать в три строки.
> public function salaryDocumentRatio
Имена функций принято начинать с глагола (хотя есть и другие подходы, где глагол не используют, например в jQuery).
> private $ishead ;
Надо isHead для читабельности (либо is_head)
> bool $i
Лучше назвать так же, как и поле. Одинаковые вещи лучше называть одинаково.
Хорошо, что ты попробовал применить альтернативный подход и не стал делать классы-наследники для профессий. Так интереснее, и дает нам возможность, не прилагая усилий, сравнить разные подходы на чужом опыте.
Код хорош, ждем вторую часть про антикризис.
Объекты создаются только через операторы new или clone. Других способов нет. Можно, разумеется использовать циклы.
>>60802
А у тебя нет потребности решить какую-то задачу, ускорить способ ее решения. Возможно, PHP тут сможет помочь. Это может быть что угодно, что тебе интересно или необходимо.
>>60682
Верно
По идее border тоже добавляется к ширине и можно было бы сделать 578px.
А так, верно.
У em стоило бы убрать наклон, а так верно. & надо было писать как & amp ; иначе ищущие за ним символы могут интерпретироваться как часть HTML entity.
> margin-left: -4px;
Костыли-костылики. На других ОС ведь метрики шрифтов могут быть немного другие. Ну ладно, пусть так будет.
Верно.
> font-family: "Trebuchet MS";
Надо всегда добавлять fallback-шрифт (вроде sans-serif, serif и тд, которые предусмотрены стандартом).
> display: inline-block;
>float: left;
float автоматически подразумевает display: block. Хак для ИЕ что ли?
Так, в общем, хорошо. Я тут подумал, может пора уже добавить в задачу требование адаптивной версии для маленьких экранов?
Ок, верно.
А зачем у примечания отступ сверху 140px? Откуда эта цифра? Также, надо бы протестировать случай, когда идет несколько примечаний подряд, хотя там идеального решения нет.
В остальном верно.
Главный подвох таблиц - они растягиваются контентом и width/height задает лишь минимальные значения ширины/высоты, а не окончательные. Что, если в тексте окажется ну очень длинное слово? Проверь-ка.
А в общем такой способ решения через таблицы допустим.
Ок, верно.
> .button > input {
> position: absolute;
> opacity: 0;
Тут надо быть осторожным, так как эти инпуты хоть и навидимы. но не пропускают сквозь себя клики, не закрыть какой-то элемент страницы. Если они гарантированно внутри кнопки то ок.
Сделано хорошо, но можешь ли ты добавить еще клавиатурную навигацию? По стандартным контролам можно двигаться Табом, переключать их Пробелом и стрелочками. Хотелось бы и тут такого же.
Ок, верно.
Объекты создаются только через операторы new или clone. Других способов нет. Можно, разумеется использовать циклы.
>>60802
А у тебя нет потребности решить какую-то задачу, ускорить способ ее решения. Возможно, PHP тут сможет помочь. Это может быть что угодно, что тебе интересно или необходимо.
>>60682
Верно
По идее border тоже добавляется к ширине и можно было бы сделать 578px.
А так, верно.
У em стоило бы убрать наклон, а так верно. & надо было писать как & amp ; иначе ищущие за ним символы могут интерпретироваться как часть HTML entity.
> margin-left: -4px;
Костыли-костылики. На других ОС ведь метрики шрифтов могут быть немного другие. Ну ладно, пусть так будет.
Верно.
> font-family: "Trebuchet MS";
Надо всегда добавлять fallback-шрифт (вроде sans-serif, serif и тд, которые предусмотрены стандартом).
> display: inline-block;
>float: left;
float автоматически подразумевает display: block. Хак для ИЕ что ли?
Так, в общем, хорошо. Я тут подумал, может пора уже добавить в задачу требование адаптивной версии для маленьких экранов?
Ок, верно.
А зачем у примечания отступ сверху 140px? Откуда эта цифра? Также, надо бы протестировать случай, когда идет несколько примечаний подряд, хотя там идеального решения нет.
В остальном верно.
Главный подвох таблиц - они растягиваются контентом и width/height задает лишь минимальные значения ширины/высоты, а не окончательные. Что, если в тексте окажется ну очень длинное слово? Проверь-ка.
А в общем такой способ решения через таблицы допустим.
Ок, верно.
> .button > input {
> position: absolute;
> opacity: 0;
Тут надо быть осторожным, так как эти инпуты хоть и навидимы. но не пропускают сквозь себя клики, не закрыть какой-то элемент страницы. Если они гарантированно внутри кнопки то ок.
Сделано хорошо, но можешь ли ты добавить еще клавиатурную навигацию? По стандартным контролам можно двигаться Табом, переключать их Пробелом и стрелочками. Хотелось бы и тут такого же.
Ок, верно.
Бамп
>Изучение или неизучение ООП никак не мешает изучать SQL.
Без ООП PDO не попишешь, а про Eloquent молчу, а это как бы стандарт де факто.
>Статические свойства это не норма, так как они могут существовать только в одном экземпляре.
Так, еще раз. У нас есть ФИКСИРОВАННЫЕ показатели: условно назовем их Expenses (расходы) и Production (feces). Если бы у нас каждый менеджер производил УНИКАЛЬНОЕ количество продукции, которая к тому же могла бы изменяться, имело бы смысл это прописывать в классе.
>То есть ты пишешь SomeClass::$something и это единственная переменная.
Ясен хуй. В этом то и суть! Что такое тарифная сетка и как она рассчитывается ты понимаешь?
http://sandbox.onlinephpfunctions.com/code/a49b0a6a3df43330c6574110717f6e069ef13b18
Вот так НАХОЙ это делается.
>http://sandbox.onlinephpfunctions.com/code/a49b0a6a3df43330c6574110717f6e069ef13b18
Тут есть недостатки:
- нет инкапсуляции, то есть в одном классе задаются базовые ставки, а в другом используются для расчета. Это усложняет код и увеличивает число связей между классами. Хотя, конечно, вполне допустимо делать отдельный класс для расчетов зарплат.
- статические свойства значат, что значение меняется для всех и сразу. Мы не можем сделать 2 компании с разными базовыми ставками.
- нельзя добавить новую профессию, не меняя существующий код. В данной задаче это не проблема, но часто бывает такая ситуация: у нас есть сторонняя библиотека, которую менять нельзя. В твоем варианте класс Expenses будет в этой библиотеке и мы, пользователь библиотеки, не имеем возможности добавлять новые профессии.
И еще. Для обозначения профессий лучше использовать константы:
Employee::POSITION_MANAGER
Или имена классов:
Manager::class
Это защищает от опечаток, позволяет увидеть все имеющиеся профессии и поддерживает автодополнение и проверки в IDE.
Опчик, раскритикуй мой "Вектор" до антикризисной оптимизации.
http://sandbox.onlinephpfunctions.com/code/fad13494af7027885e7615764833d04bd3329c82
>Для обозначения профессий лучше использовать константы
>Employee::POSITION_MANAGER
Я такого синтаксиса не видел, константы же через define оформляются, а тут как будто к статическому свойству обращаются.
Кинь ссылку на туториал по этому синтаксису.
И, пожалуйста, обоссы финальную версию вектора. Спасибо.
>>62539
Посоветуй, что по Mysql почитать. Твой туториал неполный.
Похоже ты давно изучал ООП, это в PHP5 завезли. И кстати в PHP7 константы можно объявлять по-человечески словом const:
const XYZ = 123;
Чтобы запускать код надо сначала указать PhpStorm, где находится PHP (если он установлен). Если не установлен - то есть немного староватый гайд https://github.com/codedokode/pasta/blob/master/soft/php-install.md
>>60209
> abstract function getAsString();
тут можно было бы указать тип возвращаемого значения: getAsString(): string; (да, знаю, что этого нет в уроке)
> public function checkAnswer($answer)
> return array(1, $points);
> return array(1, $points, '', '', 1);
> return array(0, $points, $text, $hint);
Если ты возвращаешь несколько значений с помощью массива с числовыми индексами, то лучше делать кол-во элементов одинаковым, чтобы можно было использовать конструкцию list:
list($isCorrect, $points, ...) = $q->checkAnswer($a);
Также, желательно документировать формат возвращаемого результата, а то это не понятно из кода функции.
Также, функция не должна возвращать посторонние знаечния. Ну например, зачем возвращать текст вопроса в функции проверки ответа? Для этого можно сделать отдельную функцию getQuestionText(). Вдобавок текст в половине случаев не возвращается. То есть функция должна делать что-то одно - проверять ответ либо возвращать текст вопроса, а не все сразу. Одна функция решает одну задачу.
> $leftDeviation = $this->correctAnswer - $this->deviation;
> $rightDeviation = $this->correctAnswer + $this->deviation;
Проще так: $deviation = abs($x - $y);
> new NumericalQuestion('Чему равна скорость света в км/с?', 15, 300000);
хоть и не совсем по теме, но пройти мимо не могу: ответ неправильный, если указан без погрешности.
> $pointsMax += $resultOfCheck[1];
Это не очень понятный код, так как глядя на функцию, непонятно, что там хранится. Лучше использовать конструкцию list() для распаковки массива.
Кстати, для возврата неск. результатов есть еще пара способов:
- ассоциотивный массив с ключами-названиями
- объект-результат с несколькими полями
(си-подобный вариант с передачей переменных по ссылке не рассматриваю, так как выглядит плохо).
Чтобы запускать код надо сначала указать PhpStorm, где находится PHP (если он установлен). Если не установлен - то есть немного староватый гайд https://github.com/codedokode/pasta/blob/master/soft/php-install.md
>>60209
> abstract function getAsString();
тут можно было бы указать тип возвращаемого значения: getAsString(): string; (да, знаю, что этого нет в уроке)
> public function checkAnswer($answer)
> return array(1, $points);
> return array(1, $points, '', '', 1);
> return array(0, $points, $text, $hint);
Если ты возвращаешь несколько значений с помощью массива с числовыми индексами, то лучше делать кол-во элементов одинаковым, чтобы можно было использовать конструкцию list:
list($isCorrect, $points, ...) = $q->checkAnswer($a);
Также, желательно документировать формат возвращаемого результата, а то это не понятно из кода функции.
Также, функция не должна возвращать посторонние знаечния. Ну например, зачем возвращать текст вопроса в функции проверки ответа? Для этого можно сделать отдельную функцию getQuestionText(). Вдобавок текст в половине случаев не возвращается. То есть функция должна делать что-то одно - проверять ответ либо возвращать текст вопроса, а не все сразу. Одна функция решает одну задачу.
> $leftDeviation = $this->correctAnswer - $this->deviation;
> $rightDeviation = $this->correctAnswer + $this->deviation;
Проще так: $deviation = abs($x - $y);
> new NumericalQuestion('Чему равна скорость света в км/с?', 15, 300000);
хоть и не совсем по теме, но пройти мимо не могу: ответ неправильный, если указан без погрешности.
> $pointsMax += $resultOfCheck[1];
Это не очень понятный код, так как глядя на функцию, непонятно, что там хранится. Лучше использовать конструкцию list() для распаковки массива.
Кстати, для возврата неск. результатов есть еще пара способов:
- ассоциотивный массив с ключами-названиями
- объект-результат с несколькими полями
(си-подобный вариант с передачей переменных по ссылке не рассматриваю, так как выглядит плохо).
Да, многие учебники по PHP пишутся как продолжение изучения HTML. Если у тебя такой, то придется изучить сначала HTML, не обязательно весь, на минимальном уровне, знать несколько популярных тегов и про экранирование спецсимволов и html-entities.
Также, многие учебники не рассказывают про экранирование выводимых значений. Если у тебя такой, то читай параллельно с ним урок https://github.com/codedokode/pasta/blob/master/security/xss.md (если ничего не понятно, значит рановато его читать).
>>60056
Чтобы ничего не разъезжалось, настрой редактор, чтобы при нажатии Таб вставлялся не символ Таб, а 4 пробела. Так как ширина табуляции в разных программах разная.
Да, else значит "выполнить, если ни одно из условий не выполняется". Потому в нем условие не пишут. Он идет в самом конце блока if.
>>59550
Есть хак - поместить внутри .box еще один див (.background-color) и спозиционировать его абсолютно, чтобы он совпадал по размеру с родителем с отрицательным z-index (чтобы он был внизу). И к нему уже применять стили.
Можно конечно, если ты свободно читаешь английский. При изучении обращай внимание на то, какие фичи являются частью стандартного SQL, а какие - особенностями MySQL.
По поводу класса Salary - замечания я вроде писал выше:
- нет инкапсуляции, то есть в одном классе задаются базовые ставки, а в другом алгоритм расчета зарплаты. Это усложняет код и увеличивает число связей между классами. Логичнее и то и другое поместить в один класс, ведь идея ООП в совмещении в одном объекте данных (полей) и методов для работы с ними. Хотя, конечно, вполне допустимо делать отдельный класс для расчетов зарплат.
- статические свойства значат, что значение меняется для всех и сразу. Мы не можем сделать 2 компании с разными базовыми ставками.
- нельзя добавить новую профессию, не меняя существующий код. В данной задаче это не проблема, но часто бывает такая ситуация: у нас есть сторонняя библиотека, которую менять нельзя. В твоем варианте класс Expenses будет в этой библиотеке и мы, пользователь библиотеки, не имеем возможности добавлять новые профессии.
> 'ме' => 500,
Для обозначения профессий лучше использовать константы или имя класса.
> public function getExpenses ()
Лучше было сделать отдельные методы для каждого вида расходов, а не собирать все в один.
> public function __construct (string $name, array $members, string $boss)
тут не мешало бы задокументировать формат передаваемых данных, а то непонятно, что должно быть в массиве.
> public function spawnMembers()
Странное решение. Ты этой функцией создаешь из описания профессий набор объектов-работников. Но может лучше сразу хранить внутри Department эти объекты, а не их текстовое описание?
Ну и ждем вторую часть. Должен предупредить тебя, что тебе скорее всего придется сильно переделывать код, но зато ты получишь ценный урок, как ведется разработка в приближенных к жизни условиях.
Ясно. Кстати, почему запросы в документации и разных туториалах пишут всегда в верхнем регистре, несмотря на то, что чувствительности к регистру у запросов нет?
Что-то у тебя один и тот же код повторяется несколько раз. Зачем это? Цикл (for) ведь как раз и придуман, чтобы несколько раз подряд выполнить один и тот же код, чтобы его не надо было дублировать. Надо убрать повторение кода.
Также, попробуй поменять в начале размер долга на
$creditBalance = 1000;
У тебя получается отрицательная выплата.
Блин, я таки это сделал с расчетом на то, что после пяти тысяч надо сделать проверку всего два раза, ибо в худшем случае надо платить еще раз после первого раза после того, как останется больше или равно пяти тысяч. Там конечно есть отрицательная плата, но ответ правильный. Как вариант написать замену значений в той строке.
Но говнокод я конечно написал, да. Посмотрел у других, у них гораздо меньше.
Вот какой алгоритм можно взять:
- прибавляем проценты и комиссию к остатку долга (!не вычитаем ничего пока!)
- если остаток маленький, выплачиваем сколько осталось и уходим
- иначе платим 5000
«Платим» здесь значит уменьшаем долг и увеличиваем общую сумму выплаченного.
Да я видал уже код, кстати мне сразу показалось стремным то, что баланс кредита содержит в себе еще те самые отрицательные пять тысяч. Увы, не дожал.
`storage` char NOT NULL,
`rack` char NOT NULL,
`cell` char NOT NULL,
`unit_name` char NOT NULL,
`unit_code` char NOT NULL,
`price` DECIMAL NOT NULL,
`model` char NOT NULL,
`sort` char NOT NULL,
`profile` char NOT NULL,
`size` char NOT NULL,
`reserve_amount` int NOT NULL,
`name` char NOT NULL,
`vendor_code` char NOT NULL,
`entry_number` int NOT NULL AUTO_INCREMENT,
`date` DATE NOT NULL,
`invoice_date` DATE NOT NULL UNIQUE,
`invoice_number` char NOT NULL,
`contractor` char NOT NULL,
`income` int NOT NULL,
`expense` int NOT NULL,
`remainder` int NOT NULL,
`check_date` DATE NOT NULL,
`check_employee` char NOT NULL,
PRIMARY KEY (`entry_number`)
);
Как это чудовище натянуть на классы? Тут полей явно больше чем пальцев в моем организме. Можно все всунуть в класс Entry например, окей, сохранить легко, а вот как потом что-то искать тут... При выборке должен заполнятся пикрил листок (как я понял каждому артикулу своя страница). Причем если ЭТО нормализовать, мне кажется производительность упадет в нулину. Ну шо, интыпрайз-макаки, настало время блеснуть ЧСВ.
`storage` char NOT NULL,
`rack` char NOT NULL,
`cell` char NOT NULL,
`unit_name` char NOT NULL,
`unit_code` char NOT NULL,
`price` DECIMAL NOT NULL,
`model` char NOT NULL,
`sort` char NOT NULL,
`profile` char NOT NULL,
`size` char NOT NULL,
`reserve_amount` int NOT NULL,
`name` char NOT NULL,
`vendor_code` char NOT NULL,
`entry_number` int NOT NULL AUTO_INCREMENT,
`date` DATE NOT NULL,
`invoice_date` DATE NOT NULL UNIQUE,
`invoice_number` char NOT NULL,
`contractor` char NOT NULL,
`income` int NOT NULL,
`expense` int NOT NULL,
`remainder` int NOT NULL,
`check_date` DATE NOT NULL,
`check_employee` char NOT NULL,
PRIMARY KEY (`entry_number`)
);
Как это чудовище натянуть на классы? Тут полей явно больше чем пальцев в моем организме. Можно все всунуть в класс Entry например, окей, сохранить легко, а вот как потом что-то искать тут... При выборке должен заполнятся пикрил листок (как я понял каждому артикулу своя страница). Причем если ЭТО нормализовать, мне кажется производительность упадет в нулину. Ну шо, интыпрайз-макаки, настало время блеснуть ЧСВ.
Xdebug поставь либу и радуйся жизни
Такой стиль кода. Я не помню, чтобы когда-то видел ключевые слова в нижнем регистре. Я советую этот style guide для SQL:
- https://www.sqlstyle.guide/ (англ)
- https://www.sqlstyle.guide/ru/ (рус)
ООП-Будильник
Необходимо сделать ООП-модель будильника, как в Андроиде. Будильник (alarm clock) позволяет добавить произвольное количество тревог (alarm), у каждой из которых есть свои настройки. Вот, какие параметры есть у тревоги:
- время срабатывания, с точностью до минуты
- одноразовый или многоразовый, по умолчанию многоразовый
- дни недели, в которые разрешено срабатывание будильника, по умолчанию все
- признак активности. Неактивная тревога не срабатывает, это можно использовать, чтобы на какой-то период отключить ее, не удаляя из списка. Для одноразовой тревоги задавать неактивность нельзя.
Будильник поддерживает такие операции:
- добавить новую тревогу в список
- удалить данную тревогу из списка
- поменять любые настройки отдельной тревоги
- получить для данной тревоги и данного текущего времени (\DateTimeInterface) ближайшие дату/время срабатывания.
Например: если есть многоразовая тревога на 08:00 на Пн, Ср, Пт и сегодня вторник 12 июня 2018, то ближайшее время срабатывания - 13 июня, среда, 08:00. А если сегодня 8:00 среды 13 июня, то ближайшее время будет пятница, 15 июня. У неактивных тревог время срабатывания рассчитывается, как если бы она была активна.
У одноразовых тревог время срабатывания возвращается, только если она еще не срабатывала ни разу. Например, если пользователь во вторник 12 июня в 9:00 поставил одноразовую тревогу на 8:00 на Пн, Ср, Пт, то она сработает только один раз - в среду в 8:00. После этого момента она еще раз никогда не сработает.
- для данного текущего времени получить ближайшую активную тревогу, которая сработает в будущем. Если таких несколько, можно вернуть любую из них. Это будет использоваться для показа времени ближайшего срабатывания будильника на экране.
- для данного текущего времени получить активную тревогу, которая срабатывает ровно в это время. Это будет использовано для проигрыша мелодии. Например, если в списке есть тревога на 08:00 в Пн, Ср, Пт и сейчас среда 08:00, то нужно ее вернуть. Если тревог больше одной - можно вернуть любую.
- для данного текущего времени удалить из списка все одноразовые тревоги, которые больше никогда не сработают.
Будильник не должен пытаться получать текущее время сам - во все функции, которым оно нужно, оно будет передано снаружи в виде объекта реализующего встроенный в PHP интерфейс \DateTimeInterface. Будильник не должен играть мелодию или что-то отображать - это не его задача. Его задача лишь управлять списком тревог.
Код, который будет играть мелодию, делать не надо, предполагается, что он уже есть, он будет вызывать функции будильника, выглядя примерно так:
- тревога = получить ближайшую тревогу
- момент = получить дату/время ближайшей тревоги
- ждать до этого момента, с прерыванием ожидания при изменении настроек будильника
- получить активную на данный момент тревогу (дополнительная проверка нужна, так как за время ожидания тревоги могли быть удалены)
- если она есть, проиграть мелодию, если нет то ничего не делать
- удалить сработавшие одноразовые тревоги
- перейти к началу алгоритма
Будильник не обязан состоять из одного класса, их может быть сколько угодно. Желательно применять инкапсуляцию (делать поля закрытыми для доступа извне) и проверять передаваемые в функции параметры, чтобы нельзя было передать, например, неправильное время (в такой ситуации выбрасываем исключение \InvalidArgumentException).
ООП-Будильник
Необходимо сделать ООП-модель будильника, как в Андроиде. Будильник (alarm clock) позволяет добавить произвольное количество тревог (alarm), у каждой из которых есть свои настройки. Вот, какие параметры есть у тревоги:
- время срабатывания, с точностью до минуты
- одноразовый или многоразовый, по умолчанию многоразовый
- дни недели, в которые разрешено срабатывание будильника, по умолчанию все
- признак активности. Неактивная тревога не срабатывает, это можно использовать, чтобы на какой-то период отключить ее, не удаляя из списка. Для одноразовой тревоги задавать неактивность нельзя.
Будильник поддерживает такие операции:
- добавить новую тревогу в список
- удалить данную тревогу из списка
- поменять любые настройки отдельной тревоги
- получить для данной тревоги и данного текущего времени (\DateTimeInterface) ближайшие дату/время срабатывания.
Например: если есть многоразовая тревога на 08:00 на Пн, Ср, Пт и сегодня вторник 12 июня 2018, то ближайшее время срабатывания - 13 июня, среда, 08:00. А если сегодня 8:00 среды 13 июня, то ближайшее время будет пятница, 15 июня. У неактивных тревог время срабатывания рассчитывается, как если бы она была активна.
У одноразовых тревог время срабатывания возвращается, только если она еще не срабатывала ни разу. Например, если пользователь во вторник 12 июня в 9:00 поставил одноразовую тревогу на 8:00 на Пн, Ср, Пт, то она сработает только один раз - в среду в 8:00. После этого момента она еще раз никогда не сработает.
- для данного текущего времени получить ближайшую активную тревогу, которая сработает в будущем. Если таких несколько, можно вернуть любую из них. Это будет использоваться для показа времени ближайшего срабатывания будильника на экране.
- для данного текущего времени получить активную тревогу, которая срабатывает ровно в это время. Это будет использовано для проигрыша мелодии. Например, если в списке есть тревога на 08:00 в Пн, Ср, Пт и сейчас среда 08:00, то нужно ее вернуть. Если тревог больше одной - можно вернуть любую.
- для данного текущего времени удалить из списка все одноразовые тревоги, которые больше никогда не сработают.
Будильник не должен пытаться получать текущее время сам - во все функции, которым оно нужно, оно будет передано снаружи в виде объекта реализующего встроенный в PHP интерфейс \DateTimeInterface. Будильник не должен играть мелодию или что-то отображать - это не его задача. Его задача лишь управлять списком тревог.
Код, который будет играть мелодию, делать не надо, предполагается, что он уже есть, он будет вызывать функции будильника, выглядя примерно так:
- тревога = получить ближайшую тревогу
- момент = получить дату/время ближайшей тревоги
- ждать до этого момента, с прерыванием ожидания при изменении настроек будильника
- получить активную на данный момент тревогу (дополнительная проверка нужна, так как за время ожидания тревоги могли быть удалены)
- если она есть, проиграть мелодию, если нет то ничего не делать
- удалить сработавшие одноразовые тревоги
- перейти к началу алгоритма
Будильник не обязан состоять из одного класса, их может быть сколько угодно. Желательно применять инкапсуляцию (делать поля закрытыми для доступа извне) и проверять передаваемые в функции параметры, чтобы нельзя было передать, например, неправильное время (в такой ситуации выбрасываем исключение \InvalidArgumentException).
Хорошая задача, пожалуй лучше Вектора. Я думаю, что задачу про список студентов тоже нужно переделать под список сотрудников. Ту, часть которая касается СПА приложения можно переделать под менеджер тасок для сотрудников. Кошки-мышки, мухиляби выкинуть - они ничего не дают обучающемуся. Задача про нахождение кратчайшего пути - хорошая.
В раздел про регулярки задачу на валидацию номера кредитки - он должен определенную контрольную сумму давать. Заодно человек научится валидировать группы цифр разделенные дефисами.
Нужно написать типичную веб-приложуху с миллионом таблиц, вкладками, таблицы в таблицах и ещё как можно больше таблиц. Приглядываюсь к Laravel + Vue.js + Vuetify. Ну и тут сразу встаёт вопрос SPA или не SPA? Начал писать SPA, реализовал небольшую часть функционала для теста, запилил парочку своих компонентов. Сейчас пока не могу представить, что из этого получится, если в будущем активно наращивать функционал. Может не стоит вскрывать эту тему дальше? Как это лучше всего реализовать?
https://code-basics.ru/languages/php/
Массивов там нет, тащемта.
Уроки пополняются, но медленно очень.
>>40726
Не советую платить за то, что можно добыть самому (да хотя бы в этом треде!). Ищи инфу сам, ищи задачи и решай кодь их. Всякие "курсы" - это вытягивание бабла и больше играет на создание "атмосферы" кодера. Когда человек за что-то заплатил, он себя чувствует более вовлеченным.
Короче, если есть лишние (лол) бабки и время то можешь вкатываться смело, нет - дрочи мануалы и шароёбся по десяткам специализированных форумов типа сабреддита по языку, форумов (на родном и чужом языке) и прочее в этом духе. Тебе ВСЁ-РАВНО ПРИДЁТСЯ это делать, так не лучше начать делать это прямо сейчас, смекаешь? Я верю, что от курсов будет польза (верю даже, что с ними ты будешь учится быстрее), но потом ты останешься один.
jdoodle.com/a/ERc
w5.6 с функцией array_rand() и православной конкатенацией
jdoodle.com/a/ERf
бамп
ОПче, у меня есть идея своего приложения в качестве замены задачам о списке студентов и др. У тебя все очень грамотно расписано в плане того, как реализовать фичи определенные, покрыть тестами, реализовать новые фичи. Я тебе напишу в почту тоже, оч нужна твоя помощь, ниче технически сложного или как там сделать спрашивать не буду, а спрошу какие бы ты классы реализовал, или в какой последовательности реализовавывал бы фичи.
ну парни
Никто не сталкивался с такой проблемой: письма отправленные через phpmailer gmail не пересылает дальше, а пишет про ошибку, но иногда передумывает и шлёт.
И ещё, мб кто посоветует хостинг, для одностраничника, чтобы недорого и хорошо.
Вкидывай конечно, только учти что у нас тут большие пинги, придется подождать пока синьеры-помидоры найдут свободное время.
А с мэйлером не подскажешь?
Пока переделал всё на яндекс, но там проблема следующая:
мыло которое пересылает с сайта на рабочий емэйл(т.е. тот, который будут проверять на наличие писем), не сохраняет в папке отправленного ничего, письма на рабочий мэйл доходят, но я боюсь, что в какой-то момент начнётся такая же херня как и с гмэйлом и проверить это возможности не будет
Что ну? Ты хочешь, что бы мы за тебя решили что тебе интересно? или книжек посоветовали? Конкретизируй вопрос бич.
Спустя полтора месяца пинания хуев, решил продолжить свое обучение, хех. Смог родить это чудо, оно почему-то даже не вардампиться, лол. Отругайте дурачка, и подскажите, что не так.
К сожалению не подскажу.
Сиди на той, которая удобнее.
А если захочешь разобраться в том, как работает веб-сервер - подними его с нуля на виртуалке.
https://ideone.com/5i9xyL
>У нас есть свои уроки по основам PHP, они собраны и выложены по адресу http://codedokode.github.io/phpbook
Никогда ещё не видел от анона (особенно после вкатывания в JS) настолько не требовательного и ласкового введения в язык. Хорошо постарался автор, снимаю залупу шляпу. Хотя уроки чувствую довольно старые, и автор возможно уже умер... тогда земля ему пухом.
Имеется:
Знание пхп - 0,00001 из 10000.
Навык погромирования - 0.
Опыт написания программ - 0.
Долбоеб - 1шт.
Настроенный сервер - 1 (апачи).
Помощь - отсутсвует (исключение: препод и двач, но ощущение, что препод сидит на дваче, так что здрасте).
Цель: написать клон Героев 3 только лишь на пхп.
Мертвая линия: декабрь.
Вопрос: Посильная задача при таких данных?
А выхода все равно нет, хули.
Конечно, я начал учить пхп, но вряд ли смогу написать игру один за 3 месяца (сентябрь опустим), так как даже банальное планирование перед созданием игры мне неведомо.
Спрайты и прочая графика не важны, так как сейчас нужна структура игры (разбиение по классам на ресурсы, постройки, армия и тд), но преподу нужно, чтоб все это было в разных файлах, которые будут вызываться в общем файле игры. Но представления об этом у меня совсем нихуя.
В общем, с чего начать путь?
А что, смысл твоего препода только в том, чтобы дать тебе невьебенную задачу и уйти в закат? Даже никак не направляя тебя? Охуенно. надеюсь ты ему не платишь
Препод говорит, что сделает сложную задачу, типа, логики и тд.
Моя же задача - понаделать классов с переменными. И заставить класс из одного файла вызываться в другом файле. А потом и все остальное для создания игры, только я хз, что. Функции всякие, подключение кнопок управления и тд. Пока что так.
Препод бесплатный, так как он университетский. А так как я отщипенец и не общаюсь с одногруппниками, то и делать буду один. Такие дела.
телефон 1: https://ideone.com/0nmMqh
телефон 2: https://ideone.com/uOeHc3
автозамена: https://ideone.com/p16mil
Нихуя, он вроде тут сидит.
Есть всё-таки ирония в том, что рандом с двача подает информацию лучше, чем преподы.
Да в том то и дело, что я, наверное, не совсем по адресу.
Пхпмэйлер свою работу делает, т.е. письма шлёт, проблема с gmail'ом, т.е. он в какой-то момент начинает думать, что это спам или что-то в этом духе. А это ещё только тест.
Может кто сталкивался с таким поведением гмэйла, им напрямую надо писать или что?
Пишет следующее:
Сообщение заблокировано
Ваше сообщение, отправленное на адрес , заблокировано. Технические подробности смотрите ниже.
в подробностях предлагает мне посмотреть на адрес получателя, предполагая, что там кавычки\пробелы или ещё какя муть, но там всё нормально.
Такие дела
>май фэйс вэн задача про студентов
Чет оп слишком резкие скачки сложности делает.
8 вариантов ответа->3 правильных-> ты выбираешь 3 правильных+1 неправильный-> набираешь ноль балов
Верно?
Можно требовать строгого совпадения, можно придумать балльную систему, где чем точнее ответ, тем больше баллов.
я тоже перерыв неделю делал, взял щенка пикрелейтед, а хотя не совсем перерыв - css еще теорию почитал
Удваиваю!
Примеры адресов?
verbose вывод мейлера.
Может у тебя проблемы с кодировкой, особенно если проблемы начинаются > в какой-то момент.
Если адреса получателя действительно нет - раньше приходил похожий ответ.
Код формирования и отправки письма тоже можешь показать на всякий случай.
Код: jdoodle.com/a/F3C
Вопрос: почему на 21 строчке если убрать $i => будет только один слог? Получается мы складываем массивы с одинаковыми ключами, верно? Но что тогда вообще происходит? Почему слог не перезаписывается другим или не вернет ошибку, мол, "неизвестен приоритет"? Как ПХП приоритезирует мои слоги?
>>64990
Вполне нормальный вопрос. Дело в том, что страницы сайта можно генерировать 2 способами:
- статически. Это значит, веб-мастер (ты) создает HTML-страницу, загружает ее на сайт. Надо что-то поменять - веб-мастер правит страницу и загружает обновленную версию
- динамически. В этом случае есть база данных, из нее берутся данные и подставляются в шаблон страницы. Чтобы изменить какие-то данные, достаточно изменить их в БД, это можно сделать через админку, не требуя навыков программирования.
В разных случаях разные способы лучше годятся. Например, если ты делаешь сайт-визитку, рассказывающий о компании, то проще всего сделать несколько статических страниц. А что, если ты делаешь интернет-магазин? Ты на каждый товар будешь вручную верстать его страницу? Нет, конечно, лучше сделать базу товаров, и админку, чтобы менеджер мог сам добавлять или редактировать товары, не привлекая менеджеров.
Вот для генерации страниц динамически и нужен какой-то серверный язык программирования - Питон, PHP, Java, C#, Ruby, Node.JS.
Ну и естественно, для реализации комментариев, форм обратной связи, тоже нужен код на сервере, который будет принимать и обрабатывать данные.
>>64937
А ты понимаешь, как работает сложение массивов? Скорее всего оно работает не так, как ты думал. Оно описано в мануале: http://php.net/manual/ru/language.operators.array.php - там же и ответы на твои вопросы.
> if (4 >= 0) {
> $glue = implode ("", $emptyMassive);
Условие бессмысленное. 4 всегда больше 0 и потому команда будет выполняться на каждом шаге цикла. Ее надо было поставить после цикла, а не в нем. В цикле мы пишем только то, что должно выполняться несколько раз подряд.
Тебе явно надо больше внимания уделить массивам, ты их плоховато знаешь. Чтобы добавить элемент в массив с автоматическим присваиванием индекса, есть конструкция:
$array[] = $value;
Чтобы лучше изучить массивы, вот тебе задача:
- дан список слов в массиве, например: $words = ['кошка', 'кит', 'собака']. Список слов может быть любым, не только как в примере.
- надо сгруппировать эти слова по первой букве и вывести (в первой строчке все слова на одну букву, во второй на другую, итд). Сортировать по алфавиту не требуется, выводить можно в любом порядке. Например, для слов выше программа должна вывести:
К: кошка, кит
С: собака
>>64990
Вполне нормальный вопрос. Дело в том, что страницы сайта можно генерировать 2 способами:
- статически. Это значит, веб-мастер (ты) создает HTML-страницу, загружает ее на сайт. Надо что-то поменять - веб-мастер правит страницу и загружает обновленную версию
- динамически. В этом случае есть база данных, из нее берутся данные и подставляются в шаблон страницы. Чтобы изменить какие-то данные, достаточно изменить их в БД, это можно сделать через админку, не требуя навыков программирования.
В разных случаях разные способы лучше годятся. Например, если ты делаешь сайт-визитку, рассказывающий о компании, то проще всего сделать несколько статических страниц. А что, если ты делаешь интернет-магазин? Ты на каждый товар будешь вручную верстать его страницу? Нет, конечно, лучше сделать базу товаров, и админку, чтобы менеджер мог сам добавлять или редактировать товары, не привлекая менеджеров.
Вот для генерации страниц динамически и нужен какой-то серверный язык программирования - Питон, PHP, Java, C#, Ruby, Node.JS.
Ну и естественно, для реализации комментариев, форм обратной связи, тоже нужен код на сервере, который будет принимать и обрабатывать данные.
>>64937
А ты понимаешь, как работает сложение массивов? Скорее всего оно работает не так, как ты думал. Оно описано в мануале: http://php.net/manual/ru/language.operators.array.php - там же и ответы на твои вопросы.
> if (4 >= 0) {
> $glue = implode ("", $emptyMassive);
Условие бессмысленное. 4 всегда больше 0 и потому команда будет выполняться на каждом шаге цикла. Ее надо было поставить после цикла, а не в нем. В цикле мы пишем только то, что должно выполняться несколько раз подряд.
Тебе явно надо больше внимания уделить массивам, ты их плоховато знаешь. Чтобы добавить элемент в массив с автоматическим присваиванием индекса, есть конструкция:
$array[] = $value;
Чтобы лучше изучить массивы, вот тебе задача:
- дан список слов в массиве, например: $words = ['кошка', 'кит', 'собака']. Список слов может быть любым, не только как в примере.
- надо сгруппировать эти слова по первой букве и вывести (в первой строчке все слова на одну букву, во второй на другую, итд). Сортировать по алфавиту не требуется, выводить можно в любом порядке. Например, для слов выше программа должна вывести:
К: кошка, кит
С: собака
Да. Но id особо и не нужен. Объект сам по себе обладает идентичностью. А если тебе надо привязать что-то к объекту, то есть SPLObjectStorage, где объект может быть ключом.
>>64786
> if($creditSum-5000<=0){
Это проще написать как if ($creditSum <= 5000)
> $creditSum-=$creditSum;
$creditSum = 0;
Также, у тебя в коде несколько раз повторяется цифра 5000, было бы лучше вынести ее в переменную - так и код будет понятнее, и поменять сумму выплаты будет проще.
7777 надо было добавлять к начальной сумме долга, а не к сумме выплаченного. От этого наверно и ошибка.
>>64614
> автомобильный номер: https://ideone.com/JLu2Pp
Верно.
> телефон 1: https://ideone.com/0nmMqh
Верно, единственный недостаток - у тебя программа не выделяет проблемные номера (которые например верны, но определяются как неверные).
> телефон 2: https://ideone.com/uOeHc3
> "/^(8|\\+\\s?7)/",
цифру 8 можно не заменять.
Решено верно.
> автозамена: https://ideone.com/p16mil
> $rusChars = ['е','у','о','р','х','а','с'];
Тут надо обязательно ставить комментарий, какой это алфавит, а то непонятно. Если кто-то начнет редактировать код, он легко может добавить букву не того алфавита.
> $pattern = str_replace($rusChars, $rusEngChars, $pattern);
Вообще, формирование регулярок с помощью кода имеет тот недостаток, что чтобы разобрать что делает твой код, мне его надо в уме выполнить. Но если более простого способа нет, то это допустимо.
Работает верно.
>>64494
Нужен текст ошибки, а также маленький кусочек кода, вызывающий ошибку, так как из поста неясно даже какую функцию ты используешь.
Да. Но id особо и не нужен. Объект сам по себе обладает идентичностью. А если тебе надо привязать что-то к объекту, то есть SPLObjectStorage, где объект может быть ключом.
>>64786
> if($creditSum-5000<=0){
Это проще написать как if ($creditSum <= 5000)
> $creditSum-=$creditSum;
$creditSum = 0;
Также, у тебя в коде несколько раз повторяется цифра 5000, было бы лучше вынести ее в переменную - так и код будет понятнее, и поменять сумму выплаты будет проще.
7777 надо было добавлять к начальной сумме долга, а не к сумме выплаченного. От этого наверно и ошибка.
>>64614
> автомобильный номер: https://ideone.com/JLu2Pp
Верно.
> телефон 1: https://ideone.com/0nmMqh
Верно, единственный недостаток - у тебя программа не выделяет проблемные номера (которые например верны, но определяются как неверные).
> телефон 2: https://ideone.com/uOeHc3
> "/^(8|\\+\\s?7)/",
цифру 8 можно не заменять.
Решено верно.
> автозамена: https://ideone.com/p16mil
> $rusChars = ['е','у','о','р','х','а','с'];
Тут надо обязательно ставить комментарий, какой это алфавит, а то непонятно. Если кто-то начнет редактировать код, он легко может добавить букву не того алфавита.
> $pattern = str_replace($rusChars, $rusEngChars, $pattern);
Вообще, формирование регулярок с помощью кода имеет тот недостаток, что чтобы разобрать что делает твой код, мне его надо в уме выполнить. Но если более простого способа нет, то это допустимо.
Работает верно.
>>64494
Нужен текст ошибки, а также маленький кусочек кода, вызывающий ошибку, так как из поста неясно даже какую функцию ты используешь.
https://ideone.com/5GYxQY
Не совсем понял, как сделать задачку на автозамену "дурака", чтобы "не пропустить капс" и русский алфавит.
Сделал такое '/ду[рp][аa][кk]/ui'
Или это как-то по-другому делается?
>чтобы "не пропустить капс"
Переводишь всю строку в нужный регистр, например - strtolower, и потом уже проверяешь.
Хотя лучше наверное mb_strtolower использовать.
почитать маны.
Пройди тут code-basics.ru
Любая книга старше 2015 года 100% устарела.
Самая актуальная конкретно по ПХП это "ПХП7 В Подлиннике"
Контроллер любая функция, которая возвращает тебе View
Мне нужно заменить все значения true, на false.
Делаю это двумя foreach, в первом передача по ссылке+unset
А что если просто сериализовать массив в строку, и пройтись регулярко, ну и потом обратно собрать?
Будет просто медленнее
Чем это лучше флага i в регулярке?
Алсо задачка на поиск емейл в тексте. https://ideone.com/bOB8LV
deadj.github.io
https://github.com/deadj/deadj.github.io
Зачем unset?
Хорошая книга, кстати. Наконец стало понятно, как и зачем комбинировать трейты и интерфейсы.
Конечно, большой секрет погромистов в том, что ты можешь быть не столько умным, но если ты упорный у тебя всё получится. Гением может ты никогда не станешь, мб даже не станешь хорошим программистом, но работу свою будешь знать и делать сносно.
Алсо можешь посмотреть решение здесь, если оно будет.
Тоже так было, первые два вечера бился над пониманием ооп, на третий день вдруг само все пришло в голову, так что не переживай, это принцип работы мозга, обрабатывает все в режиме прокрастинации. Потом, как сказал анон выше, само в мозгу будет все строиться.
Запостил бы примеры кода и вопросы по нему, что непонятно.
Также, по ООП (после Вектора) у нас есть дополнительные задачи:
- Будильник https://phpclub.tech/pr/res/1232710.html#1263399
- Гостиница https://phpclub.tech/pr/res/1082507.html#1097078
Поищи их по этим словам в этом треде.
Но ты и правда присмотрись. Обычно у животных хвост либо служит сигналом-маркером (как у собак и кошек), либо просто висит, прикрывая анус. У этого же слона (у него биологических хвост "висит") хвост поднят - значит, что анус сейчас "работает". Т.к. говна не видно, очевидно что он пускает шептуна.
Плюс к этому предположению - его ехидная рожа. Если бы пердеж был громким, все бы определили что это именно слон. А так - звука нет, хотя глаза режет. Поэтому слон с такой хитрой улыбкой, хитрее чем у редкого Пепе.
Напердел и рад.
вопрос: че может случиться, если этому совету не следовать?
Сделал вектор в свое время где-то за час. Гостиницу и будильник до сих пор ума ни приложу как делать из-за полного непонимания того, как работать с временем.
https://gist.github.com/codedokode/8733007
https://dbdesign.online/s/hr1txmykle7i6gkmsnia
https://ideone.com/3M9637
Возник следующий вопрос.
Здесь я для того, чтобы проверять букву в большом и малом регистре сделал пару из заглавной и прописной в массиве 'O'=>'O','o'=>'о'.
В JS я бы решил этот момент через колбэк в реплейс типа такого
string.replace(/'[Oo]'/gi, x=> x==x.toLowerCase()?'русская о':'руccкая О');
Как в пыхе решать такие ситуации без создания пар выборов в объекте, массиве, а на стадии матча, в зависимости от матча, на лету?
>стоит ли продолжать?
Конечно. Выучишь ООП и сразу можешь претендовать на позицию мидла в моей мухосрани https://tambov.hh.ru/vacancy/27890168
Как же хочется в Тамбов...
ты взорвешься
Значения никакого. Можешь хоть на маке код писать.
вполне хорошая зарплата даже для моего миллионника, лол
Планирую перекатиться, ибо за винду кмк могут не взять на работу особо упоротые ЖМУПИНУСЫ.
Хоть и не вижу ничего плохого в попенцорсе перспектива тратить время ЕЩЕ И НА ЭТО удручает. С другой стороны мб освою быстро.
Использую кликхаус, поэтому выбор не велик. А так что удобнее там и сиди.
Все окружение для запуска веб приложения на линуксе - не стоит ли, а НУЖНО УЖЕ ПРЯМО СЕЙЧАС.
Работать надо будет с проектом на кохане.
Зп от 20к на руки
Пишите о себе на anonymouserGD-samaANUSmai9i^lPUNCTUMrr<6u
Анус себе поищи.
Подними себе на виртуалке LAMP и ковыряйся в нём, я думаю этого будет достаточно.
Крч сам нашел, что в пыхе тоже колбэчие в реплейс сувается.
Задачка "Клавиша Shift"
https://pastebin.com/CnQ0AbL1
(в идеоне мб экстенщона нет, кодепад ругался на наличие функции в реплейсе. Проверил сниппет здесь http://phptester.net/, https://phpfiddle.org/, http://phpcodepad.com/, вроде пахает)
конечно. со временем чем ты будешь круче, тем больше у тебя будет задач, связанных с инфраструктурой (сервера очередей, написать докер-конфиг, транспорт, анализировать логи, чинить оварии и т.д.). плюс если в конторе используется локальная разработка, ты ставишь себе максимально приближенный конфиг к проду. плюс если используется докер, то там все равно внутри линукс, надо знать команды и проч.
я коггда решил вкатываться в ойти, удалил винду к хуям. щас уже два года на линуксе, как будто всю жизнь на нем сидел
спасибо за подробный анализ, анон.
это тебе нетбинс говорит?
ну полезно чистить входные данные, если ты работаешь с ними напрямую. правда сложно представить ситуацию, что ты пишешь что-то для общения с $_POST своими руками, а не используешь фреймворки или библиотеки, в которых уже все реализовано и протестировано
Ну блять...
Извините
Я же без зла сказал :3
Смотрю задачи уровня тупого джуна на апворке и там все хотят использовать именно его.
>пишу заново компоненты, которые уже миллиард раз написаны, потому что я люблю заваливать сроки
Всегда пожалуйста!
Написал выблядок дрочащий на пепу, кек
255 раз
1) Граммар нази. Тут у меня есть ощущение, что я как-то не аутентично использую функции для работы с регулярками + там же надо делать исправление больших букв и я его добавил отдельным правилом т.е. не оче умно. Но т.к. я уже долго в этом вожусь - оставил как есть.
Задача: https://ideone.com/OW5uJV
2) Опечаточники. Тут ты, ОП, в спойлере у задачки оставил примеры текстов - которые добавляют дополнительные условия, т.е. в слове может быть несколько опечаток, или англ.символы могут идти подряд, что заставляет переписывать регулярки и код. Кароче пока тоже оставил как есть.
Задача: https://ideone.com/KmRlPx
P.S. В общем мне нужен пример решения, хочется двигаться дальше. ОП'чик скинь мне на мыло vovchea~pnkoalANUSy<p/andexPUNCTUMr__mu или телегу @y0urbe3tfr1end
Эти задачи решались 1000 раз, попробуй загуглить примеры по названиям функций/комментариям/ключевым словам. В гугле не забудь добавить приставку site:ideone.com, если ничего не нашлось пробуй без неё.
>>68731
Искать лучше в архиве тредов: phpclub.tech
>>68697
>>1268987
> 1) Граммар нази.
Лучше было бы не переделывать регулярки программно, а сразу написать их в нужном виде. Это облегчит восприятие кода и не надо будет его разбирать, чтобы понять, как они трансформируются.
Читать выражения вроде $rule[2] не очень удобно, потому массив можно разобрать на переменные вручную или конструкцией list:
list($regexp, $replace, $comment) = $rule;
В выражении для контекста лучше было использовать звездочку, а не плюс, так как после или перед подстрокой с ошибкой может и не быть других букв.
А так, сделано хорошо.
> 2) Опечаточники.
Конечно, в слове может быть несколько замененных букв, почему нет?
Код можно было упростить, если разбить текст на слова, определить язык слова (по первой букве например или как-то еще) и искать в нем все буквы другого алфавита. Заодно можно было бы найти слова с несколькими опечатками.
Готового примера решения нет, другие решения можно поискать на phpclub.tech, там есть поиск.
>>68596
Это из тестового задания? Теоретически, много. Почитай урок про структуру URL: https://github.com/codedokode/pasta/blob/master/network/urls.md
Знак вопроса впоне может встретиться в query string и в якоре неограниченное число раз. Однако, в некоторых случаях длина URL может быть ограничена браузером или веб-сервер может отказаться принимать слишком длинный URL. Например, апач в конфигурации по умолчанию, если не путаю, имеет лимит в районе 2000 байт.
>>68731
Искать лучше в архиве тредов: phpclub.tech
>>68697
>>1268987
> 1) Граммар нази.
Лучше было бы не переделывать регулярки программно, а сразу написать их в нужном виде. Это облегчит восприятие кода и не надо будет его разбирать, чтобы понять, как они трансформируются.
Читать выражения вроде $rule[2] не очень удобно, потому массив можно разобрать на переменные вручную или конструкцией list:
list($regexp, $replace, $comment) = $rule;
В выражении для контекста лучше было использовать звездочку, а не плюс, так как после или перед подстрокой с ошибкой может и не быть других букв.
А так, сделано хорошо.
> 2) Опечаточники.
Конечно, в слове может быть несколько замененных букв, почему нет?
Код можно было упростить, если разбить текст на слова, определить язык слова (по первой букве например или как-то еще) и искать в нем все буквы другого алфавита. Заодно можно было бы найти слова с несколькими опечатками.
Готового примера решения нет, другие решения можно поискать на phpclub.tech, там есть поиск.
>>68596
Это из тестового задания? Теоретически, много. Почитай урок про структуру URL: https://github.com/codedokode/pasta/blob/master/network/urls.md
Знак вопроса впоне может встретиться в query string и в якоре неограниченное число раз. Однако, в некоторых случаях длина URL может быть ограничена браузером или веб-сервер может отказаться принимать слишком длинный URL. Например, апач в конфигурации по умолчанию, если не путаю, имеет лимит в районе 2000 байт.
Не знаю, зависит от ситуации и от того, как ты используешь данные. "Очистка" данных в начале скрипта работает, когда они подчиняются определенному шаблону (например, содержат только цифры), но не работает в общем случае, когда данные могут содержать любые символы (например, текст комментария), так как непонятно, как их отфильтровать.
>>68248
У меня все работает, но это временный домен и надо заходить через адрес https://codedokode.github.io/phpbook
>>68195
Теоретически можно убрать, но надо тогда предложить нормальную замену с аналогичным функционалом. Либо писать предупреждение.
>>67873
Я думаю, код получился не очень понятным. Лучше было сделать несколько вызовов preg_replace, каждый для своего правила. Один вызов расставляет пробелы, другой делает буквы заглавными.
Плюс, ты делаешь ошибку, $i[0] возвращает первый байт строки, а не первый символ, и многие символы в utf-8 занимают больше одного байта, так что ты можешь получить огрызок вместо символа. Лучше использовать mb_substr().
Двойные кавычки добавлять в строку не требовалось.
Выражения для знаков препинания и пробелов можно было объединить: искать выражение вида
(любое число пробелов)(1 или более знаков)(любое число пробелов)
Соответственно коллбек не нужен в такой ситуации.
Так-то работает верно, но код плохо читается и тяжело разбирать. Лучше было сделать отдельными правилами.
Не знаю, зависит от ситуации и от того, как ты используешь данные. "Очистка" данных в начале скрипта работает, когда они подчиняются определенному шаблону (например, содержат только цифры), но не работает в общем случае, когда данные могут содержать любые символы (например, текст комментария), так как непонятно, как их отфильтровать.
>>68248
У меня все работает, но это временный домен и надо заходить через адрес https://codedokode.github.io/phpbook
>>68195
Теоретически можно убрать, но надо тогда предложить нормальную замену с аналогичным функционалом. Либо писать предупреждение.
>>67873
Я думаю, код получился не очень понятным. Лучше было сделать несколько вызовов preg_replace, каждый для своего правила. Один вызов расставляет пробелы, другой делает буквы заглавными.
Плюс, ты делаешь ошибку, $i[0] возвращает первый байт строки, а не первый символ, и многие символы в utf-8 занимают больше одного байта, так что ты можешь получить огрызок вместо символа. Лучше использовать mb_substr().
Двойные кавычки добавлять в строку не требовалось.
Выражения для знаков препинания и пробелов можно было объединить: искать выражение вида
(любое число пробелов)(1 или более знаков)(любое число пробелов)
Соответственно коллбек не нужен в такой ситуации.
Так-то работает верно, но код плохо читается и тяжело разбирать. Лучше было сделать отдельными правилами.
> Задача "Опечаточник"
Для замены тут не требуются регулярки, можно было использовать strtr() с массивом. Также, ты ищешь только латинские буквы, но надо искать слова из букв разных алфавитов. Проще всего сделать так: разбить текст на слова и для каждого слова определить язык первой буквы и проверить наличие букв другого алфавита.
Ну или сделать регулярку, ищущую слова из букв разных алфавитов.
> Здесь я для того, чтобы проверять букву в большом и малом регистре сделал пару из заглавной и прописной в массиве 'O'=>'O','o'=>'о'.
Тут проще всего так, потому что маленькие и большие буквы не эквивалетны. Латинская H похожа на букву кириллицы, а h - уже нет. Аналогично B/b - они похожи на буквы в/ь.
>>67805
Какие паттерны и где надо использовать? Паттерны сложная штука и без опыта их учить смысла мало. Да и объясняются они плохо - попробуй, объясни начинающему, зачем нужна фабрика, когда объекты можно создавать через new.
Паттерны, которые просто заучиваются без понимания, приносят больше вреда, так как их начинают употреблять там, где не надо, и усложняют код.
>>67703
Я дебиан использовал - работает хорошо, хотя конечно без гугла и залезания в конфиги не обошлось (ну, мне не привыкать).
>>67370
Для пользователей - не забудь про хеширование и соление паролей.
Идея хранить содержимое теста в виде JSON мне не очень нравится, так как не будут работать внешние ключи (например, на выбранный вариант ответа) и не контролируется структура содержимого - а это значит, там быстро начнут накапливаться ошибки. Ну и структура никак не документирована, и глядя на базу, будет трудно ее разобрать.
> Задача "Опечаточник"
Для замены тут не требуются регулярки, можно было использовать strtr() с массивом. Также, ты ищешь только латинские буквы, но надо искать слова из букв разных алфавитов. Проще всего сделать так: разбить текст на слова и для каждого слова определить язык первой буквы и проверить наличие букв другого алфавита.
Ну или сделать регулярку, ищущую слова из букв разных алфавитов.
> Здесь я для того, чтобы проверять букву в большом и малом регистре сделал пару из заглавной и прописной в массиве 'O'=>'O','o'=>'о'.
Тут проще всего так, потому что маленькие и большие буквы не эквивалетны. Латинская H похожа на букву кириллицы, а h - уже нет. Аналогично B/b - они похожи на буквы в/ь.
>>67805
Какие паттерны и где надо использовать? Паттерны сложная штука и без опыта их учить смысла мало. Да и объясняются они плохо - попробуй, объясни начинающему, зачем нужна фабрика, когда объекты можно создавать через new.
Паттерны, которые просто заучиваются без понимания, приносят больше вреда, так как их начинают употреблять там, где не надо, и усложняют код.
>>67703
Я дебиан использовал - работает хорошо, хотя конечно без гугла и залезания в конфиги не обошлось (ну, мне не привыкать).
>>67370
Для пользователей - не забудь про хеширование и соление паролей.
Идея хранить содержимое теста в виде JSON мне не очень нравится, так как не будут работать внешние ключи (например, на выбранный вариант ответа) и не контролируется структура содержимого - а это значит, там быстро начнут накапливаться ошибки. Ну и структура никак не документирована, и глядя на базу, будет трудно ее разобрать.
>>67281
> abstract function checkAnswer($answer);
Тут можно было указать тайп-хинт на возвращаемое значение и прокомментировать его.
> public function getQuestionText()
Тут тоже мог бы быть тайп-хинт.
checkAnswer() незачем возвращать points, так как их можно получить отдельным методом (getPoints()) который никак не связан с checkAnswer(). Либо же можно возвращать число очков с учетом праивльности ответа (0 за неправильный, и тд). Тогда это будет иметь смысл.
getQuestionHint() можно перенести в базовый класс вопроса, если подсказка может быть у любого вида вопроса. Если только у вопроса с выбором, то можно оставить как есть.
> if (method_exists($question, 'getQuestionHint')) {
Вот это не очень хороший код, проверять наличие метода. Лучше сделать getQuestionHint в базовом классе. Ведь и у вопроса с вариантами ответов тоже может быть не задана подсказка.
>>66893
> '/(ж|ш)ы/u'
Здесь стоило добавить флаг i, а то "Жыр" не найдет.
> '/(\w*)\s(?<!\,\s)\b(а|но)\
Это выражение сложное, и тут много ограничений: например, то, что пробел перед "а" может быть ровно один. Лучше сделать выражение попроще: (\w) (пробелы) (а или но)
В остальном, верно.
>>67281
> abstract function checkAnswer($answer);
Тут можно было указать тайп-хинт на возвращаемое значение и прокомментировать его.
> public function getQuestionText()
Тут тоже мог бы быть тайп-хинт.
checkAnswer() незачем возвращать points, так как их можно получить отдельным методом (getPoints()) который никак не связан с checkAnswer(). Либо же можно возвращать число очков с учетом праивльности ответа (0 за неправильный, и тд). Тогда это будет иметь смысл.
getQuestionHint() можно перенести в базовый класс вопроса, если подсказка может быть у любого вида вопроса. Если только у вопроса с выбором, то можно оставить как есть.
> if (method_exists($question, 'getQuestionHint')) {
Вот это не очень хороший код, проверять наличие метода. Лучше сделать getQuestionHint в базовом классе. Ведь и у вопроса с вариантами ответов тоже может быть не задана подсказка.
>>66893
> '/(ж|ш)ы/u'
Здесь стоило добавить флаг i, а то "Жыр" не найдет.
> '/(\w*)\s(?<!\,\s)\b(а|но)\
Это выражение сложное, и тут много ограничений: например, то, что пробел перед "а" может быть ровно один. Лучше сделать выражение попроще: (\w) (пробелы) (а или но)
В остальном, верно.
мимосемиклассник
<?php
error_reporting(-1);
$dollars = 200; / Число долларов /
$exchangeRate = 32.24; / Курс обмена /
$roubles = $dollars / $exchangeRate; / А вот эту строчку надо дописать самому /
echo "$dollars долларов можно обменять на $roubles рублей";
вольфрамальфа
сам понял надо было умножить а не делить лол. Чувствую не выйдет из меня пхп макака с работой в мск
даун. это труд. тут люди годами сидят и оттачивают навыки. пока не дойдешь до классов и первых приложений можешь даже не пукать в этот тред.
иди читай литературу, смотри гайды. это процесс. не засоряй тред своим говном.
для нас свято все тут
я буду делтаь все что пожелаю. В твоем мнеии ненуждаюсь. Святое? тперь святое и буду тут. И буду ДЕЛАТЬВСЕ ТЧО ЗАХОЧУ! Запомни это и смирись потому что я тут надолго.
В реальности ты мразота пойдешь в свой манямирок плакатсья н онескажешь мне эт ов лицо
я вас мразот как гнобил так и буду гнобить. До встречи утырок
Вы видите копию треда, сохраненную 26 сентября 2018 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.