Ну что же, зима заканчивается, и это хорошо. А мы по-прежнему изучаем язык PHP (а также JS/CSS/HTML/SQL), решаем задачки, печем печенье и даже делаем простые сайты! Зачем? Кто-то хочет открыть стартап, кто-то заработать на лапшу быстрого приготовления, кому-то просто нечего делать.В нашем треде отвечают почти на все вопросы, только бампайте каждые 5 дней. И не разводите флуд, если вам скучно, лучше сходите промочите ноги на улице, например.Это тред и для начинающих. Слово "классы" у тебя ассоциируется только со школой, а в аттестате тройка по математике? Ты наш человек. Предыдущий тред был тут: >>1331378 (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.mdhttps://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.mdPSR-2: https://github.com/samdark/fig-standards-ru/blob/master/accepted/ru/PSR-2-coding-style-guide.md
Если я кому-то не ответил в прошлом треде, то постараюсь ответить сегодня-завтра. Но вы можете напомнить о себе в этом треде.
Анон помоги. Можно ли как-то заполучить доступ к полному номеру телефона на сайте, если он зашифрован звездочками? Я неумею немножко читать код, но не разобралсс(.
Пхп вообще параша. Кто будет этим всем заниматься? Язык постоянно пытается стать жабой, когда сама жаба уже существует и просто плюет в сторону этого треда. Я уже не говорю про бек на питоне или голанге, где это дело более успешней, чем перебирать говнокод 10летней давности здесь.Подумайте об этом.
>>1353742Смотри через Network, что сервер тебе присылал. Если присылал уже со звездочками, то ничего.
>>1353745Количество вакансий и фирм глянь, где используется. Пхп очень популярен, прост в осовении и гибок, инструменты все современные есть, по скорости щас тоже отдалили. С жабой имеет смысл начинать, если есть огромный энтерпрайз, где кучи сервисов друг с другом коммуницируют. Жаба в крайне малом количестве стартапов сейчас используется, проще и быстрее все на пхп бывает написать и инвесторам результаты показать, чтобы получить дальнейшее финансирование.
>>1353777Проще и быстрее писать на рельсах, если ты очередной манястартапер. Если же хочешь в норм контору - то тут уже юзается питчон, а если прям охуеваешь от своей тормознутости - присыпается голанг для убер маня хайлода.>чтобы получить дальнейший говнокод.Подправил.
>>1353803Какие плюсы у Питона? Это же по сути и по синтаксису почти тот же Яваскрипт, нет даже тайп-хинтов. В Руби та же ерунда. В PHP больше возможностей статической типизации, есть фреймворки, ORM. И разработчиков найти проще.
>>1353803И, конечно, непонятно, как просто использование Питона или Руби повышает качество кода. С чего бы вдруг? Что, менеджер по продажам, прошедший экспресс-курсы по Питону, будет писать более качественный код, чем после курсов по PHP? Вы, товарищи, просто распространяете очень далекие от реальности стереотипы.
>>1353827>В PHP больше возможностей статической типизации, есть фреймворки, ORM. И разработчиков найти проще.Это все нивелируется с существование жабы. Если бы ее не было, возможно пхп был бы еще уебищней.>>1353831Качественный код может написать любой человек который умеет читать доки. Какую-то хуйню не аргументированную спизданул.
>>1353884>Это все нивелируется с существование жабы.Ну так и есть, пхп второй после жабы, пикрелейтед. Где жабу поднимать геморно, но удобство и функциональность жабы нужна, поднимают пхп.
ОП, я сделал все задания из твоего поста и прочитал все книги из оп-поста + некоторые проскакивающие в обсуждении про шаблоны. Что мне делать дальше?
>>1353901>бекенд>мочаскриптА ты хороший сайт выбрал для сравнения. Из всех моих знакомств я ни одного пхпшника не знаю, потому что никто не хочет быть дегенератом.>>1353942>Что мне делать дальше?Делать сайты. Магазины, склады, игровые сайты, фильмы и т.д. Но мне тебя жаль.
Вопрос на засыпку:есть два скрипта. В одном весь код поделен на методы вплоть до абсурда, например, метод hasProperty имеет всего лишь одну строчку кода return isset(prop); и методов очень много, сами понимаете, код раздут, код ради кода. В другом все написано в одном методе. Какой из этих скриптов отработает быстрее?
>>1354111А ты это не читал? https://github.com/codedokode/pasta/blob/master/arch/di.md Там нет ответа?
Спрашивал в JS-треде, но там молчатПомогите изменить скрипт, пожалуйста.Логика такая: при загрузке страницы срабатывает скрипт, считывает значение поля amount, отправляет его аяксом в requestUrl.php, принимает ответ и ждёт, пока человек не нажмёт кнопку payButtonId. Нажал - данные улетают в https://pay.realexpayments.com/payПроблема в том, что кроме amount нужны дополнительные поля, но пользователь заполняет их уже на странице. То есть, нужно, чтобы он сначала заполнил их, и только потом срабатывала их отправка в requestUrl.phpУ меня не получается так сделать. Даже если ввести ещё одну кнопку и повесить на неё скрипт отправки в requestUrl.php, а на вторую отправку в платёжку, то отправка в платёжку не срабатывает. Работает только по $(document).readyВот код:https://jsfiddle.net/tw6f7y2b/
>>1354232Да. Если бы я был бы тобой и только закончил бы опа таски - то я бы сменил род деятельности ( в програмаче ). Явно не жаба, там слишком много писать. Пошел бы в питон, если бы ничего больше не знал. А если бы я делал выбор сейчас - то остался бы в мобилках. Тут языки не нужно придумывать. Все стандартно. Но для бека я бы выбрал голанг или рельсы.
>>1354342>как-год-перекатился-в-божественный-рубиА я вот выбирал между гошкой и руби. Не понравилась мне динамика. Поэтому делаю внутрипроекты на гошке.
Добрый вечер, задался вопросом как вообще устроены большие парсеры, есть ли какое-то название у этого и какие технологии используются? Например если есть какой-то агрегатор - на чем именно пишут парсеры для него?
>>1354219Смысл сервис-контейнера в том, что он может создавать сервисы с зависимостями, не заставляя нас делать это вручную. Принцип DI (внедрение зависимостей) обычно требует передавать зависимости в сервис снаружи. Вручную это выглядит так. Допустим, нам нужен сервис C, который зависит от A и B:$a = new A;$b = new B;$c = new C($a, $b);С контейнером: $c = $container->get('C'); // Или $app->make('C') в LaravelЕсли что, DI и контейнеры я попытался, как мог, описать в своем уроке: https://github.com/codedokode/pasta/blob/master/arch/di.md - без теории по DI трудно понять, зачем нужен контейнер.Второй плюс DI контейнера в том, что он умеет сохранять ранее созданный объект и возвращать его, а не создавать новый, при повторном вызове. Это в Ларавель называют "синглтоном".Далее, ты упомянул "сервис-провайдеры". Это немного другая штука. Они используются, чтобы пачкой зарегистрировать несколько сервисов. Ты мог бы обойтись и без провайдера, и просто зарегистрировать сервисы в контейнере руками, но если ты, например, делаешь библиотеку, то логично объединить предоставляемые ей сервисы в провайдер, чтобы можно было зарегистрировать их одним действием.> Заодно вопрос какая структура папок должна быть для контрактов и их реализации.Не знаю, в документации Ларавел не описано? > Если бороться с жирными контроллерами через сервисный слой то какую выбрать структуру папок чтоб можно было вернуться к проекту через месяц?А ты разобрался, что такое сервисы? Проблема "толстых контроллеров" в том, что код в них нельзя повторно использовать. Ты описал, например, код регистрации пользователя в контроллере и после этого ты не можешь создать пользователя программно из другого места кода. Сервисы решают эту проблему. Если у тебя маленький проект, то ты просто кладешь сервисы в одну папку. В простейшем случае можно для каждой сущности сделать свой сервис (сервис для работы с постами, с комментариями, с пользователями). Если большой - то делаешь, например, подпапки, а сами сервисы разделяешь по задачам: сервисы приема платежей, сервисы для подсчета статистики, итд.
>>1354379Это правильно называется "скрейперы", и как правило, абсолютно ничего сложного там нет, все элементарно: - загружаем HTML код- выделяем куски страницы с помощью какой-нибудь DOM-библиотеки, по имени CSS-класса, по тексту, по еще каким-то HTML-атрибутам- выводим собранные данные в каком-нибудь форматеЕсли ты знаешь HTML и DOM, то это обычно элементарная задача.Со сложными алгоритмами никто не заморачивается, так как обычно написанный вручную "скрейпер" стоит очень дешево, зачастую как 1 час работы профессионального разработчика.Еще можно, как Телеграм, объявить конкурс и выбрать лучшее решение: https://habr.com/ru/post/438926/Еще есть способы, когда ты берешь страницу, каким-то расширением для браузера помечаешь на ней нужные места, и оно автоматически генерирует код для скрейпинга (или, например, xpath- или CSS-выражения). Это, мне кажется, интересная идея, так как позволяет привлекать не-программистов (за меньшие деньги) к созданию скрейперов. Но те, кому нужно заниматься скрейпингом массово, например, поисковые системы, иногда пытаются что-то придумывать: микроразметку, автоматическое выделение содержимого, итд. Простейший способ автоматического анализа - взять 2 разных страницы с сайта, сравнить и таким образом увидеть различающиеся и общие (не содержащие полезной информации) части. Я когда-то давно пробовал писать такую штуку, но там оказался огромный объем работы и я забил на нее.http://xgu.ru/wiki/HTML_scraping>>1354305Какой смысл выучить один язык, забросить, и учить другой? Никакого. Это, конечно, не значит, что не надо смотреть другие языки - полезно для расширения кругозора, или повышения своих навыков.Но учить язык только потому, что анонимные эксперты с двача называют его "боежственным", довольно глупо. Есть такие люди, которым в принципе работать не интересно, они весь день сидят, пишут код на Си, PHP, C# или Яве, страдают, а тут рассуждают про "божественные" языки (которые точно так же им наскучат через неделю, если попросить их поучаствовать в большом, реальном проекте на них в команде, с реальным кодом, а не задачками на 500 строк).
>>1354305В Питоне нет тайп-хинтов, приватных полей. Там везде костыли вроде virtualenv (так как Питон и его окружение по умолчанию пытается устанавливать пакеты в системные директории, что не всегда хорошо). Несколько менеджеров пакетов, причем часто один менеджер используется только для установки другого. Ужасные сокращения, часто нелогичные (например: в matplotlib есть метод set_xlim, а не set_x_limit, но при этом есть set_xscale). Вообще, если брать библиотеки вроде numpy или matplotlib, то нелогичность названий и интерфейса там вполне сопоставима с таковой же в стандартной библиотеке PHP. matplotlib это вообще жесть. Хотя богатство возможностей, конечно, радует. Расширять библиотеки часто сложно. Например, попробуйте прикрутить DNS-кеш или подменить DNS-резолвер в стандартной библиотеке urllib. Придется поломать голову. Часто используются глобальные переменные, глобальное состояние, или статические методы. Например: в urllib3 для настройки логгирования вместо DI (создать логгер и передать в urllib3) предлагают использовать код: logging.getLogger("urllib3").setLevel(logging.WARNING)А для замены компонента SSL предлагают: urllib3.contrib.pyopenssl.inject_into_urllib3()Ну не жесть ли, везде глобальные переменные и кривые костыли вместо DI? Кстати, обратите внимание на разный стиль написания имен функций и бессмысленные части неймспейса вроде contrib. То же самое в urllib.requests: > urllib.request.install_opener(opener)> Install an OpenerDirector instance as the default global opener.Это функция, которая меняет глобальное состояние библиотеки, и я подозреваю, кому-то надо было иметь возможность подменять компоненты и он, не заморачиваясь с архитектурой и рефакторингом, просто влепил костыль по-быстрому. Обратите внимание на стиль написания функций: > urllib.request.build_opener()> urllib.request.getproxies()Я не уверен, есть ли бесплатные IDE с анализом кода, показом определений для Питон. Ну и вакансий вроде меньше.
>>1354129Ну так померяй, например, на миллионе вызовов. Желательно сделать время измерения большим, минуты или более, чтобы нивелировать разные прерывания работы программы. Должен предупредить, обычно тормоза в программах возникают совсем не из-за этого и ты просто зря потеряешь время.>>1353992Человек, обзывающий других дегенератом, хорошего впечатления не производит. >>1353942А что ты хочешь делать? Устроиться на работу, сделать свой проект, сдать сессию, какая у тебя цель? Если на работу - то с задачами про студентов и файлообменник, навыками верстки, SQL, JS вполне может быть достаточно знаний. Можно, конечно, дополнительно освоить какой-нибудь фреймворк вроде Симфони или Ларавель, или посмотреть какую-то популярную CMS. Вроде как у нас были люди, которые послет студентов или файлообменника устраивались на работу и дальше задачи не делали.
>>1353884> Качественный код может написать любой человек который умеет читать доки. Неверно. Вот, допустим, человек прочитал документацию по Питону - станет ли он писать качественный код? Да не факт, Питон очень провоцирует городить списки из словарей, называть переменные непонятно итд. Будет ли этот человек знать MVC, ООП, паттерны? Вряд ли. Вот посмотри библиотеки matplotlib или urllib. Их, наверно, писали люди, читавшие доки, но качество кода очень страдает, мягко говоря. Они даже функции назвать единообразно не смогли, не говоря уж про такие вещи, как DI. Я не вижу особого различия в качестве между PHP- и Питон-библиотеками.>>1353745Тогда что ты, болезный, забыл в нашем треде? Выкатывайся в свой тред и нахваливайте друг друга петухами и кукушками. У нас тут учебный тред, а не тред для самоубеждения, что у нас самый лучший язык.
>...использование Питона или Руби повышает качество кодадень 00:20 вот-вот начался, а ты уже сделал его
Шаблон Реестр и класс DI дублируют друг друга? Я смотрю, у них одна и та же структура. Геттер, сеттер и контейнер. Разница между ними лишь идеологическая?
>>1354517Реестр обычно это глобальное хранилище и он может быть только один. А если ты сделаешь Реестр на нестатических методах как объект, то он от DI контейнера будет не отличим.
>>1354503>А что ты хочешь делать? Устроиться на работу, сделать свой проект, сдать сессию, какая у тебя цель? Если на работу - то с задачами про студентов и файлообменник, навыками верстки, SQL, JS вполне может быть достаточно знаний. Можно, конечно, дополнительно освоить какой-нибудь фреймворк вроде Симфони или Ларавель, или посмотреть какую-то популярную CMS. Вроде как у нас были люди, которые послет студентов или файлообменника устраивались на работу и дальше задачи не делали.Я хочу устроиться на работу, но не абы куда, студии мимо, хочу заняться серьезным серверным программированием. Мне в вузе очень нравилось проектировать базы данных, вследствие этого за мной тянется фундаментальный багаж знаний о реляционных и нереляционных баз данных. Здесь я только пхп учил. Смотрел, кто из знакомых по вузу где зацепился, большинство не работает по профессии, некоторые админят (тоже не по профессии), некоторые пашут на мобилках, делают приложения, один ушел в 1С. Говно, в общем. Что делать, куда идти? Может свой проект сначала написать какой-то, чтобы крупные компании на меня обратили внимание?
>>1354520То есть они могут вместе существовать? А вот тут https://designpatternsphp.readthedocs.io/ru/latest/Structural/Registry/README.htmlпишут, что лучше использовать DI вместо Registry.
>>1354526В стартап либо компашку поменьше иди джуном. На собесе задавай вопросы, что они там пилят, если какой свой проект и начинают про архитектуру рассказывать, то круто, если про 100500 клиентов и как они им один и тот же фреймворк или цмс фигачат, то не очень. Можно в принципе и в студии свой уровень подтянуть, если по ходу дела книгу вроде зандстры осваивать и кусками паттерны и нормальный код стараться организовывать, но это дольше. Свой проект на гитхабе конечно лучше сразу, если еще и ООП нормальный там будет, то на собеседовании тебя уже будут нормально воспринимать, и будет о чем рассказать.
>>1354494резюмируя - в сервис контейнер я пихаю только если у меня присутствует необходимость в зависимости? если у меня просто вспомогательный класс (сервисного слоя) без зависимостей для контроллера я его просто делаю use и использую.>Не знаю, в документации Ларавел не описано? контракты в /app/Contracts а реализации их неизвестено где
сап, подскажет мб кто.В общем у меня есть скрипт пхп вывода значений из mysql, как его засунуть в таблицу на сайте хтмл?
>>1354495>Это правильно называется "скрейперы"Да нет, проблем с написанием его нет. Меня интересует как и на каких технологиях разворачивают крупные скрейперы а-ля momondo или другие агрегаторы. Вот допустим есть агрегатор который должен содержать актуальную информацию, то-есть нужен не только первоначальный сбор инфы с сайта но и постоянный перепарсинг сайта (не учитываем тут защиту сайтов, считаем что её нет и принимаем работу что не все сайты нужно парсить, у некоторых есть удобное API).Можно ли использовать Apache Beam для таких целей или что-нибудь подобное? Или как вообще они устроены? Докеризированные контейнеры которые разворачиваются on purpose? Меня не сам процесс парсинга интересует (тут я имею немного опыта, писал как PHP-парсеры так и мультипоточные парсеры на selenium-js) а вот та инфраструктура которая позволяет поддерживать беспрерывную работу парсеров под большой нагрузкой и в автоматическом режиме.
>>1354608Джава, если объект-ориентированный php освоил, то будет минимум отличий и без усилий перейдешь, все довольно похоже. К тому же вакансий на ней поболее и платят там лучше, ну и в джаве более серьезно к качеству кода относятся, чем в питонах.
>>1354786Тханкс. По пых я всю доку от корки до корки перечитал, долго работал пыхокодером. Хотет перекатиться во чтото для взрослых людей, чтобы быть уважаемым господином.Т.е. хочу выбрать язык которому я мог бы посвятить жизнь без всяких сомнений, изучать каждый пук. Удачным ли выбором для таких целей является джава?
>>1354777У нас в шараге под подобное были докеры на амазоне, запускались по таймеру из дженкинс, результаты потом дампом БД пересылались в основную базу. Платили только за время работы парсеров. Но наверняка есть лучшие методы.
>>1354803То-есть в докере генерились дампы, не было прямого взаимодействия с бд? Был какой-то микросервис отдельный который принимал дампы на импорт? Немного подробнее пожалуйста этот момент объясни.
>>1354794Питон по синтаксису на мой взгляд посасывает современному PHP, нет неймспейсов как у PHP, там интерпретатор ищет файлы сперва в локальной области видимости, потом в PYTHON_PATH и тд, есть конечно импорт директорий но это на мой взгляд не так удобно как с нейспейсами в PHP, нет тайпхинтов. Есть генераторы списков (удобная хрень) и есть многопоточность мимо начал изучать python параллельно с основной работой на PHP
https://github.com/someApprentice/CrypterДля начала реализовал сервис авторизации. Можно сказать, что это выполненная задача Студентов https://github.com/codedokode/pasta/blob/master/student-list.md выполненная на JavaScript, с Server Side Rendering и SPA, поэтому если новичкам интересно они могут что-то подсмотреть.Если у новичков есть какие-то вопросы - чувствуйте себя свободно задавать их.Всё сделано "как по учебнику" и интересного здесь мало чего, за исключением пару вещей.1. При первом заходе на сайт, пользователя встречает форма Приветствия, в которую нужно заполнить email и, в зависимости от того зарегистрирован ли пользователь или нет, перенаправляет на страницу регистрации или логина, а соответствующий импут email'а автозаполняется.Это реализовано с помощью пары строчек, которые добавляют для определенного роута поле data с этим email'ом:https://github.com/someApprentice/Crypter/blob/master/src/app/auth/welcome/welcome.component.ts#L46-L49https://github.com/someApprentice/Crypter/blob/master/src/app/auth/registration/registration.component.ts#L75-L77https://github.com/someApprentice/Crypter/blob/master/src/app/auth/login/login.component.ts#L35-L37Но получив некий опыт на Ангуляре, я понял что более шаблонным и следовательно простым для понимания было бы обернуть все эти компоненты в отдельный компонент AuthComponent и в нём уже сделать свойство email (а лучше объект user/form) и передавать это значение с помощью "Взаимодействий Компонентов" https://angular.io/guide/component-interaction.2. Поскольку приложение пререндерится на сервере а так же работает в браузере, ему нужен общий "источник информации" о пользовательском хранилище. Так как, для сервера используются лучшие пользовательское хранилище это Кукисы по сути кукисы не на что не влияют кроме как условий отображения пререндеренной страницы, а для браузера localStorage, то для обоих этих хранилищ написан сервис-обёртка. https://github.com/someApprentice/Crypter/blob/master/src/app/storage.service.ts#L18-L20https://github.com/someApprentice/Crypter/blob/master/src/app/storage.service.ts#L22-L26https://github.com/someApprentice/Crypter/blob/master/src/app/models/StorageWrapper.tsНебольшие вопросы, которые не критичны, но всё же знать их следует чтобы довести до идеала:https://github.com/someApprentice/Crypter/blob/master/api/api.ts#L31Позволяет ли Bearer token защититься от XSRF? Я детально изучил эту уязвимость и касаемо этого вопроса, критический момент зависит от того, что может ли злоумышленник "обмануть" браузер отправить автоматически запрос с этим токеном. Он может, например, сделать XMLHttpRequests с ним (со своего сайта), но для начала ему нужно узнать этот токен, что практически тоже самое что добавлять csrf-token, чтобы бороться с этой уязвимостью.Способ с Bearer token'ом технически идентичен с методом Cookie-to-header token ( https://en.wikipedia.org/wiki/Cross-site_request_forgery#Cookie-to-header_token ) за исключением семантики заголовка X-Csrf-Token заменённого на Bearer token. И в моём случае, токен хранится в Кукисах, которые защищены с помощью HttpOnly и Secure флагов и в localStorage.Приходит ли вам на ум какая-нибудь слабая точка которую можно эксплуатировать?https://github.com/someApprentice/Crypter/blob/master/src/app/storage.service.spec.ts#L32-L33Достаточно ли это строгая проверка на то является ли сущность экземпляром объекта localStorage?https://github.com/someApprentice/Crypter/blob/master/src/app/models/StorageWrapper.tsВ правильной ли директории находится эта обёртка? Это не совсем сущность, например как User, но места по лучше я не могу придумать для неё. Куда следует помещать обёртки?https://github.com/someApprentice/Crypter/blob/master/src/app/auth/registration/registration.component.spec.ts#L67https://github.com/someApprentice/Crypter/blob/master/src/app/auth/login/login.component.spec.ts#L66Нужно ли делать проверку на каждую валидацию? Например на встроенные в Ангуляр валидаторы или на валидацию по регулярному выражению? https://github.com/someApprentice/Crypter/blob/master/src/app/auth/registration/registration.component.ts#L21-L24Следующий шаг написания сервиса сообщений. Он будет реализован с помощь протокола WAMP и на платформе от https://crossbar.io/ , которая написана на Питоне, и для которой для аутентификации клиентов нужно тоже написать код на нём. https://github.com/crossbario/crossbar-examples/blob/master/authentication/ticket/dynamic/authenticator.pyПоэтому я сейчас буду изучать его, и возможно у меня появиться небольшие вопросы по нему. Могу я задать их в этом треде?Заодно и реактивное программирование подучу.Буду признателен за проверку моего завершающего задания на JavaScript.Это очень много значит для меня. Большое спасибо.
Аноны, меня из фронт-энд треда послали к вам. Меня интересует возможность удаленного заработка в пределах 40к. Сейчас начал изучать HTMl 5. И появилась парочка вопросов:1) Реально ли работая на фрилансе 8-10 часов в день поднимать 40к для среднестатистического человека?2) Не покажется ли такая работа скучной, через чур сидячей или все зависит от организации раб. места?Если это реально, то с такой зарплатой в 40к, в своем м-сраснке с населением 150к я буду полубогом. В принципе, верстать нравится, сейчас пилю нубский сайт по Бри Ларсон.
>>1354827Да, докер ставился на паузу через дженкинс с внешнего сервера, так что процессорное время не тратилось, когда там ничего не обрабатывалось. Парсеры забирали данные с внешних сайтов, у себя обрабатывали, во время работы на amazon aurora все промежуточные результаты хранили. В конце дамп с авроры делался и копировался на продакшн сервак и микросервис там висел, чтобы внешние парсеры запускать импорт дампов могли. Единственные сложности были с ключами в БД, которые между собой конфликтовали, но мы там потом все составные сделали основной ключ + номер парсера.
>>1355000На одном html сложновато на фрилансе поднять, обычно клиенты хотят сразу и верстку и фронтенд js и бэкенд на php, за фуллстэк работы в основном платят. Если еще в английский можешь, то 40к самый минимум, обычно больше. Делай задания из шапки, там все есть чтобы на нужный уровень выйти.
>>1355046Спасибо анон. Я за верстку и считал html, css, js. Только про php узнал сейчас.И сколько в среднем стоит обычный проект для новичка? И за какое время, например ты сам в начале пути делал верстку
Аноны, ответьте новичку. Не могу понять, как работает "поддержка" авторизации на сайтах. Взять тот же ВК. Просмотр страниц доступен только после входа.Но как потом страницы определяют, что пользователь авторизирован?Сессии? А в сессии сохранён параметр входа, типа AUTH = TRUE? Что будет, если я скопирую себе COOKIE с id сессии у другого пользователя? Получается, так я могу получить доступ к чужому аккаунту?Хранение хэшей паролей и проверка на каждой странице мне кажется бредовым решением.Подскажите, опытные аноны.
Сап! Давно тут сидел, сделал студентов и файлообменник. Потом был очень занят по работе (с кодингом совсем не связано) и где-то год ничего не делал. Теперь снова появилось свободное время и я вкатился в тред. Какую задачу посоветуете, чтобы снова все вспомнить?
>>1353705 (OP)ого, эти треды еще живыгода 2 назад вкатился благодаря им и опу, за что ему мое увожение
Написал я к примеру файл с созданием сервис провайдера и кинул его в папку с сервисами. А реализация сервиса (ну например "соединение с бд" должна в этом же каталоге лежать или где угодно?
>>1355113перекатился на голенг, неспешно ищу удаленку, но видимо придется ехать в дс>>1355114около 90к
>>1355141ну а чо пилить тонадоело говно вилкой чистить за 18к, вот и решил в ваше айти вкатитьсяпочти год после работы читал/писал и взяли меня на галеру поработал там 2 года, понял что на этой галере больше ничему не научиться и теперь пора следующий шаг делать
Нужно ли делать ячейку DI-контейнера одиночкой, если она нуждается в этом? Понятно, что содержимое ячейки будет возвращаться одно и то же, но ведь можно будет создать экземпляр и не через сервис, а вручную, поэтому я хочу дополнительно обезопасить код. Правильно мыслю?
Сука, уже целый день пытаюсь включить Xdebug в VS Сode. И нихера короче. Чеж так сложно-то? Пипец, пол-интерннета таких же мученников и у всех разные решения везде. Не подхватывает и всё тут.Может netbeans поставить, а? Может там все из коробки нормально, как думаете?
>>1355186До этого был петухом в госшараге и всю жизнь руками работал. Ну а вкатываться конечно тяжело. У меня вон почти год это дело заняло, ну и заставлять же себя надо. После работы пришел заебаный - будь добр пиши код, иначе так говно и будешь чистить.>>135521028
>>1355067>Сессии? А в сессии сохранён параметр входа, типа AUTH = TRUE? Что будет, если я скопирую себе COOKIE с id сессии у другого пользователя? Получается, так я могу получить доступ к чужому аккаунту?Концептуально так и есть, но если взять пример ВК, то там, возможно, есть какие то Cookie с хэшем которые высчитываются из ip-адреса, поэтому просто своровать их чтобы получить доступ к чужому аккаунту, скорее всего не получиться.
>>1355508Попробуй другой порт например. (я по привычке ставлю 9005)Если у тебя хост на виртуалке - remote_host будет не 127.0.0.1 а 192.168.1.Х (открываешь свойства сети на компе и смотришь свой IP в локалке) profiler_enable - тебе вряд ли нужен, но будет дико замедлять работу скриптов (будет писаться файловый лог работы скрипта), лучше поставить чтобы по GET-параметру XDEBUG_PROFILER=1 срабатывал профайлер.
>>1355557А, извини, но я не говорил, что у тебя неправильно настроено, я просто уточнил по некоторым пунктам для него из твоего скрина.
Посоветуйте бесплатную и без необходимости где-то регаться и не веб страничку блядь клиентскую софтину для redis на линупс
Верно ли утверждение, что без шаблонизатора мы не можем создать полноценную MVC на пхп, ведь шаблонизатор не убирает скрипты пхп из HTML, а заменяет его код на свой синтаксис, т.е. все скрипты их штмл никуда не деваются. Главная задача MVC отделить логику от представления, разве обязательно юзать шаблонизатор?
>>1355508https://www.youtube.com/watch?v=k1CN4YVcbHoСпасибо, бро. Но я скачал нетбинс и охуел от его аскетичности чтоли:- нет дерева файлов слева, не понял нихуя, наверное, я тупой, предлагает зачем-то импортировать из zip. А не из zip???- предлагает создать проект html файл. Нахуя мне html? Я же скачал специально php edition...- старые плагины 2014 года выпуска, например, Emmet вообще нет, он называется по-старому - Zen coding Чет мне кажется, я говна поем с этой IDE.Оууукей. скачал Codelobster - там конечно полный фарш по поддержке фреймворков и cms, смотрите сами, НО! Сука дебагер не пашет на php7, хотя вроде поддержка есть. Ладно, пока попишу на php5 свою херню, хотя странно.Бля как же сложно, я просто хочу писать и отлаживать удобно код, как раньше в дельфи, неужели я многого прошу?Алсо видео стронгли рилейтед.
>>1355898шо? В нетбинсе все это есть. Это раз.Два. Это вторая по популярности ИДЕ после пхпшторма. Три - коделобстер - кусок говна по функционалу, даже если сравнить с обычным блокнотом
>>1355930Я его пробовал несколько лет назад, поэтому точно не помню. Помню что жопа горела дико.Там какая-то перда была с тем что внутренние окна меняли свой размер, он лагал. Там ты ничего толком не настроишь, он платный. Я уже не помню есть там поддержка композера, гита и пр штук? Терминал имеется? Возможность работать с сервером удаленно?
>>1355938Терминала нету. А что ты запускаешь в терминале? Artisan?А что значит - поддерка компоузера? Удаленный сервер - всё это есть, конечно.
народ, если тут не отвечают на ваши вопросы, можете вкатиться в телегу к нам в конфу (25 чел). Тут есть как и опытные, уже работающие люди так и новички, которые хотят вкатиться и спрашивают свои ответы. Пишите почту/телегу.
Laravel1. Не понимаю в чем профит сервис контейнера? Уже пересмотрел много видео и статей и примеры. Но я не понимаю через сервис провайдеры мы как бе можем подменять реализации интерфейсов того что будет храниться в сервис контейнере, но мы как бы можем сделать это и без него в чем профит использовать именно его? Да реализация через него синглтона довольна удобно и ясна, но она не так часто нужна, так для чего еще?. Так что вопрос зачем?2. Заодно вопрос какая структура папок должна быть для контрактов и их реализации.3. Если бороться с жирными контроллерами через сервисный слой то какую выбрать структуру папок чтоб можно было вернуться к проекту через месяц?
>>1354910>Но получив некий опыт на Ангуляре, я понял что более шаблонным и следовательно простым для понимания было бы обернуть все эти компоненты в отдельный компонент AuthComponent и в нём уже сделать свойство email (а лучше объект user/form) и передавать это значение с помощью "Взаимодействий Компонентов" https://angular.io/guide/component-interaction.Здесь не получится реализовать "Взаимодействие Компонентов" потому что, всё равно, придется размещать не сами компоненты, а <router-outlet>.
Анончики, помогите найти закавыку:Допустим, массив всех строк из файла ложится в $key и я хочу организовать поиск по нему.Дальше такой код: https://ideone.com/PKbkZz 1. Почему у меня выводит только один результат, хотя их десяток в файле?2. Как мне вывестив результате номер строки именно найденного результата?Спасибо вам.
>>1356036В папке service лежат контрактыВ папке useCases реализацияПример тут https://github.com/ElisDN/laravel-demo-board/tree/master/app
>>1356329Strpos возвращает первое вхождение. Он может тебе вернуть 0 т.к нашел с индекса ноль а у тебя true стоит может быть поэтому у тебя не сходится. Мне кажется тебе надо.жестко проверить strpos() !== false
>>1356280За студентов не скажу, потому что не помню, а вот файлообменник кинул на гитхаб как пример того чо могу(ничего). Ну там еще было задание после файлообменника, но его я не делал. К слову по жс я не умел вообще ничего, даже json запрос написать не мог. Ну и вообще, то что я там пыхтел год можно реально выучить за месяц максимум на реальных проектах, так что чем скорее попадете на вашу первую ламповую галеру за еду, тем быстрее пойдет скилл.
>>1356873Ты поля из вне задаешь. Я против такого подхода потому что создается не валидный обьект. Ты через new его создаешь а потом туда пихаешь значения.
>>1356877>>1356879честно говоря, не особо понял в чем моя ошибка. Скажи,пожалуйста, что мне конкретно нужно переделать?
Котаны, совета прошу. Я нуб, пхп осваиваю понемногу. В общем сейчас свое приложение делаю, MVС, на классах, содрал структуру с сети, запросы в базу писать уже научился( с помощью PDO), sql знаю. Суть туда/сюда понимаю. Короче зайчатки разума есть.На работе появилась задача, которую мне нужно по итогу реализовать, сроки совсем не сжатые, но работу веду по факту ежедневно. Думаю что мой MVC шаблон и станет основой будещего приложения.Суть приложения проста - сотрудники заходят на сервер и получают перечень доступных им запросов в базу, которые могут использовать.Какие проблемы для себя я вижу:1. Как сделать авторизацию в MVC?2. Как делать права доступа? Т.е. сотруднику №1 доступны все отчеты, а сотруднику №2 только один.sql-отчетов гипотетически будет много разных.Делаю это для удобства всех вообще, потому как на данный момент отчеты я ручками пилю при необходимости.Такой вот учебно-практичный проект возникает.Где почитать годноты, котаны?
>>13569731. В бд есть таблица с логинами и паролями (хешами с солью). Показываешь страницу логина с полями для входа. Если пароль не подходит - посылаешь нахер. Если подходит - в сесию пишешь токен (очень длинную случайную строку). С этим токеном пользователь может лазить по сайту. Без токена - посылаешь на страницу логина. Токен проверяешь в каждом контроллере.2. В бд есть таблица с правами пользователей. В контроллере проверяешь права - в зависимости от прав выводишь нужную инфу, или вообще посылаешь нахер на первую страницу если пользователь ломиться куда не положено.Вообще лучше фрейморк какой-то взять (Yii2 или Laravel) - там эта вся хуйня сделана изначально (по крайней мере в Yii2).
>>1356943$q1 = new ChoiceQuestion("Какая планета располагается четвертой по счету от Солнца?", 'b'); $q1->options = array('a' => 'Венера', 'b' => 'Марс', 'c' => 'Юпитер', 'd' => 'Меркурий'); $q2 = new NumericQuestion("Чему равна скорость света в км/с?", 300000, 20); $q2->deviation = 20000;Поля $q1->options и $q2->deviation = 20000 ты все так же задаешь из вне.
>>1356873И еще мне кажется что делать echo в методе не совсем верно, лучше возвращать строки и пусть кто вызывал твой метод разбирается что с ней делать.echo " {$key}. {$option}\n"; заменить на return " {$key}.{$option}";
>>1357054>>1357057Переделал вот: https://ideone.com/Lb6iG1. Если я правильно понял, то переопределить метод изменив количество параметров не получится. Поэтому я в каждый дочерний класс запихнул конструктор. Верно или я ошибаюсь?
>>1357141Да норм. Конструктор часть конкретного класса. Я бы не рассматривал его как часть интерфейса
>>1356479Ого. Я тоже сделал только файлобменник. Учу шаблоны, дабы приступить к изучению Laravel.Предлагаешь с такими околонулевыми знаниями уже подыскивать галеру?
>>1357310Хз, пробуй. Если в дс то изи, если нет, то не очень. Ну от бомжа и не ждут, что он процесс от потока отличает и знает чтото про уровни изоляции транзакций.
>>1355111>ого, эти треды еще живыНе просто живы, а ещё у них появился свой сайт https://phpclub.tech/Его код находиться на ГитХабе https://github.com/richBlueElephant/phpClub и там есть issues, которые хорошо бы исправить https://github.com/richBlueElephant/phpClub/issues
>>1353745Быстро мне накидал CMS с плугами под нормальные языки!Знаю что напсавший уже и забыл о том что писал, ведь в школе каждый день кипит событиями
>>1357536Я не понимаю, мои посты скрываются каким-то специальным скриптом? На них никто не знает ответ? Вопросы дурацкие? Или просто лень отвечать?>>1355207>>1355140>>1354531>>1355798И в предыдущем треде дохуя.
>>1357536Это что бы изменение 1 вьюшки были отображены в другой?например я обычно общие куски делаю в partial и их уже где надо подключаю. Какой результвт ты хотел бы получить?
>>1353705 (OP)Господа анончики, может кто проверить задачку на айфон в кредит?https://ideone.com/ZsjeOK
>>1357720Хорошо. Лучше чем большинство делает в этот ITT треде, обычно пытаются все логические действия впихнуть в одну строку и косячат. Учись дальше.
>>1353705 (OP)Есть вопрос по "Вектору".Правильно ли я понимаю что создание всех этих объектов работников надо как то автоматизировать? Или втупую ручками создавать каждый объект?
>>1357756Ну я когда делал, то парсил из текста с твоей картинки, только там тогда были буквы из латиницы и из кириллицы намешаны, что добавило анальных болей, не знаю было ли это исправлено.
>>1357898Нет. Делай нормальные конструкторы. По факту там и ватоматизировать мало чего. В циклах создаешь объекты и все. Инициализации все равно много будет.
>>1357584Я просто еще с фреймворками не работал, так что хз, как оно там везде работает. Есть вот шаблон, куда я подключаю вид, считай, вызываю функцию getView(), которая подключает текущий вид. Например, это список товаров. А еще у меня в каждом виде меняется, к примеру, шапка. Там title разный на каждой вьюхе. И как мне его там менять? Инклюдить всю шапку как виджет в каждый вид, туда передавать параметры для title и потом выводить все вместе или еще как-то можно?
>>1357918Напрмиер, в шаблоне также как подключаешь вью с товарами, также подключашь нужную шапку. Виджет норм идея, если сможешь сделать его более-менее универсальным (тоесть можно будет использовать больше чем в одном проекте). А если придется допиливать под каждый конкретный проект то лучше всетаки как отдельное вью или типа того оформить.
>>1353705 (OP)Ребятки, проверьте "Вектор", пожалуйста : https://repl.it/@PhilPhil/GrandUrbanProjections
Расскажите нуфагу.Почему \n работает только на сайте ideone com, а человеческий '<br>', который работает везде, сайт тупо принимает за текст?
>>1356479>>1357310Вкатился на python галеру после задачи с файлообмненником, работаю уже два месяца. Самое забавное, что набирают людей с куда меньшими чем у меня знаниями, так что вкатывайтесь чем раньше, тем лучше. Кстати, огромное спасибо опу за задачки, я, правда, учился в основном, не на его уроках, но все-равно материалы из этого треда были очень полезны. >>1357424
>>1358386Я бы добавил константы и в свитчах использовал бы ихswitch($this->profession) {case self::MANAGER итд
Анон, я хохол. Хочу понаехать в МСК.Насколько будет проблемно найти работку в МСК пхп кодеру?Имеется опыт работы 3+ года, знаю ООП, фреймворки и пр. Хуйов в верстке еще немношк знаю джаву и планирую в нее перекатиться.Будут ли меня обссыкать за то что я шокаю и гакаю?
>>1358509Потому что количество элементов массива 4 а последний индекс 3. Происходит обращение к несуществующему элементу.
Первый верхний вариант функции работает, а второй нижний нет! Что делать??? В чём причина?(При вызове функции посередине)
>>1358539хмм, походу на то. Но тогда получается у меня $data - объект, а не в коим случае не объект?В связи с этим, правильно ли я думаю, что если считывать json файл где всё сосредоточено в { //что то}то это объект, а если[ // что то]то это массив?
ОП, посмотри задачи по ООП, пожалуйстаhttps://3v4l.org/NSVsb - задача про зарплатуhttps://3v4l.org/4GGth - задача про вопросыhttps://3v4l.org/3avqA - задача про Вектор
>>1358542Ну если ты обращаешься к данным через ->, то это признак того, что ты обращаешься к объекту. В javascript можно обращаться к пустому объекту, просто создав его через {}. В PHP так делать нельзя, объект нужно создать через new, поэтому твой json (ты ведь его получаешь?) сначала нужно распарсить (превратить в массив) и потом уже только обращаться к нему.
На пхп вообще есть работа?В смысле не ковыряние какой-то ублюдской параши с ключевыми словами "битрикс джумла вордпресс", а создание каких-то систем с нуля там, на фреймворках?
>>1358583Нет. Это фантастика, сынок. А фреймворки это так, хуйня. Фабьен с Тейлором их по приколу напейсали. Вкатывайся лучше в руби
>>1358583Работа есть, но только как ты выразился ковыряние cmsок в студиях, потому что дешево и быстро.
А вот такое знает кто?Есть у меня к примеру экшен, который вызывается один раз по умолчанию, когда юзверь заходит на страниц. Потом, когда программа юзверя запомнила, она будет вызывать другой экшен, при заходе на эту же страницу по умолчанию.Можно ли сделать вот так?методПоУмолчанию {if (тутБылЮзверь) { методПослеПосещения()}"Юзверь, зарегистрируйся!"}методПослеПосещения { выводимИнфу()}То есть я понимаю, что чисто физически я могу вызвать один метод в другом, но можно ли так делать в MVC шаблоне?
>>1358638Почему нет? Только если у тебя фрейморк какой-то то там скорее всего лучше не напрямую вызывать другой экшен, а сделать редирект.
>>1358643Ага, спасибо. Почему нет, я не знаю, поэтому и спрашиваю, лол. С фреймами пока не работал, на вольных хлебах пока что. Что хочу, то и ворочу.
Короче, аноны.Решил написать простенький калькулятор, но после проверки, является ли введенные значения целыми числами, но жидко обсераюсь и ловлю сообщение о том, что там не числа (хотя там числа).Посмотрите, пожалуйста, где я не прав.https://ideone.com/gwTPUt
>>1358927Там не числа. Из консоли всегда приходят строки.http://php.net/manual/ru/function.readline.phpПочитай про преобразование типов в PHP.
Создал я, значит, сущность юзер, к нему маппер, базу ещё. Заполнился юзер данными, но вот только одна беда, некому оперировать этой сущностью. Какой слой модели вызывает методы этой сущности и возвращает результат контроллеру? Или может контроллер сам это делает?
Господа, подскажите как реализовывать " антикризисные меры" в задачке "Вектор"? Это должна быть отдельная функция на каждое антикризисное решение или это должны быть три разные программы на каждый случай?
>>1359196Мне кажется, хуевый план. А если мне нужно будет этих юзеров рассортировать, пропустить их через валидатор, то где мне это делать? Явно не в контроллере. Опчик, ты ведь знаешь ответ? Взываю к тебе!
>>1359366что тебя смущает я не понимаю.class Controller{ private $search; public function __construct(Search $search) { $this->search = $search; } public function index() { $result = $this->search->search(); }}
$a='2';test($a);public function test($a) :int{return $a;}вернет ли в данном случае int или же string?
>>1359625Зависит от strict_types. Или сделает приведение типов и вернет число, или при strict_types=1 будет ошибка
>>1359634да, уже потестил в песочницах.Но в проекте просто втихую возвращает стринг и никаких ворнингов, ошибок, поэтому и пришел с этим вопросом.
>>1359640нвм, я дегенерат, дампил значение до его возвращения, а приведение типов работает во время возвращения.
>>1359816Всем плевать на вышку если ты сильный кандидат (немного похуже в Украине, у них странноватый рынок труда в IT). Больше интересует что бы в армию не ушел прямо с работы или в запой.
>>1354215Вообще, это неудобно. Что, если пользователь нажал кнопку, а данные еще не пришли? Сначала лучше сделать так: пользователь заполняет все поля и жмет кнопку. Отправляются по очереди все нужные запросы.А потом уже можно прикрутить оптимизацию, отправлять первый запрос сразу после заполнения поля amount, итд. Если у тебя нет понимания, как это делать, то скорее всего ты пока плохо знаешь Яваскрипт. Пройди учебник http://learn.javascript.ru/ и обрати особое внимание на события, анонимные функции (коллбеки), почитай про промисы. >>1354526Часто, чтобы попасть в "серьезную" компанию, надо сначала где-то приобрести опыт, возможно, что в веб-студии, в аутсорсере или где-то еще, где берут джуниоров. Ты можешь сам посмотреть вакансии компании, которая тебе нравится, на hh.ru и оценить требования. Например, если ты любишь проектировать БД, то тебе подойдет какая-нибудь компания, которая делает софт на заказ, всякий софт для банков, телекомов, госорганов - там точно будут сложные базы данных. >>1354531Реестр - это паттерн, который описывает объект, в который можно класть и получать данные ( https://martinfowler.com/eaaCatalog/registry.html ). Часто он реализуется на статических методах: ServiceRegistry::set(ServiceA::class, new ServiceA);...$srvA = ServiceRegistry::get(ServiceA::class);Но это не обязательно. Как я помню, в той же Симфони есть такие реестры: - реестр кастомных (добавленных пользователем) типов полей Доктрины- реестр типов элементов формТам, где Реестр противопоставляется DI контейнеру - противопоставляется, наверно, статическая версия реестра. То есть подход ServiceRegistry::get('ServiceA')и $container->get('ServiceA');У Реестра и Контейнера могут быть такие отличия:- Реестр часто бывает статический, а контейнер - нет- Реестр не создает объекты: он хранит то, что в него положат. DI контейнер может создавать объекты, если ему дать описание, как это делается (например, описать, что надо передавать в конструктор, или позволить ему самому это понять анализом аргументов в конструкторе).- Реестр может хранить что угодно, например, числа какие-нибудь или настройки. DI контейнер, как правило, хранит объекты-сервисы. Хотя в Симфони он хранит и настройки.
>>1357547У меня просто времени иногда нет, последние пару недель адски загружен. Как станет полегче - разберу накопившиеся вопросы. А так, я всем стараюсь отвечать. >>1355207> Нужно ли делать ячейку DI-контейнера одиночкой, если она нуждается в этом? Ни в коем случае. Идея DI контейнера - IoC - предполагает, что жизнью объекта (когда его создать, когда уничтожить, что передать в зависимости) управляют снаружи, что это не его зона ответственности. Это не дело объекта-сервиса знать, сколько экземпляров сейчас создано. Дело сервиса - указать свои зависимости, например, в конструкторе или в методах.За поддержку единственного экземпляра отвечает контейнер. Да, пользователь может создать новый объект в обход контейнера, ну, значит, он так решил. Но скорее всего это будет сложно, так как нужно где-то взять зависимости объекта, настройки конфига, и это выльется в огромный объем кода. Ну и на код-ревью такой разработчик получит по шапке за велосипедостроение. Простой пример, когда нам не нужен синглтон - это тесты. Мы хотим, чтобы тесты выполнялись в изоляции друг от друга, и можем для каждого теста создавать одноразовый экземпляр DI контейнера. DI это позволяет, а твой подход с синглтонами - нет. Потому синглтон - это почти всегда антипаттерн. Не стоит его использовать. >>1355140Я думаю, сервис провайдеры и сервисы хранятся в отдельных папках. По поводу организации структуры кода, если ты используешь фреймворк, то стоит делать, как там принято. Если не используешь, то такие варианты: - если классов мало (< 10), их можно класть в одну папку- можно делать папки по типам классов: папка для сервисов, для контроллеров, для представлений, для моделек, для классов работы с БД, для вспомогательных утилит. Этот подход начинает фейлиться, когда у тебя становится огромное приложение с сотнями серисов и моделей. - можно взять предыдущий подход и добавлять подпапки внутри папок. Ну например, папка модели, а в ней: папка пользователи, папка товары, папка статистика итд. - а можно поступить по-другому, и разбить приложение на "части". Для каждой "части" создаем свою папку, а в ней подпапки: сервисы, модели, контроллеры, утилиты и тд. То есть будет папка "пользователи", а в ней подпапки с моделями пользователей, контроллерами раздела работы с пользователями итд. Симфони, например, использует что-то отдаленно напоминающее последний подход, где можно делать разные "части" - бандлы. У каждого бандла могут быть свои конфиги. Вообще, последний подход, если делать бандлы небольшими, хорошо работает в огромных приложениях. Так как часто у нас разработка идет в стиле "создаем новый раздел сайта, дорабатываем и потом почти не трогаем". И мы сидим в основном внутри одного небольшого бандла и не трогаем остальной код. То есть для огромного магазина, например, можно сделать так: CommonBundle - общий код, который используется всеми бандлами (не контроллеры или модели, а например, сервисы, утилиты, расширения фреймворка итд)UsersBundle - управление пользователями, регистрация, личный кабинетStoreBundle - витрина, вывод товаров, оформление заказаFinanceBundle - оплата, бонусыSupportBundle - раздел техподдержкиForumBundle - форум AnalyticBundle - аналитикаAdminBundle - админка
>>1355798> что без шаблонизатора мы не можем создать полноценную MVC на пхпВ теории - можем. Например, если мы делаем сервер API, который отдает не HTML-страницы, а данные в формате JSON, то шаблоны нам не нужны. Ну и в теории, опять же, мы можем без шаблонов сделать вывод HTML кода кучей операторов echo. То есть, шаблон - это лишь один из вариантов реализации View. Я думаю, ты хотел спросить, "можно ли вместо стороннего шаблонизатора использовать встроенный в PHP?" - да, можно, но неудобно на больших проектах. Урок про шаблонизаторы: https://github.com/codedokode/pasta/blob/master/php/templates.md>>1354575Обычно все сервисы создают через контейнер. Сегодня у сервиса нет зависимостей, а завтра они появятся - и тебе придется обходить весь код и заменять создание сервиса на получение через контейнер.Также, контейнер может поддерживать существование одного экземпляра сервиса. > если у меня просто вспомогательный класс (сервисного слоя) без зависимостей для контроллера я его просто делаю use и использую.Для вспомогательных классов можно использовать паттерн Utility Class (класс со статичесикими методами).> контракты в /app/Contracts а реализации их неизвестено гдеИх реализации там, где уместно. Естественно, не в папке Contracts. Вообще, ты можешь посмотреть, как код организован в самом Laravel или стандартных библиотеках к нему. Если у тебя мало сервисов, можно просто сделать папку App/Services. Если много - то думать, как дробить на части. Можно как-то по смыслу их группировать, по разделу сайта, по компоненту приложения. >>1354604По идее так: http://php.net/manual/ru/language.basic-syntax.phpmode.phpНо это даст низкокачественный код, потому читай https://github.com/codedokode/pasta/blob/master/php/templates.md
>>1354838Он зато лаконичный. И там есть IPython Notebook - отличнейшая штука. Но отсутствие тайп-хинтов, конечно, убивает. >>1359625Вернет в любом случае то, что указано в тайп-хинте, в нестрогом режиме при этом допускает автоматическую конвертацию в int.>>1359071Можно как 3 функции, можно как 3 класса, можно как 3 метода в одном классе. Метод может принимать экземпляр Компании и делать с ней какие-то операции. >>1359022Зависит от того, как сделана работа с БД. Если у тебя используется дата маппер, то в нем и будет метод для загрузки моделек из БД. > Какой слой модели вызывает методы этой сущности и возвращает результат контроллеру? Или может контроллер сам это делает?Вызывать метод загрузки данных может контроллер. Либо сервис, который загружает данные из БД и делает какие-то еще преобразования.
>>1359366Зависит от ситуации. Контроллер должен быть тонким, то есть в основном в нем вызовы разных сервисов (тех же мапперов) для получения разных данных и передача их во View. Для валидации можно сделать отдельный класс-валидатор. Для сортировки - если это что-то простое, нужно только для вывода и не повторно используемое, то делаем в контроллере. В задаче про студентов сортировку логично сделать аргументом в методе для получения студентов: findStudents($searchBy, $orderBy, $orderDir, $offset, $limit): iterableЭтот метод может быть в маппере для работы с БД. В таком случае мы можем получать отсортированный список студентов из любого места кода. Контроллер отвечает за управление процессом обработки запроса, за интерпретацию команд пользователя. То есть контроллер как-то (например, из $_GET) определяет, какая сортировка нужна пользователю, и вызывает метод для загрузки студентов с сортировкой по данному полю. А затем передает найденных студентов во View и отдает пользователю сгенерированную HTML страницу. >>1358638Обычно это делают так: class Controller { public function indexAction(Request $req) { if (!$this->isLoggedIn($req)) { return $this->redirectTo(...); } ... }}То есть перед выполнением нужных действий проверяем наличие логина. При отсутствии - редирект на форму логина с передачей текущего URL (и проверкой, что он с нашего сайта). На форме логина пишется: "Чтобы XXX, вам надо зарегистрироваться, или ввести логин и пароль, если вы уже зарегистрированы". При желании можно как-то заморочиться и например, сделать проверку на уровне контроллера (то есть закрыть доступ ко всем методам этого контроллера сразу). Это удобно в админке, например. В твоем варианте пользователь может попробовать обойти авторизацию, вызвав напрямую метод "методПослеПосещения".
>>1358534Ты передаешь массив, а пытаешься обращаться к его элементам через стрелку. Кто тебе сказал, что так можно? Это не JS, тут с массивами работают с помощью квадратных скобок, а стрелка для полей и методов объектов. >>1358542Прочти также целиком мануал по json_decode. Там написано, когда получается объект класса stdClass, а когда массив. >>1358506Не знаю. Где-то на хабре давно была статья с такой историей, можно ее поискать. >>1358393Не думал, что у файлообменника такая сила. Сейчас, вроде начинающие разработчики делают сокращатели ссылок, но это уже неприлично просто. >>1358316<br> это тег языка HTML. Он работает только там, где данные интерпретируются как HTML-код (в браузере). А \n браузер воспринимает просто как разделитель слов и непереносит строку. На ideone и в консоли данные просто выводятся как текст. Если там будут теги - они выведутся как есть.Это не единственное отличие. Например, & lt ; в браузере выводится как знак "меньше", а в консоли - как есть.То есть различай "просто текст" и "HTML текст с тегами".Если добавить в начало header("Content-Type: text/plain; charset=utf-8"); то браузер перестанет воспринимать данные как HTML и \n начнет работать.
>>1357898Если они совсем однотипные то можно, но проще наверно через new. >>1357918Обычно делают отдельно шаблон для "лейаута" (шапка/подвал) и "контента". Лейаутов может быть несколько - например, один для морды, другой для админки. Как передавать параметры для лейаута? Тут есть варианты: - руками копипастить их в каждый метод каждого контроллера (боль)- наследовать контроллеры от базового класса и в нем формировать данные. У базового класса может быть метод вроде "поменять тайтл текущей страницы". Плюс - инкапсуляция, трудно передать что-то неправильное, например, не-строку. - передать эти данные во вью до или после выполнения контроллера, без использования наследования. Или передать в контроллер. - сделать "контроллер для лейаута" и в нем формировать данные для лейаута. У "контроллера лейаута" могут быть вспомогательные методы вроде "поменять тайтл текущей страницы".В фреймворках готового решения нет. Каждый изобретает сам.>>1357536Не очень понятно, как это. Вызывать из одного шаблона другие шаблоны можно. >>1357016В сессию токен писать нет смысла. Данные сессии хранятся на сервере и недоступны пользователю, потому можно просто писать туда userId = 123. Это безопасно. Токен нужен, если используется не сессия, а куки. Тогда писать userId = 123 нельзя, так как пользователь может их подделать. Также, некоторые шифруют и/или подписывают куки для защиты от чтения и/или модификации их пользователем. Плюс: сессии не требуется хранить.
>>1356973В твоем случае проще всего сделать либо связь многие-ко-многим между запросами и пользователями, либо сделать роли (бухгалтер, продажник, админ), для запроса указать требуемую роль, и каждому пользователю присвоить одну или несколько ролей. Последнее называется RBAC, почитай, прежде чем изобретать велосипед. Советую реализовать RBAC, в общем.Статья в википедии про RBAC трудночитаема.> 1. Как сделать авторизацию в MVC?В твоем случае: if (!$this->hasRole(Roles::ROLE_BUH)) { редиректим на форму логина, либо показываем ошибку нехватки прав;}
Господа, вопросик.Клонирую объект в свойстве которого лежит массив объектов. Правильно я понимаю, что объекты в массиве тож надо клонировать с помощью __clone()? Если да, то правильной ли будет вот такая функция:function __clone(){ foreach ($this->arrayWithObjects as $key => $object) { $this->arrayWithObjects[$key] = clone $object; }}
>>1360214Потом мне нужно работать с этими объектами в массиве и изменять их, но так чтобы оригинальные не поменялись.
>>1360320Так сделал, вроде работает. Или можно было как- то короче? Тут я сравнивал не по половинам, а целую строку. Потому что я тупой и не придумал, как сравнить одну половину со второй.
>>1360216Ты в тот же самый массив записываешь тот же самый объект с тем же ключом. Какой смысл? Массив у тебя как был один, так и будет. Или ты все-таки в другой клонируешь?
Аноны, нужен совет.Одна из моих проблем заключается в том, что я не могу в базовую терминологию, поэтому часто приходится изъяснятся как ретард. Подскажите, как можно обозначить вот эти элементы страницы любого саба на Reddit (pic related)?Хочу построить простой сайт (на локальном сервере, просто ради практики), который будет что-то листить. Людей, бананы - без разницы. Я просто селебрити выбрал. Сейчас сделал простую html форму для добавления новых записей в базу данных, на той же странице написал PHP скрипт, который пользуется переменными из $_GET для составления SQL INSERT INTO. Всё ок, только теперь не могу понять, каким образом написать скрипт для генерации html файла для каждого добавления в базу данных. То есть, у каждого селеба должен генерероваться свой профиль на основе страницы-шаблона.Затем будет стоять задача построить механизм фильтрации по атрибутам (first_name, last_name, occupation, location, etc.) при поиске на сайте. Пока не могу даже в гугле толком вопрос сформировать, чтобы найти, что нужно. То есть, как реализовать фильтрацию по базе данных на странице html?Подскажите, пожалуйста.
>>1360353В тот же массив я записываю клоны объектов, чтобы потом их изменять, без изменения оригинальных объектов.
>>1360386> теперь не могу понять1. Пишешь скрипт который просто генерирует статический профиль.2. Находишь в профиле всю инфу которая должна тянуться с базы.3. Выделяешь эту инфу в переменные. Тоесть при генерации профиля инфа не захаркоджена а берется из переменных. Переменные ты инициализируешь перед скриптом генерации.4. Придумываешь способ заполнить эти переменные инфой из бд.5. .....6. профит
>>1360452Ты берешь и перезаписываешь оригинал его клонированной копией. Так понятно?function __clone(){foreach (твойМассив как $ключ => $значение) {твойМассив[$ключ] (текущий ключ форыча, - прим. автора) = clone $объект}}Это равноценно такому$arr = [0 => 'a', 1 => 'b'];//первая итерацияforeach ($arr as 0 => 'a') {$arr[0] = 'a';}То есть форыч берет и перезаписывает значение на то же самое. Чтобы работать с копиями, тебе необходимо положить их в новый массив.
>>1359945>Реестр - это паттерн, который описывСпасибо, исчерпывающий ответ. Написал бы ты всеобъемлющую книгу по всем этим аспектам. Они ведь не устаревают. Будет пользоваться популярностью.>>1359946>У меня просто времени иногда нет, последние пару недель адски загружен. А можно узнать, чем ты занимаешься? В студии трудишься или в каком-нибудь банке софт ваяешь?>Ни в коем случае. Идея DI контейнера - IoC - предполагаетХорошо, проблему синглтона контейнер решает. А вот еще вопрос. Создал я класс подключения к мускулу, сделал для него сервис-провайдер, где он создается, а потом внедряю его, куда нужно.А вот, скажем, мне нужен не один объект, а нужно итеративно и с условиями получить много, тогда что? Нужно будет в контейнере хранить не объект, а класс, а потом внедрять этот класс и там создавать через new?>Я думаю, сервис провайдеры и сервисы хранятся в отдельных папках.Спасибо, теперь все понятно.>>1359948Если у тебя используется дата маппер, то в нем и будет метод для загрузки моделек из БД. То есть вообще всем управляет маппер, а сущности это такие пассивные ячейки памяти, к которым маппер обращается, и сущность сама по себе ничего делать не должна? И в контроллере правильно будет вызывать именно методы маппера?>>1359949> В задаче про студентов сортировку логично сделать аргументом в методе для получения студентов: Спасибо за разъяснение особенно за последний абзац и за метод, ты сэкономил мне кучу времени.>То есть перед выполнением нужных действий проверяем наличие логина. При отсутствии - редирект на форму логина с передачей текущего URL А можно такую проверку делать в конструкторах? Например, в общий абстрактный контроллер засунуть. А то не делать же ее в каждом методе (боль, лол). И если юзверь не залогинен, то просто будет редирект на контроллер залогинивания, который этот конструктор не наследует.>В твоем варианте пользователь может попробовать обойти авторизацию, вызвав напрямую метод "методПослеПосещения".Но у него не получится, если я объявлю этот метод закрытым. Можно вообще все методы сделать закрытыми и вызывать их через indexAction, в котором сформировать настройки и всякие проверки. Сигнатуру формировать по маршруту. Получится эдакий фронт контроллер, только не физический файл, а метод. Но это что-то идиотское, да? Лол.>Не думал, что у файлообменника такая сила. Сейчас, вроде начинающие разработчики делают сокращатели ссылок, но это уже неприлично просто. А это разве не проще, чем файлообменник? Там ведь просто идет редирект на реальный URI при обращении к твоей ссылке. За вечер-другой можно сделать.>>1359951>Обычно делают отдельно шаблон для "лейаута" (шапка/подвал) и "контента". Лейаутов может быть несколько - например, один для морды, другой для админки. Как передавать параметры для лейаута? Тут есть варианты: Я придумал вот что. Я в контроллере общем создал контейнер обычный массив data, куда записываю данные со всех уголков контроллеров и приходящие данные из моделей. В контроллерах-родителях задаю общие данные, в контроллерах специфичные, в методах контроллеров данные еще специфичнее. Данные записываются не через переопределение свойств, а через методы суперкласса. Потом этот контейнер передаю в вид и обращаюсь к нему из шаблонов типа $data['title'], foreach($data['posts'] as $key => $post) {}, ну и все в таком духе. То есть "лейаут" и "контент" получаются данные из одного глобального массива data, переданного в вид. Так нормально?>Не очень понятно, как это. Вызывать из одного шаблона другие шаблоны можно. Ну я имел ввиду, можно ли несколько "контентов" подключать в "лейаут".Спасибо за ответы, ты будто чистое знание вливаешь мне прямо в мозг. Я, бывает, что-то очень долго ищу, бывает, несколько дней занимает поиск ответа на какой-то вопрос, иногда бывает сам додумываюсь до ответа, но проблема в том, что я не знаю, правильный он или нет. Но вот так очень круто зайти сюда и прочитать ответы на все, что я задавал. Пасиба.
>>1360508>а нужно итеративно и с условиями получить много, тогда что? Нужно будет в контейнере хранить не объект, а класс, а потом внедрять этот класс и там создавать через new?Хранить в контейнере factory, через нее создавать объекты.
На чем в 2019 Rest сервисы на пыхе пишут? Надо бы с автодокументацией какой, как в soap, с нормальной структурой и клиентами. Есть что удобное или все свои велосипеды городят? Пока нашел swagger + swagger-php + jane openapi, может еще кто на чем делал?
>>1360209Да, ты правильно понял. По умолчанию при клонировании поля объекта копируются их оригинала в клон. Если в поле массив - то создается новая копия массива, но объекты внутри массива не клонируются - копируются просто указатели на них (ты можешь это увидеть с помощью var_dump, который выводит уникальный номер объекта). >>1360214Смысл в том, что когда мы клонируем объект и у него есть поле с массивом объектов, мы хотим сделать независимые копии этих объектов.>>1360386Тут есть 2 подхода. Статический и динамический. При статическом подходе для каждой знаменитости у нас будет отдельный HTML файл, а также будет файл-оглавление со списком знаменитостей. Их можно генерировать 2 способами: - сделать скрипт, который выбирает все записи из БД, обходит их циклом, для каждой генерирует страницу, а в конце генерирует оглавление. Такой скрипт удобнее запускать из ком. строки, так как он может долго работать.- можно при добавлении знаменитости генерировать страницу с ней и класть в папку, а также перегенерировать оглавление. Это должно быть недолго, и это можно сделать в скрипте обновления БД, только вынеси это в отдельные функции.Тут правильнее будет вынести код генерации страницы знаменитости и оглавления в функции, чтобы их можно было использовать в обоих сценариях - и для инкрементального обновления, и для полной перегенерации сайта. Есть и другой подход - динамический. При нем мы не храним HTML на диске вообще. Мы генерируем HTML-страницу знаменитости или оглавление на лету, когда пользователь ее попросит, и не сохраняем ее никуда. То есть когда пользователь заходит по адресу /celeb.php?id=123 (адрес можно будет поменять), то запускается скрипт, берет информацию о знаменитости 123, подставляет ее в шаблон и отдает получившийся HTML пользователю. Аналогично делается оглавление.Плюс динамического сайта - то, что не надо ничего обновлять при добавлении или изменении информации, и что изменения в БД мгновенно отображаются на сайте. Плюс статического сайта - скорость работы, в десятки-сотни раз выше, чем у динамического. Минус статического сайта - по мере роста объема информации обновление занимает больше времени. Представь, что у тебя оглавление содержит 20 знаменитостей на страницу, а всего знаменитостей миллион. При добавлении новой тебе придется обновлять все 50 000 страниц оглавления.Почитать про шаблоны можно тут: https://github.com/codedokode/pasta/blob/master/php/templates.mdПочитать про архитектуру MVC (для динамической генерации страниц) можно тут: https://github.com/codedokode/pasta/blob/master/arch/mvc.mdНаконец, у нас есть задача сделать список студентов - и в ней есть очень много комментариев, которые подойдут и тебе: https://github.com/codedokode/pasta/blob/master/student-list.md> Подскажите, как можно обозначить вот эти элементы страницы любого саба на Reddit (pic related)?Посты, записи. > на той же странице написал PHP скрипт, который пользуется переменными из $_GET для составления SQL INSERT INTO. Прочитай обязательно про инъекции: https://github.com/codedokode/pasta/blob/master/security/sql-injection.md> Затем будет стоять задача построить механизм фильтрации по атрибутам (first_name, last_name, occupation, location, etc.) при поиске на сайте.Это надо делать динамически, то есть при получении запроса из формы поиска ты должен сформулировать SQL запрос с условиями, выбрать знаменитостей из БД, сформировать HTML страницу и отправить пользователю. Со статическим подходом это сделать вряд ли получится, так как фильтры дают огромное количество комбинаций и ты замучаешься генерировать заранее HTML страницу под каждую комбинацию.
>>1360386Наконец, есть еще третий подход, который нельзя отнести ни к статическому, ни к динамическому. Это генерация страниц на клиенте (в браузере). Дело в том, что в HTML страницу можно встраивать программу на языке Яваскрипт. Ты можешь сделать сайт из единственной HTML-страницы. При загрузке в браузер программа на JS обратится на сервер, запросит список знаменитостей, оформит с помощью шаблона и отобразит его на странице. Когда пользователь нажмет на знаменитость, JS скрипт запросит данные о ней (или возьмет информацию из ранее запрошенных данных) и сгенерует страницу этой знаменитости. То есть HTML код будет генерироваться прямо в браузере, а сервер по сути будет просто предоставлять данные о знаменитостях в виде того же JSON. Более того, если знаменитостей ограниченное кол-во (не более нескольких тысяч), можно просто информацию о них сложить в файл JSON (или CSV, XML) на сервере, программа на JS будет скачивать этот файл, и использовать информацию из него. В таком случае нам не придется писать PHP-код, который будет выдавать информацию о знаменитостях. Этот подход самый сложный, но он дает огромные возможности, например, ты можешь скачать все данные о знаменитостях в браузер, и после этого сайт может работать даже без доступа к Интернету. Думаю, это может быть удобно для разработки сайтов для смартфонов. На практике, правда, когда пытаются реализовать этот подход, получается тормозной, глючный, плохо работающий, дергающийся сайт. Потому что этот подход сложный и не всем по плечу. Люди бездумно используют готовые библиотеки и подходы, даже не понимая толком, как они работают, какие у них ограничения.
Все чаще встречаю PostgreSQL. Хочу освоить.MySQL знаю хорошо, сильны ли различия?Где что можно посмотреть/почитать на русском, дабы обуздать PostgreSQL для людей знакомых с мускулем?
>>1360565Смысла по-моему не особо, mysql по уши хватает на задачи реляционных БД. Зато nosql решения часто в добавок к mysql на фирмах требуются, так что полезнее будет их поизучать, mongodb c редисами, elasticsearch.
>>1360712с редиской знаком, а монго давно как-то мельком юзал. Есть чето на русском годное и исчерпывающее?И всетаки интересно именно по postgre
>>1360565Есть официальный качественный мануал на русском: https://postgrespro.ru/docs/postgresql/11/index.htmlИзучить наверно стоит, так как в ней гораздо больше фич, чем в MySQL.
>>1353705 (OP)Почему в экосистеме PHP такая чудовищно всратая ситуация с поднятием локального сервера?Вот есть Нода. Спокойно запускает процесс сервера из любого каталога, лишь бы там были нужные файлы и всех пакетов хватало.То же самое у Питона, но только надо с виртуальной средой чуть заморочиться. ASP.Net? Да тоже в общем-то обычным процессом запускается, ещё и с exe-шников.Да что там, даже Хаскель компилится в нормально исполняемый из любого каталога сервер.И тут я прихожу в мир PHP. И наблюдаю удивительнейшие истории когда для запуска проекта нужно зачем-то пихать его в какую-то папку апача\нгинкса и смотреть как это чудовище пытается запускаться на 80м порту. При этом ещё по дефолту будет как-то странно всё отображать. Ещё и лагать может только в путь. Блять, ну почему осталось именно так? Почему в 2к19 приходится наблюдать эти 90е? Я прекрасно понимаю насколько это удачный подход относительно продакшн-сервера уже на готовом хосте, но для локальной работы, ещё и с несколькими проектами это какой-то ужас.
>>1360840Ты бы для начала изучил PHP получше: http://php.net/manual/ru/features.commandline.webserver.phpСервер там поднять в разы проще, чем на ноде.
>>1360858>>1360865Надо же, не думал что буду так благодарен за струю мочи в мою сторону. Работает прекраснейшим образом, без лагов и даже настраивать ничего не понадобилось. Но почему тогда мне отовсюду XAMPP, LAMP, WAMP советуют ставить чтобы хоть что-то запустить? Я в своё время по сути только из-за этого php и не трогал, что он целенаправленно MySQL пропагандирует с которым я не в ладах. А тут, получается, можно и без этого тоже чтоли?
>>1360880> XAMPP, LAMP, WAMP советуют Они желают тебе зла. Если собираешься серьезно погружаться в тему, то только php_fpm + nginx, а по мелочам и встроенного хватит.>php и не трогал, что он целенаправленно MySQL пропагандируетТы шутишь?
>>1360887>Если собираешься серьезно погружаться в тему, то только php_fpm + nginx, а по мелочам и встроенного хватит.Что-то с nginx по-моему ебли и допотопности было не сильно меньше чем с Апачем. >Ты шутишь?Да не особо. По тем же хостингам если из БД предлагают только MySQL, то уже ясно что хостинг заточен на php. Те же стандартные стаки и почти все гайды - отовсюду предлагают именно MySQL.
Хочу немного прояснить за регулярные выражения.Если мне нужно будет найти определенные буквы, то я могу написать:[а-жк-у] (от А до Ж, от К до У), то код не слепит вместе Ж и К? Есть ли какой- то символ, который можно ставить, чтоб чисто визуально видеть, что они (Ж и К) будут врознь?
Смотрю вакансии фронтенда и везде нужен какой-то из spa фреймворков, что намекает что все хотят полностью перейти на гоняние jsona между еедпоинтами apiВопрос:"Есть ли тут место php?"
Няши, посмотрите верстку по макету, дайте советов мудрых и ответьте на некоторые вопросы. https://jsbin.com/pofasoviqa/edit?html,css,outputЗнаю, код очень корявый, но я хочу стать лучше, потому мне нужны ваши ответаМожно ли сделать плавный переход по якорям без JS?Можно ли задать плавное всплывание картинок по нажатию на какую-либо из кнопок?Копирайт всегда должен быть в футере, можно ли их разделить и будет ли это правильно? Я разделил, потому что так в PSD было. С шапкой также сделал.Подписи к заголовкам обрамлять в <h> на пункт меньше или <p>?Почему "margin: 0;" в body не работал и мне приходилось подписывать его к каждому элементу?
>>1361773А, и что еще со значками соц.сетей мне делать нужно было? Я фигурку внутри кружка скачал, а она битая получилась, но я вставил все равно.
>>1354910Вот что мне в ноде кажется неудобным - так это то, что каждый в Node.JS организует код как хочет. Вот, например, код: bodyParser.json() - непонятно, почему он сделан в виде вызова функции? Если он есть в единственном экземпляре, можно просто было бы использовать свойство bodyParser.jsonParser. Если там каждый раз надо создавать новый объект, можно было бы экспортировать класс: new bodyParser.JsonParser. А тут надо вызвать функцию, причем в ее названии нет ни малейшего намека на то, что это функция-конструктор (хоть бы createJsonParser ее назвали). Понятно, что это сторонняя библиотека, но все же не привычно. А еще я открыл для себя, что в Express функция get() делает 2 разных вещи, в зависимости от числа аргументов: http://expressjs.com/ru/api.html#app . Кажется, разработчики Ноды решили пройтись по тем же граблям, которые проходили разработчики PHP.Но в общем-то, я довольно плохо знаком с Нодой. Потому перейдем к коду.Комментариев, конечно мало. Наверно стоило бы хотя бы в начале файла писать, что это за модуль и для чего.Тут ссылка на отсутствующий в репозитории файл - это нормально? Этот файл ведь из чего-то генерируется, и нельзя ли тут подключать исходный файл. Или хотя бы комментарий написать:https://github.com/someApprentice/Crypter/blob/master/server.ts#L30> const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('./dist/server/main.js');Это место очень трудно понять. Мне пришлось открыть вопрос по ссылке из комментария и прочесть его: > // https://stackoverflow.com/a/51391081> const asyncHandler = fn => (req, res, next) => {И проблема тут в плохом названии и отсутствии комментариев. Нужно было назвать функцию, например, promiseToCallback, handlePromise или adaptPromise и снабдить комментарием (я еще убрал стрелки так как на мой личный вкус, они плохо читаемы): // Комментарийfunction wrapPromise(asyncFn) { return function(req, res, next) { return Promise....; }}Еще я не очень понял: 1) зачем там нужен Promise.resolve(), если асинхронная функция при вызове и так возвращает нам промис.2) зачем использовать returnЯ бы тогда написал так: // Принимает на вход асинхронный обработчик, и возвращает// новый обработчик, который отлавливает выброшенные// в нем асинхронно исключения, передавая их в next().//// ссылка на SOfunction adaptPromise(asyncFn) { return function (req, res, next) { asyncFn(req, res, next).catch(next); }}> Does Bearer token provide XSRF protection?Я думаю, да, тут XSRF не пройдет, так как браузер автоматически добавляет к отправляемым запросам куки или заголовок Authorization для традиционной авторизации по логину-паролю (на чем и основана уязвимость), но не добавляет его для типа Bearer.> if (err) throw new err;А не throw err? err - это функция-констуктор или объект исключения? > res.cookie('uuid', uuid, ...> res.cookie('email', email, ...> res.cookie('name', name, ...А зачем тут столько кук? Они же уже содержатся внутри токена. А в твоем варианте пользователь может их подменить, и если ты доверяешь им на сервере, то получается уязвимость. Ну и вообще, нужно ли ставить куки в SPA? Это же серверное API, оно наверно не должно ставить куки. А должно отдавать JSON с токеном. > json(<U> { uuid, email, name, jwt });Не очень понятно, зачем здесь влеплен Type Assertion? Функции json() он не нужен, это для проверки, что объект соответствует интерфейсу User? Еще, кстати, вопрос: а при регистрации проверяется уникальность email? Также, я подозреваю, что удобнее может быть сделать отдельную функцию для валидации, чем использовать только встроенные возможности sequelize. По поводу JWT - я с ним не работал (но с интересом прочитал про него), но у меня уже есть сомнения: почему при подписании токена мы передаем все значения из модели? Получается, что токен перестанет работать в следующих ситуациях: - пользователь меняет имя- пользователь меняет email- пользователь меняет пароль- мы добавили новые поля в модель пользователяНа мой взгляд, токен должен переставать работать только при смене пароля (на случай, если пользователь боится, что у него украли токен и меняет пароль, старый токен должен перестать действовать). Соответственно, в подписи должны участвовать только uuid и хеш пароля. Или я ошибаюсь? И, кстати, а почему был выбран JWT? Какие-то еще варианты рассматривались? Также, я не уверен, а правильно ли токен создавать прямо в обработчике? Не логичнее ли сделать функцию такого вида: async function createToken(u: User): Promise<string>Чтобы мы могли бы создавать токены в любом месте API? > let user = new User({ email });> await user.validate({ skip: difference(Object.keys(User.rawAttributes), ['email']) });Это, конечно, выглядит немного корявым способом проверить email. Наверно, можно как-то получить функцию валидации отдельного поля? > router.get('/email/:email'Это не очень соответствует REST, так как URL в нем это указатель на "ресурс" (какую-то сущность), и при отсутствии ресурса ты должен отдавать 404. А ты всегда отдаешь 200. Я бы сделал тогда просто /email-exists?email=....Не очень понятно, зачем ты тут вызвал валидацию и не использовал результат. И еще важный момент. У тебя нет документации по API, а это плохо. Если фронтенд-разработчик хочет использовать твое API, где он прочтет документацию? Код что ли разбирать? В наши дни наверно самый популярный формат документирования - это OpenAPI 3.0 (бывший Swagger). Ты описываешь свое API в виде YAML файла, и получаешь на выходе такую красивую штуку: https://petstore.swagger.io/ или такую: https://docs.discourse.org/Естественно, логично не писать YAML руками, а генерировать его из комментариев в коде. Так ты получишь и комментированный код, и документацию для разработчиков. Еще, кстати, мне интересно, можно ли как-то использовать описания моделей (например, User) для автоматической генерации документации о формате JSON-ответа, и можно ли использовать описания для автоматического тестирования (тест берет Swagger-описание, проходится по всем методам и пробует их вызывать и проверяет, что ответ соответствует описанию).
>>1354910По тесту: https://github.com/someApprentice/Crypter/blob/master/api/api.test.ts#L31Тут код теста почти повторяет код обработчика. Это не годится, так как ты можешь сделать одинаковые ошибки и там, и там. Если мы тестируем функцию вычисления корня, то ее проверяют возведением в квадрат, а не аналогичным вычислением.В твоем случае надо сформулировать требования к функции регистрации. На мой взгляд, они такие: - она должна создавать аккаунт на сервере, под которым можно залогиниться- она должна возвращать токен, с которым можно использовать защищенное API- нельзя дважды зарегистрироваться с одинаковым email- нельзя регистрироваться без указания обязательных аргументов- и, может, еще какие-то требования по валидации. Например, что при ошибке возвращается объект определенного видаДля каждого требования мы придумываем свой способ проверки. Создание аккаунта на сервере можно проверить, попробовав залогиниться в него. Токен можно проверить, попробовав вызвать защищенное API, например "получить сведения о себе". В общем, тесты пока сделаны неправильно. Так как ты тестируешь код, использующий БД, тебе надо предусмотреть, чтобы база была перед тестом в каком-то определенном состоянии (полностью пустая, например, или с какими-то тестовыми данными). Один из вариантов - в самом начале почистить БД/загрузить дамп, а каждый тест обернуть в транзакцию, которая откатывается. Это может быть быстрее, чем загружать дамп каждый раз. На практике, может быть полезно разместить тестовую БД на ramfs, чтобы избежать вообще обращений к диску и ускорить прогон тестов. Можно также попробовать добавить тест для обработчика ошибок (вызвать специальный URL, который выбрасывает исключение). Иначе ты можешь его отключить/сломать и не заметить. > Is there any way to declare all classes at once for a webpack output file?Я думаю, это не имеет отношения к webpack, так как ты должен в sequelize передать список классов. А для этого их надо импортировать. И вебпак увидит импорты. По клиентской стороне: Ты в API при логине ставишь куки вручную, но разве это правильно? По идее, это должно работать так: - пользователь заходит на HTML-версию и его браузер отправляет запрос на сервер- на сервере создается "песочница", в которой выполняется Angular-приложение и рендерит страницу- оно добавляет записи в StorageService- серверный код видит эти изменения и формирует из них куки Если ты сделал куки аналогом localStorage для серверного рендеринга, то, наверно, логично абстрагировать это от приложения. Оно работает с StorageService, а куда потом сохраняются данные - не его забота.Тут конечно мы упираемся в проблему, что объем кук ограничен, в то время как в браузере мы можем кучу информации сохранить в localStorage. Решением наверно тут будет как можно меньше сохранять в storage, когда мы выполняемся в режиме рендера на сервере. В идеале - хранить там только JWT. Реализовать разную логику для работы на клиенте и на сервере можно, например, через интерфейс: interface Storage { getJwtToken(): Promise<string> setJwtToken(token) getUserData(): Promise<User> setUserData()}И 2 реализации: клиентская берет данные из localStorage, а серверная - берет из БД или кук. Но это, конечно, требует писать два варианта кода. Есть еще альтернатива, но она довольно сложная. Мы могли бы сделать что-то вроде "сессий" и делать для каждой "сессии" свой серверный аналог localStorage. То есть пользователь заходит на сайт, на сервере создается некий serverStorage, который не очищается между запросами. И приложение Angular, работая на сервере, работает с ним, как будто это localStorage. Ключом сессии может быть токен JWT. Данные serverStorage могут храниться в памяти Node-приложения или сбрасываться в HASH внутри редис. То есть, когда приложение работает на сервере, в итоге данные пишутся в redis с ключом на основе JWT. Там конечно еще можно подумать над оптимальным по производительности алгоримом. И опять же, стараться при работе на сервере меньше сохранять данные в serverStorage, если они есть в БД.https://github.com/someApprentice/Crypter/blob/master/src/app/app.component.htmlТут мне не кажется 100% надежной проверка залогиненности. Тут же нет проверки, что это валидный токен.И еще, я не очень понял, как будет работать форма регистрации в режиме серверного рендеринга. Как и куда она будет отправлять свои данные? > let route = this.router.config.find(r => r.path === redirect); > route.data['email'] = email;А это передает email только один раз, или ты этот email навсегда в конфиг роутинга вписал? По моем, не очень красиво получается. Разве нельзя передавать email внутри route parameters: https://angular.io/guide/router#route-parametersТогда можно сделать так: router.navigate(['/register', { email: email }])Причем, я бы хранил email не в path, а в query: /[email protected]> Позволяет ли Bearer token защититься от XSRF? > Приходит ли вам на ум какая-нибудь слабая точка которую можно эксплуатировать?Да. У тебя используются куки, и в них тоже есть токен. Предположим, у нас есть HTML версия, работающая без ангулара. Не получится ли, что злоумышленник сделает форму, которая будет имитировать отправку запроса этой HTML версией, и возникнет XSRF? > Достаточно ли это строгая проверка на то является ли сущность экземпляром объекта localStorage?Проверка достаточная, но непонятен ее смысл. Тест по идее должен проверять, что данные сохраняются и загружаются, а не какой именно класс там испольуется для хранения. > В правильной ли директории находится эта обёртка? Это не совсем сущность, например как User, но места по лучше я не могу придумать для неё. Куда следует помещать обёртки?Это сервис. Помещать - не знаю, в папку для сервисов? Но у меня есть ощущение, что в клиентском приложении файлы и так довольно хаотично разбросаны. > Нужно ли делать проверку на каждую валидацию? Например на встроенные в Ангуляр валидаторы или на валидацию по регулярному выражению?Нет смысла тестировать протестированное. Валидатор если и тестировать, то юнит-тестами, и они уже есть в сторонней библиотеке. Но надо протестировать, что: - эти валидаторы действительно вызываются и проверяют данные- их результат работы отображаетсяПотому, я думаю, нужно проверять не каждую валидацию, а просто вариант, когда поле заполнено неправильно. Можно даже сделать тест, где все поля заполнены неправильно, и проверить, что каждое из них помечено как ошибочное. Ну и тест, что есть какой-то минимум полей, без заполнения которых нельзя пройти регистрацию. > Следующий шаг написания сервиса сообщений. > Он будет реализован с помощь протокола WAMP и на платформе от https://crossbar.io/ , которая написана на Питоне, и для которой для аутентификации клиентов нужно тоже написать код на нём. А чем Node не годится, кстати? Или ты решил изучить Питон и микросервисы? Ок, но на практике такой маленький проект может быть невыгодно разбивать на микросервисы - у них ведь есть и накладные расходы.> Поэтому я сейчас буду изучать его, и возможно у меня появиться небольшие вопросы по нему. Могу я задать их в этом треде?> Заодно и реактивное программирование подучу.Конечно. Только пиши тогда, что именно ты добавил в проект и на что стоит посмотреть, а то он большой и с ходу это будет не очевидно. Я пока все не успел проверить, увы, давай сначала с тем, что я написал, разберемся, а потом остальное глянем.
>>1355067Чтобы скопировать чужие куки, тебе надо получить доступ к чужому компьютеру. А если он у тебя есть, ты можешь просто установить кейлоггер и перехватить пароль (или прочитать сохраненный в браузере пароль, если он сохранен). То есть новой уязвимости не открывается.Дополнительно да, сайт может смотреть, с какого IP ты зашел, и если он сильно поменялся, то попросить подтвердить вход ссылкой на email или SMS.
>>1355110ТестХаб или задачу на SPA, но ты от нее умрешь, ее пока никто не решил. Можешь попробовать сделать SPA, но попроще, чем описанный в ней, например: сайт, показывающий новости (наподобие мобильной версии Хабра). Можно смотреть список новостей, можно смотреть новости из какого-то хаба, можно читать новость, лайкать и добавлять в закладки. Все это в виде SPA, с умным кешированием, автоматическим обновлением и способностью временно работать без Интернета на кешированных данных. То есть Интернета нет, ты жмешь лайк, он запоминается и при появлении связи отправляется. Или ты жмешь новость, и если она есть в кеше, она открывается. Обновления отслеживаются, если появились новые новости, то ввеху появляется плашка с предложением обновить список и загрузить их. Число лайков обновляется если кто-то жмет лайк. Как тебе идея?
>>1360508> А можно узнать, чем ты занимаешься?Просто обычная удаленная работа. > А вот, скажем, мне нужен не один объект, а нужно итеративно и с условиями получить много, тогда что? Нужно будет в контейнере хранить не объект, а класс, а потом внедрять этот класс и там создавать через new?Можно хранить фабрику (класс, создающий нужные объекты), можно в контейнере сделать метод, который позволяет создавать объекты с параметрами. Но вообще, надо подумать, а нужны ли в таких объектах зависимости? Обычно, если это объект типа "Пользователь", у них нет зависимостей и их можно просто создавать через new. То есть такие "сущности" обычно в контейнер не кладут. > То есть вообще всем управляет маппер, а сущности это такие пассивные ячейки памяти, к которым маппер обращается, и сущность сама по себе ничего делать не должна? И в контроллере правильно будет вызывать именно методы маппера?Если ты читал мой урок https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md то знаешь, что есть ACtiveRecord, где сущности умеют сами себя сохранять в БД и Data Mapper, где они не умеют.Второй подход имеет тот плюс, что ты в принципе можешь где-то (например, для теста) создавать сущности, не имея базы данных и использовать их. То есть код работы с БД отделен от кода сущностей и от кода, который использует эти сущности. Ты можешь в теории создать просто массив этих сущностей и весь остальной код даже не заметит, что у тебя не подключена БД (только в теории, на практике часто это не работает, так как код все равно пытается что-то искать и загружать из БД).> А можно такую проверку делать в конструкторах? Плохая идея, из конструктора нельзя возвращать значения, да и он не для этого. Но ты можешь сделать метод вроде beforeRequest() и обязательно его вызывать из фронт-контроллера. > Я придумал вот что. Я в контроллере общем создал контейнер обычный массив data, куда записываю данные со всех уголков контроллеров и приходящие данные из моделей. В контроллерах-родителях задаю общие данные, в контроллерах специфичные, в методах контроллеров данные еще специфичнее. Данные записываются не через переопределение свойств, а через методы суперкласса. Это плохо для чтения кода, так как чтобы понять, что передается в шаблон, надо изучать все эти места кода. Удобнее, когда передаваемые данные формируются в одном месте одним массивом.
>>1361773>Почему "margin: 0;"Выбирай не через body, а через . {margin: 0; padding: 0;}>Подписи к заголовкамВ <p>. Our Featured Works и Get in Touch это будет h2. >Копирайт всегда@ 2013 Webpaint. All Rights Reserved. - у тебя в футере будет, а область выше это секция (section).>со значками соц.сетейУ тебя на фото 5 значков, полностью их вырезай из макета, прямо с кружком. Вставляешь каждую по очереди и делаешь их ссылкой. Помести их в блок div.soc-but или типа того, сделай его display:flex и justify-content: space-between.>плавное всплываниеwebref.ru/css/transition>плавный переходwebref.ru/css/scroll-behavior
сап, анонесы, подскажите с чего начать, попал в небольшую стагнацию, освоил процедурный код пхп и дальше никак. Пытаюсь в ооп, но всегда есть какое-то непонимание, нахуя и почему так. Заебался уже читать эти тонны текста по нему, может кто-нибудь подкинет какой-нибудь легкий на подъем гайд с задачками? Чтобы поменьше воды и практикапрактикапрактика, или я не верный вектор взял и нужно не ооп дрочить, а какой-нибудь фрейм/мвц и т.д?из того в чем разбираюсь норм это sql, pdo, html/css. А куда дальше ковырять не понимаю.
>>1362894ООП раскрывается на больших проектах которые разрабатываются большими группами людей. Самому понять трудно нахуя вообще нужны интерфейсы, и зачем по десять раз писать сначала обьвление в интерфейсе методов, потом их реализация. И другие вещи связанные в ООП. Но на больших проектах оказывается что это наоборот экономит время и позволяет не повторять функционал по сто раз, передавать экземпляры класса как аргумент итд.
>>1362922вот, и я нихуя не понимаю как мне это учить блждат. Или ты хочешь сказать забить на ооп и только в теории понимание этого достаточно, пока не началась работа в сфере.
Разработчики, поясните в каких случаях стоит отделять mysql от сайта, а когда нетНасколько нормально держать сайт и базу данных на одном сервере, при условии, что у бд указан локалхост вместо интерфейса
>>1362894Во-первых, если хочешь начать с самых-самых основ, то глянь учебник из ОП-поста, в нем есть глава про ООП, и там есть задачка про "Вектор". Стоит попробовать решить. Плюс в том, что там рассматриваются совсем основы ООП, которые ты может быть пропустил. Если хочешь что-то посложнее, то к твоим услугам задача про ООП-гостинцу и ООП-будильник тут: - ООП-Будильник: https://phpclub.tech/pr/res/1232710.html#1263399- ООП-Гостиница: https://phpclub.tech/pr/res/1082507.html#1097078Дальше, если ты все это сделал или все идеально знаешь, гугли и изучай инкапсуляцию, SOLID, DI. Кстати, у меня есть понятный урок по DI: https://github.com/codedokode/pasta/blob/master/arch/di.mdА еще по интерфейсам: https://github.com/codedokode/pasta/blob/master/php/interfaces.mdНу и если есть желание, почитай другие уроки тут: https://github.com/codedokode/pasta/ - там есть и про MVC и про другие трендовые слова.Ну и заодно почитай статью про выпечку хлеба: https://habr.com/ru/post/153225/Если захочется увидеть применение ООП на практике, изучи библиотеку Symfony forms, разбери ее код и нарисуй диаграмму классов и связей между ними (кто кого наследует, кто кого создает).Если ты все это прочтешь и изучишь, то ты будешь намного лучше разбираться в ООП и увереннее себя чувствовать. Я готов ответить на уточняющие вопросы, а также подсказать по задачкам или проверить решения. Изучать ООП надо с основ. Если ты их не освоил, а берешься за паттерны, фреймворки, то конечно ты будешь путаться.
>>1362992о, спасибо большое анон, отлично все расписал. Займусь сегодня, благодарю, буду вкидывать решения. Еще раз спасибо.
>>1353705 (OP)не могу вывести названия элементов из дб в список в php файлhttp://beta.phpformatter.com#.XIex79kY6AQ.linkвыдает ошибку Warning: mysqli_fetch_assoc() expects parameter 1 to be mysqli_result, null given in мой путь до файлафайл у меня на сайте на локалхосте через апач (опенсервер)
Имеет ли смысл использовать в студентах подобную систему валидации https://3v4l.org/gfBAC? Накидал на скорую руку, получился какой-то карго-культ на валидацию из симфони.Кстати про симфони, в объектах-наследниках Constraint открытые публичные свойства. Получается бывают ситуации, когда инкапсуляцией можно пренебречь?https://github.com/symfony/symfony/blob/4.2/src/Symfony/Component/Validator/Constraints/Length.php
>>1363027я дебич короче вот на пикахпервый пик подключение к дбвторой пик это я так пытался вывести тайтлы из дб в столбик
>>1363067У тебя регулярка неправильная, [ ] задают список возможных символов, там не работают всякие | и &. Если тебе нужно условие "+7 или 8", то будет `(\+7|8)`.
А как по нормальному деплоятся сайты которые больше визиток? К примеру у меня небольшой веб-магазин, тысяч 60 товаров, 40 гигов фоток к товарам. И я хочу чтобы была возможность одной кнопкой переместить это все на другой сервак. С визиткой скажем понятно. Засунул в докер, где надо запустил с образа. С большими сайтами как-то не ок, так как на стайте каждый день что-то меняют (фотки к товарам + новые товары). Тоесть просто копировать образ докера не получится (если не пересобирать его после каждой новой фотки). Ну и база еще.
Аноны, у меня такой вопрос, возможно ли каким-то образом параллельно запустить PHP для обработки данных с Mysql. Т.е. из БД я к примеру делаю запрос вида: SELECT * FROM `table` WHERE ... LIMIT 1000. А затем первые 500 строк обрабатываю в одном потоке, а остальные строки во втором потоке. Сейчас скрипт, который реализует этот функционал выполняется около 10 мин. Вся проблема в том, что записи связаны с другими таблицами, и одна запись из извлекаемой таблицы, может иметь несколько записей из других таблиц. Сам скрипт вносит определнные изменения в эти данные, т.е. вызывается UPDATE.
Если в StudentDataGateway объединить методы add и update в save() + добавить логику определения существования студента, то этот класс можно переименовывать в StudentMapper?И ещё, в классе работы с БД очевидно нужна функция поиска студентов. Например $studentMapper->find($searchQuery, $orderBy, $orderDir, $offset, $limit);Что если в find() передавать не кучу параметров, а объект с параметрами класса SearchOptions? Узнал о таком способе решения тут https://www.refactoring.com/catalog/introduceParameterObject.html
Есть вопрос насчёт цепочки исключений.Вот такая функция:[code lang="php"] %public function func1(){ $x = 0; try { /// } catch(SomeException $e) { switch ($e->getCode()) { case 1: throw new SomeException("message_1", 11, $e); break; case 2: throw new SomeException("message_2", 22, $e); break; case 3: try { /// } catch (SomeException $g) { // brainfuck $g->previous = $e; throw new SomeException('message_5', 55, $g); } throw new SomeException('message_3', 33, $e); break; case 4: /// break; } } return $x;}% [/code]Сложность в блоке с brainfuck. Так как написано - не получится хотя бы потому что и поля previous нету. Создать копию $g вроде как нельзя - перенесётся message и code, но не trace и остальное.Как же сцепить исключения таким образом чтобы все данные нормально сохранились? Может тут какая-то стилистическая или структурная ошибка?
>>1363443Код довольно большой, и не очень понятно, что ты хочешь сделать. Связь исключений используется. чтобы показать, что одно исключение было вызвано другим. Ну например, чтобы показать, что исключение DataLoadException вызвано исключнием HTTPConnectException (мы не смогли загрузить данные, так как в ходе их получения не удалось соединиться с удаленным сервером). Пример: function getData($x) {try {$a = loadDataFrom('https://a.example.com/1');$b = loadDataFrom('https://b.example.com/1');return $a + $b;} catch (HTTPConnectException $e) {throw new DataLoadException("Не удалось загрузить данные из-за проблем связи с сервером", 0, $e);} catch (AccessDeniedException $e) {throw new DataLoadException("Не удалось загрузить данные из-за того, что доступ к ним запрещен", 0, $e);}Ты же в коде ловишь одно исключение. и создаешь на его основе исключение того же класса. Это выглядит как минимум странно.
Не могу понять, где ставить поиск символов, которые могут быть посреди номера.Я пробую:([0-9]{10}) ([\w]{0,}) - цифры и знаки в разных скобках.([0-9]{10} [\w]{0,}) - цифры и знаки в одних скобках.[0-9 [\w]{0,} ]{10} - знаки внутри скобок с цифрами.Как я понял, то, что внутри (этих) скобок считается отдельным блоком, куда можно накидать кучу параметров, написанных [тут]. Но почему- то у меня не работает это никак.Объясните, как, блять, тут делать, чтоб нормально было.
>>1363604Читать нормальные статьи где объясняют регулярки. >>1353705 (OP)Вы все еще так же сидите на РПР? Это же каким дегенератом нужно быть.
сап програмач, хочу написать скрипт для регистрации на сайте, что нужно знать для этого, знаю кто то использует API с сайтов с смсками, хелпаните инфой кто какой обладает
>>1363679гугли скрипты для регистрации и делай для своей бд где у тебя юзеры будут хранитьсяесли я правильно понял что тебе нужно>>1363131вот тут я просто поменял assoc на array и дописал запроскому интересно могу показать
Всем приветик в этом чатике, это снова я.Подскажите, блять, наконец уже, как сделать поиск символов между цифр.Есть охуенная идея: Накопипастить ([\W]{0,})([0-9]) десять раз, но это же пиздец как тупо. Уверен, есть другой способ, просто я слишком туп, чтоб его найти. Подскажите, блэт.
>>1364097У программиста была проблема которую он предпочел решить регулярными выражениями. Теперь у него две проблемы.
>>1364097- напиши выражение, которое находит ровно 1 цифру и любое число доп. символов за ней- возьми его в круглые скобки и поставь после них {x}
>>1364120Чот я прикола не понял. Чому он пропускает некоторые номера? Не могу понять, по какому признаку он их выбирает.В чем причина моих мозгах, аноны?
>>1364123Смотри внимательнее на проблемные номера. В одном из них в начале идет пробел, но твоя регулярка это не предусмотрела. Попробуй мысленно сопоставить регулярку с текстом и увидеть, где она не соответствует номеру.Также, вместо {0,} можно писать просто звездочку. Также, вместо \W лучше писать конкретные символы - минусы, скобки, пробелы, а то он что угодно под это выражение подгонит.
>>1364125Спасибо тебе, помог очень сильно. Долго думал, как быть с пробелом между + и 7, но догадался(!) сделать там просто пробел.> Также, вместо {0,} можно писать просто звездочку. > Также, вместо \W лучше писать конкретные символы - минусы, скобки, пробелы, а то он что угодно под это выражение подгонит. За вот эти советы отдельное спасибо, буду знать и применять.
Аноны, привет, я нуб. Я тут валандаюсь с своим MVC, сейчас озадачен админкой и ролями и прочим.Сейчас я очевидно горожу свои костыльные недо-велосипеды.Может стоит взять какой нибудь фреймворк за основу? Сразу начинать с большого, я думаю о laravel. Или все таки какой то мини-фреймворк? Я правда о таких не знаю.Основная задача все таки - посмотреть как это должно быть реализованно.MVC для меня сейчас обязательно, так как я с начала изучения пишу классами на MVC.
>>1364171Могу предложить простой урок про основы MVC: https://github.com/codedokode/pasta/blob/master/arch/mvc.mdЗатем можно посмотреть какой-нибудь фреймворк вроде Yii2 (попроще) или Laravel, Symfony (посложнее). Это как раз подходит для варианта "посмотреть, как реализовано". Для ролей обычно принято использовать RBAC.
>>1364097Бля, анон, как же хочется помочь тебе, но мне пиздец как впадлу даже твой скрин смотреть(Гугли уроки по регуляркам от WebForMySelfмимо бог регулярок
>>1364272> WebForMySelfИ на этом спасибо. Чем больше материалов, тем лучше. Где- то одни фичи рассказывают, где- то - другие.
>>1364387Технически никакой и на скорость выполнения не влияет, просто синтаксически наглядней, особенно если будет огромный запрос, то сразу видно будет какие таблицы юзаются, а в условии будут примитивные конструкции
>>1364387Выборка из двух таблиц === inner join.Есть ещё outer join (с пустыми клеточками) и редко бывает нужен self join (поиск совпадений в таблицах).Алсо, не забываем о том, что в джойнах есть ключевое слово "ON", с ним код легче читать.
Многоуважаемые братья пхп-шники, подскажите пожалуйста. Задачка по проверке номера по регуляркам. Как написать регулярку которая: сначала идет +7 или 8, за ними ровно 10 цифр, между которыми может быть любое число скобок, минусов, пробеловЯ сделал как ^(\+?(8|7)\d{10})$ Но как сделать так, чтобы между цифрами могли быть пробелы, или другие символы?
>>1364678(\+?7|8)([()\-\s]\d[()\-\s]){10}([()\-\s]\d[()\-\s]){10}Обязательно одно число от 0 до 9 (\d). Вокруг него может быть, а может и не быть любое количество пробелов, тире, скобок.Помог как смог.
>>1364246>Могу предложить простой урок про основы MVC: https://github.com/codedokode/pasta/blob/master/arch/mvc.mdК сожалению, там упущен один очень важный момент, а именно по поводу тонкого контроллера и толстой модели.
Недавно начал осваивать Linux (Lubuntu), поэтому никак не могу настроить apache2, чтобы он корректно отображал PHP скрипты.Все установил через консоль, как описано здесь: https://howtoubuntu.org/how-to-install-lamp-on-ubuntuОднако когда закидываю свой test.php в /var/www/html, то в результате браузер открывает пустую страницу. Смотрел туториалы рандомных индусов - у них всё отображается.HTML файлы отображаются без проблем.В чём может быть проблема? Выручьте идеями, пожалуйста.
Ребята, подскажите проект php на github-е, желательно e-commerce, в котором применяется DDD и код придерживается принципам SOLID?Вроде теорию прочитал - понял, но на практике не могу применять, что касаемо DDD.
>>1364960Спасибо за вариант! Изменил файл, проблема осталась, к сожалению.Выходит абсолютно пустая страница.
>>1364964Что ты изменил :) ?Какая версия пхп у тебя под апачем работает?Покажи свой test.phpЧто ты в адресной строке набираешь?Не заставляй ванговать
>>1364968Окей, вот порядок моих действий:1) sudo vim /etc/php/7.2/apache2/php.ini2) нашёл строчку display_errors = Off, поменял на On (:wq, конечно же);3) sudo service apache2 restartСкрипт простой:<?phpecho "This is supposed to be displayed!";?>Просто без задней мысли вбиваю:file:///var/www/html/test.php
>>1364990Я просто очень большой нуб, поэтому я просто создал HTML файл в /var/www/htmlНазвал его test.html, положил туда простой контент и кликнул дважды. Затем поменял test.html в строке на test.php и ничего не получил.Почему я так сделал? Потому что на винде localhost/myfolder выводит список файлов, которые без проблем запускаются по нажатию. Тут такое не работает.Моя логика действий само собой вызывает улыбку, но вот как-то так.Анон, большое тебе спасибо. Я не перестаю удивляться, как этот тред умудряется привлекать столько отзывчивых анонов.
>>1365221Довольно быстро. Но буден непривычно выделять переменные и ставить ; в конце команд. А так - такой же простой язык, как и питхон.поначалу орал люто, потому что вместо echo писал print().
>>1353705 (OP)Какую функцию использовать чтобы в zakaz.php отображался свой элемент из моей бд для каждого элемента цикла?
аноны. хочу сделать ооп ферму. создал классы для 2-х типов животныых. Как мне описать ферму, чтобы она могла добавлять N животных, доить их и вытаскивать продукцию? опиши словесно
>>1365708Следующие советы подразумевают что ты хочешь поебаться с ООП.Рефакторишь своих животных чтобы они наследовались от общего базового класса. В базовом классе реализешь генерацию id, а также метод getYeld() - этот метод возвращает массив с дневными профитами с животного, в твоем случае это будет что-то типа ['milk' => 8] с коровы и ['egg' => 1] с курицы. В массиве можно возвращать несколько разных продуктов (если ты хардкорный фермер можно еще навоз например добавить - это важный ресурс). Ключи массива сделать костантами.В классе фермы делаешь массив для животных. Для добавления животных делаешь метод addAnimal($class, $count) - указываешь класс животного и количество, ферма добавляет нужное количество в массив животных. Делаешь массив для хранения ресурсов. Добавляешь к ферме метод getYeld() который проходит по массиву животных, вызывает у каждого животного getYeld(), полученые результаты суммирует с массивом с ресурсами - тут нужно внимательно проследить чтобы результаты для каждого ключа суммировались с теми что уже есть в массиве, а не перезаписывались новыми.
>>1365283пиши в sql запрос SELECT*FROM stor WHERE 'столбец цена' AS price AND 'столбец количество' AS quan и т.д , все отсально кроме запроса вроде корректное
функция json_decode() не работает к этой строке, json parser-ы и decode-ры говорят что всё ок, но вот json_decode() жалуетсяпомогите пожайлуста
>>1353705 (OP)Аноы, чет туплю.Есть у меня класс Klass, у этого класса есть статический метод Start(){...}создаю новый объект $obj = new Klass();И вызываю статический метод из объекта не статическим способом:$obj->Start(); и так работаетКакой жопой я читал документацию? Разве так можно?
>>1365974Объявление свойств и методов класса статическими позволяет обращаться к ним без создания экземпляра класса. Свойство класса, объявленное как статическое, не может быть доступно посредством экземпляра класса (но статический метод может быть вызван). http://php.net/manual/ru/language.oop5.static.php
>>1365937Снкачала убедись что file_get_contents правильно читает файл, потом разбивай джон на части пока не найдешь строчку с проблемой
>>1365957Хз что сказать.Имей ввиду что йава ждуниоров фильтруют сложностью тестового.Это ёба задание на 3-х листах английского текста на неделю, где специально выбирают ёба технологии про которые никто не знает (сразу отваливаются вкатальщики по роликам с ютуба и остаются тру пацаны которые умеют читать доки по английски и гуглить в стековерфлоу)Если у тебя есть зелёный гит и что нить в сети на пхп то ты уже молодец.
>>1361814>Вот что мне в ноде кажется неудобным - так это то, что каждый в Node.JS организует код как хочет. Вот, например, код: bodyParser.json() - непонятно, почему он сделан в виде вызова функции? Если он есть в единственном экземпляре, можно просто было бы использовать свойство bodyParser.jsonParser. Если там каждый раз надо создавать новый объект, можно было бы экспортировать класс: new bodyParser.JsonParser. А тут надо вызвать функцию, причем в ее названии нет ни малейшего намека на то, что это функция-конструктор (хоть бы createJsonParser ее назвали). Понятно, что это сторонняя библиотека, но все же не привычно. А ещё с TypeScript некоторые возможности теряются https://github.com/someApprentice/Crypter/blob/master/api/api.ts#L8-L9 Моё мнение что на JS не должно быть никакого кода, кроме браузерного, и максимум выдаваться SSR страницы. А серверный код должен написан на языках получше, например PHP. >Комментариев, конечно мало. Наверно стоило бы хотя бы в начале файла писать, что это за модуль и для чего.Ой-ой. Ошибка. Нужно было предупредить, что я комментарии оставлял "для себя" чтобы понимать что это и откуда взялось, и что это скорее всего нужно исправить. К сожалению, инструменты для написания кода на JS ещё не совершены, и не справляются с тривиальными задачами, по моему приземлённому мнению.Я перенёс эти проблемы в issues задачи https://github.com/someApprentice/Crypter/issues проверять это не нужно, но если у вас есть подсказка, то я с радостью её примуИсправлю эту ошибку написав хорошие комментарии. Только, я не понимаю зачем, по-моему только сервису-обёртке хранилища можно, потому что это весьма не типичный подход. В остальном, разве это не очевидно что чем занимается?У меня плохо с английским и написание комментариев утяжелит и замедлил разработку. Насколько важно их писать? >Тут ссылка на отсутствующий в репозитории файл - это нормально? Этот файл ведь из чего-то генерируется, и нельзя ли тут подключать исходный файл. Или хотя бы комментарий написать:>>https://github.com/someApprentice/Crypter/blob/master/server.ts#L30>> const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('./dist/server/main.js');>Да, эта папка генерируется после сборки приложения npm run build. Думаю тут тоже можно добавить комментарий.>И проблема тут в плохом названии и отсутствии комментариев. Нужно было назвать функцию, например, promiseToCallback, handlePromise или adaptPromise и снабдить комментариемНасчет комментария это да, их стоит добавить. Но я не понимаю почему вы пишите, что эта функция для того чтобы обрабатывать промисы, это не так. Эта функция нужна, чтобы обработать асинхронный обработчик запросов, который Эксрпресс не поддерживает (пока что?).// Это не сработаетexpress.get('/route', async (...) => {await promise = ...});https://github.com/someApprentice/Crypter/issues/12>> if (err) throw new err;>>А не throw err? err - это функция-констуктор или объект исключения? Объект исключения. Исправлю.>> res.cookie('uuid', uuid, ...>> res.cookie('email', email, ...>> res.cookie('name', name, ...>>А зачем тут столько кук? Они же уже содержатся внутри токена. А в твоем варианте пользователь может их подменить, и если ты доверяешь им на сервере, то получается уязвимость. Ну и вообще, нужно ли ставить куки в SPA? Это же серверное API, оно наверно не должно ставить куки. А должно отдавать JSON с токеном. Они нужны для отрисовки данных при серверном рендеренге. Как я уже писал, куки нужны только для условий отображений https://github.com/someApprentice/Crypter/blob/master/src/app/main/main.component.html#L3 . Возможно uuid можно убрать, но почему нет?Здесь нет уязвимости, т.к. сервер (API) не использует куки. Сделать приложение работающие без поддержки JS - я отказываюсь от этой идеи.>> json(<U> { uuid, email, name, jwt });>>Не очень понятно, зачем здесь влеплен Type Assertion? Функции json() он не нужен, это для проверки, что объект соответствует интерфейсу User? Да, именно так. Это лишнее?>Еще, кстати, вопрос: а при регистрации проверяется уникальность email? Нет, я забыл её сделать. Исправлю. И наверно нужно ещё это в схему БД добавить.>Также, я подозреваю, что удобнее может быть сделать отдельную функцию для валидации, чем использовать только встроенные возможности sequelize. Почему нужно отдельную функцию валидации? Всё же и так в одну строчку делается. https://github.com/someApprentice/Crypter/blob/master/api/api.ts#L50>По поводу JWT - я с ним не работал (но с интересом прочитал про него), но у меня уже есть сомнения: почему при подписании токена мы передаем все значения из модели? Получается, что токен перестанет работать в следующих ситуациях: >>- пользователь меняет имя>- пользователь меняет email>- пользователь меняет пароль>- мы добавили новые поля в модель пользователя>>На мой взгляд, токен должен переставать работать только при смене пароля (на случай, если пользователь боится, что у него украли токен и меняет пароль, старый токен должен перестать действовать). Соответственно, в подписи должны участвовать только uuid и хеш пароля. Или я ошибаюсь? >>И, кстати, а почему был выбран JWT? Какие-то еще варианты рассматривались? >>Также, я не уверен, а правильно ли токен создавать прямо в обработчике? Не логичнее ли сделать функцию такого вида: >>async function createToken(u: User): Promise<string>>>Чтобы мы могли бы создавать токены в любом месте API? >почему при подписании токена мы передаем все значения из модели?Да, я понимаю этот вопрос. Я думал, что можно сделать так, получать из Bearer token этот токен, и получать из него всё что нужно (имейл/что-нибудь ещё), но это, скорее всего нигде не пригодиться, так что это ошибка. Я согласен что достаточно хранить в нём только uuid и хэш.>И, кстати, а почему был выбран JWT? Какие-то еще варианты рассматривались? Он популярен. Чем популярнее технология, тем больше решений вопросов связанной с ней. В прочитанных мной статьях по JS приводят примеры именно с ним.>Также, я не уверен, а правильно ли токен создавать прямо в обработчике? Не логичнее ли сделать функцию такого вида: >>async function createToken(u: User): Promise<string>>>Чтобы мы могли бы создавать токены в любом месте API? Я скажу на чистоту мой взгляд на это - Я не понимаю зачем нужно выносить такие функции в отдельные. Это функция понятна любому разработчику и он с первого взгляда поймет что происходит в ней. Почему нужно делать обёртку ради человекопонятного названия функции?Я правда не понимаю, вот как эта функция будет выглядеть (она кстати не работает на промисах):function createToken(u: User, cb) {token.sign(u.dataValues, JWT_SECRET, cb(...))}Но мы и так передаём в неё пользователя и коллбэк, и больше ничего не делаем. Почему нужно её выносить?>> let user = new User({ email });>> await user.validate({ skip: difference(Object.keys(User.rawAttributes), ['email']) });>>Это, конечно, выглядит немного корявым способом проверить email. Наверно, можно как-то получить функцию валидации отдельного поля? Это баг библиотеки sequelize-typescript. Чтобы получить валидацию отдельного поля нужно вместо опции skip добавить fields.>> router.get('/email/:email'>>Это не очень соответствует REST, так как URL в нем это указатель на "ресурс" (какую-то сущность), и при отсутствии ресурса ты должен отдавать 404. А ты всегда отдаешь 200. Я бы сделал тогда просто /email-exists?email=....>Я бы сделал тогда просто /email-exists?email=....Всё исправлю. Здесь тоже в случае отсутствия нужно отдавать 404?>Не очень понятно, зачем ты тут вызвал валидацию и не использовал результат. Хм, возможно валидацию и не стоило вызывать. Почему нет?>и не использовал результатРезультат валидации либо вбрасывает ошибку, либо возвращает null(?). Эта ошибка обрабатывается в обработчике ошибок https://github.com/someApprentice/Crypter/blob/master/api/errorHandler.ts#L8-L10>И еще важный момент. У тебя нет документации по API, а это плохо. Если фронтенд-разработчик хочет использовать твое API, где он прочтет документацию? Код что ли разбирать? >>В наши дни наверно самый популярный формат документирования - это OpenAPI 3.0 (бывший Swagger). Ты описываешь свое API в виде YAML файла, и получаешь на выходе такую красивую штуку: https://petstore.swagger.io/ или такую: https://docs.discourse.org/>>Естественно, логично не писать YAML руками, а генерировать его из комментариев в коде. Так ты получишь и комментированный код, и документацию для разработчиков. Понял, буду работать над этим. Написать комментарии для документации API мне кажется более понятной задачей, чем писать комментарии для бушующих разроботчиков. Так вы имели ввиду комментраии для модулей API, а не фронтенд приложения?
>>1361814>Еще, кстати, мне интересно, можно ли как-то использовать описания моделей (например, User) для автоматической генерации документации о формате JSON-ответа, и можно ли использовать описания для автоматического тестирования (тест берет Swagger-описание, проходится по всем методам и пробует их вызывать и проверяет, что ответ соответствует описанию).Я ничего из этого не знаю, но постараюсь разобраться.>>1361815>Тут код теста почти повторяет код обработчика. Это не годится, так как ты можешь сделать одинаковые ошибки и там, и там.А где у меня код повторяется? То что я токен генерирую? А как я узнаю какой токен будет иначе?>Если мы тестируем функцию вычисления корня, то ее проверяют возведением в квадрат, а не аналогичным вычислением.Не понимаю сравнение.var n = 5expect(sqrt(n^2)).toEqual(n)Я же тоже "возвожу" данные пользователя в токен и проверяю совпадает ли возвращённый ответ, а именно кукисы, с ним. var user = { ... }token(user, (jwt) => {expect(cookies['jwt']).toEqual(jwt)});Ну да, теперь вижу причину. Нужно проверить что пришедший токен в дешифрованном виде равен данным пользователя?>В твоем случае надо сформулировать требования к функции регистрации. На мой взгляд, они такие: >>- она должна создавать аккаунт на сервере, под которым можно залогинитьсяЯ забыл сделать проверку, что пользователь добавился в БД и данные правильные. Это достаточное условие? Залогинивание проверяется в предназначенном для неё тесте, и там как раз сначала заполняется запись в БД.>- она должна возвращать токен, с которым можно использовать защищенное APIНужно сделать проверку как я писал выше, что пришедший токен в дешифрованном виде равен данным пользователя или действительно нужно проверять каким-то методом API?>- нельзя дважды зарегистрироваться с одинаковым emailСделаю. то нужно сделать прописав ассоциацию Sequelize на уникальность emai'а. Тогда при повтороном имейле будет вбрасываться ошибка и тест провалится.>- нельзя регистрироваться без указания обязательных аргументовСделаю.>- и, может, еще какие-то требования по валидации. Например, что при ошибке возвращается объект определенного видаСделаю.>Для каждого требования мы придумываем свой способ проверки. Создание аккаунта на сервере можно проверить, попробовав залогиниться в него. Токен можно проверить, попробовав вызвать защищенное API, например "получить сведения о себе". >Создание аккаунта на сервере можно проверить, попробовав залогиниться в него.>Токен можно проверить, попробовав вызвать защищенное API, например "получить сведения о себе". Почему? Разве не достаточно проверить что запись добавилась в базу? Разве не залогинивание не должно проверяться в своём собственном тесте?А токен не достаточно проверить просто дешифровав его (как раз метод и называется verify(token))? >Так как ты тестируешь код, использующий БД, тебе надо предусмотреть, чтобы база была перед тестом в каком-то определенном состоянии (полностью пустая, например, или с какими-то тестовыми данными). Один из вариантов - в самом начале почистить БД/загрузить дамп, а каждый тест обернуть в транзакцию, которая откатывается. Это может быть быстрее, чем загружать дамп каждый раз. В данный момент для каждого теста БД должна быть в чистом состоянии и после каждого теста база очищается это можно улучшить добавив перед каждым тестом очистку (методо beforeEach()).>На практике, может быть полезно разместить тестовую БД на ramfs, чтобы избежать вообще обращений к диску и ускорить прогон тестов. Тяжело понять. Я с таким не сталкивался. Вижу что это как бы "эмулирует" жесткий диск в оперативной памяти. Как для этого настроить psql? Как нужно будет для это настраивать найстройки соеденения к БД в Ноде? Слишком много вопросов для такой маленькой задачи. Возможно позже, с ростом приложения это будет актуально. Если что взял этот подход на вооружение и вернусь к нему, когда тесты будут делаться медленно.>Можно также попробовать добавить тест для обработчика ошибок (вызвать специальный URL, который выбрасывает исключение). Иначе ты можешь его отключить/сломать и не заметить. Сделаю.>> Is there any way to declare all classes at once for a webpack output file?>>Я думаю, это не имеет отношения к webpack, так как ты должен в sequelize передать список классов. А для этого их надо импортировать. И вебпак увидит импорты. В sequlize-typescript можно указать директорию с моделями, но webpack транспилирует всё в один файл, и это ломается. https://www.npmjs.com/package/sequelize-typescript#configurationhttps://github.com/someApprentice/Crypter/issues/7>По клиентской стороне: >>Ты в API при логине ставишь куки вручную, но разве это правильно? По идее, это должно работать так: Ставлю куки вручную в клиентской стороне? Нет, у меня такого нет. В клиентской стороне куки только берутся из реквеста, чтобы пререндерить страницу с залогиненым пользователем или нет. Для этого они и нужны. localStorage ставиться в ручную(?) в клиентской стороне при залогинивании https://github.com/someApprentice/Crypter/blob/master/src/app/auth/login/login.component.ts#L48-L51 . Не могли бы вы уточнить строку где я это делаю, я не могу понять последующие описание проблемы.>https://github.com/someApprentice/Crypter/blob/master/src/app/app.component.html>>Тут мне не кажется 100% надежной проверка залогиненности. Тут же нет проверки, что это валидный токен.Так это же отображение. Если что-то не так, то при запросе к API выдастся соответствующая ошибка. Вряд ли, пользователь сможет что-то сломать не лазия в хранилище.>И еще, я не очень понял, как будет работать форма регистрации в режиме серверного рендеринга. Как и куда она будет отправлять свои данные? >>> let route = this.router.config.find(r => r.path === redirect); >> route.data['email'] = email;Имеете ввиду версию страницы работающей с отключенным JS? Я решил отказаться от этой идеи. Она бесполезная, по крайней мере для части чата, потому что сообщения будут шифроваться на стороне клиента. Может быть позже можно что-то с этим придумать, но пока этого не будет. Я считаю, что это вопрос доверия пользователя, оно есть в каких-то границах, и эти границы могут как и широки так и малы, т.е. я пытаюсь сказать что зависит от пользователя и его доверия. Я думаю, что для приложения с открытом кодом можно даже задуматься и о вайтлисте js.>А это передает email только один раз, или ты этот email навсегда в конфиг роутинга вписал? По моем, не очень красиво получается. Разве нельзя передавать email внутри route parameters: https://angular.io/guide/router#route-parameters>>Тогда можно сделать так: router.navigate(['/register', { email: email }])>>Причем, я бы хранил email не в path, а в query: /[email protected]Можно, но мне наоборот кажется это не очень красивым, когда в URL что-то появляется. Хочу чтобы было так.Этот email удаляется из роутинга после уничтожения связанного компонента:https://github.com/someApprentice/Crypter/blob/master/src/app/auth/login/login.component.ts#L63-L68>> Позволяет ли Bearer token защититься от XSRF? >> Приходит ли вам на ум какая-нибудь слабая точка которую можно эксплуатировать?>>Да. У тебя используются куки, и в них тоже есть токен. Предположим, у нас есть HTML версия, работающая без ангулара. Не получится ли, что злоумышленник сделает форму, которая будет имитировать отправку запроса этой HTML версией, и возникнет XSRF? Как я говорил ранее, я принял решение отказаться от версии без ангуляра, что значит что не будет такого обработчика запроса, который будет работать с куками повторюсь в очередной раз, что они нужны только для условий в отоброжении (токен наверно и удалить из кук)>> Достаточно ли это строгая проверка на то является ли сущность экземпляром объекта localStorage?>>Проверка достаточная, но непонятен ее смысл. Тест по идее должен проверять, что данные сохраняются и загружаются, а не какой именно класс там испольуется для хранения. Проверить... что, например, вот для серверной части есть проверка, что вернулся StorageWrapper и всё работает, а для браузерной тоже аналогично. Это не нужно?
>>1361815>> Следующий шаг написания сервиса сообщений. >>> Он будет реализован с помощь протокола WAMP и на платформе от https://crossbar.io/ , которая написана на Питоне, и для которой для аутентификации клиентов нужно тоже написать код на нём. >>А чем Node не годится, кстати? Или ты решил изучить Питон и микросервисы? Ок, но на практике такой маленький проект может быть невыгодно разбивать на микросервисы - у них ведь есть и накладные расходы.У роутеров WAMP'а на Node, нету возможностей для аутентифекации и авторизации соединения, и документации. Вышеупомянутая платформа развита лучше других.>> Поэтому я сейчас буду изучать его, и возможно у меня появиться небольшие вопросы по нему. Могу я задать их в этом треде?>>> Заодно и реактивное программирование подучу.>>Конечно. Только пиши тогда, что именно ты добавил в проект и на что стоит посмотреть, а то он большой и с ходу это будет не очевидно. Хорошо, я буду всё подробно описывать.>Я пока все не успел проверить, увы, давай сначала с тем, что я написал, разберемся, а потом остальное глянем.Хорошо, спасибо большое! Я не успеваю ответить в тот же день. Не понимаю почему - занимаюсь каждый день, и всё больше и больше нужно изучить. Я так хочу просто писать код. Я никогда не знал что разработка на JS может быть такой сложной, и приложений вообще.Я ещё серьёзно задумываюсь о приложениях для устройств, а там либо медленный и кривой JS, либо изучать Java/Swift.Я так хочу хотя бы браузернное приложение к лету закончить, а приложения к осени.Спасибо большое, у меня нет слов как мне всё это важно.
Привет ананасы. Как-то давно начинал делать тестхаб на симфони, потом забил и сейчас опять решил, но уже на ларавель. Я уже даже немного смирился с евойной орм, пока решил не инсертить данные в таблицу. Тут просто ужасно всё, из-за архитектуры орм нельзя как в доктрине без записи в бд привязать определенные вопросы к тесту например, есть метод saveMany, думаешь что он может заинсертить всё одним запросом? он в цикле просто вызывает свой же save() метод, в итоге получается что на каждый объект идет запрос к бд, если у меня 50 вопросов и у каждого по 4 ответа то это получается 200 запросов к базе просто для сохранения. Помню в доктрине можно было банально через сеттер сначала сохранить всё как ты хочешь, а если еще и cascade: persist стоит то вообще можно не напрягаться. Читал что как вариант можно использовать DB::insert( array ), вручную расставлять внешние ключи и вот это всё. А вот та же валидация реквеста намного больше понравилась чем формы в симфони
>>1366247>валидация реквеста намного больше понравилась чем формы в симфониТебе никто не запрещает запилить аргумент ресолвер в симфе и тоже валидировать реквест.
>>1366045Вот инглиш ща взялся поттягивать. С пыхой на "ты", опыт работы и гитхаб имеется.С пыхи вообще укатиться сложно? Насколько это будет плюсом при приеме на работу? Или меня джависты будут обоссывать?
>>1353705 (OP)Вопросы по задаче про список студентов1)Где нужно создавать базу данны=х? В командной строке(КС), в самом PHP или в PHPadmin? Если использовать КС или админку, то как сохранять ... код на Git? 2) Так же не понял с, что делать с организацией доступа пользователей. Мне нужно через GRANT создать пользователя и или можно предоставить привилегированный доступ (root)? Я просто не понял, как люди проверяют работу через Git. Им же все равно нужно выгрузить весь код на свой компьютер и потом запустить у себя? Значит не нужно создавать пользователя или все таки нужно?3) Зачем в этом задании использовать классы? Разве нельзя обойтись без них? Особенно не понял, зачем нужен "класс-помощник". Раз у него отсутствуют свойства, почему бы не использовать обычные функции?
>>13664274)Также вопрос про экранирование. В уроке про шаблоны говорилось, что "данные лучше форматировать не в php-скрипте, а в шаблоне. Причина тому в том, что форматов вывода данных может быть много, а php-скрипт, получающий данные из базы, как правило один общий". Да, вроде бы логично, но неужели не правильней будет дать базе данных уже экранированную строку, а не повторять эти действия вновь и вновь в шаблоне?
>>13664271) В mysql или какой-то другой БД. У mysql есть удобный интерфейс phpmyadmin, также можно работать через КС.2) Короче говоря, ты ставишь регистрирующемуся студенту куки которые записываются в том числе в базу данных.Потом каждого пользователя подключающегося к нашему приложению проверяем на наличие кук. Если они есть, проверяем их на сущестование в БД. При положительном результате производим нужные нам действия, например вывод ФИО данного студента.3.) Так надомимо сам делаю эту задачу
Аноны, где у вас в wamp лежит ваш проект? Просто по стандарту в апач/htdocs и дальше там внутри сам проект, а базу создаёте отдельно где-то на с:/data/db допустим?
>>13665201. Хочу больше денех;2. Хочу глубоко изучать язык, жить этим, хотелось бы выбрать что-то более серьезное, на что не жалко тратить жизнь.
>>1366410>Насколько это будет плюсом при приеме на работу? Или меня джависты будут обоссывать?Ты идёшь на ждуна, но ты с опытом чувак, это большой плюс!
>>13665411)Ну про mysql понятно. А как мне создать БД, чтобы записать код в Git? 2)Тоже не то. Есть команда GRANT, управляет доступом БД. Когда я читал, про эту команду, говорилось, что лучше создать через эту команду пользователя(одного), чтобы не входить в БД через root. Вот я и спрашиваю, а оно надо? Как это будет работать, если код будет запущен на другом компе?3)Ну тут можно было бы сказать, что это сделано для удобства. Но создавать массив объектов Student не затратно по памяти?
>>1366599>1)Ну про mysql понятно. А как мне создать БД, чтобы записать код в Git?Может сделать дамп базы (только структура, без данных студентов), например students_list.sql и добавить его в репозиторий? Учитель кажется писал об этом в конце задания.2.) Понял тебя, довольно интересный вопрос. Я работаю со своей БД через root и даже не задумывался об этом, будем ждать что скажет ОП или другие опытные ребята.3.) Нужно посмотреть как делают в фреймворках и сделать выводы.
>>1366427Ты можешь создавать у себя БД любым способом, но я бы советовал попробовать описать структуру руками в формате SQL (CREATE TABLE ...). Это поможет тебе вспомнить этот язык. Затем сделай дамп БД в формате .sql и положи в репозиторий, чтобы другие люди могли бы себе развернуть этот дамп. Не включай в дамп команды создания самой БД или пользователя, только команды создания таблиц и вставки данных. Так как у людей могут быть другие названия БД и имя пользователя.Пользователя люди создадут сами, просто опиши в README, в какой файл надо прописать параметры соединения с БД и где лежит дамп. Классы можно и не использовать, но я думал, с ними будет удобнее. Ты можешь попробовать сделать и без классов. >>1366516С экранированной строкой неудобно работать. Допустим, тебе надо проверить длину строки. Тебе придется ее разэкранировать для этого. То же самое, если ты захочешь ее сдампить в файл или отдать через API - придется сначала разэкранировать, чтобы восстановить исходные данные. А это создает сложности. Где должны экранироваться пришедшие от пользователя данные - в контроллере или в коде сохранения в БД? Функция валидации данных пользователя - что она принимает на вход, экранированные или неэкранированные данные? Функция, ищущая пользователя по id - в каком виде она вернет результат? Тебе надо по всему коду как-то расставлять комментарии, и тщательно проверять, что везде данные правильно преобразуются. Если где-то программист ошибся, то программа будет либо корежить данные, либо в ней появится уязвимость XSS.Вторая проблема - если мы посмотрим на шаблон, то там нет команд экранирования. Как понять, что тут нет уязвимости? Изучать весь код и все пути, по которым могут передаваться данные? А если завтра новый разработчик добавит новый код, и забудет там поставить экранирование? Глядя на шаблон, мы это не увидим. Хотя, эти проблемы мы могли бы решить с помощью ООП. Мы бы могли сделать объект SafeString, и у него несколько методов: getRaw(), getHtmlEscaped(), итд, возвращающих данные в нужном формате (и несколько статических конструкторов, позволяющий создать объект из обычной или экранированной строки). Это защитило бы нас от ошибок, так как мы сразу бы видели, какие данные получаются. Но это получается усложнение кода.
>>1366559плиз ответь на вопрос,т.к я обычный вкатывальщик, меня интересует 1 вопрос, твои ожидания по увеличению зп с переходом пхп на яву, на сколько %.
>>1366247Вообще, если ты очень хорошо разбираешься в Ларавеле, ты наверно, можешь найти способ сделать пакетную вставку. Но даже если и нет, я думаю, это не очень принципиально. Ведь обновление тестов делается не так часто и не создает большой нагрузки. Единственное, стоит делать его в рамках транзакции, чтобы при ошибке в БД не было наполовину созданного теста. Доктрина делает обновление в рамках транзакции, а вот как это в Ларавеле сделано, я не знаю. То есть я советую сначала беспокоиться о корректности кода, а потом уже о производительности. Ну и вставка одной транзакцией иногда работает быстрее.В твоем варианте, вместо ручной расстановки startTranscation/commit лучше использовать готовый метод: https://laravel.com/docs/5.8/database#database-transactionsТакже, ты зря делаешь получение и валидацию внутри транзакции. По моему, лучше сначала подготовить граф объектов (а в идеале еще и валидировать), а только потом внутри транзакции выполнить сохранение в БД. В твоем коде, тут 'body' => $question['body'] нет проверки, что $question это массив и там есть такой элемент. Не лучше ли использовать получение элемента по пути, как описано тут: https://laravel.com/docs/5.8/requests#retrieving-input или сделать проверку на наличие ключей? > Помню в доктрине можно было банально через сеттер сначала сохранить всё как ты хочешь, а если еще и cascade: persist стоит то вообще можно не напрягатьсяpersist() ничего не сохраняет. Она лишь передает сущность под управление Доктрины. Сохранение происходит по flush(): Доктрина сравнивает данные в управляемых сущностях с теми, что были загружены из БД, и формирует запросы INSERT/UPDATE/DELETE, выполняя их в одной транзакции. Вообще, я бы тебе советовал детально изучить ORM в Laravel, и в коде немного поковыряться, чтобы ты мог сравнивать Доктрину vs Eloquent и видеть плюсы/минусы.
>>1366102А напомни пожалуйста, зачем ты решил делать server-side rendering, если ты все равно поддерживаешь только браузеры с JS? Для изучения SSR? Просто обычно SSR используется либо для поддержки поисковых ботов, либо для пользователей без JS или для создания "облегченной" версии. У тебя же ситуация усложняется тем, что ты пытаешься на сервере имитировать localStorage. Если бы у тебя был сайт вроде инстаграма или твиттера, то там можно было бы сделать SSR для поисковиков, и не было бы никаких сложностей. А для страниц с авторизацией делать SSR чуть сложнее.То есть, я хочу понять, зачем и как используется SSR и что в этом случае можно сделать с хранилищем для сервера. Идея передавать кучу данных в куках мне не особо нравится. > Исправлю эту ошибку написав хорошие комментарии. Только, я не понимаю зачем, по-моему только сервису-обёртке хранилища можно, потому что это весьма не типичный подход. В остальном, разве это не очевидно что чем занимается?Да, комментарии нужны там, где назначение модуля не очевидно. > https://github.com/someApprentice/Crypter/issues/1Тут я кстати обратил внимание, что у тебя в стектрейсе обфусцированные имена функций. Лучше было бы в dev использовать неминифицированные файлы, с исходными названиями функций, а то сложно разбираться в функции с именем t._e(). Не знаю, где это настраивается, может быть, в angular.json (но я не уверен).Вообще, по моему мнению, в dev удобнее не склеивать файлы, а подгружать динамически (через что-нибудь вроде require.js или загрузчик для модулей ES6). Тогда в dev tools и в стек трейсах ты видишь файлы с теми же именами, как в оригинале, а не огромный main.js. Но я, увы, не знаю, легко ли это сделать в твоем случае.> У меня плохо с английским и написание комментариев утяжелит и замедлил разработку. Насколько важно их писать? Там, где я работаю, проблему решили написанием комментариев на русском языке. А так, я думаю, что важно. Пока ты работаешь один, ты многое можешь держать в голове. Но что, если придет новый человек, и ему надо разобраться с кодом? Тут важно не количество комментариев, а насколько легко разобраться в проекте. У тебя в README даже не описана общая архитектура, как все связано. Я не очень хорошо знаком со всеми этими компиляторами и средствами сборки, и я путаюсь от того, что там в корне лежит куча разных конфигов. Если бы в README было описано, как происходит процесс сборки и какой конфиг за что отвечает, думаю, было бы понятнее. > Эта функция нужна, чтобы обработать асинхронный обработчик запросов, который Эксрпресс не поддерживает (пока что?).Я имею в виду, что когда смотришь на код, абсолютно непонятно, зачем эта функция и что за магию она делает. Я не знал, поддерживает ли express возврат промисов из обработчиков (теперь знаю, что нет). А если бы там был комментарий - было бы понятнее. Ну и мне кажется, функцию, которая адаптирует асинх. функцию к использованию в express вполне можно называть адаптером.> Как я уже писал, куки нужны только для условий отображенийПо идее, эти данные на сервере проще получить из БД по токену авторизации. Значит, куки можно было бы не делать. То есть тут получается избыточность, как мне кажется.>> Функции json() он не нужен, это для проверки, что объект соответствует интерфейсу User? > Да, именно так. Это лишнее?Нет, я просто хотел спросить, зачем так сделано.> Почему нужно отдельную функцию валидации? Всё же и так в одну строчку делается. https://github.com/someApprentice/Crypter/blob/master/api/api.ts#L50Пока это не требуется, но если ты захочешь сделать проверку уникальности или другую проверку, требующую обращения к БД или сервисам, то из модели ты не сможешь это сделать, так как у нее нет ссылок на эти сервисы. И тебе понадобится внешняя функция валидации. > Я скажу на чистоту мой взгляд на это - Я не понимаю зачем нужно выносить такие функции в отдельные. Это функция понятна любому разработчику и он с первого взгляда поймет что происходит в ней. Почему нужно делать обёртку ради человекопонятного названия функции?Чтобы избежать дублирования кода. Чтобы не надо было в нескольких местах править одинаковый код. Ну и чтобы не писать код длинной портянкой, а разделять на отдельные части. > Я правда не понимаю, вот как эта функция будет выглядеть function createToken(u: User): Promise<string> - наверно так? > Всё исправлю. Здесь тоже в случае отсутствия нужно отдавать 404?По идее, да, можно так, если ты хочешь следовать идеям из REST. Либо можно возвращать JSON с true/false, если не хочешь. В идеологии REST (да и в стандартах HTTP что-то может быть), как я помню, URL соответствуют ресурсам, по типу: /user/123 - пользователь 123/book/some-book - какая-то книгаИ ты можешь слать к этим ресурсам запросы GET/POST/PUT/DELETE. Такая схема очень хорошо работает с кешем - ты можешь просто использовать URL ресурса в качестве ключа кеша. У REST могут быть и минусы, например, может потребоваться делать много запросов для получения всех данных (хотя это зависит от того, как спроектировано API). Потому не все используют REST. Например, у Ютуба в API для получения списка видео и одного видео используется один и тот же эндпойнт, просто с разными параметрами: https://developers.google.com/youtube/v3/docs/videos/list> Результат валидации либо вбрасывает ошибку, либо возвращает null(?). Эта ошибка обрабатывается в обработчике ошибокТам теряются подробности ошибки: if (err instanceof ValidationError) { return res.sendStatus(400); }Ну и довольно неочевидная штука, я бы не додумался лезть в обработчик ошибок смотреть код.
>>1366102> Так вы имели ввиду комментраии для модулей API, а не фронтенд приложения?Главное, чтобы в коде было проще разбираться. > Я же тоже "возвожу" данные пользователя в токен и проверяю совпадает ли возвращённый ответ, а именно кукисы, с ним. Ты в тесте просто скопировал код из серверного API. Если ты его неправильно написал, то ты мог сделать одинаковую ошибку и в серверном коде, и в тесте. Потому проверять работу функции нужно другим кодом, другим алгоритмом, а не тем же самым. Плюс, второй недостаток теста - ты в нем используешь знание о том, как устроена функция регистрации, как она генерирует токен. Если в алгоритме генерации токена что-то поменяется, тебе придется преределывать тест. Да и это нелогично, получатель токена ведь не должен знать, как он устроен внутри. Ему достаточно того, что этот токен дает доступк API, а как он устроен - не его дело. В твоем случае, если ты вызываешь API регистрации, логичнее всего проверить, что полученный токен можно использовать для доступа к защищенному API. Или хотя бы вызвать функцию проверки токена. Тесты проверяют требования (ТЗ) для API. У тебя в требованиях (если их сформулировать и записать пиьменно) вряд ли сказано, что "функция регистрации возвращает токен JWT такой-то структуры, зашифрованный таким-то ключом". Она возвращает просто токен, неважно какой. Знание о том, как он устроен, должно быть сконцентрировано в модуле для генерации и проверки токена, а остальным знать это не важно. Потому я и советовал вынести функции генерации и проверки токена в отдельный модуль авторизации.Принцип разделения ответственности здесь нарушается. Это легко видеть по тому, что код теста использует секрет, который нужен для генерации токена. Тесты ведь имитируют поведение пользователя API. А у него нет этого секрета. > Ну да, теперь вижу причину. Нужно проверить что пришедший токен в дешифрованном виде равен данным пользователя?Мне кажется, это будет плохая идея. Получатель токена не должен знать, как он устроен.> Я забыл сделать проверку, что пользователь добавился в БД и данные правильные. Это достаточное условие? Залогинивание проверяется в предназначенном для неё тесте, и там как раз сначала заполняется запись в БД.Я думаю, что удобнее тестировать API снаружи, не имея доступа к БД, а используя только само API. Это позволяет тесту не знать о том, как и где хранятся данные, и нам не придется переделывать тест при каких-то изменениях в БД. Это экономит наше время. Но на практике, иногда для удобства добавляют специальный тестовые методы в API. Например, ты мог бы сделать тестовый метод проверки наличия пользователя, или проверки токена. Но если можно обойтись без этого, то проще не использовать их, так как это лишний код. > Тяжело понять. Я с таким не сталкивался. Вижу что это как бы "эмулирует" жесткий диск в оперативной памяти. Как для этого настроить psql?Я почитал тут: - https://ru.wikipedia.org/wiki/Tmpfs- http://www.k-max.name/linux/ramdisk-ramfs-tmpfs-in-linux/ Лучше использовать tmpfs. По идее, ты создаешь диск и монтируешь его в папку одной командой (могут понадобиться права рута, но можно прописать этот диск в /etc/fstab с опцией монтирования пользователем). tmpfs не тратит память, если на виртуальном диске нет данных, более того, она по моему не создает структуру каталогов и служебные области, а как-то хранит файлы напрямую в памяти.После этого ты как-то настраиваешь psql, чтобы данные для тестовой базы хранились бы в папке с tmpfs. Я не знаю, как это сделать, но гугление выдает статьи вроде такой https://www.manniwood.com/postgresql_94_in_ram которая описывает создание отдельного инстанса Postgres с данными в tmpfs. > В sequlize-typescript можно указать директорию с моделями, но webpack транспилирует всё в один файл, и это ломается. Можно придумать какой-то костыль, например, читать список файлов и создавать файл "models.js", импортирующий все эти модели. Пока моделей мало, проще просто вручную перечислить. > Я считаю, что это вопрос доверия пользователя, оно есть в каких-то границах, и эти границы могут как и широки так и малы, т.е. я пытаюсь сказать что зависит от пользователя и его доверия. Я думаю, что для приложения с открытом кодом можно даже задуматься и о вайтлисте js.Проблему можно решить, выложив клиентский код в открытый доступ и собрав из него electron-приложение. Если мы сами собрали его из проверенных исходников, то никто не сможет подменить код клиента. > Можно, но мне наоборот кажется это не очень красивым, когда в URL что-то появляется. Хочу чтобы было так.Так это не сохраняет состояние. Если мы обновим страницу, или используем навигацию в браузере (вперед/назад), то email потеряется. Потому аргументы и хранят в URL. Тут тогда логичнее было просто сделать единую страницу регистрации/логина на одном роуте с двумя формами и скрывать одну из них. А email хранить в обычной переменной. И не понадобятся такие явно ненадежные костыли. > Проверить... что, например, вот для серверной части есть проверка, что вернулся StorageWrapper и всё работает, а для браузерной тоже аналогично. Это не нужно?Проверять это логичнее, пытаясь что-то туда сохранить, а не проверкой, к какому классу относится объект. > У роутеров WAMP'а на Node, нету возможностей для аутентифекации и авторизации соединения, и документации. Вышеупомянутая платформа развита лучше других.Да, но это можно добавить. А в случае с Питоном, ты не сможешь вызывать функции из приложения Node, тебе придется возможно дублировать их, или настраивать взаимодействие. Я не против такого варианта, но готовься к сложностям. И надо правильно спроектировать взаимодействие между питоновским и нодовским приложениями. Это уже почти микросервисы получаются со всеми их плюсами и минусами.
Сап двощь, как сделать так чтобы между словами всегда оставался один символ замены, в данном случае | ? Ищу пробелы или % и хочу их поменять на один пробел, чтобы потом удобно было разбить массив по этому пробелу, в регулярках не силен
>>1366730Привет ОП. В ларавеле я пока не особо хорошо разбираюсь, складывается ощущение что всё почти идеально пока у тебя какая-то типичная веб-задача, немного навязывается стиль написания кода, но мне как бы и норм, пока что хз какие бест практис и можно доверять фреймворку. Готовый метод транзакции кстати делает абсолютно тоже самое что и у меня, только через анонимную функцию. Не раз замечаю что на одну функцию может идти несколько алиасов, просто чтобы было чуть более интуитивно. А граф объектов у меня уже провалидирован, на том скрине не видно, но это не обычный Request, а ларкин FormRequest, обёртка, которая при создании валидирует входные данные на правила, как на скрине, и если валидация фейлится то в контроллер даже не пускает. Я её еще не доделал правда.Я сделал объект Attempt, который представляет собой попытку прохождения теста, у него может быть два глобальных состояния, в процессе прохождения и завершен. Так вот я пока что не уверен что делать, когда клиент пытается завершить прохождение теста, но при этом присылает неправильные данные, например входной массив будет иметь вид [ключ_вопроса => ключ_варианта_ответа], клиент присылает свои варианты, но оказывается что указанный вопрос не имеет такого ответа, он относится или к другому вопросу, или его вообще не существует, айди ответа какой-то левый. Мне в таких случаях отправлять обратно что-то в стиле "Вы там у себя разберитесь, а потом перезвоните" и на этом всё или сразу завершать прохождение, помечать как зафейленное, при счете баллов можно например просто притвориться что пользователь банально не ответил на вопрос? То же относится и к отношению Тест -> вопросы в принципе.
>>1366798Покажи для начала, что ты уже сделал. Потому что твой скрин говорит о том, что ты ленивая хуйлуша.
Аноны, решаю задачу про проверку телефонов из учебника. Объясните мне пжалста, почему номера со скобками с пробелами рядом (вроде 8 (800) ...) определяются как неправильные? При этом просто с пробелами (8 8 00..) или со скобками (8(800)...) или даже со скобками и пробелами но не рядом (8 8(0)0 ...) - все нормально?https://ideone.com/2ro2xS
>>1353705 (OP)Антоны, мне нужно написать веб-морду для управления кое-каким сервисом. Основная функциональность - это внесение правок в конфиги, которые лежат на сервере, перезапуск этого сервиса ну и снятие парочки метрик с него.Сейчас это делают написанные мной скрипты на баше, но хочу чего-то более юзер-френдли для других юзеров.Ну и с авторизацией и разграничением прав, конечно (почти наверняка это будет в виде ldap учеток)С программизмом я никак не связан, писал только скрипты на баше. Питон не знаю, да. Посоветуйте какую-нибудь книжку (а лучше видеокурс), чтобы быстро вкатиться в какой-нибудь простой пэхапэ-фреймворк. Думаю, что идеально было бы, если б учили сразу пилить какую-нибудь веб-морду/cms.
247-340>>1366549На линуксе обычно проекты кладут в /var/www/название. На windows - можно сделать отдельную папку на каком-нибудь диске. Например, c:\projects\. В apache/htdocs обычно лежит тестовая страница самого апача. >>1366879Если посмотреть на твою регулярку, то она написана примерно так: - сначала идет 8- затем 1 или больше скобок- затем 1 или больше пробелов- затем цифраТаким образом, между 8 и следующей цифрой может быть последовательность вида "скобка, пробел". Тебе лучше исправить регулярку, чтобы там между цифрами могли бы идти дополнительные символы в любом порядке. Чтобы написать "любой символ из указанных", можно использовать квадратные скобки, а потом добавить к ним звездочку.>>1366855> Так вот я пока что не уверен что делать, когда клиент пытается завершить прохождение теста, но при этом присылает неправильные данные, например входной массив будет иметь вид [ключ_вопроса => ключ_варианта_ответа], клиент присылает свои варианты, но оказывается что указанный вопрос не имеет такого ответа, он относится или к другому вопросу, или его вообще не существует, Проще всего приравнять это к отсутствию ответа (отстутствию ключа в массиве). Можно еще в лог варнинг писать, вдруг это фронтенд-специалист накосячил и не те данные шлет.
>>1363045Вообще, проще наверно было бы совместить Constraint и ConstraintValidator. Не очень понятно, зачем делать 2 отдельных класса. В Симфони одна из причин - это использование аннотаций, Constraint это аннотация, потому оно сделано отдельным классом. В более простой системе разделять здесь код на 2 класса может быть, нет необходимости. Код в классе Constraint в конструкторе немного усложнен. Не очень понятно, зачем присваивать свойствам значения из массива, если значения по умолчанию можно просто прописать при объявлении свойства.> Кстати про симфони, в объектах-наследниках Constraint открытые публичные свойства. Получается бывают ситуации, когда инкапсуляцией можно пренебречь?Там скорее всего аннотации, которые никто руками не создает, а которые создаются при разборе кода. А так, иногда делают объекты из одних публичных свойств. Видимо, решили, что инкапсуляция там не требуется.>>1363410Наверно можно переименовать.> Что если в find() передавать не кучу параметров, а объект с параметрами класса SearchOptions?Вполне хорошая идея. Я думаю, что этот объект может пригодиться и в других местах, например, при генерации ссылок для пагинации. >>1364961Я не знаю, есть ли там DDD или нет, но есть Magento - это e-commerce проект.
>>1363656У тебя в регулярке написано [0-9]{10}, а это значит "10 идущих подряд цифр", без каких-то символов между ними.> Как я понял, то, что внутри (этих) скобок считается отдельным блоком, куда можно накидать кучу параметров, написанных [тут]. Квадратные скобки [abc] - обозначают "ровно один любой символ из набора a, b или c"Круглые скобки () используются для группировки, и позволяют применять квантификаторы ко всей группе. Сравни: abc+ - здесь плюс применяется только к букве c и регулярка ищет строки abc, abccc, abcccc. a(bc)+ - здесь плюс применяется к группе (bc) и регулярка ищет строки abc, abcbc, abcbcbcbc.>>1363352Да. Ты разбиваешь данные на N блоков, а затем просто запускаешь несколько PHP скриптов параллельно, передавая им границы диапазоны. Ну например: php script.php 1 199 & php script.php 200 399 & php script.php 400 1000 &waitЗдесь & - это синтаксис линуксовой оболочки bash, который запускает команду в фоновом режиме. А команда wait ждет завершения всех фоновых программ. Но здесь может быть проблема. Если ты используешь транзакции (а их стоит использовать) , то они блокируют данные, с которыми работают, и если нескольким скриптам надо работать с одними и теми же данными, то может так получиться, что работать будет только один скрипт, а другие будут ждать освобождения блокировки.
>>1363289В случае докера, данные обычно не помещают внутрь образа. Докер часто используют только для того, чтобы засунуть программу + ее конфиг + зависимости (библиотеки) внутрь контейнера. То есть у тебя будет контейнер с nginx, с php-fpm, с mysql и docker-compose, чтобы их всех одновременно запускать. Но картинки и файлы таблиц базы данных не хранятся в этих контейнерах.Более того, если у тебя есть dev сервер, тебе не требуется на нем держать все картинки с продакшена. Зачем? Пусть они на продакшене и лежат. Обычно деплоят только код. Изменения в БД деплоят как миграции. Если у тебя докер, то наверно придется заморочиться со сборкой и выгрузкой образов, но если их содержимое не изменилось, то они будут быстро создаваться на основе закешированных данных. По поводу деплоя. Самый простой вариант, для простых сайтов - это деплой через rsync (команда копирования файлов) или git. То есть ты просто обновляешь скриптом файлы на сервере. Минус - в процессе деплоя есть момент, когда часть файлов уже обновлена, а часть еще нет и в этот момент сайт может выдавать ошибки.Сине-зеленый деплой ( https://habr.com/ru/post/309832/ ) - это когда у тебя 2 папки для сайта. Сайт работает из первой папки, а деплой ты делаешь во вторую папку, и после завершения переключаешь настройку на веб-сервере, чтобы сайт отдавался теперь из второй папки. А следующий деплой делаешь в первую папку. В случае с докерами и сине-зеленым деплоем, ты можешь сделать деплой кода в новую папку. Поднять там все докеры, используя другие номера портов (php-fpm, mysql). И затем переключить нгинкс на использование кода из новой папки. А старые докеры остановить. Это дает бесшовные обновления без даунтайма. Если в момент переключения работали скрипты из старой папки, то они спокойно завершают свою работу используя старый код, а все новые запросы идут в новую папку. Единственная проблема может быть с долгоживущими cli-скриптами (за время их жизни код в папке, из которой они запущены, мог обновиться), хотя на практике это маловероятно.
>>1363131Скорее всего ошибка при выборке данных, например в SQL запросе. Ты должен после каждой команды работы с mysqli проверять, что она не вернула null или false. Или же настроить выброс исключений при ошибке и тогда проверять не придется. Также, почитай про шаблоны и про XSS: - https://github.com/codedokode/pasta/blob/master/php/templates.md- https://github.com/codedokode/pasta/blob/master/security/xss.md>>1363056[+7|8] значит "ровно один любой символ из набора: +, 7, | или 8">>1362965Если ресурсов сервера хватает, то можно держать на одном сервере. Разносят, чтобы например можно было запустить несколько отдельных php-серверов, и они бы не отъедали CPU у базы данных.
Свежее интервью с сore-разработчиком Yii - Александром Макаровым: https://youtu.be/uHHfnZDRHs8?t=109Слушать всем, кто сомневается брать ли PHP сейчас, полезно послушать.
Задача "Grammar Nazi" $text = "Жырный тролль сдесь.зделал координально срач а модеры?смотрят но всем плевать";$regexp = '/([.,;:!?](\\S))|жы|шы|координально|сдесь|зделал|([^,] (а|но) )/ui';$match = [];if (preg_match_all($regexp, $text, $match) > 0) { foreach ($match[0] as $number => $mistake) { $number++; echo "{$number}-я ашипка - {$mistake}\n";}}выводит1-я ашипка - Жы2-я ашипка - сдесь3-я ашипка - .з4-я ашипка - координально5-я ашипка - ч а 6-я ашипка - ?с7-я ашипка - т ноОбъясните мне, почему не видит слово "зделал"?
В прошлый раз никого не нашел, репост. Нужен толковый чувак, веб-разработчик широкого профиля (фуллстак).Удаленка, полностью свободный график, минимум контроля, отсутствие корпошизы (образование, внешний вид, пол и прочее тоже пофиг). Можно делать быстро и ебланить большую часть дня (не перегружаю работой), можно делать дольше, если что-то не умеешь, подождем.Языки программирования: PHP (на сервере 7.2), JS, HTML/CSS, SQL (на сервере MySQL или MariaDB).Фреймворки: Yii, jQuery.Технологии и инструменты: scss(sass), gulp, git, PHPStorm.Нужен опыт работы над крупными yii-проектами (крупнее лаба10.пхп и сокращателя ссылок).ЗП 40-50 в месяц (на руки). Если вы крутой и с ходу хотите больше (более-менее адекватно предложению) - говорите, сколько.Задачи: доработка существующего продукта, который, по идее, написан неплохо (MVC, вся фигня), с нынешним разработчиком познакомлю, введем в курс дела.[email protected]
>>1367474Вряд ли, проект уже имеющийся на yii написан, там куча строк кода, и его надо развивать, дорабатывать, фреймворк активно используется. Если ты сможешь быстро вкатиться в йиишные фичи (всякие там актив рекордс, актив форм, гридвью, контроль доступа, миграции) - то в принципе вариант.
Аноны, почему, черт возьми, этот код на идеоне не запускается?!!! https://ideone.com/Nl5UmE Я, блядь, полночи бился, выискивая ошибку в каждой букве, только чтобы обнаружить, что на phptester.net или на runphponline.com он прекрасно работает! Какого хрена?! Ну и проверьте, что ли, как я вообще решил эту задачу про палиндромы. Нормальный код?
>>1366731>А напомни пожалуйста, зачем ты решил делать server-side rendering, если ты все равно поддерживаешь только браузеры с JS? Для изучения SSR? >>Просто обычно SSR используется либо для поддержки поисковых ботов, либо для пользователей без JS или для создания "облегченной" версии. У тебя же ситуация усложняется тем, что ты пытаешься на сервере имитировать localStorage. Если бы у тебя был сайт вроде инстаграма или твиттера, то там можно было бы сделать SSR для поисковиков, и не было бы никаких сложностей. А для страниц с авторизацией делать SSR чуть сложнее.>>То есть, я хочу понять, зачем и как используется SSR и что в этом случае можно сделать с хранилищем для сервера. Идея передавать кучу данных в куках мне не особо нравится. >А напомни пожалуйста, зачем ты решил делать server-side rendering, если ты все равно поддерживаешь только браузеры с JS? Для изучения SSR? Для ускорения загрузки приложения. И для поддержки поисковых ботов, конечно.>То есть, я хочу понять, зачем и как используется SSR и что в этом случае можно сделать с хранилищем для сервера. Идея передавать кучу данных в куках мне не особо нравится. Почему не нравится? Это же тоже самое что запрос к серверной части приложения и его шаблонизатору, для которого нужны куки для отображения, той или иной информации относительно отдельного пользователя. >> https://github.com/someApprentice/Crypter/issues/1>>Тут я кстати обратил внимание, что у тебя в стектрейсе обфусцированные имена функций. Лучше было бы в dev использовать неминифицированные файлы, с исходными названиями функций, а то сложно разбираться в функции с именем t._e(). Не знаю, где это настраивается, может быть, в angular.json (но я не уверен).>>Вообще, по моему мнению, в dev удобнее не склеивать файлы, а подгружать динамически (через что-нибудь вроде require.js или загрузчик для модулей ES6). Тогда в dev tools и в стек трейсах ты видишь файлы с теми же именами, как в оригинале, а не огромный main.js. Но я, увы, не знаю, легко ли это сделать в твоем случае.У меня сейчас получилось сгенерировать не минифицированные файлы, убрав просто флаг --prod из команды сборки ng build --prod && ng run Crypter:server && webpack --config webpack.server.config.jsДобавил новый стактрейс: https://github.com/someApprentice/Crypter/issues/1#issuecomment-474728547>Тогда в dev tools и в стек трейсах ты видишь файлы с теми же именами, как в оригинале, а не огромный main.js.Разве и так в dev tools нельзя посмотреть все файлы даже после компиляции webpack'ом?pic-1>> У меня плохо с английским и написание комментариев утяжелит и замедлил разработку. Насколько важно их писать? >>Там, где я работаю, проблему решили написанием комментариев на русском языке. А так, я думаю, что важно. Пока ты работаешь один, ты многое можешь держать в голове. Но что, если придет новый человек, и ему надо разобраться с кодом? Тут важно не количество комментариев, а насколько легко разобраться в проекте. >>У тебя в README даже не описана общая архитектура, как все связано. Я не очень хорошо знаком со всеми этими компиляторами и средствами сборки, и я путаюсь от того, что там в корне лежит куча разных конфигов. Если бы в README было описано, как происходит процесс сборки и какой конфиг за что отвечает, думаю, было бы понятнее. Если честно, я сам путаюсь от такого количества конфигов, и я сам первый раз сталкиваюсь с этими всеми компиляторами и средствами сборки. Это бесконечная яма если я буду и это ещё изучать во всех тонкостях. Мне нужно изучить Python, мне нужно изучить crossbar.io (сегодня собираюсь писать действительный код), мне нужно изучить реактивное программирование, мне нужно написать само приложение, и на каждом шажке всплывает ещё 1000 подводных камней, которые нужно изучать. Я так никогда не закончу эту приложение.Простите, что противлюсь вашим наставлениям - я исправлю это после всего... А пока, всё что нужно знать о сборке, тому кто хочет протестировать приложение, нужно всего лишь набрать npm run build.Комментарии в коде для обёртки я обязательно добавлю.>> Эта функция нужна, чтобы обработать асинхронный обработчик запросов, который Эксрпресс не поддерживает (пока что?).>>Я имею в виду, что когда смотришь на код, абсолютно непонятно, зачем эта функция и что за магию она делает. Я не знал, поддерживает ли express возврат промисов из обработчиков (теперь знаю, что нет). А если бы там был комментарий - было бы понятнее. Ну и мне кажется, функцию, которая адаптирует асинх. функцию к использованию в express вполне можно называть адаптером.Хорошо, я переменную функцию и добавлю к ней более вразумительный комментарий.>> Как я уже писал, куки нужны только для условий отображений>>По идее, эти данные на сервере проще получить из БД по токену авторизации. Значит, куки можно было бы не делать. То есть тут получается избыточность, как мне кажется.Да, можно написать и серверный код в Angular-приложении за счет проверки на isPlatformServer(), но для этого нужно будет... хм, внутри этой проверки делать отдельные импорты библиотек (sequelize, dotenv, весь серверный код) чтобы они не тянулись в браузерной части. Мне не нравится этот стиль написания кода, так ещё не понятней будет, и к тому же нужно будет писать другую абстракцию - ничего от этого не выигрывается и только теряется время на написание дополнительных комментариев, увеличения кода, роста количества файлов, и что значит сложности в изучении проекта.Я вижу вашу мысль об избыточности и понимаю, что это связанно с тем что есть и localStorage и кукисы, но почему бы и нет? Это нормально использовать и кукисы и localStorage. Что мешает этому? Это же машинное хранилище, и им нужно пользоваться.Можно посмотреть на это так - сервер рендерит страницу с помощью кук, а js приложение подхватывает полученную страницу и уже работает с localStorage. То с чем и должен работать js, не получая доступ к кукам. Разве это не плохо что js имеет доступ к кукам?>> Почему нужно отдельную функцию валидации? Всё же и так в одну строчку делается. https://github.com/someApprentice/Crypter/blob/master/api/api.ts#L50>>Пока это не требуется, но если ты захочешь сделать проверку уникальности или другую проверку, требующую обращения к БД или сервисам, то из модели ты не сможешь это сделать, так как у нее нет ссылок на эти сервисы. И тебе понадобится внешняя функция валидации.А, хорошо. Конечно, для таких случаев я бы написал сервис валидации.>Чтобы избежать дублирования кода. Чтобы не надо было в нескольких местах править одинаковый код. Ну и чтобы не писать код длинной портянкой, а разделять на отдельные части. В данный момент тогда лучше сделать сервис с методом .login(...), потому что, пока что, код дублируется в двух местах и нужен как раз для залогинивания. Думаю, всё таки нужно написать сервис Authorizer.>> Я правда не понимаю, вот как эта функция будет выглядеть >>function createToken(u: User): Promise<string> - наверно так? Я выше написал, что для этой функции нужно передать коллбэк и в итоге получится тоже самое, либо нужно делать отдельную функцию для каждого случая createTokenForLogin(u: User) Promise<string>, createTokenForSomething(smth: any) Promise<string>... Может правда лучше разбить сам код на функции, и там пользоваться функцией создания токена как есть?>> Результат валидации либо вбрасывает ошибку, либо возвращает null(?). Эта ошибка обрабатывается в обработчике ошибок>>Там теряются подробности ошибки: >>if (err instanceof ValidationError) {>return res.sendStatus(400); >}>>Ну и довольно неочевидная штука, я бы не додумался лезть в обработчик ошибок смотреть код. А как иначе нужно делать? Делать блоки try/catch каждый раз и каждый раз повторять один и тот же код? Разве в PHP на Slim'е не была такая логика обработки ошибки?
>>1366734>> Я же тоже "возвожу" данные пользователя в токен и проверяю совпадает ли возвращённый ответ, а именно кукисы, с ним. >>Ты в тесте просто скопировал код из серверного API. Если ты его неправильно написал, то ты мог сделать одинаковую ошибку и в серверном коде, и в тесте. Потому проверять работу функции нужно другим кодом, другим алгоритмом, а не тем же самым. >>Плюс, второй недостаток теста - ты в нем используешь знание о том, как устроена функция регистрации, как она генерирует токен. Если в алгоритме генерации токена что-то поменяется, тебе придется преределывать тест. >>Да и это нелогично, получатель токена ведь не должен знать, как он устроен внутри. Ему достаточно того, что этот токен дает доступк API, а как он устроен - не его дело. >>В твоем случае, если ты вызываешь API регистрации, логичнее всего проверить, что полученный токен можно использовать для доступа к защищенному API. Или хотя бы вызвать функцию проверки токена. >>Тесты проверяют требования (ТЗ) для API. У тебя в требованиях (если их сформулировать и записать пиьменно) вряд ли сказано, что "функция регистрации возвращает токен JWT такой-то структуры, зашифрованный таким-то ключом". Она возвращает просто токен, неважно какой. Знание о том, как он устроен, должно быть сконцентрировано в модуле для генерации и проверки токена, а остальным знать это не важно. Потому я и советовал вынести функции генерации и проверки токена в отдельный модуль авторизации.>>Принцип разделения ответственности здесь нарушается. Это легко видеть по тому, что код теста использует секрет, который нужен для генерации токена. Тесты ведь имитируют поведение пользователя API. А у него нет этого секрета. >Плюс, второй недостаток теста - ты в нем используешь знание о том, как устроена функция регистрации, как она генерирует токен. Если в алгоритме генерации токена что-то поменяется, тебе придется преределывать тест. У меня в тесте с логином, я сначала добавляю пользователя в БД, а потом проверяю само залогиневание. То есть я здесь тоже использую знание о том как устроенна функция. А что если алгоритм сохранения пользователя тоже поменяется? Здесь тоже ошибка? Как тогда быть? Нужно писать какую-то абстракцию над БД во время тестов? Значит, нужно сначала вызвать функцию регистрации?>Принцип разделения ответственности здесь нарушается. Это легко видеть по тому, что код теста использует секрет, который нужен для генерации токена. Тесты ведь имитируют поведение пользователя API. А у него нет этого секрета. Мне тяжело понять лежащий глубокий смысл в таких принципах как SOLID. Я похоже нарушил один из его принципов. Напишу здесь чтобы не забыть - что мне нужно детальнее ознакомиться с примерами этих принципов чего я не делал. В целом, я понял свою ошибку, что я тестировал код не то как это сделал бы человек, а проверки на то что вернёт машина. Я понял, что нужно писать код теста так, чтобы с сымитировать тестирование функционала живым человек на действительном сайте.Всё исправлю.>Но на практике, иногда для удобства добавляют специальный тестовые методы в API. Например, ты мог бы сделать тестовый метод проверки наличия пользователя, или проверки токена. Но если можно обойтись без этого, то проще не использовать их, так как это лишний код. Можно проверить можно ли залогиниться/разлогиниться после этих методов.>> В sequlize-typescript можно указать директорию с моделями, но webpack транспилирует всё в один файл, и это ломается. >>Можно придумать какой-то костыль, например, читать список файлов и создавать файл "models.js", импортирующий все эти модели. Пока моделей мало, проще просто вручную перечислить. Я плохо разбираюсь как настраивать webpack. В проблемах этой библиотеке, мне сказали, что нужно написать плагин для этого. Буду пока вручную перечислять, хоть и знаю что это плохо.>> Я считаю, что это вопрос доверия пользователя, оно есть в каких-то границах, и эти границы могут как и широки так и малы, т.е. я пытаюсь сказать что зависит от пользователя и его доверия. Я думаю, что для приложения с открытом кодом можно даже задуматься и о вайтлисте js.>>Проблему можно решить, выложив клиентский код в открытый доступ и собрав из него electron-приложение. Если мы сами собрали его из проверенных исходников, то никто не сможет подменить код клиента. Вот именно. Код и так будет в открытом доступе. Только, к сожалению, не каждый пользователь сможет сделать это самостоятельно. Даже я думаю, что это не так просто, как вы говорите.Что вы знаете о других инструментах созданий приложений? Я знаю о таком инструменте как React Native и нагуглить NativeScript, но учитывая свой печальный опыт с React'ом, я боюсь что с ним тоже будет не всё так гладко. Ну конечно же, это ни секрет что JS медленный. Вы знаете что-нибудь об их этих инструментах и как легко с ними будет работать? После ваших слов, создаётся ощущение, что в случае с Electorn'ом это действительно будет достаточно склонировать репозитирий и собрать из него десктопное приложение - и мне интересно, будет ли здесь всё так же просто?>> Можно, но мне наоборот кажется это не очень красивым, когда в URL что-то появляется. Хочу чтобы было так.>>Так это не сохраняет состояние. Если мы обновим страницу, или используем навигацию в браузере (вперед/назад), то email потеряется. Потому аргументы и хранят в URL. >>Тут тогда логичнее было просто сделать единую страницу регистрации/логина на одном роуте с двумя формами и скрывать одну из них. А email хранить в обычной переменной. И не понадобятся такие явно ненадежные костыли. Мне кажется так удобно будет для каждого пользователя. Например, мы же не можем знать заранее зарегистрирован человек или только хочет зарегистрироваться, и всё что ему нужно это просто ввести свой email и дальше система определит, что он хочет сделать. Я такое видел только в моей бывшей любимой соц.сети - tumblr'е, но сейчас они убрали эту функцию. Я считаю это очень удобным и типо приветливым.>> Проверить... что, например, вот для серверной части есть проверка, что вернулся StorageWrapper и всё работает, а для браузерной тоже аналогично. Это не нужно?>>Проверять это логичнее, пытаясь что-то туда сохранить, а не проверкой, к какому классу относится объект. Понимаю, исправлю.>> У роутеров WAMP'а на Node, нету возможностей для аутентифекации и авторизации соединения, и документации. Вышеупомянутая платформа развита лучше других.>>Да, но это можно добавить. А в случае с Питоном, ты не сможешь вызывать функции из приложения Node, тебе придется возможно дублировать их, или настраивать взаимодействие. Я не против такого варианта, но готовься к сложностям. И надо правильно спроектировать взаимодействие между питоновским и нодовским приложениями. Это уже почти микросервисы получаются со всеми их плюсами и минусами.Можно вызывать функции приложения из Node с помощью Remote Procedure Calls паттерна реализуемым WAMP.Я не знаю, о каких функциях приложения Node вы говорили, но у crossbar.io есть возможность сделать компонент(?) и на другом языке https://crossbar.io/docs/Guest-Configuration/?highlight=node.js
>>1367587Что ты там выискивал, если тебе прямым текстом говорится, в чем ошибка? Похоже, что у них похапе без расширения ext-mbstring
>>1367607PHP состоит из "ядра" и "расширений", которые добавляют в него дополнительные возможности. Часто расширения поставляются в комплекте с PHP и ты можешь даже не заметить, что ты их используешь.Увидеть список основных расширений, и какие в них есть функции, можно в мануале: http://php.net/manual/ru/funcref.phpКроме них, бывают еще сторонние расширения.Про установку расширений можно почитать тут: http://php.net/manual/ru/install.pecl.php Под Windows обычно ты просто скачиваешь расширение, кладешь в папку и указываешь его в конфиге.
>>1367648Народ по полгода вкатывается, а тут Васян пришёл - быстренько подайте ему супер-курс по двухдневному вкату.Прост нахуй иди.
Привет, анончики, на связи вкатывальщик. Желаю задачи из учебника в шапке, почему-то залип на первой же, связанной с циклами.Неожиданно нашел решение, но мне кажется оно какое-то... Ну не то оно какое-то. Пните, скажите как надо было сделать красивее.https://ideone.com/N2Zr7R
>>1367657Благодарю! Пока что эта больше всего времени заняла, хотя решалась в одно действие, но тем приятнее все же было победить.
>>1367239>Посоветуйте какую-нибудь книжку (а лучше видеокурс), чтобы быстро вкатиться в какой-нибудь простой пэхапэ-фреймворкДокументация к Laravel\Symphony\etc.Следующий.
>>1367653>супер-курс по двухдневному вкатуКто тебе сказал, что по двухдневному?>Народ по полгода вкатываетсяПолгода вкатывается во что? В запись файлов на пхп? СоболезнуюКак тебя в пр занесло, ты же элементарно логически мыслить не можешь.>>1367662>Документация к Laravel\Symphony\etc.Документация == видеокурс? Похоже, у тебя с восприятием еще хуже, чем у антона выше, лол или ты просто хреново умеешь читать представляю, какой у тебя код>>1367655Тосто и тупо тут, видимо, все аноны такие же тупые?
>>1367673Ага, я понял, поэтому сменил тему разговора со своего реквеста на обсуждение тупости местных анонов
>>1367679>Давай дальше развлекай.Хорошо>запись файлов на пхпА ты в своих проектах на пхп запись в файл, видимо, не используешь, дегрод? Но я не удивлюсь, если ты еще и чтение из файла не осилил.>видеокурсНейрофизиологи давно доказали, что обучение через восприятие визуального контента более эффективно. Тем более, нормальные люди смотрят уроки/лекции на скорости х2 и выше. Но тут надо, конечно, обладать достаточно развитым абстрактным мышлением.>называет кого-то тупымВсегда приятно тупого назвать тупым, ведь он от этого начинает бомбить. А нормальному человеку всегда приятно, когда страдает тупой дегенерат. Да и как еще можно назвать человека, который думает, что любой курс для быстрого вката это именно "супер-курс по двухдневному вкату".Пиши, если тебя что-нибудь еще заинтересует
>>1367685Парни, подгоните этому гению 15 часовой курс лекций по конкатенации строк в пыхе, у кого есть.А ещё тут где-то анон ходил, с 9 часовым курсом по регуляркам.
>>1367690>Парни, подгоните этому гению 15 часовой курс лекций по конкатенации строк в пыхе, у кого есть.Опять сказал какую-то херню и даже не понял, что сказал хернюДержу пари, ты этот самый фантазер >>1367653>А ещё тут где-то анон ходил, с 9 часовым курсом по регуляркам.Снова нерелевантная хуйня. Я бы на твоем месте прошел курс по мат.логике от мфти
Что-то вспомнилось недавнее - из треда айтишников. Там аналогичного идиота вычислили, с похожим стилем постов как у этого >>1367697. Уволили ещё которого за то, что народ хуесосил и вообще токсичное чмо.Ты смотри, пацан, такая манера общения быстро прилипает. Сам не заметишь как в реале хамить людям начнёшь, а там в щи быстро прилетит административно или физически.
>>1367769>Сам не заметишь как в реале хамить людям начнёшь, а там в щи быстро прилетит административно или физически.В реале я с такими мудаками обычно не сталкиваюсь. А если сталкиваюсь, то они никогда не входят в круг моего постоянного общения, очевидно же. Ну а незнакомым людям на улице я и не хамлю без причины, так что за щи не беспокойся>вообще токсичное чмоПроиграл с адеквата:>токсичное чмо>>1367655 >>1367653 >>1367662
>>1367780>Проиграл с адеквата:Это разные люди, токсичный шизик. Ты сам не понимаешь чего несёшь. Не позорься и замолкни лучше.
>>1367786>Это разные люди, токсичный шизик. А где я сказал о том, что это один и тот же человек? Я намекнул на то, что токсичная мразь не я, а они.>Ты сам не понимаешь чего несёшь.Нет, я прекрасно понимаю.>Не позорься и замолкни лучше.Я пока еще ни разу не опозорился, никаких противоречий в моих словах нет, это твои маняпроекции.
>>1367794>токсичная мразь не я, а ониТак-то тебе вполне нормально посоветовали. Хочешь по-быстрому, то читай доки. Не поймёшь 80% так как у тебя базы нет так как ты с программизмом никак не связан, но ты сам просил "чтобы быстро вкатиться", а не нормально - значит страдай.По курсам от "Профита" не скажу - не смотрел.
>>1367803Ага, ясно>>1367803>По курсам от "Профита" не скажу - не смотрел.А, такой курс на самом деле есть, лол? Вычеркиваю >>1367655 из списка мудаков
>>1367836Да, название дурацкое, но это самый понятный курс по mvc из всех что я посмотрел.https://pr-of-it.ru/courses/php-2.html
Аноны, пытаюсь сделать большие буквы после знака препинания и пробела. $regexp = '/([.,!?])( )([а-я])/u';$text = preg_replace($regexp, '$1$2mb_strtoupper($3)', $text);Однако нихера, программа вместо перевода $3 в верхний регистр просто выводит mb_strtoupper буквально. Как сделать так, чтобы прога воспринимала это как команду?
>>13679141. функция в строке работать не будет;2. $3 - эту хуйню в строке ждет функция preg_replace, для mb_strtoupper - она нихуя не значит, поэтому сделать так, как ты задумал нельзя. Другие способы ищи
>>1367914Нужно использовать preg_replace_callback. Ты создаешь функцию, передаешь ее и preg_replace_callback вызывает ее на каждое совпадение с регуляркой и спрашивает, на что заменить текст.
Анчоусы, объясните нубу или направьте на доки, почему здесь $elem[0], это индекс массива или что?P.s это задачка.>Ведите на экран только те числа из массива, которые начинаются на цифру 1, 2 или 5.
>>1368056>$elem[0], это индекс массива или что?Да, индекс массива.Но в твоём примере цикл foreach разбирает массив на элементы, возвращая их уже без индекса. То есть у $elem нет индекса, это тупо переменная со значением.А если интересно, то у каждого элемента твоего массива, значения проставляются автоматически по порядку добавления. У первого добавленного элемента будет 0, у второго 1 и т.д.Вот как оно выглядит$arr = [0 => 10, 1 => 20, 2 => 30, 3 => 50, 4 => 235, 5 => 3000];И да, не нужно числа оборачивать в кавычки '' из-за этого они становятся строками.
>>1368065Огромное спасибо, я довольна дотошный, за это отдельное спасибо.>И да, не нужно числа оборачивать в кавычки '' из-за этого они становятся строками. P/sПросто не смог найти больше подробностей, по поводу>Но в твоём примере цикл foreach разбирает массив на элементы, возвращая их уже без индекса. То есть у $elem нет индекса, это тупо переменная со значением.
>>1368056Намекну. Чтобы отрезать первую цифру от цельного числа, можешь использовать функцию substr($number, 0, 1).Помог как смог.
>>1368069>substrСпасибо, но она со строками работает, а я сделал ошибку, анон выше правильно заметил, я числа в строку превратил, зачем? да хуй знаетдумал всегда надо оборачивать в ковычки, любые данные.
>>1368067>Просто не смог найти больше подробностей, по поводуhttps://ideone.com/WAO6TsПримерно так оно работает, короче с опытом придёт понимание.>Спасибо, но она со строками работаетСоображаешь, но она может приводить числа к строке и успешно их считать. Хотя при строгом сравнении === это не прокатывает.
>>1368088>Примерно так оно работает, короче с опытом придёт понимание.Надеюсь, я понял как происходит индексация элементов массивавсегда с 0, но можно это переделать за счет удаления , я просто не мог понять, как скрипт понимает, что надо выдергивать определенные элементы из массива, еще и с определенными условиями.P/s. https://ideone.com/WAO6TsЯ посмотрел, да красиво и элегантно непонятно мне еще учиться и учиться до PHP_EOL (string) .Спасибо еще раз за подробное объяснение, у меня проблемы с циклами, вот я и решаю с разных сайтов задачки, что могу решить, хочу довести до автомата это понимание.
>>1368097>я просто не мог понять, как скрипт понимает, что надо выдергивать определенные элементы из массива, еще и с определенными условиями.$массив = [ключ => значение];$значение = $массив[ключ];$array = [4, 20, 34];То же самое, что и:$array = [0 => 4, 1 => 20, 2 => 34];$array[0] вернет число 4;
>>1368140Первый передается в конструктор и там уже берется зависимость. Контейнер не передается в конструктор, он передает зависимость аргументом извне.
ОП, проверь список студентов, пожалуйста.https://github.com/medbrat13/students-list - кодhttp://w91118rv.beget.tech/ - сайт на бесплатном хостинге
>>136816420 дней в сумме. Бывало, что над какой-то мелочью думал целый день, а бывало, что целый компонент мог написать за пару часиков. Но это нормально в программировании, как я понял.В фаерфоксе таблица не на всю ширину открывается, какие-то баги.
>>1368176Нашел PREG_SET_ORDER.Но оно выводит массив, который в массиве, который в массиве. Как просто вывести совпадения?
Короче.Когда и вызываю [$i[0]], то он выдает пустоту.Когда вызываю просто [$i], то получаю массив, в котором массив, в котором массив. Как фиксить?
>>1368187>Когда и вызываю [$i[0]], то он выдает пустоту.Ты пытаешься получить значение нулевого ключа в переменной $i, которая не является массивом и вообще содержит число.Вбрось код с ideone, посмотрю.
>>1368194Я думал, что $i тоже массив, так как при использовании echo мне выводит, что $mails[$i] это ArrayArray.
>>1368192Вот так можно. Нулевой индекс содержит все совпадения (в твоем случае, все индексы содержат все совпадения), берешь и достаешь оттуда мыла.https://ideone.com/n9kudx
>>1368176preg_match находит только первое совпадение, тебе нужен preg_match_all. Придется раскурить мануал, и поработать с var_dump, чтобы понять, в каком формате он возвращает данные.
>>1368204Спасибо тебе, я понял свою ошибку.Я выводил [ 0 [0] ],то есть, внутри одних скобок, писал другие.Надо было просто рядом поставить, блять.
>>1368217Да то же самое решение, просто он вместо вайла взял форыч, и регулярку прям в функцию вставил.
>>1368156>Autoloader.phpПочему ты не реализовал загрузчик классов как на пике, а написал целый класс? Мне думается, что громоздко вышло.>init.phpПочему ты его решил в конфиг положить? Я такое обычно прямо в корень кладу - инициализация приложения вроде как.Или ты просто не заморачивался на этот счёт?Намотал себе на ус несколько твоих приёмов.
>>1368226Не задумывался каким образом будешь показывать страницу ошибки, если пользователь захочет зайти на несуществующую страницу или где-то выбросится исключение?Мне кажется лучшим вариантом будет перехватывать исключения во фронт-контроллере и выводить соответсвующие ошибкам страницы, попутно записывая их в лог.мимо другой анон, делающий студетов
>>1368224Я лично постоянно забываю, что означают все эти классы буквенные в регулярках. Намного нагляднее писать вместо \S - [a-z0-9.+_-], сразу видно, что ищем, читается проще, хоть и длиннее. + можно отредактировать тут же, если какой-то символ не понадобится.
>>1368228>каким образом будешь показывать страницу ошибкиЕсли маршрут не найден, то маршрутизатор возвращает заранее определённый адрес страницы ошибки. Потом всё это дело идёт на выполнение.Но я про автозагрузку классов спрашивал, а не роутинг. Это немного разное.
>>1368226>Почему ты не реализовал загрузчик классов как на пике, а написал целый класс? Мне думается, что громоздко вышло.Видел бы ты, сколько у композеровского загрузчика классов, вроде 5-8, если мне не изменяет память.Я размышлял так: автозагрузчик это ведь тоже некая сущность, а для каждой сущности нужен свой класс. >Почему ты его решил в конфиг положить? Потому что это конфигурационный файл. Он подключается во фронт-контроллер и отрабатывается. Константы рассасываются по коду, сервисы создаются, остальные классы технические типа автозагрузки подключаются. Можно его и в корень, но я не люблю, когда файлы просто так валяются. Если два файла имеют что-то общее, для них создается каталог. Если файл один, и его некуда запихнуть, то это, как правило, какая-то точка входа или особняком стоящий класс по моему скромному опыту.>Намотал себе на ус несколько твоих приёмов.Поднял мне чсв, лол. Только не копипасть, не думая. Я даже если копипащу что-то откуда-то, то всегда переписываю другим способом, чтобы понять, как это работает.
>>1368234>автозагрузчик это ведь тоже некая сущностьНо получается так, что при добавлении нового неймспейса тебе приходится лезть в этот класс и править его исходник, дописывая пути.Алсо, обрати внимание на этот диалог >>1368140 так как твой DI это Сервис-Локатор, а не Контейнер Зависимостей. Если я не ошибаюсь, то у тебя он целиком в конструкторы передаётся, что есть бад-практис, так как в норме сторонние классы не должны знать поимённо сервисы в контейнере зависимостей - внутри они их по своему даже могут называть. Потом просто при тестировании проблемы будут, и при изменении имён сервисов тоже возни много - по всему коду лазать, вместо правки в месте создании объекта.
>>1368156Забыл про расширение на затемнение всех сайтов, подумал, пиздатый ты дизайн сделал, въеби мб так приммерно или это мне уже глаза выжигает белый с непривычки, если отключить расширение?
>>1368238>Но получается так, что при добавлении нового неймспейса тебе приходится лезть в этот класс и править его исходник, дописывая пути.Щас уже не вспомню, почему я так сделал. Была какая-то причина вроде той, что этот анон пишет. >>1368228>Алсо, обрати внимание на этот диалог >>1368140 так как твой DI это Сервис-Локатор, а не Контейнер Зависимостей. Это я и отвечал. > у тебя он целиком в конструкторы передаётсяОн целиком передается только в контроллер, чтобы не передавать все зависимости вручную и в класс запуска приложения. Это этап загрузки приложения, так что тут не стоит говорить плохой практике.>в норме сторонние классы не должны знать поимённо сервисы в контейнере зависимостейА они и не знают. Сервисы это ведь не сами классы, а способ их создания. В шаблоне Service Locator контейнер передается в конструктор класса и уже там извлекаются зависимости, а в моих сервисах передаются только сами зависимости.>>1368243Я дизайн на коленке сваял, а цветовую схему взял с картинки какой-то в стиле 80х. Мне не режет ничего. Да и не дизайнер я, чтобы глаза твои беречь, лол.
>>1368238Покопался щас в своем коде. Да, действительно, в описании Connection я напрямую передаю контейнер в конструктор класса. Это ошибка, которую я не исправил. Я в самом начале написания программы где-то прочитал, как нужно готовить DI-контейнер и это оказалось брехней. Человек спутал локатор с контейнером. Но я обязательно исправлю.
>>1368254>Человек спутал локатор с контейнером.Частое явление, как я смотрю - тоже встречал такое пару раз. Подводные камни как есть.
>>1368256Материалов нет нормальных на русском. А что есть - либо какая-то общая информация из переведенных надмозгом книжек, либо неверное понимание шаблонов. Почти везде одна теория. А практика если и есть, то очень сферическая в вакууме. Нет кода из реальных проектов, пусть даже учебных.Про платную информацию не говорю, не знаю, может, и есть что-то.
>>1368259>Материалов нет нормальных на русском.Ну, кроме ОПовских. Но часто ли его ссылка мелькает в выдаче гугла? Хотя это хорошо, с другой стороны, конкуренция слабее.
Анон, расскажи, где я не прав. Вроде бы и флаг верный, но работает только с первым массивом, со вторым - второй пикрил. Может я чего-то не понял, но прег_сет_ордер должен раскидывать по массивам совпадения, но при вызове второго массива я получаю хуй.
>>1353705 (OP)1) В статье про архитектуру MVC в программе сервиса для управления студентов есть строчки типа:/ @var Post[] Список объявлений /что это значит? Зачем нужна собачка?2) И еще, если кто сможет объяснить, там есть дерево файлов. Можете объяснить всю схему: Есть 2 папки public и view. На этом уровне есть файлы bootstrap и Post. А где PostService? Он просто странно расположен.Статья про MVChttps://github.com/codedokode/pasta/blob/master/arch/mvc.md
>>1368379Ой, там звездочки были в первом примере. Две звездочки после /, одна звездочка перед @var и одна звездочка перед /Попробую обойти вакабу ари помощи комментов, но если что в статье можно найти>/> @var Post[] Список объявлений> /
>>1368379>А где PostService? Он просто странно расположенГде угодно. MVC-шаблон не обязывает хранить модели, контроллеры или представления только в определённых папках. Можно даже просто в корень всё бросать, правда это не очень удобно.Я в таких маленьких приложениях классы в папку lib кладу. Вроде как бибилиотека классов.
>>1368511Та ты заебал со своими регулярками. Я тебе скинул уроки - смотри, там все есть, доступно и понятно
>>1368297Для вывода массива лучше использовать var_dump. У тебя в регулярке стоит ^ - привязка к началу строки. Второе и далее слова она никогда не найдет.>>1368517Не нравится - не читай. Это обучающий тред.
Кстати, задачка для тех, кто хочет подумать. Как бы вы спроектировали стандартные функции preg_match и preg_match_all ? Какие аргументы они должны принимать и что возвращать?
>>1368297^ - вот этот символ означает начало строки. То биш в твоей регулярке всё что не является первым словом не соответствует регулярному выражению.А вjобще удобней проверять регулярки если сразу наглядно видно как она работает. Можешь посмотреть как она работает на таких сайтах как regexr или regex101.https://regexr.com/https://regex101.com/
Обратил внимание, что во фреймворках получают данные от пользователя не через функции типа $_POST и подобные, а объектом класса Request. Я так понимаю это нужно для тестирования? Стоит ли пилить подобный класс в списке студентов?Будет нужно сделать что-то подобное?https://ideone.com/iF8vXE
Установил yii с помощью композера. Страница приветствия «Congratulations!» недоступна. Нужно веб-сервер устанавливать? Встроенный сервер php может запускать такое? Посоветуйте мануал.
Таки запустил yii на встроенном сервере. Нужно чтобы все позеленело в Requirement Checker? У меня например Intl extension желтый, PDO MySQL extension, и еще несколько зависимостей.
>>1368569>Стоит ли пилить подобный класс в списке студентов?Думаю, что можно и без него, но с ним будет лучше - по PSR.
>>1368569>Я так понимаю это нужно для тестирования?Нет. Это абстракция скрывающая ненужное, и выделяющая существенное. Чтобы поворачивать на авто удобно руль использовать. При этом не нужно знать что под ним, как он крепится, и как управляет механизмами поворота колес. Request работает по такому же принципу. Поэтому дело тут отнюдь не в тестировании.
>>1368517Хочу учиться среди людей. >>1368520Да, там пустота. >>1368537 Указал на ошибку. Спасибо за это. Сейчас понял, в чем дело было.
Начинаю делать файлообменник. Можно ли просто и без задней мысли попробовать энджин-икс вместо апача? Или он не создан для того, чтобы быть полноценным серваком?
>>1368625Конечно, используй. Никакого требования использовать Апач нету. Только вместе с ним тебе скорее всего придется освоить php-fpm (менеджер процессов PHP и FastCGI сервер).
>>1368635А пригодится это вообще в работе дальнейшей? Не то чтобы я пекусь о том, что зря, а что нет, просто у меня срок сделать все задачи из оп-поста до сентября, хочу все успеть.
Еще раз репостну, мб найдется кто. Не злитесь, хочу найти няшу-двачера и лампово работать, а не пидорга-кидалу с хэдхантера.Нужен толковый чувак, веб-разработчик широкого профиля (фуллстак).Удаленка, полностью свободный график, минимум контроля, отсутствие корпошизы (образование, внешний вид, пол и прочее тоже пофиг). Можно делать быстро и ебланить большую часть дня (не перегружаю работой), можно делать дольше, если что-то не умеешь, подождем.Языки программирования: PHP (на сервере 7.2), JS, HTML/CSS, SQL (на сервере MySQL или MariaDB).Фреймворки: Yii, jQuery.Технологии и инструменты: scss(sass), gulp, git, PHPStorm.Нужен опыт работы над крупными yii-проектами (крупнее лаба10.пхп и сокращателя ссылок).ЗП 40-50 в месяц (на руки). Если вы крутой и с ходу хотите больше (более-менее адекватно предложению) - говорите, сколько.Задачи: доработка существующего продукта, который, по идее, написан неплохо (MVC, вся фигня), с нынешним разработчиком познакомлю, введем в курс дела.[email protected]
>>1368638Обязательно пригодится. Нужно понимать разницу между ними. Понимать какие задачи они лучше или хуже выполняют.
>>1368642Двачую этого >>1368664.Я на симфонии проект небольшой написал. Но с юей уж подавно смогу разобраться. Вам срочно нужен человек?
>>1368664>>1368674Ну, недельку могу подождать. Но там же всякие особенности типа актив рекорд с актив форм, гридвью, миграциями (хотя эти вроде везде есть), все дела. Мне главное, чтобы не вышло ситуации, когда кодер не справится, свалит через месяц-два, а кодовая база к тому времени будет представлять собой адовую лапшу без mvc и psr, за которую уже никто адекватный точно не возьмется. Могу какое-то тестовое задание дать или предложить перепилить ваш ларавель-симфони проект (крупнее сокращалки ссылок) на йии с его фишками, показать код текущему разрабу, если ему будет ок, возьму с радостью.
Уважаемые, на связи снова >>1367654 вкатывальщик.Я вас наверное заебу, простите.На циклах я опять сломался, логика никогда не была моей сильной стороной, но всё-таки осилил.Пожалуйста, напишите замечания, можно ли было сделать лучше и подскажите возможно ли менее заёбно работать с процентами?https://ideone.com/RCwvSU
>>1368691>возможно ли менее заёбно работать с процентами?Потому тебе и заёбно, что у тебя неправильно. Проценты в теле цикла считаются, а не в объявлении.
>>1368704Хорошо, но какая будет разница, поменяй я местами слагаемые ? Я к тому что я не могу написать "+15%", приходится делить на сто и у множать на процент. Можно это как-то сократить?
>>1368691>возможно ли менее заёбно работать с процентами?Типа вот так:$rubles = $rubles * $percent, где $percent = 0.1ты имеешь ввиду?
Искуственный интеллект Гугл, похоже, превзошел человека, потому что я решить эту капчу не могу.>>1368691Не надо здесь ставить скобки: ($age++); Можно писать просто $age++; Точка с запятой завершает команду и скобки тут ни на что не влияют.
>>1368726Лестницы, светофоры, витрины, автобусы, такси. Гугл нейронку-водителя на нас обучает что-ли?
Аноны, поясните за подобные вакансии. Иногда всплывают, такое ощущение, будто им нужны веб-макаки для простой (реально простой) работы. Может я не понимаю чего- то. Или они набирают нуфагов, чтоб заточить их под работу в своей конторе?
ОП, напомни пожалуйста, как в Doctrine принято организовывать переиспользуемые поведения сущностей, например я хочу сделать поведения Taggable, Likeable, Commentable и переиспользовать эти поведения в 3-х сущностях. Нагуглил в других ORM полиморфные реляции - выглядят как костыль: https://logrocket.com/blog/polymorphic-relationships-in-laravel/
>>1368790> Или они набирают нуфагов, чтоб заточить их под работу в своей конторе?Возможно, это же стажировка. Набирают чернорабочих за еду. А может просто так написали, а на собеседовании ебут всякой хуйней и хотят найти какого-то омежку стронг-джуна за еду.
>>1368821Тут это где? Просто несложный, документированный фреймворк. На чем прошлый разраб писал, на том и писали, на самом деле, просьба только была, чтоб распространенное что-то, а симфони, ларавель или йии это будет - неважно. Почему нет?
>>1355067Вообще, самый простой вариант авторизации, который приходит в голову - это при регистрации сгенерировать каждому пользователю униакльный длинный токен и сохранить БД. Когда пользователь логинится, мы ставим ему в куки токен. Когда он заходит на защищенную страницу, мы по токену находим данные пользователя в БД и проверяем, что у него есть доступ.Сессии - это чуть усложненная версия. Сессия это индивидуальное для каждого пользователя хранилище данных на сервере (в простейшем случае просто файл). Можно создавать сессию и в нее писать id пользователя. Но сессии обычно удаляют, если их не использовали некоторое время, и пользователя будет разлогинивать. Мы можем продлить время жизни сессии, но тогда наш диск будет забиваться старыми сессиями. >>1356794> if($this->correctAnswer == $answer) {> return true;Так как оператор == уже возвращает true/false, то можно писать просто return $this->correctAnswer == $answer;> if (($this->correctAnswer == $answer) || (($answer <= $plusDeviation) && ($answer >= $minusDeviation))Первое сравнение на равенство лишнее.А так, решено правильно. Вот эта версия с конструкторами >>1357141 еще лучше, так как не позволяет создать объекты без указания их свойств.>>1357720Хорошо, ответ верный.
>>1358261> https://github.com/asdasdasdasddasasdasdas/StudentList/blob/ads/students.sql#L24> `hash` varchar(100) NOT NULL,Здесь стоит добавить комментарий (COMMENT ...) с пояснением, что в этой колонке.https://github.com/asdasdasdasddasasdasdas/StudentList/blob/ads/app/bootstrap.phpТы сделал DI так, что для контроллера он возвращает функцию-фабрику, которую надо вызвать, чтобы получить сам контроллер. Но лучше было бы решить это на уровне самого DI контейнера, например, сделать отдельный метод bindFactory, чтобы указать, что этот объект создается функцией. А получатель просто вызывает $di->get() и не задумывается о том, как именно создан объект. https://github.com/asdasdasdasddasasdasdas/StudentList/blob/ads/app/helpers/DIContainer.php#L37Нет смысла писать throw и catch рядом. Ты можешь заменить их на обычный if, и код будет проще читать.https://github.com/asdasdasdasddasasdasdas/StudentList/blob/ads/app/exceptions/DIContainerException.phpТут ошибка. Исключение - это объект, хранящий информацию об ошибке. Но в нем нет обработчика, который решает, что делать в случае ее возникновения. Если ты хочешь при ошибке показывать страницу, то проще всего ловить ошибку где-то в роутере, и выводить страницу ошибки. Не забудь также логгировать исключение, например, с помощью error_log(). В твоем варианте разработчик даже не узнает про ошибку. Урок про исключения: https://github.com/codedokode/pasta/blob/master/php/exceptions.mdВ роутере мне не нравится, что у тебя у одной страницы может быть много URL, например: /registration, /registration/xyz. Это плохо для поисковой оптимизации.Сообщения о коммитах плохие: https://github.com/asdasdasdasddasasdasdas/StudentList/commits/adshttps://github.com/asdasdasdasddasasdasdas/StudentList/blob/ads/app/controller/MainController.php#L30> $countStudents = $_GET['search'] !== '' ?Здесь при отсутствии ключа search в массиве генерируется notice. Странно, что ты его не заметил - может, у тебя отключен их показ? https://github.com/asdasdasdasddasasdasdas/StudentList/blob/ads/app/model/StudentTableGateway.phpЗдесь стоило использовать DI для передачи соединения с БД снаружи. Класс DBConnector тогда становится не нужен. В коде очень мало комментариев. Понятно, что многие места очевидны, но перед некоторыми классами вроде Paginator и некоторыми публичными методами стоит их добавлять. Перед методами контроллеров удобно писать, за какую страницу они отвечают. Заодно почитай про phpDoc.Стоит добавлять тайп-хинты (string, int) в аргументы функций. Это защищает от ошибок и документирует код.https://github.com/asdasdasdasddasasdasdas/StudentList/blob/ads/app/model/StudentTableGateway.php#L70Здесь в getStudents(int $offset, int $limit) в SQL запросе ты не указал способ сортировки. Это значит, что БД может возвращать любые записи, например, одни и те же записи для любой страницы. То есть конструкция OFFSET без сортировки не имеет особого смысла.https://github.com/asdasdasdasddasasdasdas/StudentList/blob/ads/app/model/StudentTableGateway.php#L143Проверка сделана некорректно тут: > } elseif ($result['id'] == $id && $result['email'] == $email) {Может быть такое, что найдется 2 записи, но первой вернется запись с нужным id, а вторую ты не проверяешь. https://github.com/asdasdasdasddasasdasdas/StudentList/blob/ads/app/controller/ProfileController.php#L83тут можно было сделать вспомогательную функцию, чтобы не копипастить длинные выражения.> $student = $this->auth->getAuthUser($this->auth->getHash());Странно, что мы должны передавать хеш, хотя $this->auth его и так знает. https://github.com/asdasdasdasddasasdasdas/StudentList/blob/ads/app/helpers/Authorization.php#L22> public function IsLoggedIn()> {> return isset($_COOKIE['hash']) ? true : false;Этой проверки недостаточно, чтобы считать пользователя залогиненным. Что, если он сам себе поставит куку hash=1 ? https://github.com/asdasdasdasddasasdasdas/StudentList/blob/ads/app/view/partials/form.phpТут стоит добавить атрибуты для HTML5 валидации до отправки формы.> <?= $student->gender == 'f' ? 'checked=checked' : null; ?>echo выводит только числа и строки, неправильно передавать на вывод nullРадует, что ты прочитал про SQL-инъекции и XSS. А есть ли у тебя защита от XSRF? > if ($this->paginator->getPreviousPage() !== null Красивее писать if ($this->paginator->hasPreviousPage()), а еще лучше $paginator->hasPreviousPage()При ошибке 404 надо отдавать соотв. HTTP-код. То же самое касается страницы ошибки в приложении.Сессии наверно не нужны в index.php? Вообще, пока впечатление по коду хорошее.
>>1358262Есть небольшой недостаток, что нельзя добавлять новые профессии, не трогая существующий код. А так, пока неплохо, давай посмотрим, что будет с антикризисными мерами.>>1358554> https://3v4l.org/NSVsb - задача про зарплатуovertime должен вычисляться автоматически. Все, что больше 40 часов в неделю - переработка.> https://3v4l.org/4GGth - задача про вопросыТут можно было ставить тайп-хинт на возвращаемое значение: > public function checkAnswer($answer): bool А так, все верно.> https://3v4l.org/3avqA - задача про ВекторВ качестве названий профессий можно было использовать константы-имена классов вроде Manager::class: http://php.net/manual/en/language.oop5.constants.phpaddEmployees лучше бы вынести наружу из Департамента, так как это не позволяет создавать новые профессии, не трогая существующий код. Ну например, если твои классы будут оформлены в виде библиотеки, которую делает один человек, то другой человек, который ей пользуется, не сможет добавлять свои профессии. Случай, конечно, немного придуманный, но надеюсь, смысл передает. У тебя класс Department сейчас по сути содержит захардкоженный список возможных профессиий. А это не его зона ответственности - знать, какие профессии есть. > public function getInformation(): array {Мне кажется, было бы удобнее сделать несколько отдельных методов, но можно и так. Но name и employeesCount точно надо вынести отдельно. Так как неудобно будет их получать и никакой экономии от помещения их в этот метод мы не получаем. Если доводить до абсурда, то мы тогда можем сделать в любом классе 2 метода setInformation и getInformation и работать со старыми добрыми массивами. Это не очень удобно, и в плане получения данных (надо извлекать их из массива), и в плане кода (все собрано в одном огромном методе).Класс Table правильнее назвать TablePrinter, TableFormatter, так как он не представляет информацию о таблице. А вообще хорошо, меня радует, что и у нас в треде, да и вообще в программистском сообществе стали лучше понимать ООП. А не как раньше, когда все сидели на CMS и городили жуткие конструкции на многомерных массивах.
>>1358927Я приведу пример про числа и строки: $a = 123; // это число. Его можно складывать, вычитать итд.$b = "123"; // это строка. Это набор букв. Вычитать строки нельзя, но PHP// автоматически преобразует строку в число, если ты попытаешься// это сделатьКогда ты читаешь что-то из файла, из консоли, ты всегда получаешь строку. Есть функции intval, floatval, strval, которые делают преобразования между типами. Увидеть тип значения можно с помощью var_dump.Вместо is_int ты можешь использовать is_numeric.>>1360327Сделано неправильно. Ты сравниваешь только одну пару букв (самую первую и самую последнюю), и после сравнения завершаешь программу, а надо сравнивать все.>>1360712Postgres интересная БД, у нее много фич, по ней есть хорошая актуальная документация на русском, стоит прочесть. Например, там много интересных видов индексов.>>1360810Читай постепенно. Если ты не любишь читать документацию, то развиваться будет трудно.>>1360904Сегодня я выучил новую поговорку.
>>1368814Ты можешь посмотреть, как сделано в Doctrine Extensions если тебя интересует именно реализация расширений: https://github.com/Atlantic18/DoctrineExtensionsТам используются события Доктрины. Для простых случаев можно использовать просто трейты.Также, на мой взгляд, если эти расширения сложно реализуются, то лучше не заморачиваться и сделать по-простому. Плюс, надо помнить о производительности. Если тебе надо получить число лайков, то быстрее всего иметь поле с этим числом. А ставить лайк SQL-запросом (если хайлоад - то через очередь в редисе и групповые обновления). Да, не универсально, зато просто и быстро. Ну и в рамках Доктрины эффективные групповые обновления сделать будет трудно.
Я уже из себя все соки с этой задачей про айфон выпил.Вы обещали что с тройкой по математике можно!Почему это неправильно? Что вообще нужно сделать? У меня уже опускаются руки.https://ideone.com/QIFtDz
>>1369109У тебя получился какой-то сложный код. Ну например, ты в первый раз всегда платишь 5000, независимо от суммы кредита. Вряд ли рациональный человек будет так делать.Ты зря скопировал код, который был дан, так как в нем была специально сделана ошибка.Давай попробуем составить более простой алгоритм.Попробуй переписать код внутри цикла примерно так:- прибавляем проценты и комиссию к остатку долга (!не вычитаем ничего пока!)- если остаток маленький, выплачиваем сколько осталось и уходим- иначе платим 5000 «Платим» здесь значит уменьшаем долг и увеличиваем общую сумму выплаченного.
>>1369109И еще, вот здесь очень странный код: if ($creditBalance < $monthlyPayment){ $monthlyPayment = $creditBalance; / Почему это не работает? / echo "С меня хватит!\n"; break; / Почему это не работает? / }Что он должен делать? break выходит из цикла, а так как после цикла ничего больше нет, то на этом выполнение программы заканчивается. как в твоем понимании должна была "работать" строка $monthlyPayment = $creditBalance; ? Она копирует число из одной переменной в другую. Но так как дальше идет break и программа завершается, то это уже ни на что не влияет.Ни в коем случае не пытайся писать код наугад. Ты должен понимать, что ты хочешь сделать, что будет делать каждая строчка, что будет происходить, и только потом писать код, а не переставлять команды наугад в надежде, что оно как-то заработает. Даже если оно заработает, это не даст никаких навыков.
>>1369059>Читай постепенно. Если ты не любишь читать документацию, то развиваться будет трудно.Не в этом дело, просто гора чего еще в планах выучить/прочитать и postgres не в приоритете. Если бы для ознакомления надо было уделить немного времени то ок, а так придется отложить в долгий ящик
Поясните про паттерны проектирования.Имею опыт работы, пишу в ООП. Но меня отовсюду постоянно заебуют знакомые, что мол необходимо паттерны знать.Несколько раз брался их изучить (читал/смотрел видеоуроки) но так и не понял нахуя они нужны?Я понимаю например MVC - понятна суть такой структуры, но когда смотрю какуюнибудь фабрику, то не пойму о чем речь. Фабрика как я понял - это идея о порождении объектов другим объектом? Это и вся суть? Я постоянно пишу подобные структуры и не понимаю, зачем мне надо знать, что это называется фабрикой? Или я наделяю паттерны большим значением, чем они имеют на самом деле?
Верно ли я понимаю, что на PHP можно писать даже десктоп-приложения?Увидел вот это - https://github.com/cztomczak/phpdesktop - и хочу спросить мнения анона по данной идее.
>>1369356Большинство задач. с которыми часто приходится сталкиваться программистам. уже давным-давно решены другими членами сообщества. С помощью проектных шаблонов просто выделяют общие задачи, определяют проверенные решения иописывают вероятные результаты. Задачи имеют свойство повторяться, и веб-программистам приходится решать их снова и снова. Со временем мы находим более или менее изящные ответы на эти вопросы и создаем неформальный набор методик, которые затем снова и снова используем в своих проектах. Эти методики - и есть проектные шаблоны. Что касается знаний названий шаблонов, то наименование шаблона уже само по себе очень ценно; таким образом создаетсячто-то вроде общего словаря. Вот сравни две ситуации.На совещании тебе дали задание, что в проекте имеет смысл сделал интерфейс для создания семейств взаимозависимых объектов, не специфицируя их конкретных классов. Это всё должно быть реализовано созданием абстрактного класса, который представляет собой интерфейс для создания компонентов системы. Далее должны быть классы, реализующие этот интерфейс."Или просто сказали, что система должна создавать каждый набор с помощью шаблона Abstract Factory.Зандстра, Мэтт.РНР: объекты, шаблоны и методики программирования
>>1369417>Зандстра, Мэтт.>РНР: объекты, шаблоны и методики программирования То читал. Технически понятно все, но зачем все то выделяется в отдельную дисциплину - не понятно.>На совещании тебе дали задание, что в проекте имеет смысл сделал интерфейс для создания семейств взаимозависимых объектов, не специфицируя их конкретных классов. Это всё должно быть реализовано созданием абстрактного класса, который представляет собой интерфейс для создания компонентов системы. Далее должны быть классы, реализующие этот интерфейс.Вот я и буду реализовывать то, что сказали. Зачем мне для этого знать, то, что кто-то это уже реализовывал и дал этому название?
>>1369447>зачем все то выделяется в отдельную дисциплинуШаблон описывает лишь общее решение. Не обязательно им слепо следовать и пихать куда не попадя. Если задачу решить без шаблонов проще и удобней, решай без шаблонов. Шаблон не самоцель, просто некий вариант решения.>Зачем мне для этого знать, то, что кто-то это уже реализовывал и дал этому название?Если у тебя возник такой вопрос, то видимо не зачем. Но если будешь часто сталкиваться с такой ситуацией, то рано или поздно запомнишь названия шаблонов. Считай это профессиональной лексикой.
Аноны, на каком ресурсе искать книги по php в формате fb2, mobi? Конвертировал из pdf в данный формат, просто пиздец, не читабельно от слова совсем.
Котоны, помогите сделать выборку из одного массива по индексу из другого массива, пожалуйста:https://ideone.com/IKruQgТо есть у меня список Id в одном массиве вида: 3,10,12,25А другом значения.Id выводит верный - итерируется, а значение - нет.
>>1369614https://ideone.com/dCvwSrНе брезгуй залезть в документацию по языку, когда работаешь с каким-то типом данных чтобы не приходилось писать уже существующие функции.
>>1369614читай комментыhttps://ideone.com/YBE0sHбез встоенных функций:https://ideone.com/ZrcuSEа лучше как анон >>1369646 сделал.
Я тупой и заранее сори за тупые вопросы.Могу ли я прихуячить js файл в php и он будет нормально работать? Смогу ли я брать данные из sql и рендерить их при помощи js в пхп?Сильно ли отличается PHP Bootstrap от ванильного?
Аноны, есть один массив массивов arr[]:https://ideone.com/Gow8Pfкак добавить первичный индекс цифру каждого из них к значению, в начало то есть перед всем остальным subarr[]? Что я делаю не так?
>>1369851>Что я делаю не так?Ты не изучил работу с массивами и не потренировался с ними.Если ты взялся за реальную задачу, не имея скиллов, то земля тебе пухом, братишка. Тут тебя тащить никто не будет.
>>1369846Потомучто ларавель разрабатывают программисты, а не двачеры или вкатывальщики с каргокультом
>>1369113>>1369119Спасибо за подсказку, но всё равно не получается.По моей логике если долг меньше ежемесячного платежа, то ежемесячный платеж нужно сравнять с остатком долга, соответственно заплатить его, и должен получиться "0". Но почему ноль не получается? Я не могу понять.https://ideone.com/hcLusb
>>1369955Ты в последний месяц (в твоем if) не уменьшаешь $creditBalance и не изменяешь $paymentTotal и делаешь break; из цикла. Поэтому выводится баланс и т.д. за предпоследний месяц.
>>1369855В нормальных языках (C#/Java) нет никаких трейтов, люди следуют SOLID и пишут нормальный код. Ларавель пишут говнокодеры, ломающие обратную совместимость в минорных версиях ( https://github.com/laravel/framework/issues/27949 ), создающие трейты на каждый чих, порождая хрупкий код, вместо того, чтобы подумать и нормально разделить ответственности. Одно дело когда в модели переиспользуемые поведения, совсем другое - когда вся архитектура на запутанном месиве из трейтов и магических методов, которые нативно не поддерживаются IDE и статическими анализаторами. Частично помогают лишь сторонние костыли и заплатки. Не пишу на ларавеле больше года и очень рад, что больше не имею с ним дел.
>>1369971Ну неужели у меня получилось, наконец-то!Понял свою ошибку в понимании построения кода теперь скажи, это сильно пиздец и стоит попробовать как-то оптимизировать код и количество команд, или что-то вроде этого и должно было получиться?https://ideone.com/CPJLAo
>>1370030>Спустя 4 часа пердолингаПоначалу - обычное дело. Вообще привыкай учиться сразу потом мозги сами нормально встанут.
- Вникаю в паттерны и нахожу их полезными знаю не все наверно- Понимаю MVC есть свой - вечнонедоделанный и нубский микрофрейм- Работал с APIделал обёртки, встраивал, разрабатывал - разбирался- Знаю пару библиотек с Гитхаба. И вообще очень ленивый - мне проще у кого модуль скачать и встроить главное чтобы без лютого говнокода и с доками, чем с нуля собирать.- Знаю штук пять-шесть Структур Данных- Предпочитаю писать на ООП - как-то легче на нём мне пишется. Из фреймворков только пока Слим пробовал- Ну и всякое по мелочи.Можно уже ходить по собесам?
>>1353705 (OP)Подскажите дурачку какой-нибудь простой финт ушами на чистом пхп (хотя можно какую-то библиотеку, главное чтоб юзать было просто) который якобы защитит меня от sql инъекций (нужно для диплома, просто показать, в гугле какие-то сложные вещи)Начал пользоваться кодигнайтером для этих целей, но у меня стили не подгружаются, хотя гуглил и делал все как тут https://stackoverflow.com/questions/11581636/fatal-error-call-to-undefined-function-base-url-in-c-wamp-www-test-ci-applic (возможно это из-за галповских scss, хуй знает как все что на пике вообще в фреймворком подгрузить)
>>1370277Начни со статьи про инъекции: https://github.com/codedokode/pasta/blob/master/security/sql-injection.md
>>1353705 (OP)Чем бэкенд-разработчик занимается по 8 часов в день? Как часто с базами данных работает?
>>1353705 (OP)Пагни, использую symfony4. Нужно чтобы определённый пхп скрипт выполнялся перед загрузкой каждой страницы. В скрипте происходит обращение к удалённому сервису, который возвращает некоторое дерьмо. Это дерьмо должно быть доступно после в любом контроллере для последующей передачи во вьюхи.Как это правильно реализовать?
>>1370287Привет. Я бекенд-разработчик. Я пишу бекенд для сайтов, сервисов и всякие разные скрипты автоматизации. Но чаще нихуя не делаю. В среднем я работаю с базами данных по 146 раз в день.
>>1370359>Но чаще нихуя не делаюУ меня друг сеньор-помидор с $3700 на руки. Говорит что если 4.5 часа за день кодировал и на митинге орал, то это был ппц напряженный день.>>1370358https://symfony.com/doc/current/event_dispatcher/before_after_filters.html>обращение к удалённому сервису, который возвращает некоторое дерьмоЯ бы подумал о выдергивании некоторого дерьма в кэш или бд скриптом по крону например, если время жизни некоторого дерьма позволяет.
>>1370358Это плохая идея и приведет к багам и тормозам на сайте. Лучше от нее отказаться и реализовать по-другому.
>>1370381>https://symfony.com/doc/current/event_dispatcher/before_after_filters.htmlСпасибо за ответ по делу.
>>1353705 (OP)Устанавливаю зависимости через composer. Есть одна либа в приватном репозитории, у которой нет package.json и вообще файлов с метаинформацией.Добавляю я её так>{> "repositories": [> {> "type": "package",> "package": {> "name": "xxx/package_name",> "version": "1",> "source": {> "url": "https://[email protected]/xxx/package_name.git",> "type": "git",> "reference": "master"> }> }> }> ]>}Устанавливается она нормально. В папке vendor вижу склонированную репу. Но если она обновляется в удалённом репозитории и я делаю composer update - либа в vendor остаётся старой версии. Пробовал делать composer clear-cache - без изменений. Помогает только ручное удаление директории либы в vendor и запуск после composer update - только после этого скачивается новая версия из репозитория. Почему так происходит и как сделать так, чтобы composer скачивал ту версию либы, которая на данный момент находится в удалённом репозитории?
>>1370183>хтмл/кссВкатывался через вёрстку - могу делать небольшие правки. Даже пара лендосов собственноручно свёрстанных где-то есть, не то, чтобы очень хороших. Немного бутстрап пробовал, было дело и на вордпресс натягивал.>js Тоже об этом думаю. Ещё не трогал его.
>>1370476Иногда стоит смотреть мануал. Вот, что тут написано про тип package: https://getcomposer.org/doc/05-repositories.md#package-2> Composer will not update the package unless you change the version field.То есть это для случая, когда "пакет" это просто зип-архив с фиксированной версией.Тебе стоит попробовать тип VCS: https://getcomposer.org/doc/05-repositories.md#vcsВерсии пакетов автоматически определяются из меток (тегов) в репозитории.Также, я сам не разбираюсь в композере, но тебе советовал бы полистать мануал. Например: - https://getcomposer.org/doc/02-libraries.md- https://getcomposer.org/doc/articles/aliases.md
>>1370288> по их схеме версионирования Я в курсе. Это значит, что разработчикам не хватает профессионализма, чтобы релизить новый функционал, не меняя код, на который завязались люди в своих проектах. Все серьёзные фреймворки умеют в deprecation warnings:- Spring: https://beginnersbook.com/2014/07/deprecated-annotation-in-java/- ReactJS: https://reactjs.org/blog/2017/04/07/react-v15.5.0.html#new-deprecation-warnings- Symfony: https://symfony.com/doc/current/contributing/code/conventions.html#deprecationsВ симфони так вообще есть Backward Compatibility Promise, в котором точно описано, что и в каком случае может поменятся: https://symfony.com/doc/current/contributing/code/bc.htmlДумаешь им хочется с этим всем заморачиваться? Вряд ли, просто они понимают, что проекты на Symfony как правило большие, сложные и долгоживущие и ломать что-то в минорных версиях недопустимо. Да и глупо не следовать семантическому версионироваю в 2019-м году, когда любой более-менее популярный фреймворк ему следует.
Народ, поясните. Что я накосячил т к идеон выдает ошибку неверная функция, но я ее аж с мануала специально копирнул https://ideone.com/tAT7Qv
Как вы тестирование изучали, от корки до корки читали phpunit/codedeption всю доку или основоное как запускать и как что тестировать?
>>1371052В пхп должен быть подключен модуль mb_ из которого эта функция берется. Уебки ideone этого уже который год не делают. Используй другой сервис для пхп онлайн.
>>1371052в идеоне нет поддержки многобайтовой кодировки, это означает что функций mb не будут там работать, добро пожаловать в пиайчпи (используй сендбокс)
>>1371185я автор вопроса.1. Нагуглил статьи и повторил.2. Аналогично на ютубчикеЭлементарно могу после этого тестировать классы/методы/исключения, так использовать анотации, создавать структуру файлов и прочее.Но открыл доку и там яяяяябать сколько всего. Казалось бы тесты, но пиздец как лень читать
Интересные статьи про то, как оптимизировали PHP7: https://habr.com/ru/company/oleg-bunin/blog/444508/https://habr.com/ru/company/oleg-bunin/blog/445512/>>1371053У меня еще есть обзорный урок по тестам, если кому интересно: https://gist.github.com/codedokode/a455bde7d0748c0a351a
>>1371225Все прочитал что есть, статьи огонь! У меня такая проблема, вот я беру что-то учить и учу от корки и до корки. Взяля за phpunit, все видосы на ютубе пересмотрел, твою статью еще давно прочел и другие из гугла. А сейчас доку читаю. Уже тупо не лезет инфа, потому-что я заебался учить, т.к. не вижу денег от своего труда, а мозг меня нахуй посылает из-за холостой работы.И тот же yii2 учу, все видосы на ютубе (проматывал то чего знаю), статьи + вся дока для создания индексов в голове и чтобы знать что он может. Осталось добить RBAC, REST и прочееА тестирование влезло как раз в yii2 и я уже надолго забросил yii и сейчас учу его, точнее все делаю кроме того чтобы учить, то видос обычный посмотрю, то в инете мемы посмотрю и тд, уже просто отвращение пошло, планировал весной выйти на работу добив yii так вот хуй. бляя, глянул на список чего сам себе составил учить, там пиздец сколько всего(
БЛЯ!!! Отправил им недоделанных студентов и они меня позвали на собеседование на завтра. Больно будет?
>>1371294Я уверен, что это обязательно окупится. Поначалу, да, море информации кажется безбрежным, но когда ты, например, начнешь учить какой-то другой фреймворк, ты поразишься, сколько много там общего. Ну и на собеседовании, если ты начинающий, то тебя будут гонять по теории, и это тебе поможет произвести хорошее впечатление, чем кандидаты. которые что-то поверхностно знают, но не могут толком ничего рассказать.Так что считай это своим плюсом. Учиться вообще тебе придется постоянно. На досуге можешь почитывать статьи про собеседования от яндекса. Когда ты сможешь там решить все задачи, то значит, знаний ты набрал достаточно.
А что для тестирования базы данных используется?В phpunit пишут что устарело https://phpunit.readthedocs.io/ru/latest/database.htmlИ вообще, этого достаточно или еще надоphpunit, codeception (там же и BDD подход), TDDЭтого хватит для middle?
Коллеги, накопилось несколько вопросиков по студентам. Делаю сейчас первую страницу - отображение списка. БД подключено через PDO, СУБД - sqlite. В качестве шаблонизатора - twig.1. Записи выводятся по 10 штук (пока) на страницу. Записи просматриваю с помощью fetch(). Поскольку подразумевается, что записей может быть много, делать fetchAll() неправильно. Соответственно, сначала мы считываем первые десять записей в массив и отображаем. А если нам сразу нужно будет отобразить записи с 30 по 40? Также в цикле делать fetch и просто пропускать записи? Как-то принудительно можно начать читать с определенной записи?2. Вопрос вытекает из предыдущего - пагинация. Я правильно понимаю, кто кнопки пагинации содержат в своих гиперрсылках информацию о текущей странице, то есть на каждой странице ссылки разные вида, например, ?first_page=10&last_page=20 и потом мы это получаем в переменной $_GET? Я как бы сам до этого допер, но правильный ли это вообще подход? Может подскажете, где можно почитать про перенаправление и вот это вот все. Пагинацию тоже наверное имеет смысл сделать объектом?3. Уже собственно про twig. Страница шаблона должна быть в одном файле или можно их как-то объединять несколько? Может ту же пагинацию в отдельном файле хранить? И еще, передача данных в шаблон передается массивом, что насчет быстродействия при передаче больших объемов информации?4. Создание объекта PDO делаю так:$db = new StudentsTable(new PDO('sqlite:db/students.db'));Я почему-то из уроков по студентам сначала подумал, что привязка в объекту PDO будет в самом классе, но потом как-бы понял, что это свойство может быть присуще именно объекту. Поправьте меня, может я все же что-то не допонял.Сорян за нубские вопросы, но немножко тупички небольшие возниклиБыл тут с вами два года назад, принимайте пополнение, пикрелейтед
>>1371535да хуй его знает, всякие моки хуеки, вот есть AR модель, как-то че-то пошуршать и заебенить, по пацанский четко хуяк хуяк ну ты понял, да?
>>1371537>Поскольку подразумевается, что записей может быть многоВ базе - много, а на руки запрашивай ровно столько, сколько надо - одну страницу, и разбирай всё что пришло. Пагинация получается - это смещение по твоим страницам.>кнопки пагинации содержат в своих гиперрсылках информацию о текущей страницеОбъект Пагинатор должен знать сколько у тебя всего записей, сколько выводится на одну страницу и текущее смещение. Этого достаточно чтобы получить общее количество страниц и текущую.Я ему ещё иногда хтмл-шаблон для вывода всей ссылки отдаю - чтобы сразу оформленные блоки с номерами выдавал, а не тупо цифры. Удобно, но не везде любят такое.>$db = new StudentsTable(new PDO('sqlite:db/students.db'));А если с двумями таблицами будешь работать в приложении - вторую переменную создашь с ещё одним PDO? А если мне надо будет заменить объект PDO для тестов, а он у тебя гвоздями при создании вкручен.
>>13715371) Неправильно выбирать все записи, а потом читать только часть.Чтобы выбрать только часть записей есть конструкция LIMIT/OFFSET: https://www.sqlite.org/lang_select.htmlОбрати внимание, что LIMIT/OFFSET не входит в стандарт языка SQL и является дополнением, которое поддерживается только в некоторых СУБД вроде MySQL или SQlite.Описание на русском есть тут на примере Postgres: https://postgrespro.ru/docs/postgresql/11/queries-limit (прочти внимательно).Стандартные способы постраничной выборки данных есть в Википедии: https://en.wikipedia.org/wiki/Select_(SQL)#Limiting_result_rows2) Я правильно понимаю, кто кнопки пагинации содержат в своих гиперрсылках информацию о текущей страницеДа, в в соответствие с буквой S (stateless) из REST.Сервер не "запоминает", какие параметры сортировки выбирал пользователь.Ссылки неудобно собирать руками, лучше сделать фукнцию, которая их будет генерировать.3) Страница шаблона должна быть в одном файле или можно их как-то объединять несколько?Обычно делают "лейаут" - это шапка и подвал, общие для всех страниц. Потом делают страницы, каждая в своем файле. Отдельные компоненты можно и нужно выносить в отдельные шаблоны. Например, пагинацию можно вынести так, что ее можно будет подключить на любой странице сайта. > И еще, передача данных в шаблон передается массивом, что насчет быстродействия при передаче больших объемов информации?Никаких проблем нет, в PHP это сделано суперэффективно и занимает меньше микросекунды (в реальности ничего не копируется, просто передается ссылка на существующий в памяти массив). Можешь проверить, сделав большой массив, копируя его в цикле в другую переменную миллион раз и замеряя время в сравнении с пустым циклом.Учись делать измерения с помощью microtime(true).4) Ты интуитивно сделал правильное решение. Класс StudentsTable не должен думать, где взять "соединение" (на самом деле не соединение, а просто объект для связи) с БД, какие у него параметры. Он должен получать его снаружи через конструктор. Это называется DI и у меня есть урок про это на гитхабе.
>>1371555> Я ему ещё иногда хтмл-шаблон для вывода всей ссылки отдаюЭто плохая идея, так как разные ссылки могут оформляться по-разному, например, первая ссылка может быть выделена. Лучше сделать отдельный шаблон для пагинации.
>>1371537Здесь на примере Postgres на русском описан FETCH FIRST из стандарта SQL, читай и это тоже: https://postgrespro.ru/docs/postgresql/11/sql-select#SQL-LIMIT
>>1371529Саму БД тестировать не надо - ее тестируют ее разработчики. Ты наверно хотел тестировать код, который работает с БД? Тут есть пара вариантов: 1) разделить код на тот, которому точно нужна БД и тот, который только подготавливает данные. Тот, который подготавливает данные, тестировать, подсунув ему заглушку вместо реальной БД.2) код, который работает непосредственно с БД можно тестировать, используя тестовую БД. Для соблюдения требования об изоляции тестов друг от друга мы должны перед каждым тестом воссоздавать одинаковое состояние БД. Например, загружать в БД дамп. Но тут 2 проблемы: - это медленно- если у нас 1000 тестов и мы данные для каждого добавим в дамп, то он будет большой и непонятно, какие данные кому нужныПотому обычно делают так: - перед тестами один раз тестовая БД очищается и в ней создаются структуры таблиц (пустые), и может какие-то неизменные справочники. Это можно делать миграциями или загрузкой заготовленного дампа (что может быть быстрее).- перед каждым тестом мы начинаем транзакцию, и откатываем ее после теста, отменяя все изменения- если тесту нужно наличие каких-то записей в БД, он сам их создаетВот как-то так. Если СУБД поддерживает создание таблиц в памяти, то стоит это использовать для ускорения. SQlite умеет такое, например.Допустим, ты тестируешь репозиторий Пользователей, который умет создавать пользователей в БД, искать их по id, удалять. Тест создания пользователя может выглядеть так:- создать объект с параметрами пользователя- вызвать у репозитория метод сохранения этого объекта в БД- получить id- запросить у репозитория данные пользователя с таким id- проверить, что он нашелся и это тот же пользователь
Привет анон. У меня есть вопрос, поможешь мне?В пхп я (как и везде) почти ноль. Есть сайт на котором по api показывался блок погоды. После переезда сайта на новый хостинг данные перестали выводится, хотя код я не менял. Ключ АПИ так же работает и при открытии напрямую все данные есть. На сайте же невыводится ничего. В чем может быть проблема? В настройках хостинга, версии пхп или в чем?
>>1371573Я реально тупенький и не понимаю в чем может быть проблема, Код типа такой:<? $url = "мой ключ апи"; $contents = file_get_contents($url); $clima = json_decode($contents); $temp = $clima->main->temp; $temp_max = $clima->main->temp_max; $temp_min = $clima->main->temp_min; $desc = $clima->weather[0]->main;?><? echo "". $temp ."° ". $desc .""; ?>
Аноны, подскажите, в чем проблема. https://ideone.com/oO5WuX меня интересует откуда в последней строке ошибка. Функцию я вроде закрыл, а ошибка со скобкой лезет
>>1371052Вроде получилось, но я 2 момента не понимаю.http://sandbox.onlinephpfunctions.com/code/804b14ca336e4c0eed19d07f4a905cf61e897acf1. Я выдираю из противоположной стороны фразы. Если для этого я использую аргумент -$i, то после первой буквы а идет еще одна а. это легко проверяется по эху. Почему так происходит, как я понял это из за того, что при 0 аргументе первая буква всегда первая в предложении 1ца дает 2ю букву в одном направлении и 0ю(в данном случае первую с обратной стороны) так?2. Как мне сделать так, что бы если слово не было палиндромом ехо после цикла не выводилось?
>>1371621Попробовал - не пашет, сейчас переделал и все равно не пашет. https://ideone.com/ucPQkR Вроде и комментарии сам себе расписал, почему-то пишет про неопределенный аргумент, но я его определил до начала цикла
>>1371622Не совсем понял про переменные.Переменные хукают данные из JSON (см. пик) и выводят их далее через echo. Когда я со своим нулем знаний конструировал это, все работало. Все работало ровно до ебаного переезда хостинга.
Оп,а на каком уровне вёрстку стоит учить? Бесплатной хтмлакадемии и твоих задач хватит или надо ещё гриды,флексы и адаптивную подучить? Про js тот же вопрос.
>>1371573>>1371574>>1371683ПамахитиПошли меня куда-нибудь анон. Где мне искать решение? Я вижу проблему в настройках хостинга, но там реально непробиваемые сидят и без уверенности (читай доказательств) писать в поддержку даже нет желания.
>>1371952Попробуй просто в echo строку вывести без переменных,если все норм,то и хостинг не виноват. Мб какой xdebug поставь и проследи, что происходит, плюс в браузере в network посмотри, какие ответы на запросы приходят, какой код ответа. Я сам вкатывальщик, особо не шарю, но ты мало инфы дал анонам.
>>1371952Для начала, почему ты гадаешь наугад? Так можно еще 100 лет гадать. Изучи ситуацию. Сделай следующее: - убедись, что на сервере ведутся логи ошибок PHP или веб-сервера, найди их. Что логгирование не запрещено настройками PHP или хостинга.- проверь, есть ли там сообщения, относящиеся к этому файлу с кодом - вдруг там происходит ошибкаЕсли ошибок нет, возьми код и после каждой команды поставь var_dump с выводом, что она возвращает. запусти код и посмотри - все ли команды возвращают то, что ожидается? Проверь - что именно вернула file_get_contents, какую страницу, что на ней?
>>1371952Не используй echo, как тебе советуют, так как она выводит только строки и числа. Используй var_dump, которая выводит все типы данных. Подробности в мануале.
>>1371621>>1371666У тебя в условии значение никогда не становится меньше или равно 0 и, соответственно, условие функции не доходит до ложного значения, и, соответственно ничего не возвращается.>https://ideone.com/oO5WuX меня интересует откуда в последней строке ошибка.Потому что ты задаешь функцию, которая уже создана. С помощью ключевого слова function, а тебе нужно её вызвать просто написав имяФункции().
>>1371971Попробую>>1371973Спасибо, буду пробовать и курить мануал, как советует и этот >>1371975 анон>>1371977Все работало, говорю же. На двух сайтах все фурычило.
Двач образовательныйСпасибо анону >>1371973 полез искать логи и все стало ясно нет:file_get_contents(): failed to open stream: no suitable wrapper could be found in on line 90file_get_contents(): http:// wrapper is disabled in the server configuration by allow_url_fopen=0 in *Теперь дело за малым, понять что это и как фиксить. Спасибо, анонче.
>>1371655Как мне сделать так, что бы если слово не было палиндромом ехо после цикла не выводилось?Используй дополнительную переменную как флаг.http://sandbox.onlinephpfunctions.com/code/cae9f2c8f9e6ae0f1332e88c1a5336eb867b716a
>>1372058https://ideone.com/LYrtEq$overallPaid=0;переменная находится внутри цикла. И обнуляется каждый раз.В остальном всё работает. Но проценты и комиссия банка абсурдны. Анон не успевает расплачиваться с кредитом. 100 витков цикла проходят до того как он расплатится. Потому ты не видишь вывода на экран. Можешь отслеживать состояние переменных внутри программы командами echo или var_dump.
ОП, глянь, если сможешь, твои задачи по верстке:1. https://codepen.io/codecoshauni/pen/bZQKyv2. https://codepen.io/codecoshauni/pen/QoJBGz?editors=11003. https://codepen.io/codecoshauni/pen/bZzzWE4. https://codepen.io/codecoshauni/pen/YgBgMV5. https://codepen.io/codecoshauni/pen/ZPwZEz6. https://codepen.io/codecoshauni/pen/MxLRzy7. https://codepen.io/codecoshauni/pen/PLVvZM8. https://codepen.io/codecoshauni/pen/YgBbVg9. https://codepen.io/codecoshauni/pen/draExb10. https://codepen.io/codecoshauni/pen/QoPLjW11. https://codepen.io/codecoshauni/pen/ZPdyeK12. https://codepen.io/codecoshauni/pen/oVKxbL
Почему у меня в Питоне код работает по разному?Вот набросок кода: https://repl.it/repls/ConsciousBlondElectricity (можно не разбираться в том что он делает, меня интересует синтаксис)Вот примеры синтаксиса, которые работают как ожидаются:https://repl.it/repls/GiantSeveralControlpanelhttps://repl.it/repls/FixedAnnualRuntimeНо в рабочем коде, в первом случае, выдаётся ошибка >if (details is None) or (not 'Bearer token' in details['authextra']):>builtins.TypeError: argument of type 'NoneType' is not iterableИ, во втором случае, >if (details is None) :> principal[u'extra'] = {> u'error': u"Access denied: No Bearer token in authexta"> }> return principal>>> token = details['authextra']['Bearer token'];return не выполняется и код продолжает выполнятся>token = details['authextra']['Bearer token'];>builtins.TypeError: 'NoneType' object is not subscriptableИ вот ещё 3-ий пример: https://repl.it/repls/DependentUnselfishDevelopmentно в рабочем коде> try:> payload = jwt.decode(token, JWT_SECRET)> except Exception as e:> principal[u'extra'] = {> u'error': e> }> return principal>> ...return снова не выполняется и вбрасывается ошибка: "WAMP message serialization error: Object of type 'InvalidSignatureError' is not JSON serializable"https://pyjwt.readthedocs.io/en/latest/api.html#jwt.exceptions.InvalidSignatureErrorПочему так может происходить? Версии Питона 3.6.x что на Repl.it, что и на машине, и примеры синтаксиса проверялись и у себя на машине в консоли с помощью команды python.
Народ, подскажите в чем косяк. Регулярка про автомобильный номер. ВВел на сайте [а-я][0-9]{2}[а-я]{2}ugm с чувствительным кейсом тк сам автоеб и буквы всегда в нижнем регистре, но выдает ошибку. Написал простую прогу, но она внезапно корректно работает. https://ideone.com/4DlDPk чяднт на регексе?
ОП, или сочувствующие, не смог по мануалу разобраться как работает array_rand, сделал одну из задач с помощью mt_rand, но очень хочу разобраться как всё-таки надо было сделать.Мануал читал, честно, так и не дошло.https://ideone.com/UYAeWZ
>>1372438http://sandbox.onlinephpfunctions.com/code/6ec7a8b63f62394bf9896b3a58c4d3e6bb628b0dИ не выключай отображение ошибок
>>1372438Работает - значит норм. Но вообще через array_rand лучше тк тут массив проиндексирован. Если бы он не был индексирован( удали ключи) то у тебя отсекся вариант да тк он был бы 0м. И 6го тупо не было. Представь, что массивы с разным числом значений, которые потом еще и меняться могут . В итоге не высчитывать же тебе все числа? Если через эту функцию то гораздо проще https://ideone.com/Nx5ew5
>>1372489Не в этом дело, я сейчас переписал на регексе с нуля уже другую задачу и все заработало. Странная хрень
>>1353705 (OP)Возникли некоторые вопросы по объекту реализующему ResposeInterface из PSR-7.Вы писали:>Он представляет ответ на HTTP-запрос. В Симфони контроллер получает на вход Request и выдает на выходе Response, а фреймворк уже выводит его содержимое. Это удобно для тестирования, мы можем вызвать контроллер и смотреть, что он там сгенерировал.Этот объект нужен для того, чтобы содержать в себе html-код? При тестировании каким-то образом проверяется его содержимое (html)? Не могу понять.>Обычно это выглядит так: public function indexAction(Request $request): Response{,....return $this->render('template.twig', ['x' => 1, 'y' => 2]);}Получается метод $this->render(), встроенный в контроллер, подставляет наши значения в шаблон. Затем полученный html-код вставляется в поле $body конструктора объекта Response, который мы возвращаем как результат работы контроллера.В каком месте выводить полученный результат?Достаточно написать во фронт-контроллере echo $response->getBody(); ?Например, пусть примерно так у нас выглядит файл init.php, который подгружается в index.php$request = ServerRequest::fromGlobals();$app = new App($request);$response = $app->run();echo $response->getBody();
хаккеры. Я камень. Закончил шарашку по специальности инженер-строитель. корочка ПГС. Как перекатиться в кодера (а то задолбался работать в миллионике за 20к)? щас вот тут с массивами разбираюсь ) и перехожу к следующему разделу.
>>1372446Я вроде не выключал. Где включить и в чем с этим проблема?Спасибо!>>1372451Спасибо!Не очень понял как это работает в мануале, но оказалось что так, как там и было написано -_-
>>1372532самое главное мозги ебать не надо, надо постоянно учить, основы типа переменные, массивы, циклы, функций, операторы и т.д это 5% из всего что надо знать. Теория те же 5% от знаний, применил, уже 10%, чтобы более менее что-то знать надо постоянно кодить. По мере опыта уже сам будешь разбираться и таких вопросов не возникнет
>>1372532https://www.youtube.com/user/TheLukesky1/playlistsВ таком порядке:PHP Start ТеорияPHP Start ПрактикаPHP UP ТеорияPHP UP ПрактикаМимо 3-курс ПГС, но хочеться в ойти... вот вкатываюсь потихоньку...
Котаны, помогите немного по регулярным выражениям. Не пойму как работают группировки.Вот две строки, заменяю:preg_replace( '/{([a-z]+):([^\}]+)}/ ', '(<\1>\2)' , $str); //вариант из учебного пособияpreg_replace( '/{([a-z]+):([^\}]+)}/' , '(<$1>$2)' , $str); // мой вариантВ чем отличие этих двух вариантов подстановки? А еще в том учебном фреймворке если я из '(<\1>\2)' или '(<$1>$2)' убираю первую "переменную" подстановки: <\1> или <$1> - то все ломается. Указание "переменной" в скобках <> - указывает на то что не нужно использовать данные из этой переменной, вроде. Но зачем тогда ее вообще указывать?
>>1373172Не то что бы фикс - изначально в строке пособия было указано так:preg_replace('/{([a-z]+) : ([^\}]+)}/', '(?P<$1>$2)', $route); - я подумал что "?P" - ничего не значит. Однако ток сейчас прочел такое: "Указать обратную ссылку на именованную подмаску можно с помощью (?P=name)". Но в варианте пособия нет "=";Чет я запутался.
>>1373280У ЖС-макак свой манямирок, не спорь с ним. Через 3 года то же самое говорить будет. Только названия фреймворков поменяются.
>>1373272Такое требуют обычно только в днищеконторах, где ты будешь и за папу и за маму, и за админа, и за бухгалтера. И платить тебе будут как эникею.
>>1373335Руби умир. Нода нахрен никому нинужна. У пхп из альтернатив разве что питон, но он как пишут помедленнее. Но что важнее - вакансии.
>>1373333Нет, просто ты только по ЖС ситуации на рынке видишь. ПХПшники же больше по ПХП видят. Зачем вообще лезть с советами, особенно в шапку, если и без тебя разберутся?
>>1373335>делать ставку на пхпМне вообще как-то насрать. Надо будет на питон или ещё куда перееду - примерно те же яйца. Просто на ПХП хайп уже прошёл, а у питона сейчас идёт.
>>1373370>и у вас так будет через год дваРыночек по регионам несколько отличается, как по фреймворкам, так и по наборам требуемых скиллов.
>>1373370>Так я фулстакТак у вас и требования почти минимальные. У фуллстаков говнокода больше всего.
>>1373379Причем тут это вообще, я лишь сказал, что сейчас без фронта никуда. Но вы можете продолжать обучатся вебу по канонам 2013 года. Я уверен шапка не менялась с того времени
ОП или аноны, я что-то вообще залип в решении этой задачи.Толкните хоть в нужное русло.Как сделать так, чтобы случайное слово выбиралось из пяти разных массивов?
>>1373395Да просто перемешивай массивы каждый проход и всё. https://www.php.net/manual/ru/function.shuffle.php
>>1373446На 7 строке ошибка - палиндром пишется через "а".На 4 строке он функцию не знает. Как так случилось и почему? Я в душе не ебу что ты за говносборку PHP там поставил.
>>1373446Вместо $textLower[$i] != $textLower[$lenghtText-$i] должно быть$textLower[$i] != $textLower[$lenghtText-$i-1]
>>1373468>На 7 строке ошибка - палиндром пишется через "а".аха ха -ха, теперь то заработает нет =( > Я в душе не ебу что ты за говносборку PHP там поставил.на ideone php7.1.0, как я ее могу поставить?Пробовал через консоль на винде открыть (7.3.3php) - не выходит видимо что то не так делаю, >>1373474Действительно, спасибо за замечание. Но проблема в том что анон выше написал. Даже без цикла переменные выводить не хочет.
>>1373486Затестил в другой песочнице - заработало. Правда заданный текст пришлось на транслите писать.Всем спасибо
>>1373499Я уже с кирилицей тебе сделалhttp://sandbox.onlinephpfunctions.com/code/0a983d62fd8270da652bab28afb5242a22b94b1a
Я тут пытаюсь приступить к задачке тестхаб. Возник вопрос по таблицам БД.Есть таблица complited_test(список тестов которые прошёл пользователь) и она ссылается на test. Но как бы можно обойтись без этой связи. complited_test ссылается на student_answers(список вариантов ответов пользователя). Варианты ответов ссылаются на вопрос, которому они принадлежат. Вопросы ссылаются собственно на тест из которого взяты. Для того что б получить строку данных из complited_test и test нужно составить сложный запрос для всей этой цепочки.Собственно вопрос. Какой путь решения будет верным. Делать сложный запрос по всей цепочке. Или оставить лишнюю связь и получать ответы простым запросом.
>>1373534нет, не одноэто нужно для того, чтобы решить ахуительную задачку на переворачивание строки на собеседовании и кучу других
>>1373540Ну на латинице вроде работало все, почитаю об этом>>1373541Я правильно понимаю, что основная библиотека php это лишь малая часть того, что должен знать разработчик? И на собеседованиях на джуна будут гонять по алгоритмам? Нужно ли заучивать функции с гайда для нубов, ведь если с ними работать они со временем запомнятся, и достаточно знать что такие существуют?
>>1373548>что основная библиотека php это лишь малая часть тогоТы про SPL? Так-то это классика, это знать надо. Какой же ты погроммист без знаний структур данных?
>>1373484Ты в консоли вместо Subl печатаешь Slub, о чем тебе и говорит сообщение. Для проверки можно попробовать распечатать файл командой type c:\Subl\... и убедиться, что ты пишешь путь неправильно. При наборе команды стоит использовать клавишу Tab для автодополнения имен папок и файлов.
>>1373518На стандартной для Laravel орм планирую работать.Eloquent — реализация шаблона ActiveRecord.
>>1373172Повторю снова свой пост, может кто поможет: Котаны, помогите немного по регулярным выражениям. Не пойму как работают группировки.Вот две строки, заменяю:preg_replace( '/{([a-z]+):([^\}]+)}/ ', '(<\1>\2)' , $str); //вариант из учебного пособияpreg_replace( '/{([a-z]+):([^\}]+)}/' , '(<$1>$2)' , $str); // мой вариантВ чем отличие этих двух вариантов подстановки? А еще в том учебном фреймворке если я из '(<\1>\2)' или '(<$1>$2)' убираю первую "переменную" подстановки: <\1> или <$1> - то все ломается. Указание "переменной" в скобках <> - указывает на то что не нужно использовать данные из этой переменной, вроде. Но зачем тогда ее вообще указывать? Не то что бы фикс - изначально в строке пособия было указано так:preg_replace('/{([a-z]+) : ([^\}]+)}/', '(?P<$1>$2)', $route);- я подумал что "?P" - ничего не значит. Однако ток сейчас прочел такое: "Указать обратную ссылку на именованную подмаску можно с помощью (?P=name)".Но в варианте пособия нет "=";Чет я запутался.
>>1373595>Чет я запутался.Просто мозги ебёшь.Одно дело, когда у тебя загововки улетают в вывод и ты не понимаешь где как у меня недавно, и другое дело дрочить какое-то пособие до основания и спрашивать у левых людей почему там именно так написано.
Как запустить из php-файла другой заданный php-файл так, будто его запросили из браузера?То есть, нужно, чтобы у него были GET/POST параметры, куки, вся хуйня как обычно, но фактически такой запрос не выполняя.Не тупо в консоли, а именно будто пришел пользовательский запрос.
>>1373756Так из браузера и запрашивай. На локалхост положи его и вызывай.Сам так недавно делал чтобы API проверить.
>>1373595твое игнорирование пособия сразило меня наповал. зачем ты вообще его читаешь в таком случае.в пособии тебя судя по всему учат делать регулярки из регулярок.в таком ключе разумеется все что написано имеет значение.ты список вида {name:group} превращаешь в регулярки вида (?P<name>group) которые потом можно опять использовать в функциях preg(?P<name>(...)) и (?P=name(...)) разные способы сделать одно и тоже в разных регулярных синтаксисах, я в пхп использую ?P<name> - другой вариант по моему не работаетэта фишка потом позволит тебе брать уже что-то следующее, парсить и получать массив с именноваными ключами для групп. это скорее всего какой то туториал как сделать роутер по типу "fast route"
>>1373766>>1373756Разобрался. В пыхе же есть встроенный веб-сервер (и похоже этот ублюдок охуеть какой быстрый).Можно, когда нужно, оперативно поднять сервер на левом порту и в нужной папке.Узрите же великую магию: https://pastebin.com/QXzR8sy4
>>1373769Да именно это роутер.>>твое игнорирование пособия сразило меня наповалДело в том, что именно этот момент и не разъяснен. Просто дан как данность. Спасибо.
>>1373791P.S. - теперь я рили понял. В комментах к туториалу неверно эту строку истолковали. И я перерыв документацию по регуляркам - не нашел того о чем они писали.Впрочем плюс в том что регулярных я до этого косяка не знал. А так волей-не волей пришлось плотнее ознакомиться. Спасибо еще раз.
Пагни, помогите с symfony и doctrine2Я понимаю, что лезть руками в базу и вручную добавлять новые поля в таблицу это неправильный способ работы с доктриной, но чисто в учебных целях как сделать следующее: допустим в существующую таблицу добавлено новое поле напрямую, без участия доктрины. Как мне дать знать об этом доктрине и перегенерировать entity? В доке https://symfony.com/doc/current/doctrine.html есть следующий рецепт: If you prefer to add new properties manually, the make:entity command can generate the getter & setter methods for you: php bin/console make:entity --regenerateIf you make some changes and want to regenerate all getter/setter methods, also pass --overwrite.Но после запуска этой команды entity файл на меняется. ЧЯДНТ?
>>1373834Что тебе мешает руками дописать нужные поля и аннотации в entity? > Но после запуска этой команды entity файл на меняется. ЧЯДНТ?А ты добавил overwrite? Плюс, я подозреваю, эта штука перезапишет файл и может стереть какие-то методы, которые ты туда добавлял.Вообще, Доктрина очень универсальная и поддерживает 2 модели: 1) источник правды - база данных. Ты делаешь миграцию БД, а потом добавляешь в сущности нужные поля.2) источник правды - модели. Ты добавляешь нужные поля и аннотации и из них генерируешь миграции, которые вносят нужные изменения в БД.
>>1367259https://regex101.com/r/qF7vT8/192Нужна помощь с регуляркой. Как учитывать общее количество символов в группе если получается разброс от одного до трех символов в каждой группе
Оп, глянь, как будешь свободен, финальное задание по верстке твое "Webpaint". Остальные аноны тоже можете указать на ошибки.https://codecoshauni.github.io - сама страница.https://github.com/codecoshauni/codecoshauni.github.io - ну и код.
Господа, нужен ваш совет.Нужно сделать редактируемую таблицу, а введенные в таблицу данные отправлять в базу.Я так понимаю саму таблицу и отправку данных только с помощью js можно сделать?
>>1353705 (OP)Вопрос по HTML и CSS...Задача: сделать вывод текста и текстареи - в две колонки,как тут: https://css-live.ru/articles/css-gridy-css-kolonki-%E2%99%A5.htmlно так, чтобы при изменении размера текстареи, изменялся и размер line-height,и чтоб не ровно на половину страницы разделялось, а с небольшим отступом.Вопрос - как правильно сделать?
>>1373892>Что тебе мешает руками дописать нужные поля и аннотации в entity? Лень конечно же. Думал доктрина сделает это за меня при regenerate>А ты добавил overwrite?Да>Плюс, я подозреваю, эта штука перезапишет файл и может стереть какие-то методы, которые ты туда добавлял.Да, знаю, но я ничего в файл не добавлял, поэтому значения не имеет
>>1373769Раз ты помог мне, подскажи еще с регулярками. Меня эта тема выносит уже.СмотриЯ выполняю этот код на ideone$str = 'admin/delete/{id:\w+}';$newstr = preg_replace( '/{([a-z]+):([^\}]+)}/' , '(?P<\1>\2)' , $str);echo $newstr; результат : admin/delete/(?P<id>\w+)Все как ты и объяснил. Все логично.Я выполняю эти же строки на своем сервере и в результате получаю в результате: admin/delete/(?P\w+). Куда девается '<id>' ? Что за дела?Сервак OpenServer, версия PHP 7.2.10 Выполняю в отдельном файле. То есть ничего на этот код не влияет.
Как в phpunit передать некоторые параметры?Есть интеграционные тесты, нужно передать такую инфу, как логин/пароль.
>>1373952У меня была такая же проблема. Ты пытался написать код разделяя на очень много промежутков, которые могут быть при написании телефона. Твой код:^\s?(\+\s?7|8)\s?[\s-]?\(?\s?\d{3,4}\s?\)?(([-\s]){0,3}(\d{1,3})){0,}$Есть в коде лишние скобки и тут например вместо ([-\s]){0,3} можно было бы написать [-\s]{1,3} ну или вообще [-\s]+ ну и тд, упрощать и упрощать. В общем мой код для данной задачи такой: ^([ +]+7|\s?8)([() -]?\d){10}$. Тут есть начало кода ^([ +]+7|\s?8) потом середина, которая либо есть, либо её нету [() -]? и конец это. Помогите понять как решать задачу по регулярке: https://ideone.com/yxFIpHЯ никак не могу понять почему он выдаёт 892754-54305 и не считывает дефис посередине\d)$.
Хотел создать ib. Кхм... "Парашу" на бесплатном хостинге 000webhost. Взял движок Kusaba X, установил, но вот проблема. У меня вообще не отображается стиль на глав.странице, а вот с админ панелью почти все хорошо, стиль есть, правда правила нельзя отредактировать, и нельзя добавить доску.В чем может быть проблема?Хотелось бы верить, что это дерьмо заработает :d
Аноны, подскажите, как сделать перенаправление с, допустим, /randomfile.php обратно на index? По примеру как это в phpmyadmin. Долго ковырял это приложение, так и не понял как оно перенаправляет
При конфигурации движка lainchan вылезает ошибка "Unknown column 'uri' in 'order clause' "Что делать?
>>1374247Обычно так не делают. Ведь когда твои тесты будет запускать CI сервер, он дописывать пароли не будет. Но есть варианты: - сделать кастомный конфиг, в него вписать пароли. Он не комитится в гит, а туда коммитится лишь образец (config.ini.example) и каждый разработчик из образца делает себе конфиг со своими паролями- передавать логины и пароли через переменные окружения: APP_XYZ_LOGIN=123 phpunit
>>1374121Тогда есть еще вариант переместить куда-то файл и попросить Доктрину сгенерировать его заново. Там наверняка есть опции для генерации только одного файла.Вообще, я тут пару минут погуглил и понял, что ты все перепутал. make - это команда из MakerBundle, она, как я понимаю, годится только для создания файлов с нуля.Но у Доктрины есть инструменты для синхронизации кода и БД. Набери php bin/console list | grep doctrine (показать все команды и оставить только имеющие слово doctrine) и ты увидишь кучу полезных команд, например: doctrine:mapping:import Imports mapping information from an existing databasedoctrine:migrations:diff Generate a migration by comparing your current database to your mapping information.doctrine:schema:update Executes (or dumps) the SQL needed to update the database schema to match the current mapping metadataИзучи их и посмотри, нет ли там чего-то нужного.
>>1374206Браузер воспринимает результат вывода скрипта как HTML а <id> - как тег. Решение - используй var_dump вместо echo или ставь правильные заголовки: header("Content-Type: text/plain; charset=utf-8");Это заставит браузер воспринимать то, что выводит твоя программа, как обычный текст, а не HTML.
Вот допустим у нас выбросилось исключение в каком-то классе приложения. Ведь не хорошо показывать пользователю подробности ошибки. Получается нужно показать ему заглушку, а ошибку записать в лог и завершить программу. Ах, да. Ошибки и предупреждения нужно каким-то образом превращать в исключения.Мой вариант решения это проблемы, что скажете?Допустим у нас есть фронт-контроллер, который расположен в public/index.phpОбъявляем обработчик ошибок set_error_handler, в нём превращаем предупреждения/ошибки в исключения.Затем оборачиваем исполняемый код в try catchtry { // Код выполняемого приложения} catch (Throwable $e) { // Запись в лог // Загрузка страницы ошибки}
>>1353705 (OP)Не могу разобраться с рутингомхочу чтобы при нажатии на линк (пик 1) у меня открывалась форма поста в той же секции, где на линку нажали, а не в начале страницычто для этого нужно сделать?сама форма (пик 2)вопрос скорее по верстке, но может кто подскажет
>>1374466>>1374704Спасибо большое.ток var_dump не отображает все равно.Помогла функция htmlspecialchars();
На основе прикрепленных данных (resultset.csv) которые можно скачать здесь : https://mega.nz/#!UsARmI7T!wBBsHHKtJVPRB6ontDHRpsX7QAVq_DTUh4pY4aQaoQ4нужно, создатьсоответствующую структура базы данных MySQL и импортировать данные в нее.PHP скрипт должен выбрать 10 последних заголовков из базы данныхстатьи, предполагая, что каждый заголовок должен исходить из разныхкатегорий (категории в списке из 10 названий не могут повторяться).Полученные записи должны отображаться на странице в формате"категория - название - дата".
>>1374705Можно и так, вполне хороший вариант. Если что, у меня это описано в уроке: https://github.com/codedokode/pasta/blob/master/php/exceptions.md
>>1374364Открой инструменты разработчика в браузере (Ctrl + Shift + I), вкладку "Сеть" и перезагрузи страницу. Посмотри, нет ли ошибок загрузки каких-то ресурсов. Если потребуется, почитай про инструменты разработчика.>>1374792Header в начале кода бы тоже помог. Ну хоть освоил функцию htmlspecialchars().>>1374757Если ты хочешь, чтобы форма появлялась на той же странице без перезагрузки, то тебе и нужна одна страница, а не две. Также нужен яваскрипт или продвинутый CSS (псевдоселектор :target либо невидимый input type="checkbox" ). Например: - можно сделать форму скрытой и открывать яваскриптом при нажатии на кнопку (а ссылку убрать)- попробовать использовать тег HTML5 details, который делает примерно то, что нужно- можно сделать в кнопке невидимый input type="checkbox" и показывать форму при галочке в нем. Примеры похожих штук, где что-то показывается/скрывается: https://webref.ru/layout/pseudo-class-checked/tabs https://habr.com/ru/post/174029/
Делаю задачки по гайду из ОП-поста, дошёл до работы со строками а ideone отказывается работать с mb_string (хотя в гайде написано что он установлен на ideone). Пробовал repl.it и phptester, нормально на моём ведре работает только ideone а возможности сесть за пк нет. Может есть какой-нибудь нормальный компилятор для ведра?
Аноны, есть у кого решение этой задачки?Я так сделал, но кажется что не совсем правильноhttp://sandbox.onlinephpfunctions.com/code/f444a95132632b1a6ee1253a93e8cad13a903b53
>>1374280Твое не отлавливает скобки и с таким подходом можно каждую цифру оборачивать в скобки и она пройдет
Как запилить нечеткий поиск с ограничениями? Нужно найти (в sql) все записи, содержащие "строка" или отличающиеся от нее на <=N символов. Например, если N=4, при поиске "строка" должны находиться "строки", "стрАка" (1 <= 4), "срака" (2 <= 4) и "строковой" (4 <= 4), но не должны находиться, например, "строка-массив" (7 > 4) или "строка12345" (5 > 4). У LIKE есть процент, означающий 0, 1 или более символов - это все подстроки в строке, есть _ - это 1 символ, а как мою хуйню запилить, я даже хз.
>>1375156Бамп вопросу. Все чаще симфони на слуху стал быть, да и yii опять чето мелькать начал.Стоит ли вкатиться в эти фреймворки или лары достаточно и потратить силы на изучение чего-то другого?
>>1375100ты опять делаешь слишком длинный код. Вот посмотри наглядный пример рабочего кода https://regex101.com/r/qF7vT8/196
>>1375291Посдскажи, не могу понять (я другой анон). В твоем коде проверка символов идет так (после 7или 8) скобка, тире пробел затем цифра. А если человек дебил и скажем поставил скобку после последней цифры? Например так 8 (888)(8888888) теоретически это неправильно и должно отсеяться тк последняя скобка не проверяется. Добавив проверку на знаки после цифры можно обойти это. Может я просто переусложняю без дела? И второй момент, при поиске первых цифр можно написать так ^(\s7или\s8) хз как горизонтальную линию с телефона ставить. почему ты ищешь [ 7]* в таком виде?
Парни, посоветуйте как правильно делается подобное в symfony:у каждого сайта есть какие-то элементы, общие для всех страниц - это, например, шапка и футер. Если данные для шапки и футера подтягиваются из базы логично сделать так, чтобы эти данные были доступны в любой шаблоне сразу или любом контроллере, чтобы дальше передать их в шаблон. Как этот сделать без дублирования кода в каждом из контроллеров? Нужно добавить эти данные как глобальную переменную? Или как-то инжектить в каждый контроллер?
>>1374702>Изучи их и посмотри, нет ли там чего-то нужного. Спасибо, анончик. Очень полезно! Справился с задачей.
>>1375048Тут всё проще. Сначала надо выкинуть весь мусор - то есть всё, что не является цифрамиПотом проверить длину строки и если больше 11 то забраковатьЕсли 11, то проверить какая цифра первая - если не 7 или 8 то забраковатьЕсли 7 то поменять на 8
>>1375312вот смотриhttps://symfony.com/doc/current/templating/global_variables.html#referencing-services
>>1375354А почему не должен? 11 цифр есть. И если ввод никак не ограничивается на стороне клиента то может быть и такое - клавиша залипла, например, тачскрин заглючил.
>>1372026>$symbol2= mb_substr( $text, -$i-1,1);Неплохо, я бы даже сказал элегантно. А я доп. переменную вводил сразу, не мог допереть как с конца нормально индексировать.
>>1371655>2. Как мне сделать так, что бы если слово не было палиндромом ехо после цикла не выводилось?Можно вызовом exit() сделать:if($first!=$last){echo "Not palindrom\n";exit(); }
аноны, подскажите где можно найти человека который бы писал небольшие php халтурки за небольшие деньги, и так что бы не кинули?
Анончики, где ошибка, впервые сталкиваюсь с ошибкой 'break' not in the 'loop' or 'switch' contexthttps://ideone.com/WeE8Hi
Может не в тот тред, но он вроде тут самый адекватный.Вот веб-студия. Допустим, я пойду туда устраиваться. Попрошу 80к. Оформят наполовину в серую, итого для конторы я обойдусь в 100к в месяц. Допустим, я чистый фронтендер. За две недели могу слепить сайт из шаблона от дизайнера. Сам шаблон дизайнер будет рисовать те же условные 2 недели. и бек-энд будет делать отдельный человек за 2 недели. Плюс ПМ, он же менеджер по работе с клиентами, он же притаскивает новые заказы и тому подобное. Итого - 4 человека будут работать 2 недели ради одного сайта. Если каждый получит 100к (до налогов), то за 2 недели заказчику это всё обойдётся в 200к. Плюс пренда офиса, уборщица-бухгалтер-печенки-кофемашина. Плюс хоть какая-то прибыль для владельца. Итого, обычный сайт будет стоить от 300к рублей. Я не понимаю этого. Неужели кто-то платит такие деньги? Или там берут количеством и дизайнер только слегка перерисовывает готовые шаблоны, фронт натягивает очередной шаблон на вордпресс, а бек пилит мелкие свистелки? По паре сайтов в день. С утра ты пилишь сайт-визитку на вордпрессе, после обеда магазин на опенкарте, назавтра нужно запустить три лендинга на шаблонах, так что ли?
>>1375571http://docs.php.net/manual/ru/control-structures.break.php >break прерывает выполнение текущей структуры for, foreach, while, do-while или switchможешь использовать exit()лучше переписать скрипт без подобных вещей.
>>1375635Думаю если дизайн пилит дизайнер, фронтенд - фронтендер, а бэк - бэкэндер, то продук определённо годным будет.Во-первых, это может быть шаблон на продажу.Во-вторых, это может быть сайт для больших дядей.В-третьих, это может быть тупа аутсорс на забугор.В-четвёртых, есть разные системы и проекты, и это даже необязательно может быть обычный сайт - какая-нить система автоматизации и прочий софт с годным дизайном, фронтендом и бэком.Ну и прочие фантазии.
>>1375636Спасибо, поясни как это нормально сделать. Мы же проверяем функцией if, а если не соответствует прекращаем проверку на одном из этапов
И пожалуйста анончики, старайтесь новичкам вроде меня не давать решения, которые отходят от объема функционала из методички. Все таки с начала пусть и через жопу стараемся решить с чем есть, а потом уже в оптимизацию идти
>>1375636Переписал с exit. Теперь ошибка в строке https://ideone.com/m02OaI. Упростил вырезав плюс, вроде получилось.https://ideone.com/xMO55G
>>1375635Давай я тебя верну на землю. Вот, допустим есть веб-контора. В ней программисту платят 30-40 к в месяц, с налогами пусть это 60. В итоге 3 000 р расходов за рабочий день, который мы естественно удлиняем как можем. Менеджер тратит 4 часа своего времени на переговоры и обсуждения. Покупается готовый шаблон долларов за 20. Берется CMS и программист, пыхтя, за день натягивает на нее шаблон. Затраты ты можешь оценить. Там, правда, еще деньги нужны на рекламу. Ну то есть существуют разные сегменты. Есть студии, где бизнес-аналитики будут чертить флоучарты, а ведущие разработчики проектировать бекенд на современном фреймворке и изобретать штуки, которых вообще в паблике нету, а есть бюджетный сектор, где все делается максимально экономно.Я помню, как-то у меня спрашивали, сколько стоит создание сайта, а потом сказали, что есть компания, которая делает сайт за 3000. А что, почему бы и нет.Что касается стоимости, то на высококонкурентном рынке маржа получается минимальной, и получается, значительная часть денег заказчика идет на расходы, а не в карман владельцу.Если заказчику нужно то, что можно сделать за день - он идет в бюджетную студию. Если у него высокие запросы - вполне возможно, что с него возьмут эти 200к или больше. Если у него работы на человекогоды - он сам начинает нанимать разработчиков. Да и 200к не большие деньги же, особенно для организации.Но тут конечно есть свои нюансы. Например, широко практикуется апселлинг - клиент хотел сайт, а мы продаем ему еще и продвижение по завышенной цене.Если тебя интересует, как живут именно студии верхнего сегмента, то читай описание проектов Студии Лебедева ( https://www.artlebedev.ru/everything/ ), они очень интересно все описывают, Советы у Бюро Горбунова ( https://bureau.ru/bb/soviet/ ) ну и можно посмотреть, сайты каких-то студий из топа ( http://www.ruward.ru/index-ruward/united-web-rating-2018/ ) - вдруг они что интересное выкладывают.Я должен предупредить, работать в студиях нижнего сегмента не очень интересно и не очень легко. Перфекционист там вообще умрет в первый же день. Не стоит наверно туда особо стремиться.
>>1375312Скопипащу ответ из старого поста: https://phpclub.tech/pr/res/1353705.html#1359951Обычно делают отдельно шаблон для "лейаута" (шапка/подвал) и "контента". Лейаутов может быть несколько - например, один для морды, другой для админки. Как передавать параметры для лейаута? Тут есть варианты:- руками копипастить их в каждый метод каждого контроллера (боль)- наследовать контроллеры от базового класса и в нем формировать данные. У базового класса может быть метод вроде "поменять тайтл текущей страницы". Плюс - инкапсуляция, трудно передать что-то неправильное, например, не-строку.- передать эти данные во вью до или после выполнения контроллера, без использования наследования. Или передать в контроллер.- сделать "контроллер для лейаута" и в нем формировать данные для лейаута. У "контроллера лейаута" могут быть вспомогательные методы вроде "поменять тайтл текущей страницы".В фреймворках готового решения нет. Каждый изобретает сам.Добавлю, что стоит держать в уме, что лейаутов может быть несколько (сайт, админка) и у них могут быть разные наборы параметров. Идея Симфони с прописыванием глобальных переменных в конфиге мне не очень нравится, но какой-то хелпер так передать вполне допустимо.
>>1375693Раз уж такая тема, то тоже спрошу:вот у меня есть простой самописный фрейм, который роутит роуты, передаёт зависимости, имеет базовые Реквест и Респонс. Ну на коленке собираю для изучения темы.Не могу решить как там представление реализовать. Есть вариант через класс Представления обрабатывать лайеры с шаблонами и контентом, и отдавать это всё строкой в Респонс несколько вычурно и нелепо получается, конструкция вида $Response->body = $View->reder(бла-бла-бла), или лучше вообще его не использовать и тупо выводить рендером в любом месте, правда мне не очень это по нраву - я хотел бы чтобы вывод был в одном месте, в конце приложения.Есть какие-то намёки как это половчее сделать?
>>1375690Спасибо за ссылки, посмотрю.>Если у него высокие запросы - вполне возможно, что с него возьмут эти 200к или больше. Но верхушка - это процентв 10-20 рынка, не более, так ведь? Почему тогда так дико популярны фреймворки? Сделать сайт на вордпрессе можно за вечер, покликав мышкой и не оскверняя мозги киким-то там пхп и жаба-скриптом вообще. Сделать то же самое на условном Ларавеле займёт гораздо больше времени даже у профи. Если ент спроса, то людей, работающих с фреймворками (а тем более с машин лёрн, биг дата, блок чейн, пит буль) должно быть мало. Однако, когда я открываю хх, то у вебов почти все вакансии обязывают знать хоть один фреймворк.
>>1375713>Сделать сайт на вордпрессе можно за вечерТак там нормальных интерактивных сайтов почти и нет - вукомерс, который всё равно кодить придётся, и лэндосы, которые суть - один жаваскрипт.
>>1375713Так на вордпрессе, что не делай, получится блог. CMS - это для случаев, когда тебе нужен именно ее функционал, плюс может какие-то готовые плагины + готовая или своя тема + немного написанных тобой кастомных плагинов. CMS - это в первую очередь настройка готового решения через админку. Если же твою задачу вордпресс не решает, и нужно писать много кастомного кода, то писать будет выгоднее на фреймворке, так как это удобнее, быстрее и надежнее. Я сомневаюсь, что ты на вордпрессе сделаешь что-то сложное и нестандартное, а даже если и сделаешь, то будешь постоянно плеваться.Ну банальный пример: в Laravel есть ORM на основе ActiveRecord, в Symfony - Data Mapper. Что насчет вордпресса? Там этого банально нет. Там даже миграций БД по моему нет. Нет тестов, нет нормального деплоя. То есть CMS заточены под создание решений по определенному шаблону, где ты можешь только менять отдельные настройки. Фреймворки - для произвольных кастомных, нестандартных решений.Что касается магазинов, то я работал над ними, и могу сказать, что все крупные магазины используют самописный код. Им нужен уникальный функционал, которого нет в коробочной CMS, и делать его на CMS просто менее удобно, чем на фреймворке. Ну и оптимизировать свой код проще, например, чем пытаться оптимизировать CMS. Например, коробочные CMS часто плохо работают с большим кол-вом товаров и большой нагрузкой. Так как в них главное не производительность, а возможность настройки через админку. Но крупному магазину нужно не это. > Сделать сайт на вордпрессе можно за вечер, покликав мышкой и не оскверняя мозги киким-то там пхп и жаба-скриптом вообще. Сделать то же самое на условном Ларавеле займёт гораздо больше времени даже у профи.В такой ситуации естественно, выгоднее, делать на вордпрессе. Но большой сложный магазин ты так не сделаешь. И Яндекс-такси не сделаешь. И инстаграм. И альфа-банк. И госуслуги.> Однако, когда я открываю хх, то у вебов почти все вакансии обязывают знать хоть один фреймворк. Значит, они решают задачу, которую средствами CMS не решить. Ты бы посмотрел, чем компания занимается, какие проекты делает.
Есть функция, которой передаешь время ("17:42"), а она возвращает ДейтТайм этого времени в ближайшем будущем? То есть если сегодня еще будет это время,то со сегодняшним числом, иначе с завтрашним?
>>1353705 (OP)не могу в yii 2 не открывается даже стартовая страница-примерхотя все требования на сервере естьAn Error occurred while handling another error:exception 'yii\web\HeadersAlreadySentException' with message 'Headers already sent in An Error occurred while handling another error:exception 'yii\web\HeadersAlreadySentException' with message 'Headers already sent in E:\openserv\OSPanel\domains\ex\config\web.php on line 1.' in E:\openserv\OSPanel\domains\ex\vendor\yiisoft\yii2\web\Response.php:366Stack trace:#0 E:\openserv\OSPanel\domains\ex\vendor\yiisoft\yii2\web\Response.php(339): yii\web\Response->sendHeaders()#1 E:\openserv\OSPanel\domains\ex\vendor\yiisoft\yii2\web\ErrorHandler.php(135): yii\web\Response->send()#2 E:\openserv\OSPanel\domains\ex\vendor\yiisoft\yii2\base\ErrorHandler.php(111): yii\web\ErrorHandler->renderException(Object(yii\base\ErrorException))#3 [internal function]: yii\base\ErrorHandler->handleException(Object(yii\base\ErrorException))#4 {main}Previous exception:exception 'yii\base\ErrorException' with message 'session_start(): Cannot send session cookie - headers already sent by (output started at E:\openserv\OSPanel\domains\ex\config\web.php:1)' in E:\openserv\OSPanel\domains\ex\vendor\yiisoft\yii2\web\Session.php:137Stack trace:#0 [internal function]: yii\base\ErrorHandler->handleError(2, 'session_start()...', 'E:\\openserv\\OSP...', 137, Array)#1 E:\openserv\OSPanel\domains\ex\vendor\yiisoft\yii2\web\Session.php(137): session_start()#2 E:\openserv\OSPanel\domains\ex\vendor\yiisoft\yii2\web\Session.php(612): yii\web\Session->open()#3 E:\openserv\OSPanel\domains\ex\vendor\yiisoft\yii2\web\Session.php(751): yii\web\Session->get('__flash', Array)#4 E:\openserv\OSPanel\domains\ex\widgets\Alert.php(53): yii\web\Session->getAllFlashes()#5 E:\openserv\OSPanel\domains\ex\vendor\yiisoft\yii2\base\Widget.php(140): app\widgets\Alert->run()#6 E:\openserv\OSPanel\domains\ex\views\layouts\main.php(65): yii\base\Widget::widget()#7 E:\openserv\OSPanel\domains\ex\vendor\yiisoft\yii2\base\View.php(348): require('E:\\openserv\\OSP...')#8 E:\openserv\OSPanel\domains\ex\vendor\yiisoft\yii2\base\View.php(257): yii\base\View->renderPhpFile('E:\\openserv\\OSP...', Array)#9 E:\openserv\OSPanel\domains\ex\vendor\yiisoft\yii2\base\Controller.php(399): yii\base\View->renderFile('E:\\openserv\\OSP...', Array, Object(app\controllers\SiteController))#10 E:\openserv\OSPanel\domains\ex\vendor\yiisoft\yii2\base\Controller.php(385): yii\base\Controller->renderContent('<div class="sit...')#11 E:\openserv\OSPanel\domains\ex\controllers\SiteController.php(64): yii\base\Controller->render('index')#12 [internal function]: app\controllers\SiteController->actionIndex()#13 E:\openserv\OSPanel\domains\ex\vendor\yiisoft\yii2\base\InlineAction.php(57): call_user_func_array(Array, Array)#14 E:\openserv\OSPanel\domains\ex\vendor\yiisoft\yii2\base\Controller.php(157): yii\base\InlineAction->runWithParams(Array)#15 E:\openserv\OSPanel\domains\ex\vendor\yiisoft\yii2\base\Module.php(528): yii\base\Controller->runAction('', Array)#16 E:\openserv\OSPanel\domains\ex\vendor\yiisoft\yii2\web\Application.php(103): yii\base\Module->runAction('', Array)#17 E:\openserv\OSPanel\domains\ex\vendor\yiisoft\yii2\base\Application.php(386): yii\web\Application->handleRequest(Object(yii\web\Request))#18 E:\openserv\OSPanel\domains\ex\web\index.php(12): yii\base\Application->run()#19 {main}
Хелпер относится к модели в MVC?Можно ли из хелпера обращаться к глобальным переменным? Или он как часть модели ничего не должен знать о пользовательских данных, а получать их только снаружи?Что правильнее?class Controller{ function indexAction() { if (AuthHelper::isAuthenticated()) { $this->view->render('шаблон1'); } else { $this->view->render('шаблон2'); } }}Илиclass Controller{ function indexAction() { if (AuthHelper::isAuthenticated($_COOKIE['student'])) { $this->view->render('шаблон1'); } else { $this->view->render('шаблон2'); } }}
Вскоре после того, как я освоил тесты, и прочитал фразу "Если вы хотите что-то напечатать методом print_r(), var_dump() и типа того - напишите вместо этого тест".Я подумал: "Бля, а внатуре".Теперь, когда надо проверить какую-то хуйню, тупо ебашу тест, там вывожу и заодно делаю какую-нибудь проверку побыстроляну.Итого, я проверил что хотел - и у меня лишний ствол тест появился.Это и называется test-driven development
>>1375887Распаковка аргументов штука прикольная, можно задавать массив объектов последним параметром.Но только 1 раз за метод и только последним.Возвращаемого тайпхинта массива объектов в пыхе нет.Кстати, я тот самый чел, что 2 треда рассирался про дженерики в пыхе и как их можно сделать.В одном проекте даже реализовал.Но понял, что это потребляет больше времени, чем экономит.Теперь тупо делаю это через phpdoc.Автокомпликт работает, это самое главное.Ну а то, что фактической проверки типа возвращаемых значений и аргументов нет - ну что же, приходится забить на это хуй в угоду быстроте разработки.
>>1376037>Это и называется test-driven developmentБлять, вообще это был вопрос.Это и называется test-driven development?
>>1376047Как говорил мой дед: "Сначала пишешь тест, потом пишешь код, пока он не пройдет твой тест" Но меня такой подход ебет, потому что я почти всегда не знаю что хочу, и пишу сразу тесты для контроллера, типа при таких то параметрах вернуть то и то, а при таких ошибку высрать.
Аноны, может поймет кто, что у меня не так? $regexp = '/\s{2,}/u'; $text = preg_replace($regexp, '',$text); $regepx = '/([.?!;:,])(.)/ui'; $text = preg_replace($regexp, '$1 $2',$text); return $text; Первая регулярка проходит, вторая - нет. Ощущение что я ее не правильно написал, но тут все ок.https://regex101.com/r/H2Cwq3/1
Сделал тестовое задание, но реакцию конторы узнать не получилось. Задача:>Сделать RESTful API телефонного справочника c использованием фреймворка Laravel.https://github.com/tsubaku/phonebookЕсли у кого-то есть свободное время, может посмотрите? Что там плохо?
>>1376366Разрешите доебаться. В названии грится RESTful, а у тебя аутентификация походу через куки и сессии, и вообще не понятно нужно ли для этого задания использовать что-то другое. Можно через гварды указывать для каких методов нужна авторизация и получается что не особо много смысла иметь два Number контроллера в разных неймспейсах (это было бы не так важно если бы ты руты замапил без перфикса admin, ну это уже холиварная тема сама по себе). Для джсон ответов кстати очень удобно юзать ларавельские Resources. Контроллер search в неймспейса Ajax опять же не особо нужен, не проще в Number@index ( / url) добавить возможность фильтровать по запросу, например /?name=123&number=456 и возвращать отфильтрованные звонки. Еще не совсем понятно зачем сортировать в пхп а не в бд, и вообще про методы all() лучше забыть.Из такого тестового хз какой вывод можно сделать, там и задания то внятного не было с требованиями, просто ЗДЕЛОЙТЕ, ну ты и сделал
Аноны, я помню, в этом или предыдущем треде шла речь про тестирование приложений с БД, и я дал совет для тестов сделать раздел tmpfs и хранить таблицы БД на нем, но не смог пояснить, как именно это делать. Так вышло, что я случайно наткнулся на интересную информацию в документации Postgres и вспомнил про этот вопрос.В Postgresql есть "табличные пространства": https://postgrespro.ru/docs/postgresql/11/manage-ag-tablespaces (русс.)Они позволяют хранить часть таблиц в определенном месте файловой системы. Соответственно, логика получается такая: - делаем раздел tmpfs, например, в /var/test-database/, даем на него права пользователю postgres. Чтобы он монтировался при старте системы, пишем его в /etc/fstab, если он будет пустой, то память все равно не тратит.- даем пользователю postgres, под которым гоняются тесты, права создавать табличные пространства- создаем в postgres табличное пространство в этой папке- создаем в postgres новую БД под тесты и указываем ей это табличное пространство (CREATE DATABASE ... TABLESPACE = ...)- очищаем тестовую БД, загружаем в неё дамп- прогоняем тесты- дропаем тестовую БД
>>1361773Кстати, для выкладывания сайта можно использовать github sites, если ты готов разобраться с гитом. Это будет удобнее для отладки и проверки сайта, так как там не будет постороннего кода. Можно, например, оценить его вес и скорость загрузки.> Можно ли сделать плавный переход по якорям без JS?В новых браузерах, как пишет анон, есть scroll-behaviour.> Можно ли задать плавное всплывание картинок по нажатию на какую-либо из кнопок?Изучи CSS-переходы (transition) и анимации, и посмотри, есть ли что-то подходящее. Тут трюк в том, что смена некоторых свойств отключает переход или анимацию. Например, смена display с block на hidden. И приходится скрывать элементы каким-то другим способом.> Копирайт всегда должен быть в футере, можно ли их разделить и будет ли это правильно? Я разделил, потому что так в PSD было. С шапкой также сделал.В принципе, можно.> Подписи к заголовкам обрамлять в <h> на пункт меньше или <p>?Если ты про Consectetur, Tritiquet - то там наверно <p>. Если ты про "We are webpaint", то можно сделать h2 или div. <p> - это абзац текста, тут явно не абзац текста.> Почему "margin: 0;" в body не работал и мне приходилось подписывать его к каждому элементу? Если ты про поля по краям окна, то они могут быть заданы не на body, а на html, и не в виде маргина, а в виде паддинга. Стандарта тут нет. Потому надо обнулять и маргин, и паддинг на обоих элементах.Пункты меню стоило слегка подсвечивать при наведении или как-то еще выделять. Также, расскажу хитрость, так как они далеко друг от друга и маленькие, то стоит добавить им за счет паддинга небольшую активную зону вокруг надписи. То есть если даже пользователь ткнул не в саму надпись, а близко к ней, то клик засчитывается. Это облегчает попадание в пункты меню. Иначе надо точно в буквы попадать.Кнопки соцсетей должны реагировать на наведение, например, бледнеть, становиться ярче, еще как-то меняться, ты можешь поискать готовые CSS эффекты. Также, картинки на кнопках очень плохого качества: https://imgur.com/a/WuWquKP в FF66Надо извлечь из PSD более качественные картинки. Я проверил, значки с кнопок можно извлечь даже бесплатным гимпом, без покупки фотошопа. Увы, гимп извлекает их только в расторовой форме.Скорее всего ты потерял полупрозрачность. Там иконки полупрозрачные, то есть там есть частично прозрачные пиксели с альфа-каналом. У тебя же альфа-канала в картинке нет и из-за этого иконки стали с угловатыми краями, а не плавными. Почитай про формат PNG, полупрозрачность и альфа-канал. Для адреса и телефона надо использовать иконки из файла, а не посторонние.Адаптивность под разные разрешения экрана сделана слабо, для галочки. Вот косяки: - если мы уменьшаем ширину окна, то надпись "digital & branding agency based ..." криво переносится - она разбивается на 3 строчки разной ширины. Это из-за наличия там br, который надо либо отключать, либо заменить на что-то получше.- на ширине 700 px меню упирается в правый край окна без отступов, а надпись ниже We Are Webpaint смотрится непропорционально большой. Я бы уменьшил шрифт заголовков до 44 px / 30 px на такой ширине, слегка убавил бы вертикальные паддинги в шапке. Попробуй сам на глаз подобрать размеры, чтобы надписи были бы не слишком большие, и не слишком маленькие, а в самый раз, и чтобы шапка смотрелась пропорционально. - на ширине в 700px блоки Consectetur, Tristiquet разваливаются и выглядят криво- на ширине в 540 px меню проваливается вниз- на ширине 430 px надпись digital & branding agency упирается в края окна, что некрасиво. Вертикальное меню, наверно, тоже не самое удачное решение тут. Лучше наверно сделать его в 2 колонки и сделать расстояние между пунктами больше, чтобы пальцем не промазать. Также, можно сделать кнопку "меню" и спрятать меню за ней, хотя это снижает discoverability пунктов в нем - пользователь о них не узнает.- на маленькой ширине блок Consectetur лучше было бы выстроить вертикально, в 1 колонку, вынеся картинку влево или убрав ее вообще. - на маленькой ширине картинки в портфолио очень мелкие. Удобно ли их разглядывать? Хотя, мне нравится компактность и возможность их всех увидеть на одном экране- На маленькой ширине иконка перед адресом вываливается на отдельную строку- на маленькой ширине иконки соцсетей и телефон слишком близко и пальцем можно нажать не туда. Нужно предусмотреть отступ от телефона до иконок, сам телефон, кстати можно сделать крупнее. Я для эксперимента поставил ему размер 24px, отступы по 20px, выглядит не так и плохо.Надо более тщательно проработать адаптивность. Пока я вижу, что ты просто в паре мест уменьшил размеры блоков и шрифта. Этого недостаточно. Попробуй подумать, как пользователю на маленьком экране будет удобнее пользоваться твоим сайтом. По коду. Иконки принято делать не img, а фоновыми картинками. img используется для картинках в контенте - статьях, например. Тут img подходит для картинок портфолио, может быть для блока Consectetur, но не для остальных мест.Названия css классов должны быть сделаны в одинаковом стиле, а вразнобой. У тебя то минус, то подчеркивания использованы.> title__of__serviceТак длинно, пишут просто service-title. Плюс, тут этот класс вообще не нужен, так как ты можешь использовать стиль .service h3Завязываться в CSS на тег nav не очень хорошо, так как завтра могут добавить какую-то вторую навигацию и твои стили будут ей мешать, придется переделывать. Это плохо.Вместо i.font__light проще было бы выделить жирную часть просто тегом strong.> .service{> display: inline-block;Стоит тут указывать vertical-align.Когда ты используешь transition, стоит явно перечислять анимируемые свойства, чтобы не анимировалось ничего лишнего.Далее, тестировал ли ты кроссбраузерность? Знаешь, где можно генерировать скриншоты? Надо проверить поддержку в разных браузерах. Вот примеры сервисов: - https://developer.microsoft.com/en-us/microsoft-edge/tools/screenshots/ для IE (Не отображает сайты с jsbin)- http://browsershots.org/https://jsbin.com/pofasoviqa/1/edit?output для FF/Chrome (плохо отображают сайты на jsbin)- есть еще browserstack, он они хотят регистрацию, деньги и тдТакже, если что, для FF/Chromium можно найти портабельные версии, которые можно себе установить. С ИЕ так не получится и ради него придется делать виртуалки (по одной на каждую версию - спасибо Майкрософт). Хотя для этой задачи хватит и скриншотов, но для более серьезной работы удобнее иметь сами браузеры.Я бы советовал поделить браузеры на 2 категории: новые и не-новые. В новых браузерах макет соответствует дизайну. В не-новых - может отступать от дизайна, если там нет нужной фичи, но оставаться читабельным. Например, если в браузере нет скругления уголков, то в таком браузере можно их сделать квадратными. ИЕ ниже 8 поддерживать не требуется, как и браузеры старше 10 лет. Картинки в портфолио сделаны в PNG. Посмотри, можно ли их сжать в JPEG без заметных артефактов, чтобы получить меньший объем? Это умеет делать даже бесплатный GIMP.Задавай вопросы, если что-то непонятно.
>>1376037Вообще, мне кажется, что не совсем. TDD - это когда ты получаешь задачу (надо добавить страницу, на которой пользователь может подписаться или отписаться от рассылки), формулируешь требования (пользователь должен иметь возможность подписаться, пользователь должен иметь возможность отписаться, нельзя 2 раза подписаться на одну рассылку итд). Пишешь тесты, проверяющие эти требования. Пишешь код. В отличие от обычного подхода, когда ты сначала пишешь код, а потом перечитываешь задачу и пишешь тесты. У тебя же другой подход: ты подгоняешь тесты под то, что вернет код. Значит, это скорее всего не очень хорошие тесты. Возможно, например, при твоем подходе у тебя в тестах захардкожены какие-нибудь массивы, которые возвращает функция, вместо проверки требований к ней. Не забывай, что тесты проверяют именно выполнение требований. Фраза про var_dump, думаю, относится к случаю, когда ты тестируешь написанный код, расставляя в нем вар-дампы и смотря глазами, что они выведут. Это действительно неудачный подход. Но если ты, например, исправляешь баг, и хочешь что-то сдампить, то тут тест вместо этого писать не надо. >>1376041Если тебя волнует проверка типов, можно по-старинке, циклом foreach проверить. А подробности про типы указывать в phpDoc.> Но понял, что это потребляет больше времени, чем экономит.Получил ценный опыт.
>>1372521>>1375943>> Он представляет ответ на HTTP-запрос. В Симфони контроллер получает на вход Request и выдает на выходе Response, а фреймворк уже выводит его содержимое. Это удобно для тестирования, мы можем вызвать контроллер и смотреть, что он там сгенерировал.> Этот объект нужен для того, чтобы содержать в себе html-код? При тестировании каким-то образом проверяется его содержимое (html)? Не могу понять.Да, содержит. И упрощает тестирование не только этим. В чистом PHP у программы нет явно определенных входных и выходных данных. Данные запроса она берет из глобальных переменных, а результат выводит куда-то наружу через echo. И это неудобно и при разработке, и при тестировании. Вот, допустим, мы хотим написать функцию, которая что-то определяет по входным данным. Как описать, что ей нужны эти данные? Тут-то нам и поможет реквест: function getPageName(Request $req): string {}Теперь явно видно, что использует функция. И это удобно при тестах, мы просто создаем временный объект Request, передаем ей, и это никак не влияет на остальной код. А если бы мы использовали глобальные переменные вроде $_GET, то не было бы видно, что функция зависит от входных данных, а при тесте изменения в $_GET либо пришлось бы как-то откатывать, либо бы наш тест мог бы повлиять на другие. Разве это удобно? Наконец, в случае с объектом Request мы можем вызвать функцию на несуществующих данных. Если мы хотим проверить, "в случае, если пользователь пришлет такой запрос, что вернет функция?" - мы просто создаем временный объект Request, и вызвыаем функцию, а что делать при использовании глобальных переменных? Придется городить костыли. Что касается Response, то он позволяет нам решать, что делать с ответом. В чистом PHP код отдает заголовки через header, отдает контент через echo и мы не можем их перехватить и что-то с ними сделать. В случае с Response, нам возвращают Response и мы с ним делаем, что хотим. То есть теперь мы решаем, что делать с ответом. Это полезно в тестах, и не только.Например, мы хотим сделать автоматическое шифрование кук - при отдаче шифруем, при получении расшифровываем. В случае с Request/Response мы это можем сделать, не меняя сам код приложения. Просто пишем функцию, которая принимает на вход Response с открытыми куками и возвращает Response с зашифрованными (и тестировать такую функцию несложно). А вот если приложение использует глобальные переменные и отдает куки через setcookie, то сделать это сложно - без костылей вроде runkit вызов функции не перехватить. Наконец рассмотрим еще один пример. Допустим, мы используем какую-то другую модель сервера, когда PHP код не умирает, а обрабатывает много запросов в цикле. Естественно, для отдачи контента там будут другие функции, и без объекта Response код, использующий Header/echo, с такой моделью работать не будет. В случае наличия объекта код трогать не придется. То есть разговор о Request/Response похож на разговор про недостатки глобальных переменных. Плюсы: - мы контролируем входные/выходные данные для кода и решаем, что с ними делать. Можем как-то их модифицировать, подменять итд.- мы явно описываем, что код получает на вход и дает на выходе- мы не получаем проблем, типичных для глобальных переменныхНу и как дополнительный плюс, у объекта Request/Response могут быть какие-то дополнительные возможности, например, готовый метод для установки имени скачиваемого файла, или срока кеширования, чтобы нам не надо было вспоминать, какие заголовки за это отвечают.> В каком месте выводить полученный результат?> Достаточно написать во фронт-контроллере echo $response->getBody(); ?Достаточно. Но только там не только тело, но и еще код ответа и HTTP-заголовки. В симфони у респонса есть метод send(), который все это отправляет в браузер.
>>1375673break можно использовать только в определенных случаях, в циклах, например. В твоем случае хватит просто if/else. exit не требуется. Повтори, как работает if, и напиши так: if (номер соответствует выражению) {делать что-то одно;} else {делать что-то другое;}if/else можно вкладывать друг в друга. Не забывай про отступы и форматирование.Твой код пока что неверный, так как он признает верным телефон из 11 букв.> ^[7]Скобки около семерки тут не требуются.Регулярку стоит писать примерно так: - в начале +7 или 8- затем 11 раз повторяется конструкция: (одна цифра и любое число дополнительных скобок, минусов, пробелов)- затем конец строки>>1375846Его обычно не включают ни в один компонент, он сбоку сам по себе. Если речь о хелперах вроде преобразования даты в текстовый формат. В твоем примере это может быть часть контроллера, так как работает с даными запроса, хотя кто-то отнесет ее к модели. Тут пограничный вариант. Вообще, код не обязан строго относиться к M, V или C. MVC - это ключевые компоненты, которые участвуют в обработке запроса. Ну и MVC вообще был придуман для долгоживущих десктопных приложений с окошечками и кнопочками, и главной идеей было отделение кода UI от модели (так как до этого их могли смешивать). К веб-приложениям он немного притянут за уши, скажем так.Ну например, крон-скрипт - это что? По расположению похож на контроллер. А почему он с пользователем не взаимодействует? А где его View?> Можно ли из хелпера обращаться к глобальным переменным? Обращаться к глобальным переменным плохо почти всегда, так что не стоит. Лучше, когда функция получает аргументы явно. А так, получается скрытая недокументированная зависимость: если ты не задал какую-то глобальную переменную, то функция не будет работать. Как об этом догадаться? Это не очевидно. А если функция меняет глобальную переменную, то это называется "побочный эффект".В твоем случае, идеально, было бы, например, так: $this->authHelper = new AuthHelper($request, $userDb);...if ($this->authHelper->isAuthorized()) ...Или так (объект можно использовть многократно): $this->authHelper = new AuthHelper($userDb);...if ($this->authHelper->isAuthorized($request))Тут мы явно видим, от чего зависит класс. Но если у тебя нет класса Request, то можно работу с кукой сделать в хелпере, но оговориться, что с этой кукой никто больше не имеет право работать для соблюдения принципа единой ответственности.
>>1375838Проверь, нет ли в твоих файлах символа BOM. Если есть, сохраняй в utf-8 без BOM.>>1375786Придется наверно писать руками. Можно попробовать new DateTime("tomorrow 12:00");>>1375710> как там представление реализоватьОтдавать HTML и пусть тот, кому нужно, сам загоняет его в респонс. Добавить функцию, которая принимает респонс и загоняет HTML в него. >>1375354Тут сложно определить момент, где заканчивается правильный номер и начинается неправильный. Потому для упрощения я предложил идею про наличие 11 цифр. Но ты можешь предложить более удачные правила, если хочешь.
>>1376421Спасибо за предоставленный приём. Тесты на JS (а точнее на TypeScript) действительно проходят медленно, и иногда даже без асинхронных операций проверка запуска теста с единственной строчкой expect(true).toBeTrue() выдавал ошибку таймаута (???) или выполнялся спустя секунд 15. Представляю как серверная обработка запросов будет проходить так же медленно. Всё больше убеждаюсь, что серверная часть должна быть написана на предназначенных для этого языках, например PHP. Передаю этот ценный опыт всем анонам и хочу чтобы они оценили преимущество этого языка в том, что он как раз предназначен для веб-технологий.
>>1376437>Проверь, нет ли в твоих файлах символа BOM. Если есть, сохраняй в utf-8 без BOM.да каждый файл проверил в нотпаде, там кодировка без бом тем более это дефолтная страница от yii, все должно работатьможет я просто с настройками (пик1) где-то проебался или ещё что-тохотя тот же codeigniter у меня нормально работал
>>1376041> Ну а то, что фактической проверки типа возвращаемых значений и аргументов нет - ну что же, приходится забить на это хуй в угоду быстроте разработки.Проверки типов для каждого из элементов массива и не должно быть. В PHP проверки типов происходят в рантайме, а значит время проверки будет увеличиваться в зависимости от длины массива, такого ни в одном языке нет. Способы обхода проблемы:1) Создавать коллекцию для каждого класса:class UserCollection {addUser(user: User) {}removeUser(user: User) {}}Тогда UserCollection можно использовать в качестве тайп-хинта и проверка не будет зависеть от числа элементов в массиве. Generic-коллекцию с таким вариантом создать не получится, поэтому этим способом никто не пользуется.2) Использовать статические анализаторы вроде PHPStan/Psalm. До языка TypeScript им, конечно же, далеко, но базовые потребности покрывают неплохо. Мы внедряли PHPStan с самым щадящим режимом (level 0) в CI, постепенно повышая уровень строгости, польза есть. Python, кстати, пошёл именно по этому пути, там типы в рантайме не проверяются: https://docs.python.org/3/library/typing.html>>1375887Это костыльно (работает только если аргумент последний) и влияет на перформанс. Лучше попробуй статические анализаторы.
Сап двач.Дошел до задачи с калькулятором, не могу понять, как выполнить операцию из переменной $op над $result и $number
>>1376436>- затем 11 раз повторяется конструкция: (одна цифра и любое число дополнительных скобок, минусов, пробелов)Ебните меня хуем по лбу. Почему я до этого не допер. Никак не привыкну разбивать целое к частным.
>>1376436>- в начале +7 или 8>- затем 11 раз повторяется конструкция: (одна цифра и любое число дополнительных скобок, минусов, пробелов)>- затем конец строкиЯ над этим покумекал, а не будет ли выгоднее убрать плюс, но при этом оставить 11 цифр ( тут ошибку понял). А потом сделать проверку 7 или 8
>>1376399>В названии грится RESTful, а у тебя аутентификация походу через куки и сессииДелал через стандартную ларавелевскую. Думаешь, они имели в виду перепилить её на рестфулл? Возможно и так, но я не сообразил.>Контроллер search в неймспейса Ajax опять же не особо нужен, не проще в Number@index ( / url) добавить возможность фильтровать по запросу, например /?name=123&number=456 и возвращать отфильтрованные звонки.Аякс же. Там в дополнительных требованиях было обеспечить работу поиска без перезагрузки страницы (а ещё про то, что хорошо бы вообще весь фронт написать на реакте/ангуляре, но поскольку я в них не умею, то просто убрал лишнее из описания).>Еще не совсем понятно зачем сортировать в пхп а не в бд, и вообще про методы all() лучше забыть.Да, пожалуй. Надо будет мне переписать запросы.Спасибо за ревью!
Аноны, можно ли сделать так? Я просто не уверен почему у меня это не работает. Может так вообще не выйдет, а я сижу и туплю. Функция же строку возвращает, так что должно работать. В итоге вопрос состоит в том, могу ли я использовать $0,$1,$2 в данной ситуации?$text = preg_replace($regexp,mb_strtoupper('$0'),$text);
>>1376879Ты сначала применяешь к строке '$0' функцию mb_strtoupper (от этого она не меняется), а потом передаешь результат в preg_replace.Для твоей задачи нужна функция preg_replace_callback().
>>1376833>Аякс же. Там в дополнительных требованиях было обеспечить работу поиска без перезагрузки страницы (а ещё про то, что хорошо бы вообще весь фронт написать на реакте/ангуляре, но поскольку я в них не умею, то просто убрал лишнее из описания).Эти два метода делают одно и тоже, только формат ответа разный. Можно явно передавать ключ format=json/html где html будет дефолтным или смотреть например по Accept заголовку но я так не делал никогда и хз.
>>1376912>Эти два метода делают одно и тоже, только формат ответа разный.А и верно. Надо будет попробовать сделать поиск тем же контроллером, что и выдачу.
>>1376892>Ты сначала применяешь к строке '$0' Т.е я применяю функцию не к найденному тексту, а конкретно заданной строке '$0'? Соответственно возвращается это же строка, и только потом она считывается как "найденный по регулярке текст", и в итоге ничего не меняется.Правильно ли я понимаю что preg_replace_callback принимает в себя только функции, а preg_replace функции не принимает?С первого раза, кстати, вышло. Спасибо большоеhttp://sandbox.onlinephpfunctions.com/code/acc29ae465e387db405a8aacfcf5a583138c2c37
>>1353705 (OP)Ну кто делает треды с более 500-ми постов?Тред сдох а весь браузер висит, а процессор в ноутбуке свестит и пердит.А что если я прогружают с тилибона, где каждый килобайт трафика бабло насчитывает?Зашёл ещё, как-то в arduino тред в /ra - так там вообще больше 1000 постов, ещё и с картинками, блядь.Обычно на треды 500 постов до бамплимита, и перекат,либо же - бесконечные треды с лимитом в 500 постов, в которых старые посты - обрезаются...Пилите перекот!
>>1377027Погоди еще 2-3 дня. Сейчас разберемся с анончиками, которые писали свои вопросы, и сделаем перекат. Про тормоза я знаю.
Последний пых - пиздат, но пиздат потомучто почучуть становится джавой.В связи с этим вопрос: зачем нужен язык, который становится джавой, когда есть джава?
Какой редактор / IDE посоветуешь, анон? Я нью, планирую вкатываться. Хочу нормальную подсветку синтаксиса, автокомплит и прочее.
>>1377061Потому, что он заточен под свою задачу. ЯП, который и швец и жнец и в жопе холодец - не очень обычно получается.
https://ideone.com/A4UKZi Задачка по регулярке, на проверку текста на ошибки с последующим их исправлением. Я текст разбил на массив и каждый элемент проверяю отдельно. Вот не знаю как сделать так, чтобы значение в условии if (это $result=", {$result}";) сохранилось для значения в массиве $results.
>>1377423Ох, раза 3 перечитал, пока понял. Ты хочешь исправить все ошибки в словах и сделать текст со всеми исправлениями? Тогда лучше всего просто создать новый, пустой массив слов. На каждом шаге цикла класть в него либо исходное, либо исправленное слово. После окончания цикла собрать массив в строку с помощью implode(). Учти, что там могут быть сложности с пробелами между словами: Были слова в массиве: да|но|это|не|точноСтали после исправления: да|, но|это|не|точно Если ты теперь склеишь это, добавляя пробел, то получится "да , но это..." с лишним пробелом. Если же склеивать, не добавляя пробелы, то их надо как-то добавлять вручную к каждому слову. Тут можно добавлять запятую в другое слово: да,|но|это|не|точноИли же можно вообще не разбивать текст на слова, и искать ошибки регуляркой по всему тексту. Например, для пропущенной запятой можно написать выражение: - сначала идет буква- за ней любое число пробелов- далее "а" или "но"- далее граница слова (чтобы не срабатывало на любые слова, начинающиеся с "а")И стоит называть переменные лучше. Не results, а, например, foreach ($words as $word).
>>1377455>На каждом шаге цикла класть в него либо исходное, либо исправленное слово. У меня на картинке есть массив, Там каждый индекс (ключ) из массива с его значением проверяется на регулярку и потом изменяется в условии if. По сути программа считает переменную $result внутри if (preg_match($regex3, $result)) как временную переменную. И я не понимаю, как изменения в $result передать для значения в массиве, чтобы он часть текста с ошибкой заменил на уже исправленный.
>>1377463Во-первых, result - это не ключ, а значение элемента массива. Во-вторых, если тебе надо изменить исходный массив $results, то ты можешь это сделать, записывая в него значение по ключу: foreach ($words as $key => $word) {$words[$key] = "hello, $word";}Но это усложняет понимание работы программы (ты на лету изменяешь массив, по которому идет цикл). Лучше не записывать изменения в исходный массив, а создать новый и записывать исправленные слова в него.
>>1353705 (OP)Господа, я тупой или не очень?Для одного проекта мне надо поставить db* из pearPear мне говорит, что db депрекейтед в пользу mdb2При этом, 1.9.3 (stable) released on 2018-12-05https://pear.php.net/package/DB/download/а mdb2: Status: 2.5.0b5 (beta) released on 2012-10-29
>>1376454пофиксил господи наконец-тоне юзайте говно мамонта типа пхп <7 как бы вам удобно это не казалось
>>1353705 (OP)Вопрос по организации архитектуры сайта.Например я сделаю личный бложек (с помощью фреймворка или велосипеда). И тут понадобится расширить сайт чем-то массивным, например прирутить форум. Как поступить в этом случае? Делать форум на фундаменте текущего блога (то есть писать код прямо рядом с php-классами блога) или создавать отдельный 'репозиторий', в который перенаправлять запросы через index.php? А если я хочу сделать общую авторизацию то как быть?
Нужно вставить переменную со случайным значением в http-запрос, но с выделением переменная не читается. Например:$foo = 'n';$request = '/bar/$foo/more';
>>1372258tl;dr Проблема решена>>if (details is None) or (not 'Bearer token' in details['authextra']):>>builtins.TypeError: argument of type 'NoneType' is not iterable>>И, во втором случае, >>>if (details is None) :>> principal[u'extra'] = {>> u'error': u"Access denied: No Bearer token in authexta">> }>> return principal>>>>>> token = details['authextra']['Bearer token'];>>return не выполняется и код продолжает выполнятся>>>token = details['authextra']['Bearer token'];>>builtins.TypeError: 'NoneType' object is not subscriptableЗдесь нет проверки на существование свойства authextra.>> try:>> payload = jwt.decode(token, JWT_SECRET)>> except Exception as e:>> principal[u'extra'] = {>> u'error': e>> }>> return principal>>>> ...>>return снова не выполняется и вбрасывается ошибка: "WAMP message serialization error: Object of type 'InvalidSignatureError' is not JSON serializable">https://pyjwt.readthedocs.io/en/latest/api.html#jwt.exceptions.InvalidSignatureErrorПитон сам по себе не сериализирует исключение в строку.Решено в связи с https://forum.crossbar.io/t/python-code-does-not-work-as-expected/1495
>>1377697>Делать форум на фундаменте текущего блога (то есть писать код прямо рядом с php-классами блога)Конечно так. Тебе нужно чтобы у тебя были отдельно файлы например blog.php и forum.php. Почитай ещё про архитектуру MVC, станет очень много понятно. https://github.com/codedokode/pasta/blob/master/arch/mvc.md
Хотелось спросить бы, ОП-кун, в частности. Я когда-то вкатился в PHP с твоих тредов, порешал все задачки, подтянул верстку и нашел работу. С тех пор прошло 3 года, я стал крепким мидлом, успел поработать в старапе с Y Combinator, собеседования для меня теперь не страшны и найти работу я легко могу почти в любом селе.Чего мне читать, и как стать все-таки сеньером помидором? Если что js я почти не трогаю, текущий фреймворк Symfony 4. Комьюнити PHP в моем городе почти не существует, судьба забросила, увы.
Анончик помогающий с регулярками, глянь, где я не прав. https://ideone.com/S53UAG Решение я обосновал так, с начала я выкидываю к хуям все кроме цифр. Теперь нам не принципиально что в начале, затем проверяем число знаков и наконец проверяем что в начале 7 или 8, потом сразу же меняем 7 на 8мь. Я не могу понять почему на этапе проверки первых цифр происходит ошибка.
>>1353705 (OP)Ох уж эта ебля с настройками, не могу направлять запросы через ФронтКонтроллер. Если на прямую к нему обращаться, то создает роутер и выполняет функцию из класса роутера. Чего я только не делал. И закидывал в стандартный путь, и новый адресс делал, и разные htaccess создавал, и переустанавливал ос. Уже не понимаю куда смотреть.php7.2 Апач2.4 на виртуалке ubuntu 18.04. Это в .htaccess: "AddDefaultCharset utf-8RewriteEngine onRewriteBase /RewriteRUle ^(.*)$ index.php"
>>1377929Я не анончик проверяющий регулярки, сам только начал. Но кое-чем подсобить могу. С ideone лучше перекатывайся, у меня там тоже много чего не работало.http://sandbox.onlinephpfunctions.com/code/134052c9924b5d9c6751b620f4774cb5533fec30Вот, скрипт выполняется, но он все равно не правильный. Как минимум из за этой регулярки '/\D/' в 4 строке. Тебе же по заданию нужно сначала проверить верный ли номер. Если я напишу "+7892()326 ()-()2_032 сап Двач", то все кроме чисел выкинется, "+" тоже выкинется, а по заданию нам нужна проверка стоит ли там +7 или 8 (+8 и 7 - номер неверный) и т.дЕще не забывай при выводе переменной, если сразу за ней идет текст заключать ее в {}.
>>1377979Попробуй сделать такRewriteEngine OnRewriteRule ^(.*)$ index.phpЕсли получится, желательно ещё отключить переадресацию для публичных файлов.
>>1377979А в чем проблема? В том, что не вызывается index.php? Для начала проверь, включено ли в конфиге Апача выполнение htaccess: - https://httpd.apache.org/docs/2.4/mod/core.html#allowoverride- https://www.linode.com/docs/web-servers/apache/how-to-set-up-htaccess-on-apache/Не забудь, что после изменения конфига надо перезапустить Апач.Далее, глянь в лог ошибок веб-сервера (/var/log/apache2 или /var/log/httpd). Посомтри, нет ли там чего странного.>>1377929Там в начале может быть либо +7, либо 8. Если просто 7 или +8 - то это ошибка. Также, выкидывать лучше не все, а только пробелы, скобки, минусы. Ну а еще лучше все же написать полноценную регулярку для проверки: - в начале идет 8 или +7- затем выражение (одна цифра, за ней любое число скобок, минусов, пробелов), которое повторяется 11 разДалее, у тебя ошибки в коде: > if (mb_substr ($clearNum,0,1)=='/7|8/'){Знак "равно" просто делает посимвольное сравнение, он не интерпретирует выражение как регулярку. Тебе тут нужен preg_match.
>>1377837Сеньор - это в каждой компании разное понятие. Общее там то, что у сеньора обычно порядка 6 лет опыта, высокий уровень знаний в своей области, развитый кругозор, способность самостоятельно решать сложные задачи, проектировать систему или ее компоненты. Высокий уровень ответственности (он не может выгрузить обновление на прод и уйти домой, не убедившись, что все ок и никаких ошибок нет). Но сам по себе уровень разный - сеньор в подвальной веб-студии может не пройти собеседование в Яндексе на джуниора. В какой-то компании "сеньор" может просто значить "человек с 6 годами опыта". Сеньор способен передавать свой опыт и знания младшим разработчикам, способен руководить ими. 3 года - это скорее мидл, если только ты не какой-нибудь вундеркинд с выдающимися способностями.Вот, первая попавшаяся статьи из гугла, довольно адекватная: https://dataart.ru/news/junior-middle-senior-v-chem-raznifa-i-kuda-dalshe/Так что ответ: развивайся, чтобы соответствовать написанному выше представлению. Изучай внимательно технологии, с которыми работаешь, интересуйся другими технологиями, изучай теорию, читай статьи, смотри доклады. Читай и решай задачи с собеседований в Яндекс. Вот сегодня, например, ты изучил что-то новое? Что касается того, что ты живешь в маленьком городе, то во-первых, можно попробовать найти работу удаленно, во-вторых, сейчас же не крепостное право, тебя там никто цепями не держит. Я также могу добавить, что один из лучших способов развиваться - это попасть в компанию с сложными проектами. Туда, где ты еле-еле можешь пройти собеседование, и то не факт, что примут. Где есть куча людей умнее тебя. Если ты можешь такую компанию найти и внедриться туда, то ты будешь учиться, получая за это деньги. Что может быть лучше? >>1377697Удобнее всего будет сделать форму на отдельном домене (forum.example.com) или URL (http://example.com/forum/), взяв готовый движок. При необходимости интегрировать с сайтом (сделать сквозной логин, например).
>>1377739Жаль, что-то у меня руки не дошли проверить код. Но я бы тебе посоветовал:- использовать объекты вместо массивов для ключевых типов данных, которые используются во многих функциях в коде- не городить такие массивы, когда можно обойтись без них. Тут вместо сложного массива principal можно было использовать внутри функции просто переменные вроде error, role, и при необходимости перед возвратом результата собирать из них массив. Хотя, тут можно просто возвращать кортеж (role, error), как мне кажется.- разбивать стену кода на отдельные функции. Ты и токены проверяешь, и к БД подсоединяешься, и что только не делаешь.- в try/except указывать конкрентные классы исключений, которые тебя интересуют, а не ловить все подряд>>1377564Возможно, что последние изменения - это багфиксы или исправления безопасности, а никакого нового функционала не добавляется. >>1377517Чтобы не нарушать семантику, можно еще использовать display: table вместо настоящих таблиц. А так, да, вертикальное центрирование - это table или flexbox.>>1377063Sublime Text, Netbeans for PHP, Eclipse PDT, если ты богат (или если можешь выпросить лицензию как студент) и у тебя быстрый проц, то PHPStorm. VS Code неплоха, но не у всех быстро работает.
>>1376921preg_replace принимает текстовое выражениеpreg_replace_callback принимает функцию для заменыТвой код склеивает слова вместе, если между ними 2 или более пробелов.$count; - эта строка ничего не делает, ее надо убрать.[а-яё]|[a-z] - это равносильно [а-яёa-z]
<?php for ($i = 1; $i <= 5; $i++): ?><a href="<?php echo Utils::generateLink($i, 'query'); ?>"><?php echo $i ?></a><?php endfor; ?>Можно ли так смешивать php и html?
>>1377901Вообще програмировать начал класса так с 6 или 7, какие-то основы паскаля и на олимпиадки ходил(правда там нифига не смог решить кроме первых задач ибо разрыв когда в школе тебя учат ифам, а на олимпиаде поиск минимального пути на графе просто выносит нахуй). На работу за бабло пошел через 3 месяца, как стукнуло 18, когда понял что найти работу джуном на яве - анриал, и пошел задротить PHP. Щас мне 22.>>1378170Я и не планирую в яндекс на джуна идти. Что бы пройти туда собеседования не плохо надо знать Computer Science и матан, не то, что бы что-то плохое, но сейчас не в приоритете. Ну я и сказал, что я крепкий мидл середнячек. Я нашел работук и даже здесь, я просто переехал в родное село пол года назад. Местная продуктовая компания.Яв основном так и вывозил и быстренько подрос по карьере. Чё. Оп-кун, короче спасибо тебе, я тут где-то с 18 или 20 треда сидел, хахахахахах.
>>1378210Мда, а меня пхнула бабка на инженегра. Окончил бакалавра и 2 годика проработал. Сейчас понял, что это не мое, хотя к пк всегда душа лежала. Вот переучиваюсь сызнова.
>>1353705 (OP)Пагни, поясните по структуре проекта на симфони 4. В /src проекта есть директории Entity и Repository. С Entity более менее понятно - там хранятся файлы-модели таблиц БД. А для чего нужна директория Repository?
Протестировал WAMP и сейчас собираюсь писать сервис сообщений. И сначала я хотел бы обсудить архитектуру которую я выбрал. Я считаю её безупречный, но я не безупречный разработчик, поэтому мне хотелось бы услышать опытный взгляд со стороны.ЗадачаКаждый пользователь может написать другому пользователю. При первой отправке сообщения создаётся диалог. Сообщения могут быть текстовые, могут быть голосовые и могут быть видео. Каждое сообщение может удаляться либо у себя лично, либо у обоих пользователей. Диалоги так же могут удаляться у каждого пользователя лично (но не у обоих, т.е. каждый пользователь имеет только ссылку на диалог).К каждому текстовому сообщению могут прикрепляться данные: изображение, аудио, видео, файл, пересылка сообщения и ответ на конкретное сообщение.Прикреплений может быть несколько за сообщений.Диалоги могут быть приватные (тет-а-тет) а могут быть публичные (конференции).Соответственно архитектура будет такая:пользователь:- ...текстовое_сообщение:-uuid-пользователь (автор сообщения)-сообщение-дата-прочитано (булевый)-...аудио_сообщение:-uuid-пользователь (автор сообщения)-звукозапись (путь/к/аудиофайлу)-дата-прочитано (булевый)-прослушано (булевый)-...видео_сообщение:-uuid-пользователь (автор сообщения)-видеозапись (путь/к/видеофайлу)-дата-прочитано (булевый)-просмотрено (булевый)-...текстовое_сообщения: (хранит в себя ссылки на сообщения для каждого отдельного пользователя)-uuid-пользователь (кому принадлежит ссылка)-диалог (диалог в котором сообщение находится)-сообщение-...аудио_сообщения:-...видео_сообщения:-...прикрепление_изображения:-uuid-сообщение-изображение-...прикрепление_аудиозаписи:-...и т.д. за исключением что у каждого прикрепления своя ссылка на источник.диалог:-uuid-приватный (булевый)-...участники: (для приватных диалогов всегда будет два участника)-uuid-диалог-пользователь...диалоги: (ссылки на диалоги для каждого пользователя)-uuid-пользователь-диалог...Такова вся архитектура. База данных будет psql.Название таблиц в боевой базе данных будет идентично т.е. будет и сообщение и сообщения. Это же не создаёт затруднения для понимания? Разделение приложений к сообщению на отдельные таблицы для каждого типа, а не хранения всех видов файлов в одной, позволяет в будущем расширять приложение, если появятся новые типы данных.>>1378171>Жаль, что-то у меня руки не дошли проверить код. Но я бы тебе посоветовал:>>- использовать объекты вместо массивов для ключевых типов данных, которые используются во многих функциях в коде>- не городить такие массивы, когда можно обойтись без них. Тут вместо сложного массива principal можно было использовать внутри функции просто переменные вроде error, role, и при необходимости перед возвратом результата собирать из них массив. Хотя, тут можно просто возвращать кортеж (role, error), как мне кажется.>- разбивать стену кода на отдельные функции. Ты и токены проверяешь, и к БД подсоединяешься, и что только не делаешь.>- в try/except указывать конкрентные классы исключений, которые тебя интересуют, а не ловить все подряд>Жаль, что-то у меня руки не дошли проверить код.Всё хорошо, у меня было время чем другим заняться. Я рад, что сэкономил ваше время.>- использовать объекты вместо массивов для ключевых типов данных, которые используются во многих функциях в коде>объектыЯ правильно понимаю, что в Питоне объект, это instance класса, как в PHP, а не как в JS? Для каких ключевых типов данных вы имеете ввиду?>- не городить такие массивы, когда можно обойтись без них. Тут вместо сложного массива principal можно было использовать внутри функции просто переменные вроде error, role, и при необходимости перед возвратом результата собирать из них массив. Хотя, тут можно просто возвращать кортеж (role, error), как мне кажется.>Тут вместо сложного массива principal можно было использовать внутри функции просто переменные вроде error, role, и при необходимости перед возвратом результата собирать из них массив.Разве это не создаст дополнительные проверки и не раздует код? Т.е. во время ответа писать: if error is not None: principals['extra']['error'] = error; Почему нельзя собирать массив "на ходу"?>Хотя, тут можно просто возвращать кортеж (role, error), как мне кажется.Возвращать кортеж из функции авторизации, вы это имели ввиду? Это не правильно, потому что principals сериализуется в json и возвращается клиенту.>- разбивать стену кода на отдельные функции. Ты и токены проверяешь, и к БД подсоединяешься, и что только не делаешь.Конечно. Это только черновик где я тестирую чтобы посмотреть как работает код.У меня будет вопрос по архитектуре, когда я его сформулирую.>- в try/except указывать конкрентные классы исключений, которые тебя интересуют, а не ловить все подрядПонял.
>>1378248Ну я на математика учился. Мехмат. Любил математику, но понял, что хочется жрат и денех. Бросил где-то на втором курсе, хотя жалею сейчас немного.
Вопрос по симфони.Допустим юзер отправляет через форму какие-то данные. Сразу, как эти данные приходят в контроллер мне нужно сделать с ними некоторую работу, которая требует времени. Результат этой работы возвращать юзеру не нужно. Но нужно вернуть ему сообщение, типа "мы вас услышали. спасибо. идите нахуй". Как мне это сделать, не дожидаясь, пока вот та времязатратная работа завершится?
>>1378169Ну, надеюсь теперь норм. Хотя я не понимаю, почему не могу выбить буквы. http://sandbox.onlinephpfunctions.com/code/abbfee8d43d3a7f0868c9a58441b1f02e5a19b1e
>>1378542Буквы-флаги. В начали урока по регуляркам. Вместо /[a-zA-Z]/можно написать /[a-z]/i Если используешь русские буквы в выражении - ставь флаг 'u'./[а-яё]/iuТак же у тебя по условию нужно проверить является ли строка номером. У тебя она является номером, хотя содержит "позвать Люсю".
Не могу понять что делает <<<? В книге написано что это какой то маркер но больше нихуя не написано, помогите плиз.
>>1378586Окей понял. За флаги спасибо, а то только через 101 проверил, а там автоматом проверяется. Перепсал с первичной проверкой любого текста. Но теперь почему-то выражение принимается в любом случае вне зависимости от того есть в нем буквы или нет (я писал только русские). http://sandbox.onlinephpfunctions.com/code/cce3879a8929314360111bd939069d09b7020410
>>1378663Есть несколько моментов:-в PHP есть функция preg_match($regexp, $text, $match). Она принимает на вход регулярку, текст и пустой массив. Она проверяет, есть ли в тексте подстрока, соответствующая данному шаблону и возвращает 0, если нет, или 1, если она есть.If (preg_match('/[a-z]/',$text)), если функция найдет что нибудь по регулярному выражению - вернет 1. В обратном же случае вернет 0.if (1) - Правда, идем дальшеif (0) - Ложь, переходим к Else.-https://regex101.com/r/qF7vT8/3 Видишь, твоё регулярное выражение не очень то и работает. Должны светиться только ВСЕ правильные номера. -Читай внимательнее уроки и задачки.-Сделай сначала первую часть задания, где программа должна из массива номеров выдавать только правильные, а только потом преступай к их форматированию
>>1378756>должна из массива номеров выдавать только правильныеВот в чем цимес. а я получается пытался один насильно привести к формату. http://sandbox.onlinephpfunctions.com/code/c0635168d02a3291ef7885de84e3891b2615f6e5Буквы не пропускает, знаки удаляет, 7 на 8 меняет
>>1378980ПХП разрабы. Вот вы риал учите такую хуйню? Сука, ониб еще спросили каким цветом кнопка по созданию бэкапа блядь.У пыхи огроменная экосистема - вордпресы, битриксы, друпалы, хуялы, ларавели, мускули, посгресйли, мариидб, докеры, композеры, паттерны, хуятерны, мемкешы, хуешы блядь. Этот список можно на 100500 страниц составить.Это все выучить невозможно физически, а учитывая, что все оно периодически обновляется/меняется - то и поддерживать знания на актуальном уровне.Вы реально все это учите?Я работаю и когда мне приходится иметь дело с новой цмс - я просто тыкаю куда попало, лишь бы работало, потомучто я не собираюсь тратить свою жизнь на знание ебучих говно-цмс, которые через год будут работать по другому.
Подскажите пожалуйста как эту регулярку одной скобкой записать. Заранее спасибо(11|12|13|14|15|16|17|18|19)
Как правильно создавать константу? В видеоуроках говорят что const CONSTANT, а в кнгиге define('CONSTNAME', value).Где истина?
>>1379090Тут цимес не в учении, один хер забудешь половину, но когда столкнешься снова уже не будешь орать в ужасе и более менее соориентируешься куда копать.
>>1378889Сделал, глянь, https://ideone.com/v2XnwF. Дуболомно, но пашет. Я сейчас кстати сам с себя проиграл, половина номеров повторяются, а я думал, что один и тотже в цикле идет
>>1379319Раз все работает - можешь дальше задачки решать. Я сам только учусь, так что могу подсказать только то, что сильно выделяется. Например "грамматика", если ее можно так назватьВот как тут >>1353706 пытайся делать. Скобки, пробелы в блоках.Чтобы код был более правильно оформлен
>>1379335Согласен, но со скобками пришлось так сделать т к я изначально накосячил с ними и подбивал куда нужно, спасибо тем не менее
>>1379090Всё сразу знать и не надо. Обычно у кодера есть какой-то свой стек полюбившихся\прибыльных технологий.Ну понятно, что всегда есть какая-то база кодерская, которую знать просто необходимо для понимания как оно вообще работает и куда смотреть.
Люди, а у вас регэксп нормально работает? Вот я сделал выражение для проверки почты из задания (условно, сейчас вопрос не в этом) https://regex101.com/r/wTzjEo/1 и у меня высвечивается pattern error, когда же я переписываю это так-же http://sandbox.onlinephpfunctions.com/code/b7b2d7d49e417c2b39be6f9dd27368f640ca136c все прекрасно заменяется.
Аноны, поясните по хардкору по исключениям. Прочитал уже много чего и не совсем понимаю, где нужно ловить, где нет и вообще для чего это все. Вот я делаю чтение ini файла с конфигурацией подключения к mysql.if (file_exists(__DIR__ . '/' . 'dbconfig.ini')) { $config = parse_ini_file(__DIR__ . '/' . 'dbconfig.ini');} else { throw new Exception('Database config file missing');}Так это должно выглядеть?
>>1379475Ты этот урок читал? Там разве нет ответа? https://github.com/codedokode/pasta/blob/master/php/exceptions.mdТебе нужно сделать свой кастомный класс исключений, если ты хочешь его ловить и обрабатывать. Хотя я не очень понимаю, что ты собрался делать, если нет файла конфига.Если не собираешься, то можно использовать стандартное исключение.
>>1379512Прочитал сейчас второй раз и уже понял более менее. В самом простом случае можно просто везде, где могут быть косяки выбрасывать исключения, а в фронт контроллере зарегать set_error_handler и там уже сохранять в лог, для всех исключений выводить в http ответ 503 и страницу с этой ошибкой для пользователя.
>>1379535Что значит "во время разработки выбрасываешь"? В продакшене специально условие писать, чтобы не выбрасывать? Тут каких-то различий между продакшеном и dev не требуется, разве что в dev можно подробности выводить.
>>1379547Исключительные случаи должны обрабатываться так, чтобы во время разработки они были очевидны, а в промышленном коде — позволяли продолжить работу.С. Макконелл Совершенный кодя понимаю так, как написал здесь >>1379535
>>1379475По идее перед деплоем ты всё равно запускаешь тесты, и если конфиг с подключением к бд куда-то пропал то ты об этом узнаешь, я не понимаю как такое можно обработать чтобы приложение не упало>>1379543>в http ответ 503Почему не 500?Никого, кстати, не смущает что код ответа http часто совмещают с ответом самого приложения? Например мы сделали форму на сайте, клиент отправляет запрос с данными, мы видим там ошибку, часто ставят ответ 422, хотя по сути ответ же 200, сервер всё прочитал и понял, хттп на транспортном уровне сделал своё дело, а то что внутри запроса данные не такие это уже наше дело, нет?
>>1379581Оп писал,что пустая страница с ответом 200 при выбросе исключения - это плохо. Там что-то про гугл и яндекс, которые индексируют такие страницы, а 503 они не трогают.
>>1379557После выброса исключения невозможно продолжить работу. Возможно, Макконелл имел в виду "продолжить работу" с точки зрения пользователя, например, показать страницу ошибки и дать возможность повторно отправить запрос.
>>1379581Вообще, коды ошибки предназначены для программ и роботов. Человек их не видит. Они должны передавать роботам информацию о результате выполнения запроса.Ты наверно имел в виду HTTP API.Там часто код используют для сигнализирования об ошибке на уровне логики (пользователь с таким емайл уже существует). Почему бы и нет? Кто-то использует код ошибки, кто-то возвращает 200 и информацию об ошибке в JSON. Оба подхода имеют право на жизнь, лишь бы они были задокументированы.Я недавно думал на эту тему, какие есть плюсы, и подумал, что код ошибки в API позволяет быстро понять результат запроса не заглядывая в содержимое. В случае же HTML-страниц это обычно не используется. Если ты ввел существующий email в форму регистрации, то ты получаешь страницу с кодом 200. Хотя с другой стороны, коды 404 или 403 используются.В принципе, можно возвращать 422 и в ответ на форму регистрации, если ты гарантируешь, что браузеры вместо нее не покажут стандартную страницу ошибки.
Сап двачеры. Помогите с одной проблемой: echo <<< ENDхуй залупаEND; - видимо не работает в 7 версии - так как по-другому вывести несколько строк?
пишу на симфони, после того как залогинился страница исчезает и остается адресная строка, не пойму в чем проблемаа
Аноны, вот в выводе списка студентов есть кнопки постраничной навигации, сортировки и поиска, по отдельности это все понятно как сдклать. Вопрос, я жму на смену страницы в постраничной навигации, передается по get параметром номер страницы, а как передать текущую выбранную пользователем сортировку в таблице,чтобы она не сбилась?
>>1379804Надеюсь я тебя правильно понял.Если пользователь выбрал сортировку в таблице, то значит у нас на стороне пхп должны быть гет-параметры. Соответственно нужно вставить их во все ссылки при генерации.$orderBy = $_GET['orderBy'];$orderDir = $_GET['orderDir'];LinkHelper::generateLink($page, $searchQuery, $orderBy, $orderDir);Должно получиться, что-то подобное/?page=7&orderBy="name"&orderDir="DESC"
>>1379804Вот моя функция на пике, которая решает эту проблему. Идея в том, что гет-параметры сохраняются из предыдущего запроса и просто подставляются в новую ссылку. Функция передаётся как замыкание в шаблон и через неё формируются ссылки на пагинацию и т.д.Если у кого есть идея лучше - прошу озвучить, так как я писал от балды.
ОП, можешь 2 задачки глянуть? Они работают, но мне кажется что уж сильно говнокод. Стоит ли пытаться решать по другому или идти дальше?Числа в строки: http://sandbox.onlinephpfunctions.com/code/8f78a64f577b9d3eb6c00dfb5df5cba88483bd29Простой калькулятор: http://sandbox.onlinephpfunctions.com/code/5a4761d4e56d1d933fa1dbfe2f80e6feebe2f89aАноны, нужно ли устанавливать библиотеки функций для php? У меня и консоль и localhost жалуются: Call to undefined function mb_... on line ...
Я начал с нуля изучать PHP и хочу сходу указать 2 недостатка этого phpbooktest'а. В пикриле справа сверху написано, что mb_substr вырезает подстроку, но это не так. mb_substr возвращает подстроку, а вот просто substr вырезает. И еще уроком ранее не был объяснен принцип цикла foreach (пришлось разбираться самому). В целом интересно и сжато (зато по существу), спасибо ОПу (если это сделал он)
Что поделать, если впадлу делать сайт для тестирования (Который после файлообменника)? Вроде хочу начать, а ничего не понятно (тупо на ленивычах разбираться) и закрываю, и так не первый день.
>>1379765НУ и нахуй так писать, не говоря, что за ошибка и как ты её исправил? Может кому-то полезно будет. И вообще это хороший тон отвечать с конкретикой на свой вопрос если удалось самому справиться с проблемой.
Котаны, подскажите - почему когда я пишу в txt файл, то у меня символы \n\r в нем отображаются? Пишу в виндоовс.Я построчно из одного файла, где сплошной текст без переносов читаю, и пишу в другой файл, но так, что бы каждая новая часть была с переносом строки. Что характерно в новом файле переносы работают, но '\r\n' так же отображаются. Как так то?Код: $handle = fopen($path, "r"); $handle1 = fopen($path1, 'a'); while(!feof($handle)){>>1380236 $str = fgets($handle, 50); $str = $str.'\r\n'; fwrite($handle1, $str."\r\n"); } fclose($handle); fclose($handle1);
>>1379990Если тебе это неинтересно, то ты можешь придумать какую-то другую задачу аналогичной сложности на более интересную тему. Если непонятно, то это задача на фреймворки. Возьми какой-нибудь фреймворк (Laravel, Symfony), почитай туториалы к нему и станет понятнее.Ну или задавай вопросы, если есть какие-то конкретные вопросы.>>1379893Да, там не все идеально, если будет возможность, то надо будет исправить. Насчет "вырезает" - имелось в виду, естественно, возвращает. Разница между substr и mb_substr в том, что первая работает только с 8-битными кодировками, а вторая - с той, что задана в опции default_encoding в php.ini или функцией mb_default_encoding().>>1379860> Числа в строки: http://sandbox.onlinephpfunctions.com/code/8f78a64f577b9d3eb6c00dfb5df5cba88483bd29> if(preg_match('/(11|12|13|14|15|16|17|18|19)/',$lastTwo))Тут можно просто написать что lastTwo больше/равно 11 и меньше/равно 19. Числа все же правильнее сравнивать с помощью математических операций.В if/else надо использовать фигурные скобки, так как иначе легко допустить ошибку при чтении или правке кода. Это же не Питон, где все оступами определяется. В функции inclideWord if/else можно было написать в один уровень, без вложенности.> $count = strlen($number);> if ($count == 1){Тут лучше использовать математику, например условие что number меньше 10.Функция smallNumberToText переусложнена и в ней много копипасты. Нужно ее переделать. Например, так: - если в числе есть сотни, добавить слово для сотен- если число оканчивается на 11-19, добавить соотв. слово- если в числе есть десятки, то добавить слово для них- если в числе есть единицы, то добавить слово для них (с учетом пола)Смотри, всего 4 условия. То же касается функции numberToText(), ее надо упростить и избавить от копипасты.> Аноны, нужно ли устанавливать библиотеки функций для php?> У меня и консоль и localhost жалуются:> Call to undefined function mb_... on line ...Если ты под виндой, то скорее всего она просто не включена в php.ini директивой extension = .... Если под линуксом, то там обычно расширения ставятся отдельно (в Убунте/дебиане через apt-get install).> Простой калькулятор:http://sandbox.onlinephpfunctions.com/code/5a4761d4e56d1d933fa1dbfe2f80e6feebe2f89a> if ($operation == ''){> ...> if ($operation == '+')Здесь лучше было использовать elseif, так как у нас либо есть заданная ранее операция, либо нет.А так, верно.
>>1379833У тебя как-то странно сделано, что параметры сохраняются в $this->get. Это значит, что если ты с помощью функции linkMaker() создашь 2 анонимных функции, то одна будет влиять на другую (параметры, переданные в одну, отобразятся в другой). Это неправильно. Лучше сделать так: function makeLinkGenerator(array $basicParams): callable { return function (array $override) { ... };}Использование: $linkGen = makeLinkGenerator(['sort' => 'name', 'page' => 3]);echo $linkGen(['page' => 2]); // Меняем страницуecho $linkGen(['sort' => 'score', 'page' => '']); // при смене сортировки сбрасываем пагинациюМожно сделать аналогичную штуку с помощью объекта: $linkGen = new LinkGenerator([....]);$linkGen->makeLink([....]);Можно сделать специализированные функции для разных видов ссылок: $linkGen = new LinkGenerator([....]);$linkGen->makePaginationLink(3);$linkGen->makeSortLink('-name');Ты же зачем-то смешал оба подхода. Если ты используешь анонимную функцию, то не надо перезаписывать поля объекта.Можно вместо массива с базовыми параметрами использовать объект ViewParams/ViewFilter. Также стоит предусмотреть такие вещи: - если номер страницы равен 1, то его не надо добавлять в ссылку- если мы меняем сортировку, то надо сбрасывать пагинацию>>1379741Возможно, у тебя там отступ (пробелы) перед END или какие-то лишние символы после.
>>1379617Да, HTTP-код предназначен для роботов и программ, и они его используют. >>1379411Сейчас оба регекспа работают. Надо учесть, что на regex101 немного другие флаги (в PHP нет флага global), и могут быть немного другие правила использования бекслешей (в PHP сначала обрабатываются бекслеши как часть синаксиса записи строк, а потом в том, что останется, обрабатываются бекслеши как часть регулярки).>>1379090Этот тест проверяет знание Битрикса. Если ты с ним каждый день работаешь, то ты и так знаешь ответы на эти вопросы. ООП и паттерны запоминаются, если не заучивать их наизусть, а попытаться разобраться и понять, зачем это нужно и как бы ты сам бы решил такюу задачу.Гордиться низким уровнем знаний и нежеланием развиваться довольно странно.>>1379314Решено верно, но.> if (preg_match('/^(\+7)/',$checkNum)) {> $checkNum=preg_replace('/^(\+7)/',8,$checkNum);Тут сразу можно делать preg_replace без предварительной проверки.И по тестированию: лучше не просто писать, что номер верный/неверный, а сразу добавлять, правильно ли определила его программа или нет. Так как сейчас у тебя надо вручную читать то, что вывели программа, чтобы проверить, что она правильно определяет номера.
>>1378663> Но теперь почему-то выражение принимается в любом случае вне зависимости от того есть в нем буквы или нет (я писал только русские). У тебя стоит звездочка, которая значит, что предыдущий символ может встретиться 0 или более раз. Даже если в строке нет букв, это соответствует условию "0 раз". Под твою регулярку вообще любая строка подходит, даже пустая строка. Надо убрать зведочку либо заменить ее на плюс.>>1378542Чтобы регулярка корректно работала с нелатинскими символами в кодировке utf-8 (а у тебя она), надо ставить флаг u. Иначе регулярка думает, что перед ней текст в 1-байтовой кодировке, а русская буква - это 2 отдельных символа (так как она кодируется 2 байтами в utf-8). Описано тут: https://github.com/codedokode/pasta/blob/master/php/strings-utf8.md>>1379192const появился в PHP7, а книга наверно написана раньше. Лучше использовать const.>>1378611Это способ записи больших строк. Можно использовать кавычки, а можно heredoc. Ты бы документацию вместо книги почитал бы, например: - https://www.php.net/manual/ru/language.types.string.php- https://ru.wikipedia.org/wiki/Heredoc-%D1%81%D0%B8%D0%BD%D1%82%D0%B0%D0%BA%D1%81%D0%B8%D1%81Главный плюс в том, что в нем можно использовать кавычки и/или спецсимволы без экранирования, что удобно. К тегу <pre> он отношения не имеет.>>1378531Есть очереди задач для этого.
>>1378381Использование таблиц с похожими именами будет однозначно вызывать путаницу. Более того, я пока сам не понял, в чем разница между "сообщением" и "сообщениями" или "диалог" и "диалоги". Если ты хочешь делать для каждого пользователя свою копию сообщения, то не проще ли просто сделать таблицу "диалог", и таблицу "сообщения", где в сообщении стоит ссылка на диалог и ссылка на получателя, кому оно предназначено? То есть, так: диалог:- uuidучастники диалога:- id пользователя- id диалогасообщения: (копия для каждого получателя)- uuid- id, объединяющий копии одного сообщения- id диалога- id отправителя- id получателя этой копии- признак прочтения- текстКстати, в больших чатах невыгодно будет делать для каждого свою копию сообщения. Выгоднее делать всего одну копию для всех.Далее, у тебя есть наследование таблиц (для текстовых, аудио, видео сообщений сделаны отдельные таблицы). Ты использовал Concrete Table Inheritance. Не очень удобно делать их разными таблицами. Представь, что тебе надо получить последние 10 сообщений в диалоге. Тебе надо будет запрашивать данные из каждой таблицы (из текстовых сообщений, аудио сообщений, видео сообщений) и объединять. Как ты себе представляешь эффективную пагинацию по ним? Логичнее было бы использовать другой паттерн наследования, например, Single Table Inheritance или Class Table Inheritance. В случае STI мы делаем единую таблицу для всех видов сообщений. В случае CTI мы делаем одну таблицу для полей, которые есть в каждом виде сообщения (отправитель, время отправки, получено), и отдельные таблицы для доп. полей (которые есть только у опр. вида сообщения): - http://design-pattern.ru/patterns/class-table-inheritance.html- http://design-pattern.ru/patterns/single-table-inheritance.htmlВ обоих случаях мы можем легко получить последние N сообщений или сделать пагинацию без использования OFFSET. Также, возможно, имеет смысл свести любые сообщения к текстовым сообщениям с приложениями. Тогда аудиосообщение будет просто текстовым сообщением без текста с приложенным аудио, с пометкой, что аудиосообщение тут главное. Тут надо взвесить плюсы и минусы. Плюс в упрощении структуры таблиц.Примерно то же относится к вложениям. Возможно, проще просто сделать одну таблицу для любых вложений. Наконец, тут надо быть готовым к денормализации или кешированию. Допустим, мы хотим показывать пользователю число непрочитанных сообщений в диалоге. Делать это через подсчет сообщений без признака прочтения неэффективно. Эффективнее иметь готовую циферку. Или, допустим, мы хотим вывести верхние 50 диалогов. Эффективнее одним простым запросом получить список диалогов, циферки непрочтенных сообщений, чем выбирать эти данные через джойны и группировки.Потому вначале надо придумать правильную нормализованную схему, а потом составить список типичных запросов, которые мы будем делать, и при необходимости реализовать индексы, денормализацию либо кеширование. В мессенджере чаще будут идти запросы на чтение, и они должны выполняться быстро, и с использованием индексов. Запросы также можно разделить на часто и редко выполняемые (например, получение списка последних диалогов выполняется часто, а получение истории месячной давности - редко) и учитывать это.Поэтому, думаю, схему надо доработать. > Разделение приложений к сообщению на отдельные таблицы для каждого типа, а не хранения всех видов файлов в одной, позволяет в будущем расширять приложение, если появятся новые типы данных.Но оно не дает нам эффективно делать пагинацию по сообщениям, что сводит плюсы на нет.> Я правильно понимаю, что в Питоне объект, это instance класса, как в PHP, а не как в JS? Для каких ключевых типов данных вы имеете ввиду?Да, как в PHP. Я имел в виду, что если у тебя в коде есть какой-то массив, который много где используется, передается и возвращается разными функциями, то правильнее будет сделать его объектом. Но, как я понял, там был просто тестовый код, и тогда это не важно.> Разве это не создаст дополнительные проверки и не раздует код? Т.е. во время ответа писать: if error is not None: principals['extra']['error'] = error; Почему нельзя собирать массив "на ходу"?Потому, что это разные задачи: получение данных и формирование ответа на JSON-запрос. И скорее всего, лучше чтобы отдельно была функция проверки авторизации, а отдельно функция, которая формирует JSON-ответ. А не совмещать это все в одной функции. Но так как это тестовый код, то это не принципиально.
>>1378326Repository это паттерн, про который можно прочесть тут: - https://www.google.com/search?client=firefox-b-d&q=%D0%BF%D0%B0%D1%82%D1%82%D0%B5%D1%80%D0%BD+repository- http://design-pattern.ru/patterns/repository.html- https://martinfowler.com/eaaCatalog/repository.htmlРепозиторий изображает "хранилище", в котором хранятся сущности, откуда их можно получать, добавлять, удалять. При этом пользователь Репозитория не знает, где они хранятся: в БД, в массиве в памяти или где-то еще. В Доктрине репозиторий реализует такие интерфейсы, из которых видно, что он может делать: - https://github.com/doctrine/persistence/blob/master/lib/Doctrine/Persistence/ObjectRepository.php- https://github.com/doctrine/collections/blob/master/lib/Doctrine/Common/Collections/Selectable.phpВидно, что там в основном получение данных. Доктрина предоставляет готовый общий репозиторий: - https://github.com/doctrine/orm/blob/master/lib/Doctrine/ORM/EntityRepository.phpНо ты можешь сделать свой репозиторий для какой-то сущности на основе доктриновского, и добавить туда дополнительные методы поиска данных. В общем: если ты изучаешь Симфони, то изучи Доктрину. А если ты ее изучаешь, то изучи связанные с ней паттерны, такие, как Entity Map, Unit Of Work, Lazy Load: http://design-pattern.ru/index.html . Посмотри, как они реализованы в Доктрине. Доктрину надо изучать. Я постоянно вижу, что люди ее не знают, и думают, например, что persist сохраняет объект в базу данных. Почему им лень даже документацию прочесть? >>378182Вместо echo лучше использовать <?= , и надо экранировать спецсимволы в ссылках при выводе.>>1380244В одиночных кавычках \n это просто бекслеш и буква n.>>1380297А я посто везде \n использую. Пишется короче и код читабельнее. Блокнотом Windows я все равно не пользуюсь.
Аноны, переходите в новый тред >>1380485 (OP)Я постараюсь тут в ближайшие пару дней проверить оставшиеся посты, но для надежности вы можете напомнить о них в новом треде.
>>1380460>Использование таблиц с похожими именами будет однозначно вызывать путаницу. Более того, я пока сам не понял, в чем разница между "сообщением" и "сообщениями" или "диалог" и "диалоги".Сообщение - это конкретная запись сообщения имеющая все данные о нём, от содержания до автора, id, даты публикации и т.д., а сообщения - это запись какие сообщения принадлежат какому пользователю и/или диалогу. Т.е. "сообщения" хранит ссылки для пользователя на id конкретного сообщения. Как можно понятней назвать таблицы чтобы не вызвать путаницу? Такая схема была предложена вами при обсуждении моей задачи чата на чистом JS:https://phpclub.tech/pr/res/1019301.html#1028550>чаты и диалоги лучше делать одинаковым способом, то есть представить диалог 2 пользователей как чат из 2 участников.>Первый вариант - сделать у каждого пользователя списки входящих и исходящих сообщений (по аналогии с почтовым ящиком), и помещать копии сообщения как отправителю, так и получателю. При этом каждый может независимо управлять своей историей сообщений, например, очищать ее. Для чатов сообщение придется копировать многократно.>>При этом, чтобы связать сообщения, можно сделать какой-нибудь добавочный id. Можно например сделать таблицу сообщений (где и будет этот id), и отдельно таблицу, которая хранит копию сообщения для конкретного получателя.Мне хочется казать, что я слегка её отшлифовал, убрав многократное копирование сообщений заменив его "ссылками" на сообщения.>Если ты хочешь делать для каждого пользователя свою копию сообщения, то не проще ли просто сделать таблицу "диалог", и таблицу "сообщения", где в сообщении стоит ссылка на диалог и ссылка на получателя, кому оно предназначено? То есть, так: >>диалог:>- uuid>>участники диалога:>- id пользователя>- id диалога>>сообщения: (копия для каждого получателя)>- uuid>- id, объединяющий копии одного сообщения>- id диалога>- id отправителя>- id получателя этой копии>- признак прочтения>- текст>>Кстати, в больших чатах невыгодно будет делать для каждого свою копию сообщения. Выгоднее делать всего одну копию для всех.>- id, объединяющий копии одного сообщенияЭто получается что объединяющее копия одного сообщения это отдельная сущность/таблица? Я не понимаю тогда, это получается тоже самое что и я предложил, только колонки в разных таблицах. Ну и контент сообщения в моём предложении находиться только оригинальном, а не дублируется.Повторюсь, что в ссылке на сообщение находиться id на сообщение, а не его содержимое:>текстовое_сообщения: (хранит в себя ссылки на сообщения для каждого отдельного пользователя)>-uuid>-пользователь (кому принадлежит ссылка)>-диалог (диалог в котором сообщение находится)>-uuid сообщения>-...>Далее, у тебя есть наследование таблиц (для текстовых, аудио, видео сообщений сделаны отдельные таблицы). Ты использовал Concrete Table Inheritance. Не очень удобно делать их разными таблицами. Представь, что тебе надо получить последние 10 сообщений в диалоге. Тебе надо будет запрашивать данные из каждой таблицы (из текстовых сообщений, аудио сообщений, видео сообщений) и объединять. Как ты себе представляешь эффективную пагинацию по ним? >>Логичнее было бы использовать другой паттерн наследования, например, Single Table Inheritance или Class Table Inheritance. В случае STI мы делаем единую таблицу для всех видов сообщений. В случае CTI мы делаем одну таблицу для полей, которые есть в каждом виде сообщения (отправитель, время отправки, получено), и отдельные таблицы для доп. полей (которые есть только у опр. вида сообщения): >>- http://design-pattern.ru/patterns/class-table-inheritance.html>- http://design-pattern.ru/patterns/single-table-inheritance.html>>В обоих случаях мы можем легко получить последние N сообщений или сделать пагинацию без использования OFFSET. Я думал об этом и предполагал, что у psql есть встроенная поддержка этого, и как оказалось, действительно есть https://postgrespro.ru/docs/postgresql/11/ddl-inherit>Также, возможно, имеет смысл свести любые сообщения к текстовым сообщениям с приложениями. Тогда аудиосообщение будет просто текстовым сообщением без текста с приложенным аудио, с пометкой, что аудиосообщение тут главное. Тут надо взвесить плюсы и минусы. Плюс в упрощении структуры таблиц.Не согласен. Аудиосообщение по сути это аудиозапись, и в прикрепление тоже могут прикладывать аудиозапись, и поэтому будет конфликт, что есть голосовое сообщение, а что аудиофайл. Для этого нужно будет наследовать отдельный тип прикрепления, что является тем же самым что и унаследовать от сообщений. Я считаю, что голосовые сообщения должны быть отдельным типом сообщения, а не прикрепления. >Наконец, тут надо быть готовым к денормализации или кешированию. Допустим, мы хотим показывать пользователю число непрочитанных сообщений в диалоге. Делать это через подсчет сообщений без признака прочтения неэффективно. Эффективнее иметь готовую циферку. Или, допустим, мы хотим вывести верхние 50 диалогов. Эффективнее одним простым запросом получить список диалогов, циферки непрочтенных сообщений, чем выбирать эти данные через джойны и группировки.Да, я думаю, что можно хранить количество непрочитанных сообщений и дату последнего сообщения прямо в таблице диалога.>>1380460>> Я правильно понимаю, что в Питоне объект, это instance класса, как в PHP, а не как в JS? Для каких ключевых типов данных вы имеете ввиду?>>Да, как в PHP. Я имел в виду, что если у тебя в коде есть какой-то массив, который много где используется, передается и возвращается разными функциями, то правильнее будет сделать его объектом. Но, как я понял, там был просто тестовый код, и тогда это не важно.Этот массив был бы объектом с одним свойством этого самого массива?
>>1380456>У тебя как-то странно сделано, что параметры сохраняются в $this->get. Это значит, что если ты с помощью функции linkMaker() создашь 2 анонимных функции, то одна будет влиять на другую (параметры, переданные в одну, отобразятся в другой). Это неправильно.>$this->getТак ведь там весь массив гет из реквеста, а не просто место для сохранения. Параметры не столько сохраняются, сколько апдейтятся - меняется только один, за который отвечает ссылка, и она пересобирается с новым значением.Ну и разные функции нет смысла создавать - всегда один гет-массив приходит в запросе и с ним работаем.Вообще, задумка была такой, что замыкание передаётся в шаблон под каким-то именем, где просто вызывается как на пикрелейтед. Меняются только запрошенные параметры, остальные не остаются как были. Ну и пустой писанины чтоб поменьше.Я тут не подумал сразу и вкинул эту функцию в тред, без комментов, без пояснений нормальных. Потом только дошло, что она не оформлена никак у меня.>если мы меняем сортировку, то надо сбрасывать пагинациюЗачем? Количество записей ведь не изменилось. Я вот со своей этой функцией поигрался - вполне юзабельно вроде. Страницы жмёшь - меняет страницы, сортировку меняешь - сортировка только и меняется, что нажали - то и выводит.
так, при регистрации валидатор симфони ругается: data.password This value should not be blank. nullConstraintViolation {#1123 -message: "This value should not be blank." -messageTemplate: "This value should not be blank." -parameters: [] -plural: null -root: Form {#594 } -propertyPath: "data.password" -invalidValue: null -constraint: NotBlank {#905 …} -code: "c1051bb4-d103-4f74-8988-acbcafc7fdc3" -cause: null}помогите пж нубасу)
>>1381798Во-первых, иди в новый тред, этот утонул, >>1380485 (OP) Вот-вторых, у тебя же в ограничении стоит NotBlank, то есть поле обязательно к заполнению.
>>1380677>>> Я правильно понимаю, что в Питоне объект, это instance класса, как в PHP, а не как в JS? Для каких ключевых типов данных вы имеете ввиду?>>>>Да, как в PHP. Я имел в виду, что если у тебя в коде есть какой-то массив, который много где используется, передается и возвращается разными функциями, то правильнее будет сделать его объектом. Но, как я понял, там был просто тестовый код, и тогда это не важно.>Этот массив был бы объектом с одним свойством этого самого массива?Или я подумал, что это может быть объект со свойствами которые содержатся в этом массиве, и сделать этому объекту метод toArray().
>>1380459>Есть очереди задач для этого. Ты имеешь в виду какой-нибудь rabbitmq? Из пушки по воробьям же. Мне нужно просто отправить юзеру view сразу, до того как долгий таск завершится. Я до этого писал всякую шляпу на fat free framework и там есть функция abort, которая делает нужноеhttps://fatfreeframework.com/3.6/base#abortЯ вполне способен залезть в исходники и посмотреть, что она там делает и перенести это в симфони, но ведь скорее всего это уже там есть и мой велосипед всяко будет хуже.
Анонче, подскажи, а то я застрял. Делаю грамматического нациста, хочу сделать проверку по отсутствию знака препинания. Идея такая я делаю preg match all с preg set order< затем дампую. 0й массив. Но как мне ограничить регулярку? Я думал таком варианте '/s|^. - это либо символ начала строки либо ограничивающий пробел.\.\S - условие замены.\s|.*\. - ограничение по пробелу или концу строкЯ хочу что бы сделав дамп 0го массива вылезли все ошибки. Но почему - то даже правильные последовательности тоже выдаются. Где я перемудрил? По возможности намекните т к хочу допереть сам
>>1380677>Как можно понятней назвать таблицы чтобы не вызвать путаницу? Также, можно добавлять комментарии к таблицам. Разработчики часто их читают?https://postgrespro.ru/docs/postgrespro/11/sql-comment
>>1380677>>1383892>>Использование таблиц с похожими именами будет однозначно вызывать путаницу. Более того, я пока сам не понял, в чем разница между "сообщением" и "сообщениями" или "диалог" и "диалоги".>Сообщение - это конкретная запись сообщения имеющая все данные о нём, от содержания до автора, id, даты публикации и т.д., а сообщения - это запись какие сообщения принадлежат какому пользователю и/или диалогу. Т.е. "сообщения" хранит ссылки для пользователя на id конкретного сообщения. >>Как можно понятней назвать таблицы чтобы не вызвать путаницу? Можно вместо создания бесконечного количества ссылок создать поле с типом ARRAY и помещать в него все ссылки (UUID) на необходимые данные.https://postgrespro.ru/docs/postgresql/11/arrayshttps://postgrespro.ru/docs/postgresql/11/functions-arrayСоответственно, все операции будет выполнятся легко и ловко.Прим.Message:-uuid...Dialog:-uuid-private BOOLEAN-participants UUID[] //массив из uuid получателейParticipant:-uuid-user-messages UUID[] //массив из uuid сообщенийИ все операции выполняются очень легко:// Пользователь удаляет свою копию сообщенияUPDATE Partcipant SET messages = array_remove(messages, uuid_of_message) WHERE uuid = uuid_of_participant;// Проверить существует ли приватный диалог,// не смотря на то что один из пользователей когда-то покинул диалогSELECT * FROM Dialog WHERE private = true AND (uuid_of_alice = ANY(participants) OR uuid_of_bob = ANY(participants));
Есть ли какая-то принципиальная разница между этими методами?public function do() { //... this->calculate($someVar);}private function calculate($someVar) { //.. $this->supaVar = $someVar 42;}ИЛИpublic function do() { //... $this->supaVar = this->calculate($someVar);}private function calculate($someVar) { //.. return $someVar 42;}
Не пишите пожалуйста в закрытый тред, когда есть новый >>1380485 (OP)Ответил в новом треде: пост >>1380677 - ответ >>1388212пост >>1380688 и >>1381843 - ответ >>1388213пост >>1382020 , >>1383863 и >>1383892 - ответ >>1388214
Если планируете перекатываьтся за границу, то забейте на пхп. он мертв в развитых странах.Говорю на своем опыте. я перекатился в израиль и тут нет вакансий. нода в 3-4 раза востребованей. самые топовые языки тут это с#, питон и джава