24 декабря Архивач восстановлен после серьёзной аварии. К сожалению, значительная часть сохранённых изображений и видео была потеряна. Подробности случившегося. Мы призываем всех неравнодушных помочь нам с восстановлением утраченного контента!
Добро пожаловать. Тут мы изучаем язык PHP (а также JS/CSS/HTML/SQL), решаем задачки и даже делаем простые сайты! Зачем? Кто-то хочет сделать себе блог, кто-то приобрести новую профессию, кому-то просто нечего делать.
Пожалуйста, пишите один большой пост вместо нескольких маленьких и не флудите не по теме.
Это тред для начинающих. Не написал за свою жизнь ни одной программы и имеешь тройку по математике? Ты наш человек.
Предыдущий тред был тут: >>1109863 (OP). Остальные треды есть в архиве: https://phpclub.tech/ или ищутся в гугле по словам "клуб изучающих php" и в архиваче.
Мейлач лежит? Есть запасной тред на доброчане: /s/res/23225.xhtml#i46467
Что самое главное для программиста? Умение аккуратно оформлять код (как, написано во втором посте).
Правила: ведем себя воспитанно, помогаем новичкам, читаем учебники, решаем задачки, постим ссылки на решения, ОП их проверяет и дает советы и замечания. ОП заходит редко, где-то раз в 2-3 дня, у него мало времени, не жди его, решай задачки дальше. ОП отвечает на все вопросы по его задачкам и учебнику, а вот насчет каких-то других вещей - только если останется время. Но в треде немало анонимных экспертов разного уровня, так что вряд ли вопрос останется без ответа.
С чего начать
У нас есть свои уроки по основам PHP, они собраны и выложены по адресу http://archive-ipq-co.narod.ru/ Это учебник для изучающих с нуля, то есть если ты вообще ничего не знаешь, то можно начать с него. Он простой и понятный. Там есть задачи, их нужно решать (чтобы стать программистом, надо писать код — иначе никак). Пости ссылки на решения в тред, мы их проверим, напишем замечания и дадим советы по улучшению. С другой стороны, если этот учебник тебе не нравится, можно читать любой другой. Или официальный мануал. Или все сразу.
Устанавливать пока что ничего не требуется, разве что редактор кода вроде Sublime Text 3, Notepad++, Visual Studio Code, Netbeans PHP или PhpStorm (с ним будет удобнее).
Если не знаешь как решать, запости код, напиши в каком месте остановился и попроси подсказку.
Ты прошел весь учебник? Молодец, но это были лишь основы языка PHP, этого недостаточно. Вот что в идеале надо изучить еще: ООП, как работает веб-сервер, HTML/CSS, SQL, PDO, работа с таблицами в БД, работа с формами, MVC, git, composer, JS, фреймворки, автоматизированное тестирование.
Надо переходить к более серьезным задачкам, которые научат тебя всему этому.
Решения задач лучше показать мне, особенно на ООП,так как сам ты вряд ли увидишь все ошибки. Пости свой код на гитхаб и вкидывай ссылку в тред по мере решения. Я прокомментирую и укажу на ошибки.
Также, у нас есть задачи которые позволят тебе изучить или подтянуть до нормального уровня знания JS/HTML/CSS/SQL. Решай их параллельно с задачами выше.
Оформляй код аккуратно!!! — например пропусти через 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, там тоже есть функция форматирования кода.
Вообще, в 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 пробела)
Вот ссылка на стандарты, где все это описано подробнее и даны примеры оформления:
Сап анончики. У меня интересная задачка. В прошлом треде я уже спрашивал но тут мне понадобилось кое что уточнить.
Суть такова. Допустим есть карта (просто jpg изображение на котором карта ). Нужно поверх этого изображения разместить ещё 40-50 мелких изображений (20*20px). При этом если первое изображение карта занимает всю страницу, то другие изображения будут мелкими типа маркеров на гуглмапсе. При это каждое из 40 мелких должно иметь свои координаты. В прошлом треде мне помогли с координатами z index и CSS скинув очень годные ссылки. Эти https://www.w3schools.com/cssref/pr_pos_z-index.asp https://www.w3schools.com/css/css_positioning.asp
Но теперь вопрос как будет лучше это всё размещать так чтобы небыло говнокода. И при этом работало. Например есть карты с 59 обьектами (или 23, или вовсе 2 чтобы вы поняли). Я скриптом прохожусь чтобы узнать количество обьектов, потом формирую страницу, и сразу генерирую CSS встроенный в страницу чтобы создать 59 обьектов и сразу дать им координаты? Или можно это всё сделать по другому, например через JS?
>>1118287 Я не смог применить эти функции, у меня с ними не работает и я так до конца и не понял, каким образом их использовать. >>1118475 >Ты каждый раз заполняешь строку в ручную, а нужно делать это программно, чтобы программа работала с заведомо неизвестным количеством массивов и элементов Ну эту проблему я тоже не смог решить, до оепратора точка не додумался. >>1118548 >// Идем по массиву массивов слов и на каждом шаге выбираем 1 слово foreach ($allWords as $variants) { var_dump($variants); } Но как он будет случайные слова подбирать? Он же их просто перебирает.
Это снова я со своим массивом, спасибо анончикам за их терпение и помощь, уменьшил количество кода, запилив все циклом с условиями. https://ideone.com/YMAqiv Ниже функции пока не пробовал применить, ща буду макакить >foreach ($allWords as $variants) { var_dump($variants);
>>1118617 Дополню, что по условиям должно быть >words1, words2, word3 >words1, words2, words3 >words4, words5 то есть четко поставлены условия, из каких массивов должны быть взяты рандомные слова.
Правда, я попробовал почитать, русский перевод очень плохой, и сделан явно через Гугл Translate (и это не мешает сайту быть в топе выдачи). Так что по возможности лучше читать исходную документацию на английском.
Никогда не сталкивался с докером, но сейчас придется. Вопрос у меня вот в чём: достаточно ли одного докера или нужно будет ещё что-то для того, чтобы на чистой убунте создать несколько виртуальных машин на борту, каждая из которых будет загружать определенный контейнер. (хочу потестировать горизонтальное масштабирование)
Имеются более менее знания python/django, знаю что такое ООП и нахуя оно, БД так сяк. Вопрос стоит ли вкатиться в php? (в основном из-за большего количества как вакансий, так и заказов на фрилансе) И смогу ли уложиться в 3 месяца (начинаю прям щас), если буду ебашить прерываясь только на поспать и посрать?
Начал вкатываться. Писал пару пробных чятиков и гостевуху, теперь хочу поближе познакомиться с основами, скачал какое-то приложение на телефон, вникаю. Язык не нравится. Как сишника, отталкивает буквально всё. Но учу. Зачем? Потому что простой. Потому что хочу понимать различные технологии, а не говноедствовать, задрачивая на один язык.
>>1118712 Насколько я понял, докер разворачивает каждый процесс как отдельный контейнер, и так как я думал: nginx + php-fpm + mysql в одном контейнере не выйдет, или я ошибаюсь? Или посоветуйте что-то для быстрого деплоя/развертывания одного проекта на N-нод
>>1118617 http://archive-ipq-co.narod.ru/l1/strings.html >Подсказка: так как первая и вторая строка формируются по одинаковому принципу, то незачем копировать код 2 раза, можно использовать цикл из 2 шагов. Тебе просто нужно выполнить два раза циклом склеивоние 1-ых по 3-их слов и добавить перенос строки, и затем отдельно вначале добавить "Я", и склить 4-ые и 5-ые
>>1118618 >Подсказка: можно упростить программу, сделав что-то вроде шаблона для генерации стиха на основе массива. В каждый элемент массива мы кладем массив вариантов слова или строки, из которого надо сделать выбор: [$word1, $word2, $word3, ["\n"], ...]. Мы добавляем массив с "\n", чтобы в нужном месте вывелся перевод строки. Остается только пройти по массиву циклом и сгенерировать стих.. В этом случае можно будет воспользоваться foreach
Если ты запускаешь простые скрипты, то тебе может быть проще просто использовать встроенный в PHP веб-сервер как описано по ссылке, которую дал анон выше.
Гугли наследование css селекторов, поймёшь всё очень быстро. Если коротко, то ты даёшь стиль элементу а внутри класса sidebar-module, а если ты напишешь a.sidebar-module, то получиться, что ты даёшь стиль всем элементам a с классом sidebar-module.
кто фронтом и версткой занимается, как вы это делаете вообще? решил себе сайт запилить, абсолютно невозможно спрогнозировать, что сколько времени займет. можно за 5 минут приделать всплывающую подсказку для формы поиска, а потом час равнять два дива по высоте. и главное в итоге удовольствия никакого (в отличие от бэкенда)
Как правильно кнопки оформлять? Я сейчас не про внешний вид, а про сам код. Задавать через <a href="#"> и потом их оформлять я уже заебался, подкидывая при этом <a>дский костёр градиенты, вертикальные линии и ставя красивые границы, а ещё нужно стили убрать, ух бля. Знаю про элемент button, но нигде не видел по этому поводу, формы не подходят изначально, они для другого сделаны, для отправки данных на сервер, или я долбоёб? Скажите что-то по этому поводу, вкатился недавно и верстаю себе очко пока что, через неделю-две вкатываюсь в джс и нужно до конца отдрочить этот html/css.
>>1119251 >сбрасываешь стили >ставишь дисплей блок >оформляешь как обычный див >profit... Мимо вкатывальщик из фронт-энд треда, а еще есть фреймворки типа бутстрапа...
Аноны если мне нужно в слиме в middleware доступ к бд. А получить через контейрнер его я там не вижу как. То это хуевая реализация. Или мне создать свой пдо в нем?
>>1119307 Разве ты не регистрируешь __invoke() класс в контейнере прежде чем добавить его в промежуточный слой? В нём и добавляй все зависимости через конструктор.
>>1119300 Нет, у тебя там 3 функции с одинаковым кодом, это плохо - копипаста. У тебя должна быть одна функция, а переменные, которые ты задаешь в начале, должны передаваться через аргументы.
>>1119337 А что такого? Вообще нейросети довольно старое понятие, их ещё в прошлом веке наверное с 60ых годов разрабатывали, потом хайп ушел так как не хватало мощностей, сейчас вторая волна началась (может и не вторая, а N-волна). Во-вторых кому-то надо будет поддерживать эту верстку, кому-то надо будет работать с самими нейронками, заказчики сами этого не сделают. Я глазами пробежал, там только статика? Сейчас любой сайт, это наполовину js-приложение, которое без js зачастую просто развалится либо превратится в тыкву. Ну и в третьих, это даже хорошо когда механические задачи больше не надо будет делать.
>>1119337 по правде говоря, тот самый "верстальщик", который 10 лет назад верстал статику, уже не существует в природе. щас любую статику можно сделать быстро и без гемора с помощью существующих инструментов (бутстрап, например) при наличии минимального опыта. то есть, такой профессии уже давно нет, сейчас есть фронты.
Прежде чем создать какой-то сервис нужно зарегистрировать его в контейнере. Но это не точно.
>>1119358 >хотя не уверен, что это именно то, что ты имел ввиду В задаче сначала был массив массивов $words с всеми словами
В посте >>1118981 есть подсказка как решить такую задачу >>Подсказка: можно упростить программу, сделав что-то вроде шаблона для генерации стиха на основе массива. В каждый элемент массива мы кладем массив вариантов слова или строки, из которого надо сделать выбор: [$word1, $word2, $word3, ["\n"], ...]. Мы добавляем массив с "\n", чтобы в нужном месте вывелся перевод строки. Остается только пройти по массиву циклом и сгенерировать стих..
>>1119435 Лучше не к фреймворкам привязываться, а делать упор на фундаментальные вещи - сети, ООП, линукс. Я к примеру устраивался Symfony джуном и за полгода успел поработать с Laravel, Yii2, Zend. При том, что ранее с этими фреймворками знаком не был.
>>1119540 пхп как бы не только в окошечке браузера работает. большую часть современных больших приложений составляют cli-скрипты. также потому что ты будешь подключаться по ssh к удаленному серверу, который на линуксе. плюс гит. плюс баш-скрипты автоматизации на дев-сервере. плюс перезапуск сервисов, сборка фронта, еще куча всего.
>>1119543 >> устраивался Symfony джуном > какие вопросы задавали на собесе? Конкретно по Symfony не спрашивали ничего серьёзного - какие FormType использовать если есть сущность и связанные с ней через 1:M другие сущности, какие существуют способы описания метаданных сущностей, в чём преимущества недостатки у каждого из способов, какие бандлы юзал и т.д.
Больше было общих вопросов, например как работают сессии, что такое DNS, зачем используются трейты/итераторы/генераторы, магические методы, какие новые фичи в PHP7. Тестовые задания не просили делать, видимо из-за аккаунта на гитхабе, но было пару задачек на проектирование простой иерархии классов и на рекурсивный обход массива (у ОПа как раз есть эта похожая задача: https://github.com/codedokode/pasta/blob/master/interview-tasks.md#%D0%94%D0%B5%D1%80%D0%B5%D0%B2%D0%BE ). Код на листочке не писал (как этим любят запугивать в перезвоним-тредах), описывал алгоритмы словами.
По JS - чем отличаются call и apply, почему теряется this, что нового в ES6, что такое прототипы (ни разу не юзал их за всё время что работаю, но на собесе ответил, так как решал здесь задачи). Ещё немного тут писал: https://phpclub.tech/pr/res/1067944.html#1075232
>>1119900 В том и дело, хотел пообщаться с кем-то по поводу докера и систем виртуализации в целом, но никто не отвечает. В чате может быстрее это произошло бы
>>1119867 есть. тут даже был один, который пытался версию пхп обновить что ли. просто я к тому что это не повод не учить линукс в надежде, что попадется виндос сервер (который поди еще замороченнее линукса в изучении).
Такая задача: Необходимо написать скрипт парсера, который будет выполняться несколько дней неиспользуйпхпшники идут нахуй.
Проблема в том, что во время выполнения скрипта может произойти где-то ошибка, например мне нужно писать спрасеное в удаленные БД, где админы любят мутить всякую хуйню из-за чего порой можно не получить соденения с базой. Либо еще какойто ноунейм fatal error.
Соответственно скрипт упадет. А мне этого ненужно.
Пишу перехватчики через set_error_handler() и set_exception_handler() при получении ошибки - шлю к себе на почту. Но как быть в случае fatal error? Как сделать так, чтобы при получении таковой ошибки скрипт продолжил выполнение?
Можно конечно обвешать все try catch throwable, но это хуита ибо не всего не учесть. Ваши предложения?
>>1119947 >один и только один Попахивает индексом Unique для поля в БД. В принципе, в твоем случае идентификация происходит по Primary key а он всегда unique. А какой программой ты пользуешься для моделирования?
>>1120023 >но я уже не уверен, что это относится к проектированию бд. это я имел в виду про одинарную черточку, т.к. они там моделируют далеко не только бд. возможно в бд достаточно обозначить тип связи и все
>>1120110 Может быть и не знаю, но вопрос тем не менее остаётся в силе, с каких пор в пхп можно или нужно указывать типы данных при объявлении функций?
>>1120023 >https://www.lucidchart.com/ Не вижу там возможности экспорта схемы БД. Подобный софт должен это делать в форматах SQL и XML, да еще и с тестовыми данными, как это делает Sybase Power Designer. А в идеале он еще должен генерировать классы для работы с базой и фреймворка, как это делает Skipper (ORM Designer), но для него кряка нет, а он стоит баков 300 отсоси у тракториста.
Есть у меня допустим страница с кнопками от бутстрапа. Есть файл php скрипта. Как их законектить самым простым способом? Чтоб при нажатии на кнопку выполнялся скрипт.
Гуглением нашел всякие ассинхронные фреймворки, но мне нужен максимально простой способ. Или хотя бы хороший пример - потому что в гугле тонна примеров сабмит формы, но мне это не очень подходит.
>>1120128 -можешь положить все кнопочки в форму в которой у тебя прописан action='твой скрипт' -Можно с помощью жквери. Типа присваиваешь функцию кнопочке, а в функции у тебя аякс.
Во первых учи PSR и юзай скобки!!! Во вторых, у тебя тут цикл по пустому массиву $randomText, чего ты ожидаешь? Во третьих, ты украл чей то код? >/ Выкидываем случайное число (count - число элементов в массиве) / >/ Точка склеивает 2 строки в одну / Эти комменты указывают на вещи которые не используются в коде, а должны бы.
>>1120212 >Во вторых, у тебя тут цикл по пустому массиву $randomText, чего ты ожидаешь? Что я несу, совсем обджиэсился. У тебя цикл по ВСЕМ слогам, $randomText это переменная цикла - значение каждого слога, но в цикле ты присваиваешь ей новое значение, что бессмысленно
Здравствуйте, нулевый болванчик итт. Есть сайт на одной из страниц которого лежат изображения, нужно их заменить на новые. Скачал фтп, все залез, нашел где лежат данные картинки. Но не могу найти файл где они прописаны что они должны находится на именно той странице сайта (не знаю как правильно объяснить но вы поняли) Т.е на сайте они лежат по адресу www.site/wp-content/uploads/2011/12/filename.jpg На фтп они там есть. Искал через notepad++ во всех файлах упоминание filename.jpg, его там тупо нету. Что я делаю не так?
>>1120168 они там поди генерятся динамически и их названия лежат где-то в бд в отдельной ячейке или генерятся по названию статьи, хз. может кто-то, знающий вп, ответит более конкретно
>>1120234 Какое ВП? Какая база, поехавший? >>1120180 Жопой читаешь? Поясню сокращенно: вешаю обработчик на set_exception_handler() можно как-то сделать, чтобы в случае fatal error скрипт не падал, а продолжал выполнение? Повторю: Я НЕ ХОЧУ ОТЛАВЛИВАТЬ КАЖДЫЙ ПУК ЧЕРЕЗ try catch
>>1120218 да, просто эта возможность тесно связана с тайп-хинтом аргументов и возврата, о котором спрашивал анон.
алсо, я тут пытаюсь использовать эту строгую типизацию, она конечно прикольная, но какая-то недоделанная по сравнению с джавой. нельзя указать тип переменной например int $count; надо писать обязательно $count = 0; но это хуета в принципе, а вот что нельзя сделать массив строк или массив интов - это недоработка по мне.
плюс есть некоторые функции, которые исторически выдают либо фолс, либо тру, либо число, либо массив. допустим preg_replace возвращает либо массив, либо строку, либо нулл.
>>1120236 >нельзя указать тип переменной например int $count; Чел ну это не недоделанность, это другой синтаксис. А ты что думал, что выучишь джаву и всё? Везде так будет?
>>1120236 Видимо ты не правильно пользуешься функцией preg_replace. Так как регулярные выражения в php работают очень хорошо и никаких проблем не вызывают
>>1120236 preg_replace() возвращает массив, если параметр subject является массивом, иначе возвращается строка. Если найдены совпадения, возвращается новая версия subject, иначе subject возвращается нетронутым, в случае ошибки возвращается NULL.
Так вот, исключения тем и отличаются от ошибок PHP, что в случае их возникновения PHP выходит из функции вверх (в вызвавшую фукнцию), из нее еще вверх и так, пока не наткнется на catch или не выйдет на самый верх. Это поменять нельзя.
В случае обычных ошибок принцип другой - при ошибке вызывается обработчик, и есть выбор, завершить скрипт либо проигнорировать ошибку. Опции "повторить проблемную команду" нет и там.
Тебе придется править код программы и добавлять повтор попыток явно. По моему, проще просто настроить БД нормально (или запускать скрипт у себя, где ничего не отвалится). Иначе надо искать все места в скрипте, где идет обращение к БД и заменять стандартные функции на свои, которые будут ловить исключение и при его возникновении делать повторное соединение к БД. желательно ограничить число попыток.
>>1120244 Ну и что в этом такого необычного? В php это обычная практика делать функции, которые возвращают разные типы данных в зависимости от различных параметров.
У ответа ведь все равно всегда можно проверить тип данных при помощи функций is_bool, is_double, is_string, is_array и так далее.
>>1120243 это просто пример того, что встроенные функции под возврат нужного типа не приспособлены. таких примеров много. в случае с preg_replace можно возразить "ну шли туда всегда строку и будет возвращаться строка", но тут другой нюанс: допустим, я хочу обернуть логику в свой метод, в других языках для обработки разных типов данных есть перегрузка, а тут ее нет, придется писать replaceString(), replaceArray()
Суть программирования в том, что тебе надо написать решение задачи в виде набора шагов, которые поймет компьютер. Он твои мысли читать не может и не угадывает, что ты имел в виду, а выполняет программу строго, как она написана.
Ты можешь для начала расписать, что должно делаться внутри цикла, на русском языке? Чтобы было видно, где проблема - ты не понимаешь, какие действия надо сделать, или же ты понимаешь, но не знаешь, как их записать на языке PHP?
По твоему коду, у меня ощущение, что ты просто там писал наугад команды в надежде, что оно как-то заработает. Увы, так это не работает. Нужно понимать, что делает каждая строчка.
Я дам тебе пример, как сгенерировать имя из 2 цифр (согласен, странное имя, но это ради простоты):
$number1 = сгенерировать случайную цифру от 1 до 6; $number2 = сгенерировать случайную цифру от 1 до 6; $result = склеить $number1 и $number2 в одну строку; вывести $result;
Заметь, что у меня нет цикла. Это для простоты. Я сначала написал простое решение без цикла и для 2 слогов, а потом могу переделать на цикл с любым числом повторений. Ты можешь сделать так же, сначала без цикла, с 2 слогами, а потом уже сделать нормально.
Попробуй свое решение записать так же. Если ты не понимаешь, какие должны быть шаги, напиши, дадим еще подсказки.
>>1120253 >>1120241 Спасибо за развернутый ответ, анон. Мой же пост. Понимаю как это выглядит в русском языке, но знаний в php не хватает для отражения онного же в коде. Немного не ту версию кода засейвил на работе, поэтому так и выглядит. А исходник лежит на домашнем пека.
>>1120251 Я к тому, что я смог найти это в доках за 5 секунд. PHP не идеален, но блин вот эта функция по моему работает вполне внятно. Ладно не буду превращать тред в чатик.
В чем отличия и надо ли использовать ссылки? Например тут function trim_value(&$value) { $value = trim($value); } Я бы бы через foreach перебрал. Чем мой вариант хуже кроме того что он длиннее?
>>1120252 >в других языках для обработки разных типов данных есть перегрузка
В php конечно же нет перезагрузки функций, т.е. создание функций с одинаковыми названиями, но разными параметрами. Но этого обычно и не требуется, так как во-первых, можно объявить параметры с default-значениями: function func($int, $string = ''),
а еще можно проверять тип данных параметра: function func2($var) { if (is_array($var)) //сделай это else if (is_string($var)) //сделай что-то другое else //сгенерируй сообщение об ошибке }
Обе эти возможности на 100% заменяют перезагрузку функций.
PHP называют языком с "добровольной типизацией" - кто хочет, тот и ставит тайп-хинты. Тайп-хинты можно ставить на аргументы и результат функций но, увы, нельзя на поля и переменные. Также, увы, тайп-хинты ограничены в возможностях и пока нет generics.
Как видишь, с тайп-хинтами код становится намного лучше, так что советую ставить их везде.
Замечу, что эта опция влияет только на отключение преобразования типа в тайп-хинтах. Мне она не нравится тем, что теперь у нас может быть 2 вида исходников, в одних все совсем строго, в других не совсем. Опять они не смогли выбрать одно решение и решили всем предложить выбор.
По моему субъективному мнению, отсутствие единого типа аргументов или результатов ухудшает код и повышает вероятность ошибок. Я бы сделал для массивов отдельную функцию preg_replace_array.
А вот возвращать что-то или null вполне допустимо. null для этого и придуман.
По моему субъективному и ничем, кроме моего опыта, не подкрепленному мнению, это плохо. Нельзя же писать нормально код, когда ты не уверен, какого типа результат. Нужно строго определять типы аргументов и результата, если они могут быть разные, лучше сделать несколько разных функций. Иначе легко ошибиться.
Контент (в том числе HTML код статей) может храниться в базе данных. Редактировать их можно в случае вордпресса через админку, в которую тебе должны были выдать доступ.
Но ты можешь заменить файлы картинок, оставив те же самые имена.
>>1120235 >Какое ВП? Какая база, поехавший? а, это я не тебе. это я >>1120217 анону
алсо, валерианочку попей.
>>1120265 >Если ты хочешь как на Джаве, то проще на ней и писать туда хер вкатишься. сам язык не сильно сложнее пхп, но экосистема просто безумно большая.
плюс если перекатываться, там будет явно меньше зп вначале, но это уже для другого треда разговор.
>>1120270 >Редактировать их можно в случае вордпресса через админку, в которую тебе должны были выдать доступ. Не совсем понял, но полный доступ к хостингу, фтп вот к этому всему есть. Пикрил - список плагинов. Да, я так уже и сделал - заменил изображения на новые с такими же именами, но одно изображение исчезло (пустое место) но кликабельность и ссылка на него осталась, блин
>>1120270 https://ideone.com/IlvuRW Не понимаю как из $letters перетащить данные последовательно по слогу. Поэтому собственно и спрашивал о переборке через foreach.
>>1120270 >>У нас обучающий тред, желательно писать, почему. А то без аргументов выглядит как чье-то личное мнение. >У нас обучающий тред, желательно писать, почему. А то без аргументов выглядит как чье-то личное мнение.
Причина очень проста. Использование ссылок делает код более трудным для понимания и для поддержки, не давая почти ничего взамен
Странно, что ты никогда не слышал про админки. Там на сайте есть форма входа, вводишь туда логин и пароль и получаешь доступ. Попроси у заказчика "логин и пароль администратора сайта" и адрес страницы, куда его вводить. Они же как-то эти статьи туда добавили.
// Берем случайный элемент массива и сохраняем в random его ключ (не значение, то есть не сам слог) $random = array_rand($letters);
// Создаем пустой массив и помещаем в переменную $randomText = array();
// склеиваем все 16 слогов из массива letters в одну длинную строку и помещаем в randomText, // удаляя хранившийся там ранее массив $randomText = implode($letters);
Соответственно, тебе надо немного вернуться и повторить такие вещи:
- что массив состоит из элементов, у каждого есть ключ (=индекс) и значение. Ключи уникальны и не повторяются внутри одного массива. - как, имея массив слогов и ключ одного слога, получить значение этого слога? Подсказка: использовать квадратные скобки. Может, в уроке это плохо описано, но конструкция вида массив[ключ] возвращает значение элемента с данным ключом. Здесь "ключ" может быть переменной, числом, строкой в кавычках, сложным выражением. - далее, получая на каждом шаге цикла один слог, как их собрать в массив? Надо до цикла создать пустой массив, а в цикле добавлять в него еще один элемент. Добавление элемента в массив (внутри цикла) делается так: массив[] = значение; При этом ключ для нового элемента генерируется автоматически. Ну а после цикла ты уже можешь склеить собранные слоги из массива в одну строку.
То есть, ты плоховато знаешь работу с массивами и отсюда проблемы.
Давай после задачки про слоги решим дополнительную задачку, чтобы лучше в них разобраться. Дано 2 массива с оценками за январь и за февраль вида:
Привет всем анонам. Всё еще пилю сайт про студентов. Я много слышал про разделение логики приложения и логики представления, но с пагинацией я немного запутался, есть класс, в одном из методов которого я просто через цикл печатаю ссылки на экран, а потом объект пагинации передаю во вью, так нормально делать? Альтернативой будет сделать цикл в отдельном шаблоне, и передавать туда объект, а потом еще и написать тыщу геттеров для полей класса, я ж инкапсулирую. И еще вопрос по неймспейсам, если у меня например класс вью называется App\View\View , а шаблоны лежат например в App/templates, как лучше всего подключить шаблоны уровнем ниже(выше?) неймспейса? Я пытался как-то изворачиваться с двойными точками, но полное понимание так и не пришло.
Вот все говорят что задачку из учебника на генератор стишков нужно делать через цикл склеивающий строки. Но не будет ли быстрее (по производительности) прост дважды склеить строку, без цикла? (Вопрос из опыта на питоне, где все встроенные функции написаны на С и без цикла обработалось бы быстрее). На пхп второй день, хз че у него под капотом.
Как в Symfony сделать форму для свойства, которое хранится как массив, а в БД как json. Для хранения переменного числа характеристик. Использовал пока CollectionType, в котором кастомный keyValueType (key, value поля). Получается в БД поле такого вида: [ {"key": "Материал", "value": "металлический каркас"}, {"key": "Цвет подставки", "value": "черный"} ], а хотелось бы такого: [ {"Материал": "металлический каркас"}, {"Цвет подставки": "черный"} ]. Или вообще только массив, без объектов внутри, но теперь, так понимаю, json_array в Doctrine теперь deprecated. Что можно придумать, чтобы при этом формы редактирования выводились в два поля: название характеристики и ее значение. Data Transformer? Вроде не то. Пробовал через FormEvents::PRE_SUBMIT, тоже не вышло ключи изменить у коллекции. Возможно, это я неправильно делал. На крайний случай можно через Event[Subcriber|Listener] Доктрины, но кажется, что это кривые костыли.
>>1120238 Я знаю что вп - это вордпресс причем он тут? >оно на то и фатал еррор, чтобы останавливать программу через try catch throwable не останавливает
>>1120308 Также, на regex101 https://regex101.com/r/qF7vT8/3 уже введены номера и можно простестировать свою регулярку. Помни что на этом сайте надо писать бекслеш один раз, например \s, а не \\s. Флаг m там стоит чтобы ^ и $ в регулярке обозначали «начало и конец любой строки», а не «начало и конец всего текста». Флаг g (его нет в PHP, он только на этом сайте) значит что надо искать все совпадения с регуляркой, а не только первое. Там в уроке все написано, внимательнее будь
кто подскажет? использую симфони4+доктрину. хочу чтобы доктрина сама обновляла created_at и updated_at для полей. такая возможность была раньше в бандле расширений доктрины https://github.com/Atlantic18/DoctrineExtensions/blob/v2.4.x/doc/timestampable.md там именно так как я хотел - в аннотации указываешь по какому событию обновлять дату и не паришься. но проблема в том, что оно работает только для симфони2.
есть какое-то более актуальное расширение? понятно, можно вручную добавлять, но вдруг кто-то уже запилил готовое.
>>1120204 >можешь положить все кнопочки в форму в которой у тебя прописан action='твой скрипт' >Можно с помощью жквери. Типа присваиваешь функцию кнопочке, а в функции у тебя аякс. Можешь пожалуйста пример привести?
Есть данные в двумерном массиве. Необходимо вности в БД. А теперь вопрос. Например есть 10000 строк. То как лучше внести данные? Какой способ быстрее и выгоднее для сервера? 1) Построчно прогоняя массив через форыч вносить в базу каждый раз используя INSERT:
>>1120270 >А может ты тогда напишешь код (внутри цикла) на русском и на PHP Взять случайный элемент из массива и добавить к имеющемуся слову: $name = $name . $letters[rand(0, 15)];
>>1120332 Один большой запрос всегда быстрее, чем много мелких. Однако, у БД есть ограничение на размер запроса, поэтому возможно потребуется разбить его на несколько множественных инсертов. Заметим, что при импорте дампа отключают для ускорения отключают проверку foreign key и удаляют индексы: SET FOREIGN_KEY_CHECKS=0; ALTER TABLE mytable DROP INDEX myidx; По окончании импорта эти параметры восстанавливают.
>>1120282 Пагинация относится исключительно к представлению. Класс, в котором метод печатает ссылки на экран, не должен находится в модели. Только в представлении. Контроллер должен запрашивать у модели данные с двумя параметрами: $number_of_results, $skip_results, где первое - количество результатов на страницу. А второе = $number_of_results х $номер_страницы
>>1120282 >Альтернативой будет сделать цикл в отдельном шаблоне, и передавать туда объект, а потом еще и написать тыщу геттеров для полей класса Цикл в шаблоне - это нормально, если оформлен по канонам
>>1120320 не шарю в doctrine, но автоматическое обновление полей с датой - это функция БД. Для этого у поля типа timestamp прописывается дефолтное значение CURRENT_TIMESTAMP.
>>1120262 В php по умолчанию всегда неявным образом передает в функцию ссылку на параметр. Переменная создается в памяти только, когда ты внутри функции начинаешь её менять.
>>1120368 1. у меня не мускул. 2. это можно делать где угодно (в принципе), но если ты используешь такую жирную абстракцию как ОРМ, то логично всю работу с БД делегировать ей. а как она там технически будет добавлять - мне пока неважно. возможно, она это делает по-разному в зависимости от БД.
>>1120116 Повторюсь. Можно ли свой проект вместо студентов делать? ОП будет помогать тогда? Хочу сделать порезанную версию Anki, что бы дни для spaced repetition считались, а то руками в календаре отмечать я утомился.
>>1120407 >@Gedmo\Timestampable(on="create") >@Gedmo\Timestampable(on="change", field={"title", "body"}) О чем я и говорил. Это функция БД, которую ты включил с схеме базы.
Можно, но при условии, что ты прочитаешь комментарии к задаче про студентов и будешь стараться делать, как там написано, стараться соблюдать лучшие практики и тд. То есть, если ты собираешься чему-то учиться.
Нет, не все так просто. Если бы это делала БД, то после сохранения сущности с такими полями нам надо было бы делать дополнительный запрос на загрузку сгенерированных дат. Потому лучше не гадать, а посмотреть исходник:
>>1120436 >denwer >PHP 5.3.13, MySQL 5.1, PostgreSQL 8.4 etc это говно мамонта. зачем советовать людям говно мамонта?
>>1120429 open server. я когда сидел на винде, сравнивал его с xampp, первый намного пизже. больше функционала, удобный доступ к конфигам, удобное переключение, прочие плюшки
Есть у меня какой-то условный index.html и script.php. Привязываю я скрипт к кнопке в индексе. Как он будет работать? Индекс то я могу и в хроме посмотреть, а вот пхп? Нужно запускать какой-нибудь сервер, чтоб все заработало?
>>1120574 Бля, PDO - это прослойка между скриптом пхп и базой данных. Системы управления базами данных это Oracle, MSSQL, MySQL, PostgreSQL - это программы на подобие Excel, только текстовые. Они все управляются одним языком SQL. И если ты хочешь освоить базы данных, то тебе нужно освоить этот язык.
у меня короче есть две сущности: Article и Tag. у них будет bidirectional связь manyToMany (у многих статей может быть много тегов, для каждой статьи хочется знать ее теги и наоборот).
то есть по логике мануала должна создаться промежуточная таблица articles_tags (указана в аннотации JoinTable) и там должны быть два поля с айдишками статью и тега, которые будут образовывать составной первичный ключ. вроде заебись все.
далее делаю php bin/console doctrine:migrations:diff, создается файл миграции, но там ДВЕ промежуточные таблицы: $this->addSql('CREATE TABLE articles_tags (article_id INT NOT NULL, tag_id INT NOT NULL, PRIMARY KEY(article_id, tag_id))'); // эта моя $this->addSql('CREATE TABLE tag_article (tag_id INT NOT NULL, article_id INT NOT NULL, PRIMARY KEY(tag_id, article_id))'); // эта такая же, но автоматически сгенерированная
как так-то? почему их две? как сделать так, чтобы создавалась и использовалась только та, которую я указал?
>>1120574 как и везде, на начальном уровне несложная. пдо - это не только про БД, как правильно сказали, сначала надо освоить азы sql, уметь создавать таблицы, выбирать-добавлять-изменять-удалять данные через консоль. пдо - это встроенная библиотека пхп, предоставляющая несколько классов для работы с БД и предполагающая, что ты будешь использовать определенный подход при работе с ней
Привет! Прохожу урок по работе со встроенным в PHP веб-сервером. Почему-то не работает пример из урока, который должен был посчитать сумму двух чисел. Браузер выводит просто пустую страницу. Хотя hello world из прошлого примера срабатывает нормально. Подскажите пожалуйста,что я делаю не так?
>>1120574 >>1120604 >выбирать-добавлять-изменять-удалять данные через консоль. Лучше через phpmyAdmin или его аналог для других баз. Там наглядно можно видеть текст запроса, манипулируя интерфейсом. Пробовать менять запрос, вводить свои.
>>1120620 Вот для таких случаев и придуман дебаггер. Прямо построчно выполняет программу и после каждого шага ты можешь посмотреть значения любой переменной.
Аноны, а кто-нибудь из вас согласился бы поучастовать бесплатно в написании просмотрщика трейсов от xdebug? "Поучаствовать" здесь значит "сделать проект целиком", конечно.
Трейсы позволяют найти, какие функции в коде дольше всего выполнялись, найти проблемные места, из-за которых страница долго рендерится. Вроде в платных IDE есть просмотр трейсов, но хочется бесплатный инструмент.
Трейсы - это не то же, что результат профайлинга. Это именно последовательность вызовов всех функций в коде. Трейсы с реальных сайтов обычно весят десятки или сотни мегабайт, что добавляет интереса. Сами понимаете, расковырять такой лог вручную нереально.
Если есть заинтересованные люди, через пару-другую недель я распишу задачу подробнее.
Еще в Хроме в отладчике есть мощные средства для просмотра разных трейсов (вроде https://chromedevtools.github.io/timeline-viewer/ ), можно еще рассмотреть вариант конвертировать PHP трейс в JSON, который скушает и отобразит Инспектор.
Вопрос по вёрстке. Есть ячейка <td></td> произвольной ширины. Внутри должен быть <input></input> и <button></button>. Кнопка строго 23х23 пикселя, прижата вправо. А инпут должен быть резиновым, занимая всё оставшееся место ячейки. Вроде простая задача, но я не осилил.
>>1120871 Что-то типа такого: https://jsfiddle.net/dj03n8sj/ Только там вообще даже в одну строку всё не умещается. У мен уже голова квадратная, с утра получше сделаю.
>>1120282 >Я много слышал про разделение логики приложения и логики представления, но с пагинацией я немного запутался, есть класс, в одном из методов которого я просто через цикл печатаю ссылки на экран, а потом объект пагинации передаю во вью, так нормально делать? Не совсем, ты должен передавать в шаблон переменные с результатом, и уже в нём (шаблоне) выводить циклом
>И еще вопрос по неймспейсам, если у меня например класс вью называется App\View\View , а шаблоны лежат например в App/templates, как лучше всего подключить шаблоны уровнем ниже(выше?) неймспейса? Я пытался как-то изворачиваться с двойными точками, но полное понимание так и не пришло. __DIR__ . '/../level/up/path'
Вообще, обычно, папка с шаблонам находятся снаружи снаружи папки приложения
>>1120902 Не пиши на венде локалхост. Это так, к слову. По поводу кода: мы тут не обязаны угадывать "у миня там ни праходит ряяя". Пиши четко, какая ошибка. Если пусто ,как у тебя в голове, въеби PDO::ATTR_ERRMODE=>PDO::ERRMODE_EXCEPTION и оберни скрипт в try—catch, опять же скажешь ошибку сюда, ну пшёл бля нах быстра!
>>1120919 А как писать если не локалхост? Работает же. А в коде, в 13 строчке $dbh->execute([NULL,$task,0,$taskDate]) or die ("Problems adding!"); срабатывает or die ("Problems adding!").
Тебе надо включить режим выброса исключений в PDO, иначе ты не увидишь сообщение об ошибке. передать этот параметр можно через конструктор или как в коде тут:
Ставить try/catch не требуется. Просто включи у себя display_errors= 1 в php.ini и ошибка будет выведена на экран. Если проблема на хостинге, то на экран может и не вывестись, смотри тогда логи ошибок.
>>1120964 По крайней мере у меня, по крайней мере на семерке локалхост в майэскуэл работает намного медленнее 127.0.0.1 , попробуй поменять? На хрюше было норм, десятку нахуй родили непонятно.
Экзекьют возвра... ты читал доки а?? Не маневрируй — это тебе не поможет! Ошибку давай сюда але.
GET - для форм, не изменяющих состояние сервера, с небольшим объемом данных, и чтобы можно было поделиться/сохранить ссылку на результат (например: поиск, сортировка, переход к странице)
POST - для форм, меняющих состояние сервера, для форм с закачкой файлов, для больших объемов данных. Ссылкой поделиться нельзя, при обновлении страницы выскочит предупреждение.
У меня вопрос по бутсрапу. После добавления php кода из урока с ООП перестал работать hover. https://ideone.com/ZSKmtw Что я делаю не так и как отлаживать такие моменты?
>>1121098 Ты выбрал нелучшее место для php кода. Если пхп покажет warning, то этот текст попадет в код твоей страницы между head и body. Броузер интерпретирует этот текст как начало body, а реальный боди будет игнорировать.
>>1121233 >И как тогда правильно передавать значения с формы в пхп-скрипт?
смотря какие значения. особенность гета в том, что его параметры можно сохранить как ссылку и добавить в закладки, отправить другу и т.д. поэтому его используют в основном для путей. все остальное идет в пост, т.к. он во-первых защищает переданные данные при наличии https-соединения, а во-вторых, там нет ограничения на размер передаваемых данных.
>>1121241 Мне не нужны закладки, но у меня была проблема в том, что через форму поступает тип данные не "дата", а строка. Пришлось даже массивом разбивать и собирать заново, чтобы привести к формату, который требуется.
>>1120892 Блин, точно, флекс. Спасибо. >>1120888 Не знал, что такое есть. Ведёт себя немного по другому, но тоже подходит.
Ещё вопрос по бутстрапу. Какой путь кастомизации бутстрапа в Yii2 наиболее фен-шуйный? Мне нужно убрать padding у ячеек таблицы. В tables.less написано padding: @table-cell-padding;, а сам этот параметр прописан в variables.less. Но его изменение ничего не даёт. Гугл заводит то в перекомпиляцию бутстрапа, требующую NodeJS и ещё чего-то, то в принудительное отключение бутстрапа из зависимостей Yii и ручное подключение бутстрапа, сгенерированного с нужными параметрами на https://getbootstrap.com/docs/3.3/customize Как это вообще делается правильно?
>>1121244 у тебя по-моему нет понимания что за что отвечает. в пхп и нет такого типа "дата". это может быть ты имешь в виду тип поля в html, он не имеет никакого отношения к типу данных, который есть в ЯП.
>>1121260 Раньше лепили float ко всему где только можно, теперь flex и grid. У ячейки таблицы есть свой display, а менять его на flex? А нужна ли тогда таблица вообще? Таблица — для вывода табличных данных. Да, понятно что соблазнительно воспользоваться ей для автоматического выранивания сеточки, но мне лично кажется это неправильным.
Да, при желании содержимым ячейки можно поставить span или div c флексбоксом, внутрь которого запихнуть хоть анус Девы Марии, так чего бы весь сайт не засунуть туда а не только инпут с кнопкой?
>кастомизации бутстрапа А какие варианты есть? 1) В своем стиле переопределить селекторы и подрубить его поверх. 2) >ручное подключение бутстрапа, сгенерированного с нужными параметрами Это когда уже определился со стилями, на финалочку.
>Have an existing configuration? Upload your config.json to import it. Может быть, у тебя уже есть основное, загрузи и подредактируй что нужно.
3) >Но его изменение ничего не даёт Ну как бы ты не должен лезть в папку vendor, если я тебя правильно понимаю. Все изменения должны накатываться в твоем приложении.
А если я неправильно понимаю, может быть ты что-то неправильно сделал, поэтому оно не отобразилось.
>>1121280 Окей, тогда опишу целиком систему: Пользователь вводит дату через форму HTML с type="date" Дату нужно привести к определенному формату. После этого, она вставляется в ссылку. Я кликаю по ссылке и перехожу на сайт, который хавает геты и выдает мне нужное окно.
>>1121283 >В своем стиле переопределить селекторы и подрубить его поверх. Не плучается. Подключаю css, в нём стили для td (к примеру). border почему-то удаётся изменить, а padding и margin нет, как будто они не учитываются вообще. Не понимаю, почему так происходит. >Это когда уже определился со стилями, на финалочку. Тоже не совсем понятно. Просто сгенерировать bootstrap на сайте и заменить им потороха папки vendor\bower\bootstrap ? Или отключить дефолтный бутстрап и рядом положить сгенерированный, подключив его в Ассетс?
>>1121289 >Не плучается Твой стиль подключаешь последним в списке? Может фреймворк где-то после тебя сует стили, а ты не видишь.
Если уверен что ты папа:
Тогда открывай инструменты разработчика и смотри: а) код самой готовой страницы, какие стили идут за какими, убедись все-таки, что ты последний б) уже скомпилированные значения. Смотри всю историю, кто где padding-и на td менял. (инспектировать элемент)
Бутстрап с помощью js может тебе нагадить уже после загрузки страницы.
Еще раз: ты не должен лезть в вендор! Эти вещи писал не ты, и не тебе их редактировать. Раз ты используешь bower, там должно быть что-то наподобие нашего composer-овского конфига, вот в нем ты можешь переписать пути на папку assets (ну или как там это в твоем фреймворке делается вообще ;))
>>1121285 почему такие странные названия переменных? зачем массив - str_replace же есть? + валидация где?
я бы так сделал: $userDate = array_key_exists($_GET['from']) ? strval($_GET['from']) : '';
if (!preg_match('~^(19|20)\d\d[-](0[1-9]|1[012])[-](0[1-9]|[12][0-9]|3[01])$~', $userDate)) { throw new InvalidArgumentException('Incorrect data format'); // можешь на die() заменить }
>>1121285 >>1121302 >>1121305 Алсо просто ору >With HTML5 support, web designer no longer needs to download fancy Javascript control for basic date input. Exactly what you need to do is just <input type="date"/> Once again HTML5 has made our life easier!
Можно ли c помощью какой-нибудь команды сделать значения массива $names индексами массива $rates? Или по любому придется назначать индексы вручную?Как-то не очень удобно.
Решил дописать в урок про студентов раздел про контроль версий и хостинги репозиториев. Естественно, я не хочу всех отправлять на гитхаб, а хочу предложить выбор, и решил добавить битбакет. Замучался искать пример какого-нибудь хорошо оформленного PHP проекта. Вы такого не знаете?
Без превращения варнингов в эксепшены переменная $content всегда определена. А, сука, если превращать - то при эксепшене undefined variable, сука! Да как так-то?! А как мне вытянуть значение функции, если там незначительный нотис выскочил (а при этом нотисы я хочу тоже кидать исключениями)? На самом деле ясно как - надо писать воркараунд в exception_error_handler для конкретного, сука, варнинга, и не кидать на него исключение. Это же пиздец. Кто это проектировал?! Почему нельзя запустить exception_error_handler после того, как строка отработала, а не во время работы функции! Процедурный код же не рассчитан на такое поведение, он рассчитан, что он срет ошибками и при этом невозбранно возвращает значение! Ааааааааааааа
Вот что мне делать, если я хочу получать $content и при этом кидать эксепшены? Хуячить собаку на file_get_contents, затем чекать error_get_last()? А как я узнаю, что это ошибка именно с предыдущей строки?
> https://github.com/moabit/student-list/blob/master/public/index.php > ini_set('display_errors', 1); Это лучше прописывать в php.ini, а то не хочется, чтобы на продакшене ошибки выводились. Можно конечно прописать настройку в конфиге, но непонятно зачем дублировать функционал php.ini.
Также, мне кажется, в контейнере не стоит хранить классы с состоянием вроде Authorisation, а стоит создавать новую копию при каждом обращении. Представь, что мы обрабатываем 2 HTTP-запроса подряд. Первый запрос изменит состояние авторизации, и оно может повлиять на выполнение второго запроса.
> throw new RouterException('Неправильный путь'); надо назвать класс лучше, так как этот класс генерирует 404 и должен использоваться только в таких ситуациях, когда надо отдать 404. Например, RouteNotFoundException или Http404Exception.
> if (Util::checkCSRFToken() == false) { Можно писать if (!Util::checkCSRFToken()), почитай про булевы значения.
https://github.com/moabit/student-list/blob/master/app/Controllers/ProfileController.php#L60 > $this->c['authorisation']->signIn($token); > $student->setToken($token); вот тут есть тонкий момент. Что, если мы сгенерируем токен, поставим куку, а потом скрипт упадет, не записав данные в БД. Пользователь останется с кривым токеном. Это не проблема? Хотя, если сделать наоборот, может получиться, что мы создадим пользователя в БД, а куку не выдадим - будет еще хуже.
https://github.com/moabit/student-list/blob/master/app/Controllers/ProfileController.php#L93 > $student = new Student; > if ($this->user) { > $student->setID($this->user->getID()); > } При обновлении данных лучше сделать так: загрузить студента из БД и затем обновить ему поля из POST. А то в твоем случае, если добавить какие-то новые поля, которые не редактируются через форму, но хранятся в БД и есть в объекте, то они могут потеряться при редактировании.
> private function editUser($token): void Для $token можно поставить тайп-хинт
https://github.com/moabit/student-list/blob/master/app/Helpers/ErrorHandler.php#L33 > header("HTTP/1.0 404 Not Found"); > echo "Страница с таким адресом не существует"; без указания кодировки кириллица может не отобразиться. Добавь либо Content-Type либо тег meta charset. Также, на мобильных надпись будет выводиться очень мелко, можно добавить meta viewport.
> $student->setSurname($faker->lastName.'а'); Faker не умеет в женские фамилии? Не хочешь исправить этот баг и законтрибутить исправление в Faker на благо всех? Сначала, конечно, надо повнимательнее изучить Faker, может там уже есть решение.
>>1121611 >Сорян, такой код для меня сложен. Можешь объяснить?
мы не можем просто так взять из гета элемент массива, т.к. если этот параметр (from) не передадут, мы получим нотис от пхп undefined array index 'from'. чтобы этого не было, мы сначала должны убедиться, что элемент с таким ключом существует. мы это делаем внезапно функцией array_key_exists. strval нам приводит значение к типу "строка", как часть валидации опять же.
а тернарный оператор - это такой сахар для задания значения переменной в зависимости от условия. пример: $foo = isset($bar) ? $bar : $somethingElse; значит тоже самое, что if ($isset($bar) { $foo = $bar; } else { $foo = $somethingElse; }
важно знать, что тернарный оператор - не замена if, то есть нельзя использовать его для реализации логики. только для задания значения переменной.
>Т.е. это создаст переменную date из формата 'd/m/Y' и переменной strtotime($userDate) ? да
>>1121639 >мы не можем просто так взять из гета элемент массива Погоди.. что? Я просто написал $datefrom = date('d/m/Y', strtotime($_GET[from])); и все сработало.
>т.к. если этот параметр (from) не передадут Я просто указал value="2018-01-01" . Я так понял, это костыль был?
Черт! Я только сейчас понял. У меня там ещё одно значение из get бралось и пустое значение дальше передавалось для обработки. Чтобы этого избежать я написал:
Нет, мне интересен пример хорошо оформленного проекта на битбакете, а не на гитхабе. У них раньше была ссылочка /explore, но сейчас она убрана, подозреваю, из-за того, что на нем мало публичных известных проектов.
>>1121644 ну я не знаю, какой у тебя код и поэтому говорю в общем случае.
если ты запросишь $_GET[blahblah], а его не передадут, то ты получишь php notice в процессе выполнения своего кода. поэтому данную ситуацию надо предусмотреть.
>if (empty($country)){ >} else{
тут два пути. если ты работаешь менеджером или в ТП, а тебя начальник загрузил какой-то временной задачей, то делай как работает и забей. а если ты планируешь дальше работать с пхп для себя или перекатиться, то имеет смысл изучить какой-то минимум основ. иначе будет постоянная боль и непонимание где сломалось, а каждая задача будет отнимать кучу времени.
>>1121655 >если ты запросишь $_GET[blahblah], а его не передадут, то ты получишь php notice в процессе выполнения своего кода. поэтому данную ситуацию надо предусмотреть. Дай угадаю: если у меня там дальше SQL-запрос (сам скрипт для внутреннего пользования и можно не бояться инъекций), то у меня вылезет целая куча говна?
>если ты работаешь менеджером или в ТП, Этот случай. НО!
>а если ты планируешь дальше работать с пхп для себя или перекатиться Посему, воспользуюсь тем, что написал ты.
>>1121655 По поводу это строчки: $userDate = array_key_exists($_GET['from']) ? strval($_GET['from']) : '';
есть ощущение, что я что-то недопонимаю.
array_key_exists - это функция для проверки существует ли что-то в массиве. 1.Для переменных сгодится isset? Вот так, например. $userDate = isset($_GET['from']) ? strval($_GET['from']) : ''; 2.А разве можно передать массив через форму?
strval - функция для превращения числа в строку. Как итог ты используешь логику "если есть что-то в массиве (у меня "в переменной"), то преврати полученное из гета в строку. в противном случае - пусть будет пустота.
>>1121703 >А разве можно передать массив через форму? Форма это и есть массив. У элементов формы есть name и value. И если не ошибаюсь, multiple select может прислать однотипный массив из всех выбранных option value.
$_POST("select") / ["option 1","option 2", ...]
Еще (поправьте меня если нет) можно через URL передать массив:
>strval - функция для превращения числа в строку Не только числа, а всех типов. Приведение к строке (если это возможно). Можно даже объекты в строку превращать и массивы.
>в противном случае - пусть будет пустота Вернется пустая строка. Именно строка! (пустая, да)
До кучи про тернарный: (условие) ? (инструкция если условие вернуло true) : (инструкция если условие вернуло false)
>>1121691 >вылезет целая куча говна? она может не вылезти, если у тебя на продакшн-сервере не проставлено error_reporting E_ALL (а оно на проде не проставлено), но в любом случае надо это предусмотреть, т.к. на дев сервере обычно стоит максимально многословный вывод ошибок (если там не легаси) и намеренно генерировать нотисы - это говнокод.
Посоны поставил php сервер, но он жалуется на mb_ функции Uncaught Error: Call to undefined function mb_internal_encoding(), такой вопрос, а вообще на php7 multibyte string работает?
<?php error_reporting (-1); mb_internal_encoding('utf-8'); $a = "Добра тебе \n Выпей чаю"; $b = mb_strlen($a); echo $b; Вот код из задачи, при исполнении в браузере выдает следущее Fatal error: Uncaught Error: Call to undefined function mb_internal_encoding()
>>1121783 Не, тут такая ситуация: у меня значение из гет передается в preg_split, чтобы разбить вводимую строку на значения. Потом эти значения втупую скармливаются sql-запросу и далее, после переработки результата, запиливаются ссылки.
>>1121878 > >Configuration File (php.ini) Path: C:\WINDOWS >Loaded Configuration File: (none) >Scan for additional .ini files in: (no хуита какая-то. на винде поставь опен сервер, там все из коробки работает
В пхп скрипте будет доступно по $_GET['yoba'][1]; // тут 23 $_GET['yoba'][2]; // тут 24
А на самом деле в форме индекс в скобочках можно не указывать. Тогда в скрипте будешь обходить массив foreach ($_GET['yoba'] as $item) { echo "$item \n"; }
>>1121878 Файл php.ini положи в одном месте - в директории с php.exe. В файле php.ini расскомменти строку, где подключается mbstring. Убедись, что эта библиотека присутствует у тебя на диске. В файле php.ini также должна быть правильно указана директория extensions. После всех изменений перезагрузи вебсервер.
Крч, есть сайт и надо, чтобы он выглядел как архив, кидаю файл через программу на C#, а она идёт туда и пишет дату, название и его можно открыть (тхт файлы) Часть на шарпе я то напишу, но вот с пхп не знаю, что делать ;d
>>1121787 Нужно документацию читать, а не туториалы от васянов. В первых страницах документации есть объяснение, почему вариант с var_dump работать не будет.
>>1121641 Читал обновления в уроке, мне кажется автор переборщил с выбором. Зачем новичку знать про Mercurial, когда от джуна почти 100% будут требовать Git? Зачем другие хостинги кода, если аккаунт на GitHub всё равно рано или поздно появится, ведь без него не создашь issue и не отправишь патч в популярную библиотеку. А тот же BitBucket лежит регулярно, у нас он на работе и я думаю склонять людей к GitLab после этого: https://www.theregister.co.uk/2018/01/10/bitbucket_outage/
Особенности работы с pg-функциями без PDO, ИМХО, стоит вынести в отдельный урок, уж слишком специфично, у новичка глаза разбегутся от обилия информации. Есть ещё такой анти-паттерн - soft coding, его можно применить не только к программированию: идея в том, что человек потерятеся, если дать ему слишком большой выбор. Хорошо, что выбор есть, но тут, как мне кажется, он только усложнит жизнь.
Посоветуйте, как сделать drag and drop загрузку файлов. Может уже есть какие-то хорошие готовые решения или мне самому ее писать? Я в жс не очень, поэтому такой вопрос задаю.
>>1121989 UPD. Я перечитал твой пост 20 раз, заглянул в предыдущие и все понял. Проще говоря, ты задаешь поля, как индексы массива, а он уже "собирается" в php скрипте.
Да, из-за своей невнимательности я запутался.
Короч, через форму мне нужно передать только отдельные значения, а не элементы массива. Тот вопрос был больше теоретическим.
Вопрос по SPA задаче. В подсказках написано что нужно сохранять состояние приложения если у клиента оборвалась связь. Окей, если он не закрыл вкладку. А как можно сделать, чтобы он мог в оффлайне открыть это приложение, или если он закрыл уже вкладку с нашим сайтом или вообще браузер/телефон/компьютер перезагрузил?
Когда он в первый раз заходит - у него сохраняется костяк приложения (кешируется джаваскрипт, стили), но как быть с html страничками, они же не кешируются сами по себе?
Допустим я могу и темплейты страниц закешировать (в джаваскрипт).
Но как потом запустить этот джаваскрипт прямо во вкладке, когда нет доступа к сайту? Чтобы можно было работать и потом закоммитить изменения.
кто vps использует для хостинга сайтов клиентов? вопросики есть:
1. как вы расчитываете мощности? по наитию (тормозит - докупили) или какими-то инструментами/методиками?
2. насколько сильное значение для задержки имеет физическое расположение сервера? допустим, vps в амстердаме, а сайт русский. по идее задержка минимальная, но почему-то все используют русские vps для таких целей.
Подскажите, какая цель таких вот запросов? SELECT CHAR(113)+CHAR(107)+CHAR(113)+CHAR(107)+CHAR(113)+(SELECT (CASE WHEN (4622=4622) THEN CHAR(49) ELSE CHAR(48) END))+CHAR(113)+CHAR(107)+CHAR(107)+CHAR(106)+CHAR(113)) Да, это sql-инъекции, но какая их роль? В данном случае это просто текст 'qkqkq1qkkjq0', у меня залогированно несколько подобных запросов которые получают текст 'qkqkq1qkkjq0' разными запросами.
Там есть варианты (да, какие-то сервис-вокеры), но если ты почитаешь описание, то увидишь, что это самая кривая и неудачная архитектура из всех, что можно было придумать. Поэтому предлагаю не делать такой функционал. Если у клиента постоянно нет связи, для него лучше сделать оффлайн приложение.
Русские впс используют, потому что они дешевые (poiskvps). У хостеров часто можно попросить тестовый период и протестировать сайт под нагрузкой. Можно также предложить оплатить эти несколько дней. Также, можно читать отзывы.
Изучаю ООП, и параллельно курю MVC. Верно ли суждение, что при создании экземпляра класса, у которого отсутствует конструктор, будет вызываться конструктор родительского класса?
>>1122446 Да, робот спамил, так как там порядка 5-6 запросов в секунду приходило. Я тоже подумал, что скорее всего проверка чисто на получение ошибки БД. Нагуглить похожих запросов не вышло и само слово вроде как рандомное, но тогда не ясно, зачем именно это слово впихивалось разными способами в запросы
>>1122462 Да но только в случае если у родительского класса конструктор не private метод, так как дочерний класс наследует все public/protected методы от своих родителей
Да. А если этот конструктор приватный/защищенный, то будет выдана ошибка. Такие конструкторы используют, чтобы запретить создание объекта через new снаружи класса.
> Ареал макак простирается от Афганистана до Юго-Восточной Азии, а также до Японии. Особенным разнообразием видов отличается остров Сулавеси, где проживают шесть эндемичных видов макак. Единственным представителем семейства, встречающимся за пределами Азии, является магот, живущий в Северной Африке и в Гибралтаре.
>>1122497 так это ж ПРОГРАММИРОВАНИЕ. профессия будущего.
если хочешь дешевле, ищи школьников, правда возможно потом будешь с ошпаренной жопой искать кого-нибудь, кто выправит их говнокод, и тебе 50 баксов в час покажутся выгодной сделкой. но ты видать предприниматель, поди любишь риск, азарт, адреналин
кто на vps ставил vestaCP или другие панели? ответьте на вопрос, зачем они нужны, если можно ручками в консоли все поставить самому? особенно учитывая, что они жрут ресурсы, которых на vps мало
Решил зайти поблагодарить ОПа за всю его работу, что он делает и отчитаться об успехах. Не уверен на 100%, что нынешний ОП - тот самый, но, надеюсь, что это так. В любом случае рапортую: в конце 2015 - в начале 2016 года каждый день сидел в этих тредах, изучая погромрование по сайту опа и слушая его советы. На прошлой неделе повысили до миддла бекендщика, компания одна из топовых в рашке. Стек - symfony3, doctrine, redis. Всё пока складывается охуeнно, то ли ещё будет. Cпасибо, опушка, за всё.
> Чтобы вывести ссылку, ты пишешь в шаблоне {{ path(...) }} . Вместо этого можно сделать класс UrlGenerator, в нем методы вроде getTestsByTagUrl(Tag $tag): string. И использовать их. Выгоды:
>> По переменным окружения - не стоит ли добавить им уникальный префикс вроде TH_..., чтобы они были гарантированно уникальными? > И тут тоже не понял, о каких переменных ты говоришь Переменные окружения в env.dist - больше их вроде нигде нету. В этом файле стандартные переменные APP_ENV и DATABASE_URL. Зачем их переименовывать и как их система прочтет? (в этом разобраться самому)
Нужно тестировать репозитории на копии основной БД? А как держать эту БД актуальной? Это ж нужно миграции и там и там проводить. Как-то не удобным это кажется
> Set number of failed attempts for instantly created item > public function setFailedAttempts($failedAttempts) Вот такого лучше избегать. Увеличивать число попыток в тесте лучше тем же способом, каким это будет делать приложение, а не делать костыли там, где без них легко обойтись. > Более того, смотри, ты добавил метод setFailedAttempts для тестов, а затем еще и написал тест для него. Ты тесты ради тестов пишешь, получается? Так делать не надо, это просто трата времени. Тестировать надо тот код, который будет использовать приложение.
Нет, эти 2 ф-ии используются исключительно для заполнения Fixtures. Вот тут https://goo.gl/FB1ikp Собственно, я и тестирую, что они отрабатывают первый раз и больше не срабатывают
> Я тут еще хотел посоветовать использовать faker в fixtures, но погуглил, и увидел, что он там уже используется (через alice), интересно. не знал про такую штуку. Ну прекрасно, если вдруг не знаком с ним, изучи faker, пригодится.
Ага, именно их я и использую. Правда до конца разобраться не могу, т.к. я учился на Alice 2, а уже давно существует 3-я версия, её я и поставил. Но в ней много чего поменялось. Долгое чтение документации и дебаг исходников результатов не дал. Позже вернусь к этому
использовать синтаксис для переводимых строк? Это как?
>> public function tagList(Request $request, PaginatorInterface $paginator) > Почему пагинатор передается в аргументы метода контроллера? Это такой DI?
>>1122787 >Спрыгнул с bitrix'а на symfony Поздравляю, братишка. Привыкай к ООП-парадигме, и никогда не возвращайся в битрикс, ни за какие деньги, иначе умрёшь в душе как специалист
Программач, ищу подработку от 10-20к в неделю, т.к зп на ништяки не хватает. PHP, неплохо знаю Yii2 и хотелось именно на ней работать, js/jquery разумеется. Ещё могу парсеры писать на selenium+python, покрайней мере один для себя написал. Телеграм @hysdop.
В новых проектах постоянно предлагает добавить под гит кэш и вендор. Раньше такой фигни не было. Они автоматом былы подсвечены серым и содержимое игнорилось. В .gitignre строки нужные есть /var/ /vendor/
>>1121562 ОП, добра тебе, что посмотрел! >вот тут есть тонкий момент. Что, если мы сгенерируем токен, поставим куку, а потом скрипт упадет, не записав данные в БД. Пользователь останется с кривым токеном. Это не проблема? Хотя, если сделать наоборот, может получиться, что мы создадим пользователя в БД, а куку не выдадим - будет еще хуже. Я подумал, может лучше через транзакцию в бд добавление/редактирование студента сделать? Или после редиректа проверять куку, и если она кривая, то ее удалять? >Faker не умеет в женские фамилии? Фейкер умеет только в женское имя и ФИО. Метод lastName не примает параметр $gender как, например, метод для генерации ФИО. Можно было бы генерировать женское ФИО, и затем выдерать из строки имя и фамилию, но я подумал, что проще просто сделать фамилию и добавить 'а'.
Если в консоли сделать git status, он эти папки показывает? Если да, то гитигнор настроен неправильно, если нет, то проблема в phpstorm и стоит начать с гугления по словам phpstorm gitignore not working.
И вот я решил посмотреть что за метод такой create. В моделе Eloquent'a такого метода нет. Но есть функция public static function __callStatic($method, $parameters) { return (new static)->$method(...$parameters); } Я так понимаю что функция создает инстанс модели и запускает статический метод, как обычный. Но метода create нет в модели и нет в интерфейсах которые она реализует и нет в трейтах которые она наследует. Ну собственно вопрос что за метод такой и откуда он берется.
Она определяет что в / @Route('/tests/tag/{name}') / public function testsByTag(Tag $tag){ ... }
{name} это $tag->getName() И как я понял, это фишка аннотаций.
Получается при использовании yaml-роутинга нужно будет писать типа public function testsByTag(string $name){ $tag = $tagRepository()->findByName($name); ... }
По-моему, это только усложнения. Или есть еще варианты?
Это очень специфичная для Laravel магия, не уверен, что тебе нужны эти кишки. И не знаю, что там у тебя за васян-гайд, но created_at самому ставить не нужно, он и так сгенерируется благодаря трейту HasTimestamps. Лучше почитай: https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md
>>1122978 если ты тот анон, про которого я думаю, то у тебя паранойя: тебе мерещится, что все кругом читают "васян-туториалы", а один ты в мире знаешь о существовании мануала
>>1122787 >>1122771 У меня пока рост с "саппорт по коду, умеющий только читать иногда правильно мычать", к "недо-джуниор, который боится JS как тней и делает весь код процедурами", но тоже благодарен этому треду за существование!
>>1118555 (OP) Посоны, допустим на сайте вам нужно выбирать данные из базы для формирования странички. Допустим же, что для этого нужно больше, чем один или даже два запроса к базе. Вы что их последовательно делаете что ли? Или, всё-таки, параллельно? Если параллельно, то кто как это делает? Я пришёл к вам из питона и немного охуел что нет одного хорошего простого решения, которым бы все пользовались. Помогите понять и определиться.
>>1123273 Запросы делаются последовательно. Про параллельные запросы на пхп впервые слышу, хотя, наверное можно форкнуться в пхп и сделать их. Нормальная практика делать по 50-100 запросов на страничку. Кто крут в SQL может все данные достать за один запрос с подзапросами и хранимыми функциями.
>>1123276 >Нормальная практика делать по 50-100 запросов на страничку shiiiiiii~ >Кто крут в SQL может все данные достать за один запрос с подзапросами и хранимыми функциями. Это-то как раз несложно. Вот только потом обрабатывать это в контроллере ебанёшься.
Мда, видимо в пхп-мирке свои понятия нормальности. Придётся приспосабливаться. Хотя вот я нагуглил php-icicle и там есть вот такое https://github.com/amphp/mysql
Анон, я делал простенький код для генерации ссылок с использованием БД, но вот мое задание изменили и мне теперь нужно вместо обращений к БД использовать обращение к массивам.
Т.е.: у меня есть две таблицы из базы данных. Нужно сделать из них многомерные массивы, а потом научить код их обрабатывать.
>>1123281 есть разные варианты, погугли по теме "асинхронный php" или "php pthreads". разные запросы К СКРИПТУ выполняются параллельно и так. если тебе требуется ускорять обращения к бд в рамках одного запроса к скрипту, то это наверное надо делать не распараллеливанием, а оптимизацией запроса.
другое дело, если у тебя один запрос выполняется 10 секунд, второй 10, они никак не зависят друг от друга и оба нужны для вывода данных, то можно заморочиться с асинхронностью или multithreading. но это история для каких-то внутрисерверных cli-ситуаций, а не для формирования страничек пользователям.
Тоже хочу поблагодарить ОПа из этого треда и ОПа из версткотреда. Работаю щас фуллстаком под вордпресс. Изучал где-то с 2012 по 2016. В 2017 переехал в дс и нашел работу. Всем спасибо. До миддла пока не повысили, но получаю довольно таки миддловскую зарплату судя по рынку
>>1123404 Сейчас набегут дебилы которые "Да я как только Hello World" написал сразу за 100к работу нашол. А потом получил опыт 7 дней и сразу синьюр помидор 300к релокейт релокейт в гугол. Я вот даже не знаю откуда столько желчи в людях.
>>1123404 Так понимаю, что это настоящий ответ автора поста >>1123325, что ж, неплохо. Через год уже на 100+ выйдешь. Посоветовал бы только уходить от вордпресса.
>>1123438 >>1123325 Пару лет как обучился у опа, нахватался всяких гайдов с интернета, даже 2 месячный курс купил по PHP. Но дальше фриланса так и не вкатился, причём получаю с него тыщ 15 в месяц(имею основную работу). Не ххватает уверенности в силах хоть убей. всё кажется что возьмусь сейчас за работу, а там 9000 подводных камней, подведу работодателя. Больше всего мешает то, что не знаю досконально Wordpress, laravell, а от симфони я вообще в обморок падаю. Столько то там наворотов. Я наверное один такой неудачник.
>>1123445 Не расстраивайся. Сидя в своей Мухосрани я даже фриланс за 15к не смог найти, поэтому пришлось рвануть в дс. Тоже был дикий страх подвести, моментами в начале работы хотелось просто послать все, менеджеров, тестеров, всех. И было такое, что поначалу сильно говнокодил. В одной конторе даже сайт положил без восстановления XD. Но они и сами виноваты, там не было ни гита, ни других кодеров. Свалил оттуда на следующий день, оформление не по ТК было. Но ничего, вытянул, с вордпрессом немного помог удаленный кодер, который давно на нем сидит. Постепенно дали нормального лида, который ведет все переговоры по срокам и ТЗ и вообще сильно помогает. Помогает то, что многие чуваки в айти натурально сидят на бордах, т.е. с ними проще на одной волне быть.
>>1123502 Спасибо за стори анон, прямо мёд для моего сердца (или как-то так). Буду пытаться вкатываться. Всю жизнь мечтал быть программистом, да только в моём мухосранске платят больше не программистам. Буду дальше искать работу мечты.
>>1123290 В reference manual почитай array functions. Их много и под все нужды. Советую ограничиться двумерными массивами. Пхп очень много памяти на многомерные тратит, ему может не хватить, упрется в ограничение в настроке.
Как настроить PHP, так, чтобы через функции, которые лезут в сеть, можно было достучаться только до одного доменного имени, либо до нескольких из белого списка? На всякий случай. А то нашел небольшой баг у себя, при некорректном ответе внешнего API можно исказить URL для следующего запроса.
Нужен ли pixel perfect, или достаточно примерного (ну, скажем, расхождения есть, но на глаз не отличить) соответствия дизайну? Что большее зло: расхождение с pp, или всякие магические margin-top: 3px, потому что расходится с дизайном?
А если мне сейчас 26 лет, учу несколько месяцев язык, до этого пробовал си шарп немного, есть ли смысл в таком возрасте вообще учить кодинг, или на работу все равно потом хуй устроишься?
>>1123556 >питоном Тогда уж с С. Но на самом деле в php это тоже рабочий код. fwrite - функция вывода в resource-первый-аргумент строки второго-аргемента первый аргумент - константа стандартного потока-вывода STDOUT, второй - строка.
По сути так и работает под капотом echo или print. Я, например, люблю все эти fwrite, fputs, fgets и тп
>>1123541 Ээ... ну как бы сокращение общего времени запросов к базе. Что быстрее: - 10 последовательных запросов к базе - 10 параллельных запросов к базе
В первом случае общее время запросов будет равно сложению времени каждого из них. Во втором - длине самого долгого запроса.
>>1123531 Я про запросы к базе из скрипта. Допустим, у тебя есть контроллер, где ты вызываешь несколько методов, которые возвращают тебе из базы результат.
>>1123591 Будут на собесы приглашать чаще, чем вкатывальщика из другой области. А на практике не поможет, будет столько же страгглинга на первых порах, как и у всех. Разве только если ты не пм какой, тогда тех процессы тебе понятней будут, но они и так не сложные.
>>1123468 >Вот есть у меня html страница и php скрипт, где я там должен прописать Переименуй файл с html страницей в .php и напиши в началит файла <?php include "script.php"; ?> имя и путь к скрипту свои.
На твой вопрос так просто не ответить. Это ведь зависит от конфигурации сервера. Обычно сервер настраивают так:
- если идет обращение к файлу с расширением .php, то выполнить код из него - если идет обращение к файлу с другими расширениями, вроде .html, то просто отдать его клиенту
В этом случае описанное тобой никак не реализовать без изменения настроек сервера.
> где я там должен прописать что-то типа execute main.php? Надо настроить сервер, чтобы он файлы html выполнял бы как PHP код. Как именно, зависит от используемого веб-сервера. Но я не очень понимаю, зачем и что тебе мешает назвать файл .php или использовать ЧПУ.
- одни запросы могут зависеть от других и их нельзя выполнить параллельно - база данных обладает неограниченным резервом производительности и выполняет запрос за одно и то же время независимо от нагрузки
На практике, второй пункт может выполняться, если сервер мощный и посетителей немного, но в других случаях запросы могут начать выполняться медленнее, когда их много.
Также, чтобы использовать параллельные запросы, надо, как я понимаю, использовать асинхронное программирование, и это та еще боль. Надо переписывать код из последовательного скрипта в более сложную конструкцию. И как там с обработкой ошибок? В питоне невыполненные обещания умеют бросать исключения? Я не знаю, я имел дело только с промисами из JS и PHP, там они не умеют это.
Ну и я плохо представляю, как можно распараллелить ORM, с наличием там "ленивых" запросов. Это все функции в сущностях надо переделывать на асинхроонную модель.
Так что сомневаюсь, что это так просто и всегда оправданно.
Не забывай также, что программисты часто стремятся оптимизировать технические характеристики, как память или потребление CPU, но бизнесу еще может быть интересно, чтобы разработка шла быстро и не стоила как космический корабль. Параллельный код может быть дороже и сложнее.
Ну и ты еще исходишь из предположения, что запросы к БД это самая долгая часть выполнения скрипта. Я смотрел трейсы в PHP-приложениях, и могу сказать, что это далеко не всегда так. Оптимизированный запрос с индексами на хорошем сервере может выполняться меньше 1 мс. Нужно ли его распараллеливать?
На Питоне все SQL запросы выполняют параллельно? Теперь уже я удивлен, первый раз про такое слышу. Покажи-ка ссылочку.
Если тебе все равно хочется отправлять параллельные запросы, я бы начал с изучения фреймворка ReactPHP и поиска асинхронного драйвера для БД. По моему, mysqli что-то такое может уметь, но я не уверен.
Зависит от ситуации и заказчика. Если ты учишься, то я бы советовал хоть раз сделать идеально. А так, конечно, важно, чтобы выглядело так, как задумал дизайнер, чтобы все было выровнено (частая проблема - выравнивание иконок относительно кнопок или текста). Иногда бывает, что на макете дизайнер поленился все до конца выровнять и приходится выравнивать за него.
> $text = str_ireplace(" ", null, $text); Заменять на null нелогично, так как в строку можно вставить только другую строку (например, пустую). Также, ireplace тут использовать нелогично, так как тут не нужна проверка регистра символов. Ну, и наконец, хочу сообщить, что эта функция в принципе нерабочая (в том, что касается регистра символов): https://github.com/codedokode/pasta/blob/master/php/strings-utf8.md
В PHP был так называемый safe mode, где ставились разные ограничения, но это все работало плохо и всегда находились какие-то обходные пути. Глупо пытаться ограничивать программу, работая на том же уровне привилегии, то есть имея равные с ней возможности. Для твоей задачи больше подойдет такой подход:
- сделать в linux отдельного пользователя - запускать приложения из-под него - с помощью iptables настроить список IP, с которыми он может соединяться. Чтобы он не сливал данные через DNS, вместо доступа к настоящему DNS даем ему доступ только к своему DNS-серверу, который резолвит только жестко прописанные в конфиге имена доменов (это умеет делать dnsmasq, я такое делал для того, чтобы телефон не мог сливать данные через DNS запросы). - как альтернатива, можно вообще не давать прямого доступа в сеть, а перенаправлять трафик на squid (как прозрачный прокси, прозрачный тут значит, что клиент о нем не подозревает), в котором настроить правила фильтрации
Также, ты можешь подключить сервер со своим приложением через фаерволл и фильтровать трафик на нем, если ты богат.
Я так фильтровал трафик с андроид-телефона: все DNS-запросы шли на dnsmasq, все HTTP-соединения перехватывались и отправлялись в squid, все остально резалось. Возни, конечно, много, пока во всем этом разберешься и отладишь, сразу скажу, что чтением документации вряд ли обойдешься. Мне пришлось даже немного пропатчить сквид ради такого перехвата HTTPS, который мне был нужен, с подменой сертификатов.
Если все равно хочется сделать по-простому, то возьми расширение runkit и перехвати с его помощью функции, работающие с DNS, но конечно, это можно будет обойти.
Ну вот, жаль, что так получается, что человек, который в нашем треде учился - и не может найти нормальную работу. Если у тебя есть возможность, я советую попробовать все же изучать технологии более глубоко - в ОП посте, например, есть задача на TestHub, которую можно делать на Симфони, ну и конечно, подучить то, что плохо знаешь - ООП там, HTTP, linux, тестирование. Может, изучить современные сложные JS фреймворки. Развиваться, расширять кругозор. А то иначе, если изучить только основы, то ты будешь конкурировать с тысячами таких же начинающих.
Если же ты все это знаешь, то может, ты подаешь себя как-то не так. Не представляю, чтобы человек с такими знаниями не мог найти работу.
> не знаю досконально Wordpress, Поставь его себе на локалхост, изучи админку, прочитай пяток статей в стиле "лучшие плагины для вордпресс в 2017", поставь себе эти плагины. Этого уже хватит, чтобы какие-то простые задачи делать. Дальше, почитай документацию, сделай какой-нибудь простой плагин, сделай тему для ВП и в общем-то это и все, что обычно требуется от ВП разработчика.
Но конечно, в некоторых задачах требуется знать гораздо больше. Вот например, тебе скажут "сайт тормозит" - и тут надо будет смотреть его разными инструментами (htop, strace), профайлить, может, оптимизировать SQL запросы, настраивать кеширование - то есть тут уже нужен другой уровень, нужно знание линукса, индексов в SQL итд. Обычный "разработчик ВП" не справится (я с такой ситуацией сталкивался).
Мы, кстати, этому всему можем помочь научиться, по крайней мере, ссылками, задачками и ответами на вопросы.
Я обычно не комментирую такие сообщения, но всегда приятно их читать. И можно будет, если что, показывать их новичкам для мотивации или даже повесить на сайт в раздел "отзывы" (не знаю, впрочем, будут ли они вызывать доверие).
Вот, вот, такой отзыв я и ждал. Смотрите все, аноны, как важно изучать linux, ООП, фреймворки и автоматизированное тестирование, а не ограничиваться основами. А то что-то редко я тут вижу вопросы по этим темам. Наш тред этому тоже вас научит, если будет желание с вашей стороны.
Не надо конкурировать с настройщиками вордпресса, вы по цене их не перебьете.
Прежде чем говорить про ТДД, мы должны поговорить про экономическое обоснование автоматического тестирования. Написание и настройка тестов требует времени (=денег), и нам надо понять, как эти расходы окупаются.
Считается, что выгода тестов в том, что при многократном запуске мы тратим время на их написание только первый раз, а второй и далее запуски нам бесплатны (в отличие от ручного тестирование, где каждый прогон стоит денег). Плюс, автоматические тесты выполняются быстрее. Следовательно, автоматические тесты могут окупаться там, где их многократно запускают.
Использование тестов также позволяет разработчикам более смело делать большие рефакторинги и изменения в коде. Тесты позволяют "защитить" однажды написанный функционал от повреждения, позволяют раньше находить ошибки и повысить качество кода.
Оправданно ли это в верстке, если ты делаешь ее один раз, проверяешь визуально и сдаешь заказчику? Оправданно ли это, если ты поддерживаешь и дорабатываешь верстку в течение долгого времени?
----
Теперь поговорим, как именно можно применить ТДД к верстке. Я не большой знаток ТДД, потому пролистал википедию по этой теме и первый вопрос, который у меня возник, а какие мы будем писать сценарии и что можно тестировать в верстке? Какие требования мы к ней хотим предъявить и проверить их соблюдение? Что мы будем считать критерием "хорошей" верстки?
- "заголовок должен быть черного цвета, крупнее основного текста и прижат влево"? - "картинка должна быть отцентрирована в блоке вертикально"? - "карточка отеля не должна разваливаться, даже если у отеля очень длинное название"? (это, кстати, мне уже нравится) - "карточка отеля должна отображаться корректно, на какую бы страницу мы ее не вставили"? - "карточка отеля на мобильной версии с узким экраном не должна вылезать за его пределы"? - "карточка отеля должна выглядеть в ИЕ9 аналогично виду в Хроме"?
Так, боюсь, нам придется очень долго и подробно описывать макет в виде кода, и это сомнительная затея. Представь сам, сколько в макете независимых элементов, и сколько надо для них написать правил.
Я, кстати, советовал бы использовать методологию вроде БЭМ и разбивать верстку на независимые блоки - это здорово упростит проверку, облегчит поддержку и повысит пуленепробиваемость верстки.
Вместо того, чтобы описывать ожидаемый результат кодом, мы можем сделать что-то другое. Мы можем сверстать элемент, проверить на глаз, что он выглядит корректно, и сохранить его внешний вид - может быть, в виде скриншота, может быть в виде куска DOM с проставленным размерами и координатам элементов (скриншоты могут немного различаться в разных ОС и браузерах из-за особенностей рендеринга шрифтов, видеокарт и тд). И после этого мы можем написать тест, проверяющий, что после изменений в верстке данный блок не поменял внешний вид.
Но это будет не совсем TDD, боюсь. Там ведь мы пишем тесты сначала. Хотя, может, можно придумать какой-то текстовый формат описания внешнего вида блока и сделать на его основе тест (в идеале - вообще генерировать из макета, но тут может понадобиться машинное зрение и искуственный интеллект). Но не уверен, что это будет быстро.
Также, можно попробовать подключить инструменты для валидации кода - они тоже могут что-нибудь находить.
Еще можно придумать какие-то простые тесты в стиле "вставляем данные в БД, загружаем страницу, проверяем их наличие" или "загружаем страницу, проверяем, что в логе пхп нет ошибок". Может, тут надо только часть задач автоматизировать.
Если у тебя есть каике-то интересные идеи, и тем более, ты готов их испробовать, мне было бы очент интересно почитать, и я может быть могу где-то помочь советом. Мне это интересно, так как у нас есть задачи на CSS и мне было бы пригодилась возможность автоматически проверять их решения.
Вот, кстати, с точки зрения ООП, это очень странный код. Если ты хочешь вызвать обычный метод, то ествественно, нужно иметь экземпляр объекта. Если ты создаешь объект и тут же выкидываешь, то не очень понятно, а не проще ли метод сделать статическим. И если это обычный метод, то не проще ли его вызывать как обычный. Вот такое отношение к ООП мне в ларавеле не нравится.
Также, узнать, какие функции вызываются в ходе работы программы, можно, освоив xdebug и сделав трейс, и да!!!, я все еще интересуюсь, не хочет ли кто сделать визуализатор логов трассировки? Ссылка: https://xdebug.org/docs/execution_trace
Насчет роутов в YAML - это очень помогает, когда, например, у тебя много роутов, и ты можешь посмотреть, как добавить новый, чтобы он не конфликтовал со старыми и можешь даже настроить их порядок вручную. А что делать в случае аннотаций? Также, к роутам можно писать регулярки для параметров, опять же, наверно, неудобно писать их в аннотациях. Ну и наконец, при желании к роутам можно писать дополнительные опции (права доступа, правила переключения на другую страну, настройки кеширования - но учти, что они в Симфони вроде не кешируются и надо это исправить сначала) и тут YAML файл очень удобен.
Также, в конфиге роутинга несколько роутов могут вести на одно действие, но с разными параметрами.
Я не представляю, как со всем этим работать в аннотациях. Придется постоянно вызывать команду, дампящую роуты и смотреть результат. неудобно же, когда 200 роутов раскиданы где-то по коду. Единственный плюс - при удалении контроллера роут удаляется вместе с ним.
Но это мое субъективное мнение.
Что касается @ParamConverter, это же часть контроллера, его можно наверно оставить в аннотации. Нельзя? Предложи исправить это.
Транзакции нужны, если запросов больше одного. Если у тебя один INSERT, он и так идет как одна транзакция.
Проще наверно просто игнорировать кривые куки. А то вдруг админ удалит студента, а он пытается зайти на сайт.
> Фейкер умеет только в женское имя и ФИО. Не хочешь допилить и поделиться решением со всеми? Придется расковырять фейкер, понять, как он рабоатет, и может обсудить это с его разработчиками.
>>1123585 как вы заебали, реально. вот тебе на дваче скажут "нет смысла, иди таксистом рабоать" и что дальше? пойдешь?
если хочешь чем-то заниматься, должно быть похуй на чужие мнения. иначе будешь вяло подрачивать и "вкатываться" пять лет. а потом не вкатишься и скажешь "ну да, меня не берут потому что мне 26".
Решил эту задачу вот так, но ведь это очевидно не самый оптимальный вариант. Как можно поменять части элементов массива без перевода массива в строку? Нашел только array_replace, но это вроде не то. Либо я не разобрался.
Я не люблю всякие гайды и туториалы, так как они часто ничего толком не объясняют и заключаются в просто выкладывании готовых кусков кода с краткими объяснениями. Вот пример правильного туториала, который мне нравится: https://vulkan-tutorial.com/
>>1118555 (OP) Впервые тут у вас. Заглянул в первый гайд для новичков в шапке и охуел. Кто и зачем так постарася? Гайд правда толковый или только выглядит так?
>>1123605 Я вот просто на физическом уровне пытаюсь представить распаралеленный запрос к бд и что-то не могу. Просто потому-что знаю как устроены запросы внутри большинства бд. Ну тоесть допустим у тебя есть "Select from users" и "Select from questions" (это гипотетические запросы выдуманные для примера, не надо до синтаксиса докапываться). И обычная скажем MSSQL смотрит когда был подан запрос и тупо выполняет сначала тот который был раньше, а потом тот который был позже. А тут как ты себе представляешь это? Сначала БД выбирает первую запись первого запроса, потом первую запись второго, и так пока до конца не дойдёт? Что-то тут не так мне кажется.
С микросервисами так можно, если у тебя данные для разных частей страницы формируют разные микросервисы, работающие на разных серверах, то можно параллельно им запросы отправить.
>>1123935 ну там не то чтобы прямо верстка по макету, просто у друга условный автосервис, он заказал сайт "шоб читалось легко". и главное не объебаться с тем, что везде все нормально, а в ИЕ все пополам складывается.
я для себя выделил такие аргументы против использования готовых пакетов: 1. сложно дебажить 2. нет предупреждений об утечках памяти 3. нельзя использовать thread safety 4. возможная несовместимость патчей внутри одного пакета
я на своем опыте сталкивался только с проблемой того, что нельзя использовать pthreads. но там ясно в мануале написано мол хотите использовтаь - перекомпилируйте с каким-то там ключом.
кто-то реально заморачивается с самостоятельной пересборкой? допустим, есть некий хостинг, они когда обновляют версию, они сами ее компилируют из исходников?
Вопрос по проектированию базы данных. Задача файлообменник. У меня получается три базы данных: 1. files ( id name size linkaname created_at updated_at lifetime user_id public comment status) 2.comments ( id user_id parent_id child_id comment) //Вообще для комментариев будет две базы данных для реализации древовидных комментариев. Здесь просто указаны поля 3.users ( id name email avatar? hash) Ну и собственно вопрос. Нормально ли что у меня в таблице files столько столбцов? Есть ли какое-то ограничение на колличество? Ну и вообще правильно ли спроектировал?
где он предлагает для реализации closure table (которую ты, судя по всему, вырбал) использовать дополнительную таблицу связей. ты же кладешь parent_id и child_id в ту же таблицу комментов, а поле указания глубины не используешь. в итоге как ты собираешься строить структуру комментариев?
от себя добавлю, я бы использовал nested_sets, они быстры на выборку, а для манипуляций с перемещением-удалением есть библиотеки для той же Доктрины (наверняка еще миллион standalone). если конечно не стоит задачи написать все самому.
>>1124403 на случай, если ты не передашь этот конкретный параметр. значение по умолчанию в качестве аргумента значит, что этот аргумент необязательный.
что значит устарело? deprecated? нет, оно не депрекейтед, если ты имеешь в виду указание ссылки в определении функции типа function foo(&$number) {...}
а вот указание ссылки при ВЫЗОВЕ функции с 5.4 (кажется, точно не помню) запрещено: function foo($number) {...} $a = 5; echo foo(&a); // это вызовет ошибку
Мой очередной нубский вопрос: есть один объект, он передается через конструктор в качестве свойства в другой объект. Как туда передается первый объект - по ссылке или он клонируется? То есть, если я изменю через второй объект, какое то свойство первого объекта-свойства, то измениться ли оно в первом глобальном объекте?
>>1124222 > сложно дебажить На продакшен сервере не дебажат. На память просто поебать. Тем не менее, у нас он скомпилирован админом вместе с использованными нами библиотеками. Дополнительно он там какие-то заплатки прикомпилил, чтобы не похакали. Из минусов только то, что при необходимости добавить или поменять библиотеку приходится дергать админа, чтобы он все заново перекомпилил.
Вообще, это возможно. Обычно да, в рамках одного соединения запросы выполняются последовательно. Но базы данных обычно многопоточные/многопроцессные и можно открыть несколько соединений и выполнять несколько запросов.
Но важно понимать, что тот же дисковый трафик и число процессоров ограничены и нужно подобрать такие параметры распараллеливания, которые смогут задействовать имеющиеся ресурсы максимально.
Я стараюсь у себя локально использовать готовые пакеты, так как это быстрее. Расширения тоже ставлю через apt-get, а если их там нет, то под линуксом они легко компилируются одной командой через pecl install.
Я думаю, что сборка из исходников нужна тем, кто разрабаитывает интерпретатор PHP или исследует баги в нем.
Также, есть набор скриптов phpenv, который позволяет автоматизировать установку версий PHP, и даже ставить их несколько на один компьютер.
> 1. сложно дебажить Ну, мне это и не требуется и я не силен в gdb
Вообще, по поводу отладочных данных, мне нравится, как это сделано у майкрософт: у них отладочные данные идут в отдельном pdb-файле, а не встраиваются в exe-шник.
> 2. нет предупреждений об утечках памяти Это да. Но я не сталкивался с проблемами из-за них.
> 3. нельзя использовать thread safety Версия PHP под винду, кстати, thread-safe.
> кто-то реально заморачивается с самостоятельной пересборкой? допустим, есть некий хостинг, они когда обновляют версию, они сами ее компилируют из исходников?
Думаю, они используют phpenv или что-то аналогичное. Хотя, собрать PHP не так и сложно. Я, например, собирал PHP7 под XP (пришлось чуть-чуть пропатчить), а под линуксом это вообще стандартно делается, configure + make + make install.
Не забудь внешние ключи, ограничения уникальности полей. Если твоя БД поддерживает ограничение CHECK (например: postgres и sqlite), используй его там, где это уместно.
Я бы советовал сравнить плюсы и минусы разных вариантов реализации деревьев и попробовать выбрать наиболее подходящий ответ. А потом сравнить с тем, что я написал ниже:
Для комментариев чаще всего применяют (не заглядывайте раньше времени) material path material path material path
> Все получилось, как раз клоужер тейбл использовал Попробуй оценить ее размер в зависимости от числа файлов, средненго числа комментариев, средней глубины ответов. Попробуй оценить число SQL запросов (выборок, вставок) при добавлении нового комментария.
Объект передается как будто по ссылке. Если быть точным, то в PHP объекты хранятся в отдельной области памяти, а в переменной хранится лишь идентификатор (указатель) объекта. И ты передаешь в функцию не копию объекта, а просто его идентификатор. Чтобы сделать копию, используется оператор clone.
>>1124343 >Вообще для комментариев будет две базы данных для реализации древовидных комментариев. 1. Прекрати называть таблицу базой данных. У тебя три таблицы в одной базе.
2. На вскидку, я не вижу повода создавать две таблицы для древовидных комментов. Просто каждая запись комментария будет содержать поле со ссылкой на предыдущий комментарий.
Вопросо по юнит тестам. Вот, допустим, у меня файл пдо в контейнере. Как лучше сделать тест класса, который работает с БД - подключать весь контейнер во время тестов, или в тесте в методе setUp создавать тестовое подключение к БД?
я тут впс поднял и на нем захуярил гит-сервер (gogs.io). не хочу, чтобы туда всякие левые чуваки регистрировались и вообще он только для меня и полутора коллег. а он там по умолчанию открыт для всех и пиздец. можно прямо из интернета зайти, зарегить сто аккаунтов и пожрать мне все ресурсы.
какие есть варианты вменяемо ограничить доступ ко всему домену? знаю вариант поднимать vpn сервер и пускать к гиту только через тоннель, но это чуток заебно, т.к. во-первых, vpn пожрет и так ограниченные ресурсы впс, а во-вторых, надо впн поднимать на клиенте, отсылать ему файл с конфигом и прочее. не хочется заморачиваться.
в идеале на уровне конфига нжинкса повесить какую-то авторизацию по ключу, например. есть какой-то такой вариант?
Как средствами PHP преобразовать текст пикрелейтед в читаемый вид? Может уже есть стандартные функции. Вообще, забыл, как называется это кодирование? (аналогично преобразуются русские символы в адресной строке браузера)
Привет, делаю базуданых для birthday-remider, посмотрите пожалуйста пикрил, все ли ок. Пример записей, которые должно показывать приложение: 1. "23 января 1905 г. день рождение Антона Голубцова, напомнить 22 января 2018 г." 2. "01 июля 2018 г. свадьба Антона Голубцова и Тани Яотиной, напомнить 25 июня 2018 г. (купить подарок), 30 июля 2018 г. (помыться)"
Записи можно сортировать по датам, по событиям, по участникам. Напоминаний и участников у события может быть несколько. Типы событий можно добавлять.
>>1124744 Представил как одним запросом СУБД захватывает аж 6 таблиц и немного погрустнел. И ведь целая система нормализации есть. Только непонять в чём профит, столько данных тащить. На ум приходит только тотальная и маниакальная экономия дискового пространства.
>>1124745 >>1124748 ок, можно избавиться от таблицы Event-types, пускай названия событий будут в таблице Events, но как совместить Events + Participants + Reminders в одной таблице, учитывая что там отношения один к многим?
>>Только непонять в чём профит, столько данных тащить А как по другому сделать?
>>1124655 >в идеале на уровне конфига нжинкса повесить какую-то авторизацию по ключу, например. есть какой-то такой вариант? Ну естественно так и надо делать. Это для доступа по ssh. И не забудь после отключить доступ по паролю. А если у тебя есть веб-морда к серверу, то очевидно нужно закрыть доступ для незарегистрированных в системе юзеров - проще говоря страницу логина добавь, если таковой по умолчанию нет.
>>1124771 про доступ по ssh это да. но у меня грубо говоря есть сайт, к которому я хочу ограничить доступ. есть возможность в https логиниться по ключу?
>>1124797 Нет, такой возможности нет. Зачем тебе это нужно вообще? Настрой ssh доступ и делай пулы/пуши через ssh. Ну либо по https - но нужен будет пароль. Тебе нужно ограничить доступ к веб-морде? Используй страницу логина либо, если известны адреса клиентов, добавь их в белый список веб-сервера, а остальным айпи просто заблокируй доступ.
>>1118555 (OP) Посоны, у меня вопрос по базам данных. Какие ключи лучше использовать - автоинкрементальные или генерируемые? Какие недостатки/преимущества есть у тех и других? Я вижу серьёзное преимущество генерируемых в том, что при добавлении записи во множество таблиц, мне не нужно сначала вставлять данные в основную таблицу, получать автоинкрементальный айди и потом только делать вставку с этим айди в дочерние таблицы. Я просто генерирую айди и распихиваю связанные по этому айди данные в нужные таблицы без лишних телодвижений. Единственный серьёзный недостаток, который я вижу в генерации, это возможность коллизий. Но всегда можно подобрать алгоритм генерации, который сведёт такие случаи к нулю.
>>1124816 вот эти рекомендации тоже особо никто не выполняет: >Всегда используйте ключевое слово AS для лучшей читаемости. >По возможности избегайте объединения названий двух таблиц для построения таблицы отношений. Например, вместо названия cars_mechanics лучше подойдёт services.
1. в мускуле надо делать два запроса, а в постресе есть RETURNING. 2. по инкрементному айди можно отсортировать, а по сгенерированному нет. 3. генерация по-настоящему уникального значения - более дорогая операция. 4. он займет больше места для хранения и в теории поиск по индексу будет чуть медленнее.
>>1124824 >2. по инкрементному айди можно отсортировать, а по сгенерированному нет.
то есть, тебе надо заводить дополнительное поле для сортировки по нему. created_at не подойдет - в одну секунду может прилететь 10 записей. только если хранить microtime.
role - не лучше ли сделать ENUM или foreign key на другую таблицу?
А у тебя предусмотрены ли периодические ивенты, например, день рождения по идее каждый год происходит.
Ключом в event_type наверно лучше сделать id. Он меньше места занимает.
Меня конечно беспокоит наличие похожих сущностей (users - participants, events - reminders), тут явно просится наследование или еще какое-то обобщение, но не станет ли из-за этого схема БД сложнее...
Профит в том, что данные хранятся в единственном экземпляре и не может быть противоречий. Также, их легко редактировать, так как не надо искать все копии данных. Выгоды/недостатки нормализации давно изучены.
Насчет скорости выполнения запроса, джойны не проблема, если там джойнится например 1 запись и все это по индексам. Джойны - проблема, когда у тебя 2 больших таблицы и надо искать по обеим сразу и по каждой таблице поиск дает много результатов (например: найти компании с отделением в городе X, работающие в сфере Y, где связи компания-город и компания-сфера это многие-ко-многим).
Если номализованные данные работают медленно, всегда можно сделать денормализованную копию, в каком-нибудь отдельном хранилище, заточенном под поиск, вроде сфинкса или кеша. Но там свои подвохи.
Профит генерируемых ключей - возможность генерации на клиенте. Это годится в таких ситуациях: в моб. приложении при отсутствии связи с сервером, при отсутствии прямого доступа к БД (приложение генерирует сущность и связанные с ней, кладет в локальное хранилище, позже синхронизирует с центральной БД).
> Я вижу серьёзное преимущество генерируемых в том, что при добавлении записи во множество таблиц, мне не нужно сначала вставлять данные в основную таблицу, получать автоинкрементальный айди и потом только делать вставку с этим айди в дочерние таблицы. Я просто генерирую айди и распихиваю связанные по этому айди данные в нужные таблицы без лишних телодвижений.
Не очень понятно, а в чем тут выгода? Что мешает вставить сначала запись, а потом связанные с ней?
> Единственный серьёзный недостаток, который я вижу в генерации, это возможность коллизий. Но всегда можно подобрать алгоритм генерации, который сведёт такие случаи к нулю.
Я думаю, речь о том, что если в данных есть естественный ключ, то рекомендуется использовать его, а не создавать искуственный. Но должен заметить, что у искуственных ключей есть преимущества, например:
- он останется ключом даже при смене условий задачи (ты сделал номер паспорта ключом, а потом узнал, что паспорта можно менять и в каких-то случаях иметь несколько) - он мало весит, а размер полей влияет на размер индекса и объем требуемой под них памяти в больших таблицах. Индексы с 100-символьным колонками работают совсем не так хорошо, как индекс из интов (желательно подтвердить это тестом).
Обычно для тестов используют отдельный конфиг и в нем указывается отдельное соединение с тестовой БД. Насчет контейнера, тут можно выбирать - брать сервисы из контейнера или создавать самостоятельно.
> created_at не подойдет - в одну секунду может прилететь 10 записей А когда может понадобиться такая сортировка, с точностью до микросекунд? В высокочастотной торговле? В списке комментариев или статей она точно не нужна.
Блядь, я прошел самый первый гайд по основам основ, за пару недель. Но я даже и представить не могу, как можно связать то что я прошел с чем то на сайтах. Мне дурно становиться, когда я осознаю что для того что бы потом зарабатывать хотя бы 15-20к надо еще года 2 учить и читать, пиздееееец.
>>1124918 Ты имеешь ввиду полгода для начала чтоб меня взяли в какую нибудь контору? Но что делать, если я школьник 16 лвл? Я даже если выучу сейчас то, с чем меня возьмут на какую никакую работу, то из за возраста все пойдет нахуй.
>>1124920 изучай, пили свои проекты, чтобы в 18 тебя с руками оторвали. в айти нет дискриминации по возрасту, как многие вкатывальщики думают, но есть особая любовь многих компаний к молодым "перспективны" студентикам. также на фрилансе можешь работать без ограничений по возрасту.
плюс когда я учился в школе, у меня не было вопросов "но что делать". я помню тусил с друзьями, пытался поебаться, гулял.
>>1124925 >чтобы в 18 тебя с руками оторвали ты хочешь сказать, что если я буду до 18 изучать php и пилить проекты(сайты, как я понял?), то меня могут просто взять в какую нибудь компанию, без вышки и прочего?
Тяжело ли освоить AJAX, если практически не можешь в жс? Пилю задачу от ОПа на файлообменник, хочу, чтобы комменты на странице после отправки сразу отображались. Как вообще такое реализуется, через фреймворк? Или на чистом жс тоже можно?
>>1124889 >role - не лучше ли сделать ENUM или foreign key на другую таблицу?
пожалуй ENUM норм, т.к. пока будет только одна роль user.
>>1124889 >А у тебя предусмотрены ли периодические ивенты, например, день рождения по идее каждый год происходит.
да, в таблице Event_types, поле is_annual, например тип "день рождения" is_annual: true. Но можно его перенести в таблицу Events. Я не стал этого делать, потому что хотел избежать при создании нового события необходимость выставлять периодичность, когда выбрал один из типов событий, который ее предполагает. Если периодичность перенести в таблицу Events, то это поле будет или дублироваться или придется каждый раз указывать периодичность. Насколько приемлемо дублирование, нужно выбрать то, которое будет приоритетное? Можно еще сделать два события "ежегодное событие без названия" и "разовое событие без названия", которые будут присваиваться событию, если не выбран тип но периодичность.
Только сейчас понял, что события получились общие для всех. Наверное, нужно сделать, чтобы часть типов событий была общая - предустановленные типы (др, свадьба и тд.), а часть приватными, те что юзер создаст сам, были видны только ему. Добавить еще одно поле "owner_user_id" в таблице Event_types, в которое вписывать создателя.
>>1124889 >Ключом в event_type наверно лучше сделать id. Он меньше места занимает. А если в таблице появится поле owner_user_id, то ключом можно сделать сочетание type и owner_user_id? Или id будет удобнее?
>>1124889 >Меня конечно беспокоит наличие похожих сущностей (users - participants, events - reminders), тут явно просится наследование или еще какое-то обобщение, но не станет ли из-за этого схема БД сложнее... Пойду полистаю аниме про базы данных, там наверняка есть про наследование.
Аноны, все тот же долбоеб 16 лвл , стоит ли вообще поступать в вуз, если есть возможность? Насчет армии похуй, я уже вроде не годен из за сколиоза 2 степени и бронхиальной астмы. Если я буду сейчас вкатываться, то к 18-19 я наверное смогу найти днищеработку макакой за 15-20к? А там уже по нарастающей.
>>1124929 Это можно сделать на жс без фреймворков. В оп посте есть задачи по js.
Еще есть фрейморк Jquery, который несколько упрощает запросы к элементам на странице и работу с Ajax. Но использование его без знания основ js - это путь на темную сторону.
>>1124964 >стоит ли вообще поступать в вуз да, стоит, даже если не возможности. Не факт, что ты в конечном итоге свяжешь свою жизнь с программированием, и при трудоустройстве на любую другую работу наличие диплома о во будет играть если не решающую роль, то наверняка скажется на твоей зарплате. Многим приходится заканчивать заочку в 30+ лет, чтобы получить повышение или определенную должность. И чем старше ты будешь, тем более значимым будет диплом или его отсутствие. Устроиться в днищеконтору ты всегда успеешь, а если тебе придется выбирать, на что потратить свою молодость, то универ будет лучшим выбором. Если ты будешь заниматься, то сможешь подрабатывать, главное не соглашайся на полную ставку, пока не закончишь универ.
>>1124975 >будет играть если не решающую роль, то наверняка скажется на твоей зарплате скажется на зарплате, серьезно? ты в каком мире живешь? я в дс работаю, тут все хуй клали на дипломы.
>Многим приходится заканчивать заочку в 30+ лет а может ты просто в россельхознанотехнологиях работаешь?
>>1125021 для изучения фреймворков нужно знать сам язык, чтобы понимать, что к чему. он не легче и не тяжелее, а избавляет тебя от рутинных операций. допустим, орм тебе дает возможнсть не писать запросы самому, но для того чтобы ее использовать, нужно сначала пописать их вручную, построить связи между таблицами и т.д.
>>1124926 пхп многогранен, на нем можно пилить большие проекты, не только сайты. тебя могут легко взять в компанию, если ты будешь обладать хорошими навыками и знать фундамент. если ты будешь еще параллельно студентом, это дополнительный плюс, не более.
>>1124964 если есть возможность, поступай, главное не думай что диплом "скажется на зарплате" и прочую хуйню. для зарплаты полезнее будет решить задачу ОПа про список студентов.
но сам по себе вуз (нормальный) - это заебись. я когда учился, было весело.
>>1124744 У тебя все связи реализованы через промежуточные таблицые. Такое используют используют только для реализации связей многие-ко-многим. Ты уверен что оно тебе надо. Как минимум, в случае reminder-to-event мне не приходит в голову сценария когда на один reminder будет несколько событий.
>>1123868 >Не хочешь допилить и поделиться решением со всеми? Придется расковырять фейкер, понять, как он рабоатет, и может обсудить это с его разработчиками. Посмотрел исходники фейкера, по ходу это надо на уровне ядра библиотеки менять, чтобы такую возможность добавить. Я пока что наверное слишком ньюфаг для такого, но мб потом, когда опыта наберусь.
Приветствую анонов. У меня вопрос про класс валидации. Я смотрел несколько разных вариантов его реализации, но так и не пришел к единому решению. В одном варианте есть один класс валидации, и работает он образно в духе isValid = validator->validate(['username' => 'required']), в самом классе много методов и переменных, сообщения об ошибке могут храниться как в нем, так и во вспомогательном классе, но в целом много разных циклов работы с массивами, их ключами и т.д. То есть в целом сам класс выглядит как большая обёртка функций скорее, ну или мне так просто кажется. Другой подход это делать очень много громоздких классов валидаторов, где каждый класс отвечает за определенное правило, например EmailValidator или LenghtValidator, они могут наследовать абстрактный валидатор, это выглядит более "правильно", каждый класс делает только то, что от него нужно, но кода получается значительно больше, еще и объекты "лишние" нужно создавать, при том что в задаче про студентов довольно много инпутов у формы. Я не знаю насколько сильно нужно заморачиваться по этому поводу, и насколько одно работает быстрее другого.
>>1125034 >скажется на зарплате, серьезно? ты в каком мире живешь? я в дс работаю, тут все хуй клали на дипломы. Твой опыт не показателен, т.к. вероятно тебе меньше 30 и ты работаешь в ойти. Мало информации, чтобы сделать достоверный вывод о том, насколько скажется диплом на зп или нет.
>>1125034 >а может ты просто в россельхознанотехнологиях работаешь? Именно. Гос сектор и обслуживающий его бизнес самый крупный работодатель в РФ. А трактористом дают дополнительные балы за диплом. И если он будет учиться не только для корочки, то это только прибавит возможностей для последующего трудоустройства. Хорошие специалисты нужны всегда и везде.
>>1125351 Хорошие спецы и без корочки нужны, поверь. Знакомый 3 фирмы держит, постоянно ищет спецов, ибо именно спецов в России очень сильно не хватает.
>>1123856 Ого, как сложно. Я остановился на том, что сделал обертку для file_get_contents, кидающую эксепшн на домен не из вайт-листа, а саму fgc для интернета не использую.
Поясните за полиморфизм. Есть объект А, он реализует метод lol(int $digit). Есть объект B extends A, который реализует lol по-своему, а именно ему для работы нужно два параметра - lol(int $digit, bool $flag). Флаг мне этот жизненно необходим, он участвует в переопределнной реализации. Задать через конструктор я его не могу, потому что флаг может быть разным при каждом вызове метода. Метод может вызываться много раз за жизнь объекта. Хуячить по объекту каждый раз, чтобы вызвать lol, мне кажется хреновой идеей. Что делать? Можно так ломать сигнатуру метода, если очень надо?
>>1125113 >Как минимум, в случае reminder-to-event мне не приходит в голову сценария когда на один reminder будет несколько событий. На один event может быть несколько reminder. Reminder это дата+время когда должно сработать напоминание. Т.e. связь один-к-многим. Например, когда нужно сделать несколько дел заранее, найти подарок - на это потребуется неделя, и погладить носки - это можно сделать накануне события. Думаю, что этот функционал нужно реализовать. Но можно обойтись без промежуточной таблицы, добавив в reminder поле event_id. Поскольку я нубас, не сразу понял, что можно сделать проще. Какого отношение выгоды к геморрою обоих решений?
>>1125399 >и все? Во-первых, одно это уже должно быть определяющим фактором в выборе, во-вторых, mysqli не поддерживает именованные параметры, в-третьих, pdo - уже давно стандарт в разработке, в-четвёртых, гугл ит pdo vs mysqli
>>1125351 >Именно. Гос сектор и обслуживающий его бизнес самый крупный работодатель в РФ ну все, вопросов нет тогда. у вас-то реально тимлидом без диплома не станешь. а так поучиться в хорошем вузе - это не то чтобы плохо, я и не агитировал против этого. главное - работать параллельно. а то я на одной работе видел много выпускников, которые свои дипломные проекты делали про машинное обучение, а в офисе два дня не могли понять как послать апи-запрос.
Понравилась данная полоска у гугла. Попробовал сделать своими силами, получилось только через костыль "width: max-content; display: flexbox;", ползает. Полез проверить себя в код страницы гугла, а там нет флексбокса и ширина нигде не затрагивается вообще (блоки в блоках в блоках...) и офк работает у них. Пытался проследить стили, не могу понять как они такого эффекта добились с использованием базовых параметров только.
(Еще блоки, содержащие картинку на 4 пикселя выше и оставляют прозрачную полосу внизу, хотя должны бы тютелька в тютельку облегать картинку, этому я ответа пока не нашел тоже)
Может заглядывают фанаты верстки, поднаправьте пожалуйста в нужное русло.
>>1125490 Если есть документация к этому ZipArchive, посмотри, как там выбрасываются наружу ошибки (а может быть он сам с ними что-то делает?), вот эти ошибки (или исключения) тебе и нужно ловить.
В целом каждый этап может возвращать какие-то результаты, тебе может понадобиться проверять их все, а может ни одного, надо смотреть в класс объекта.
За пять месяцев я переписал сервис по автоматизации отслеживания грузов охранниками с голого php на Yii2 и добавил некоторую функциональность. А именно "Постовую ведомость" - журнал выданного охранникам оружия. Плюс отдельную таблицу для оружия и таблицу связей "многие ко многим" между таблицами охранников и оружия, чтобы в постовой ведомости можно было выбрать охранника и далее выбирать только те стволы, которые принадлежат именно ему. Писал это в качестве хобби, в свободное время, для текущей работы (работаю не программистом).
Посмотрите пожалуйста код на кривости, которые бросаются в глаза (в недра лучше не лазить, просто проглядеть по верхам). Знаю, что написанное можно номинировать на говнокод.ру, но всё же сервис работает.
Конфиг подключения к бд не стоит хранить в системе контроля версий.
Контроллер SiteController слишком жирный, потому что ты свалил туда в кучу вообще всё. Надо разделить логически на меньшие контроллеры, примерно как у тебя сделано с моделями.
>>1125542 >Конфиг подключения к бд не стоит хранить в системе контроля версий. Блин, не заметил. Выпилить весь файл config/db.php через .gitignore? >Контроллер SiteController слишком жирный Сам подумывал, но как-то не собрался. Разобью. Так же, по отдельному контроллеру для каждой модели/странице, или делить по другим признакам?
>>1125546 >Блин, не заметил. Выпилить весь файл config/db.php через .gitignore? Ну да. И добавить туда пример конфига. >Так же, по отдельному контроллеру для каждой модели/странице, или делить по другим признакам? Нужно руководствоваться логикой приложения и удобством последующей разработки-рефакторинга. Когда вся логика загрузки файлов, например, у тебя в отдельном контроллере, то это удобно, например.
Я пока еще не проверил код, с удовольствием проверю позже, а пока дам совет не использовать размытие для скрытия приватных данных, а использовать черные или серые плашки. А еще лучше - вбить у себя на локалхосте фейковые данные и сделать скриншоты с ними. Статья про восстановление размытых картинок: https://habrahabr.ru/post/152885/
Контроллеры не обязаны соответствовать моделям. Они соответствуют разделам и страницам сайта. На каждый раздел обычно делается свой контроллер. У тебя есть меню, на каждый пункт стоит сделать свой контроллер.
Ну например, контроллер GuardController с методами actionList, actionEdit, actionDelete может отвечать за вывод списка охранников и его редактирование. Но не за все сразу.
Если ты сомневаешься, то лучше выбирать вариант, при котором будет больше маленьких контроллеров. Я например иногда подумываю над идеей вообще делать каждое действие отдельным классом.
Название SiteController ничего не значит - Site тут ничего не знаичт и остается просто "контроллер" непонятно чего.
Верстка кривовата - если есть желание разобраться, в ОП посте есть задания на HTML/CSS.
Папку с тестами надо почистить, раз они не используются. Зачем держать неактуальный код? А еще лучше - прочесть урок по тестированию из ОП-поста и сделать их нормально.
Перед классом надо бы написать, чему он соответствует. А то не очень понятно. Понятно, что клиент, но что за клиент - непонятно. Это организация-клиент, или клиент в смысле HTTP клиент?
Формы и модели БД - не лучше ли хранить в 2 отдельных папках?
В общем, шаблоны надо тоже почистить и привести в порядок.
> public function actionManager() > if ( Yii::$app->request->post('add-button') ) { Добавление надо бы сделать отдельным действием.
В контроллере не должно быть SQL запросов. Вместо этого должно быть обращение к методу модели. То есть разделение таке: модель отвечает за получение/исправление данных в БД, а контроллер - за прием параметров запроса (GET/POST) и вывод результатов. Не так:
> $query = "SELECT * FROM flight WHERE data_vyezda between :date1 and :date2"; > $listFlight = flight::findBySql($query, [':date1' => $date1, ':date2' => $date2])->with('photo')->asArray()->all();
> $cellColumn = Yii::$app->request->post('column_in_db'); > $model = Flight::findOne($cellId); //Выбрать из таблицы Flight первую запись с id=$cellId > $model->$cellColumn = $cellValue; //Выбрать из этой записи ячейку в столбце $cellColumn и записать туда $cellValue В таком подходе есть недостаток: ты не проверяешь, какие поля можно редактирвать, а какие нельзя. Должен быть белый список разрешенных к редактированию полей. Удобно описать его где-то в модели.
> Возвращаемые значения > Возвращает TRUE при успешном завершении или код ошибки. > ZipArchive::ER_EXISTS > Файл уже существует. ...
Вот и ставь проверку, что open вернула true, а если не true, то анализируешь код ошибки и выводишь сообщение. Там ниже есть пример кода.
И так по каждой использованной функции. Некоторые IDE умеют показывать такие подсказки прямо не выходя из редактора.
Также, у тебя довольно опасный код: ты позволяет открывать вообще любой архив на компьютере. надо сделать ограничение, например, открывать архивы только из определенной папки и только с разрешенными символами в названии.
Зависит от архитектуры. Ты можешь либо написать этот код в файле инициализации (bootstrap) и передавать объект соединения куда требуется, либо сделать функцию, осуществляющую подключение.
Скорее всего ты не сможешь использовать аппаратное ускорение виртуализации,то есть будет медленно. Кроме виртуализации есть еще паравиртуализация (OpenVZ) и linux контейнеры (lxc, docker), которые делают примерно то же, но без тормозов. Ну и наконец, может тебе просто сделать несколько linux-пользователей? linux довольно хорошо изолирует пользователей друг от друга.
Для микросервисов пойдут контейнеры.
И еще можно вместо одной виртуалки купить несколько, но поменьше.
Ты используешь свойства, которые мало где поддерживаются, и хорошо, что ты это понял.
Я вижу такие варианты с классическим CSS2.1:
1) сделать враппер width: 100%, overflow: auto (hidden, если хочешь прокручивать яваскриптом), в него вложить див .line с display: inline-block, white-space: nowrap и картинками с display: inline-block. Плюс: вертикальное выравнивание. Подвох: пробелы между картинками, статья с костылями http://css-live.ru/articles/zagadochnye-otstupy-mezhdu-inlajn-blokami.html . Подвох: nowrap надо отключать для подписей к каринкам. Плюс: Можно использовать text-align для выравнивания .line по центру, когда картинок мало.
Объяснение: картинка или див с inline-block ведет себя как слово в тексте, nowrap запрещает перенос слов и они выстраиваются в длинную линию. inline-block на родителе (.line) нужен, чтобы он тянулся по ширине содержимого, просто block по умолчанию принимает ширину 100% родителя и не годится.
2) сделать враппер width 100%, ovf auto;. В него вложить блок div с width=суммарная ширина картинок,вычисленная JS или на сервере, и с clearfix. В него вложить блоки картинок, каждая с float: left. Плюс: нет пробелов между блоками.
Объяснение: флоаты встраиваются горизонтально по ширине родителя, мы задаем такую ширину, чтобы они все влезли в одну строчку.
3) сделать враппер width 100%, ovf: auto, в него вложить таблицу из 1 строки и множества колонок. Таблицу сделать не тегом table, а дивами с display: table, table-row, table-cell. Плюс: выравнивание как угодно, в том числе вертикально, железобетонность конструкции. Минус: у таблиц куча ограничений в плане позиционирования. Например, нельзя делать pos abs относительно ячейки.
Я бы сделал все 3 варианта и протестировал, и вбросил ссылочки в тред.
Так нельзя. Есть принцип Лисков (это не название инопланетной расы, а фамилия), который говорит, что объект-наследник можно использовать вместо объекта-предка. То есть если где-то есть код
$a->lol($digit)
То он должен корректно работать с обоими классами.
Ты что-то делаешь не так. Если даже методы назвыаются одинаково, но у них разные аргументы - это разные методы, и надо переименовать метод в B (например в lolWithFlag). И в функции писать в тайп-хинте что ей нужен именно B.
> и работает он образно в духе isValid = validator->validate(['username' => 'required']) Плохо, что тут не возвращается сам список ошибок. Какой смысл возвращать его как-то обходными путями?
> Другой подход это делать очень много громоздких классов валидаторов, где каждый класс отвечает за определенное правило Сделай их негромоздкими.
Вообще, для простого приложения можно сделать все в одном классе. Но полезнее было бы попробовать спроектировать ООП-модель для описания и проверки правил. Пусть ты накосячишь, но хоть чему-то научишься и на какие-то грабли наступишь.
Ну например, сделать так:
- классы элементарных валидаторов - класс для хранения набора правил и прогона валидаторов по данным - класс-билдер для задания набора правил - класс для информации об ошибках
> и насколько одно работает быстрее другого. думаю, что это непринципиально так как ты не будешь проверять тысячи форм в секунду.
Поясните мне за исключения. Вижу примеры кода, когда наследуют кучу исключений от базового \Exception, а потом ловят их в set_exception_handler(function { }). Если видов исключений много и обрабатывать их надо по разному, то скоро вырастет простыня кода. Как от этого избавится? Видел, что бросают исключения при валидации пользовательского ввода. Это вообще хорошая практика?
>>1125758 >Ты скорее всего что-то плохо спроектировал. В методе B::lol(int $digit, bool $flag = false) аргумент $flag внутри метода влияет на $digit. Если быть точным, $digit - количество попыток сделать http-реквест, а $flag - флаг, говорящий, надо ли делать другие попытки, либо хватит одной. Проще говоря, лежит ли сайт. A::lol(int $digit) принимает только количество попыток, это обобщенный отправитель http-реквестов. Класс B - это отправитель реквестов, заточенный под конкретный сайт. Внутри lol обоих классов всегда вызывается A::doRequest(int $digit). Разумеется, там еще url в параметрах, и даже streamContext, я упрощаю. Я могу сделать сделать много реквестов за жизнь скрипта от одного инстанса. Каждый раз состояние флага неизвестно. Но, теоретически, я могу спрятать всю обработку флага внутрь класса B. Чтобы он, кроме реквестов, еще и сам читал этот флаг из файла перед отправкой, и сам писал в файл этот флаг. И тогда у обоих классов будет сигнатура lol(int $digit). Это будет ок?
Алсо, еще вопрос. Сейчас у меня и А::lol, и B::lol возвращают объект WebResponse. Есть метод WebResponse::getStatusCode(). Для B мне нужно его пропатчить. Я делаю BWebResponse extends WebResponse и реализую метод BWebResponse::getStatusCode(). Теперь метод B::lol должен возвращать BWebResponse. Нормально ли будет написать в B::lol такое: $webResponse = $this->doRequest($url, $streamContext, $qtyAttempts); // A::doRequest() return new BWebResponse($webResponse->getHeaders(), $webResponse->getContent()); Проще говоря, я из объекта-предка делаю объекта-наследника не снимая свитер не реализуя B::doRequest(), а то геморройно.
>>1125831 А еще я могу сделать класс А и B фабрикой одноразовых объектов для реквестов, а вот сигнатура метода будет везде одинаковой: AProduct::lol($url) и BProduct::lol($url). Фабрика - синглтон, где живет базовый конфиг реквеста. Но это какое-то дикое усложнение, как мне кажется.
Утро в хату, пыханы. Нужен джуниор для удаленного сотрудничества с опытом Вордпресс или способностью его быстро освоить. В перспективе - рост до фреймворков и прочих серьезных вещей. Почта: [email protected]
Посоны, возможно ли подсоединиться к базе данных при помощи PHP 7 (или даже 5), если база данных находится на SQL Server 2000? Дали такое задание на работе (эникейщиком сижу), второй день ебусь. Якобы ODBC драйвера 13ые не поддерживают SQL 2000, 11ые тоже, а старее я хуй знает как найти, еще и сервак сайта на Убунте виртуальной, а я вообще в линуксе ноль и как их ставить и где искать.
Делаю простенькую задачу по форме с поиском по БД. Запилил такой запрос:
SELECT id FROM dbCountries WHERE fruit COLLATE UTF8_GENERAL_CI LIKE '%$food%' OR vegetable COLLATE UTF8_GENERAL_CI LIKE '%$food%'
Только-только вкатываюсь в пхп, посему к PDO даже не лезу.
Проблема в том, что сраный скрипт скармливает в БД массив, собранный из слов в строке, разделенных знаками или пробелами.
Как итог, если будет введена дебильная фраза "А Наташа любит банан", чертова буква "а" будет послана по бд и вылезет целая куча "подходящих" значений, типа "апельсин", "банан" и прочая хуита.
Казалось бы, простой ответ: замени свой паршивый лайк на что-нибудь по-проще и что-нибудь более строгое!
Но задача усложнена тем, что в одной ячейке, через запятую может находится несколько названий, разделенных запятой (можно заменить на пробелы, но кому это поможет?).
>>1119406 смотри, я сделал через foreach, но так и не понял, как сделать через него так, чтобы он две строки делал, копипаста же не пройдет? или оно так и задумано, чтоб с копипастой? https://ideone.com/UDmeve
>>1126159 Тебе нужно было поместить слова в один массив и так же добавить в него перенос строки в нужных местах, и затем пройтись по всему массиву с помощью foreach Я же писал тебе подсказку из задачи дважды
>Подсказка: можно упростить программу, сделав что-то вроде шаблона для генерации стиха на основе массива. В каждый элемент массива мы кладем массив вариантов слова или строки, из которого надо сделать выбор: [$word1, $word2, $word3, ["\n"], ...]. Мы добавляем массив с "\n", чтобы в нужном месте вывелся перевод строки. Остается только пройти по массиву циклом и сгенерировать стих..
>$array = array( >$word1 = array Внутри массива не делают присваивание Либо просто помещают значение или переменную, либо пользуются конструкцией key => value
Для вложений используют табуляцию 4 пробела
>foreach($array as $word) >{ В циклах и условиях, перед скобкой, не ставиться перенос строки
>$text = array_rand($word); >$text2 = $word[$text]; >echo "$text2"; Можно было написать проще $text = $word[array_rand($word)]
>>1125999 Читал файл install.txt прилагающийся к php и вспомнил про тебя > MDAC requirements: If you use Microsoft Windows 98/NT4 download the latest version of the Microsoft Data Access Components (MDAC) for your platform. MDAC is available at http://msdn.microsoft.com/data/. This requirement exists because ODBC is built into the distributed Windows binaries.
Вопрос: есть родительская таблица Товар, у него есть связь многие-ко-многим к таблице Жесткость (т.к. две стороны, могут быть обе одинаковые, а могут – разные) с промежуточной таблицей ТоварЖесткость. Надо выбрать Товары с определенной жесткостью, при этом не исключая наличия других. SELECT p., h. FROM product p LEFT JOIN product_hardness ph ON ph.product_id = p.id LEFT JOIN hardness h ON h.id = ph.hardness_id WHERE h.id = 3 Как быть? Мне надо отбросить только те, где нет Жесткости с id = 3, а не все те, где id !=3
>>1126200 щас все бэкенд языки (пхп, питон, руби, нода, джава) на 80 процентов одинаковы. вопрос в том, что недостаточно выучить язык, надо еще знать экосистему (фреймворки, библиотеки, бп).
Пыханы, как вы тестируете на локальной машине передачу данных от одного сервиса другому? Ну то есть есть у меня сайт, с которого я curl'ом или ajax'ом отправляю на сервер какие-то данные и получаю ответ. Вот как вы это дело тестируете?
>>1126751 Если тебе нужно регулярное выражение, для разбиения строки, то естественно preg_split. Для простых случаев - типа разбиения строки по пробелу, запятой или другому разделителю - explode.
>>1126752 >Вот как вы это дело тестируете? тестируем - в смысле пишем тесты? ну твоя задача - не тестировать ответ от чужого приложения, а что данные от тебя ушли в нужном формате и был правильно обработан ответ.
>>1126753 Но тот же руби, нода, питон отличаются довольно разительно. А насчет джавы согласен, вкатываться несложно. Мимо пришел с шарпа, ибо ASP подзаебал
Всегда писал на пхп для себя, понадобилось вкатиться на работку. Какой фраемворк не сильно тяжело выучить и который можно запускать с флешки через локальный сервер? С опенсервера например, привык к нему
>>1126872 если битрикс такое гавно то почему он так популярен?
yii не говно, конечно. но популярен он на территории СНГ. мое предположение: из-за того, что его мануал переведен на русский, а для большинства вкатывальщиков английские мануалы - непреодолимое препятствие.
Люди поясните за "первые столбцы": Обе таблицы должны быть InnoDB-типа; обязательно также наличие индекса, в котором внешний ключ и ссылочный ключ должны находиться в первых столбцах. Для таблиц InnoDB индексы по внешним ключам или ссылочным ключам не создаются автоматически: их создание требуется задавать явно. http://www.mysql.ru/docs/man/SEC451.html
Перед объявлением внешних ключей, нужно создать одинаковые по типу столбцы, один из которых должен быть первичным ключом. А что значит "внешний ключ и ссылочный ключ должны находиться в первых столбцах"?
/ for ($i = 1; $i <= 4; $i++) { $random = mt_rand(1, count($letters)); $randomText = $letters[$random]; Я не могу понять это. Объясните пожалуйсто, всмысле как это работает?
Есть старое ПХП-приложение. Возможно ли, что из-за использования mysql_connect() вместо mysqli_connect() замедляется работа и сайт имеет боттлнек именно в этом месте?
Привет, аноны. Подскажите где почитать/посмотреть про загрузку файлов, чтобы прямо как здесь можно было несколько штук загрузить отдельно, а они бы списке красиво отобразились. Я может искал криво, но как такое сделать не нашел нигде.
>>1127368 есть массив $letters. в нем что-то лежит. дальше у тебя видимо куска кода нет, потом цикл for, видимо 4 раза делается echo $randomText.
в переменной $random задается число, которое представляет собой индекс массива (предполагаем, что массив не ассоциативный), далее переменной $randomText задаем значение в виде какого-то элемента из массива $letters.
>>1127368 ты видимо из другого языка пришел. в пхп в качестве индекса массива можно указывать переменную, метод, функцию, объект (при наличии у него метода __toString()), выражение, константу и т.д.
вообще в пхп (с версии 7, т.к. до нее было слишком много исключений) есть т.н. uniform syntax, т.е. возможно без страха задавать конструкции типа getFilters()[1]('Foo');
что означает "выполнить анонимную функцию с аргументом 'Foo', которая содержится в массиве с индексом 1, который возвращается при вызове getFilters()"
Пыханы, подскажите, как правильно поступить. Когда юзер заходит на сайт мне нужно ему отобразить некую информацию, которая зависит от параметров в адресной строке. Для этого мне нужно обратиться на другой сервер и получить её оттуда. Как это лучше сделать: на бекенде сайта c помощью php, до того, как юзеру отрисована страница (тут, понятно, будет блок до того, как информация получена) или делать это после загрузки страниц посредством ajax? Во втором случае придётся делать больше работы (корректировать скрипт для каждого последующего сайта, куда буду подключать всё это дело, да и будет заметно дёргание и смена дефолтной информации на обновлённую), но зато, типа не будет блокирующего соединения. Информация не прям критическая, но всё-таки очень хочется чтобы она всегда была донесена до юзера. В первом случае с php можно установить таймаут для соединения, чтобы не терять - в случае с очень долгим ответом от сервера - юзера совсем. И отдавать ему дефолтное значение, если превышен таймаут.
>>1127705 Для начала убедись, что ты можешь яваскриптом дергать чужие сайты. Для этого они должны отдавать тебе заготовок Access-Control-Allow-Origin с твоим доменным именем, либо звездочкой.
Если у тебя задача поддерживать только современные браузеры на новых мощных компах, делай как угодно. Если у тебя задача, чтобы и пользователи ИЕ, и Оперы Мини, и Тор Браузера не получили фигу, то делай всё на бэкэнде. Заодно сможешь настроить кэширование по вкусу. А на клиенте для кэширования придется работать либо с LocalStorage, либо с Cache API через сервисворкеры.
>>1127802 >А на клиенте для кэширования придется работать А, ну и конечно, старые добрые заголовки Cache-Control, Last-Modified и ETag. Но это уже как настроено на другом сервере.
Как думаете, я сильно тупой, если я вроде как более менее прочитал прорешал всего кантора по жс, а сейчас не могу сделать задачу ОПа про создание стиха? Выдумываю какие то циклы, циклы в циклах, хоспади
>>1125829 Гугол читеры! Это не Respоnsive как он должен быть, они генерируют свою версию под каждый экран и устройство на основе кучи факторов (например точно 2 разных экземпляра при медленном и быстром интернете, проверял, специально подсовывают "лайт" версию), короче лажа, зря ебался два дня. Такие дела. Алсо у меня нет возможности проверять на мобильных браузерах, но есть подозрение, что они оптимизируют под хром (на котором я тестировал) добавляя свои -webkit свойства, которым я поддержки не нашел на caniuse. Например они убирают тут >>1125441 полосу прокрутки насильно (::-webkit-scrollbar {display: none;}).
Тру Respоnsive например у https://www.microsoft.com/ru-ru/ но здесь нет такого "вау"-эффекта. Все предсказуемо собирается-разбирается как в бутстрапе (от которого тошнит уже). Я расстроен.
>>1128136 Кароч я сделал но как то хуево. Я хотел что бы все само подбиралось элегантно, бегало циклами по массивам и само подставлялось, а получилась какая то наивная фигня. https://ideone.com/OedzJO
>>1128388 Командная строка чего? Какой командой? filename.php просто текстовый файл. Ты вызываешь интерпретатор с параметром имя файла, например для линупса: php filename.php
>>1128308 во-первых, я предлагаю ОПу в шапку вынести: "для работы с массивами НЕ ИСПОЛЬЗУЙТЕ for и mt_rand. используйте foreach и array_rand"
во-вторых, помимо дублирования (это очевидный признак неправильного решения) желательно решение сделать более человеко-читаемым. все условия желательно подавать сначала, а у тебя порядок слов жестко определен в решении и надо смотреть весь код, чтобы его понять.
я бы сделал так https://ideone.com/Ec6w04 что позволяет нам все исполнение вынести в функцию, куда мы на вход подаем список слов и их порядок, а все решение скрыть от наших глаз.
>>1128576 Сложна. Хз как те кто только открыл этот тред вообще понимают foreach. Я после Кантора все равно не уверен что до конца понимаю. Или я на самом деле просто очень тупой.
Есть PHP код, выполняющий процедуру в базе данных (запрос в духе EXEC _название процедуры_ _параметры_). Заголовки результирующей таблицы идут названиями полей таблицы, (к примеру, ID, Name, Client и прочее). Можно ли сделать так, чтобы названия столбцов были на русском, не меняя код в процедуре, а только в PHP?
>>1128701 Жди ответа опа, а пока ждёшь -0 приступай к следующему (хотя тут ты должен поставить что-то типа break(); при выполнении какого--либо условия)
>>1128710 Я вообще решил пхп учить потому что в жс обосрался. Ну как обосрался, Кантора вроде с горем поплам прорешал, а потом решил закрепить хекслетом - а там уже пиздец, ес6 синтаксис, функции в функции в функции вот это вот все. Вот сюда пришел опять обсираюсь. Пиздец. Надо наверное все свободное время пытаться ебенить эти задачи, палиндромы и всякие вот эти задачи, что у кантора что у Опа. По два часа в день нихуя не прокатит.
>>1128717 Не отчаивайся бро. Тут главное не бросить это дело, и по несколько часов таки уделять, даже если пока ничего не понимаешь. Поверь, спустя какое-то время прийдёт знание.
>>1128738 Сайт стоит на самописной цмс. Нужно допилить функционал корзины (фронт уже запилен) и прикрутить оплату от яндекса. + пара мелких фиксов Бюджет – 3к
Для показа элементов фиксированной высоты идеально подходит inline-block (лента картинок)
Поддерживается в мобильных, десктопах и ие с 5.5
Для сколь угодно сложных элементов — table. Растягивается, позволяет держать сетку. Минусы: 1) при вложении картинок тегом <img> при пересчете пропорций появляются мерзкие полосы, у inline-block такого нет. 2) таблица рассчитана на скроллинг вертикально, в ней обычно добавляются строки, а тут для заполнения надо добавлять столбцы. Приходится разбирать содержимое на "слои": одна строка для каждого кусочка, и привставке нового элемента добавлять ячейку в каждую строку. Геморно, непонятно, как использовать в темплейтах. Или использовать одну строку, но тогда теряется выгода таблицы.
Поддерживается в мобильных, десктопах и ие с 8
Решил буду использовать оба.
Вариант с flоat — надо знать ширину ленты. Сложнее inline-block, а выгоды никакой, не подходит.
Кстати, самое современное — flex, но это уже совсем не кроссбраузерное, не подходит.
>>1128751 >2) таблица рассчитана на скроллинг вертикально, в ней обычно добавляются строки, а тут для заполнения надо добавлять столбцы. Приходится разбирать содержимое на "слои": одна строка для каждого кусочка, и привставке нового элемента добавлять ячейку в каждую строку. Вот тут непонятно. Ты ведь заранее знаешь сколько фоток будешь в таблицу пихать. Какие проблемы?
>>1128762 Ну смотри: при открытии страницы я ставлю 10 фоток. Крутишь влево, доходит до конца, и тут в зависимости от контекста оно может подгрузить еще фоток (бесконечная лента) или показать кнопку "еще" / "подробно" и т.п.
А если тебе не интересен этот блок ты просто скроллишь дальше вниз.
Сап, программач, поясни за класс Request. Я понимаю, что это обертка для запросов, для удобной работы с post, get, но можно еще немного разъяснить для меня.
Как выполнить часть кода PHP на странице только после того, как пользователь введет нужные данные в поля? Примечание: поля для ввода данных генерируются до этого, то есть они могут быть разными и разное количество.
Если подробней то, есть БД с названиями процедур и отдельной колонкой с перечислением параметров. На стартовой странице я их вывожу и по клику перехожу на новую страницу, где я, забрав название процедуры, забираю уже из БД ее параметры, а зависимости от параметров отрисовываю поля для их ввода. Теперь же нужно, чтобы процедура выполнилась после введения данных в поля для ввода (а они могут быть разными, в зависимости от процедуры). Плюс необходимо допустить возможность менять данные в полях для ввода и запускать процедуру сколько хочешь.
Отправляю c клиента пост запрос, на сервере принимаю. Вывожу его в лог print_r и почему то эти данные попадают в ключ массива. Что за фигня? То есть выглядит это так
>>1129584 >если ты имеешь в виду, что выводишь в файл лога, то надо использовать var_export($data, true) Не-не-не. Я долбоёб и отправлял в теле пост запроса инфу тупо сериализуя массив без http_build_query и на выходе получалась такая хуйня.
Сап двач. Есть один заказчик, ему нужно показать пример проекта на Joomla. У меня нет опыта на Joomla (только Laravel, Wordpress). Так вот, может какой нибудь добра-анон поделится годным проектом на Joomla? Буду крайне признателен.
Код конечно надо форматировать, добавлять отступы, а то трудно понять, где начинается и заканчивается функция.
Имена переменных начинаются с маленькой буквы.
"} else {" пишется в одну строку
> $creditBalance;/ Долг анона перед банком / Так писать вообще неправильно. Что делает эта строчка? Если ты хотел добавить комментарий к аргументу функции, то лучше было перед ней написать так
/ $creditBalance - Долг анона перед банком /
Результат получился неточный. Во втором кредите плата будет 61270 с копейками.
Скорее всего, это из-за того, что ты проверяешь, что долг меньше 5000 до того, как начислены проценты и комиссия. Получается такая вещь: прибавляется комиссия, проценты, остается 9000 долга, анон выплачивает 5000, остается 4000 и в следующем месяце ты без добавления комиссии и процентов погашаешь остаток.
access_control это для закрытия целой области на сайте. Например, всех URL вида /admin/... или весь поддомен admin.example.com. Не надо беспокоиться о том, что кто-то при добавлении нового действия забудет поставить там проверку.
Далее можно использовать @security или ручную проверку для ограничения доступа к отдельным действиям.
Ты вот не написал, о каком фреймворке или библиотеке идет речь. Это ведь не стандартный класс PHP, а часть какой-то библиотеки. И не написал конкретного вопроса.
Лучше всего наверно прочесть документацию.
Я предположу, что ты хотел задать вопрос "зачем нужен этот класс, если можно брать данные напрямую из $_GET/POST/SERVER".
Обычно объект класса Request представляет собой информацию о HTTP-запросе, пришедшем от пользователя. Представление запроса в виде объекта позволяет явно показать, что той или иной функции нужны данные из запроса, явно их передать. Ну например:
- getUserCity(Request $req) - определяет город пользователя по каким-то параметрам запроса (скорее всего, по IP адресу). Явно видно, что она использует данные из запроса.
Сравни с функцией, которая не использует объект Request:
- getUserCity() - непонятно, по каким данным она определяет город.
При этом мы можем легко создавать свои объекты Request, например, для тестирования, имитируя приход какого-то запроса. Можем сохранять объект Request куда-то и позже восстанавливать обратно, можем дампить его в лог итд.
Часто он также содержит полезные методы вроде getInt (преобразовать параметр к числу) или getRemoteIp().
Наконец, PHP парсит входные данные не любых типов. Например, если твой код в браузере присылает POST запрос с телом в формате application/json, то эти данные не попадут в $_POST, тебе надо самому их как-то парсить. Класс Request может взять это на себя (если ты это в нем реализуешь).
Убедись, что исходник в кодировке utf-8 и что при разборе XML ты правильно выставляешь все кодировки. Если в XML не указана кодировка, его надо привести к utf-8.
У таблицы (и флоатов) нет проблемы с пробелами между элементами, можно задавать произвольный шаг для ячеек. А так да, у таблиц есть разные заморочки, например, нельзя позиционироваться относительно элементов таблицы, overflow на ячейках может не работать и тд.
У flex полно своих проблем. Баги ( гугли flex bugs ), было 2 версии спецификации, плюс, там сложный алгоритм расчета размеров, в котором надо разбираться. Ну например, я встречал случаи, когда флекс масштабировал картинки до нулевых размеров из-за нехватки места.
Более того, first/last хранят букву, а не число, и нет никакого смысла пытаться их увеличивать.
Попробуй вставить в цикл echo, который будет выводить значение first и lost, чтобы увидеть, что именно ты сравниваешь. Вообще, выводить содержимое переменных полезно, чтобы увидеть, где именно твоя программа работает не так.
Если ты обнаружил различие между буквами, то нет смысла продолжать цикл, надо выйти из него с помощью break.
А что в foreach сложного? он используется так в простом варианте:
foreach ($массив as $переменная) { тело цикла; }
Он берет по очереди каждый элемент массива, копирует его значение в указанную переменную и выполняет тело цикла. То есть тело выполняется столько раз, сколько элементов в массиве. Простейший пример:
У анона вместо массива-переменной в foreach указано выражение (explode(' ', $pattern), которое разбивает строку по пробелам на массив слов. Соответственно, foreach на каждом шаге берет очередное слово (первый раз - word1, второй раз - word2 и тд).
При этом если php не в PATH, то надо писать полный путь к нему, например c:\php\php.exe. Если filename.php не в текущей папке, то к нему тоже надо написать полный путь. Под windows пути с пробелами надо брать в двойные кавычки.
> Это не Respоnsive как он должен быть, они генерируют свою версию под каждый экран и устройство Да, есть такое, я замечал, они для старых браузеров могут отдавать старую верстку. Вот видишь, как полезно ковыряться в других сайтах и смотреть, как что сделано.
Может это оптимизация, не отдавать на устройство правила, которые ему не понадобятся все равно.
> Алсо у меня нет возможности проверять на мобильных браузерах Можно использовать Хром (с движком webkit или blink) и в инструментах разработчика ставить эмуляцию мобильных устройств - она довольно хорошо работает.
> но есть подозрение, что они оптимизируют под хром (на котором я тестировал) добавляя свои -webkit свойства, которым я поддержки не нашел на caniuse А большинство мобильных браузеров на движке webkit/blink (андроидовский встроенный, Хром, safari). Не на нем разве что мобильный фаерфокс и может еще какая-то экзотика. Сейчас осталось всего 3 движка - Webkit/blink, Gecko (FF) и Trident (IE).
Вообще, кроссдоменные запросы можно сделать и для старых браузеров, без поддержки кроссдоменных заголовков, например, с помощью древней технологии JSONP: https://learn.javascript.ru/ajax-jsonp - там единственная проблема, не всегда удается обнаружить ошибку, только если по таймауту.
Также, я помню, была какая-то хитрая технология передачи данных через hash в URL страницы в ифрейме.
Была библиотека easyxdm для поддержки таких вот древних браузеров https://easyxdm.net/wp/ (список поддерживаемых браузеров впечатляет).
> $randomText = $letters[$random]; Найти в массиве $letters элемент с ключом, который хранится в $random, и вернуть значение этого элемента в переменную $randomText.
> Перед объявлением внешних ключей, нужно создать одинаковые по типу столбцы, один из которых должен быть первичным ключом Не требуется, чтобы один из столбцов был бы первичным ключом. Не требуется, чтобы они были в разных таблицах. Можно связать любые поля или группы полей, лишь бы они были одного типа.
> А что значит "внешний ключ и ссылочный ключ должны находиться в первых столбцах"? В обоих таблицах должны быть индексы, где колонки, из которых составлен внешний и ссылочный ключ, идут в начале списка полей.
Допустим, есть таблицы a и b, и поля в них a.b_id (внешний ключ) и b.id (первичный ключ).
Чтобы создать внешний ключ, связывающий поле a.b_id с b.id, нужно, чтобы для обоих этих полей были бы созданы индексы. Иначе проверка наличия связи будет очень медленной и потребует перебора всей таблицы.
Следовательно, в таблице a должен быть индекс либо по полю b_id, либо по нескольким полям, где b_id идет первым (например: (b_id, x, y)). Аналогично должно быть и в таблице b для поля id. Если id - это первичный ключ, то индекс по нему уже есть, так как при объявлении первичного ключа в MySQL создается уникальный индекс по указанному полю.
Внешний ключ может связывать не одно поле с одним, а пары или группы полей. Например, можно определить, что тройка полей (a.x, a.y, a.z) ссылается на тройку полей (b.x, b.y, b.z). В этои случае должен быть индекс, содержащий эти 3 поля или такой, в котором список полей начинается с них.
Однако, информация у тебя в переводе немного устарела. Вот более новый мануал на англ:
> MySQL requires indexes on foreign keys and referenced keys so that foreign key checks can be fast and not require a table scan. In the referencing table, there must be an index where the foreign key columns are listed as the first columns in the same order. Such an index is created on the referencing table automatically if it does not exist.
> MySQL требует наличия индексов на внешних и ссылочных ключах так, что проверки могут быть быстрыми и не потребуют полного обхода таблицы. В ссылающейся таблице должен быть индекс, где колонки из внешнего ключа идут первыми, в том же порядке. Такой индекс создается в ссылающейся таблице автоматически, если он не существует.
Один из вариантов - сделать сайт-имитацию, который будет притворяться другим сайтом и отдавать заранее заложенные в него ответы. И поменять на основном сайте настройку, чтобы он обращался к этой копии.
Другой вариант - просто в коде предусмотреть заглушку, чтобы возвращались какие-то заранее заготовленные данные безо всяких запросов.
Речь об автоматизированных тестах или ручной проверке?
Еще тут вопрос, что именно ты хочешь протестировать?
1) что твое приложение отправляет запрос с определенными параметрами на внешний сервер? 2) что твое приложение корректно разбирает пришедший от внешнего сервера ответ? 3) что твое приложение корректно обрабатывает ошибки соединения с внешним сервером? 4) что твое приложение корректно использует полученные от внешнего сервера данные?
Для случаев 1-3 надо либо делать имитацию внешнего сайта, либо для автоматических тестов, можно мокать HTTP-клиент. Для случая 4 можно просто возвращать заранее заготовленные данные.
Я думаю, что тут нужна группировка строк, относящихся к одному товару, и проверка по условию HAVING (это условие, которое применяется к сгруппированным строкам, после группировки, в отличие от WHERE).
То есть:
- джойним к товару все его значения жесткости, получаем несколько строк на товар - группируем строки, относящиеся к 1 товару - отбираем только те, где есть (или где нет) определенная жесткость
SELECT ... FROM products p LEFT JOIN product_hardness ph LEFT JOIN hardness h ... GROUP BY p.id HAVING SUM(h.id = 3) > 0
Как это работает?
h.id = 3 возвращает 0 или 1 в зависимости от выполнения равенства SUM() складывает результаты (0 и 1) в группе
В чем тут подвох?
Если у товара нет жесткости, то LEFT JOIN произведет строку, где h.id IS NULL и равенство h.id = 3 даст тоже NULL. Не испортит ли это результат суммирования, превратив его в NULL? Гуглим:
Потому тебе придется их устанавливать и компилировать самому.
Я бы попробовал его поставить в virtual box и посмотрел.
Ну и вообще, я бы смотрел в сторону Debian Testing - он не такой огромный, консольная версия отнимает меньше гига на диске по моему и памяти много не ест, но выбор пакетов куда больше.
> Короч, посаны, че делать? Вообще, лучше нормально проектировать БД. В твоем случае - можно попробовать искать не просто "а", а например CONCAT(',', friut, ',') LIKE '%,а,%'. Ну или использовать принципы нормализации и не писать в одну ячейку несколько разных значений: https://github.com/codedokode/pasta/blob/master/db/normalization.md
Также, в PostgreSQL можно хранить в ячейке массив строк или даже JSON объект.
> Если быть точным, $digit - количество попыток сделать http-реквест, а $flag - флаг, говорящий, надо ли делать другие попытки, либо хватит одной Зачем flag, если можно просто указать digit = 1 ?
> A::lol(int $digit) принимает только количество попыток, это обобщенный отправитель http-реквестов. Класс B - это отправитель реквестов, заточенный под конкретный сайт.
Тогда я не уверен, что тут стоит применять наследование A от B. Это же по сути разные классы. "обобщенный отправитель реквестов" называется HTTP-клиент и как минимум, он должен принимать URL, куда делается запрос. А класс B мог бы получать его через конструктор:
$httpClient = new HttpClient(...); $exampleComParser = new ExampleComParser($httpClient);
Теперь про HttpClient. Часто код в нем можно разделить на "базовый клиент" и "расширения", например, расширение для кеширования ответов, расширение для повторных запросов при ошибке, расширение для использования случайного прокси-сервера из списка. Тут обычно используют один из 2 подходов:
1) встраивают возможность расширения в сам HttpClient, чтобы он держал в себе список расширений (тот же DI) и вызывал бы их на разных этапах:
Для расширений стоит сделать интерфейс и/или базовый класс.
2) используют "оборачивание" HttpClient в расширения. При этом стоит их объединить общим интерфейсом:
$httpClient = new HttpClient; $cachedClient = new CachedHttpClient($httpClient, параметры кеширования); $response = $cachedClient->get(...);
Во втором случае HttpClient не обязан знать ничего про расширения к нему и как-то с ними специально взаимодействовать.
> Сейчас у меня и А::lol, и B::lol возвращают объект WebResponse. Есть метод WebResponse::getStatusCode(). Для B мне нужно его пропатчить. Я делаю BWebResponse extends WebResponse и реализую метод BWebResponse::getStatusCode().
Не надо патчить, надо сразу создавать объект с нужным кодом.
В общем, мне не нравится твоя архитектура. Посмотри на мои предложения, также посмотри на готовые библиотеки вроде Guzzle, как у них сделано.
ОПчик, спасибо большое за твой труд и помощь. Мне больше не к кому обратиться по поводу код-ревью - только к тебе и анону. Можешь посмотреть этот небольшой метод для отправки данных на сервер через fsockopen и посоветовать что улучшить и ответить на вопросы, которые я написал в комментариях к коду? Спасибо.
Парни, всем добра. Подскажите какие плагины мне смотреть что-бы превратить Sublime в PhpStorm? Интересует отладка XDEBUG ну это гуглится и форматирование кода, проверки на ходу, которые делает PhpStorm, ну и если будет так же дополнять код по мере набора и высвечивать описание функций - будет просто супер.
Сделал временное зеркало для сайта без рекламы и прочей ерунды https://codedokode.github.io/phpbook (оно вас отредиректит на временный домен, не запоминайте его, не сохраняйте, не распространяйте, он тестовый, временный и в будущем поменяется. Плюс, это бесплатный домен и я ему абсолютно не доверяю).
>>1130639 Для разработки на php лучше всего подойдёт phpstorm, но он платный. Можешь бесплатно купить с торрентов. А для решения задач опа хватит и нотепада или саблайма с головой.
>>1130647 Просто я сейчас работаю недомакакой (преобразование текста в ссылку) и вот подумал, что нужно отучиваться от нотпада.
Алсо, а куда можно скинуть код, чтобы меня обоссали? Ну т.е. у меня уже есть полностью рабочая версия кода, но я хочу, чтобы мне заяснили, где я изобретал велосипед, где делал бессмысленные вещи, а где просто валял хуйню?
пацаны, а что значит "изучать фреймворк"? я вот учу симфони и пока получается, что я изучаю как писать конфиги к компонентам, грубо говоря. предполагает ли изучение фреймворка изучение исходного кода?
Здравствуйте, тут год назад ( наверное) кто то создавал конференцию в телеграмме, я туда зашел, был в числе первого десятка кто сидел, но проебал сим-карту, и теперь ее не могу нигде найти. Может у кого сохранилась ссылка, не могли-бы вы поделиться, пожалуйста?
Да, это понадобится, как только ты захочешь сделать что-то нестандартное. У нас в шапке есть задача про TestHub, в ней конфигами ты вряд ли обойдешься.
Здравствуйте, я вот начал изучать с++, сделал на нем примитивный текстовой квест на чистых условиях, параллельно потихоньку просматривал пхп из гайда для новичков в шапке, и решил спросить, а можно ли такое же сделать и на пхп?
В с++ как, в вижуал студио написал, скомпилировал - и весь квест в консольке работает, а взаимодействие - введите 1 или 2 для продвижения, и тому подобное.
Условия в пхп я изучил, но что то не наблюдаю такой возможности, что бы человек мог ввести какую либо цифру, или значение - и что то произошло. Это уже дальше будет?
Сап, Оп. Я мелкопараша-кун, если помнишь. Разгреб свои дела и приступил к разработке, а если точнее, то к проектированию бд. Поизучал другие движки, как ты и советовал, сел с ручкой и листком, вроде сделал. Но тут возникла проблема в моем непонимании устройства самой борды, т.к я на бордах относительно недавно да и педалику вакабу не настраивал. Не могу понять, как тонут и как взлетаю треды, что значит поле bump (если тред, то время последнего отписанного в него поста, но что это значит??) и тд. Буду очень благодарен, если кто-то объяснит этот аспект.
>>1131257 Если в треде постов меньше бамп-лимита, то при добавлении поста обновляем поле бамп (меняем там время на свежее), если больше, не обновляем. При сортировке по этому полю по убыванию, свежие треды будут сверху, чутка подтухшие ниже, треды в бамплимите в самом низу. Так же мы выбираем только треды до определенного лимита (например не более 50 для раздела). Если при сортировке по бампу тред идет 51, пользователь его не увидит, тред "смыло". В базе он еще будет, нам нужно позаботится что бы иногда чистить базу от старых тредов (например отправлять их на архивач). Если у тебя открыта вкладка в браузере со старым тредом, ты некоторое время еще можешь открывать картинки из него, значит скрипт уборщик еще не отработал.
>>1121562 >Может тогда автоматические тесты сделаешь? Сделал тесты для задачки по студентам (а заодно переделал все по твоим замечаниям): https://github.com/moabit/student-list/tree/master/app/Tests ОП, можешь глянуть, если не сложно? Тесты пока что никогда не пробовал писать. Нужно ли для них тоже писать комментарии и PHPDoc? Я правильно понял, что тесты для контроллеров не имеют смысла?
Почему header("Location:dashboard.php"); не работает у меня? Он не перенаправляет на страницу, перезагружает текущую без вывода каких-либо ошибок? Может ли это быть из-за того, что я pdo накосячи а я накосячил?
Как в Symfony инициализируется приложение? Т.е. работа приложения начинается с индексной страницы, насколько я понимаю? Она создаётся автоматически и со всему настройками, после composer create-project symfony/website-skeleton my-project? Почему, кстати, в Quick Tour написано просто skeleton? Где можно прочитать об этом?
>>1130056 >С помощью @ подавляю ошибки Никогда так не делай. Некоторые ребята говорят, что всякие запросы через интернет - это исключения, когда можно юзать собачек. Нет, нельзя. В интернете может сломаться даже небо, даже аллах - такой уровень абстракций скрывается под простым открытием сокета. Но что интересно - ломается, как правило, однократно. Можешь сделать трассировку от твоего хостинга до сайта, куда ты ломишься. Там будет 10-20 хопов. На каждом хопе пакетик может куда-нибудь деться, переполниться буфер или еще что-нибудь. Так как fsockopen не кидает обрабатываемых эксепшнов, надо это починить. Делаешь так: https://pastebin.com/LaVbsbGQ (Заметь, что сломаются собачки. Их можно починить, но не скажу как. В хорошем коде никаких собачек нет, только try/catch.) Затем оборачиваешь fsockopen в try/catch, пишешь в лог, что случилось, и вот тогда уже возвращаешь что-то дефолтное. Но это уже две задачи для твоей функции. Сделай обертку, которая будет делать sockPost(), и возвращать либо ответ, либо дефолт. Плюс дефолт не должен быть захардкожен.
>Какая разница между timeout в fsockopen и этой настройкой? Полагаю, ее нет.
>если я меняю версию HTTP на 1.1 то время ответа увеличивается в несколько раз! Почему так? Потому что HTTP 1.1 по умолчанию ждет от тебя несколько запросов в одном сокете. Ждет-ждет, не дожидается, рвет коннект. Тебе нужно явно обзначить, что запрос только один, заголовком Connection: close.
>Вот эту часть не понимаю - зачем вообще она нужна Ты читаешь все http-заголовки в переменную headers. Так как заголовки отделены от тела пустой строкой, цикл прекращает крутится на пустой строчке.
>Если я правильно понял, metainfo['timed_out'] нужно, чтобы закрыть соединение Неправильно. При наступлении тайм-аута соединение уже оборвано. fgets просто вернет тебе false, а feof не вернет, конец-то не достгнут. А еще false от fgets может прилететь и по другим поводам. Вот так лучше: https://stackoverflow.com/questions/18349123/stream-set-timeout-doesnt-work-in-php#18350140
А теперь самое главное и веселое. Ты зачем это написал-то? file_get_contents делает всё то же самое, только под капотом. POST-запросы и куча других опций отправляются добавлением stream context.
>>1131954 Сколько нужно сторонних модулей, чтобы, мать его, просто сграбить посты, положить в базу, показать юзеру? Серьезно, там же вообще список охуевший.
>>1131957 ты видимо просто еще не привык. в реальных приложениях зависимостей всегда дохуя. для crud-приложения на симфони с 4 сущностями их допустим 25+. но я тут проблемы не вижу - они жрать не просят
Делал задачку из шапки, где надо сделать форму, которая расчитывает кредит на пхп. Поясните дебилу, как сделать так, чтобы мой код не выполнялся до того, пока не отправишь форму.
вывести форму; если проведен расчет, вывести результаты;
Проверить, что форма была отправлена, можно разными способами:
- по наличию в $_GET ключей, соответствующих полям формы - по наличию в $_GET ключа, соответствующего имени кнопки - для POST-форм проверкой $_SERVER['REQUEST_METHOD'] (не для нашего случая)
>>1132198 >Проверить, что форма была отправлена, можно разными способами: Единственно верный способ уходить на ветку обработки формы - проверять присутствие всех необходимых ключей в $_GET либо $_POST.
>>1132011 В том-то и дело, что я один из 25 человек, пилящих ебовешие сервисы на PHP, в багтрекере скоро будет тикет номер 17000. И, сука, у нас конфиг композера размером примерно с этот, а это малюсенький сервис, который просто архивирует сообщения.
>но я тут проблемы не вижу - они жрать не просят А я - вижу. Когда-то давным-давно у нас первопроходцы натаскали зависимостей, и теперь, несмотря на то, что всё лежит локально, бутстрап лезет на какие-то CDN; выполняешь тикет и меняешь input type="text" на input type="number" и модалка с формой просто перестает открываться, потому что плагин для jQuery ожидает только type="text", сука. Чужой модуль - это куча чужих багов и хуй знает как написанного кода. Ты экономишь полчаса-час работы, прикручивая васянский модуль, а затем живешь с черными ящиками в своем проекте.
Ощущение, что ты просто то ли в композере не разбираешься, то ли еще в чем-то.
> бутстрап лезет на какие-то CDN При чем тут композер, если бутстрап это JS-код и если он и ставится через менеджер пакетов, то через какой-нибудь bower или yarn. И даже в этом случае он не должен лезить ни на какие CDN.
Просто у вас какой-то инвалид вписал ссылку на CDN и ты теперь винишь в этом композер.
Мог бы исправить, кстати.
> выполняешь тикет и меняешь input type="text" на input type="number" и модалка с формой просто перестает открываться, потому что плагин для jQuery ожидает только type="text"
Это ваши проблемы и композер тут не при чем.
> Чужой модуль - это куча чужих багов и хуй знает как написанного кода.
Не надо ставить все подряд, надо изучить доступные библиотеки и выбрать нормальные.
> Ты экономишь полчаса-час работы, прикручивая васянский модуль, а затем живешь с черными ящиками в своем проекте. Это несерьезное рассуждение. за сколько часов ты напишешь аналог Доктрины? Или Guzzle?
У нас есть ровно 2 варианта: либо использовать сторонние библиотеки, либо не использовать и писать велосипед. Если мы используем, то либо копируем и ставим все руками, либо перекладываем эту задчу на композер.
В том проекте все зависимости
- Доктрина - для ORM - migrations - для миграций - slim, php-view - как фреймворк - cache - для кеширования - dom-crawler - для парсинга HTML - guzzle - как HTTP клиент
И так далее. Расскажи, как обойтись без них и сколько часов ты на этом сэкономишь.
>>1132212 я твою позицию понимаю, система разрастается и копит зависимости, а потом ее и еще 25 других встраивают в другую систему и все растет как снежный ком. тревожненько.
но зато 1) RAD 2) я не вижу альтернатив. ты же не будешь писать свои сервисы контейнеров, логгеров, валидаторов и т.д.? а если и будешь, в них будут такие же баги
>первопроходцы натаскали зависимостей звучит как косяк в архитектуре и кто-то просто не ожидал, что проект выстрелит. ну ничего, так везде
вообще это забавно, т.к. у меня на прошлой работе все было наоборот. почти все компоненты были написаны сотрудниками компании из-за того, что легаси. потом легаси отрефакторили, а сервисы остались собственными. в них везде была какая-то поебень, мешанина подходов и прочее. только сторонние библиотеки доставляли удовольствие при работе с собой
>>1132272 >У нас есть ровно 2 варианта: либо использовать сторонние библиотеки, либо не использовать и писать велосипед Писать велосипед - это с нуля написать свой DOM-парсер, например. А написать вспомогательный класс из 50-100 строк вместо подтягивания какой-то либы - это нормально. Это как глупые ребята, не шарящие в CSS, везде суют reset.css, потому что им стандартные стили говна в жопу залили, а умные ребята знают, как верстать без таких глупостей.
>Доктрина - для ORM Пишу класс DBSaver с методами saveUser, saveNebo, saveAllah, куда передаю объекты User, Nebo, Allah. >migrations - для миграций Не знаю, что это. >slim, php-view - как фреймворк Для роутинга пишу правила регулярками и классы, куда должно улетать исполнение при совпадении. >cache - для кеширования Что может быть проще, чем файловый кэш? Сохраняешь файл, при запросе чекаешь, есть ли файл и не тухлый ли он. > dom-crawler - для парсинга HTML Тебе из коробки даются либы на любой вкус - https://secure.php.net/manual/en/refs.xml.php > guzzle - как HTTP клиент file_get_contents отличный http-клиент.
Для начала хватит кода на гитхабе. Потому что я в основном смотрю код, а прокликать сайт и проверить что все работает, ты можешь и без меня. Но если будет еще и сайт, то может это пригодится.
Давай просто разберем по частям тобой написанное. Допустим, class Fetcher.
Начнем с того, что я не понимаю, зачем все методы передают друг другу $url, а не хранят его внутри объекта. Почему нельзя создавать инстанс на каждый $url?
Опа-ча, работаем с урликами, а внутри $url может быть локальный путь. Как так? Урл - это указатель чего-то в сети.
>getDomainForPause Хм, что это такое и что оно делает >parse_url($url, PHP_URL_HOST) Вау, стоило выносить и давать загадочное имя.
Оп-па, у функции pause сайд-эффект - она сохраняет время последнего запроса. Причем она делает это до запроса. Таким образом, $this->interval соблюдаться не будет. Ведь http-реквест может затормозить в любой момент - на открытии сокета, на открытии сокета сервером, на выдаче первого HTTP-заголовка, на выдаче любой порции стрима, где угодно. Реквест может проходить сколько угодно секунд, и сервер может контролировать частоту твоих запросов от закрытия сокета, например. Но вот беда - сокет может держаться и больше дефолтных трез секунд, и в итоге ты сделаешь два последовательных запроса, а юзер твоего кода мог ожидать 3 секунды задержки.
>if ($response->getStatusCode() != 200) Код 203 равен коду 200, если информация берется из кэша сервера. Я на одном проекте отдаю 203, если предполагаю, что в базе может быть информация актуальнее, но репликация еще не произошла. Код 300 может быть отдан, если страница либо файл доступны в разных форматах. А еще можно получить 101, если сайт хочет работать только по HTTP/2. Во всех этих случаях юзер получает сайт, ничего не подозревая, а у тебя - ошибка.
>$response->getStatusCode() >= 300 && $response->getStatusCode() < 400 && $response->hasHeader('Location') У нас код 300 и Location. Нас хотят перенаправить? Не обязательно. Файл либо страница доступны в разных форматах, и юзер волен выбрать, в каком он хочет получить. При этом Location определяет дефолтный выбор, куда браузер может, но не обязан перейти. Для юзера это будет абсолютно обычная страница, как код 200.
Вообще, очень странно, что функция fetchUrl заодно выносит какие-то вердикты и просто не возвращает $response. Любые вынесения вердиктов стоит делать методами в классе ResponseMetadata.
if (!$type) { $errorText = "No Content-Type"; Сервер не обязан отсылать Content-Type. Если его нет, браузер угадывает его по сигнатуре первых байтов.
if (!preg_match("#^text/html#i", $type)) { $errorText = "Content-Type invalid: $type"; application/xhtml+xml, application/xml и text/plain грустят. text/vnd.wap.wml и не надеется, что про него вспомнят некоторые олдфаги.
Преимуществ guzzle не увидел. Мало того, если ты спустишься на уровень сокетов, сможешь просто закрывать его после получения заголовков через GET. Будет тот же HEAD, только без возможных 405.
>>1132341 Ну и про черные ящики. Вот ты предполагаешь, что Grunt вернет тебе Content-Type так, что строка будет начинаться с text/... А что будет, если сервер поставит два пробела между двоеточием и значением? Это валидный заголовок. У тебя будет первый пробел? Или не будет? Ты не можешь ответить на этот вопрос. Это не твой код.
>основная функция spellNumber(), которая принимает на вход большое число, разбивает его на части по 3 цифры и вызывая указанные выше функции, получает число прописью. И как мне это сделать, если >Некоторые делают ошибку, пытаясь работать с числами строковыми функциями вроде mb_substr() или mb_strlen(). Это неправильно.
Тогда как мне >разбивает его на части по 3 цифры
Нужно число делить на 10, сотни и тысячи для того, чтобы разделить?
>>1132364 Так, я придумал. Сперва поделить число на десятки миллионов, если делится, то задать переменной то количество десятков и форму слова миллион\ов\а. Потом взять остаток и его уже делить на миллионы. Повторить то же, что и с десятками. Проделывать так до единиц. Потом вывести эти переменные.
Ну проект довольно маленький, и он на ООП, так что не требуется его целиком изучать, можно смотреть отдельный класс. И да, он не идеальный, так как написан по сути (видно по коммитам) в 2 присеста и мне надо было получить что-то работабщее побыстрее. И я получил - теперь я могу получить список "сомнительных", потенциально сломанных или изменившихся ссылок для ручной перепроверки, не обходя все свои уроки вручную. Разве это не прекрасно?
Также, я думал использовать эту проверялку через Travis (CI сервис), чтобы при каждом коммите Travis бы скачивал мой репозиторий с уроками или сайтом, скачивал проверяльщик, проверял все ссылки, и я бы мог видеть по значку в ридми, что появились сломанные ссылки. И да, у меня еще есть (пока очень сырой и требующий работы) набор скриптов для проверки правописания через hunspell.
> Начнем с того, что я не понимаю, зачем все методы передают друг другу $url, а не хранят его внутри объекта. Почему нельзя создавать инстанс на каждый $url?
Потому, что Fetcher - это сервис, который может сделать много запросов. Не вижу, в чем мне выгода на каждый запрос создавать новый Fetcher. Более того, у него есть состояние - он запоминает время последней отправки запроса к каждому домену, чтобы не делать запросы к одному домену чаще, чем раз в 3 секунды.
И кстати, я там в checker.php прикрутил костылек, чтобы делать сначала запросы к доменам, которые с меньшей вероятностью заблокируются. Хотя, конечно, самое правильное решение было бы сделать параллельный запрашиватель файлов, но это бы потребовало намного больше времени на написание и отладку (хотя в Guzzle вроде что-то такое есть, может когда-нибудь гляну).
И заметь, я еще стараюсь по возможности делать HEAD, если он поддерживается сервером и если мне не нужно тело запроса. И умею перепрыгивать на GET, если сервер отказывается выполнять этот метод.
Вот реальная проблема, которую я пока не исправил - это отстутствие четкого разделения обязанностей между Fetcher и LinkChecker, это да.
> file — Имя локального файла > tel — звонок по указанному телефону (хотя, тут может правильнее было бы использовать URN) > data — Непосредственные данные (Data: URL)
Поддержка file пока не готова, но планируется на будущее, чтобы можно было проверять ссылки в папке с HTML файлами. Удобно же.
>>getDomainForPause > Хм, что это такое и что оно делает Наверно неудачно названо и не хватает комментария. Определяет ключ, по которому проверяется частота запросов. Может быть, я захочу завтра ограничивать частоту запросов не по всему домену, а по домену 2-го уровня.
> Оп-па, у функции pause сайд-эффект - она сохраняет время последнего запроса. В этом ее предназначение - сделать паузу необходимой длины перед отправкой запроса.
> Но вот беда - сокет может держаться и больше дефолтных трез секунд, и в итоге ты сделаешь два последовательных запроса, а юзер твоего кода мог ожидать 3 секунды задержки. interval это интервал, чаще которого нельзя посылать запросы к одному домену.
> Код 203 равен коду 200, если информация берется из кэша сервера Не исключаю, что мой код не идеален. Однако, я не сталкивался пока с кодом 203, и никто мне не писал про этов Issues - значит, пока можно не тратить время на решение этой проблемы. Однако, записал твою идею в TODO.
Я тебе могу рассказать про более интересную проблему - обнаружение припаркованных (то есть потерянных или проданных владельцем) доменов. Эти домены отдают 200 на любой URL, но естественно, не содержат никакой полезной информации, а лишь список рекламных ссылок. Пример ww1.verginmobile.com
Другая проблема - некоторые домены не любят ботов (а я честно подписываю User-Agent) и отдают им ответ 403 или редиректят на localhost (я не шучу). Видимо, придется как-то вручную сделать исключения по доменам. Не знаю, как это лучше оформить, чтобы не хардкодить.
Третья проблема - проверка ссылок вроде mega.nz/#12345 (хеш там проверяется JS-кодом, даже если файлы недоступны, отдается 200) или rghost.net/12345 (если файл удален, он все равно отдает страницу 200). Опять же, наверно, нужны исключения на основе домена.
Сейчас эти проблемы актуальнее, чем экзотичные коды ответа.
> А еще можно получить 101, если сайт хочет работать только по HTTP/2. Надеюсь, что Гузл это сам обработает, так как код 1xx - это информационный код, который не завершает HTTP запрос, как я помню, и за ним придет настоящий код. Если нет, то просматривая список ошибок, я увижу проблему и исправлю код.
> У нас код 300 и Location. Нас хотят перенаправить? Не обязательно. Странно, мне кажется, что обязательно. Но я, конечно, так тщательно спеку HTTP не читал. Можешь дать пример страницы, где есть 3xx но это не редирект?
Ну и как я понимаю, большинство браузеров отредиректит пользователя, значит, ссылка у меня в статье неправильная. Может, конечно, надо различать виды редиректов, 301 от других, но по факту на сайте может быть криво настроен код, и мой скрипт должен работать в этом неидеальном мире.
> Вообще, очень странно, что функция fetchUrl заодно выносит какие-то вердикты и просто не возвращает $response. Любые вынесения вердиктов стоит делать методами в классе ResponseMetadata.
Я думал, но тогда нам придется просто засунуть туда целиком содержимое Response, а он еще и не сериализируемый и в кеш не пойдет. Я подумал, что проще будет переименовать его в CheckResult.
> Сервер не обязан отсылать Content-Type. Если его нет, браузер угадывает его по сигнатуре первых байтов. Не уверен. Знаю, что так любил делать ИЕ (content sniffing) и это приводило к уязвимостям. У тебя есть ссылка по теме?
> application/xhtml+xml, application/xml и text/plain грустят. ты бы мог еще добавить, что в статье может стоять ссылка на картинку или PDF. да, это написано в TODO. Тут еще сложность, что мне надо как-то отличать технические страницы с ошибкой от нормальных.
> Преимуществ guzzle не увидел. Мне не пришлось писать свой HTTP клиент, объекты для представления HTTP запросов и ответов. Не пришлось изучать кучу тонкостей, про которые ты написал (про 203 я например не знал), это уже скорее всего сделано за меня. Если это сделано - прекрасно, я сэкономил время. Если нет - то в любом случае, и со сторонней библиотекой, и со своей, придется тратить время на решение.
Чтобы делать запросы, нам в любом случае нужен HTTP клиент. Кто-то должен его написать, отладить, протестировать (а тесты тоже требуют немало времени), задокументировать, поддерживать, исправлять баги. При использовании сторонней библиотеки делать это придется не мне, я экономлю время.
Или по твоему, каждый разработчик в мире должен писать свою версию HTTP клиента? Или может, лучше просто взять библиотеку и исправить, если в ней чего-то не хватает? Так все сообщество будет в выгоде, получив твои исправления.
Ты не забывай, что приоритеты могут быть разными. Часто программисты пытаются оптимизировать код по каким-то техническим критериям: время работы, потребление памяти, уровень соответствия спецификации, покрытие тестами, субъективное восприятие качества кода. Но если это не учебный код, часто надо учитывать еще и бизнес-факторы (время/деньги). Ну например, бизнес может предпочесть получить код, потребляющий 1 Гб памяти и написанный за час коду, который потребляет 100 Мб, но требует 20 часов на написание. И даже если проект некоммерческий, бизнес-критерии к нему применимы, так как ты тратишь на него свое время и время доровоьцев, которое ограничено. То есть опен сурс живет по тем же экономическим законам.
Для меня это всего лишь вспомогательный инструмент, задача у меня уменьшить количество битых ссылок. В идеале до нуля, но не обязательно.
Для меня это всего лишь вспомогательный инструмент, задача у меня уменьшить количество битых ссылок. В идеале до нуля, но не обязательно.
> Мало того, если ты спустишься на уровень сокетов, сможешь просто закрывать его после получения заголовков через GET. Будет тот же HEAD, только без возможных 405. Это костыльно и недружелюбно по отношению к серверу, зачем его заставлять генерировать ответ, который мне не нужен? Ну и я подозреваю, что в Guzzle это тоже возможно (ограничивать размер ответа 0 байтами).
Я кстати, когда-то давно тоже страдал изобретением велосипедов, но, к счастью, много времени на это потратить не успел.
Но вообще, спасибо за подробный пост, я даже узнал что-то новое для себя. Не так часто такое бывает. Заходи почаще в наш тред, у нас есть и сложные задачки (как тебе задача на SPA из Оп поста?), может тебе интересно будет что-то поделать.
Я с таким не сталкивался. Если такое произойдет, то я увижу ошибку, начну разбирать ее и либо 1) найду баг в своем коде и исправлю 2) пойму что проблема на сервере и сделаю костыль дял нее 3) пойму что проблема в сторонней библиотеке, зарепорчу баг, и пока у себя сделаю костыль для исправления.
Я ведь точно так же и в своем коде не предусмотрю все возможные ситуации. да и я не хочу писать свой клиент, параллельно разгребая 100-страничный RFC.
Используй математику. Есть 2 функции для разделения чисел на части, $x % 1000 - берет 3 последние цифры, floor($x / 1000) - отбрасывает 3 последние цифры.
Ты бы изучил рассматриваемые библиотеки получше. Может и тебе пригодятся ;)
> Это как глупые ребята, не шарящие в CSS, везде суют reset.css Это плохой подход, сбросить все стили, а потом переопределять их заново или получить текст без абзацев.
> Пишу класс DBSaver с методами saveUser, saveNebo, saveAllah, к В Доктрине намного больше. Там еще есть загрузка объектов из БД, ленивая загрузка, поддержка отношений (ну-ка, напиши-ка), автоматический поиск изменений в объектах и тд. Это все экономит время.
>>migrations - для миграций > Не знаю, что это.
Миграции позволяют фиксировать в репозитории изменения в структуре БД, привязывать их к коммитам, воссоздавать структуру БД в любой точке истории, позволяют обновлять структуру БД без потери данных в ней, передавать эту информацию другим разработчикам. Иногда позволяют выражать изменения структуры БД не на SQL, чем достигается поддержка нескольких СУБД. А как ты в своих проектах обновляешь структуру БД? Вот понадобилось тебе например таблицу добавить, или поле, или индекс?
Я обычно пишу миграции руками на SQL, но некоторые любят сначала поменять схему БД вручную и потом сгенерировать миграицию из разницы схем новой и старой версии.
> Для роутинга пишу правила регулярками и классы, куда должно улетать исполнение при совпадении.
Изобретаешь велосипед. Symfony Routing например умеет генерировать из удобного читабельного YAML конфига (который читать проще чем твой код) код с регулярками ради оптимизации: https://symfony.com/doc/current/routing.html
Попробуй, только советую не использовать аннотации, а использовать YAML.
> Что может быть проще, чем файловый кэш? Сохраняешь файл, при запросе чекаешь, есть ли файл и не тухлый ли он. Так я это и делаю, только не пишу этот код сам. И получаю кучу готовых видов кешей, могу кеширвоать данные вообще куда угодно, хоть в шареную память.
> Тебе из коробки даются либы на любой вкус - https://secure.php.net/manual/en/refs.xml.php Они очень неудобные и не поддерживают CSS синтаксис (а в XSLT искать классы неудобно и громоздко).
> file_get_contents отличный http-клиент. Нет, чтобы получить просто заголовки, тебе придется писать код, чтобы добавить таймаут, еще какой-то код и так далее.
И кстати, я использую из Гуззла еще URL resolver - он умеет делать так: http://example.com/a/b + ../file.txt = http://example.com/file.txt . На сайтах ведь встречаются относительные ссылки. Ты его тоже предлагаешь самому писать?
В любом случае, кто-то должен написать, протестировать, поддерживать библиоетку - либо ты, либо сообщество. Не вижу в чем выгода тратить время на переизобретение того, что уже написано. И что я теряю, используя готовую библиотеку.
Тот проект (phpclub.tech) пишу не я, а аноны сами организовались и пишут. У них есть много своих дел, работа, учеба, и тд. Вряд ли они могут себе позволить тратить время на переизобретение ORM или HTTP клиента.
- CacertBundle дает мне файл cacert.pem для проверки HTTPS-сертификатов. А как же иначе, без корневого набора сертификатов ты HTTPS корректно выполнять не сможешь, и в той же винде например у PHP этих корневых сертификатов нет, использовать системные он видимо не умеет. В линуксе дела получше, но тоже наверно зависит от репозитория, так что проще исопльзовать готовое решение.
- ConsoleOutput и ConsoleLogger из symfony/console дают мне готовый PSR-логгер. Я могу легко перенаправить сообщения куда хочу и переключать подробный/краткий вывод логов.
- new InputDefinition из компонента symfony/console дает мне средство для разбора аргументов из $argv, а также умеет генерировать help по ним. Я знаю про getopt, он ужасен и сквозит своей сишной сущностью.
- guzzle делает HTTP запросы, и вроде как даже умеет параллельность, если не умеет, я могу взять клиент из ReactPHP
- FilesystemCache отвечает за кеширование с проверкой времени, и умеет очищать кеш. Это не очень долго писать, но ведь потом захочется сделать тесты, добавить какие-то фичи, и тд, и куча времени уйдет.
- symfony/dom-crawler и symfony/css-selector не идеальны, но парсить ими HTML удобнее, чем встроенным в PHP XML-расширением. Чего там стоит возня с настройкой кодировки или перехват ошибок.
Каждая зависимость в моем проекте обоснована и добавлена на основе взвешивания ее преимуществ/недостатков.
Ты наверно и шаблонизаторы не используешь? Зря, советую тебе изучить библиотеки, которые использовал я и аноны из phpclub, и они тебе не раз пригодятся. Я всегда готов что-то по ним подсказать и поделиться опытом.
Вот ты там выше анону написал про кучу тонкостей работы с HTTP, но ведь многое из этого, если не все, уже решено в Гуззле.
Что сложного в пагинации тредов? Берешь таблицу тредов и делаешь SELECT ... FROM threads ORDER BY bump_date DESC LIMIT :x OFFSET :y. Если тредов не тысячи, это будет быстро работать.
Тут стоит просто поставить себе образец Symfony приложения (например https://github.com/symfony/demo/ ) и смотреть код, начиная с public/index.php.
Там происходит все примерно так:
- инициализируем автозагрузку - создаем объект класса Kernel (я думаю, это будет App\Kernel: https://github.com/symfony/demo/blob/master/src/Kernel.php ). Его задача - инициализация фреймворка, загрузка DI контейнера, бандлов, разбор конфигов. - инициализируем DI контейнер - загружаем все бандлы (они тоже объекты), инициализиурем их, они читают свои конфиги и настриваются, ставят обработчики разных событий. Этот этап зверски оптимизирован и использует кеш, чтобы не делать это на каждом запросе, но пока на кеш можно не смотреть. В Симфони есть несколько встроенных бандлов (увидеть их список можно в AppKernel), и тебе придется посмотреть их код тоже. - создаем Request, передаем его Kernel для обработки - создаем по моему HttpKernel и заходим в цикл обработки запроса: https://symfony.com/doc/current/components/http_kernel.html - на всех этапах работы HttpKernel в процесс вмешиваются бандлы, и что-то делают свое. Роутер например разбирает URL запроса и ищет соответствие ему в конфиге роутинга, фаерволл проверяет права доступа - затем Httpkernel определяет текущий контроллер и запускает его - контроллер получает на вход Request и должен вернуть Response (HTTP-ответ с телом страницы внутри) - HttpKernel отдает Response юзеру
Также, прочитай про структуру приложения, что такое бандлы (расширения к ядру фреймворка, которые могут добавлять свои сервисы, роуты, обработчики событий и тд).
Также, есть подвохи: например, ты там не найдешь прямого вызова роутера для разбора URL или вызова фаерволла, который проверяет права доступа. Бандл с роутером просто в своем конфиге прописывает вызор роутера перед обработкой запроса HttpKernel, роутер разбирает URL и добавляет результаты разбора назад в объект запроса. Это специально так сделано, чтобы банглы могли менять процесс обработки запроса и отдачи ответа.
> # Какая разница между timeout в fsockopen и этой настройкой? Как правильно сделать? Надо читать мануал, думаю, в timeout ставится таймаут на установку TCP-соединения с сервером, а тут таймаут на ожидание пакета данных.
> fwrite($fp, $head); Тут ошибка. Ты почему-то думаешь, что все данные отправятся за один запрос. Но если почитать описание fwrite, то она всегда может вернуться раньше, отправив только часть данных. Надо проверять результат, который она возвращает, там есть много вариантов:
- отправлены все данные - отправлены не все данные - произошла ошибка
То есть надо читать мануал.
> # Вот эту часть не понимаю - зачем вообще она нужна, но если её убрать то мне всегда вместе с данными с > # сервера приходят и заголовки, которые мне не нужны. Изучи протокол HTTP, у меня есть урок: https://github.com/codedokode/pasta/blob/master/network/http.md
Тут тоже написано неправильно, кстати, надо проверять результат fgets. И опять же прочесть мануал по ней.
В общем, для всех функций, которые могут возвращать разные результаты, надо их проверять, не произошло ли ошибки. И изучить сам протокол HTTP сначала.
>>1132464 >Почему нельзя использовать Guzzle? Потому что не нужны зависимости лишние. Этот метод будет в классе, который предполагается подключать к сайтам клиентов. И почему для такой простой задачи ты советуешь огромный guzzle, а не curl тогда уж?
Тогда тем более надо сделать проверки всех результатов и обработку ошибок. А то ошибка произойдет - и никто не разберется почему.
Ну и я плохо понимаю в чем проблема использовать сторонние библиотеки. Ты хочешь, чтобы все в одном файле было? Тогда можно использовать склейщик (хотя он вызовет проблемы, если у клиента уже подключен Guzzle).
Но вообще, это сложная затея на мой взгляд. Если клиент не использует тот же композер, то скорее всего у него легаси сайт с неизвсетными настройками PHP, неизвестной конфигурацией обработчика ошибок и тд.
И кстати, да, curl или file_get_contents в твоем случае лучше бы подошел.
Вот я тебе (и другому любителю писать велосипеды) еще такой вопрос задам: а что, если с сервера приходит HTML в формате chunked ? Вы тоже его будет сами разбирать своим велосипедом? А поддержку gzip?
>>1132496 Ничего с сервера в формате chunked приходить не будет. Сервер будет наш, посылать будет в ответ строку определённого формата. С клиента же должна уходить некоторая информация, в том числе сессионные переменные. Да, важно, чтобы не было лишних зависимостей, класс этот простой, будет представлять из себя один файл - чем проще, тем лучше, потому что скорее всего клиенты будут подключать его сами - втыкать будут в индексный файл. Не думаю, что им захочется возиться с установкой композера и зависимостей. Спасибо. Сделаю, видимо, с помощью file_get_contents.
Некто кладет в банк 10000 р. Банк начисляет 10% годовых (то есть, каждый год на счету становится на 10% больше, чем в прошлом году). Напиши программу, считающую, через сколько лет в банке будет миллион? Сколько лет будет этому некто? Доживет ли некто до этого дня, если сегодня ему 16 лет?
https://ideone.com/SjLcUJ Я не пойму, мое решение норм или нет? Просто все, что я нагуглил выглядит иначе.
там есть компонент symfony cache. это по сути такая обертка на memcached или другой кэш-драйвер, который мы выберем. это понятно
но что за компонент управляет кэшом, который кладет скомпилированные твиги и аннотации в var/cache? где его настройки? это тот же компонент или часть frameworkbundle? как понять логику прогрева кэша - если у меня для каждого пользователя должен быть уникальный csrf-токен, он будет сгенерирован при прогреве? как этим управлять?
и главный вопрос: это вообще можно называть кэшом или это правильнее назвать чем-то типа компилятора из кода фреймворка в raw php-код?
буду также благодарен, если кто-то скинет ссылки где про это почитать. я искал, но не нашел.
У кого есть опыт подскажите как сохранять несколько объектов одного класса в бд? У меня есть объекты Event и мэппер EventMapper, в котором есть метод Insert для сохранения одного ивента. Если я хочу сохранить несколько, нужно сделать метод вроде InsertEvents(array $events), или для каждого ивента создавать новый мэппер?
Еще вопрос, а что если ивент содержит вложенные классы Reminder, которые тоже нужно сохранить. Пусть родительский EventMapper проверяет наличие "детей" и сам создает ReminderMapper и вызывает ReminderMapper->insertReminders(Reminders)? Или это забота контроллера, вытащить детей из родителя, и для каждого класса создать соответствующий мэппер?
И похожая ситуация, нужно трансформировать Event из класса в json определенной структуры. Event содержит дочерние классы Reminder. Есть соответствующие мэпперы для них. Должен ли родитель проверять наличие детей и создавать мапперы для них или вынести это в код, который создает родительский мэппер, например создать супер класс Mapper, который уже достает детей из родителей и для всех создает нужные мэпперы?
>>1132769 Я читаю это вот всё из треда и про себя думаю. Господи Как же ты хорошь. ты знаешь про обьекты, ты определаешь их типы, ты сохранаешь ивенты. И хочешь это многократно делать. Как же ты по сравнению со мной хорошь. Я ведь только начал путь. Я ведь только начинаю айфоны и айпады, я только начинаю оп задачки, а ты уже на вершине. Смогу ли я достичь такого мегамонстрячества? Сорян за оффтоп. Накипело всё.
> который кладет скомпилированные твиги Это сам твиг делает, и бандл Симфони только задает настройки для него вроде пути к папке.
> и аннотации в var/cache О каких аннотациях речь? Если о Доктриновских, то это делает сама Доктрина. Если об аннотациях контроллеров, то думаю, надо искать где-то в FrameworkBundle или по коду, где они ищутся.
> как понять логику прогрева кэша - если у меня для каждого пользователя должен быть уникальный csrf-токен, он будет сгенерирован при прогреве? как этим управлять?
"прогревом кеша" называется генерация симфониевских кешей (например создание компилированной версии DI контейнера или компилированной версии роутера или прокси-классов для доктрины или твиг-шаблонов) при вызове команды cache:warmup. На продакшене это делается вызововом команды, на dev кеш генерируется и обновляется сам при обновлении любого из файлов (например конфига), на основе которого он сгенерирован.
Прогрев кеша не относится к каким-то поьзовательским кешам и твой токен тут не при чем.
Вообще, я вроде писал про кеши в Симфони, но не могу найти пост, продублирую тут.
1) кешер опкода (например, opcache) - не часть Симфони, но крайне рекомендуется, если вам важна производительность. Нужно включить. На дев настраиваем revalidate_freq (частота проверки времени модификации файла) низким 1-2 секунды, на продакшене можно настроить его на 1-2-3 минуты, и сбрасывать кеш после деплоя скриптом.
2) Кеш DI контейнера и роутера
Симфони читает конфиги бандлов и пользователя, и создает компилированную версию DI контейнера (то есть PHP класс со всеми вписанными в него настройками и сервисами из контейнера) и роутера (PHP класс, где роуты превращены в код разбора URL на основе preg_match, а также класс генератора URL).
Просто посмотри эти классы в var/cache, это будет лучше любого объяснения. Имена классов вроде devUrlMatcher, devDEbugProjectContainer если я не путаю.
Обрати внимание, что там есть бандлы и компоненты. Компоненты Симфони вроде DI Container - это независимые от фреймворка части, которые можно использовать без него, а бандлы - это именно части фреймворка. Контейнер сделан именно в виде отдельного компонента.
Обрати внимание, что есть твиг - независимый компонент, и есть бандл TwigBundle, часть Симфони, которая интегрирует его в фреймворк. Не путай их.
4) Кеш аннотаций доктрины
Доктрина кеширует аннотации из сущностей в php-файлы (которые затем кешируются в opcache). ПРинцип генерации тот же, на продакшене явно, на dev - автоматически при изменении исходных файлов.
5) Прокси-классы Доктрины
Нужны для реализации ленивой загрузки сущностей из БД. На проде генерируются при прогреве и сохраняются как php файлы, на dev вроде бы генерируются на лету в памяти и не сохраняются.
6) Кеш DQL-запросов Доктрины и кеш метаданных сущностей
DQL-запросы надо конвертировать в SQL, это требует время и потому результат конвертирования кешируется. По моему, в Apc.
Это наверно не все кеши, остальные надо искать разбором кода Симфони.
> и главный вопрос: это вообще можно называть кэшом или это правильнее назвать чем-то типа компилятора из кода фреймворка в raw php-код? Можно назвать кешем.
> У меня есть объекты Event и мэппер EventMapper, в котором есть метод Insert для сохранения одного ивента. Если я хочу сохранить несколько, нужно сделать метод вроде InsertEvents(array $events), или для каждого ивента создавать новый мэппер?
Маппер по логике должен быть в одном экземпляре. Ты либо несколько раз вызываешь Insert, либо делаешь метод InsertMany и вызываешь его один раз.
Вообще, классы часто делят на "сущности", которых может быть много экземпляров и "сервисов", которые существуют в одном экземпляре и не имеют состояния.
> Еще вопрос, а что если ивент содержит вложенные классы Reminder, которые тоже нужно сохранить. Пусть родительский EventMapper проверяет наличие "детей" и сам создает ReminderMapper Маппер точно не должен заниматься созданием других объектов-мапперов, это задача каких-то внешних классов, например, фабрики мапперов:
Фабрику можно внедрить в маппер через DI. Подумай на досуге, почему я не предлагаю вместо фабрики внедрить в маппер сразу DI контейнер.
> Или это забота контроллера, вытащить детей из родителя, и для каждого класса создать соответствующий мэппер? Зависит от выбранного тобой подхода. Кстати, Доктрина все это делает сама.
> Есть соответствующие мэпперы для них. Должен ли родитель проверять наличие детей и создавать мапперы для них Лучше фабрику. Если класс занимается конвертацией в JSON, не его задача создавать другие классы.
Сможешь, но надо изучать все последовательно - если ты сейчас возьмешься за мапперы, то можешь запутаться. Но если тебе хочется глянуть одним глазком, то:
>>1132847 >Фабрику можно внедрить в маппер через DI. Подумай на досуге, почему я не предлагаю вместо фабрики внедрить в маппер сразу DI контейнер. Спасибо, буду думать
>>1132846 огромное спасибо! получается, что это можно назвать кэшем, т.к. кэш - это некий буфер между системой и запросом, но в то же время это и компиляция конфигов с аннотациями и прочим. меня само слово "кэш" и немного смутило, т.к. есть еще symfony/cache, а еще FrameworkBundle\HttpCache
>>1132463 >Тут стоит просто поставить себе образец Symfony приложения (например https://github.com/symfony/demo/ ) и смотреть код, начиная с public/index.php. Я смотрел, но в Get Started ничего не говориться о таком коде. Это же автоматически создается?
допустим есть страничка которая, логирует ипишники пользователей, емли я вставлю эту страничку через айфрейм, на другой сайт, то в итоге будут логировптьмя ип пользователей или ип сайта с айфреймом?
>>1132847 >Вообще, классы часто делят на "сущности", которых может быть много экземпляров и "сервисов", которые существуют в одном экземпляре и не имеют состояния. А свойство с объектом PDO означает, что экземпляр имеет состояние?
>Фабрику можно внедрить в маппер через DI. вот так? $jsonMapper = new JsonMapper($container['JsonMapperFactory']) $dbMapper = new DBMapper($container['DBMapperFactory'])
>внедрить в маппер сразу DI контейнер. $jsonMapper = new JsonMapper($container) а внутри $jsonMapper: $reminderMapper = $this->container['reminderMapper']
>почему я не предлагаю вместо фабрики внедрить в маппер сразу DI контейнер. Наверное потому, что JsonMapper'y не нужно создавать ничего кроме потомков определенного класса, и передача контейнера означала бы передачу большей ответственности, чем необходимо.
DI контейнер, насколько я понял, это более сложная версия фабрики, которая умеет создавать и инициализировать переданные ей объекты вместе с дополнительными параметрами, которые можно легко изменить.
Как правильно делать пагинацию, если есть ассоциации, а надо отобрать 30 основых сущностей со всеми их ассоциациями? Речь о Доктрине. Если я делаю LIMIT 30, то в БД это 30 строк, среди которых может быть только одна главная сущность со всеми своими ассоциациями и вторая с неполным набором ассоциаций?
https://ideone.com/FCtJz7 Подскажите, пожалуйста, если у меня код получился рабочим, но у меня, как я понял, "слишком сложный" код, когда решение может быть гораздо проще. Это сильно плохо?
Почему при добавлении строки $category = $connection->quote($_POST["Category"]); перестаёт работать header("Location:dashboard.php");? Я всё облазил, всё проверил. Вроде всё правильно, но браузер не перенаправляет на нужную страницу, а просто перезагружает текущую без выведения ошибок. Однако, если я удалю строку с connection, то всё работает.
подскажите по симфони еще раз. вот есть два способа показать пользователю страничку с какой-то сущностью:
1 вариант - как в демо приложении симфони: public function showArticle(Article $article): Response { return $this->render('article.html.twig', ['article' => $article]); }
2 вариант (как я сначала написал): public function showArticle(int $id): Response { $repo = $this->getDoctrine()->getRepository(Article::class); $article = $repo->find($id);
if (!$article) { throw new NotFoundHttpException('The article is not found'); }
>>1133245 Что за ошибки? Вот простой и понятный пример использования pdo https://phpdelusions.net/pdo Внимательно изучи и попробуй разобраться что к чему.
>>1132459 >interval это интервал, чаще которого нельзя посылать запросы к одному домену. И в чем его смысл, если этот интервал может истечь до завершения текущего запроса?
>я не сталкивался пока с кодом 203, и никто мне не писал про этов Issues Лол. У меня тут на проекте с посещалкой 4к уников/день месяца два назад, оказывается, отвалилась фича, не покрытая тестами. Багрепорт я получил только вчера. Никто никогда не напишет тебе issue про такие вещи.
>обнаружение припаркованных (то есть потерянных или проданных владельцем) доменов Обходим все ссылки первый раз. Здесь придется проверить глазками, отдают ли ссылки то, что отдавали ранее. Пишем таймстамп последней проверки, пишем eTag, если имеется, Last-Modified, если имеется, Content-Length, если имеется. Делаем запрос whois, записываем expire-date. Алгоритм последующих проверок: Отправляем запрос с Etag / If-Modified-Since. Получаем 304? Ссылка живая. Делаем запрос. Content-Length прежний? Ссылка живая. Expire-date < now? Делаем запрос в whois. Домен перерегистрирован? Подозрительность ссылки +1. Днс поменялись на днс из словаря доменных парковок? Подозрительность ссылки +1. На странице присутствуют вхождения $domainParkingMarkers = ['parking', 'for sale', 'domain owner']? Подозрительность ссылки +1. site.com/dsfjklsjfklsjdf отдавало 404, а теперь отдает 200, и Content-Length плюс-минус одинаков на любой странице? Подозрительность ссылки +1. Ответы в твоем же вопросе.
>Другая проблема - некоторые домены не любят ботов (а я честно подписываю User-Agent) Если 403, либо редирект на локалхост, делаешь второй запрос с юзер-агентом браузера. А вообще веб должен быть доступен для любого клиента, поэтому можешь слать к черту такие ссылки. Btw, если ты претендуешь на честность, тебе нужно уважать robots.txt.
>Третья проблема - проверка ссылок вроде mega.nz/#12345 Ну да, здесь придется писать правила. Btw, ргхост отдает мне 404.
>Надеюсь, что Гузл это сам обработает Проблемы черных ящиков.
>Странно, мне кажется, что обязательно >Можешь дать пример страницы, где есть 3xx но это не редирект? Пожалуйста. Запусти да проверь. https://pastebin.com/VAmaBpLQ Ты увидишь "Есть два стула". Редиректа не произойдет. А еще 304 не редирект. А еще 305 deprecated. А еще 306 зарезервирован. А еще все коды, начиная с 309. Ты обязан игнорировать Location у таких кодов. Итого, безусловных редиректов пять - 301, 302, 303, 307, 308. А у тебя - сотня.
>Ну и как я понимаю, большинство браузеров отредиректит пользователя Неправильно понимаешь, не отредиректит. Ты споришь со мной, хотя можешь открыть первую ссылку в гугле и почитать RFC. https://tools.ietf.org/html/rfc7231#section-6.4.1 > The user agent MAY use the Location field value for automatic redirection. > MAY
>> Сервер не обязан отсылать Content-Type. >Не уверен. А RFC уверен. https://tools.ietf.org/html/rfc7231#section-3.1.1.5 > A sender that generates a message containing a payload body SHOULD > generate a Content-Type header field in that message unless the > intended media type of the enclosed representation is unknown to the > sender. If a Content-Type header field is not present, the recipient > MAY either assume a media type of "application/octet-stream" > ([RFC2046], Section 4.5.1) or examine the data to determine its type. Напомню, что SHOULD это не MUST. Должен, но не обязан. Юзер-агент может посмотреть данные, чтобы определить тип.
>Мне не пришлось писать свой HTTP клиент file_get_contents >объекты для представления HTTP запросов и ответов Для запросов из коробки stream context. Для ответов обертка хидеров и контента пишется за 5 минут. >Не пришлось изучать кучу тонкостей, про которые ты написал (про 203 я например не знал) Одну секунду, причем тут 203? Газл тебе возвращает ответ, а дальше, чем делать с этими кодами - твой геморрой. Газл тебя от этого не избавляет. >4 строчки про то, зачем писать HTTP-клиент Действительно зачем, если есть file_get_contents, который даже из коробки, мать его, через stream notification callback может рассказать тебе о переадресациях согласно RFC, и так же из коробки ты можешь запретить ходить по переадресациям. Но лучше я возьму Газл, он лучше, и напишу свой велосипед, предполагая, что все 3хх коды - переадресации. Вместо использования того, что решает задачу из коробки! Ты не поверишь, можно даже подписаться на STREAM_NOTIFY_MIME_TYPE_IS! В момент получения Content-Type сработает твой коллбэк! Из коробки!
В итоге я только укрепляюсь во мнении, что ты бездумно используешь черные ящики лишь потому, что тебе лень разобраться в протоколе, который общается обычным ASCII-текстом.
>>1132460 >недружелюбно по отношению к серверу Лол! Серьезно?! TCP вообще похуй, когда ты закроешь сокет. Закрыл, досвидос. Ах да, если ты не знал, сервер обязан выполнить все те же действия при запросе HEAD, что и при запросе GET. Даже сходить куда-нибудь в MySQL-базу за океан. Потому что код не знает, вдруг, если в базе небо == аллаху, то где-то дальше добавится заголовок X-Allah: Bicycle. А вот контента ты не получишь. Представляешь как недружелюблюбно?
>тут для Guzzle 6 >можно костылем передать нужные опции для curl Лол, да что ж тебя на подвиги-то тянет. Из коробки (повторяю - из ко-роб-ки!) можно открыть сокет, функцией stream_get_meta_data прочитать только хидеры и исключительно хидеры, и закрыть сокет! Из коробки! Три строчки кода! fopen, stream_get_meta_data, fclose!
>>1132462 >Нет, чтобы получить просто заголовки, тебе придется писать код, чтобы добавить таймаут, еще какой-то код и так далее. Это уже не смешно. Вы чего, стандартную либу не знаете? Три строки кода, три! fopen, stream_get_meta_data, fclose! Таймаут задается параметром в stream context! >он умеет делать так: http://example.com/a/b + ../file.txt = http://example.com/file.txt Да ладно! if (strpos($href, '/') !== 0) { $url = realpath(dirname('http://example.com/a/b') . '/' . $url); } else { // да, для абсолютного пути придется пересобрать хост через parse_url с учетом возможного порта и даже логина-пароля } Минута программирования. Нет, надо подтянуть библиотеку.
Кстати, спешу огорчить. Есть тег <base>, который переопределяет, от какой директории строить url. Твой скрипт это учитывает? А может, учитывает Газл? Ой нет, он просто по ссылочкам ходит. Что же делать? Нужно срочно искать библиотеку!
> Не вижу в чем выгода тратить время на переизобретение того, что уже написано. Изобретение чего? Конкатенации директорий? Тебе нужен jQuery, чтобы сложить 2 + 2?
>И что я теряю, используя готовую библиотеку. Если в готовой библиотеке находится уязвимость, тоби пизда. У тебя тоже могут быть уязвимости, но здесь работает теория неуловимого Джо - ты никому не нужен.
Вы просто клепаете веб-приложушки из готовых модулей, а за моими плечами база. Мои абстракции - это голый PHP, ваши - библиотечки, чтобы склеивать директории. Если мне дать микроволновку, где будет крутиться Java Micro Edition и в либе только сокеты, я смогу сделать http-реквест и получить ответ, а вы не сможете ничего.
Также, вы можете щелкнуть правой кнопкой по полю поиска там, выбрать "добавить как поисковую систему", задать ключевое слово и открывать подсказку прямо из адресной строки браузера.
>>1133266 Не понял смысл этого сайта. Там же просто выводится строка из справки. Не проще ли и не полезней, раз уж вы ИЗУЧАЕТЕ линукс, читать справку по программе programma_name --help?
> И в чем его смысл, если этот интервал может истечь до завершения текущего запроса? Смысл в том, чтобы не перегружать сторонний сервер запросами и тем самым снизить вероятность получения бана моего бота. Я хочу, чтобы запросы к определенному домену отправлялись бы не чаще, чем раз в N (сейчас N=3) секунд, если интервал будет больше - ничего страшного.
По факту, это да, интервал не между окончанием одного запроса и началом следующего, а между началом одного и второго. Пусть пока так будет.
> Никто никогда не напишет тебе issue про такие вещи Значит, это никого не беспокоит.
> таймстамп последней проверки, пишем eTag, если имеется Это будет вызывать ложные срабатывания, особенно если контент динамический и last modified нету или он постоянно увеличивается. Content-length будет меняться при изменении где-то в шапке, сайдбаре и тд.
У меня кстати была мысль интереснее: многие припаркованные домены подгружают ссылки через JS и их можно детектирвоать по отсутствию (или маленькому количеству) текста в HTML.
Про whois - да, вариант, хотя это требует подключать стороннюю библиотеку и разбираться с протоколом whois.
> Домен перерегистрирован? Подозрительность ссылки +1. Это надо где-то держать историю проверок домена. Это снижает автономность инструмента.
> Днс поменялись на днс из словаря доменных парковок? Подозрительность ссылки +1. Согласен, это можно.
> site.com/dsfjklsjfklsjdf отдавало 404, а теперь отдает 200, и Content-Length плюс-минус одинаков на любой странице? Да, это тоже рабочий вариант, только не хочется слать запросы подряд на все домены, это надо как-то сначала отобрать "подозрительные" ссылки и их уже тщательнее проверять.
> А вообще веб должен быть доступен для любого клиента, поэтому можешь слать к черту такие ссылки Не, я не хочу прикидываться браузером. Да и тот же cloudflare все равно не пропустит браузер без JS.
> Btw, если ты претендуешь на честность, тебе нужно уважать robots.txt. Есть в TODO.
> Пожалуйста. Запусти да проверь. > https://pastebin.com/VAmaBpLQ > Ты увидишь "Есть два стула". Это интересно, но я пока с такой проблемой все равно не сталкивался. Так да, можно повнимательнее разобрать 3xx коды.
> Из коробки! Три строчки кода! fopen, stream_get_meta_data, fclose! А где объекты Response? Где разбор заголовков? Где задание корневых SSL-сертификатов? В Guzzle я просто пишу $response->getHeader() или $response->getStatusCode(), корневые сертификаты получаю другой библиотекой.
Ты бы код Гуззле открыл и посмотрел, что там понаписано. Она конечно местами переусложненная, но свои задачи решает, так что я не против.
> стандартную либу не знаете? Она такая страшная, что к ней подходить лишний раз не хочется. И к тому же в исключения не умеет.
>>он умеет делать так: http://example.com/a/b + ../file.txt = http://example.com/file.txt > Да ладно! > if (strpos($href, '/') !== 0) { $url = realpath(dirname('http://example.com/a/b') . '/' . $url); } else { // да, для абсолютного пути придется пересобрать хост через parse_url с учетом возможного порта и даже логина-пароля }
Ну то есть надо изучать RFC про относительные ссылки и писать код. А я могу взять готовый код и ничего не писать. Какая мне выгода выбрать первый вариант? У меня есть вполне конкретные аргументы:
- экономия времени на написании кода и комментариев/документации к нему - надежда, что код в библиотеке протестирован (в случае с Guzzle, у них есть тесты и подключен CI сервер, проверяющий коммиты) - надежда, что сообщество будет править баги, закрывать уязвимости и поддерживать библилотеку. Я ничего не делаю, а баги исправляются. Разве это не прекрасно?
А завтра мне может понадобится параллельная отправка запросов (которая вроде как есть в Гуззл), это мне тоже все самому написать?
Какие у тебя есть аргументы за написание велосипеда? Не из серии "мне не нравится" или "надо RFC изучать", а объективные преимущества написания своего велосипеда в данном случае? Что я выигрываю?
> Если в готовой библиотеке находится уязвимость То может быть, ее исправят без меня.
> Вы просто клепаете веб-приложушки из готовых модулей, а за моими плечами база. У меня просто ограниченное количество времени.
> Если мне дать микроволновку, где будет крутиться Java Micro Edition и в либе только сокеты, я смогу сделать http-реквест и получить ответ, а вы не сможете ничего. Я смогу, но не понимаю, зачем мне это нужно.
Вот кстати, я сейчас несколько часов угробил, пытаясь запустить firefox 3.5.19 под xvfb (он падает на старте скорее всего из-за современной версии glib), вот тебе бы, как любителю во всем разбираться, наверно было бы интересно исследовать проблему? Я конечно подумываю просто попрбовать еще другие версии фаерфокса. Или найти способ поставить как-то ему старый glib.
Там все настолько плохо, что даже отладочные символы для этой старой версии непонятно где искать. gdb малополезен, нужно разбираться с breakpad (или брать где-то Visual Studio, хотя дампы линуксовые), причем новый, естественно, не читает старые дампы, а старый еще замучаешься собирать. Про менеджеры пакетов сишники и не слышали (по задумке, надо использовать apt-get, но попробуй им поставь старую версию библиотеки или что-то, чего нет в репозитории). Ох, как просто с PHP работать в сравнении с этим сишно-яваскриптовым монстром.
У тебя переусложнен код поиска элемента в массиве. ЧТобы найти значение элемента, имея ключ, надо сделать так: $value = $array[$key], цикл городить не надо.
Но я ему не довряю, так как боюсь, что он там нагородит что-то сложное. Проще просто выбирать нужные тебе сущности без джойнов (то есть вместо SELECT x, y просто писать SELECT x). Да, там написано, что с джойном оно должно выбираться быстрее, но ты померяй - я наблюдал ровно обратную ситуацию.
Если тебе не нужны полные сущности (а например только id), то проще вообще SQL запрос сделать.
> А свойство с объектом PDO означает, что экземпляр имеет состояние? нет, это не мешает ему быть "сервисом".
> >Фабрику можно внедрить в маппер через DI. > вот так? Нет, тогда уж так
$dbMapperFactory = new DBMapper($container['DBMapperFactory']);
>> почему я не предлагаю вместо фабрики внедрить в маппер сразу DI контейнер. > Наверное потому, что JsonMapper'y не нужно создавать ничего кроме потомков определенного класса, и передача контейнера означала бы передачу большей ответственности, чем необходимо. Да, и вообще, это нарушение идеи DI container, так как объекты о контейнере знать ничего не должны и не должны от него зависеть.
Я думаю, можно просто посмотреть инструкции по установке в symfony-demo, скорее всего надо просто запустить композер и может что-то в конфиге подправить. Ну если ставить обычный шаблон (как тут http://symfony.com/doc/current/setup.html ) то примерно то же получишь. Я думаю, там тоже будет public/index.php и примерно те же классы.
>>1125519 У меня случился отпуск. Хочу походить по собеседованиям. Но для этого, для начала, нужно откликнуться на вакансии. Вопрос: с моим уровнем (за полтора года смог немного выучить html, css, js, php, yii, mysql, git) можно откликаться только на самые днищевакансии стажёров, или уже можно чуть повыше? Какой примерно должна быть адекватная вакансия по требованиям и условиям?
>>1133624 походи по собесам, поймешь что нужно будет подучить. я бы пошел на 60к посмотрел (в дс), если совсем не потянешь, то снижать планку. плюс определись, какие технологии тебе интересны и не разбрасывайся на остальные (очевидно в твоем случае это yii).
по проекту, по моему опыту такие проекты на собеседованиях никто особо не смотрят, может поставят галочку в голове типа "учится-интересуется", но вообще всем похуй. еще вариант: могут ткнуть в случайное место, увидеть какой-то один косяк и сделать по нему преждевременные выводы.
если будешь показывать этот проект, удали все ненужные комментарии в коде, их там больше половины от всего проекта. все "было-стало" видно по коммитам, такие комменты бессмысленны. также в качестве коммит-меседжей пишут "добавил штуку такую-то", а не номер версии. еще отформатируй ридми, в одной строке текст и картинка не комильфо.
>>1133631 >scrinshots => screenshots Исправил. >>1133644 >"было-стало" видно по коммитам, такие комменты бессмысленны Это где такие комменты? Хотя, наверное есть. Завтра на свежую голову всё прогляжу и удалю лишнее. >в качестве коммит-меседжей пишут "добавил штуку такую-то", а не номер версии Ты прав, надо будет начать писать более содержательные месседжи. >еще отформатируй ридми Отформатировал. >я бы пошел на 60к Окей, от этой цифры и буду отталкиваться.
>>1133624 Откликайся на всё. Я без опыта откликнулся на вакансию на 70к, написал тест, мне еще сказали, что по результатам я опытный мидл, лол. Приняли без вопросов. Единственно, что я все-таки полупридумал предыдущее место работы. Два года назад написал сайт для организации, прямо как ты, и написал - опыт работы два года, ООО Ромашка.
>>1133666 >опыт работы два года >>1133631 >"английский на уровне понимания документации" под вопросом. Откуда вы это взяли? Я ведь оставлял только гитхаб, а не резюме на хх? Там именно это и написано, но ссылку же не оставлял, откуда ни знают?!
>>1133669 >Там именно это и написано Осторожнее с этим дерьмом. У меня было указано то же самое. И мне дали тест на английском. А когда приняли, посадили на мультиязычный проект, где надо писать все строковые литералы на русском, и на английском. Пишу на ломаном английском, тимлид пока не доебывается.
>>1133673 Дословно там стоит галочка на "Английский — читаю профессиональную литературу". И это правда. Читать-то я могу. А вот писать... >>1133698 Что там не так? Если там прям бомба, то может напишешь мне но почту [email protected] о ней?
>>1133713 там ничего секретного, просто ОЧЕНЬ много комментариев вида #$arr1 = 22; //$arr2 - вчера работало
и прочего. на работе твой код будет проверяться по строчке и по символу (если ты не будешь работать в дизайн-студии, конечно). если есть кодстайл, то по нему ебут даже за переводы строк в неправильных местах. так что учитывай, что это будут смотреть такие вот чуваки.
для джуна это все конечно придирки, но и возможность заработать плюсик
>>1133764 Уф, анон, ты даже не представляешь, на какую измену я подсел. Думал уже, в репу пробралось что-то из продакшен-версии. А там реальные фамилии, названия фирм заказчиков и прочая ботва. И вроде все данные в базе были, но а вдруг...
Надо и вправду причесать всё хоть как-то. Когда один пишешь, все эти комменты таки помогают. Хотя бы уже тем, что можешь быстро вспомнить, где какие косяки. Но для показа, лучше будет хотя бы создать видимость, что с этим можно работать коллегиально.
>>1133770 это не значит, что ничего не просочилось. просто я посмотрел три класса и там везде было вот такое. при твоем вольном отношении к коду возможно, что где-то лежит >//Кротов Сергей 4500 224331 перезвонить по телефону 3215411
надо разок так обосраться, чтобы потом поменять отношение. я когда первый аудит проходил, вообще не понимал нахуй он нужен - у меня же все нормально! оказалось, я похерил все, что можно было похерить.
Мой очередной нубский вопрос про предназначение middleware. Сейчас делаю задачку на файлообменник на слиме и думаю, как лучше проверять файлы, приходящие из формы. Создавать класс-валидатор, который будет смотреть сколько файлов было отправлено, их размер и т.д. , или все это через middleware можно сделать?
Есть шаблон сайта, который юзает контора. CMS нужно указать, где находится папка core от корня.
Как мы делаем: закидываем файл с выводом результата команды <? __DIR__; ?> в public_html и потом дописываем до конца.
Короч, если ты не понял, что я несу, то сам вопрос таков: Есть ли какая-то встроенная функция, чтобы от результата __DIR__ можно было отрезать часть пути с конца?
Осваиваю WordPress, хочу разобраться с правильным редактированием тем (то есть, через дочерние темы), чтобы изменения не слетали при обновлении темы. Но вот какая беда: не могу найти старую версию какой-нибудь темы, которая предложила бы мне обновиться. Скачал с гита Chronus Версия: 1.1, WP через каталог предлагает установить 1.2.3, но при этом предложения обновиться нет.
ЧЯДНТ? Скиньте мне, пожалуйста, какую-нибудь тему, которая желала бы обновиться, чтобы я смог изучить этот вопрос.
Если ты чувствуешь, что не до конца разобрался в какой-то теме, можно попросить усложненную задачку, чтобы ты мог убедиться, что ты с ней справишься и не беспокоиться.
Друзья, подскажите, что можно почитать по теме распарсивания выражений типа "(((ID = 14) OR ((COUNTRY = USA) AND (ID < 4)))" в исполняемый код.
Имеется в виду как правильно распарсить вложенные скобки, преобразовать в простые логические условия, провалидировать в корректном ли порядке они идут и т.д.
Пользовался кто AWS? Жалко платить за платные VPN, думаю арендовать AWS и поднять там на докере OpenVPN + ещё для всяких тестов будет тачка практически личная. Из минусов - стремаюсь на свою карточку регать аккаунт после статьи https://geektimes.ru/post/247794/ , что скажете?
Я увидел, что там используется KnpPagination, описание у него подозрительное, решил посмотреть его код и как чувствовал - нашел сомнительное место (использование $_GET):
А что там подозрительного? А подозрительно то, что они в ридми в примере кода указывают на возможность сортировки, но 1) нигде не передаются параметры сортировки и 2) белый список полей: https://github.com/KnpLabs/KnpPaginatorBundle
То, что параметр сортировки не передается из Request - значит, они сами откуда-то его берут (из $_GET в данном случае). Если не задан белый список полей - значит, что это может создать уязвимость, позволяющую злоумышленнику угадывать значеия скрытых полей в таблице.
Поясню. Допустим, у нас на сайте есть список пользователей с возможностью сортировки, и мы можем делать сортировку по любому полю. Допустим, мы хотим узнать email пользователя, который не выводится на сайте. Мы регистрируем аккаунты [email protected], [email protected], [email protected] и используя сортировку списка по email, определяем, в каком диапазоне (a-n или n-z) лежит первая буква списка. Затем сужаем диапазон и так примерно за сотню-две попыток получаем нужный email.
Разумеется, этот же принцип можно применить для подбора значения любого другого скрытого поля, включая хеш пароля, если нам известен механизм хеширования. Если он не известен, можно подбирать какой-нибудт токен или что-нибудь еще.
То есть сортировка без белого списка полей, если она там включена по умолчанию - это уязвимость.
https://github.com/TheSidSpears/test_hub/blob/master/templates/tags/list.html.twig#L28 > {% if tags.getTotalItemCount == 1 %} > {% set tagWithSuffix = 'tag' %} Может тебе посмотреть в расширения для локализации? Там должен быть синтаксис для форматирования строк с учетом особенностей языка. Например, в расширении Intl используется такой немного громоздкий синтаксис:
>"{num_guests, plural, offset:1 " > "=0 {{host} does not give a party.}" > "=1 {{host} invites {guest} to her party.}" > "=2 {{host} invites {guest} and one other person to her party.}" > "other {{host} invites {guest} and # other people to her party.}}}"
903 килобайта JS в build/app.js - не слишком ли много?
Это зависит от того, как ты настроишь. В контейнере может быть много процессов.
> Или посоветуйте что-то для быстрого деплоя/развертывания одного проекта на N-нод Деплой PHP кода или деплой нгинксов? Второе можно поручить админу, для первого использовать ansible.
Ты не написал, какой командой ты пытаешься ее создавать, что пишет эта команда. По идее конечно должно работать и с аннотациями. Также, не забыл ли ты правильно указать use при использовании аннотаций? Он иведь тоже в неймспейсах находятся.
PDO занимается только соединением с БД и отправкой в нее запросов. Надо дописать свой код, который будет брать полученные из формы данные и формировать на их основе SQL запрос.
Нужен супервизор, который будет перезапускать скрипт при падении. Ловить исключение и перезапускать функцию - плохая идея, так как состояние программы может быть неправильным и будет накапливаться ошибки.
Я не очень разбираюсь в диаграммах, но мне кажется, у тебя ошибка. Ты используешь ER диаграмму в нотации crow's foot (кроме нее есть еще другие способы обозначать отношения: https://en.wikipedia.org/wiki/Entity%E2%80%93relationship_model#Cardinalities ). На ней мы отображаем сущности и связи между ними. bridge - это не сущность, это промежуточная таблица, которая нужна для реализации связи многие-ко-многим в SQL.
Можно было бы в setRank() поставить защиту от установки неправильного ранга с выбрасыванием исключения (если ранг < 1 или > 3).
Давай, ради расширения кругозора, ты попробуешь сделать максимально параноидальный код, который проверяет все параметры на разумность. Ну например, чтобы нельзя было попытаться выставить отрицательную зарплату или удалить работника, который не работает в этом департаменте.
Это поможет тебе увидеть, как ООП и инкапсуляция (закрытие доступа к полям извне) позволяют сделать защищенный от ошибок код, который в любой ситуации работает корректно, даже при попытке подать на вход некорреткные данные.
Говоря о корретности программы, есть еще один интересный подход - Value Objects. Суть его в том, что мы могли бы для отдельных значений в нашей программе вроде ранга создать классы - класс Rank, который оборачивает число (то есть это класс с единственным неизменяемым приватным полем rank, которое задается в конструкторе. Он должен быть неизменным после создания). В чем плюс?
- мы можем гарантировать корректность значения. Например, прямо в конструкторе Rank поставить проверку, что он должен быть от 1 до 3 и не позволять создавать некорректный ранг. В этом случае, если у нас есть объект Rank, то это значит, что ранг в нем 100% корректный. - мы можем задать допустимый набор действий с значением с помощью методов. Ну например, мы можем не выдавать ранг как число наружу, а сделать только методы вроде $rank->isEqual(1) и $rank->increase(2) и тем самым запретить перемножать ранги (с обычным числом по ошибке это можно сделать). При изменении ранга через методы мы можем предоставратить получение неправильных значений (повысить 3-й ранг до 4-го) - мы можем ставить тайп-хинты и писать например setRank(Rank $rank) и это не позволит передать в функцию что-то, кроме ранга (зарплату например). В случае int $rank такой защиты нет. Также такие тайп-хинты делают код еще понятнее. - мы можем защищаться от ошибок, связанных с единицами измерения. Если у нас время выражено числом, то в чем оно измеряется? В часах, минутах, секундах, миллисекундах? Если длина, то в метрах или футах? Если момент времени, то в каком часовом поясе? В случае с ValueObject единица измерения известна и мы можем сделать методы $time->getAsSeconds(), $time->getAsHours(), защищая себя от ошибок при ручной конвертации. - мы можем делать полезные вспомогательные методы, например, для времени мы можем сделать метод $time->diff($otherTime), вычисляющий разницу между 2 точками во времени.
В чем минус?
- сильно раздувается объем кода
Иммутабельность нужна, чтобы защититься от ошибок, когда мы меняем использующийся в нескольких местах объект.
Может, ты захочешь тут применить этот паттерн. Он обычно применяется для простых знаечний вроде Денег, Времени, Точек (координат), Цветов. В PHP есть классы DateTimeImmutable и DateImmutable.
> public function getWorker(int $key): AbstractWorker > public function deleteWorker(int $key): void Это не очень удачные методы, так как непонятно, где брать этот key. У работника ведь нет метода getKey(). Но он и не нужен - работник сам по себе имеет идентичность и можно просто передавать объект в deleteWorker.
> public function selectWorkers(string $profession): array Не хочешь подумать над универсальной функцией поиска по произвольным критериям?
> $workersOfCertainProfession = array(); Можно просто $result.
> public function changeBoss(int $oldBoss, int $newBoss) Та же проблема. Передаются какие-то непонятные инты, которые непонятно где брать.
> class HiringWorkers Этот класс мог бы хранить в себе (или принимать через конструктор) базовые значения зарплат, чтобы не дублировать их многократно.
> $department->selectWorkers("Engineer"); Лучше Engineer::class
Сортировка пузырьком??? Во-первых, ее надо выносить в отдельный метод (чтобы не ухудшать читабельность кода и не раздувать функцию), во-вторых, используй usort с анонимной функцией.
> ceil(count($workersOfCertainProfession) / 2.5)); В задании было написано 40%, а ты заменил его на 2.5, в итоге я секунд 10 думал, откуда тут эта цифра. Лучше было умножать на 0.4 или на $engineerCutPercent.
Цикл удаления переусложнен из-за того, что твой код требует определить key работника, а это просто не сделать. Код мог бы быть проще и короче.
> changeDataAnalytics Тут отбор аналитиков можно было сделать функцией. Также, функцию смены босса можно было спроектирвоать более удачно и код был бы проще и аккуратнее. Попробуй написать прототип (заголовок) функции замены босса, не думая о том, как устроен Департамент внутри и как там хранятся работники. Как бы ты ее записал?
> $worker->setRank($worker->getRank()+1); Возможно, есть смысл сделать метод повышения работника.
В общем, для упрощения антикризисного кода я бы советовал улучшить:
> свойства, которое хранится как массив, а в БД как json. Это надо делать не в форме, это надо делать в Доктрине. В ней создаешь свой кастомный тип данных, ставишь его полю и пишешь, как преобразовывать значения поля при загрузке/записи в БД. Может даже такой тип уже написан кем-то.
Но конечно я бы тут применил ООП и сделал массив объектов Property. В этом случае может быть это даже работало бы с CollectionType без преобразований.
Что касается форм, то да, Data Transformer тут бы подошел. Либо можно написать свой FormType для работы с таким типом данных.
Не знаю, в чем проблема. А что, если открыть страницу в браузере, потом открыть ее исходный HTML код (меню или Ctrl + U) и сравнить с первоначальным HTML?
Можно попробовать выставить какие-то агрессивные параметры кеширования для страницы и ресурсов к ней - тогда браузер сможет открыть ее из кеша, если она там будет лежать. Но это не гарантированно.
> В этом файле стандартные переменные APP_ENV и DATABASE_URL. Зачем их переименовывать и как их система прочтет? (в этом разобраться самому) ну я предлагал добавить префиксы, чтобы было видно, от какого приложения эти переменные и чтобы они не конфликтоваи с другими. Может, и не стоит заморачиваться конечно.
> Нужно тестировать репозитории на копии основной БД? А как держать эту БД актуальной? Это ж нужно миграции и там и там проводить. Как-то не удобным это кажется
В идеале - тестовая БД, которая заполняется перед тестами. Миграции руками проводить не надо, надо все автоматизировать.
Да, это сложновато, ну а как без этого тестировать код, завязанный на БД? Не делать же полноценную эмуляцию всей SQL-базы данных. Ну и без этого тебе ведь руками все тестировать придется.
Это ты еще до браузерного тестирования и селениума не дошел, там еще сложнее.
> Нет, эти 2 ф-ии используются исключительно для заполнения Fixtures Тогда ок.
Например, $repo->findBy(['tag' => $tags]) или findByTag($tags) и посмогтреть что он найдет и какой SQL запрос сформирует.
> В нём определяется какой-то persister Судя по названию, это объект для сохранения (persist) сущностей в БД.
> Видим, что класс зависит от `InheritanceType`. Названия классов намекают, будет ли проходить поиск по конкретной таблице или по объединенной (joined) Да, это для разных вариантов наследования таблиц вроде http://design-pattern.ru/patterns/class-table-inheritance.html .
>> Вот это мне не нравится. У тебя переменная может быть передана, а может не быть. Как писать надежный код в такой ситуации?
> А как быть то? Передавать isMainRoute во всех контроллерах избыточно, а как-то определять, что "вид вызван из MainController" надо
Тут надо подумать логически. Вот у нас есть серединка страницы, которая разная и формируется контроллерам, а есть шапка/меню/подвал/сайдбар (лейуат), которые везде одинаковые. Но им тоже нужны данные. Надо искать варианты, например:
- сделать отдельный "контроллер" (или контроллеры) для сбора данных для лейаута. Или оформить их как "виджеты". - добавить свои переменные в {{ app }} - добавить глобальные переменные в твиг - сделать, чтобы эти части вызывали какие-то функции или методы и получали нужные им данные - внедриться в событие, которое срабатывает до запуска контроллера и куда-нибудь что-нибудь передает - сделать наследование контроллера и формировать данные для шапки в базовом контроллере
> использовать синтаксис для переводимых строк? Это как? Смотри например класс MessageFormatter в расширении Intl, смотри средства локализации в Симфони:
>"{num_guests, plural, offset:1 " > "=0 {{host} does not give a party.}" > "=1 {{host} invites {guest} to her party.}" > "=2 {{host} invites {guest} and one other person to her party.}" > "other {{host} invites {guest} and # other people to her party.}}}"
>> Почему пагинатор передается в аргументы метода контроллера? Это такой DI? > Как я понял, нужно в конструкторе его определять? Не, наверно надо оставить DI. Тут нет проблемы, я ошибся.
>> А зачем else? > При переходе на следующую страницу, условие $form->isSubmitted() уже не выполняется, поэтому я беру $searchString из get-параметра Это какой-то косяк в твоем использовании формы. Если форма GET, то она дложна брать данные из GET.
Можно просто циклом foreach пройти по массиву и по очереди каждый элемент поменять. Если не пытаться проверить все телефоны за 1 заход, то будет проще.
>>Ключом в event_type наверно лучше сделать id. Он меньше места занимает. > А если в таблице появится поле owner_user_id, то ключом можно сделать сочетание type и owner_user_id? Или id будет удобнее? Можно использовать любой вариант.
> Если периодичность перенести в таблицу Events, то это поле будет или дублироваться или придется каждый раз указывать периодичность. Насколько приемлемо дублирование, нужно выбрать то, которое будет приоритетное?
Наверно, тогда лучше назвать поле в Event_type is_annual_by_default, и использовать его только для начального значения в галочке. Дублирования не будет.
AWS недешевый. Подозреваю, что если и есть бесплатный тариф, он с какими-то подвохами. Не вариант завести виртуальную карточку от того же qiwi или яндекс-денег? Они правда могут ее не принять, DO например не принимает.
Для дешевых VPS есть poiskvps.ru, но там в основном сервисы с русскими или СНГ-шными корнями.
Также, открою секрет за 1 евро в мес. можно у арубы арендовать.
Конец тредаАноним08/02/18 Чтв 23:44:34#835№1135058
Этот тред закрыт. Переходите в новый тред >>1135053 (OP)
Если я кому-то не ответил, напомните, пожалуйста, о себе в новом треде.
> Ошибку выдает такую: String could not be parsed as XML. Как и что тогда передавать итератору? Ты уверен, что ошибка на строке с итератором, а не на строке simplexml_load_file? Скорее всего там просто некорретный XML, можно проверить его валидатором XML, например, тут: https://www.xmlvalidation.com/ или в любом другом.
У каждого треда можно определить время последнего поста в нем (lastBumpDate). Если отсортировать треды по убыванию этого времени, то получится как раз то, что нужно.
А дальше уже идут нюансы. Например, бамп лимит - если в треде более 500 постов, то при расчете lastBumpDate берется время 500-го поста, а не последнего. Закрепленные треды - идут всегда раньше, чем незакрепленные.
Ты знаком с SQL? Это там не так сложно сделать.
Архивирование делается примерно так: раз в час, минуту, сутки или как-то еще запускаем скрипт, который сортирует треды и находит те, что находятся ниже определенной позиции. Они архивируются. Это может быть как просто добавление пометки в таблицу, так и перемещение в отдельную таблицу (чтобы основная таблица оставалась маленькой и быстрее работала).
При проектировании лучше всего сначала спроектирвоать БД в нормализованном виде. Позже для оптимизации допустимо применить денормализацию, то есть дублирование данных.
> что значит поле bump Где ты увидел это поле? В каком-то уроке или в каком-то движке?
Реквестирую гайд по пхп для не новичка в программировании. Чтобы не поясняли 5 минут что такое переменная, а сразу к сути. Желательно видосик, хотя врядли такое существуют.
Пожалуйста, пишите один большой пост вместо нескольких маленьких и не флудите не по теме.
Это тред для начинающих. Не написал за свою жизнь ни одной программы и имеешь тройку по математике? Ты наш человек.
Предыдущий тред был тут: . Остальные треды есть в архиве: https://phpclub.tech/ или ищутся в гугле по словам "клуб изучающих php" и в архиваче.
Мейлач лежит? Есть запасной тред на доброчане: /s/res/23225.xhtml#i46467
Что самое главное для программиста? Умение аккуратно оформлять код (как, написано во втором посте).
Правила: ведем себя воспитанно, помогаем новичкам, читаем учебники, решаем задачки, постим ссылки на решения, ОП их проверяет и дает советы и замечания. ОП заходит редко, где-то раз в 2-3 дня, у него мало времени, не жди его, решай задачки дальше. ОП отвечает на все вопросы по его задачкам и учебнику, а вот насчет каких-то других вещей - только если останется время. Но в треде немало анонимных экспертов разного уровня, так что вряд ли вопрос останется без ответа.
С чего начать
У нас есть свои уроки по основам PHP, они собраны и выложены по адресу http://archive-ipq-co.narod.ru/ Это учебник для изучающих с нуля, то есть если ты вообще ничего не знаешь, то можно начать с него. Он простой и понятный. Там есть задачи, их нужно решать (чтобы стать программистом, надо писать код — иначе никак). Пости ссылки на решения в тред, мы их проверим, напишем замечания и дадим советы по улучшению. С другой стороны, если этот учебник тебе не нравится, можно читать любой другой. Или официальный мануал. Или все сразу.
Устанавливать пока что ничего не требуется, разве что редактор кода вроде Sublime Text 3, Notepad++, Visual Studio Code, Netbeans PHP или PhpStorm (с ним будет удобнее).
Если не знаешь как решать, запости код, напиши в каком месте остановился и попроси подсказку.
Ты прошел весь учебник? Молодец, но это были лишь основы языка PHP, этого недостаточно. Вот что в идеале надо изучить еще: ООП, как работает веб-сервер, HTML/CSS, SQL, PDO, работа с таблицами в БД, работа с формами, MVC, git, composer, JS, фреймворки, автоматизированное тестирование.
Надо переходить к более серьезным задачкам, которые научат тебя всему этому.
- для начала прочти урок https://github.com/codedokode/pasta/blob/master/soft/web-server.md
- установи Апач + PHP (советы выше и ниже) и читай туториал http://php.net/manual/ru/tutorial.php
- Учи HTML/CSS и SQL, PDO, хотя бы основы
- Далее простая, но полезная задача сделать список студентов, в ней много полезных советов: https://github.com/codedokode/pasta/blob/master/student-list.md
- Более сложная задача сделать файлообменник на микрофреймворке Slim: https://gist.github.com/codedokode/9424217
- Еще более сложная и долгая задача на Yii/Symfony: https://gist.github.com/codedokode/8733007
- После нее можно изучать автоматизированное тестирование https://gist.github.com/codedokode/a455bde7d0748c0a351a
- Если ты все решил, переходи к Symfony 3/Doctrine 2
- Почитать про паттерны http://designpatternsphp.readthedocs.org/ru/latest/README.html (если ты не изучил ни одного фреймворка, то это будет рановато), тут с примерами кода http://designpatternsphp.readthedocs.org/ru/latest/README.html . Имей в виду что без примеров использования их учить бесполезно - не поймешь, хочешь увидеть примеры использования паттернов - ковыряй исходники Симфони, например Symfony Forms. Не заучивай паттерны - смотри код и думай, зачем тут они использованы.
Чтобы делать эти задания, тебе надо установить Апач + PHP (можно заодно сразу и MySQL) на компьютер. Вот полезные инструкции:
https://github.com/codedokode/pasta/blob/master/soft/php-install.md
https://github.com/codedokode/pasta/blob/master/soft/apache-install.md
Может тебе понадобится пользоваться командной строкой, вот гайд https://github.com/codedokode/pasta/blob/master/soft/cli.md
Решения задач лучше показать мне, особенно на ООП,так как сам ты вряд ли увидишь все ошибки. Пости свой код на гитхаб и вкидывай ссылку в тред по мере решения. Я прокомментирую и укажу на ошибки.
Также, у нас есть задачи которые позволят тебе изучить или подтянуть до нормального уровня знания JS/HTML/CSS/SQL. Решай их параллельно с задачами выше.
- HTML/CSS: https://github.com/codedokode/pasta/blob/master/html/html.md
- JS: https://gist.github.com/codedokode/ce30e7a036f18f416ae0
- SPA (сложно): https://github.com/codedokode/pasta/blob/master/js/spa.md
- Проверялка решений на JS: http://dkab.github.io/jasmine-tests/
- MySQL: https://github.com/codedokode/pasta/blob/master/db/databases.md
Что почитать
- Мануал по PHP — http://www.php.net/manual/ru/langref.php
- Сайт phptherightway (перевод на русский: http://getjump.me/ru-php-the-right-way/ )
- По PHP: Профессиональное программирование на PHP Джордж Шлосснейгл
- По PHP: Мэтт Зандстра — PHP: Объекты, шаблоны, методики программирования
- JS: learn.javascript.ru
- Про Git: https://git-scm.com/book/ru/v1
Оформляй код аккуратно!!! — например пропусти через phpformatter.com . Также, если ты пользуешься IDE вроде PhpStorm, Netbeans, Eclipse, то в них эта опция встроена, подробнее: https://gist.github.com/codedokode/8759492
У ОПа нет аккаунтов и групп вконтакте, в фейсбуке, в твиттере, все "пхп-треды" там поддельные.
Платиновые вопросы
- Почему PHP? Потому что вакансий море, и учить легко.
- Сайт опять упал!!!!! — Не паникуй, а открой http://rghost.ru/6bfCY9lfl и получи личную немного устаревшую оффлайновую копию сайта (можно читать хоть на андроиде без интернета)
- Что надо знать чтобы найти работу - разработчику: PHP, SQL, HTML/CSS, JS, ООП, Git, композер, MVC, фреймворк. Верстальщику - HTML/CSS, JS, jQuery. У нас в треде были люди, которые практически с нуля учились и смогли найти работу.
- Что будут спрашивать на собеседовании если 0 опыта - гонять по теории, по официальному мануалу PHP, давать дурацкие задачки на переворачивание строк, гонять по SQL (транзакции, внешние ключи, напиши запрос), по JS (как сделать анимацию при нажатии кнопки), ну погугли, не ленись
- Можно подробнее про поиск работы, собеседования - нет, ОП писать не будет, но может кто из анонов захочет рассказать. Поищите тред перезвонивших, а также раздел /wrk/
- Сколько времени надо изучать все это? - все зависит от тебя, но не меньше 6-8 месяцев
- Нужен ли ООП, фреймворки, MVC, git, composer? — Да, однозначно. Посмотри любую вакансию.