Это копия, сохраненная 22 марта 2017 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
Пожалуйста, пишите один большой пост вместо нескольких маленьких и не флудите не по теме. ОПу ведь все это читать придется.
Это тред для начинающих. Не написал за свою жизнь ни одной программы и имеешь тройку по математике? Ты наш человек.
Устанавливать пока что ничего не требуется, разве что редактор кода вроде Sublime Text 3, Notepad++, Visual Studio Code, Netbeans PHP или PhpStorm (с ним будет удобнее).
Предыдущий тред был тут: >>919074 (OP) ( http://arhivach.org/thread/233392/ )
Еще предыдущие треды в архиве:
- 84 >>898502 http://arhivach.org/thread/224683/
- 83: https://2ch.hk/pr/arch/2016-12-26/res/880700.html (М)
- 82: https://2ch.hk/pr/arch/2016-12-01/res/864640.html (М)
- другие: https://www.google.ru/search?q=site:2ch.hk/pr/+клуб+php
Мейлач лежит? Есть запасной тред: 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
- Можно подробнее про поиск работы, собеседования - нет, ОП писать не будет, но может кто из анонов захочет рассказать. Поищите тред перезвонивших, а также раздел /wrk/.
- Сколько времени надо изучать все это? - все зависит от тебя, но не меньше 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, там тоже есть функция форматирования кода.
Горячие клавиши для форматирования кода в разных IDE: https://gist.github.com/codedokode/8759492
Вообще, в PHP долгое время не было единого стандарта оформления кода, все писали как попало и было много бардака, но сейчас дело лучше — есть стандарты PSR-1 и 2. Вот как надо оформлять код:
- переменные и функции пишутся с маленькой буквы, подчеркивание не используется, используется camelCase, пример: $x, $numberOfPeople, printResults()
- Название функции начинается с глагола, в стиле «сделайЧтоТо»
- не знаешь английский? Не беда, в 21 веке есть решение этой проблемы. Не пиши транслитом, открой лучше Гугл Транслейт или slovari.yandex.ru и найди название для переменной там
- в именах классов используется CamelCase, первая буква большая, «_» может использоваться
- мы предпочитаем подстановку переменных вместо конкатенации строк: "I am $age years old" — хорошо, 'I am ' . $age . ' years old' — плохо из-за обилия точек и кавычек
- мы используем для отступов 4 пробела (можно настроить редактор, чтобы при нажатии Tab он вставлял 4 пробела)
Вот ссылка на стандарты, где все это описано подробнее и даны примеры оформления:
PSR-1: https://github.com/samdark/fig-standards-ru/blob/master/accepted/ru/PSR-1-basic-coding-standard.md
PSR-2: https://github.com/samdark/fig-standards-ru/blob/master/accepted/ru/PSR-2-coding-style-guide.md
Если тебе лень выравнивать код руками, закачай его на http://beta.phpformatter.com/ и нажми «format». Робот исправит выравнивание и отступы в мгновение ока (да, прогресс не стоит на месте). Если ты используешь мощную IDE вроде PhpStorm, там тоже есть функция форматирования кода.
Горячие клавиши для форматирования кода в разных IDE: https://gist.github.com/codedokode/8759492
Вообще, в PHP долгое время не было единого стандарта оформления кода, все писали как попало и было много бардака, но сейчас дело лучше — есть стандарты PSR-1 и 2. Вот как надо оформлять код:
- переменные и функции пишутся с маленькой буквы, подчеркивание не используется, используется camelCase, пример: $x, $numberOfPeople, printResults()
- Название функции начинается с глагола, в стиле «сделайЧтоТо»
- не знаешь английский? Не беда, в 21 веке есть решение этой проблемы. Не пиши транслитом, открой лучше Гугл Транслейт или slovari.yandex.ru и найди название для переменной там
- в именах классов используется CamelCase, первая буква большая, «_» может использоваться
- мы предпочитаем подстановку переменных вместо конкатенации строк: "I am $age years old" — хорошо, 'I am ' . $age . ' years old' — плохо из-за обилия точек и кавычек
- мы используем для отступов 4 пробела (можно настроить редактор, чтобы при нажатии Tab он вставлял 4 пробела)
Вот ссылка на стандарты, где все это описано подробнее и даны примеры оформления:
PSR-1: https://github.com/samdark/fig-standards-ru/blob/master/accepted/ru/PSR-1-basic-coding-standard.md
PSR-2: https://github.com/samdark/fig-standards-ru/blob/master/accepted/ru/PSR-2-coding-style-guide.md
------------------
Итак, ты зашел в тред и решил помочь какому-то анону, дав ему совет или подсказку. Спасибо! Но прочти сначала эти напоминания, чтобы твоя помощь действительно была полезной.
Давай удочку, а не рыбу
Лучше не давать готовое решение проблемы, а рассказать как его искать. Может дать ключевые слова для гугла или ссылку. Но помогай, а не пытайся показать превосходство. Если даешь ссылки на нерусскоязычные статьи, упомяни об этом.
Будь доброжелателен
Не годится: «Ты мануал хоть раз в жизни открывал, обезьяна?»
Не годится: «В гугле забанили?»
Не годится: «Твой код плохой»
Хорошо: «Вот, как можно улучшить этот код: ...»
Хорошо: «Ты неправильно используешь функцию abc(). Вот ее описание: ссылка, и как видишь ей надо передать строку, а не массив»
Не придирайся к знанию английского или русского языка.
Объясняй
Не очень хорошо: «сделай как в этом коде»
Хорошо: «если ты вставляешь текст от пользователя в SQL запрос, то получается SQl-инъекция, которая позволяет взломать твой сервер (ссылки). Чтобы этого избежать, надо вставлять данные с помощью плейсхолдеров (ссылки)»
Хорошо: «Помни, что код пишется для людей. Если писать такие большие функции, то в них становится трудно разобраться...»
Не проповедуй
Мы учим использованию самых распространненных подходов, стандартов, библиотеки фреймворков. Если ты не любишь ООП, пробелы в коде, jQuery, сам PHP, то рассказать об этом стоит в каком-нибудь другом треде.
Не придирайся к знанию английского языка, анон пишет как умеет.
Ах да. Если тебе кажется, что что-то в учебнике или задачах можно сделать лучше — пиши, обратная связь всегда очень полезна.
Если тебе лень выравнивать код руками, закачай его на http://beta.phpformatter.com/ и нажми «format». Робот исправит выравнивание и отступы в мгновение ока (да, прогресс не стоит на месте). Если ты используешь мощную IDE вроде PhpStorm, там тоже есть функция форматирования кода.
Горячие клавиши для форматирования кода в разных IDE: https://gist.github.com/codedokode/8759492
Вообще, в PHP долгое время не было единого стандарта оформления кода, все писали как попало и было много бардака, но сейчас дело лучше — есть стандарты PSR-1 и 2. Вот как надо оформлять код:
- переменные и функции пишутся с маленькой буквы, подчеркивание не используется, используется camelCase, пример: $x, $numberOfPeople, printResults()
- Название функции начинается с глагола, в стиле «сделайЧтоТо»
- не знаешь английский? Не беда, в 21 веке есть решение этой проблемы. Не пиши транслитом, открой лучше Гугл Транслейт или slovari.yandex.ru и найди название для переменной там
- в именах классов используется CamelCase, первая буква большая, «_» может использоваться
- мы предпочитаем подстановку переменных вместо конкатенации строк: "I am $age years old" — хорошо, 'I am ' . $age . ' years old' — плохо из-за обилия точек и кавычек
- мы используем для отступов 4 пробела (можно настроить редактор, чтобы при нажатии Tab он вставлял 4 пробела)
Вот ссылка на стандарты, где все это описано подробнее и даны примеры оформления:
PSR-1: https://github.com/samdark/fig-standards-ru/blob/master/accepted/ru/PSR-1-basic-coding-standard.md
PSR-2: https://github.com/samdark/fig-standards-ru/blob/master/accepted/ru/PSR-2-coding-style-guide.md
------------------
Итак, ты зашел в тред и решил помочь какому-то анону, дав ему совет или подсказку. Спасибо! Но прочти сначала эти напоминания, чтобы твоя помощь действительно была полезной.
Давай удочку, а не рыбу
Лучше не давать готовое решение проблемы, а рассказать как его искать. Может дать ключевые слова для гугла или ссылку. Но помогай, а не пытайся показать превосходство. Если даешь ссылки на нерусскоязычные статьи, упомяни об этом.
Будь доброжелателен
Не годится: «Ты мануал хоть раз в жизни открывал, обезьяна?»
Не годится: «В гугле забанили?»
Не годится: «Твой код плохой»
Хорошо: «Вот, как можно улучшить этот код: ...»
Хорошо: «Ты неправильно используешь функцию abc(). Вот ее описание: ссылка, и как видишь ей надо передать строку, а не массив»
Не придирайся к знанию английского или русского языка.
Объясняй
Не очень хорошо: «сделай как в этом коде»
Хорошо: «если ты вставляешь текст от пользователя в SQL запрос, то получается SQl-инъекция, которая позволяет взломать твой сервер (ссылки). Чтобы этого избежать, надо вставлять данные с помощью плейсхолдеров (ссылки)»
Хорошо: «Помни, что код пишется для людей. Если писать такие большие функции, то в них становится трудно разобраться...»
Не проповедуй
Мы учим использованию самых распространненных подходов, стандартов, библиотеки фреймворков. Если ты не любишь ООП, пробелы в коде, jQuery, сам PHP, то рассказать об этом стоит в каком-нибудь другом треде.
Не придирайся к знанию английского языка, анон пишет как умеет.
Ах да. Если тебе кажется, что что-то в учебнике или задачах можно сделать лучше — пиши, обратная связь всегда очень полезна.
У тебя видимо загвоздка в том, что ты не очень понимаешь что сортируешь. Наверное ты хочешь отсортировать массив по значению, хотя пытаешься через ключи.
http://php.net/manual/ru/array.sorting.php
Попробуй что-то из этого. ИМХО, у тебя очень хромает теория.
для начала вот это начни использовать:
foonction coolestDumpYouEvaSeen($array) {
echo "<pre>";
print_r($array);
exit;
}
А потом еще сформулируй вопрос нормально. Что из твоего данного массива после сортировки должно получиться.
Мне после Питона все языки говном кажутся.
До этого писал на пхп. Не представляю как бы снова пришлось писать на нём. Хотя ты мыслишь и делаешь правильно, на пыхе вакансий больше.
C хаскелем бы смешнее зашло
Спихдили из перла, проебав по пути всю идею.
> Наверное ты хочешь отсортировать массив по значению
>>945131
> А потом еще сформулируй вопрос нормально. Что из твоего данного массива после сортировки должно получиться.
Ничего не получается. Есть уникальный id, есть значение, которое присваивается этому id. Нужно вывести все id, отсортировав по значению, которому им присвоено. Что-то вроде ORDER BY id
Все, получилось. Слава аллаху
>1000 строчек с присваиванием вместо цикла
>$peremennye_translitom
По-моему тебе уже только живительная эвтаназия поможет.
> >$peremennye_translitom
Могу себе позволить. Я не кодер, которого ебет начальство за каждую орфографическую ошибку в доках, а управленец, который как раз ебет кодеров который ебет нижестоящее начальство, чтобы оно ебало вас
> По-моему тебе уже только живительная эвтаназия поможет.
Программист - это, блядь, бледная моль, шестеренка №64. Кто-то скажет "кококо, а как же Джобс, Гейтсс, Цукерберг?". А вот хуй, эти люди прославились как организаторы-управленцы-бизнесмены, а собственно код писали безликие макаки, на которым всем похуй.
Так что под шконку. Сколько я таких ограниченных перевидала
Смог найти только скрипты-галереи без масштабирования и перетаскивания.
що ты раскудахтался додик, что не пиши уже всем понятно что ты дебил
Укради с двача че ты как не пират?
А вообще, 99% уже есть такой скрипт, нужно больше искать. Попробуй по-английски составить вопрос гуглу, либо например на stackoverflow создай тему на английском.
>>945285
Добавил в коллекцию паст, это блять эпично.
Алсо, пацаны объясните, как это работает:
>>945259
>if ($ballov -- 0) {} else { print... }
?
Это называется lightbox, жс-либ для этого навалом.
>Алсо, пацаны объясните, как это работает:
Это тоже самое, что if ($ballov != 0) без лишних элсов потом.
Алсо, перехватывает, если такие ошибки возникаю внтури классов. Но не работает, когда внутри обычного кода
Конструктор чекает на нулл и невалидные значения? Публичные сеттеры есть? Если нет, то могут ли затереться значения где-то в коде класса? Если с этим всем разобрался, то можешь не проверять нихуя. Однако, поскольку код имеет свойство внезапно подвергнуться правкам твоей же рукой и ты уже забудешь где чего, то для верности можешь чекать вообще всегда.
Да и вообще паранойя пограмистам еще никогда не мешала.
Так пускай твои работники это все делают, хули ты тут делаешь? Хуевый ты управленец раз не можешь поручить такую простую задачу кому-то.
не увидел перекат.
Тогда я ушел с твоей обоссаной галеры вместе с половиной команды, спиздил сорцы проекта, написал обличающую статьюу на хабре-хуябре и доу, гуд лак искать макак за доширак.
Чего раскудахтался-то, придурок? Я в код заглядываю раз в 10 лет, чтобы отправить разъеботчикам не только exception.log, но и кусок говно кода, который надо поправить.
>перевидала
Ой, иди нахуй, зелень.
Вы, мамкины кодеры, никчемные пустые людишки. Посредственности, серая масса. Жизнь ваша убогая, никто вас не любит, никому вы не нужны. Ваши "умные, нестандартные мысли" про спиздить сорцы и написать обличающую статью за пределами интернета никому не интересны, рассуждения уровня пятиклассника о жизни никто слушать не будет, а за особо дерзкие выпады и по ебалу могут накидать. У вас нет чувства юмора и эрудиции, чтобы остроумно шутить, нет знаний и жизненного опыта, чтобы поведать что-нибудь интересное предложениями больше чем из 3-х слов. Детские максимы, псевдознания, почерпнутые из роликов на ютубе и передач по рен-тв, стереотипы, рожденные в среде клешированного офисного планктона и нитакихкакфсе - вот и весь ваш "интеллектуальный" арсенал. Разумеется, ни девушку, ни взрослого, думающего человека таким богатством духа не заинтересовать. Вам хочется денег, славы, признания, но в жизни никто вас даже не замечает, как никто не замечает вошь на бездомной собаке. Вот и приходится вам, бедненьким, привлекать к себе внимание на интернет-пространстве самыми идиотскими высказываниями, на которые сбегаются точно такие же обделенные жизнью, чтобы поспорить, давать советы, увещевать, хоть как-то почувствовать себя чем-то "значимым" для кого-то на другой стороне провода. В интернете вы все аналитики. философы и выдающиеся мыслители современности, а на деле неуверенные в себе, зажатые, зависимые от родителей и мнения окружающих человечишки, прячущиеся в своей комнате от мира и людей, как тараканы от включенного ночью на кухне света. Мне вас жаль.
Оп посмотри, пожалуйста. Если правильно реализовал попап, то буду пробовать сделать виджет для меню.
>>945646
- название Student::GENDER_FEMALE намного больше говорит чем просто строка 'f'.
- сразу видно, какие константы есть и какие варианты значений доступны
- если ты опечатаешься в константе, будет фатальная ошибка, а в случае со строкой -это останется незамеченным
- в IDE будет работать автодополнение при вводе названия константы
Еще хуже было бы, если бы ты например использовал для обозначения пола числа 1 и 2 вместо строк, тогда вообще понять в коде было бы ничего нельзя без констант.
> Если у меня некоторые свойства объекта устанавливаются в конструкторе, должен ли я проверять их существование в других методах?
А о каком языке идет речь? В PHP если ты в классе объявил свойство, то оно всегда существует и проверять ничего не надо. Или ты имеешь в виду, что в свойство могут записать неправильное значение?
Лучше всего конечно ставить проверку там, где свойство меняется. Если оно приватное и меняется через метод setSomething() то нужно там поставить проверку и при попытке передать неверное значение выбросить исключение, завершающее программу. Если свойство публичное то проверку не сделать.
Я бы советовал также подстраховаться и добавить проверку при чтении свойства, примерно такого вида:
если ($this->something неправильное) {
выбросить исключение;
}
Также, эту проверку можно сделать короче с помощью функции assert. Она правда не бросает исключение, а только дает warning:
assert($this->x > 0);
зато выглядит очень наглядно. Любому теперь ясно, что функция рассчитывается что в x будет положительное значение.
>>945331
Throwable это интерфейс, потому не наследуются, а реализуют. Это было сделано специально, чтобы можно было делать свои классы исключений, не наследующие Exception.
в новом PHP7 вроде бы ошибка синтаксиса вызывает исключение ParseError и его можно ловить: https://www.daveyshafik.com/archives/69237-an-exceptional-change-in-php-7-0.html
В мануале оно тоже еcть: http://php.net/manual/en/class.parseerror.php
http://php.net/manual/ru/function.set-exception-handler.php
Учти, что ловятся ошибки только в подключенных или выполненных через eval файлах.
Но я не очень понимаю, зачем это нужно. Если ты написал кривой код то программа дальше выполняться не может и надо исправить код.
> Если у меня некоторые свойства объекта устанавливаются в конструкторе, должен ли я проверять их существование в других методах?
А о каком языке идет речь? В PHP если ты в классе объявил свойство, то оно всегда существует и проверять ничего не надо. Или ты имеешь в виду, что в свойство могут записать неправильное значение?
Лучше всего конечно ставить проверку там, где свойство меняется. Если оно приватное и меняется через метод setSomething() то нужно там поставить проверку и при попытке передать неверное значение выбросить исключение, завершающее программу. Если свойство публичное то проверку не сделать.
Я бы советовал также подстраховаться и добавить проверку при чтении свойства, примерно такого вида:
если ($this->something неправильное) {
выбросить исключение;
}
Также, эту проверку можно сделать короче с помощью функции assert. Она правда не бросает исключение, а только дает warning:
assert($this->x > 0);
зато выглядит очень наглядно. Любому теперь ясно, что функция рассчитывается что в x будет положительное значение.
>>945331
Throwable это интерфейс, потому не наследуются, а реализуют. Это было сделано специально, чтобы можно было делать свои классы исключений, не наследующие Exception.
в новом PHP7 вроде бы ошибка синтаксиса вызывает исключение ParseError и его можно ловить: https://www.daveyshafik.com/archives/69237-an-exceptional-change-in-php-7-0.html
В мануале оно тоже еcть: http://php.net/manual/en/class.parseerror.php
http://php.net/manual/ru/function.set-exception-handler.php
Учти, что ловятся ошибки только в подключенных или выполненных через eval файлах.
Но я не очень понимаю, зачем это нужно. Если ты написал кривой код то программа дальше выполняться не может и надо исправить код.
Мы уже в новом треде.
В каждой компании свои градации. Синьора из какой-нибудь провинциальной веб-студии в Гугле даже на собеседование на стажера не пустят.
Обычно эти градации соответствуют опыту:
- стажер - человек, как правило, студент, который пока не имеет нужных для полноценной работы навыков
- джуниор - человек с минимальным опытом, которому нужен постоянный надзор и помощь, что-то вроде разнорабочего на стройке
- миддл - человек с определенным опытом, способный сам решать более сложные задачи, оценивать их трудоемкость
- сеньор - человек с значительным опытом, способный руководить другими разработчиками, принимать решения, понимать, что нужно бизнес-заказчику (не красивый код с кучей абстракций, а быстрое и эффективное решение задач)
Если ты ни дня ни работал, то выше джуниора должность ты в принципе получить не можешь в связи с отсутствием опыта.
Что должен делать претендент на пост джуниора с 0 опытом работы? Конечно, учиться. Зубрить вещи, которые пригодятся ему на работе:
- алгоритмы и структуры данных
- объектно-ориентированное программирование
- понятный и самодокументируемый код (есть книга "Совершенный код" на эту тему)
- системы контроля версий (git)
- если ты вебщик, то веб-технологии (HTML, CSS, JS)
- базы данных, SQL, нормальные формы, транзакции
- изучать популярные инструменты, библиотеки и технологии (фреймворки например)
Так как у такого кандидата нет опыта работы, то говорить на собеседовании с ним про предыдущие проекты смысла нет. Потому их гоняют по теории, то, что я перечислил выше, про ООП, про нормальные формы, как найти число в массиве, что нового появилось в последнем PHP.
Кстати, специально для такого целеустремленного тебя, у меня есть сборник реальных задач с собеседований: https://github.com/codedokode/pasta/blob/master/interview-tasks.md
Конечно, не везде это нужно. В провинциальной веб-студии, чтобы попасть на должность перекрашивателя меню и натягивателя верстки на CMS, это может не потребоваться. Но ты ведь вряд ли заинтересован в том, чтобы этим всю жизнь заниматься. Наверняка ты хочешь быть полноценным разработчиком в большой команде, разрабатывающей какой-нибудь серьезный продукт.
Мы уже в новом треде.
В каждой компании свои градации. Синьора из какой-нибудь провинциальной веб-студии в Гугле даже на собеседование на стажера не пустят.
Обычно эти градации соответствуют опыту:
- стажер - человек, как правило, студент, который пока не имеет нужных для полноценной работы навыков
- джуниор - человек с минимальным опытом, которому нужен постоянный надзор и помощь, что-то вроде разнорабочего на стройке
- миддл - человек с определенным опытом, способный сам решать более сложные задачи, оценивать их трудоемкость
- сеньор - человек с значительным опытом, способный руководить другими разработчиками, принимать решения, понимать, что нужно бизнес-заказчику (не красивый код с кучей абстракций, а быстрое и эффективное решение задач)
Если ты ни дня ни работал, то выше джуниора должность ты в принципе получить не можешь в связи с отсутствием опыта.
Что должен делать претендент на пост джуниора с 0 опытом работы? Конечно, учиться. Зубрить вещи, которые пригодятся ему на работе:
- алгоритмы и структуры данных
- объектно-ориентированное программирование
- понятный и самодокументируемый код (есть книга "Совершенный код" на эту тему)
- системы контроля версий (git)
- если ты вебщик, то веб-технологии (HTML, CSS, JS)
- базы данных, SQL, нормальные формы, транзакции
- изучать популярные инструменты, библиотеки и технологии (фреймворки например)
Так как у такого кандидата нет опыта работы, то говорить на собеседовании с ним про предыдущие проекты смысла нет. Потому их гоняют по теории, то, что я перечислил выше, про ООП, про нормальные формы, как найти число в массиве, что нового появилось в последнем PHP.
Кстати, специально для такого целеустремленного тебя, у меня есть сборник реальных задач с собеседований: https://github.com/codedokode/pasta/blob/master/interview-tasks.md
Конечно, не везде это нужно. В провинциальной веб-студии, чтобы попасть на должность перекрашивателя меню и натягивателя верстки на CMS, это может не потребоваться. Но ты ведь вряд ли заинтересован в том, чтобы этим всю жизнь заниматься. Наверняка ты хочешь быть полноценным разработчиком в большой команде, разрабатывающей какой-нибудь серьезный продукт.
Прежде чем браться за адаптивную верстку, надо освоить резиновую, то есть такую, которая тянется по ширине, а не имеет фиксированную ширину. Адаптивность заключается в более тщательной адаптации верстки под разные устройства. На практике адаптивность реализуют подстройкой верстки под маленькие экраны - планшеты и смартфоны. Обычно выделяют так называемую линию перелома (break point), если экран имеет ширину меньше определенной, то мы меняем верстку так, чтобы страница отображалась на нем без необходимости прокручивать ее горизонтально (то есть выстраиваем все в столбик, вместо нескольких колонок делаем одну).
Также добавляется тег meta viewport, который заставляет браузер рендерить страницу под реальную ширину устройства, а не имитировать экран шириной 900px и заставлять пользователя приближать текст.
Я советую начать с изучения примеров адаптивных сайтов. Гугли статьи вроде "примеры адаптивных сайтов" и смотри примеры там, чтобы понять, как это обычно выглядит. Если у тебя нет смартфона, то ты можешь имитировать мобильный браузер, сделав окно узким либо открыв инструменты разработчика (Ctrl + SHift + I) и нажав там кнопочку со смартфоном.
Технически нужно изучить всего несколько вещей:
- медиа-запросы CSS @media
- тег meta viewport, говорящий браузеру, что страница адаптирована под мобильные устройства
У нас в ОП-посте есть задачи на CSS и там есть макет, которй надо свестать в том числе с адаптивностью
Иногда еще добавляют адаптацию страницы под экраны с высокой плотностью пикселей (ретина), чтобы для них использовались картинки более высокого разрешения. Гугли HTML-атрибут srcset и теги picture, source.
Вообще, адаптивность не ограничивается мобильными устройствами. Есть и другие вещи, которые можно улучшить. Ну например, при печати страницы ссылки становятся недоступны (ты не можешь кликнуть пальцем на бумагу). Можно в таких случаях сделать правило, чтобы при печати выводились URL ссылок. Изучи медиа-запросы, там много разных опций.
Вот еще скопирую старый ответ на эту тему:
------
Адаптивность значит способность отображаться на разных устройствах с учетом их особенностей. И это обычно не просто уменьшение шрифта. На мобильных устройствах (адроид/айфон) браузер по умолчанию рисует страницу на холсте шириной 800px точнее, 960px и отображает в уменьшенном виде. Пользователь кликает, чтобы ее увеличить, и если абзацы широкие, то ему приходится прокручивать экран вправо-влево чтобы читать текст (увидеть все это можно тут: http://www.youtube.com/watch?v=-1haU-WRMoA если ты с этим явлением не знаком).
Также, надо понимать, что на мобильных устройствах нет средней и правой кнопки мыши, возможности точно нажать маленький элемент, а также возможности навести мышь на элемент, только тап пальцем по экрану или жесты.
Смартфон также может быть повернут набок — тогда ширина экрана получается больше. Кроме смартфонов, есть планшеты, где ширина экрана большая, но используется палец вместо мыши.
Соответственно, адаптивные сайты на мобильных устройствах часто меняют расположение контента так, чтобы информация была в виде узкой вертикальной полосы и не требовала зума и прокрутки вбок. Элементы управления, кнопки, делают крупными. Для этого применяют такие вещи:
1) правило @media в CSS которое позволяет применять блок правил только при определенных условиях (ширина экрана меньше определенного значения — например меньше 640px). Информация:
http://htmlbook.ru/css/value/media
http://htmlbook.ru/css/media
(обрати внимание, сколько разных видов устройств поддерживается — можно отдельно задавать стили для телевизоров, а отдельно для печати)
Заметь что @media не поддерживается в старом ИЕ, потому логично верстать страницу по умолчанию под обычные браузеры, а правила для маленьких экранов заключить внутрь @media, который ИЕ наверно проигнорирует (если нет — выносим в отдельный файл и подключаем через условные комментарии).
Кстати, насчет vw, ты можешь делать так:
font-size: 14px; // правило для старых браузеров
font-size: 5vw; // правило для CSS3 браузеров
Это будет работать, если писать в таком порядке так как браузеры игнорируют свойства которые они не поняли.
2) тег meta viewport который говорит мобильному устройству что страница учитывает его особенности, и указывает что ее надо рисовать на холсте, равном реальной ширине экрана, чтобы отображалась в 100% масштабе. Часто (подозреваю по незнанию) запрещают зум, хотя мне это не нравится — может у человека маленький экран и плохое зрение и он хочет увеличить текст. Я против таких штук, но среднестатистический верстальщик делает такие вещи методом «скопипастил из интернета» и сам часто не понимает что он делает.
Инфо:
http://frontender.com.ua/mobile-web/wtf-viewport/
http://frontender.com.ua/mobile-web/useful-mobile-head-elements/
http://www.quirksmode.org/mobile/metaviewport/
(только не копируй оттуда куски кода бездумно)
Соответственно, вот примеры реализации адаптивной верстки (уменьши ширину окна чтобы увидеть изменения):
http://foodsense.is/ (комментарии под постами здесь не адаптивные)
http://alistapart.com/d/responsive-web-design/ex/ex-site-FINAL.html
http://robot-or-not.com/
http://spigotdesign.com/
Заметь что там шрифт нигде не меняется.
Если ты понимаешь английский, то вот еще неплохой гайд по основам адаптивного дизайна: https://developers.google.com/web/fundamentals/layouts/
Для отладки адаптивного дизайна лучше всего конечно использовать реальные устройства, но в Хроме в инспекторе есть неплохой режим имитации маленьких экранов, и в фаерфоксе что-то для этого есть.
Вот еще скопирую старый ответ на эту тему:
------
Адаптивность значит способность отображаться на разных устройствах с учетом их особенностей. И это обычно не просто уменьшение шрифта. На мобильных устройствах (адроид/айфон) браузер по умолчанию рисует страницу на холсте шириной 800px точнее, 960px и отображает в уменьшенном виде. Пользователь кликает, чтобы ее увеличить, и если абзацы широкие, то ему приходится прокручивать экран вправо-влево чтобы читать текст (увидеть все это можно тут: http://www.youtube.com/watch?v=-1haU-WRMoA если ты с этим явлением не знаком).
Также, надо понимать, что на мобильных устройствах нет средней и правой кнопки мыши, возможности точно нажать маленький элемент, а также возможности навести мышь на элемент, только тап пальцем по экрану или жесты.
Смартфон также может быть повернут набок — тогда ширина экрана получается больше. Кроме смартфонов, есть планшеты, где ширина экрана большая, но используется палец вместо мыши.
Соответственно, адаптивные сайты на мобильных устройствах часто меняют расположение контента так, чтобы информация была в виде узкой вертикальной полосы и не требовала зума и прокрутки вбок. Элементы управления, кнопки, делают крупными. Для этого применяют такие вещи:
1) правило @media в CSS которое позволяет применять блок правил только при определенных условиях (ширина экрана меньше определенного значения — например меньше 640px). Информация:
http://htmlbook.ru/css/value/media
http://htmlbook.ru/css/media
(обрати внимание, сколько разных видов устройств поддерживается — можно отдельно задавать стили для телевизоров, а отдельно для печати)
Заметь что @media не поддерживается в старом ИЕ, потому логично верстать страницу по умолчанию под обычные браузеры, а правила для маленьких экранов заключить внутрь @media, который ИЕ наверно проигнорирует (если нет — выносим в отдельный файл и подключаем через условные комментарии).
Кстати, насчет vw, ты можешь делать так:
font-size: 14px; // правило для старых браузеров
font-size: 5vw; // правило для CSS3 браузеров
Это будет работать, если писать в таком порядке так как браузеры игнорируют свойства которые они не поняли.
2) тег meta viewport который говорит мобильному устройству что страница учитывает его особенности, и указывает что ее надо рисовать на холсте, равном реальной ширине экрана, чтобы отображалась в 100% масштабе. Часто (подозреваю по незнанию) запрещают зум, хотя мне это не нравится — может у человека маленький экран и плохое зрение и он хочет увеличить текст. Я против таких штук, но среднестатистический верстальщик делает такие вещи методом «скопипастил из интернета» и сам часто не понимает что он делает.
Инфо:
http://frontender.com.ua/mobile-web/wtf-viewport/
http://frontender.com.ua/mobile-web/useful-mobile-head-elements/
http://www.quirksmode.org/mobile/metaviewport/
(только не копируй оттуда куски кода бездумно)
Соответственно, вот примеры реализации адаптивной верстки (уменьши ширину окна чтобы увидеть изменения):
http://foodsense.is/ (комментарии под постами здесь не адаптивные)
http://alistapart.com/d/responsive-web-design/ex/ex-site-FINAL.html
http://robot-or-not.com/
http://spigotdesign.com/
Заметь что там шрифт нигде не меняется.
Если ты понимаешь английский, то вот еще неплохой гайд по основам адаптивного дизайна: https://developers.google.com/web/fundamentals/layouts/
Для отладки адаптивного дизайна лучше всего конечно использовать реальные устройства, но в Хроме в инспекторе есть неплохой режим имитации маленьких экранов, и в фаерфоксе что-то для этого есть.
Проверяю на практикте:
mysql> CREATE TABLE test (number INT(6), text VARCHAR(6));
Query OK, 0 rows affected (0,41 sec)
mysql> INSERT INTO test VALUES (7, "abcdef");
Query OK, 1 row affected (0,16 sec)
mysql> INSERT INTO test VALUES (7777777, "abcdef");
Query OK, 1 row affected (0,05 sec)
mysql> INSERT INTO test VALUES (7777777, "abcdefg");
ERROR 1406 (22001): Data too long for column 'text' at row 1
Как такое может быть? Это значение не на что не полвияло.
Цифра в скобках значит разные вещи для разных типов данных.
https://dev.mysql.com/doc/refman/5.7/en/numeric-types.html (англ)
https://dev.mysql.com/doc/refman/5.7/en/numeric-type-attributes.html
https://dev.mysql.com/doc/refman/5.7/en/floating-point-types.html
http://phpclub.ru/mysql/doc/numeric-types.html (рус)
Для типов вроде INT это просто рекомендуемая ширина колонки при выводе чисел
Для DECIMAL задает точность в знаках
Для FLOAT - точность, но не в знаках, а в битах, выделяемых под хранение мантиссы (влияет на то, будет ли использоваться для хранения числа 4 или 8 байт). Если указать 2 числа, то точность в знаках, до которой числа принудительно округляются.
Может. Так как значения для номеров в скобках это не размер(он всегда фиксирован для инт типов), а количество цифр для отображения при запросе, например, mysql консольным клиентом.
Отсюда: https://github.com/codedokode/pasta/blob/master/db/databases.md#Задачка-про-лайки/
На всякий случай напишу, что на sqlfiddle результат SELECT'ов по умолчанию выводится в виде HTML-таблицы, что выглядит громоздко, как по мне. Но можно выбрать plaintext (пик).
[code]
$_SERVER["DOCUMENT_ROOT"]. '/students/src/views/'. $view.'.php'
[/code]
Что-то подсказывает мне, что это говнокод.
Если использовать __DIR__, то у меня получается папка /src/controllers, так как класс контроллера расположен там.
https://github.com/TheUnravelGhoul/Students
мои глаза. просто возьми фреймворк и не парься.
>>945887
дебильные задачки для тупых олимпиадников. даже текст задачи нормально составить не могут. какие-то склеенные банкноты, натуральные числа, вообще ахуеть.
У тебя в шаблонах код контроллера. Шаблоны только отображают переданные сверху данные, а не обращаются к HTTP/выполняют SQL-запросы, как в твоём случае.
Формирование ссылки на CSS в контроллере выглядит странным (HTML это код шаблона, а не контроллера). Контроллер у тебя создаёт PDO, лучше бы передавать в контроллер сразу AbiturientGateway. Контроллеры в студентах необязательно делать классами, хватит двух скриптов list.php и form.php, которые будут разбирать HTTP-запрос, обращаться к модели и в конце подключать шаблон. Валидировать студента - не ответственность Gateway, нужно вынести валидатор оттуда. Мне кажется, что ты не читал пасту про MVC: https://github.com/codedokode/pasta/blob/master/arch/mvc.md
Исполняемый файл композера, папки vendor и .idea в системе контроля версий нет смысла хранить, добавь их в .gitignore
foreach ($this->css as $css){
$list .= "<link rel = 'stylesheet' href = '". $css ."'>\n";
}
бляяя, такого ахуенного подключения стилей прямо в контроллере я еще не видел. просто 10 из 10 говнокод.
>htmlspecialchars($_GET['action']);
Ты нахрена так делаешь, у тебя что в контроллере SQL инъекция может быть?
Я честно говоря даже боюсь подумать нахуя так делать то.
Мы потихоньку пилим сообщество тех, кто учит вёрстку, полноценный frontend или же backend - https://vk.com/webdevheroes
Учимся вместе, чтоб было поменьше прокрастинации, поддержка, все дела.
Всех, кто желает получить новую специальность или кому просто интересно, приглашаю начинать учиться вот прямо сейчас: https://vk.com/webdevheroes
Большинство начинают учить по этому курсу с самого начала: https://htmlacademy.ru/courses
Какие-то аноны учат по книгам, кто-то по другим сайтам. Заходите, рассказывайте о том, как учите, к чему стремитесь, и, самое главное, просите помощи, если есть трудности.
Что я могу предложить от себя? На данный момент имеется два с половиной наставника, конференция вконтакте и группа там же. Бесплатно.
Если у вас возникнут вопросы - можете задать их в группе или же в конференции.
https://vk.com/webdevheroes
require_once './../config/db.php';
require_once './../vendor/autoload.php';
use ghoul\controllers\SiteController;
use ghoul\helpers\gateways\AbiturientDataGateway;
use ghoul\models\Abiturient;
$action = empty($_GET['action']) ? "index" : htmlspecialchars($_GET['action']);
$site = new SiteController($config);
$site->registerCss("css/style.css");
$abiturientGateway = new AbiturientDataGateway($site->pdo);
?>
<html>
<head>
<title>Список абитуриентов</title>
<?=$site->getCssList()?>
</head>
<div class = "wrapper">
<?php $site->render($action) ?>
</div>
</html>
Html код у тебя отдельно в папке вью лежит, ты по ходу не понял mvc, просто возьми пример mvc с хабра и давай-ка переписывай это все.
https://github.com/TheUnravelGhoul/Students/blob/master/src/views/index.php
Метод POST у тебя тоже должен быть в контроллере отдельно от html, а не во вьюхах. Во вьюхи выводится только хтмл код и переменные, которые ты передаешь во вью через контроллер. Весь код лежит в контроллерах или моделях. Во вью только циклом по массиву, который лежит в переменной, переданной через контроллер, можешь пройтись.
require_once './../config/db.php';
require_once './../vendor/autoload.php';
use ghoul\controllers\SiteController;
use ghoul\helpers\gateways\AbiturientDataGateway;
use ghoul\models\Abiturient;
$action = empty($_GET['action']) ? "index" : htmlspecialchars($_GET['action']);
$site = new SiteController($config);
$site->registerCss("css/style.css");
$abiturientGateway = new AbiturientDataGateway($site->pdo);
?>
<html>
<head>
<title>Список абитуриентов</title>
<?=$site->getCssList()?>
</head>
<div class = "wrapper">
<?php $site->render($action) ?>
</div>
</html>
Html код у тебя отдельно в папке вью лежит, ты по ходу не понял mvc, просто возьми пример mvc с хабра и давай-ка переписывай это все.
https://github.com/TheUnravelGhoul/Students/blob/master/src/views/index.php
Метод POST у тебя тоже должен быть в контроллере отдельно от html, а не во вьюхах. Во вьюхи выводится только хтмл код и переменные, которые ты передаешь во вью через контроллер. Весь код лежит в контроллерах или моделях. Во вью только циклом по массиву, который лежит в переменной, переданной через контроллер, можешь пройтись.
Джанга лучше пхп, фласк лучше джанги. Питон лучше пхп. На питоне нет работы, на пхп дохуя. Выбор за тобой.
Ты глупости пишешь. Начинающим надо сначала разобраться вообще с тем, как веб-страницы делаются, а браться за фреймворк, не изучив предыдущие темы. По твоей логике и массивы с регулярками изучать не надо, а сразу брать фреймворк и повторять то, что делают в видеокурсе. Так ты научишься только повторять за другими, а не писать сам.
Вообще, твой комментарий тут довольно бесполезный. Лучше бы и не писал.
>>945963
Контроллеры можно делать и классами, и скриптом, и так и тк можно.
>>945964
>>945966
Он не сеньор с 20 годами опыта чтобы с первого раза все идеально написать. Не понимаю, в чем твоя претензия.
Вы прежде чем комментировать, не пробовали понять, что тут происходит, что это за тред и зачем люди здесь код постят? В ОП посте написано, прочитайте сначала.
>>945971
Прочитай второй пост внимательно прежде чем комментировать.
Алсо, какое отношение htmlspecialchars имеет к SQL инъекциям, можешь прояснить? советую для начала изучить этот урок https://github.com/codedokode/pasta/blob/master/security/sql-injection.md
Есть варианты. Во-первых можно писать так:
__DIR__ . '/../src/';
.. - значит подняться на 1 уровень выше
можно так:
dirname(__DIR__) . '/src/xxx';
>Вы прежде чем комментировать, не пробовали понять, что тут происходит, что это за тред и зачем люди здесь код постят? В ОП посте написано, прочитайте сначала.
Да я не придираюсь, просто мне было бы реально интересно понять ход мыслей - зачем в объекте хранить подключение таблицы стилей. А так у него типичная проблема неофита -понимание MVC.
На пхп очень много всего написано. Куча ORM, фреймворков и т.п. А на питоне? Собственно питон же и не заточен чисто на веб, а вот пхп полностью, того он в нем и доминирует, ничего странного.
2: https://jsfiddle.net/Lq1fgjde/
3: https://jsfiddle.net/jf001qkz/
4: https://jsfiddle.net/zvcemf1n/
5: https://jsfiddle.net/716kuL41/
Я, правда, не все статьи по ссылкам читал, если видел, что и так удалось (удалось ли?) решить задание. Обязательно почитаю их.
Но на пистоне можно писать все то же самое, что и на пхп, только в разы изящнее. Еще руби есть, он например тоже заточен только под веб.
Все дело в говноедстве пидорах, эти тупые уебаны без чувства прекрасного будут еще сто лет форсить убеанскую хуйню, типа 1С или хостинга всего и вся на шинде и аспе. Эта тяга к безвкусице и некрасивым решениям, костылям и говну уже в крови.
как буд то на западе этого нет.питоном пользуються в основном узкая прослойка проэктов,заточеная на что то новое
>куча фреймворков
Пхп:
Cимфони, ларавел. Остальное хуйня для хипстеров.
Питон:
Джанга, фласк Остальное хуйня для хипстеров.
короче,зря я бросил пыху,дохуя времени потратил на питон
>Но на пистоне можно писать все то же самое, что и на пхп, только в разы изящнее.
Так бери и пиши, в чем проблема? Вот когда будут полноценные альтернативы симфони, доктрины, зенда и прочего - тогда посмотрим, может пхп и зафейлится. Понимаешь, "изящность" это ну очень мутное преимущество. Я например не перевариваю snake-case и табуляцию как часть синтаксиса.
>Еще руби есть, он например тоже заточен только под веб.
Руби ВСЁ, официально.
зато для веба надо выучить питон,а потом еще и фраймворк и дрочить его.а на пыхе сразу в бой
джанго говно каждый школьник в своем тех.пту учит, а потом эти толпы после выпуска со знаниями одной джанги валят на рынок труда и переполняют его.
ssh://g;//itANUSsport.te1^tstdevPUNCTUMrqP(u:22111/dev.git
>зато для веба надо выучить питон,а потом еще и фраймворк и дрочить его
Пыха:
Учишь пыху, учишь фреймворк, дрочишь его. ЧЯДНТ?
Я сам учился кодить в этом треде и сейчас уже джуном работаю, но даже я на начальных этапах начинал с верстки и таких ошибок в мвц не делал. он даже мвц толком не написал, а создал какого-то монстра, мог просто погуглить статьи о мвц и ПОВТОРИТЬ простенький апп-бутсрап.
а зачем в гет запросе, который передается в урл эскапировать html тэги? Это приведет только к искажению урла, который ты получаешь гетом.
bump
почему?
1. Если это ссылка на другую страницу этого же сайта, но адрес на картинку недоступен на этой страницы из запроса к базе данных.
2. Если это ссылка на другой сайт.
Я так понял тут нужны какие-то парсеры чтоли, но как их делать на яваскрипте?
Зато любит матан и создает рандомные многоугольники через синусы всякие. Еще один пруф, что матанобляди не могут в кодинг
поэтому и не вкатишься, что его каждый школьник с нейросетями в вузах типа бауманки учит, а потом со 2ого курса идет работать.
на всем, чему учат в вузах, нет работы, потому что там программа устарела лет на 50. еще спроси, почему нет работы для паяльщиков микроконтроллеров, хотя этому учат в вузах.
Лол. Зато если тебе когда-нибудь поставят задачу написать граф, ну там поиск пути - ты соснешь, а она на повышение пойдет.
там могут преподавать полную ересь-но без бумашки,ты какашка.а с бумашкой-человек
как и у вас в обратку.весь этот хайп,о том что кодинг последний вагон уходящего поезда возможностейЮмиф для быдла
еще раз,нет диплома,тебя не возьмут,особенно по джаве и плюсам,может макакой пхпешной и то маловероятно
>кодинг последний вагон уходящего поезда возможностей
Щито? У тебя какой-то неправильный манямирок.
Кодинг это сознательный выбор, никакого хайпа.
Короче, не вижу смысла дальше общаться с тобой, укатывайся на софтач траллировать.
Доброчан давно мертв, а доброчановские аноны - гнилье анимешное.
еще как хайп,миллионы говно сайтов с азами как бы намекают и книги изучим говно за 21 день
поэтому в программаче я предлагаю создать тред о РЕАЛИЯХ кодинга в плане менеджмента,финансов и требованиях
Ии2 самый поплуярный. Или ларавель, хуй знает. Симфони и зенд это для илитки уже, не влезай пока не будет хотя бы года кодинга.
пруфов как всегда не будет
>веб
>написание графов
вылези из своих маняфантазий. она разве что синус у треугольника посчитает и ребро у ромба найдет.
нахуя ты его учишь?пополнишь ряды говнокодеров
как будто это не правда
Но ведь работодатели любят нанимать малолеток. Сейчас придешь в контору 22+ - сразу начнутся подозрительные взгляды - а где вы до этого хуи пинали?
потому что малолеток можно ебать в хвост и гриву,за маленькую зп
>>946114
>>946110
Нытики, выкатывайтесь в свой нытик-тред и перестаньте оффтопить. Это тред изучения PHP
Любят, но только в днищеконторы на мелкую зп, где дикая потребность в кадрах.
Давайте лучше перекатимся с этим обсуждением в перезвони тред.
зато как оживился тред!
На ней тоже работаю кстати. Правда в меньшей степени гораздо.
ну мы же котаны
потому что мы тяночки-анимешницы с доброчана.
толсто
Если тебе тяжело понять это, советую потратить денек на http://nnmclub.to/forum/viewtopic.php?t=1046622 второй курс, 1-4 уроки. Только я например так и не понял зачем он там синглтоны пихает, но MVC поясняет очень хорошо. Да, я знаю что смотреть курсы - тупиковый путь, но там просто лектор реално хороший.
1) Весь код содержится в контроллере.
2) В view содержится только html с выводом необходимых переменных.
3) Вызывать view через include(файл) в контроллере - это нормально.
Где я не прав, поправьте.
>>946178 -кун
В моделях содержится вся работа с данными. Вьюхи, понятно, чисто для рендера. Контроллер как связующее звено между всем этим выступает. Вьюха дергает контроллер - контроллер дергает модели (а может и не дергать) - контроллер дергает вьюху какую-то, чтоб та отрендарилась и так до усеру.
Стоит заметить, что это вебовское mvc, каноничное вообще не так работает, а тут это скорее mvp напоминает.
> контроллер дергает модели (а может и не дергать)
Это понял.
>контроллер дергает вьюху какую-то, чтоб та отрендарилась
Тоже понял.
>Вьюха дергает контроллер
А вот это - не совсем. Вью же отвечает только за отображение информации, райт? Она не должна трогать контроллер, разве что в плане получения из него каких-то данных для рендера.
Ты совсем не понял. MVC не значит, что у тебя должен быть определенный набор файлов, скриптов, это логическое разделение кода. Контроллер - это часть кода, куда попадает запрос пользователя. Он обрабатывает запрос и передает необходимые данные модели. Модель - это код отвечающий за всю логику приложения считай. Вычисления, сущности, операция с БД - это все модели. Сама по себе данные для работы она получает только из контроллера(запомни, это важно). Получив необходимые данные модель отправляет их контроллеру, тот уже подключает шаблон(через include например). Как-то так.
>>946187
Котнроллеры должны дергать всякие методы. Модель и вьюха живут отдельно и не знают о существовании друг друга.
Да нет же, я понимаю это. Наверное, просто не совсем ясно выразился.
>Сама по себе данные для работы она получает только из контроллера(запомни, это важно)
Спасибо, запомню.
Ну это я образно, типа жизненный цикл запроса описал с учетом, что страница в браузере это уже отданная клиенту вьюха. Ну да, технически это не вью, я выразился так просто. Давай по новому, клиент делает запрос откуда то, твое приложение его роутит и он приходит на контроллер, контроллепр работает с моделями и сам чет делает, что считает нужным (логику работу с данными, однако, ты инкапсулируешь в модели), в конце концов контроллер отдает какие-то данные вьюхе, та их использует для рендера статики, ну а статика уже выплевывается обратно клиенту.
Вот, теперь понятно, спасибо.
Помню еще в треде упоминался видеокурс https://www.youtube.com/watch?v=R-yQux1S63w , стоит его смотреть вместо книг?
Есть уже большое приложение с рест апи, все как всегда. Но один из маршрутов возвращает кириллицу в виде "????". Весь проект на utf-8, вся база в utf8-general-ci. Откуда по совершенно такому же гет запросу, как и остальные, вдруг меняется кодировка ума не приложу. (жизненный цикл абсолютно одинаков для каждого гет запроса) Во время выполнения самого приложения вплоть до отдачи из контроллера данные в нужной кодировке находятся. Вот такие дела. С учетом этого можно все это обойти просто сделав эхо прямо из контроллера, но хотелось бы все же понять в чем дело то может быть.
>>946181
>>946178
Гляньте тогда и мой урок по MVC: https://github.com/codedokode/pasta/blob/master/arch/mvc.md
>>946184
Не, контроллер нужен для того, чтобы принять запрос от браузера, вызвать нужные методы модели и затем вызвать вью чтобы отобразить результат. Ну например, запросить у модели список студентов,а затем вызвать вью, чтобы отобразить его.
> Вызывать view через include(файл) в контроллере - это нормально.
В общем, да.
>>946185
>Вьюха дергает контроллер - контроллер дергает модели (а может и не дергать)
Не, такого нет. Бывают архитектуры, когда вью вызывает методы модели, чтобы получить у нее какие-то данные, но в вебе обычно это делает контроллер и передает полученные данные во вью, а оно только их отображает.
Нельзя вызывать контроллер, это не модель, чтобы кому-то какие-то данные предоставлять.
Контроллер просто принимает данные от браузера (например, анализирует GET/POST) и затем вызывает модель и вью.
>>946190
> Сама по себе данные для работы она получает только из контроллера(запомни, это важно). Получив необходимые данные модель отправляет их контроллеру
Не совсем так. Правильнее сказать, что контроллер вызывает методы модели, чтобы получить какие-то данные или изменить их.
Условно говоря, модель содержит всю логику приложения, кроме вывода данных (это задача вью) и приема HTTP запросов от браузера (это работа контроллера). То есть любое действие в приложении можно сделать программно, вызывая методы модели. Хочешь получить список студентов? есть такой метод. Хочешь найти студентов по ключевому слову? Есть такой метод. Хочешь добавить нового студента? Есть и такой метод. То есть имея только модель, ты можешь программно (вызывая функции) делать все действия, которые доступны в приложении. Или, если перефразировать, для любых действий, которые доступны в приложении (просмотр, поиск, регистрация), есть методы модели, которые их выполняют.
>>946181
>>946178
Гляньте тогда и мой урок по MVC: https://github.com/codedokode/pasta/blob/master/arch/mvc.md
>>946184
Не, контроллер нужен для того, чтобы принять запрос от браузера, вызвать нужные методы модели и затем вызвать вью чтобы отобразить результат. Ну например, запросить у модели список студентов,а затем вызвать вью, чтобы отобразить его.
> Вызывать view через include(файл) в контроллере - это нормально.
В общем, да.
>>946185
>Вьюха дергает контроллер - контроллер дергает модели (а может и не дергать)
Не, такого нет. Бывают архитектуры, когда вью вызывает методы модели, чтобы получить у нее какие-то данные, но в вебе обычно это делает контроллер и передает полученные данные во вью, а оно только их отображает.
Нельзя вызывать контроллер, это не модель, чтобы кому-то какие-то данные предоставлять.
Контроллер просто принимает данные от браузера (например, анализирует GET/POST) и затем вызывает модель и вью.
>>946190
> Сама по себе данные для работы она получает только из контроллера(запомни, это важно). Получив необходимые данные модель отправляет их контроллеру
Не совсем так. Правильнее сказать, что контроллер вызывает методы модели, чтобы получить какие-то данные или изменить их.
Условно говоря, модель содержит всю логику приложения, кроме вывода данных (это задача вью) и приема HTTP запросов от браузера (это работа контроллера). То есть любое действие в приложении можно сделать программно, вызывая методы модели. Хочешь получить список студентов? есть такой метод. Хочешь найти студентов по ключевому слову? Есть такой метод. Хочешь добавить нового студента? Есть и такой метод. То есть имея только модель, ты можешь программно (вызывая функции) делать все действия, которые доступны в приложении. Или, если перефразировать, для любых действий, которые доступны в приложении (просмотр, поиск, регистрация), есть методы модели, которые их выполняют.
Рейтаните контроллер плиз. Слишком толстый?
https://github.com/grigoryMovchan/zuihitsu/blob/master/app/Http/Controllers/PostController.php
Мне кажется, ты зря прямо в контроллер передаешь посты. Хотя я так понял у тебя там ларавель, может там так и надо.
А ты про что именно?
Если про переменные с постами, то они для шаблонизатора, который их потом раскидывает по виду. Сами посты я получаю из модели, контроллер только отправляет их шаблонизатору.
алсо, можете еще порейтить стиль кода, тоже будет кстати
Я про вот это.
>public function __construct(Post $posts, Tag $tags, Attitude $attitude)
Я конечно не знаю что ты хочешь там вообще сделать, но по идее ты должен внутри контроллера получать из модели посты, не? А так ты выходит получаешь где-то посты, потом передаешь их в контроллер. Со стороны выглядит как грубое нарушение принципов MVC.
https://github.com/someApprentice/maintaskforlayout/ >>919288
https://github.com/someApprentice/Students/ >>926219
https://github.com/sylenien/php-news-site/ >>927983
https://github.com/grigoryMovchan/zuihitsu >>932473
https://github.com/greenTea242/MinesweeperMVC >>938223
https://github.com/anotherCodeMunkey/fileshare >>938323
Не, это какая-то ларавелевская хуйня, так уже было из коробки
Я так понял, она получает класс модели, чтобы создать из него объект, который присваивается свойству внутри контроллера, чтобы потом получать доступ к методам модели через это приватное свойства конструктора.
Можно в конструктор ничего не передавать, тогда в модели методы должны быть статичными, чтобы обращаться к ним без создания нового объекта из класса модели.
я потом хуй забил и просто нагородил статичных методов в модели, о чем теперь жалею, потому что дошло, что надо выбирать что-то одно
Тебе наверное надо побольше документации читать, или там советы какие в интернете ищи. Тут вроде не объявлялись знатоки ларавели.
Топ по популярности. Но я вот например его не люблю.
Это кривой код, он толком сам не понимает что представляет собой объект Post и что надо передавать в контроллер. Просто где-то что-то похожее видел и бездумно написал по аналогии.
>>946284
Ты бы посмотрел, как в этом фреймворке принято делать, и делал бы аналогично.
Вот мануал по моделям в Eloquent - ты читал? https://laravel.com/docs/5.4/eloquent#introduction
Если ты не знаком с Active Record то опять же, прочти сначала теорию прежде чем писать код: https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md
У тебя вообще код странный и такое ощущение что ты сам толком не понимаешь что пишешь.
В Eloquent объект Post представляет собой один пост, а для работы с таблицей постов в целом используются статические методы. Найти пост - статический метод. Изменить заголовок поста, проверить пост - обычный.
> return $this::where
Так не пишут. для вызова статических методов используют self::
Ну вот давай посмотрим на этот метод поиска поста по id:
> public function getPost($id)
Это не статический метод. Чтобы его вызвать, нам надо иметь объект класса Post, который соответствует одному посту в БД. То есть чтобы вызвать getPost (и найти пост в БД), мы должны сначала загрузить из БД объект поста. Ну бред же, как ни смотри.
Та же проблема с нестатическим методом forUser. Получается чтобы найти все посты пользователя, мы должны сначала загрузить какой-нибудь другой пост. Ну и вообще, этот метод наверно логичнее бы смотрелся в классе User. $user->findPosts(...)
> public static function getPageCount(User $user)
Неправильное название функции, она считает не число страниц, а число постов. Опять же, возможно ее логичнее в класс юзера поместить. Я не знаю, как в ларавел принято это делать.
> public function setPost($request, $post)
Почему у тебя модель работает с запросом? Это задача контроллера.
> public function countPages($request, $posts_on_page, $this_page)
Эта функция вообще непонятно, что делает в этом классе. Вот смотри, простой пример: допустим ты захочешь сделать пагинацию для еще каких-то сущностей, тебе придется скопировать в тот класс весь этот код. Очевидно, что его надо вынести в отдельный универсальный класс, а не копировать в каждую модель.
Далее, про класс Attitude. Во-первых, у него неправильное название, не Attitude, а Relation. Во-вторых, Relation тоже неправильное название, так как не говорит, связь чего с чем представляет это класс, правильно PostToTag или PostTagRelation, как-то так.
Но нужно ли писать этот класс? В документации по Eloquent написано что есть поддержка отношений многие-ко-многим: https://laravel.com/docs/5.4/eloquent-relationships#many-to-many
В общем, впечатление пока плачевное. Пока ты своим кодом показываешь что ты даже не пытался разобраться в фреймворке, который используешь, на каких принципах он построен. Ты просто пишешь код по аналогии с где-то увиденным (в видеоуроке?) не читая документацию и не понимая, что он значит. Ну и статические методы с обычными путаешь. Я бы такого кандидата отправил домой читать документацию.
Вот там был выше анон, который написал глупый комментарий вроде "зачем тратить время на написание задачи про студентов с нуля, бери фреймворк". Вот когда сразу берут фреймворк, получается такой результат.
Это кривой код, он толком сам не понимает что представляет собой объект Post и что надо передавать в контроллер. Просто где-то что-то похожее видел и бездумно написал по аналогии.
>>946284
Ты бы посмотрел, как в этом фреймворке принято делать, и делал бы аналогично.
Вот мануал по моделям в Eloquent - ты читал? https://laravel.com/docs/5.4/eloquent#introduction
Если ты не знаком с Active Record то опять же, прочти сначала теорию прежде чем писать код: https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md
У тебя вообще код странный и такое ощущение что ты сам толком не понимаешь что пишешь.
В Eloquent объект Post представляет собой один пост, а для работы с таблицей постов в целом используются статические методы. Найти пост - статический метод. Изменить заголовок поста, проверить пост - обычный.
> return $this::where
Так не пишут. для вызова статических методов используют self::
Ну вот давай посмотрим на этот метод поиска поста по id:
> public function getPost($id)
Это не статический метод. Чтобы его вызвать, нам надо иметь объект класса Post, который соответствует одному посту в БД. То есть чтобы вызвать getPost (и найти пост в БД), мы должны сначала загрузить из БД объект поста. Ну бред же, как ни смотри.
Та же проблема с нестатическим методом forUser. Получается чтобы найти все посты пользователя, мы должны сначала загрузить какой-нибудь другой пост. Ну и вообще, этот метод наверно логичнее бы смотрелся в классе User. $user->findPosts(...)
> public static function getPageCount(User $user)
Неправильное название функции, она считает не число страниц, а число постов. Опять же, возможно ее логичнее в класс юзера поместить. Я не знаю, как в ларавел принято это делать.
> public function setPost($request, $post)
Почему у тебя модель работает с запросом? Это задача контроллера.
> public function countPages($request, $posts_on_page, $this_page)
Эта функция вообще непонятно, что делает в этом классе. Вот смотри, простой пример: допустим ты захочешь сделать пагинацию для еще каких-то сущностей, тебе придется скопировать в тот класс весь этот код. Очевидно, что его надо вынести в отдельный универсальный класс, а не копировать в каждую модель.
Далее, про класс Attitude. Во-первых, у него неправильное название, не Attitude, а Relation. Во-вторых, Relation тоже неправильное название, так как не говорит, связь чего с чем представляет это класс, правильно PostToTag или PostTagRelation, как-то так.
Но нужно ли писать этот класс? В документации по Eloquent написано что есть поддержка отношений многие-ко-многим: https://laravel.com/docs/5.4/eloquent-relationships#many-to-many
В общем, впечатление пока плачевное. Пока ты своим кодом показываешь что ты даже не пытался разобраться в фреймворке, который используешь, на каких принципах он построен. Ты просто пишешь код по аналогии с где-то увиденным (в видеоуроке?) не читая документацию и не понимая, что он значит. Ну и статические методы с обычными путаешь. Я бы такого кандидата отправил домой читать документацию.
Вот там был выше анон, который написал глупый комментарий вроде "зачем тратить время на написание задачи про студентов с нуля, бери фреймворк". Вот когда сразу берут фреймворк, получается такой результат.
Потому, что для проверки уникальности email надо обращение к БД (через объект StudentDataGateway). В модели такого объекта нет. Также может потребоваться обращение к каким-то другим сервисам. Поэтому валидатор логично сделать внешним по отношению к модели сервисом.
Я не ОП, но вот основные, на мой взгляд, проблемы:
Вызывает вопросы сама архитектура приложения, код очень плохо разделен, у тебя в одном файле смешана верстка, SQL запросы, валидация и сама логика приложения. Ты видимо не совсем понимаешь как должен выглядеть нормальный MVC проект, попробуй поискать примеров и перечитать уроки ОПа.
По стилю кода тоже возникли вопросы, у тебя имена методов и переменных написаны снейк кейсом, код оформлен не по стандартам, почитай второй пост в треде, у нас есть стандарты PSR-1 и PSR-2.
Обработка ошибок сделана неправильно, ты поставил PDO в режим исключений, но потом при запросе ты все равно почему-то делаешь проверку
https://github.com/grigoryMovchan/auth/blob/master/php/module.php#L18 Если у тебя PDO стоит в режиме исключений, этого делать не нужно, при любой ошибке БД PDO выбросит исключение, которое ты потом сможешь обработать как хочешь.
https://github.com/grigoryMovchan/auth/blob/master/php/mysql.php#L21 И тут сразу же бросается в глаза неправильная работа с исключениями. Почитай урок ОПа https://github.com/codedokode/pasta/blob/master/php/exceptions.md
>TODO: вынести валидацию формы на фронт с помощью AJAX
Это сделано очень неудачно. Мало того что у тебя в коде две разные валидации (одна обычная, другая для аякса), так ты еще хочешь оставить только аякс, чтобы у пользователей без JS совсем ничего не работало. На мой взгляд это неправильный подход. Я бы сделал отдельный класс или метод для валидации данных которые пришли, этот метод возвращал бы массив с ошибками типа ['имяПоля' => 'текст ошибки'] (или пустой массив если все хорошо). Затем использовать один и тот же метод при аяксе и при обычной отправке формы сабмитом. В случае если запрос пришел аяксом, отдаешь JSON с массивом ошибок, если при обычном сабмите формы - показываешь пользователю ту же форму с ошибками.
https://github.com/grigoryMovchan/auth/blob/master/php/module.php#L179 Не совсем понятно зачем ты используешь сессии и куки одновременно. Ты же понимаешь как работают сессии и в чем их отличие от кук?
https://github.com/grigoryMovchan/auth/blob/master/php/module.php#L120 Не работает с кириллицей, почта вида ива~"sнANUSпykiримерPUNCTUMрY*#ф валидацию не пройдет.
Это только что бросилось в глаза при беглом просмотре, основная проблема в том что код плохо разделен и читать его трудновато.
Я не ОП, но вот основные, на мой взгляд, проблемы:
Вызывает вопросы сама архитектура приложения, код очень плохо разделен, у тебя в одном файле смешана верстка, SQL запросы, валидация и сама логика приложения. Ты видимо не совсем понимаешь как должен выглядеть нормальный MVC проект, попробуй поискать примеров и перечитать уроки ОПа.
По стилю кода тоже возникли вопросы, у тебя имена методов и переменных написаны снейк кейсом, код оформлен не по стандартам, почитай второй пост в треде, у нас есть стандарты PSR-1 и PSR-2.
Обработка ошибок сделана неправильно, ты поставил PDO в режим исключений, но потом при запросе ты все равно почему-то делаешь проверку
https://github.com/grigoryMovchan/auth/blob/master/php/module.php#L18 Если у тебя PDO стоит в режиме исключений, этого делать не нужно, при любой ошибке БД PDO выбросит исключение, которое ты потом сможешь обработать как хочешь.
https://github.com/grigoryMovchan/auth/blob/master/php/mysql.php#L21 И тут сразу же бросается в глаза неправильная работа с исключениями. Почитай урок ОПа https://github.com/codedokode/pasta/blob/master/php/exceptions.md
>TODO: вынести валидацию формы на фронт с помощью AJAX
Это сделано очень неудачно. Мало того что у тебя в коде две разные валидации (одна обычная, другая для аякса), так ты еще хочешь оставить только аякс, чтобы у пользователей без JS совсем ничего не работало. На мой взгляд это неправильный подход. Я бы сделал отдельный класс или метод для валидации данных которые пришли, этот метод возвращал бы массив с ошибками типа ['имяПоля' => 'текст ошибки'] (или пустой массив если все хорошо). Затем использовать один и тот же метод при аяксе и при обычной отправке формы сабмитом. В случае если запрос пришел аяксом, отдаешь JSON с массивом ошибок, если при обычном сабмите формы - показываешь пользователю ту же форму с ошибками.
https://github.com/grigoryMovchan/auth/blob/master/php/module.php#L179 Не совсем понятно зачем ты используешь сессии и куки одновременно. Ты же понимаешь как работают сессии и в чем их отличие от кук?
https://github.com/grigoryMovchan/auth/blob/master/php/module.php#L120 Не работает с кириллицей, почта вида ива~"sнANUSпykiримерPUNCTUMрY*#ф валидацию не пройдет.
Это только что бросилось в глаза при беглом просмотре, основная проблема в том что код плохо разделен и читать его трудновато.
> Attitude::getTags($post->id, 'name'))
Почему не $post->getTags()->pluck('name')->all() ? Изучи какие есть методы у коллекций: https://laravel.com/docs/5.4/collections#method-pluck
Но правильнее передавать в вью не склеенную строку, а коллекцию тегов, а оно пусть делает с ней что хочет.
Дальше, редактирование у тебя сделано в виде 2 методов:
> public function edit(Request $request, Post $post)
> public function save(Request $request, Post $post)
При таком подходе, как ты сделаешь обработку ошибок? Вот пользователь заполнил форму неправильно, мы должны показать ему эту форму и сообщение об ошибке. Но в твоем варианте с редиректами введенные в форму данные просто потеряются. Тебе надо почитать про алгоритм обработки форм: https://github.com/codedokode/pasta/blob/master/forms.md
У тебя даже валидации нет. У тебя можно отправить форму с пустыми полями.
Поиск отсутствующих/новых тегов надо было делать в модели. ты похоже не понимаешь идею MVC и кто за что отвечает. С твоим кодом, если мы захотим где-то в другом месте поменять теги поста, нам придется копипастить код из контроллера так как повторно его вызывать из другого места нельзя.
Вообще, тебе надо сделать задачу про студентов и почитать комментарии к ней (в ОП посте). Ты взялся за фреймворк, не изучив много более базовых вещей вроде валидации или работы с формами.
Насчет валидации, в Юи можно прописывать правила валидации в модели и там один и тот же код обеспечивает валидацию и обычного POST-запроса и аякс-валидацию для отдельных полей. Я подозреваю, в Laravel тоже есть какое-то готовое решение для работы с формами и валидацией и надо использовать его.
Первый раз вижу чтобы фреймворк из коробки не работал по гайду, это я об Slim v3, всегда 404 ошибка, /hello/lorem не отрабатывает вообще, об htaccess вообще речи не идет в их официальном installation guide.
Полазив в инете единственное, что понял - популярность этого фреймворка довольно низкая, так как нет абсолютно ничего, ни рабочего примера нигде, ни гайдов нормальных, комьюнити нет совсем. Зачем на нем писать fileshare ?
Слим это микрофреймворк, конечно у него будет ниже популярность чем у серьезных вещей вроде Symfony или Yii.
>всегда 404 ошибка, /hello/lorem не отрабатывает вообще
Это потому что у тебя на веб-сервере не настроен URL Rewrite.
>об htaccess вообще речи не идет в их официальном installation guide
Плохо искал.
https://www.slimframework.com/docs/start/web-servers.html
https://github.com/slimphp/Slim
и
https://www.slimframework.com/docs/start/installation.html
Попробуй фалкон, еще захочешь.
https://github.com/slimphp/Slim#usage
Вот же есть раздел про использование, там пример с встроенным в PHP веб-сервером (на котором URL Rewrite работает из коробки), а про другие веб сервера написано
>For more information on how to configure your web server, see the Documentation.
С ссылкой на нужный тебе раздел в документации.
Спасибо. А как вообще делать валидацию? Тупо регулярками, или есть какие-то хитрости там, средства php для этого?
Почему у тебя Гахара на пике? Это намёк, что мы (программисты на PHP) все крабы?
приятно, что пхп не тонет и не умирает как язык.
За год я овладел пхп, нодой, питоном и сейчас учу руби, но пыха всегда будет в моем сердце как что-то простое, понятное, но от этого ничуть не менее эффективное.
Спасибо, очень отрезвляет, много ценных замечаний. Понял, что работу мне еще рано искать, буду дальше учиться.
>Пока ты своим кодом показываешь что ты даже не пытался разобраться в фреймворке, который используешь, на каких принципах он построен.
Вот тут я не верю что есть человек который может сесть и не разбираясь что-то написать на нем. Там же свой уровень абстракции. Я месяц делал эту поделку, до нее сделал похожую на чистом MVC https://github.com/grigoryMovchan/blog_mvc Старался внимательно читать официальную документацию, видео уроки обхожу стороной. Да, месяца мало, но вот чтоб говорить что я не пытался разобраться и не читал документацию, тут у меня бомбит.
>>946312
Спасибо. Да, это не MVC, скорее просто поделка в процедурном стиле с использованием классов, чтобы потом использовать в другой поделке, которая уже будет в MVC. Поэтому сори что запутал. Про PDO ценные замечания.
>Это сделано очень неудачно. Мало того что у тебя в коде две разные валидации (одна обычная, другая для аякса), так ты еще хочешь оставить только аякс, чтобы у пользователей без JS совсем ничего не работало. Стандарты PSR-1 и PSR-2 почитаю.
Тут я косноязычно выразился. Я хотел не вместо, а дополнительно ее сделать. Про один класс для валидации ценное замечание.
Куки использую чтобы снова не проходить аутентификацию, когда время сессии выйдет, а вот зачем тогда сессии использовать я не знаю, часть кода взял из урока. Возможно, и правда не нужны.
>>946313
Спасибо. Почитаю про коллекции. Валидация там есть https://github.com/grigoryMovchan/zuihitsu/blob/master/app/Http/Controllers/PostController.php#L113-L116 но текст и правда не сохраняется, были планы этим заняться.
>Поиск отсутствующих/новых тегов надо было делать в модели. ты похоже не понимаешь идею MVC и кто за что отвечает. С твоим кодом, если мы захотим где-то в другом месте поменять теги поста, нам придется копипастить код из контроллера так как повторно его вызывать из другого места нельзя.
Тут не понял, ведь все методы для работы с тегами в моделях Attitude и Tag.
> Ты взялся за фреймворк, не изучив много более базовых вещей вроде валидации или работы с формами.
Опять я ничего не знаю. Не представляю чтобы кто-то без этих базовых представлений сходу мог написать что-то на ларавел без опыта в других фреймворках.
P.S. Еще раз спасибо, господа. Все замечания взял на заметку. Впереди предстоит объемная работа. Исправлять эту поделку на ларавел я уже не буду, но в будущем, постараюсь сделать лучше.
Спасибо, очень отрезвляет, много ценных замечаний. Понял, что работу мне еще рано искать, буду дальше учиться.
>Пока ты своим кодом показываешь что ты даже не пытался разобраться в фреймворке, который используешь, на каких принципах он построен.
Вот тут я не верю что есть человек который может сесть и не разбираясь что-то написать на нем. Там же свой уровень абстракции. Я месяц делал эту поделку, до нее сделал похожую на чистом MVC https://github.com/grigoryMovchan/blog_mvc Старался внимательно читать официальную документацию, видео уроки обхожу стороной. Да, месяца мало, но вот чтоб говорить что я не пытался разобраться и не читал документацию, тут у меня бомбит.
>>946312
Спасибо. Да, это не MVC, скорее просто поделка в процедурном стиле с использованием классов, чтобы потом использовать в другой поделке, которая уже будет в MVC. Поэтому сори что запутал. Про PDO ценные замечания.
>Это сделано очень неудачно. Мало того что у тебя в коде две разные валидации (одна обычная, другая для аякса), так ты еще хочешь оставить только аякс, чтобы у пользователей без JS совсем ничего не работало. Стандарты PSR-1 и PSR-2 почитаю.
Тут я косноязычно выразился. Я хотел не вместо, а дополнительно ее сделать. Про один класс для валидации ценное замечание.
Куки использую чтобы снова не проходить аутентификацию, когда время сессии выйдет, а вот зачем тогда сессии использовать я не знаю, часть кода взял из урока. Возможно, и правда не нужны.
>>946313
Спасибо. Почитаю про коллекции. Валидация там есть https://github.com/grigoryMovchan/zuihitsu/blob/master/app/Http/Controllers/PostController.php#L113-L116 но текст и правда не сохраняется, были планы этим заняться.
>Поиск отсутствующих/новых тегов надо было делать в модели. ты похоже не понимаешь идею MVC и кто за что отвечает. С твоим кодом, если мы захотим где-то в другом месте поменять теги поста, нам придется копипастить код из контроллера так как повторно его вызывать из другого места нельзя.
Тут не понял, ведь все методы для работы с тегами в моделях Attitude и Tag.
> Ты взялся за фреймворк, не изучив много более базовых вещей вроде валидации или работы с формами.
Опять я ничего не знаю. Не представляю чтобы кто-то без этих базовых представлений сходу мог написать что-то на ларавел без опыта в других фреймворках.
P.S. Еще раз спасибо, господа. Все замечания взял на заметку. Впереди предстоит объемная работа. Исправлять эту поделку на ларавел я уже не буду, но в будущем, постараюсь сделать лучше.
>Вот тут я не верю что есть человек который может сесть и не разбираясь что-то написать на нем. Там же свой уровень абстракции. Я месяц делал эту поделку,
пиздец, я уже и забыл, как сложно первое время вкатываться. код плох на уровне смешения хтмл и кода. посмешила папочка с названием пхп.
Несколько минут думал как ее назвать, просто хотел хоть как-то разделить. Как обычно называют?
Обычно называют app или src, если у тебя там скрипты твоего приложения.
Хотя, я догадываюсь, что такой папочки быть не должно, когда есть божеcтвенный MVC
В том смысле что файлы сортируются не по расширению, а по их функции
в роутах:
'admin/blabla'=> 'admin/blabla',
'admin'=> 'admin/index'
это проблема роутера или htaccess?
Предлагаю топить тред сразу сажей на дно. Заметили, что активность долбоёбов критически возрастает в начале каждого треда, а далее идет на спад, после бамплимита? Если бы у нас был доступ к модератору, то можно прикрепить для новичков тред в шапку и обновлять ссылку с каждым перекатом.
А то сидит завсегдатай такой, ковыряет в носу, рефрешит - "о бля! свеженький анимешный пэхэпэ тред, зайду ка посру..."
сам разобрался.
когда проверяю на совпадения урл с роутами нужно проверть как ~^путь$~, а я забыл $
Читай спокойно. Насколько я знаю список выпиленного там не очень большой и проблем особых не должно быть.
Если ты не заметил, то /pr/ это одна из самых токсичных тематических досок на всей борде, такое поведение вполне нормально.
я для своего сделал через запись в сессию масива с товарами(айди->кол-во). Ну и можно в бд еще писать для залогиненых юзеров, тип чтоб не проебать.
А ты попробуй усвоить столько инфы и при этом не стать токсичным тщеславным снобом. Это мишен импосибл.
мб лучше генерить уникальный код, писать его в куки и в бд, в бд хранить товары
сессии быстро умирают
Не подкинешь инфы, если не тяжело? В PHP я полный 0, JS хоть как-то понимаю и то начал относительно недавно изучать его. Если всё это дело лучше написать будет на PHP, то буду значит разбираться. Спасибо за ответ.
git clone https://github.com/PrestaShop/PrestaShop.git
Этот достаточно большой и весь код соответствует PSRам, юзает инверсию зависимостей и разные современные практики.
Php, в нем ООП стандартный и нет callback hellа. В JS без опыта в нормальном ООП языке ты увязнешь и не будет понимания в голове, что и как работает, не будет понимания паттернов, наследования, разделения ответственности. JS лучше учи после, будут отличия от нормальных языков понятны.
Но она вроде относительно популярна и даже продается.
Ты бы мог обратить проблему ("тормозит") себе на пользу - учиться на примере этой CMS оптимизации и профайлингу, выяснить источник тормозов, понять, это принципиально неустранимая вещь или просто где-то кеширование не настроено.
> Тут не исправлена проблема модификации переданной коллекции:
Там было исправлено, метод removeProduct возвращал новую коллекцию, потому CountDiscount исходную коллекцию не модифицировал. Мне кажется есть смысл сделать её неизменяемой, а не надеяться, что пользователь вспомнит вызвать clone (вот я как раз забыл).
Сейчас ошибки нет: https://bitbucket.org/learning_acc/discounts/src/be3e1a13fda16af5b5397c94428c4d9b25632d29/combination_discount_test.php?at=master&fileviewer=file-view-default
ProductCollection на основе SplObjectStorage: https://bitbucket.org/learning_acc/discounts/src/be3e1a13fda16af5b5397c94428c4d9b25632d29/src/Collection/ProductCollection.php?at=master&fileviewer=file-view-default
> в языках вроде Ява эта проверка делается одним тайп-хинтом вроде Map<int, DepreciationInterface>.
Ещё классы DiscountCollection и DiscountResult служат только ради тайп-хинтов.
> if( Math.abs(a-b) < 0.00001) // wrong - don't do this
Посмотрел, PHPUnit как раз так и сравнивает, если исключить проверки is_nan и is_infinite: https://github.com/sebastianbergmann/comparator/blob/master/src/NumericComparator.php#L46
И тут так советуют: https://secure.php.net/manual/en/language.types.float.php#language.types.float.comparison
Настораживает, что функция автора статьи при epsilon 0.00001 считает, что 1000000 и 1000001 равны: http://floating-point-gui.de/errors/NearlyEqualsTest.java
Строки 46-47
Ну и конечно же, задачку было решить очень полезно, спасибо за объяснения и исправления!
Трейт это инструмент для реализации множественного наследования. Чтобы ты мог два класса унаследовать от разных классов, но при этом в обеих классах реюзать один и тот же код.
В PHP есть интерфейсы: https://github.com/codedokode/pasta/blob/master/php/interfaces.md
Интерфейсы и трейты - абсолютно разные вещи. Первое - это контракт, не содержащий никакой реализации. Трейты (миксины) удобны когда нужно добавить классу какое-то поведение. Например, поведение объекта, который может генерировать события и оповещать слушателей: https://learn.javascript.ru/mixins
ИМХО, по возможности стоит предпочитать внедрение зависимости трейтам, так как зависимости можно подменить, а вот трейты вбиты в класс намертво.
Скачал книгу по PHP 7 Дмитрия Котерова (2016 год).
И в учебнике выводят на этот сайт http://windows.php.net/download
Это так называемая "установка" Php определенной версии скачал седьмую. Что она дает вообще? и нужна ли она мне на этапе изучения? так как там вообще не особо об этом расписывают
Как редактор скачал sublime text 3. Этого достаточно или еще что-то нужно?
Посаны, а в фильтрах для uBlock пхп или нет?
Мне, короче, надо знать как в них поставить вместо символа переменнную, чтобы там был диапазон значений. То есть вот есть у меня 10 строк, которые отличаются только одной циферкой - хочу вместо 10 сделать одну. Звёздочка почему-то не работает. Может её в какие-нибудь сраные скобки надо заключить или типа того? Причём в строках, когда меняется целое... слово (наверное, хуй знает как это называется) она работает, например -
||yastatic.net/morda-logo/i/cards/8march2017/enter/.png$image
А когда надо поменять только его часть
yandex.ru##.b-cards__enter_bg_*.b-cards__enter_8march2017.b-cards__enter
уже нет.
задумался об изучении фреймворков и смене рабочего места. На русском рынке сейчас самый популярный - симфони? просто мне больше нравится йи.
Блять, ебучая макаба, посчитала звёздочки элементами разметки.
Первая строка должна выглядеть так - ||yastatic.net/morda-logo/i/cards/8march2017/enter/*.png$image
На русском как раз самый популярный ЙИ. Если смотреть глобально, то наверное топ 1 по популярности - ларавел. Симфони вряд-ли где-то в топе, слишком навороченный фреймворк.
я вот эти туториалы читаю (платные там только видосы, текст из них продублирован внизу)
"Столько инфы" усваивают только бородачи-профессор. А на уровень тутошних знатоков можно выйти за пару лет. Просто у нас кодеры получают сравнительно дохуя, вот они себя илитой и считают. Смотрел на западных кодеров - там разница в зарплатах не такая значительная, от того эти ребята в среднем менее упоротые, и комунити там гораздо более добродушное, серьезно. Просто если почитать наши ресурсы типа хабры и доу - складывается впечатление, будто погромисты все поголовно озлобленные, чсвшные мудаки, еще и делают все возможное что бы затопить новичков потому, т.к. боятся что наплодится конкурентов и начнется демпинг зарплат, а кроме как кодить они нихуя не умеют. Даже тот же стековерфлоу как ресурс для неофитов гораздо более дружелюбный, чем бОльшая часть ру-комунити. А проблема этого ИТТ треда скорее в мочерации, точнее ее отсутствие.
>>946764
>Скачал книгу по PHP 7 Дмитрия Котерова (2016 год).
Выбрось это, лол. Котеров и Костарев это просто легенды говнокодинга. Лучше по учебнику ОПа занимайся.
Нужно ли сразу вкатываться на фреймворки? Есть ли вообще какая-то работа на чистом пхп?
Может быть тут кто то шарит и может рассказать. Сложно ли выучить php для того, чтобы начать фрилансить и сложно ли это?
Что значит чистый пхп? Фреймворки не на чистом пхп написаны? Фишка в том, что для того, чтобы решить более-менее определенную задачу, то тебе надо либо использовать либо фреймворк, либо cms, либо писать свой велосипед, который по сути будет таким же фреймворком. Естественно, пилить свой велосипед, когда все уже давно сделано до тебя очень глупо. Поэтому использовать фреймворк это умное решение - вопрос лишь только в том какой тебе подходит для твоей задачи.
Если под чистым пхп ты подразумеваешь работу вообще без какого-либо паттерна, архитектуры и прочего, то максимум для чего такой "чистый пхп" подходит - это написать файлик-скриптик для генерации капчи или гостевой книги. В 2017 это нафиг никому не нужно.
>Нужно ли сразу вкатываться на фреймворки?
Лол. Это просто такой платиновый вопрос, что ОПу давно пора его жирный курсивом в ОП-посте добавить. Даже в этом треде уже было это. Поясню по хардкору - нив коем случае блять. Да, на чистом пхп чаще всего не пишут. Однако если ты хочешь именно стать разработчиком, тебе надо знать и уметь применять все принципы, которые лежат в основе пхп-фреймворков. А именно, помимо синтаксиса пхп тебе надо хорошо, именно что хорошо понимать ООП - зачем оно надо, основные фишки и плюсы которые оно дает. А так же MVC, ORM, и PSR желательно - а то увидишь, допустим, в документации фреймворка что такой-то класс реализует интерфейс из PSR-7, и начнется тупняк у тебя, пока не полезешь в гугл и не узнаешь что за PSR-7 такой. Вот когда хорошо разберешься в этом, напигешь пару MVC-бложиков, тогда уже можно и за фреймворки браться.
шикарно
Так что все-таки дает этот сайт http://windows.php.net/download
Вроде как на пхп.нет что-то важное должно быть
Я распаковал архивы и ничего полезного там не вижу как новичок
На офсайт иди, там тебя научат.
какая у тебя задача-то? если установить локальный сервер на винде, то есть либо openserver, либо xampp.com, либо если хочется установить самому, есть урок от ОПа в шапке.
учебник Котерова определенно надо сжечь, намного лучше учиться хотя бы по тем же урокам в шапке.
>учебник Котерова определенно надо сжечь, намного лучше учиться хотя бы по тем же урокам в шапке.
Двачую. Там в предисловии указано на то, что учебник не для самых новичков, а для тех кто хотя бы поверхностно знаком с алгоритмизацией. Хотя я паскаль изучал давно и основы помню, но ничего не понимаю по его учебнику
А Колисиченко "Php и MySQL"?
я так понимаю, require_once просто включает содержание файла шаблона, как будто он там и был, и следовательно у шаблона должен быть доступ к импортированным пространствам дочернего контроллера и все должно быть ОК. Где я не прав?
У меня кстати похожий вопрос. Есть у меня класс View(), который зависимость для контроллера. Однако там только метод display который просто передает параметры и инклюдит шаблон. Что бы еще такого в эту вьюху добавить? Что обычно в фреймворках там есть? Просто не хочется пока фреймворки вообще трогать.
А модули как подключать, как подключить фреймворки, как запустить чтобы это всё работало на внешнем айпи или локалохосте?
как можно работать на чистом (!) пхп еще и год. откуда вы такие беретесь? тут с тремя яп и 10 фреймворками хуй устроишься, а они ни чистом пхп работают. ахуеть
Странно, в моем кругу общения, почему то, симфони. Спасибо.
>>946774
лучше один хорошо, чем десять плохо.
>>946982
Просто сделал на фл.сру заказ лендинг для небольшой компании, потом разговорились, подружились, вышло, что они из города, в который я поступил учиться, и я с ними остался.
За год сделал какое-то подобие фреймворка своего, за теми отличиями, что у меня это хуево реализованная мешанина того, чтотя использую чаще всего. Короче, мне норм.
Ведь и без него будет работать
Отсюда https://github.com/codedokode/pasta/blob/master/arch/mvc.md
На больших фирмах как раз выкидывают эти твои фреймворки и пишут на чистом php. Фреймворк - зависимость от разрабов фреймворка и тормоза, большим фирмам не нравится. А вот мелким как раз.
За год нормальный фреймворк не написать? Ну ты герой. Учи ООП, паттерны и SOLID принципы, это максимум за пару месяцев делается.
вновь
по счастливой случайности я скроллил /pr и заметил твой пост. Ну, вообще в идеале, попробуй запилить виртуалбокс и в нём эмулировать Убунту. Самая хорошая для изучения линукса. Плюс, неплохо бы комбинировать с знаием Си. Хотя там и неплохая поддержка Питона есть. Вообще-то я не помню, что именно можно спокойно компилировать из терминала в Убунте. Но вот потом с помощью "help" изучай утилиты терминала. Поиграйся с файлами. Почитай пару гайдов по Bash. Ну и пиком будет установка стороннего приложения, например шиндосовского. Особенно с помощтю Wine.
install gentoo
Самое главное -никогда не юзай десктопный линупс. А учить его легко, учишь ls, cd и прочее по мере надобности.
Я так довольно хорошо освоился с линуксом, постоянно работая с серваками через ссх.
>никогда не юзай десктопный линупс
Это почему? Я с 2010 юзаю генту, все ок. Оче легко создать среду для погромирования, будь то пыха, руби, да что угодно. Кресты вообще по умолчанию встроены, благодаря особенностям генты.
мвц-мвц, я ж не совсем аутист. ну если только немножко
>>947113
так я летом заработал тогда, а на что тратить деньги долбоебу-домосиду? Купил книг и это. Игрулечки в печенках уже тогда засели, хавчик я тогда ограничивал, чтоб похудеть.
>>947122
А зачем? В смысле, нормальный фреймворк писать. Я сделал то, что помогло мне сократить время разработки без лишних танцев с бубном вокруг компа, чтоб было лишнее время на изучение английского языка. Теперь вот.
Ставишь эмулятор vmware или virtual box, накатываешь mint linux или другой популярный дистриб, проходишь всю инсталляцию. Потом гуглишь как ставить там php, apache, виртуальные хосты, все настраивать. Гуглишь руководство по основным командам bash. Запускаешь апачу с пыхой, делаешь так чтоб сервак из винды видно было по ip. SSH еще с FTP осваиваешь до линукса из винды, cron для запуска скриптов. Можно еще какой-нибудь Docker попробовать. В принципе все, больше тебе обычно ничего не требуются при типичной разработке. Усилий не так много, за пару недель легко осваивается.
>А зачем? В смысле, нормальный фреймворк писать.
Нормальный не значит, что там фич овердохуя, просто что нормально написан - все разделено на отвечающие за свои роли классы, везде зависимости через dependency injection, юзается наследование и соблаюдаются SOLID принципы. Зачем надо? Просто потом ты этот фреймворк уже понимать будешь и в любом новом проекте просто его заюзывать. А если нормально написан, то и код сразу везде чистый станет без проблем с расширением и поддержкой. Сейчас это тебе неочевидно, но время действительно экономится будет, особенно когда требования заказчика на ходу меняются. Если у тебя кривой плохо расширяемый фреймворк с говнокодом, то ты и дальше в нем будешь не пойми что городить, проблем будет только прибавляться с увеличением сложности проектов, а с ними и временных затрат на любые изменения.
Хочу быстро вкатится в погромирование, до этого писал хелло ворлды с циклами на крестах всего-лишь, и немного долбился в ассемблер с флагами там и регистрами.
Хочу на галерку, грести, хоть за копейки и погонщика за спиной, чтоб мотировал. Я в тот тред зашел?
В тот, шапку читай и вперед.
Учим для галер же, чтоб потом в них работать, так что тред все равно тот.
У Godaddy толи цены сменились, толи меркетинговый ход с ценами. Сегодня посмотрел выставленный счёт на оплату. И получилось овер 16к рублей. Это за продление 1 домена на 12 месяцев и эконом хостинг на линуксе. Учитывая что за весь прошлый год я заплатил тыщь 6, то тут прямо таки странная картина.
Если в треде есть кто может подсказать по вопросам буду рад.
Можно ли домен перенести на нового хостера и как это сделать?
Будут ли с этим проблемы?
Как поступать с оплатой? Тоесть сейчас я плачу за продление Godaddy и не парюсь, а дальше платить новому хостеру? Как платить если у меня ещё пол года осталось и я боюсь что после того как домен закончится, его перехватят сквоттеры?
Перенеси его в Ру-центр, оплатить можно в любом платёжном терминале (а тж. заранее положить на счёт X денег на N лет вперёд).
Спасибо!
Закрывай двач -> смотри нище вакансии -> учи что написано в вакансиях
Так ты при переносе днс-записи меняешь, лол.
Приглашаем на работу программиста.
Требования:
Опыт работы из 1С; РНР, MySQL, JS,HTML, CSS, Yii;
Базовые навыки системного администрирования;
Обязанности:
Написание с ноля интернет-магазинов;
Написание сайтов с ноля, внесенние изменений.
Админ.сети;
Настройка и контроль за работой ПК в офисах;
Условия Труда:
6-дневный рабочий день;
8:00−18:00.
Как найти работу?
Чота дохуя долгий рабдень. Плюс будешь как собачка-эникейщик бегать. У тебя только одна вакансия штоле?
Да все тоже самое. Може попробовать фриланс за еду и опыт? Но как-то совсем страшно, тем более я так понял там везде надо CMS-ки, а я ни одной не знаю.
>>947414
Меня больше порадает набор технологий. Я раньше думал, что пхп-разработчик кодит только пхп, а судя по всему еще и жс надо знать хорошо, и верстать клево.
приглашает кандидатов на должность ВЕБ — ПРОГРАММИСТ
Требования:
о/р от 3 лет;
желательно высшее техническое образование;
знание языков html, php, css;
умение работать с Mysql, Apache;
навыки работы с CMSWordpress, Joomla, OpenCart (создание сайтов, настройка);
кроссбраузерная, адаптивная верстка;
умение работать с графическими редакторами (Photoshop, CorelDRAW, Illustrator);
понимание и навыки в SEO и SMM продвижении сайта;
работас Google analytics, Google AdWords;
предоставление портфолио.
Преимуществом будет:
знаниеJava Script/JQuery/AJax, ASP.NET;
навыки копирайтинга;
опыт работы с облачными платформами (WIX, WEEBLYи др.);
опыт работы с торговыми площадками (prom.uaи др.);
работа с системой Moodle;
системное мышление, опыт работы с системами мониторинга и сбора данных;
умение пользоваться поисковыми системами для нахождения решений.
Обязанности:
Обновление дизайна, верстка отдельных страниц сайта.
Разработка графических элементов, баннеров.
Использование рекламных каналов. Продвижение сайта в поисковых системах. Сопровождение сайтов на платформе WordPress.
Техническая поддержка и администрирование сайтов.
Разработка дополнительных модулей для сайтов.
Обеспечение интеграции сайтов с внешними системами (CRM, 1С, мобильные приложения).
Выполнение задач по модернизации и развитию сайтов своими силами и с помощью подрядчика.
Усовершенствовать и поддерживать ecommerce.
Просьба ВНИМАТЕЛЬНО читать требованияи присылать резюме только при соответствии ВАШИХ практических навыков указанным требованиям минимум на 80%.
конт.тел.: 067−776−38−86
приглашает кандидатов на должность ВЕБ — ПРОГРАММИСТ
Требования:
о/р от 3 лет;
желательно высшее техническое образование;
знание языков html, php, css;
умение работать с Mysql, Apache;
навыки работы с CMSWordpress, Joomla, OpenCart (создание сайтов, настройка);
кроссбраузерная, адаптивная верстка;
умение работать с графическими редакторами (Photoshop, CorelDRAW, Illustrator);
понимание и навыки в SEO и SMM продвижении сайта;
работас Google analytics, Google AdWords;
предоставление портфолио.
Преимуществом будет:
знаниеJava Script/JQuery/AJax, ASP.NET;
навыки копирайтинга;
опыт работы с облачными платформами (WIX, WEEBLYи др.);
опыт работы с торговыми площадками (prom.uaи др.);
работа с системой Moodle;
системное мышление, опыт работы с системами мониторинга и сбора данных;
умение пользоваться поисковыми системами для нахождения решений.
Обязанности:
Обновление дизайна, верстка отдельных страниц сайта.
Разработка графических элементов, баннеров.
Использование рекламных каналов. Продвижение сайта в поисковых системах. Сопровождение сайтов на платформе WordPress.
Техническая поддержка и администрирование сайтов.
Разработка дополнительных модулей для сайтов.
Обеспечение интеграции сайтов с внешними системами (CRM, 1С, мобильные приложения).
Выполнение задач по модернизации и развитию сайтов своими силами и с помощью подрядчика.
Усовершенствовать и поддерживать ecommerce.
Просьба ВНИМАТЕЛЬНО читать требованияи присылать резюме только при соответствии ВАШИХ практических навыков указанным требованиям минимум на 80%.
конт.тел.: 067−776−38−86
Верстать вообще не сложно. Вот как раз изучи вёрстку, хтмл сначала, может и понравится. Вкатиться во фреймворки и кмс тоже не сложно. Главное не лезть в жс с вебпаками. И обычно только в мухосрансках такие охуевшие, где нужно быть фулстеком. На фрилансе тебя никто не будет просить верстать или делать жс плюхи, для этого есть фронтотяночки
Вангую что эти дауны 90% технологий вообще использовать на практике не будут, а просто так упомянули их.
Это охуевшие мрази, которые не шарят и хотят всё и сразу. Можешь прийти к ним на собеседование и прямо сказать - вы охуевшие мрази, идите нахуй.
Забыли хаскель со скалой упомянуть, лол.
Короче, твой путь - учишь пхп, учишь хтмл, учишь парочку фреймворков -> пишешь пару своих сайтов с пользователями, борду, чатик, магазин, набиваешь первичный опыт -> идешь на фриланс, ищешь простые типовые задачи, типа сделать несложный магаз на всяких уиихах и ларавелях -> получаешь свою копеечку и радуешься жизни. Конечно, сразу это не придет, придется хотя бы полгода хорошо все изучить, и не лениться, тратить на это все не меньше пяти часов в день, а не полчасика на туториалы и дальше в дотку. Так не пойдет. Нужно работать. А когда ты дома и тебя никто не гонит, это совсем не сложно. Все получится, няша.
Да я как-то так и думал. Щас где-то на середине студентов. Алсо поясните еще такую фишку - часто говорят, что не стоит начинать карьеру с CMSок, типа это тупиковый путь и все такое, надо искать работу на фреймворках. В чем суть? Неужели все цмс-ки дерьмо такое?
Кмски это не программирование, это говно уровня админов на винде в шаражкиных конторах, ты этим заниматься не должен.
В пидорахии вообще популярно делать сайты без программирования - берешь вордпресс, ебашишь плагины, натягиваешь на кмс.
Я смотрел вакансии с опытом >3 лет, там много работы на ЦМСках. Правда там чаще не вордпресс, а всякие мадженты. И я так понял, там они скорее занимаются разработкой плагинов.
Моей первой работой была работа на цмске. Не магента, а блядов вебасист шопскрипт, чтоб он в аду горел сука. Да, плагины хуярил.
>>914237
Этот пост почему-то удалили, поэтому ещё раз запощу.
https://github.com/kubk/students
> PageObject
Пока гуглил, заметил, что многие понимают PageObject по-разному: кто-то предлагает просто выносить селекторы в объекты со статическими свойствами, кто-то считает, что PageObject должен предоставлять интерфейс страницы, пользователи которого не знают ничего о селекторах и взаимном расположении DOM-элементов. Мне второй вариант понравился больше.
> поиск по фамилии зависит от регистра букв
Этого бы не произошло, если был бы написан тест: https://github.com/kubk/students/blob/master/tests/StudentGatewayTest.php
Насчёт теста функции экранирования:
> - передаем строку с тегом и проверяем, что на выходе тега нет
> - вызываем html_entity_decode на результате и проверяем, что получилась исходная строка
> - аналогично можно проверить кавычки, а также отдельные угловые скобки, что их нет в результирующей строке
Если правильно понимаю, то второй пункт работает, только если искомая строка не будет найдена. В противном случае результат будет содержать тег b или mark, и исходную строку от такого результата не получим. В общем, сам тест: https://github.com/kubk/students/blob/master/tests/StudentTwigExtensionTest.php#L71
> тут https://github.com/kubk/students/blob/master/src/LinkGenerator.php#L54 HTML в коде, и ссылка не экранируется как положено.
> Лучше было бы использовать для HTML кода макрос твига, а генерировать в PHP только сам URL.
Теперь html в php нет https://github.com/kubk/students/blob/master/src/LinkGenerator.php#L47
, но как мне кажется, тут https://github.com/kubk/students/blob/master/templates/student-list.twig#L14+L15
какой-то низкоуровневый код в шаблоне. Ну и ссылка генерируется только в одном месте, нужен ли макрос, который будет использоваться лишь один раз?
> Насчет авторизации по паролю - лучше в куке (и в БД) хранить не пароль, а его соленый хеш. Чуть безопасней, а так у тебя пароль в открытом виде на каждый запрос шлется. И в базе лежит. Украли базу/куки - и можно идти проверять, подойдет ли этот пароль к почте, к соцсетям итд.
В базе был только хеш, а насчёт кук - да, сглупил.
> я бы назвал класс не UniqueEmail, а StudentEmailUnique, так как это ограничение работает только для одного класса - студента.
Насчёт универсального решения понятно, но вряд ли оно мне где-либо ещё пригодится, раз доктрина в симфони почти что стандарт и там уже есть UniqueEntity.
Впредь постараюсь быть внимательнее и лучше тестировать то, что отдаю на проверку.
>>914237
Этот пост почему-то удалили, поэтому ещё раз запощу.
https://github.com/kubk/students
> PageObject
Пока гуглил, заметил, что многие понимают PageObject по-разному: кто-то предлагает просто выносить селекторы в объекты со статическими свойствами, кто-то считает, что PageObject должен предоставлять интерфейс страницы, пользователи которого не знают ничего о селекторах и взаимном расположении DOM-элементов. Мне второй вариант понравился больше.
> поиск по фамилии зависит от регистра букв
Этого бы не произошло, если был бы написан тест: https://github.com/kubk/students/blob/master/tests/StudentGatewayTest.php
Насчёт теста функции экранирования:
> - передаем строку с тегом и проверяем, что на выходе тега нет
> - вызываем html_entity_decode на результате и проверяем, что получилась исходная строка
> - аналогично можно проверить кавычки, а также отдельные угловые скобки, что их нет в результирующей строке
Если правильно понимаю, то второй пункт работает, только если искомая строка не будет найдена. В противном случае результат будет содержать тег b или mark, и исходную строку от такого результата не получим. В общем, сам тест: https://github.com/kubk/students/blob/master/tests/StudentTwigExtensionTest.php#L71
> тут https://github.com/kubk/students/blob/master/src/LinkGenerator.php#L54 HTML в коде, и ссылка не экранируется как положено.
> Лучше было бы использовать для HTML кода макрос твига, а генерировать в PHP только сам URL.
Теперь html в php нет https://github.com/kubk/students/blob/master/src/LinkGenerator.php#L47
, но как мне кажется, тут https://github.com/kubk/students/blob/master/templates/student-list.twig#L14+L15
какой-то низкоуровневый код в шаблоне. Ну и ссылка генерируется только в одном месте, нужен ли макрос, который будет использоваться лишь один раз?
> Насчет авторизации по паролю - лучше в куке (и в БД) хранить не пароль, а его соленый хеш. Чуть безопасней, а так у тебя пароль в открытом виде на каждый запрос шлется. И в базе лежит. Украли базу/куки - и можно идти проверять, подойдет ли этот пароль к почте, к соцсетям итд.
В базе был только хеш, а насчёт кук - да, сглупил.
> я бы назвал класс не UniqueEmail, а StudentEmailUnique, так как это ограничение работает только для одного класса - студента.
Насчёт универсального решения понятно, но вряд ли оно мне где-либо ещё пригодится, раз доктрина в симфони почти что стандарт и там уже есть UniqueEntity.
Впредь постараюсь быть внимательнее и лучше тестировать то, что отдаю на проверку.
Вот тебе пример двух вакансий. Как видишь, ничего заоблачного и нет никакой еботни с кмсками.
Вот я специально потратил вчера вечер целый, поставил себе Apache с официального сайта, PHP тоже скачал, добавил как модуль чё-то там, в общем всё работает, хелловорлд все дела (прикольно кстати, я так понял это как настоящий интернет-сервер, по IP зашел к себе с телефона, офигеть).
Так вот допустим я смогу нарисовать формы, там для выбора файлов, всякие опции, которые часто использую, кодеки, тайминг, трим, склейка, ну в общем всё в виде удобных менюшек-переключателей-слайдеров (для домашней коллекции вырезаю из сериалов опенинги, титры, рекламу, лишние озвучки, меняю местами серии и т.п., и так сложилось что с каждым файлом приходится вручную работать, что очень утомительно)
Так вот, получится ли как-то динамически из маленьких таких кусочков составлять привычную команду для консоли и запускать ее из PHP?
ИНБИФО: еще одна макак — НЕТ, "ПРОГРАММИРОВАНИЕМ" ЗАРАБАТЫВАТЬ НЕ СОБИРАЮСЬ, так что если хотите, можете гнать.
Это и есть настоящий веб-сервер.
Да, в пхп есть shell_exec для отправки команд в консоль или как-то похоже называется.
Ты еще не научился биндить консоль в пхп?
Ну, можешь попробовать https://github.com/PHP-FFMpeg/PHP-FFMpeg, например.
Мой вопрос - зачем, когда есть божественный nginx? Его даже развернуть проще намного, чем монструозный апач.
Наследие социализма
Мимо-вкатывальщик из фронт-енд тредов, до этого верстал и учил JS. За вчера сделал вроде бы на Zend вывод и хранение альбомов, но как делать 4-5 пункт пока неебу совершенно.
На вскидку выглядит очень сложно. (Ну то есть из примера Basic usage я не понял ничего).
>>947455
>$cmd = "ffmpeg -codecs 2>&1";
>print shell_exec($cmd);
выводит ошибку:
>'ffmpeg' is not recognized as an internal or external command, operable program or batch file.
хотя уже давно добавил ffmpeg в PATH и запускаю из любой локации, очевидно для PHP другие правила, нужно где-то зарегистрировать путь к экзешнику? Винда 7 если что.
>>947460
Не знаю, с этим апачем довольно быстро разобрался. А чем именно отличается для тебя nginx? Советуешь на него поменяться?
Купи инстанс с центосью и накати энжинкс, в чем проблема? Деплоить не могешь штоле? Обычные линуксы же.
Правда не ебу, что такое php-fpm, но гугл подсказывает что это кэширующий сервер, так что поебешься с часок и настроишь из мануалов, ничего сверхъестественного.
Это задание нихуя не на стажера. В зависимости от качества реализации на джуна/мидла. Стажеры поидее вообще беспомощные и нихуя сделать не могут. В любом случае не на 15к уж точно.
>>947468
>Правда не ебу, что такое php-fpm, но гугл подсказывает что это кэширующий сервер
Это менеджер процессов пхп.
А что с графической частью?
HTML и CSS каждый школьник уже знает, и любую информацию найти легко. Да и нет у меня цели учить какой-то ёба язык. Мне нужно с нуля за пару вечеров то что я хочу получить, и с PHP это симс риал.
Так ты делаешь свой локальный сайтек или что? На питоне можно в пару строк поднять фласк-сайтик и тыкать через него биндинги в ffmpeg-консоль.
Или тебе нужна консольная приблуда без гуев? Тогда на питоне еще проще и любой школьник сможет написать.
Ну и ладно.
Достаточно простенькое. В зенде ебашишь контроллер, вьюхи и редирект на урл, потом чтение из бд и вывод. Настройка nginx c php-fpm в гугле везде описана, тоже ничего сложного. За 2 недели управишься.
Поясню окончательно:
>тебе нужна консольная приблуда без гуев?
я сам заебался в cmd писать все руками, от консоли тошнит уже
>На питоне можно в пару строк поднять фласк-сайтик и тыкать через него биндинги
Если эти биндинги можно динамически составлять, и весь процесс вкатывания и написания подобного займет не более двух вечеров, и есть хоть одна причина почему это будет лучше PHP, то я хочу быть твоим падаваном, мастер.
(а то я вчера задумался, а сегодня уже реализую на PHP первые фичи, и если мне придется начинать заново и ебать очко змеей еще неделю... а нахуя оно мне вообще?)
>ты делаешь свой локальный сайтек или что?
хочу так: приду я на работу, и в свободное время прямо с телефона зайду, щелкну пару кнопочек, найду нужные фреймы в видео, обрежу, склею, оно сохранится у меня на компе там где я хочу! Быстро. Дешево. Охуенно.
http://dkab.github.io/jasmine-tests/
> >>947454 по IP зашел к себе с телефона, офигеть
утром включил, посмотрел IP, у меня не меняется до конца сессии, так что пока всё нормально с этим.
>найду нужные фреймы
Вот тут не знаю. Ты собрался вываливать все видео на сайт или как ты вообще представляешь находить нужные кадры?
Ну вообще задачи похоже можно даже через телеграм-бота забиндить.
Архитектура же простая - парсить человеческие команды и преобразовывать их в понятную ffmpeg-командную строку.
Вот, например, мой говноскрипт, который отправляет скриншоты с вебки по запросу. Точно также можно намутить что угодно, сделать более сложный парсер предложений.
https://gist.github.com/anonymous/a9f7376d140e82ab1cc85ac90c812f96
Поясни, как это всё работает у тебя?
>Ты собрался вываливать все видео на сайт
ну наверное 2 пути:
1) выбираю файл
2) конвертирую в webm с низким качеством
3) через HTML5 <video> смотрю, отмечаю (на бумажке) нужные секунды
или:
1) выбираю файл
2) тут придется подшаманить, сделать виджет который позволит конкретный фрейм в виде картинки рипать, то есть как бы все в браузере просчитывается, а потом одна команда отправляется которая покажет где ты сейчас, на каком фрейме. А дальше режу по этим координатам.
Нужно пробовать.
Только там параметры лишку напередавал, но тесты пройдет, похуй.
>Поясни, как это всё работает у тебя?
Говноскрипт?
Подключаю либы, телеграм-бота.
Функция Camera() - делает скриншот, посылая прямую команду в ос через os.system(), на всякий случай обрабатываю возможные ошибки, т.к. если попытаться сохранить через ffmpeg c этим же именем, вылезет бесконечный цикл ффмпега, поэтому предыдущий файл нужно удалить.
def echo(bot, update): - стандартная функция обработки сообщений телеграма.
if update.message.text == "screenshot' - проверяю текст, если сообщение содержит в себе нужный текст то далее выполняется функция Camera, которая сохраняет скриншот на диске, затем bot.sendPhoto - отправляю скриншот в телеграм. Можно также отправить видео, документы, что угодно.
def main():- тут думать не надо, стандартный обработчик бота, который будет крутиться в фоне и обрабатывать входящие сообщения.
Первый путь легко реализовать через sendVideo, отправляешь видео, смотришь, затем пишешь боту что тебе нужно и он выполняет любую команду.
Насчет второго пути и быстродействия ffmpeg не знаю, по сути разбить на картинки и выбирать из них удаленно может быть даже медленней чем залить и смотреть тупо видеофайл на странице.
Огромное спасибо, правда я нихуя не понял, пойду читать про генераторы.
Вот статья: https://habrahabr.ru/sandbox/80371/
>Литература
>Курсы обучения за деньги
>Бесплатные курсы
>Через месяц, я смогу написать первое приложение
Ну ты понял.
>Насчет второго пути и быстродействия ffmpeg не знаю, по сути разбить на картинки и выбирать из них удаленно может быть даже медленней чем залить и смотреть тупо видеофайл на странице.
Нет, ты не понял, я уже знаю какой фрейм мне нужен (например начинаем с ss 00:00:00.000), поэтому только его присылаю в виде "картинка + тайминг", а дальше средствами PHP делаю определенный шаг назад или вперед, получаю другой фрейм. Так пока не подберется идеальный. В принципе я и сейчас так примерно делаю, только в Free Video Editor, только он сук работает не так как надо, я там смотрю только тайминги и потом руками через консоль вырезаю и т.п.
>Вот статья:
К чему это?
> я уже знаю какой фрейм мне нужен
Ну ок, отправляешь картинки определенного тайминга боту.
Для более сложной обработки сообщений тебе нужно будет выучить только строки и регулярочки, чтобы вычленять оттуда логические цепочки типа "обрежь от и до", "сделай главной вторую дорожку" и т.д. Это совсем не сложно и будет быстрее, чем писать целый сайт на пхп и в итоге заниматься тем же самым биндингом команд.
Просто бери, разбирайся, делай, в чем проблема вообще. Все предельно ясно.
>>947528
Это троллинг? Или вы поехавшие? Писать телеграм-бота и гонять данные через полмира только чтобы получить скриншот? Во многих видеоплеерах скриншот делается нажатием кнопки.
Питон не то что бы сложнее, но вся информация по Питону в основном на английском, а по PHP например в ОП посте и в интернете куча информации на русском.
>>947454
Можно, но это в общем не очень праивльный подход, по нескольким причинам.
Во-первых, уже есть куча видеоредакторов, в которые вложено множество труда. Вряд ли ты в краткие сроки сможешь сделать что-то сопоставимое. Эффективнее будет сделать поискать разные варианты.
Даже если тебе надо просто перекодировать файл - есть куча оберток над ffmpeg, в том числе open source и бесплатные.
Наконец, если делать самому, то на мой взгляд архитектура получается неэффективная. Ты предлагаешь ради GUI поднять веб-сервер и гонять запросы из браузера, чтобы этот сервер что-то делал с видеофайлом. Это очень неэффективно, тут явно нужно десктопное приложение, без всяких серверов. Но его написание это конечно намного более сложная задача чем вызвать ffmpeg. Если под винду то удобнее всего писать на C# и .NET. Есть еще варинант писать HTML/CSS/JS приложение и упаковать его в десктопное приложение с помощью Electron, но не уверен что это все эффективно и надежно будет работать.
Ну а телеграм приплетать сюда еще неэффективнее, он вообще тут никак не подходит.
В общем мой совет - найти нормальный готовый видеоредактор.
Вот живой пример: сайт, на котором размещена таблица. Каждую ячейку в ней можно редактировать прямо на странице. Нажимать кнопки, выбирать радиобаттоны и всё такое. При этом на странице (без перезагрузки) происходят какие-то изменения.
Технически я сейчас это реализовал так:
- На странице ловится событие (например, onclick или onchange) по которому срабатывает жабаскрипт.
- Он собирает введённые данные (id элемента, value инпута и т.п.) и передаёт их через аякс в пхп-скрипт.
- Этот скрипт - отдельный файл, например url:"refresh_cell.php", . В нём первым делом из $_POST извлекаются переменные и по ним что-то там обсчитывается.
- Причём, большей частью в функциях, которые записаны где-то в другом файле (у меня они сведены в один function.php).
- В итоге, пхп-скрипт выдаёт сгенерированную разметку через echo.
- Он завершается, и в js через аякс возвращается эта выдача success: function (data) {.
- Ну и дальше эта data куда-то встраивается на странице.
Это так и должно быть, или я набыдлокодил слишком много костылей?
Как быть, если нужно извлечь не один кусок данных, а несколько? Например, при изменении одной из трёх ячеек, обновить в БД не только её саму, но и их сумму в четвёртой?
В целом все правильно. Конкретно архитектура на фронте и беке вызывает много сомнений, типа почему у тебя там не мвс, а какойто дикий файлик с функциями, но это ты с опытом нагородишь. Сам процесс верно протекает. Ну а для того, чтобы решить твой вопрос просто дописывай и на фронт и на бек необходимый функционал.
Вообще, я бы конечно разделял это на компоненты. У тебя все перемешано в кучу и намертво связано. Я бы сделал отдельно на яваскрипте виджет таблицы, который генерирует события изменения. Отдельно бы код, который подписывается на эти события и отправляет данные на сервер. Отдельно на сервере код, который их принимает и сохраняет в БД. Там отдельно модели и контроллеры.
С сервера удобнее присылать не HTML, а JSON, а то непонятно как сообщать об ошибках например.
> Как быть, если нужно извлечь не один кусок данных, а несколько? Например, при изменении одной из трёх ячеек, обновить в БД не только её саму, но и их сумму в четвёртой?
Реши, где будут делаться изменения. Если на сервере - то пусть тот присылает содержимое не одной, а всех изменившихся ячеек, если на клиенте - пусть см их пересчитывает.
Он хочет это делать удаленно с работы
>почему у тебя там не мвс, а какойто дикий файлик с функциями
Я пока не умею в паттерны. Почитал про MVC, офигел от того, что большинство объясняющих даже не могут внятно объяснить, что такое "модель" и в основном срутся по этому поводу друг с другом. А когда попробовал разобраться, получилось какое-то описание идеального программирования в стране эльфов. Типа вот волшебный идеальный пользователь, который волшебным идеальным способом контактирует через волшебного обозревателя с волшебными данными. А на деле получается что-то вроде "модель - это данные на сервере, но на самом деле в 2017 году это уже не совсем данные, а данные, плюс логика работы с ними, поэтому все серверные скрипты - это тоже данные, но только модель, правда собирать их в одну модель некорректно, потому что тогда контроллер размазывается между клиентом и сервером, а это а-та-та и ой-ёй-ёй, поэтому вот тут мы нарисуем стрелочку, этот блок на рисунке расположим чуть ближе - и теперь всё в порядке. Данные, которые не модель, видятся контроллером через вид, затрагиваемый моделью контроллера пользователя. Модель. Данные."
Пока что для себя я сделал вывод, что вид страницы настраивается только через css и рулится чере id и классы элементов, а активность пользователя отслеживается только через js. Данные лежат только в БД и все операции с ними проходят только на стороне сервера.
>просто дописывай и на фронт и на бек необходимый функционал
>С сервера удобнее присылать не HTML, а JSON, а то непонятно как сообщать об ошибках например.
Тоже о нём думал, не хотел с ним морочиться, но видно придётся.
>>947550
>Если на сервере - то пусть тот присылает содержимое не одной, а всех изменившихся ячеек
Вот как раз этого и хочу избежать.
>Я бы сделал отдельно на яваскрипте виджет таблицы, который генерирует события изменения.
А чем стандартные onchange и onclick не устраивают?
Ты читал про классическое мвс, раз там обсервер фигурирует. В связи со спецификой бекенда обсервер между вьюхой и моделью быть в принципе не может.
Тут значит схема такая.
Модель - данные и логика работы с этими данными. Самый распространенный пример, который тебе в большинстве фреймворков встретистя - одна модель на одну сущность в бд.
Вьюха - в данном конкретном контексте просто создает статичный хтмл.
Контроллер - это в принципе центральная точка работы всего этого говна. Запрос с браузера маршрутизуется приложением так, что в конечном счете он приходит на какой-то контроллер. Контроллер его обрабатывает, вызывает методы моделей, какие требуется. В конечном счете контроллер какие-то данные отдает вьюхе, чтобы та отредерилась. И после этого статичный хтмл, полученный с вьюхи, отдается клиенту обратно.
Ну вот такая сама стандартная схемка в двух словах.
Почитай еще мой урок про MVC тогда https://github.com/codedokode/pasta/blob/master/js/minesweeper-mvc.md
>>Я бы сделал отдельно на яваскрипте виджет таблицы, который генерирует события изменения.
> А чем стандартные onchange и onclick не устраивают?
Может в твоей ситуации они и подойдут, так трудно сказать.
>>947515
Переусложнено. Во-первых, это элементарно решается без генераторов, кода будет намного меньше. Во-вторых, тут: return function(start, step) - не должно быть аргументов. В третьих, вместо 2 yield можно использовать один.
То есть тебе стоит разобраться в теории, в каких именно ситуациях стоит использовать генераторы.
>>947513
Ты замыкания знаешь? Если нет, изучи в learn.javascript.ru. Ты создаешь функцию, а переменную-счетчик располагаешь снаружи от нее, таким образом, что эта функция может увеличивать ее при каждом вызове.
>>947468
Комментарии такого типа, как у тебя, тут не приветствуются. Ты ведь не помочь хочешь, а похвастаться что вчера прочел статью для чайников про настройку нгинкса? Это конечно большое достижение, но наш тред не для таких целей.
php-fpm это менеджер процессов PHP и FCGI сервер, с твоим гуглом какие-то проблемы.
>>947466
Если ZF знаешь, то делать недолго, несколько дней максимум.
>>947460
Апач проще наверно. В случае нгинкса надо отдельно поднимать и настраивать php-fpm, а с апачем не нужно. Хотя конечно в плане конфигурации нгинкс современней, логичнее и удобнее. Но возни-то больше получается, особенно начинающему.
Ну и кстати у нгинкса полезных модулей меньше. Например, у него нет модуля, который умеет в отдаваемой странице заменять что-то по регулярке (тот модуль от китайцев, что есть, убогий и малопригодный).
Ты случайно не из тех, кто считает что новая модная технология X всегда лучше чем старая Y? Нгинкс ориентирован на производительность, а Апач на число фич и модулей.
>>947458
Что за термины? "биндить"? Bind значит привязывать, и смысл твоего предложения понять трудно.
И не надо вкидывать ссылки на вещи, которые ты берешь из гугла, не разобравшись. Гуглить любой может. А ты расскажи про свой опыт и подводные камни.
Почитай еще мой урок про MVC тогда https://github.com/codedokode/pasta/blob/master/js/minesweeper-mvc.md
>>Я бы сделал отдельно на яваскрипте виджет таблицы, который генерирует события изменения.
> А чем стандартные onchange и onclick не устраивают?
Может в твоей ситуации они и подойдут, так трудно сказать.
>>947515
Переусложнено. Во-первых, это элементарно решается без генераторов, кода будет намного меньше. Во-вторых, тут: return function(start, step) - не должно быть аргументов. В третьих, вместо 2 yield можно использовать один.
То есть тебе стоит разобраться в теории, в каких именно ситуациях стоит использовать генераторы.
>>947513
Ты замыкания знаешь? Если нет, изучи в learn.javascript.ru. Ты создаешь функцию, а переменную-счетчик располагаешь снаружи от нее, таким образом, что эта функция может увеличивать ее при каждом вызове.
>>947468
Комментарии такого типа, как у тебя, тут не приветствуются. Ты ведь не помочь хочешь, а похвастаться что вчера прочел статью для чайников про настройку нгинкса? Это конечно большое достижение, но наш тред не для таких целей.
php-fpm это менеджер процессов PHP и FCGI сервер, с твоим гуглом какие-то проблемы.
>>947466
Если ZF знаешь, то делать недолго, несколько дней максимум.
>>947460
Апач проще наверно. В случае нгинкса надо отдельно поднимать и настраивать php-fpm, а с апачем не нужно. Хотя конечно в плане конфигурации нгинкс современней, логичнее и удобнее. Но возни-то больше получается, особенно начинающему.
Ну и кстати у нгинкса полезных модулей меньше. Например, у него нет модуля, который умеет в отдаваемой странице заменять что-то по регулярке (тот модуль от китайцев, что есть, убогий и малопригодный).
Ты случайно не из тех, кто считает что новая модная технология X всегда лучше чем старая Y? Нгинкс ориентирован на производительность, а Апач на число фич и модулей.
>>947458
Что за термины? "биндить"? Bind значит привязывать, и смысл твоего предложения понять трудно.
И не надо вкидывать ссылки на вещи, которые ты берешь из гугла, не разобравшись. Гуглить любой может. А ты расскажи про свой опыт и подводные камни.
>То есть тебе стоит разобраться в теории, в каких именно ситуациях стоит использовать генераторы.
Типа такого? А вообще я не жсер, увидел что там генераторы просят, полез юзать генераторы.
>Апач проще наверно
Мне он напротив перегруженным кажется. Кому как. А вот энжинкс прост и прозрачен для меня, работаю с ним и прямо душа радуется. С пхпфпм так же сложностей не имею. Все это даже на винде легко разворачивается (в несколько урезанном виде) для быстрой разработки.
>Ты случайно не из тех, кто считает что новая модная технология X всегда лучше чем старая Y?
Нет, дело не в новом. Да и о чем новом может идти речь, если для меня энжинкс и апач на первой же работе в связке попались
>Нгинкс ориентирован на производительность, а Апач на число фич и модулей.
Мне приятно осознавать, что он быстр, это тоже плюсом идет.
Ой, не ту ссылку про MVC дал, вот правильная: https://github.com/codedokode/pasta/blob/master/arch/mvc.md
>>947501
даже если Ip меняется, эта проблема решается с помощью Dynamic DNS - ты ставишь себе на компьютер программку и она автоматически обновляет DNS-запись. Есть бесплатные сервисы.
Проблема будет для тех, кто сидит за NAT (большинство пользователей интернета по кабелю). Там надо покупать белый IP у провайдера.
>>947470
PHP ничем не сложнее.
>>947467
Правила у PHP такие же, просто после изменения PATH в панели управления надо перезагрузить компьютер чтобы службы получили новые переменные окружения. Это кстати не проблема винды, в линуксе наверно так же.
>>947445
Откуда столько негатива? Не все готовы заказывать разработку с нуля, кто-то хочет взять готовое решение и сконфигурировать под свои цели, верстку натянуть. Что плохого?
Это во всем мире так делают.
Хотя конечно программистам лучше от этого подальше держаться.
>>947444
CMS рассчитаны на создание сайта с минимумом программировния. То есть это не для программистов, а для верстальщиков, админов, контент-менеджеров и эникейщиков.
>>947431
Зачем сомнительные задания с фриланса и конкуренция за еду? Это для тех, кто учиться не любит или не способен, а хочет поскорее зарабатывать. Я вижу другой вариант: в нашем треде всерьез изучить ООП, MVC, фреймворки вроде Симфони, тестирование, с таким набором знаний анон будет выглядеть лучше 90% вкатывальщиков, учившихся по видеокурсам, и его возьмут в любую нормальную компанию стажером.
Ой, не ту ссылку про MVC дал, вот правильная: https://github.com/codedokode/pasta/blob/master/arch/mvc.md
>>947501
даже если Ip меняется, эта проблема решается с помощью Dynamic DNS - ты ставишь себе на компьютер программку и она автоматически обновляет DNS-запись. Есть бесплатные сервисы.
Проблема будет для тех, кто сидит за NAT (большинство пользователей интернета по кабелю). Там надо покупать белый IP у провайдера.
>>947470
PHP ничем не сложнее.
>>947467
Правила у PHP такие же, просто после изменения PATH в панели управления надо перезагрузить компьютер чтобы службы получили новые переменные окружения. Это кстати не проблема винды, в линуксе наверно так же.
>>947445
Откуда столько негатива? Не все готовы заказывать разработку с нуля, кто-то хочет взять готовое решение и сконфигурировать под свои цели, верстку натянуть. Что плохого?
Это во всем мире так делают.
Хотя конечно программистам лучше от этого подальше держаться.
>>947444
CMS рассчитаны на создание сайта с минимумом программировния. То есть это не для программистов, а для верстальщиков, админов, контент-менеджеров и эникейщиков.
>>947431
Зачем сомнительные задания с фриланса и конкуренция за еду? Это для тех, кто учиться не любит или не способен, а хочет поскорее зарабатывать. Я вижу другой вариант: в нашем треде всерьез изучить ООП, MVC, фреймворки вроде Симфони, тестирование, с таким набором знаний анон будет выглядеть лучше 90% вкатывальщиков, учившихся по видеокурсам, и его возьмут в любую нормальную компанию стажером.
С виртуальной машины и дебиана (потому что меньше всего места занимает в сравнении с другими дистрибутивами). Есть кое-какие инструкции: https://gist.github.com/codedokode/420c8c12a1edae25f0ec
>>947230
> Кресты вообще по умолчанию встроены, благодаря особенностям генты.
Анон оптимист, во всем видит хорошее (для тех, кто не понял шутки - компоненты генту распространяются в виде исходных кодов и их надо скомпилировать, чтобы установить).
>>947109
Не все проекты такие нагруженные, чтобы нужна была кастомизация. На небольших проектах проще воткнуть кеширование.
Ну и тот же гитхаб, он вообще на Руби (и рельсах по моему: https://github.com/showcases/projects-that-power-github ) написан, не самый быстрый язык, но они просто наставили серверов побольше, где-то что-то подкрутили и проблема тормозов решилась. Хорошо, когда есть инвесторы и много денег!
>>947103
Без DIR, если ты пишешь относительный путь вроде
require 'something.php';
относительно чего он считается? Ты думаешь, относительно текущего файла? Неверно. Если посмотреть документацию по require, правила там запутанные и в каких-то случаях это работает, в каких-то нет. А __DIR__ сожержит полный путь к текущему файлу и с ним все работает гарантированно.
"у меня работает" - это вообще ничего не значит. Сегодня работает, а завтра нет. Надо смотреть документацию.
>>946938
Открой документацию: http://php.net/manual/ru/function.preg-replace.php
preg_replace находит все фрагменты текста, соответствующие регулярке (первому аргументу) и заменяет их на второй аргумент. При этом при замене можно использовать подстановки из исходного текста вида $0, $1 и тд.
С виртуальной машины и дебиана (потому что меньше всего места занимает в сравнении с другими дистрибутивами). Есть кое-какие инструкции: https://gist.github.com/codedokode/420c8c12a1edae25f0ec
>>947230
> Кресты вообще по умолчанию встроены, благодаря особенностям генты.
Анон оптимист, во всем видит хорошее (для тех, кто не понял шутки - компоненты генту распространяются в виде исходных кодов и их надо скомпилировать, чтобы установить).
>>947109
Не все проекты такие нагруженные, чтобы нужна была кастомизация. На небольших проектах проще воткнуть кеширование.
Ну и тот же гитхаб, он вообще на Руби (и рельсах по моему: https://github.com/showcases/projects-that-power-github ) написан, не самый быстрый язык, но они просто наставили серверов побольше, где-то что-то подкрутили и проблема тормозов решилась. Хорошо, когда есть инвесторы и много денег!
>>947103
Без DIR, если ты пишешь относительный путь вроде
require 'something.php';
относительно чего он считается? Ты думаешь, относительно текущего файла? Неверно. Если посмотреть документацию по require, правила там запутанные и в каких-то случаях это работает, в каких-то нет. А __DIR__ сожержит полный путь к текущему файлу и с ним все работает гарантированно.
"у меня работает" - это вообще ничего не значит. Сегодня работает, а завтра нет. Надо смотреть документацию.
>>946938
Открой документацию: http://php.net/manual/ru/function.preg-replace.php
preg_replace находит все фрагменты текста, соответствующие регулярке (первому аргументу) и заменяет их на второй аргумент. При этом при замене можно использовать подстановки из исходного текста вида $0, $1 и тд.
В таких случаях все равно пишут корпоративную хуйню. Или же можно использовать микро-фрейморвки тпа FT, какие у них могут быть тормоза?
use работает только в пределах файла и не распространяется на файлы, которые ты вызываешь из него.
В use по моему нельзя использовать две точки, это не имя папки.
> я так понимаю, require_once просто включает содержание файла шаблона
Где это написано? require это что-то вроде вызова функции, выполнить код из указанного файла. Только в отличие от вызова функции, вызванный файл видит те же переменные, что и родительский.
>>946901
Не надо ничего специально добавлять, если тебя так все устраивает.
Скорее
apt-get install php5 или как там этот пакет называется. Ну и расширения надо ставить отдельно, вроде php5-gd или php5-curl.
Модули ставятся через apt-get и обычно настраивать их не надо, но если что, конфиги в /etc/php/ есть.
Вот инфа на англ для старой убунты: https://www.digitalocean.com/community/tutorials/how-to-change-your-php-settings-on-ubuntu-14-04
> как подключить фреймворки
Как написано в документации к ним, скорее всего через composer, независимо от операционной системы.
> как запустить чтобы это всё работало на внешнем айпи или локалохосте?
Если линукс твоя основная система, то тебе нужно еще Апач или нгинкс, в качестве веб-сервера, который будет принимать запросы от браузера. Ставится опять же через ept-get install, конфиги в /etc/ как всегда, логи в /var/log/
В браузере вводишь http://localhost/, если хочется использовать свое доменное имя вроде example.local, пропиши его в /etc/hosts
>>946840
Надо делать отдельный класс, и может, не один. Потому что там довольно сложная схема с генерацией ссылок, обработкой ответов итд. Посмотри на сущестующие библиотеки для авторизации через соцсети и увидишь что там все не просто: https://packagist.org/search/?search_query[query]=auth
Можно, и даже полезно, чтобы сравнить разные подходы.
>>946810
Урок по установке PHP читал? https://github.com/codedokode/pasta/blob/master/soft/php-install.md
Там либо инсталлятор, либо архив с файлами, которые надо распаковать и прописать в PATH.
В ОП посте еще есть урок по командной строке и Апачу, тоже пригодятся.
>>946799
PHP выучить не очень сложно, но фрилансер ведь не будет писать абстрактные программы на чистом PHP. Тебе надо знать верстку, может CMS, может фреймворки, ООП, MVC, базы данных и при всем этом конкурировать с толпой людей. Зайди на фл.ру и сам почитай какие там задачи.
>>946792
Есть, но плохая. Сразу не получится, надо сначала ООП, DI, MVC и некоторые паттерны изучить. В ОП посте есть задача на студентов, почитай комментарии к ней, а это ведь задача без фреймворков, а сколько всего надо учитывать.
>>946772
Я про ларавел много чего слышу, но не вижу его ни в вкансиях, ни в задачах на фрилансе. У него по моему пиара больше чем случаев использования.
Хотя изучить можно, вредно не будет.
>>946768
Симфони самый сложный.
>>946765
Нет. Там свой синтаксис. Наверняка есть документация где-то.
Можно, и даже полезно, чтобы сравнить разные подходы.
>>946810
Урок по установке PHP читал? https://github.com/codedokode/pasta/blob/master/soft/php-install.md
Там либо инсталлятор, либо архив с файлами, которые надо распаковать и прописать в PATH.
В ОП посте еще есть урок по командной строке и Апачу, тоже пригодятся.
>>946799
PHP выучить не очень сложно, но фрилансер ведь не будет писать абстрактные программы на чистом PHP. Тебе надо знать верстку, может CMS, может фреймворки, ООП, MVC, базы данных и при всем этом конкурировать с толпой людей. Зайди на фл.ру и сам почитай какие там задачи.
>>946792
Есть, но плохая. Сразу не получится, надо сначала ООП, DI, MVC и некоторые паттерны изучить. В ОП посте есть задача на студентов, почитай комментарии к ней, а это ведь задача без фреймворков, а сколько всего надо учитывать.
>>946772
Я про ларавел много чего слышу, но не вижу его ни в вкансиях, ни в задачах на фрилансе. У него по моему пиара больше чем случаев использования.
Хотя изучить можно, вредно не будет.
>>946768
Симфони самый сложный.
>>946765
Нет. Там свой синтаксис. Наверняка есть документация где-то.
Компьютер и ОС Windows не понимают язык PHP и не могут выполнить твою программу. Тебе надо скачать интерпретатор PHP и запускать его, чтобы он выполнил твою программу, которую ты написал.
То есть ты запускаешь этот интерпретатор, указываешь имя файла с программой, а он уже читает твой PHP код и выполняет (интепретирует) записанные в нем команды.
Урок https://github.com/codedokode/pasta/blob/master/soft/php-install.md
>>946711
Еще с трейтами возможны конфликты имен полей и функций, как я понимаю, хотя там есть какие-то проверки на этот счет. Вообще, мало где они полезны и мне не очень нравятся.
>>946706
Множественное наследование это странная и неоднозначная вещь.
>>946697
Трейт это трейт.
>>946499
Какую инфу ты ждешь? В ОП посте есть инфа по PHP в общем, или тебе надо, чтобы тебе корзину написали?
>Вообще, мало где они полезны
Я их время от времени юзаю для реализации поведений. Конечно так, чтобы конфликтов не было. дешево и сердито, скажем так. Нормальные поведения заходят лучше, но не всегда стоят того, чтобы их пилить попросту.
>Множественное наследование это странная и неоднозначная вещь.
Если везде(вроде как) применяется принцип единственной обязанности, то зачем надо множественное наследование?
Сессии быстро умирают, зашел на сайт через час, а товаров нет.
>>946493
Да, анонимность дает возможность всяким неприятным людям высказать то, что они не могут высказать ИРЛ.
>>946491
В мануале есть страница, даже на русском: http://php.net/manual/ru/migration70.new-features.php
Читать можно, но потом прочти что нового. Так-то PHP5 код будет работать в PHP7.
>>946455
На доброчане хорошо сделано, там вроде ОП может выпиливать любые посты, которые ему не нравятся.
>>946448
Мы не видели твой код, скорее всего в нем где-то ошибка. htacess тут не при чем скорее всего.
>>946416
src - исходники
Можно еще по названию приложения, например StudentList
>>946377
Ну может я ошибся насчет того что ты не читал документацию, но вот с моделями ты явно не разобрался. Прочти мой урок по паттернам работы с БД, прочти документацию ларавель по моделям и коллекциям, и я думаю, ты сам увидишь свои ошибки. А если что-то остается непонятным - спрашивай. Тут важно понять именно принципы, что куда надо добавлять, кто за что отвечает и тд.
> Да, это не MVC, скорее просто поделка в процедурном стиле
А MVC не требует наличия ООП кстати. Это независимые вещи.
> Тут я косноязычно выразился. Я хотел не вместо, а дополнительно ее сделать. Про один класс для валидации ценное замечание.
В ларавель есть своя валидация, тебе надо просто разобраться, как ее приспособить для твоей задачи.
> Куки использую чтобы снова не проходить аутентификацию, когда время сессии выйдет, а вот зачем тогда сессии использовать я не знаю
Получается можно и без сессии обойтись. Можно и с ней конечно, но сложнее выходит.
>>Поиск отсутствующих/новых тегов надо было делать в модели. ты похоже не понимаешь идею MVC и кто за что отвечает. С твоим кодом, если мы захотим где-то в другом месте поменять теги поста, нам придется копипастить код из контроллера так как повторно его вызывать из другого места нельзя.
> Тут не понял, ведь все методы для работы с тегами в моделях Attitude и Tag.
Вот у тебя код в контроллере: https://github.com/grigoryMovchan/zuihitsu/blob/master/app/Http/Controllers/PostController.php#L270
Он анализирует список тегов, ищем те, что надо добавить, те, что удалить. Так как он в контроллере, то есть нельзя исплоьзовать повторно в другом месте.
И посмотри мой урок по MVC: https://github.com/codedokode/pasta/blob/master/arch/mvc.md
Я там даже дописал:
> Весь функционал приложения содержится в модели....К примеру, если мы делаем сайт объявлений, с такими функциями, как "добавить объявление", "удалить объявление", "найти объявления по критериям", то для каждого действия где-то в модели должна быть функция, которую можно вызвать. Если выкинуть все контроллеры и вью, то мы все равно можем добавлять объявления, вызывая методы модели.
То есть это определение, какие теги новые, какие надо удалить, должно быть в модели. Должна быть функция вроде "обновить теги" и уже она ищет, что надо удалить, а что добавить.
А у тебя получился толстый контроллер.
Сессии быстро умирают, зашел на сайт через час, а товаров нет.
>>946493
Да, анонимность дает возможность всяким неприятным людям высказать то, что они не могут высказать ИРЛ.
>>946491
В мануале есть страница, даже на русском: http://php.net/manual/ru/migration70.new-features.php
Читать можно, но потом прочти что нового. Так-то PHP5 код будет работать в PHP7.
>>946455
На доброчане хорошо сделано, там вроде ОП может выпиливать любые посты, которые ему не нравятся.
>>946448
Мы не видели твой код, скорее всего в нем где-то ошибка. htacess тут не при чем скорее всего.
>>946416
src - исходники
Можно еще по названию приложения, например StudentList
>>946377
Ну может я ошибся насчет того что ты не читал документацию, но вот с моделями ты явно не разобрался. Прочти мой урок по паттернам работы с БД, прочти документацию ларавель по моделям и коллекциям, и я думаю, ты сам увидишь свои ошибки. А если что-то остается непонятным - спрашивай. Тут важно понять именно принципы, что куда надо добавлять, кто за что отвечает и тд.
> Да, это не MVC, скорее просто поделка в процедурном стиле
А MVC не требует наличия ООП кстати. Это независимые вещи.
> Тут я косноязычно выразился. Я хотел не вместо, а дополнительно ее сделать. Про один класс для валидации ценное замечание.
В ларавель есть своя валидация, тебе надо просто разобраться, как ее приспособить для твоей задачи.
> Куки использую чтобы снова не проходить аутентификацию, когда время сессии выйдет, а вот зачем тогда сессии использовать я не знаю
Получается можно и без сессии обойтись. Можно и с ней конечно, но сложнее выходит.
>>Поиск отсутствующих/новых тегов надо было делать в модели. ты похоже не понимаешь идею MVC и кто за что отвечает. С твоим кодом, если мы захотим где-то в другом месте поменять теги поста, нам придется копипастить код из контроллера так как повторно его вызывать из другого места нельзя.
> Тут не понял, ведь все методы для работы с тегами в моделях Attitude и Tag.
Вот у тебя код в контроллере: https://github.com/grigoryMovchan/zuihitsu/blob/master/app/Http/Controllers/PostController.php#L270
Он анализирует список тегов, ищем те, что надо добавить, те, что удалить. Так как он в контроллере, то есть нельзя исплоьзовать повторно в другом месте.
И посмотри мой урок по MVC: https://github.com/codedokode/pasta/blob/master/arch/mvc.md
Я там даже дописал:
> Весь функционал приложения содержится в модели....К примеру, если мы делаем сайт объявлений, с такими функциями, как "добавить объявление", "удалить объявление", "найти объявления по критериям", то для каждого действия где-то в модели должна быть функция, которую можно вызвать. Если выкинуть все контроллеры и вью, то мы все равно можем добавлять объявления, вызывая методы модели.
То есть это определение, какие теги новые, какие надо удалить, должно быть в модели. Должна быть функция вроде "обновить теги" и уже она ищет, что надо удалить, а что добавить.
А у тебя получился толстый контроллер.
>>Как найти работу?
Вон Ванечка Ерохин уже работает похрамистом, функционал на кассе тестирует, баги шваброй убирает. А все свои книжки читаешь.
>>947717
На твоей картинке черным по белому написано protected? Или ты тут тонко затролить решил?
https://ideone.com/EFEACD
>В мануале есть страница, даже на русском: http://php.net/manual/ru/migration70.new-features.php
>Оператор объединения с null
>$username = $_GET['user'] ?? 'nobody';
Ух ты как удобно оказывается
Даже так можно:
>$username = $_GET['user'] ?? $_POST['user'] ?? 'nobody';
Просто выражение лица нравится. Какого-то тайного смысла я не закладывал.
>>946334
Есть функции вроде filter_var ( http://php.net/manual/ru/filter.examples.validation.php ) , но в общем-то да, регулярками, проверкой на заполненность, длину строки итд.
В плане архитектуры иногда делают отдельные классы-валидаторы и из них комбинируют правила валидации:
$v = new Validator;
$v->addRule('name', new NotEmptyRule());
$v->addRule('name', new MaxLengthRule(100));
..
$errors = $v->validate($data);
С этим можно заморочиться, если тебе хочется попрактиковаться в ООП, тут много интересных подвохов.
>>946315
Ты на русскомискал информацию? В приципе, не обязательно именно этот, можно Silex, тем более что он на компонентах Симфони.Можно и большой фреймворк, вроде Yii.
Просто знакомиться с фреймворками проще с минималистичных фреймворков, да и вдруг потом пригодится.
>>946278
Не, это не нужно, это просто ты не разобрался скопировал откуда-то.
>>946217
Ты уверен что проблема в приложении? Как ты проверял? Может быть в том месте, где ты получаешь результат, ты неправильно как-то его обрабатываешь?
Можешь через командную строку напрмер программой curl или wget запросить ответ с сервера, или браузером?
Просто выражение лица нравится. Какого-то тайного смысла я не закладывал.
>>946334
Есть функции вроде filter_var ( http://php.net/manual/ru/filter.examples.validation.php ) , но в общем-то да, регулярками, проверкой на заполненность, длину строки итд.
В плане архитектуры иногда делают отдельные классы-валидаторы и из них комбинируют правила валидации:
$v = new Validator;
$v->addRule('name', new NotEmptyRule());
$v->addRule('name', new MaxLengthRule(100));
..
$errors = $v->validate($data);
С этим можно заморочиться, если тебе хочется попрактиковаться в ООП, тут много интересных подвохов.
>>946315
Ты на русскомискал информацию? В приципе, не обязательно именно этот, можно Silex, тем более что он на компонентах Симфони.Можно и большой фреймворк, вроде Yii.
Просто знакомиться с фреймворками проще с минималистичных фреймворков, да и вдруг потом пригодится.
>>946278
Не, это не нужно, это просто ты не разобрался скопировал откуда-то.
>>946217
Ты уверен что проблема в приложении? Как ты проверял? Может быть в том месте, где ты получаешь результат, ты неправильно как-то его обрабатываешь?
Можешь через командную строку напрмер программой curl или wget запросить ответ с сервера, или браузером?
Скопирую с прошлого треда:
>>939966
>>938135
>>938130
Почитай посты по этим ссылкам.
>>946138
Не очень понял вопрос. Уточни, что именно непонятно.
А то пока я могу только ответить, что аргументы передаются через скобки после имени функции.
>>946077
Для управленцев и депресснутых есть перезвоним-тред. зачем нам второй тред? Надо просто модерировать тред нормально.
Хорошо бы конечно банить даунов, они мешают отвечать на вопросы.
>>946038
ДА, нужно в фоновом режиме, например, по крону, собирать нужные картинки. Скрипт на странице может получать ссылку на нее либо из HTML атрибутов, либо аякс-запросом.
>>946025
Почитай документацию по гиту, git book например или мануал. Это URL репозитория,а не адреса для входа через ssh.
https://git-scm.com/book/be/v2/Git-on-the-Server-The-Protocols (англ)
https://git-scm.com/book/ru/v1/Git-на-сервере-Протоколы
https://git-scm.com/book/ru/v1/Основы-Git-Работа-с-удалёнными-репозиториями
Скопирую с прошлого треда:
>>939966
>>938135
>>938130
Почитай посты по этим ссылкам.
>>946138
Не очень понял вопрос. Уточни, что именно непонятно.
А то пока я могу только ответить, что аргументы передаются через скобки после имени функции.
>>946077
Для управленцев и депресснутых есть перезвоним-тред. зачем нам второй тред? Надо просто модерировать тред нормально.
Хорошо бы конечно банить даунов, они мешают отвечать на вопросы.
>>946038
ДА, нужно в фоновом режиме, например, по крону, собирать нужные картинки. Скрипт на странице может получать ссылку на нее либо из HTML атрибутов, либо аякс-запросом.
>>946025
Почитай документацию по гиту, git book например или мануал. Это URL репозитория,а не адреса для входа через ssh.
https://git-scm.com/book/be/v2/Git-on-the-Server-The-Protocols (англ)
https://git-scm.com/book/ru/v1/Git-на-сервере-Протоколы
https://git-scm.com/book/ru/v1/Основы-Git-Работа-с-удалёнными-репозиториями
1) верно
2) верно (хотя ты не учел что бордер добавляет к ширине 2 px)
3) верно
4) цвета вырвиглазные. Почему-то у тебя стоит margin-right 5px, но в задаче требуется 10, почитай, как избавиться от пробелов и вызванных ими отступов
5) верно
>>946011
Мне в питоне не нравится отстутвие тайп-хинтов и своеобразное ООП. Сам-то язык неплохой, его много где используют, но не уверен что он проще для изучения.
>>946009
Поинтересоваться можно было в более вежливой форме, а так выглядит как попытка самоутвердиться за счет новичка.
>>945979
Возьмите лучше мой MVC, он проще: https://github.com/codedokode/pasta/blob/master/arch/mvc.md
> Вывести информацию о пользователе, сколько лайков поставил/получил, сколько взаимных лайков
Решено пока неэффективно, с лишними подзапросами. Это можно сделать с 2 джойнами без подзапросов. Если непонятно, как, попроси подсказку.
Но вообще, надо приучаться мыслить так:
- джойним нужные нам таблицы
- условиями ON/WHERE отсекаем ненужное
- группируем, если надо
- отсеиваем сгруппированные данные по условию HAVING
- сортируем
- отбираем нужные колонки из сгруппированных данных
В данном случае очевидно нам нужна группировка по пользователям, вопрос только что и как к ним приджойнить.
Джойны в данном случае сделают код читабельнее и дают оптимизатору больше свободы.
> Все пользователи, которые не поставили лайк юзеру 3
Опять же, решается без подзапросов одним джойном.
> Все пользователи, которые поставили лайк 1,2 но не поставили 3
И тут то же самое.
Попробуй все это сделать через джойны.
> Вывести информацию о пользователе, сколько лайков поставил/получил, сколько взаимных лайков
Решено пока неэффективно, с лишними подзапросами. Это можно сделать с 2 джойнами без подзапросов. Если непонятно, как, попроси подсказку.
Но вообще, надо приучаться мыслить так:
- джойним нужные нам таблицы
- условиями ON/WHERE отсекаем ненужное
- группируем, если надо
- отсеиваем сгруппированные данные по условию HAVING
- сортируем
- отбираем нужные колонки из сгруппированных данных
В данном случае очевидно нам нужна группировка по пользователям, вопрос только что и как к ним приджойнить.
Джойны в данном случае сделают код читабельнее и дают оптимизатору больше свободы.
> Все пользователи, которые не поставили лайк юзеру 3
Опять же, решается без подзапросов одним джойном.
> Все пользователи, которые поставили лайк 1,2 но не поставили 3
И тут то же самое.
Попробуй все это сделать через джойны.
Посмотрел код попапа.
https://github.com/greenTea242/MinesweeperMVC/blob/master/src/views/PopupView.js#L33
> PopupView.prototype.addButton = function(option, title) {
> if (!this._buttons) {
> throw new PopupViewException("Необходимо создать контейнер кнопок.");
> }
Вот это по моему неудачное ограничение. Обычно сначала добавляют кнопки, а только потом отображают попап, а не наоборот.
> var template = document.querySelector(".template-popup");
Тут логичнее использовать id так как шаблон может быть только один. Но это так, мелочь незначительная.
>>947683
Там еще дело может быть в лицензии, если ты торгуешь продуктом, то не можешь любые библиотеки использовать.
>>947635
Да я тоже против нгинкс ничего не имею. Хороший сервер, тем более что сделан нашим человеком.
>>947627
В документации вроде есть туториал, но на англ.
>>947617
Да, так, только я бы previous переместил во внутреннюю функцию.
> верно (хотя ты не учел что бордер добавляет к ширине 2 px)
Насколько знаю, есть 2 пути:
- вычесть эти 2 пикселя из ширины элемента. Получится width: 578px, выглядит как магическое число: https://jsfiddle.net/Lq1fgjde/1/
- выставить ширину с учётом паддингов и использовать box-sizing: border-box: https://jsfiddle.net/Lq1fgjde/2/
Оба подхода дали одинаковые результаты, какой лучше?
4: https://jsfiddle.net/zvcemf1n/1/
6: https://jsfiddle.net/ba2qgzt6/1/
Вывод списка смежности в виде дерева без рекурсии: https://jsfiddle.net/wkL0ka7u/
На PHP вышло многословно: https://ideone.com/YKik59
В вебаче все тухло, поэтому спрошу здесь - когда верстаешь, то просто прикручиваешь ксс и хтмл, всякие жс-штуки не надо прикручивать? А если надо, то какие? Можно верстать просто так или все заказы обычно на верстку на какую-то платформу, типа бутстрапа?
Если ты делаешь чисто хтмл + цсс - это верстка. Если еще и жс, или только жс - это уже фронтендом называется.
А существуют заказы где просто собираешь хтмл+цсс?
Чем тогда фронтенд отличается? Фронт это когда добавляешь анимацию или что?
>А существуют заказы где просто собираешь хтмл+цсс?
Да, но это уже лучше к дизайну отнести. Сейчас время такое, что верстал наплодилось пиздец. Фронтенд - это любая логика, вычисления, которая делается на стороне клиента. Если короче - вся жаваскрипт хуйня.
Ты вообще при вызове не обязан указывать переменные, можно указать любое выражение.
func(1, 3, "hello") например
Чего-то я не понимаю. Ведь функции выполнены действия с переменными, указанными уже. В эти переменные я после подставляю то, что нужно. А если я укажу любое выражение, которое не было указано, то как она будет выполняться, если в самой функции таковых нет?
Переменные, которые при описании функции указаны в скобках, называются аргументы.
Когда ты вызываешь функцию, то внутри нее эти переменные-аргументы создаются и им присваивается значение, указанное при вызове.
Допустим, мы создадим такую функцию:
function something($x, $y) { ...
И позже ее вызовем так:
something(1, 3);
тут внутри функции $x получит значение 1, а $y значение 3.
Функция не имеет доступа к глобальным переменным, созданным снаружи нее (и наоборот, снаружи не видны локальные переменные, созданные в функции), потому даже если у тебя снаружи есть переменные с такими же именами (x, y) то они не имеют никакого отношения к тем, что внутри функции.
Потому аргументы как раз и нужны, чтобы передать данные в функцию снаружи.
И если ты еще не видел, в прошлом треде были посты про функции: >>939966 >>938135 >>938130
Стало https://github.com/grigoryMovchan/auth/tree/auth_mvc
Было https://github.com/grigoryMovchan/auth
Пока нет роутера - доступ к страничкам по прямой ссылке на их контроллер, понятно что в продакшене это недопустимо. Еще не разбирался как составить htaccess, если скрипт делит домен с другим приложением
Знаю, что косяк, когда модель непосредственно работает с глобальными переменными. Пока думаю над этим
Покритикуйте плиз
>>946192-кун
>Не, это не нужно, это просто ты не разобрался скопировал откуда-то.
Отсюда скопировал https://laravel.ru/docs/v5/quickstart-intermediate
Да, не разобрался, для меня до сих пор там какая-то магия происходит, хоть и получилось написать блог-поделку.
Ну да, лярва выскоабстрактный кусок блевотины. Так сходу въехать во все происходящее именно в этом фреймворке и у опытного человека не сразу получится (например пришедшего с юи), попробуй доки почитать очень внимательно, хз че тут еще сказать.
Да мне доки бесполезно просто так читать. Стал въезжать только когда начал пилить свою поделку, с этими уровнями абстракции как будто новый язык учу.
Но это так, лирическое отступление
В шапке вся информация есть.
да
Нет, не совсем правильно. Нужно делать что-то своё, а не просто повторять. Напиши что-нибудь по аналогии, похожее, но не тупо переписывай с туториалов.
Неправильно. Видео уроки и вебинары ничего не дают, бездумное повторение в основном тоже. Делать надо задачки как у ОПа, читать книги и документации. Прочел о какой-то новой фишке - пилишь под нее мини проектик. Когда достаточно много разных фишек освоил - пилишь проектик, где все их сразу используешь, тут-то сложности и возникают. Решаешь их, приходит понимание что и зачем, и в голове откладываются знания.
А я не гнушаюсь видео уроками. Такой же источник инфы, как и остальные. Доки/статьи/книги могут быть перегружены либо некритичной инфой, либо попросту водой. Видеоуроки напротив кучу инфы не досказывают, но для беглого взгляда на какие-то вещи очень хорошо подходят иногда.
Я так напили поделок в процедурном стиле, теперь хуй разгребешь, при этом некоторые используются в поле. Так что тоже не серебряная пуля. Необходимости в ООП и MVC может долго не появляться, пока не придется что-то поддерживать или расширять, а когда для себя пишешь может и не придется.
>Учи SQL, PDO, хотя бы основы
Собственно, есть что-нибудь годное по этому? Пасту читал. По идее сейчас должен делать список студентов, но по sql и pdo нихуя не знаю.
Кевин Янк - PHP и MySQL. От новичка к профессионалу - 2013
Даст базовые знания как засунуть-вынуть данные с таблиц, соединить их и тому подобное.
О! Я как раз около недели назад решил, что пора переходить на линукс. До этого всю жизнь сидел на винде тоже. Делал вот что:
1. Сначала почитал какой дистр выбрать, так как они все кажутся одинаковыми, первым выбрал дебиан, поставил на виртуальную машину и не проперся, но подумал "по описанию Дебиан вроде заебись, буду привыкать".
2. По совету друга "не выебываться и ставить убунту" поставил убунту и понял, насколько она охуенная с т.з. использования. Насколько там все проще и лучше для пользователя. В дебиане прям с момента установки какая-то еботня начинается.
3. Понял, что работать в виртуальной машине невозможно, все тормозит и нет стимула глубоко лезть в настройки. От опыта системы воодушевился настолько, что подчистил место на диске и сделал логический диск для убунты, поставил ее туда вместе с виндой. Пару дней поебался, поставил виртуальный сервер и проч., уже чуок привык и теперь от винды блевать тянет, когда залезаю туда. А раньше сидел и думал, что все заебись.
Минусы, которые отмечаю в убунте по сравнению с виндой:
жесткий диск греется сильнее на несколько градусов (я в этом параноик), хотя можно поебаться и выключить всякие индексации;
флеш тормозит, мультики в браузере не посмотришь, хотя на ютубе все норм работает;
многих программ нет, например пунто свитчера, для других какие-то ебаные версии (флукс), но для флукса хотя бы есть альтернативы;
драйвера для графических и звуковых карт тоже вроде какие-то ебаные, периодически все рывками двигается, хотя драйверов около 10 версий на выбор;
грузится раза в два дольше винды, хотя выключается в десять раз быстрее.
Но в целом по ощущениям от использования, количеству горячих клавиш, фич и общего ощущения некоей целостности убунту мне нравится намного больше винды, я теперь не вернусь туда ни за что. Винда стала казаться огромной кучей не связанных между собой и не доведенных до ума компонентов. Особенно я прозрел насколько в винде уебищно реализованы права и пользователи
Я короче ставил бы убунту и ставил ее не на виртуалку, а вместе с виндос, чтобы был стимул сидеть и копать. Не знаю позволяют ли другие дистры ставить их вместе с виндой без еботни, но убунту позволяет. Плюс там из коробки уже все работает, а в дебиане надо ебаться начиная с установки и потом после нее с добавлением репозиториев, судо, нормальых шрифтов. Подозреваю, что в других дистрах все еще сложнее (хотя могу ошибаться)
И еще, 90% всех вопросов-ответов в гугле связаны с убунтой, а не с другими дистрами.
О! Я как раз около недели назад решил, что пора переходить на линукс. До этого всю жизнь сидел на винде тоже. Делал вот что:
1. Сначала почитал какой дистр выбрать, так как они все кажутся одинаковыми, первым выбрал дебиан, поставил на виртуальную машину и не проперся, но подумал "по описанию Дебиан вроде заебись, буду привыкать".
2. По совету друга "не выебываться и ставить убунту" поставил убунту и понял, насколько она охуенная с т.з. использования. Насколько там все проще и лучше для пользователя. В дебиане прям с момента установки какая-то еботня начинается.
3. Понял, что работать в виртуальной машине невозможно, все тормозит и нет стимула глубоко лезть в настройки. От опыта системы воодушевился настолько, что подчистил место на диске и сделал логический диск для убунты, поставил ее туда вместе с виндой. Пару дней поебался, поставил виртуальный сервер и проч., уже чуок привык и теперь от винды блевать тянет, когда залезаю туда. А раньше сидел и думал, что все заебись.
Минусы, которые отмечаю в убунте по сравнению с виндой:
жесткий диск греется сильнее на несколько градусов (я в этом параноик), хотя можно поебаться и выключить всякие индексации;
флеш тормозит, мультики в браузере не посмотришь, хотя на ютубе все норм работает;
многих программ нет, например пунто свитчера, для других какие-то ебаные версии (флукс), но для флукса хотя бы есть альтернативы;
драйвера для графических и звуковых карт тоже вроде какие-то ебаные, периодически все рывками двигается, хотя драйверов около 10 версий на выбор;
грузится раза в два дольше винды, хотя выключается в десять раз быстрее.
Но в целом по ощущениям от использования, количеству горячих клавиш, фич и общего ощущения некоей целостности убунту мне нравится намного больше винды, я теперь не вернусь туда ни за что. Винда стала казаться огромной кучей не связанных между собой и не доведенных до ума компонентов. Особенно я прозрел насколько в винде уебищно реализованы права и пользователи
Я короче ставил бы убунту и ставил ее не на виртуалку, а вместе с виндос, чтобы был стимул сидеть и копать. Не знаю позволяют ли другие дистры ставить их вместе с виндой без еботни, но убунту позволяет. Плюс там из коробки уже все работает, а в дебиане надо ебаться начиная с установки и потом после нее с добавлением репозиториев, судо, нормальых шрифтов. Подозреваю, что в других дистрах все еще сложнее (хотя могу ошибаться)
И еще, 90% всех вопросов-ответов в гугле связаны с убунтой, а не с другими дистрами.
>Понял, что работать в виртуальной машине невозможно, все тормозит и нет стимула глубоко лезть в настройки.
Ну как сказать... Стоит в виртуалке, не тормозит и в настройки лезть приходится. Причем убунта
У тебя консоль показана, а как насчет GUI приложений, анимаций, видео, тяжелых интернет-страниц?
Зачем же убунта-то для повседневного юзания? Это ж самый тормоз, скатившийся до уровня винды, щас в моде linux mint и elementary os.
Пару лет назад ставил убунту с GUI в виртуалку - на экране логина времяреакции на клик мышью было около минуты. Тогда Убунта что-то поменяла в интерфейсе так, что он должен был рассчитываться на GPU (использовался OpenGL, я так думаю), а в случае его недоступности GPU эмулировался на CPU и работало это сверхмедленно.
А зачем? Мне от линукса для разработки только сервер нужен. А как выше кун писал, в винде обычные программы лучше работают и выбор больше.
Винду на том пике я не переустанавливал с 2011 года, я даже программы редко удаляю, ставлю и забиваю. Производительность никак не изменилась.
>>948870
Это проблема виртуалбокса, убунту ради гуи (хз зачем) надо ставить в vmware
>Понял, что работать в виртуальной машине невозможно, все тормозит и нет стимула глубоко лезть в настройки. От опыта системы воодушевился настолько, что подчистил место на диске и сделал логический диск для убунты, поставил ее туда вместе с виндой
Виртуальную машину небось virtual box какой-нибудь юзал. Ставь Xen, он намного быстрее.
>90% всех вопросов-ответов в гугле связаны с убунтой, а не с другими дистрами.
А знаешь почему? Потому что убунта - днище. Есть 3 дистра, где ничего не надо спрашивать, ибо все описано в мануале либо в виках - гента, арч и дебиан.
Для этого xen c vga passthrough ставят. Из под линукса запускаешь винду, а в ней игры и анимации твои.
Вот видос, 60fps:
https://www.youtube.com/watch?feature=player_detailpage&v=iBaetUjsr7s
В виртуалбоксе тоже есть проброс видеокарты, но там определенные условия. Как я понимаю, видеокарту надо отдать виртуальной машине целиком, а значит, надо иметь 2 видеокарты.
Вот, что пишут:
- нужно 2 видеокарты
- You need a CPU that supports IOMMU which is VT-D (Intel) and AMD-Vi. This allows Virtual Machines to interface directly with peripheral devices.
Также, в виртуалбоксе есть какое-то экспериментальное ускорение, когда в гостевую машину ставится драйвер и она как-то через виртуалбокс может использовать аппаратное ускорение (OpenGL или DirectX как я понимаю). Как минимум винда начинает намного быстрее работать в таком случае и разрешение экрана в ней автоматически подстраивается под размер окна.
https://blogs.oracle.com/fatbloke/entry/3d_acceleration_with_ubuntu_guests
>Есть 1 дистра, где ничего не надо спрашивать, ибо все описано в мануале либо в виках - Windows 10
Не благодари
Нахуй пошел.
>You need a CPU that supports IOMMU which is VT-D (Intel) and AMD-Vi
и хуй найдешь сейчас такой процессор
Это pr или софтач? Если ты хотел научиться кодить на линуксах, достаточно было поставить серверную версию или купить нищевпску, десктоп для кодинга не нужен.
Где-то в апреле прошлого года понял, что хватит пинать хуи и пора таки становится нормальным программистом. Мой опыт - это работки в колледже, сами понимаете, не серьезно и не достаточно чтоб работу найти. Начал с нулевых задач этого треда, потом студенты, потом файлообменник. До конца они у меня так и не доделаны - функционал весь, но ОП еще присылал правки, то есть было, что улучшать. Параллельно работал курьером, то за 10к по полдня, потом за ~30к за месяц (да, очень хорошо платили). В ноябре заболел и пока сидел дома подумал, а дай-ка размещу резюме на hh, вдруг выйдет чего. В итоге на меня сами откликнулись. Больной бегал на собеседования. Их было целых три. Еще и тестовое дома делал. В итоге взяли на техподдержку. Современная веб-студия, пилящая на Битриксе (ба-дум-ц). Первые три месяца - 32к, потом 40. Вот жду-не дождусь повышения.
На собеседовании, кстати, оценили мои знания. То, что использую PDO прям плюсец жирный.
Теперь вот надо сдать 2 экзамена от Битрикса и потом у меня планы перевестись на разработку в этой же компании. (потому что, честно говоря, мне похуй почему у вас там сайт тормозит и почему слетает авторизация)
Ну а так вообще я подумал, что не хочу свою карьеру связывать с Битриксом, поэтому как-нибудь начну изучать серьёзный фреймворк.
Не могу вот решить с чего начать, Laravel или Symphony, кто что думает? На hh у них доли примерно равные
Время проебываешь не битриксе только. Мне за год зарплату до 120к повысили, при чем я пишу даже без фреймворков на чистом php. Ну я правда в ДС, в других городах думаю вряд ли столько дали бы. Учи паттерны, mysql, юнит тестинг, архитектуру и написание нормального кода, а не конкретные фреймворки. Фреймворки имеет смысл смотреть только, чтоб понять как они написаны, зубрить сам фреймворк тоже смысла мало, они на разных фирмах разные все.
120 за год? Круто, вдохновляет? Ну а разве фреймворк не является хорошим примером и способом изучения хорошего кода, паттернов и прочего?
Так-то да, понятно, что хороший уровень, это когда смена фреймворка - дело пары месяцев
> при чем я пишу даже без фреймворков на чистом php
Ты по отдельности компоненты ставишь или свои изобретаешь? Ведь не дано другого + ты пишешь про тесты и архитектуру, значит у тебя там просто свой фреймворк велосипедный? Можно глянуть твои компоненты?
>>948869
Тормознутость определяется не дистром, а окружением рабочего стола (Desktop Environment). Они все почти одинаково тормозят, за исключением LXDE/Xfce. Из убунты можно выкинуть Unity и поставить что-нибудь полегче или вообще изначально собирать всё самому из Ubuntu Minimal: https://help.ubuntu.com/community/Installation/MinimalCD
А у питона пип и джанги-фласки работают как часы на винде.
Ну не знаю.
Я вот в Линуксе не разобрался вообще.
Тут всё делается легко и просто, там надо было пердолиться со всем на свете.
Это потому что ты в линуксе не сидел. там установка любого модуля или фреймворка или даже скачка верстки делается в одну команду в консоли.
Всё сложное придумано для того, чтобы стало легче.
А что сложного? Как раз просто в проектах: объявлен класс, пользуешься методами в любом файле, лишь указав namespace.
Если судишь по задачам ОПа, то не надо.
Они как олимпиадные задачки, такое тебе никогда в жизни не понадобится.
В проектах и фреймворках такого не бывает, чтобы в одном файле столько всего было наверчено.
Проверь плз задачу про айфон и кредит
http://codepad.org/lIrhPaUj
Все работает (проверял с разными суммами), но подозреваю что в плане элегантности это не самое лучшее решение. Есть какой-то образцовый вариант, на который можно равняться?
Подкинул.
Задачки в ОП-посте, думаю, заебись подойдут.
Плюс вот, например https://toster.ru/q/384556#answer_943242
Не иди туда. Битрикс это смерть. Если ты человек с позитивным уровнем icq то больше года не выдержишь, а потом еще и оказывается что за год ты приобрел бесполезный, и даже вредный опыт.
Нет, так тоже не работает. И на php.net именно "utf8".
ПОдсоединись к mysql из консоли или другой программы и сделай запрос SHOW CHARACTER SET как тут:
https://dev.mysql.com/doc/refman/5.7/en/charset-charsets.html
Какая ОС, откуда MySQL брал?
>>949251
В mysql она без дефиса пишется.
Ubuntu 16.04, из репов ставил.
Есть строка utf8 UTF-8 Unicode utf8_general_ci. Возможно ли ошибка из-за того, что при создании базы я указал uft8_unicode_ci?
Попробуй задать кодировку с помощью запроса SET NAMES utf8 вместо set_charset.
И кстати, ты с БД-то соединился перед тем, как set_charset вызывать? И правильно ли вызываешь, как в мануале?
C SET NAMES все работает. Но смущает, что в мануале так не рекомендуют делать.
Создал еще одну базу с utf8_general_ci, таже самая ошибка.
Попробуй что-то вроде charset-set-server = utf8 в конфигуе мускл прописать, и ресни базу.
Есть ли отличия, что сложнее, ларавел, уи и т.д?
Есть ли там непонятная магия, сложно ли их изучить?
Не знаю че там у пиздона, но вроде как шо там шо там по идее фичи должны не сильно различаться, не? Ну с учетом разницы в реализации ООП.
Зачёт.
С битриксом не связывайся, это полное дно, и в профессиональном плане, и в плане зарплат.
Учи Symfony и перекатывайся в какую нибудь серьёзную контору, пишущую что то сложное на нём (CMS-ки, какие нибудь внутренние корпоративные порталы для автоматизации бумагоперекладывания, или в подобную фигню - такие есть, сам в такой работаю). Через 3-4 года, если голова светлая, будешь получать не меньше, чем синьёр на какой нибудь джаве-хуяве.
Добавил роутер, переписал на классы с наследованием.
Теперь файлов стало в два раза больше чем в ветке без MVC, но, возможно, теперь расширять проект и вносить правки будет легче
Не знаю на счёт питона, но думаю что примерно такие же.
Там вся фишка в том, что подавляющее большинство современных пехапешных фреймворков (yii, laravel, zend) созданы под сильным влиянием ruby on rails и сильно на него похожи. Соответственно и друг на друга они очень похожи. Считай - если знаешь один - знаешь их все. В изучении довольно простые, особой магии нет.
Особняком только Symfony стоит. Он делался под влиянием java-вских spring mvc + hibernate, соответственно довольно сильно от них отличается. И область применения у него та же - всякая энтерпрайз фигня. Вот тут уже и магия присутствует (в виде кодогенерации и прочей фигни), и, самое главное, он предназначен для программистов, которые хорошо представляют себе, что такое ООП и как им пользоваться для того, чтобы не получилось такой ситуации, что на середине написания проекта код превращается в такие дикие макароны, что проще проект выкинуть, чем дальше развивать.
но это всего лишь инструмент - сам посебе фреймворк качества кода воообще никак не гарантирует.
> довольно сильно от них отличается
довольно сильно отличается от других php-фреймворков, я хотел сказать.
На spring mvc + hibernate он как раз сильно похож (по крайней мере на их раниие версии, пока те в монстров современных не разрослись)
А почему не фалкон?
Да, он не популярен так, как вышеозвученные, но он быстр, как шайтан. В целом по возможностям он предоставляет все, что нужно для комфортной разработки, разве что возникает желание обертку другую нагородить поверх не самого привлекательного апи.
Почему бы его не переместить в шапку? А то эта технология, очень даже привлекательная в плане потребления ресурсов сервера, остается практически неизвестной. Добавлю, что в нагрузку идет зефир, который позволит вынести в сишные расширения большую часть рутинной блевотины.
Потому что идея, заложенная в основу phalcon - абсолютно бредовая.
ПХП выбирают из-за скриптовой природы и, как следствие, предельной простоты разработки на нём. Естественно, в ущерб быстродействию потом. ничего бесплатно не бывает.
Если тебе нужно быстродействие .... то нафига тогда вообще php брать?? Для этого есть java, c++, go наконец.
А проект на phalcon - это какая то дикая менашиша из кода на PHP и C - ну пиздец. В итоге ни удобства разработки на PHP, ни быстродействия полностью компилируемых языков.
в жопу тибя поебали, а ты питухом завизжал, хехе.
Ну вот есть у меня проект на фалкон. Я в сишный и зефирный код не залезал даже, все на пхп. Немного неудобное апи в сравнении с остальными обдроченными абстракциями фреймфорвками, но востальном все точно то же самое, только пашет намного быстрее. Фалкон не минифреймворк, он решает своим сраным сишным расширением 80% рутинных задач, я не вижу причин его не использовать и не развивать.
На работе фалькон, никакой мешанины из Си там нет, обычный PHP. Не знаю откуда ты взял что там какая-то мешанина будет, фалькон в использовании ничем от других фреймворков не отличается.
На самом деле, все довольно просто. Я тоже сначала охуевал. Почитай пару статеек про MVC сначала.
http://suyati.com/about-us/management-team/
Лол, оказывается его индусы разрабатывают. А еще говорят индусский код то, индусский код се.
Посмотри в книжке из разряда пхп для даунов как работают с бд для начала, освоишь взаимодействие бд и пыхи, навертишь верстку и вот студенты и готовы. А потом ОП тебе разъяснит что ты лалка, пойдет процесс и ты все поймешь.
Ночь через ночь - это 15 дней в месяц надо работать за 8000 р? Я боюсь считать даже сколько там в час выходит. 1 доллар?
А ты комментарии к задаче и статьи по ссылкам из комментариев прочел? А задания отсюда https://github.com/codedokode/pasta/blob/master/soft/web-server.md решил? А туториал из офиц. мануала прочел?
И не бойся, в видеокурсах сразу с этого начинают, без задач на циферки.
Я таки считаю, что переход к студентам несколько резковат. Но может это и к лучшему, ибо отсеет даунито, которые не могут даже в гугл.
Ты освоил тернарный оператор? Ну охуеть теперь.
Что мешает не работать так?
Любым копирайтером ты заработаешь тысяч десять в месяц без особого напряга.
можно, если только тебе на свjих коллег насрать. И на себя тоже.
1) $status = '0'; echo $status == 1 ? 'yes' : 'no' выведет 'yes'. Это раз.
2) статус = 1. Ну заебись. Это что за статус такой? а если там 2 будет - это что значит?
Правильно хотя бы так
<?php echo CategoryStatusConverter::statusToString($category) ?>
где:
class CategoryStatusConverter {
const STATUS_ENABLED = 1;
const STATUS_DISABLED = 2;
public static function statusToString(array $category)
{
if (array_key_exist('status', $category)) {
if ($category['status'] === self::STATUS_ENABLED) {
return 'yes';
} elseif ($category['status'] === self::STATUS_DISABLED) {
return 'no';
}
}
return 'unknown';
}
}
а ещё лучше djj,ot без статических методов обойтись.
>$status = '0'; echo $status == 1 ? 'yes' : 'no' выведет 'yes'.
обосрался, будет 'no', но остального это не отменяет
Вся ппроблема работы в сети , что надо пару месяцев сосать хуи без соли, пока набьешь клиентуру.
Где лучше выполнить ридерект если запрос не валиден? В самой функции проверки на валидность или в контроллере?
function getID()
{
if (isset($_GET['id']) and is_numeric($_GET['id'])) {
return $_GET['id']
}
????
}
function runUser()
{
$id = getID();
//Правильно?
if (!$id) {
redirect...
}
}
Не всегда так надо усложнять. Если вывод нужен только в одном месте программы (а в других местах статус обозначается по-другому), то можно сделать и тернарным оператором.
Если вариантов больше, то можно сделать массив для перевода из статуса в текст.
схрена ли?
задача валидатора - проверить валидность и ответить, валидно ли значение или нет. Но ни в коем случае не редиректить.
Задача контроллера - принять запрос, проверить с помошью валидатора и вернуть ответ. Или вернуть ошибку, если запрос невалиден.
Так что редиректить тут вообще не нужно. Нужно юзеру ошибку вернуть и показать в браузере.
Проверка на валидность более комплексное действие в общем случае, чем проверка одно айдишника. В целом моя позиция в том, что валидатор должен вернуть тру или фалс в зависимости от результата, + сообщение читаемое.Результат работы обрабатывается в коде, например, контроллера, и при фалсе редиректит куда-илбо. Но сама проверка должна осуществляться валидатором, контроллер, или кто там выше валидатора стоит, должны лишь отрегировать на валидацию.
ohuet'
я совсем забыл, спасибо.
>>949592
ты совсем поехал?
во первых, работает абсолютно корректно, во вторых, вариантов статуса всего 2. 1 и 0. Ты что, надграфу не можешь почитать? IS VISIBLE. Да и нет. Какие еще варианты? на пол шишечки?
>>949597
в сложных вариантах - да, а тут почти человеческая речь. Статус равняется единице? напечатай да, или нет. Не знаю, все лучше, чем писать огромные if ($qwe == 1) echo '1'; else echo '2';
Я всегда писал сайты на фреймворках - CodeIgniter, Yii, Django, ASP.NET MVC, Spring и Play - а сейчас вот предложили работу на Joomla.
Это что ли такой визуальный конструктор типа Delphi?
Добавлю, что своим опытом выстраданные проекты привели меня к следующей схеме: любое несоответсвие отплевывается в виде жэксепшена, принимаего одни или несколькими обработчиками (чаще всего все же одним), и в связи с этим до контроллера вообще не доходит ничего в случае провала валидации.
Это способ работатьб слесарем в чужой системе. Когда мы работаем на фреймворках мы и есть творцы системы в целом (бизнес логики). Когджа ты работаешь внутри какой-нибудь цмс ты лишь можешь рядом с этой системой (уже заранее заданной бизнес логкиой) возвести костыль, фиксящий то-то и то-то в самой системе. Но свобода твоя очень сильно ограничена. Вот в этом и разница.
На вопрос о визуальном контрукторе типа делфи: и да, и нет. Ограничения примерно те же на самом деле, но все же свободы у тебя чуть больше.
>любое несоответсвие
Зачем вбрасывать исключение при проверке данных введенных пользователем? Исключения нужны только для программистов, чтобы в случае если вся программа по какой-то исключительной причине не может продолжать или выполнить работу.
Зависит от того, как ты исключения обрабатываешь. У меня большая часть исключений выбрасывается клиенту в виде удобочитаемого сообщения че там и не так. Но я в основном апишник, мне этот момент очень важен.
>>9496
Писать легче, но «огромные» условные операторы читать легче. Поймешь, когда начнёшь поддерживать чей то код
Ну, сорян, мои апи репы закрыты. Если на словах, то суть исключений апишных в том, чтобы в коцне сформировать короткой и понятное сообщение для клиента. притом для меня. Адово помогает в отладке. клиентов много ,апи одно, ты и сам знаешь наверно.
Если его не сформировать, то я и сам не буду знать че там такое произошло прямо. Случаи подобного очень часты. Апи призвано отдавать либо ошибку подробную, либо валидные данные. Тут мимо идут сразу верстка и фронт, а потом эксепшены с моей стороны обязательны, иначе хуй отдебажишь вообще что-либо.
Ну а с точки зрения клиентов мои ошибки обрабатываются как валидные ответ с отличным от 200 кода.
Да я новичок вообще! Мне интересно как правильно должны писаться исключения.
Я обычно пишу так:
if (something wrong) {
throw new Exception("error");
}
Но мне хотелось бы знать как получить с помощью исключений максимально информации! Пока именно даже не знаю какой.
Думаю что нужно наследовать и писать своё исключение, и потом в конструкторе писать все нужные подробности. Но почему-то мне кажется что в конструкторе плохо писать логику исключения.
Максимум информации ты получаешь уже в конструкторе исключения. Стак и прочее у тебя дступны силами разрабов самого языка, твое дело отдать наилучшее сообщение при new Exception, корторое ты только можешь, + определить форматирование в завимимости от способа отлдачи (я предпочитаю джейсон апи).
На хуй присядь. ОП очень много объясняет того, чего ты нигде не прочтешь. Но для того, чтобы добраться до кладезя его знаний, гуглом нужно уметь пользоваться. На кой ты вообще нужен, если общедосьупную информацию получить не можешь?
Сап, доброкун, а ты не думал перезалить на более качественный хостинг свой проект и сделать там генератор .pdf, .doc, .epub, .fb2 слепка сайта. Ты же вроде еще не бросил учить анонов, а так бы было всем желающим удобно получать все в одном месте, я вот читаю с андроида, оно вроде бы удобно, но иллюстрации распидорашивает и если изначально у тебя была задумка с пошаговым изучением, то затем все меню сайта расползлось куда-то в ебеня, а материал все равно прибывает. Вот если бы ты сделал в более читабельном виде и автоматическую генерацию, то тебе бы не надо было бы каждый раз обновлять весь набор работ, а пользователи бы просто догружали файлы по завершенным "аркам" уроков.
Инб4: сделай сам
Я бы и рад, да пока знаний на этот счет не особо, но если вообще тебе нравится идея, то я бы покопался на этот счет и как найду в себе силы, то готов сделать это вместо тебя.
О чём ты говоришь? В мобильном браузере всё прекрасно видно.
Обрисую ситуацию. Я обычный гуманитарий, учитель по образованию. Работаю в школе, и тут мне подкинули задание - сделай-ка ты нам сайт школы. В общем, как бы сам сайт делать мне не пришлось, его нам зарегистрировали и создали на джумле какие-то левые типы. Но теперь директор постоянно ебет мозги. Нанимать умеющего человека она не хочет, поэтому все село на меня, а я этим делом даже и не интересовался никогда. По-быстрому скачал какой-то шаблон, накидал информации (как от меня и требовалось), но теперь, оказывается, требуется сделать все красиво.
http://dushuo.ru
^ Сам сайт. И я так и не смог понять, как сделать отображние материалов, как это обычно идет на всех сайтах - прикрепленное фото с кратким описанием либо началом материала, которое можно увидеть, непосредственно открыв этот материал. У меня почему-то всегда получается простой список заголовков материалов. Пытался читать туторы, решения моей проблемы так и не нашел. Извините, если ошибся тредом, но не мог бы кто-нибудь тезисно объяснить мне, как это сделать? Всем добра.
Сделаю вам сайт за 60 штук вместе с дизайном с тем функционалом, что уже есть те без доработок. Предоплата - половина.
Все скриптовые языки похожи, выучил пхп и делать перекат в рельсы или питон уже легко.
Все MVC фреймворки похожи,если хорошо освоил язык и патерны перекатываться между ними не так уж и сложно.
Для старта, посоветовал бы выбирать что по сложнее и правильнее с точки зрения языка и его патернов. В пхп это Symfony, вроде как.
Нашей школе за последние лет 5 учредитель столько денег не дал, откуда такие деньги?
сделай условие: если длина материала выше n символов, то проверить, есть ли краткое описание материала и отобоазить его, если такошо нет, то отобразить первые первые n символов материала. И в конце добавь строку с ссылкой на страницу материала, или на расширение статьи. Во втором случае обрезать материал будешь через js и jquery.
>>949829
Спасибо, анон, сейчас разгребусь с соревнованиями и отчётами и напишу тебе чуть позже. Спасибо за помощь.
Сразу видно, что учитель из тебя не очень. Запрягаешь ученика 9 - 11 класса за пятёрку в четверти сделать сайт и всё, проблем нету. Ещё потом и хвастаетесь другим школам, что у вас вот такие ПРОГРАММИСТЫ умные в школе есть. А вообще гугли создание блога на джумле, хотя там всё должно работать хорошо из коробки, но я уверен что весь нужный функционал для сайта будет в таких статьях.
а там контента много? Не проще поставить блогодвижок типа postleaf/wordpress?
Ставить жумлу в 2017 это какой-то зашквар
Тут всяко интересней сидеть, чем на пхп кодить. Что бы не делать, лишь бы не работать.
Например есть ['a','b','c','d','e','f']
И я хочу отсечь всё с номера 3 включительно, так чтобы новый массив выглядел так - ['d','e','f']
Как мне это сделать?
Спасибо
Хуясе ты агресивный. Курс евгеники закнчивал?
>Ой, не ту ссылку про MVC дал, вот правильная: https://github.com/codedokode/pasta/blob/master/arch/mvc.md
Спасибо, уже читаю.
Вот ещё вопрос по архитектуре (или чему-то подобному).
На сайте есть таблица в некими полями. Одно из полей предназначено для миниатюр фотографий, которые загружают пользователи. Но как эти файлы лучше хранить? Помещать в БД, вроде, не стоит. Просто хранить в отдельной папке, а в БД сделать таблицу соответствий (Фото164542.jpg - это вторая миниатюра для записи №476)? Или сразу переименовывать (Фото164542.jpg -> Фото164542-2-476.jpg), а потом парсить всю папку силами пхп?
Я часто работал с такой схемой, что миниатюры и прочие пресеты (у нас их штук 100 на сайте одном было) хранятся по разным путям. То есть например оригиналы по адресу /originals/image-name.png, а к примеру миниатюра 100х100 для этого же лежит в /100x100/image-name.png. Довольно наглядно выходит. Там конечно структура на реальном проекте будет сложнее, но ничего сверхъестественного.
Вариант с названием самих файлов тоже нормальный. В бд, конечно же, изображение лучше не хранить.
>миниатюры и прочие пресеты (у нас их штук 100 на сайте одном было) хранятся по разным путям
Это понятно.
>Вариант с названием самих файлов тоже нормальный.
То есть, оптимально будет при загрузке файла добавлять в его название информацию, к чему он относится, а когда нужно прикрепить изображение к странице, парсить имена файлов? А если файлов будет несколько десятков тысяч? У меня ожидается добавление примерно 30-40 тысяч картинок в год и сайт с этим должен работать хотя бы лет пять.
Я видимо не понял, какую ты задачу решить пытаешься, ибо при любой схеме с составлением пути или имени файла по каким-то определенным тобой правилам ничего тебе парсить не нужно будет в поисках нужной картинки. Опиши тогда саму задачу подробнее.
Задача такая:
Для контроля выполнения работы, работнику нужно сделать фото до, в процессе (возможно, несколько) и в конце. Кроме того, проставить время выполнения и некоторую другую информацию. Для этого, сначала менеджер забивает заказ в таблицу заказов и выбирает исполнителя (через интерфейс менеджера). Исполнитель заходит под своим логином на сайт (через интерфейс исполнителя) и видит, что у него образовался заказ, а так же его параметры. В ходе выполнения, он делает фотографии и загружает их на сайт. У них автоматически проставляется время. А менеджер в офисе видит в строке заказа миниатюры. Ну или хотя бы текст типа "2 фото прикреплено", кликнув по котором, можно эти фотографии просмотреть.
На сервере фотографии скорее всего будут сразу ужиматься до некоторого стандартного разрешения и делаться миниатюры. А вот с тем, как потом быстро и удобно прикреплять их к страницам, пока не разобрался.
<VirtualHost *:80>
DocumentRoot /home/lpkn/bogdan-footer
ServerName www.koloda.org
<Directory "/home/lpkn/bogdan-footer">
allow from all
Options +Indexes
</Directory>
</VirtualHost>
Как нужно обратится к www.koloda.org в браузере что бы оно показало мои файлы , а не ресурс в интернете?
"Создайте две страницы сайта, используя технику шаблонов и класс View из предыдущего ДЗ:
1.news.php - отображает список всех новостей. Заголовок у каждой - ссылка на страницу этой новости, под заголовком - краткий текст
2.article.php?id=NNN - отображает новость номер NNN с полным текстом"
Объясните, пожалуйста, как именно должен передаваться get запрос. Переход на article.php ведь осуществляется по ссылке на страницу, а не через <form> с кнопкой.
Я даже знаю откуда эта задачка, сам проходил два курса (первый скачал, второй оплачивал).
Гет-запрос передается по умолчанию, когда ты запрашиваешь URL.
article.php?id=<?php echo $article['id']; ?>
Почитай урок по http из шапки, у методов гет и пост применение шире, чем отправка форм.
Задача стоит следующая, после PDO::FETCH_CLASS, из базы я получаю массив объектов своего класса (длина массива неизвестна). Допустим $clients. У объектов есть несколько свойств включая, допустим $clients->state (бинарная false || true). Теперь мне необходимо создать два цикла, которые позволят мне обработать все свойства объекта. Но дело в том, что в одном цикле должны быть только объекты со значением state == true, а во втором только с фолсами. Проблему можно решить, просто составив два SQL запроса в БД, (вроде SELECT хуй FROM игрушки WHERE state = false). Но мне нутром кажется, что можно не дергать лишний раз базу, а как-то раскидать по двум циклам массив объектов исходя из свойства state. Мальчиков налево, девочек направо. Внимание, как это сделать? http://php.net/manual/ru/language.oop5.iterations.php тут читал, нихуя не понял. Похоже это даже не то что мне нужно.
>ДЮСШ
>пятёрку в четверти
Чета обзмеился.
>хвастаетесь другим школам, что у вас вот такие ПРОГРАММИСТЫ умные в школе есть
А потом его заставляют за бесплатно поднимать и обслуживать сайты всем этим другим.
Вообще, >>949761 выглядит неплохо, но тебе с нулевыми знаниями тяжело будет, пиши >>949829 анону полюбасу.
Просто прописываешь в ссылке на файл после названия и расширения это ?id='number', это и передает GET запрос. т.е, на новой странице ты уже можешь получить 'number' через $_GET['id]. Мимо несчастный с циклами
Нет, ты не понял. Ты лезешь в ООП, не зная толком циклы. Советую прорешать задачки из ОП-поста. С самой первой.
'к. Порешаю обязательно. Циклы и ветвления я немного знаю, просто похоже действительно сегодня переработал. А ООП сразу, потому что в конторе, сказали приходи через месяц с PDO и ООП и возьмем тебя за еду. В любом случае больше чем есть сейчас.
Потом удаляешь все файлы через unlink, подключаешься через сокет к апишке сервера и запускаешь детонатор, чтобы взорвать сервак к чертям. А все потому что пользователь ввел невалидный email.
Упереться в его потолок и начать писать к нему костыли.
Подключил автозагрузчик композера, прописал неймспейсы, орнул когда схватил "class pdo not found", но быстро вдуплил почему.
Собственно, теперь авторизация и каркас готовы, буду наращивать функционал.
https://fastvps.ru/t4u
Накидал за 5 минут, обоссываем:
1)
function count_smileys($arr): int {
$count = 0;
foreach($arr as $smile){
if(preg_match('^[:;][-~]{0,1}[)D]', $smile)){
$count++;
}
}
return $count;
}
2)
function get_volume_of_cuboid($length, $width, $height) {
if (
gettype($length) !== 'integer') ||
gettype($width) !== 'integer') ||
gettype($height) !== 'integer')
) {
return;
}
return $length $width $height;
}
3)
function solution($str) {
$length = mb_strlen($str);
if (($length / 2) == 1) {
$str .= "_";
}
$array = [];
for($i=0; $i<$length; $i++) {
$array[$i] = mb_substr($str, $i, 2);
}
return $array;
}
Гуглил только что такое кубоид, лол.
https://fastvps.ru/t4u
Накидал за 5 минут, обоссываем:
1)
function count_smileys($arr): int {
$count = 0;
foreach($arr as $smile){
if(preg_match('^[:;][-~]{0,1}[)D]', $smile)){
$count++;
}
}
return $count;
}
2)
function get_volume_of_cuboid($length, $width, $height) {
if (
gettype($length) !== 'integer') ||
gettype($width) !== 'integer') ||
gettype($height) !== 'integer')
) {
return;
}
return $length $width $height;
}
3)
function solution($str) {
$length = mb_strlen($str);
if (($length / 2) == 1) {
$str .= "_";
}
$array = [];
for($i=0; $i<$length; $i++) {
$array[$i] = mb_substr($str, $i, 2);
}
return $array;
}
Гуглил только что такое кубоид, лол.
Блять , сука, рыгать хочу от вида кода php. Язык как язык, но выглядит просто пиздец.
"делать роутинг средствами сервера. Для каждой страницы в папке public создается отдельный скрипт (index.php, register.php) и из него либо вызывается соответствующий контроллер, либо прямо там же и пишется код контроллера"
Что за папка public? Это типо public_html на убунте? Что за контроллеры? Их надо писать средствами php? Я нихуя не понял, простите, я туповат, да , на пальцах , примерах только понимаю.
Тут нет другого варианта, кроме как прочитать кучу статей и уроков по теме, попутно пытаясь сначала повторить, а потом сделать свою поделку. У меня на это действительно много времени ушло.
Я учил не по ОП-посту, но там в принципе тоже все есть и объясняется проще чем на хабре.
Удачи.
>>948039-кун
Старый фрейморк, учит неудачным решениям.
>>949986
Тебе надо изучить циклы и массивы сначала.
>>949968
GET-запрос это когда браузер запрашивает страницу с определенным URL с сервера. GET-параметры пишутся после знака вопроса в этом URL. Форма не обязательна.
>>949950
Браузер преобразует имя узла (www.koloda.org) в Ip-адрес этого узла с помощью системы DNS, отправляя запрос на DNs-сервер. Однако, с помощью файла hosts можно указать соответствие имени и IP явно, и в качестве IP прописать адрес твоей машины (127.0.0.1). Тогда браузер будет соединяться с запущенным на ней веб-сервером (Апачом).
>>950215
Это лучше отправить на проверку в ту компанию.
Раз у тебя есть папка public, надо бы в нее перенести index.php и сделать ее корневой папкой веб-сервера, а то у тебя весь код наружу выставлен получается.
https://github.com/grigoryMovchan/auth/blob/auth_mvc/db.sql#L25
> ENGINE=MyISAM
Прочитай в интернете различия между движками MyISAM и InnoDB, особенно про поддержку внешних ключей и транзакций
nbproject возможно стоит внести в gitignore целиком. Это же конфиги конкретной IDE, а не часть проекта.
https://github.com/grigoryMovchan/auth/blob/auth_mvc/index.php
> require 'app/bootstrap.php';
Идея bootstrap-файла в том, что он инициализирует приложение, а не запускает разбор запроса. Он нужен на тот случай, когда у тебя несколько точек входа в приложение, например cli-скрипты. И не хочется копипастить один и тот же код в начало каждого из них.
В твоем варианте bootstrap тут никак не помогает и вообще его правильнее было бы назвать index.php, а не bootstrap.php.
https://github.com/grigoryMovchan/auth/blob/auth_mvc/app/models/AuthModel.php
тут все смешано в кучу, все компоненты MVC в одном классе. Да и даже если рассматривать одну функцию, там все перемешано, потому что ты не смог разделить стену кода на отдельные действия-функции.
Идея ООП в том, что у нас каждый компонент отвечает за свою часть задачи. Один класс, который умеет соединяться с БД и выполнять запросы, другой класс, который умеет искать пользователей в базе, третий класс, который умеет еще что-нибудь.
Ну и название - "модель" тоже очень неудачное. Что такое модель, в твоем понимании?
https://github.com/grigoryMovchan/auth/blob/auth_mvc/app/core/Model.php
Тут все неправильно с начала и до конца.
Ну например у тебя в каждом объекте-модели свой объект PDO в то время как правильнее создать один объект и совместно его использовать.
Далее, у тебя смешано много задач. У тебя базовый клсс модели занимается:
- чтением конфигов
- установкой соединения с БД
- выполнением SQL запросов
https://github.com/grigoryMovchan/auth/blob/auth_mvc/app/core/Model.php#L69
> } catch (PDOException $e) {
> //TODO: убрать при переносе на сервер, строка только для отладки
> echo '<p>' . $query . '</p>';
Ты собрался catch и echo ставить после любой функции, которая может выкинуть исключение? Это ведь будет почти каждая функция в программе. И зачем ты выводишь сообщения? Какая польза посетителю твоего сайта от непонятных сообщений на английском?
Вообще, PHP по умолчанию сам выводит на экран сообщение при выбрасывнии исключеия. Ты зачем-то пытаешься повторить то, что PHP и так умеет делать по умолчанию (если включено отображение ошибок).
Тебе надо разобраться с исключениями.
https://github.com/grigoryMovchan/auth/blob/auth_mvc/app/core/Model.php#L43
> switch ($type) {
Свитч сделан не очень правильно. Если передать в качестве type неправильное значение (например, из-за опечатки), то твой код притворятся что все в порядке, вместо того, чтобы сообщить тебе что ты передал неправильное значение. Так ошибку в коде придется искать намного дольше.
Вообще, это плохая идея сделать одну функцию с вариантами выбора. Надо тогда делать N функций, на каждый вариант свою.
https://github.com/grigoryMovchan/auth/blob/auth_mvc/views/auth/authForm.php
В шаблонах лучше использовать версии операторов с двоеточием, а не фигурными скобками.
> if (isset($error)) {
Это плохой подход. Если у тебя переменная может быть, а может не быть, то очень неудобно писать код.
https://github.com/grigoryMovchan/auth/blob/auth_mvc/views/auth/authForm.php#L12
> @$_POST['login']
@ неправильно тут использовать (и вообще неправильно использовать). Оно подавляет вообще любые ошибки, например, если ты опечатаешься в названии $_POST.
Также, тут XSS.
Также, view не должен лезть в POST-данные. Это из-за того, что ты пока не научился разделять код на отдельные независимые действия. Должно быть так:
- получить данные из POST
- сделать с ними что-ниудь
- проверить их
- ...
- вывести форму
А у тебя это смешано. Когда код разбит на отдельные действия, в нем легче разбираться, его легче править. А твой запутанный код очень тяжело поддерживать, так как изменение в одном месте ломает что-нибудь в другом.
Тебе бы стоило сделать задачу на Вектор, если ты ее не делал. Она в том числе пытается научить этому разделению на части.
Раз у тебя есть папка public, надо бы в нее перенести index.php и сделать ее корневой папкой веб-сервера, а то у тебя весь код наружу выставлен получается.
https://github.com/grigoryMovchan/auth/blob/auth_mvc/db.sql#L25
> ENGINE=MyISAM
Прочитай в интернете различия между движками MyISAM и InnoDB, особенно про поддержку внешних ключей и транзакций
nbproject возможно стоит внести в gitignore целиком. Это же конфиги конкретной IDE, а не часть проекта.
https://github.com/grigoryMovchan/auth/blob/auth_mvc/index.php
> require 'app/bootstrap.php';
Идея bootstrap-файла в том, что он инициализирует приложение, а не запускает разбор запроса. Он нужен на тот случай, когда у тебя несколько точек входа в приложение, например cli-скрипты. И не хочется копипастить один и тот же код в начало каждого из них.
В твоем варианте bootstrap тут никак не помогает и вообще его правильнее было бы назвать index.php, а не bootstrap.php.
https://github.com/grigoryMovchan/auth/blob/auth_mvc/app/models/AuthModel.php
тут все смешано в кучу, все компоненты MVC в одном классе. Да и даже если рассматривать одну функцию, там все перемешано, потому что ты не смог разделить стену кода на отдельные действия-функции.
Идея ООП в том, что у нас каждый компонент отвечает за свою часть задачи. Один класс, который умеет соединяться с БД и выполнять запросы, другой класс, который умеет искать пользователей в базе, третий класс, который умеет еще что-нибудь.
Ну и название - "модель" тоже очень неудачное. Что такое модель, в твоем понимании?
https://github.com/grigoryMovchan/auth/blob/auth_mvc/app/core/Model.php
Тут все неправильно с начала и до конца.
Ну например у тебя в каждом объекте-модели свой объект PDO в то время как правильнее создать один объект и совместно его использовать.
Далее, у тебя смешано много задач. У тебя базовый клсс модели занимается:
- чтением конфигов
- установкой соединения с БД
- выполнением SQL запросов
https://github.com/grigoryMovchan/auth/blob/auth_mvc/app/core/Model.php#L69
> } catch (PDOException $e) {
> //TODO: убрать при переносе на сервер, строка только для отладки
> echo '<p>' . $query . '</p>';
Ты собрался catch и echo ставить после любой функции, которая может выкинуть исключение? Это ведь будет почти каждая функция в программе. И зачем ты выводишь сообщения? Какая польза посетителю твоего сайта от непонятных сообщений на английском?
Вообще, PHP по умолчанию сам выводит на экран сообщение при выбрасывнии исключеия. Ты зачем-то пытаешься повторить то, что PHP и так умеет делать по умолчанию (если включено отображение ошибок).
Тебе надо разобраться с исключениями.
https://github.com/grigoryMovchan/auth/blob/auth_mvc/app/core/Model.php#L43
> switch ($type) {
Свитч сделан не очень правильно. Если передать в качестве type неправильное значение (например, из-за опечатки), то твой код притворятся что все в порядке, вместо того, чтобы сообщить тебе что ты передал неправильное значение. Так ошибку в коде придется искать намного дольше.
Вообще, это плохая идея сделать одну функцию с вариантами выбора. Надо тогда делать N функций, на каждый вариант свою.
https://github.com/grigoryMovchan/auth/blob/auth_mvc/views/auth/authForm.php
В шаблонах лучше использовать версии операторов с двоеточием, а не фигурными скобками.
> if (isset($error)) {
Это плохой подход. Если у тебя переменная может быть, а может не быть, то очень неудобно писать код.
https://github.com/grigoryMovchan/auth/blob/auth_mvc/views/auth/authForm.php#L12
> @$_POST['login']
@ неправильно тут использовать (и вообще неправильно использовать). Оно подавляет вообще любые ошибки, например, если ты опечатаешься в названии $_POST.
Также, тут XSS.
Также, view не должен лезть в POST-данные. Это из-за того, что ты пока не научился разделять код на отдельные независимые действия. Должно быть так:
- получить данные из POST
- сделать с ними что-ниудь
- проверить их
- ...
- вывести форму
А у тебя это смешано. Когда код разбит на отдельные действия, в нем легче разбираться, его легче править. А твой запутанный код очень тяжело поддерживать, так как изменение в одном месте ломает что-нибудь в другом.
Тебе бы стоило сделать задачу на Вектор, если ты ее не делал. Она в том числе пытается научить этому разделению на части.
В твоем коде XSS. Почитай урок https://github.com/codedokode/pasta/blob/master/security/xss.md
>>949921
Файл помещаем на диск, после этого в таблицу - относительный путь к нему. Для уменьшенной картинки можно либо формировать путь из пути к основной, либо хранить в базе оба пути.
Всегда надо сначала сохранять файлы, а только потом записывать в БД, чтобы не было такого, что запись в Бд есть, а файла нет. Удалять в обратном порядке.
Иногда исплоьзуют схему, когда имя файла как-то формируется из id, чтобы не надо было брать его из базы, но там есть свои недостатки - неудобно сохранять картинку.
Так как у тебя к записи можно приложить несколько картинок, нужна отдельная таблица для них.
Еще какие-то полезные вещи могут быть в комемнтариях к задаче про файлообменник в ОП посте.
>>949786
Скорее всего ты заходишь не на свой сервер. Если у тебя серый IP (10.xxx, 192.168.xxx, 172.16.xxx), то он действует только в пределах локальной сети.
>>949682
Я хотел оптимизировать верстку для мобильных устройств, но руки пока не дошли.
Насчет переноса, я тоже все хочу перенести сайт хотя бы на github pages, но руки не доходят.
Насчет архивов - в ОП посте есть ссылка на rghost, там какой-то старый архив есть.
>>949681
Мануал это больше справочник, а не учебник.
>>949650
Файл .htaccess нужно настроить. Напиш, что именно тебе нужно. Скорее всего перенаправлять все запросы на index.php
В твоем коде XSS. Почитай урок https://github.com/codedokode/pasta/blob/master/security/xss.md
>>949921
Файл помещаем на диск, после этого в таблицу - относительный путь к нему. Для уменьшенной картинки можно либо формировать путь из пути к основной, либо хранить в базе оба пути.
Всегда надо сначала сохранять файлы, а только потом записывать в БД, чтобы не было такого, что запись в Бд есть, а файла нет. Удалять в обратном порядке.
Иногда исплоьзуют схему, когда имя файла как-то формируется из id, чтобы не надо было брать его из базы, но там есть свои недостатки - неудобно сохранять картинку.
Так как у тебя к записи можно приложить несколько картинок, нужна отдельная таблица для них.
Еще какие-то полезные вещи могут быть в комемнтариях к задаче про файлообменник в ОП посте.
>>949786
Скорее всего ты заходишь не на свой сервер. Если у тебя серый IP (10.xxx, 192.168.xxx, 172.16.xxx), то он действует только в пределах локальной сети.
>>949682
Я хотел оптимизировать верстку для мобильных устройств, но руки пока не дошли.
Насчет переноса, я тоже все хочу перенести сайт хотя бы на github pages, но руки не доходят.
Насчет архивов - в ОП посте есть ссылка на rghost, там какой-то старый архив есть.
>>949681
Мануал это больше справочник, а не учебник.
>>949650
Файл .htaccess нужно настроить. Напиш, что именно тебе нужно. Скорее всего перенаправлять все запросы на index.php
Нужно просто делать нормальное сообщение об ошиюке. Не читается файл - напиши, какой, не можешь соединиться с сервером - напиши, с каким, передано неверное значение - напиши, какое. Поможет при поиске ошибок.
Можно делать свои исключения и делать у них дополнительные поля, но это на тот случай если тебе надо потом их извлекать. Если не надо, то пиши все в сообщении.
>>949636
Для отладки можно использовать логгирование. Или показывать подробности ошибки только на локальном сервере.
Ну например если ты не можешь соединиться с базой то АПИ не должно отдавать эти подробности (а тем более - с какой базой с каким логином). а просто писать, что временно недоступно.
>>949618
Это (CMS/фрйемворки) просто разные вещи. В бизнесе кстати тоже что-то похожее есть - франшиза называется.
>>949614
CMS это система, позовляющая сделать сайт с минимумом или без программирования. Для типовых сайтов. Все настраивается через админку мышкой.
>>949613
Для 2 вариантов вообще логично true/false использовать.
>>949612
тут есть варианты, что возвращать:
- а что если несколько ошибок?
- а что если у одного поля несколько ошибок?
- а что если есть предупреждение?
- а что если мы хотим знать у какого именно поля ошибка?
- а что если мы хотим иметь код ошибки, чтобы программно его проверить ифом?
>>950235
Папка public это корневая папка сервера, в которой он ищет файлы при обращении к нему.
Нужно просто делать нормальное сообщение об ошиюке. Не читается файл - напиши, какой, не можешь соединиться с сервером - напиши, с каким, передано неверное значение - напиши, какое. Поможет при поиске ошибок.
Можно делать свои исключения и делать у них дополнительные поля, но это на тот случай если тебе надо потом их извлекать. Если не надо, то пиши все в сообщении.
>>949636
Для отладки можно использовать логгирование. Или показывать подробности ошибки только на локальном сервере.
Ну например если ты не можешь соединиться с базой то АПИ не должно отдавать эти подробности (а тем более - с какой базой с каким логином). а просто писать, что временно недоступно.
>>949618
Это (CMS/фрйемворки) просто разные вещи. В бизнесе кстати тоже что-то похожее есть - франшиза называется.
>>949614
CMS это система, позовляющая сделать сайт с минимумом или без программирования. Для типовых сайтов. Все настраивается через админку мышкой.
>>949613
Для 2 вариантов вообще логично true/false использовать.
>>949612
тут есть варианты, что возвращать:
- а что если несколько ошибок?
- а что если у одного поля несколько ошибок?
- а что если есть предупреждение?
- а что если мы хотим знать у какого именно поля ошибка?
- а что если мы хотим иметь код ошибки, чтобы программно его проверить ифом?
>>950235
Папка public это корневая папка сервера, в которой он ищет файлы при обращении к нему.
>В твоем коде XSS. Почитай урок https://github.com/codedokode/pasta/blob/master/security/xss.md
>
Понял, спасибо. Тогда так
article.php?id=<?php echo htmlspecialchars($article['id'], ENT_QUOTES); ?>
Не знал, что надо фильтровать любые данные, думал только те, которые можно подставить через get или через формы. И сейчас честно говоря пока не понимаю зачем. Если у меня допустим эта переменная лежит в базе (и у этого поля тип INT), то это только чтобы перестраховаться на случай, если злоумышленник влезет в базу или есть еще какие-то способы подменить значение таких переменных?
МММ... какие остальные? Если ты имеешь в виду что тебе мешает эта тупая форма на экране, то вот тебе хинт.
Естественно проверить их нельзя никак, увы.
Нужно указывать сравнение или выбирать какую то конкретную кодировку?
Алсо, я видел в интернете на десятках источников предлагают непосредственно в PHP при каждом соединении с БД устанавливать кодировку на сессию, но разве это выход? Это ж накладные расходы по времени при каждом соединении.
Прости, анон, что не написал вчера и, скорее, всего, не напишу сегодня. Просто Я ДОЛЖЕН ПРОИЗВЕСТИ ИНВЕНТАРИЗАЦИЮ ВЫБРОСОВ ВРЕДНЫХ ВЕЩЕСТВ В АТМОСФЕРНЫЙ ВОЗДУХ.
>>949875
У нас школа другого плана.
>>949876
Да я вообще хотел сделать сайт на укозе каком-нибудь, кому какая разница? Но нет, директор хочет сайт на домене второго уровня, и сам сайт заказал у каких-то левых типов.
Можешь немножко отсыпать статей?
>Файл помещаем на диск, после этого в таблицу - относительный путь к нему. Для уменьшенной картинки можно либо формировать путь из пути к основной, либо хранить в базе оба пути.
>Всегда надо сначала сохранять файлы, а только потом записывать в БД, чтобы не было такого, что запись в Бд есть, а файла нет. Удалять в обратном порядке.
>Так как у тебя к записи можно приложить несколько картинок, нужна отдельная таблица для них.
>Еще какие-то полезные вещи могут быть в комемнтариях к задаче про файлообменник в ОП посте.
В общем, понятно. Буду делать таблицу.
>Файл .htaccess нужно настроить. Напиш, что именно тебе нужно. Скорее всего перенаправлять все запросы на index.php
Задачка про студентов.
Вот ты не вбросил текст заданий и зря - мне попались другие. Твоё 3-е на JS в одну строку:
let third = (str) => str.concat('_').match(/.{2}/g);
https://jsfiddle.net/ans4w1q1/
По второму: непонятно почему ты запрещаешь использовать float/double - в PHP есть функция is_numeric. Твоё первое задание не понял.
>>950270
В исходном коде страницы (Ctrl+u в Firefox) можно найти задания.
Но я посоветую зайти хотя бы на codewars - там задания в меру сложные, но без олимпиадного задротства как на codeforces.
Хуле фронточервь может о вебе в целом знать?
И что он там взамен предлагает? MVC в вебе штука настолько удобная, что я вот никак не пойму какие там альтернативы могут быть.
Он, небось, намекает на ивент драйвен в духе ноды (аналоги уже повсюду есть). Но тут такое. Где-то будет лучше, где-то будет хуже такой подход. Поидее фронт это не должно беспокоить, просто жсеры обязательно играются с нодой, и вот результат.
Лет 10 назад все ржали над жс, теперь просто достают елду и начинают молча, мрачно и сосредоточенно дрочить на его достижения и возможности.
Устарели ли сейчас сессии?
>Flux
Ой, ебал. Прямо вся суть жспетушни - "выучи стопицот фреймворков и еще по десятку в месяц учи и получи работу за еду".
Лет 10 назад я еще не знал, что в эту тему залезу.
Пописываю на ноде микросервисы, выполнить на ней здоровущий проект с жесткой бизнес логикой желания не возникает, во всяком случае сейчас. Продроченным жсерам либо похуй, либо они идейно сопротивляются присутствующим неудобствам. Редуксы ваши тут тоже не серебряная пуля нихуя, да и не ново это ниразу.
>>95058
Хе-хе, самое смешно что я так и не получил удобоваримого объяснения что такое flux. Идея MVC зато проста как лопата. >>950588 А что было раньше.
Срачи разводить вы горазды, зато вопрос задашь - как хуев в рот набрали , хоть бы одна жопа пернула.
> let third = (str) => str.concat('_').match(/.{2}/g);
чем это лучше чем
funcion third(str) { ... }
Блин, не то написал, результат работы цикла, в голове просто вертелся вариант решения через массив
Вообще, если погуглить, можно найти описание: https://facebook.github.io/flux/docs/in-depth-overview.html#content
Сначала конечно надо изучить реакт, так как эта система под него заточна. Реакт, как известно, это библиотека, реализующая view, а flux видимо должен помочь реализовать остальные части.
Вполне возможно что оно заточено под специфические нужды фейсбука (реализация интерактивных интерфейсов на отдельных страницах сайта).
Я особо в нее не вникал и что-то прокомментирвоать трудно. Если кто-то хочет на флуксе и реакте сделать задачу на SPA из Оп-поста - всегда пожалуйста.
В смысле как записать? Берешь и записываешь. Покажи лучше задачу что ты хочешь реализовать.
Cуть не в стрелочных функциях, они там только ради читабельности. Суть в том, что для решения той задачи не нужны цикл+иф как у того анона, достаточно коротенького регулярного выражения.
>>950626
Ну а чего ты пропускаешь темы, вот паста про ООП и задачи: http://archive-ipq-co.narod.ru/l1/pasta.html
Работать закончил, покормлю.
А нахуй тебе нужно спрашивать про флукс, если ты сам знаешь что это?
В двух словах способ управления данными, основанный на хранилище (хранит модели и работает с ними), диспетчере (регистрирует и дергает ивенты между хранилищем и вьюхой), ну и вьюха, которая без задней мысли в любой непонятной ситуации перерендеривается по причине изначальной ориентации на реакт.
Пойдем дальше. Этот инновационный паттерн родился по той причине, что некоторые фронты чувствовали потребность в решении извечной проблемы "МЫ ЗАПУТАЛИСЬ В СВОЕЙ ЛАПШЕ, СПАСИТЕ". Проебываем и еле находим состояния во всяких ангулярах, нокаутах и прчоем, скопы все перемешались и ебут друг друга в жопу и уже нет архитектуры, просто каша, да ко всему нормального паттерна для работы с новой мокрой писечкой реактом нет, а без гайда мы удобную архитектуру выстроить не в состоянии - и тут снизошло откровение от фейсбучных гуру "а давайте все данные держать в куче и изолируем их нахуй".
На самом деле ничего плохого, удобство присутствует, и фронт пилить в этом стиле очень даже неплохо, но и новизны тут особой нет, просто фанатичные жсеры снова подхватили велосипед с неуемной энергий и в лучших традициях баранов пытаются притащить свою моду в каждый чужой монастырь. А идея, тем временем, не нова, и встречалась во множестве проектов, где оказывалась к месту. У меня на работе в одном из приложений на андроид реализована практически такая же архитектура для некоторых целей. Все просто и наглядно, притом о флуксе вообще никто не думал, когда пилили. Была задача - нашлось ее решение. И все же это не спасительная таблетка.
Теперь к изначальному тезису - мвс в вебе качается не только фронта. Переходим к беку - там у нас, во первых, есть самые настоящие хранилища в виде бд и слоя с моделями на любом фреймворке, не в дикие времена ведь живем. А вот нахуя изобретать диспетчер событий, когда у нас в целом исполнение приложения линейное? В реализациях схожих с нодой (а этого добра уже прилично) это тоже нахуй не уперлось, т.к. в беке вьюха не занимается тем, что судорожно перерисовывается на каждый чих, и отдельно взятый запрос все равно остается линеен, не говоря уже о том, что значимая часть бекенда это различные апи и им в принципе нихуя рендерить не нужно. Вебсокеты всякие и без того сильно отличаются от обычного бекенда, так и там хранилищем выступает какой-нибудь редис, у которого и так под любой изврат из коробки находится решение, и вьюх тут вообще не существует. Впрочем тут еще концепция флукса сама собой хорошо проявляет себя. В целом в беке как было удобно мвс, так и осталось. Флукс сюда тащить попросту не за чем, это наркомания самая настоящая.
Работать закончил, покормлю.
А нахуй тебе нужно спрашивать про флукс, если ты сам знаешь что это?
В двух словах способ управления данными, основанный на хранилище (хранит модели и работает с ними), диспетчере (регистрирует и дергает ивенты между хранилищем и вьюхой), ну и вьюха, которая без задней мысли в любой непонятной ситуации перерендеривается по причине изначальной ориентации на реакт.
Пойдем дальше. Этот инновационный паттерн родился по той причине, что некоторые фронты чувствовали потребность в решении извечной проблемы "МЫ ЗАПУТАЛИСЬ В СВОЕЙ ЛАПШЕ, СПАСИТЕ". Проебываем и еле находим состояния во всяких ангулярах, нокаутах и прчоем, скопы все перемешались и ебут друг друга в жопу и уже нет архитектуры, просто каша, да ко всему нормального паттерна для работы с новой мокрой писечкой реактом нет, а без гайда мы удобную архитектуру выстроить не в состоянии - и тут снизошло откровение от фейсбучных гуру "а давайте все данные держать в куче и изолируем их нахуй".
На самом деле ничего плохого, удобство присутствует, и фронт пилить в этом стиле очень даже неплохо, но и новизны тут особой нет, просто фанатичные жсеры снова подхватили велосипед с неуемной энергий и в лучших традициях баранов пытаются притащить свою моду в каждый чужой монастырь. А идея, тем временем, не нова, и встречалась во множестве проектов, где оказывалась к месту. У меня на работе в одном из приложений на андроид реализована практически такая же архитектура для некоторых целей. Все просто и наглядно, притом о флуксе вообще никто не думал, когда пилили. Была задача - нашлось ее решение. И все же это не спасительная таблетка.
Теперь к изначальному тезису - мвс в вебе качается не только фронта. Переходим к беку - там у нас, во первых, есть самые настоящие хранилища в виде бд и слоя с моделями на любом фреймворке, не в дикие времена ведь живем. А вот нахуя изобретать диспетчер событий, когда у нас в целом исполнение приложения линейное? В реализациях схожих с нодой (а этого добра уже прилично) это тоже нахуй не уперлось, т.к. в беке вьюха не занимается тем, что судорожно перерисовывается на каждый чих, и отдельно взятый запрос все равно остается линеен, не говоря уже о том, что значимая часть бекенда это различные апи и им в принципе нихуя рендерить не нужно. Вебсокеты всякие и без того сильно отличаются от обычного бекенда, так и там хранилищем выступает какой-нибудь редис, у которого и так под любой изврат из коробки находится решение, и вьюх тут вообще не существует. Впрочем тут еще концепция флукса сама собой хорошо проявляет себя. В целом в беке как было удобно мвс, так и осталось. Флукс сюда тащить попросту не за чем, это наркомания самая настоящая.
Жабогосподин в треде, приходилось недавно в проекте работать с React+Redux+TypeScript, как же заебала эта параша.
Суть там в SPA, т.е. вместо нескольких страниц существует одна, которая динамически меняется (т.е. ее DOM). Например, убирается окно логина (в виде <div> компонента), отображается другое окно, с профилем пользователя. Плюс у каждого компонента хранится состояние, ну типа чтобы реже обращаться к базе.
На MVC с шаблонами все это реализуется намного проще, а данные из базы можно кэшировать. Но хуесосы весь фронтенд перевели на этот Flux (Redux - одна из его реализаций). Ебал я в рот это говно.
Натыкался на него, когда набирал в гугле КОСТЫЛЬ1 vs КОСТЫЛЬ2, а сейчас не могу найти.
JS как был недоязыком уровня бейсика, так и остался. Еще лет через 10 в каждом браузере будет WASM, и от него наконец-то избавятся.
Вот я кстати думаю, что рендеринг через реакт хорош для задач вроде обновление циферок на странице, но такие вещи, как появление нового окна, переключение вкладок, в общем, навигация, лучше делать не через реакт. Так как иначе мы должны в страницу вставить кучу скрытых окон, причем они возможно будут пересчитываться при каждом изенении, то есть как-то неэффективно это выглядит.
То есть лучше сделать это окно логина отдельной сущностью со своим контекстом, который мы активируем при появлении и отключаем при скрытии.
Вообще, у меня такое ощущение, что реакт делался не для полноценных SPA приложений, а для мини-приложений, интерактивных интерфейсов в рамках страницы. Чтобы там можно было нажимать кнопки, и менялись какие-то циферки.
Я тут вижу кучу недостатков:
- у wasm кода нет доступа к DOM, значит JS-прослойка нужна
- wasm код это результат компиляции, неудобно при разработке, после любой правки надо перекомпилировать код, в то время как с JS таких проблем нет
Так что я за то, чтобы не заменять JS, а не использовать его без надобности, а если использовать, то писать правильный код, а не брать вкатывальщика, который до этого работал менеджером по продажам и единственный его талант - врать не краснея.
>В двух словах способ управления данными, основанный на хранилище (хранит модели и работает с ними), диспетчере (регистрирует и дергает ивенты между хранилищем и вьюхой), ну и вьюха, которая без задней мысли в любой непонятной ситуации перерендеривается по причине изначальной ориентации на реакт.
Нихуя не понял, а чем оно от мвц отличается?
> у wasm кода нет доступа к DOM
Это допилят, JS ведь тоже хотят запускать через WASM. Значит, будут все возможности.
>wasm код это результат компиляции, неудобно при разработке, после любой правки надо перекомпилировать код
Пакетный менеджер будет компилить и запускать. Как сейчас TypeScript, по одной команде npm start выполняется пересборка и запуск.
Лол чем хуев JS? Обычный язык, проблема то в вебе. Натаскали хворосту , хуев собачих, говен кошачих, и все шо было в доме и давай кашу из топора варить. Кто шо хочет, то и кидает в каструлю.
У тебя нет контроллера. У тебя есть вью, есть модель и хранилище. А еще есть диспетчер, принимает события от вьюхи и регистрирует события на изменения хранилища. Вьюха (обычно через фабрику называемую action creator) отправляет события диспетчеру, тот на них реагирует, харнилище чего-то там с моделями творит, по итогу зарегистрированные на изменения события вызываются, и по канону связанному с реактом вьюха без всяких подумать просто перерендеривается целиком (типа так можно, потому что реакт на виртуальном доме работает, там оверхеда нет для реального дома при рендере)
>отправляет события диспетчеру
Правильнее даже сказать команду.
И да, это во многом очень похоже на мвс.
Она похожа, но там есть разница. В MVC контроллер может дергать любые методы модели, получать данные, менять данные. А тут у нас есть диспетчер, и у него N методов для изменения данных в модели. То есть диспетчер + хранилище примерно соответствуют модели из MVC. Через диспетчер ее можно менять, с другой стороны view ее может читать.
И важный момент в том, что сторы подписываются на события в диспетчере.
Вообще, я плохо это все представляю, как например там делаются формы и валидация. Где хранятся данные формы, как валидируются, как выводятся ошибки, и тд.
Если мы храним модель формы и ошибки внутри хранилища, то должны тогда в диспетчере делать методы на изменение каждого поля в каждой форме? Или делаем один метод для всех полей? Один метод для всех форм? Кто работал с реактом, напишите, интересно.
Python намного продуманнее. Например, там нет автоматического преобразования типов.
Так это и есть неудобно. Смотри сам:
- с JS: отредактировал файл, обновил страницу. В отладчике виден код, можно ставить брейкпойнты, выводить выражения
- с другими языками: надо ждать пока все перекомпилируется, отлаживать нормально нельзя, так как в отладчике будет виден JS
В случае с wasm отлаживать вообще придется ассемблер.
Я думаю, он для тех случаев, когда нужны какие-то производительные вычисления. Например, аудиотрек сконвертировать, PDF отобразить. На практике конечно будут использовать для просчета анимированных рекламных баннеров.
А может какой-нибудь маньяк додумается сделать фреймворк, чтобы вместо HTML сделать канвас на весь экран и на нем рисовать сайт с помощью wasm. Преимущества: нельзя масштабировать, прокрутка работает так как решил автор кода, нельзя выделять текст, сохранять картинки, блокировать рекламные баннеры.
О, а еще можно скопилировать вебкит в wasm чтобы избавиться от разницы в поддержке технологий браузерами.
И тайп хинтов нет. Там вообще статической типизации нет.
Вот мне интересно, а как работают с большими проектами на Питоне? Можно ли в IDE кликнуть по методу и перейти к его определению?
Я тут пробовал открыть большой проект в Eclipse и обнаружил косяк - она не может перейти к методу, если не знает, какого класса объект. То есть в случае использования DI контейнера вроде :
$doctrine = $container->get('doctrine');
$doctrine->method();
Она не знает класс объекта $doctrine и не может перейти к method. ПРиходится копировать имя метода, и вызвать диалог "Search method", где он и ищется.
Для сравнения, Sublime text 3 не анализирует код, а лишь индексирует имена методов и классов. И он умеет переходить к определению, ища метод по имени. Правда, если там распространенный метод вроде get, он вываливает список всех классов, где он определен, что минус.
В общем, я плохо представляю как с большими проектами на Питоне работать. А как понять, данные каких типов нужны функции?
Плюс, там меня напрягает необходимость писать self в методах. что за атавизм?
Из тех языков, которые хорошо реализованы - это наверно C#. Вижуал студио делает полноценное автодоплнение, умеет переименовывать методы, и перед каждым методом даже пишет, сколько раз он используется.
> А еще есть диспетчер, принимает события от вьюхи и регистрирует события на изменения хранилища.
Короче, это когда бородые хипстеры объебались перебродишим смузи и решили переименовать MVC.
Примерно. Потому что с mvc в том же ангуляре справиться было непосильной задачей.
спасибо! не знал про codewars
>Зачем вбрасывать исключение при проверке данных введенных пользователем?
Низачем. Не слушай наркомана. Кидать исключение при неправильном заполнении пользователем формы это bad practice. Суть исключений в том, чтобы выбрасывать их, когда ход программы пошел не так, как было задумано - т.е. против твоего изначального замысла. А ввод пользователем неправильного имейла или формата телефона не должен выбрасывать исключений, это абсолютно регулярное и постоянно происходящее, нормально, адекватное событие. То что кто-то оформляет таким образом обычные сообщения о неправильно заполненной формы очень и очень дебилистичностранно. Можно таким же образом вообще без вьюшек обойтись и бросать исключения тут и там. Но исключения предназначены не для этого.
Хз, мне охуенно удобно. До этого было без исключений, был ад. Речь о внешнем рест апи, вьюхи я хз нахуя ты приплел.
Lisp тоже продуманый и че? Тут же как в той пасте про перфициониста выдрачивающий продукт и васян четкий который выбросил продукт самый первый. Продукт выброисл на рынок корявый и забаженый, но первый. И пока перфик выдрачивал свой продукт еще, вася четкий патчил свое поделие и выпускал обновления. И пока перфикцтонист доедал хуи без соли, васян разбил второй лексус.
Бля сука, ну я пишу откровеную хуйню, а вы блять на обычный вопрос не отвечаете.>>950676
phpstorm клевый, но пока он запустится, пропадает желание кодить.
Пользуюсь brackets что на линуксе, что на виндовсе, и вроде бы все неплохо, но он ориентирован на фронт + недостает автоподставлений имен функций итд.
Да.
PHP storm IDE а не редактор.
Там можно не только набирать код, но и подключить те же базы данных, композер, в нем есть консоль. Автодополнение переменных с баз данных, опять же. Там встроен GIT, и UI к нему оформлен просто отлично. Можно коммиты на гитхаб отправлять, прямо из редактора. Да много чего, проще сказать что он не делает.
тормозит
прям ужасно. Пока запустится - я умру. У меня атом, обмазанный тем же функционалом, запускается быстрее и работает идеально, но я от него отошел, т.к пересел за бракетс. В нем идеально все, кроме автозаполнения я по невнимательности иногда допускаю мелкие ошибки и в итоге все ломается к чертям
пропустил твой ответ.
Вим не очень хочу, т.к он довольно-таки своеобразный и надо выделять пару дней на его изучение, чтоб нормально в нем работать, а потом еще пару, чтоб дополнения, а потом я еще свое захочу написать, в итоге забуду зачем он мне.
Нетбинс попробуй, только качай только пакет где хтмл/цсс+пхп+жс что бы не тормозило. По части всяких автодополнений годнота не хуже шторма, но всякие фишки типа встроенного гита и композера похуже, естественно. Зато швабодно и шустро работает.
А ты знаком с протоколом HTTP и таким понятием как "заголовки ответа"? header просто добавляет заголовок к HTTP-ответу. Также она может задавать код статуса (404, 503, 302 и тд).
Он был нужен в Apache 2.2, если реврайт делается не в корне сайта, а в папке в нем. Ну например если мы хотим реврайтить /folder/x на /folder/x.php и htaccess находится в /folder.
В Apache2.4 не нужен.
Попробовал в нетбинсе подключится у БД, охуенно удобно. Даже не знал о такой функции.
А как ты это сделал? Гит да, композер да, но бд как? А то я mysqlworkbench юзаю.
>экранировать
Это как? Что значит экранировать? Ещё одни скобки поставить?
Извиняюсь за несколько сообщений сразу, просто пока я читал эти слова, вызвал сатану.
>квантификатор, означающий 1 или более вхождений
Вхождений чего и куда?
и вот там есть такая функция
public function addPost(Post $post)
{
// Проверим, что объявления еще нет в списке
if (null !== array_search($this->posts, $post, true)) {
throw new \Exception("Post already added");
}
Что обозначает (Post $post) ? Из переменой зразу лепят обьет класса Post?
открой свою залупу в хроме, нажми ctrl+p, выбери печать в пдф и не еби себе мозги
Это тайп-хинт: http://php.net/manual/ru/functions.arguments.php#functions.arguments.type-declaration
Он указывает, значения какого типа можно передавать в функцию.
Он делает код понятнее и защищает от ошибок.
>>951054
Я бы не сказал, что он не востребован совсем. Есть проекты на Питоне, но начинающим там конечно не особо рады, нужны опытные разработчики. Также часто его используют как вспомогательный язык, для написания каких-то простых скриптов.
Ну а оценить востребованность по моему нетрудно поиском на сайте с вакансиями.
Вообще, редко такое бывает, что достаточно знать один какой-то язык. Обычно нужно знание какой-то области, например: веб-разработка, десктопные приложения, приложения под Андроид и тд.
>>951012
Кроме печати в PDF, есть еще утилиты для командной строки, преобразующие HTML в PDF.
>>951010
Вхождений символов из регулярки в строке. "вхождение" тут значит "в строке встречаются символы, которые указаны в регулярке".
Это слово используется примерно так: "в строке abcabc найдено 2 вхождения подстроки bc". "Подстрока" - значит часть строки.
Квантификатор - это символ, указывающий на то, что предыдущее выражение может повторяться. Например, плюс, звездочка: a+ значит "1 или более повторений буквы a".
Это тайп-хинт: http://php.net/manual/ru/functions.arguments.php#functions.arguments.type-declaration
Он указывает, значения какого типа можно передавать в функцию.
Он делает код понятнее и защищает от ошибок.
>>951054
Я бы не сказал, что он не востребован совсем. Есть проекты на Питоне, но начинающим там конечно не особо рады, нужны опытные разработчики. Также часто его используют как вспомогательный язык, для написания каких-то простых скриптов.
Ну а оценить востребованность по моему нетрудно поиском на сайте с вакансиями.
Вообще, редко такое бывает, что достаточно знать один какой-то язык. Обычно нужно знание какой-то области, например: веб-разработка, десктопные приложения, приложения под Андроид и тд.
>>951012
Кроме печати в PDF, есть еще утилиты для командной строки, преобразующие HTML в PDF.
>>951010
Вхождений символов из регулярки в строке. "вхождение" тут значит "в строке встречаются символы, которые указаны в регулярке".
Это слово используется примерно так: "в строке abcabc найдено 2 вхождения подстроки bc". "Подстрока" - значит часть строки.
Квантификатор - это символ, указывающий на то, что предыдущее выражение может повторяться. Например, плюс, звездочка: a+ значит "1 или более повторений буквы a".
Спасибо, нашел. Действительно прикольная штука, все необходимые действия с базой легко доступны. Не вижу только где делать экспорт/импорт, ну да и хуй с ним.
Экранировать - значит поставить бекслеш перед символом, который лишает его специального значения. Ну например,
a+ - значит должно быть 1 или больше повторений буквы a
a\+ - значит искать символы a и плюс, без какого-то специального смысла
При экранировании надо учесть, что бекслеш имеет специальное значение в строках в одинарных и двойных кавычках: http://php.net/manual/ru/language.types.string.php
Ну например, \$ вставляет в строку просто знак доллара:
echo "\$"; // выводит $
Допустим мы хотим в регулярке искать знак доллара. Так как это спецсимвол, мы должны его экранировать как \$. Но если мы напишем "\$" то PHP создаст строку из символа доллара, без слеша. Потому мы должны дополнительно заэкранировать бекслеш, чтобы он передался как есть:
echo "\\$"; // выводит \$
Эти сложности из-за того, что бекслеш используется для экранирования на 2 уровнях:
- сначала при интепретации строки в двойных кавычках
- затем, в регулярке
Самый сложный случай - это если ты хочешь искать безслеш регуляркой. Согласно правилам регулярок, мы должны его заэкранировать и писать так:
\\
Но в строках бекслеш имеет специальное значение, и чтобы вставить в строку бекслеш, мы должны его записать дважды. Так как тут бекслеша два, то мы должны вписать в итоге 4 бекслеша. Проверим:
echo "\\\\"; выведет \\
Если использовать строки в одинарных кавычках, то там комбинаций с бекслешем меньше и например \$ можно писать как есть (а можно и как \\$). Также, если использовать синтакси nowdoc, где бекслеши не интепретируются, то регулярку можно будет писать как есть:
echo <<<'EOF'
\\
EOF;
выведет \\
Экранировать - значит поставить бекслеш перед символом, который лишает его специального значения. Ну например,
a+ - значит должно быть 1 или больше повторений буквы a
a\+ - значит искать символы a и плюс, без какого-то специального смысла
При экранировании надо учесть, что бекслеш имеет специальное значение в строках в одинарных и двойных кавычках: http://php.net/manual/ru/language.types.string.php
Ну например, \$ вставляет в строку просто знак доллара:
echo "\$"; // выводит $
Допустим мы хотим в регулярке искать знак доллара. Так как это спецсимвол, мы должны его экранировать как \$. Но если мы напишем "\$" то PHP создаст строку из символа доллара, без слеша. Потому мы должны дополнительно заэкранировать бекслеш, чтобы он передался как есть:
echo "\\$"; // выводит \$
Эти сложности из-за того, что бекслеш используется для экранирования на 2 уровнях:
- сначала при интепретации строки в двойных кавычках
- затем, в регулярке
Самый сложный случай - это если ты хочешь искать безслеш регуляркой. Согласно правилам регулярок, мы должны его заэкранировать и писать так:
\\
Но в строках бекслеш имеет специальное значение, и чтобы вставить в строку бекслеш, мы должны его записать дважды. Так как тут бекслеша два, то мы должны вписать в итоге 4 бекслеша. Проверим:
echo "\\\\"; выведет \\
Если использовать строки в одинарных кавычках, то там комбинаций с бекслешем меньше и например \$ можно писать как есть (а можно и как \\$). Также, если использовать синтакси nowdoc, где бекслеши не интепретируются, то регулярку можно будет писать как есть:
echo <<<'EOF'
\\
EOF;
выведет \\
>>950808
Sublime Text 3 не тормозит, но это просто редактор, не IDE.
Чтобы им эффективно пользоваться, надо выучить полезные горячие клавиши.
Он умеет переходить к определению класса или функции.
Автодополнение только по словам из текущего файла.
>>950807
Это не всегда работает. Вот эппл например, нельзя сказать, что она жертвует качеством, и вполне себе успешная компания.
>>950801
Так ты можешь то же самое решить и без исключений, используя например возврат значения вместо выброса исключения:
list($error, $result)= $service->doSomething($data);
if ($error) {
вернуть ответ с ошибкой
} else {
вернуть $result;
}
Другой вопрос, что если у тебя код бестолково написан, и ты хочешь из любого места кода возвращать ошибку, а не только из doSomething() - но это скорее всего просто говорит о том, что код некачественный. И добавляя исключения ты его качественнее не делаешь.
>>950799
Еще эта система с исключениями не работает, если тебе надо вернуть информацию о нескольких ошибках.
>>950808
Sublime Text 3 не тормозит, но это просто редактор, не IDE.
Чтобы им эффективно пользоваться, надо выучить полезные горячие клавиши.
Он умеет переходить к определению класса или функции.
Автодополнение только по словам из текущего файла.
>>950807
Это не всегда работает. Вот эппл например, нельзя сказать, что она жертвует качеством, и вполне себе успешная компания.
>>950801
Так ты можешь то же самое решить и без исключений, используя например возврат значения вместо выброса исключения:
list($error, $result)= $service->doSomething($data);
if ($error) {
вернуть ответ с ошибкой
} else {
вернуть $result;
}
Другой вопрос, что если у тебя код бестолково написан, и ты хочешь из любого места кода возвращать ошибку, а не только из doSomething() - но это скорее всего просто говорит о том, что код некачественный. И добавляя исключения ты его качественнее не делаешь.
>>950799
Еще эта система с исключениями не работает, если тебе надо вернуть информацию о нескольких ошибках.
Я еще у себя включил синхронизацию с ФТП, тоже очень удобно, сохранил файл и он сразу обновился на сервере. Также недавно начал коммитить в гит прямо из нетбинса без юзанья командной строки.
Было тоже самое, что ты с возвратом описал. Попросту менее читаемо и все равно требуется обработчик исключений для перехвата говна, прилетевшего с чужого кода. Насчет качественно не качественно - работает стабильно, занимаюсь только поддержкой и пробросом новых маршрутов, на все уходит по несколько минут, в правках не нуждается, создание нового маршрута в среднем занимает строк 10 (в минимальном виде всего одну вообще).
Я тут еще много написал про внутреннюю работу, потому что критика (множество ошибок, логирование и тд) хз с какой колокольни берется, но стер. У меня исключения обеспечивают самую гибкую и при этом простую работу с ошибками из всех, что я видел. Но я не смогу в этом убедить авторитетов этого треда, так что впизду простынями тут расшаркиваться еще.
Пускай я буду говнокодером и закроем эту тему, потому что от выстраданного за 1.5 года опыта работы над такими задачами я от исключений в этом контексте не откажусь, как от наиболее прозрачного механизма возврата ответов с отличным от 200 кода. Сириусли, не убедите, просто останемся при своем. Новичкам тогда не советую, раз людям так моя система не нравится. Уточню еще, что говорил я об апи, для сайтов самих я такую схему не использую.
Ну вот, я тут теперь выгляжу злодеем, который предлагает сломать работающее решение. Мне это не нравится.
Я предлагал различать ожидаемые ошибки (клиент передал неправильные данные, в базе нет нужной записи) от неожиданных (не удалось соединиться с БД, нет записи, которая обязана быть). И для первых не использовать исключения. А для вторых - возвращать ошибку 503 без подробностей, логгировать в лог, чтобы разработчики их исправили.
Как-то ОП заскакал: это просто, а потом начинается адовый трэш, угар, содомия, вектор, вектор, пидор.
https://t.me/joinchat/AAAAAAlT02py0soe6xnbMw
Сотни талантливых программистов легко помогут вам в освоении РНР!
Потому что за первый ответ даётся 10 баллов, за второй 5, а за третий 30.
Ошибка в третьем ответе, поэтому всего 15 баллов.
Все верно.
Если ты дошел до последней главы, значит ты не просто случайно забредший анон, а как минимум, целеустремленный, и тебе можно давать задачи посложнее.
>If an object is converted to an array, the result is an array whose elements are the object's properties. The keys are the member variable names, with a few notable exceptions: integer properties are unaccessible; private variables have the class name prepended to the variable name; protected variables have a '' prepended to the variable name. These prepended values have null bytes on either side.*
Божечки, во что я ввязался...
Ты пропустил знак доллара, и проще всего запустить код и проверить.
>>951424
Это преобразование лучше бы вообще не использовать, как мне кажется.
А-а-а-а-а-а-а-а!
>>951465
>и проще всего запустить код и проверить.
Так и сделал. Строка не расширяется.
Мне редактировать же еще его надо, хотя тоже вариант, да.
>>951153
>Кроме печати в PDF, есть еще утилиты для командной строки, преобразующие HTML в PDF.
Попробовал популярный pandoc + miktex, при первой же попытке вывалился с критическими ошибками. Причем если просто от руки создаешь html + css, то нормально конвертит. Но чуть что более сложное, и он падает. Похоже в 2017 в мире так и не тула, чтобы html+css перегнать в любой подходящий для редактирования в редакторе формат. В итоге 5 часов писал свой скрипт для open office на office basic, который недостающую css разметку сам генерит уже в формате офиса, благо там немного разметки было.
Спасибо!
А вот тут: var_dump(strlen($employee->name)); выводит int(21), но ведь там Иван Иванов!
Какого, спрашивается? Там же должно быть int(11)?
Короче, я не понял, что такое с идеоне, но с латиницей всё работает: http://ideone.com/9UQfxt
mb_internal_encoding("UTF-8"); почему-то перестало работать, я не понял.
Что по задаче, верно?
типа 123
1 2
1-2-3 и тд
Почитай урок https://github.com/codedokode/pasta/blob/master/php/strings-utf8.md
>>951532
Не надо возлагать на класс пагинации задачу выполнения запросов к базе данных, и сразу все станет проще. Используй его только для расчета пагинации.
>>951522
На ideone сейчас вроде проблема с mb-функциями, они расширение mbstring не включили.
Ну вот в чём дело!
Спасибо, ОП. А то я помню же, что всё работало отлично с mb_strlen, а сейчас выдаёт ошибку.
Ну а так по задаче вроде нормально всё, следующий пункт делаю.
http://ideone.com/BN1WN0
>Constants do not have a dollar sign ($) before them;
>$this is a special variable that can't be assigned.
Ааааааааа! Нахрен там доллар, если ей нельзя присвоить значение?
$that = 10;
for ($this=1;$this < $that; $this++) {
echo $this;
}
Ну так например. $this же идеально для текущей переменной подходит.
Ну, увы тебе тогда. $this считай то же, как ключевое слово, зарезервировано языком. Оно хранит ссылку на текущий объект, этакое Я.
Ну и так исторчиески сложилось, что для простых счетчиков цикла используется i.
Потому что это зарезервированное слово. Точно так же ты не можешь назвать свою функцию for или echo.
в файле есть функция получения ссылки, объявленная приватный. Далее идет метод run, который собственно определяет нужный контроллер и экшен.
Квк мне вызывать получение ссылки?
$this->getURI();
self::getURI();
обе строки работают и вроде бы даже одинаково по скорости. Вкусовщина?
При работе с Апачом ошибки пишутся по умолчанию в лог ошибок Апача (под windows это обычно папка logs в папке Апача, под линукс это /var/log). Но все, конечно, зависит от настроек Апача и PHP.
Для себя ты можешь запускать код используя встроенный в PHP сервер, чтобы не мучаться с Апачом.
А так да, по апачу надо по идее отдельный подробный урок делать. Хотя вроде есть же документация на английском...
Шаблонизация не нужна, она тормозная. В php уже встроен краткий синтаксис циклов, он для шаблонов и подходит как раз.
$this вызывает через экземпляр класса, self только статические методы на самом классе. Php позволяет вызывать так же статический метод через $this, но это криво. Статические методы лучше не использовать, они ведут к созданию кривой архитектуры, т.к. с ними ты создаешь всякие синглтоны и не используешь инверсию зависимостей, что ведет к созданию тесной связи между классами. Их стоит использовать, когда тебе действительно нужен синглтон, например если предполагается одно соединение с БД на весь проект.
т.е в моем случае лучше зыс?
я, если честно, совершенно не вижу разницы. Так и так работает одинаково, так зачем трогать лишний раз?
Ознакомься с докой по статическим методам:
http://php.net/manual/ru/language.oop5.static.php
По скорости разницы нет конечно, только по структуре твоего кода. В нормальном коде не должно быть статических методов, они используются лишь в исключительных случаях, когда без них не обойтись. Если будешь городить статические методы везде, то быстро придешь к проблемам с архитектурой.
Ну вот, о чем я и говорю, вот челоек что то пытается посоветовать, но о чем он говорит не понятно....
Глупости пишешь. МНогие шаблонизаторы умеют компилировать шаблоны в PHP код.
И насчет "тормозная" - расскажи, какие ты тесты и измерения делал. Интуиция подскаызвает мне, что никаких не делал, а просто выдумал это все.
Мне лень тут расписывать преимущества шаблонизаторов, открой документацию по твигу, там есть сравнение с простыми php шаблонами.
>>951656
Не совсем так. Статические методы используются, если метод не привязан к конкретному объекту. Обычно это всякие вспомогательные методы.
Например... функция, которая генерирует случайный пароль или функция преобразования километров в мили.
Также, статические методы используются для создания статических конструкторов.
>>951658
Оба неправильно. Зачем вообще в роутере метод getURI? URL передается в роутер снаружи.
>Superglobals cannot be used as variable variables inside functions or class methods.
Чот не врубился, объясните.
Внутри функции или метода нельзя писать так
$name = '_POST';
var_dump($$name_);
Я бы советовал вообще никогда не использовать variable variables. Это плохо спроектированная и ненужная особенность языка.
Правильно ли я сделал то, что на скрине?
http://ideone.com/Zjk63v
Не пойму, для чего мы будем применять метод класса к $employee в цикле, когда проще сделать
$totalHours += $employee->getTotalHoursWorked();
$totalSalary += $employee->getSalary();
$totalOvertime += $employee->overtimeHours;
Это всё в цикле же сложится и посчитается.
Чую, не то делаю, но не пойму, объясните!
Или в том же методе getNormalHours($variable) нам и нужно было указать
return $variable += $this->hours;
И потом просто делать в цикле $totalHours = $employee->getNormalHours($variable)
?
Что-то такое?
>$totalHours = $employee->getNormalHours($variable)
То есть там будет так, наверное:
$totalHours = $employee->getNormalHours($employee->hours);
Ну а смысл?
Ты сделал неправильно. Ты сделал свойство overtimeHours, как будто бы это какая-то отдельное, независимое от других, свойство. Но это не так. Оно вычисляется из hours.
Соответственно ты вручную занимаешься теми подсчетами, которые нужно было переложить на компьютер. overtimeHours не надо вводить руками, надо просто взять hours и все, что больше 40 часов в неделю - это овертайм. А normalHours это соответственно все, что в пределах 40 часов в неделю.
Потому свойство overtimeHours не нужно, так как переработку всегда можно вычислить из значений в hours.
Спасибо за помощь!
Ну а как сейчас, всё верно: http://ideone.com/n2qlzR
?
Чувствую, что начинаю немного нащупывать суть ООП :3
Но пока боюсь дальше заглядывать.
Сложную конструкцию в getNormalHours() можно упростить с помощью функций min/max. А можно упростить еще сильнее, если вспомнить что normalHours + overtimeHours= TotalHours.
Попытался решить задачку из http://archive-ipq-co.narod.ru/l1/strings.html (задача "На словах ты Лев Толстой"), но вместо аккуратного результата получился мусор.
1.Как сделать перенос по строкам в рамках одной переменной?
2.Как исправить ошибку рендома, из-за которой получается одинаковый результат при генерации?
https://ideone.com/pf6Rn8
>Сложную конструкцию в getNormalHours() можно упростить с помощью функций min/max.
Хм, не понял, как это сделать. Ведь в min/max возвращается единственное большее или единственное меньшее значение в массиве? А у нас в массиве с часами может быть как угодно: [40, 50, 60, 45, 35].
>А можно упростить еще сильнее, если вспомнить что normalHours + overtimeHours= TotalHours.
Точно, спасибо: http://ideone.com/Tly7EQ
Первые две строчки однотипные, поэтому могут быть в цикле с for, где $i < 2.
Я впервые вижу, что такой текст на идеоне работает, раньше только с EOF работали переносы строк.
Что непонятно, давай вместе обсираться, я только вот доделал задачу и подошёл к копированию и клонированию объектов.
Домо аригато, сенсей!
И почти каждая - бесполезна.
Что это за конструкция ?
foreach ($question->answers as $letter => $answer)
Что за $letter => $answer, это что для того что бы letter воспринимался как массив? Больше никаких задач конструкция не несет?
А ты проверь, сделай вардамп внутри цикла и засунь туда обе переменные.
У меня палево в нике, давай свою или присоединись к нашей конфе новичков: https://t.me/joinchat/AAAAAAlT02py0soe6xnbMw
>let third = (str) => str.concat('_').match(/.{2}/g);
Вся суть, некоторым просто не дано быть программистами мне
Ты разносторонняя личность.
Присоединяйтесь к нашей группе!:
https://t.me/joinchat/AAAAAAlT02py0soe6xnbMw
Множество талантливых программистов, победителей олимпиад по математике, а также просто замечательных людей легко решат любую вашу задачу бесплатно!
Что ты имеешь в виду под "проверять"? Если ты хочешь проверить равна ли вся длинна строки, скажем, 15 - регулярка тут нахуй не нужна, используй встроенные средства языка для этой хуйни.
Если же количество символов это только часть того, что ты ищешь, то хуле нет-то?
^.{3,12}$ - найти любой символ (.) от 3 до 12 раз
Ну или там ^[a-z]{20}$ - найти строку ловеркейсных латинских букв ровно в 20 символов
Да я уже разобрался, просто мне эти регулярки напоминают черное колдовство. Например, не могу понять почему нельзя сделать диапазон типа a-Z, а надо обизательно писать a-zA-Z, уебство какое-то.
Алсо
/^[а-яА-Яa-zA-Z-']{1,10}$/u
Норм регулярка для валидации имени? Тире и апостроф для экзотических двойных имен, или там О'Коннелы всякие.
Если как упражнение, то наверно норм, хуй знает. Если в реальном ирл мире™ то валидировать номера телефонов, имена, имейлы и подобную хуйню регулярками - говно полнейшее, если меня родители уебанским именем на дохуя букв назвали, что мне, уже твоим сервисом нельзя воспользоваться?
>а надо обизательно писать a-zA-Z
потому что "-" это оператор диапазона, если посмотришь в таблицу символов юникода, ловеркейс и аперкейс символы сгрупированы отдельно друг от друга, так что диапазон a-Z нихуя в себя не включит то, чего ты ожидаешь.
> Если в реальном ирл мире™
А как еще можно валидировать? Без учета длинны что ли? Вообще расскажи в кратце как это в крутых фреймворках делается, что бы самому не лезть поперед батька в пекло.
Ну можно ебануться на отличненько как ютуб и позволить вообще всё, что угодно. Крутые фреймворки не думают за тебя, та же симфони позволяет указать разные требования к полям при валидации, типа "Не должно быть пустым" или "Может содержать только цифры", или кастомное какое угодно условие, тут вопрос не в регулярках, а в общей идее. Отсыпь юзеру символов двести по длинне и не ограничивай диапазон, если тебе норм с тем, что какой-то один из тысячи хипстер засунет туда залго и эмодзи. Если не норм, то всё равно, нету никакой причины вводить бессмысленные анальные ограничения на 10 символов в имени, или невозможности напечатать там какую-то польско-чешскую диакритику с точечками и хвостиками, или ещё что. Если же такая причина у тебя есть, и она хорошая - тогда ограничивай, хуле
Необходимо через стандартную хтмл форму получить пост запрос и внести результат в сессионный массив.(Тут проблем нет пока) Следующий ввод значения чтобы добавился следующим элементом без потери прошлого результат.
И когда наберется 5 элементов в массиве, то вывести его и провести сортировку, но это уже ерунда, сам справлюсь.
Помогите, молю!
Не проблема абсолютно, но как мне в цикле реализовать возможность ожидания ввода значения которое впоследствии окажется в массиве?
$array[$value] = $value прямо в цикле, будет тебе ассоциативный массив.
array_push($array, $value) - просто добавит значение в конец массива. Наверное ты вообще плохо усвоил основы работы с массивами.
Спасибо. Криво до жути, но получилось.
if (!isset ($_SESSION ['mass']))
{
$_SESSION ['mass'] = array (1,2,3,4,5);
$_SESSION ['attempts'] = 0;
}
$_SESSION ['mass'] [$_SESSION ['attempts']] = $_POST['arr'];
if ($_SESSION ['attempts'] < 4)
{
$_SESSION ['attempts']++;
}
else
{
session_destroy();
}
echo '<pre>';
print_r($_SESSION ['mass']);
print_r($_SESSION ['attempts']);
echo '</pre>';
Это не сишка, зачем массив сразу заполнять чем-то. А ещё твое условие считает от 0 до 3, это не 5 элементов, есичо.
Вангую что у тебя ssl в конфиге пхп не включен, эта залупа пытается по https сконектиться с своим сервером, жрет говно и, естественно, не показывает сообщение об ошибке, обходясь стандартным "что-то пошло не так". Ну или чего-то другого у тебя в системе не хватает, curl выключен, хуй знает,
Мне необходимо, чтобы со стороны сервера постоянно выполнялась определенная функция класса, которая будет выполняться, допустим, каждые 10 минут или в определенный момент времени (В 12:00 в субботу)? Функция должна выполняться с определенного класса, язык обязательно PHP.
В laravel можно как-то забиндить команды на таймеры, но ларавел мне сейчас не надо, я хочу решить эту проблему на чистом PHP. Может кто-то подсказать? Предлагайте решения, где гуглить, куда смотреть.
И еще, функция должна выполняться со стороны сервера. Уточняю: она не должна зависеть от того, что кто-то посещает сайт.
А, не дочитал, без лярвы. Все то же самое, просто пилишь голый пхп скрипт, добавляешь его в крон на запуск.
Спасибочки, дружище
ideone любит ломаться, палю годноту
https://3v4l.org/ хоть и немного не для того предназначен, но ваши скрипты в десять строк похуй где исполнять, а для чего-то поинтереснее придется поднимать сервер (учитывая что блядь в пхп уже встроен веб сервер который в одну строку поднимается, не вижу смысла возиться с онлайн хуитой вообще)
Годно! Спасибо! Удобнее идеоне раза в три.
Ставишь jenkins и выставляешь в нем по расписанию хоть 100500 php функций. Вывод сохраняется в истории дженкинса весь автоматом.
Что здесь у меня не так?
Что-то почва из-под ног ушла, не пойму, в чём обосрался.
Методы непонятные в классах с вопросами дублируются - вроде так нормик.
Не пойму, в чём дело.
Логика проверки ответа на правильность в разных типах вопроса разная. Потому в каждом классе будет своя реализация этого метода.
Но в твоем случае, у тебя код методов checkAnswers почти полностью совпадает в обоих классах. Копипаста - это плохо, и ее быть не должно. Это первая ошибка.
Вторая ошибка в том, что у тебя checkAnswers предполагает что все вопросы в массиве одинакового типа. Но они могут быть разного.
Третья ошибка: класс Question представляет один вопрос в тесте. Но метод checkAnswers работает не с одним вопросом, а с массивом вопросов, и наверно, в этом классе ему не место.
Тебе надо подумать, что в коде проверки ответов - общее для всех видов вопросов, а что для каждого вопроса свое.
Ну например, вот это:
> if (count($questions) != count($answers)) {
> die("Число ответов и вопросов не совпадает\n");
> }
Одинаково для всех видов вопросов.
Надо сделать так: внешняя функция checkAnswers принимает массив вопросов и ответов. И для каждой пары вопрос-ответ вызывает метод проверки на правильность. Вот этот метод проверки, правильный ли ответ к тесту, и должен быть описан в классах вопросов.
Перечитай внимательно 3 проблемы с твоим кодом, и попробуй понять их, чтобы больше таких ошибок не повторять.
Также, еще одна вещь. Допустим мы хотим добавить новый тип вопроса. Для этого мы должны создать класс, наследующийся от Question. А в нем сделать метод проверки ответа. Но это нигде не описано. Глядя только на класс Question, об этом никак не догадаться. Тут могут помочь абстрактные методы. Если все наследники класса обязаны реализовать какой-то метод, то надо объявить его как абстрактный метод в базовом классе. Тогда унаследоваться, не описав этот метод, будет нельзя. Ну и будет сразу видно, что мы обязаны добавить такой метод в класс-наследник.
Спасибо за разбор, бро, завтра уже постараюсь вдуплить и советы учту.
>Также, еще одна вещь. Допустим мы хотим добавить новый тип вопроса. Для этого мы должны создать класс, наследующийся от Question. А в нем сделать метод проверки ответа. Но это нигде не описано. Глядя только на класс Question, об этом никак не догадаться. Тут могут помочь абстрактные методы. Если все наследники класса обязаны реализовать какой-то метод, то надо объявить его как абстрактный метод в базовом классе. Тогда унаследоваться, не описав этот метод, будет нельзя. Ну и будет сразу видно, что мы обязаны добавить такой метод в класс-наследник.
А ведь у меня там так и есть:
abstract class Question
{
...
abstract function checkAnswers($questions, $answers);
}
По этой ссылке https://3v4l.org/fd5qV в классе Question абстрактных методов нет. Наверно ты уже позже там это дописал.
Наркоман штоле сука, у тебя в >https://3v4l.org/fd5qV у квесчена ни одного метода нету
Ну и если мы тут дрочим на правильное ооп, то тут вообще творится какой-то форменный пиздец.
В конце один из вопросов принимает в себя массив всех вопросов, одним и тем же методом проводит санити чек, сверяет ответы, печатает, играет на балалайке и вышивает крестиком.
По хорошему, у тебя должен быть класс, грубо говоря, игры, который и будет делать то, что сейчас делает checkAnswers, а один отдельно взятый вопрос должен только говорить, правильный ли ему вариант ответа предложили, или нет. Баллы-хуялы тоже должна играть менеджить, а не один ответ.
Сайт отличный, у него даже есть вкладка "VLD opcodes", которая показывает, в какие опкоды компилируется программа. Опкоды - это низкоуровневые инструкции (вида "взять число из переменной и прибавить к числу на стеке") в которые преобразуется программа, перед тем как ее выполнять.
>>953234
Ой, ребята, извините, я не разобрался с тем увалом просто.
Почему-то он при сохранении выдал другую ссылку: https://3v4l.org/bIDqI
Или я что-то напутал, извините.
Советы учту ваши, сейчас пока не менял то, что было вчера сделано.
SteamAPI только JS или на пыхе тоже можно писать?
Еще авторизация
Для работы с стим апи тебе в первую очередь нужен ключ, который получается тута http://steamcommunity.com/dev/apikey
Авторизация работает как обычный OpenID провайдер, так что найди библиотеку, которая работает с OpenID, если лень разбираться, и хоть на си, хоть на пыхе, хоть на аллахе пиши, получай свой токен, и делай хттп реквесты.
А вообще ты хуесосина очередную ебливую РУЛЕТОЧКУ КСГО ИЗИ ДЕНЬГИ пилишь, так что желаю тебе рака яиц и больше помогать не хочу.
Почему не любишь рулеточки-то? Спасибо за помощь
А у тебя выводятся сообщения об ошибках от БД? Если нет, сделай (и проверь), чтобы выводились, а то вслепую можно долго искать причину.
Ты пишешь в блокноте, поэтому иде тебе не могла подсказать насчет синтаксической ошибки и отключил сообщения об ошибках, поэтому реакция бд на твой запрос в стиле "что такое INSER нахуй начальник выпустите меня я не буду с этим запросом сидеть" тоже до тебя не дошла?
скачал PHP Version 5.6.30. Дошёл до уроков про ООП. Но у меня никак не работают функции mb_internal_encoding() и mb_strlen(). На всем форумах говорят скачать php_mbstring.dll
и в файле php.ini разкомментировать extension. .dll у меня уже было в папке ext, с .ini тоже разобрался (кстати, почему их два?). А всё равно ничего не запускается.
https://t.me/joinchat/AAAAAAlT02py0soe6xnbMw
Лучше программисты России помогут Вам своить РНР легко и непринужденно!
Раскомментировать нужно 2 строки:
extension_dir = "ext"
extension=php_mbstring.dll
После этого следует перезагрузить сервер, чтобы он перечитал конфигурацию.
Учимся дебажить пхп для самых маленьких, ебанарот.
Хуяришь файлик в котором написано
<?php
phpinfo();
исполняешь его, ищешь во-первых mbstring и смотришь, что про него сказано, во-вторых ищешь loaded configuration file и смотришь из какого именно пхп.ини твое пхп берет настройки (да, оно проверяет в нескольких местах, дил виз ит)
> (кстати, почему их два?)
production и прочие версии, это пресеты более безопасных настроек для продакшена, в отличии от разработки, и тп.
Ну вот, в этом твоя проблема. Ты вносишь изменения в конфиг файл, который пхп даже не читает. Почему оно его не читает, это уже другой вопрос. Начнем с тупого:
Ты уверен что у тебя файл называется php.ini, а не php.ini-dist, например?
Возможно в этом и проблема, что там none
Если ты запускаешь PHP скрипты через сервер и Апач, то в конфиге Апача надо указать путь к PHP файлу.
Вот есть такая большая статья в мануале: http://php.net/manual/ru/install.windows.legacy.index.php
Все, что относится к IIS, можно игнорировать, так как у нас Апач.
Там есть раздел "Установка PHP как обработчика под Apache"
В нем то, что надо вписать в конфиг Апача, и там:
> # конфигурирование пути к php.ini
> PHPIniDir "C:/php"
Тебе разумеется надо указать свой путь к папке с php.ini
У меня их 2: php.ini-development и .ini-production,
я разкомментировал всё что нужно в обоих файлах
У меня их 2: php.ini-development и .ini-production,
я разкомментировал всё что нужно в обоих файлах
Алсо апач на винде это вообще адов спермоцирк
В том же пхпинфо выше у тебя будет Configuration File (php.ini) Path, это путь, где система сейчас ожидает увидеть инишник, если там C:\Windows, значит пришло время ебаться с конфигом апача, который настолько охуевший, что PHPIniDir может хотеть чтоб ты написал "C:\php\zalupa", а может хотеть "C:\php\zalupa\"с трейлинг слешем в конце, а может хотеть слеши "/" вместо "\". У меня уже пичот от этой хуйни, как вспоминаю.
>>953626
Оно не так работает, бака.
Пхп хочет увидеть файл который называется php.ini, поэтому если ты хочешь использовать девелопмент конфиг, ты берешь файл -development и ПЕРЕИМЕНОВЫВАЕШЬ в php.ini
Ок. А пикрелейтед сам тогда исправится?
А хуй знает
Кто знает, ты при установке пхп должен был указать директорию, где она ищет инишник. Может исправится, может нет, на крайний случай можешь засунуть инишник в то место, которое в пхпинфо указано как Configuration File (php.ini) Path
Оп в своём мануале писал https://github.com/codedokode/pasta/blob/master/soft/php-install.md
что надо просто скачать архив и распаковать. Я так и сделал.
А это нормально, что
Configuration File (php.ini) Path - C:\Windows.
Хотя само PHP я скачал на D?
А вообще, всем спасибо за вашу отзывчивость
Спермовеселье на спермовинде, хуле.
Сам на ней сижу
Да, это нормально, если ты скачал архив, значит кто-то другой скомпилировал его за тебя и указал эти настройки за тебя. Ну и переменные среды в винде тоже не прописаны, очевидно. Если у тебя не хочет читать инишник из дефолтной директории, можешь поебаться с реджистри ключами http://php.net/manual/en/configuration.file.php
Не понимаю зачем ньюфагам этот пердолинг, бери и качай готовую сборку ептыть типа ксамп или опен сервер.
Так ты эцсамое, у тебя по пути D:\sperma\php5\php.ini есть теперь? В той же папке, где php.exe и прочая куча файлов, без продакшенов-хуякшенов в имени, просто пхп.ини? И дальше Loaded Configuration File (none) ?
И чем тебе не нравится? Просто пока ты нуфаг у тебя куча времени на это уйдет, а потом оно само собой все придет. Или почитай уроки ОПа, я уж не знаю куда проще чем у него разжевано.
Хуямп. Если ты их, как говоришь, выучил, то примеры того, зачем они нужны, должен был видеть в учебниках. Они нужны, чтоб разбивать твою систему на логические компоненты, если ты в теории понимаешь, что это, но все эти примеры с котиками и собачками, наследующими класс животное, и менеджерами и уборщиками, наследующими класс сотрудник это какая-то невнятная хуйня для тебя, то никто тебе не скажет магические слова, которые ВНЕЗАПНО обьяснят тебе, что такое классы и зачем они нужны. Гугли любые задачки по ООП и решай их, пока не почувствуешь сам, зачем.
Тут у человека с одним конфигом проблема, а ты предлагаешь ему целый стак из технологий навернуть, которые непонятно как работают, и вообще хер знает с какой стороны к ним подойти, если что-то сломается. Нюфане надо не только язык изучить, но и среду, в которой он вариться будет, тоже, даже если придется лишнюю неделю угробить на возню с конфигами и вырывание волос из жопы с воплями да почему ты не работаешь сука не могли всё проще сделать, в будущем окупится.
Если не ньюфаг, то почему элементарно не можешь проверить наличие расширения или хотя нагуглить как это делается?
>>953717
На примерах типа $котик->рычи() и правда тяжело разобраться в ООП.
Я вообще не он, я на твой совет отреагировал. Он же ничему не научится и не поймет вообще сути работы вебсерверов, если подсядет на игру ксампов и опенсерверов. Там развертка руками простейшая 10 минут всего, без изощренной ебли с конфигами, обо всем почитать можно, хоть на винде, хоть на линухе, хоть на аллахе.
А да хуй с ним, зря влез только.
Ты решал задачу про ООО Вектор отсюда: http://archive-ipq-co.narod.ru/l1/pasta.html ?
Без классов ее решать будет неудобно например (можешь попробовать и сравнить).
>>953626
Это лишь образцы файлов. Ты должен из них сделать php.ini
>>953630
Слеши должны быть прямые. Это написано в самом конфиге английскими буквами.
>>953633
А, тогда другой случай. Опять же, открываем мануал, главу "Установка" ( http://php.net/manual/ru/install.php ) и смотрим, как определяется путь к php.ini при запуске в командной строке:
http://php.net/manual/ru/configuration.file.php
> Директория веб сервера (для SAPI модулей), или директория PHP (иначе в директории Windows).
Звучит немного странно, потому я для верности посмотрел английскую версию:
> The web server's directory (for SAPI modules), or directory of PHP (otherwise in Windows).
Соответственно вопрос, куда ты положил php.ini? В ту же папку, что и php.exe? И он точно называется php.ini? Если редактировать файл блокнотом винды, то он может добавлять .txt
Ты решал задачу про ООО Вектор отсюда: http://archive-ipq-co.narod.ru/l1/pasta.html ?
Без классов ее решать будет неудобно например (можешь попробовать и сравнить).
>>953626
Это лишь образцы файлов. Ты должен из них сделать php.ini
>>953630
Слеши должны быть прямые. Это написано в самом конфиге английскими буквами.
>>953633
А, тогда другой случай. Опять же, открываем мануал, главу "Установка" ( http://php.net/manual/ru/install.php ) и смотрим, как определяется путь к php.ini при запуске в командной строке:
http://php.net/manual/ru/configuration.file.php
> Директория веб сервера (для SAPI модулей), или директория PHP (иначе в директории Windows).
Звучит немного странно, потому я для верности посмотрел английскую версию:
> The web server's directory (for SAPI modules), or directory of PHP (otherwise in Windows).
Соответственно вопрос, куда ты положил php.ini? В ту же папку, что и php.exe? И он точно называется php.ini? Если редактировать файл блокнотом винды, то он может добавлять .txt
Тут описан порядок поиска файла: http://php.net/manual/ru/configuration.file.php
В c:\Windows он ищет только если не нашел в других местах. Я советую просто положить рядом с php.exe.
>>953671
Все описано в мануале, надо просто открыть и прочесть. Ключи не нужны.
>>953711
Молодец, правильно мыслишь. Лучше сейчас научиться разбираться с такими проблемами.
>Слеши должны быть прямые. Это написано в самом конфиге английскими буквами.
Угумс~, и в всем конфиге стоят прямые слеши. Кроме ссаной PHPIniDir, где у меня стоят обратные. Если я сейчас пойду и поставлю там прямые, она перестанет работать. В LoadModule стоят прямые, в PHPIniDir обратные, иначе нихуя не работает. Почему - я до сих пор не знаю.
> Он же ничему не научится и не поймет вообще сути работы вебсерверов, если подсядет на игру ксампов и опенсерверов.
С тобой можно согласиться. Да только вот все равно дальше чем "браузер отправляет запрос на сервер - сервер возвращает ответ" он не разберется, лол. И смысла в начале глубоко копать я считаю нет, без какого-либо опыта в разработке оно будет мертвым грузом ему. Давайте еще учить ньюфагов конфигурировать апач, лол.
Сам я в php не умею пока что, могу немного в плюсыООП, STL, Win32 API, и совсем чуть-чуть во всякое другоенастолько чуть-чуть что нет смысла называть.
Но недавно мне предложили заказ, запилить биржу фриланса на студенческую тему. Типо такого:
https://studwork.org/
https://vbaze.com.ua/ua
https://megauniver.ru/author
Подскажите, реально ли запилить такое за месяц-другой, с учётом того, что свободное время у меня есть. Стоит ли писать движок с нуля, или использовать CMSесть ли для них годные реализации фриланс биржи? В общем, направьте на путь истинный, если не трудно.
>>953552
Я пишу в иде и внутри кавычек, где текст запроса, иде ничего не предлагает. Сообщения вкл, было что-то вроде sphinxql: unexpected IDENT near blalala. Естественно я полез в доки сфинкса что за идент и вообще, потом полез в консоль, и только потом случайно увидел что буковки то не хватает. Вобщем смысл рейджа в том что я просто в глаза продолбился полдня.
Дефайн "тебе предложили запилить". Верстка и дизайн тоже на тебе? Хуярить будешь в одиночку, а спрашивать будут как с высокобюджетной команды.
И самое главное - есть ли тех заказ и насколько он четкий и дерзкий. Если быстро новые технологии осваиваешь и не будешь тупить с понятиями роутинга, контроллера и прочей хуйни, ну за два месяца биржу сможешь сделать, эз ин там можно будет размещать обьявления, создавать аккаунты, писать заказчикам и оставлять отзывы. Если же весь заказ звучит как "сделай как вон там ёпт, ну ты ж компуторщик", то нахуй и впизду, просто завалят деталями, прикрути посредников, логи, рефанды, комиссии, десять разных апи оплаты, небо и аллаха. И всё за два месяца, да. Насчет готовых решений для такой хуйни ничего не скажу, увы.
С твоим опытом, мне кажется, если ты чего и сделаешь то это все равно дерьмо какое-то будет. CMS-ки тут вряд ли подойдут, лучше уже фреймворк какой взять
var dataToSend = {}
$.each(mySerializedArray, function(k, fieldData){
dataToSend[fieldData.name] = fieldData.value
});
отправляешь серверу JSON.stringify(dataToSend)
на сервере соответственно json_decode'ишь то, что получил
Да. Именно
Что у тебя до serializeArray происходит, ты уверен что данные до отправки на сервер это красивые пачки key value пар? Логируй данные на каждом этапе трансформации, хуй знает, что тут ещё сказать.
Ну и ещё
>serialize() не подходит так как возвращает строкове представление
как что-то плохое,
$meow = array();
parse_str($_POST, $meow);
Есть вакансия, которую я хочу занять, требования: "C++, Perl, PHP". Пишу на плюсах, с Перлом знаком. Не совсем понятно, что имеют ввиду, когда говорят PHP, так как без HTML или фреймворка это ничего не значит.
Перед тем, как буду откликаться и рубить правду матку и просить тестовое, спрашиваю у вас: что имеют ввиду, когда говорят "PHP"? Zend Framework кокойнить?
PHP имеют в виду PHP. Это как спросить что имеют в виду, когда говорят "С++"? QT кокойнить? Хуй знает, может фреймворк, может инхаус решение, может мейнтейн легаси говна, может всё вместе.
Да, структуру я не менял, до этого данные отправлялись обычным постом без ajax и на бэкенде был многомерный массив, сейчас мне надо разбить отправку на мелкие порции.
>как что-то плохое,
>$meow = array();
>parse_str($_POST, $meow);
Изначально форма была не особо большой, сейчас модуль вырос и передается единомоментно 1200 переменных, после serialize() я не смогу разбить строку таким образом, чтобы потом собрать целостные данные на PHP, поэтому я разбил массив на куски и отправляю их порционно по порядку (порядок тоже важен)
> Бекенд будет на yii, причем в виде REST api, а фронт будет на реакте и будет выполнятся еще на сервере (изоморфизм и все дела)
Изоморфизм подразумевает, что на сервере код будет на Node.JS и Yii тогда не подходит. Как ты это себе представляешь?
Мое личное мнение - выделение REST API это лишнее усложнение кода, так как во многих случаях проще написать 1 кусок кода на сервере, генерирующий страницу, чем 2 куска (генерирующий данные + код для фронтенда, интепретирующий эти данные).
>>953801
Что делает splice(0, 105)? ты просто выкидываешь част данных?
Насчет битых данных на сервере - может это какая-то проблема с отображением? Проверь:
- что возвращает serializeArray(), какие там данные
- как выглядит POST запрос (на вкладке Network), какие там данные
У тебя не обрабатываются ошибки при отправке AJAX или при декодировании ответа. Советую глянут мой урок про то как надо делать аякс-запросы: https://github.com/codedokode/pasta/blob/master/js/ajax.md
Я бы советовал не использовать $.post, а использовать $.ajax. Она возвращает джейквериевский аналог промиза так что тебе не надо будет создавать свой.
NEAR как раз указывает на то место, где (перед которым) ошибка. Очень полезно.
>>953809
На фреймворке наверно делать недолго.
>>953823
Ты как-то все переусложнил. Во-первых твой код не позволяет слать массивы с именами вида name[], во-вторых, какой смысл добавлять дополнительное перекодирование в JSON и обратно, если данные можно отправить напрямую?
Усложнение кода ради усложнения и модного 5 лет назад слова JSON.
>>953847
То представление, которое возвращает seialize(), по моему можно передать в $.ajax и оно придет как обычные POST-данные на сервер.
Вы бы изучили сначала multipart/form-data и apllication/x-www-form-encoded прежде чем JSON советовать.
>>953864
Без ООП, MVC, фреймворка, баз данных SQL это ничего не значит. Если есть время, можешь порешать наши задачки в ОП посте, рано или поздно все вышеперечисленное освоишь.
>>953895
Ты что-то где-то переусложнил. В PHP конечно есть ограничения на число входных данных, они настраиваются в php.ini, но тебе лучше бы подумать, как слать меньше данных за раз.
NEAR как раз указывает на то место, где (перед которым) ошибка. Очень полезно.
>>953809
На фреймворке наверно делать недолго.
>>953823
Ты как-то все переусложнил. Во-первых твой код не позволяет слать массивы с именами вида name[], во-вторых, какой смысл добавлять дополнительное перекодирование в JSON и обратно, если данные можно отправить напрямую?
Усложнение кода ради усложнения и модного 5 лет назад слова JSON.
>>953847
То представление, которое возвращает seialize(), по моему можно передать в $.ajax и оно придет как обычные POST-данные на сервер.
Вы бы изучили сначала multipart/form-data и apllication/x-www-form-encoded прежде чем JSON советовать.
>>953864
Без ООП, MVC, фреймворка, баз данных SQL это ничего не значит. Если есть время, можешь порешать наши задачки в ОП посте, рано или поздно все вышеперечисленное освоишь.
>>953895
Ты что-то где-то переусложнил. В PHP конечно есть ограничения на число входных данных, они настраиваются в php.ini, но тебе лучше бы подумать, как слать меньше данных за раз.
>Что делает splice(0, 105)? ты просто выкидываешь част данных?
Не выкидываю, я из переданного массива беру 105 первых элементов и передаю их в пост, дальше рекурсивном через промисы передаю остаток первоначального массива обрезая по 105 элементов за каждый виток рекурсии.
>как выглядит POST запрос (на вкладке Network), какие там данные
Пик 1
- что возвращает serializeArray()
Пик 2
>но тебе лучше бы подумать, как слать меньше данных за раз.
Минимум затрат по времени это просто слать данные кусками. Если менять способ сохранения - мне придется как минимум менять не только способ сохранения но и всю логику модуля, на что уйдет намного больше времени.
С php-v8 можно ебашить изоморфизм на пхп, но ящитаю слишком сыро и экспериментально, так что нахуй не нужно. Разбить на фронтенд и рест апи в принципе норм тема, если у тебя интерактивности дохуя на странице, магазины как раз из этой оперы.
if ($createAbsoluteURI && !substr($url, 0, 4 ) != "http") {
Нет, проблема была не в этом, проблема в обертке была { data : chunk_data, ... } почему это при отправке оборачивало часть ключей в [], отправил просто как chunk_data и прилетела нормальная структура: пик
>>953906
parse_url
Тогда уже я ничего не понимаю...
А можешь перед отправкой законсолить тип перменной chunk_data ?
ОПчик, не выебывайся. JSON был "модным" лет пять назад, сейчас это нативно поддерживаемый стандарт. В жкверивском аякс методе много подводных камней с отправкой урлэнкодед массивов из массивов, особенно если оставить dataType и contentType по умолчанию, так что если мне надо заниматься диагностикой по снипету кода из трех с половиной строк, я его пережму в жсон и не буду заниматься микрооптимизациями.
Какое отношение имеет
>Вы бы изучили сначала multipart/form-data и apllication/x-www-form-encoded прежде чем JSON советовать.
к посту >>953847 я вообще не понимаю.
"смеющаяся над долбоебом Саша Грей*
Эмулятор-хуятор, там всё можно на Ideone.com делать, можно на Apache+PHP+IDE/Блокнот/какое дерьмо по вкусу.
Разберем по частям тобою написанное, складывается впечатление..:
>if ($createAbsoluteURI(1) && !substr($url, 0, 4 ) !=(2) "http") {
1) Это тебе не JS, с $createAbsoluteURI нужно что-то сделать (проверить на пустоту, сравнить с чем-то), иначе будет хуйня.
2) У тебя PHP !умер !от рака
Какой эмулятор, чего вообще?
Хоть бы где ты запускал, echo и подобные будут куда-то печатать, в документ для браузера, в stdout, в твой эмулятор, что бы это не было.
Браузеру можно сказать что бы выводил ввиде обычного текста. Для этого нужно отправить http заголовок. Добавь в начале скрипта ДО любого вывода строку:
header('Content-Type: text/html; charset=utf-8');
Правда я не уверен, что кто-нибудь понял что ты хочешь.
Увы. Это не может не быть не косяком.
https://jsfiddle.net/svdgn8tm/
В ивентах написано по какому урлу находится скрипт, который их обрабатывает, ф12 твой лучший друг и всё такое.
А по теме могу отметить, что ты используешь event.target в обработчиках, и в этом случае ничего плохого в этом нету, но когда ты начнешь создавать элементы динамически и биндить к ним ивент хендлеры, незнание разницы между event.target и event.currentTarget укусит тебя за жопу.
Вообще, JSON тут имеет смысл передавать, так как у него 1200 полей, а у PHP есть ограничение на число элементов в POST, и подозреваю, онопо умолчанию ниже.
Еще есть ограничение на длину URL, 1000-2000 байт, если используется метод GET.
Но если большого числа полей нет, то никакого смысла использовать JSON для данных формы нет. Если писать код праивльно, то все должно передаться нормально.
Ну и использование JSON усложняет код. Например, ты должен строить многомерные массивы, которые пол умолчанию за тебя строит PHP при разборе POST-данных.
> В жкверивском аякс методе много подводных камней с отправкой урлэнкодед массивов из массивов,
Это называется "лень читать документацию" и по моему лучше ее читать, чем усложнять код без надобности и лепить костыли.
> так что если мне надо заниматься диагностикой по снипету кода из трех с половиной строк, я его пережму в жсон и не буду заниматься микрооптимизациями.
Это не оптимизация, а отладка и исправление ошибок. Данные из serialize() и serializeArray() можно передавать в $.ajax в поле data, ничего сложного в них нет, и content-type для них по идее $.ajac должен выставлять атоматически (либо multipart/form-data, либо application/x-www-form-encoded)
Дело не в большом числе полей, дело в урлэнкодинге рекурсивных структур (массивов из массивов)
>Это называется "лень читать документацию"
А вы таки не повегите, но оффициальная тм документация жквеги гекомендует использовать json во избежание всякой хуйни как газ в таких случаях
>Это не оптимизация, а отладка и исправление ошибок.
Нет, как раз рекомендация запаковать в джейсон это поиск ошибки, исключим хуйню при передаче, будем искать хуйню при создании, а аргументы уровня "зачем тут кодировать чтоб на сервере ещё раз раскодировать", это как раз микрооптимизации. Вас что, хипстеры макбуками избили, с таким джихадом против джейсона?
иерархические структуры прекрасно передаются ии принимаются обычным POST, даже вообще без яваскрипта. JSON для них не требуется.
На самом деле проблема уже давно решена, зря спорите.
Бамп вопросу, что в коде юзать и когда? Фронтенд контроллер паттерн, диспатчер или роутер?
Да и хуй с ним, джейсон вс урлэнкод при передаче это настолько платиновая и обсосаная тема, что хуже только про табы против пробелов сраться.
Если совсем примитивно - фронт контроллер это единственная точка входа в твою программу, какой бы урл у тебя не запросили, он придет к фронт контроллеру.
Вот приходит тебе на сервер реквест mypage.com/images/nigra.jpg
Фронт контролер создает диспетчера и передает ему этот запрос.
Диспетчер вызывает роутер, передает ему этот реквест и спрашивает, что он о нем думает.
Роутер сравнивает его с списком роутов, находит роут "/images/*.jpg" и говорит обратно диспетчеру "да у нас же картинку запросили, ебать"
Диспетчер говорит "понял, вызываю спеца по картинкам" и вызывает отвечающий за картинки метод контроллера (не путать с фронт контроллером) сайта
Тот уже в свою очередь что-то делает, ищет, существует ли в базе данных запись о такой картинке, хуемое, создает респонс, куда пакует картинку, выставляет хедеры, и вся эта ссань отдается обратно фронт контроллеру, который и отдает респонс в твой браузер.
я для себя написал интернет-магаин резиновых хуев категориями, описаниями, корзиной, регистрацией и всем осталтным с админской панелью за две недели, а дизайн еще неделю делал. И это я кодил часа по 3 в день.
Чем коммерческие проекты такие сложные и большие?
Не все заказы - магазины.
А магазинчики в большинстве своем покрываются функционалом готовых цмсок, их хоть жопой жуй, это уж твое или заказчика желание писать самому так то.
ну, ту же фриланс биржу выше в неск.месяцев оценили, хотя принцип, на мой взгляд, примерно тот же. Только каждый юзер-заказчик добавляет товар(заказ), и прочие мелкости
Ну покажи свой магазин, а я покосплею заказчика и подоебываюсь.
>прочие мелкости
Дьявол в мелочах кроется, большая часть функционала запиливается быстрее, чем отдельные микрописечки в нем, с которыми возникают проблемы.
Потом качество кода это не шутки. Можно нахуярить быстро, и даже самому нормально им пользоваться, в том числе не замечая очевидных косяков, а как только в руках юзера окажется, который немного по другому мыслит так сразу и пойдет отваливаться все к хуям.
Заказчик без правок не обойдется никогда, даже если ты с ним кровью скрепишь договор, что при первой же просьбе о правке он должен будет зарезать всю свою семью и скормить свой хуй собаке. Правки будут все равно, когда он уже глазами, а не умозрительно, на проект посмотрит.
Есть такая тема, как работа со сторонними сервисами. Не всегда это впиливается быстро и прозрачно.
На цмске можно брать не ссыкуя большую часть заказов с магазинами, и то понимая, что скорее всего придется плагинами своими докидываться, кроме как верстку натянуть.
>>954398
Качество кода это особенно не шутки, если тебе придется потом сопровождать этот код, когда от тебя потребуют впилить фичу потом через полгода, а ты во-первых нихуя не понимаешь как эта ссань вообще работает, во-вторых у всех компонентов настолько tight coupling, что tighter только писечка у лолей из хентая. Зато в свое время за две недели по три часа в день справился, да.
Пробую форычем, пробую просто $questions[0] - это не то.
Упустил суть, блин, помогите!
С eval вот какая проблема - при смене ip он меняет ссылку и при простом запуске кода. В тот момент, когда я обкакунькался, то же было, походу.
Можно открыть анонимное окно браузера и открыть ссылку в нем (или в другом браузере), чтобы понять, что увидят другие люди по этой ссылке.
По поводу твоего вопроса:
> ну и как мне теперь вызвать этот паблик метод у этих классов -
Берешь объект нужного класса и вызываешь метод стрелочкой, примерно так же, как и функцию, добавляя скобки после названия метода:
$result = $object->checkAnswers(...);
Но у тебя пока не исправлены замечания, что я писал выше, тут >>953203
Да забей ты на эти онлайн иде, срсли.
Ставишь пхп, кидаешь свой код в файлик index.php, в папке с ним в консоль делаешь
php -S localhost:8000 и всё, рефрешь http://localhost:8000/ в браузере и смотри на изменения.
По коду - может ты опять что-то не то отправил, но у тебя тот же пиздец остался, что и в прошлый раз - checkAnswers это метод одного отдельно взятого вопроса, а должен быть отдельной функцией, как и printQuestions. Ты не заставляешь один вопрос печатать все вопросы, но почему-то заставляешь один вопрос проверять все ответы.
Отдельная функция проверки ответов будет обходить список из всех вопросов и список из всех ответов и предлагать одному вопросу один вариант ответа, а тот должен всего лишь ответить за себя, правильный этот вопрос или нет.
Как земля.
Просто есть ведь div. Смотрел исходники разных сайтов, там только через div и строится все. Так как быть?
Если после этого ты будешь работать исключительно с $a, то всё хорошо. Если же ты решишь что если intval($_POST['var']) вернул ненулевое значение, то значит с $_POST['var'] всё хорошо, то тут тебя ждет приятный сюрприз.
https://3v4l.org/iSovA
>>954517
У них разное применение. div это, ну как сказать, технический элемент. Твой документ состоит из частей, у которых есть стили, классы, к ним прикручены какие-то данные и обработчики событий.
article, header, footer, section, nav и подобное - это семантические элементы, когда поисковик индексирует твою страницу, ему похуй из каких дивов она состоит, но если ты ему подскажешь, что вот это заголовок, это главная статья, ради которой эта страница создавалась, а вон там список глав в твоей статье, ему это (по идее) будет полезно. Суть семантик элементов - предоставить другим программам, которые будут смотреть на твою страницу всякие полезные метаданные. Это не значит что вместо дивов надо верстать секшенами теперь, если чо.
Я так и делал. Через header итд, а пару дней назад наткнулся на комент что "онли див, а все остальное фигня" Вот и решил обратится. Спасибо
Это потому что, во-первых, хер знает что они точно делают. Если бы гугл наебашил заявление, что мол так и так, если ваш документ семантически разбит на части, то мы будем индексировать его намного выше, то адопшн пошёл бы быстрее и веселее. А во-вторых, человеческой спецификации тоже нету, описания в стиле "элемент предназначен для группирования контента по темам", ну охуеть теперь, у всех немного свои идеи насчет того, что это значит.
>мол так и так, если ваш документ семантически разбит на части, то мы будем индексировать его намного выше, то адопшн пошёл бы быстрее и веселее.
Поговаривают, что в будущем так оно и будет.
>$a <=> $b
>Spaceship
>An integer less than, equal to, or greater than zero when $a is respectively less than, equal to, or greater than $b. Available as of PHP 7.
'b-a' не подходит из-за краевых случаев?
Господа, кто-нибудь работал с CodeIgniter?
Я не пойму, почему при отправке аяксом мне не возвращается строчный ответ, а только цифры. НА стаке пишут, что этот фреймворк пинимает только данные в виде джейсон строки. Мне нужно через аякс динамически подгрузить данные из бд без перезагрузки страницы.
Пример.
var url = window.location.href;
$.ajax({
url: url,
type: "POST",
dataType:"json",
data: {"gender":"m"},
success: function(data){
console.log(data);
}
});
В контроллере пишу
echo $_POST["gender"]; (причем если использую кодеигнитовский $this->input->post("gender") - тоже ничего)
и в консоли у меня ничего не выводится. а я хочу, чтобы дата ответ подгружалась в хтмл. пробовал dataContent подставлять - ничего.
притом просто вставить значение в базу данных через аякс я могу, а вот именно вернуть ответ и загрузить в хтмл через аякс - нет.
У тебя вопрос настолько сумбурный, что я даже не понял, у тебя проблема в том, что ничего не приходит в контроллер, или что?
Ты уверен что контролер вообще отрабатывает? window.location.href в качестве урла меня смущает, но может это только пример.
Дампни полностью $this->input и посмотри в каком формате тебе данные приходят, если контроллер правильно вызывается.
>>954517
Исходники других сайтов - это не образец, так как неизвестно кто и с каким уровнем подготовки их делал. Назначение тегов описано в спецификации HTML, но она сложная и на английском и может тебе не захочется ее читать.
Суть в том, что теги используются для смысловой (семантической) разметки. Ну к примеру, если ты хочешь каким-то тегом выделить шапку,то для этого придуман тег header.
div используется только если нужного тега не существует.
А так конечно, CSS позволяет переопределять любые свойства и можно страницу хоть одними тегами <a> сверстать, пусть люди и роботы потом мучаются и расшифровывают.
Что тебе мешает постить в этом треде, зачем новый? Почитай первые ~200 постов треда - сплошной оффтоп из-за толпы случайных людей. Добавь тред в избранное.
>>954468
По моему опыту, проекты на том же Yii, в общем случае, такого же низкого качества, как и на битриксе, всё из-за низкого порога входа. Так что мы тут все в разной степени говноеды.
А 1С-Битрикс тем временем проводит олимпиады с весьма нескучными задачами. Вот пример:
На вход подаётся файл, в котором через запятую перечислены следующие параметры:
текущая дата, начало/конец рабочего дня, выходные (номера дней недели), даты выходных в компании, количество задач, время выполнения каждой задачи в часах, приоритеты задач. Нужно вывести времена окончания каждой из задач с учётом всех выходных, праздников и так далее. К примеру, для таких данных:
23.12.2016 12:15:00
9 18
6 7
01.01.2016 23.02.2016
2
9 1
10 20
Ответ:
23.12.2016 13:15
26.12.2016 13:15
Объясняю ответ: начинаем с отметки 23.12.2016 12:15:00, вторая задача (та, которая делается за час) приоритетнее первой, поэтому выполняем её, выводим 23.12.2016 13:15. Время на выполнение второй задачи - 9 часов, до конца рабочего дня - 4 часа 45 минут. 24-е и 25-е февраля - суббота и воскресенье (6 и 7 дни недели, по условию выходные), пропускаем их. 9 часов + оставшиеся 4 часа 15 минут - 13:15, число мы уже выяснили - 26-е.
Посидим пока тут, когда тред на первой, в него набегают всякие бездельники, посмотри первые 500 постов.
>>954693
Это запутывает, так как можно подумать что ты хочешь найти разницу, а не сравнить числа. А тут сразу видны намерения. Плюс, он возвращает строго -1, 0 или 1.
>>954701
ЧТо на вкладке Network в инструментах разработчика?
>>954540
Вообще, описание есть в спецификации. Какой тег тебя интересует?
Вот например header: https://www.w3.org/TR/html5/sections.html#the-header-element
> The header element represents introductory content for its nearest ancestor sectioning content or sectioning root element. A header typically contains a group of introductory or navigational aids.
И ниже там пример разметки.
>Надо сделать так: внешняя функция checkAnswers принимает массив вопросов и ответов. И для каждой пары вопрос-ответ вызывает метод проверки на правильность. Вот этот метод проверки, правильный ли ответ к тесту, и должен быть описан в классах вопросов.
Блин, бро, я ни хрена не пойму, какое отношение имеет проверка правильности ответа к классу Вопрос или к его наследникам? Разве не логичнее делать это всё в отдельной функции?
Вот у нас массив с вопросами, но нам ведь этот метод можно применить к одному вопросу, а нужно будет в этот метод передать массив вопросов? Что за голимая байда? Вы мне втиrаете какую-то дичь!!1 Шучу
Ну что за бредятина: у меня есть класс Вопрос и этот же класс работает с массивом ответов!
Не лучше ли сделать тогда уж в классе Вопрос проверку конкретного соотношения ответ пользователя/правильный ответ?
Вот так попробовал: https://3v4l.org/i76fY
Notice: Undefined property: ChoiceQuestion::$correctAnswer in /in/i76fY on line 14 - что за перда, что тут не так?
Верный ли подход?
>>954465
Браток, у меня Yii2 развёрнут, там что-то в httpd.config прописано - пока не запускаю сейчас скрипты на локалке.
Ну там реально годный сайтец, идеоне нервно курит в сторонке.
Единственное - при любом запуске кода даёт новую ссылку, код поправить нельзя после запуска. Типа версии или я просто тупой.
> Блин, бро, я ни хрена не пойму, какое отношение имеет проверка правильности ответа к классу Вопрос или к его наследникам? Разве не логичнее делать это всё в отдельной функции?
Примерно так и надо, но проверка одного ответа к одному вопросу - она зависит от типа вопроса и потому для разных вопросов ее код будет разный. И потому этот код надо поместить в класс.
Я же тебе написал: вот у нас есть задача проверить массив ответов на массив вопросов. Вопросы разных типов и у каждого свой способ проверить ответ. Мы должны разбить код проверки на части:
- то что общее для всех видов вопросов - вынести в отдельную функцию
- то, что у каждого вида вопросов свое - поместить в класс вопроса
> Не лучше ли сделать тогда уж в классе Вопрос проверку конкретного соотношения ответ пользователя/правильный ответ?
Я об этом и писал. Объект Вопрос должен проверять только свой ответ, а не все воросы и ответы в массиве.
> Notice: Undefined property: ChoiceQuestion::$correctAnswer in /in/i76fY on line 14
Если посмотреть на класс Question то в нем нет поля correctAnswer. Почему ты к нему обращаешься в 14-й строке? Это неправильно.
>Браток, у меня Yii2 развёрнут, там что-то в httpd.config прописано - пока не запускаю сейчас скрипты на локалке.
Поэтому я тебе и говорю запускать скрипты на серваке пхп, чтоб ни с чем не конфликтовать, ну то такое.
>что за перда, что тут не так?
Твой абстрактный класс это предшественник, у него нету свойства correctOption и correctAnswer, к которым ты обращаешься в том методе, потому что эти свойства появляются только в наследниках, отсюда и ошибка.
Ну и ещё у тебя метод checkQuestionAndAnswer зачем-то первым аргументом принимает в себя самого себя, хоть этот обьект и так доступен через this внутри метода.
А, и если хочешь ещё поломать голову, то ответь вот на какой вопрос - не лучше было бы в этом случае применить интерфейс, а не абстрактный класс, и почему.
Странная схема. Зачем такое нагромождение классов? Почему в точке входа просто не принимать все роутером (там вообще класс по сути не нужен, это обычный php файл, где роутеру передается пару переменных из массива $_GET), а роутер уже отдает контроллер + метод по мапу роутов, который тут же и вызывается. Дальше весь запрос уже в полученном от роутера контроллере обрабатывается. Где смысл диспатчера и фронт контроллера? Какие-то излишние сущности получаются без четко отведенной им роли.
Я тебе советую решить все задачи в главе про ООП, так как сейчас ты пока не понимаешь, что к чему.
В этой задаче важно правильно разбить код: что-то пойдет в один класс, что-то в другой, а что-то вообще будет в отдельной функции.
Надо начать с того, что представляет и за что отвечает класс Question и унаследованные от него классы? Он представляет собой один вопрос в тесте. Он хранит информацию об этом вопросе.
Далее, что он должен уметь делать (какие у него есть методы)? Пока не понятно, потому посмотрим, что нам надо сделать в задаче.
А в задаче нам дам массив вопросов, массив ответов, их надо проверить и посчитать баллы.
Очевидно, что один объект Вопрос не может проверять все остальные вопросы, он отвечает только за себя, потому напишем отдельную функцию, которая будет перебирать ответы, проверять их, считать баллы.
Но когда мы дойдем до проверки ответа, мы обнаружим проблему. У каждого типа вопроса свой способ проверки ответа. Ну например в случае если это Вопрос с вариантами, то мы должны проверить, что выбран верный вариант. Если это Вопрос, где ответ - число, то мы должны проверить, что оно находится в определенном диапазоне.
Мы конечно можем сделать if вроде такого:
если (вопрос - экземпляр класса ChoiceQuestion) {
проверить что ответ совпадает с корректным;
} инчае если (вопрос - экземпляр класса NumericQuestion) {
проверить что ответ попадает в диапазон;
} иначе {
вывести ошибку;
}
Но тут есть недостаток. Что если завтра мы добавим новые типы вопросов? Этот код надо будет переделывать. Это неудобно, и ООП как раз должно решать эту проблему, а не создавать ее.
Более того, с точки зрения ответственности логично переложить задачу проверки ответа на класс соответствующего вопроса. То есть пусть у каждого вопроса будет метод проверитьОтвет(ответ) и пусть он по своему алгоритму его проверяет. И соответственно алгоритм получается такой:
для (каждой пары вопрос-ответ) {
результат = вопрос->проверитьОтвет(ответ);
если (результат == правильно) {
...
} иначе {
...
}
}
Таким образом при добавлении новых типов вопросов нам не придется переписывать эту функцию проверки ответов. Тот, кто написал новый класс, обязан будет сделать в нем метод проверитьОтвет.
Твой код неправильный. Ты пытаешься добавить метод проверки в базовый класс, но это неправльно по такой причине:
- базовый класс ничего не должен знать о наследниках, так как ты сам не предугадаешь, кто от него будет наследоваться в будущем.
Соответственно базовый класс не может обращаться к тем полям и методам, которых в нем нет.
Таким образом мы разделили ответственность:
- проверка ответа на один вопрос - ответственность класса Question и наследников
- подсчет очков, вывод подсказок - ответственность отдельной функции проверки ответов
Это важно понять, потому я советую тебе решить все задачи из главы ООП, чтобы полностью разобраться.
Я тебе советую решить все задачи в главе про ООП, так как сейчас ты пока не понимаешь, что к чему.
В этой задаче важно правильно разбить код: что-то пойдет в один класс, что-то в другой, а что-то вообще будет в отдельной функции.
Надо начать с того, что представляет и за что отвечает класс Question и унаследованные от него классы? Он представляет собой один вопрос в тесте. Он хранит информацию об этом вопросе.
Далее, что он должен уметь делать (какие у него есть методы)? Пока не понятно, потому посмотрим, что нам надо сделать в задаче.
А в задаче нам дам массив вопросов, массив ответов, их надо проверить и посчитать баллы.
Очевидно, что один объект Вопрос не может проверять все остальные вопросы, он отвечает только за себя, потому напишем отдельную функцию, которая будет перебирать ответы, проверять их, считать баллы.
Но когда мы дойдем до проверки ответа, мы обнаружим проблему. У каждого типа вопроса свой способ проверки ответа. Ну например в случае если это Вопрос с вариантами, то мы должны проверить, что выбран верный вариант. Если это Вопрос, где ответ - число, то мы должны проверить, что оно находится в определенном диапазоне.
Мы конечно можем сделать if вроде такого:
если (вопрос - экземпляр класса ChoiceQuestion) {
проверить что ответ совпадает с корректным;
} инчае если (вопрос - экземпляр класса NumericQuestion) {
проверить что ответ попадает в диапазон;
} иначе {
вывести ошибку;
}
Но тут есть недостаток. Что если завтра мы добавим новые типы вопросов? Этот код надо будет переделывать. Это неудобно, и ООП как раз должно решать эту проблему, а не создавать ее.
Более того, с точки зрения ответственности логично переложить задачу проверки ответа на класс соответствующего вопроса. То есть пусть у каждого вопроса будет метод проверитьОтвет(ответ) и пусть он по своему алгоритму его проверяет. И соответственно алгоритм получается такой:
для (каждой пары вопрос-ответ) {
результат = вопрос->проверитьОтвет(ответ);
если (результат == правильно) {
...
} иначе {
...
}
}
Таким образом при добавлении новых типов вопросов нам не придется переписывать эту функцию проверки ответов. Тот, кто написал новый класс, обязан будет сделать в нем метод проверитьОтвет.
Твой код неправильный. Ты пытаешься добавить метод проверки в базовый класс, но это неправльно по такой причине:
- базовый класс ничего не должен знать о наследниках, так как ты сам не предугадаешь, кто от него будет наследоваться в будущем.
Соответственно базовый класс не может обращаться к тем полям и методам, которых в нем нет.
Таким образом мы разделили ответственность:
- проверка ответа на один вопрос - ответственность класса Question и наследников
- подсчет очков, вывод подсказок - ответственность отдельной функции проверки ответов
Это важно понять, потому я советую тебе решить все задачи из главы ООП, чтобы полностью разобраться.
>Почему в точке входа просто не принимать все роутером
Это в любом случае фронт контроллер, если у тебя есть одна точка входа, это уже фронт контроллер паттерн.
>Зачем такое нагромождение классов?
Да незачем, роутер может сам быть фронт контроллером, матчить урл, сам лезть в базу данных, получать оттуда данные и тут же печатать в аутпут хтмл, таким образом он будет фронт контроллером, роутером, моделью, контроллером и представлением одновременно. Поздравляю, ты раскрыл заговор ООП жидорептилоидов, классы и фреймворки придумывают просто чтоб объебывать тебя на бабло. За тобой уже выехали
В перле этот пейсшип есть уже лет 20, и является багофичей (специально не вводили).
В использовании видел разве что в ебантяйских скриптах, обфусцированных почти до уровня однострочника rm -rf.
Он удобен при сортировке объектов например:
usort($users, function ($a, $b) {
return $a->rating <=> $b->rating;
});
>>954740
>>954743
>>954748
Спасибо за подробный такой разбор.
Я как раз иду строго по всем задачам.
Вот предыдущие:
1. http://ideone.com/KJNmR1 - начало про тесты.
2. http://ideone.com/9UQfxt и http://ideone.com/Tly7EQ - начало про Вектор.
3. https://3v4l.org/i76fY - продолжение про тесты (что вы/ты смотрел/и только что).
Так, сейчас буду разбираться, вдупливать. Я медленный. Пока не вижу во многом логики, но вроде как начало доходить.
>- то что общее для всех видов вопросов - вынести в отдельную функцию
>- то, что у каждого вида вопросов свое - поместить в класс вопроса
Общее у них - плюсуются баллы и количество правильных ответов, если правильно отвечено.
Своё у них - различие в наименовании "правильного ответа": $correctAnswer и $correctOption.
Я вот так сначала и хотел сделать - метод в каждом потомке класса Вопрос проверяет пункт из массивов $questions и $answers с учётом наименований своих правильных ответов.
О, тупанул: мне надо просто в классе Вопрос этот метод сделать абстрактным, а в потомках реальные методы - чтобы проверялся один вопрос и один ответ, а не как у меня сначала было - проверялись массивы. Тогда каждый экземпляр будет со своим определённым методом работать.
Так, пока пробую это.
И вроде все ошибки должны пропасть.
Пока писал это - сделал: https://3v4l.org/3CJfg
То ли это, что было нужно? Вроде схватилось что-то.
>>954748
>Очевидно, что один объект Вопрос не может проверять все остальные вопросы, он отвечает только за себя, потому напишем отдельную функцию, которая будет перебирать ответы, проверять их, считать баллы.
Да, вот это я сейчас схватил, уловил.
>Соответственно базовый класс не может обращаться к тем полям и методам, которых в нем нет.
Да, уловлено, а то я навертел несуразицы.
Языки, в которых намешано всё на кучу, чуток процедурщины, чуток ооп, чуток функциональщины, типа пхп или плюсов, они хуево учат ньюфагов ООП, ящитаю.
Если бы эту задачу человек решал на каком-то языке, где его заставили бы создавать классы и только классы сразу, ему бы пришлось создать класс Игра, в котором бы были контейнеры вопросов, у класса игра были бы методы показать вопросы, получить ответы, ну и проверить ответы интуитивно захотелось бы запихнуть туда же. А тут у нас функции которые не методы, просто висят в воздухе, понадобился способ проверить ответы - ну прицепили его к какому-то обьекту, в него масивчик передали, вообще процедурный стиль пошёл, нуачо, работает же.
Это я к чему - долбись об эту хуйню головой, дойдет в итоге. Если в процессе написания тебе придется копипастить абзацы кода и вставлять в другое место, чтоб поменять там три переменных, это знак того, что надо остановиться и подумать над иерархией ещё раз. Если у тебя есть функция, но ты не можешь решить, кто из обьектов её должен выполнять, опять таки хороший повод остановиться и подумать над схемой в целом. На листочке не стесняйся классы с стрелочками порисовать, тоже помогает.
Буду, спасибо!
Зандстру начал читать, точнее, продолжаю.
Немного улучшил вывод (просто подсказки и отступы добавил): https://3v4l.org/rsbB5
В целом то, но ты продолжаешь передавать в обьект самого себя
$questions[$i]->checkQuestionAndAnswer($questions[$i], $answers[$i])
В методах проверки у тебя есть защитный стейтмент if (isset($this->correctAnswer))
но ничего не написано на тот случай, если он действительно не будет определен, если ты исходишь из того, что он всегда будет определен, то зачем он вообще нужен?
Вот так: https://3v4l.org/FTQYo
?
Я лишний аргумент передавал, который даже и не использовался, - глаз просто замылился.
> Своё у них - различие в наименовании "правильного ответа": $correctAnswer и $correctOption.
Не только это, там еще может быть разный алгоритм проверки. Например, для числового ответа может быть не одно число, а диапазон, от x до y.
Именно потому, из-за разного алгоритма проверки, проверка должна быть в виде метода в классах-наследниках Question.
> public function checkQuestionAndAnswer($question, $answer)
Вот здесь, если посмотреть на вызов метода, видна избыточность:
> if ($questions[$i]->checkQuestionAndAnswer($questions[$i], $answers[$i]) == true) {
Зачем 2 раза указывать $questions[$i]? Объект, на котором вызван метод, доступен внутри метода в переменной $this. То есть передавать $question через аргументы не надо.
Также, не нужен isset. Поле либо гаратированно есть, либо его гарантированно нет (и обращаться к нему нельзя), и isset не требуется.
Еще у тебя много раз повторяется $questions[$i], не лучше ли это в переменную поместить?
А так, идея верная, остается только ошибки исправить.
Также, позже советую добавить в код тайп-хинты.
Тайп хинты позволяют указать, что аргумент функции должен быть определенного типа (например быть объектом определенного класса или его наследника). Тайп хинт делает код понятнее (так как видно какого типа переменная) и надежнее (так как PHP не позволит передать что-то неразрешенное и ты сразу увидишь ошибку). Используй их везде.
Мануал: http://php.net/manual/ru/language.oop5.typehinting.php
Обрати внимание, что php7 усовершенствовал систему тайп-хинтов - теперь можно в их качестве указывать примитивные типы вроде int/string, а в php7.1 стало можно указывать тайп-хинт для возвращаемого функцией значения: https://habrahabr.ru/post/267799/ (увы, возможность вернуть null пока не реализовали, так что ждем)
>>954777
Не соглашусь. Простые скрипты удобнее бывает просто как последовательность команд записать. А в той же Яве начинающий должен изучить классы до того, как напишет Hello World. Язык явно не для начинающих (хотя надо вспомнить что он пришел на замену C++ и в сравнении с ним невообразимо лучше. Вообще, Си и Си++ это боль и мрак).
Так что делать класс ради того, чтобы он был, не требуется.
>>954792
Я знаю, что можно писать return $a - $b, но писать $a >= $b не очень корректно, так как одинаковые сущности пересортируются в случайном порядке.
>>954791
У тебя там isset ненужный.
> Своё у них - различие в наименовании "правильного ответа": $correctAnswer и $correctOption.
Не только это, там еще может быть разный алгоритм проверки. Например, для числового ответа может быть не одно число, а диапазон, от x до y.
Именно потому, из-за разного алгоритма проверки, проверка должна быть в виде метода в классах-наследниках Question.
> public function checkQuestionAndAnswer($question, $answer)
Вот здесь, если посмотреть на вызов метода, видна избыточность:
> if ($questions[$i]->checkQuestionAndAnswer($questions[$i], $answers[$i]) == true) {
Зачем 2 раза указывать $questions[$i]? Объект, на котором вызван метод, доступен внутри метода в переменной $this. То есть передавать $question через аргументы не надо.
Также, не нужен isset. Поле либо гаратированно есть, либо его гарантированно нет (и обращаться к нему нельзя), и isset не требуется.
Еще у тебя много раз повторяется $questions[$i], не лучше ли это в переменную поместить?
А так, идея верная, остается только ошибки исправить.
Также, позже советую добавить в код тайп-хинты.
Тайп хинты позволяют указать, что аргумент функции должен быть определенного типа (например быть объектом определенного класса или его наследника). Тайп хинт делает код понятнее (так как видно какого типа переменная) и надежнее (так как PHP не позволит передать что-то неразрешенное и ты сразу увидишь ошибку). Используй их везде.
Мануал: http://php.net/manual/ru/language.oop5.typehinting.php
Обрати внимание, что php7 усовершенствовал систему тайп-хинтов - теперь можно в их качестве указывать примитивные типы вроде int/string, а в php7.1 стало можно указывать тайп-хинт для возвращаемого функцией значения: https://habrahabr.ru/post/267799/ (увы, возможность вернуть null пока не реализовали, так что ждем)
>>954777
Не соглашусь. Простые скрипты удобнее бывает просто как последовательность команд записать. А в той же Яве начинающий должен изучить классы до того, как напишет Hello World. Язык явно не для начинающих (хотя надо вспомнить что он пришел на замену C++ и в сравнении с ним невообразимо лучше. Вообще, Си и Си++ это боль и мрак).
Так что делать класс ради того, чтобы он был, не требуется.
>>954792
Я знаю, что можно писать return $a - $b, но писать $a >= $b не очень корректно, так как одинаковые сущности пересортируются в случайном порядке.
>>954791
У тебя там isset ненужный.
Ну типа спецификация усорта говорит что туда должен приходить именно больше, меньше или 0, так что оптимизации хуемое.
>>954795
>Простые скрипты удобнее бывает просто как последовательность команд записать.
Я где-то говорил из пхп яву сделать? Ява вообще параша та ещё.
>А в той же Яве начинающий должен изучить классы до того, как напишет Hello World.
И если ты хочешь научить начинающего именно оопшной парадигме, это очень хорошо.
Да, скорее всего, тебя будут учить говорить public static void main как магическому заклинанию, которое надо произнести в начале, чтоб твоя программа заработала, щито поделать. Что бы ооп-сектанты не утверждали, это совсем не интуитивно понятная вещь, которая вот прямо охуенно позволяет описать реальный мир, это такой же маняаутизм, как и все остальные модели, в который надо въехать, а чтоб в что-то въехать, желательно, чтоб у тебя было поменьше альтернатив, потому что "А зачем, и так же работает"-мышление это просто адов пиздец, который приводит к тому, что люди пишут хуйню, а раз их хуйня работает, то убеждаются в том, что они всё делают правильно и в штыки воспринимают пожелания не писать хуйню.
>Вообще, Си и Си++ это боль и мрак
Я тебя найду и укушу, насчет крестов согласен.
А почему насчет Си не согласен? Чего стоят только пляски с подключением dll, которая скомпилирована с одной версией рантайма Visual Studio, к exe-файлу, который скомпилирован другой версией. Я уж не говорю про случаи, если они разными компиляторами скомпилирваны. Это же надо так безнадежно все сломать было.
Ну и отстутствие менеджеров пакетов, допотопные системы сборки с кучей препроцессоров, это же боль и мучения сплошные.
Маленький и очень статический, соответственно шустрый как говно язык. Содержит одну парадигму, по минимуму абстракций, и при его минимальности, на нем можно написать всё.
Насчет рантаймов - все претензии к мс, не одной вижуал студио живем, знаете ли.
Менеджер пакетов и всё такое, это очень мило, но их отсутствие это не боль и мрак, ничего в этом мире не бывает бесплатно.
За каждый import sdelatzaebis, за каждый джиттер и автоматический менеджмент памяти надо платить чем-то ещё, поэтому у нас и есть разные языки для разных областей.
Более того, если тебе от yoba.dll нужно две процидурки (то есть ты не пишешь dll-прокси типа читов для кваки, запиханных в opengl32.dll) - то и необязательно грузить адреса всего шлака.
Выше смотри, рантайм нормальные люди вообще ебут по минимуму. Потому что почти все, что умеет это говно мамонта из белл лабс - умеет и ОС, только лучше.
Может ты не понял, в чем проблема. Проблема в том, например, что есть 1.dll скомпилирована VS2003, а 2.dll - VS2008 то у них у каждой может быть свой менеджер памяти и куча, и не только.
А что насчет dll, собранных разными компиляторами?
Чтобы они были совместимым, должен быть какой-то единый ABI. Таблиа импорта в dll определяет по моему только адреса функций, но знать только адрес недостаточно.
>strdup
Есть виндовый аналог
>fopen
Вообще нахуй никому не нужен что в винде, что в никсах. Не умеет в опции типа кэширования, синхронного/асинхронного ВВ по желанию, мапинга в память и так далее.
Вот как раз чит под контру я и писал. При этом контра скомпилена VS6, системная либа по-моему 2008, а моя дллка, подменяющая пару-тройку функций - gcc.
Так мы про крестовую парашу или что? Если хочешь кидаться объектами, или выделять через new в одном рантайме и deleteить в другом, ну готовь вазелин, хуле.
С стайл апи таки попроще и поинтероперабельнее будет.
у фпм меньше потребление памяти и проца.
Кроме того, сысоев впереди апача/фпм нужен не столько для отдачи статики, сколько для того, чтобы быстро забрав у тормозного бэкэнда данные, потом отдавать их клиенту на той скорости, на какой позволяет его канал. Количество процессов у сысоева от этого не увеличится, в отличии от пэхапни с форками.
Как насчет nginx, где ты в location можешь указать, где отдавать статику, а остальное все ложится на пхпфпм уже?
данные вообще не приходят. притом, если я отправляю не джейсоном, а обычной строкой, то при вызове echo [название переменной с пост запросом] выводит аж всю хтмл страницу. наверное тип возвращаемых данных надо указать, я хз, как там пхп тип указать? по-моему это анриал. или в джейсоне возвращать? у меня тока цифры выводятся при передачи джейсоном данных через аякс, а строки = нет((
https://github.com/never3ver/fileshare
Почти все поправил, остались вопросы. Ты писал:
>Это конечно хорошая идея, добавить поддержку gzip, но тогда надо дописать генератор сжатых версий файлов (и тщательно протестировать это в разных браузерах).
В условия, кроме проверки наличия сжатого файла, стоит еще добавить проверку существования оригинала.
Что понимается под генератором сжатых версий? В интернетах я встречаю мнение, что .htaccess достаточно и не надо себе голову делать лишними скриптами. Все что я нашел по этой теме датируется древними годами.
>Я не помню, давал я тебе такую задачу или нет. Чтобы лучше понять идею MVC, надо бы сделать альтернативный контроллер и вью для той же задачи. А именно: надо сделать скрипт для командной строки, позволяющий загружать файлы в файлообменник с локального диска и выводящий ссылку (ссылки) на них.
К этому я вообще не знаю как подойти. Если это cli, то как и зачем вью? И что будет из себя представлять контроллер? Мне в голову кроме допустим switch с кейсами в виде опций командной строки ничего в голову не приходит.
То, что ты отправляешь, это не json
data: JSON.stringify({"krokodil": "zalupa"})
Дампни весь весь пост массив, весь инпут и посмотри, приходит ли туда что-то и под каким индексом. Код контроллера и скрипта нормально запости, в конце концов
https://t.me/joinchat/AAAAAAlT02py0soe6xnbMw
Ведущие программные архитекторы Google, Oracle и Facebook с готовностью помогут вам освоить РНР и возьмут к себе работать!
Удели внимание изучению языка и релейтед технологий. С помощью фреймворка ты можешь написать цмс, с помощью цмс ты можешь делать только то, что предусмотрел автор цмс, если функционал понадобиться расширить, то см. в начало. Сколько платят натягивателям верстки на цмс понятия не имею, но почему-то мне кажется, что не шибко много.
Пытаюсь так, но не получается:
$s = 731656;
printf(' Эту страницу посетили ',$s,' раз');
p.s. Знаю что для данного примера проще использовать echo, но работаю с printf и в нем нужно разместить код.
Заходим на php.net.
Ищем там printf.
Видим в описании:
printf
(PHP 4, PHP 5, PHP 7)
printf — Output a formatted string
Description
int printf ( string $format [, mixed $args [, mixed $... ]] )
Produces output according to format.
Parameters
format
See sprintf() for a description of format.
Переходим по ссылке sprintf()
Наслаждаемся описанием формата с примерами.
Разобрался
>include returns FALSE on failure and raises a warning. Successful includes, unless overridden by the included file, return 1.
Подгорело.
Лушче использовать require которое вызывает ошибку при отстутсвии файла. А так да, эта система предупреждений в PHP безнадежно плохая, должны быть только исключения.
То, что инклуд ненужен, я сразу понял.
Я вообще о всяком. О том, что break число принимает, например - кому это надо хоть? Дезертирам?
Расскажите как это сделать и возможно ли?
О, вы хотите поговорить о возвращении разных типов? Просто обожаю пхп за вот этот нюанс
https://3v4l.org/9WRaN
Любителям спагетти, можно сразу гото использовать, если собираешься брейкать несколько контрол структур, читабельнее будет.
Теперь с $deviation в типе вопроса с указанием числа.
Перехожу к "Вектору", и сразу появились вопросы.
1. Нужен ведь класс Компания?
2. Нужны ведь класс Департамент и его наследники - отдельные департаменты?
3. Нужны ведь отдельные классы Менеджер, Маркетолог и так далее??
Это ж сколько будет кода, я стесняюсь спросить...
4. Как создавать экземпляр класс Менеджер, например? Функцию отдельную, у неё в аргументе количество манагеров и их ранг, такое?
На верном ли я пути?
В доках можно много комеди голда найти.
https://3v4l.org/oYWvI
Проигрываю каждый раз с этой хуйни.
if ($this->correctAnswer == $answer) {
return true;
} elseif ($answer == $this->correctAnswer - $this->deviation || $answer == $this->correctAnswer + $this->deviation) {
return true;
а мог бы вместо всей этой хуйни сравнить abs($correctAnswer - $answer) и девиацию
У тебя погрешность сейчас не работает.
Поставь её в, например 0.1 и ВНЕЗАПНО окажется, что 3.14 недостаточно точный ответ, хотя казалось бы.
Но ведь она всего в 0.001 может быть, это важно ведь тут?
Ну да, я делал как-то не особо подумав, действительно.
Но с abs() я вообще не пойму пока.
Да и голова уже Вектором забита.
В мануалах пишут, что это бывает при обшике, но дело в том, что все error-ы пустые.
Так а он удаляет-то?
Если нажать на символ номера '№' поста, то выведется вся цепочка ответов, с учетом предыдущих тредов. Прим. http://phpclub.rf.gd/pr/chain/955227#955227 http://phpclub.rf.gd/pr/chain/946271#946271 Естественно, если в посте несколько ссылок на посты, то все эти посты попадут в цепочку
Кому интересно: https://github.com/someApprentice/phpClub
Планируется ещё:
Написать пагинацию по мере появления тредов
Поиск с google-like(?) синтаксисом запросов Может кто-нибудь подскажет готовое решение?
Свои стили и скрипты, возможно
Технические исправления
Ещё у меня есть отличная идея:
Я видел как тут аноны собираются в конфочки, поэтому я подумал что можно написать наш собственный мессенджер внутри этого сервиса.
Что скажите? Стоит сделать?
Сервис абсолютно сырой и наверняка содержит большое количество багов, поэтому любой фидбэк будет полезен. Если можно, с готовым решением
Фидбэк можно написать сюда или мне на почту someApprenticXS[eANUSopenmv.jailboxPUNCTUMo?=/rg
Один большой баг уже удалось найти: Иногда при обновлении тредов в БД добавляется тред с записью NULL и созданием поврежденного json-файла с пустым именем. Установить причину бага не удалось т.к. такое поведение было замечено лишь однажды.
Баг приводит к крашу индексной страницы. Так что если вы увидите пустую страницу, то это поэтому.
https://en.bitcoin.it/wiki/Original_Bitcoin_client/API_calls_list
Я правильно понимаю что сначала нужно создать адрес а затем аккаунт, и потом делать с этим всё что я захочу? А где тут пароли или то что аутентифицирует кошелек?
Пиши мессенджер, хуле нет. Вполне в духе треда начинающих уеб девелоперов.
Да я хз, встречал тебя полгода или чуть больше назад, ты ж делал всяких лиличек и прочую поеботу из середины учебника?
Отличная штука.
Я сразу по коду хочу дать совет: https://github.com/someApprentice/phpClub/blob/master/src/File.php
Вместо того, чтобы ручками копипастить вот это вот:
$file->post = $result['post'];
$file->displayname = $result['displayname'];
$file->duration = $result['duration'];
Лучше было бы сделать так:
protected function getFields()
{
return ['post', 'displayname', 'duration'];
}
foreach ($this->getFields() as ...) { ... }
Более того, этот код (вынесение свойств из массива и заполнение объекта) можно сделать в базовом классе ActiveRecord. И там же можно сделать метод для генерации INSERT'ов.
Ну и еще в AR проблема с тем, что PDO надо передавать в каждый объект File. Часто разработчики AR просто отказываются от DI и делают где-то глобальный метод для получения зависимости.
Пример из Yii2: https://github.com/yiisoft/yii/blob/master/framework/db/ar/CActiveRecord.php#L633
Ну и конечно, стоит помнить, что есть Доктрина, которая конечно притормаживает иногда, но зато избавляет от необходимости вообще писать код маппинга.
Я не предлагаю делать так же, просто хотел показать примеры других реализаций.
Генерацию всех путей и URL стоит вынести в хелпер, просто в статические методы.
Для страницы 404 очень желательно выдавать HTTP заголовок 404. Всего одну строчку header() надо добавить.
Threader лучше было назвать ThreadController.
> $count = $post->getCountByThread($somethread->number);
Это возможно стоило встроить в класс Thread, чтобы можно было вызывать $thread->getPostCount();
Также, если интересен вопрос оптимизации выборки, то тут придется усложнять схему БД. Сейчас, чтобы вывести посты на главной, приходится делать много запросов, и они не очень эффективные (например, подсчет числа постов в каждом треде отдельно).
Можно добавить в тред поля для хранения числа постов, а также ссылки на последние посты (либо сделать это через отдельную таблицу связи тред - последние посты). Соответственно данные можно будет выбрать в 2 захода: выбираем треды, затем собираем из них id ОП-поста и последних постов и выбираем их одним запросом. Но это конечно немного усложнит работу с базой, так как при изменениях надо обновлять эти дополнительные поля. Но зато снизит нагрузку на базу при выборке.
Также, строить цепочку постов через выбор всех постов в БД очень неэффективно. Лучше сделать таблицу связи "многие-ко-многим", связывающую посты, может быть такого вида:
from_id | to_id
или такого
from_id | to_id | depth
То есть мы берем пост, и для каждой ссылки в нем вставляем записи в таблицу связи. Можно вставлять только ссылки из самого поста, тогда надо делать несколько SQL запросов, чтобы построить цепочку, а можно вставлять ссылки еще и на посты с большей глубиной вложенности, тогда цепочка выбирается одним запросом, но таблица будет больше по объему.
В интерфейсе есть небольшая проблема: на главной странице невозможно догадаться, что с нее можно перейти в тред. Стоит после ОП поста добавить ссылку вроде "Просмотреть тред целиком" или как-то так. Догадаться, что можно кликнуть на номер треда, невозможно.
И еще, может стоит добавить опцию, чтобы сохранялись и выводились ссылки на тред в архиве /pr/ и в архиваче, если они есть. Просто, чтобы было.
А так, прикольно, почти что отдельная доска, состоящая только из PHP тредов.
> Поиск с google-like(?) синтаксисом запросов Может кто-нибудь подскажет готовое решение?
Есть поисковый демон Sphinx, который умеет строить индексы на основе БД и искать по ним, и у меня есть старый урок, и в интернете полно инфы: https://gist.github.com/codedokode/10539366
Если сфинкс на хостинге запускать не разрешают, то можно использовать полнотекстовый индекс и поиск по нему в MySQL:
- https://ruhighload.com/post/Полнотекстовый+поиск+в+Mysql
- (англ, офиц.) https://dev.mysql.com/doc/refman/5.7/en/fulltext-search.html
Ну и при желании можно нагуглить еще статьи. Преимущество исопльзования MySQL:
- не надо ничего дополнительно ставить
- не надо настраивать индексирование
Недостатки:
- вставка и обновление таблицы влечет обновление полнотекстового индекса, и увеличивает нагрузку на базу, особенно если эти операции часто выполняются, то очень сильно увеличивается нагрузка. Но так как в данном случае никаких частых вставок нет, то это не проблема.
- у сфинкса больше возможностей по настройке индекисрования и поиска, например, он умеет делать стеммииг (отбрасывание окончаний у слов, чтобы можно было искать слово в разных формах, падежах, числе, времени), поиск по части слова, в общем, много всего
- умение работать со сфинксом может где-нибудь пригодиться
Оба этих способа (полнотекстовый поиск в MySQL и сфинкс) подразумевают создание индекса примерно таким способом: берутся все документы, они разбиваются на слова и строится такой индекс, похожий на таблицу:
слово | id документов, где оно встречается | позиция (порядковый номер) слова в документах
Позиции слова хранят, чтобы можно было при поиске фразы найти документы, где слова стоят близко друг к другу.
То есть строится по сути огромная таблица со всеми словами из всех документов, оптимизированная на быстрый поиск по слову. Поисковый запрос разбивается на слова, для каждого извлекается список id документов, эти списки объединяются и итоговый список сортируется по "релевантности".
При этом слова перед индексировнием можно дополнительно обработать. Например, стеммингом отсечь окончания, чтобы искать слово в любой форме.
> Я видел как тут аноны собираются в конфочки, поэтому я подумал что можно написать наш собственный мессенджер внутри этого сервиса.
Если хочется потренироваться в написании мессенджеров, советую делать его как отдельный проект. Наверно тут понадобится JS-приложение, чтобы на каждый чих не дергать сервер. Можно и без JS, но будет работать наверно не очень быстро.
> Иногда при обновлении тредов в БД добавляется тред с записью NULL и созданием поврежденного json-файла с пустым именем.
Скорее всего где-то нет проверки на ошибки. Ну то есть не удалось загрузить файл, но код все равно продолжает бодро выполняться дальше. Нужно ставить проверки и бросать исключения, если что-то не так. Обрати внимание на функцию json_decode: при ошибке в JSON-данных она просто молча возвращает NULL или false, не выдавая никаких предупреждений. Также, для file_get_contents стоит проверять результат и может быть Content-Type в http://php.net/manual/ru/reserved.variables.httpresponseheader.php
Также, картинки на дваче не хранятся вечно и надо их либо скачивать, либо не выводить.
Также, не знаю, нужно это или нет, но у меня есть кое-какие архивы с HTML-файлами тредов и картинками. Я их уже который год собираюсь выложить, но руки не доходят.
Отличная штука.
Я сразу по коду хочу дать совет: https://github.com/someApprentice/phpClub/blob/master/src/File.php
Вместо того, чтобы ручками копипастить вот это вот:
$file->post = $result['post'];
$file->displayname = $result['displayname'];
$file->duration = $result['duration'];
Лучше было бы сделать так:
protected function getFields()
{
return ['post', 'displayname', 'duration'];
}
foreach ($this->getFields() as ...) { ... }
Более того, этот код (вынесение свойств из массива и заполнение объекта) можно сделать в базовом классе ActiveRecord. И там же можно сделать метод для генерации INSERT'ов.
Ну и еще в AR проблема с тем, что PDO надо передавать в каждый объект File. Часто разработчики AR просто отказываются от DI и делают где-то глобальный метод для получения зависимости.
Пример из Yii2: https://github.com/yiisoft/yii/blob/master/framework/db/ar/CActiveRecord.php#L633
Ну и конечно, стоит помнить, что есть Доктрина, которая конечно притормаживает иногда, но зато избавляет от необходимости вообще писать код маппинга.
Я не предлагаю делать так же, просто хотел показать примеры других реализаций.
Генерацию всех путей и URL стоит вынести в хелпер, просто в статические методы.
Для страницы 404 очень желательно выдавать HTTP заголовок 404. Всего одну строчку header() надо добавить.
Threader лучше было назвать ThreadController.
> $count = $post->getCountByThread($somethread->number);
Это возможно стоило встроить в класс Thread, чтобы можно было вызывать $thread->getPostCount();
Также, если интересен вопрос оптимизации выборки, то тут придется усложнять схему БД. Сейчас, чтобы вывести посты на главной, приходится делать много запросов, и они не очень эффективные (например, подсчет числа постов в каждом треде отдельно).
Можно добавить в тред поля для хранения числа постов, а также ссылки на последние посты (либо сделать это через отдельную таблицу связи тред - последние посты). Соответственно данные можно будет выбрать в 2 захода: выбираем треды, затем собираем из них id ОП-поста и последних постов и выбираем их одним запросом. Но это конечно немного усложнит работу с базой, так как при изменениях надо обновлять эти дополнительные поля. Но зато снизит нагрузку на базу при выборке.
Также, строить цепочку постов через выбор всех постов в БД очень неэффективно. Лучше сделать таблицу связи "многие-ко-многим", связывающую посты, может быть такого вида:
from_id | to_id
или такого
from_id | to_id | depth
То есть мы берем пост, и для каждой ссылки в нем вставляем записи в таблицу связи. Можно вставлять только ссылки из самого поста, тогда надо делать несколько SQL запросов, чтобы построить цепочку, а можно вставлять ссылки еще и на посты с большей глубиной вложенности, тогда цепочка выбирается одним запросом, но таблица будет больше по объему.
В интерфейсе есть небольшая проблема: на главной странице невозможно догадаться, что с нее можно перейти в тред. Стоит после ОП поста добавить ссылку вроде "Просмотреть тред целиком" или как-то так. Догадаться, что можно кликнуть на номер треда, невозможно.
И еще, может стоит добавить опцию, чтобы сохранялись и выводились ссылки на тред в архиве /pr/ и в архиваче, если они есть. Просто, чтобы было.
А так, прикольно, почти что отдельная доска, состоящая только из PHP тредов.
> Поиск с google-like(?) синтаксисом запросов Может кто-нибудь подскажет готовое решение?
Есть поисковый демон Sphinx, который умеет строить индексы на основе БД и искать по ним, и у меня есть старый урок, и в интернете полно инфы: https://gist.github.com/codedokode/10539366
Если сфинкс на хостинге запускать не разрешают, то можно использовать полнотекстовый индекс и поиск по нему в MySQL:
- https://ruhighload.com/post/Полнотекстовый+поиск+в+Mysql
- (англ, офиц.) https://dev.mysql.com/doc/refman/5.7/en/fulltext-search.html
Ну и при желании можно нагуглить еще статьи. Преимущество исопльзования MySQL:
- не надо ничего дополнительно ставить
- не надо настраивать индексирование
Недостатки:
- вставка и обновление таблицы влечет обновление полнотекстового индекса, и увеличивает нагрузку на базу, особенно если эти операции часто выполняются, то очень сильно увеличивается нагрузка. Но так как в данном случае никаких частых вставок нет, то это не проблема.
- у сфинкса больше возможностей по настройке индекисрования и поиска, например, он умеет делать стеммииг (отбрасывание окончаний у слов, чтобы можно было искать слово в разных формах, падежах, числе, времени), поиск по части слова, в общем, много всего
- умение работать со сфинксом может где-нибудь пригодиться
Оба этих способа (полнотекстовый поиск в MySQL и сфинкс) подразумевают создание индекса примерно таким способом: берутся все документы, они разбиваются на слова и строится такой индекс, похожий на таблицу:
слово | id документов, где оно встречается | позиция (порядковый номер) слова в документах
Позиции слова хранят, чтобы можно было при поиске фразы найти документы, где слова стоят близко друг к другу.
То есть строится по сути огромная таблица со всеми словами из всех документов, оптимизированная на быстрый поиск по слову. Поисковый запрос разбивается на слова, для каждого извлекается список id документов, эти списки объединяются и итоговый список сортируется по "релевантности".
При этом слова перед индексировнием можно дополнительно обработать. Например, стеммингом отсечь окончания, чтобы искать слово в любой форме.
> Я видел как тут аноны собираются в конфочки, поэтому я подумал что можно написать наш собственный мессенджер внутри этого сервиса.
Если хочется потренироваться в написании мессенджеров, советую делать его как отдельный проект. Наверно тут понадобится JS-приложение, чтобы на каждый чих не дергать сервер. Можно и без JS, но будет работать наверно не очень быстро.
> Иногда при обновлении тредов в БД добавляется тред с записью NULL и созданием поврежденного json-файла с пустым именем.
Скорее всего где-то нет проверки на ошибки. Ну то есть не удалось загрузить файл, но код все равно продолжает бодро выполняться дальше. Нужно ставить проверки и бросать исключения, если что-то не так. Обрати внимание на функцию json_decode: при ошибке в JSON-данных она просто молча возвращает NULL или false, не выдавая никаких предупреждений. Также, для file_get_contents стоит проверять результат и может быть Content-Type в http://php.net/manual/ru/reserved.variables.httpresponseheader.php
Также, картинки на дваче не хранятся вечно и надо их либо скачивать, либо не выводить.
Также, не знаю, нужно это или нет, но у меня есть кое-какие архивы с HTML-файлами тредов и картинками. Я их уже который год собираюсь выложить, но руки не доходят.
Там интересная схема. Там при создании кошелька генерируется набор случайных байт (то есть очень большое число). Это закрытый, секретный ключ, который позволяет делать любые операции с кошельком (им подписываются транзакции). Из этого ключа необратимым преобразованием генерируется открытый ключ (по моему, просто берется хеш от закрытого ключа). Это публичный идентификатор кошелька.
Соответственно когда ты создаешь новую транзакцию, и подписываешь ее закрытым ключом, участники сети, каждый, проверяют, что подпись соответствует открытому ключу и таким образом удостоверяются что ты именно владелец кошелька.
Транзакции в биткойне неотзываемые и необратимые. Если ты потерял закрытый ключ, то считай что потерял кошелек.
Если интересно, советую про все это почитать, это интересная система. Только возможно сначала стоит почитать про асимметричную криптографию, открытые и закрытые ключи.
И еще, я бы советовал выделить публичную папку и сделать ее корневой. Даже если хостинг не позволяет задать свою корневую папку, все равно обычно можно исхитриться и так закачать проект, чтобы публичной была только одна папка, а остальное было за ее пределами.
Также, еще один маленький совет, он в принципе к любому сайту подходит. Я советую на странице где-нибудь написать кратко, хотя бы в одно предложение в уголке, что это за сайт. Вот если взять например случайный вопрос на stackoverflow: http://stackoverflow.com/questions/29854982/for-linux-how-can-i-kill-all-processes-in-a-session-with-same-sid-using-syste - то там написано что это за сайт.
А то человек из гугла открывает страницу и не очень понимает, что это за сайт вообще.
Нет, я серьезно, ты молодец. Писать какие-то применимые в комюнити вещи всегда больше мотивирует, чем абстрактные упражнения, да и тестеров побольше наберется.
That said, месенджер это совсем другой зверь, чем типичный вебсайт, с другим стаком технологий, отличных от привычного реквест - респонс - закрыть соединение цикла, если мы говорим о настоящем дуплексном соединении. Пхп вообще не очень язык для написания долгоиграющих приложений с ивент лупом.
Для трех с половиной анончиков можно соорудить и решение из существующих технологий с помощью старого доброго поллинга, но и тут тебе понадобится продумать фронтэнд на жсе и апи твоего сервера, с которым он будет общаться.
>>931910 | http://arhivach.org/thread/233392/#931910
>>955417
задача про addProperty
> Исправил, теперь всё работает: https://jsfiddle.net/sh21j4p1/1/
Ок, все верно теперь. Кстати, в новом JS (ES5 может быть) есть такая штука, как defineProperty: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty .
Она интересна тем, что позволяет задавать разные опции (например не показывать свойство getTest/setTest при переборе циклом for ..in). Но наверно в задаче надо было написать свою функцию, а не использовать готовую, я уже не помню.
вопрос про прототипы
> Я пытался задать метод через прототип и обратиться к нему в "конструкторе" функции, но мне выдалась ошибка о том что этот метод не является функцией: https://jsfiddle.net/3sjvm5gp/
> Почему так получилось? Ведь если функция не находиться в объекте она ищется по цепочке в его прототипе.
Верно. Но трюк в том, что свойство prototype не задает прототип для объекта-функции Foo. Оно задает прототип для объектов, которые будут созданы с помощью new Foo. В данном коде Foo.prototype - это просто обычное свойство с именем prototype.
А вот если мы сделаем var f = new Foo;
То у f будет взят прототип из Foo.prototype. И можно будет писать foo.func
То есть прототип задается объекту в момент создания. У Foo прототипом является Function (и она создается даже до того, как выполнится строчка Foo.prototype.func = ...), так как в JS все функции это объекты, созданные конструктором Function.
Важно не путать свойство с именем prototype и прототип объекта, который можно получить через Object.getPrototypeOf() или нестандартное свойство x.__proto__ которым я советую не пользоваться.
То есть задавать прототип объекту нужно в момент создания и есть 2 способа:
- var f = new Foo - прототип берется из свойства Foo.prototype
- (ES5) var f= Object.create(p) - прототип берется из p
Если вдруг есть желание залезть в стандарт ES5, довольно тяжелый для чтения, то вот:
- описание оператора new: https://es5.github.io/#x11.2.2
- описание функции[[construct]]: https://es5.github.io/#x13.2.2
В описании [[construct]] есть такой пункт:
> 5. Let proto be the value of calling the [[Get]] internal property of F with argument "prototype".
> 6. If Type(proto) is Object, set the [[Prototype]] internal property of obj to proto.
То есть при создании объекта берется значение свойства F.prototype и если это объект, то он становится прототипом создаваемого объекта.
Задача про addMethod и super
> Что-то у меня не получилось понять подвоха этой задачи: https://jsfiddle.net/zmLjh7ur/
> Более того, я не смог понять как работает функция super(): https://jsfiddle.net/b073aLb5/1/
> В чем моя ошибка? Здесь же должна быть такая же ситуация, super должен искать метод в прототипе.
Подвох в том, что функции super() в JS нету, и в задаче требуется ее сделать. То есть если просто сделать добавление метода так:
function addMethod(object, name, fn) {
object[name] = fn;
}
То super() конечно никак не сможет найти метод в объекте-предке. Она ведь даже не знает, из какого метода с каким именем, и на каком объекте она вызвана. А передавать имя метода или ссылку на объект в super() по условию задачи нельзя.
То есть addMethod должен быть чуть сложнее. Он должен вставлять в объект не fn, а функцию-обертку, которая перед вызовом исходного метода как-то найдет и передаст в super ссылку на объект-предок или на метод в предке. А после обнулит эту ссылку. Примерно так:
- задать ссылку на метод-предок для super
- вызвать исходную функцию
- (при желании) обнулить эту ссылку после завершения исходной функции
Дополнительный подвох заключается в том, что метод-предок тоже может оказаться такой "оберткой", вызывающей super().
Второй подвох, который стоит оставить на потом, в том, что исходная функция может выбросить исключение и выполнение метода прервется. Надо корректно это обрабатывать.
Это сложное задание, потому можно сразу спросить, если что-то не понятно, а не ломать голову. Я могу дать дополнительные подсказки.
Задача про гамбургер
> if (size == Hamburger.SIZE_SMALL || size == Hamburger.SIZE_LARGE) {
> } else if (size === undefined) {
> } else if (size != Hamburger.SIZE_SMALL || size != Hamburger.SIZE_LARGE) {
В третьем случае лучше просто написать else. Также, можно убрать второй случай.
Также, может быть стоит хранить где-то список допустимых значений отдельно, чтобы было легко его править.
> определил this.menu
Странно, я в коде не вижу this.menu = {}; Наверно это было в другой версии кода.
В остальном выглядит верно.
Электросеть
>> Для ЛЭП проще всего указать нули и учитывать их вклад отдельно (сделать у них методы для получения информации, сколько мощности доступно и по какой цене).
> Но мы можем и даже должны иметь возможность узнать её мощность.
Да, но я предлагал сделать для этого отдельное свойство, ну например не "мощность", а "пропускная способность". Так как все другие потребители, кроме ЛЭП, могут сами посчитать, сколько они потребляют/генерируют, а ЛЭП не может, она должна дождаться пока мы подведем баланс. Потому я предлагал сделать у ЛЭП мощность 0 и сделать отдельные свойства для хранения пропускной способности и цены.
> А почему ЛЭП не может спросить сколько энергии нужно?
Она может, но получается как минимум 2 проблемы:
- ЛЭП надо будет дать ссылку на Сеть, в то время как c другими элементами у нас односторонняя связь: у Сети есть ссылка на Элемент, а у Элемента на Сеть - нет. Такая односторонняя связь удобнее, ее проще поддерживать и лучше видно кто кем управляет
- будет запутанная цепочка вызовов: Сеть опрашивает Элементы, сколько они генерируют, а ЛЭП в свою очередь опрашивает Сеть, какой получился баланс (а ей для этого надо опять опрашивать Элементы). Запутанное отношение, и тут легко даже сделать бесконечную рекурсию.
Потому удобнее сделать расчет, сколько мы закупаем/продаем энергии, в Сети, а ЛЭП эти цифры не давать, зачем они ей.
> Тут дело даже не в этом, ЛЭП сама по себе ничего не спрашивает - мы просто передаем энергию и пользуемся её функцией счетчиком, который работает с её же свойством цена.
Это можно, сделать у ЛЭП метод, который отвечает на вопрос, сколько будет стоит передача данного количества энергии.
>>Мне кажется, тут неправильно используется свойство power, так как у ЛЭП это не фактически переданная мощность, а пропускная способность (сколько максимум можно купить/продать), и логично для нее использовать другое название, чтобы не было путаницы.
> В реальной жизни тоже некоторые свойства могут называться одинакового, не смотря на то что выполняют разные функции.
Это плохая идея, так как повышает вероятность сделать ошибку. Лучше назвать по-разному, чтобы меньше была вероятность напутать.
Ну и код упростится: из этого цикла
> for (var element in this.elements) {
> if (this.elements[element] instanceof PowerLine != true) {
Можно будет убрать if.
> power мы делим саму на себя чтобы узнать прибавлять или отнимать энергию каждый раз, чтобы достичь баланса, т.е. узнать обратный знак своего значения. То есть, мы каждый раз либо прибавляем или отнимаем по одному, до тех пор пока значение не станет нулём.
Вместо вычитания в цикле надо использовать деление или умножение и функции min()/max().
> price += powerlines.countPrice(balance);
> balance = powerlines.countPower(balance);
Здесь идея правильная, но код не очень логчный. Мы сначала спрашиваем сколько стоит передача энергии, а только потом - сколько можно передать. Логичнее сделать наоборот, узнать, сколько можно передать, а потом - сколько это стоит.
Ну и функции стоило назвать логичнее. Не countPower(), а например getTransferredPower(), хотя мне кажется что сделать тут min(balance, line.getThroughput()) было бы нагляднее.
> function Electrostation(power) {
> NetworkElement.apply(this, arguments);
apply(arguments) тут использовать неправильно, так как у функций разные наборы аргументов и аргументы от одной функции не соответствуют аргументам от другой. В NetworkElement надо передавать мощность в ваттах, а в Electrostation в мегаваттах.
> if (power >= 1 Math.pow(10, 6) && power <= 100 Math.pow(10, 6)) {
> this.power = power;
> this.nightpower = power;
Тут нелогично, что мы сначала передаем в конструктор предка одно значение мощности, а потом меняем его на другое. А вдруг в предке в конструкторе будет например логгирование, или проверка какая-нибудь?
Лучше сначала рассчитать мощность, а потом вызвать конструктор предка и дать правильные значения.
> function House(apartments = 0) {
> this.apartments = apartments;
> this.power = this.apartments -5 Math.pow(10, 3);
Здесь есть маленький недостаток, что свойство power зависит от apartments и логично тогда power вообще не хранить, а просто вычислять из apartments в момент вызова getPower. Плохо хранить зависящие друг от друга свойства, так как есть риск что они перестанут соответствоват друг другу (если мы разрешим менять apartments например).
То есть надо либо не хранить this.apartments, либо не хранить this.power.
>>931910 | http://arhivach.org/thread/233392/#931910
>>955417
задача про addProperty
> Исправил, теперь всё работает: https://jsfiddle.net/sh21j4p1/1/
Ок, все верно теперь. Кстати, в новом JS (ES5 может быть) есть такая штука, как defineProperty: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty .
Она интересна тем, что позволяет задавать разные опции (например не показывать свойство getTest/setTest при переборе циклом for ..in). Но наверно в задаче надо было написать свою функцию, а не использовать готовую, я уже не помню.
вопрос про прототипы
> Я пытался задать метод через прототип и обратиться к нему в "конструкторе" функции, но мне выдалась ошибка о том что этот метод не является функцией: https://jsfiddle.net/3sjvm5gp/
> Почему так получилось? Ведь если функция не находиться в объекте она ищется по цепочке в его прототипе.
Верно. Но трюк в том, что свойство prototype не задает прототип для объекта-функции Foo. Оно задает прототип для объектов, которые будут созданы с помощью new Foo. В данном коде Foo.prototype - это просто обычное свойство с именем prototype.
А вот если мы сделаем var f = new Foo;
То у f будет взят прототип из Foo.prototype. И можно будет писать foo.func
То есть прототип задается объекту в момент создания. У Foo прототипом является Function (и она создается даже до того, как выполнится строчка Foo.prototype.func = ...), так как в JS все функции это объекты, созданные конструктором Function.
Важно не путать свойство с именем prototype и прототип объекта, который можно получить через Object.getPrototypeOf() или нестандартное свойство x.__proto__ которым я советую не пользоваться.
То есть задавать прототип объекту нужно в момент создания и есть 2 способа:
- var f = new Foo - прототип берется из свойства Foo.prototype
- (ES5) var f= Object.create(p) - прототип берется из p
Если вдруг есть желание залезть в стандарт ES5, довольно тяжелый для чтения, то вот:
- описание оператора new: https://es5.github.io/#x11.2.2
- описание функции[[construct]]: https://es5.github.io/#x13.2.2
В описании [[construct]] есть такой пункт:
> 5. Let proto be the value of calling the [[Get]] internal property of F with argument "prototype".
> 6. If Type(proto) is Object, set the [[Prototype]] internal property of obj to proto.
То есть при создании объекта берется значение свойства F.prototype и если это объект, то он становится прототипом создаваемого объекта.
Задача про addMethod и super
> Что-то у меня не получилось понять подвоха этой задачи: https://jsfiddle.net/zmLjh7ur/
> Более того, я не смог понять как работает функция super(): https://jsfiddle.net/b073aLb5/1/
> В чем моя ошибка? Здесь же должна быть такая же ситуация, super должен искать метод в прототипе.
Подвох в том, что функции super() в JS нету, и в задаче требуется ее сделать. То есть если просто сделать добавление метода так:
function addMethod(object, name, fn) {
object[name] = fn;
}
То super() конечно никак не сможет найти метод в объекте-предке. Она ведь даже не знает, из какого метода с каким именем, и на каком объекте она вызвана. А передавать имя метода или ссылку на объект в super() по условию задачи нельзя.
То есть addMethod должен быть чуть сложнее. Он должен вставлять в объект не fn, а функцию-обертку, которая перед вызовом исходного метода как-то найдет и передаст в super ссылку на объект-предок или на метод в предке. А после обнулит эту ссылку. Примерно так:
- задать ссылку на метод-предок для super
- вызвать исходную функцию
- (при желании) обнулить эту ссылку после завершения исходной функции
Дополнительный подвох заключается в том, что метод-предок тоже может оказаться такой "оберткой", вызывающей super().
Второй подвох, который стоит оставить на потом, в том, что исходная функция может выбросить исключение и выполнение метода прервется. Надо корректно это обрабатывать.
Это сложное задание, потому можно сразу спросить, если что-то не понятно, а не ломать голову. Я могу дать дополнительные подсказки.
Задача про гамбургер
> if (size == Hamburger.SIZE_SMALL || size == Hamburger.SIZE_LARGE) {
> } else if (size === undefined) {
> } else if (size != Hamburger.SIZE_SMALL || size != Hamburger.SIZE_LARGE) {
В третьем случае лучше просто написать else. Также, можно убрать второй случай.
Также, может быть стоит хранить где-то список допустимых значений отдельно, чтобы было легко его править.
> определил this.menu
Странно, я в коде не вижу this.menu = {}; Наверно это было в другой версии кода.
В остальном выглядит верно.
Электросеть
>> Для ЛЭП проще всего указать нули и учитывать их вклад отдельно (сделать у них методы для получения информации, сколько мощности доступно и по какой цене).
> Но мы можем и даже должны иметь возможность узнать её мощность.
Да, но я предлагал сделать для этого отдельное свойство, ну например не "мощность", а "пропускная способность". Так как все другие потребители, кроме ЛЭП, могут сами посчитать, сколько они потребляют/генерируют, а ЛЭП не может, она должна дождаться пока мы подведем баланс. Потому я предлагал сделать у ЛЭП мощность 0 и сделать отдельные свойства для хранения пропускной способности и цены.
> А почему ЛЭП не может спросить сколько энергии нужно?
Она может, но получается как минимум 2 проблемы:
- ЛЭП надо будет дать ссылку на Сеть, в то время как c другими элементами у нас односторонняя связь: у Сети есть ссылка на Элемент, а у Элемента на Сеть - нет. Такая односторонняя связь удобнее, ее проще поддерживать и лучше видно кто кем управляет
- будет запутанная цепочка вызовов: Сеть опрашивает Элементы, сколько они генерируют, а ЛЭП в свою очередь опрашивает Сеть, какой получился баланс (а ей для этого надо опять опрашивать Элементы). Запутанное отношение, и тут легко даже сделать бесконечную рекурсию.
Потому удобнее сделать расчет, сколько мы закупаем/продаем энергии, в Сети, а ЛЭП эти цифры не давать, зачем они ей.
> Тут дело даже не в этом, ЛЭП сама по себе ничего не спрашивает - мы просто передаем энергию и пользуемся её функцией счетчиком, который работает с её же свойством цена.
Это можно, сделать у ЛЭП метод, который отвечает на вопрос, сколько будет стоит передача данного количества энергии.
>>Мне кажется, тут неправильно используется свойство power, так как у ЛЭП это не фактически переданная мощность, а пропускная способность (сколько максимум можно купить/продать), и логично для нее использовать другое название, чтобы не было путаницы.
> В реальной жизни тоже некоторые свойства могут называться одинакового, не смотря на то что выполняют разные функции.
Это плохая идея, так как повышает вероятность сделать ошибку. Лучше назвать по-разному, чтобы меньше была вероятность напутать.
Ну и код упростится: из этого цикла
> for (var element in this.elements) {
> if (this.elements[element] instanceof PowerLine != true) {
Можно будет убрать if.
> power мы делим саму на себя чтобы узнать прибавлять или отнимать энергию каждый раз, чтобы достичь баланса, т.е. узнать обратный знак своего значения. То есть, мы каждый раз либо прибавляем или отнимаем по одному, до тех пор пока значение не станет нулём.
Вместо вычитания в цикле надо использовать деление или умножение и функции min()/max().
> price += powerlines.countPrice(balance);
> balance = powerlines.countPower(balance);
Здесь идея правильная, но код не очень логчный. Мы сначала спрашиваем сколько стоит передача энергии, а только потом - сколько можно передать. Логичнее сделать наоборот, узнать, сколько можно передать, а потом - сколько это стоит.
Ну и функции стоило назвать логичнее. Не countPower(), а например getTransferredPower(), хотя мне кажется что сделать тут min(balance, line.getThroughput()) было бы нагляднее.
> function Electrostation(power) {
> NetworkElement.apply(this, arguments);
apply(arguments) тут использовать неправильно, так как у функций разные наборы аргументов и аргументы от одной функции не соответствуют аргументам от другой. В NetworkElement надо передавать мощность в ваттах, а в Electrostation в мегаваттах.
> if (power >= 1 Math.pow(10, 6) && power <= 100 Math.pow(10, 6)) {
> this.power = power;
> this.nightpower = power;
Тут нелогично, что мы сначала передаем в конструктор предка одно значение мощности, а потом меняем его на другое. А вдруг в предке в конструкторе будет например логгирование, или проверка какая-нибудь?
Лучше сначала рассчитать мощность, а потом вызвать конструктор предка и дать правильные значения.
> function House(apartments = 0) {
> this.apartments = apartments;
> this.power = this.apartments -5 Math.pow(10, 3);
Здесь есть маленький недостаток, что свойство power зависит от apartments и логично тогда power вообще не хранить, а просто вычислять из apartments в момент вызова getPower. Плохо хранить зависящие друг от друга свойства, так как есть риск что они перестанут соответствоват друг другу (если мы разрешим менять apartments например).
То есть надо либо не хранить this.apartments, либо не хранить this.power.
>>931910 | http://arhivach.org/thread/233392/#931910
>>955417
Определение типа переменной
> как проверить что у объекта есть свойства от 0 до length - 1.
Пройтись циклом от 0 до length - 1 и для каждого числа проверить наличие свойства с помощью in.
> А что с этим циклом делать? Нельзя же вернуть значение только по окончанию цикла, если in всегда были истины.
Можно писать так:
для (i от 0 до length - 1) {
если в объекте нет свойства i, то вернуть false;
}
вернуть true;
15. Напиши функцию неглубокого копирования объектов и массивов
Вот тут я бы обратил внимание на то, как копируются даты:
> var clone = new Date();
Мы создаем объект Date и копируем свойства по одному. Но тут есть подвох. Date это встроенный в JS объект и потому он не подчиняется общим правилам (более того, в разных браузерах этот объект может быть реализован по-разному). Например, у него могут быть свойства, которые не перебираются через for .. in (как свойство length у массива), или вообще скрытые внутренние свойства, недоступные из JS. Потому копировать его таким способом рискованно.
Вот, к примеру, если в консоли разработчика в Хромиуме сделать dir(new Date) то там нет никаких видимых свойств, только методы в прототипе.
В твоем коде дата не копируется (проверь), а создается объект с текущим временем.
Мануал в помощь: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Date
В общем, встроенные в JS и в браузер объекты - это не обычные JS объекты и они не играют по общим правилам. Они могут делать все, что угодно, а вот с ними делать можно только то, что описано в документации. Если там не описаны свойства, то значит они могут быть скрытыми.
>>Не, до такой степени скопировать объект мы вряд ли сможем. Достаточно копировать только свойства самого объекта, копировать прототип не требуется.
> А понял. Подвох в том что копируется не сам прототип а только его свойства, верно же?
Да. И мы скорее всего вообще не можем создать объект с таким же прототиом, что у исходного, так как не знаем, каким конструктором и с какими аргументами он был создан. Потому в задаче требуется только копировать обычные объекты вроде {x: 1, y: 2}, без копирования прототипов.
>>Тут в коде, я вижу, есть поддержка копирования объектов Date и обычных объектов, а что с массивами? Для них ведь надо изначально создавать пустой массив и копировать элементы.
> А других встроенных объектов это замечание касается?
Да, если надо копировать встроенные объекты, то для каждого придется писать свою логику. Один способ для Regexp, другой для Function, и так далее. Встроенные объекты могут иметь скрытые свойства и просто циклом их копировать нельзя.
Глубокое копирование
В старом коде была такая строка:
> var clone = new object.constructor;
Тут есть проблема, что constructor это обычное свойство и оно может быть перезаписано, или неправильно проставлено, и твой код из-за этого сломается. Также, конструктор может иметь аргументы, а ты их не передаешь при вызове new. Потому я советую не пытаться вызывать неизвестный тебе конструктор.
Также тут та же проблема, что Date не копируется, так как у него свойства скрыты.
> } else if (variable instanceof Array) {
Тут есть маленький подвох. Если объект был создан в другом окне или ифрейме и передан нам, то проверка не сработает. Потому что в каждом окне/ифрейме свой экземпляр window.Array и они не равны друг другу.
Вот примерный код (я мог ошибиться):
<script>
function test(x) {
console.log(x instanceof window.Array);
}
</script>
<iframe id="x" src="inner.html"></iframe>
В inner.html пишем:
<script>
window.parent.test([]);
console.log(window.Array === window.parent.Array);
</script>
И видим false.
Проверка через Object.prototype.toString лишена этого недостатка. Также, в ES5 есть метод Array.isArray().
>>931910 | http://arhivach.org/thread/233392/#931910
>>955417
Определение типа переменной
> как проверить что у объекта есть свойства от 0 до length - 1.
Пройтись циклом от 0 до length - 1 и для каждого числа проверить наличие свойства с помощью in.
> А что с этим циклом делать? Нельзя же вернуть значение только по окончанию цикла, если in всегда были истины.
Можно писать так:
для (i от 0 до length - 1) {
если в объекте нет свойства i, то вернуть false;
}
вернуть true;
15. Напиши функцию неглубокого копирования объектов и массивов
Вот тут я бы обратил внимание на то, как копируются даты:
> var clone = new Date();
Мы создаем объект Date и копируем свойства по одному. Но тут есть подвох. Date это встроенный в JS объект и потому он не подчиняется общим правилам (более того, в разных браузерах этот объект может быть реализован по-разному). Например, у него могут быть свойства, которые не перебираются через for .. in (как свойство length у массива), или вообще скрытые внутренние свойства, недоступные из JS. Потому копировать его таким способом рискованно.
Вот, к примеру, если в консоли разработчика в Хромиуме сделать dir(new Date) то там нет никаких видимых свойств, только методы в прототипе.
В твоем коде дата не копируется (проверь), а создается объект с текущим временем.
Мануал в помощь: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Date
В общем, встроенные в JS и в браузер объекты - это не обычные JS объекты и они не играют по общим правилам. Они могут делать все, что угодно, а вот с ними делать можно только то, что описано в документации. Если там не описаны свойства, то значит они могут быть скрытыми.
>>Не, до такой степени скопировать объект мы вряд ли сможем. Достаточно копировать только свойства самого объекта, копировать прототип не требуется.
> А понял. Подвох в том что копируется не сам прототип а только его свойства, верно же?
Да. И мы скорее всего вообще не можем создать объект с таким же прототиом, что у исходного, так как не знаем, каким конструктором и с какими аргументами он был создан. Потому в задаче требуется только копировать обычные объекты вроде {x: 1, y: 2}, без копирования прототипов.
>>Тут в коде, я вижу, есть поддержка копирования объектов Date и обычных объектов, а что с массивами? Для них ведь надо изначально создавать пустой массив и копировать элементы.
> А других встроенных объектов это замечание касается?
Да, если надо копировать встроенные объекты, то для каждого придется писать свою логику. Один способ для Regexp, другой для Function, и так далее. Встроенные объекты могут иметь скрытые свойства и просто циклом их копировать нельзя.
Глубокое копирование
В старом коде была такая строка:
> var clone = new object.constructor;
Тут есть проблема, что constructor это обычное свойство и оно может быть перезаписано, или неправильно проставлено, и твой код из-за этого сломается. Также, конструктор может иметь аргументы, а ты их не передаешь при вызове new. Потому я советую не пытаться вызывать неизвестный тебе конструктор.
Также тут та же проблема, что Date не копируется, так как у него свойства скрыты.
> } else if (variable instanceof Array) {
Тут есть маленький подвох. Если объект был создан в другом окне или ифрейме и передан нам, то проверка не сработает. Потому что в каждом окне/ифрейме свой экземпляр window.Array и они не равны друг другу.
Вот примерный код (я мог ошибиться):
<script>
function test(x) {
console.log(x instanceof window.Array);
}
</script>
<iframe id="x" src="inner.html"></iframe>
В inner.html пишем:
<script>
window.parent.test([]);
console.log(window.Array === window.parent.Array);
</script>
И видим false.
Проверка через Object.prototype.toString лишена этого недостатка. Также, в ES5 есть метод Array.isArray().
>Вместо того, чтобы ручками копипастить вот это вот:
>
>$file->post = $result['post'];
>$file->displayname = $result['displayname'];
>$file->duration = $result['duration'];
>
>Лучше было бы сделать так:
>
>protected function getFields()
>{
>return ['post', 'displayname', 'duration'];
>}
>
>foreach ($this->getFields() as ...) { ... }
>
>Более того, этот код (вынесение свойств из массива и заполнение объекта) можно сделать в базовом классе ActiveRecord.
Имелось ввиду получение свойств с помощью get_class_vars()? Хорошо ли это? В объекте могут быть свойства которые не предназначены для заполнения из БД.
У меня были мысли написания универсального метода для заполнения, но sublime text позволяет мне редактировать такие записи в пару нажатий.
>Ну и еще в AR проблема с тем, что PDO надо передавать в каждый объект File. Часто разработчики AR просто отказываются от DI и делают где-то глобальный метод для получения зависимости.
Да, у меня как раз возникали с этим проблемы - чтобы получить все записи какой-то сущности, мне нужно было создать сначала саму эту сущность. Мне хотелось написать статичный метод для этого и передавать в него PDO.
Я думал переделать всё на TDG, но теперь мне интересно попробовать Доктрину.
>Если сфинкс на хостинге запускать не разрешают, то можно использовать полнотекстовый индекс и поиск по нему в MySQL:
Возможно у меня получиться найти хостинг с большим доступом, а файлы хранить на этом на нём нету ограничения на использование места.
>>Я видел как тут аноны собираются в конфочки, поэтому я подумал что можно написать наш собственный мессенджер внутри этого сервиса.
>Если хочется потренироваться в написании мессенджеров, советую делать его как отдельный проект. Наверно тут понадобится JS-приложение, чтобы на каждый чих не дергать сервер. Можно и без JS, но будет работать наверно не очень быстро.
Можно написать и отдельно. Ведь ничего не мешает потом интегрировать это куда угодно.
>Также, картинки на дваче не хранятся вечно и надо их либо скачивать, либо не выводить.
А они и так скачиваются.
>Также, не знаю, нужно это или нет, но у меня есть кое-какие архивы с HTML-файлами тредов и картинками. Я их уже который год собираюсь выложить, но руки не доходят.
Это будет замечательно.
Парсить из html-файла... Это будет сложнее. Сначала я разберусь с текущими замечаниями, затем возьмусь за это.
Завтра я глубже проанализирую ваши советы. Возможно будут ещё вопросы.
>Вместо того, чтобы ручками копипастить вот это вот:
>
>$file->post = $result['post'];
>$file->displayname = $result['displayname'];
>$file->duration = $result['duration'];
>
>Лучше было бы сделать так:
>
>protected function getFields()
>{
>return ['post', 'displayname', 'duration'];
>}
>
>foreach ($this->getFields() as ...) { ... }
>
>Более того, этот код (вынесение свойств из массива и заполнение объекта) можно сделать в базовом классе ActiveRecord.
Имелось ввиду получение свойств с помощью get_class_vars()? Хорошо ли это? В объекте могут быть свойства которые не предназначены для заполнения из БД.
У меня были мысли написания универсального метода для заполнения, но sublime text позволяет мне редактировать такие записи в пару нажатий.
>Ну и еще в AR проблема с тем, что PDO надо передавать в каждый объект File. Часто разработчики AR просто отказываются от DI и делают где-то глобальный метод для получения зависимости.
Да, у меня как раз возникали с этим проблемы - чтобы получить все записи какой-то сущности, мне нужно было создать сначала саму эту сущность. Мне хотелось написать статичный метод для этого и передавать в него PDO.
Я думал переделать всё на TDG, но теперь мне интересно попробовать Доктрину.
>Если сфинкс на хостинге запускать не разрешают, то можно использовать полнотекстовый индекс и поиск по нему в MySQL:
Возможно у меня получиться найти хостинг с большим доступом, а файлы хранить на этом на нём нету ограничения на использование места.
>>Я видел как тут аноны собираются в конфочки, поэтому я подумал что можно написать наш собственный мессенджер внутри этого сервиса.
>Если хочется потренироваться в написании мессенджеров, советую делать его как отдельный проект. Наверно тут понадобится JS-приложение, чтобы на каждый чих не дергать сервер. Можно и без JS, но будет работать наверно не очень быстро.
Можно написать и отдельно. Ведь ничего не мешает потом интегрировать это куда угодно.
>Также, картинки на дваче не хранятся вечно и надо их либо скачивать, либо не выводить.
А они и так скачиваются.
>Также, не знаю, нужно это или нет, но у меня есть кое-какие архивы с HTML-файлами тредов и картинками. Я их уже который год собираюсь выложить, но руки не доходят.
Это будет замечательно.
Парсить из html-файла... Это будет сложнее. Сначала я разберусь с текущими замечаниями, затем возьмусь за это.
Завтра я глубже проанализирую ваши советы. Возможно будут ещё вопросы.
Не, имелось в виду что мы описываем список свойств руками в методе getFields(), а потом проходим по нему циклом и копируем из массива в объект. get_class_vars конечно не даст нам то, что нужно.
Некоторые фреймворки автоматически загружают список свойств из базы, запрашивая список колонок в таблице и кешируя информацию.
> У меня были мысли написания универсального метода для заполнения, но sublime text позволяет мне редактировать такие записи в пару нажатий.
Код будет проще. В твоем варианте трудно сравнить например что списки при INSERT и при загрузке записей совпадают и ничего не пропущено.
> Да, у меня как раз возникали с этим проблемы - чтобы получить все записи какой-то сущности, мне нужно было создать сначала саму эту сущность. Мне хотелось написать статичный метод для этого и передавать в него PDO.
Да, используют либо статические методы, либо сторонний объект PostFinder.
Кроме Юи, еще AR используется в laravel, можно посмотреть и как у них сделано: https://laravel.com/docs/4.2/eloquent#basic-usage
> $users = User::all();
> $user = User::find(1);
Тот же принцип.
> Я думал переделать всё на TDG, но теперь мне интересно попробовать Доктрину.
Да, это хорошая идея.
> Парсить из html-файла... Это будет сложнее. Сначала я разберусь с текущими замечаниями, затем возьмусь за это.
Это может быть хорошим поводом изучить DOM и jquery подобные библиотеки. хотя конечно, да, там подвох в том, что верстка менялась со временем, и придется писать несколько версий парсера.
Не, имелось в виду что мы описываем список свойств руками в методе getFields(), а потом проходим по нему циклом и копируем из массива в объект. get_class_vars конечно не даст нам то, что нужно.
Некоторые фреймворки автоматически загружают список свойств из базы, запрашивая список колонок в таблице и кешируя информацию.
> У меня были мысли написания универсального метода для заполнения, но sublime text позволяет мне редактировать такие записи в пару нажатий.
Код будет проще. В твоем варианте трудно сравнить например что списки при INSERT и при загрузке записей совпадают и ничего не пропущено.
> Да, у меня как раз возникали с этим проблемы - чтобы получить все записи какой-то сущности, мне нужно было создать сначала саму эту сущность. Мне хотелось написать статичный метод для этого и передавать в него PDO.
Да, используют либо статические методы, либо сторонний объект PostFinder.
Кроме Юи, еще AR используется в laravel, можно посмотреть и как у них сделано: https://laravel.com/docs/4.2/eloquent#basic-usage
> $users = User::all();
> $user = User::find(1);
Тот же принцип.
> Я думал переделать всё на TDG, но теперь мне интересно попробовать Доктрину.
Да, это хорошая идея.
> Парсить из html-файла... Это будет сложнее. Сначала я разберусь с текущими замечаниями, затем возьмусь за это.
Это может быть хорошим поводом изучить DOM и jquery подобные библиотеки. хотя конечно, да, там подвох в том, что верстка менялась со временем, и придется писать несколько версий парсера.
Я могу ошибаться, но по моему, первая задача, с которой к нам пришел someApprentice, была про написание то ли регистрации, то ли это была задача про сервис уменьшения картинок.
Всё верно, вот эта задача https://github.com/someApprentice/simpleRegistration Сервис по уменьшению картинок мне оказался не по зубам, не мог справиться с ООП, поэтому я взялся за вектор а затем за студентов. Вашими усилиями теперь для меня такие вещи проще простого. Я действительно думаю что я ничего не сделал - я просто делал что вы говорили. Спасибо за всё что вы сделали. Я не знаю как я смогу отплатить вам за это. Возможно, если я сделаю что-то стоящее, это будет значить что это было сделано под вашим влиянием, а значит сделано благодаря вам. У меня просто нету другого выбора как сделать это.
Насколько я помню, я делал задачи и из учебника, только не скидывал в тред - я мог решить их самостоятельно.
Молодец, отличная штука. Ты её сам делаешь, или пулл реквесты принимаешь? У меня есть несколько предложений по улучшению структуры проекта, архитектуры и других вещей. Я могу их подробно описать, потом мы это обсудим в треде или на гитхабе. Как тебе идея? Будет интересный опыт создания чего-то общего нашим уютным тредом.
Что мне нужно, что вообще такое происходит, всё пропало, шеф....
http://sqlfiddle.com/#!9/a5b842/5
>> Вывести информацию о пользователе, сколько лайков поставил/получил, сколько взаимных лайков
> Решено пока неэффективно, с лишними подзапросами. Это можно сделать с 2 джойнами без подзапросов.
Долго ломал голову, не понял как решить без подзапросов. Для того, чтобы сосчитать количество полученных/поставленных лайков нужно ведь сгруппировать по пользователю и выбрать count(), эта функция будет применяться к сгруппированным элементам. Но запрос вида "SELECT user.id, count(likes.from_user), count(likes.to_user) ..." выдаёт 2 одинаковых count'а. А JOIN ON ведь указывает только как фильтровать соединённые таблицы, как туда впихнуть свой count или группировку (без подзапросов) - не могу понять.
Ты забываешь, что можно считать не просто число строк, а например, число различных значений поля или выражения в группе.
Изучи-ка мануал
(англ ) https://dev.mysql.com/doc/refman/5.7/en/group-by-functions.html#function_count
(рус) http://www.mysql.ru/docs/man/Group_by_functions.html
Насчет поиска числа взаимных лайков, тут конечно, интереснее. Подскажу: можно для каждой строчки в группе определить, является ли лайк взаимным выставив 0 или 1, и сложить эти значения.
Добвил тут пару подсказок: https://github.com/codedokode/pasta/blob/master/db/databases.md#Задачка-про-лайки
> -- Все пользователи, которые поставили лайк 1,2 но не поставили 3
У тебя тут список пользователей, которые поставили лайк 1 или 2, но надо те, кто поставили лайк и пользователю 1, и пользователю 2.
Решается без джойнов, в один проход по таблице.
Свойство companySalary избыточное, так как зарплату по компании можно всегда получить, просуммировав зарплату по департаментам. Хранить его - плохая идея, так как при добавлении новых департаментов, найме работников, изменении их ранга или зарплаты это поле надо будет не забыть пересчитать, а забыть легко (и получить в итоге устаревшие данные). Лучше вообще не хранить его.
> class Department {
> public function setDepartmentEmployees($departmentName, $department) {
Здесь какая-то ерунда. передается какой-то двухмерный массив непонятной структуры. Вот например, что это значит?
> $department[$i][$i - 1]
Если $i == 5 то получается $department[5][4]. И в чем смысл этого выражения? Мы берем из массива элемент с ключом 5, а в этом элементе-массиве ищем элемент с ключом 4?
Ты можешь объяснить что это за массив и какого он вида, что хранит? Из кода понять невозможно.
Лучше просто сделать объект, поедставляющий работника, а в департменте - метод принятия работника на работу в этот департамент.
>Пхп вообще не очень язык для написания долгоиграющих приложений с ивент лупом.
В целом да, но это не нереально. Ратчет по бенчам примерно вдвое меньше реквестов, чем нода держит, к примеру, с чем так же работать можно. Обещали еще ускорить. Есть еще воркерман какой-то от китайцев, этот судя по гитхабу в каждой жопе затычка.
>Можно добавить в тред поля для хранения числа постов, а также ссылки на последние посты (либо сделать это через отдельную таблицу связи тред - последние посты). Соответственно данные можно будет выбрать в 2 захода: выбираем треды, затем собираем из них id ОП-поста и последних постов и выбираем их одним запросом.
То есть одним запросом? SELECT * FROM posts WHERE id IN (1, 2, ...)?
Я сомневаюсь что при хранении ссылок на последние посты и их выборка будет делать гораздо меньше нагрузки чем у простого запроса с OFFSET. Даже если мы сделаем отдельную таблицу связей, то мы все равно будем обращаться к ней на главной странице, что будет делать ту же нагрузку.
Я провел тест чтобы проверить это, и если я правильно выбрал метод проверки, мои сомнения подтвердились:
mysql>set profiling=1;
...
mysql>show profiles;
+----------+------------+------------------------------------------------------------+
| Query_ID | Duration | Query |
+----------+------------+------------------------------------------------------------+
| 1 | 0.00255000 | SELECT ∗ FROM posts WHERE thread=945059 LIMIT 3 OFFSET 938 |
| 2 | 0.00241925 | SELECT ∗ FROM posts WHERE post IN (955807, 955816, 955833) |
+----------+------------+------------------------------------------------------------+
Как мы видим, время выполнения почти одинаково.
Есть что-то что я упускаю? Или я путаю скорость выполнения запроса с его нагрузкой (по-моему, это пропорционально)?
Что касается создания поля с числом постов и таблицы с цепочкой постов, то с этим мне понятно.
>Также, строить цепочку постов через выбор всех постов в БД очень неэффективно. Лучше сделать таблицу связи "многие-ко-многим", связывающую посты, может быть такого вида:
>
>from_id | to_id
>
>или такого
>
>from_id | to_id | depth
>
>То есть мы берем пост, и для каждой ссылки в нем вставляем записи в таблицу связи. Можно вставлять только ссылки из самого поста, тогда надо делать несколько SQL запросов, чтобы построить цепочку, а можно вставлять ссылки еще и на посты с большей глубиной вложенности, тогда цепочка выбирается одним запросом, но таблица будет больше по объему.
>а можно вставлять ссылки еще и на посты с большей глубиной вложенности, тогда цепочка выбирается одним запросом
А что находиться в глубине вложенности? Насколько я знаю глубина вложенности это расстояние до корневого узла. Как из этого получить всю цепочку?
>>955523
>Не, имелось в виду что мы описываем список свойств руками в методе getFields(), а потом проходим по нему циклом и копируем из массива в объект. get_class_vars конечно не даст нам то, что нужно.
Как тогда определить такой метод в базовом классе?
>Можно добавить в тред поля для хранения числа постов, а также ссылки на последние посты (либо сделать это через отдельную таблицу связи тред - последние посты). Соответственно данные можно будет выбрать в 2 захода: выбираем треды, затем собираем из них id ОП-поста и последних постов и выбираем их одним запросом.
То есть одним запросом? SELECT * FROM posts WHERE id IN (1, 2, ...)?
Я сомневаюсь что при хранении ссылок на последние посты и их выборка будет делать гораздо меньше нагрузки чем у простого запроса с OFFSET. Даже если мы сделаем отдельную таблицу связей, то мы все равно будем обращаться к ней на главной странице, что будет делать ту же нагрузку.
Я провел тест чтобы проверить это, и если я правильно выбрал метод проверки, мои сомнения подтвердились:
mysql>set profiling=1;
...
mysql>show profiles;
+----------+------------+------------------------------------------------------------+
| Query_ID | Duration | Query |
+----------+------------+------------------------------------------------------------+
| 1 | 0.00255000 | SELECT ∗ FROM posts WHERE thread=945059 LIMIT 3 OFFSET 938 |
| 2 | 0.00241925 | SELECT ∗ FROM posts WHERE post IN (955807, 955816, 955833) |
+----------+------------+------------------------------------------------------------+
Как мы видим, время выполнения почти одинаково.
Есть что-то что я упускаю? Или я путаю скорость выполнения запроса с его нагрузкой (по-моему, это пропорционально)?
Что касается создания поля с числом постов и таблицы с цепочкой постов, то с этим мне понятно.
>Также, строить цепочку постов через выбор всех постов в БД очень неэффективно. Лучше сделать таблицу связи "многие-ко-многим", связывающую посты, может быть такого вида:
>
>from_id | to_id
>
>или такого
>
>from_id | to_id | depth
>
>То есть мы берем пост, и для каждой ссылки в нем вставляем записи в таблицу связи. Можно вставлять только ссылки из самого поста, тогда надо делать несколько SQL запросов, чтобы построить цепочку, а можно вставлять ссылки еще и на посты с большей глубиной вложенности, тогда цепочка выбирается одним запросом, но таблица будет больше по объему.
>а можно вставлять ссылки еще и на посты с большей глубиной вложенности, тогда цепочка выбирается одним запросом
А что находиться в глубине вложенности? Насколько я знаю глубина вложенности это расстояние до корневого узла. Как из этого получить всю цепочку?
>>955523
>Не, имелось в виду что мы описываем список свойств руками в методе getFields(), а потом проходим по нему циклом и копируем из массива в объект. get_class_vars конечно не даст нам то, что нужно.
Как тогда определить такой метод в базовом классе?
Вопрос в том, зачем мне Nginx, если статики нет? Апач напрямую с php-fpm соединен, soap сервер отдает и принимает данные веб-сервиса.
> Я сомневаюсь что при хранении ссылок на последние посты и их выборка будет делать гораздо меньше нагрузки чем у простого запроса с OFFSET.
Конечно, на практике скорость выполнения запроса зависит от многих факторов, но один из главных факторов - это сколько строк таблиц должна MySQL обойти, чтобы получить результат. Индексы тут конечно тоже влияют на результат, позволяя вместо изучения всей таблицы быстро найти строки, подходящие под условие.
Чтобы сделать OFFSET, мы сначала должны сделать COUNT() для постов в треде, а это обход N строк, где N = число постов в треде. Затем, взятие 3 последних постов через OFFSET это обход и пропуск почти всех постов в треде. Тут кстати можно было просто остортировать посты треда по убыванию даты и взять первые 3, если есть индекс по (thread_id, post_date) то запрос SELECT FROM posts WHERE thread_id = ? ORDER BY post_date DESC LIMIT 3 приведет к обходу только этих 3 постов (MySQL в индексе найдет самый последний пост треда и сделает 3 шага по индексу чтобы найти 3 последних поста).
(если что, простая статья про индексы: https://ruhighload.com/post/Работа+с+индексами+в+MySQL )
Но даже в этом случае, я вижу тут недостаток: мы должны делать 2N запросов, где N - число тредов, так как для каждого треда мы должны 1 запросом получить ОП пост и вторым - последние 3 поста. Тут конечно можно выкрутиться, используя UNION, тогда нам надо сделать N запросов, а не 2N.
Много запросов - это не очень хорошо, так как каждый запрос поразумевает накладные расходы (формирование запроса, передача данных по сети, разбор запроса, построение плана и оптимизация) и потому 1 запрос, выбирающий 10 записей выгоднее чем 10 запросов, выбирающих 1 запись. Так как во втором случае накладные расходы добавляются на каждый запрос. Они маленькие, на практике это может 0.2 - 1мс, но когда запросов много, в сумме может набежать много времени.
Если хочешь, можешь сделать тест, меряющий разницу между 1 и 10 запросами. Не забудь запустить его несколько раз, например 5 раз, и взять среднее, чтобы убрать погрешности. Можно даже просто сравнить запросы вида SELECT 1 и SELECT 1 UNION SELECT 2 UNION SELECT 3 .. чтобы не обращаться к таблицам и считать только накладные расходы на передачу данных.
Потому я и предложил такую схему, чтобы взять сначала N тредов, затем выбрать из них (или из доп. таблицы связи) id нужных постов и запросить посты одним запросом через WHERE id IN (?). На практике конечно надо тестировать, я мог что-то не учесть.
> Есть что-то что я упускаю? Или я путаю скорость выполнения запроса с его нагрузкой (по-моему, это пропорционально)?
А ты отключил кеш запросов? MySQL имеет кеш результатов, то есть если выполнить одинаковый запрос 2 раза, второй раз результат вернется из кеша. Надо либо отключать его через SET какой-то глобальной переменной, либо конструкцией SELECT SQL_NO_CACHE.
Также, можно посмотреть план выполнения запроса через EXPLAIN SELECT ...
Я сомневаюсь, что обход 938 строк занимает то же время, что выбор 3 записей по индексу. Ты точно отключил кеш? На 1000 строк разница должна быть заметна, даже если эти данные целиком поместились в память, и не вызвают обращения к диску.
> А что находиться в глубине вложенности? Насколько я знаю глубина вложенности это расстояние до корневого узла. Как из этого получить всю цепочку?
Глубина вложенности - это расстояние от первого поста цепочки до самого глубокого, если идти по ссылкам. Мы можем представить посты в цепочке как дерево, где корень это оргинальный пост, узлы второго уровня - посты, на которые ссылается оригинальный пост, и так далее. А у дерева есть глубина.
(если что, дерево - это структура данных, состоящая из узлов, где у каждого узла, кроме корневого, один родитель и сколько угодно детей: https://ru.wikipedia.org/wiki/Дерево_(структура_данных) )
Если A ссылается на B, B на C, C на D то глубина цепочки получается 3.
Я предложил 2 варианта, чтобы для оригинального поста выбрать все дерево постов, на которые он ссылается:
1) таблица хранит просто связь между исходным постом и теми, на которые он ссылается (один уровень). Чтобы выбрать все дерево, надо сделать N запросов где N - глубина дерева. Таблица небольшая.
Для примера выше будут записи:
A -> B
B -> C
C -> D
2) таблица хранит для каждого поста ссылки на все листья дерева, то есть для примера выше там будут записи
A -> B
A -> C
A -> D
B -> C
B -> D
C -> D
Соответственно выбрать дерево постов можно 1 запросом.
>>Не, имелось в виду что мы описываем список свойств руками в методе getFields(), а потом проходим по нему циклом и копируем из массива в объект. get_class_vars конечно не даст нам то, что нужно.
> Как тогда определить такой метод в базовом классе?
Использовать абстрактные методы: abstract protected function getFields().
> Я сомневаюсь что при хранении ссылок на последние посты и их выборка будет делать гораздо меньше нагрузки чем у простого запроса с OFFSET.
Конечно, на практике скорость выполнения запроса зависит от многих факторов, но один из главных факторов - это сколько строк таблиц должна MySQL обойти, чтобы получить результат. Индексы тут конечно тоже влияют на результат, позволяя вместо изучения всей таблицы быстро найти строки, подходящие под условие.
Чтобы сделать OFFSET, мы сначала должны сделать COUNT() для постов в треде, а это обход N строк, где N = число постов в треде. Затем, взятие 3 последних постов через OFFSET это обход и пропуск почти всех постов в треде. Тут кстати можно было просто остортировать посты треда по убыванию даты и взять первые 3, если есть индекс по (thread_id, post_date) то запрос SELECT FROM posts WHERE thread_id = ? ORDER BY post_date DESC LIMIT 3 приведет к обходу только этих 3 постов (MySQL в индексе найдет самый последний пост треда и сделает 3 шага по индексу чтобы найти 3 последних поста).
(если что, простая статья про индексы: https://ruhighload.com/post/Работа+с+индексами+в+MySQL )
Но даже в этом случае, я вижу тут недостаток: мы должны делать 2N запросов, где N - число тредов, так как для каждого треда мы должны 1 запросом получить ОП пост и вторым - последние 3 поста. Тут конечно можно выкрутиться, используя UNION, тогда нам надо сделать N запросов, а не 2N.
Много запросов - это не очень хорошо, так как каждый запрос поразумевает накладные расходы (формирование запроса, передача данных по сети, разбор запроса, построение плана и оптимизация) и потому 1 запрос, выбирающий 10 записей выгоднее чем 10 запросов, выбирающих 1 запись. Так как во втором случае накладные расходы добавляются на каждый запрос. Они маленькие, на практике это может 0.2 - 1мс, но когда запросов много, в сумме может набежать много времени.
Если хочешь, можешь сделать тест, меряющий разницу между 1 и 10 запросами. Не забудь запустить его несколько раз, например 5 раз, и взять среднее, чтобы убрать погрешности. Можно даже просто сравнить запросы вида SELECT 1 и SELECT 1 UNION SELECT 2 UNION SELECT 3 .. чтобы не обращаться к таблицам и считать только накладные расходы на передачу данных.
Потому я и предложил такую схему, чтобы взять сначала N тредов, затем выбрать из них (или из доп. таблицы связи) id нужных постов и запросить посты одним запросом через WHERE id IN (?). На практике конечно надо тестировать, я мог что-то не учесть.
> Есть что-то что я упускаю? Или я путаю скорость выполнения запроса с его нагрузкой (по-моему, это пропорционально)?
А ты отключил кеш запросов? MySQL имеет кеш результатов, то есть если выполнить одинаковый запрос 2 раза, второй раз результат вернется из кеша. Надо либо отключать его через SET какой-то глобальной переменной, либо конструкцией SELECT SQL_NO_CACHE.
Также, можно посмотреть план выполнения запроса через EXPLAIN SELECT ...
Я сомневаюсь, что обход 938 строк занимает то же время, что выбор 3 записей по индексу. Ты точно отключил кеш? На 1000 строк разница должна быть заметна, даже если эти данные целиком поместились в память, и не вызвают обращения к диску.
> А что находиться в глубине вложенности? Насколько я знаю глубина вложенности это расстояние до корневого узла. Как из этого получить всю цепочку?
Глубина вложенности - это расстояние от первого поста цепочки до самого глубокого, если идти по ссылкам. Мы можем представить посты в цепочке как дерево, где корень это оргинальный пост, узлы второго уровня - посты, на которые ссылается оригинальный пост, и так далее. А у дерева есть глубина.
(если что, дерево - это структура данных, состоящая из узлов, где у каждого узла, кроме корневого, один родитель и сколько угодно детей: https://ru.wikipedia.org/wiki/Дерево_(структура_данных) )
Если A ссылается на B, B на C, C на D то глубина цепочки получается 3.
Я предложил 2 варианта, чтобы для оригинального поста выбрать все дерево постов, на которые он ссылается:
1) таблица хранит просто связь между исходным постом и теми, на которые он ссылается (один уровень). Чтобы выбрать все дерево, надо сделать N запросов где N - глубина дерева. Таблица небольшая.
Для примера выше будут записи:
A -> B
B -> C
C -> D
2) таблица хранит для каждого поста ссылки на все листья дерева, то есть для примера выше там будут записи
A -> B
A -> C
A -> D
B -> C
B -> D
C -> D
Соответственно выбрать дерево постов можно 1 запросом.
>>Не, имелось в виду что мы описываем список свойств руками в методе getFields(), а потом проходим по нему циклом и копируем из массива в объект. get_class_vars конечно не даст нам то, что нужно.
> Как тогда определить такой метод в базовом классе?
Использовать абстрактные методы: abstract protected function getFields().
https://t.me/joinchat/AAAAAAlT02py0soe6xnbMw
Сам Расмус Лердорф уже вступил в неё и прямо сейчас раздает бесплатные советы всем желающим!
Почему-то click у jQuery не работает, использовал нативный.
test[BOLD][0][/BOLD].click()
7: https://jsfiddle.net/fxzmLmc1/
8: https://jsfiddle.net/7w3eg396/3/
У меня получилось так, что примечание можно добавить к любому тегу p, вставив aside перед ним. Так и нужно было? Добавил границы, чтобы удобнее было смотреть отступы.
9: https://jsfiddle.net/9mvy5jr7/
Тут отступ текста привязан к ширине жёлтого блока, это неправильно? Где-то читал о препроцессорах, там ширину блока можно загнать в переменную, тогда отступ текста не нужно будет менять при изменении ширины жёлтого блока.
Тут https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-12/ ссылка http://cssdeck.com/labs/full/css-responsive-tabs не работает.
> $("body img")
body тут лишний. Не стоит усложнять селекторы.
> $that.width()
Это не ошибка, но тут я хотел заметить, что важно знать различия между $that.width(), $that.outerWidth() и that.prop('width'). Первые 2 - это размеры элемента на странице, заданные через CSS, третье - это исходный размер картинки.
> $("body form textarea, input, button, select [name]")
Неправильный селектор. запятая работает не так, как ты думаешь, и выражение равносильно:
body form textarea
input
button
select [name]
Опять же, непонятно зачем тут body.
> a.getAttribute("name")
Можно просто a.name: https://developer.mozilla.org/ru/docs/Web/API/HTMLInputElement
> $postList.map(function () {
Зачем тут функция map() если ты никуда не сохраняешь результат? Для простого перебора ведь есть функция each? Map нужна для преобразования одного массива в другой.
А вообще, конечно, мне не нравится эта дурацкая тенденция лепить какие-то функции там, где должен быть цикл:
$(...).each(function () { ... });
[].forEach(function() { .. });
Разве это норально? Разве для перебора массива не принято использовать циклы (по крайней мере в других языках)? Какая выгода от добавления тут функции? разве это не лучше читается?
для каждого (x в массиве y) {
сделать что-нибудь с x;
}
Это не претензия к твоему решению, это претензия к Яваскрипту и людям которые в каждой первой статье вместо цикла городят какие-то костыли. Может и вместо if функции будет использовать? Поехавшие, честное слово, услышали что функциональный подход это модно и лепят его везде, а сами даже hello world на хаскелле написать ведь не могут.
Вот кстати, статья, где человек делает функцию для if, раз тебе нравятся функции вместо циклов, тебе может и статья понравиться: https://habrahabr.ru/post/321078/
> data.postName = $postTitle.html();
Неправильно ведь. Нам нужен не HTML код, описывающий название поста, а простой текст. Ну к примеру если в названии используются HTML-сущности вроде & lt; то мы хотим получить соответствующие им символы, а не эти коды.
> var data = {
> "postName": null,
> "views": null,
Тут ведь не требуются кавычки. И мне кажется, было бы читабельнее вычислить значения до того, как создать объект:
var postName = ...
var data = {
postName: postName,
..
};
Или даже так:
var data = {
postName: $(...).text()
};
> $comments = $comments.html();
Это конечно дело вкуса, ставить доллар или нет в переменных, но в данном случае если переменная содержит число комментариев, а не jquery элементы, то что там делает доллар?
В остальном верно.
> $("body img")
body тут лишний. Не стоит усложнять селекторы.
> $that.width()
Это не ошибка, но тут я хотел заметить, что важно знать различия между $that.width(), $that.outerWidth() и that.prop('width'). Первые 2 - это размеры элемента на странице, заданные через CSS, третье - это исходный размер картинки.
> $("body form textarea, input, button, select [name]")
Неправильный селектор. запятая работает не так, как ты думаешь, и выражение равносильно:
body form textarea
input
button
select [name]
Опять же, непонятно зачем тут body.
> a.getAttribute("name")
Можно просто a.name: https://developer.mozilla.org/ru/docs/Web/API/HTMLInputElement
> $postList.map(function () {
Зачем тут функция map() если ты никуда не сохраняешь результат? Для простого перебора ведь есть функция each? Map нужна для преобразования одного массива в другой.
А вообще, конечно, мне не нравится эта дурацкая тенденция лепить какие-то функции там, где должен быть цикл:
$(...).each(function () { ... });
[].forEach(function() { .. });
Разве это норально? Разве для перебора массива не принято использовать циклы (по крайней мере в других языках)? Какая выгода от добавления тут функции? разве это не лучше читается?
для каждого (x в массиве y) {
сделать что-нибудь с x;
}
Это не претензия к твоему решению, это претензия к Яваскрипту и людям которые в каждой первой статье вместо цикла городят какие-то костыли. Может и вместо if функции будет использовать? Поехавшие, честное слово, услышали что функциональный подход это модно и лепят его везде, а сами даже hello world на хаскелле написать ведь не могут.
Вот кстати, статья, где человек делает функцию для if, раз тебе нравятся функции вместо циклов, тебе может и статья понравиться: https://habrahabr.ru/post/321078/
> data.postName = $postTitle.html();
Неправильно ведь. Нам нужен не HTML код, описывающий название поста, а простой текст. Ну к примеру если в названии используются HTML-сущности вроде & lt; то мы хотим получить соответствующие им символы, а не эти коды.
> var data = {
> "postName": null,
> "views": null,
Тут ведь не требуются кавычки. И мне кажется, было бы читабельнее вычислить значения до того, как создать объект:
var postName = ...
var data = {
postName: postName,
..
};
Или даже так:
var data = {
postName: $(...).text()
};
> $comments = $comments.html();
Это конечно дело вкуса, ставить доллар или нет в переменных, но в данном случае если переменная содержит число комментариев, а не jquery элементы, то что там делает доллар?
В остальном верно.
Твой код анимирует body.scrollTop. Ты его тестировал в разных браузерах? Как я помню, Webkit/Blink (движок Хрома и Сафари) и Gecko (движок Firefox) используют разные элементы, один body, а другой html для прокрутки. Обычно анимируют оба элемента по этой причине.
У меня в ФФ (правда, не самом новом) страница просто прыгает скачком. Лучше чем ничего, конечно.
> Почему-то click у jQuery не работает, использовал нативный.
У меня все работает. Я зашел в консоль в браузере, перешел там внутрь ифрейма с результатом и после этого выполнил 2 команды:
var test = $("a[href='#anchor2']");
test.click();
И все заработало.
Ты все правильно сделал? У тебя в коде там click() стоит раньше чем ты ставишь обработчик на body, может в этом дело?
Ну и важно еще, чтобы страница не была уже прокручена к нужному элементу.
>>947862
> Насколько знаю, есть 2 пути:
> - вычесть эти 2 пикселя из ширины элемента. Получится width: 578px, выглядит как магическое число:
В новом CSS для этого придумывают calc и переменные: width: calc(600 - 20 - 2), также в препроцессорах CSS (которые мне не нравятся) есть вычисления и переменные, но я не вижу проблемы. Можно комментарий добавить при желании.
Если ты например захочешь сделать колонки шириной в 1/8 родителя, там ведь тоже считать придется.
Хотя конечно логика в твоих словах есть. Но использование вычислений сокращает набор поддерживаемых браузеров, оно того не стоит по моему.
> выставить ширину с учётом паддингов и использовать box-sizing: border-box:
Так тоже можно.
> Оба подхода дали одинаковые результаты, какой лучше?
Оба верные. box-sizing не поддерживался в древних фаерфоксах по моемуи в ИЕ7-, но их вряд ли где можно встретить сегодня.
Ок, верно.
> ООО «
Удобнее наверно писать & raquo; ?
> font-family: "Trebuchet MS";
Нужно тем, у кого нет шрифта, давать альтернативу в виде стандартного шрифта (serif, sans-serif и тд) которые определены стандартом CSS. Хотя требушет конечно почти везде или есть, или задана альтернатива, но все же такие правила.
> #content #list
#content тут лишний так как id уникален на странице
У тебя проблема с прочностью верстки. Попробуй сократить текст статьи до 2 слов, и увеличить число пунктов в меню, и увидишь, что рамка не охватывает меню. Я вижу что ты пытался там сделать clearfix, но clear действует только на float идущие в том же "стакане" до элемента с clear (то есть на флоаты внутри статью или перед ней), а у тебя меню в коде идет после контента. Чтобы его "очистить" тебе надо ставить clearfix на #container.
> padding-bottom: 100px;
Это ведь костыль какой-то? Я думаю, это тут не нужно.
> Вывод списка смежности в виде дерева без рекурсии:https://jsfiddle.net/wkL0ka7u/
> // var [depth, current] = stack.shift();
Ага, это ES6 и мало где поддерживается. Я даже насчет использования ES5 не уверен, а ES6 и подавно.
> var stack = list
> .filter(node => node.parentId === null)
> .map(node => [0, node]);
Этот код повторяется 2 раза, стоило вынести в функцию.
Так, в общем верно. Хотя конечно я видел дерево, нарисованное горизонтально в комментарии, и надеялся что увижу алгоритм его вывода....
Также, ты бы мог чуть улучшить (ну или запутать) код, если бы разделил код на 2 части: обход дерева и посещение вершин. Чтобы было примерно так:
traverseTree(list, visit);
И чтобы мы например этот обход где-то еще могли бы использовать.
Также, на больших деревьях оптимальнее будет вначале преобразовать линейный список в древовидную структуру, чтобы не обходить его каждый раз.
Так, решено верно.
> На PHP вышло многословно: https://ideone.com/YKik59
Ну да, тут анонимные функции чуть более громоздкие. Но зато у нас в PHP есть нормальный foreach! И тайп-хинты.
>>956568
> form input {
Хочу предупредить, такие селекторы можно использовать только в учебных задачах. На реальном сайте этот селектор заденет все инпуты во всех формах.
> form input, button {
Ты наверно хотел написать form input, form button?
Так, в общем верно.
> У меня получилось так, что примечание можно добавить к любому тегу p, вставив aside перед ним. Так и нужно было?
Да.
Но у тебя есть проблемка: попробуй поставить 2 или 3 примечания подряд. Они накладываются друг на друга. Надо решить эту проблему. Ну и опытный верстальщик конечно должен предугадывать возможность появления такой проблемы.
> Добавил границы, чтобы удобнее было смотреть отступы.
Тут удобно использовать outline, так как оно не влияет на верстку и размеры.
> Тут отступ текста привязан к ширине жёлтого блока, это неправильно?
Ничего не поделать.
> Где-то читал о препроцессорах, там ширину блока можно загнать в переменную, тогда отступ текста не нужно будет менять при изменении ширины жёлтого блока.
Да, есть такое. Но мне они не нравятся тем, что появляется дополнительный этап и надо перекомпилировать код чтобы увидеть изменения. Но это мое личное мнение. Также, в новом CSS будут переменные (с жутким синтаксисом, сделанным чтобы их никто не хотел использовать): http://frontender.info/css-variables-why-should-you-care/
Вообще, раз тебе интересны препроцессоры, я советую с ними познакомиться. Самые известные - LESS и SASS, увы, не помню какой из них сейчас в моде. Изучи их, это недолго, но вдруг что полезное увидишь.
Решено верно.
> Тут https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-12/ ссылка http://cssdeck.com/labs/full/css-responsive-tabs не работает.
Спасибо за информацию. Изучение исходного кода показывает, что там стоит ифрейм, меняем там в URL s.cssdesk.com на cssdesk.com и все работает: http://cssdeck.com/labs/full/css-responsive-tabs//noframe#dontkillanim
Твой код анимирует body.scrollTop. Ты его тестировал в разных браузерах? Как я помню, Webkit/Blink (движок Хрома и Сафари) и Gecko (движок Firefox) используют разные элементы, один body, а другой html для прокрутки. Обычно анимируют оба элемента по этой причине.
У меня в ФФ (правда, не самом новом) страница просто прыгает скачком. Лучше чем ничего, конечно.
> Почему-то click у jQuery не работает, использовал нативный.
У меня все работает. Я зашел в консоль в браузере, перешел там внутрь ифрейма с результатом и после этого выполнил 2 команды:
var test = $("a[href='#anchor2']");
test.click();
И все заработало.
Ты все правильно сделал? У тебя в коде там click() стоит раньше чем ты ставишь обработчик на body, может в этом дело?
Ну и важно еще, чтобы страница не была уже прокручена к нужному элементу.
>>947862
> Насколько знаю, есть 2 пути:
> - вычесть эти 2 пикселя из ширины элемента. Получится width: 578px, выглядит как магическое число:
В новом CSS для этого придумывают calc и переменные: width: calc(600 - 20 - 2), также в препроцессорах CSS (которые мне не нравятся) есть вычисления и переменные, но я не вижу проблемы. Можно комментарий добавить при желании.
Если ты например захочешь сделать колонки шириной в 1/8 родителя, там ведь тоже считать придется.
Хотя конечно логика в твоих словах есть. Но использование вычислений сокращает набор поддерживаемых браузеров, оно того не стоит по моему.
> выставить ширину с учётом паддингов и использовать box-sizing: border-box:
Так тоже можно.
> Оба подхода дали одинаковые результаты, какой лучше?
Оба верные. box-sizing не поддерживался в древних фаерфоксах по моемуи в ИЕ7-, но их вряд ли где можно встретить сегодня.
Ок, верно.
> ООО «
Удобнее наверно писать & raquo; ?
> font-family: "Trebuchet MS";
Нужно тем, у кого нет шрифта, давать альтернативу в виде стандартного шрифта (serif, sans-serif и тд) которые определены стандартом CSS. Хотя требушет конечно почти везде или есть, или задана альтернатива, но все же такие правила.
> #content #list
#content тут лишний так как id уникален на странице
У тебя проблема с прочностью верстки. Попробуй сократить текст статьи до 2 слов, и увеличить число пунктов в меню, и увидишь, что рамка не охватывает меню. Я вижу что ты пытался там сделать clearfix, но clear действует только на float идущие в том же "стакане" до элемента с clear (то есть на флоаты внутри статью или перед ней), а у тебя меню в коде идет после контента. Чтобы его "очистить" тебе надо ставить clearfix на #container.
> padding-bottom: 100px;
Это ведь костыль какой-то? Я думаю, это тут не нужно.
> Вывод списка смежности в виде дерева без рекурсии:https://jsfiddle.net/wkL0ka7u/
> // var [depth, current] = stack.shift();
Ага, это ES6 и мало где поддерживается. Я даже насчет использования ES5 не уверен, а ES6 и подавно.
> var stack = list
> .filter(node => node.parentId === null)
> .map(node => [0, node]);
Этот код повторяется 2 раза, стоило вынести в функцию.
Так, в общем верно. Хотя конечно я видел дерево, нарисованное горизонтально в комментарии, и надеялся что увижу алгоритм его вывода....
Также, ты бы мог чуть улучшить (ну или запутать) код, если бы разделил код на 2 части: обход дерева и посещение вершин. Чтобы было примерно так:
traverseTree(list, visit);
И чтобы мы например этот обход где-то еще могли бы использовать.
Также, на больших деревьях оптимальнее будет вначале преобразовать линейный список в древовидную структуру, чтобы не обходить его каждый раз.
Так, решено верно.
> На PHP вышло многословно: https://ideone.com/YKik59
Ну да, тут анонимные функции чуть более громоздкие. Но зато у нас в PHP есть нормальный foreach! И тайп-хинты.
>>956568
> form input {
Хочу предупредить, такие селекторы можно использовать только в учебных задачах. На реальном сайте этот селектор заденет все инпуты во всех формах.
> form input, button {
Ты наверно хотел написать form input, form button?
Так, в общем верно.
> У меня получилось так, что примечание можно добавить к любому тегу p, вставив aside перед ним. Так и нужно было?
Да.
Но у тебя есть проблемка: попробуй поставить 2 или 3 примечания подряд. Они накладываются друг на друга. Надо решить эту проблему. Ну и опытный верстальщик конечно должен предугадывать возможность появления такой проблемы.
> Добавил границы, чтобы удобнее было смотреть отступы.
Тут удобно использовать outline, так как оно не влияет на верстку и размеры.
> Тут отступ текста привязан к ширине жёлтого блока, это неправильно?
Ничего не поделать.
> Где-то читал о препроцессорах, там ширину блока можно загнать в переменную, тогда отступ текста не нужно будет менять при изменении ширины жёлтого блока.
Да, есть такое. Но мне они не нравятся тем, что появляется дополнительный этап и надо перекомпилировать код чтобы увидеть изменения. Но это мое личное мнение. Также, в новом CSS будут переменные (с жутким синтаксисом, сделанным чтобы их никто не хотел использовать): http://frontender.info/css-variables-why-should-you-care/
Вообще, раз тебе интересны препроцессоры, я советую с ними познакомиться. Самые известные - LESS и SASS, увы, не помню какой из них сейчас в моде. Изучи их, это недолго, но вдруг что полезное увидишь.
Решено верно.
> Тут https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-12/ ссылка http://cssdeck.com/labs/full/css-responsive-tabs не работает.
Спасибо за информацию. Изучение исходного кода показывает, что там стоит ифрейм, меняем там в URL s.cssdesk.com на cssdesk.com и все работает: http://cssdeck.com/labs/full/css-responsive-tabs//noframe#dontkillanim
на практике по моему нет. Там есть функции вроде headers_sent, но они часто возвращают что-то не то (или они делают не совсем то, что описано в названии).
>>956671
Я когда-то давно проверял ее и она врала. По умолчанию, кстати, там есть какая-то буферизация и если ты вывел немного текста, то заголовки еще по-прежнему можно слать, но это зависит от конфига PHP и используемого веб-сервера.
>>956211
Нужно настроить веб-сервер, чтобы он например для URL /xyz вызывал бы нужный тебе скрипт. Это настраивается по-разному в разных серверах. В Апаче через .htaccess и mod_rewrite. Обычно просто все нестатические УРЛ переадресовывают на index.php.
В этом и предыдущем треде под 1000 постов и я замучаюсь все это читать.
А строки точно удалились? Скорее всего была ошибка, просто может у тебя они не отображаются или не проверяются и ты не знаешь о них.
Если ты использешь mysqli то там после каждого действия с базой надо вручную проверять, нет ли ошибки, сам он ничего не сообщает.
>>955259
Алгоритм неправильный. Надо проверять что x >= min && x <= max, а не как у тебя. Ну или проверять abs(x - correct) <= dev
>>955233
Ну это такие особенности PHP. Там разница в том, что во втором случае toString вызывается неявно. Я бы советовал не использовать такое в своем коде вообще. Также, мне не нравится tosString так как при его наличии можно не заметить ошибку (использование объекта там, где нужна строка).
А так, ты правильно делаешь, что читаешь документацию. Если ты новичок, с большой вероятностью на собеседовании будут вопросы или тесты по ней.
>>955227
> abstract function checkQuestionAndAnswer($answer);
Лучше checkAnswer. Ты же ответ проверяешь. Или isAnswerCorrect.
> if ($this->correctOption == $answer) {
> return true;
Так как оператор == возвращает true/false, то можно писать просто:
return x == y
Проверка ответа с погрешностью сделана неправильно.
В остальном верно.
>>955205
Не уверен.
>>955187
Это пример неудачного проектирования функции. Ты, как будущий разработчик, должен учиться на таких примерах и не повторять чужих ошибок в своем коде. Да, всегда лучше иметь один строго заданный тип данных и для аргументов, и для результата.
Давай я тебе дам еще примеров, изучай: https://habrahabr.ru/post/315152/ (правда перевод ужасного качества)
>>955157
Ты про alert в JS? Нельзя, можно только создать имитацию окна с помощью дивов на странице.
>>955156
Очень редко, лучше избегать.
А строки точно удалились? Скорее всего была ошибка, просто может у тебя они не отображаются или не проверяются и ты не знаешь о них.
Если ты использешь mysqli то там после каждого действия с базой надо вручную проверять, нет ли ошибки, сам он ничего не сообщает.
>>955259
Алгоритм неправильный. Надо проверять что x >= min && x <= max, а не как у тебя. Ну или проверять abs(x - correct) <= dev
>>955233
Ну это такие особенности PHP. Там разница в том, что во втором случае toString вызывается неявно. Я бы советовал не использовать такое в своем коде вообще. Также, мне не нравится tosString так как при его наличии можно не заметить ошибку (использование объекта там, где нужна строка).
А так, ты правильно делаешь, что читаешь документацию. Если ты новичок, с большой вероятностью на собеседовании будут вопросы или тесты по ней.
>>955227
> abstract function checkQuestionAndAnswer($answer);
Лучше checkAnswer. Ты же ответ проверяешь. Или isAnswerCorrect.
> if ($this->correctOption == $answer) {
> return true;
Так как оператор == возвращает true/false, то можно писать просто:
return x == y
Проверка ответа с погрешностью сделана неправильно.
В остальном верно.
>>955205
Не уверен.
>>955187
Это пример неудачного проектирования функции. Ты, как будущий разработчик, должен учиться на таких примерах и не повторять чужих ошибок в своем коде. Да, всегда лучше иметь один строго заданный тип данных и для аргументов, и для результата.
Давай я тебе дам еще примеров, изучай: https://habrahabr.ru/post/315152/ (правда перевод ужасного качества)
>>955157
Ты про alert в JS? Нельзя, можно только создать имитацию окна с помощью дивов на странице.
>>955156
Очень редко, лучше избегать.
https://github.com/never3ver/fileshare
>>Это конечно хорошая идея, добавить поддержку gzip, но тогда надо дописать генератор сжатых версий файлов (и тщательно протестировать это в разных браузерах).
>> В условия, кроме проверки наличия сжатого файла, стоит еще добавить проверку существования оригинала.
> Что понимается под генератором сжатых версий? В интернетах я встречаю мнение, что .htaccess достаточно
Там предлагают сжимать файлы на лету, то есть тратить какую-то часть времени процессора ради уменьшения трафика и ускорения отдачи файлов. В принципе смысл в этом есть, если сервер используется только для раздачи файлов, то скорее всего у него процессор не сильно нагружен, да и gzip современные процессоры не сильно грузит. Но есть и другой подход - заранее положить на диск сжатые версии файлов и отдавать их клиентам, заявляющим о поддержке сжатия. Так мы не грузим процессор, но появляется необходимость создавать и обновлть эти сжатые копии файлов.
На практике можно смотреть на загрузку процессора - если свободные ресурсы есть, то можно жать и на лету. Обычно они есть.
> К этому я вообще не знаю как подойти. Если это cli, то как и зачем вью?
Я думаю, там не нужен отдельный вью, хватит команды echo.
> И что будет из себя представлять контроллер?
Простой php-файл в папке с названием вроде cli или command.
> Мне в голову кроме допустим switch с кейсами в виде опций командной строки ничего в голову не приходит.
Есть стандартная функция getopt, если она не подойдет, пиши свою функцию разбора аргументов.
Мануал в помощь:
- http://php.net/manual/ru/function.getopt.php
- http://php.net/manual/ru/reserved.variables.argv.php
- http://php.net/manual/ru/features.commandline.php
https://github.com/never3ver/fileshare/blob/master/test_fileshare.sql
> COMMENT 'artificially generated name of file',
Лучше было написать 'the name under which the file is stored on disk'
> `json` varchar(128) DEFAULT NULL
Название неудачное, JSON это ведь формат хранения, а не смысл хранимых данных. Правильнее metadata например или properties, как-то так.
> `uploadTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
Почему время загрузки может меняться при обновлении записи?
Индекс по tmpName должен быть уникальным.
https://github.com/never3ver/fileshare/blob/master/sphinx.conf
Тут есть недостаток, что нам приходится дублировать данные конфига (например доступа к БД). А также, многократно копипастить пути к папкам. Обрати внимание, что sphinx позволяет добавлять в конфиги php-код (или код на других языках): http://sphinxsearch.com/blog/2013/11/05/sphinx-configuration-features-and-tricks/
Это позволяет брать данные из конфига или из переменных окружения или просто задавать их 1 раз.
Хотя если это усложнит код, может тут и не стоит это использовать. Подумай.
> sql_field_string = name
А зачем объявлять name как отдельный атрибут? Это как-то используется? Если нет, то лучше не тратить память на дублирование данных которые есть в БД. для поиска не требуется создавать атрибут. Атрибут нужен для фильтров по нему и для хранения данных в сфинксе.
> source name
можно было придумать название источника получше
> html_strip = 1
Не очень понятно зачем вырезать HTML-код из имен файлов, где его в общем-то и нет.
https://github.com/never3ver/fileshare/blob/master/copyBootstrap.php#L13
тут нет перевода строки, и возможно, при ошибке лучше выкидывать исключение? Или завершать скрипт с ненулевым кодом. А сейчас твои ошибки увидит разве что человек, а при автоматизированном разворачивании проекта никто и не заметит.
По поводу тестов: а ты бы не хотел попробовать подключить CI сервер к гитхабу, который может автоматически прогонять тесты на каждый коммит? Также ты сможешь добавить в ридми значок, показывающий текущий результат тестирования.
Гитхаб умеет интегрироваться с разными сервисами: https://github.com/integrations/feature/continuous-integration
Из этих сервисов мне знаком Travis CI. Это коммерческий сервис, я не говорю что он лучше или хуже других, и не рекламирую его, просто он бесплатен для открытых проектов.
Для интеграции надо сделать в репозитории конфиг, который описывает порядок разворачивания проекта и запуска тестов, задает разные настройки. Все это описано в документации:
- https://docs.travis-ci.com/user/languages/php/
При желании можно на гитхабе легко найти примеры готовых конфигов.
Тебе надо будет настроить в конфиге установку зависимостей через композер, разворачивание БД, установку и запуск сфинкса, если он участвует в тестах.
После того, как конфиг готов, надо настроить интеграцию на гитхабе, чтобы он сообщал в Travis о каждом коммите и забирал результаты тестов. Ну и можно добавить бейджик в ридми.
Также, phpunit умеет генерировать coverage report, то есть считать, какая часть кода была задействована в ходе тестирования.
Можешь попробовать, если есть время. Я, конечно, могу подсказать что-то по настройке.
> php_value max_execution_time 500
Вот эта строчка мне не очень нравится, она ведь защищает от кривых зависших скриптов, может быть время загрузки файла не учитывается тут и нет необходимости повышать это ограничение?
> $container['FileDataGateway']
> $container['sphinx']
Надо привыкать называть однотипные вещи единообразно, а у тебя одно название с маленькой буквы, другое с большой.
> $app->post('/', function (Request $request, Response $response) {
> if ($_FILES) {
> много кода
> }
> });
А что будет, если if не сработает? Надо бы ошибку выдавать. И конечно надо этот if перевернуть, не надо такие огромные ифы делать.
И лучше было проверять не _FILES, а результат getUploadedFiles(), мы же с фреймворком работаем.
> $tmpName = $this->FileDataGateway->createTmpName();
> if ($this->FileDataGateway->isTmpNameExisting($tmpName)) {
Это лучше было сделать по-другому, если не удалось сгенерировать имя с N попыток, то выбрасывать исключение.
Более того, я тут вижу баг: ты сначала генерируешь имя и проверяешь на уникальность, а только потом приписываешь к имени папку с датой. То есть проверяешь ты непонятно что.
И где тут разделение ответственности? Кто отвечает за генерацию и проверку имени, FileDataGateway или index.php?
Ну и может стоило имена как-то почеловечнее сделать.
https://github.com/never3ver/fileshare
>>Это конечно хорошая идея, добавить поддержку gzip, но тогда надо дописать генератор сжатых версий файлов (и тщательно протестировать это в разных браузерах).
>> В условия, кроме проверки наличия сжатого файла, стоит еще добавить проверку существования оригинала.
> Что понимается под генератором сжатых версий? В интернетах я встречаю мнение, что .htaccess достаточно
Там предлагают сжимать файлы на лету, то есть тратить какую-то часть времени процессора ради уменьшения трафика и ускорения отдачи файлов. В принципе смысл в этом есть, если сервер используется только для раздачи файлов, то скорее всего у него процессор не сильно нагружен, да и gzip современные процессоры не сильно грузит. Но есть и другой подход - заранее положить на диск сжатые версии файлов и отдавать их клиентам, заявляющим о поддержке сжатия. Так мы не грузим процессор, но появляется необходимость создавать и обновлть эти сжатые копии файлов.
На практике можно смотреть на загрузку процессора - если свободные ресурсы есть, то можно жать и на лету. Обычно они есть.
> К этому я вообще не знаю как подойти. Если это cli, то как и зачем вью?
Я думаю, там не нужен отдельный вью, хватит команды echo.
> И что будет из себя представлять контроллер?
Простой php-файл в папке с названием вроде cli или command.
> Мне в голову кроме допустим switch с кейсами в виде опций командной строки ничего в голову не приходит.
Есть стандартная функция getopt, если она не подойдет, пиши свою функцию разбора аргументов.
Мануал в помощь:
- http://php.net/manual/ru/function.getopt.php
- http://php.net/manual/ru/reserved.variables.argv.php
- http://php.net/manual/ru/features.commandline.php
https://github.com/never3ver/fileshare/blob/master/test_fileshare.sql
> COMMENT 'artificially generated name of file',
Лучше было написать 'the name under which the file is stored on disk'
> `json` varchar(128) DEFAULT NULL
Название неудачное, JSON это ведь формат хранения, а не смысл хранимых данных. Правильнее metadata например или properties, как-то так.
> `uploadTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
Почему время загрузки может меняться при обновлении записи?
Индекс по tmpName должен быть уникальным.
https://github.com/never3ver/fileshare/blob/master/sphinx.conf
Тут есть недостаток, что нам приходится дублировать данные конфига (например доступа к БД). А также, многократно копипастить пути к папкам. Обрати внимание, что sphinx позволяет добавлять в конфиги php-код (или код на других языках): http://sphinxsearch.com/blog/2013/11/05/sphinx-configuration-features-and-tricks/
Это позволяет брать данные из конфига или из переменных окружения или просто задавать их 1 раз.
Хотя если это усложнит код, может тут и не стоит это использовать. Подумай.
> sql_field_string = name
А зачем объявлять name как отдельный атрибут? Это как-то используется? Если нет, то лучше не тратить память на дублирование данных которые есть в БД. для поиска не требуется создавать атрибут. Атрибут нужен для фильтров по нему и для хранения данных в сфинксе.
> source name
можно было придумать название источника получше
> html_strip = 1
Не очень понятно зачем вырезать HTML-код из имен файлов, где его в общем-то и нет.
https://github.com/never3ver/fileshare/blob/master/copyBootstrap.php#L13
тут нет перевода строки, и возможно, при ошибке лучше выкидывать исключение? Или завершать скрипт с ненулевым кодом. А сейчас твои ошибки увидит разве что человек, а при автоматизированном разворачивании проекта никто и не заметит.
По поводу тестов: а ты бы не хотел попробовать подключить CI сервер к гитхабу, который может автоматически прогонять тесты на каждый коммит? Также ты сможешь добавить в ридми значок, показывающий текущий результат тестирования.
Гитхаб умеет интегрироваться с разными сервисами: https://github.com/integrations/feature/continuous-integration
Из этих сервисов мне знаком Travis CI. Это коммерческий сервис, я не говорю что он лучше или хуже других, и не рекламирую его, просто он бесплатен для открытых проектов.
Для интеграции надо сделать в репозитории конфиг, который описывает порядок разворачивания проекта и запуска тестов, задает разные настройки. Все это описано в документации:
- https://docs.travis-ci.com/user/languages/php/
При желании можно на гитхабе легко найти примеры готовых конфигов.
Тебе надо будет настроить в конфиге установку зависимостей через композер, разворачивание БД, установку и запуск сфинкса, если он участвует в тестах.
После того, как конфиг готов, надо настроить интеграцию на гитхабе, чтобы он сообщал в Travis о каждом коммите и забирал результаты тестов. Ну и можно добавить бейджик в ридми.
Также, phpunit умеет генерировать coverage report, то есть считать, какая часть кода была задействована в ходе тестирования.
Можешь попробовать, если есть время. Я, конечно, могу подсказать что-то по настройке.
> php_value max_execution_time 500
Вот эта строчка мне не очень нравится, она ведь защищает от кривых зависших скриптов, может быть время загрузки файла не учитывается тут и нет необходимости повышать это ограничение?
> $container['FileDataGateway']
> $container['sphinx']
Надо привыкать называть однотипные вещи единообразно, а у тебя одно название с маленькой буквы, другое с большой.
> $app->post('/', function (Request $request, Response $response) {
> if ($_FILES) {
> много кода
> }
> });
А что будет, если if не сработает? Надо бы ошибку выдавать. И конечно надо этот if перевернуть, не надо такие огромные ифы делать.
И лучше было проверять не _FILES, а результат getUploadedFiles(), мы же с фреймворком работаем.
> $tmpName = $this->FileDataGateway->createTmpName();
> if ($this->FileDataGateway->isTmpNameExisting($tmpName)) {
Это лучше было сделать по-другому, если не удалось сгенерировать имя с N попыток, то выбрасывать исключение.
Более того, я тут вижу баг: ты сначала генерируешь имя и проверяешь на уникальность, а только потом приписываешь к имени папку с датой. То есть проверяешь ты непонятно что.
И где тут разделение ответственности? Кто отвечает за генерацию и проверку имени, FileDataGateway или index.php?
Ну и может стоило имена как-то почеловечнее сделать.
> if (!is_dir($this->helper->getFilePath('') . $datePath)) {
Это какие-то костыли, ты передаешь в функцию вместо имени пустую строку. Это же неправильно. И вдобавок код генерации имени файла размазан по index.php и другим классам.
Сделай просто нормальную функцию, которая получает на вход UploadedFile, генерирует подходящее имя, создает папки и помещает туда файл, и может быть, возвращает это временное имя.
Заодно эту функцию можно будет покрыть тестами.
> $file->setType($uploadedFile->getClientMediaType());
Я бы советовал особо не доверять переданному типу. Там может быть что угодно. Если ты вызываешь getId3, то стоит брать тип, который она определит.
> $url = $this->router->pathFor('list');
> $response = $response->withStatus(302)->withHeader('Location', $url);
А не лучше редиректить на страницу с самим файлом?
> if (is_readable($this->helper->getFilePath($file->getTmpName()))) {
> } else {
> throw new \Slim\Exception\NotFoundException($request, $response);
Это тоже неправильно. При внутренней ошибке на сервере надо использовать код 5xx, коды 4xx предназначены для ошибок в запросе от клиента. Почитай про коды состояния HTTP хотя бы в википедии, когда какие применяются.
https://github.com/never3ver/fileshare/blob/master/public/index.php#L125
Отдачу файла стоило бы вынести в отдельную функцию где-нибудь в хелпере.
https://github.com/never3ver/fileshare/blob/master/public/index.php#L122
> $file = $this->FileDataGateway->getFile($id);
> $path = $this->helper->getFilePath($file->getTmpName());
тут нет проверки что файл с таким id вообще есть в БД.
Если файл есть в БД, но нет на диске, я бы предлагал бросать исключение. Чтобы информация попала бы в логи ошибок. Это ведь именно ошибка на сервере, а не 404.
> if ($file->getJson() != '') {
> $sql = "INSERT INTO fileshare (`name`, `tmpname`, `size`, `type`, `json`)"
> . " VALUES (:name, :tmpname, :size, :type, :json)";
Если JSON отстутвует, незачем делать второй вариант SQL запроса, можно просто передать вместо него NULL.
> https://github.com/never3ver/fileshare/blob/master/app/File.php#L77
Если это функция для проверки, надо ли отдавать файл в getId3, то я советую просто проверять на такие типы:
image/
audio/
video/
То есть не проверять вторую часть, тем более что getId3 поддерживает намного больше форматов, чем у тебя указано. А так, если что, официальный список типов можно найти например тут: http://www.iana.org/assignments/media-types/media-types.xhtml
Про то, как формируются эти типы, что значит vnd и плюсики, можно прочесть в википедии.
Насчет метаданных - я бы предложил попробовать класть объект с метаданными внутрь File. Чтобы мы могли вызывать $file->getMetadata()->getBitrate(). Надо будет немного заморочиться с преобразованием в JSON при сохранении и с обратным преобразованием при загрузке из БД. Хотя, может конечно, это лишнее усложнение.
Также, я бы сделал 2 отдельных статических конструктора: для случая когда надо сгенерировать данные, и для случая, когда надо восстановить их из БД. Так было бы намного нагляднее и меньше шансов допустить ошибку.
Не уверен, что нужно передавать контейнер в FileInfo, это не соответствует DI, лучше передавать конкретные сервисы. А еще лучше - не передавать зависимостей вообще (кроме GetID3 при генерации данных).
https://github.com/never3ver/fileshare/blob/master/app/FileInfo.php#L58
Мне кажется, эта функция должна быть не тут. Класс называется FileInfo и хранит информацию о файле, почему он еще создает какие-то папки? Я бы посместил эту задачу в сервис работы с файлами, можно туда же, где и функция сохранения файла в хранилище.
Что-то у тебя плохо с разделением обязанностей между классами. Ну не, правда, код как-то случайно раскидан по классам.
https://github.com/never3ver/fileshare/blob/master/app/FileInfo.php#L83
Эту стену кода однозначно надо выносить в какой-нибудь хелпер. И убрать из нее копипасту, если можно. Может эта функция где-то еще пригодится.
И кстати, превью для png не обязано быть в формате png.
Можно еще подумать над генерацией превьюшек для видео.
> public function getImagePreviewUrl($tmpName) {
> return '../files/preview/' . $tmpName;
Это ненадежная функция, так как относительный путь зависит от текщего URL. Не надо так делать.
https://github.com/never3ver/fileshare/blob/master/app/Sphinx.php#L12
Здесь ты передаешь запрос в сфинкс без изменений - так и надо? Чтобы можно было использовать в запросе всякие операторы?
> INSERT INTO rt VALUES (:id, 'temp', :name)";
Тут надо указывать, в какие колонки ты что вставляешь, а то у тебя все зависит от порядка в котором определены колонки в конфиге. Ненадежно.
Я не вижу единой функции поиска, которая бы искала данные и в обычном, и в RT индексе и объединяла результаты.
Название индекса тоже неудачное, лучше rt_files.
https://github.com/never3ver/fileshare/blob/master/templates/base.html.twig#L27
> placeholder="{{query}}"
зачем запрос подставлять в плейсхолдер? Почему не в value?
https://github.com/never3ver/fileshare/blob/master/templates/file.html.twig#L19
> <img class="leftmargin" src="{{ fileInfo.getPreview() }}">
По моему, по стандарту атрибут alt с описанием содержимого обязателен. В стандарте этому факту отведено много места и подробно расписано почему (на англ): https://www.w3.org/TR/html5/embedded-content-0.html#the-img-element
Так как ты пока не на работе, старайся соблюдать стандарты. А на работе будешь соблюдать требования заказчика.
> if (!is_dir($this->helper->getFilePath('') . $datePath)) {
Это какие-то костыли, ты передаешь в функцию вместо имени пустую строку. Это же неправильно. И вдобавок код генерации имени файла размазан по index.php и другим классам.
Сделай просто нормальную функцию, которая получает на вход UploadedFile, генерирует подходящее имя, создает папки и помещает туда файл, и может быть, возвращает это временное имя.
Заодно эту функцию можно будет покрыть тестами.
> $file->setType($uploadedFile->getClientMediaType());
Я бы советовал особо не доверять переданному типу. Там может быть что угодно. Если ты вызываешь getId3, то стоит брать тип, который она определит.
> $url = $this->router->pathFor('list');
> $response = $response->withStatus(302)->withHeader('Location', $url);
А не лучше редиректить на страницу с самим файлом?
> if (is_readable($this->helper->getFilePath($file->getTmpName()))) {
> } else {
> throw new \Slim\Exception\NotFoundException($request, $response);
Это тоже неправильно. При внутренней ошибке на сервере надо использовать код 5xx, коды 4xx предназначены для ошибок в запросе от клиента. Почитай про коды состояния HTTP хотя бы в википедии, когда какие применяются.
https://github.com/never3ver/fileshare/blob/master/public/index.php#L125
Отдачу файла стоило бы вынести в отдельную функцию где-нибудь в хелпере.
https://github.com/never3ver/fileshare/blob/master/public/index.php#L122
> $file = $this->FileDataGateway->getFile($id);
> $path = $this->helper->getFilePath($file->getTmpName());
тут нет проверки что файл с таким id вообще есть в БД.
Если файл есть в БД, но нет на диске, я бы предлагал бросать исключение. Чтобы информация попала бы в логи ошибок. Это ведь именно ошибка на сервере, а не 404.
> if ($file->getJson() != '') {
> $sql = "INSERT INTO fileshare (`name`, `tmpname`, `size`, `type`, `json`)"
> . " VALUES (:name, :tmpname, :size, :type, :json)";
Если JSON отстутвует, незачем делать второй вариант SQL запроса, можно просто передать вместо него NULL.
> https://github.com/never3ver/fileshare/blob/master/app/File.php#L77
Если это функция для проверки, надо ли отдавать файл в getId3, то я советую просто проверять на такие типы:
image/
audio/
video/
То есть не проверять вторую часть, тем более что getId3 поддерживает намного больше форматов, чем у тебя указано. А так, если что, официальный список типов можно найти например тут: http://www.iana.org/assignments/media-types/media-types.xhtml
Про то, как формируются эти типы, что значит vnd и плюсики, можно прочесть в википедии.
Насчет метаданных - я бы предложил попробовать класть объект с метаданными внутрь File. Чтобы мы могли вызывать $file->getMetadata()->getBitrate(). Надо будет немного заморочиться с преобразованием в JSON при сохранении и с обратным преобразованием при загрузке из БД. Хотя, может конечно, это лишнее усложнение.
Также, я бы сделал 2 отдельных статических конструктора: для случая когда надо сгенерировать данные, и для случая, когда надо восстановить их из БД. Так было бы намного нагляднее и меньше шансов допустить ошибку.
Не уверен, что нужно передавать контейнер в FileInfo, это не соответствует DI, лучше передавать конкретные сервисы. А еще лучше - не передавать зависимостей вообще (кроме GetID3 при генерации данных).
https://github.com/never3ver/fileshare/blob/master/app/FileInfo.php#L58
Мне кажется, эта функция должна быть не тут. Класс называется FileInfo и хранит информацию о файле, почему он еще создает какие-то папки? Я бы посместил эту задачу в сервис работы с файлами, можно туда же, где и функция сохранения файла в хранилище.
Что-то у тебя плохо с разделением обязанностей между классами. Ну не, правда, код как-то случайно раскидан по классам.
https://github.com/never3ver/fileshare/blob/master/app/FileInfo.php#L83
Эту стену кода однозначно надо выносить в какой-нибудь хелпер. И убрать из нее копипасту, если можно. Может эта функция где-то еще пригодится.
И кстати, превью для png не обязано быть в формате png.
Можно еще подумать над генерацией превьюшек для видео.
> public function getImagePreviewUrl($tmpName) {
> return '../files/preview/' . $tmpName;
Это ненадежная функция, так как относительный путь зависит от текщего URL. Не надо так делать.
https://github.com/never3ver/fileshare/blob/master/app/Sphinx.php#L12
Здесь ты передаешь запрос в сфинкс без изменений - так и надо? Чтобы можно было использовать в запросе всякие операторы?
> INSERT INTO rt VALUES (:id, 'temp', :name)";
Тут надо указывать, в какие колонки ты что вставляешь, а то у тебя все зависит от порядка в котором определены колонки в конфиге. Ненадежно.
Я не вижу единой функции поиска, которая бы искала данные и в обычном, и в RT индексе и объединяла результаты.
Название индекса тоже неудачное, лучше rt_files.
https://github.com/never3ver/fileshare/blob/master/templates/base.html.twig#L27
> placeholder="{{query}}"
зачем запрос подставлять в плейсхолдер? Почему не в value?
https://github.com/never3ver/fileshare/blob/master/templates/file.html.twig#L19
> <img class="leftmargin" src="{{ fileInfo.getPreview() }}">
По моему, по стандарту атрибут alt с описанием содержимого обязателен. В стандарте этому факту отведено много места и подробно расписано почему (на англ): https://www.w3.org/TR/html5/embedded-content-0.html#the-img-element
Так как ты пока не на работе, старайся соблюдать стандарты. А на работе будешь соблюдать требования заказчика.
https://github.com/never3ver/fileshare/blob/master/tests/app/HelperTest.php#L5
> PHPUnit_Framework_TestCase
Обрати внимание, что сейчас в phpunit используются неймспейсы вместо подчеркиваний, подчеркивания поддерживаются только ради совместимости. Советую отказаться от них.
https://github.com/never3ver/fileshare/blob/master/tests/app/HelperTest.php#L10
Для тестов логично иметь доступ к настроенному контейнеру, чтобы брать из него сервисы. Зачем создавать их вручную?
Однако, нам может понадобиться отдельный конфиг. Для этого вводят такое понятие, как окружение: в тестовом окружении данные берутся из одного конфига (config_test.php), в продакшене - из другого (config_prod.php). Окружение можно выбирать через переменные окружения, например APP_ENV.
Другой вариант - можно переопределять настройки в переменных окрежения. В случае то же Travis это позволяет прописать настройки тестовой БД прямо в конфиге тревиса и не загрязнять ими код:
- env:
- APP_DB_NAME: test_db
- APP_DB_HOST: 127.0.0.1
Также, есть еще такой вариант: делаем основной конфиг (config.php) и дополнительный (config.local.php), который переопределяет часть настроек. Локальный конфиг не отравляется в гит и может отсутствовать вообще.
https://github.com/never3ver/fileshare/blob/master/tests/app/HelperTest.php#L19
> $this->assertRegExp('/^[a-zA-Z0-9]{45}$/i',
Тут в тесте заложено слишком много подробностей. Почему имя должно иметь длину 45 символов? Что если завтра длина поменяется?
Я бы просто проверял, что возвращается не пустая строка, может дополнительно - что она содержит определенные символы, но уж точно не стоит закладывать в тест конкретную длину строки, если только она не прописана в ТЗ на разработку приложения.
Вот попробуй подумать с точки зрения требований к функции: нам принципиально, чтобы она генерировала имена ровно в 45 символов? Наверно, нет. Нам надо чтобы она 1) генерировала имена файлов 2) чтобы они не повторялись с уже существующими. При этом требование 2 без базы проверить сложно.
https://github.com/never3ver/fileshare/blob/master/tests/app/FileInfoTest.php
Тут я вижу такие проблемы:
Ты опираешься на знание о том, как работает внутренняя логика класса. Ты передаешь имя несуществующего файла, зная, что класс не будет к нему обращаться. Это ненадежно, так как завтра он начнет проверять наличие файла и тест сломается.
В принципе ради теста вполне можно сгенерировать или загрузить файл, который автоматически удалить после теста в tearDown(). А вот опираться на знание внутренней логики работы класса не стоит. Тестировать надо публично доступные интерфейсы, то, что класс выставляет наружу, что что описано в комментариях к функциям.
В твоем случае можно заказчать заранее подготовленную картинку или текстовый файл. Но важно сделать тест так, чтобы он тестировал именно логику в твоем коде, а не например способность getId3 определить битрейт видеофайла - это уже не наша задача.
Что тут можно протестировать? Первое - что код просто работает и не падает (smoke test). Берем заранее подготовленный файл, создаем для него FileInfo, и просто проверяем что он что-то распознал в файле (что свойства файла не пустые) и не упал с ошибкой.
Затем можно проверить корректность сохранения и восстановления JSON данных. Мы берем файл, создаем для него FileInfo. Затем генерируем JSON и создаем новый объект FileInfo из этого JSON. И проверяем, что оба объекта возвращают одинаковую и корректную информацию о файле. Пр этом сам JSON код мы не анализируем, так как его формат может со временем меняться.
Еще можно протестировать функцию генерации превью, но она на мой взгляд должна быть где-то в другом классе.
То есть мы берем класс, смотрим на его публичные поля и методы и формулируем требования, которым они должны соответстовать. Именно требования к публичному интерфейсу, без закладывания слишком конкретных деталей. Не надо проверять, что функция генерирует путь к файлу длиной ровно в 45 символов, достаточно проверить что она его генерирует вообще.
Представь, что ты - ручной тестер, тебе дали тостую распечатку с техническим заданием на приложение, дали приложение. И ты открываешь ТЗ, берешь первое требование, тестируешь. Берешь второе, тестируешь. И так далее. А не смотришь на внутреннуюю логику кода и отражаешь ее в своих тестах. Это будут плохие, часто ломающиеся и мало полезные тесты.
Что касается testGetDataForTemplate(), я думаю, что функция getDataForTemplate не нужна, а значит не нужен и этот тест.
> require_once 'vendor/autoload.php';
Обрати внимание, что в конфиге phpunit.xml можно указать путь к бутстрап-файлу.
https://github.com/never3ver/fileshare/blob/master/tests/app/FileDataGatewayTest.php#L18
Здесь проблема в том что идет дублирование кода из SQL-дампа. Лучше бы как-то сделать чтобы например тестовая БД очищалась и в нее закачивался дамп перед тестами.
Также, тестировать FileDataGatewayTest удобно так:
- вставить запись в БД
- запросить эту запись и проверить, что она вернулась
- удалить запись
- запросить снова и проверить, что результат пуст
Таким образом мы тестируем несколько функций и не особо зависим от начального состояния таблицы, есть в ней записи или нет.
Но конечно в общем в примитивных методах вроде вставки и удаления записи тестировать особо нечего, можно просто вызвать их и проверить, что они не падают.
Вообще, тестирование важная тема, хорошо бы в ней разобраться, может у тебя какие-то вопроcы есть? Можете тебе подсказать, что в каком классе можно проверить?
Пока на мой взгляд главная проблема - отстутствие нормального разделения обязанностей между классами, некоторые вещи не вынесены в отдельные функции, а просто вписаны в стену кода.
https://github.com/never3ver/fileshare/blob/master/tests/app/HelperTest.php#L5
> PHPUnit_Framework_TestCase
Обрати внимание, что сейчас в phpunit используются неймспейсы вместо подчеркиваний, подчеркивания поддерживаются только ради совместимости. Советую отказаться от них.
https://github.com/never3ver/fileshare/blob/master/tests/app/HelperTest.php#L10
Для тестов логично иметь доступ к настроенному контейнеру, чтобы брать из него сервисы. Зачем создавать их вручную?
Однако, нам может понадобиться отдельный конфиг. Для этого вводят такое понятие, как окружение: в тестовом окружении данные берутся из одного конфига (config_test.php), в продакшене - из другого (config_prod.php). Окружение можно выбирать через переменные окружения, например APP_ENV.
Другой вариант - можно переопределять настройки в переменных окрежения. В случае то же Travis это позволяет прописать настройки тестовой БД прямо в конфиге тревиса и не загрязнять ими код:
- env:
- APP_DB_NAME: test_db
- APP_DB_HOST: 127.0.0.1
Также, есть еще такой вариант: делаем основной конфиг (config.php) и дополнительный (config.local.php), который переопределяет часть настроек. Локальный конфиг не отравляется в гит и может отсутствовать вообще.
https://github.com/never3ver/fileshare/blob/master/tests/app/HelperTest.php#L19
> $this->assertRegExp('/^[a-zA-Z0-9]{45}$/i',
Тут в тесте заложено слишком много подробностей. Почему имя должно иметь длину 45 символов? Что если завтра длина поменяется?
Я бы просто проверял, что возвращается не пустая строка, может дополнительно - что она содержит определенные символы, но уж точно не стоит закладывать в тест конкретную длину строки, если только она не прописана в ТЗ на разработку приложения.
Вот попробуй подумать с точки зрения требований к функции: нам принципиально, чтобы она генерировала имена ровно в 45 символов? Наверно, нет. Нам надо чтобы она 1) генерировала имена файлов 2) чтобы они не повторялись с уже существующими. При этом требование 2 без базы проверить сложно.
https://github.com/never3ver/fileshare/blob/master/tests/app/FileInfoTest.php
Тут я вижу такие проблемы:
Ты опираешься на знание о том, как работает внутренняя логика класса. Ты передаешь имя несуществующего файла, зная, что класс не будет к нему обращаться. Это ненадежно, так как завтра он начнет проверять наличие файла и тест сломается.
В принципе ради теста вполне можно сгенерировать или загрузить файл, который автоматически удалить после теста в tearDown(). А вот опираться на знание внутренней логики работы класса не стоит. Тестировать надо публично доступные интерфейсы, то, что класс выставляет наружу, что что описано в комментариях к функциям.
В твоем случае можно заказчать заранее подготовленную картинку или текстовый файл. Но важно сделать тест так, чтобы он тестировал именно логику в твоем коде, а не например способность getId3 определить битрейт видеофайла - это уже не наша задача.
Что тут можно протестировать? Первое - что код просто работает и не падает (smoke test). Берем заранее подготовленный файл, создаем для него FileInfo, и просто проверяем что он что-то распознал в файле (что свойства файла не пустые) и не упал с ошибкой.
Затем можно проверить корректность сохранения и восстановления JSON данных. Мы берем файл, создаем для него FileInfo. Затем генерируем JSON и создаем новый объект FileInfo из этого JSON. И проверяем, что оба объекта возвращают одинаковую и корректную информацию о файле. Пр этом сам JSON код мы не анализируем, так как его формат может со временем меняться.
Еще можно протестировать функцию генерации превью, но она на мой взгляд должна быть где-то в другом классе.
То есть мы берем класс, смотрим на его публичные поля и методы и формулируем требования, которым они должны соответстовать. Именно требования к публичному интерфейсу, без закладывания слишком конкретных деталей. Не надо проверять, что функция генерирует путь к файлу длиной ровно в 45 символов, достаточно проверить что она его генерирует вообще.
Представь, что ты - ручной тестер, тебе дали тостую распечатку с техническим заданием на приложение, дали приложение. И ты открываешь ТЗ, берешь первое требование, тестируешь. Берешь второе, тестируешь. И так далее. А не смотришь на внутреннуюю логику кода и отражаешь ее в своих тестах. Это будут плохие, часто ломающиеся и мало полезные тесты.
Что касается testGetDataForTemplate(), я думаю, что функция getDataForTemplate не нужна, а значит не нужен и этот тест.
> require_once 'vendor/autoload.php';
Обрати внимание, что в конфиге phpunit.xml можно указать путь к бутстрап-файлу.
https://github.com/never3ver/fileshare/blob/master/tests/app/FileDataGatewayTest.php#L18
Здесь проблема в том что идет дублирование кода из SQL-дампа. Лучше бы как-то сделать чтобы например тестовая БД очищалась и в нее закачивался дамп перед тестами.
Также, тестировать FileDataGatewayTest удобно так:
- вставить запись в БД
- запросить эту запись и проверить, что она вернулась
- удалить запись
- запросить снова и проверить, что результат пуст
Таким образом мы тестируем несколько функций и не особо зависим от начального состояния таблицы, есть в ней записи или нет.
Но конечно в общем в примитивных методах вроде вставки и удаления записи тестировать особо нечего, можно просто вызвать их и проверить, что они не падают.
Вообще, тестирование важная тема, хорошо бы в ней разобраться, может у тебя какие-то вопроcы есть? Можете тебе подсказать, что в каком классе можно проверить?
Пока на мой взгляд главная проблема - отстутствие нормального разделения обязанностей между классами, некоторые вещи не вынесены в отдельные функции, а просто вписаны в стену кода.
> function createClick(elem) {
Название лучше было сделать setPopupClickListener или как-то так.
> document.querySelector("#" + target.dataset.popupId
Проще использовать getElementById
При обработке клика не учтено, что если кнопка содержит внутри другие DOM элементы то target может указывать на них. Для решения этой проблемы мы ищем нужный элемент с помощью closest() в новых браузерах или его аналога. В jQuery тоже есть closest.
Вообще, я сейчас подумал, конечно, что с jQuery эту задачу решать удобнее, так как она избавляет от необходимости решать эти проблемы кроссбраузерности, что closest, dataset, querySelector (часть стандарта DOM Level 3 по моему) есть только в новых браузерах.
Далее, в задаче, увы, не решена проблема автоматического определения размеров попапа. Важно понимать, как это делать, какие есть подводные камни. А они есть, такие:
- для элементов скрытых через display: none нельзя получить размеры, они не считаются браузером
- для многих случаев высота зависит от ширины. Ну например, абзац текста может иметь разную высоту в зависимости от выделенной ему ширины
- некоторые элементы задают минимальную ширину, меньше которой элемент не ужать, например очень длинное слово, картинка, кнопка
- для автоматического определения ширины в CSS часто используется алгоритм shrink-to-fit, а его результат зависит от ширины родителя: https://github.com/codedokode/pasta/blob/master/html/shrink-to-fit.md
- таким образом, чтобы получить размеры попапа, мы должны как-то выбрать ширину контейнера для него. И попробовав отрендерить его в контейнере этой ширины, получим его истинные размеры.
- можно также добавить в разметку подсказки, например, задающие рекомендуемую ширину
В общем, хотелось бы, чтобы ты сделал автоматическое определение оптимальных размеров попапа. Есть идеи, как это сделать? Например, задавать ширину в data-атрибутах, но разрешить попапу быть меньше, если в нем мало контента.
Теперь про позиционирование. Хорошо бы учесть такие факторы:
- если элемент уезжает за левый или верхний край страницы, то эту часть никак не увидеть. Может стоит в такой ситуации ужимать попап по ширине или переносить на противоположный край?
- если элемент выезжает за правый или нижний край, он вызовет удлинение полосы прокрутки
- соответственно, при определении ширины/высоты можно учитывать ширину окна браузера
- можно учитывать положение кнопки в окне. Если кнопка сверху окна, то логично попап выводить под ней, и наоборот
И это еще не все. Ты позиционируешь попап относительно левого верхнего угла страницы. Это имеет тот недостаток, что если на странице что-то поменяется (например появится новый элемент или пользователь изменит ширину окна) и кнопка уедет вверх/вниз, а попап останется на месте. Это можно решить, добавив пустой дивнулевых размеров перед или после кнопки и позиционировать попап относительно него. Но тут появляется другая проблема, а можем ли мы гарантировать, что этот див будет всегда правильно расположен, независимо от верстки окружающих элементов? И есть еще третий вариант, обернуть кнопку в див и позиционироваться относительно него. Там есть свои недостатки, можно сломать верстку.
Это наверно получается совсем сложно, но ты подумай, может что-то можно улучшить. Нет, так нет.
По коду в function positioningPopup(elem, popup) - нельзя ли его упростить? а то выглядит как стена кода.
> function createClick(elem) {
Название лучше было сделать setPopupClickListener или как-то так.
> document.querySelector("#" + target.dataset.popupId
Проще использовать getElementById
При обработке клика не учтено, что если кнопка содержит внутри другие DOM элементы то target может указывать на них. Для решения этой проблемы мы ищем нужный элемент с помощью closest() в новых браузерах или его аналога. В jQuery тоже есть closest.
Вообще, я сейчас подумал, конечно, что с jQuery эту задачу решать удобнее, так как она избавляет от необходимости решать эти проблемы кроссбраузерности, что closest, dataset, querySelector (часть стандарта DOM Level 3 по моему) есть только в новых браузерах.
Далее, в задаче, увы, не решена проблема автоматического определения размеров попапа. Важно понимать, как это делать, какие есть подводные камни. А они есть, такие:
- для элементов скрытых через display: none нельзя получить размеры, они не считаются браузером
- для многих случаев высота зависит от ширины. Ну например, абзац текста может иметь разную высоту в зависимости от выделенной ему ширины
- некоторые элементы задают минимальную ширину, меньше которой элемент не ужать, например очень длинное слово, картинка, кнопка
- для автоматического определения ширины в CSS часто используется алгоритм shrink-to-fit, а его результат зависит от ширины родителя: https://github.com/codedokode/pasta/blob/master/html/shrink-to-fit.md
- таким образом, чтобы получить размеры попапа, мы должны как-то выбрать ширину контейнера для него. И попробовав отрендерить его в контейнере этой ширины, получим его истинные размеры.
- можно также добавить в разметку подсказки, например, задающие рекомендуемую ширину
В общем, хотелось бы, чтобы ты сделал автоматическое определение оптимальных размеров попапа. Есть идеи, как это сделать? Например, задавать ширину в data-атрибутах, но разрешить попапу быть меньше, если в нем мало контента.
Теперь про позиционирование. Хорошо бы учесть такие факторы:
- если элемент уезжает за левый или верхний край страницы, то эту часть никак не увидеть. Может стоит в такой ситуации ужимать попап по ширине или переносить на противоположный край?
- если элемент выезжает за правый или нижний край, он вызовет удлинение полосы прокрутки
- соответственно, при определении ширины/высоты можно учитывать ширину окна браузера
- можно учитывать положение кнопки в окне. Если кнопка сверху окна, то логично попап выводить под ней, и наоборот
И это еще не все. Ты позиционируешь попап относительно левого верхнего угла страницы. Это имеет тот недостаток, что если на странице что-то поменяется (например появится новый элемент или пользователь изменит ширину окна) и кнопка уедет вверх/вниз, а попап останется на месте. Это можно решить, добавив пустой дивнулевых размеров перед или после кнопки и позиционировать попап относительно него. Но тут появляется другая проблема, а можем ли мы гарантировать, что этот див будет всегда правильно расположен, независимо от верстки окружающих элементов? И есть еще третий вариант, обернуть кнопку в див и позиционироваться относительно него. Там есть свои недостатки, можно сломать верстку.
Это наверно получается совсем сложно, но ты подумай, может что-то можно улучшить. Нет, так нет.
По коду в function positioningPopup(elem, popup) - нельзя ли его упростить? а то выглядит как стена кода.
Напоминаю:
>>946704
>>947452
На постгрес меня хероку заставил перебраться. Ты писал о том, что в постгрес можно использовать regex-ограничения для полей, но я не совсем понимаю зачем. Мне кажется, если злоумышленник обойдёт PHP-ограничения, то продублированные регулярки на стороне БД вряд ли чем-то помогут. Про CI прочитал, попробую поднять. Насчёт уровня покрытия тестами, то мне кажется, что чем он выше, тем более хрупкими будут тесты (так как их придётся постоянно подстраивать под изменения в проекте).
Ну и можно делать файлообменник на Симфони? Там уже много чего настроено из коробки (есть дебаг-панель, cli-утилиты, проще тестировать, чем Silex, есть плагин для PHPStorm, добавляющий автодополнение для сервисов/шаблонов/функций Twig и так далее). Понимаю, что оверхед, но взамен готов делать более сложные задания по файлообменнику.
Чтобы можно было не заходя посмотреть на вас и решить, вступать или нет.
Завести глобальную переменную с флагом для консольных скриптов? Сделать отдельный bootstrap для них с другим обработчиком? Как это лучше исправить?
В общем, я написал такой контроллер, в нем стартует сессия и инстанцируются общие для всех страниц классы.
https://github.com/honeydev/s-blog/blob/master/app/Controllers/MainController.php
Этот класс наследуют все остальные классы контроллеры. Которые в свою очередь уже запускаются роутером. Все ли я правильно делаю?
Что-то у тебя там много всего, что можно вынести в класс аутентификации
Вот мой велосипед с похожими функциями https://github.com/grigoryMovchan/STKApps/blob/master/app/core/Controller.php
Тут же есть люди с нулевым опытом, которые делали первое задание про список студентов? Как у вас вообще получилось к нему подступиться? Чувствую себя полнейшим идиотом, который не способен выполнить даже самую простую задачу.
Какое первое задание про список студентов?
Это такое первое задание, что файлообменник - второе?
Обосраться.
А ты урок https://github.com/codedokode/pasta/blob/master/soft/web-server.md прочел?
Туториал в офиц. мануале прочел? http://php.net/manual/ru/tutorial.php
Какую-нибудь статью про HTML для чайников, или хотя бы вступление отсюда прочел? https://github.com/codedokode/pasta/blob/master/html/html.md
Комментарии к задаче про студентов, урок про MVC читал? https://github.com/codedokode/pasta/blob/master/arch/mvc.md
Посмотри эти уроки, и спрашивай, что именно не понятно. Если не понятно, с чего начать, то сделай 2 PHP страницы (файла), выводящие слова "список студентов" и "регистрация" соответственно, и подними веб-сервер, чтобы на эти страницы можно было зайти через браузер.
Это для тех, кто прошел учебник из ОП поста (или любой другой учебник по PHP), и прочел урок про настройку веб-сервера.
Спасибо за первую ссылку, ее не видел.
Но проблема даже не в этих ссылках. Самая жопа заключается в самом mvc, потому что вариантов реализации куча, а у каждого все по-своему. Ладно, пойду дальше дрочиться. Когда-нибудь да сделаю.
что тебе конкретно не ясно-то?
Начинаешь с роутинга, потом клепаешь контроллер, потом модель, которая получает данные.
оп, посмотри, пожалуйста, и подскажи, в чем проблема
https://github.com/sylenien/students-exercise/tree/master
переделал давеча автозагрузчик из простого перебора массива путей до компонентов в неймспейсовый и у меня сломался механизм логининга. Всегда активным юзером становится первая запись в базе данных вне зависимости от ввода
ну и вообще побей меня палкой за косяки, если не сложно
>>957222
Там же до студентов полно заданий, открываем http://archive-ipq-co.narod.ru/ и делаем, на ООП задачки особенно.
Mvc это вообще самое простое. Задача MVC просто держать весь код по отдельности, все что за отображение - во view, за ход процесса, запуск моделей и вводы-выводы - в контроллере, логику - в моделях. Варианты реализации там вообще неважны, главное чтобы все эти вещи оставались, и код друг с другом не смешивался. Накосячить можно, если во view модели например пихаешь.
>Mvc это вообще самое простое.
Как же выводят из себя такие отеты. На любой затык - это элементарно! Скоро будут писать - полиморфизм, инкапсуляцию и абстрактные фабрики даже даун сразу поймет.
Так вот, самое простое - это хеллоуворд написать и то если сервер не надо ставить, все остальное - не просто. Тот кто так пишет, либо пхп учит не первым языком, либо уже забыл как тыжело было вкатываться.
Простомэны кругом, теште свое тщеславие в другом месте
Но тот кто про MVC спросил, тем не менее, жопа ленивая. У него ведь нет конкретного вопроса, он просто поленился нагуглить несколько статей , причем в оппосте тоже есть хороший материал на эту тему, и попробовать сначала что-то руками сделать.
P.S. мимопроходил
Да, ты прав, мимокрокодил.
Я помню, как меня дядя учил кататься на велике: ну что тут сложного, берешь и крутишь педали, балансируешь, ну что ты никак не поймёшь!
Я как вспомню - так ору от его педагогических способностей.
Ведь var dump только выводит данные?
Понял, сам ступил, невнимательно прочел.
На этом сайте только выражение надо вставлять. Справа будет разбор по частям тобой написаного регекса, снизу можешь печатать и в риал тайме смотреть какие части твоей строки попадают под условие.
http://ideone.com/42lK3L
Потому что индекс первого символа у тебя 0, ты хочешь получить индекс последнего символа и передаешь туда -0, то есть ещё раз получаешь первый символ, соответственно первый шаг у тебя неправильный. Ну и ещё на идеоне мультибайт стринги тупо не работают.
https://3v4l.org/VaKAJ
спасибо, а то я всю голову сломал, как заставить mb_strtolower работать
>полиморфизм, инкапсуляцию и абстрактные фабрики даже даун сразу поймет.
Вообще так и есть, это ж самое простое из ООП, ну разве абстрактные фабрики слегка сложнее. Сложность начинается, когда любую книгу по паттернам открываешь, или алгоритмы те же.
public function __construct()
{
// Список объявлений, который у нас жестко заложен в коде
$this->posts[] = $this->createPost(
'Продам слона',
'+79990000001',
'Продается пока еще небольшой дрессировнный африканский слон.'
);
$this->posts[] = $this->createPost(
'Сдам 8-к квартиру около метро недорого',
'+79990000002',
'Сдается квартира, евроремонт, без хозяев, только серьезным людям.'
);
// .. при желании можно добавить еще
}
Блин, почему тут в __construct() не передаются никакие аргументы?
Я балда.
То есть если бы мы получали какие-то введённые данные, то аргументы нам там были бы нужны?
Я теперь понял, что у нас же просто там уже имеется информация, да.
Вот, обьясните мне это мышление, я его слишком много раз видел. Человек не думает "В этой функции мне надо знать чему равно что-то там, как бы мне это туда передать", человек видел что где-то что-то можно передавать и спрашивает почему у него тоже что-то не передается, он не такой как все щтоле. Это как-то жопой кверху получается.
Ну вот я только познакомился с ООП, познакомился с __construct() у ОПа и у Зандстры. В обоих случаях в конструктор передавались аргументы, которые при создании экземпляра класса мы передаём для нужных нам свойств у объекта.
А тут раз - и пустой конструктор.
Я как увидел, так сразу в треде спросил, а потом отвлёкся от MVC ОПовского.
Для меня это было чем-то новым и непонятным абсолютно - для чего именно так, с __construct(), почему не просто метод сделать, который создаёт объявления.
Так понятен ход мыслей?
<br>, подсказали уже.
Зарепортил.
Конструктор подготавливает объект к работе, задает начальные значения свойств, иногда что-то еще делает. Если ему для этого нужны какие-то внешние данные то тогда мы можем передать их через аргументы. Если не нужны - то аргументы тоже не нужны.
То есть обычно аргументы указываются, чтобы потребовать от пользователя класса задать какие-то значения при создании объекта. Но тут так получилось, что объекту ничего в общем-то и не нужно.
Создавать объявления отдельным методом можно, но это бы значило что их можно и не создавать. Нам в задаче это не требуется, потому проще создать их прямо в конструкторе.
Если бы PostsService работал с базой данных, то скорее всего мы бы в конструктор передавали объект соединения с БД вроде PDO, через который можно делать запросы к базе. Это подробнее описано в уроке про DI https://github.com/codedokode/pasta/blob/master/arch/di.md
>>958222
Важно, что анон обратил внимание на то, что что-то не так, и задал вопрос, чтобы разобраться.
Конечно важно понимать, почему что-то так сделано, а не бездумно копировать и писать по аналогии с увиденным.
Спасибо!
http://ideone.com/xkk3U1
Подозреваю, что знай я регулярки, то парсить такие вещи было бы проще?
Это копия, сохраненная 22 марта 2017 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.