Добро пожаловать в наш уютный тред. Тут мы изучаем язык PHP (а также JS/CSS/HTML/SQL), решаем задачки и даже делаем простые сайты! Зачем? Кто-то хочет научиться программировать, кто-то - делать сайты, кто-то - просто размять мозги и заняться чем-то полезным.
Это не чат! Высказывайтесь одним большим постом, а не цепочкой мелких
Это тред для начинающих. Не написал за свою жизнь ни одной программы и имеешь тройку по математике? Ты наш человек.
Устанавливать пока что ничего не требуется, разве что редактор кода вроде Sublime Text 3, Notepad++, Netbeans PHP или PhpStorm (с ним будет удобнее).
Что самое главное для программиста? Умение аккуратно оформлять код (читай второй пост, прежде чем писать код).
Правила: ведем себя воспитанно, помогаем новичкам, постим ссылки на решения задачек, ОП их проверяет и дает советы и замечания. ОП заходит редко, где-то раз в 2-3 дня, у него мало времени, не жди его, решай задачки дальше. ОП отвечает на все вопросы по его задачкам и учебнику, а вот насчет каких-то других вещей - только если останется время. Но в треде немало анонимных экспертов разного уровня, так что вряд ли вопрос останется без ответа.
У нас есть уроки по основам PHP, они собраны и выложены по адресу http://archive-ipq-co.narod.ru/ Это учебник для изучающих с нуля, то есть если ты вообще ничего не знаешь, то надо начать с него. Он простой и понятный (по крайней мере в начале). Там есть задачи, их надо решать обязательно (чтобы стать программистом, надо писать код — иначе никак). Пости ссылки на решения в тред, мы их проверим, напишем замечания и дадим советы по улучшению.
Если не знаешь как решать, запости код, напиши в каком месте остановился и попроси подсказку.
Ты прошел весь учебник? Молодец, но это были лишь основы языка 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 - Сколько времени надо изучать все это? - все зависит от тебя, но не меньше 6-8 месяцев - Посоветуйте редактор кода - Sublime Text 3, Notepad++, PhpStorm - Нужен ли ООП, фреймворки, MVC, git, composer? — Да, однозначно. Посмотри любую вакансию. - Что самое главное для программиста? Умение аккуратно оформлять код. - ОП, сделай за меня мою работу или домашнее задание? — Это конечно, хорошая идея, но нет. - Подскажи сайты для поиска работы, я не умею гуглить? — hh.ru, geekjob.ru, moikrug.ru (склеен с brainstorage.me), fl.ru, upwork.com (бывший одеск). Имей в виду, что кроме фриланса есть еще постоянная удаленная работа (remote job) когда тебе не надо тратить время на поиск заказов и переговоры с неадекватными заказчиками.
Код нужно писать не как попало, а аккуратно и по правилам. Почему? Потому, что на неакуратно написанный код не хочется даже смотреть.
Если тебе лень выравнивать код руками, закачай его на 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 пробела)
Вот ссылка на стандарты, где все это описано подробнее и даны примеры оформления:
Итак, ты зашел в тред и решил помочь какому-то анону, дав ему совет или подсказку. Спасибо! Но прочти сначала эти напоминания, чтобы твоя помощь действительно была полезной.
Давай удочку, а не рыбу
Лучше не давать готовое решение проблемы, а рассказать как его искать. Может дать ключевые слова для гугла или ссылку. Но помогай, а не пытайся показать превосходство. Если даешь ссылки на нерусскоязычные статьи, упомяни об этом.
Будь доброжелателен
Не годится: «Ты мануал хоть раз в жизни открывал, обезьяна?» Не годится: «В гугле забанили?» Не годится: «Твой код плохой» Хорошо: «Вот, как можно улучшить этот код: ...» Хорошо: «Ты неправильно используешь функцию abc(). Вот ее описание: ссылка, и как видишь ей надо передать строку, а не массив»
Не придирайся к знанию английского языка.
Объясняй
Не очень хорошо: «сделай как в этом коде» Хорошо: «если ты вставляешь текст от пользователя в SQL запрос, то получается SQl-инъекция, которая позволяет взломать твой сервер (ссылки). Чтобы этого избежать, надо вставлять данные с помощью плейсхолдеров (ссылки)» Хорошо: «Помни, что код пишется для людей. Если писать такие большие функции, то в них становится трудно разобраться...»
Не проповедуй
Мы учим использованию самых распространненных подходов, стандартов, библиотеки фреймворков. Если ты не любишь ООП, пробелы в коде, jQuery, сам PHP, то рассказать об этом стоит в каком-нибудь другом треде.
Не придирайся к знанию английского языка, анон пишет как умеет.
Ах да. Если тебе кажется, что что-то в учебнике или задачах можно сделать лучше — пиши, обратная связь всегда очень полезна.
Yii2-знатоки, вопрос к вам. Имеется пикрелейтед. Header и footer подключаются через шаблон. При переходе на данную страницу срабатывает actionProfile контроллера Master, который рендерит страницу целиком(кроме очевидных хедера и футера). При нажатии на ссылку из меню управление передается контроллеру Master actionСсылкаНейм, который рендерит тот же самый profile, а помимо этого через параметры передает ссылку для рендера в правой части вида, т.е получается рендер в рендере.
По-хорошему же надо сделать так, чтобы view Profile, в котором только левое меню рендерилось один раз, а правая часть страницы менялась ajaxом при клике на другой пункт меню. Через скрытие блоков сделать нельзя, т.к. url в зависимости от выбранной ссылки должен меняться. Также планируются пункты меню из других контроллеров, которым тоже нужно передавать значение Мастера, в результате получаются охуенные костыли. Буду рад любой помощи.
ребят помогите мне самбу настроить делаю вроде простой конфиг, а всё равно ничего не разрешает в папке редактировать comment = none path = /var/www/html browsable = yes guest ok = yes writable = yes
Аноны, подскажите мне пожалуйста. Хочу запилить свою страничку, что-то типа бложика + раздел с проектами. Как думаете стоит это делать сейчас (Изучаю с 1 октября), когда знаю только функционалку, или стоит ещё месяц изучать ООП и MVC?
>>865015 >бэкенд Часто только PHP (+ вариации CGI, Java, Linux...) >фулстэк PHP(в общих чертах) + JS + CSS + HTML + 100500 технологий JS типа cofeeScript, React, Angular нутыпонял.
Чот в прошлом треде спросил про то, как push делать через PHPStorm, мне ответили, я сказал спасибо, да и забил. А сечас перечитываю тред, а там ответов 40 про то, что надо консоли изучать и вообще я нуб. Ребзя, вопрост был, "Почему после каммита и пуша, происходит 20 изменений в 20 разных файлах и пуш перестаёт работать, выдавая сообщение что изменений нет? " Откуда вы взяли что я про Gitbush не знаю? Почему вы подумали что я консольные команды не знаю? Зачем вы об этом спорили, когда вопрос был именно про IDE? Вообще непонял.
ПОБЕДА. Взяли джуном, на испытательный. Опыта 0. Показал решение задачи про регитрацию студентов из ОП-поста и решил тестовое задание. На вопросы на собеседовании отвечал очень хуево. Знаю ли битрик, что такое ORM, как сделать наследовать от нескольких классов, как запрашивать данные сразу из нескольких таблиц, ни на что ответить не смог. Спасло только то что, в отличии от конкурентов, придумал хороший алгоритм тестовой задачи и хорошо закомментировал там все. И наверное что попросил низкую зп на первое время. Очень признателен ОПу за его уроки.
>>865339 Но там еще был такой момент, в тестовом задании говорилось что нужно использовать МВЦ, ну я вспомнив урок Опа разделил всю логику приложения, работы с данными и отображения по разным классам и шаблонам и думал что этого достаточно, требования соблюдены. Но в конторе мне сказали ни хрена так не правильно, нужно именно создавать три папки модел, вью, контролер и складывать все в них. Такая хуйня. А и да, я 27 лвл, образования нет, кодинг учу полгода где то.
Не в тему, но спрошу тут, так как нигде больше не отвечают: вот я через npm глобально установил яpug-cli (интерфейс командной строки для pug), все компилируется, а тогда зачем сам pug нужен, в том числе глобальный?
>>865344 > ни хрена так не правильно, нужно именно создавать три папки модел, вью, контролер Ну тогда понятно, почему они берут тех, кто "что такое ORM, как сделать наследовать от нескольких классов, как запрашивать данные сразу из нескольких таблиц, ни на что ответить не смог".
Серьёзно торможу, как выбрать при помощи jQuery или JS значение поля формы, если есть несколько полей с одним именем в виде массива. Есть скрипт, который генерирует количество форм с одинаковым параметром name, взависимости от выбора пользователя. В каждую из этих форм вводится значения, как получить массив со всеми значениями? То есть допустим пользователь выбрал 3 формы и в каждое ввёл данные:
Введите телефон номер 1: <input type="text" name="phones[]"> Введите телефон номер 2: <input type="text" name="phones[]"> Введите телефон номер 3: <input type="text" name="phones[]">
Как при помощи jquery выбрать все введённые значения?
Сап , аноны. Помогите начинающему программисту. Я изучаю PHP по вашим урокам ( http://archive-ipq-co.narod.ru/). На 3 уроке встретился с проблемой выполнения задания , анон , помоги. Вот код который я написал для выполнения : <?рhp error_reporting(-1) ; $anonDice1 = mt_rand (1, 6); $anonDice2 = mt_rand (1, 6); $compDice1 = mt_rand (1, 6); $compDice2 = mt_rand (1, 6); echo "У анона выпало {$anonDice1} и {$anonDice2} \n У компьютера выпало {$compDice1} и {$compDice2}\n"; if {$anonDice1} == {$anonDice2} && {$compDice1} == {$compDice2} { echo "У тебя выпали даблы\n"; exit(); } $anonSum = $anonDice1 + $anonDice2; $compSum = $compDice1 = $compDice2; if {$anonSum} > {$compSum} { echo "anon wins"; } else { echo "comp wins" exit() } ?> Но вместо выполнения оператора условия , мой код просто полностью выходит и всё. Команды не выполняются. Жду вашей помощи , аноны
>>858807 > Насчет валидатора - у тебя нет желания как-то сделать его более ООП?
Да, попозже займусь этим
> У тебя есть такие относительные УРЛ и потому возможен баг.
Все url'ы рабочие
> > if( (isset($user->email)) and ($user->email==$student->email) ): > Лучше проверять наверно по hash или id как неизменному значению. А если используется правильный дата маппер с Identity Map, то можно просто писать $user === $student.
Звучит прикольно, но как это реализовать? Погуглил, суть ясна, но сложно представляю с чего начать. $user - это return ф-ии getStudentByHash(); $student- это элемент массива полученного от getStudents();
>>865626 Кидай лучше ссылку на код, а не копируй сюда.
Начни с простого: http://ideone.com/cptdIr У тебя уже на этом этапе код работает неверно (см. на то, что он выводит). Разберись сначала с этим, дальше может поймешь, что не так
Кошерно ли использовать $_SESSION для передачи какихнить не очень важных данных между файлами пхп. например у меня сложный сайт с роутером и отедльными классами для работы с данными. Мне надо как то на рендер передавать информационные сообщения или ошибки (не кода, а пользовательских действий), после нескольких проб я попробовал передавать в $_SESSION['errors'] массив с ошибками, после чего я обрабатываю его при рендере, в зависимости от массива вывожу сообщение или информацию и очищаю эту переменную в $_SESSION. какие подводные камни? работает и выглядит все просто вроде
Нет, неправильно. Зачем тебе сессия для передачи данных внутри скрипта если их просто можно передать через переменные?
Для передачи данных между скриптами сессии тоже не лучший вариант, так как куки (а следовательно и сессии) общие для всех вкладок в браузере. Если ты знаешь, как реализованы сессии, то понимаешь почему.
>>865852 вот именно между скриптами. там просто есть класс который возвращает данные, так за время выполнения (загрузки одной страницы) создается 3 экземпляра в разных местах. Получается в одном из экземпляров есть нужный мне массив, но хз как из него передать в другой скрипт, в котором создается новый экземпляр.
а $GLOBALS не правильно, аналогично сессиям или $GLOBALS уже норм?
Нет, все это не норм. Проблема с сессиями, как я уже написал, в том, что они общие для нескольких вкладок и данные будут перепутываться если открыть несколько вкладок с сайтом.
Способ, который работает в нескольких вкладках - передавать данные через POST/GET (но тут есть подвох что пользователь видит и может менять передаваемые данные).
Проблема с глобальными переменныим в том, что код превратится в нечитаемую лапшу. Трудно будет понять откуда берутся и куда передаются данные.
Добрый вечер, не знаю в этот или в JS тред писать, с какой стороны проблема. Написал скрипт который работает долго, если лимитов нет по времени на сервере то часов 5-6, для того, чтобы не смущать пользователя сделал вывод информации в реальном времени о ходе выполнения, онлайновый стрим данных сделал с помощью 'text/event-stream', echo json даты и ob_flush(); flush(); На стороне браузера есть eventListener по message который обновляет статистику для юзера. Так вот, на локалке у меня всё нормально работает, обновляется примерно раз в 1-2 секунды, на продакшне сервер пошустрее работает - по-идее там выполнение скрипта в пару раз быстрее и статистика там не обновляется, висит долго ожидание соединения, потом через пару минут прилетает сразу огромное количество сообщений по eventStream за всё время ожидания, потом снова пауза. Я подозреваю что из-за более быстрой работы скрипта - браузер не справляется с флудом и не отрабатывает так как надо. Или всё же может быть другая проблема?
>>866039 А нет ли у тебя примеров заданий средней высокой сложности? Напомню задание на позицию джуна. Я вот даже не знаю что такое роутинг и зачем он нужен. Это что то с __DIR__? Кстати, был еще в двух конторах, в одной попросили написать скрипт который бы находил страницу пользователя в фейсбуке зная его телефон. В другой нужно было написать 2 СКЛ запроса на выборку из двух таблиц.Как по мне это значительно проще.
>>866042 >Я вот даже не знаю что такое роутинг Это формирование линков >Построить пути к элементам. Элементы каталога выводить ссылками. Например для Id=6 «Телевизор Series 7» вида «/catalog/samsung/s7/» >средней высокой сложности Мне давали тестовый таск однажды: Есть сторонний API который отдает за один раз 200 записей, API принимает некоторые параметры, к примеру я могу задать начиная с какой записи получить эти 200 записей. Задача состояла получить все записи начиная с первой, вне зависимости от их общего числа и записать в CSV-файл, при этом остановиться, когда записи закончатся. На PHP это было бы просто, но задача стояла на nodejs и там была рекурсивная функция с асинхронными запросами.
>>866051 http://ideone.com/mGR87D Потом в шаблоне $linkArray выводиться на экран. Это и есть роутинг? >Мне давали тестовый таск однажды На php задача и правда не сложная. А есть примеры именно для php?
Аноны, как настроить ебучий автокоплит в Атоме? Ну это просто пиздец, такой красивый редактор, есть плагины, а автокомплит просто сука не работает, я же везде прописал верные пути к композеру и пхп, ну вы только гляньте на сколько красив атом и вырвиглазен нетбинс.
Что делать? Хожу писать код в красивом редакторе, а в нетбинсе сидеть противно.
А может кто сказать как работает роутинг простым языком? А то у меня голова взорвалась.
Все объяснения которые я нахожу в интернете.
1 Делаем ссылку вида /pr/res/privet 2 Передаём её в роутер 3 ???? 4 ШАБЛОН
3 пункт мне совершенно непонятен. Как роутер понимает какой шаблон брать? Как он понимает что нужно взять 5 шаблонов (футеры хедеры и прочее)? Как шаблон контактирует с CSS? Как шаблон содержит переменные, но при этом они все должны обрабатываться роутером, или нет?
>>866128 Точка входа в программу у тебя одна. Роутинг всегда обрабатывается. Получаешь ссылку по которой зашел пользователь, потом в зависимости от правил роутинг у тебя, делишь ссылку на составные части, из базы получаешь, что означает каждая часть (декодишь), исходя из этих данных определяешь какой контроллер должен обрабатывать ссылку и передаешь управление ему. При построении ссылок пользуешься обратной функцией - которая из параметров собирает ссылку.
Роутинг (=маршрутизация) это процесс определения контроллера по УРЛ. Роутер - это часть приложения, которая получает на вход УРЛ определяет, какой контродллер его будет обрабатывать.
Логика работы роутера может быть любая, как программист решил, так и будет.
Если ты по-прежнему не понимаешь, могу пример кода дать, без ООП, сделам роутер обычной функцией:
>>865956 Вот этот алгоритм, только исправленный так, как у меня работает. $data = new Data(); //создаем экземпляр класса для работы с данными $values = значения по умолчанию (пустые); $errors = пустой массив; Если (форма отправлена) { Копируем переданные значения полей в $values; Проверяем значения в $values и записываем найденные ошибки в $errors; Тут валидация простая. а у меня идет в $data работа с БД + потом возвращаются данные. Конкретно у меня проводятся транзакции, где проверяется 1. Не заблокирован ли счет отправителя/получателя. 2. Хватило ли баланса 3. Если все ок с 1 и 2 проведена ли транзакция успешно.
Если (ошибок нет) { $errors = $data->someDataMethod($values); // если все ок то $errors = ['check' => 1, 'balance' => 1, 'transaction' => 1]; // Но как его передать в следующий скрипт, в котором ко всему создается свой экземпляр $data.
} }
Выводим форму($values, $errors);
Но потом на самой странице выводится темплейт и в начале него создается еще один экземпляр Data(), я пробовал сохранить как public свойство в $data, но т.к. создается новый экземпляр, это не работает.
>>866468 не обратил внимание на ссылки, проблема в настройке сервера, походу твой сервер настроен так, что не может видеть тот файлик, глянь в настройках сервера либо в .htacess.
либо же у тебя где-то есть файлик который обрабатывает входящие запросы и соответственно отдает нужные вьюшки, а твою ссылку обработать не может
>>866505 да и блять по папкам твоего приложения видно же, что запросы чем-то обрабатываются, у тебя вьюхи в отдельной папке лежат, ты же когда заходишь на сайт не пишешь http://localhost/view/index.html
так что в эту сторону и копай, разберись для начала как работает твой код
Это ошибка Апача, а не PHP. Можешь посмотреть в логе ошибок полный путь к файлу, который он не может найти.
Если ты не разбираешься в конфигах Апача и PHP, то даже если ты исправишь проблему, все равно твой скрипт будет скорее всего кривой и глючный, может быть с уязвимостями, открывающими доступ к серверу. Не надо браться за то, что не умеешь.
Анончики, помогите написать инъекцию, когда попадает 'test', выдает следующее
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'test'')' at line 1
А ты думаешь, все остальные с первого раза все правильно делают? Если бы каждый после неправильно решенной задачи постил по лягушке, наш тред бы давно уже перенесли в /zoo/
Привет, объясните пожалуйста одно из условий 5ой задачи по JS (остальные все выполнил) http://dkab.github.io/jasmine-tests/?spec=6 "должна подставлять лишние аргументы в конец списка: partialAny(fn, 1)(2, 3) -> [1, 2, 3]"
Как должен выглядеть массив аргументов на примере исходных данных: partialAny(test, 1, undefined, 3)(5)
Функция partialAny(fn, foo, bar...) дожна возвращать функцию OK должна использовать строгое сравнение с undefined (null или 0 не должен восприниматься как undefined) OK
Возвращаемая функция должна подставлять переданный аргумент вместо undefined: partialAny(fn, 5, undefined, 10)(1) -> [5, 1, 10] OK должна оставлять undefined если аргумент не передан: partialAny(fn, 5, undefined, 10)() -> [5, undefined, 10] OK должна подставлять несколько аргументов в partialAny(fn, a, undefined, undefined, b) OK должна подставлять undefined если аргумент не передан в partialAny(fn, a, undefined, undefined, b) OK
должна подставлять лишние аргументы в конец списка: partialAny(fn, 1)(2, 3) -> [1, 2, 3] NOT OK
не должна передавать лишние аргументы внутренней функции: partialAny(fn, 1, undefined, 3, undefined)(2) -> [1, 2, 3, undefined] OK может вызываться несколько раз и результаты во второй раз не зависят от первого OK
Вроде бы тут нет лишних аргументов, а если они были бы, то я должне их добавить в конец списка? Но следующее условие говорит, что я не должен их передавать во внутреннюю функцию, значит, затем я должен удалить их из списка, так?
>>864640 (OP) Сап помогач, я сам джавист потому реквестирую вашей помощи, третий час бьюсь в истерике, суть такова: надо скомпилить протобаф.
В идеале если раскажете как его потом POSTом отправить.
Есть сервер на джаве и клиент на пыхе. они должны обмениваться протобафами. С джавой проблем нет, а как эту ебатеку скомпилдить на пхп для меня высшее колдунство. Помоги анон, волосы седеют.
>>866928 Это условные названия, есть два сервака, один на джаве другой на пыхе. Надо обмен протобафами устроить. Нужна помощь по пхп части, кто в теме, пожалуйста.
Сам протобаф простоейший
package text.protobuf;
message Text{ required string text = 1; }
Надо только его скомпилить, а дял этого надо скомпилить модуль пхп, и куда-то его потом подключить или положить, и это какой-то особый пиздец.
>кнопки и ссылки должны реагировать на нажатие и наведение мыши А как узнать как они должны выглядеть?
>тег <img> используется только для картинок в портфолио >используй псевдоэлементы, чтобы уменьшить объем HTML, например для значка телефона внизу А почему нельзя использовать тег img? Так бы можно было бы вывести все иконки в старых браузерах.
>здесь используются внешние шрифты, и довольно тяжелые. Если ты можешь уменьшить их объем, это будет плюсом Не разу не работал со шрифтами. Можно подсказку как это сделать? Мне приходилось преобразовывать формат шрифтов для старых браузеров, это оно и есть?
Там обычно и не требуется делать скриншоты для всех версий браузеров. Самый проблемный тут ИЕ, потому для него стоит сделать по скрншоту для каждой версии. Для других браузеров хватит последней версии + при желании какую-нибудь древнюю. Плюс мобльные браузеры.
Тут важно понимать, что браузерных движков не так и много:
- trident (в IE) - presto (старая Опера, почти никем не используется) - gecko (firefox) - webkit (Хром, новая Опера, Яндекс браузер, мейл ру браузер, сафари, мобильные браузеры) - blink, форк вебкита, использующийся по моему в новых версиях браузеров, ранее работавших на вебките
Если стандарты соблюдать, то с gecko и вебкитом проблем практически нет, если за новыми фичами CSS3 не гнаться, то все будет работать даже в первом Хроме.
> А почему нельзя использовать тег img? Так бы можно было бы вывести все иконки в старых браузерах. Псевдоэлементы не работают в старых браузерах? По моему разве что в ИЕ7 и ниже ( https://css-tricks.com/browser-support-pseudo-elements/ )
Если нужна поддержка ИЕ7 можно вместо псевдоэлементов использовать например спаны с background-image. Если нужен еще ИЕ6 то надо отказаться от полупрозрачных PNG. Но если подумать, это очень древние браузеры и в принципе иконки не настолько критичный элемент, чтобы ради них заморачиваться.
img не годится так как его принято использовать для картинок и иллюстраций, являющихся контентом сайта. Иконки - это оформление и они не должны использовать тег img. Псевдоэлементы я рекомендую чтобы не раздувать HTML сохранять его осмысленным.
> Не разу не работал со шрифтами. Можно подсказку как это сделать? Мне приходилось преобразовывать формат шрифтов для старых браузеров, это оно и есть? Новые форматы вроде woff/woff2 действительно поддерживают сжатие и позволяют уменьшить объем. Но более радикальный способ - выкинуть ненужные символы. Условно говоря, если твой сайт на английском, зачем тебе кириллица или хинди или математическеи символы? Если взять например шрифт roboto: https://fonts.google.com/specimen/Roboto (какой они сделали ужасный интерфейс, старый нематериальный веб-1.0 был в 100 раз лучше) то в нем много разных символов, и не все они нужны.
Если использовать конвертер на fontsquirrel, то там можно указать диапазоны символов, которые нужны.
Если заказчик требует наличие определенных шрифтов, то конечно надо их подключать. Но я в общем против веб-шрифтов. Они как правило тяжелые, и пока они не загрузятся, текст не отображается (чтобы не было скачков). И победить это никак в принципе нельзя. Если ты программно будешь ставить в css шрифт только после его загрузки то текст появится сразу, но позже скачком заменится на новый шрифт с измененем размеров блоков.
Ну например, с тех пор как сайт php перешел на веб-шрифты, время ожидания до появления текста сильно увеличилось. Причем они там делают какие-то костыли вроде кеширования шрифтов в locastorage (точно не помню), но это именно что костыли в то время как очевидное решение - не использовать веб шрифты на техническом сайте для программистов. Причем они там используют тяжеленные шрифты с кучей символов разных алфавитов даже в английской версии и с кучей начертаний, в сумме больше мегабайта (хотя тут тоже не все просто, в английской документации могут быть примеры или комментарии на других языках).
В общем, мое мнение - минусы веб-шрифтов настолько перевешивают их плюсы (проявление оригинальности в дизайне) что лучше всего их не использовать. на своем сайте я их точно не поставлю (или поставлю так, чтобы они не замедляли показ текста). Но это только мое мнение. Если заказчик дал тебе дизайн с веб-шрифтами то твоя задача придумать, как их подключить с минимальным ущербом для времени появления текста и трафика.
Кстати, в твоем случае - у тебя один шрифт используется только ради логотипа. Оцени, сколько он добавляет к весу страницу и что будет если заменить его на SVG/PNG. (тут конечно свои минусы - чтобы поддерживать ретину, надо закладывать PNG с повышенным качеством, также поисковые роботы не прочитают текст в виде картинки).
При нажатии на кнопки all/graphic/illustration часть работ должна скрываться.
Телефон в подвале должен быть кликабельным с помощью tel: ссылки, адрес - вести на любой картографический сервис.
надо бы сделать адаптивную версию для узких экранов.
У тебя стоит <meta name="viewport" content="width=device-width"> но фактически адаптивности там ноль. Зачем было ставить вводящий браузер в заблуждение тег?
meta charset не прописан.
> <i> Сейчас для смыслового выделения фразы используют em, а тег i получил какое-то другое назначение в HTML5.
> PORTFOLIO Текст в HTML надо писать в нормальном регистре. Верхний регистр делается через CSS, так как это часть оформления.
> <a name="portfolio"> Чтобы сделать якорь, лучше использовать атрибут id - он вроде даже в старых ИЕ работает. Тег a для этого использовать - устаревший подход.
> <img src="img\home Почему слеш обратный? В веб используют прямой, как в линуксе.
> <li><a class="rss" href=""></a></li> Плохо что ссылка пустая. Как поисковый бот или программа чтения текста воспримет такую ссылку?
Тебе надо открыть HTML и почитать его, и такие нелогичности сразу станут видны.
В остальном HTML код хорош. Никаких лишних тегов, это хорошо.
Для ссылок на соцсети надо сделать реакцию на наведение.
Шрифты ты определил неправильно. Ты объявляешь щрифт LatoBlack:
> @font-face { > font-family: LatoBlack; Но это просто шрифт lato в жирном начертании. Все начертания шрифта Lato надо определить под одним именем, просто указать их вес и курсивность.
А в твоем варианте если ты сделаешь абзац с текстом Lato, а в нем strong, то браузер не догадается использовать LatoBlack так как для него это другой шрифт.
Их форматов - я бы добавил как минимум woff, если он весит меньше других. Найди где-нибудь список, какие браузеры какие форматы поддерживают.
> font-family: 'Times New Roman', Arial, Helvetica, sans-serif; Бредовый список. Times New Roman - шрифт с засечками, Arial и sans-serif - без, они едва ли взаимоменяемы.
> a, a:visited { > color: #d9d9d9; не надо отключать выделение посещенных ссылок на всем сайте, так как это полезная функция. Отключи только в тех местах, где тебе надо.
Далее, тебе надо проработать базовые стили CSS. Сделай новый файл с пустым body и впиши в него простой HTML без классов, с тегами вроде h1, h2, ul, li, p, a, img, blockquote (если нет фантазии или лень писать, скопируй с http://motherfuckingwebsite.com/ ). У тебя этот текст выводится бледно-серым на белом фоне - это значит, базовые стили не продуманы совсем. Ты написал не базовый CSS для всего сайта, а стили для единственной страницы и при добавлении новых страниц твой ксс придется значительно переделывать.
Почитай про назнаечние тегов в HTML5.Теги i и b в старом значении (задание начертания шрифта больше не используютя так как офомление должно задаваться в ксс, а не в HTML. Эти теги не соответствуют принципам HTML5).
> font-family: ReklameScriptRegularDEMO; Не задан фоллбек (запасной) шрифт.
> .services .content div { Неудачное на мой взгляд правило, слишком широкого действия. Представь завтра в этот блок добавят новый див и твое правило применится к нему, что заставит переделывать верстку, тратить время. Надо делать правила точечного действия, которые действуют только на нужные элементы.
В данном случае можно либо добавить > либо добавить класс на див.
Вообще, по поводу выбора селекторов, я советую почитать про подход в БЭМ. Он очень практичный и как раз предусматривает поддержку и изменение верстки в будущем.
Слишком много копипасты. Там различается только позиция в спрайте.
> .portfolio .content .works :nth-child(4n) { Это не будет работать с адаптивностью скорее всего, так как на узком экране картинок меньше.
> @media (max-width: 1110px) { > body { > width: 1110px; Это так хитро записанный min-width? Он противоречит тегу meta viewport который говорит о поддержке маленьких экранов. А ее нет.
А ты не хочешь голову поломать над дополнителным заданием? Вот оно:
---------
Подбери (гуглить и использовать готовое можно) способ подключения SVG картинки, работающий максимально кросбраузерно. Рассмотри подключение через теги img, object и через backgorund-image. Проверь, работает ли автоматическое определение размеров картинки или их надо указывать.
----------
SVG довольно интересная штука. С одной стороны, у него много преимуществ (поддержка дисплеев с произвольным разрешением), с другой стороны проблем у него не меньше. Ты берешь, рисуешь картинку в inkscape и внезапно оказывается что в части браузеров не поддерживается часть фич SVG. Или что ее нельзя использовать в качестве фоновой. Я изучал и так, и эдак, и решил что проще использовать SVG только в процессе разработки, а в браузер отдавать сгенерированный из него PNG.
>>867039 >Там обычно и не требуется делать скриншоты для всех версий браузеров. Самый проблемный тут ИЕ, потому для него стоит сделать по скрншоту для каждой версии. Для других браузеров хватит последней версии + при желании какую-нибудь древнюю. Плюс мобльные браузеры. Я не пользуюсь этим сайтом, у меня есть инструменты разроботчика + имуляция ie. Я просто несколько раз переделывал перед тем как скинуть в тред.
>Псевдоэлементы не работают в старых браузерах? Я имел ввиду что нельзя воспользоваться нельзя воспользоваться такими свойствами как content и background: url, которые по версии caniuse не доступны с 8 версии.
>Если нужен еще ИЕ6 то надо отказаться от полупрозрачных PNG. А можно пример что нужно написать? У меня не получилось вывести изоброжение с помощью background-image: url(img.jpg).
>Но если подумать, это очень древние браузеры и в принципе иконки не настолько критичный элемент, чтобы ради них заморачиваться. В нашем шаблоне есть иконки которые являются ссылками на контакты. По моему это важно выводить.
>> font-family: 'Times New Roman', Arial, Helvetica, sans-serif; >Бредовый список. Times New Roman - шрифт с засечками, Arial и sans-serif - без, они едва ли взаимоменяемы. Я не знаю чем различаются разные шрифты. Теперь буду замечать.
>надо бы сделать адаптивную версию для узких экранов. Как она должа выглядеть? Я старался сделать чтобы для экранов меньше 1110px (размер контной части) всё выглядело точно так же, за исключением резиновых отступов.
>У тебя стоит <meta name="viewport" content="width=device-width"> но фактически адаптивности там ноль. Зачем было ставить вводящий браузер в заблуждение тег? Должны размеры шрифтов поменяться.
>> @media (max-width: 1110px) { >> body { >> width: 1110px; >Это так хитро записанный min-width? Он противоречит тегу meta viewport который говорит о поддержке маленьких экранов. А ее нет. На самом деле всё наманого хуже. Я совсем не понял как работают media features и не нашел описаний атрибута content для тэга viewport А хотелось бы знать как работают все его свойства. Например, что указывает max-width в этом поле? Интуиция мне подскзывает что это максимальная ширина окна, но как оно определяется? Допустим моё окно будет 1000px, почему правило max-wdith: 1110px срабатывает? Как высчиталось 1110px из 1000px? Почему не 9999px?
Пока я приходил к этому решению, я натыкался на некоторые баги, и скорее это решение просто грязный хак.
>>867043 >А ты не хочешь голову поломать над дополнителным заданием? Принято, но позже. Сначало нужно хотя бы js сделать.
Имей в виду, что эмуляция IE (через панель инструментов F12 или сторонние программы) не совсем полноценно повторяет все особенности той или иной версии. ИЕ так глубоко встроен в систему, что эмулировать все баги точно не получается.
То есть пользоваться этим можно, но надо понимать, что могут быть какие-то тонкие отличия от настоящего браузера.
Если же ты используешь виртуальные машины с ИЕ то там все ок.
background: url работает даже в Ие6. Вот псевдоэлементы, да, есть только начиная с ИЕ8. Но тут получается такой выбор:
- замусоривать верстку, добавляя спаны, чтобы работало в ИЕ6 - решить, что сайтом можно пользоваться и без этих иконок в ИЕ6-7, и оставить псевдоэлементы
> А можно пример что нужно написать? У меня не получилось вывести изоброжение с помощью background-image: url(img.jpg). ИЕ6 в полупрозрачных (то есть с альфа-каналом) картинках формата PNG делает полупрозрачные пиксели черными. Изображения PNG8 с палитрой из 256-цветов и с прозрачностью без полупрозрачности работают нормально.
Изучи-ка особенности графических форматов, а то нам трудно будет понять, о чем речь, а тебе трудно решить, какой формат когда лучше использовать.
> В нашем шаблоне есть иконки которые являются ссылками на контакты. По моему это важно выводить. Это соцсети? Они да, должны быть видны. Но там ведь и не нужны вроде бы псевдоэлементы.
> Как она должа выглядеть? Я старался сделать чтобы для экранов меньше 1110px (размер контной части) всё выглядело точно так же, за исключением резиновых отступов. В отладчике Хрома (да и фаерфокса тоже по моему) есть кнопка "тестирование адаптивной верстки". Можно нажать ее и походить по разным сайтам, посмотреть.
Или можно сделать узкое окно браузера - будет почти то же самое.
Также, можно погуглить статьи вроде "лучшие примеры адаптивной верстки" и зайти на упомянутые там сайты и опять же посмотреть.
Википедию посмотри. Хабр (m.habrahabr.ru). Ютуб. Яндекс. Любые известные сайты.
Проблема с обычным сайтом в том, что он широкий (рендерится на 800-1000px) и на мобильном устройстве отображается в сильно уменьшенном масштабе. А если пользователь тапом приближает абзац текста, то абзац уходит за край экрана и надо его таскать вправо-влево, чтобы прочесть. Очень неудобно. Потому делают дополнительно верстку под ширину устройства (320-500px). Соответственно, блок с картинками скорее всего будет выводиться в 1-2 столбика. Размер текста, заголовков и отступов иногда также меняют чтобы не было больших пустых пространств (экран смартфона не резиновый) и смотрелось гармонично.
Ну и соответственно весь сайт обычно делается в одну колонку, а не в несколько. Все располагается вертикально. Иногда часть информации скрывают, но это не лучшая идея.
> Например, что указывает max-width в этом поле? @media (max-width: 1110px) значит что стили в этом блоке применяются только если ширина окна не более 1110 px.
> Допустим моё окно будет 1000px, почему правило max-wdith: 1110px срабатывает? Как высчиталось 1110px из 1000px? Почему не 9999px? Так как 1000px меньше чем 1110 то правила в блоке @media применяются к странице. Если окно станет шире 1110, то они перестанут применяться.
И еще одна вещь, про которую надо хотя бы почитать. Это ретина-дисплеи, то есть экраны с повышенной плотностью пикселей. Условно говоря на смартфоне может быть ширина экрана 720px. Но если вывести на нее сайт такой же ширины, то текст будет мелкий и нечитаемый. Потому браузер рендерит страницу на ширине 360px но в увеличенном масштабе. Если при этом на странице обычные картинки,то они будут увеличены и выглядеть не очень красиво. А если использовать векторный формат или картинки с двойной плотностью пикселей, то другое дело.
Zend Studio - норм IDE для нуфага? Нетбинс и пхпшторм моя некропека не тянет, а использовать редакторы стало геморно когда я начал использовать ООП и пространства имен.
Привет анончики! делаю ТЗ в конторку и вот столкнулся с проблемой. нужно организовать фильтра для выборки из БД
4. При выводе данных добавить возможность отфильтровать сотрудников по отделу, должности или типу. (Пользователь может одновременно выбрать две и более критерии фильтрации)
5. Так же при выводе данных необходимо учесть возможность сортировки по дате рождения или по количеству месячного оклада.
Так вот. базу спроектировал и заполнил. запросы для вывода данных понаписывал - все работает четенько, только вопрос в том как это теперь все упаковать? Ведь пользователь может комбинировать запросы как угодно, и мне нужно сделать все гибко. Может шарит кто статьи какие-то или прост может подсказать - буду очень благодарен.
>>867533 >добавить возможность отфильтровать сотрудников по отделу where otdel like ITdept and igorDapt >учесть возможность сортировки по дате рождения Sort by Birsday Sort by ZORPLATA
Аноны. У кого-то я видел в регулярке для проверки email предположение, что домен верхнего уровня (то что идет после последней точки, например .ru) занимает от 2 до 6 символов. Это давно уже неактуально, не ставьте таких огранчиений.
Обратил внимание, что скайп не выделяет ссылки если в домене верхнего уровня много символов, например как в http://arzamas.academy/materials/994
В природе существуют Java to JS/PHP трансляторы/конверторы? Очень нннада переписать код с жабки на пыхо-жс, а жабки-то я и не знаю. >GWT, Vaadin, JSweet Что из этого действительно может сгенерить код в js + node или в js + php из джава-кода, использующего JPA и JSP?
>>867652 Это мне 5 вариантов кода писать? 1 для идеон, второй чтобы у меня работал в браузере, третий чтобы на гитхабе выложить закоментированный, четвёртый себе сохренить со всеми дампами м echo тестовыми...
>>868197 Ты либо не мне ответил, либо обьясни как Header влияет на отображение пробелов при финальном отображении в браузере? Например хром видит что у меня 10 пробелом и символ и отображает это как один пробел. В результате всё форматирование отваливается.
>>868201 А, ну да, оно там по умолчанию. Но всё равно ничего не выходит. Если через паддинг родительского элемента задавать тот самый отступ в 10px, то он сам, естественно, раздвигается. А это, вроде, недопустимо, если судить по картинке.
>>868481 Я бы не стал проводить подобную аналогию. Популярность для языка значит, что у языка есть комьюнити, библиотеки, фреймворки и тд. А еще с ним намного проще найти работу.
Хорошо друзья. Хорошо. Теперь я понимаю что такое роутер, как он работает. Я бы даже смог написать свой, возникни вдруг такая необходимость. Но я все еще не понимаю, НАХУЙ ОН НУЖЕН БЛЯДЬ?!
>>868763 У тебя есть многостраничный проект, к примеру блог какой-нибудь или инет магазин. Человек зашел на главную, потом решил кликнуть на список постов/категорий/товаров, соответственно ссылка уже не "/", а к примеру index.php?route=category или "/category" смотря какие у тебя правила формирования линка, когда роутер обработает такую ссылку он передаст управление в контроллер категории, который отработает и вернет тебе представление категории. Зашел человек в товар/пост, "/product" "index.php?route=product&product_id=22" и роутер передал управление в контроллер продукта с гет параметром product_id = 22. Контроллер отработал и вернул представление продукта. Видимо ты ещё не работал с многостраничными приложениями. Советую всё же изучить уроки из ОП-поста, особенно MVC и задачу на студентов. там как раз и роутинг разберешь.
> Я не глупый, шарю в опп, но хоть убей не пойму что они от меня хотят.
Написано же, что хотят: "создать 2 базовых класса". Если ты не разбираешься в ООП, то открой учебник из ОП-поста, там есть глава по ООП.
> типа при выводе всех сотрудников определять тип сотрудника и переводить его в нужный объект, который просто пересчитает его зп и закинет все параметры в свойства У тебя массиво-ориентированное мышление. Такой подход при разработке больших приложений приводит к некачественному трудночитаемому коду с большим числом ошибок.
ООП подразумевает что сотрудник представлен в виде объекта все время, а не только когда тебе надо что-то вывести.
Начни с чтения урока. Если тебе не нравится урок, в ОП посте есть 2 книги, в которых тоже есть подробный раздел про ООП.
sup аноны. я тот анон, что просил у вас помощи по фильтрам. В общем я уже подошел к концу своего тз и опять прочитав задания понял, что нихуя не понял что от меня хотят собственно вот:
Создать два базовых класса описывающих сотрудника с почасовой оплатой, второй, описывающий сотрудника с месячной ставкой. Вычисление оплаты труда для сотрудников с почасовой оплатой будет иметь следующую формулу: количество часов * сумму за один час. Для сотрудников со ставкой метод расчета возвращает месячную ставку. Реализовать следующую функциональность:
ну собственно дальше функциональность всю запилил, что они хотели. Я не глупый, шарю в опп, но хоть убей не пойму что они от меня хотят. как именно описать сотрудника?, типа при выводе всех сотрудников определять тип сотрудника и переводить его в нужный объект, который просто пересчитает его зп и закинет все параметры в свойства. По типу метода фабрики. В общем кто из более опытных анонов понял в чем дела, прошу объяснить.
Аноны, как парсить битый JSON? Надо получить всего 2 параметра, но никак немогу. По любому поводу мне выдаётся ошибка конвертации обьекта в стринг. Второй день бьюсь.
>>865956 >Проблема с глобальными переменныим в том, что код превратится в нечитаемую лапшу. Трудно будет понять откуда берутся и куда передаются данные. Для таких кейсов стоит реализовать сервис, в котором можно спрятать логику получения нужного значения.
>>868903 Да блин, мне надо ЭЛЕМЕНТ массива вывести, и вот когда я обращаюсь к массиву как к массиву, он ВНЕЗАПНО говорит что массив у меня не массив, а обьект.
Твой вопрос был про битый JSON. Выяснилось что ничего битого в нем нет, просто ты не хочешь изучать PHP и читать мануал, а хочешь переставлять строчки, в надежде что само заработает. Недальновидный подход.
И не превращайте тред в чат пожалуйста, пишите 1 большое сообщение, а не 10 сообщений по одному предложению.
>>868908 начал оформлять всё на IDEone и всё заработало. Даже не подозреваю что я сделал. Вообще тот же код. >>868911 Поле Revisions графа * обрати внимание на неё. Некоторые парсеры его отказываются из JSON декодировать. И получается что они декодируют всё до и всё после.
>>868917 Потому, что кругом полно ебанатов с комплексами, которые нуждаются в том, чтобы унижать других. Не слушай юродивых, язык хуярит уже лет 15 и будет хуярить дальше как основной для веба. В нем есть почти что полноценное ооп, и всё что есть в современных яп. И вобше , плохих или хороших технологий нет, все зависит от разработчика и его уровня. Гавно можно клепать и на джаве или с и на прочих охуенных языках. Если что тыкай еблом в фесбук, контакт и хуеву тучу сайтов и пусть тебе объеснят почему эти гиганты успешно рвботают на php а не на их пиздатой джаве
>>868917 В пхп низкий порог входа, а потому дофига гавнокода
Сейчас работаю над проектом, что параллельно со мной ведет 42х летний самоучка, уверяющий про свой 3х летний опыт. Думаю молодость он провел веселую, увлекаясь тяжелыми наркотиками, потому что такие шедевры он пишет - это пиздец. Я нахожусь в состоянии близком к восторгу, пытаясь осознать масштабы его безумия, и животной истерики сразу. Ну и в отделе давно подшучивают, что когда он совсем съедет, то ссылки на репозитории с его кодом приобщат к истории болезни.
Писать регулярки это все равно что в 2016 году самопальные очереди email-рассылок на пхп делать, лол
>>868917 У языка дурная слава за счет того, что большая часть наших собратьев некомпетентные говноеды и разработка на пхп было про говномес с HTML либо MVC. С другой стороны, тебе ничто не мешает не быть говноедом, знать по настоящему ООА/П с принципами SOLID, GRASP и DDD, разрабатывать REST API на каком-нибудь Zend Expressive и когда ты зарабыватаешь > 250k на PHP в месяц как я, тебе уже решительно похуй на то, какое там мнение про твой стек технологий имеет рандомный скам.
На данный момент стек PHP становится нишевым, а роль некомпетентных долбоебов сейчас играет толпа nodejs-дебилов, а адекватные PHP-разработчики на рынке труда внезапно все поразобраны, так что новые адекватные няши расходятся как горячие пирожки
>>867533 Почему ты просто не использовал Doctrine 2?
>>869219 > функция filter_var Только она не может в кириллические домены.
Ну и раз уж зашёл, расскажи, если не сложно, как докатился до своего состояния, что было наиболее полезным на пути становления тебя как толковго PHP программиста и вообще что можешь посоветовать ботающему молодняку.
>>869226 > >Только она не может в кириллические домены. Тогда надо ебаться с конвертацией доменной части в пуникод, да. Но thx за инфу.
> Ну и раз уж зашёл, расскажи, если не сложно, как докатился до своего состояния, что было наиболее полезным на пути становления тебя как толковго PHP программиста и вообще что можешь посоветовать ботающему молодняку.
Во-первых, как это ни банально, но перестать пытаться реализовывать очередные велосипеды. Все, что так или иначе относится к инфраструктуре проекта, почти всегда уже написано и готово к использованию, то есть не надо страдать хуйней вроде "а чему бы свою ORM не написать эт же будет быстрее". И вообще приучить себя к мысле, что при любых мало-мальских сомнениях или незнании нужно открывать гугл со стековерфлоу, гугл почти никогда хуйни не посоветует.
Во-вторых, серьезно инвестигейтить в ООА/П, в знание принципов SOLID, DDD, GRASP, читать соотвествующие ресурсы и умных ребят вроде Сергея Теплякова. Читать дохуя книг обо всем и вся, о чистом коде, об ооа/п, всякие там дедлайны и прочее – чем больше кругозор, чем больше ты всего знаешь, тем более ценным разработчиком ты являешься. Работать с персонажами "я фронтенд-разработчик но верстать я не умею" очень сложно
В-третьих, поработать в серьезных, желательно богатых на бизнес-логику проектах. Корпоративные ERP, CRM = годно, пилить сайты на симфонипараше или интернет-магазина на магенто = fail
В чертвертых опыт и знание огромного количества инструментов. Больше знаешь = больше пользы. "Чистые бэкендщики" полезны в крупных ИТ-конторах, но большая часть бабла лежит не в ИТ-сфере и там гораздо полезнее фуллстекщики.
Что касается меня, то хз. С 14 лет пишу на пхп, вот 25 и теперь по два-три одновременно работаю, то есть по каждому проекту получается средние деньги, но оба вместе дают мне очень вкусные цифры
сап, аноны. пишу сейчас роутер (так для тренировки) и вот словил проблему на ошибке 404. .htaccess все запросы перенаправляет на index, после я забираю урл и проверяю его, чуть что выкидываю 404. И вот самой главной целью- это передать заголовки в которых ответ 404, но интерпретатор не пускает- говорит, что заголовки уже переданы, но по сути я еще ничего не выводил в html, только инклудил один файл, в котором класс валидатора. Да без инклуда заголовки передает. без BOM сохранял
>>869248 >В-третьих, поработать в серьезных, желательно богатых на бизнес-логику проектах. Корпоративные ERP, CRM = годно, пилить сайты на симфонипараше или интернет-магазина на магенто = fail Не понял, поясни за симфонипарашу. Хочешь сказать на фреймворках писать хуёво, или у тебя претензии только к симфони?
Тебе надо прочитать уроки по HTTP выше. Ты умеешь просматривать заголовки, например в отладчике браузера или сделав запрос курлом вручную?
Посмотри что приходит в ответе.
В твоем коде как минимум 2 ошибки:
- после header Location ты не завершаешь скрипт - ты не понимаешь как работает редирект. header Location выставляет код ответа 3xx вместо нужного.
То есть ты вместо "страница не найдена" говоришь браузеру "страница переехала по другому адресу".
Вообще, я почему-то часто вижу вот это, что люди вместо отдачи страницы ошибки редиректят на нее. Вы все что ли по видеокурсам учились?
Алсо, название плохое - Validator - надо было написать конкретнее, что это за валидатор. Алсо статические методы это не ООП.
В общем, я тебе советую поставить курл (не расширение к PHP, а утилиту командной строки) и например с помощью curl -v 'http://localhost/test' запрашивать страницу и смотреть заголовки.
Либо можно поставить wget и сделать wget -d 'http://...' -O - (не перепутай пробелы).
Либо какую-нибудь программу для отправки HTTP запросов с GUI.
Кстати про кириллические домены написано в документации по FILTER_VALIDATE_URL, и не написано в части про email. Вообще, у меня там сложилось ощущение что для них поддержка кириллицы не выглядит очень важной и многие функции ее не поддерживают. Это конечно слабое место пхп.
> и теперь по два-три одновременно работаю, Это вообще-то плохо, это значит что у человека нет времени и сил нормально разобраться в проекте и он будет лепить не самый лучший код.
Доктрина там по моему к вопросу прямого отношения не имеет. Ты бы мог упомянуть Query Builder.
И хотя это хорошая идея, использовать доктрину в простых проектах, чтобы не изобретать дата маппер, но у нее тоже куча своих подвохов, мне за время работы с ней даже в ее потрохах приходилось ковыряться иногда.
Зато она простая для понимания. В конце концов, основная цель валидации ведь отслеживать случайные, а не намеренные ошибки. Вот я например могу сказать что люди часто делают такие ошибки:
Надо отслеживать именно их. А если пользователь хочет ввести несуществующий или чужой емайл намеренно, он это и с гигантской регуляркой сможет сделать.
>>846554 >>Метаданные о файле наверно стоит хранить в БД, чтобы не дергать файл при каждом просмотре страницы. Особенно если у нас файлы хранятся на отдельном сервере.
Для одного типа файлов будут одни поля, для другого другие. Как это организовать, чтобы не было избыточности?
>>869482 >Зато она простая для понимания. В конце концов, основная цель валидации ведь отслеживать случайные, а не намеренные ошибки. Вот я например могу сказать что люди часто делают такие ошибки: > >[email protected] >ivan.ivanov @example.com > >Надо отслеживать именно их. А если пользователь хочет ввести несуществующий или чужой емайл намеренно, он это и с гигантской регуляркой сможет сделать. Верно, тем более настоящей валидацией существующего емейла должна быть ссылка активации в письме.
Аноны, объясните в задачке навигатор пикрелейтед. Ведь в константы можно сразу вписать значения массива ниже, и не использовать массив совсем. Или может весь смысл в том, чтобы написать функцию принимающую значения констант, а отдающую значения массива? Или может существует ещё что-то о чем я не знаю, и для чего это нужно?
Уютный тредик, открытый в браузере, отъедает память сотнями мегабайт и тормозит? Кажется, я нашел решение. Отключите "Автоматически следить за ...", отключите Топ тредов, и может еще несколько настроек, и вкладка с мейлручем перестает отъедать память. Посмотрим, конечно, еще пару дней, сколько там набежит.
Аноны, объясните в чем беда. Только начал изучать программирование. Поставил Denwer, решил проверить, как выглядит решенная задачка в браузере, а он мне выдал пикрелейтед. Пробовал поменять в настройках браузера кодировку с Windows-1251 на UTF-8, но это не помогло. Если что , пользуюсь яндекс браузером. На ideone все работает
>>869736 Отключил через File>Remove BOM в PhpStorm не помогло >>869737 Если я тебя правильно понял, я должен прописать в начале кода: $header = 'Content-type: text/html; charset=UTF-8'; ? Если я правильно все сделал, то это тоже не помогает
>>869774 > Тесты в run examples проходит, а те которые в run suit нет. Первый раунд тестов для тебя, ты их изменяешь и тут же в браузере всё тестишь. Там хоть assert 1 == 1 пиши, всё будет зелёненьким.
> ну и хули ему надо от меня? Неправильно расставлены скобки. Но непонятно для какого слова. У меня тоже такое бывало, что непонятно какие тесты падают. Можно заглянуть в Discourse задачи, если проблема не только у тебя одного, то ты там найдёшь решение. Конкретно в твоём случае всё не так плохо, написано "should ignore case". Попробуй кодировать слова вроде WoRdD, wORDd и посмотри, правильно ли кодирует твоя программа.
Конкретно твоё решение слишком мудрёное, я без регулярок сделал.
>>868786 >>868803 У меня в задаче про студентов в шаблонах были прописанны ссылки на контролеры(../registeration.php). Никаких недостатков этого подхода я не заметил, поэтому и спрашиваю. Зачем? >>868766 Лучше чем здесь я бы не сказал>>868786
Как тут код узнал что именно где пишется дата, а где - ивент? Цикл идет, задается в теле цикла значение, что будет первым, а что нет. Понятно. Но где именно обозначение что индекс массива - это дата, а значение - ивент?
Только не гоните ссаными тряпками, я вот не понял действительно. Как работает вообще цикл с массивом?
> Но где именно обозначение что индекс массива - это дата, а значение - ивент? Потому что одна переменная стоит слева от стрелки, а другая справа. Слева стоит ключ, справа значение. Мануал в помощь http://php.net/manual/ru/control-structures.foreach.php
Вообще, ты правильно делаешь, что задаешь такие вопросы, по ним становится понятно что стоит поменять или добавить в уроке.
Чтобы браузер понял, в какой кодировке страница, ему надо об этом сказать. Либо с помощью опции в заголовке Content-Type либо с помощью HTML-тега meta charset.
>>870030 Да вот почему-то Шторм изначально делает какие-то кривые файлы. Я сам возился три часа и орал в треде, пока анон не надоумил поменять файл с BOM на без него. И с HTML простым там тоже может быть проблема, имей это в виду. Но при этом у меня сейчас выходят нормальные файлы .php, уже и не вспомню, что именно сделал для этого. Может, по умолчанию поставил без BOM и в UTF-8, даже скорее всего.
Сап, у меня тут маленький бугурт возник. Отправил свой код с тестовым. Там проверяющий сделал несколько мелких справедливых правок. Но что меня удивило, что он все мои двойные кавычки сменил на одинарные и записал это как мой недостаток, мол одинарные кавычки это тру, а двойные кавычки - это плохой тон в программировании. Это вообще нормально? Просто я вообще никогда не слышал что между ними есть хоть какая-то разница. Also в двойных кавычках есть профит в том, что внутри них моно писать одинарные, что даёт профиты в скорости написания кода. Есть тут кто сможет мне объяснить?
>>870243 Я PSR-2 сейчас листаю, там вроде ничего такого нет, именно про кавычки, или поправьте меня пожалуйста если я неправ. Что-то прямо смущает меня этот коментарий. Всё-таки я ньюфаг с опытом в 2 месяца, могу ошибаться.
есть программа которая берёт файлы из диска и из бд. те файлы которые есть в бд но нет на диске она удаляет из бд. те файлы которые есть на диске но нет в бд она добавляет в бд.
мне нужно сделать не так топорно как сейчас, а в виде абстракций.
в частности, мне нужно сделать ПРАВИЛА для добавения.
то есть допустим я захочу добавлять файлы размер которых больше 10МБ
чтобы не писать всякие ИФ или условия, а чтобы создал indexatorSizeRule, установил там всё, и чтобы индексатор видел это правило.
то есть, мне нужно какая-то абстрактная конструкция. понимаешь? вот эта вся ооп магия.
Обоснуй причину, почему ты хочешь сделать правила в виде объектов? Ты пишешь универсальную библиотеку синхронизации файлов, которую будут расширять другие люди? Тебе надо строить сложные конструкции из правил?
Даже в этом случае на мой взгляд предпочтительнее сделать объект-компаратор, получающий информацию о 2 файлах и принимающий решение, что с ними делать.
Не надо слепо стараться все вынести в отдельные объекты. Надо применять инженерный подход, то есть ответить на вопрос: в чем преимущества подхода A перед B? Чем отдельный класс-компаратор лучше просто заложенного в коде if или приватного метода? Я например думаю, что приватный метод сделать проще и это его преимущество.
Также, мне не очень нравится интерфейс твоего объекта, вот эти вот методы setFilesFromDb, setFilesFromFilesystem. Ты по моему имитируешь тут передачу аргументов функции через сеттеры. Не проще просто написать
reindex(filesFromDb, filesFromFilesystem) ?
В твоем коде например можно вызвать run() , не задав файлы, а в моем примере - нельзя. В твоем коде надо сначала разбираться, какие методы в каком порядке вызывать.
Также, хочу предупредить, что твой алгоритм предполагает что полный список файлов содержится в памяти. Если у тебя десятки миллионов или больше файлов, то наверно это не очень выгодно и надо будет думать над последовательной обработкой (итераторы?) без полной загрузки в память. Но если у тебя пока нет столько файлов, можешь не заморачиваться.
В общем, я тебе советую сделать сравнение через компаратор либо в виде приватного метода либо в виде интерфейса, если нужна расширяемость и возможность задавать произвольные правила.
Чтобы сделать обновление части страницы через аякс, советую сделать так. На клиенте при клике по ссылке делать запрос с добавлением параметра, например /some/page?noHeader=1
В приложении дописать костыль, который будет убирать header/footer при наличии параметра. В Юи есть такая штука как layout, она отвечает за вывод шапки/подвала. Надо в ней разобраться и доработать чтобы она могла ее не выводить.
Стоит как минимум прочесть комментарии к задаче про студентов. МОжно делать блог вместо задачи про студентов, но следуя всем описанным там рекомендациям, иначе ты навелосипедишь не самый качественный код. И конечно советую показывать на проверку.
>>870276 >Обоснуй причину, почему ты хочешь сделать правила в виде объектов? я хуёвый погромист и хочу дома попердолить что-нибудь посложнее тупых методов
>объект-компаратор не понимаю что он должен из себя представлять. отдельный класс, и там куча методов?
>Если у тебя десятки миллионов или больше файлов нет, количество файлов небольшое, не нужно это учитывать
>>870287 >Фулстек конечно. Странно, я вот недавно начал работать фуллстек девом, и я ощущаю себя эдаким jack of all trades, master of none. Я думал нужно стремиться к чему-то одному, а фуллстек оставлять тем, кто только начинает свой путь разработки и еще не является профессионалом в какой-то конкретной области.
Ну так хороший программист тем и отличается от плохого что не усложняет код без необходиости. Если ты прочел учебник по паттернам, это не значит что их надо использовать при каждом удобном случае.
Если у тебя нет веских аргументов, то проверку условий можно сделать обычным ифом.
Если ты хочешь попрактиковаться в паттернах, выбери задачу, где их использование будет уместно. Например, напиши свой ORM.
> не понимаю что он должен из себя представлять. > отдельный класс, и там куча методов? Насколько я понимаю, твой класс проходит по списку файлов на диске и в базе, сопоставляет их и для каждого принимает решение, что с ним делать: добваить в базу, обновить существующую запись, удалить. Если бы ты хотел сделать универсальный класс, ты бы мог абстрагировать правила сравнения с помощью класса-компаратора.
И используй инженерный подход. Если ты строишь мост через ручей, тебе не нужны те же технологии, что и для моста через большую реку.
Декомпозиция (разделение логики на классы) используется либо когда кода становится много и он становится сложным, либо когда код выносится в библиотеку, функциональность которой будут модифицировать другие люди.
>>870388 >Если у тебя нет веских аргументов мой веский аргумент - я хочу практиковаться в этих паттернах и абстракциях, но я не вижу смысла городить какой-то ёба-проект в стол ради этого.
этой программой я пользуюсь, почему бы здесь не сделать это.
>>870388 >Насколько я понимаю, твой класс проходит по списку файлов на диске и в базе, сопоставляет их и для каждого принимает решение, что с ним делать: добваить в базу, обновить существующую запись, удалить нет, сначала есть 2 списка - файлы в бд и файлы на диске
затем вызываются методы по очереди setFilesToInsert(filesFromFilesystem, filesFromDbMap); setFilesToDelete(filesFromDb, filesFromFsMap);
я так и не понял куда тут должен встать компаратор.
как сделать это красиво и абстрактно? плес не надо больше про ТЕБЕ НЕ НУЖНА СЛОЖНОСТЬ. нужна, в этом и смысл
Зачем практиковаться в написании переусложненного кода? Я тебе уже написал, если ты хочешь изучать паттерны, открой любой сложный фреймворк или ORM (Spring, Hibernate, код аднроида) и изучай. Это даст тебе намного больше пользы чем прикручивание паттернов туда, где они не нужны.
У тебя какой-то странный алгоритм. Я бы сделал так:
- для каждого файла с диска filefromDisk { - находим fileInDb = соответстующий ему файл в БД или null - сравниваем fileInDb и FileFromDisk и решаем, что с ним делать - помещаем fileFromDIsk в нужный список (на вставку, обновление итд) }
Я могу только рассказать, как сделать код лучше. Рассказать, как его переусложнить, я не могу.
Можешь задать вопрос в этом треде, главное правильно его сформулируй и дай ссылки на примеры кода. Может, я смогу разобраться. Ну или ссылку мануал дам.
Вообще, это может только повредить так как перемножение - точная операция (если мы остаемся пределах диапазона int), а взятие логарифма - операция с потерей точности.
Ты уверен, что не работает? Сдампь содержимое массива до и после array_push и покажи, что после добавления массив остается точно таким же. Я думаю, причина в чем-то другом.
>> а почему это делается не через класс авторизации? > А зачем? Чтобы не копипастить код, когда тебе понадобится получить залогиненного пользователя в другом месте. И чтобы разделить код на отдельные части, а не писать все длинной портянкой. Обычно каждый класс занимается своим делом, соответственно получение текущего пользвоателя логично поручить классу авторизации.
> Лучше всё вручную передавать? Я думаю, лучше делать проверку или список полей где-то в контроллере. Чтобы сразу было видно, что значения 100% проверяются.
В случае, если бы ты использовал фреймворк, там есть объект формы и он гарантирует что из POST берутся только заданные в форме поля.
>Все url'ы рабочие Это они сейчас рабочие, а если ты завтра добавишь УРЛ вроде /student/123/profile то перестанут работать. Лучше бы использовать УРЛ от корня сайта, вроде '/register' вместо относительных 'register'.
> Звучит прикольно, но как это реализовать? Погуглил, суть ясна, но сложно представляю с чего начать.
=== для объектов проверяет, это один и тот же объект или разные.
Некоторые ORM, например, Doctrine, умеют автоматически искать и сохранять в базу изменения в ранее загруженных объектах. Эти же ORM гарантируют что одной записи в БД всегда соответствует один и тот же объект - если 2 раза запросить из базы одного и того же пользоватля, то во второй раз обращения к БД не будет, а будет возвращен ранее загруженный объект. Если бы это правило не соблюдалось, и записи могли бы соответствовать 2 разных объекта, то было бы непонятно, в каком из них актуальные данные.
> Звучит прикольно, но как это реализовать? Это паттерн Identity Map. Тебе придется сделать класс, хранящий ранее загруженные сущности и настроить его взаимодействие с Data Mapper. Не уверен, что стоит с этим заморачиваться в простом приложении, проще взять доктрину, которая уже умеет это делать.
Вкатываюсь в тред, чтобы отписаться о своей стори. Гуманитарий, 25-лвл. В начале года усиленно занимался по учебнику ОПа, старательно проходя все задания (был уровень нуль нулём). Почти доделал студентов, активно писал в тредах и буквально жил тут у вас.
Потом как-то забил на довольно-таки долгое время(проблемы ИРЛ), не трогал пограминг до начала сентября почти. Вот пару месяцев назад вновь вспомнил и попытался восстановить в памяти всё. Довольно трудно было, но всё же мне это удалось. Начал искать работку, на удивление, ОПовский учебник мне охуенно помог(рили, прям всё-всё оттуда) и уже через пару собеседований мне перезвонили из одной конторы и вот уже полтора месяца я джуниор php-программист с окладом в 40 деревянных для ДС мало, но всё же.
На работе пишем на php(правда без ООП почти) + js(jquery) + css/html ну и на битриксе, как я понял, он оче у нас в рф популярен
ОП, не знаю, тот ли ты легендарный оп из начала года, если это ты, то спасибо тебе большое за учебник, за то, что ты всегда в треде сидел помогал и смотрел решения.
так что, корзинки, не теряйте надежд, забейте на возраст и вышку, и желательно не брать перерывов, а сразу идти искать работу, даже до студентов
>>870547 Я в 21 лвл на последнем укурсе пошёл работать, брали везде, толком нихуя не знал. Отработал в 3ёх конторах по неделе, не выдерживал из-за социофобии. Сейчас уже почти год сижу дома, хуй знает что делать. Реален хоть какой-т офриланс для программиста? Куда деваться? Батя предлагает лечь в больничку навсегда
>>870587 Социофобия начала развиваться на 3-4 курсе, тогда я ещё мог себя хоть как-то контролировать и терпеть. Потом уже контроль был утрачен практически полностью. Побороть я не смог. Работать в обществе не могу. В больничку тоже не хочу.
>>870592 Первый раз психиатр в военкомате, второй раз в районной больнице. Диагноз там из 3ёх вещей состоит - социофобия, на её фоне какая-то там депрессия развилась плюс ещё подозрение на какое-то там расстройство. Я это точно не помню. Ну и само собой. когда у тебя едет крыша, то как-то сложно это не заметить. Даже некоторые шизофреники понимают. что они больные.
>>870601 как можно не хотеть вылечится то? вот болит у тебя зуб - ты же не сидишь дома подыхая - ты идёшь и лечишь.
а тут год сидеть дома? нахуя? родители твои куда смотрят? ты же жизнь проёбываешь свою. год без работы - тебя уже и не примут работать никуда, ты же всё забыл с вуза
Друзья, помогите. Срочно по работе приспичило написать веб-сервис, пхп изучаю параллельно. Встала проблема. Есть одна страница, на ней таблица, где есть поле "количество" и кнопки - и +. Пользователь по ним жмакает, кол-во меняется. Сделал на jquery, все отлично. Теперь мне надо на этой странице жмакнуть на кнопку "сгенерачить" и открыть таким образом другую страницу, где я выведу то, что там наотмечал пользователь. Как собрать инфу со страницы и собрать в массив, я понял. Как передать массив? json или не json? Или как-то по-другому? Еще не догоняю немного про get и post. Я хочу в итоге получать короткую ссылку вида site.ru/ier234kj или site.ru/dks0992ww в зависимости от того, что там в массиве, чтобы сгенераченной страницей можно было поделиться с товарищем, а не заставлять его тыкать те же плюсики-минусики. Это значит, мне нужно передавать через get? Там вроде ограничение на кол-во данных, а у меня большой массив.
Это уже совсем оффтопик, но по моему ты переоцениваешь возможности медицины. Мозги вправлять пока не научились, в лучшем случае колют какие-нибудь вещества, повышающие активность или наоборот отупляющие человека
Зайди на фриланс-сайты и проанализируй. Но лучше поискать на сайтах поиска работу, на которой можно работать удаленно. на фрилансе ты будешь половину времени тратить на поиск и переговоры с заказчиками, и это время никто не оплатит.
>>853691 >5) Напиши на php простой echo-сервер, который слушает порт, принимает соединение и отсылает каждую принятую строчку обратно. Как-то так http://ideone.com/UgSyOM
>6) Напиши простой HTTP-клиент на php, скачивающий файл по указанной ссылке Не уверен, что я правильно понял задание http://ideone.com/rkE6MM
Я тут начал делать студентов. В принципе все понятно, только не знаю как реализовать архитектуру по людски. А именно, как правильно распределять контроллеры? Вот тут короче решил проблема максимально просто, но как по мне тупо. Есть .htacces который перенаправляет все на индекс.пхп в корне сайта. В нем этот код http://ideone.com/dSXrX3 т.е. если есть кука включается главный контроллер(в нем список студентов), если нет - идет форма регистрации и кука устнавливается. Так же не следует делать, да?
>>870870 Для каких? Я же не собираюсь этот хттп сервер использовать где-то, просто в целях ознакомления написал. А вообще хотелось бы какой-нибудь десктопный язык знать несложный, чтобы можно было какие-нибудь штуки полезные для ОС писать, я вот подумываю о Питоне.
что скажите про этот код в контексте уместности? Вообще не понимаю как мне преодолеть пропасть от "я выучил ООП-примитивы и понятия" до "я уверенно пишу на ООП и знаю что где к месту"?
>>870882 >Я же не собираюсь этот хттп сервер использовать где-то, просто в целях ознакомления написал. Ну так можно же было знакомиться сразу с тем, с чем удобнее работать. >я вот подумываю о Питоне Скриптопараша.
>>870894 >Ну так можно же было знакомиться сразу с тем, с чем удобнее работать. Ну так мне и удобнее на пхп работать. >Скриптопараша. Поясни. И что не скриптопараша? inb4: GO
Вот есть семейство шрифт Open Sans, который я скачал с Google Fonts, и в архиве находятся шрифты OpenSans-Regular\Bold\Italic\etc. Как определить через @font-face __всё__ семейство?
Кажется, до меня доходит, почему в npm так много пакетов. preg_quote в JS нет (!), свопнуть ключи и значения ассоциативного массива нельзя (array_flip в PHP), нельзя заменить в строке символы, используя карту (strtr в PHP). Нельзя из коробки, нужно велосипедить/копипастить/тыкать npm install. Или у меня PHP головного мозга?
>>870903 У меня для тебя плохие новости. Ява умерла 2 года назад. Её главная фича была в кросплатвформенности, а она как раз и отвалилась в 2014. А если нет кросплатформенностиЮ то и ява ненужна.
>>871284 Какой ты соня, тебя даже вчерашний шторм не разбудил. Всех подзадолбало что Оракл подаёт в суд на всё что движется и уже два года как все отказываются от Java. Эпл так вообще по дефолту 1.6 поддерживает. Такие дела.
>>871300 Ты бы ещё сказал что Delphi не помирает, лол. Очнись, большинство разрабов на жабе были только плагодаря андройду. Который судя по всему перекатится на какой-нибудь Go.
>>871319 да все знают с явы так быстро не соскочить , даже если гугл откажется от ведра , ява будет в интерпрайзе , суть в том что , среднему и малому бизнесу ява не нужна ибо жрёт рам как не в себя
>>871326 да все знают с делфи так быстро не соскочить , даже если Борланд откажется от Delphi7, Delphi будет в интерпрайзе , суть в том что , среднему и малому бизнесу Delphi не нужна ибо жрёт рам как не в себя ой, сейчас вроде ведь не 2007 год.
>>871325 В общем-то ничего удивительного. У JS нет альтернативе в веб фронтенде, да и кодеров на нем благодаря простоте побольше. А ява как жрала свой энтерпрайс, так и жрет.
>>871329 >ой, сейчас вроде ведь не 2007 год. Ну как, вы же и в 2007 яву хоронили. А уже без пяти минут 2017. Подумай на досуге, почему ява успешна и какие у неё альтернативы.
>>871333 Ну так и в 2007 про делфи все говорили что непомрёт. >почему ява успешна Кросплатформенность во все поля. И маниакальные желания джава разрабов переписать всё на Java. >какие у неё альтернативы. С\ С++ сейчас они даже двигают в сторону веба. >вы же и в 2007 яву хоронили. Тогда это был язык для аплетов под банк клиенты. Алсо это были последние годы Sun, до того как их купили оракловцы. И все предрекали смерть именно поэтому.
Начал сейчас читать про анонимные функции и постоянно слышу какие-то восхищения о том что "Наконец-то они появились в PHP, так долго ждали, так долго хотели и вот, новые возможности!!!". И как-то я вообще не понимаю в чём профит то? Ну вот была у нас классическая функция, теперь у нас тоже самое, только с немного другим вызовом. А посему вопрос. Хоть кто-ниюудь на практике сталкивался именно с использованием анонимной функции? Не для того чтобы её использовать, а чтобы что-то сделать, без чего не обойтись.
Оп сейчас пишет небольшую утилиту на Го и там много неудачных решений. Отовсюду лезут сишные корни, указатели, нет классов, нет коллекций, нет даже функции вроде in_array, и попробуй найти, как в Го сделать exec (подсказываю: правильный ответ сильно зависит от версии Го, в той что в дебиане, придется вручную побайтово упаковывать параметры для сисколла execve) или fork (fork в Го делать нельзя).
Также там есть дебильное правило, что видимость поля струткуры определяется регистром буквы. Выглядит ужасно и очень неудобно когда эту видимость надо менять.
Они не используют libc если я не путаю, и из-за этого многие полезные функции недоступны, надо вручную вызвать сисколлы. Кстати, часть библиотеки, отвечающая за них, постоянно меняется.
Нет генериков. Хочешь автоматически разбирать параметры конфига и командной строки разных типов - обращайся к рефлекшену с runtime panic.
Вообще, после ООП в PHP тяжело воспринимать код на Го - всюду глобальные переменные и глобальное состояние. Ну например встроенная библиотека flag для разбора аргументов командной строки ориентирована на ручной кодинг и автоматизировать ее (например чтобы аргументы командной строки не были прописаны вручную в коде, брались из структуры настроек) очень непросто и приходится всюду ставить костыли. Проще наверно форкнуть и переделать модуль flag.
В моей утилите 80% кода занимает именно разбор аргументов и конфига, и только 20% - код, ради которого она писалась (несколько системных вызовов и libseccomp).
Мне кажется, восторженные отзывы про Го пишут либо те, кто в нем только не разобрался, либо те, кто другие языки не видел.
И еще нет никакой логики в организации кода. Люди просто раскидыают функции и переменные по файлам как хотят, и понять ничего невозможно. Видимо бывшие сишники пишут. Не представляю чтобы Ява разработчик например такой бардак в коде устроил.
Нет пакетного менеджера, и дурацкая схема организации папок по умолчанию.
Изучи функции usort, array_map, array_filter - там они полезны. Ну например в сортировке функция-компаратор определяет порядок сортировки. Или можно написать функцию, которая из списка объектов отбирает часть по заданному в анонимной функции критерию.
>>871344 >например в сортировке функция-компаратор определяет порядок сортировки. А рекурсивный вызов функции из тела функции тут непоможет? Или почему тут именно анонимная нужна?
>>871380 >The TIOBE Programming Community index is an indicator of the popularity of programming languages так и представляю что ты такой ОЙ, Я БЫЛ НЕ ПРАВ
>>864640 (OP) Привет. Разбираю ответы опа, исправляю старый код. Не знаю как тут принято выкладывать исправления, но в общем так вот.
Игра в кости > elseif ($sumManThrow = $sumAIThrow) { >тут можно было не писать условие, а просто написать else. Исправлено. http://ideone.com/hs55ma
Миллион в банке > $starterMoney+($starterMoney(10/100)); >Тут вместо числа 10 стоило использовать переменную $percent. Исправлено http://ideone.com/ujbtNY
Школьник и кредит на айфон >Вообще, тут переменная $oversum лишняя и ее можно убрать. Также, хорошо бы избавиться от if/else где почти 2 одинаковых копии кода. Сделал предварительный обсчёт $oversum и убрал всё что обсчитывалось в ней из if\else Дальше не понимаю как улучшать. Исправил http://ideone.com/p494L2
Ответ на любой вопрос > $random=array_rand ($answers, 2); > не очень понятно, зачем брать 2 случайных ответа, но работает в общем верно. Исправил http://ideone.com/oKdt3x
Шифр >Верно, хотя у тебя при расшифровке точка превращается в твердый знак. Да я как-бы почти срзу сделал вот так. Надеюсь это считается как правильное решение тоже. http://ideone.com/nZQDpf
Лев Толстой >Вот тут не очень удачно: $rndWord1=mt_rand(0,3); - надо вручную считать число слов в массиве и пересчитывать при изменении. Лучше без этого. >Также, тут можно было сделать массив вариантов и пройтись по нему циклом:
Айпады. Тут была куча недочётов то именования переменных, до неправильного подсчёта. Тот случай когда у себя поправил, а выложить забыл. http://ideone.com/7Hc2oC
Задача на автономера. > (А|В|Е|К|М|Н|О|Р|С|Т|У|Х) >Удобнее использовать тут символьные классы: [АВЕКМНО...] Вообще не догадывался что так можно, спасибо! > for ($i=0;$i<$arCount;$i++){ >тут лучше foreach Исправил. http://ideone.com/fMXK7v
Спасибо тебе ОП, за твои уроки. Я и сам уже начал понемного понимать как и где что улучшить в старом коде, ты лучший!
>>871342 >Отовсюду лезут сишные корни Ну ты неверно рассматриваешь го. Это же и есть сишка, только чуть захипстованная. Ты же не жалуешься на отсутствие вменяемого мультитретинга в пхп. Вот и там не нужны эти ваши дженерики (хоть и хочется).
Приветствую. Хотел задать несколько вопросов. По большей части про css, вы же не против? Первое. Как выровнять основное содержимое сайта по центру, без задания фиксированной ширины страницы, например, когда задаешь значение в процентах. Второе. Как можно полностью убрать элемент со страницы? Не спрятать его, а именно чтобы его не было Спасибо.
>>871343 > Нет пакетного менеджера Гугли glide, мне хватает. > И еще нет никакой логики в организации кода. За этим сам следи. Вообще странно на это жаловаться в треде php.
Зачем нужны магические методы __get и __set, ведь если их определить, то по сути свойства станут публичными – какой смысл в их private? И не проще ли тогда их сразу как public объявить?
>>871688 Ты мало видимо читал их. Они нужны что бы тебе не динамически всякую хуиту не прописывали в объекты, если ты того не хочешь. Или если хочешь, но так что бы это все управляемо было.
>>871688 Это просто синтакический сахар. Представь что у тебя 10 приватных методов, каждому из них нужен геттер и сеттрер. У тебя будет 20 методов в класе, ололо.
А эти меджик методы автоматически их за тебя создают.
>>871688 > И не проще ли тогда их сразу как public объявить? Нет, а если я хочу проверять, что свойству в качестве значения выставляется именно строка, а не число? Публичному полю можно присвоить всё, что угодно. В сеттере же можно делать проверки/валидацию.
Что делать если при запуске скрипта из консоли он выдает синтакс эрор?
При этом скрипт как я полагаю даже не начинается, просто ругается на те классы, которые консольно никак не дергаются, а просто находятся в этом же проекте.
Через веб приложение работает, а вот через консоль и кроном соответственно некоторый функционал не хочет вызываться, падая вот так.
>>864640 (OP) Ребятки! А возможно ли в регулярное выражение засунуть переменную? Вот допустим есть у меня функция, я в эту функцию передаю переменную: $str = 'ня', и я хочу найти все слова содержащие "ня". как написать регулярное выражение тогда? "/w($key)w/u" не работает.
Для года, возможно, было лучше применить тип number. Тип инпута влияет например на то, какие кнопки показываются на виртуальной клавиатуре на мобильных устройствах.
В форме поиска можно было бы использовать required
> редактировать мои/ваши данные Немного сбивает с толку. Если "мои" употреблено рядом с "ваши", то появляется ощущение что тут как минимум 2 разных человека - пользователь и наверно автор программы.
Если результатов поиска нет, лучше так и писать, а не показывать заголовок таблицы. Если пользователей нет, тоже лучше так и написать и предложить зарегистрироваться.
Нет надписи "показаны результаты поиска по слову...". При поиске введенное слово не отображается в поле ввода после отправки формы.
Баг с вводом года 1900 так и не исправлен.
В общем, надо поработать на багами. Когда будешь сдавать на проверку, напомни, что у тебя все почти готово и все замечания исправлены.
папки .idea и vendor надо добавить в .gitignore. Их не должно быть в репозитории. Идея в том, что каждый скачавший твой проект запускает композер и устанавливает нужные зависимости сам.
> enum('муж','жен') Обычно используют латинницу. Это ведь все равно идентификатор, а не строка для вывода на экран. В PHP коде в модели студента создаются константы для этих идентификаторов.
> `birth` date Там ведь вроде только год нужен был, или ты дату вводишь?
> `hash` varchar(100) NOT NULL, Нужно бы добавить комментарий к этой колонке, что там хранится и зачем.
В таблице надо проставить уникальные ключи для колонок, значения которых не повторяются.
Вместо include я бы советовал настроить автозагрузку через композер.
Также, надо понимать, что любые внешние переменные могут отстуствовать. Стоит проверять, что d POST есть элемент searchValue, прежде чем обращаться к нему.
Насчет поиска и показа списка студентов - по моему, это довольно-таки похожие задачи и обычно их делают одним контроллером.
> https://github.com/ghp26/Students/blob/master/public/register.php#L4 > //include "src/DBGateway.php"; инклудиться в валидаторе Вот это верный путь сделать ошибку. Завтра кто-нибудь уберет инклюд из валидатора, и код перестанет работать. Лучше использовать require_once, который подключает файл только 1 раз. А еще лучше - автозагрузку.
Далее, в этом файле https://github.com/ghp26/Students/blob/master/public/register.php у тебя кроме обработки формы идет низкоуровневая возня с куками. Лучше выделить код в отдельный класс, отвечающий за авторизацию, а в контроллере только вызывать методы вроде "получить текущего пользователя", "залогинить пользователя" и тд.
А так у тебя код не повторно используемый, мы не можем где-то в другом месте проверить залогиненность не копипастя код.
> $_POST[email] Строку надо писать в кавычках.
> if (!$_COOKIE["MuhosranskUniversity"]) { Название куки должно отражать ее назначение.
> header("location: index.php"); После выдачи заголовка у тебя скрипт не завершается, а продолжает работать.
В register.php у тебя 3 вызова $displayer. Получается слишком запутанная логика и легко пропустить какую-то ветку и ничего не вывести. Предлагаю упростить код, оставив единственный вызов внизу файла.
В шаблоне шапка и подвал страницы (<head>) скопипащена в оба файла. Не надо копипастить, надо вынести ее в отдельный файл.
Для подключения твига не надо вручную делать require, достаточно где-то в начале скрипта приинклудить vendor/autoload.php и все библиотеки из композера будут подключаться сами.
Смысл класса Displayer не очень понятен. Не проще ли из контроллера сразу вызывать твиг?
> https://github.com/ghp26/Students/blob/master/src/Displayer.php#L46 > 'name' => $profileData['name'], > 'surname' => $profileData['surname'], > 'sex' => $profileData['sex'], Удобнее не передавать поля по одному, а передать весь массив. А еще правильнее использовать ООП, и передавать модель Abiturient.
> foreach ($errorsArray as $key => $value) {//в $errorsArray будет единственное значение > $errorKey = $key; > $errorMessage = $value; > } Не очень понятен смысл этого действия. Чтобы взять последний элемент, кстати, можно сделать $value = end($array); $key = key($array), почитай мануал по этим функциям.
> print_r($errorKey); забыл отладочный код
https://github.com/ghp26/Students/blob/master/src/Abiturient.php#L15 > public function __construct($values) не очень удобно, что нельзя создать пустого студента и заполнять постепенно, а надо передать все поля сразу. Часто необходимо именно создать модель с значениями по умолчанию.
https://github.com/ghp26/Students/blob/master/src/DBGateway.php Если ты захочешь создать еще одну-две таблицы, ты будешь код работы с ними тоже писать в этот класс? Обычно для каждой таблицы делают свой Gateway и соответственно отражают это в названии класса.
Можно собрать выражение по частям, это же обычная строка. Не забудь обработать свою переменную через preg_quote, чтобы заэкранировать спецсимволы в ней, чтобы они тоже искались правильно.
Они нужны чтобы обрабатывать обращения к свойствам программно, создать видимость что у объекта есть свойства которых на самом деле нет. Это обычно в библиотеках и фреймворках используется.
Ну например можно сделать чтобы при обращении к $obj->name вызывался бы метод getName().
Или если например есть старый код, который пишет данные в свойства, а мы хотим перехватывать эти обращения и проверять данные.
Магическими методами лучше не злоупотреблять, так как они затрудняют понимание кода.
> Зачем нужны магические методы __get и __set, ведь если их определить, то по сути свойства станут публичными – какой смысл в их private? Их можно использовать по-разному. Не только как ты написал. Или можно добавить какие-то проверки перед записью данных в свойство.
> Гугли glide, мне хватает. Только там еще десяток есть. Где гарантия что в итоге все не пересядут на что-нибудь другое?
А так, надо будет попробовать. Если бы ее не установка через shell скрипт, который что-то непонятно куда скачивает и распаковывает. Прямо как пользователь винды себя чувствуешь.
А встроенный go get просто скачивает пакет непонятно какой версии непонятно куда и непонятно как это интегрировать в обычный проект с гитхаба.
>> И еще нет никакой логики в организации кода. > За этим сам следи. Вообще странно на это жаловаться в треде php В пхп как раз с этим все в порядке: PSR-4, каждый класс в своем файле. После этого лапшу из хаотично разбросанных функций начинающихся то с маленькой, то с большой буквы, тяжело воспринимать.
Задать max-width и margin auto. Вообще, эта особенность блоков - это основы CSS, которые изучаются в самом начале. если ты это не знаешь, возможно тебе стоит подучить CSS и пройти наши задачки на CSS из ОП поста. Тогда верстка не будет для тебя представлять особой сложности.
>>872095 > Где гарантия что в итоге все не пересядут на что-нибудь другое? Это не js, да и функционал в целом опирается на заложенный в самом языке. В целом сама идеология говорит что каждая новая версия пакета должна быть обратно совместна со следующей, но от дураков защиты нет. > В пхп как раз с этим все в порядке: PSR-4, каждый класс в своем файле. Счастливый человек. Я php начал с 4 ещё на поддержке проекта говнокодеров, вот это ад во плоти.
В целом хочу сказать что от го многого ждать не стоит, это не сильвер булет и во многом на php удобней писать средние и даже большие проекты. Но когда нужен маленький и быстрый сервис, с высокой отказоустойчивостью го почти нет равных.
>>871829 Все, понял в чем была проблема. Я просто не уточнил в начале, мне надо было эти параметры задать через @media и вышло так, что display: none не работал из-за того, что уже задан дисплей у блока, которому я хотел задать значение. >>872095 >Задать max-width и margin auto Не, не, это я знаю, я спрашивал о том, можно ли задать width или max-width в процентах, а потом его выровнять, пример выше работает только с шириной в пикселах. > возможно тебе стоит подучить CSS и пройти наши задачки на CSS из ОП поста Спасибо, гляну что здесь у вас.
> } elseif ($oversum <= 5000) { Можно просто else, условие не требуется.
> Ответ на любой вопрос Верно.
> Шифр О, хорошо сделано.
> Лев Толстой > http://ideone.com/PWMgWZ > if (is_array($someword) == true) { Можно просто if (is_array($someword)) так как if по сути приводит значение в скобках к true или false и в зависимости от этого выбирает, выполнять ли код. Оператор == сам возвращает true/false и соответственно проверка вроде == true по сути возвращает то же самое значение. Смотри мануал http://php.net/manual/ru/language.types.boolean.php
Ты забыл еще букву "Я", но в остальном, решено верно.
> Айпады.
Число 5000 встречается много раз в коде, должно быть только в одном месте. Код в ветках ифа почти одинаковый, хорошо бы избавиться от дублей.
> } elseif ($debt < 0) { > // echo "Что-то пошло не так."; Ну так тут exit надо писать, если уверен что твой код правильный и это никогда не сработает.
Я не вижу особых причин, почему код на Го будет при прочих равных лучше кода на PHP. Да, там есть система типов, это плюс, но нет классов и стандартов, а значит будет типичный сишный бардак.
>>872167 > Я не вижу особых причин, почему код на Го будет при прочих равных лучше кода на PHP. Он не лучше, он другой. Нужен онлайн магазинчик - php, нужен чатик для обратной связи или нужно заткнуть высоконагруженную часть - go.
> нет классов и стандартов Структуры и интерфейсы. Стандарты вообще самые жёсткие из всех языков пожалуй, но опять же они отличаются от php.
> Вообще-то менеджеров пакетов там не меньше 10 Лучшие из них основываются на работе компилятора go с vendor. На пакетном менеджере по сути только хранение версий.
> Но все приходится писать руками. По этому я и не говорю что go подходит для написания больших программ.
Я вот пишу парсер сайта и мне нравится что я могу запустить сразу 500 корутин и особо не волноваться.
Вот это вот обсуждение рейтнга языков - это пример постов, которые не приветствуются в нашем треде. Давайте заниматься изучением программирования, а не пустыми обсуждениями. Не нравится PHP - не изучайте.
Классы IncomingDamage и FilteredDamage не имеют никакого смысла. Чем IncomingDamage отличается от Damage? Ради чего здесь применено наследование? Какие это выгоды нам дает?
Я вижу только неудобства из-за того, что например какая-то функция приниамет на вход один вид Damage, а у нас есть другой, и надо их преобразовать. Например, функция filterDamage() вынуждена создавать новый объект. Причем она копирует только 2 вида урона, все остальные данные теряются. Если ты даже напишешь копирование всех видов урона, все равно, в будущем добавят новый вид урона и он будет теряться.
Соответственно, если оставить только класс Damage, код упрощается.
Также, я бы еще может убрал метод getTotalDamage, так как наверняка на разных персонажей разные виды урона действуют по-разному и их нельзя складывать.
В классе Armor я бы добавил конструктор, чтобы нельзя было создать защиту, не указав какие-то важные характеристики.
> $this->$elementResist Доллар лишний. Или это специально? Тогда это плохая идея так как внешний код должен знать подробности внутреннего устройства класса (названия приватных полей), да вдобавок еще нет проверки, а есть ли такое поле вообще.
Вот представь, что ты - програмист, который хочет использовать класс в своем коде. Так как внутреннее устройство класса тебя не касается, ты видишь только публичные поля и заголовки методов:
class Armor { public function setArmor($armor); public function getArmor(); public function setElementalResist($elementResist, $resist); public function getElementalResist($elementResist); public function getElementDamageReduction($elementResist); public function filterIncomeDamage(Damage $damage); }
Вот по этому описанию ты должен как-то догадаться, как использовать объект. Не очень понятно, если честно. Например, невозможно понять, что хранится в $elementResist.
Если ты хочешь обощенно работать с разными видами защиты, тебе надо сделать массив и константы для обозначения их видов:
Ты же по сути из объект пытаешься использовать как массив.
Идея ООП в разделении кода по классам, чтобы каждый из них был вроде небольшого независимого модуля. Но разделять надо без фанатизма. Плохо если будут огромные классы, отвечающие за слшком много задач, и плохо, если будет слишком много мелких классов. Надо искать золотую середину.
Все это придумано исключительно из прагмтичных соображений. До ООП код писали процедурно, то есть программа по сути была набором функций и глобальных переменных. По мере того, как объем программы рос, разбираться в этой куче функций было все тяжелее. Кто-то догадался, что функции и данные, с которыми они работают, можно объединить в классы.
Соответственно ты не должен стремиться использовать все паттерны проектирования в своем коде, а должен ответить на вопрос, зачем это нужно? какая от этого выгода? легко ли понять мой код? легко ли использовать? защищен ли он от ошибок?
Учиться можно, решая задачки, а также изучая код фреймворков вроде Симфони, где активно используется ООП.
Во-первых, у нас в учебнике из ОП поста в главе "ООП" есть задачка "кошки-мышки". Можешь для начала ее решить. Далее, есть такая задача:
Напиши систему классов для валидации данных в формах. Ну например, у нас есть форма регистрации, состоящая из разных полей. Надо как-то с помощью ООП задать набор правил и проверить с их помощью данные на правильность.
Система должна быть расширяемой, то есть должна быть возможность добавлять новые виды правил и проверок. Желательно, чтобы классы были переиспользуемыми, например, если есть код для проверки email на правильность, то нужно чтобы им можно было пользоваться и без формы. Правила валидации могут затрагивать несколько полей (ну например, проверка что 2 поля с паролем совпадают).
Соответственно, если у шрифта несколько начертаний, то надо на каждое начертание сделать @font-face с одинаковым font-family, но разными font-weight, font-style и разумеется src.
Также, надо учесть что разные браузеры поддерживают разные форматы, и указать ссылки для нескольких форматов. Также, старый ИЕ не поддерживает несколько форматов, потому для него надо указать ссылку хитрым костылем. есть готовый образец под названием Mo Bulletproof Font-face syntax: https://habrahabr.ru/post/113136/
Питон не десктопный язык. Я бы советовал C#, он хорош, но по факту только под винду (я знаю про кроссплатформенность, но WPF никто не портировал). Либо, если ты хочешь кроссплатформенности, а производительность не очень важна, то HTML/CSS/JS упакованные с помощью программы вроде Electron. Работает кроссплатформенно, высокая скорость разработки, но память будет кушать как браузер.
Вообще, после HTML интерфейсы делать на чем-то другом - сплошная боль и трата времени.
> socket_write() не обязательно записывает все байты из указанного буфера. Нормально то, что, в зависимости от сетевых буферов и т. д., только некоторое количество данных, даже один байт, будет записан, хотя ваш буфер больше. Вы должны следить за тем, чтобы непреднамеренно не забыть передать остаток ваших данных.
Тебе надо обязательно читать мануал по всем использованным функциям, иначе ты не будешь знать особенностей их работы. Сетевые функции чтения и записи, как правило работают так: ты можешь указать любой объем передаваемых или принимаемых данных, но по факту они возвращают выполнение после отправки/получения одного пакета. Если твои данные не влезли в один пакет - ты должен снова вызывать socket_write с остатком данных. И разумеется, любая сетевая операция может дать еще 2 исхода:
- ошибку - EOF, например получатель мог закрыть соединение до передачи/получения всех данных, в этом случае функция возвращает 0 и ты можешь проверить вроде бы через feof(), открыто ли еще соединение.
Ты не проверяешь результат socket_write. И кстати, socket_close тоже может дать ошибку.
Также, твой HTTP сервер не читает запрос от браузера. Сделай-ка чтобы в ответе он передавал полученный запрос, чтобы ты в браузере видел его. Сразу предупрежу, что придется помучаться, так как с первого раза скорее всего запрос будет просто подвисать. Если у тебя есть возможность например отправлять запрос курлом (утилитой), и видеть, на каком месте подвисает, или Wireshark перехватывать трафик, это поможет в отладке.
Архитектура MVC: например, скрипты-контроллеры, шаблоны, и остальные классы образующие модель: классы работы с БД, классы валидации данных. Плюс какие-то дополнительные классы вроде класса с вспомогательными функциями, класса авторизации, защиты от CSRF.
> если есть кука включается главный контроллер(в нем список студентов), если нет - идет форма регистрации и кука устнавливается. Так же не следует делать, да? Лучше делать роутинг с проверкой УРЛ, то есть взять текущий УРЛ из REQUEST_URI и проверять:
если (УРЛ == '/register') вызвать контроллер регистрации если (УРЛ == /) вызвать контроллер списка студентов иначе выдать 404 ошибку
> простой echo-сервер, При ошибке создания сокета надо завершать скрипт.
Не проверяется результат вызова socket_write, не реализована проверка числа отправленных байт и доотправка данных.
При чтении ты предполагаешь что все данные придут одним пакетом. Это не гарантируется. Ты можешь для теста сделать клиент, который шлет по 1 байту за раз, и увидеть что твой код увидит только первый байт.
> socket_read($msgsock, 2048, PHP_NORMAL_READ
Эта функция может вернуть:
- ошибку - пустую строку, что значит что передающий закрыл соединение (аналогично случаю когда при чтении файла мы обнаруживаем конец файла). Ты это не проверяешь и можешь войти в вечный цикл из-за этого.
Также, 2048 это лишь ограничение на объекм полученных данных, вернуть она мжет и меньше, хоть 1 байт.
> if (!$buf = trim($buf)) { Во-первых, не стоит совмещать присваивание и иф. Во-вторых, if (!) сработает если в $buf будет строка "0".
> Напиши простой HTTP-клиент на php > Не уверен, что я правильно понял задание надо написать его на сокетах, а не на курле. Самому сформировать HTTP-запрос. Хотя написание на курле - тоже полезная практика.
Записывать пришедшие данные в фал желательно поточно, по мере скачивания. Если можешь, сделай поддержку gzip сжатия в ответе.
$app->run(); Но силекс в браузере пишет: Sorry, the page you are looking for could not be found. Работаю с nginx, то же происходит и со слимом. Гуглил, но пока ничего внятного по этому вопросу не нашел.
>>872430 Ну и посмотри 15ую, решение получилось короткое, что подозрительно. http://ideone.com/ztZNiF . 16ая судя твоему примечанию очень сложная? Отложить ее после DOM задачек?
всем привет. начал изучать php и всю телегу, поэтому нубский-нубский вопрос: если мы где-то определили строковую переменную вида там $a = '$b + $c' (или просто $a = '2 + 3)', есть какой-то очевидный (правильный, короткий и т.д.) способ эту переменную выполнить как код?
>>872165 Новый пак исправлений. > Школьник и кредит на айфон >Это почти одинаковый код. Попробуй избавиться от повторов строчек. Избавился >Можно просто else, условие не требуется. Исправил. http://ideone.com/yb1bfA
>Ты забыл еще букву "Я", но в остальном, решено верно. Есть такое решение, но мне оно ужасно не нравится. Новый массив строк и снова код менять. http://ideone.com/X8kp2g Есть ещё такое, гораздо "эластичнее". http://ideone.com/FV1P5O
Обьединил в один класс. >Слишком длинный номер считается почему-то верным: Очень странно пикрил говорит что нет, или ты про другой? http://ideone.com/P2kkv1
>>869823 Почему скрипт должен быть заключен в <?php?> Почему именно в это? Раз мы пишем на php, то понятно что это php. И как оно расшифровывается? В моем учебнике указывается Hypertext Preprocessor, но если сократить то выйдет только hp
То, что не заключено в <?php просто выводится как есть. Этот синтаксис позволяет делать например HTML шаблоны с вставками PHP кода.
PHP задумывался как простой язык, позволяющий добавлять веб-страницам динамическое содержимое. Первоначально программа на PHP обычно состояла именно из HTML кода с небольшими вставками PHP.
> И как оно расшифровывается? PHP = PHP Hypertext Processor. рекурсивный акроним. Первоначально имелось в виду Personal Home Page.
Нормеа телефонов > (^ ?8|^\+ ?7) >^ можно вынести за скобки
> echo " ".phoneNumberCheck($correctNumbers[$i])." \n "; >Но функция phoneNumberCheck() ничего не возвращает, а ты пытаешься ее результат вклеить в строку.
>>872217 Спасибо большое за такой развернутый ответ. Ну я просто новичек, и когда у тебя 0 опыта, перед тобой постоянно всплывают выборы в которых ты понятия не имеешь как лучше поступить, сделать так или иначе, создавать еще 1 класс или обойтись одним, делать ли метод тут или там и прочее. В общем вот примерно какая была у меня логика: >Классы IncomingDamage и FilteredDamage не имеют никакого смысла. Чем IncomingDamage отличается от Damage? Ради чего здесь применено наследование? Какие это выгоды нам дает? Ну я подумал, что IncomingDamage будет передаваться именно в Armor, что бы та его обрабатывала, а FilteredDamage уже например существу, что бы непосредственно снижать его здоровье.
>Причем она копирует только 2 вида урона, все остальные данные теряются. Потому что просто набросок, в теории будут обрабатываться все виды урона, причем всеми возможными механиками. Опять же думал что если добавлю новую механику, то легко расширю ею класс Armor.
>акже, я бы еще может убрал метод getTotalDamage, так как наверняка на разных персонажей разные виды урона действуют по-разному и их нельзя складывать. Конечно по разному, в зависимости от защиты и прочих резистов. Но суть в том, что урон хоть и может быть смешанным аля ОГНЕННАЯ СТРЕЛА (физик + фаер), то у существа в итоге нужно отнять какое-то фиксированное количество жизней. Для этого и нужен метод, что бы собственно после всех резистов взять этот тотал дамаг и отнять из хп.
>Доллар лишний. Или это специально? Тогда это плохая идея так как внешний код должен знать подробности внутреннего устройства класса (названия приватных полей), да вдобавок еще нет проверки, а есть ли такое поле вообще. Я подумаю. Просто я столкнулся с тем, что выше писал в треде вот этот господин >>871884 и придется для каждого резиста писать по 2 метода только что бы БЛЮСТИ ИНКАПСУЛЯЦИЮ, хз кароче как пока с этим разобраться. Если расширять в перспективе еще 1 резистом, то и так придется ВСЕ методы переписывать которые обрабатывают входящий урон и прочее. Хоть резисты блин в массиве храни, что бы можно было форичем обходить их. Ну или как-то так :(
Анончики, хожу за бесплатно на практику с возможностью трудоустройства.
В принципе, почему бы и нет, так бы все равно дома сидел, поначалу дали пару полезных заданий учебных, я их кое как сделал, теперь дали подправить в коммперционном проекте 2009 года, код пикрелейтед, написанный на первом зенде, все такое старинное, что просто пиздец.
Шо делать, анончики? Терпеть или сьебывать оттуда? Я хожу туда, чтобы учиться и развиваться, а не ковыряться в говне.
Требуется помощь в составлении правильного SQL-запроса. Ситуация такова: есть 2 таблицы:
1) поля 'uid' (INT) и 'quantity' (DECIMAL 9,2) 2) поля 'id' (INT AUTOINCREMENT) , 'quantity' (DECIMAL 9,2) , 'uid' (INT)
Первая хранит расходы, вторая - поступления.
Поле 'uid' - это номер из внутреннего учета (для бухгалтерии). Он уникален для каждой уникальной вещи (например вот этот стул и ни какой другой). 'quantity' соответственно количество поступления и расхода.
Нужно составить выражение, при котором будет подсчитываться баланс, то есть количество всех прибывших вещей за вычетом ушедших.
Пока что родить смог только нечто подобное:
SELECT DISTINCT `uid`, ((SELECT SUM(`quantity`) FROM `incomes` WHERE `uid` = `uid`) - (SELECT SUM(`quantity`) FROM `demands` WHERE `uid` = `uid`)) AS `balance` FROM `incomes`;
Этот запрос на выходе дает таблицу из уникальных 'uid' и вторым полем по идее должен давать баланс, но там всегда одно число. Проблема, возможно, там где выделено жирным, а может и во всем запросе. Как не пытался сформулировать вопрос для гугла - выдает не то, даже близко нет.
не знал, что ты юзаешь неймспейсы, тогда все окей.
в добавок скажу, что подключения разных автолоадеров и конфигов должны находиться в отдельном файле от создания классов и функций и тому подобного, в стандартах это описано
>>872943 >в добавок скажу, что подключения разных автолоадеров и конфигов должны находиться в отдельном файле от создания классов и функций Это как? Т.е. >>872893 как тут я сделал нельзя? Как тогда правильно сделать?
> spl_autoload_register(autoload); Строки надо заключать в кавычки.
> require_once '/' . $class . '.php'; это абсолютный путь, то есть он отсчитывается от корня диска. Маловероятно что все файлы будут лежать там. Особенно если речь про Линукс, где дисков нет и корень у файловой системы один.
Плюс, имя класса может быть с нейспейсами и бексешами. Это ты не учел.
Также, класс может отсутствовать. Ну например если написать
if (class_exists("ZZZZZ"))
С именем несуществующего класса то это вызовет ошибку при попытке подключить файл ZZZZZ.php
> в добавок скажу, что подключения разных автолоадеров и конфигов должны находиться в отдельном файле от создания классов и функций и тому подобного, в стандартах это описано Можно ссылку?
Скорее всего тебе нужен юнион. Хотя я толком не понял условия задачи, например если uid это идентификатор одной вещи, то зачем там поле с количеством если уникальная вещь может быть только одна?
Я бы тебе советовал посмотреть наши задачки по SQL из ОП поста, чтобы лучше в нем разбираться. Или почитать любой учебник по SQL. Тут нельзя наугад переставлять запросы в надежде что заработает.
> Потому что просто набросок, в теории будут обрабатываться все виды урона, причем всеми возможными механиками. Опять же думал что если добавлю новую механику, то легко расширю ею класс Armor.
Это неправильный подход. Если делать как ты предлагаешь, то потом кто-то добавит новый вид урона в класс Damage и не обновит класс Armor потому что не знает что его надо обновить.
Правильно либо не пересоздавать объект либо сделать в самом Damage функцию для создания новой версии объекта.
Ты должен писать код в расчете на обычных людей, а не на то, что твой код будут поддерживать гении-вундеркинды с способностью к телепатии.
> Для этого и нужен метод, что бы собственно после всех резистов взять этот тотал дамаг и отнять из хп. Вообще, у разных существ может быть разная восприимчивость к видам урона, логичнее сделать у существа метод "принять урон", а не закладывать что он всегда складывается.
> Если расширять в перспективе еще 1 резистом, то и так придется ВСЕ методы переписывать которые обрабатывают входящий урон и прочее. Хоть резисты блин в массиве храни, что бы можно было форичем обходить их. Ну или как-то так :( Я тебе выше и написал, что можно хранить виды дамаджа в массиве.
> foreach ($autonombers as &$value) { зачем тут & ?
> [АВЕКМНОРСТУХ|A-Z] Тебе надо перечитать про символьные классы. Если ты ставишь вертикальную черту после X, почему не ставишь ее между остальными буквами?
В квадратных скобках вертикальная черта обозначает саму себя.
Круглые скобки там не нужны.
Имя функции принято начинать с глагола: checkNumber
- убрать else - убрать $credit = 0; $worthMoney += $oversum; - использовать min/max для расчета суммы месячного платежа
> Лев Толстой > if ($i==9) { // плохое решение если добавить массивы, но как по другому отследить последнюю строку я не знаю Букву Я можно просто положить в массив со структурой стиха.
> Есть ещё такое, гораздо "эластичнее". Так и надо делать.
> Ну и к айпадам применил модификации. Тоже можно упростить как и айфоны.
Посоны, объясните! ковыряю yii2/ миграции. И вот что тут нашел {{%user}} что это за хуйня? видал такое и раньше, но не придал значение. Предполагаю что это переменная или ссылка на нее, но почему так, чтоб я не понял? реквестую объяснения или хоть где почитать про такое явление.
>>873019 >Тут нельзя наугад переставлять запросы в надежде что заработает.
Вот это я уже ощутил. Буду больше читать тогда.
uid это идентификатор ти'па вещи, которой может быть много (например, "молоко простоквашино 2,5% жирности 0,5мл" - обозначает только определенный уникальный продукт, которых может быть quantity - много-много штук, постепенно прибывающих и убывающих). Итоговый результат селекта должен как раз выводить пару 'тип предмета' - 'остаток', и состоять по логике из уникальных первых значений. Короче, я не могу даже здесь объяснить, аргх.
>>873130 Давай я тебя научу: 1. ОТкрываешь свою страничку с JS скриптом в браузере. 2. Нажимаешь F12, идешь на вкладку Net/Network/Сеть 3. Обновляешь страничку. 4. Смотришь на появившиеся запросы - ищешь свой. 5. Если не нашел - идешь на вкладку Console/Консоль и смотришь ошибку. 6. Если нашел, но PHP не работает - ставишь первой строкой своего скрипта print_r($_POST) 7. Смотришь, что PHP получил. 8. Думаешь 9. ??? 10. ПРОФИТ
Если сюда, то сюда, если нет то извиняйте: для юникс (линукс)-подобных для верстки html/css подскажите годноту по программам. В идеале отображение html кода и css кода сразу (т.е либо 2 окна либо удобное переключение между ими).
Переменные надо было назвать получше. Параметры задачи (5000, 0.03 итд) лучше указывать в начале задачи как переменные, чтобы их было легко поменять и чтобы было понятно, что это за числа. У тебя ничего не понять.
Тебе надо не гуглить, а изучить яваскрипт, основы HTTP и jQuery. (в ОП посте кстати есть задачки). Гугление не поможет так как вряд ли кто-то специально для твоей задачи решение напишет.
ОП, ты советовал написать тесты на файлообменник, возник вопрос, на какие методы нужно писать тесты? На геттеры и сеттеры свойств модели не надо же? Надо только на методы которые внутри себя совершают какие-то действия? С phpunit немного разобрался, но не могу уяснить для себя когда это нужно применять. В туториалах рассматриваются примеры с арифметическими действиями или заполнением массива, такие вещи тоже нужно тестировать?
А зачем вообще писать тесты? Очевидно, чтобы иметь возможность быстро проверить: работает ли кусок кода корректно или нет.
Ну например, мы поручаем начинающему разработчику Васе добавить какую-то фичу или провести рефакторинг и можем проверить, все ли в порядке после его вмешательства.
Тесты часто запускают автоматически, например специальная программа следит за репозиторием, как только видит там новый коммит - выгружает код на тестовый сервер и прогоняет тесты. При наличии ошибок бот пишет об этом в чат разработчиков, иногда даже с указанием автора коммита, после которого тесты сломались.
Также, надо понимать, что написание тестов не бесплатно - на них надо тратить время.
Исходя из этого, понятно, что в первую очередь мы заинтересованы в написании тестов на сложный код, который легко сломать. А тесты на сеттеры ... ну конечно теоретически там можно что-то сломать, но это надо уже специально вредительством заниматься.
> В туториалах рассматриваются примеры с арифметическими действиями Это просто для примера. Они тестируют функцию сложения, а ты тестируй например функцию преобразования имени файла.
Лучше всего, когда тест ведет себя так же как пользователь кода. Если ты тестируешь класс, то тестируешь его публичные методы, не привязываясь к внутреннему устройству класса. Если тестируешь интерфейс то опять же стараешься имитировать действия пользователя, а не лезть напрямую во внутренности кода.
Сами тесты как правило пишут на основе требований к функции или странице. Ну условно говоря, ты пишешь функцию выбора имени файла для хранения и предъявляешь к ней такие требования:
- имя файла должно иметь длину в заданных пределах - имя файла должно содержать только разрешенные символы - имена файлов должны быть уникальны даже если исходные имена одинаковые
Ну вот осталось только это тестами проверить. Аналогично проверяется интерфейс. Ну например, есть страница загрузки файла. К ней предъявляются такие требования:
- при выборе файла и загрузке пользователя должно перекинуть на страницу просмотра файла. При скачивании файла мы должны получить назад загруженный файл с тем же именем и содержимым - при отправке пустой формы мы должны получить сообщение об ошибке
Вот опять же из требований мы получили основу для написания тестовых сценариев.
То есть берем требования, пишем тестовые сценарии, пишем код тестов.
Если времени совсем нет, то можно сделать smoke test - просто вызвать функцию или загрузить страницу и просто проверить что не произошло никакой ошибки. Это лучше чем отсутствие теста.
В файлообменнике я вижу такие тесты:
- юнит-тесты отдельных классов и функций, где есть какая-то логика - возможно, тесты для проверки взаимодействия нескольких классов. Ну например, тест, тестирующий загрузку и сохранение файла с записью данных в БД. - тесты интерфейса для страниц сайта
Советую показать тесты на проверку. Также, могу прокомментировать тестовые сценарии.
Тут кто-то пользуется эклипсом? Я вот доволен им неимоверно, но не хватает всего одной фичи - хочется создавать классы по клику, а не создавать пхп файл, потом прописывать название класса и неймспейс.
>>873461 Первая иде была именно эклипс, но быстро переполз на нетбинс. В 2 раза быстрее, темы встают нормально, нету этих дурацких перспектив и вообще збс. По твоему вопросу сказать нечего, никогда это не парило.
У меня в саблайме плагин прописывает неймспейс на основе пути к файлу нажатием одной кнопки.
Алсо вот это вот расширение http://p2.pdt-extensions.org/phpfeatures.html вроде как поддерживает создание класса через диалог (но мне кажется, тут с тобой что-то не так, по идее руками должно быть быстрее).
>>873482 Спасибо, попробую. Ну не знаю насчет удобно/не удобно, но имхо легче сразу же указывать название класса и неймспейса, таким образом в зендстудио можно даже каталоги сходу создавать.
>>873488 Добавлю ифов для троеточий и цикл буду организовывать с -3 до +3 от нынешней страницы, ничего особо не изменится. Если я правильно тебя понял.
Надо проверить телефонные номера через регулярное выражение.
>Подсказка: не надо строить сложных выражений и предусматривать все возможные комбинации символов. Достаточно написать: сначала идет +7 или 8, за ними ровно 10 цифр, между которыми может быть любое число скобок, минусов, пробелов
$regexp = '/^(\+7|8)[0-9]{10}$/u';
Здесь соовтетсвенно проверка, что в начале +7 или 8 и десять цифр. А вот как записать, что между цифрами было сколько угодно скобок, - и пробелов я не пойму. Пиздец какой-то, нихуя не соображу.
Там будут еще другие условия, например, отдельную ссылку на 1-ю страницу не надо выводить, если она есть посередине. Такую логику неправильно писать в шаблоне и логично перенести ее в класс, отвечающий за пагинацию.
>>873512 >Попробуй написать выражение "одна цифра, за которой идет любое число скобок, пробелов, минусов".
Ну, моей фантазии хватает только на такое: $regexp = '/^(\+7|8)[0-9](\(\-\s\))*$/u'; но похоже несу лютый порожняк, потому что конечно же не работает. Как меня вымораживают эти спецсимволы.
Хм. Я кажется понял почему у меня нетбинс медленно работал - я раньше качал пакет, в котором сразу же все фичи были. Сейчас скачал пакет только с пхп, аштиемель/цсс и яваскриптом и все залетало, не хуже эклипса, а функциональность больше. Алсо, поясните мне чего все так носятся с пхпштормом? Что в нем такого крутого по сравнению с тем же нетбинсом, который вроде все основные преимущества дает, но при этом швабодным и быстрый?
Не обращайтесь непосредственно к суперглобальному массиву $_SERVER.
Вместо этого можно использовать функции фильтрации (например, filter_input(), conditions with is_() functions и др.). ----* Вот такое мне выдает нетбинс когда я использую $_SERVER['REQUEST_URI'] в методе класса. С чего бы это было плохо?
>>873486 >>873512 >Там будут еще другие условия Ну ок, теперь совсем все переделал. ОП, ты просил напомнить, что >Когда будешь сдавать на проверку, напомни, что у тебя все почти готово и все замечания исправлены. https://github.com/never3ver/students_list
Пишу проект с нуля для довольно крупного (по сравнению с моими предыдущими работами) сайта-магазина, посещаемость в день планируется около 4-5 тыс. человек. На данный момент идёт тестирование и допиливается фронтенд (заказчики из серии "кнопкуПовышеМожно?"). В общем в чём суть вопроса: вся html-часть состоит из множества (около сотни) файлов-чанков по 1-2 кб, и всё это дело вызывается в движке функциями с file_get_contents() и подстановкой значений из базы с помощью strtr() вместо каких-то переменных по типу {MENULIST}. Концепция в том, что чем меньше HTML внутри php, тем лучше. Так вот иногда на сервере возникают ошибки функции file_get_contents(), мол, не удалось выполнить HTTP-запрос, ошибка 503. F5 - всё ок. Но раз в 15-20 запросов такая шляпа возникает. Вопрос: забить ли на это хуй (ведь, когда тестирование закончится, я припилю на всё это дело memcached), изменить логику в сторону уменьшения количества запросов к файлам, или поменять хостинг (beget)?
>>873552 И ещё вопрос вдогонку: Хорошая ли практика для передачи значений переменных в js использовать код по типу:
(В HTML-шаблоне) ... <script> var a = {NUM}; </script> ...
(PHP) return strtr($template, ['{NUM}' => $a]);
Или лучше закидывать переменные в hidden input'ы, или, как на первый взгляд кажется наименее костыльно, всё-таки для получения вообще всех данных с бэкенда выполнять get-запросы непосредственно из js?
>>873557 2) Нормальная практика, нужны переменные - генерируй код, нужны данные форм - делай инпуты. Я делал и так, и эдак - никто не умер. 1) Похуй что там на бекенде с чанками, раз горячие данные все равно в мемкеш.
>>873582 Так, что-то я запутался. Я думал, что ТДГ это типа есть класс Users, и для него создается класс для работы с БД UsersGateway с объектами типа insert, delete и прочее, но это датамаппер, а из уроков ОПа я что-то вообще не понял что такое ТДГ - как это для работы с разными сущностными использовать один класс?
Судя по описанию твой код это набор плохих практик. Дабы другие аноны не использовали их в своих проектах, опишу подробнее:
1) не надо писать свой кривой велосипедный шаблонизатор, есть twig который по возможностям раз в 100 мощнее "шаблонизатора" на strtr() 2) для получения данных по HTTP есть нормальные HTTP-клиенты 3) разобраться, почему происходят ошибки, надо 4) в принципе неправильно если при генерации обычной страницы ты шлешь куда-то HTTP запросы
> Концепция в том, что чем меньше HTML внутри php, тем лучше. Ты плохо понял идею. Идея в том, чтобы отделить логику отображения страниц от логики обработки данных.
Плохо сделано. А что если в переменной есть что-то, кроме цифр? А что, если она пуста?
В twig я делаю так:
var a = {{ a | json_encode | raw }};
В качестве домашнего задания оставлю тебе и другим анонам объяснить, как это работает, насколько надежно и зачем там raw.
> , всё-таки для получения вообще всех данных с бэкенда выполнять get-запросы непосредственно из js? Какой смысл делать запрос, если можно обойтись без этого?
TDG принято называть класс, который содержит в себе все методы для работы с определенной таблицей. Дата маппер - класс, который отображает записи из БД на объекты. То есть TDG может включать в себя и функционал дата маппера, и что-то еще сверх того.
Также даю ссылки на перевод статей Фаулера по этим классам, попробуй сравнить их самостоятельно:
>>873607 >Это почему? То я сначала все вообще не так понимал. >Также даю ссылки на перевод статей Фаулера по этим классам, попробуй сравнить их самостоятельно: Честно говоря, так и не понял в чем разница. А вот это вообще даже примерно не понял: >Это что-то напоминающее DataMapper, но он может быть реализован без объектов-сущностей. https://gist.github.com/codedokode/c4cbc4d7dc8e45ea074a
>>873616 Короче в TDG можно делать так: $userGateway->setName($id, 'Новое имя') и объекты-сущности не требуются. В DataMapper будет так: $user = new User(); $user->setName = 'Новое имя'; $userMapper->persist($user);
>>873635 >$userGateway->setName($id, 'Новое имя') Зачем $id? > и объекты-сущности не требуются. А как отображать данные? Ну т.е. вот у меня есть метод getAll. Где-то там в недрах есть код return $sth->fetchAll(\PDO::FETCH_CLASS, $class) - и что тогда вместо класса?
Читаю ссылка на ТДГ в Зенд. https://framework.zend.com/manual/1.12/ru/zend.db.table.html у меня сложилось впечатление, буд-то ТДГ скорее на эктив рекорд похоже. Я похожий велосипед недавно писал, как тут все наследуются от Zend_Db_Table, так у меня был класс Model, в котором были методы для работы с БД, а в наследованых классах-сущностях я только добавлял соответствующие поля и название таблицы. Или это у меня не эктив рекорд был?
TDG принято называть класс, который содержит в себе все методы для работы с определенной таблицей. Дата маппер - класс, который отображает записи из БД на объекты.
> А вот это вообще даже примерно не понял: >>Это что-то напоминающее DataMapper, но он может быть реализован без объектов-сущностей.
Имеется в виду, что в TDG может быть метод updateName($userId, $userName), а в Data Mapper обычно сначала загружают объект в память, меняют ему имя и сохраняют обратно в БД. Но зато некоторые Data Mapper вроде Doctrine умеют сами искать измененные объекты и автоматически сохранять эти изменения.
Неправильный пример. new User создаст нового пользователя. Редактирование делается так:
$user = $userMapper->findById(10); $user->name = 'Новое имя'; $userMapper->save($user); // или, в продвинутых мапперах, просто $mapper->flush(), а дальше он сам найдет измененные сущности и сохранит их
>>$userGateway->setName($id, 'Новое имя') > Зачем $id? А как без него понять, какому именно пользователю мы меняем имя?
>> и объекты-сущности не требуются. > А как отображать данные? Ну т.е. вот у меня есть метод getAll. Где-то там в недрах есть код return $sth->fetchAll(\PDO::FETCH_CLASS, $class) - и что тогда вместо класса? Имелось в виду, что для выполнения update() можно обойтись без загрузки и сохранения сущностей. В отличие от Data Mapper.
class Bugs extends Zend_Db_Table_Abstract { protected $_name = 'bugs'; }
Класс Bugs это класс для работы с таблицей, один его объект обеспечивает доступ ко всей таблице. С помощью этого объекта можно загружать и изменять любые строки.
В актив рекорд же методы работы с таблицей размещаются в модели, и один объект модели соответствует одной записи в таблице. И с его помощью можно менять только эту запись.
При этом в зенде некоторые методы выборки из БД возвращают объекты класса Zend_Db_Table_Row_Abstract. Они реализуют паттерн Row Data Gateway, то есть позволяют изменять соответствующую запись в БД и чем-то в этом плане напоминают актив рекорд.
Это абсолютно безопасно. Согласно стандарту HTML содержимое тега script (а также style) воспринимается как есть и HTML-сущности там не декодируются. То есть если внутри script написать & quot то это будет воспринято буквально, а не как кавычка.
Если raw не использовать, то твиг заэкранирует спецсимволы и может получиться некорретный яваскрипт вроде
var x = & quot ; test & quot ;;
Вместо
var x = "test";
Единственный риск тут - если в наших данных содержится закрывающий тег </script> то можно закрыть тег script и вставить произвольный HTML. Но json_encode заменяет слеш / на \/ и потому закрывающий тег там не получится - получится <\/script>'
var x = '<\/script>'; // это не закрывающий тег
То есть то, что я предложил, основано на изучении стандарта и особенностей json_encode. Разумеется, большинство разработчиков, в том числе иностранных, почему-то не следует моему совету и придумывают каждый свой способ, либо с ошибками, либо с уязвимостями. Не хотят учиться.
Если используется шаблон на php то вывод еще проще:
var x = <?= json_encode($x); ?>;
Этот способ позволяет передать из PHP в JS любые значения, включая массивы и хеши.
А без json_encode очень легко сломать JS. Ну например, в JS строках не разрешен перенос строки, и как я выше написал, если вставить строку </script> то можно закрыть тег script.
Так как JSON является (почти) подмножеством яваскрипт, то (почти) любой JSON код является валидным JS-выражением. Что бы мы не передавали в json_encode, мы получим (почти) валидное выражение.
(почти) здесь относится к паре экзотических символов которые недопустимы в JS строках, но допустимы в JSON:
К счастью (проверил экспериментально) json_encode кодирует эти спецсимволы как \u2028, а не вставляет как есть, и таким образом генерирует валидный JS-код.
>>873738 Теперь почти все понял насчет ТДГ и дата мапера. Кроме одного - допустим мне нужен метод getAllNews что бы отображать новости на главной. В каком виде их выгружать из БД? Сохранять в виде масива объектов того же ТДГ, или же просто массив массивов делать?
Ребятааааа, а есть среди вас те, кто может странички вконтакте взломать? Очень нужно. Дело тянет на уголовщину а-ля хабаровска, а доказать причастность не можем
Вебом последний раз занимался в 2010-м, мама попросила запилить ей магазин для продажи шмоток-тряпок (авито уже не катит), порекомендуйте пхп магазин, чтобы поднять и настроить методы оплаты для русского покупателя, без лишнего геморроя?
> Сохранять в виде масива объектов того же ТДГ TDG представлят объект для работы с базой данных, а не новость. Ты все равно все путаешь.
Открой урок и посмотри на пример класса NewsTableGateway. Он не может представлять новость так как у него нет нужных полей, вроде заголовка, текста новости и тд.
Чтобы представить новость, делается отдельный класс News, пример которого тоже есть в уроке.
Соответственно метод getAllNews() может возвращать массив объектов News. Иногда возвращают массив массивов, чтобы не делать отдельный класс для новости, но код в таком случае быстро превращается в лапшу, становится легко допустить ошибку итд.
>>873527 Ладно. Тогда ответ на твой предыдущий вопрос: >Попробуй написать выражение "одна цифра, за которой идет любое число скобок, пробелов, минусов".
>>873864 >Чтобы представить новость, делается отдельный класс News, пример которого тоже есть в уроке. Понял. Вот это мне и нужно было. Но с моей колокольни выглядит несколько неудобно то, что приходится делать пустой класс чисто для отображения. Ну да и ладно. Кстати ОП, а ты будешь делать уроки по всяких паттернам окромя баз данных? Ну там всякие фабрики, фасады, декораторы? Уж больно годно у тебя получается. Алсо есть такой баг или фича непонятная в IDE - когда я делаю класс синглтононом я не могу смотреть их через автодополнение. Такая хуита в нетбинсе и эклипсе. Что бы это значило? Это баг, или я чего-то не понимаю в ООП и паттерне синглтон?(использую синглтон для класса соединения с БД)
Добрый день, парсил с помощью curl большой инет магазин (700к товаров) и вроде как парсил мелкими порциями но (250 товаров раз в 15 минут) но теперь ловлю ответом access denied. Сервер мой стоит на виртуалке убунты, внешний IP у неё такой же как и на основной машине. При этом с браузера я могу зайти нормально, а именно curl нарывается на баг, пробовал сменить CURLOPT_USERAGENT - не помогло. Если бан дали не на IP и не на IP + useragent - тогда на что?
В ie7,8 ширина body всегда равна ширине окна. А вот в ie6 всё хорошо.
Даже оригинальный otf формат шрифта главного заголовка не отображается в ie6-8. В отличие от шрифта Lato.
Стили и вес моего семейства шрифтов Lato распределяются как попало:
firefox, webkit Наличие описания веса bolder переопределяет значение normal, т.е. c regular на bolder ie<8 Цифровые значения веса наклоняют шрифты с жирным начертанием ie Лёгкие шрифты становится жирными firefox Лёгкие шрифты не определяются
Если убрать описание шрифтов с цифровым значением веса, то в webkit'е так же ломается отображение легких шрифтов - они становиться жирными. Далее, если убрать описание bolder, то абзацы вместо того чтобы стать lighter становится regular, т.е. normal. Однако, это чинит наклонность шрифтов в ie<8.
>адаптивность Теперь должно быть лучше. При ширине в 320px всё выглядит хорошо, а вот если сжимать больше, то изображения и другие элементы будут вылазить за пределы тела в зависимости от своих размеров.
Ещё я заметил странный отступ у ссылок на соц.сети в webkit'е. Его задает ul, menu, dir { user agent stylesheet display: block; list-style-type: disc; -webkit-margin-before: 1em; -webkit-margin-after: 1em; -webkit-margin-start: 0px; -webkit-margin-end: 0px; -webkit-padding-start: 40px; }
Что это такое?
Удивительно то, что в остальных браузерах элемент выглядит точно так же - без отступа, но на том же месте.
>переработка базовых стилей >Далее, тебе надо проработать базовые стили CSS. Сделай новый файл с пустым body и впиши в него простой HTML без классов, с тегами вроде h1, h2, ul, li, p, a, img, blockquote (если нет фантазии или лень писать, скопируй с http://motherfuckingwebsite.com/ ). У тебя этот текст выводится бледно-серым на белом фоне - это значит, базовые стили не продуманы совсем. Ты написал не базовый CSS для всего сайта, а стили для единственной страницы и при добавлении новых страниц твой ксс придется значительно переделывать. А нужно добиться чтобы на этой странице все заголовки и т.д. были как на главной странице? Как быть с цветом? В шаблоне половина страницы с черным фоном, половина с белым - тяжело догадаться какой будет у остальных страниц. Всегда должен быть белый?
Я старался найти ответы самому. Я могу хотя бы рамках обучения спросить подсказку? Учитывая что я первый раз верстаю. Что делать если такие не очевидные вопросы появится в боевых задачах? Такое поведение браузеров для меня очень странное, и я не знаю где я допустил пробел в изучении верстки, что у меня нету понимания почему так происходит.
>>873130 >>873130 я конечно только вкатывальщик с недельным стажем. но в пятой сточке не хватает открывающих кавычек. и вроде бы именно об этом написано внизу.
Привет, подскажите по JS 12 задаче: метод hamburger.calculateCalories() указанный в примере работы с классом и метод Hamburger.prototype.getCalories указанный в заготовке класса, это разные методы? Если да, то чем они отличаются? Или один, просто названия разные?
Ты ее хоть тестировал? И там внизу ошибка написана.
Ну и я бы советовал внимательнее читать официальный мануал или мои уроки. То, что функция strrev переворачивает строку в каких-то других языках, не значит, что она работает так же в PHP. В PHP она работает только с ASCII символами и не работает с кириллицей: https://gist.github.com/codedokode/ff99e357e9860ea169b8
PHPч, помоги нуфаку. Нормальным ли является решение написание php скриптов прямо в html файле страницы? Как я понял, браузером они не отображаются. И как можно изолировать .php файлы от .html файлов, и как потом их вызывать в html-формах в атрибуте form [action], если .php скрипт изолирован от .html файла? inb4 гугли собака гуглю уже прямо сейчас, просто мб анон может сам расписать или дать линк на достоверный/годный источник, где расписаны за и против различных методов симбиоза html и php?
>>874405 В файлах шаблонов лежит только вывод информации, вся логика работы лежит отдельно. PHP, JS скрипты лежат отдельно. Когда твой php-скрипт отработал и все данные уже в конечном виде находятся и готовы к отображению - подключаешь подходящий файл с шаблоном и выводишь информацию на экран.
Если у тебя есть форма для обратной связи: в атрибуте action хранится путь к файлу который будет обрабатывать информацию из твоей формы, в атрибуте method хранится способ передачи: (POST/GET). Когда ты отправил данные, скрипт из action её обработал (валидация данных и тд) исходя из того какой результат обработки ты возвращаешь пользователю ту же страницу с ошибками, либо с надписью, что всё ОК и тд. Лучше почитай у ОПа есть статья по работе с формами.
>>874405 Гугли MVC. Если кратко - то пхп-код можно использовать только в шаблонах для вывода содержимого страницы. Допустим, есть у тебя пхп-код, в котором ты подключаещбся к БД и вытаскиваешь из нее инфу по юзеру. Выглядит примерно так: $user = new User(); $user->getById(1) //метод который заполняет свойства объекта user по id Дальше просто подключаешь шаблон(именно так тоже лучше не делать, просто для наглядности) include 'user_template.html'; В подключаемом файле, помимо хедера и боди что-то вроде того: <table> <tr> <td><?php> echo $user->name; </php></td> <td><?php> echo $user->secondName; </php></td> </tr> </table> Как-то так. Короче в шаблоне можно использовать немного пхпшного когда для вывода инфы, но вот в пхпшном коде нельзя. Если все правильно делаешь, то у тебя получается нормальное разделение когда на бизнес-логику(т.е. само программирование) и логику отображения(для того верстка и нужна).
> Нормальным ли является решение написание php скриптов прямо в html файле страницы? Нет, это ведет к бардаку в коде.
> И как можно изолировать .php файлы от .html файлов, и как потом их вызывать в html-формах в атрибуте form [action], если .php скрипт изолирован от .html файла? Тебе надо разобраться как работает веб-сервер. Без этого дальше двигаться нельзя. Что по твоему указывается в атрибуте action у тега form? Ты можешь объяснить, что происходит когда ты заполняешь форму и нажимаешь кнопку отправки?
>>873025 Ну так вот об этом и речь. Что непонятно нифига новичку, куда какие методы нужно писать. Некоторые вещи как например взаимодействие классов вообще не ясно как будет работать.
Например по моей логике как раз >Вообще, у разных существ может быть разная восприимчивость к видам урона, логичнее сделать у существа метод "принять урон", а не закладывать что он всегда складывается. За эту разную восприимчивость к разному урону будет отвечать обязательный для каждого существа объект армор.
>>874421 Спасибо за ответ, пока, правда, не совсем понимаю сути include 'user_template.html' Типа берется шаблон разметки (причем не всей, а какой либо её части, типа только div с таблицой из бд), заполняется посредством скрипта php, который в свою очередь соединяется с MySQL (кстати, только MySQL или возможны соединения с любыми БД, типа там постгрес, мсскл, и прочие?) бд, а потом заполненный контентом кусок html подгружается пользователю через какой нибудь ajax? >>874427 >Что по твоему указывается в атрибуте action у тега form? Ты можешь объяснить, что происходит когда ты заполняешь форму и нажимаешь кнопку отправки? На данный момент думаю (не знаю точно, но исходя из того, что успел прочитать по html, js и php), по нажатию input-элемента с type-submit происходит invoke действия, указанного в action. В целом, как я понимаю, туда можно захуячить что угодно: js code, php code, главное, чтобы браузер мог это выполнить. Думаю, что в action <form> можно указать путь к .php файлу, который содержит инструкции, которые необходимо выполнить, используя полученные от клиента параметры из $_GLOBALS и прочих $_POST $_GET, ну и потом по необходимости сообщить клиенту соответствующий ответ. Насчёт урока и require вместо include - патиба, сейчас посмотрю.
>>874442 >Типа берется шаблон разметки (причем не всей, а какой либо её части, типа только div с таблицой из бд), заполняется посредством скрипта php, который в свою очередь соединяется с MySQL (кстати, только MySQL или возможны соединения с любыми БД, типа там постгрес, мсскл, и прочие?) бд, а потом заполненный контентом кусок html подгружается пользователю через какой нибудь ajax? Смотри. Ты видимо не до конца понял что такое программирование, а что такое верстка. Представь что ты работаешь в команде из двух человек. Ты кодер - т.е. делаешь внутренную логику сайта, а твой напарник верстальщик, он делает красивый дизайн. Ты плохо разбираешься в верстке, он плохо в программировании. Задача, допустим, сделать маленький новостной сайт. Есть база данных(любая - mysql, postrge)в ней таблица - с новостями, поля - id новости(надеюсь ты понимаешь что это и зачем оно), заголовок новости, автор, ну и содержимое. Твоя задача как кодера - написать код, который каким-то образом вытаскивает данный из таблица и представляет ее в удобном виде(массив новостей, а еще луче массив объектов-новостей). А верстальщик делает красивую верстку для странички со списком новостей. Вот и подумай - будет ли вам удобно работать с кодом, где все это смешано? Того то и разделяют дизайн(отображение) и логику(код). Допустим ты сделал свой код, в качестве условного шаблона просто подключаешь сначала пустой шаблон в котором максимум выводишь все данные из весртки, а верстальщик уже расставляет эти данные что бы все красиво выглядело.
Привет, анон. Нужен твой совет. Суть такова. Живу в сраной Украшке. И срочно потребовалась прибавка к зп, небольшая по московским или даже киевским меркам, может и небольшое, но по нашим мухосранским достаточно ощутимая. И я в общем-то наслышан, что Пых предоставляет такую возможность. Знаю английский на хорошем уровне. Из программирования знаком с сишкой (по учебнику Дейтела) и Жабку на уровне первого тома опус магнума Хорстманна-Корнелла. Я просто в начале года пытался раньше вкатиться в кодинг, но обстоятельства так сложились, что очень мало было свободного времени, да и то проебал попусту.
Так вот в чём вопрос. Сейчас как раз у меня нечто вроде отпуска почти на месяц, свободное время есть. Имеет ли смысл его потратить на пых, вместо того чтобы ковырять жабку? И как это сделать максимально быстро? Имеет ли смысл следовать гайду в оп-посте, или мой мизерный и не из этой оперы опыт поможет мне начать с чего-то более хардкорного, но быстрее?
>>874470 Ну то есть ты хочешь за месяц вкатится во фриланс на языке, с которым не знаком + не имея опыта коммерческой разработки вообще ни на одном языке?
>>874470 Тут наверное стоит упомянуть какие вещи ты писал на каких языках, потому что книги, которые ты прочитал ни о чем не говорят, судить о твоих скилах можно только по практическому опыту.
>>874470 Чё-т не пойму эту гифку, не в первый раз вижу, только сейчас заинтересовался. Какого чёрта deadline переносится, когда соня переносит с 15 пятницы на 13 среды? Dead - по этой логике - должна была пройти мимо его...
По сути твоего поста: всё имеет смысл. В PHP ты вкатишься быстро, если Javascript знаешь, поскольку PHP почти полностью копирует Javascript (ну, мне так показалось, когда одно после другого изучал, а JS всё-таки появился раньше и намного). Другое дело, что надо будет разбираться во всяких CMS, работающих на PHP, а этого за месяц не освоить. Но пробовать надо всегда и в любом случае.
Я бы советовал не перемешивать файлы бутстрапа со своими, а положить их в отдельную папку. Так легче понять где чей код и проще обновлять библиотеку потом будет.
https://github.com/anonymous011010/studentslist/blob/master/app/bootstrap.php Задача бутстрап-скрипта только инициализировать приложение и подготовить к работе. А не определять УРЛ и запускать контроллер. Ну вот например если мы захотим написать скрипт для командной строки, мы не сможем использовать бустрап файл, так как он попытается запустить контроллер, который в командной строке не имеет никакого смысла.
В твоем случае содержимое бустрап файла можно было бы просто поместить в index.php.
Непонятно, почему разработчики PHP не сделали так с самого начала. Вся эта идея с 20 видами ошибок - пример неправильного проектирования. Статья по теме: https://habrahabr.ru/post/218325/
Ты там еще пытаешься не завершать приложение при непойманном исключении, но это бессмысленно, так как скрипт в любом случае завершится.
Также, ты по моему изобретаешь велосипеды. Ну например, ты выводишь ошибки при установленном APP_DEBUG, но в php.ini уже есть настройка, отвечающая за вывод ошибок на экран: display_errors.
Ты делаешь свой логгер, но в PHP уже есть лог ошибок и возможность писать в него через error_log(). В чем смысл заводить отдельный лог?
Наконец, если уж делать логгер, то лучше следовать интерфейсу логгера из PSR-3:
В этом случае ты мог бы использовать любой из сторонних логгеров.
Также, в логгере не очень понятно назначение метода setLogFile(). Зачем может понадобиться менять путь к лог-файлу в процессе? Разве недостаточно указать его при создании объекта?
Запись в файл сделана довольно неэффективно. Если тебе надо что-то писать в файл кусочками, то стандатный способ - fopen/write/fclose, а ты по сути на каждое сообщение открываешь и закрываешь файл.
> \RuntimeException('Unable to create the log file'); В исключении надо указывать путь к файлу, иначе непонятно какой именно файл не удалось создать.
> public function log($type, $message, $file, $line) { Ты в функию логгирования уже закладываешь что всегда есть имя файла и номер строки. Это потому что ты не не разделяешь функционал обработчика ошибок от логгера и у тебя логгер "знает" про то, какие свойства есть у ошибки.
> return $url = \explode Зачем тут "$url = "? зачем создавать переменную, которая нигде после не используется?
> list($urlPath, ) = \explode('?', \filter_input(\INPUT_SERVER, 'REQUEST_URI', \FILTER_SANITIZE_URL)); для этого есть функция parse_url
> \rtrim(\ltrim($urlPath, '/'), '/') trim умеет обрезать с обоих сторон.
> if (\class_exists('\Studentslist\\Controllers\\' . \ucfirst($url[0]) . 'Controller')) { > $this->controller = \ucfirst($url[0]); Тут тоже нелогично, получается при любом несуществующем URL вроде /asdasdad будет вызван контроллер index, а должна быть страница 404.
Ну и твой метод роутинга на мой взгляд неудачный, так как он допускает существование множества URL для одной страницы, вроде /index/action/1/2/3/4/5/6/7/8, хотя у каждой страницы должен быть единственный URL.
> $page = ((!$page) || ($page < 1)) ? 1 : $page; тут удобнее использовать max()
Я конечно не знаю, как тут лучше сделать, может быть стоит сделать отдельный контейнер для получения объектов, и передавать его в контроллер, но это немного усложнит код.
> $token = (isset($_COOKIE['authToken'])) ? \filter_input(\INPUT_COOKIE, 'authToken', > if ($auth->isRegistred($token)) { Получение токена тоже наверно лучше инкапсулировать в класс авторизации
> $ErrorController = new \Studentslist\Controllers\ErrorController; > $ErrorController->error404(); Название метода должно начинаться с глагола.
> \filter_input(\INPUT_GET, 'order', \FILTER_SANITIZE_STRING) Ты знаешь, что именно делает \FILTER_SANITIZE_STRING, и зачем это тут нужно? Или ты ставишь "на всякий случай"? На мой взгляд бесполезные действия только усложняют проверку, безопасен ли код.
Методы search() и all() очень похожи, зачем 2 раза писать одно и то же?
> \filter_input(\INPUT_GET, 'q') А что эта функция делает?
> public static function renderViewTable Базовый контроллер должен содержать какие-то универсальные методы. Но тут явно метод, который нужен только на странице вывода таблицы со студентами. Зачем его помещать в общий для всех базовый контроллер?
> exit(0); Это на мой взгляд неправльно. А что если тебе надо после отображения страницы еще что-то сделать? да и название функции никак не говорит о том, что она завершает программу.
> public static function renderErrorView Непонятно, чем это отличается от public static function renderView.
Вообще, у тебя в коде слишком много die и exit. Я бы их убрал.
> header("Refresh:5; url=" . \APP_URL_ADDR, true, 303) Это неправильный подход. Где гарантия что пользователь за 5 секунд успеет прочитать страницу? А если он слепой и исполоьзует программу для чтения вслух? А если он отвлекся?
> } catch (\PDOException $ex) { > $data['fail']['message'] = "Не удалось изменить данные, пожалуйста, повторите попытку снова."; PDOException возникает при ошибке работы с БД, например если SQL запрос написан непраивльно. Какой смысл писать особый код для обработки этой ошибки? У тебя ведь уже есть страница на случай исключения.
Сам класс пагинации на мой взгляд, сделан переусложненно. Проще было наверно сформировать в функции массив для вывода, содержащий номера, ссылки на страницы и признак многоточия.
В ссылки не обязательно подставлять имя хоста, хватило бы относительной ссылки.
Еще, задачи классов TableHelper, NavHelper, Paginator довольно-таки сильно пересекаются, не лучше ли генерацию ссылок перенести в один класс и передавать параметры как аргументы, вроде такого:
Более того, там у тебя и сеттер есть, непонятно, зачем там вообще магические методы. Главный их недостаток в том что они запутывают код, надо их изучать и тратить время. Я бы советовал их избегать, тем более что особой надобности в них тут нет.
> (\S[^@])+ А что это значит? Должны чередоваться не-пробел и не-@? Вроде "@ @ @ @ @ @" ?
> if (!\preg_match_all($regExp, $email)) { preg_match_all используется для поиска нескольких совпадений с регуляркой, тут логичнее использовать preg_match
> } elseif ($this->gateway->checkEmailExists($email)) { > if ($this->gateway->getEmailOwnerId($email) != $id) { Это кстати можно сделать одним SQL запросом
> "/^([а-яё]+[-\\s']?){1,32}$/ Эта регулярка пропустит гораздо больше 32 символов.
Для значений пола стоит завести константы Student::GENDER_MALE. Для метса жительства либо константы, либо true/false.
Имена шаблонов обычно выбирают, чтобы они соответствовали именам контроллеров и действий.
> Возможна попытка CSRF-атаки, пожалуйста, проверьте Лучше бы убрать про CSRF атаку и просто написать что для успешной отправки формы нужно включить поддержку кук в браузере.
Чтобы не писать везде в шаблоне $data, обычно данные из массива превращают в переменные с помощью extract().
> Даже оригинальный otf формат шрифта главного заголовка не отображается в ie6-8. В отличие от шрифта Lato.
Для старых IE скорее всего нужен eot.
Также,мне кажется, не надо было определять шрифты для всех значений веса и стиля. Достаточно определить только для тех, что нужны на странице: напимер, обычный, тяжелый, сверхтяжелый.
> firefox, webkit Наличие описания веса bolder переопределяет значение normal, т.е. c regular на bolder Я думаю, проблема была в 2 свойствах src. Также, у браузеров есть особенность: если им нужен тяжелое или курсивное начертание шрифта, а оно отсутствует, то они генерируют его из обычного механически (получается очень некрасиво). Возможно в этом дело?
И еще, font-weight bold и font-weight 700 по моему это одно и то же. bold это синоним 700:
"firefox Лёгкие шрифты не определяются" - а где это можно увидеть? Без кода я не могу проверить. Можешь на jsfiddle или отдельной html страницей сделать пример?
С шрифтами надо бы разобраться.
> При ширине в 320px всё выглядит хорошо, а вот если сжимать больше, то изображения и другие элементы будут вылазить за пределы тела в зависимости от своих размеров. Ну я сомневаюсь что есть устройства меньше 320px: http://mydevice.io/devices/
Дефолтные стили
> Ещё я заметил странный отступ у ссылок на соц.сети в webkit'е. Его задает ul, menu, dir { user agent stylesheet user agent stylesheet - это встроенные в браузер CSS стили. Их можно увидеть в исходных кодах браузера по ссылкам тут:
Они нужны чтобы по HTML без CSS смотрелся относительно нормально: чтобы между абзацами были отступы, чтобы заголовки были написаны большим шрифтом, чтобы ссылки были синими и подчеркнутыми. (и кстати твой CSS тоже должен адекватно отображать обычный HTML код)
Стили по умолчанию отображают HTML примерно так, как отображали первые браузеры.
В твоем примере
ul { display: block; list-style-type: disc; -webkit-margin-before: 1em;
задает, что тег ul по умолчанию имеет указанные свойства. Например, что он блочный, что элементы списка в нем маркируются точками и что перед ним делается отступ в 1em.
Стили по умолчанию надо учитывать, если они тебе мешают, то можно переопределить нужные своства.
> А нужно добиться чтобы на этой странице все заголовки и т.д. были как на главной странице? Как быть с цветом? В шаблоне половина страницы с черным фоном, половина с белым - тяжело догадаться какой будет у остальных страниц. Всегда должен быть белый? Нужно догадаться, какой стиль является "стилем по умолчанию". В случае с этим макетом, я думаю, по умолчанию текст должен быть написан примерно как в абзаце под заголовком "Consectetur" на белом или бледно-сером фоне, шрифтом Lato. А черный фон как раз используется чтобы выделить шапку и подвал и как бы показать что это отдельные блоки.
Стили по умолчанию нужны, представь, что завтра мы захотим добавить на сайт просто текстовую страницу. Хорошо бы, чтобы нам не пришлось для нее почти ничего добавлять в CSS и чтобы при этом она соответствовала сайту по стилю.
Ссылки в стилях по умолчанию наверно можно сделать красными (или сделать их красными при наведении).
Для соцсетей надо сделать изменение при наведении.
Разработчики Slack: "...По итоговым результатам, PHP предоставляет наилучший фундамент для создания, изменения и эксплуатации успешного веб-проекта по сравнению с конкурирующими средами. Сегодня я хотел бы начать новый проект на PHP...."
К кому мы прислушаемся, к разработчикам добившегося многомиллионного успеха стартапа или живущим на мамкином борще анонимным экспертам из раздела /pr/?
>>874578 Я конечно ньюфаг в PHP но >К примеру, 123 == '123foo' оценивается как истина (что он там делает?), но 0123 == '0123foo' является ложью (хмм). какого хрена вообще кому-то пришло в голову сравнивать число со строкой? Почему когда Антон делает это на Java - ему говорят "Ты чё, дебил?", а когда так делат на PHP - "Это язык странный".
В Яве еще веселее. Там строки - это объекты класса String и при сравнении через
s1 == s2
сравнивается не содержимое, а проверяется, ссылаются ли s1 и s2 на один и тот же объект. То есть 2 разных объекта, содержащих одинаковые строки, дадут false.
Сравнивать надо через метод, как if (s1.equals(s2))
Справедливости ради, в С++, от которого отпочковалась Ява, примерно такая же ерунда, если не переопределить оператор сравнения для класса строк.
Но конечно, все эти неявные преобразования в PHP это проблема в дизайне языка, добавленная давно в ранних версиях. Я надеюсь, что в будущем либо что-нибудь придумают либо в самом PHP либо в том же HHVM который не так печется о совместимости.
>>874585 >2 разных объекта, содержащих одинаковые строки, дадут false. Кошмар. Меня до сих пор передёргивает от арифметических операций в JAVA и от бесконечных циклов как вполне себе обычное дело для реализации демонов.
>>874581 > вообще кому-то пришло в голову сравнивать число со строкой? Дело в том, что в твоей программе может произойти такая ситуация, когда ты будешь ожидать сравнения строки со строкой, а получишь число из-за закравшегося неведомо где бага. Решение крайне простое - ВСЕГДА использовать === (оператор сравнения без конвертации типов). JS-линтеры даже ругаются, если видят в коде двойное равно. Алсо, кто как борется с отсутствием тайп-хантинга в JS? Браться за TypeScript/Flow не очень хочется. Вот вроде интересная либа: http://is.js.org/ но многовато туда всего напихали.
У вас тут ньюфажеские вопросы по HTML допускаются, а то отдельного треда не нашёл ни в /pr, ни в /web. Короче, допустим, есть сайт, у которого есть некоторая статическая часть: хэдер над меню, само меню (nav > ul), и футер. Хочу добиться следующего: при нажатии на кнопку в меню, в div (такой то wrapper) под меню идёт подгрузка контента html файла с помощью ajax'a. Всё бы казалось чикибрики, но, при обновлении страницы, меня, естессно, кидает на основную страницу. Следовательно, при подгрузке контента раздела сайта мне нужно менять текущий URL в браузере, что я хз как сделать. Мне кажется жутко уебищным в каждом html-файле раздела дублировать <head></head> <nav><ul></ul></nav> <footer> и то, что до блока с контентом. Какие есть workaround'ы для этой проблемы? или проблема в том, что я ебучая макака и неправильно проектирую дерево сайта? Сейчас пытаюсь сделать что то типа следующего: по нажатию на кнопку вообще, <a href="nextpage.html">" в меню на основной странице идёт переход на страницу nextpage.html, в которой находится только контент раздела, при этом через jquery подгружаю то, что должно быть до контента (head, nav>ul) и то что должно быть после (footer), и только по завершению after(). делаю .show("fast"); Как такой вариант? Или это ещё уебищнее, чем дублировать в каждом html-файле head, nav>ul и footer?
Можно ли как то по вызову submit у формы вывести результаты некоторой работы в пхп скрипте на ту же страницу в определенном месте, например, в каком нибудь div'е под самой формой, и чтоб без перезагрузки страницы? Или только заново страницу загружать с результатами обработки формы?
Вообщем решил я сделать список студентов, и в итоге по быстрому получилось вот сие https://github.com/InitF/StudentList . До этого пришлось немного поработать на Yii2, так что структура в общем может быть похожа. Собственно чего можете посоветовать (окромя самоубийства и стерилизации). Особенно интересно, как лучше разгрести ад в controllers/RegController.
>>874513 >Я попробовал открыть страницу в фаерфоксе и там в отладчике пошли ошибки: Я не знал про этот инструмент. Я посмотрел что там за ошибки и исправил их. У меня был лишний пробел в описании форматов format (. Я исправил этот пробел, и это починило всё(!), за исключением наклона и отсутствия легких шрифтов в ie<8.
Далее, я убрал лишнюю строчку src, это не на что не повлияло - в ie шрифы ставятся, но с теми же багами.
Затем, я убрал определения шрифтов с цифровыми значениями веса, и это вызвало несколько других багов:
webkit, firefox Перестают определять шрифт regular firefox <b> теряет жирность (можно починить добавив этому элементу свойство font-weight: bold) ie По прежнему легкие шрифты не определяются. Однако, в ie определятся шрифт regular. ie<8 И по прежнему отсутствие цифровых значений веса чинят наклонность у жирных шрифтов
Я решил что можно определить шрифт regular цифровым значением т.е. 400, это починило регулярные шрифты, но сломало легкие. Я точно так же определил шрифты для легких задав значение 100. Что-то из этого сломало легкие наклонные шрифты в ie>8 сделав их жирными наклонными. Это так же починилось определив наклонный шрифт цифровым значением т.е. задав font-weidght: 100 и font-style: italic.
В ie<8 по прежнему не отображаются легкие шрифты (заместо них regular).
Firefox, кстати, всё равно выдает ошибки парсинга font-weight на значения bolder и lighter (если их убрать то ничего не изменится). Как такое может быть?
>>864640 (OP) Почему если при использовании YII2, я убираю имя формы из правила required в функции rules, то в переменной создания экземпляра класса модели значение поле формы не передаеётся? Передаются только те, которые указаны как required? Значения же сами должны передаваться, вне зависимости от того, обязательно поле для заполнения или нет?
Задам ещё один вопрос, по YII2, да и вообще. Допустим, в контроллере я добавлюя некоторую строку с данными, и после этого хочу перенаправить пользователя на страницу которая их выводит. Ничего если я это сделаю методом взятия последнего добавленного id записи в базу данных? Или так небезопасно и могут быть ошибки? Так вообще можно делать?
Я хотел бы поблагодарить господина OP за всё что он делает. Меня впечатляет как он успевает всем ответить, это невероятно продуктивная работа и это продолжается уже не один год. Это вдохновляет! То что он делает означает, что сколько бы не было в мире зла, добро всё равно победит! Такая работа безусловно достойна работы гения, и для меня большая честь учиться под его начинанием.
>>874984 нет , например если будет в базу параллельно записывать пару запросов (от 2 одновременно пользователей ) то выйдет что вы будете давать не ту инфу
>>875005 ОП, ты ли это? Здесь все еще разбирают и проверяют задачи? Собираюсь вкатиться в пых по хардкору, пилить задания и всякое такое каждый день. Знал, что раньше тут был ОП с учебником, и вот нашел тред.
>Это не нужно так как первичный ключ по определению (ПК = идентификатор записи) уникален. Да, этот индекс надо убрать.
>Задача бутстрап-скрипта только инициализировать приложение и подготовить к работе. А не определять УРЛ и запускать контроллер. Ну вот например если мы захотим написать скрипт для командной строки, мы не сможем использовать бустрап файл, так как он попытается запустить контроллер, который в командной строке не имеет никакого смысла.В твоем случае содержимое бустрап файла можно было бы просто поместить в index.php. Я этого не знал. Cпасибо, я учту это.
>Мне не очень нравится идея использования констант для настроек: они доступны везде глобально и мы не можем ограничить область, где они доступны, не можем их передать только в определенные объекты. Я и использовал их из-за глобальной доступности, но так делать не стоит, согласен.
>Этот класс стоило поместить в файл, путь к которому соответствует неймспейсу. Название стоит поменять, так как Handler значит "обработчик" и непонятно, что именно он обрабатывает. Да, определенно стоит поменять ему название. Только как его назвать, если он содержит методы для обработки как исключений так и ошибок.
>Имена функций принято начинать с глагола, handleError, а не errorHandler. Хорошо, буду знать.
>У тебя не очень логичный подход в обработке ошибок. Если произошла ошибка, то ты продолжаешь выполнять программу, скорее всего с неправильными данными. Идея была в том, чтобы не прекращать работу в случае некритических ошибок. Но, наверное, так делать не стоит.
>На мой взгляд единственно верный способ обработки ошибок это преобразование их в исключения: http://php.net/manual/ru/class.errorexception.php О, это действительно хороший способ, я не знал о существовании ErrorException. Спасибо.
>Ну например, ты выводишь ошибки при установленном APP_DEBUG, но в php.ini уже есть настройка, отвечающая за вывод ошибок на экран: display_errors. Да, константу APP_DEBUG лучше убрать и управлять отображением ошибок через display_errors.
>Ты делаешь свой логгер, но в PHP уже есть лог ошибок и возможность писать в него через error_log(). В чем смысл заводить отдельный лог? Хм.. В моем случае он действительно не нужен и логичнее использовать встроенную функцию.
>Также, в логгере не очень понятно назначение метода setLogFile(). Зачем может понадобиться менять путь к лог-файлу в процессе? Разве недостаточно указать его при создании объекта? Да, это и вправду нелогично сделано.
>Ты в функию логгирования уже закладываешь что всегда есть имя файла и номер строки. Это потому что ты не не разделяешь функционал обработчика ошибок от логгера и у тебя логгер "знает" про то, какие свойства есть у ошибки. Да, он действительно "прибит" к логгированию ошибок.
>use принято ставить в самом начале файла. Это не вызовет ошибки в том случае если оно стоит до подключения автозагрузчика?
>Здесь тоже сделано нелогично. Конструктор предназначен для инициализации и подготовке объекта к использованию. Нелогично и неожиданно что конструктор может внезапно вызвать контроллер, который выведет страницу. Да, это неправильно. Эту функциональность нужно перенести в отдельный метод.
>А что будет если условие не сработает? Переменная $url будет иметь тип NULL, потому что ей не будет присвоено никакое значение. Потом не сработает условие проверки на существования класса и будет свойство $controller будет иметь значение по умолчанию Ну и т.д. Я раньше не обращал внимания на это, честно говоря. Это нужно переделать.
>Зачем тут "$url = "? зачем создавать переменную, которая нигде после не используется? Действительно, это совершенно бесполезная переменная.
>для этого есть функция parse_url C REQUEST_URI parse_url работать не будет.
>Тут тоже нелогично, получается при любом несуществующем URL вроде /asdasdad будет вызван контроллер index, а должна быть страница 404. Да, это плохо.
>Ну и твой метод роутинга на мой взгляд неудачный, так как он допускает существование множества URL для одной страницы, вроде /index/action/1/2/3/4/5/6/7/8, хотя у каждой страницы должен быть единственный URL. Да, он действительно довольно неудачный.
>ты для каждого класса будешь делать по статическому методу в контроллере? При этом для класса DBHelper ты почему-то метод не сделал, а создаешь его через new. Я конечно не знаю, как тут лучше сделать, может быть стоит сделать отдельный контейнер для получения объектов, и передавать его в контроллер, но это немного усложнит код. Нет, это только для TDG. Я сам так и не решил как все это лучше сделать, честно говоря.
>Получение токена тоже наверно лучше инкапсулировать в класс авторизации Хорошо
>Ты знаешь, что именно делает \FILTER_SANITIZE_STRING, и зачем это тут нужно? Или ты ставишь "на всякий случай"? На мой взгляд бесполезные действия только усложняют проверку, безопасен ли код. Знаю, но этот фильтр там бесполезен и не нужен. Его определенно нужно оттуда убрать.
>Методы search() и all() очень похожи, зачем 2 раза писать одно и то же? Да, и мне это не нравится, но я не придумал хорошего решения для того чтобы избежать дублирования кода.
А что эта функция делает? Получает переменную извне (в этом случае с массива $_GET) и при необходимости фильтрует значение. Поскольку фильтр не указан, используется FILTER_UNSAFE_RAW. Поэтому вызов этой функции с этими параметрами фактически равен присвоению переменной значения элемента суперглобального массива $_GET c ключем 'q'.
>Базовый контроллер должен содержать какие-то универсальные методы. Но тут явно метод, который нужен только на странице вывода таблицы со студентами. Зачем его помещать в общий для всех базовый контроллер? Да, это неправильно. Но я не знаю где их лучше расположить.
>Непонятно, чем это отличается от public static function renderView. Подключает файлы из другой директории.
>И кстати, почему методы render статические? В этом нет никакой необходимости, я не обратил на это внимание.
>Тут методы редактирования и регистрации почти одинаковые. Не надо копипастить код. Опять-таки, мне это самому не нравится, но я не знаю как это решить.
>Вообще, у тебя в коде слишком много die и exit. Я бы их убрал. В тех случаях разве не надо быть уверенным в том, что выполнение кода завершено?
>Это неправильный подход. Где гарантия что пользователь за 5 секунд успеет прочитать страницу? А если он слепой и исполоьзует программу для чтения вслух? А если он отвлекся? Действительно.
>PDOException возникает при ошибке работы с БД, например если SQL запрос написан непраивльно. Какой смысл писать особый код для обработки этой ошибки? У тебя ведь уже есть страница на случай исключения. Да, без этого можно обойтись.
>тут слишком много вызовов renderView на мой взгляд. Да, согласен.
>Это нужно для записи в БД? Тогда этот метод должен быть в StudentDataGateway. У меня были мысли о размещении его там, но я не был уверен в том, что его стоит там размещать.
>тут слишком много аргументов у конструктора. Надо либо передавать опции массивом, либо, что лучше, разделить их на обязательные и необязательные, необязельные задавать отдельными методами Они там все обязательные
>getStudentTableLink($order = null, $sort = null, $query = null) Но это приведет к загромождению view.
>Не лучше ли сделать геттер и тем самым явно показать что оно только для чтения? Да, лучше.
>LIMIT и OFFSET надо бы поставлять через плейсхолдеры. Но как?
>Я вижу что тут переменные вставляются прямо в SQL запрос, значит возможна SQL инъекция. Да, поэтому пользовательские данные не вставляются напрямую, а вставляется значение которое соответствует запросу. Это, конечно, костыль но я не знаю как это лучше сделать.
>Неудачная идея возвращать true либо строку. Логичнее при отсутствии ошибок возвращать пустое значение. Да, это действительно логичнее.
>А что это значит? Должны чередоваться не-пробел и не-@? Вроде "@ @ @ @ @ @" ? Любой символ кроме проблема и @.
>gitignore лучше класть в корень проекта в одном экземпляре. Он там для того, чтобы создать пустую директорию.
Заметил интересную особенность поведения БД. Есть у меня табличка со студентами, поле email уникальное. Пытаюсь вставить методом поля, указал повторяющийся имейл - > ошибка. Но вот фишка в том, что если у последней записи id был 3, то у следующей, правильно вставленной, id уже 5. Т.е. из-за ошибки один порядковый номер айдишника куда-то пропал. Чому так?
Я правильно понял, что в классе можно объявить только 1 конструктор. Если мне нужен конструктор с другим набором параметров - соси писос/делай статические методы, возвращающие новый инстанс?
>>875147 Зачем тебе два конструктора? Если тебе надо изменять свойства класса то делай методы. Или можешь делать это динамически, а еще лучше почитай про магические методы.
Ньюфаг врывается. Встал ступором на регулярных выражениях. Т.е. появляются какие-то мысли, но на уровне интуиции, а что-то дельное в голову не идёт. Есть ли какие-то годные уроки для всего этого делать, кроме учебника для нюфань из шапки?
Почему-то мой хттп сервер перестал нормально отдавать данные браузеру. Когда делаешь socket_close сразу после socket_write браузер выдает ERR_CONNECTION_ABORTED, если поставить перед закрытием сокета sleep(10) все нормально отображается.
>>875147 Да, в PHP нет перегрузки конструктора. Обычно используют статические конструкторы, выглядящие примерно так Foo::createFromBar($bar) Вообще здесь всё очень спорно и нужно смотреть в код. Если нужно большим количеством разных способов создать объект, то быть может есть смысл выделить дополнительную абстракцию?
>>875151 Ух, и магия и сеттеры, изменяющие состояние. Это всего надо избегать по возможности, передавая параметры конфигурации в конструктор. Оцени новую магию в Laravel: https://laravel-news.com/2016/11/higher-order-messaging/ Они используют свойство объекта как callable. Восторженные фанбои уже ставят очередную звезду репозиторию.
Почему объект класса сериализуется через serialize($object), т.е. вижу полученные CSV-подобные данные, но не сохраняются значения массивов - свойства $anArray=array(); ?
>>875155 Чисто в учебных целях не засирай себе голову ими. Просто в общих чертах пойми что это и зачем это, и потом уже если они тебе понадобятся, сломай себе моск.
>>875004 А как поступать в таком случае? Записывать в куки часть информации (если id то метод последнего id снова не прокатывает) которую ввёл пользователь, перенаправлять его на нужную страницу, а уже затем по этим записанным данным из куки выводить нужную инфу?
>>875183 Бамп вопросу? Есть класс, в котором есть двумерный массив, объект которого пробовал сериализовывать двумя способами: 1. просто использовать функцию serialize() 2. реализовал в классе интерфейс Serializable, пробовал сериализовать через $s = $obj.serialize(); где obj - объект класса с массивом. Но при записи в файл всё равно нет значений матрицы. Алсо, я нуфак
ОП у меня вопрос. У тебя в гите в теме про паттерны работы с бд есть цитата: "для работы с разными таблицами стоит использовать разные классы ". А если у меня инет магазин с кучей таблиц: продукты, их описание, опции, атрибуты и прочее. Как сделать через такие классы выборку? К примеру я пишу модуль Аякс фильтрации. Мне исходя из этой цитаты придется вместо одного запроса с парой join делать неудобные 3-4 запроса плюс обрабатывать это все на стороне php. Что скажешь?
Рано радоваться, они тебе советуют неправильные вещи. Надо остановиться и изучить, чтобы непонимания не было. Есть официальный мануал по регуляркам pcre, есть наши задачки, можно в треде задать вопросы.
Не надо темы пропускать, надо все изучать последовательно.
serialize() работает рекурсивно и сериализует вложенные массивы и объекты. если ты считаешь что это не так, покажи простой пример кода.
Интерфейс Serializable нужен когда стандартный способ не работает.
> Но при записи в файл всё равно нет значений матрицы. Надо проверять не так. Надо сериализовать, потом десериализовать и проверить, что получилось. Не надо пытаться разбирать сериализованные данные.
> echo "Не удалось выполнить socket_accept(): причина: " . socket_last_error($sock) . "\n"; > break; тут наверно логичнее continue
> while ($read = socket_read($msgsock, 2)) { Неправильно сделана проверка. Что, если socket_read вернет строку "0" ?
Плюс, не понимаю какая выгода читать по 2 байта? И почему именно 2?
> socket_set_nonblock($msgsock); Неправильно. Если ты хочешь сделать сокет неблокирующим, то это надо делать один раз, а не каждый раз, как что-то из него прочитал. Плюс, для работы с неблокирующими сокетами нужен select (который ты изучишь чуть позже). Если не использовать select, то socket_read будет сразу же возвращаться при отсутствии данных и ты будешь грузить процессор на 100% в цикле while.
> function socketWrite Эта функция делает только 2 попытки записи. Почему из должно быть 2? В теории за раз может даже 1 байт отправляться. Тут нужен цикл.
Плюс, у тебя неблокирующий сокет, а это значит что 2 вызова могут отправить вообще 0 байт. Ведь блокирующий сокет блокируется до возможности отправить/получить данные, а не блокирующий всегда возвращает управление сразу.
> //без этой функции мы повиснем на чтении из сокета навечно, но почему-то если объявить её до этого цикла, то даные из сокета не прочтутся Потому, что неблокирующий сокет не ждет поступления данных, а возвращает управление сразу. Понятно, что браузеру нужно какое-то время на то, чтобы сформировать и отправить заголовки, и твой сервер просто их не дожидается, а сразу получает строку длиной 0 байт (значащую, что данных пока нету).
> //здесь был sleep(10) до того, как я стал читать данные из сокета. Без socket_read или sleep сокет как будто закрывается до того, как клиент успевает принять респонс, что приводит к ошибке в браузере Скорее всего потому, что неблокирующий сокет не успевает отправить данные.
Видимо, ты не изучил, как работают блокирующие и неблокирующие сокеты. Давай повторим.
Чтение
Блокирующий сокет при чтении блокируется до возникновения одного из событий:
- пришел пакет данных - будет возвращен этот пакет (в пределах указанного тобой числа байт, если там больше, то остаток вернется при следующем чтении) - удаленный хост закрыл соединение - будет возвращена строка длиной 0 байт и feof($socket) вернет true - проихошла ошибка - будет возвращен false. Ошибка может быть в том числе если например удаленный хост отсоединился от сети и связь с ним прервалась. Ну сети на то и сети, что там сломаться может все, что угодно. Любая функция может вернуть ошибку.
Неблокирующий сокет отличается тем, что он не ждет прихода данных. Если данных пока нет, он сразу вернет строку длиной 0 байт (но feof($socket) покажет false). Если же данные пришли, соединение закрыто или произошла ошибка, он возвращает то же самое что и блокирующий.
Запись
Блокирующий сокет отправляет данные в сеть и блокируется до одного из событий:
- один пакет с данными успешно передан операционной системе и поставлен в очередь на отправку. Возвращается число байт, которые поставлены в очередь, оставшиеся ты обязан отправить повторным вызовом функции. - произошла ошибка при попытке отправить данные
Обычно у ОС есть буфер определенного размера (из которого она потихоньку отправляет данные в сеть), и пока он не заполнен, socket_write кладет туда данные и сразу возвращает управление. Но если он заполнен, а данные из него еще не ушли в сеть, то функция отправки блокируется до момента, когда буфер освододится и можно будет положить в него еще немного данных.
Неблокирующий сокет в отличие от блокирующего возвращает управление сразу, если буфер заполнен и положить в него данные нельзя.
Неблокирующие сокеты позволяют параллельно работать с несколькими соединениями и передавать данные в 2 направлениях. Но для работы с ними нужно использовать select() или (если соединений очень много) специальные высокопроизводительные системы событий вроде libevent.
В общем, ощущение, что у тебя сделано как-то неправильно все. Алгоритм должен быть такой:
- используем блокирующий сокет - читаем данные из сокета, и проверяем, есть ли там пустая строка (которая обозначает конец заголовков и начало тела запроса, если оно есть). - получив пустую строку, мы имеем заголовок запроса и можем сгенерировать и отправить ответ - после отправки закрываем соединение
Заметь, что тут есть один хитрый момент: как определить, что браузер закончил передавать запрос и ждет ответа? Если мы начнем передавать данные раньше времени, возможно что браузер будет еще не готов их принимать, и мы заблокируемся навечно (мы передаем ответ и ждем что браузер примет его, а браузер пытается передать остаток запроса и ждет что мы примем данные). Важно правльно определить тот момент, когда передача запроса закончена и можно передавать ответ.
Протокол HTTP определен в RFC 7230, 7231, 7232, 7233, 7234, 7235. Поищем ответ там.
> The normal procedure for parsing an HTTP message is to read the > start-line into a structure, read each header field into a hash table > by field name until the empty line, and then use the parsed data to > determine if a message body is expected. If a message body has been > indicated, then it is read as a stream until an amount of octets > equal to the message body length is read or the connection is closed.
Необходимо прочитать первую строку запроса, затем прочитать строки с заголовками до пустой строки (которая обозначает конец заголовков). Затем необходимо проанализировать заголовки и определить, есть ли у запроса тело (при его наличии в Content-Length указывается его длина в байтах). Если тело есть, то прочитать указанное число байт.
Заметь, что браузер не обязан закрывать соединение на передачу (и генерировать EOF на сервере). Сервер должен сам определить конец запроса. Если это не делать, и ждать EOF то ты просто будешь висеть, пока браузер не закроет соединение по таймауту.
Так как мы делаем простую задачу, ты можешь не читать тело запроса и слать ответ сразу после окончания заголовков. Запрос GET все равно не содержит тела. Но если хочется, можешь добавить поддержку Content-Length и тогда сможешь например принимать тело POST-запросов.
В общем, тебе надо
1) разобраться получше, как работают блокирующие сокеты 2) разобраться получше, как работает HTTP
Если ты мог бы отслеживать соединение через Wireshark, то было бы хорошо. Если нет, то ты можешь попробовать соединяться со своим сервером через telnet или putty и отправлять запрос руками.
Пока, к сожалению, твой сервер совсем нерабочий.
Если тебе что-то непонятно по сокетам или HTTP - задавай вопросы.
>>875254 Всю стену еще не осилил, но пока ты тут пару вопросов/примечаний >Плюс, не понимаю какая выгода читать по 2 байта? И почему именно 2? Забыл вернуть обратно, проверял все ли данные читаются >Эта функция делает только 2 попытки записи. Почему 2? По идее она будет вызываться пока все данные не запишутся >Скорее всего потому, что неблокирующий сокет не успевает отправить данные. С блокирующим он тоже не работал, в общем-то sleep я туда поставил еще когда он был блокирующим.
>>875253 Нет, я понял как они работают и как поставить, но всё это слишком сложно на моём уровне. Возможно это потому, что я делал перерыв около двух месяцев в изучении языка и кое-что мог забыть.
> По идее она будет вызываться пока все данные не запишутся Действительно. Только у тебя это все неправильно сделано. Ты написал рекурсию, в результате чего логику работы стало сложно понимать, а надо было просто сделать цикл.
> С блокирующим он тоже не работал, в общем-то sleep я туда поставил еще когда он был блокирующим. значит, ты неправильно что-то сделал. Я написал в своем ответе логику, по которой должен работать сервер.
> 1) Все нужные регулярки как правило давно без особых проблем гугляться Не всегда гуглятся, и не всегда они правильные (могут например не поддерживать кириллицу или еще что-то не учитывать)
> 2) Их лучше вообще избегать. Странно. Потому что код, делающий то, же что и регулярка, будет более громоздкий и менее понятный. Регулярки это специальный язык, заточенный на поиск и замену текста.
А ты все задачи из учебника решил? Если по-прежнему непонятно, может тебе дополнительную заадчку дать? А если не решил и на чем-то застопорился, то покажи код и напиши, что именно непонятно.
Регулярки надо знать. Чтобы при чтении кода ты с первого взгляда понял, что она делает, а не долго гуглил и мучал справочник.
Ну там же в ответе написано, в чем причина. Ты видишь? Надо не гадать, а сдампить, что куда приходит, что куда передается. В данном случае впрочем все написано в самом сообщении.
Ну и кстати это плохо что твое приложение отдает пользователям подробности ошибки.
> Только как его назвать, если он содержит методы для обработки как исключений так и ошибок. ErrorHandler
> Идея была в том, чтобы не прекращать работу в случае некритических ошибок. Но, наверное, так делать не стоит. Не стоит, это только усложняет обнаружение ошибки. И откуда ты знаешь, что она некритическая? Может из-за этой некритической ошибки у пользователя обнулится баланс счета.
Встроенный в PHP подход неправильный. Не бывает "некритических" ошибок. Программа либо написана правильно, либо нет.
>>use принято ставить в самом начале файла. > Это не вызовет ошибки в том случае если оно стоит до подключения автозагрузчика? Нет. use ничего не загружает, он просто задает короткое обозначение для класса в коде ниже, что класс X это на самом деле \A\B\C\X.
> >для этого есть функция parse_url > C REQUEST_URI parse_url работать не будет. Будет, если ты пытаешься получить PHP_URL_PATH. Посмотри мануал и поэкспериментируй.
> Я конечно не знаю, как тут лучше сделать, может быть стоит сделать отдельный контейнер для получения объектов, и передавать его в контроллер, но это немного усложнит код. Вот я тоже не знаю. В больших фреймворках делают специальный класс - DI контейнер, который умеет создавать нужные объекты. Но в твоем крошечном приложении - нужны ли такие сложности? Просто без него тоже плохо. Ну например, тебе надо как-то обеспечить чтобы все классы использовали общее соединение к БД, чтобы другие класы были бы в одном экземпляре, и код создания объекта придется везде копипастить. Если бы ты не использовал классы дял контроллеров, можно было бы все объекты просто создать в бутстрап-скрипте.
Я все же предлагаю выбрать одно из решений, например:
- создать в бутстрап-скрипте объекты и положить в контейнер (объект или массив), который передавать в контроллер - сделать класс-DI контейнер, умеющий создавать все объекты - взять готовый контейнер, например, Pimple
> Да, и мне это не нравится, но я не придумал хорошего решения для того чтобы избежать дублирования кода. Делаешь один метод, а в нужных местах ставишь if ($isSearch).... Если передан не пустой поисковый запрос - значит, у нас поиск.
> Поэтому вызов этой функции с этими параметрами фактически равен присвоению переменной значения элемента суперглобального массива $_GET c ключем 'q'. Я хотел написать, что проще сразу обращаться к $_GET, но поймал себя на мысли что там придется писать array_key_exists, и код с filter_input может быть получается короче, так что есть смысл его использовать. Ну добавил бы хотя бы strval() и trim() тогда что ли.
>>Базовый контроллер должен содержать какие-то универсальные методы. Но тут явно метод, который нужен только на странице вывода таблицы со студентами. Зачем его помещать в общий для всех базовый контроллер? > Да, это неправильно. Но я не знаю где их лучше расположить. В контроллере вывода списка студентов.
>>Непонятно, чем это отличается от public static function renderView. > Подключает файлы из другой директории. Для этого наверно отдельную функцию заводить и не требуется.
>>Вообще, у тебя в коде слишком много die и exit. Я бы их убрал. > В тех случаях разве не надо быть уверенным в том, что выполнение кода завершено? лучше бы делать return, так как вызывающий может захотеть что-то сделать после обработки запроса.
>>тут слишком много аргументов у конструктора. Надо либо передавать опции массивом, либо, что лучше, разделить их на обязательные и необязательные, необязельные задавать отдельными методами > Они там все обязательные Тогда надо внимательно посмотреть, правильно ли спроектирован класс. Ну например, можно убрать из него функционал генерации URL. Например, так:
- задать функцию-генератор УРЛ вида function ($page) { ... }, которая по номеру страницы генерирует УРЛ (наиболее универсально) - передать объект, генерирующий УРЛ - передать шаблон URL вида /table?order=sort&page={page}, в который класс подставит номер страницы (немного костыльно конечно так как в теории например у 1-й страницы может быть УРЛ немного не такой, как у других, и вообще, может мы захотим номер страницы римскими цифрами вписывать)
Вот у тебя генерация УРЛ по моему по 3 классам раскидана. Может можно ее всю убрать в один класс?
Также, $maxVisiblePages вряд ли обязательный аргумент. Можно задать ему в классе значение по умолчанию и метод для изменения (и скорее всего он даже не понадобится).
Вот видишь, мы обнаружили в итоге что класс решает 2 задачи сразу (расчет пагинации и генерацию УРЛ) и этим вызвано такое большое число аргументов.
>>getStudentTableLink($order = null, $sort = null, $query = null) > Но это приведет к загромождению view. Ну не знаю, мне кажется, что нет. Ну можно попробовать сделать еще так:
getTableLink(['page' => 1]), getTableLink(['order' => 'name']), то есть передавать только параметры, которые должны измениться.
>>Я вижу что тут переменные вставляются прямо в SQL запрос, значит возможна SQL инъекция. > Да, поэтому пользовательские данные не вставляются напрямую, а вставляется значение которое соответствует запросу. > Это, конечно, костыль но я не знаю как это лучше сделать. Проверку надо делать прямо в этом классе, а не где-то далеко в контроллере. Чтобы была гарантия, что неправильное знаечние ни при каких условиях не попадет в запрос.
Если ты делаешь проверку в контроллере, во-первых, трудно ее найти, во-вторых, кто-то может вызвать функцию работы с БД, передав в нее непроверенные данные.
>>А что это значит? Должны чередоваться не-пробел и не-@? Вроде "@ @ @ @ @ @" ? > Любой символ кроме проблема и @. Ну у тебя там неправильная регулярка. \S[^@] значит "сначала идет символ, не являющийся пробелом, за ним идет символ, не являющийся @".
> Он там для того, чтобы создать пустую директорию. Для этого используют файл с другим именем, например .gitkeep. .gitignore - это специальное имя, там задается список файлов, которые не должны попасть в репозиторий, и его лучше иметь в одном экземпляре в корне.
Надо разобраться, в чем проблема. Скорее всего в том, что ты используешь col-md-3, а это float. Флоаты выстраиваются горизонтально, а если места не хватает, то они пытаются встать ниже, и видимо потому 5-й блок оказался под 4-м.
Тебе надо вместо флоатов использовать inline-block, которые выстраиваются в строки и переносятся аналогично буквам.
Ну и это показывает, что тебе надо бы изучить CSS. Бутстрап придуман для тех, кто уже знает CSS. У нас в ОП посте есть задания по CSS.
Там есть ограничение, какие поля могут передаваться из POST в модель по умолчанию - только явно разрешенные. Если это не делать, то будет уязвимость и злоумышленник сможет при редактировании обновлять любые поля.
Описано же в мануале (хотя если честно, замучался искать, но ты как специалист по Юи должен был найти быстрее меня):
> Я исправил этот пробел, и это починило всё(!), за исключением наклона и отсутствия легких шрифтов в ie<8. Я решил заглянуть в MSDN (мануалы майкрософта), чтобы найти информацию про font-face в ИЕ. Если что, информация по ИЕ есть в MSDN, по фаерфоксу в MDN, а у других браузеров нет таких сайтов и они обычно кивают в сторону стандартов, мол они их поддерживают.
Я думаю, что в данном случае особо делать ничего не надо. Раз ИЕ8 и ниже не поддерживают семейства из нескольких начертаний, то пусть отображают шрифт как умеет. Моя точка зрения такая, что для малопопулярных браузеров достаточно, чтобы сайтом можно было пользоваться, а каким шрифтом будет отображена информация, не так и принипиально.
Если хочется поддерживать ИЕ8 и ниже, придется наверно делать отдельный CSS файл, подключаемый через условные комментарии https://msdn.microsoft.com/ru-ru/library/ms537512(v=vs.85).aspx . В нем объявить шрифты каждый под своим именем, только с eot файлами, например IeLatoRegular, IeLatoBold. Вписать эти имена в отдельные CSS правила только для ИЕ:
h1 { font-family: IeLatoBold, sans-serif; font-weight: normal; - сбрасываем вес, чтобы ИЕ не пытался "ужирнять" шрифт }
Но на мой взгляд, оно того не стоит. Достаточно, чтобы в ИЕ можно было прочесть текст. То есть я за поддержку максимального числа браузеров, но без цели сделать чтобы везде выглядело одинаково и без больших затрат времени на древние браузеры. Это лично моя точка зрения, другие считают по-другому - кто-то просто не умеет поддерживать старые браузеры, кто-то не хочет, кто-то требует чтобы везде страница выглядела одинаково.
> Firefox, кстати, всё равно выдает ошибки парсинга font-weight на значения bolder и lighter (если их убрать то ничего не изменится). Как такое может быть? Это относительный вес ("чуть потяжелее") и его не стоит указывать внутри font-face в любом случае, так как непонятно относительно чего его отсчитывать.
https://github.com/someApprentice/maintaskforlayout/blob/master/stylesheets.css#L97 > font-family: Lato, 'Times New Roman', Arial, Helvetica, sans-serif; Times New Roman совсем не похож на Lato (у него засечки). Я бы Arial и Helvetica тоже убрал (а зачем?) и оставил бы только Lato и sans-serif. sans-serif определен в стандарте и любой браузер должен уметь отобразить текст таким шрифтом. Arial это по сути стандарт де-факто (даже на тех системах, где его нет, например, Андроид, вместо него подставляют что-то похожее), но зачем он нужен, если есть sans-serif.
> a { > font-weight: bold; > color: #d9d9d9; > text-decoration: none; Что-то мне не очень нравится стиль. Серые неподчеркнутые ссылки жирным шрифтом. Должны ли они так выглядеть везде? Если ссылки жирные в меню, может стоит их только там такими и делать.
> p { > font-weight: lighter; Вот это мне тоже не нравится. Почему вес шрифта изменен именно для абзацев? А что насчет таблиц, списков? Если ты хочешь сказать, что шрифт по умолчанию должен иметь вес 300, то надо объявить это на элементе html - шрифт по умолчанию задается именно там.
> .header ul { Хочу предупредить насчет таких селекторов, что на мой взгляд это селекторы слишком широкого действия и в будущем они могут распространиться на те элементы, для которых не предназначались. Вот допустим завтра кто-то добавит в шапку ul и твои правила к нему применятся. Придется разгребать код и смотреть, как исправить их.
Я думаю, что тут ты не хотел написать "для всех списков внутри шапки". Скорее, ты хотел написать "для меню в шапке". Ну тогда так и напиши: .header .header-menu { ... }. А теперь, если подумать, то не так важно где находится это меню - в шапке или нет, и можно упростить до .header-menu { ... }.
Важно делать селекторы максимально точными, иначе потом будет придется больше усилий тратить на поддержку верстки.
> .header ul :nth-child(1n) { С этим правилом проблема в том, что если мы захотим сделать подменю внутри меню, то правило сработает и на него. Лучше писать что-то вроде .header-menu > li.
Видно, что между шапкой и бледно-серым блоком есть белая полоска. Скорее всего у тебя там margin collapsing - маргин вывалился из шапки или из серого блока.
насчет хаков с :nth-child - мне кажется, для ИЕ лучше использовать либо специальные ориентированные на него хаки (звездочка или минус перед именем свойства), либо отдельные стили, подключенные через условные комментарии. А у тебя это по сути тест не на поддержку ИЕ, а тест на поддержку CSS3. И допустим старый фаерфокс получит те же правила, что и ИЕ, а ты вряд ли такое задумывал.
По моим ощущениям, у тебя многовато этих хаков с nth-child. Лучше наверно стараться, чтобы правила для ИЕ были как исключение, а не правила для нормальных браузеров.
Я бы использовал хак со звездочкой для ИЕ или отдельный файл стилей.
> .consectetur::before { > .tristiquet::before { > .fermentum::before { Тут написано почти одно и то же. Надо избавиться от повторов. Размеры картинки там почти одинаковые, проще сделать их везде одинаковыми.
>.services .content .box p { Что-то многовато тут компонент в селекторе. Зачем, например, тут .content? Он тут по моему лишний.
Когда задаешь font-size, стоит задавать и line-height. В абзаце текста под заголовком "Consectetur" например строки стоят очень тесно, правильный ли там line-height?
> .portfolio .content .works :nth-child(4n) { > padding-right: 0px; Это плохая идея, так как подразумевает что картинки идут ровно в 4 ряда, хотя на узком экране удобнее их размещать например по 2-3 в ряд. И будет ли это работать корректно, когда мы скроем часть картинок?
> .rss:before { > .facebook:before { Надо избавиться от повторов
> @media (max-width: 1110px) { Что-то тут подозрительно много правил. Это может говорить о том, что верстка сделана не очень гибко и плохо подстраивается под внешние размеры.
И мне кажется что точка переключения 1110px не очень удачная. Наверно, лучше сделать ее в районе 700-800px, так как на большем размере блоки consecutor смотрятся не очень удачно.
ну и например, что касается меню, можно для него использовать свои правила, например, перемещать логотип вверх только при ширине меньше 500px. А то на 800px там места сбоку вполне достаточно остается.
Для иконок соцсетей надо сделать реакцию на наведение.
Далее, я открыл отладчик в Хроме и закомментировал тег link, подключающий CSS файл. Именно так, без CSS, видят твой сайт поисковые роботы и программы чтения вслух. Сразу же нашлась проблема: ссылки на соцсети сделаны пустыми тегами <a>. Это плохо, надо бы, чтобы в них был какой-то текст, например название соцсети или надпись "мы на facebook".
Адрес и номер телефона при отсутствии CSS склеились слитно.
title у тебя идет раньше чем meta charset. Это может привести к тому что meta charset будет проигнорирован.
>>875388 Покажи решение задачи про Айфон - по всей видимости, ты её тоже неправильно решил. Во втором банке (это тот же по параметром, который был в задаче про Айфон) должно получиться 61270, около того.
>>875407 Попробуй начать с того, чтобы регулярка просто верно определяла + 7, +7 и 8, потому что у тебя в самом конце такое: 7 234 5678901 - correct. Дальше пробуй код, дальше основной номер. Надо идти по чуть-чуть в этой ситуации.
>>875483 Что я только что прочитал, это бред какой-то. >Социально незащищенные категории: Инвалиды Что бы это значило? Инвалиды же и так получают пенсию, она у них явно больше 12к. Неужели, инвалид пойдёт работать за меньшие деньги, чем у него пенсия?
Как нормально подключать скрипты жс? Нихуя не выходит чет. Есть у меня файл шаблон, в нем же лежит js скрипт. Подключаю <script src="search.js"></script> - не работает. ЧЯДНТ?
По моему ты невнимательно пользовался инструментами разработчика. На вкладке Network надо нажать на запрос с search.js и проверить, что в содержимом правильный JS код, а не HTML.
Короче я понял в чем проблема. Суть в том, что я запускаю не какой-то файл, а метод контроллера из корня сайта, в index.php. Поэтому естественно не срабатывает подключать скрипт из просто закинув его туда же, куда и шаблон. Как тогда правильно подключать? Пробовал указывать путь <script src="/app/scripts/search.js"></script> - не срабатывает. Еще пробую <script src="<?php echo getcwd() . "\app\scripts\search.js"; ?>"></script> - но так возникает ошибка, браузер не разрешает из пеки грузить скрипт.
У меня есть ощущение, что урок выше тебе все же надо прочитать.
Ты написал первоначально script src="search.js". То есть ты использовал относительный путь. Очевидно что тебе надо сначала изучить, как работают относительные пути, прежде чем их использовать. То есть прочитать урок по ссылке.
Ты пытаешься наугад подобрать правильный путь. Так не пойдет. надо писать код, полностью понимая, как он работает, а не перебирать разные варианты.
> Суть в том, что я запускаю не какой-то файл, а метод контроллера из корня сайта, в index.php > браузер не разрешает из пеки грузить скрипт. У тебя проблема с пониманием, как работает браузер и веб-сервер. И также проблема с пониманием, как устроены ссылки и что можно, а что нельзя писать в атрибуте src.
Браузер, как я написал, ничего не знает ни про PHP, ни про то, откуда на сервере берется страница. Он просто посылает запрос и получает в ответ HTML-файл, находит в нем ссылку на скрипт и посылает второй запрос для его получения.
Тебе надо:
- разобраться с относительными и абсолютными ссылками - исправить приложение, чтобы при запросе с неправильным URL вроде /search/search.js отдавался код 404 как и положено в протоколе HTTP
>>875192 зачем ? просто загрузил в модель или модели , сделал сейв и либо отрисовал вьюху или узнал id этой записи (в AR должна быть функция) и направил на контроллер который будет брать эту запись с базы и рисовать во вьюхе
>>875253 >Надо использовать lastInsertId не прокатит например если я сохранил запись а за мной сразу человек ешё сохранил запись оно вернёт значение записи 2 человека тк оно и будет последнее
>>875667 >- разобраться с относительными и абсолютными ссылками >- исправить приложение, чтобы при запросе с неправильным URL вроде /search/search.js отдавался код 404 как и положено в протоколе HTTP Читал. Мало чего понял, но вроде как просто "search.js" - это относительный путь, тогда абсолютный должен быть \app\scripts\search.js? Т.е. от корня сайта. Но не работает же.
> The ID that was generated is maintained in the server on a per-connection basis. This means that the value returned by the function to a given client is the first AUTO_INCREMENT value generated for most recent statement affecting an AUTO_INCREMENT column by that client. This value cannot be affected by other clients, ....
>>875691 Лол, так я это уже много раз делал. Не работает. Т.е. я так понимаю, если указать абсолютный путь, то без разницы из какого скрипта ты подключаешь другой скрипт? Вот есть у меня сайт students.local, скрипт лежит в /app/scripts/search.js, значит абсолютный путь будет src="/app/scripts/search.js"? Может мне лучше весь код показать? Заодно разберусь как выгружать проект на гитхаб. Но уже завтра.
>>875702 >Может у тебя .htaccess файлы переопределяет работу сервера? Тогда тебе надо разобраться в директивах, которые там вписаны. Бля лол, спасибо. Это же надо так, слона то и не заметил. У меня же там просто редирект на index.php в любом случае. >Код можешь показать, я гляну. Тогда уже как студентов доделаю.
Как изучать YII2? Прочитал документацию, посмотрел несколько видео. Понял как создавать модели, контроллеры, представления, понял как обрабатывать и выводить информацию в простейшем случае, узнал что есть хелперы и виджеты, которые всё упрощают, сделал постраничную разбивку, сделал формы, научился записывать в базу данных и выводить из неё данные. Смог написать блог, с добавлением записей, их отображением и сортировкой. Работает. Но такое ощущение что так ничего и не понял. Все эти модули, компоненты, приложения и многое другое о чём пишется в документации, воспринимаются как другая вселенная, я о них читаю и не представляют как их можно вписать и как их использовать. Складывается ощущение, что если не смотреть как кто-то их использует на реальной практике, я не смогу понять их смысл. Так как подсматривать не у кого, что делать? Как вы учили YII2 дальше знаний необходимых для создания блога? В документации у всех этих компонентов, модулей и всего остального нет демонстрации реального использования, только немного о том как они устроены, их код и синтаксис внутри фреймворка, и словесное описание для чего они нужны. Но так очень сложно понять их смысл.
>>875380 >https://someapprentice.github.io/maintaskforlayout/MotherfuckingWebsite.html - вот это конечно никуда не годится. Ладно, отсутствие полей у html можно объяснить необходимостью, но шрифт по умолчанию С этим ещё я не разбирался, сначала нужно было с шрифтами разобраться. Закинул чтобы посмотреть что будет и случайно закоммител его.
>Я решил заглянуть в MSDN (мануалы майкрософта), чтобы найти информацию про font-face в ИЕ. > >https://msdn.microsoft.com/ru-ru/library/ms530757(v=vs.85).aspx А я заместо этого читал про свойство font-weight в котором об этого ничего не сказано, а лишь помечено версией CSS2.1. Не удивительно что у меня столько проблем.
>http://itsravenous.com/ Красивый дизайн. Похоже у меня появился один из примеров как должно выглядеть среднестатистическое портфолио верстальщика. (Для себя я сделаю что-нибудь по лучше)
>Я думаю, что в данном случае особо делать ничего не надо. Раз ИЕ8 и ниже не поддерживают семейства из нескольких начертаний, то пусть отображают шрифт как умеет. Моя точка зрения такая, что для малопопулярных браузеров достаточно, чтобы сайтом можно было пользоваться, а каким шрифтом будет отображена информация, не так и принипиально. Интуитивно я приходил к этой мысли.
>Но на мой взгляд, оно того не стоит. Достаточно, чтобы в ИЕ можно было прочесть текст. То есть я за поддержку максимального числа браузеров, но без цели сделать чтобы везде выглядело одинаково и без больших затрат времени на древние браузеры. Это лично моя точка зрения, другие считают по-другому - кто-то просто не умеет поддерживать старые браузеры, кто-то не хочет, кто-то требует чтобы везде страница выглядела одинаково. Мне все равно, я могу сделать как угодно, оказывается, это не так уж и сложно. Мое мнение, это зависит от цели. Думаю, в обучающих целях сделаю, чтобы везде было одинаково.
>> .consectetur::before { >> .tristiquet::before { >> .fermentum::before { >Тут написано почти одно и то же. Надо избавиться от повторов. Размеры картинки там почти одинаковые, проще сделать их везде одинаковыми. Я пытался это сделать, присвоить для всех заголовков общие свойства, но ничего не получилось https://jsfiddle.net/3fsukce0/
> .portfolio .content .works :nth-child(4n) { > padding-right: 0px; >Это плохая идея, так как подразумевает что картинки идут ровно в 4 ряда, хотя на узком экране удобнее их размещать например по 2-3 в ряд. И будет ли это работать корректно, когда мы скроем часть картинок? А как тогда убрать отступ для последнего элемента в ряду? Учитывая что он не последний элемент по списку.
>>875765 Ну и как газлом качать многопоточно? Нужно как минимум pthreads ставить. Да и информация по этому расширению в сети скорее справочная, для тех, кто уже работал с многопоточностью в других языках. Для Java есть целые вводные книги по многопоточности.
Не нужно. Нужно разобраться в возможностях курла и guzzle.
pthreads и треды уровня ОС работают хорошо только пока их мало. Странно, ты пишешь что работал с многопточностью, но не знаешь про другие подходы (например кооперативная многозадачность и асинхронные операции внутри одного потока ОС).
Yii очень гибкий, на некоторые вопросы о том, как правильнее использовать компоненты, разработчики отвечают, "Как хотите".
Есть https://github.com/samdark/yii2-cookbook можно полистать её, но лучше всего, смотреть, как сделаны готовые приложения или проекты. Хотя везде всё не однозначно.
>>876044 > должен быть. В описании написано, что книга полностью свободная, пишется Макаровым и контрибуторами с гитхаба, поэтому "полный сборник" искать бессмысленно. Есть ещё полный Cookbook, но он по Yii 1.
поясните ньюфагу, для чего в пышке имена переменных предваряются долларом? Только начал учиться по гайдам опа, никаких затруднений нет, но необходимость вставлять доллар перед именами заёбывает ппц как.
>>876209 А var писать в JS/Pascal не надоедает? А объявлять тип переменной в C/C++/Java/C#? В Perl и Bash тоже доллары предваряют переменные, привыкнешь и не будешь замечать.
Где можно почитать про так называемые "горячие клавиши", которым вы наверняка вы пользуетесь и какими чаще? Я имею ввиду допустим когда я пишу код все время переставлю все мышкой, кроме очевидных абзацев клавишей enter.
>>876209 Чтобы была иллюзия прибыльности в изучении программирования в общем и использования этого языка в частности... (Смахивая скупую мужскую слезу.)
>>876386 Я может в глаза долблюсь, но в твоем пикрелейтеде не вижу, как в атоме отформатировать код? Для примера, в нетбинсе я жму контрол-шифт-f и у меня сразу пробелы, отступы, переносы скобок и вся такая фигня появляется, а как в атоме?
Привет, не могу понять как реализуется наследование в es3. Что такое "хак с прототипами" ? Rabbit.prototype.__proto__ = Animal.prototype;? В learn.javascript наследование описано с помощью Object.create().
Всем доброго дня, http://ideone.com/YSfidW - опечаточки. Проблема в том, что бормалеи-корупционеры меняют сразу по две, а то и три буквы в слове и получается не очень. http://ideone.com/meYReN - Gr. Nazi. Вроде работает.
>>876632 Ну я в игори не играю, поэтому мне хватает некропеки. Поставил пхпшторм - тормозит, один запуск секунд 30-40 чего стоит. Поставил нетбинс - все летает, грузится за 5 секунд, а функционал тот же. Еще и швабодно.
>>876628 Поставил я плагин, а оно мне ошибку, гуглю ошибку - 24000 результатов и танцы с бубнами. С емаксом то я погорячился. Атом - стильно, модно, молодежно и малопригодно к использованию.
>>876653 нормально пригодно, лол. Да, у меня тоже не работает плугин (php-linter), а некоторые настраивать надо. НАпример этот же бьютифаер может потребовать немного в конфиге поковыряться или зависимости поставить
>>876653 Потому и стоит использовать IDE. Когда используешь редактор все время хочется еще какого-то функционала, а значит куча времени уходит на танцы с бубнами, в то время как в IDE есть все сразу искаропки. Тот же нетбинс удобен, швабоден, и темку можно как в атоме поставить, например.
А у меня шото, шо то тормозит. При то что саблайм текст нормально работает и я того же от атома ожидал в надежде уйти на него со шторма, хотя в нем всё же нет менеджера баз данных например и еще некоторых плюшек
>>876687 >А у меня шото, шо то тормозит. Поставь пакет нетбинса, в котором только пхп+хтмл/цсс+жс. Тогда норм должно быть. Если и тогда будет тормозить - ну тогда не знаю, твоя последняя надежда эклипс.
>>876520 Я его у другого анончика украл из готового решения, хех (когда одним глазком подсмотрел непонятный момент в задаче), так что не знаю что за способ. Обычный цикл с вызовом функций. Лет? 0,25, т.е. 3 месяца (если сложить время продуктивного обучения, то наберется на недели 3).
>>876822 Зачем ты его бампаешь? ОП проверяет всех без исключения, только это происходит не сразу и по очереди. А кроме ОПа тебе вряд ли кто-нибудь хороших советов напишет.
Куда дальше копать в отношении этого задания ? Как добиться того, чтобы 8 (8122) 56-56-56 - этот номер принимало ? Почему из списка неправильных номеров так много проходит ?
Как правильно делать валидацию в на сервере? Гугл находит статьи, в которых данные просто надо прогонять через кучу функций типа трим, стрип_слешес и прочее, но я чую, что это плохой способ. Как это делать правильно?
>>877253 Нормальный способ, так оно и бывает. Сейчас смотрю валидацию в Yii2 - там куча валидаторов, каждый цепляется один к другому, проверяя значение переменной на любые соответствия.
Валидация - это проверка введенных данных на соответствие правилам. Например, что имя пользователя состоит из латинских букв, что возраст - это число от 1 до 200 и тд.
Прочитав этот абзац, подумай, как использование "всяких стрип слешес" относится к валидации? Никак.
trim() это не часть валидации, но ее стоит делать, так как лишние пробелы справа не видны, но могут помешать прохождению валидации.
>>877299 >Валидация - это проверка введенных данных на соответствие правилам. Например, что имя пользователя состоит из латинских букв, что возраст - это число от 1 до 200 и тд. Знаю, а разве вместе с валидацией не убирают пробелы там и прочее?
>>877303 >Валидация - это проверка данных. Убирают пробелы где-то в другом месте кода, например в коде для работы с формами. Хм. А почему нельзя все это в одном классе делать, например?
Точнее так - я хочу сделать класс валидатор, допустим Validator, который убирает проблемы, прогоняет данные через htmlspecialchars а потом проверяет данные по нужным мне критериям. Так сойдет?
> Очистить от мусора, преобразовать "инъекции" в простой HTML. В документации по strislashes написано, что она удаляет мусор и защищает от инъекций?
Ты видимо просто не понимаешь как работают SQL-инъекции (и XSS) и потому не знаешь, как от них надо защищаться. Люди, у которых мало знаний, часто обращаются к религии и суевериям. Потому ты ставишь в начале программы пару "волшебных" функций как оберег.
Валидатор не должен убирать пробелы и тем более прогонять данные через htmlspecialchars. Идея ООП в том, чтобы каждый класс занимался своей задачей, а ты вопреки принципам ООП хочешь все смешать вместе.
> В Yii2 это trim валидатор будет. я сомневаюсь, что это "валидатор", ты по моему просто так думаешь потому, что trim в модели пишется рядом с правилами валидации.
>>877310 Зачем тебе htmlspecialchars, он для защиты от XSS при выводе информации, отправленной пользователем. Не надо думать "понипихаю побольше функций, хуже не будет". Будет. Вот пример: http://pyha.ru/forum/topic/5684 > 'format' => 'json', Заметил сколько мусора здесь? Это потому, что люди бездумно используют кучу функций, думая, что "хуже не будет, только безопасней".
>>877375 >Как отличить SQL-код от не SQL кода? LIMIT 10 это SQL код или нет? Что, если надо опубликовать комментарий или пост, содержащий SQL код? Теперь понятно.
>>877350 >Ты видимо просто не понимаешь как работают SQL-инъекции (и XSS) и потому не знаешь, как от них надо защищаться. Люди, у которых мало знаний, часто обращаются к религии и суевериям. Потому ты ставишь в начале программы пару "волшебных" функций как оберег. Я только ещё учусь. Но ты же не думаешь, что не нужно преобразовывать введённый пользователем код в простой и безопасный HTML? А чего тогда? Мы только об этом и говорим пока, что это нужно. >я сомневаюсь, что это "валидатор", ты по моему просто так думаешь потому, что trim в модели пишется рядом с правилами валидации. Это базовый FilterValidator ([[yii\validators\FilterValidator|trim]]), вот его структура: [ [['username', 'email'], 'trim'], ] Никто не говорит про смешать всё вместе и не по ООП, мы говорим про то, что надо всячески проверять введенные данные на клиенте и сервере, для этого надо использовать функции, если человек всё пишет с нуля.
Там написано, как с ними бороться. Ну например, в случае с SQL мы используем плейсходеры или экранируем данные в функции работы с БД. Делать любое экранирование надо в том месте где данные используются - чтобы сразу было видно, что все безопасно.
Делать это например в контроллере (как ты предлагаешь) не имеет никакого смысла, так как данные по пути могут подвергаться разным преобразованиям и отследить, что с ними происходит, и куда они передаются, сложно. И соответственно понять, правильно ли все сделано, тоже сложно.
Также, данные надо по-разному экранировать и обрабатывать в разных случаях. Например, одним способом перед выводом на странице, другим при подстановке в JSON и третьим при вставке в SQL запрос. Ты это никак не учел.
Потому не надо писать бессмысленные функции. Если у тебя правильно экранируются данные, то, что бы не пришло от пользователя, угрозы нет. И скорее всего эти данные будут отловлены еще на этапе валидации.
А если ставить бессмысленные преобразования, как ты предлагаешь, то данные будут искажаться, как это видно по ссылке на форум выше.
> Это базовый FilterValidator ([[yii\validators\FilterValidator|trim]]), Действительно, в неймспейсе написано validators. Но я не поленился заглянуть в код:
Это просто разработчики Юи неудачно назвали класс. Это правильнее называть "фильтр". Чтобы увидеть разницу между фильтром и валидатором, можно попробовать применить валидацию не к данным из формы, а например к данным из БД. Для них trim делать не потребуется, так как они там уже отфильтрованные.
> что надо всячески проверять введенные данные на клиенте и сервере, для этого надо использовать функции, если человек всё пишет с нуля. Проверять надо, но ты-то предложил просто поставить в начале strip_tags не особо разбираясь, к чему это приведет. А приведет это к искажениям пользовательских данных.
Анончик, ответь, пожалуйста, на нубовопрос. Задачка из учебника ОПа про кредиты на гейфон. И в конце вывожу методом echo переплату и период. Причём переплата вычисляется непосредственно в методе. Из-за чего в выходной строке пропадает слово "Переплата" как на пикрелейтед. Почему так происходит? И как правильно вставлять выражения в строку вывода?
>>877662 Это из-за приоритета операторов, сначала происходит конкатенация строки "Переплата" и переменной $total, а из получившегося результата вычитается $credit. Можно явно указать PHP повысить приоритет для вычитания, обернув выражение $total - $credit в скобки.
Здесь вертикальная черта имеет самый низкий приоритет, то есть если разбить твое выражение на чсти, получается
(\+7) или (\+\s7) или (^8) или (^\\s8([0-9](\s|\-|\(|\))?){10})
То есть например, если номер начинается с 8 то он всегда пройдет независимо от того, что идет дальше. Или если в номере на любой позиции есть +7, он тоже проходит.
Ты наверняка имел в виду что-то другое, потому используй круглые скобки, чтобы огранить действие вертикальной черты. Примерно так: (a|b|c)d
Далее, \+7 и \+\s7 можно легко объединить вместе.
(\s|\-|\(|\))? - это значит, что может встретиться любой из этих символов не более 1 раза. Но я бы сделал, чтобы они могли встретиться любое число раз, так как например скобка может быть окружена пробелами.
Через плейсхолдеры можно подставлять только числа (WHERE x = 100) или строки в кавычках (WHERE x = 'abc'). Подставить имя колонки нельзя, так как оно вставится как ORDER BY 'name' - и смысл меняется, так как 'name' это постоянная строка, а не значение соотв-й колонки.
Подставлять имя колонки придется напрямую в строку. Чтобы не было инъекции, сделай тут же проверку на то, что переменная содержит какое-либо из разрешенных значений.
> \p{Cyrillic} Так можно писать? да, помню что-то такое. Интересно, редко используемая возможность.
Проблема твоей регулярки в том, что она реагирует даже на слово целиком из латинских букв. А это неправильно. Надо искать слова, содержащие буквы обоих алфавитов. В том числе английские слова где буква заменена на русскую.
> Проблема в том, что бормалеи-корупционеры меняют сразу по две, а то и три буквы в слове и получается не очень. Для этого надо брать найденные регуляркой слова и уже в них например делать замену латинских букв на такие же со скобками.
Gr. Nazi.
Боюсь, у тебя проверяются не все правила. Вот например: "нет пробела после запятой, точки с запятой, восклицательного знака, вопросительного знака, двоеточия" - это не проверяется. Или "в тексте есть слово «координально» или «сдесь», «зделал», «зделаю», «зделан»". Также, есть правило для "но", но нет правила для "а".
Выражения для жы/шы можно было бы объединить вместе.
Я думаю, ты зря там используешь preg_quote и проще было бы сразу писать нужные регулярные выражения.
__proto__ - это нестандартная конструкция и ее использовать не стоит (ее используют в учебнике для простоты). В ES5 есть функция Object.getPrototypeOf(o) чтобы получить прототип объекта (а в ES6 - еще и Object.setPrototypeOf()).
В JS есть 3 способа создать объект с заданным прототипом:
1) в ES5 есть функция Object.create(p), которая создает пустой объект с прототипом p 2) в ES6 есть Object.setPrototypeOf(), которая задает объекту прототип 2) с помощью оператора new
В ES3 нам доступен только new. Посмотрим, как он работает:
function F() { ... }; F.prototype = p; obj = new F;
Оператор new F() делает следующее:
- создает новый пустой объект - делает его прототипом объект, хранящийся в F.prototype - вызывает функцию F, передав в качестве this новый объект
Таким образом, мы можем написать на ES3 аналог функции Object.create(). Очевидно, что нам надо использовать оператор new, а объект-прототип p сохранить в свойство prototype функции-конструктора. Саму функцию-конструктор можно сделать пустой:
function createWithPrototype(p) { function F() {}; F.prototype = p; return new F(); }
> А я заместо этого читал про свойство font-weight в котором об этого ничего не сказано, а лишь помечено версией CSS2.1. Не удивительно что у меня столько проблем. Видимо там имелось в виду свойство, задающее вес шрифта в тексте, а не определяющее вес подключаемого шрифта.
>>Это лично моя точка зрения, другие считают по-другому - кто-то просто не умеет поддерживать старые браузеры, кто-то не хочет, кто-то требует чтобы везде страница выглядела одинаково. > Мне все равно, я могу сделать как угодно, оказывается, это не так уж и сложно. Мое мнение, это зависит от цели. Думаю, в обучающих целях сделаю, чтобы везде было одинаково. Ну попробуй, если хочешь.
> Я пытался это сделать, присвоить для всех заголовков общие свойства, но ничего не получилось https://jsfiddle.net/3fsukce0/ h3 и h3::before это разные элементы. Потому нельзя задавать content на h3, надо на h3::before.
> А как тогда убрать отступ для последнего элемента в ряду? Учитывая что он не последний элемент по списку. Надо что-то придумать. Может быть можно делать отступы слева, и задать отрицательный маргин на контейнере, который компенсирует первый отступ:
Может тебе надо попробовать сделать что-то посложнее блога? У нас в ОП посте есть задача на сайт TestHub например.
- "компоненты" в Юи, как я понимаю, это обычные классы-сервисы, выполняющие какую-то функцию. Например, компонент для отправки уведомлений на почту. - "модули" нужны для группировки контроллеров, вью и моделей в больших приложениях. Когда у тебя будет 20-30-40-50 контроллеров и куча моделей, неудобно хранить все в одной папке. Удобно разбить приложение на отдельные модули. Также модули можно делать для повторного использования. Например, модуль форума, который можно подключить к любому сайту. - "приложения" можно исплользовать, например, если мы хотим в одном проекте реализовать несколько сайтов, мы можем сделать каждый отдельным приложением. При этом какие-то модули можно использовать в нескольких приложениях сразу. Иногда админку или личный кабинет делают отдельным приложением. Главное что для приложения можно задать индивидуальные настройки.
Вот ты наверно не писал большие приложения, но без разделения их на каике-то модули получается очень неудобно. По моему опыту, как раз схема с модулями работает очень хорошо. Вот допустим у нас есть огромный сайт и мы хотим добавить новый раздел. Мы просто добавляем новый модуль и в нем создаем контроллеры, модели, вью для этого раздела. И в итоге наше приложение состоит из относительно небольших модулей, и мы можем работать только с одним модулем, не залезая в другие. А без модулей нам бы пришлось в папку с 50 контроллерами добавлять еще несколько и они бы там просто перемешались все.
В общем, модули и приложения нужны для организации кода в больших приложениях.
>>877694 Я вот этот парень >>876599. В Gr.Nazi использовал такой подход чтобы упростить добавление или удаление правил и все правила я не прописал, постараюсь переписать для каждого правила своя регулярка. Над "опечатками" мысль принял к обдумыванию. Тысячу лет жизни тебе ОП.
Возомжно ли нетбинс обмазать под JS и HTML/CSS так, что бы не пользоваться вебштормом? А то нетбинс и быстрей, и бесплатный, и в качестве ide для пхп меня более чем устраивает.
Подскажите, нигде не могу найти информации: Есть ли какой то существенный недостаток такого использования $$ http://ideone.com/fpraVK кроме засорения пространства имен ? Я конечно не так использую, просто для наглядности сделал пример. К примеру у меня есть большой массив который хранит в себе информацию по действиям который должны выполняться над некоторым текстом, и чтобы не выдумывать имена переменным внутри foreach я использовал $$ с ключом .
>>878073 те., я бы прочитал этот кусок так: "должны быть цифры и опционально разделители. И суммарно их должно быть не больше 10". Но в итоге число 10 применяется именно к цифрам, а не ко все длине строки.
{10} применяется к тому, что идет перед ним, в данном случае там круглые скобки и повторение относится к их содержимому. То есть 10 раз x ( любое число дополнительных символов, за которыми ровно одна цифра ). В итоге получается ровно 10 цифр и произвольное число доп. символов перед каждой.
>>878072 foreach ведь перебирает элементы начиная с 0, а array_pop уменьшает стек, поэтому в массиве text_r(reverse)_ar будет не столько же элемов, сколько и в стеке. Поэтому я решил исп. простой цикл. Или я хуйню несу?
Длительно работающие скрипты лучше запускать из командной строки, а не в браузере. По поводу твоей проблемы - надо отслеживать, что передается по сети и смотреть, в чем проблема. Для начала - на вкладке Network в инструментах разработчика и далее в WireShark.
Все зависит от того, какое ПО стоит на сервере и какие у него настроки. Может быть там использутся нгинкс в таком режиме, что он сначала получает весь ответ, а только потом отдает клиенту.
> (ideone не отобразит) Почему не отобразит? Надо, чтобы отображал.
> $sinalpha=$lk/$lo; Надо выбирать нормальные имена переменных. Что такое lk? Непонятно.
> $alpha=$key/$radius; Вот наверно здесь ошибка. Непонятно, на каком основании ты делишь номер буквы на радиус? Надо преобразовть номер буквы в угол так, чтобы получались бы числа от 0 до 360 градусов. Градусы потом перевести в радианы с помощью deg2rad(). И радианы уже подставлять в синус.
> sin($alpha)*57.2958 Это попытка перевести радианы в градусы? Неправильно. Радианы и градусы - это меры величины угла, и радианы являются аргументов функции sin(). А результат sin() - это отношение сторон треугольника, от 0 до 1, и его умножать на 57 не имеет никакого смысла.
Ребята, плАчу в голос: знакомый прислал тестовое задание на джениора в контору, в которой он работает, у них там всё на yii2. Эх, я вообще тупой и никуда не гожусь - я даже не понимаю, как так можно сделать, чтобы в любой год находился, допустим, второй вторник ноября... Вот ТЗ тестовое:
Тестовое задание, Yii2 - несколько событий, обработчики, запуск и оповещения; - веб-интерфейс создания и настройки события: само событие, время срабатывания (месяц, число, день недели и час суток) и время окончания, прочие условия срабатывания на своё усмотрение (выбор конкретного год срабатывания события или выбор повторения события каждый год). - проверка: 1) события должны срабатывать каждый первый понедельник июня вне зависимости от года; 2) события должны срабатывать каждый четвёртый вторник ноября вне зависимости от года; 3) события должны срабатывать каждые третье воскресенье ноября вне зависимости от года; - срок реализации: 5 часов. Я плачу и ору в голос, не понимаю, что тут возможно сделать. P.S. Я не устраиваюсь туда, просто решил проверить себя, годен ли. Подскажите, как такое реализовать, чтобы конкретные дни недели определить в любой год.
>>878307 Спасибо! http://ru.wikibooks.org/wiki/Реализации_алгоритмов/Вечный_календарь#PHP Но я всё равно пока не соображу, как именно ко дню недели это привязать. Вот надо найти второй вторник ноября в любой год. Например, можно сделать цикл switch, в котором прогонять каждый день ноября через алгоритм, если это вторник - вуаля, событие активизируется. Я верно мыслю?
Тебе ведь не надо определять, какой день будет вторым вторником. Тебе надо только проверить, что сегодня второй вторник ноября, а это проверяется элементарно:
- проверяем что сегодня вторник - проверяем (по числу прошедших с начала месяца дней) что до сегодня в месяце был ровно один вторник
Нетрудно обобщить функцию до проверки что сегодня N-й по счету день недели M.
>>878344 Как я понял, именно так - находишь дату, инсертишь в базу сразу на текущий год (например, 1 января каждого года или 31 декабря на будущий), а потом в эту дату срабатывает event, либо каждый день проверяется дата на такое соответствие и если находится, то срабатывае event (наверное, так даже предпочтительнее). UPD: Знакомый сейчас сказал, что желателен для запуска проверки соответствий каждый день, чтобы любые изменения в течение года чекать. >>878363 Спасибо, тоже интересный подход. Хотя, в принципе, и в алогритме вечного календаря тоже всё есть, что нужно для этого. UPD: Ну йокарный бабай, всё это есть в простой функции date(), как говорит ОП. Вот так, собака была зарыта неглубоко. >>878384 Если сегодня вторник, то проверяем, не является ли он вторым вторником в ноябре? Хм, немного кажется нелогичным, что ли.. Это так будет каждый вторник в течение года проверяться? Не проще ли экономичней исходить из месяца: - опачки, ноябрь, 1 число - проверяем, не вторник ли это - нет, не вторник - опачки, ноябрь, 2 число - проверяем, не вторник ли это - опачки, вторник - активизируется event >Почитай мануалы по функции date, strtotime Спасибо, посмотрю, пригодится всегда такое. А то я дальше простого вывода времени на сервере ничего не делал. >Этот алгоритм давно встроен в PHP (точнее в стандартную библиотеку Си под линуксом), определить текущий день недели можно через функцию date(). Ору от смеха теперь.... Я эту функцию одной из самых первых выводил на локалочке. Тормозень, короче, полная. Спасибо, ОП, тебя не спутаешь ни с кем. >Я думаю, там нужен крон. Знакомый сейчас сказал, что желателен для запуска проверки соответствий каждый день, чтобы любые изменения в течение года чекать.
В итоге вышло, что тут работы для разибрающегося в Йии2 фреймворке и cron от силы на полчаса, если делать всё руками, а не с помощью Gii. Вот так, буду знать, такая вроде бы несложность, а орал и плакал.
Анончики, устроился на бесплатную практику на фирму.
Получаю задания типа сделай страницу регистрации, измени дизайн главной страницы.
У них есть их личная cms сделанная в 2008 году и все новые и старые проекты пишутся на этой ебаной cms которая написана на первом зенде. Проекты они делают для городских сайтов и учебных заведений и со стремным дизайном.
Как думаете, анончики, стоит ли там оставаться или искать какую-то современную веб-студию которая дрочит на все новое и современное?
>>878518 А какой нужно метод? Я знаю, что вычитаю лишнее, это типа сдача.
Можно высчитывать дополнение 0 до долга, но когда оно будет < 5k, то заплатить его, а не 5к. Но это больше действий занимает, чем просто 1 раз вычесть.
Разумеется, надо запускать специальный скрипт по крону каждый и день и он будет проверять, что назначено на этот день. Вставкой только даты в базу не отделаешься, так как вторник в разные года выпадает на разные числа.
Зенд еще не самый плохой вариант. Он хоть и старый, но модульный и объектно-ориентированный.
Смысла в бесплатной практике я особо не вижу. С таким же успехом ты мог бы сидеть дома, читать учебники, писать свой проект (например, делать нашу задачу на testhub) и узнать гораздо больше.
> Можно высчитывать дополнение 0 до долга, но когда оно будет < 5k, то заплатить его, а не 5к. Но это больше действий занимает, чем просто 1 раз вычесть. Ну да, но ненмного, на 1 строку больше, зато без костылей. Если ты понимаешь, как это сделать, то в принципе можешь и не делать.
>>878560 >Разумеется, надо запускать специальный скрипт по крону каждый и день и он будет проверять, что назначено на этот день. Получается, всё-таки будет лучше так, как ты говоришь: - день недели - вторник - месяц - ноябрь - что у нас на первый вторник ноября? - действие - день недели - среда - что у нас на первую среду ноября? - действие
Сейчас вспомнил, что знакомый говорил про сайт про фитнес с разными тренями. Если это треня рассчитана на сентябрь, допустим, а 1е сентября у нас в среду, то может потребоваться начать треню с 30го августа - чтобы четко вписаться в месяц, там обычно по дням недели рассчитывается: сентябрь, понедельник - то-то, сентябрь, вторник - то-то. Поэтому нужно добавить условия для восстановления этой целостности у недели. И вот тут уже сложнота поперла. Это у меня загоны, канешн, немношк, но походу так и нужно, скорее всего, такое подразумевалось.
>>878571 нет по моему ты усложняешь анон , в задание чётко сказано что сделать , а та часть которая про 2 вторник месяца , это уже считай тесты , если так делать как ты и думать то за 5 ч явно не сделать , на тестовых нужно делать ровно то что дано и не придумывать
>>878560 >Смысла в бесплатной практике я особо не вижу. С таким же успехом ты мог бы сидеть дома, читать учебники, писать свой проект
для этого нужно само организация , не каждый человек её имеет , у меня например чёткие грани между дом\работа , дома я отдыхаю на работе я работаю , если этот анон так не сможет то по пи*де пойдёт обучение , в конторе же хоть по шапке настучат за то что вбыдле сидишь
>>878596 Оке, так тож думаю. Ну просто подумал, для чего такая перда может пригодиться им, пока с тем челом не связывался, выходной. Что посоевтуешь на CodeSchool? Там есть бесплатные курсы ведь? По php и мускулу там норм курс?
>>878545 зенд не так плох , тот же МВЦ потому можешь месяц попрактиковать изучить его в комерц разработке (и в резюме написать , что не домашние странички делал , а сайты этот этот этот делал в них то то то) а потом свалишь на джуна в другую контору , для твоего уровня разницы будь то Ларавель или ЗФ нет
>>878600 по пхп нету ешё , по SQL норм , там сейчас 2 дня все курсы открыты на халяву так что успей пройти . Можно ешё JQ LESS SASS пройти чтоб понимать хоть что это такое
Посоны, почему у Laravel такая убогая документация? Почему там нет ни слова про тот же RedirectIfAuthenticated? Почему не сказано, как вывести ошибки аутентификации/авторизации? Что за хуйня происходит? Хоть бери и пиши свои классы для аутентификации, иначе вообще нихуя не понятно.
>>878679 Обычно говно же какое-то изобрели, которое под конкретный проект с пинками и костылями подходит, криво встает и багами покрывается, сразу ограничивая возможности. Сениорам зарплаты за то и платят, что свое такое могут написать под конкретные задачи и без багов. А для каких-то сложных фич есть подключаемые через Composer библиотеки, CMSы там нахуй не нужны.
>>879116 На самом деле не много, первые 10 задач из мануала я решил за 3 дня. И примерно неделя ушла на решение 11, 12 и 13 задачи. В процессе решения последних были перерывы, и по факту с первой задачи прошел почти месяц.
Статья для идиотов, которые выбирают технологию по тому, что пишут на hacker news. Вчера им сказали писать на Руби, сегодня - не писать.
Я бы еще это отметил:
> фронтенд мигрировал с Prototype на jQuery, потом на Coffeescript, потом на Angular, потом на React.
Хорошо, когда есть лишние деньги, которые можно тратить на ерунду.
Также, в статье используются подогнанные под нужный результат графики. Ну например, график "А здесь показано, что происходит на рынке труда" на первый взгляд показывает превосходство Node.JS, а PHP почти на нуле. Но если присмотреться, то он показывает на абсолютные величины, а прирост в процентах. Пхп очень популярен и потому не особо растет. Понятно, что прирост от 100 до 1000 пользователей на этом графике будет выглядеть выше чем от 10000 до 11000.
> Прямо сейчас Go очень популярен для микросервисов, Писал небольшую утилиту на Го, много неудобных моментов. Не знаю, его нахваливать может только тот, кто плохо разбирается.
Начни с вопроса, а зачем она тебе вообще нужна? Сессии не очень хорошо вписываются в концепцию REST. Зачем ты их используешь? Потому что в сомнительном устаревшем учебнике в каждом файле в начале стоит session_start()?
Также, знаешь ли ты, что сессия (как и куки) будет общая если открыть сайт в нескольких вкладках браузера?
Если тебе все равно нужна сессия, то очевидно:
- сессия привязана к протоколу HTTP , то есть к тому как браузер взаимодействует с сервером, и не может быть частью модели - сессия не может быть частью предсталвения так как никак не связана с задачей отображения данных - значит, с ней надо работать в контроллере.
>>879602 >Сессии не очень хорошо вписываются в концепцию REST. Зачем ты их используешь? Потому что в сомнительном устаревшем учебнике в каждом файле в начале стоит session_start()? Нет, сейчас на курсе по PHP. Дали тех задание написать свою реализацию. Собственно я на функционалке делал сессию и потом проверял её существование чтобы ограничить доступ незалогиненных людей к личным частям сайта.
>- значит, с ней надо работать в контроллере. Хм... Спасибо огромное. Теперь я знаю что мне нужно делать.
> Собственно я на функционалке делал сессию и потом проверял её существование чтобы ограничить доступ незалогиненных людей к личным частям сайта. Неиспользуемые около получаса сессии подчищаются. Недолгая у тебя авторизация получится.
>>879610 >Недолгая у тебя авторизация получится. Ну лично мне для своих нужд именно это и нужно, так что даже хорошо. А на курсе - скорее всего попросят куки прикручивать. А с ними я вообще никогда не работал. Но пока решаю проблемы по мере их поступления.
>если удалить весь текст справа или все пункты меню, верстка не должна ломаться. удалять можно по-разному: li в целом, или только текст, что находится между тегами <а>?
Каким образом вёрстка сломается, если удалить текст справа? Есть ли в коде то, чего можно избежать/заменить?
В Опен сервере если зайти в консоль и попытаться установить composer в какую-нибудь папку, высвечивается:
Package name(<vendor>/<name>) [клыаы/yii]
Проблема в этом клыаы, хоть там и не клыаы а просто каракули напоминающие кириллицу, в чём проблема? Там же должно быть root? Какая-то проблема с кириллицей? Я просто скачал опен сервер и распаковал его на диск С, после чего запустил. Как исправить?
>>880079 100% это ширина родительского элемента В данном случае это body, ну ширина экрана. Зачем ты задаешь ширину в 230p параграфу и вообще применяешь к нему все стили? Примени к article, тк это контейнер, а параграфов у тебя может быть несколько. (конечно если ты не делаешь верстку в стиле газеты)
>>880072 Исправить это можно удалив опенсервер. По какой-то причине на него композер встает криво. Если не хочешь настраивать все ручками, то можешь накатить Winginx. На нем все работает без вопросов. Но лучше все-таки сборками не пользоваться.
Чего врут-то? Тут дело в том, что class и extends - это относительно новые вещи в JS, поэтому для них лучше использовать конверторы из нового синтаксиса в старый, чтобы больше браузеров поддерживало. Об этом у Кантора тоже написано. А твои примеры с наследованием через прототипы - суть одно и то же. Я вот споткнулся на модулях в JS, так как там зоопарк способов организовывать модульный код, да ещё и каждый способ требует ставить какой-то hipster.js
Конверторы, насколько я знаю, работают только из ES6 в ES5. То есть старенькие браузеры ES3 не будут поддерживаться. Стоят ли новые фичи потери кроссбраузерности? Мне это не нравится, хотя это мое мнение, а в индустрии многие об этом даже не беспокоятся.
> Rabbit.prototype = animal; Это в общем довольно неудобный способ, так как требует создать экземпляр объекта, а это может повлечь какие-то побочные эффекты.
> this.__proto__ = animal; Это не часть стандарта ES и соответственно будет работать только в части браузеров. Ну и опять же, надо объект создать сначала.
> Rabbit.prototype = Object.create(Animal.prototype); Это требует поддержки ES5.
Кстати, какие браузеры поддерживают или неподдерживают новые стандарты можно глянуть тут:
Обратите внимание, что сайт caniuse в хипстерской манере показывает по умолчанию только несколько последних версий браузеров и создает видимость что все хорошо поддерживается.
Удобно конечно ориентироваться на последние версии браузеров, но все же интернет задумывался как среда, доступная с самых разных видов устройств, стоит ли сокращать эту доступность?
> Object.setPrototypeOf() Только в ES6
> Кто-то должен это остановить... Это мое личное мнение, но кто-то должен был при разработке языка сделать нормальные классы в стиле Ява, а не копировать идею прототипов из никем не используемого языка. Сами авторы утверждают что прототипы наоборот, не навязывают использование классического ООП, а позволяют каждому использовать свой подход.
По задумке, в JS должно было не быть классов (только функции-конструкторы, в первой версии синтаксиса литерала { a: 1 } еще не было), а объекты должны были "наследоваться" друг от друга с помощью прототипов. Я сам плохо понимаю, какие в этом преимущества и пока не видел внятного объяснения.
Что еще интересно, в первой версии языка не было Object.create(), и видимо наследование предполагалось делать по схеме:
> While this is often considered to be one of JavaScript's weaknesses, the prototypal inheritance model is in fact more powerful than the classic model. It is, for example, fairly trivial to build a classic model on top of a prototypal model.
> Хотя это считается слабым местом языка, прототипное наследование в действительности гораздо мощнее, чем классическая модель. Например, несложно построить классическую модель поверх прототипной.
> А должно наверное так https://jsfiddle.net/w22g1txz/5/ Тут недостаток, что если растянуть окно, статья не растягивается и не занимает всю доступную ширину. Статья должна занимать всю ширину окна, за вычетом поля слева, которое отведено под меню. То есть ширина статьи = ширина окна - ширина меню.
> и попытаться установить composer в какую-нибудь папку, высвечивается: Ты имеешь в виду "попытаться установить что-нибудь с помощью композера"? Возможно, в openserver надо использовать его специальную консоль и работать в ней. В мануале ничего не написано?
Напиши, что именно (как запускаешь консоль и какую команду пишешь) ты делал. Если можно приложить скриншот или текст из консоли - вообще замечательно. А то очень трудно понять, о чем речь, особенно если я сам никогда не пользовался оперсервером.
> >100%-230px > что это значит? Это значит, что ширина статьи равна ширине окна минус 230px которые отведены на меню и отступы.
По коду:
> article p Статья может содержать не только абзацы, но и заголовки, цитаты, таблицы, ты это учел?
Определяй line-height вместе с font-size.
> font-family: Trebuchet MS; Имена с пробелами безопаснее писать в кавычках. Также, что если у пользователя нет этого шрифта? Надо указать в конце один из стандартных шрифтов вроде sans-serif.
Текст статьи и меню тоже должны быть требушетом. Его надо задать как шрифт страницы по умолчанию.
Зачем для p задан display: inline-block? Это ведь заставит абзацы выстраиваться горизонтально, а не вертикально. Ты знаешь как работает inline-block? Инлайн-блоки выстраиваются горизонтально и переносятся, как слова внутри абзаца.
> Каким образом вёрстка сломается, если удалить текст справа? Имеется в виду, что если удалить элемент article, меню не должно никуда съехать. И наоборот. И если добавить текста или пунктов меню, тоже ничего не должно сломаться.
То есть верстка не должна быть хрупкой и не содержать ненужных зависимостей между блоками.
Прочти мануал по json_encode. JSON не обязательно представлять в виде объектов, и я не очень понимаю, зачем ты выбрал такой вариант. И зачем разработчики PHP его сделали.
> Массивы преобразуются в object с именами полей, названными согласно ключам массива и соответствующими им значениям, за исключением числовых ключей, которые не будут доступны пока не проитерировать объект.
> if (arguments.length != 1) { В JS так делать не принято, насколько я знаю. Ошибки впрочем тут нет, просто так обычно не делают. Ведь тогда тебе придется в каждой функции это в начале писать.
> if (typeof(power) != "number") { Обычно, когда требуется проверка типов, используют надстройку над JS вроде TypeScript. Советую почитать про него, в нем это делается гораздо проще. Правда это уже другой язык, хоть и компилируемый в JS.
Опять же, ошибки тут нет. Я иногда делал специальную функцию и писал так:
Util.assert(typeof(power) == "number");
В программе я вижу недостаток в том, что объекты энергосети не имеют у тебя ничего общего. Мы вынуждены передавать их по отдельности в конструктор департамента и по отдельности обрабатывать. Если мы захотим добавить методы вроде "добавить элемент сети", нам придется его добавлять 4 раза.
А если мы захотим добавить новый вид элементов сети, например, ПромышленноеПредприятие? Переписывать весь код?
Но ведь у элементов энергосети есть много общего:
- их всех можно подключить к энергосети - они могут выкачивать/закачивать из нее энергию
Это явно случай, где стоит применять наследование. Сделать базовый класс ЭлементСети и наследовать от него Дома, Электростанции и тд.
Имей в виду что наследование A от B подразумевает что "A является (разновидностью) B". Не используй наследование там, где это утверждение неверно. В этом случае надо использовать подход "A содержит B внутри".
Также, неудобно что при создании Департамента надо сразу передать все элементы сети. Сделай, чтобы был метод "добавить новый элемент сети".
> Array.PowerStation Неверно указан тип. В твоем случае это понимается как то, что PowerStation является свойством объекта Array. надо писать
> powerStationsMegawatts += pwrStat.getPower() / 2; Не очень понятно, зачем деление на 2? Попытка учесть дневную/ночную генерацию? Это лучше сделать по аналогии с другими элементами сети.
> @param {сonst} timesOfDay - Константы класса DepartmentOfEnergy Мне стало интересно, а можно ли описать как-то что тут константы, с помощью jsdoc? Я нашел такое:
Но это по моему все не то. В TypeScript вроде есть enum для этого.
> if (tempPwrLines.getPower() >= demandPower - power) { Тут можно использовать min/max
> tempPwrLines[ i ] Это часто повторяется, стоит сделать переменную.
> function Report(timesOfDay, consumption, production, balance, balanceConverge, purchasePower, purchaseCost, salesPower, salesCost) { Многовато аргументов, легко перепутать порядок или пропустить один из них.
Лучше использовать литерал объекта, хотя тогда не очень нужен сам класс Report, так как в нем больше ничего и нет.
> this.consumption = consumption / 1000; Вот такие преобразования повышают риск ошибиться.
Сап двачь, в чём профит от Eloquent и ему подобных надстройках? Насколько я понял оно по производительности сильно душит сервак. А ещё заставляет программиста подстраиваться под "его" синтаксис, не особо при этом давая профиты над тем же PDO. Или есть что-то, что даёт профиты?
>>880397 Сложность тут не причем. Код sql довольно громоздкий, не очень красивый, и большинство запросов все равно довольно простые и вместо того, чтобы писать их из раза в раз, ОРМ предлагает тебе удобные методы.
> $request = implode("<br>", preg_split("/\r\n/", $request)); Ты мог бы не делать этого если используешь content-type text/plain. Но если ты используешь HTML то используй и htmlspecialchars.
Алсо есть функция nl2br
> if($read == "") break; Лучше писать в 3 строки.
> socket_close($msgsock); Она тоже может дать ошибку. закрытие сокета подразумевает обмен TCP пакетами FIN/ACK по сети.
Можешь попробовать погуглить про устройство протокола TCP, пригодится, хотя не знаю, понятно ли там объяснено:
>>880408 >в том же eloquent есть методы в которые можно передать чистый SQL код. Забавно когда подключаешь ОРМ чтобы SQL код не писать, а потом пишешь SQL код... >Смотря что в твоем понимании сложный. Множественная выборка из 5 таблиц например.
Там есть то, что нужно? Если нет, я могу нужный пост у себя поискать.
>>880392 Ты плохо понял. Это ORM и его основное назначение - Object to Relational database Mapping, то есть загрузка и сохранение объектов в базу данных.
Если тебе это не надо, или ты не используешь ООП, то не используй.
1) установи Wireshark (программа перехвата пакетов на сетевой карте), закрой все лишние программы, кроме браузера. запусти wireshark, открой в браузере любую страницу, посмотри какие пакеты будут пойманы. Учти что там обычно еще идет куча мусора от соседних узлов сети и от других запущенных программ
Если ты под линуксом, то еще можно использовать tcpdump
2) с помощью команды nslookup запроси IP сервера yandex.ru у DNS-сервера 8.8.8.8
3) с помощью tracert/traceroute и whois узнай, через какие узлы и города идут пакеты, отправляемые на адреса google.com, twitter.com, vk.com, yandex.ru (или другие сайты)
4) С помощью telnet или putty соединись с сервером yandex.ru и отправь HTTP-запрос GET / HTTP/1.0
5) Напиши на php простой echo-сервер, который слушает порт, принимает соединение и отсылает каждую принятую строчку обратно.
6) Напиши простой HTTP-клиент на php, скачивающий файл по указанной ссылке
7) Напиши простой HTTP-сервер на php, отдающий какую-то простую страницу, и протестируй его с помощью браузера. В случае затруднений можно использовать wireshark (только ловить пакеты на 127.0.0.1 скорее всего не получится, используй IP на сетевой карте, узнать его можно через ifconfig)
8) Простые программы выше были однопоточными. Напиши многопоточный сервер. Его суть такая: он принимает соединения от клиентов, и все, что напишет клиент, пересылает всем остальным (что-то вроде чата). Тебе понадобится socket_select или strea_select для этого. Тупо сделать синхронный алгоритм вроде "отправить сообщение клиенту 1, затем клиенту 2" не получится, так как при зависании одного из клентов (если он перестанет принимать пакеты) зависнет и сервер до истечения таймаута.
9) перепиши свой сервер на reactphp
10) Напиши простой многопоточный HTTP сервер на reactPHP
SQL это язык, специально придуманный для написания запросов к таблицам. Очевидно что он гораздо эффективнее для выборки данных чем громоздкие конструкции.
Однако, есть случаи, когда нужна именно надстройка:
- в тривиальных случаях написать $em->find('User, 10) быстрее, чем SQL запрос - сохранить изменения в объекте удобнее через save() чем искать что именно изменено и писать запрос - в случае, если запрос формируется кусками в зависимости от условий, то строить его через Builder выгоднее. - в ORM Doctrine мы работаем не с таблицами, а с сущностями, и для выборки из коллекции сущностей нам нужен свой язык DQL, похожий на SQL
То есть в разных ситуациях нужны разные подходы. Глупо заменять большой SQL запрос на еще более громоздкую конструкцию из вызовов методов.
Насчет Eloquent, я его не изучал и не могу сказать насколько он адекватный. Laravel славится нестандартными подходами. Если ты хочешь пример "правильного" ORM, изучи Доктрину.
Кстати, ORM - хорошая тема для собеседования и проверки, понимает ли кандидат что он изучил или просто заучил примеры использования, правда? Также, можно поспрашивать всякие сложные ситуации вроде реализации наследования таблиц или EAV.
Жаль только что в этом случае вакансия так и останется незанятой, а бизнесу все же нужно ее заполнить.
Асло, насчет тормозов, не знаю, как тормозит Eloquent, но думаю, что до Доктрины ему далеко. На быстром сервере выборка 1 объекта занимает где-то 1-2 мс и это довольно много. Но если не выбирать много объектов, то терпимо.
Может кто-то хочет поковыряться в доктрине и придумать способ более быстрой генерации объектов? Например через кодогенерацию кода маппинга вроде:
Задача очень сложная, требует ковыряться в внутренностях доктрины и есть ненулевая вероятность, что ничего не получится.
Вообще, надо бы нам сформулировать "сложные" задачи для тех, кто хочет прокачать свои навыки. Вот что у меня есть в запасе:
- ускорение выборки из доктрины - оптимизация композера, который часто минутами разрешает зависимости и ест полгигабайта памяти - доработка доктрины, чтобы большую таблицу можно было мапить на несколько связанных один-к-одному сущностей
Надо наверно это оформить в задачи, вдруг кто заинтересуется. Не всем же наверно интересно студентов из массива в массив перекладывать.
>>880443 Меня всегда интересовало, как доктрин узнает, что доставленный объект изменил свои свойства где-то в скрипте, чтобы потом проапдейтить его в бд.
>>880432 Да там всё изучение состоит в >Зайти на сайт ORM >Прочитать 1 страницу инструкции Если и не знаешь, выучишь за минут 10. >>880443 >Асло, насчет тормозов, не знаю, как тормозит Eloquent, но думаю, что до Доктрины ему далеко. Интересно насчёт торможения vs Самописной ORM. >придумать способ более быстрой генерации объектов? Весьма интересная задача должен заметить!
Тогда постараюсь как-нибудь на неделе сформулировать нормально задачу, пока, если хочешь, установи доктрину, поработй с таблицами, сравни скорость выборки например 100 сущностей через доктрину и напрямую, попробуй попрофайлить это все.
> https://github.com/TheSidSpears/Students > Скопировать проект в web-директорию Мне не очень нравится эта идея. Небезопасно выкладывать код в публичную папку, и в твоей инструкции лучше бы сделать по умолчанию безопасный способ с папкой public в качестве корня сервера. Да и не очень понятно, в чем сложность сделать папку public корнем. Встроенный в PHP сервер можно запустить в этой папке за поминуты (правда, ему понадобится вспомогательный скрипт для роутинга...).
> `hash` varchar(200) NOT NULL, хеш, используемый для авторизации Комментарии надо добавлять через ключевое слово COMMENT, чтобы они сохранились в БД и отображались в программах просмотра таблиц: id INT NOT NULL COMMENT '....'
> https://github.com/TheSidSpears/Students/blob/master/app/container.php > Контейнер, использующий технологию Dependency Injection Не совсем точный комментарий. DI это передача зависимостей классу извне (например, в конструктор). DI контейнер сам по себе ничего не получает через конструктор и к нему эта фраза неприменима. Он скорее используется как вспомогательный компонент, чтобы не было нескольких копий одного сервиса и чтобы не надо было много раз копипастить код создания сервиса.
https://github.com/TheSidSpears/Students/blob/master/app/Validators/StudentValidator.php Я не помню, говорил я тебе или нет, что тут можно перейти от массива с описанием формы к ООП. Ну например, тут можно сделать элементарные валидаторы отдельными классами. Это позволит легко добавлять новые валидаторы, а также позволит использовать их и в других проектах.
В принципе, в твоем случае массив еще допустим, но по мере развития кода там скорее всего станет слишком много всяких условий и код получится запутанным.
> if($mask['type']=='string'){ > elseif($mask['type']=='int'){ > elseif($mask['type']=='enum'){ В таких случаях надо всегда ставить else с выбросом исключения, иначе опечатка останется незамеченной.
> if (($this->checkEmail( $s->email,$s->getId() ))) { Название неудачное, так как непонятно, что она должна вернуть. Надо использовать название вроде isEmailUsed/isEmailAvailable.
> $s->$field Это там так много раз повторяется, что стоит однозначно вынести его в переменную
> $punctuation = ['!',',','.','?',':',';']; > foreach ($punctuation as $symbol){ Ты недооцениваешь мощь регулярных выражений. С их помощью можно искать все знаки препинания одновременно, используя конструкцию вроде
(a|b|c) или [abc]
И $0 ... $9 в выражении для замены (смотри офиц. мануал).
> ([!,.:;?]<!{$symbol}) Вот тут явно ошибка. Символы
<!
обозначают тут сами себя.
> preg_replace($pattern,$replacement,$processed_sentences); Preg_replace не трогает исходную строку, а возвращает новую. Надо ее сохранять.
>>880355 >Удобно конечно ориентироваться на последние версии браузеров, но все же интернет задумывался как среда, доступная с самых разных видов устройств, стоит ли сокращать эту доступность?
Можно же сравнить разные подходы разработки: 1. С самого начала пытаемся поддерживать максимум устройств и версий браузеров. Используем ES3 и кроссбраузерные решения. Плюсы: - Начиная с первых этапов разработки программа поддерживает много устройств - Код весит меньше, чем в случае подключения библиотек для поддержки старых браузеров, т.к. мы используем хаки только там, где это необходимо Минусы: - Придется писать больше строчек кода - Код несколько сложнее читать / модифицировать, т.к. часть которая отвечает за логику самого приложения смешана с частью, которая осуществляет кроссбраузерность и поддержку старых устройств - Разработчик не может знать все, соответственно в конце придется тестировать код на разных браузерах, и либо искать решение самостоятельно, либо брать готовое куски для определенных багов из библиотек - Сложнее оценить время на разработку - Для заказчика такой подход достаточно затратен, требует поиска профессионала с опытом, и платить ему придется больше 2. Ориентироваться на последние версии браузеров и устройств. ES6 Плюсы: - Писать такой код приятнее - Код понятнее, так как сама логика программы отделена в пространстве-времени от той части, в которой мы затыкаем дыры и осуществляем кроссбраузерность и поддержку старых браузеров - Меньше строк кода - Фактически мы используем готовые библиотеки для поддержки старых устройств, соответственно тратим меньше времени - Весь проект легче оценить с точки зрения трудозатрат. Время на разработку программы будет зависеть, только от скорости кодера писать простой код. Он не будет тратить время на дебаг и поиск решений для поддержки старых браузеров для каждой конкретной проблемы, появляющейся по мере написания программы. За это отвечают сторонние библиотеки, качество которых мы можем оценить заранее. Минусы: - На первом этапе разработки программа будет корректно работать только в браузере разработчиков - Финальная версия программы тяжелее, т.к. тянет за собой несколько сторонних библиотек 3. Ориентируемся на распространенные браузеры среди нашей аудитории, и соответственно используем стандарт, который наиболее широко поддерживается в этой среде. Далее используем либо первую, либо вторую стратегию.
Можно сделать вывод, что наиболее оптимальный способ для сферической разработке в вакууме, это выбрать наиболее распространённый стандарт. А поддержку старых устройств осуществлять за счет подключения сторонних библиотек. Это сэкономит время и нервы.
Кстати EA нынче делают игры для топовых конфигураций, а потом оптимизируют под старое железо, в т.ч. консоли.
>Желтый старичок (:older_man:) отмечаeт комментарии. Встретив его, компилятор сразу же переходит к следующей строчке. >Многострочные коммeнтарии удобнее делать при помощи старушек (:older_woman:). Все, что попaдает между двух старушек, будет проигнорировано.
> Код несколько сложнее читать / модифицировать, т.к. часть которая отвечает за логику самого приложения смешана с частью, которая осуществляет кроссбраузерность и поддержку старых устройств
Не обязательно. Я обычно такие вещи выношу в отдельные функции в отдельном модуле, и ничего не смешивается. Ну условно говоря, если мне нужен аналог indexOf для массива, то я делаю отдельную функцию для этого.
> Разработчик не может знать все, соответственно в конце придется тестировать код на разных браузерах, и либо искать решение самостоятельно, либо брать готовое куски для определенных багов из библиотек Это верно, но это повышает уровень разработчика и со временем кроссбраузерность перестает быть сложным моментом. Хорошим источником информации может быть код библиотек вроде jQuery.
> требует поиска профессионала с опытом, Ну зато наличие профессионала повышает вероятность, что приложение будет качественным, а не сделанным на "отвяжись".
Ты в общем прав в выводе, что делать кроссбраузерно может быть чуть дороже, а не кроссбраузерно - дешевле. Но тут есть подвох, что начинающие разработчики, которые не умеют писать кроссбраузерный код, скорее всего не умеют и многое другое.
Сейчас в комментах на хабре прочел например, что на собеседовании в booking.com спрашивали про особенности IE6.
Ну и надо понимать, что если например есть андроид-смартфон 2-3 летней давности, его браузер вполне может не справиться с рассчитанным на ES6 кодом.
Потому мне кажется, что разработчику стоит учиться делать все правильно и кроссбраузерно, а на работе - делать так, как скажут.
> Кстати EA нынче делают игры для топовых конфигураций, а потом оптимизируют под старое железо, Скорее всего они заранее в архитектуру закладывают такие возможности.
> Но как его передать в следующий скрипт, в котором ко всему создается свой экземпляр $data. Если ошибок нет, то ты сохраняешь данные в базу и следующий скрипт может взять их оттуда. Если ошибки есть, то ты выводишь форму повторно и таким образом проблем с передачей данных нет.
> Но потом на самой странице выводится темплейт и в начале него создается еще один экземпляр Data(), я пробовал сохранить как public свойство в $data, но т.к. создается новый экземпляр, это не работает. Значит надо не создавать новый экземпляр, а использовать старый.
Название - Data - неудачное так как почти любой класс хранит какие-то данные. Класс логично назвать SomethingForm если он хранит данные формы. И непонятно, зачем тогда массив $values, если у нас есть $data.
> Если (ошибок нет) { > $errors = $data->someDataMethod($values); И это тоже странно. Ты же выше проверил данные, зачем их еще раз проверять?
> если все ок то $errors = ['check' => 1, 'balance' => 1, 'transaction' => 1]; И это странно, $errors это массив или объект для хранения ошибок. Зачем туда сохранять единицы? Если ошибок нет, то $errors пуст.
Ты как-то странно изменил алгоритм, добавив в него нелогичные вещи.
Что-то у тебя пример конфига нгинкса какой-то запутанный. Ну вот например:
> rewrite ^(.*)$ /index.php; Там для статических файлов наверно запрос к PHP отправлять не надо. Обычно статические файлы определяют по расширениям, и отдают их нгинксом, а все остальное перенаправляют на php-fpm.
А твой конфиг выглядит каким-то переусложненным. Один и тот же root несколько раз прописан. зачем-то сделан location для php-файлов который все равно перенаправляется на index.php. Советую почитать мануал по нгинксу, благо он есть на русском.
Класс роутера можно было положить в app, а не выделять для него отдельную папку.
https://github.com/anotherCodeMunkey/studentsList/blob/master/router/Router.php#L11 > $routesPath = '../config/routes.php'; > $this->routes = include($routesPath); Плохо использовать относительные пути к файлам. Там запутанная система, относительно какого именно каталога ищется файл. Соответственно, есть вероятность что в каких-то случаях он просто не найдется. Надо использовать абсолютные пути через __DIR__
В роутере плохо, что у тебя в нем захардкожено обращение к $_SERVER. Почему мы не можем вызвать роутер и передать ему произвольный URL?
> if(preg_match("/bootstrap/",$uri)) > require_once $uri; Вот это неправильно. require_once выполняет PHP код, а при отдаче статики никакого PHP кода там не должно быть. Тут бы больше подошел readfile. Ну и отдавать статические файлы надо сразу веб-сервером, не дергая PHP для этого.
> if(preg_match("/bootstrap/",$uri)) Ты не проверяешь, что bootstrap идет именно в начале, а не в середине URL.
> if(preg_match("~$uriPattern~", $uri)) А почему ограничитель ~ не хранить тоже в конфиге? Будет меньше путаницы.
> $controllerName = 'app\controller'."\\".ucfirst(array_shift($pieces)).'Controller'; Лучше указывать полное имя класса. При поиске по имени класса (чтобы узнать, где он используется), например твой конфиг не найдется. То же касается и метода.
Методы контроллеров обычно называют как somethingAction.
Твой роутер - это не роутер, а Front Controller. Обычно роутер только определяет, кто должен обработать URL, но сам контроллер не вызывает.
Метод run() написан некорректно. Что, если URL не соответствует ни одному маршруту в конфиге? У тебя это просто не обрабатывается. Что, если URL соответствует 2 маршрутам? У тебя вызовутся оба контроллера по очереди.
> if(!empty($_SERVER['REQUEST_URI'])) И что должно происходить, если REQUEST_URI пуст?
Приведу пример проблемы: как ты проверишь, что пришедшее значение содержит не более N символов, если htmlspecialchars может удлинять обработанное им выражение?
> $student->insertName($this->info['name']); > $student->insertLastName($this->info['lastName']); > $student->insertGender($this->info['gender']); Тут стоило бы использовать цикл или сделать в классе метод для простановки значений разрешенных полей из массива.
Также, логичнее сделать валидатор для модели студента, а не для массива с неопределенным набором полей.
> private function getValidation() Как читать это название? "получить валидацию"? Что значит получить? Нужно выбрать более логичное название для метода.
Также, не вижу особого смысла хранить данные из формы в поле info. зачем хранить их в поле, если можно просто передать в функцию, как аргумент? Вот у тебя код:
> $this->getInputData(); > $this->getValidation(); Непонятно, как тут передаются данные. Если же написать
> if($_POST == NULL) В какой ситуации это условие выполняется? $_POST это всегда массив.
> $user = $pdo->hashSearch($_COOKIE['student']); > if(is_array($user)) > { > $student = array_shift($user); > } > return $student; Что произойдет с этим кодом, если условие is_array не выполнится? Подсказываю: тут будет ошибка. Это некорретный код. Понять, что он некорректный, очень легко: видно что переменная $student иногда создается, а иногда - нет и при этом используется ниже.
Вообще, эти контроллеры никуда не годятся и их надо переписывать.
> static function destroyCookie() > header("Location: http://$serverHost/"); Это нелогично. Почему функция, которая называется "уничтожить куку", делает редирект? Что, без редиректа унитожить куку невозможно? Вот представь, кто-то использует твою функцию, не зная, что она делает редирект, а потом будет долго искать причину ошибки. Название функции должно соответствовать ее логике работы.
Код валидатора явно неправильный. Ну например, ты не проверяешь email, если он не указан. Но ведь отстутствие email - это тоже ошибка, не позволяющая зарегистрироваться.
Как я написал выше, удобнее валидировать не массив неизвестной структуры, а модель студента. Тогда валидатор сможет проверять любых студентов, а не только пришедшие из формы данные.
> $validation['name'] = 1; > $error['name'] = true; А в чем именно ошибка, ты не сообщаешь? И не очень понятно, зачем 2 массива, если достаточно просто массива $errors.
> if (isset($error) != NULL) isset возвращает true или false, зачем ты сравниваешь его с NULL? Также, зачем тут вообще isset, ты хочешь проверить, что переменная существует? Не надо писать такой код, где переменная может существовать, а может и нет, так как его труднее читать и поддерживать.
Способ возврата выбран неправильно. Функция должна возвращать значение определенного типа, а не иногда массив, иногда true. Это усложняет работу с результатом этой функции.
Ты создаешь объект TDG иногда по несколько раз. А ты знаешь, что при каждом создании объекта PDO создается новое соединение к БД? Это неэффективно, надо переиспользвоать одно соедиенние. Также, класс работы с БД не должен сам устанавливать с ней соединение, а получать объект PDO через Dependency Injection, у меня есть урок по нему.
> $sql = $pdo->prepare("SELECT * FROM list WHERE eMail = :eMail"); Неудачное название переменной, там возвращается объект PDOStatement, а не SQL код.
> <br> Вы вошли как: <br> Использование br тут показатель того, что ты плоховато знаешь CSS. Логичнее было завернуть строки в дивы. Отступы надо делать через CSS. В ОП посте, если что, есть задачи по этй теме.
Куки в браузере хранятся отдельно для каждого домена. Если открыть один сайт в нескольких вкладках то логично что все эти вкладки будут использовать одни и те же куки. Так как идентификатор сессии хранится в куке, то и сессия общая для всех вкладок. Если ты в одной вкладке записал что-то в куки или сессию, то при загрузке страницы в другой вкладке она увидит эти изменения.
Ну например, если ты используешь куки для логина, то пользователь будет залогинен во всех вкладках (это плюс). А если ты используешь сессию для вывода уведомлений, то вполне возможно, что оно выведется не в той вкладке.
Значит ты все-таки что-то вывел. Проверь, что в конце файла ты не ставишь ?> за которым может прятаться лишний пробел. И что в файле перед <?php ничего нет, включая BOM (то есть файл сохранен в кодировке utf-8 без BOM).
header Location автоматически ставит код из серии 3xx (так как именно этот код говорит браузеру сделать повторный запрос). Ты должен отдать код 404 и страницу ошибки и завершать скрипт, а не редиректить. Плюс, при редиректе теряется УРЛ в адресной строке и бесполезно обновлять страницу. Где такому учат? В устаревших учебниках?
Если ты не можешь сделать на JS, можешь сделать без JS. Сделай радиокнопки перед каждым комментом и замаскируй их под кнопку "ответить на комментарий", а также подсвечивай выбранный комментарий.
Обычно значение константы не так важно. Константу в принципе не предполагается выводить. Или например, если для 2 констант мы должны выводить один и тот же текст - как их различать?
Ну и с константой могут быть связаны еще другие дополнительные значения.
Использовал разные подходы/инструменты, у меня результаты такие: - самый медленный загрузчик - тот, что использует file_(get|put)_contents; - использование cURL вместо file_get_contents немного уменьшает время загрузки, синхронный газл ещё чуть-чуть быстрее; - асинхронный газл во много раз быстрее загрузчиков, упомянутых выше; - для файлов малого размера (до мегабайта) форки немного медленне асинхронного газла (создаю форк процесса на каждую ссылку), но с оговоркой - если мне нужно скачать, к примеру, 500 файлов, то создаётся 500 форков, посылающих запросы на скачивание файла. Доброчан отдаёт код 503, сосач же просто перестаёт отвечать; - форки быстрее асинхронного газла если размер файлов больше 5-10мб и их немного;
Там сейчас много копипаста в загрузчиках + их неудобно запускать с разными файлами (нужно менять лезть в исходник загрузчика, а не указывать ссылки для скачивания к примеру из консоли). Приоритетным было научиться писать что-то более сложное, чем file_(get|put)_contents. Хотя, я ведь просто воспользовался готовыми инструментами, понимания это не прибавило.
http://ideone.com/uNsBBv - первое задание с выделением текста. У меня сложилось ощущение, что тут нужно больший кусок текста выводить с ошибкой, но я без понятия как это сделать. В голову приходит работа с флагом PREG_OFFSET_CAPTURE, но как на деле это все применить - хз...
Это не очень удачная рекомендация, на мой взгляд. И мне эти функции filter_input не очень нравятся, так как они дают людям ложное чувство защищенности. Для защиты от разных уязвимостей фильтровать данные на входе недостаточно.
С другой стороны, многие классы (кроме специально для этого предназначеннных) не должны обращаться к глобальным переменным, ни через $_SERVER, ни через filter_input, а получать информацию от того, кто их использует.
Очень странно, что ты получаешь некоторые шаблоны по HTTP. Где тут логика? Это медленнее и ненадежнее, чем брать их с диска. Если не используется HTTPS, то это еще и создает вектор атаки для "человека посередине", способного перехватывать трафик, он может вместо шаблона что-то еще подсунуть. Или может это закладка от предыдущих разработчиков?
Писать свой шаблонизатор, на мой взгляд, глупая затея. Тем более такой убогий.
> Концепция в том, что чем меньше HTML внутри php, тем лучше. Концепция не в этом, а в том, что надо отделять логику обработки данных от логики вывода данных. PHP внутри HTML использовать можно, как и писать логику вывода данных в шаблонах.
- цифра - за ней любое число открывающих скобок - за ними любое число закрывающих - за ними любое число минусов - за ними любое число пробелов
А надо именно "любые из указанных символов в любом порядке". Ну дам подсказку. Написать "один любой из указанных символов" можно аж 2 способами:
- (a|b|c) - [abc]
Перечитай внимательно урок про ветртикальную черту и квадратные скобки.
Ну а написав "один любой из символов", несложно там добавить кое-что, чтобы получилось "любое число этих символов". Ну а далее останется только добавить "повторить 10 раз" и задача решена.
Этот класс пригодится и в других местах. Ну например, объект News можно передать в функцию валидации (проверки правильности заполнения). Или в шаблон для вывода на экран.
> Алсо есть такой баг или фича непонятная в IDE - когда я делаю класс синглтононом я не могу смотреть их через автодополнение. Такая хуита в нетбинсе и эклипсе. Не знаю, не могу сказать без примера кода. Но могу сказать что синглтон довольно плохой паттерн и вместо него надо в большинстве случаев применять Dependency Injection.
> использую синглтон для класса соединения с БД Зря. Синглтон не нужен для этого, объект PDO можно просто создать через new и не усложнять код. Это типичный пример как писать не надо. Кто-то неграмотный написал про это в учебнике, теперь все это копипастят как самый простой паттерн для изучения.
Советую прочитать мой урок по Dependency Injection.
Старые ответыАноним29/11/16 Втр 21:17:51#805№884470
Ну да, поначалу бывает трудно понять, как именно взаимодействуют классы. Можно попробовать написать код и глянуть на него критически. Обычно хорошо написанный код выглядит логично, ничего лишнего, а неправильно написанный - выглядит громоздко, или неудобен в использовании.
У меня в учебнике есть задача "Вектор" и "Кошки-мышки", которые пытаются помочь с этим разобраться.
Также, есть аббревиатура SOLID, можешь погуглить "solid ооп".
Ну и еще полезно смотреть примеры ООП кода, ну например, из компонент Симфони.
>>Вообще, у разных существ может быть разная восприимчивость к видам урона, логичнее сделать у существа метод "принять урон", а не закладывать что он всегда складывается. > За эту разную восприимчивость к разному урону будет отвечать обязательный для каждого существа объект армор. Это тоже возможно, хотя в моем представлении у воина может не быть брони, ну например, не купил или сломалась. И тогда логично сделать, чтобы удар сначала гасился броней, и остаток, возможно, уже применялся к персонажу. Можно конечно и твой вариант использовать, если броня будет всегда.
> Типа берется шаблон разметки (причем не всей, а какой либо её части, типа только div с таблицой из бд), заполняется посредством скрипта php, который в свою очередь соединяется с MySQL (кстати, только MySQL или возможны соединения с любыми БД, типа там постгрес, мсскл, и прочие?) бд, а потом заполненный контентом кусок html подгружается пользователю через какой нибудь ajax?
Для начала лучше не использовать аякс, тебе надо сначала с основами разобраться на простых примерах. Один скрипт получает данные, неважно как, и вызвает шаблон, чтобы тот их отобразил.
> по нажатию input-элемента с type-submit происходит invoke действия, указанного в action. Складывается ощущение, что ты как раз не понимаешь, что происходит, и используешь английские слова, чтобы это замаскировать. Вот если посмотреть на твой ответ:
- что значит "действие, указанное в action"? Там не действие указывается, а URL - что значит "invoke"? Такого термина в протоколе HTTP я не видел.
Происходит вот что. Браузер собирает значения всех не-деактивированных полей ввода и отправляет HTTP-запрос методом GET или POST на указанный в атрибуте action URL. Полученный ответ он отображает на экране.
Тебе надо почитать про протокол HTTP и отправку форм.
Там написано: "action - URI-адрес программы, которая обрабатывает информацию переданную через форму.". Имеется в виду URL, который обслуживается программой на сервере (например это может быть адрес, по которому расположен PHP скрипт вроде http://example.com/handler.php).
Создать объект можно разными способами. Ну например, объект Отрезок можно создать, указав координаты 2 точек, можно через 1 точку и смещение по 2 осям, можно через точку, угол и длину. Соответсвенно, нужно несколько конструкторов.
По идее ты должен увидеть, какие стили применены к элементу, как они перекрывают друг друга. В твоем случае видно, что в файле upload-master.css написан код, который перекрывает значения из бутстрапа. Приоритет у них равный, просто видимо он подключен позже.
Не понимаю, зачем ты переопределил стандартный класс из бутстрапа. В твоем коде логично добавлять свои классы.
> if (!$content) { > throw new Exception(curl_error($handler)); Это неправильно. Что, если файл - пустой или состоит из единственного символа "0"? Твой код выдаст ошибку, хотя ее нет. Изучи внимательно мануал по curl_exec и curl_error.
Небольшая мелочь. Функция curl_init может вернуть false, у тебя это не проверяется.
Еще одна мелочь. При выбросе исключения curl_close() не вызывается. Я не знаю, возможно, он сам вызывается при уничтожении переменной, но если нет, то мы получаем утечку объектов curl, которые никогда не будут высвобождаться при исключении. Я проверил мануал:
И вроде как все в порядке (объект curl будет автоматически освобожден при уничтожении переменной при выходе из функции). Но помнить о таких вещах при использовании исключений стоит.
Для курла нет ограничения на скорость скачивания. Нет вывода статистики.
> chdir(__DIR__ . '/../'); Не советую так делать, не будут работать относительные имена файлов, заданные относительно текущей директории. Консольные команды обычно не должны менять текущую директорию.
> echo getElapsedTime(function ($total = null) Почему $total не обязательный, непонятно. Может он вообще не нужен тогда?
> for ($i = 0; $i < $total; ++$i) { Тут лучше foreach использовать.
В случае с скачиванием в несколько потоков нужно всегда делать ограничение на число потоков. Любой нормальный сервер тебя забанит при превышении. В протоколе HTTP есть рекомендация о 6 соединениях на домен. Таким образом, тебе надо реализовать нужное ограничение, отслеживать завершение дочерних процессов и запускать новые. На мой взгляд, использовать форк тут самый неудобный вариант, так как сложно передать обратно результат загрузки, сложно как-то взаимодействовать, но в принципе можно извернуться - уведомления о завершении дочернего процесса приходят в виде unix сигналов SIGCHILD, и в них же приходит информация о коде завершения (по pid процесса можно понять, какая именно ссылка не скачалась). Ну или можно использовать твой вариант с wait(), но не знаю, можно ли там получать коды ошибок для каждого процесса.
Для отслеживания ограничений на число соединений удобно использовать ООП.
> } catch (Exception $e) { > exit(1); Неправильный код. Сообщение об ошибке просто теряется и никуда не выводится и не фиксируется в логи.
В общем, код с форками надо переделать, чтобы была полноценная обратная связь, чтобы родительский процесс знал об ошибке в дочернем. И чтобы было ограничение на число соединений. И я думаю, стоит сделать еще общее ограничение на число процессов, так как в общем при большом числе процессов будут большие накладные расходы на переключения между ними.
> // Тут надо остановить все форки, временный грязный способ: > // shell_exec('killall php'); Это конечно неправильно. Как минимум стоит прибивать процессы по тому, что они - дети текущего. Ну или сделать группу процессов во главе с основнмы ( https://en.wikipedia.org/wiki/Process_group ) и прибивать по ее идентификатору.
Ну и опять же, нет управления потоками на основе числа соединений, нет ограничений общей скорости, нет статистики.
Вообще, ограничение на общую скорость - интересная штука. Позволяет ли guzzle ее реализовать? Я тут подумал, что может и не позволяет, и придется делать свой клиент на основе ReactPHP. Ну ограничение по числу соединений точно можно сделать.
Насчет измерений скорости разных методов - мне кажется, тут сложно сказать, что должно быть быстрее. С одной стороны, записывать данные по мере скачивания выгодно, так как диск не простаивает зря, с другой стороны, записать несколько файлов по очереди выгоднее, чем писать куски файлов вразнобой, так как последовательный доступ н магнитном диске быстрее случайного.
> Хотя, я ведь просто воспользовался готовыми инструментами, понимания это не прибавило. Ну так реализуй ограничения.
Самый простой способ вывести окружающий текст - это добавить в регулярку "от 0 до 10 любых символов" в начало и конец.
Второй вариант - разобраться по мануалу с PREG_OFFSET_CAPTURE. Учти, что он возвращает позицию в байтах, а не в символах (один символ в строке кодируется от 1 до 6 байтами). Чтобы перевести байты в символы, придется заморочиться с функциями вроде substr/mb_substr/strlen/mb_strlen.
> '/(здела)(л|ю|н)/ui' Сработает на слово "разделать на части", которое пишется через З. И не сработает на "зделать", "зделаем".
> for($i = 0; isset($errors[0][$i]); Немного странное условие. тут можно было просто сделать foreach по $errors[0].
вторая часть
Тут те же замечания по поводу "зделан". В остальном, решено верно.
Это не чат! Высказывайтесь одним большим постом, а не цепочкой мелких
Это тред для начинающих. Не написал за свою жизнь ни одной программы и имеешь тройку по математике? Ты наш человек.
Устанавливать пока что ничего не требуется, разве что редактор кода вроде Sublime Text 3, Notepad++, Netbeans PHP или PhpStorm (с ним будет удобнее).
Предыдущий тред был тут:
Мейлруч лежит? Есть запасной тред: http://dobrochan.org/s/res/23225.xhtml#i46467
Что самое главное для программиста? Умение аккуратно оформлять код (читай второй пост, прежде чем писать код).
Правила: ведем себя воспитанно, помогаем новичкам, постим ссылки на решения задачек, ОП их проверяет и дает советы и замечания. ОП заходит редко, где-то раз в 2-3 дня, у него мало времени, не жди его, решай задачки дальше. ОП отвечает на все вопросы по его задачкам и учебнику, а вот насчет каких-то других вещей - только если останется время. Но в треде немало анонимных экспертов разного уровня, так что вряд ли вопрос останется без ответа.
У нас есть уроки по основам PHP, они собраны и выложены по адресу http://archive-ipq-co.narod.ru/ Это учебник для изучающих с нуля, то есть если ты вообще ничего не знаешь, то надо начать с него. Он простой и понятный (по крайней мере в начале). Там есть задачи, их надо решать обязательно (чтобы стать программистом, надо писать код — иначе никак). Пости ссылки на решения в тред, мы их проверим, напишем замечания и дадим советы по улучшению.
Если не знаешь как решать, запости код, напиши в каком месте остановился и попроси подсказку.
Ты прошел весь учебник? Молодец, но это были лишь основы языка 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 2/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
- Сколько времени надо изучать все это? - все зависит от тебя, но не меньше 6-8 месяцев
- Посоветуйте редактор кода - Sublime Text 3, Notepad++, PhpStorm
- Нужен ли ООП, фреймворки, MVC, git, composer? — Да, однозначно. Посмотри любую вакансию.
- Что самое главное для программиста? Умение аккуратно оформлять код.
- ОП, сделай за меня мою работу или домашнее задание? — Это конечно, хорошая идея, но нет.
- Подскажи сайты для поиска работы, я не умею гуглить? — hh.ru, geekjob.ru, moikrug.ru (склеен с brainstorage.me), fl.ru, upwork.com (бывший одеск). Имей в виду, что кроме фриланса есть еще постоянная удаленная работа (remote job) когда тебе не надо тратить время на поиск заказов и переговоры с неадекватными заказчиками.