Это копия, сохраненная 14 июня 2015 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
Это тред для начинающих. Не написал за свою жизнь ни одной программы? Ты наш человек.
Устанавливать пока что ничего не требуется, разве что редактор кода вроде Sublime Text 3, Notepad++, Netbeans PHP или PhpStorm (с ним будет удобнее).
Предыдущий тред был тут: >>468317
Правила: ведем себя воспитанно, помогаем новичкам, постим ссылки на решения задачек, ОП их проверяет и дает советы и замечания. ОП отвечает даже на самые нубские вопросы. ОП заходит где-то раз в день, не жди его, решай задачки дальше.
У нас есть уроки по основам PHP, они собраны и выложены по адресу http://archive-ipq-co.narod.ru/ Это учебник для изучающих с нуля, то есть если ты вообще ничего не знаешь, то надо начать с него. Он простой и понятный (по крайней мере в начале). Там есть задачи, их надо решать обязательно (чтобы стать программистом, надо писать код — иначе никак). Пости ссылки на решения в тред, мы их проверим, напишем замечания и дадим советы по улучшению.
Если не знаешь как решать, запости код, напиши в каком месте остановился и попроси подсказку.
Учебник дает основы языка PHP, но чтобы делать сайты, этого недостаточно. Если ты его прошел, то надо переходить в более серьезным задачкам, которые научат тебя как выдавать страницы в браузер, работе с таблицами в БД, работе с формами, MVC.
- Простая, но полезная задача сделать список студентов: https://github.com/codedokode/pasta/blob/master/student-list.md
- Более сложная задача сделать файлообменник на микрофреймворке Slim: https://gist.github.com/codedokode/9424217
- Еще более сложная и долгая задача на Yii/Yii2: https://gist.github.com/codedokode/8733007
- После нее можно изучать автоматизированное тестирование
- Если ты все решил, переходи к Symfony 2/Doctrine 2
Чтобы делать эти задания, тебе надо установить Апач + PHP (можно заодно сразу и MySQL) на компьютер. Вот полезные инструкции:
https://gist.github.com/codedokode/10774100
https://gist.github.com/codedokode/7054af4a03865c4cc863
Может тебе понадобится пользоваться командной строкой, вот гайд https://gist.github.com/codedokode/10539568
Вот небольшой туториал по тому как начать использовать PHP на сервере для отдачи странички в браузер: https://php.net/manual/ru/tutorial.php Увы, уроков плавно подводящих к тому, как сделать задачи выше, пока нет, так что если что, задавай вопросы.
Решения задач лучше показать мне, особенно на ООП,так как сам ты вряд ли увидишь все ошибки. Пости свой код на гитхаб и вкидывай ссылку в тред по мере решения. Я прокомментирую и укажу на ошибки.
Также, у нас есть задачи которые позволят тебе изучить или подтянуть до нормального уровня знания JS/HTML/CSS/SQL. Решай их параллельно с задачами выше.
- HTML/CSS: https://gist.github.com/codedokode/58ebc90bd006baf4b35c
- JS: https://gist.github.com/codedokode/ce30e7a036f18f416ae0
- Проверялка решений на JS: http://dkab.github.io/jasmine-tests/
- MySQL: https://gist.github.com/codedokode/10539213
Что почитать
- Мануал по PHP — http://www.php.net/manual/ru/langref.php
- Сайт phptherightway (перевод на русский: http://getjump.github.io/ru-php-the-right-way/ )
- По PHP: Профессиональное программирование на PHP Джордж Шлосснейгл
- По PHP: Мэтт Зандстра — PHP: Объекты, шаблоны, методики программирования
- JS: learn.javascript.ru
- Про Git:
Подскажи сайты для поиска работы, я не умею гуглить? brainstorage.me, geekjob.ru, hh.ru
Нужен ли ООП, фреймворки, MVC? — Да, однозначно. Посмотри любую вакансию.
Сайт опять упал!!!!! — Не паникуй, а открой http://rghost.net/45000175
Оформляй код аккуратно!!! — например пропусти через phpformatter.com . Также, если ты пользуешься IDE вроде PhpStorm, Netbeans, Eclipse, то в них эта опция встроена, подробнее: https://gist.github.com/codedokode/8759492
ОП, сделай за меня мою работу или домашнее задание? — Это конечно, хорошая идея, но нет.
Где искать работу и заказы — hh.ru, geekjob.ru, brainstorage.me, fl.ru, odesk.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/php-fig/fig-standards/blob/master/accepted/ru/PSR-1-basic-coding-standard.md
PSR-2: https://github.com/php-fig/fig-standards/blob/master/accepted/ru/PSR-2-coding-style-guide.md
Будь доброжелателен
Не годится: «Ты мануал хоть раз в жизни открывал, обезьяна?»
Не годится: «В гугле забанили?»
Не годится: «Твой код плохой»
Хорошо: «Вот, как можно улучшить этот код: ...»
Хорошо: «Ты неправильно используешь функцию abc(). Вот ее описание: ссылка, и как видишь ей надо передать строку, а не массив»
Объясняй
Не очень хорошо: «сделай как в этом коде»
Хорошо: «если ты вставляешь текст от пользователя в SQL запрос, то получается SQl-инъекция, которая позволяет взломать твой сервер (ссылки). Чтобы этого избежать, надо вставлять данные с помощью плейсхолдеров (ссылки)»
Хорошо: «Помни, что код пишется для людей. Если писать такие большие функции, то в них становится трудно разобраться...»
Не проповедуй
Мы учим использованию самых распространненных подходов, стандартов, библиотеки фреймворков. Если ты не любишь ООП, пробелы в коде, jQuery, сам PHP, то рассказать об этом стоит в каком-нибудь другом треде.
Ах да. Если тебе кажется, что что-то в учебнике или задачах можно сделать лучше — пиши, обратная связь всегда очень полезна.
>Будь доброжелателен
Нет. Дауны борзеют, и думают что это норма ездить на чужих горбах.
ОП итт как пример.
И сложно ли его будет освоить? у меня есть опыт разработки на чистом php, можно ли ломануться и изучать сразу его, или все же будет быстрее сперва попробовать микрофреймворк, который советует оп?
12:57:12 [mysql] \tMySQL WILL NOT start without the configured ports free!
12:57:12 [mysql] \tYou need to uninstall/disable/reconfigure the blocking application
12:57:12 [mysql] \tor reconfigure MySQL and the Control Panel to listen on a different port
Анон, что xampp от меня хочет? Не включается MySQL
А как мне это исправить?
Посмотри в списке запущенных процессов mysqld или что-то похожее. У тебя наверно 2 версии mysql на компьютере установлено. Этот порт только MySQL и занимает обычно. Надо тогда вторую версию либо остановить (через пуск -> services.msc ) либо вообще удалить.
в запущенных процессах до попытки включить MySQL в xampp'e его нет. После нажатия "старт" в логах выдает ошибку, а в запущенных процессах он висит. Закрываю процесс - тоже самое повторяется
14:04:27 [mysql] \tMySQL Service detected with wrong path
14:04:27 [mysql] \tChange XAMPP MySQL and Control Panel settings or
14:04:27 [mysql] \tUninstall/disable the other service manually first
14:04:27 [mysql] \tFound Path: "C:\Program Files (x86)\MySQL\MySQL Server 5.5\bin\mysqld" --defaults-file="C:\Program Files (x86)\MySQL\MySQL Server 5.5\my.ini" MySQL
14:04:27 [mysql] \tExpected Path: c:\games\xampp\mysql\bin\mysqld.exe --defaults-file=c:\games\xampp\mysql\bin\my.ini mysql
14:04:27 [mysql] \tService was NOT (un)installed!
Ну так он тебе и пишет то же самое, что я написал: у тебя уже установлен другой MySQL который очевидно занимает порт и надо его либо отключить либо удалить совсем.
Алсо, если ты начинающий то полезнее самому ставить Апач/PHP/MYSQL. Сборки для опытных программистов которым некогда с этим возиться.
Хорошо, а как удалить? Пишет, что операция не может быть завершена, открыто другой программой. Все программы я закрыл, которые могут быть связанны с mysql
Также как и устанавлиал, там должен быть анинсталлер. Может в той же папке, может в меню пуск. Ну и первым делом надо зайти в панель управления — удаление и установка программ (это стандартный способ для Windows).
Laravel, легко ничего не бывает.
Вкатился в похапэ, такая проблема:
Такая проблема:
Накатил fatfree фреймворк.
Проблема в том, что роутинг для корня работает нормально,
Но любой другой типа "/test" уже нет.
Вангую, что я как-то коряво настроил апач.
Помогите плз
не помогло
Все разобрался. Спасибо, проблема была в другом.
http://serdce-kamnya.comeze.com/
Но суть в том, что через сервер она работает дико медленно, лагает, если анон оче много кликает, то она вообще у него крашится и перестает работать. В целом выглядит не очень все это. Хотелось бы перенести это дело на js, что бы все игралось прям в браузере без ожидания откиков, постоянной перезагрузки страницы и все такое. С чего начать?
http://pastebin.com/g4USpHM6
Я только наполовину разобравшись записал код для модели, вот здесь switch для двух вьюшек. Там блог
Грубо говоря- list работает нормально, а view entry нет.
Чтобы исключить ошибку в них самих я там сделал код вывода идентичным , поэтому проблема точно где-то здесь.
Ткните меня в ошибку пожалуйста
Думаю что это не очень идея, тоже самое говно же. Куда лучше, если с сервера будет просто подгружаться код, который будет в браузере работать, и картинки иногда.
Ну так и подгружай аджаксом что надо, без обновления страницы. Надо допустим из базы данных что-нибудь вытащить, взял и вытащил и не надо всю страницу грузить по новой.
Вполне удобно.
Мелкобуквенный, уходи отсюда уже, в конце-концов.
Если ты начинающий, то тебе надо создавать таблицы через запрос CREATE TABLE. Так как эта форма в итоге создает тот же самый запрос, но по ней не видно что именно не так. А по запросу будет видно.
Ну и в качестве движка надо брать не MyISAM, а InnoDB, вот сравнение:
http://rtfm.co.ua/mysql-otlichiya-mezhdu-myisam-i-innodb/
http://itif.ru/otlichiya-myisam-innodb/
Алсо проверь можно ли для DATE выставлять по умолчанию CURRENT_TIMESTAMP? По моему только для типа TIMESTAMp
Продолжаю корпеть над заданием про бд кинотеатра.
>Если ты хочешь защититься от джойна фильма самого на себя ... можно поставить условие что первый id должен быть больше второго.
В этом случае работает привязка к айди подходит.
А вот во второй задаче, где нужно выбрать промежутки между соседними фильмами, не могу придумать, как отобрать эти самые соседние сеансы.
Привязывать к айди не решение, потому что я допускаю что сеансы могут заноситься не в хронологическом порядке. Т.е. допустим манагер занес в расписание сеанс на 17 число, потом на 15, затем на 18.
В третьей части смог сделать только кассовые сборы по каждому фильму и общее кол-во посетителей.
Не могу понять, как вывести среднее кол-во посетителей для каждого фильма за сеанс.
Там должно быть AVG, COUNT, SUM чего-то там и еще две группировки по фильму и по сеансу.
Но что-то у меня получается не так как нужно.
http://sqlfiddle.com/#!9/6f0cd/5
Попроще заданий нет?
ОП, а на cms у тебя есть задания?
Я знаю, что cms для быдла, но у меня займет еще по меньшей мере год, чтобы дорасти до миддла (в моей мухосрани джуниоры не нужны), а кушать хочется.
Так что придется мне уж вооружиться вилкой, а в свободное время учить нормальные технологии.
Есть что-нибудь про создание тем и плагинов на вордпресс и друпал?
С трехзначными числами легко разобрался, но вот больше уже давно сижу и туплю - я хочу сделать функцию, разбивающие числа на трехзначные. То есть например число 123456789 на массив [1] => 123 [2] => 456 [3] => 789 и там уже подставлять миллионы это или тысячи или ничего.
Это правильная идея вообще или можно/нужно сделать проще?
А точнее, по моей идее число разбивается с конца, то есть [1] => 789 и так далее
Как мы это проверим если ты не показываешь код?
Алсо на сервере который смотрит в интернет надо отключать display_errros и смотреть ошибки в логах. Приучайся сейчас, пока не поздно, а то так вредная привычка и останется.
>>479672
Лучше сначала микрофреймворк например slim или silex так как они очень простые. У нас там и задачка есть как пример, на файлообменник.
насчет самый востребоанный — это все меняется. Попробуй сам посмотреть например сайты с вакансиями и посчитать.
>>479837
Там у тебя то ли код медленный то ли из-за того что хостинг бесплатный. Если он на одном человеке тормозит то на нескольких вообще умрет наверно.
>>479863
Тогда тебе нужно сделать все на явскрипте. То есть страница загружается один раз и после этого все работает в браузере без обращения к серверу вообще. Яваскрипт как раз для этого и предназначен.
>>479842
Готовой базы книг нет. Если сайты которые торгуют книгами вроде озона, у них накопилась база, и может они ее отдают через API или как список XML.
Потому надо придумать решение, желательно найти какое-то АПИ которое бы эти данные предоставило. То есть человек вводит название или ISBN, мы через Api ищем подходящие книги.
Вот пример XML файлов с озона: http://www.ozon.ru/context/partner_xml/
Вот что-то от гугла https://support.google.com/books/answer/59888?hl=ru
Вот еще что-то http://api.knigafund.ru/api/doc
У амазона есть что-то: http://job-blog.bullgare.ru/2012/10/api-amazon-%D0%B4%D0%BB%D1%8F-%D0%BF%D0%BE%D0%B8%D1%81%D0%BA%D0%B0-%D0%BA%D0%BD%D0%B8%D0%B3/
Многие из этих API рассчитаны на получение партнерской ссылки для продажи, но мы можем ими воспользоваться чтобы например найти информацию о книге и (хорошо бы) обложку.
Для работы с некоторым АПИ есть готовые PHP библиотеки, для гугловского вроде есть.
В общем попробуй погуглить, по словам вроде «api поиска книг», подумай у кого есть база книг и проверь нет ли у них API/партнерской программы.
Также, книги можно искать в википедии, или может есть какая-нибудь книгопедия, кто знает.
То есть надо найти либо базы книг которые можно импортировать либо API которые можно запрашивать динамически когда пользователь вводит название. Одной базы наверно мало, чем больше будет, тем лучше.
Вот я еще нашел такой сайт http://lookforabook.ru/shop который откуда-то берет каталоги книг и на котором есть список магазинов (и который тебе стоит обойти в поисках партнерских апи).
Вот партнерская программа еще одного магазина: http://www.labirint.ru/partner/?w=ins и он предлагает список своих книг в формате Yandex YML (не знаю, можно ли его получить без регистрации). Но регистрацию нетрудно обойти гуглением по фразе «site:labirint.ru filetype:xml» которая дает нам такие страницы: http://partner.labirint.ru/xml/export/genres/2379.xml (осторожно, браузер подвисает). Yandex YML это формат в котором магазины отдают список тоаров яндекс-маркету, и эти же файлы часто используют в партнерских программах.
Вот еще: http://www.books.ru/pages.php?id=435
По моему это хорошая задача получается, она учит тебя не только программировать, но и искать решения не совсем программистских задач.
Как мы это проверим если ты не показываешь код?
Алсо на сервере который смотрит в интернет надо отключать display_errros и смотреть ошибки в логах. Приучайся сейчас, пока не поздно, а то так вредная привычка и останется.
>>479672
Лучше сначала микрофреймворк например slim или silex так как они очень простые. У нас там и задачка есть как пример, на файлообменник.
насчет самый востребоанный — это все меняется. Попробуй сам посмотреть например сайты с вакансиями и посчитать.
>>479837
Там у тебя то ли код медленный то ли из-за того что хостинг бесплатный. Если он на одном человеке тормозит то на нескольких вообще умрет наверно.
>>479863
Тогда тебе нужно сделать все на явскрипте. То есть страница загружается один раз и после этого все работает в браузере без обращения к серверу вообще. Яваскрипт как раз для этого и предназначен.
>>479842
Готовой базы книг нет. Если сайты которые торгуют книгами вроде озона, у них накопилась база, и может они ее отдают через API или как список XML.
Потому надо придумать решение, желательно найти какое-то АПИ которое бы эти данные предоставило. То есть человек вводит название или ISBN, мы через Api ищем подходящие книги.
Вот пример XML файлов с озона: http://www.ozon.ru/context/partner_xml/
Вот что-то от гугла https://support.google.com/books/answer/59888?hl=ru
Вот еще что-то http://api.knigafund.ru/api/doc
У амазона есть что-то: http://job-blog.bullgare.ru/2012/10/api-amazon-%D0%B4%D0%BB%D1%8F-%D0%BF%D0%BE%D0%B8%D1%81%D0%BA%D0%B0-%D0%BA%D0%BD%D0%B8%D0%B3/
Многие из этих API рассчитаны на получение партнерской ссылки для продажи, но мы можем ими воспользоваться чтобы например найти информацию о книге и (хорошо бы) обложку.
Для работы с некоторым АПИ есть готовые PHP библиотеки, для гугловского вроде есть.
В общем попробуй погуглить, по словам вроде «api поиска книг», подумай у кого есть база книг и проверь нет ли у них API/партнерской программы.
Также, книги можно искать в википедии, или может есть какая-нибудь книгопедия, кто знает.
То есть надо найти либо базы книг которые можно импортировать либо API которые можно запрашивать динамически когда пользователь вводит название. Одной базы наверно мало, чем больше будет, тем лучше.
Вот я еще нашел такой сайт http://lookforabook.ru/shop который откуда-то берет каталоги книг и на котором есть список магазинов (и который тебе стоит обойти в поисках партнерских апи).
Вот партнерская программа еще одного магазина: http://www.labirint.ru/partner/?w=ins и он предлагает список своих книг в формате Yandex YML (не знаю, можно ли его получить без регистрации). Но регистрацию нетрудно обойти гуглением по фразе «site:labirint.ru filetype:xml» которая дает нам такие страницы: http://partner.labirint.ru/xml/export/genres/2379.xml (осторожно, браузер подвисает). Yandex YML это формат в котором магазины отдают список тоаров яндекс-маркету, и эти же файлы часто используют в партнерских программах.
Вот еще: http://www.books.ru/pages.php?id=435
По моему это хорошая задача получается, она учит тебя не только программировать, но и искать решения не совсем программистских задач.
> Попроще заданий нет?
Если ты решил задачу про лайки, то задача про кинотеатр и про календарь как раз твоего уровня, зачем тебе примитивные задачи для тех кто только начал изучать SQL?
Вот тебе еще мини-задача тогда (простая конечно): сделай базу для имиджборды из 1 раздела и запрос на вывод главной страницы, 10 верхних тредов, в каждом ОП-пост + 3 последних поста. Свойства поста: дата/время + текст.
> BETWEEN s1.date AND s1.date + INTERVAL(f1.duration) MINUTE
Если один фильм начинается сразу после второго то накладывается, хотя по времени как-раз впритык выходит: http://sqlfiddle.com/#!9/2eed3/1 — будь внимательнее.
Алсо в условии задачи написано
> ошибки в расписании (фильмы накладываются друг на друга), отсортированные по возрастанию времени
добавь сортировку.
> где нужно выбрать промежутки между соседними фильмами, не могу придумать, как отобрать эти самые соседние сеансы.
Для начала попробуй мыслить реляционно: мы приджойниваем к сеансу все существующие сеансы и выбираем например тот, время до начала которого минимальное относительно нашего. Если это не помогает, то печально, придется идти другим путем. Вот есть такой пост: http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/
Я думаю, что в твоем случае можно сначала построить таблицу вида «фильм — время начала следующего», а потом к ней приджойнить следующий фильм по этой дате.
Если так не получится, то напиши, я еще подумаю.
SQL не позволит нам например отсортировать сеансы по времени и вычитая время соседних сеансов, получить таблицу перерывов. В некоторых базах данных есть разные хитрые команды для таких целей (пример https://www.simple-talk.com/sql/t-sql-programming/calculating-gaps-between-overlapping-time-intervals-in-sql/ ) но в MySQL их нет.
Также у меня есть еще одна мысль: а можем ли мы приджойнить таблицу саму на себя 3 раза? Первые 2 джойна ищут фильмы, которые идут друг за другом по времени. Третий джойн приджойнивает фильмы попавшие между ними и используется чтобы сделать условие «фильмы между которыми нет других фильмов», то есть идущие последовательно. Так не получится?
> потому что я допускаю что сеансы могут заноситься не в хронологическом порядке. Т.е. допустим манагер занес в расписание сеанс на 17 число, потом на 15, затем на 18.
В базе данных никакого порядка хранения нет, записи хранятся в случайном порядке, пока ты не начнешь сортировать по какой-то колонке.
> как вывести среднее кол-во посетителей для каждого фильма за сеанс.
Среднее число зрителей за сеанс = общее число зрителей делить на число сеансов. Арифметику забыл? Группировки достаточно одной.
> Попроще заданий нет?
Если ты решил задачу про лайки, то задача про кинотеатр и про календарь как раз твоего уровня, зачем тебе примитивные задачи для тех кто только начал изучать SQL?
Вот тебе еще мини-задача тогда (простая конечно): сделай базу для имиджборды из 1 раздела и запрос на вывод главной страницы, 10 верхних тредов, в каждом ОП-пост + 3 последних поста. Свойства поста: дата/время + текст.
> BETWEEN s1.date AND s1.date + INTERVAL(f1.duration) MINUTE
Если один фильм начинается сразу после второго то накладывается, хотя по времени как-раз впритык выходит: http://sqlfiddle.com/#!9/2eed3/1 — будь внимательнее.
Алсо в условии задачи написано
> ошибки в расписании (фильмы накладываются друг на друга), отсортированные по возрастанию времени
добавь сортировку.
> где нужно выбрать промежутки между соседними фильмами, не могу придумать, как отобрать эти самые соседние сеансы.
Для начала попробуй мыслить реляционно: мы приджойниваем к сеансу все существующие сеансы и выбираем например тот, время до начала которого минимальное относительно нашего. Если это не помогает, то печально, придется идти другим путем. Вот есть такой пост: http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/
Я думаю, что в твоем случае можно сначала построить таблицу вида «фильм — время начала следующего», а потом к ней приджойнить следующий фильм по этой дате.
Если так не получится, то напиши, я еще подумаю.
SQL не позволит нам например отсортировать сеансы по времени и вычитая время соседних сеансов, получить таблицу перерывов. В некоторых базах данных есть разные хитрые команды для таких целей (пример https://www.simple-talk.com/sql/t-sql-programming/calculating-gaps-between-overlapping-time-intervals-in-sql/ ) но в MySQL их нет.
Также у меня есть еще одна мысль: а можем ли мы приджойнить таблицу саму на себя 3 раза? Первые 2 джойна ищут фильмы, которые идут друг за другом по времени. Третий джойн приджойнивает фильмы попавшие между ними и используется чтобы сделать условие «фильмы между которыми нет других фильмов», то есть идущие последовательно. Так не получится?
> потому что я допускаю что сеансы могут заноситься не в хронологическом порядке. Т.е. допустим манагер занес в расписание сеанс на 17 число, потом на 15, затем на 18.
В базе данных никакого порядка хранения нет, записи хранятся в случайном порядке, пока ты не начнешь сортировать по какой-то колонке.
> как вывести среднее кол-во посетителей для каждого фильма за сеанс.
Среднее число зрителей за сеанс = общее число зрителей делить на число сеансов. Арифметику забыл? Группировки достаточно одной.
Да, есть на вордпресс. Как насчет сделать на вордпресс клон вот такого сайта: http://m.siliconrus.com/ (мобильная версия проще по дизайну)? Менять код вордпресса нельзя, ты должен сделать сайт в виде кастомной темы и плагина если требуется.
Также, есть задача про плагин к вордпрессу для защиты от спама и троллей.
Вот что я наковырял со старых тредов:
-----------------
Читай документацию на http://codex.wordpress.org/
Вот часть страниц что на русском: http://codex.wordpress.org/%D0%97%D0%B0%D0%B3%D0%BB%D0%B0%D0%B2%D0%BD%D0%B0%D1%8F_%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D0%B0
Чтение официальной документации это первое что должно приходить тебе в голову.
Теперь поговорим про то как сделать сайт на вордпрессе. Вордпресс расширяется двумя путями:
1) написание и установка своей темы. Тема задает внешний вид сайта, ты можешь либо скачать одну из тысяч готовых либо сделать свою на основе существующей верстки (надо знать HTML/CSS)
2) написание и установка плагина. Плагин это код который позволяет добавлять новые возможности, страницы, а также изменять поведение существующего кода. Плагины опять же можно брать готовые, а можно писать самому.
Плагин изменяет поведение вордпресса за счет хуков. Хук — это функция, которая вызывается при совершении определенного действия, например входе в админку, добавлении комментария, вывода поста. Ты можешь сделать в плагине свою функцию, которая вызывается в этих случаях и что-то делает или меняет.
Как создать тему или плагин, описано в документации.
Также, тебе понадобится изучить API вордпресса. API это набор функций которые ты можешь вызывать из тем или плагинов и набор событий, для которых ты можешь создавать свои функции-хуки.
Вот стартовая страница с информацией по созданию темы: http://codex.wordpress.org/%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5_%D1%82%D0%B5%D0%BC
Вот стартовая страница по созданию плагина: http://codex.wordpress.org/%D0%9D%D0%B0%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BB%D0%B0%D0%B3%D0%B8%D0%BD%D0%B0
Ты можешь также погуглить другие уроки (например http://www.google.ru/search?sourceid=chrome&ie=UTF-8&q=habr+%D0%B2%D0%BE%D1%80%D0%B4%D0%BF%D1%80%D0%B5%D1%81%D1%81+%D1%82%D0%B5%D0%BC%D0%B0 ) но документацию ты должен читать в любом случае. Потому что в уроках показывают как сделана та или иная вещь но не объясняют подробностей как работают использованные функции, зачем нужен этот файл и тд
Я могу дать задачу на вордпресс, именно на плагины, если ты так хочешь. Задача из 2 частей, попроще и посложнее.
1) сделай плагин который позволяет задать «черный список» слов и выражений, которые считаются спамерскими. Комментарии с такими словами не должны публиковаться и сразу удаляться. При этом желательно не выводить сообщение об ошибке, а делать вид как будто все ок.
В админке должна быть отдельная страница, со списком слов и выражений, просто текстареа, каждое выражение с новой строки, и галочка или кнопка для включения/отключения плагина (можно не делать если это делается стандартными средствами вордпресса).
Выражения при сравнении игнорируют регистр букв, всякие небуквенные символы вроде запятых и html (а еще желательно чтобы нельзя было обойти список заменой русских букв на похожие латинские). То есть выражение «казино» соответствуют комментариям «заходите в КаЗиНо», «заходите в к.<b>а</b>.з.и.н.о.».
В выражениях можно использовать символ «звездочка» который значит «любые буквы». Ну например, выражение «лекарств×» соответствует словам «лекарство», «лекартства», «лекарственный». Можно найти готовую функцию или библиотеку, которая позволяет работать с такими выражениями, не обязательно писать свой алгоритм. Также, это можно делать в последнюю очередь, пока сделай без звездочек.
Также на странице в админке должно выводится число заблокированных комментариев и должно быть поле для проверки, куда можно вставить текст и проверить проходит он фильтр или нет.
Замечание: надо всего лишь найти хук, отвечающий за публикацию комментария и проверять этот комментарий.
2) усложненная версия. Сделай кроме «черного» списка еще возможность высчитывать рейтинг доверия к комментаторам.
Принцип такой: у каждого пользователя есть рейтинг доверия, по умолчанию он равен 0. Рейтинг доверия показывает, сколько комментариев можно опубликовать без модерации. Каждый одобренный комментарий увеличивает рейтинг на k, k задается в админке и может быть дробным, по умолчанию k = 1. То есть:
— пользователя оставляет первый комментарий, он идет на модерацию
— после одобрения пользователь получает рейтинг k = 1 и оставляет второй комментарий без модерации
— после этого третий комментарий снова идет на модерацию
— после одобрения пользователь получает рейтинг = 2 и может оставить 2 комментария без премодерации
— после этого комментарий снова подвергается модерации
— после этого пользователь может следующие 3 комментария без модерации
При этом есть определенный предел, он тоже задается в админке (maxTrustRating) выше которого k не увеличивается.
То есть пользователь постепенно накапливает что-то вроде рейтинга доверия. Если комментарий помечен модератором как спам (в том числе уже ранее одобренный) или был распознан как спам системой из первого пункта, рейтинг сбрасывается в ноль. Если число спам-комментариев больше определенного предела (maxSpamComments), пользователь отключается от этой системы (считается что он навсегда потерял доверие), рейтинг сбрасывается в ноль и все его дальнейшие комментарии подлежат модерации.
В админке должно быть:
— страница с настройкой параметров и выводом статистики: число автоматически одобренных комментариев, число пользователей с рейтингов больше нуля.
— страница для просмотра пользователей, выводит пользователей по убыванию рейтинга, для каждого пользователя пишет число оставленных/опубликованных комменатриев, рейтинг доверия, число спам комментариев, потерял ли он доверие или нет. На странице есть фильтр, позволяющий показывать только доверенных/потерявших доверие пользователей. Есть кнопки для принудительного лишения доверия или сброса репутации в начальное состоняие.
Если этот функционал можно сделать не отдельной страницей, а интегрировать в существующую админку пользователей, было бы здорово.
Пользователь идентифицируется по логину, если он зарегистрирован, если нет то по IP, то есть для анонимных пользователей рейтинг считается для Ip адреса.
замечания: тут скорее всего надо будет делать дополнительные таблицы в базе или добавлять колонки к существующим.
Реализовать это надо как плагин к вордпрессу, соотвествующий всем стандартным требованиям к плагинам и устоявшимся принципам их разработки. Устанавливаться и удаляться плагин должен стандартными средствами вордпресс, причем если установить и удалить плагин несколько раз подряд, ничего ломаться не должно. Изменять код самого вордпресса или сторонних плагинов, разумеется недопустимо, так как для проверки я захочу поставить плагин на чистую инсталляцию вордпресса.
Что скажешь? Ту работы недели на 2-4 в неспешном темпе.
Код (только самого плагина) хорошо бы постить на гитхаб.
-----------------
Алсо в ОП-посте есть еще хорошие задания по CSS/HTML.
Да, есть на вордпресс. Как насчет сделать на вордпресс клон вот такого сайта: http://m.siliconrus.com/ (мобильная версия проще по дизайну)? Менять код вордпресса нельзя, ты должен сделать сайт в виде кастомной темы и плагина если требуется.
Также, есть задача про плагин к вордпрессу для защиты от спама и троллей.
Вот что я наковырял со старых тредов:
-----------------
Читай документацию на http://codex.wordpress.org/
Вот часть страниц что на русском: http://codex.wordpress.org/%D0%97%D0%B0%D0%B3%D0%BB%D0%B0%D0%B2%D0%BD%D0%B0%D1%8F_%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D0%B0
Чтение официальной документации это первое что должно приходить тебе в голову.
Теперь поговорим про то как сделать сайт на вордпрессе. Вордпресс расширяется двумя путями:
1) написание и установка своей темы. Тема задает внешний вид сайта, ты можешь либо скачать одну из тысяч готовых либо сделать свою на основе существующей верстки (надо знать HTML/CSS)
2) написание и установка плагина. Плагин это код который позволяет добавлять новые возможности, страницы, а также изменять поведение существующего кода. Плагины опять же можно брать готовые, а можно писать самому.
Плагин изменяет поведение вордпресса за счет хуков. Хук — это функция, которая вызывается при совершении определенного действия, например входе в админку, добавлении комментария, вывода поста. Ты можешь сделать в плагине свою функцию, которая вызывается в этих случаях и что-то делает или меняет.
Как создать тему или плагин, описано в документации.
Также, тебе понадобится изучить API вордпресса. API это набор функций которые ты можешь вызывать из тем или плагинов и набор событий, для которых ты можешь создавать свои функции-хуки.
Вот стартовая страница с информацией по созданию темы: http://codex.wordpress.org/%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5_%D1%82%D0%B5%D0%BC
Вот стартовая страница по созданию плагина: http://codex.wordpress.org/%D0%9D%D0%B0%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BB%D0%B0%D0%B3%D0%B8%D0%BD%D0%B0
Ты можешь также погуглить другие уроки (например http://www.google.ru/search?sourceid=chrome&ie=UTF-8&q=habr+%D0%B2%D0%BE%D1%80%D0%B4%D0%BF%D1%80%D0%B5%D1%81%D1%81+%D1%82%D0%B5%D0%BC%D0%B0 ) но документацию ты должен читать в любом случае. Потому что в уроках показывают как сделана та или иная вещь но не объясняют подробностей как работают использованные функции, зачем нужен этот файл и тд
Я могу дать задачу на вордпресс, именно на плагины, если ты так хочешь. Задача из 2 частей, попроще и посложнее.
1) сделай плагин который позволяет задать «черный список» слов и выражений, которые считаются спамерскими. Комментарии с такими словами не должны публиковаться и сразу удаляться. При этом желательно не выводить сообщение об ошибке, а делать вид как будто все ок.
В админке должна быть отдельная страница, со списком слов и выражений, просто текстареа, каждое выражение с новой строки, и галочка или кнопка для включения/отключения плагина (можно не делать если это делается стандартными средствами вордпресса).
Выражения при сравнении игнорируют регистр букв, всякие небуквенные символы вроде запятых и html (а еще желательно чтобы нельзя было обойти список заменой русских букв на похожие латинские). То есть выражение «казино» соответствуют комментариям «заходите в КаЗиНо», «заходите в к.<b>а</b>.з.и.н.о.».
В выражениях можно использовать символ «звездочка» который значит «любые буквы». Ну например, выражение «лекарств×» соответствует словам «лекарство», «лекартства», «лекарственный». Можно найти готовую функцию или библиотеку, которая позволяет работать с такими выражениями, не обязательно писать свой алгоритм. Также, это можно делать в последнюю очередь, пока сделай без звездочек.
Также на странице в админке должно выводится число заблокированных комментариев и должно быть поле для проверки, куда можно вставить текст и проверить проходит он фильтр или нет.
Замечание: надо всего лишь найти хук, отвечающий за публикацию комментария и проверять этот комментарий.
2) усложненная версия. Сделай кроме «черного» списка еще возможность высчитывать рейтинг доверия к комментаторам.
Принцип такой: у каждого пользователя есть рейтинг доверия, по умолчанию он равен 0. Рейтинг доверия показывает, сколько комментариев можно опубликовать без модерации. Каждый одобренный комментарий увеличивает рейтинг на k, k задается в админке и может быть дробным, по умолчанию k = 1. То есть:
— пользователя оставляет первый комментарий, он идет на модерацию
— после одобрения пользователь получает рейтинг k = 1 и оставляет второй комментарий без модерации
— после этого третий комментарий снова идет на модерацию
— после одобрения пользователь получает рейтинг = 2 и может оставить 2 комментария без премодерации
— после этого комментарий снова подвергается модерации
— после этого пользователь может следующие 3 комментария без модерации
При этом есть определенный предел, он тоже задается в админке (maxTrustRating) выше которого k не увеличивается.
То есть пользователь постепенно накапливает что-то вроде рейтинга доверия. Если комментарий помечен модератором как спам (в том числе уже ранее одобренный) или был распознан как спам системой из первого пункта, рейтинг сбрасывается в ноль. Если число спам-комментариев больше определенного предела (maxSpamComments), пользователь отключается от этой системы (считается что он навсегда потерял доверие), рейтинг сбрасывается в ноль и все его дальнейшие комментарии подлежат модерации.
В админке должно быть:
— страница с настройкой параметров и выводом статистики: число автоматически одобренных комментариев, число пользователей с рейтингов больше нуля.
— страница для просмотра пользователей, выводит пользователей по убыванию рейтинга, для каждого пользователя пишет число оставленных/опубликованных комменатриев, рейтинг доверия, число спам комментариев, потерял ли он доверие или нет. На странице есть фильтр, позволяющий показывать только доверенных/потерявших доверие пользователей. Есть кнопки для принудительного лишения доверия или сброса репутации в начальное состоняие.
Если этот функционал можно сделать не отдельной страницей, а интегрировать в существующую админку пользователей, было бы здорово.
Пользователь идентифицируется по логину, если он зарегистрирован, если нет то по IP, то есть для анонимных пользователей рейтинг считается для Ip адреса.
замечания: тут скорее всего надо будет делать дополнительные таблицы в базе или добавлять колонки к существующим.
Реализовать это надо как плагин к вордпрессу, соотвествующий всем стандартным требованиям к плагинам и устоявшимся принципам их разработки. Устанавливаться и удаляться плагин должен стандартными средствами вордпресс, причем если установить и удалить плагин несколько раз подряд, ничего ломаться не должно. Изменять код самого вордпресса или сторонних плагинов, разумеется недопустимо, так как для проверки я захочу поставить плагин на чистую инсталляцию вордпресса.
Что скажешь? Ту работы недели на 2-4 в неспешном темпе.
Код (только самого плагина) хорошо бы постить на гитхаб.
-----------------
Алсо в ОП-посте есть еще хорошие задания по CSS/HTML.
> дорасти до миддла
Ты не можешь стать миддлом в обход джуниора так как миддл это обычно разработчик с опытом.
>>480280
Это просто, вот 2 волшебных команды:
// получить последние 3 цифры числа:
echo 1234567 % 1000; // выведет 567
// получить число миллионов
echo floor(1234678 / 1000000); // выведет 12
Комбинируя их, можно получить что угодно.
Поищи похожие задачи. Но вообще цена формируется по принципу
стоимость часа × затраченное время + бонус
Стоимость часа и бонус определяешь ты (но заказчика это может не устроить, так что в твоих интересах минимизировать время). Стоимость часа можно определить как (зарплата за месяц + налоги) / 168.
Насколько*
Не думал об организации лагеря?
Fatal error: Uncaught exception 'PDOException' with message 'could not find driver' in Z:\home\test_sait\www\.....\bd.php
Причём указывает адрес где подключаю файл с настройками ПДО, на сайт. Что то с ПДО я так понял, надо что то расскоментировать в пхп.ини что бы начало работать? До того ПДО работал нормально.
Чтобы найти ошибку, поставь var_dump и echo чтобы видеть значения переменных и какой код выполняется и делай выводы.
Я не очень понял что именно не работает, ты не написал подробностей. Сообщения об ошибках выводятся? В логах есть?
В PHP по умолчанию выключено отображение ошибок в браузере, так как обычному пользователю сайта эта информация ни к чему. Но тебе, как программисту, надо видеть эти ошибки. Вот, как можно их просмотреть:
- ошибки сохраняются в лог ошибок. Можно открыть его и почитать. Если ты запускаешь код на локалхосте, у себя, то лог хранится в папке Апача (обычно она называется logs) и имеет название вроде error.log (в линуксе в папку /var/log/apache2 ). Если на хостинге — там либо есть файл error.log либо раздел в панели управления, где лог можно посмотреть
- также, ты можешь включить отображение ошибок. Открой файл php.ini, поставь там display_errors = On и error_reporting = E_ALL и перезапусти сервер. Теперь ошибки должны выводиться на экран.
Проверить, работает ли вывод ошибок, можно запустив скрипт содержающий обращение к несуществующей переменной вроде echo $sdgasdad; и проверив, выведется ошибка или нет. Если все верно, то должна вывестись.
-------------
Также, код не годится никуда. Тебе надо переучиваться, потому что так писать конечно нельзя. Ты явно читал какие-то устаревшие учебники.
Вот смотри, что надо исправить:
SQL запросы не должны быть размазаны по всему приложению. Надо создать класс или классы для работы с БД и писать запросы только в них. Вот урок как работать с базой: https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md
Вместо массивов лушче сделать нормальные объекты-модели и их выбирать из базы.
> if (mb_strlen($row['content'])>300){
$row['content'] = > mb_substr($row['content'], 0, 197).'...';
Это надо сделать отдельной функцией. не надо писать код одной простыней, надо разбивать его на части.
> $row['header'] = htmlspecialchars($row['header']);
Это лучше делать при выводе в самом шаблоне.В твоем варианте глядя на шаблон нельзя сказать, экранированы ли значения так как ты делаешь это в другом месте кода и разобраться потом будет нереально.
> define ('IS_ADMIN', isset($_SESSION['IS_ADMIN']));
Не стоит для этого использовать коснтанты, контсанта это неизменное значение. Стоит просто сделать функцию вроде isLoggedIn()
> ("SELECT * FROM entry WHERE id = $id")
Данные надо вставлять в запрос через плейсхолдеры. Это и просто, и безопасно, и они специально для этого придуманы.
> f (!$entry) die ("No such entry");
Неправильная обработка ошибок так как ты выводишь просто черную непонятную надпись. Такие вещи надо делать нормально, например сделать нормальную страницу-заглушку, а также надо выдавать HTTP код 5xx чтобы роботы не индексировали страницы с ошибками.
> while ($row = $sel->fetch_assoc()){
Там есть метод чтобы получить все сразу.
Также, прочти мануал по функции которую ты используешь: $mysqli->query — она может вернуть ошибку (false), и ты должен ее проверять иначе скрипт пойдет выполняться дальше и скорее всего выведет битую страницу или что-нибудь еще нехорошее.
Я бы тебе советовал сделать наши задания, например на список студентов (в Оп посте), потому что там как раз изучается все, что ты пока не знаешь.
Чтобы найти ошибку, поставь var_dump и echo чтобы видеть значения переменных и какой код выполняется и делай выводы.
Я не очень понял что именно не работает, ты не написал подробностей. Сообщения об ошибках выводятся? В логах есть?
В PHP по умолчанию выключено отображение ошибок в браузере, так как обычному пользователю сайта эта информация ни к чему. Но тебе, как программисту, надо видеть эти ошибки. Вот, как можно их просмотреть:
- ошибки сохраняются в лог ошибок. Можно открыть его и почитать. Если ты запускаешь код на локалхосте, у себя, то лог хранится в папке Апача (обычно она называется logs) и имеет название вроде error.log (в линуксе в папку /var/log/apache2 ). Если на хостинге — там либо есть файл error.log либо раздел в панели управления, где лог можно посмотреть
- также, ты можешь включить отображение ошибок. Открой файл php.ini, поставь там display_errors = On и error_reporting = E_ALL и перезапусти сервер. Теперь ошибки должны выводиться на экран.
Проверить, работает ли вывод ошибок, можно запустив скрипт содержающий обращение к несуществующей переменной вроде echo $sdgasdad; и проверив, выведется ошибка или нет. Если все верно, то должна вывестись.
-------------
Также, код не годится никуда. Тебе надо переучиваться, потому что так писать конечно нельзя. Ты явно читал какие-то устаревшие учебники.
Вот смотри, что надо исправить:
SQL запросы не должны быть размазаны по всему приложению. Надо создать класс или классы для работы с БД и писать запросы только в них. Вот урок как работать с базой: https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md
Вместо массивов лушче сделать нормальные объекты-модели и их выбирать из базы.
> if (mb_strlen($row['content'])>300){
$row['content'] = > mb_substr($row['content'], 0, 197).'...';
Это надо сделать отдельной функцией. не надо писать код одной простыней, надо разбивать его на части.
> $row['header'] = htmlspecialchars($row['header']);
Это лучше делать при выводе в самом шаблоне.В твоем варианте глядя на шаблон нельзя сказать, экранированы ли значения так как ты делаешь это в другом месте кода и разобраться потом будет нереально.
> define ('IS_ADMIN', isset($_SESSION['IS_ADMIN']));
Не стоит для этого использовать коснтанты, контсанта это неизменное значение. Стоит просто сделать функцию вроде isLoggedIn()
> ("SELECT * FROM entry WHERE id = $id")
Данные надо вставлять в запрос через плейсхолдеры. Это и просто, и безопасно, и они специально для этого придуманы.
> f (!$entry) die ("No such entry");
Неправильная обработка ошибок так как ты выводишь просто черную непонятную надпись. Такие вещи надо делать нормально, например сделать нормальную страницу-заглушку, а также надо выдавать HTTP код 5xx чтобы роботы не индексировали страницы с ошибками.
> while ($row = $sel->fetch_assoc()){
Там есть метод чтобы получить все сразу.
Также, прочти мануал по функции которую ты используешь: $mysqli->query — она может вернуть ошибку (false), и ты должен ее проверять иначе скрипт пойдет выполняться дальше и скорее всего выведет битую страницу или что-нибудь еще нехорошее.
Я бы тебе советовал сделать наши задания, например на список студентов (в Оп посте), потому что там как раз изучается все, что ты пока не знаешь.
> Что то с ПДО я так понял, надо что то расскоментировать в пхп.ини что бы начало работать? До того ПДО работал нормально.
Надо подключить драйвер PDO для работы с нужной тебе БД (драйверы баз идут как отдельные расширения). Название драйвера можно найти в мануале php.
Ну надо же где то учиться, лучше поясни по вопросу, выбивает вот эту ошибку:
Warning: file_get_contents() [function.file-get-contents]: Unable to find the wrapper "https" - did you forget to enable it when you configured PHP? in
Warning: file_get_contents(https://oauth.vk.com/access_token?client_id=4922074&client_secret=vydI8DuMH3ZAPla5P0gJ&code=4f2e4e8c80e0b6565e&redirect_uri=http://test_sait/) [function.file-get-contents]: failed to open stream: No such file or directory in
>зачем тебе примитивные задачи
На примитивах легче понять, как оно работает.
Потому что пока я теряюсь. Например, даты соседних сеансов у меня получилось вывести с горем пополам, но в результате дата не соответствует сеансу.
http://sqlfiddle.com/#!9/6f0cd/7
Ах, чертов sqlfiddle вообще вывел по-своему... Теперь и название фильма неправильное.
У меня на машине получилось пикрелейтед.
>>480302
Сохранил эту простыню себе на жесткий диск. А то пока я это дочитаю, тред утонет.
В общем, до завтра. Я сегодня наверное не выспался, совсем не соображаю.
Говносборка требует библиотеку. Ее надо скачать и прописать в php.ini.
Твой вопрос легко гуглится, кстати.
http://ideone.com/IZPlHK
Ну это очевидно. А почему она локальная? На C/C++, Python в этом случае все прекрасно видится.
Если средствами php, то сделай названия книг ссылками с передаваемым через гет параметром id:
while($row = $result->fetch_assoc()){
....
<a href="<?php echo $_SERVER['SCRIPT_NAME'] . '?id=' . {$row['id']};?>">{$row['book_name']}</a>
....
}
Затем в контроллере проверяешь, передавался ли параметр id гет-запросом: if(isset($_GET['id'])){ выводим вид с описанием книги на отдельной странице } иначе {вывести таблицу книг}
Спасибо, но уже сам додумался
Спасибо, но уже сам додумался
В php функция не видит переменных, объявленных снаружи (даже если их имена совпадают).
Здесь две разные переменные (глобальная и локальная), которые не имеют ничего общего:
$word = 'hello';
function sayWord(){
echo $word;
}
Локальная переменная уничтожается, когда функция отрабатывает.
Из функции ты можешь получить доступ к глобальной переменной передав ее в качестве параметра:
$word = 'hello';
function sayWord($phrase){
echo $phrase;
}
sayWord($word);
или через ключевое слово global
$word = 'hello';
function sayWord(){
global $word;
echo $word;
}
Либо через замыкание:
$word = 'hello';
function sayWord() use ($word){
echo $word;
}
Конкретно автолод делается не так.
Но я не буду расписывать, у треда ревнивый оп, дождись когда он вернется или загугли автозагрузку php.
В php функция не видит переменных, объявленных снаружи (даже если их имена совпадают).
Здесь две разные переменные (глобальная и локальная), которые не имеют ничего общего:
$word = 'hello';
function sayWord(){
echo $word;
}
Локальная переменная уничтожается, когда функция отрабатывает.
Из функции ты можешь получить доступ к глобальной переменной передав ее в качестве параметра:
$word = 'hello';
function sayWord($phrase){
echo $phrase;
}
sayWord($word);
или через ключевое слово global
$word = 'hello';
function sayWord(){
global $word;
echo $word;
}
Либо через замыкание:
$word = 'hello';
function sayWord() use ($word){
echo $word;
}
Конкретно автолод делается не так.
Но я не буду расписывать, у треда ревнивый оп, дождись когда он вернется или загугли автозагрузку php.
Автолоад делается так, я уже погуглил. А __autoload() устарел и скоро будет депрекатед.
В итоге сделал через класс, все идеально работает. К тому же лишняя инкапсуляция не помешает. И глобал скоуп не засоряется.
Да, надо где-то как-то разрешить wrapper https
>>480393
> Например, даты соседних сеансов у меня получилось вывести с горем пополам, но в результате дата не соответствует сеансу.
Посмотри на свой селект. Там написано:
SELECT ....
f2.name,
MIN(s2.date)
...
GROUP BY s1.date // кстати тут наверно группировать надо не по дате а по id сеанса, так надежнее
Мы присоединяем к каждой строчке в таблице сеансов s1 все сеансы из s2 и затем группируем так, что останется только одна строчка из s2.
MIN(s2.date) означает что тут мы должны взять наименьшее значение из группы
f2.name значит «взять любое значение». Такую конструкцию стоит использовать только когда все значения полей в группе одинаковые, иначе результат получится не предсказуем.
> Ах, чертов sqlfiddle вообще вывел по-своему...
Потому что ты фактически берешь случайное значение из группы.
Решения (если ты не прочел статью по ссылке то конечно жаль) описаны в статье по ссылке, вот какие они:
— сделать таблицу вида сеанс — дата следующего сеанса и к ней приджойнить таблицу сеансов по дате следующего сеанса
— вариант с 3 джойнами таблицы сеансов, который я описал, второй джойн прикрепляет все сеансы которые идут позже сеанса из первой таблицы, а третий отсекает все сеансы из второй таблицы, для которых есть более ранний сеанс, так что остается только следующий, а не второй, третий и тд. Я не проверял эту идею, но она по моему выглядит интересно.
> Потому что пока я теряюсь.
Попробуй сделать то что я выше написал, если понимаешь английский то почитай статью, если нет то попробуй перевести ее бингом и что-нибудь понять: http://www.microsofttranslator.com/
Уж SQL код то ты прочесть в любом случае можешь.
Если будет что-то непонятно, задавай вопросы.
Да, надо где-то как-то разрешить wrapper https
>>480393
> Например, даты соседних сеансов у меня получилось вывести с горем пополам, но в результате дата не соответствует сеансу.
Посмотри на свой селект. Там написано:
SELECT ....
f2.name,
MIN(s2.date)
...
GROUP BY s1.date // кстати тут наверно группировать надо не по дате а по id сеанса, так надежнее
Мы присоединяем к каждой строчке в таблице сеансов s1 все сеансы из s2 и затем группируем так, что останется только одна строчка из s2.
MIN(s2.date) означает что тут мы должны взять наименьшее значение из группы
f2.name значит «взять любое значение». Такую конструкцию стоит использовать только когда все значения полей в группе одинаковые, иначе результат получится не предсказуем.
> Ах, чертов sqlfiddle вообще вывел по-своему...
Потому что ты фактически берешь случайное значение из группы.
Решения (если ты не прочел статью по ссылке то конечно жаль) описаны в статье по ссылке, вот какие они:
— сделать таблицу вида сеанс — дата следующего сеанса и к ней приджойнить таблицу сеансов по дате следующего сеанса
— вариант с 3 джойнами таблицы сеансов, который я описал, второй джойн прикрепляет все сеансы которые идут позже сеанса из первой таблицы, а третий отсекает все сеансы из второй таблицы, для которых есть более ранний сеанс, так что остается только следующий, а не второй, третий и тд. Я не проверял эту идею, но она по моему выглядит интересно.
> Потому что пока я теряюсь.
Попробуй сделать то что я выше написал, если понимаешь английский то почитай статью, если нет то попробуй перевести ее бингом и что-нибудь понять: http://www.microsofttranslator.com/
Уж SQL код то ты прочесть в любом случае можешь.
Если будет что-то непонятно, задавай вопросы.
В PHP глобальные переменные недоступны в функциях, а локальные снаружи функций. Это сделано специально ради повышения качества кода. В Питоне порядок другой, но там по моему глобальные переменные доступны только на чтение из функции.
А что мешает поместить $directories внутрь функции autoload?
Или как второй вариант ты можешь использовать замыкание и передать переменную через use:
spl_a...d_register(function (...) use ($var) {
....
});
Так даже удобнее, незачем твоей функцией засорять область видимости.
Вот мануал, изучай:
http://php.net/manual/ru/functions.user-defined.php
http://php.net/manual/ru/functions.anonymous.php
Задача про миллион решена верно. Кстати, ты бы мог поместить переменные в заголовок цикла, так как там в первую и третью части можно вставлять несколько выражений, разделяя их запятыми:
for ($i=1, $year = 16; $totalMoney<=1000000; $i++, $year++) ...
Аналогично если тебе нечего написать, то в первой и третьей части можно оставить пустое место:
for ( ; $totalMoney<=1000000 ; )
Главное что точек с запятой должно быть ровно две.
И кстати непонятно зачем там $i? Она же не используется.
А вот про кредит считает неправильно. Там получается около 61270.
Смотри, у тебя в последний месяц анон платит 5000, и сразу же выплачивает 4139 остатка. А ведь он не может сразу это выплатить, он должен подождать месяц, за который набегут проценты и комиссии и итоговая сумма выйдет больше — не 59139, а около 61270.
Надо смотреть чему равен остаток долга и обрабатывать ситуацию, когда она маленький, а не выплачивать сразу же 5000 вот в этом месте: ... + $servicePayment - $monthlyPayment;
Попробуй переписать код внутри цикла примерно так:
- прибавляем проценты и комиссию к остатку долга
- если остаток маленький, выплачиваем сколько осталось и уходим
- иначе платим 5000
«Платим» здесь значит уменьшаем долг и увеличиваем общую сумму выплаченного.
Задача про миллион решена верно. Кстати, ты бы мог поместить переменные в заголовок цикла, так как там в первую и третью части можно вставлять несколько выражений, разделяя их запятыми:
for ($i=1, $year = 16; $totalMoney<=1000000; $i++, $year++) ...
Аналогично если тебе нечего написать, то в первой и третьей части можно оставить пустое место:
for ( ; $totalMoney<=1000000 ; )
Главное что точек с запятой должно быть ровно две.
И кстати непонятно зачем там $i? Она же не используется.
А вот про кредит считает неправильно. Там получается около 61270.
Смотри, у тебя в последний месяц анон платит 5000, и сразу же выплачивает 4139 остатка. А ведь он не может сразу это выплатить, он должен подождать месяц, за который набегут проценты и комиссии и итоговая сумма выйдет больше — не 59139, а около 61270.
Надо смотреть чему равен остаток долга и обрабатывать ситуацию, когда она маленький, а не выплачивать сразу же 5000 вот в этом месте: ... + $servicePayment - $monthlyPayment;
Попробуй переписать код внутри цикла примерно так:
- прибавляем проценты и комиссию к остатку долга
- если остаток маленький, выплачиваем сколько осталось и уходим
- иначе платим 5000
«Платим» здесь значит уменьшаем долг и увеличиваем общую сумму выплаченного.
Локальная это переменная созданная внутри функции, глобальная снаружи. В функции видны только локальные переменные.
Правила из других языков тут не применимы.
>>480428
ты молодец, что помогаешь анонам, хотя тут (и в остальных ситуациях) лучше обойтись без global. Например использовать замыкание.
>>480445
Через класс можно, но посмотри вариант с замыканием — там просто меньше кода выйдет.
Автозагрузчик не должен возвращать false/true, PHP сам увидит что класс загружен.
Также обрати внимание что существует готовая функция автозагрузки: http://php.net/manual/ru/function.spl-autoload.php
Дописать в httpd.conf / apache2.conf (или как он там сейчас называется) строку
ServerName localhost
и перезагрузить апач
https://wiki.apache.org/httpd/CouldNotDetermineServerName
Чтобы работало net start, надо установить Апач как службу, по моему командой
httpd.exe -k install -n "apache2.4"
обрати внимание на расстановку пробелов, это важно.
Описано тут: https://httpd.apache.org/docs/2.4/platform/windows.html
проверить установлена ли служба можно открыв Пуск -> services.msc (откроется окно управления службами) и поискав там Апач.
Может у тебя служба не установлена, а может установлена но под другим именем. Открой services.msc и проверь.
Ну и еще в services.msc можно поставить службу на автозапуск, чтобы Апач запускался при загрузке системы.
>- JS: https://gist.github.com/codedokode/ce30e7a036f18f416ae0
А где бы подглядеть правильно решение задачек?
напиши что работал гей-шлюхой, сразу возьмут тимлидом, базарю.
Присоединяюсь к реквесту.
>>480661
Напиши, что неоконченное высшее если семестров хватает. Про покер не пиши. Мало кто положительно оценит (даже мини исследование было на эту тему). Напиши, что сделал на заказ калькулятор вероятностей на C++/C#. Подробнее расскажешь на собеседовании про него если спросят. И тебя "не выпиздывали", а ты сам ушел по какому-нибудь важному поводу и планируешь доучиться как стабилизируешь карьеру с финансами. Конечно доучиться так, что это не будет мешать рабочему процессу заочное/дистанционное и т.д.
>неоконченное высшее если семестров хватает
А что, неоконченное считается с какого то определённого числа семестров?
нет конечно, дибилы блять.
Вроде как 2 полных курса надо (4 семестра). Но у меня только по семестру в каждом вышло. А точнее даже по месяцу. Быстро надоедало просиживать штаны.
У меня один семестр, лол, говорю, что неоконченное.
SELECT FROM `rentobject` WHERE `showing` = 1 AND `price` < 100000 AND `price` > 0 ORDER BY `editingDate` DESC LIMIT 30, 45
Последние две цифры заменяются для постраничной навигации, но разница между ними всегда 15 (число строк на странице). Однако при получении результатов через mysql_fetch_row и присвоении через list() и цикл while в результате выдаётся не 15 строк, а по последней цифре LIMIT. То есть, запрос с LIMIT 30, 45 даст не 15 результатов, а 45. В чём дело? Как это исправить?
SELECT * FROM `rentobject` WHERE `showing` = 1 AND `price` < 100000 AND `price` > 0 ORDER BY `editingDate` DESC LIMIT 30, 45
Последние две цифры заменяются для постраничной навигации, но разница между ними всегда 15 (число строк на странице). Однако при получении результатов через mysql_fetch_row и присвоении через list() и цикл while в результате выдаётся не 15 строк, а по последней цифре LIMIT. То есть, запрос с LIMIT 30, 45 даст не 15 результатов, а 45. В чём дело? Как это исправить?
Надо запостить ссылку на код и спросить правильно решено или нет. Также желательно перед этим проверить их роботом на сайте dkab.github. У нас нет готовых решений.
>>480633
Это какой-то тролль написал
Насчет xdebug, отладка делается через IDE и она описана в мануалах к IDE:
https://netbeans.org/kb/docs/php/debugging_ru.html
http://habrahabr.ru/post/209024/
https://www.jetbrains.com/phpstorm/help/debugging-php-applications.html
Потому у меня это пока не в приоритете, хотя общий, не привязанный к IDE мануал было бы неплохо сделать, который бы вообще рассказывал что такое отладка.
Если у тебя есть какие-то общие вопросы вроде «а что такое точка останова», или что-то не работает, то можешь их тут задавать. Но сначала прочти мануалы которые есть в сети.
Почитай как работает LIMIT, он работает не так как тебе кажется:
http://www.tigir.com/paging.htm
http://www.phpfaq.ru/paginator
http://www.lissyara.su/articles/freebsd/programms/mysql_-_base_descriptions/
Если что-то будет непонятно, задавай вопросы.
Единственное, что мне не нравится в статье это упоминание SQL_CALC_FOUND_ROWS. Он ни разу не элегантный и не всегда дает оптимизацию (часто отдельный запрос COUNT быстрее), потому я бы не советовал его использовать, по крайней мере пока не научишься разбираться в индексах и оптмимизации запросов.
Блин, спасибо тебе огромное! Ты охуенен!
Комментарии это дело добровольное, программа будет работать и без них, но вот легко ли другим будет в ней разобраться?
Помни, что код пишется в первую очередь для людей.
Прежде всего ты должен стараться делать код максимально самодокументирующим, чтобы имена функций и переменных были максимально понятными и говорили о том, что они хранят или делают. Не называй переменные/функции бессмысленными словами вроде tmp, key, getData(), и почитай статью http://learn.javascript.ru/write-unmain-code
Теперь про комментарии. Комментарий в картинке довольно старомодный, я бы не советовал писать эти линии из минусов, они только замусоривают файл. Стандарт для описания комментариев называется phpDoc:
http://habrahabr.ru/sandbox/22836/
https://ru.wikipedia.org/wiki/PHPDoc
http://en.wikipedia.org/wiki/PHPDoc
http://www.phpdoc.org/docs/latest/index.html
На русском мало хорошей документации, только на английском.
Стандарт не заставляет тебя использоввать описанные там теги. Но если ты например хочешь написать что функция возвращает массив объектов класса User то не пиши это словвами и не выдумывай свой стандарт, а используй phpDoc:
@return User[] список друзей пользователя
Тогда эту информацию сможет использовать например IDE для автодополнения и вывода подсказок. Также, из комментариев phpDoc можно автоматически сгенерировать документацию вроде такой:
http://www.doctrine-project.org/api/orm/2.0/class-Doctrine.ORM.EntityManager.html
вот исходный файл с комментариями: http://www.doctrine-project.org/api/orm/2.0/source-class-Doctrine.ORM.EntityManager.html
Комментарий в твоем примере устаревший: во-первых, там лишние линии, во-вторых @access писать незачем. это делали в PHP4 где не было public/private. Смотри на комментарии в моем примере, там они лучше.
Комментарии нужны для описания неочевидных вещей. Ну например такие очевидные комментарии малополезны:
// увелчивает число на 1
$x++;
// возвращает залогинен ли юзер
function isUserLoggedIn()
А такие полезны:
// мы должны увеличить число новостей на 1 чтобы учесть выведенную в топ новость при расчете номеров страниц
$news++;
/××
× возвращает, залогинен ли юзер и подтвердил ли он свой аккаунт, если еще нет, то функция вернет false
×/
function isUserLoggedIn
Потому все зависит от ситуации. Если ты пишешь библиотеку или код, который будет исплоьзовать много людей то хорошо бы иметь phpDoc комментарии ко всем публичным функциями и сгенерированную документацию. Если у вас большой проект который пилить еще несколько лет, то опять же комментарии хорошо бы иметь. Если ты делаешь маленький сайт, то просто освети неочевидные с первого взгляда вещи и пиши качественный самодокументирующий код, чтобы с первого взгляда все было понятно.
Комментарии это дело добровольное, программа будет работать и без них, но вот легко ли другим будет в ней разобраться?
Помни, что код пишется в первую очередь для людей.
Прежде всего ты должен стараться делать код максимально самодокументирующим, чтобы имена функций и переменных были максимально понятными и говорили о том, что они хранят или делают. Не называй переменные/функции бессмысленными словами вроде tmp, key, getData(), и почитай статью http://learn.javascript.ru/write-unmain-code
Теперь про комментарии. Комментарий в картинке довольно старомодный, я бы не советовал писать эти линии из минусов, они только замусоривают файл. Стандарт для описания комментариев называется phpDoc:
http://habrahabr.ru/sandbox/22836/
https://ru.wikipedia.org/wiki/PHPDoc
http://en.wikipedia.org/wiki/PHPDoc
http://www.phpdoc.org/docs/latest/index.html
На русском мало хорошей документации, только на английском.
Стандарт не заставляет тебя использоввать описанные там теги. Но если ты например хочешь написать что функция возвращает массив объектов класса User то не пиши это словвами и не выдумывай свой стандарт, а используй phpDoc:
@return User[] список друзей пользователя
Тогда эту информацию сможет использовать например IDE для автодополнения и вывода подсказок. Также, из комментариев phpDoc можно автоматически сгенерировать документацию вроде такой:
http://www.doctrine-project.org/api/orm/2.0/class-Doctrine.ORM.EntityManager.html
вот исходный файл с комментариями: http://www.doctrine-project.org/api/orm/2.0/source-class-Doctrine.ORM.EntityManager.html
Комментарий в твоем примере устаревший: во-первых, там лишние линии, во-вторых @access писать незачем. это делали в PHP4 где не было public/private. Смотри на комментарии в моем примере, там они лучше.
Комментарии нужны для описания неочевидных вещей. Ну например такие очевидные комментарии малополезны:
// увелчивает число на 1
$x++;
// возвращает залогинен ли юзер
function isUserLoggedIn()
А такие полезны:
// мы должны увеличить число новостей на 1 чтобы учесть выведенную в топ новость при расчете номеров страниц
$news++;
/××
× возвращает, залогинен ли юзер и подтвердил ли он свой аккаунт, если еще нет, то функция вернет false
×/
function isUserLoggedIn
Потому все зависит от ситуации. Если ты пишешь библиотеку или код, который будет исплоьзовать много людей то хорошо бы иметь phpDoc комментарии ко всем публичным функциями и сгенерированную документацию. Если у вас большой проект который пилить еще несколько лет, то опять же комментарии хорошо бы иметь. Если ты делаешь маленький сайт, то просто освети неочевидные с первого взгляда вещи и пиши качественный самодокументирующий код, чтобы с первого взгляда все было понятно.
Алсо @library — так сейчас тоже не пишут. Аргумент описывается так:
@param string $library Название библиотеки которую надо загрузить
Я вижу ты взял этот код из какого-то старого фреймврка вроде CodeIgniter. Не бери его в пример, он старый и плохой по нынешним меркам.
Ты наверно больше 20 строчек скрипты не писал. В реальных приложениях сотни файлов, десятки тысяч строк, пишет часто не один человек, и как это можно запомнить, я не представляю.
>>480661
Не знаю. Для меня лично покер ничего не значит, ни плюс, ни минус, но другие люди могут считать по-другому. То, то ты бросал учебу аж 2 раза подряд скорее негативная характеристика. Если тебе так не нравится учиться, зачем было поступать — подумает рекрутер.
где об этом писать? Пхп я изучать сегодня начал
Тебе надо изучить сам PHP. Можешь почитать мой учебник в оп посте, можешь начать с маунала: http://php.net/manual/ru/tutorial.php , можешь читать оба сразу.
В мануале разумеется весь язык описан, на то он и мануал. Но учебник для начинабщих проще в понимании.
Правильно ли понял условия задачи?
https://github.com/tokotun/JS/blob/master/lesson_11.html
https://github.com/tokotun/JS/blob/master/lesson_11.js
РНР поддерживает все 3 фреймворка, поэтому советую использовать их все одновременно
LAMP
Дико извиняюсь за самый кривой код на свете, плюс еще не переименовал переменные нормально, но я уже реву от этой задачи.
Никак не могу понять, как вставлять где нужно "миллионы" и "тысячи", а еще надо род как-то учитывать и вообще полный ад.
http://ideone.com/dNE9Iq
Я почитал учебник, вроде понял синтаксис, но вот как решить задачу до сих пор не знаю.
Наткнулся на WebSockets, как их использовать? Гугл выдаёт монструозные примеры, которые не работают.
> Наткнулся на WebSockets, как их использовать?
Я думаю лучше начать с теории, что такое Websocket и как работает (просто погугли по этому слов и ищи статьи описывающие именно подробности протокола, а не примеры кода), потом почитать про клиентские библиотеки для работы с ним, потом про серверные. Чтобы обрабатывать websocket на PHP, тебе нужно написать свой сервер который будет слушать порт и принимать соединения (если ты не знаешь что такое порт то стоит почитать про сокеты и может даже сделать простую программку, работающую с ними). При этом если ты хочещь обрабатывать больше одного соединения, то тебе нужна асинхронная работа с сокетами, то есть event loop, и это все предоставляют библиотеки вроде Ratchet. Но начинать надо с теории, нет никакого смысла пользоваться библиотекой если ты не понимаешь как она работает.
>Вот тебе еще мини-задача тогда (простая конечно): сделай базу для имиджборды
>простая конечно
Все, я понял: это ты так тонко тралируешь.
У меня там получилось 25 строк, 7 этапов решения с тремя джойнами. И это я еще не дописал финальную часть с WHERE.
На предпоследнем этапе пока запнулся. Мне нужно выбрать из таблицы с постами (id, thread_id, text, date, ...) по три последних даты для каждого треда, и присобачить приджойнить их к результирующей таблице, тогда я смогу наконец выставить условия where и получить список постов.
https://gist.github.com/anonymous/5002185bf9254d35c061
sqlfiddle пиздит, что многобуков: Request content too large (>8000)
Убрал инсерты, оставил голые таблицы. Теперь говорит: Oops! something went wrong
А, вроде заработал. Но там эмпти сеты, ест-но.
Нет, опять лагает.
>>480302
Схоронил пасту про вордпресс. Задание про бд кинтоеатра >>480475 тоже доделаю позже.
Если можешь сделать простой сайт типа блога двумя способами - на голом php и на любом фреймворке.
http://thejackalofjavascript.com/git-and-github-for-beginners/
Вот суперски хороший гайд для бегиннеров
О, кажется что-то похожее нашел. Оставлю это здесь, вдруг кому еще пригодится. Довольно интересная штука:
как выбрать из таблицы вида
id | Название фильма | Категория | Дата выхода в прокат
по (например) 5 самых новых фильмов для каждой категории?
http://stackoverflow.com/questions/1442527/how-to-select-the-newest-four-items-per-category/1442867#1442867
В оп-посте еще кажется где-то была ссылка на мануал по гиту, но там много букв.
https://git-scm.com/book/ru/v1/%D0%9E%D1%81%D0%BD%D0%BE%D0%B2%D1%8B-Git
>>480877
Спасибо, но я другой гайд нагуглил. Пиздец пердольное говно, нахуй так жить? Неужели по человечески все нельзя сделать? 21 век на дворе.
Кароч залил свой первый сайтец на гитхаб этот и прошу ОП-а проверить его. Меня в основном общая структура и безопасность волнует, а не красота и поддерживаемость кода. Но и по ней тоже могу рекомендации учесть.
https://github.com/Nattpyre/randomwebm
А какие альтернативы есть? Прост мне md5 нужен в основном для того, чтобы название файлам давать и проверять при загрузке, есть ли такая вебм в базе. Ну и соответственно не загружать повторно. Название то конечно можно и другими функциями давать, а вот как проверять файлы на дублирование по содержимому - хз.
В плане? Я знаю что пиздец, но как лучше сделать пока не понял. А ты точно ОП? ОП, насколько я помню, очень добрый и снисходительный.
Иногда мне кажется, что они - одно целое.
> Все, я понял: это ты так тонко тралируешь.
Это не столько троллинг, сколько желание научить тебя решать не совсем стандартные задачи. Я вижу (по тому, что ты решил лайки), что ты в общем сообразительный, ведь задачу про лайки многие джуниоры либо не решат, либо нагородят вложенных запросов, и потому стараюсь подбирать такие задачи, которые заставят тебя думать и помогут что-то понять.
По твоему коду: первая мысль, это то, что «тред» в общем-то это тоже пост и незачем для него делать особую таблицу (ну а если и делать, то без titlem достаточно одного поля id). Просто у ОП-поста thread_id либо пуст либо совпадает с id (я не помню, позволяют ли внешние ключи ссылаться на саму же запись, надо бы это проверить, если нет то можно ставить NULL как признак того что это ОП-пост. Более того, использование NULL позволяет использовать индекс в запросах вроде WHERE thread_id IS NULL и потому выгоднее. С другой стороны выбрать все посты треда по ид треда в таком случае чуть сложнее).
Слышал ли ты про нормализацию? У тебя явные нарушения нормализации, так как заголовок треда повторен 2 раза:
> Обсуждения следующей части тред №2
Отказ от нормализации приводят потом к сложностям с выборкой или обновлением информации в базе. Если совсем кратко то нормализация это когда данные не дублируются и когда одна ячейка содержит одно значение, а не несколько. Вот ссылки, почитай обязательно, чтобы не совершить таких ошибок при проектированиии реальной БД (также про это любят спрашивать на собеседовании):
http://club.shelek.ru/viewart.php?id=311
http://i-novice.net/6-normalnyx-form-bd/
http://habrahabr.ru/post/193756/
Есть также денормализация ( http://ruhighload.com/post/%D0%94%D0%B5%D0%BD%D0%BE%D1%80%D0%BC%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F+%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85 ), которая делается ради ускорения выборки. Денормализация это не значит что мы проектируем таблицы как попало, а значит что мы делаем сначала нормализоанную базу, а потом немного меняем ее под наши нужды. Например в блоге мы можем добавить в таблицу постов колонку «число комментарив» для того чтобы быстро выбирать самые популярные посты без джойна на огромную таблицу комментариев. За денормализацию мы расплачиваемся усложнением работы с базой и возникновением риска рассинхронизации числа в конлонке и числа реальных комментариев (но этот риск лучше чем лежащий под нагрузкой сайт).
В твоем случае денормализация может помочь упростить выборку, но сначала конечно надо сделать без нее.
> ОКАЗЫВАЕТСЯ можно джойнить не только существующую в бд таблицу,
А еще можно делать SELECT FROM не из таблицы а из подзапроса.
> Мне нужно выбрать из таблицы с постами (id, thread_id, text, date, ...) по три последних даты для каждого треда
Самое простое что приходит в голову это подзапрос в WHERE:
— выбрать из таблицы тредов, приджойненной к постам, все посты, id которых равняется (выбрать id 3 последних постов из текущего треда)
То есть подзапрос в WHERE выбирает id 3 последних постов в треде (id которого берется из внешнего запроса). Но такой подзапрос конечно не очень эффективен, ведь фактически для каждого треда будет делаться отдельный подзапрос, сколько тредов столько и подзапросов.
Потому если у тебя есть решение получше то было бы интересно его увидеть. Я думаю, что в статье которую я давал, есть пара вариантов как это можно сделать.
Ну и возвращаясь к денормализации. На практике конечно сложными подзапросами мы убьем базу и нам нужно быстрое решение. Быстрое значит что id последних постов должны где-то храниться как избыточная информация. Вариантов 2:
— в треде сделать несколько колонок вида «последний пост», «предпоследний пост» и при постинге в тред обновлять их. Если ты прочел про нормализацию, то интуиция должна тебе подсказать что это не очень удачная схема, хранить id в таком виде: нельзя просто так увеличить число постов, неудобно писать запросы
— сделать отдельную таблицу «последние посты» которая хранит связь «тред — последний пост» и которую мы тоже обновляем при постинге в тред.
— в треде сделать колонку, где хранить список последних постов например через запятую. делать выборку в 2 этапа: сначала получаем список тредов, затем выбираем из них id последних постов и вторым запросом выгребаем все посты.
> Все, я понял: это ты так тонко тралируешь.
Это не столько троллинг, сколько желание научить тебя решать не совсем стандартные задачи. Я вижу (по тому, что ты решил лайки), что ты в общем сообразительный, ведь задачу про лайки многие джуниоры либо не решат, либо нагородят вложенных запросов, и потому стараюсь подбирать такие задачи, которые заставят тебя думать и помогут что-то понять.
По твоему коду: первая мысль, это то, что «тред» в общем-то это тоже пост и незачем для него делать особую таблицу (ну а если и делать, то без titlem достаточно одного поля id). Просто у ОП-поста thread_id либо пуст либо совпадает с id (я не помню, позволяют ли внешние ключи ссылаться на саму же запись, надо бы это проверить, если нет то можно ставить NULL как признак того что это ОП-пост. Более того, использование NULL позволяет использовать индекс в запросах вроде WHERE thread_id IS NULL и потому выгоднее. С другой стороны выбрать все посты треда по ид треда в таком случае чуть сложнее).
Слышал ли ты про нормализацию? У тебя явные нарушения нормализации, так как заголовок треда повторен 2 раза:
> Обсуждения следующей части тред №2
Отказ от нормализации приводят потом к сложностям с выборкой или обновлением информации в базе. Если совсем кратко то нормализация это когда данные не дублируются и когда одна ячейка содержит одно значение, а не несколько. Вот ссылки, почитай обязательно, чтобы не совершить таких ошибок при проектированиии реальной БД (также про это любят спрашивать на собеседовании):
http://club.shelek.ru/viewart.php?id=311
http://i-novice.net/6-normalnyx-form-bd/
http://habrahabr.ru/post/193756/
Есть также денормализация ( http://ruhighload.com/post/%D0%94%D0%B5%D0%BD%D0%BE%D1%80%D0%BC%D0%B0%D0%BB%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F+%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85 ), которая делается ради ускорения выборки. Денормализация это не значит что мы проектируем таблицы как попало, а значит что мы делаем сначала нормализоанную базу, а потом немного меняем ее под наши нужды. Например в блоге мы можем добавить в таблицу постов колонку «число комментарив» для того чтобы быстро выбирать самые популярные посты без джойна на огромную таблицу комментариев. За денормализацию мы расплачиваемся усложнением работы с базой и возникновением риска рассинхронизации числа в конлонке и числа реальных комментариев (но этот риск лучше чем лежащий под нагрузкой сайт).
В твоем случае денормализация может помочь упростить выборку, но сначала конечно надо сделать без нее.
> ОКАЗЫВАЕТСЯ можно джойнить не только существующую в бд таблицу,
А еще можно делать SELECT FROM не из таблицы а из подзапроса.
> Мне нужно выбрать из таблицы с постами (id, thread_id, text, date, ...) по три последних даты для каждого треда
Самое простое что приходит в голову это подзапрос в WHERE:
— выбрать из таблицы тредов, приджойненной к постам, все посты, id которых равняется (выбрать id 3 последних постов из текущего треда)
То есть подзапрос в WHERE выбирает id 3 последних постов в треде (id которого берется из внешнего запроса). Но такой подзапрос конечно не очень эффективен, ведь фактически для каждого треда будет делаться отдельный подзапрос, сколько тредов столько и подзапросов.
Потому если у тебя есть решение получше то было бы интересно его увидеть. Я думаю, что в статье которую я давал, есть пара вариантов как это можно сделать.
Ну и возвращаясь к денормализации. На практике конечно сложными подзапросами мы убьем базу и нам нужно быстрое решение. Быстрое значит что id последних постов должны где-то храниться как избыточная информация. Вариантов 2:
— в треде сделать несколько колонок вида «последний пост», «предпоследний пост» и при постинге в тред обновлять их. Если ты прочел про нормализацию, то интуиция должна тебе подсказать что это не очень удачная схема, хранить id в таком виде: нельзя просто так увеличить число постов, неудобно писать запросы
— сделать отдельную таблицу «последние посты» которая хранит связь «тред — последний пост» и которую мы тоже обновляем при постинге в тред.
— в треде сделать колонку, где хранить список последних постов например через запятую. делать выборку в 2 этапа: сначала получаем список тредов, затем выбираем из них id последних постов и вторым запросом выгребаем все посты.
Нужен SSH-доступ и возможность запускать долгоживущие программы, прописав их в автозапуск. Скорее всего хостинг не подойдет, нужен VPS или сервер в облаке (Digital Ocean стоит от 5 долларов в месяц по моему, селектеловское облако при маленьком трафике стоит от 200 р в месяц).
>либо нагородят вложенных запросов
Лови:
http://sqlfiddle.com/#!9/e8c31/3
Тут правда куча джойнов, а не подзапросов. Но что удивительно, ОНО работает.
>тред это тоже пост и незачем для него делать особую таблицу
Да, была такая мысль. Нужно объединить таблицу тредов и постов в одну, и добавить либо колонку, либо таблицу последних постов.
Ну хорошо, завтра переделаю. Я слегка вымотался. Фигурально выражаясь.
Про нормализацию я в курсе (хотя почитать еще не помешает, да).
> Пиздец пердольное говно, нахуй так жить? Неужели по человечески все нельзя сделать? 21 век на дворе.
git великолепен. github это лишь хостинг для git-репозиториев и разумеется тебе нужно сначала знать git (и уметь работать с репозиториями) чтобы им пользоваться. А чтобы знать git тебе надо прочесть git book.
Если ты планируешь работать программистом не в дноконторе, то вы будете использовать git или аналогичную систему управления версиями (в дноконторах, как ты догадался, файлики копируют руками и постоянно теряют так как время работающих там студентов все равно ничего не стоит). Потому что без нее работать над проектом даже одному неудобно, а командой вообще невозможно.
Потому вместо ненависти попробуй открыть и почитать git book. Там много букв, но там все объяснено простыми словами, а если что-то непонятно ты всегда можешь тут задать вопрос.
Там надо пользоваться командной строкой. Командная строка — прямой интерфейс с компьютером, ты пишешь команды, он выполняет, вот гайд для начинающего: https://gist.github.com/codedokode/10539568
Если ты под Wndows и ставишь git то для работы с ним ты запускаешь git bash и тебе надо читать инструкции для линукса, а не Windows в моем гайде.
Как минимум, используя git ты можешь не бояться потерять свой код так как репозиторий хранит полную историю и всегда можно вернуться к предыддущей версии. Плюс, можно эту самую историю смотреть. Можно посмотреть кто поменял эту строчку в файле, когда и почему. Ну а если ты например запилишь совместный проект с другими анонами, без гита вам вообще не обойтись.
К гиту есть программы с кнопками и окошками, но изучать надо именно с командной строки иначе ты будешь как обезьяна которая тыкает кнопки не понимая что они делают и которая застопорится на первой же проблеме. По моему опыту, вносить изменения (коммитить, мерджить, переходить между ветками) удобно из командной строки, а просматривать историю удобнее програмами с графическим интерфейсом.
В общем, предлагаю прекратить нытье и взяться за книгу.
> Пиздец пердольное говно, нахуй так жить? Неужели по человечески все нельзя сделать? 21 век на дворе.
git великолепен. github это лишь хостинг для git-репозиториев и разумеется тебе нужно сначала знать git (и уметь работать с репозиториями) чтобы им пользоваться. А чтобы знать git тебе надо прочесть git book.
Если ты планируешь работать программистом не в дноконторе, то вы будете использовать git или аналогичную систему управления версиями (в дноконторах, как ты догадался, файлики копируют руками и постоянно теряют так как время работающих там студентов все равно ничего не стоит). Потому что без нее работать над проектом даже одному неудобно, а командой вообще невозможно.
Потому вместо ненависти попробуй открыть и почитать git book. Там много букв, но там все объяснено простыми словами, а если что-то непонятно ты всегда можешь тут задать вопрос.
Там надо пользоваться командной строкой. Командная строка — прямой интерфейс с компьютером, ты пишешь команды, он выполняет, вот гайд для начинающего: https://gist.github.com/codedokode/10539568
Если ты под Wndows и ставишь git то для работы с ним ты запускаешь git bash и тебе надо читать инструкции для линукса, а не Windows в моем гайде.
Как минимум, используя git ты можешь не бояться потерять свой код так как репозиторий хранит полную историю и всегда можно вернуться к предыддущей версии. Плюс, можно эту самую историю смотреть. Можно посмотреть кто поменял эту строчку в файле, когда и почему. Ну а если ты например запилишь совместный проект с другими анонами, без гита вам вообще не обойтись.
К гиту есть программы с кнопками и окошками, но изучать надо именно с командной строки иначе ты будешь как обезьяна которая тыкает кнопки не понимая что они делают и которая застопорится на первой же проблеме. По моему опыту, вносить изменения (коммитить, мерджить, переходить между ветками) удобно из командной строки, а просматривать историю удобнее програмами с графическим интерфейсом.
В общем, предлагаю прекратить нытье и взяться за книгу.
Я не говорю, что сама идея говно. Сам функционал хороший и полезный. А вот его реализация говно. Все должно быть предельно просто и понятно на интуитивном уровне, в этом же сервисе этим даже близко не пахнет. Изучать какие-то книги чтобы просто пользоваться сайтом - это уже за гранью.
Ну во-первых от консольки избавиться и перейти на графический интерфейс. Во-вторых, максимально упростить работу с базовыми функциями сервиса, чтобы не приходилось в гугл лезть для этого или вообще хоть какие-то мануалы курить. Далеко не всем интересно разбираться во всем подряд, большинству людей нужен простой и понятный функционал, а не пердолиться с консолькой чтобы просто файлы на сервер загрузить.
Посоны, как я могу передать пхп-страницей получить параметры, например
http://fgsfds.ru/fgsfds.php?parameter=fgsfds
?
Спасибо, разобрался.
Ты не путаешь git и github? Git это система хранения и управления изменениями файлов. github это просто хостинг для репозиториев git. Github не требует от тебя вообще ничего нового изучать, при условии что ты уже знаешь и используешь git. Github же ориентирован на программистов, которые скорее всего его уже знают и используют.
> во-первых от консольки избавиться и перейти на графический интерфейс
Графический интерфейс во многих случаях требует больше действий чем набор команды, особенно когда она уже есть в истории. Его нельзя так просто автоматизировать скриптами, в отличии от командной строки. Я например (как и многие программисты) недолюбливаю повторяющиеся рутинные действия.
К гиту есть программы с графическим интерфейсом, но они требуют понимания самого гита, без этого ты даже смысл команд не поймешь, то есть вначале все равно надо повозиться с командной строкой где ты явно отдаешь команды и видишь реакцию на них, и где гит от тебя не спрятан за кнопками (потому что когда он спрятан тебе надо в голове представлять что происходит внутри). В многие IDE (phpStorm например) встроены кнопки для работы с гитом.
По моему опыту, вносить изменения удобнее командой в командной строке, а просматривать изменения и историю удобнее через графический интерфейс.
Вот список программ: https://git-scm.com/downloads/guis
> Во-вторых, максимально упростить работу с базовыми функциями сервиса,
Если ты про гитхаб, то работа с ним очень проста если ты уже знаешь гит. Тебе достаточно добавить один remote в свой гит и сделать push. Не надо ничего скачивать и устанавливать, не надо ничего менять в своей работе. Куда удобнее?
Разумеется это удобство ты получаешь только если уже знаешь гит, но большинство программистов знают какую-либо систему контроля версий и это проблем не вызывает. А по твоему надо качать какую-то дебильную программу, которая не везде работает, в которой есть баги (то есть у тебя и так куча работы, сроки, а тут, внезапно, баги), в которой надо руками жать кучу кнопок и это удобнее чем просто ввести 2 команды? Ну извините. Я думаю, многие программисты с таким не согласятся.
> или вообще хоть какие-то мануалы курить
Если ты хочешь заниматься программированием и расти (а не делать рутинную однообразную работу), то мануалы курить тебе придется все время, предупреждаю заранее.
> Далеко не всем интересно разбираться во всем подряд,
Гит это не все подряд и не какая-то отдельная штука которая нужна только для гитхаба и ничего больше. Если ты будешь работать не в дноконторе, то вы будете его (или может аналогичную систему вроде меркуриала) использовать и тебе он понадобится.
> пердолиться с консолькой
Ты можешь установить GUI программу если так не любишь консоль, но учиться на консоли проще так как там ты видишь команды и реакцию на них, а в GUI программах все скрыто и они плохо годятся для обучения. Они сложнее так как тебе надо в голове представлять что они делают, а в консоли ты все видишь глазами. Новичок, берущий GUI программу просто придет к тому, что сломает репозиторий.
Ты не путаешь git и github? Git это система хранения и управления изменениями файлов. github это просто хостинг для репозиториев git. Github не требует от тебя вообще ничего нового изучать, при условии что ты уже знаешь и используешь git. Github же ориентирован на программистов, которые скорее всего его уже знают и используют.
> во-первых от консольки избавиться и перейти на графический интерфейс
Графический интерфейс во многих случаях требует больше действий чем набор команды, особенно когда она уже есть в истории. Его нельзя так просто автоматизировать скриптами, в отличии от командной строки. Я например (как и многие программисты) недолюбливаю повторяющиеся рутинные действия.
К гиту есть программы с графическим интерфейсом, но они требуют понимания самого гита, без этого ты даже смысл команд не поймешь, то есть вначале все равно надо повозиться с командной строкой где ты явно отдаешь команды и видишь реакцию на них, и где гит от тебя не спрятан за кнопками (потому что когда он спрятан тебе надо в голове представлять что происходит внутри). В многие IDE (phpStorm например) встроены кнопки для работы с гитом.
По моему опыту, вносить изменения удобнее командой в командной строке, а просматривать изменения и историю удобнее через графический интерфейс.
Вот список программ: https://git-scm.com/downloads/guis
> Во-вторых, максимально упростить работу с базовыми функциями сервиса,
Если ты про гитхаб, то работа с ним очень проста если ты уже знаешь гит. Тебе достаточно добавить один remote в свой гит и сделать push. Не надо ничего скачивать и устанавливать, не надо ничего менять в своей работе. Куда удобнее?
Разумеется это удобство ты получаешь только если уже знаешь гит, но большинство программистов знают какую-либо систему контроля версий и это проблем не вызывает. А по твоему надо качать какую-то дебильную программу, которая не везде работает, в которой есть баги (то есть у тебя и так куча работы, сроки, а тут, внезапно, баги), в которой надо руками жать кучу кнопок и это удобнее чем просто ввести 2 команды? Ну извините. Я думаю, многие программисты с таким не согласятся.
> или вообще хоть какие-то мануалы курить
Если ты хочешь заниматься программированием и расти (а не делать рутинную однообразную работу), то мануалы курить тебе придется все время, предупреждаю заранее.
> Далеко не всем интересно разбираться во всем подряд,
Гит это не все подряд и не какая-то отдельная штука которая нужна только для гитхаба и ничего больше. Если ты будешь работать не в дноконторе, то вы будете его (или может аналогичную систему вроде меркуриала) использовать и тебе он понадобится.
> пердолиться с консолькой
Ты можешь установить GUI программу если так не любишь консоль, но учиться на консоли проще так как там ты видишь команды и реакцию на них, а в GUI программах все скрыто и они плохо годятся для обучения. Они сложнее так как тебе надо в голове представлять что они делают, а в консоли ты все видишь глазами. Новичок, берущий GUI программу просто придет к тому, что сломает репозиторий.
упрлс?
Еще раз, у меня претензии не к Git, а именно к гитхабу. Интерфейс у него не интуитивный. А GUI версия программы убогая и сделана на отъебись. Все те функции, что есть в консольке можно и в графическом виде сделать, если захотеть. В том числе и автоматизацию рутины, вывод данных выполнения команд и прочее.
> у меня претензии не к Git, а именно к гитхабу. Интерфейс у него не интуитивный.
Он неинтуитивный для тебя, потому что (мне кажется) ты не знаком с гитом, если бы ты был с ним знаком то для тебя запушить код на гитхаб было бы можно всего парой команд, при этом ничего не скачивая и не устанавливая. Куда проще?
Гитхаб ориентирован на программистов, которые уже как правило знакомы с гитом и им дополнительно ничего изучать не требуется.
> А GUI версия программы убогая
Она может и убогая, не знаю, я ее не скачивал, и слышал такое мнение, но твои сложности именно из-за незнания гита. Без этого гитхабом нормально пользоваться нельзя. Я например пользуюсь обычным гитом из командной строки и мне ничего скачивать дополнительно не понадобилось чтобы работать с гитхабом. Соответственно ты тоже не обязан использовать github for Windows, ты можешь использовать любую программу для работы с гитом.
> Все те функции, что есть в консольке можно и в графическом виде сделать, если захотеть. В том числе и автоматизацию рутины, вывод данных выполнения команд и прочее.
Ну так та же самая командная строка в итоге и получится, только в запутанном виде с кучей лишнего. Впрочем, я тебе дал ссылку по которой есть разные гит-клиенты.
Ну естественно я не знаком с Git, т.к. я только-только первый сайт сделал. И запушил я таки парой команд, но для этого мне пришлось в гугл лезть. А если бы была нормальная GUI версия, то сделал бы я это в пару кликов и без гугла. Второй вариант лучше, чем первый, не?
Неужели они его приняли? И кто в здравом уме стал бы писать архиватор использующий JSON и увеличивающий объем файла? Я бы был настороже с людьми которые придумывают такие задания.
Я переписал его часть. Да, они его приняли. Похоже они просто смотрели на то, как я пишу код и все и как быстро я разберусь с топиком. Я смотрел на код их проектов, он был не плохим, прямо моя любимая django в обличии php.
Поправь, если я что-то неправильно понял про нормализацию.
1 н.ф. В одном поле для каждой записи только одно значение. Т.е. недопустимо вставлять несколько значений через запятую или пробел.
Например, если в нашем интернет-магазине господин Иванов приобрел ботинки, рубашки и штаны, нельзя писать в таблицу заказов (id, customer, item)
386 | Иванов | Ботинки, рубашки, штаны
Нужно писать
386 | Иванов | Ботинки
387 | Иванов | Рубашка --(теперь даже можно добавить столбец с кол-вом товара)
388 | Иванов | Штаны
2 н.ф. В таблице обязательно должен быть первичный ключ, и все поля должны функционально полно от него зависеть.
То есть нельзя в таблицу заказов писать характеристики покупателя или товара. Неправильно:
386 | Иванов | Москва, ул.Пушкина, д.Колотушкина 1 | (495) 663-77-22 | Ботинки | Черные
Нужно вынести все сущности по справочникам, а в результ.таблице оставить только внешние ключи:
386 | 145 | 740 --(id заказа | id заказчика | id товара)
3 н.ф. Не должно быть транзитивной зависимости, т.е. поля должны зависеть только от первичного ключа, но не друг от друга.
Например, здесь нарушение третьей формы:
id | name | city | zip
8 | Иванов | Москва | 198328
поскольку почтовый индекс зависит от города, нужно вынести в справочник.
-----------------------------------------------------------------------------
А, я вспомнил, почему отказался от идеи свалить треды и посты в одну таблицу. Потому что плохо представляю себе, как потом идентифицировать тред. То есть как понять, к какому треду относится пост, да и вообще чем обозначить тред? Номером первого поста, который придет из формы создания нового треда?
Кроме того, для треда заголовок и пикча обязательны, а для обычного поста - нет. Можно конечно переложить ответственность на заполнение этих полей в оп-посте на программиста php и js, который должен в своем коде проверять форму создания треда на пустоту, но что-то мне такая идея не нравится.
Поэтому я решил создать две таблицы - треды и посты, где название треда дублировало заголовок его первого поста. Это было сделано не из-за незнания нормализации, а специально для того, чтобы выводить общий список постов, например. Первоначально я вообще хотел хранить оп-пост с его атрибутами в таблице тредов. Но потом понял, что в таком случае мне придется искать новые посты не только в таблице постов, но и в таблице тредов, иначе опу принудительно придется бампать свой тред, иначе не взлетит.
Поэтому решил перенести все атрибуты оп-поста в таблицу постов. Но тогда в таблице тредов оставался только айди и больше ничего! Я такое видел в первый раз, поэтому запутался (как же в него инсертить-то?) и оставил заголовок, лишь бы что-то было, да.
Только что проверил: оказывается можно создавать таблицу только с полем айди.
create table test( id int not null auto_increment primary key );
Тогда автоинкремент произойдет при попытке вставки null:
insert into test values (null);
Итак, какие теперь попробовать варианты структуры базы?
Вариант первый. Свалить все в одну таблицу.
Тогда я затрудняюсь идентифицировать принадлежность поста к треду. Можно добавить спец.колонку, куда php будет записывать номер оп-поста. А если не передано, значит это не пост, а тред, оставляем либо пустым, либо записываем какую-то константу, например 0:
id int unsigned not null auto_increment primary key,
.....
thread int unsigned not null default 0
Второй вариант, это сделать таблицу тредов из одной колонки id. Получится фактически то же самое, что я уже делал.
Третий вариант, создать таблицу специально для хранения последних n постов. Выглядит муторно, много операций в одной транзакции.
Поправь, если я что-то неправильно понял про нормализацию.
1 н.ф. В одном поле для каждой записи только одно значение. Т.е. недопустимо вставлять несколько значений через запятую или пробел.
Например, если в нашем интернет-магазине господин Иванов приобрел ботинки, рубашки и штаны, нельзя писать в таблицу заказов (id, customer, item)
386 | Иванов | Ботинки, рубашки, штаны
Нужно писать
386 | Иванов | Ботинки
387 | Иванов | Рубашка --(теперь даже можно добавить столбец с кол-вом товара)
388 | Иванов | Штаны
2 н.ф. В таблице обязательно должен быть первичный ключ, и все поля должны функционально полно от него зависеть.
То есть нельзя в таблицу заказов писать характеристики покупателя или товара. Неправильно:
386 | Иванов | Москва, ул.Пушкина, д.Колотушкина 1 | (495) 663-77-22 | Ботинки | Черные
Нужно вынести все сущности по справочникам, а в результ.таблице оставить только внешние ключи:
386 | 145 | 740 --(id заказа | id заказчика | id товара)
3 н.ф. Не должно быть транзитивной зависимости, т.е. поля должны зависеть только от первичного ключа, но не друг от друга.
Например, здесь нарушение третьей формы:
id | name | city | zip
8 | Иванов | Москва | 198328
поскольку почтовый индекс зависит от города, нужно вынести в справочник.
-----------------------------------------------------------------------------
А, я вспомнил, почему отказался от идеи свалить треды и посты в одну таблицу. Потому что плохо представляю себе, как потом идентифицировать тред. То есть как понять, к какому треду относится пост, да и вообще чем обозначить тред? Номером первого поста, который придет из формы создания нового треда?
Кроме того, для треда заголовок и пикча обязательны, а для обычного поста - нет. Можно конечно переложить ответственность на заполнение этих полей в оп-посте на программиста php и js, который должен в своем коде проверять форму создания треда на пустоту, но что-то мне такая идея не нравится.
Поэтому я решил создать две таблицы - треды и посты, где название треда дублировало заголовок его первого поста. Это было сделано не из-за незнания нормализации, а специально для того, чтобы выводить общий список постов, например. Первоначально я вообще хотел хранить оп-пост с его атрибутами в таблице тредов. Но потом понял, что в таком случае мне придется искать новые посты не только в таблице постов, но и в таблице тредов, иначе опу принудительно придется бампать свой тред, иначе не взлетит.
Поэтому решил перенести все атрибуты оп-поста в таблицу постов. Но тогда в таблице тредов оставался только айди и больше ничего! Я такое видел в первый раз, поэтому запутался (как же в него инсертить-то?) и оставил заголовок, лишь бы что-то было, да.
Только что проверил: оказывается можно создавать таблицу только с полем айди.
create table test( id int not null auto_increment primary key );
Тогда автоинкремент произойдет при попытке вставки null:
insert into test values (null);
Итак, какие теперь попробовать варианты структуры базы?
Вариант первый. Свалить все в одну таблицу.
Тогда я затрудняюсь идентифицировать принадлежность поста к треду. Можно добавить спец.колонку, куда php будет записывать номер оп-поста. А если не передано, значит это не пост, а тред, оставляем либо пустым, либо записываем какую-то константу, например 0:
id int unsigned not null auto_increment primary key,
.....
thread int unsigned not null default 0
Второй вариант, это сделать таблицу тредов из одной колонки id. Получится фактически то же самое, что я уже делал.
Третий вариант, создать таблицу специально для хранения последних n постов. Выглядит муторно, много операций в одной транзакции.
Насчет нормальных форм, ты можешь особо не заморачиваться с их запоминанием по отдельности, главное чтобы твои данные были хотя бы в третьей форме.
У тебя в общем верно написано. Но только вот это не совсем точно:
> в результ.таблице оставить только внешние ключи
Тут не очень понятно, что именно за таблица «результирующая». Ну и например в ситуации посты-комменты у тебя будет ровно 2 таблицы и не будет отдельной таблицы с ключами.
Насчет 2 НФ, это про случаи когда у нас составной ПК: https://ru.wikipedia.org/wiki/%D0%92%D1%82%D0%BE%D1%80%D0%B0%D1%8F_%D0%BD%D0%BE%D1%80%D0%BC%D0%B0%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D1%84%D0%BE%D1%80%D0%BC%D0%B0
То есть если у тебя в таблице первичный ключ это id товара + имя клиента то да, твой пример правильный так как адрес клиента зависит от его имени но не от id товара.
Главное понимать, что цель нормализации избежать дублирования и смешивания (это про 1 НФ ) данных, чтобы с ними было удобно работать и не могло быть противоречий в таблице.
> Потому что плохо представляю себе, как потом идентифицировать тред.
Либо WHERE thread_id = id либо WHERE thread_id IS NULL. Первый вариант не очень удобен (так как ты не можешь прописать thread_id не зная id поста до вставки) и не может использовать индексы в отличие от второго.
> к какому треду относится пост
По thread_id, только это поле ссылается не на таблицу threads а на ОП-пост в таблице постов. На имиджборде обычно id треда — это id ОП поста.
> Номером первого поста, который придет из формы создания нового треда?
да
> Кроме того, для треда заголовок и пикча обязательны, а для обычного поста - нет. Можно конечно переложить ответственность на заполнение этих полей в оп-посте на программиста php и js, который должен в своем коде проверять форму создания треда на пустоту, но что-то мне такая идея не нравится.
В других базах данных для этого есть хорошая конструкция CHECK которая задает ограничения на вставляемые значения: http://dimonchik.com/sql-check.html
В MySQL это условие игнорируется, так что да, вся надежда на программиста.
Твой подход нарушает одну из нормальных форм (какую? не знаю точно) так как заголовок ОП-поста продублирован.
> Первоначально я вообще хотел хранить оп-пост с его атрибутами в таблице тредов.
Это плохая идея хранить 1 сущность в двух разных таблицах.
> Но тогда в таблице тредов оставался только айди и больше ничего! Я такое видел в первый раз, поэтому запутался (как же в него инсертить-то?)
INSERT INTO t (id) VALUES (NULL)
> Вариант первый. Свалить все в одну таблицу.
По моему хороший вариант.
> thread int unsigned not null default 0
FOREIGN KEY не работает с 0, он воспримет его как id записи, нужен NULL
> Второй вариант, это сделать таблицу тредов из одной колонки id.
не очень понятен ее смысл если список тредов можно получить по условию thread IS NULL
> Третий вариант, создать таблицу специально для хранения последних n постов.
Я написал как один из вариантов оптимизации, можно сделать таблицу связей вида (тред — последние посты). Но сами-то посты зачем по разным таблицам хранить? Исопльзуй внешние ключи.
Насчет нормальных форм, ты можешь особо не заморачиваться с их запоминанием по отдельности, главное чтобы твои данные были хотя бы в третьей форме.
У тебя в общем верно написано. Но только вот это не совсем точно:
> в результ.таблице оставить только внешние ключи
Тут не очень понятно, что именно за таблица «результирующая». Ну и например в ситуации посты-комменты у тебя будет ровно 2 таблицы и не будет отдельной таблицы с ключами.
Насчет 2 НФ, это про случаи когда у нас составной ПК: https://ru.wikipedia.org/wiki/%D0%92%D1%82%D0%BE%D1%80%D0%B0%D1%8F_%D0%BD%D0%BE%D1%80%D0%BC%D0%B0%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D1%84%D0%BE%D1%80%D0%BC%D0%B0
То есть если у тебя в таблице первичный ключ это id товара + имя клиента то да, твой пример правильный так как адрес клиента зависит от его имени но не от id товара.
Главное понимать, что цель нормализации избежать дублирования и смешивания (это про 1 НФ ) данных, чтобы с ними было удобно работать и не могло быть противоречий в таблице.
> Потому что плохо представляю себе, как потом идентифицировать тред.
Либо WHERE thread_id = id либо WHERE thread_id IS NULL. Первый вариант не очень удобен (так как ты не можешь прописать thread_id не зная id поста до вставки) и не может использовать индексы в отличие от второго.
> к какому треду относится пост
По thread_id, только это поле ссылается не на таблицу threads а на ОП-пост в таблице постов. На имиджборде обычно id треда — это id ОП поста.
> Номером первого поста, который придет из формы создания нового треда?
да
> Кроме того, для треда заголовок и пикча обязательны, а для обычного поста - нет. Можно конечно переложить ответственность на заполнение этих полей в оп-посте на программиста php и js, который должен в своем коде проверять форму создания треда на пустоту, но что-то мне такая идея не нравится.
В других базах данных для этого есть хорошая конструкция CHECK которая задает ограничения на вставляемые значения: http://dimonchik.com/sql-check.html
В MySQL это условие игнорируется, так что да, вся надежда на программиста.
Твой подход нарушает одну из нормальных форм (какую? не знаю точно) так как заголовок ОП-поста продублирован.
> Первоначально я вообще хотел хранить оп-пост с его атрибутами в таблице тредов.
Это плохая идея хранить 1 сущность в двух разных таблицах.
> Но тогда в таблице тредов оставался только айди и больше ничего! Я такое видел в первый раз, поэтому запутался (как же в него инсертить-то?)
INSERT INTO t (id) VALUES (NULL)
> Вариант первый. Свалить все в одну таблицу.
По моему хороший вариант.
> thread int unsigned not null default 0
FOREIGN KEY не работает с 0, он воспримет его как id записи, нужен NULL
> Второй вариант, это сделать таблицу тредов из одной колонки id.
не очень понятен ее смысл если список тредов можно получить по условию thread IS NULL
> Третий вариант, создать таблицу специально для хранения последних n постов.
Я написал как один из вариантов оптимизации, можно сделать таблицу связей вида (тред — последние посты). Но сами-то посты зачем по разным таблицам хранить? Исопльзуй внешние ключи.
вот на этом месте всё и стопориться. дальше ничего не происходит сколько не жди.
Все дело в винде.
Анон, напиши какая версия симфони и как ты ее устанавливал, какие дополнительные расширения или библиотеки ставил? В чем ты запускаешь программу, это ведь не стандартная консоль винды?
Я сейчас скачал 2.3 (Standard) и когда я попытался сгенерировать то я наткнулся на ошибку: директория DemoBundle не пуста, так как в составе стандартной сифмони идет этот бандл (у тебя не может быть той же проблемы? глянь-ка в папку src). Тогда я стер директорию, почистил AppKernel и запустил генерацию заново и все сгенерировалось.
Также во время зависания если смотреть диспетчер задач, php потребляет процессорное время или нет?
В общем, нужны подробности.
>Но сами-то посты зачем по разным таблицам хранить? Исопльзуй внешние ключи.
Я это и имел ввиду, ссылки на них, а не сами посты, конечно.
Впрочем, в итоге отказался от этой идеи в пользу внешнего джойна.
Вот тут >>480875
показано решение подобной задачи, когда нужно выбрать не просто N последних записей, а по N записей каждой категории, в моем случае N последних постов каждого треда.
Короче, лучше такого решения ничего не могу придумать. Из очевидных минусов это лишний (с точки зрения конечного результата) столбик, он мне нужен был для промежуточных вычислений. Но я не думаю, что это сильно увеличит трафик, колонка ведь в формате даты, а не блоб или текст.
http://sqlfiddle.com/#!9/9ceff/1
В общем, даже если это не самое оптимальное решение, я себя уже чувствую увереннее с джойнами и группировками, так что можно быть довольным.
Завтра еще подумаю, как со стороны php теперь разгрести эту кучу. Как внутри цикла определить, какая из строк является оп-постом, а какая обычным постом.
Хм, лучше было бы все-таки на стороне sql возвращать результат таким образом, чтобы сначала шел оп-пост, затем все относящиеся к нему каменты, затем снова оп-пост, а потом каменты. Потому что на данный момент мой запрос возвращает все оп-посты, а потом все каменты (тоже неупорядоченно).
Видимо придется лепить еще доп. ORDER и GROUP.
Я слегка удручен. Пойду посплю.
http://ideone.com/fork/BBnXl0
Задание "Айпад в кредит" из раздела функции.
Бесконечный цикл.
У тебя условие выполнять цикл, while($creditSum>0)
Что всегда true.
($creditSum x 1.4) по-твоему увеличит долг на 1.4 процента?
Блять правильно 1.04. Спасибо няша.
Можно сделать несколько баз данных, с разными именами и в каждом будут свои таблицы. Собственно так и делают чтобы несколько проектов запускать, каждый свою базу использует.
На трезвую голову подкорректировал.
Теперь все возвращается в правильном порядке, без лишнего мусора.
http://sqlfiddle.com/#!9/b98e8/4
Где здесь в скрипте выставляется класс active для кнопки люди?
http://factcloud.com/search/?search=%D1%82%D0%B5%D0%BC%D0%B0#index=userIndex&template=user&search=%D1%82%D0%B5%D0%BC%D0%B0
Таки книги не по php.
оказалось у меня тоже дело в этом, потер директорию и создалось(проц жрет очень сильно).но когда пытаюсь запустить по инструкции первый бандл, после перехода по ссылке localhost/web/app_dev.php/name/ivan например, то локальный сервер начинает грузить систему чуть ли не на 100% и ничего не происходит. Хотя я всё делаю по инструкции, хотя бы ошибку выдало что ли. Так и кампуктер сгорит. В чем может быть дело?
(еще сперва не удавалось даже конфиг открыть localhost/web/config.php, но я нагуглил что апачу не хватает каких-то файлов, которые лежат в папке с пхп, ну я их и скопировал, после чего таки конфиг открылся, правда, без изображений, почему-то).
По какой инструкции? Ты уверен что она правильная и актуальная если там даже первый бандл не создается? Кинь-ка ссылку.
И откуда ты симфони брал и как устанавливал? С официального сайта?
Насчет потребления CPU, поставь в настройках php.ini set_time_limit на несколько секунд. Учти что он может быть переопределен в htaccess или в коде (проверь поиском), в этом случае надо менять не в php.ini, а там. При превышении лимита должна вывалиться ошибка и по стектрейсу будет видно на чем именно зависло.
> но я нагуглил что апачу не хватает каких-то файлов, которые лежат в папке с пхп, ну я их и скопировал,
Это не очень хорошо, потому что надо бы разбираться в чем ошибка, а не выполнять странные советы которые могут привести например к другим ошибкам.
http://jsfiddle.net/9L64t9db/ Что-то вроде этого, только элемент должен быть снизу а не сверху. Но снизу его спрятать не получается, ибо браузер увеличивает высоту окна до бесконечности, как далеко вниз ты бы ни прятал элемент.
http://symfony-gu.ru/documentation/ru/html/book/page_creation.html
симфони с оф сайта ставил. и устанавливал как там написано http://symfony.com/doc/current/book/installation.html
Поместить меню в ящик с overflow: hidden маленькой высоты и увеличивать высоту этого ящика. А еще лучше наверно уменьшить высоту самого меню и на него overflow ставить. Зачем на body ставить? Ты так просто выступающие части отрежешь и все.
Это если я тебя правильно понял, что тебе надо именно чтобы кусок меню заранее неизвестной высоты был виден. Если у тебя меню из 2 частей, вроде кнопки и самого меню, то лучше невидимую часть скрыть display: none чтобы она не рендерилась и на это не тратилось время.
Алсо у нас есть хорошие полезные задания по HTML/CSS в оп-посте для тех кто эти языки не очень хорошо знает.
И праивльно делает, так как иначе страницы в которых текст на один экран не помещается, были бы нечитаемы.
Какую версию симфони качал? 2.3 или 2.6?
Кстати, в туториале надо создавать бандл с именем AcmeDemoBundle, а ты пытался создать DemoBundle, может из-за этого и были проблемы вчера. В Симфони название бандла именно так составляется, включая неймспейс.
Нет, не хочешь, так как в этом случае твоя страница не будет прокручиваться. Тебе надо ограничить overflow не на всей странице а только на диве внутри которого засунуто меню. А этот див разумеется прибить к низу экрана.
> Если вы увидите ошибку, то скорее всего вам всего лишь необходимо очистить кэш, выполнив команду:
> php app/console cache:clear --env=prod --no-debug
Сделай еще это, только для того env в котором ты пытаешься открывать страницу.
И еще в русском туториале написано создать HelloBundle, а не DemoBundle (я к тому что ты как-то не совсем по туториалу делаешь). Ну и когда будешь например реальный сайт делать не забудь заменить Acme и DemoBundle на название компании и сайта.
То есть чтобы этот элемент "выезжал" снизу?
Можешь попробовать поместить элемент меню под пустым дивом с фиксированной высотой, оба внутри дива-обертки с оверфлоу хидден, и при наведении курсора на элемент "меню" див выше плавно уменьшает высоту, следом за ним вылезет и эл.меню.
Ну ты понял: див оверфлоу хидден, в нем пустышка с фикс.высотой и твое меню.
Я плохо знаю css, поэтому сделал бы такое джаваскриптом.
делол.((
>>480503
http://ideone.com/dxcMIl
Подскажи, анон
Не понимаю момент как в if если <5000 сделать действие, а потом еще раз проверить <5000 или нет.
У меня получилось нечто подобное:
http://jsfiddle.net/v5epyux5/3/
>>481415
Иф внутри ифа.
if($x < 5000){
$x -= $procent;
if($x < 5000){ break;}
}
>>481421
нет
Ну так по хтмлбук и читаю, а там фреймы. И так как сейчас есть ajax, я подумал, что фреймы как бы не нужны.
Не пойму почему тут переменной vid присваивается элемент с айди "myVideo" но в функции используется просто айди элемента myVideo?
мимо нуб в жсе, не шарящий в DOM
https://ideone.com/W2zC1P
Заранее спасибо, ОП.
чистый симфони, только установлен. стоит последний openserver.
Класс Collator предоставляется расширением intl, но когда его нет, Симфони предоставляет его аналог, правда, поддерживающий только английский язык. А у тебя используется французский. Соответственно либо переключи его на английский либо что лучше, установи расширение intl.
archive-ipq-co.narod.ru/l1/mou-ikkai.html
почему это происходит с чистой установкой симфони?? почему я не могу блять просто прочесть мануал и выполнить всё пошагово, как там написано, а должен решать эту хуйню с какими-то расширениями, которые я не должен устанавливать, а я, блять, просто впервые пытаюсь запустить эту ебалу.
Прости анон, сорвался. нет сил уже с этой ебучей симфонией.
Я ставил английский язык в конфиге, выдает ту же ошибку, только вместо fr_FR en_En:(
Это задача о ранце: http://neerc.ifmo.ru/wiki/index.php?title=%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%B0_%D0%BE_%D1%80%D1%8E%D0%BA%D0%B7%D0%B0%D0%BA%D0%B5#.D0.97.D0.B0.D0.B4.D0.B0.D1.87.D0.B0_.D0.BE_.D1.80.D0.B0.D0.B7.D0.BC.D0.B5.D0.BD.D0.B5
Простой но неэффективный метод - перебрать все возможные сочетания банкнот пока не найдется нужное. сложный но более бстрый метод описан в вики и тут http://informatics.mccme.ru/mod/book/view.php?id=815
>установил говносборку
>жалуется на конфигурацию сервера
Симфони нужно ставить только на денвер.
чето мне денвер не очень.
так это не в сервере ведь дело, нормально же всё работает. пишу целые социальные сети на этом опенсервере и никаких проблем. а это говно почему так ведет себя..
Спс и добра тебе
А в чем проблема? По моему сообщение об ошибке написано максимально понятным английским языком, плюс ты всегда можешь открыть документацию или исходники и посмотреть код, или воспользоваться отладчиком.
Это фреймворк для программистов.
Ну и напомню что у Сифмони открытый код. Если ты считаешь, что что-то в нем можно улучшить, ты просто можешь сделать это исправление и отправить пулл-реквест авторам симфони (еще ты можешь отправить баг-репорт, но это менее полезно, так как у авторов симфони ограниченные ресурсы чтобы тратить их на минорные баги). Я могу подсказать как это делать, если надо, и что надо прочесть. Нужно умение пользоваться гитом, разумеется.
Алсо там написано en, а не EN_en. Ну и лучше бы просто (хе-хе. на самом деле конечно это может оказаться не совсем просто) установить intl.
какой баг репорт если я даже в глаза не видел работу этого фреймворка, а только пытаюсь его запустить? какой исходный код? сейчас это для меня напоминает заклинания. я всего лишь хочу прочесть мануал, опробовать примеры у себя на локальном сервере, начать понемногу понимать какой метод за что отвечает..
пойду пробовать установить этот чудес
Алсо, залил на хостинг. Вроде норм работает, но нужно кнопку допилить, а то если на нее слишком быстро тыкать, то звук от предыдущих вебмок продолжает играть. Думаю можно это починить сделав так, чтобы кнопка после нажатия на секунду деактивировалась. Но я если честно не знаю как это сделать, т.к. в JS полный ноль.
http://randomwebm.esy.es/
Можете вебмки подобавлять, буду очень признателен.
Вот такое вернет фатальную ошибку http://pastebin.com/zqHFsfbf
Оно и понятно, я пытаюсь вызвать метод to_lower_case у строки, строки-и-и блять, ты ебанутый?!. Надо значит сделать так, чтобы возвращался объект. А как?
Кэшировать может жадный провайдер.
В том, что PHP - не язык программирования, а шаблонизатор HTML формочек?
перестань фапать
Ага, на диванную работу
Удваиваю этого тормоза.
Устройся на быдло-работу в офис, например. Ездить в вонючем общественном транспорте с наглым быдлом. Выслушивать сплетни офисного планктона и их мудрые суждения о политике. Дружный коллектив офисных хомяков, их сначала подозрительное, затем агрессивное отношение к твоему нелюдимому характеру.
С утра до вечера звоночки, тупые клиенты, тупая бумажная работа без надежды на что-то хорошее.
Ты очень быстро охуеешь от ужаса прожить так всю жизнь, уволишься и с остервенением примешься за учебу.
Серьезно, попробуй, больше не захочешь.
Я имел в виду на работу кодером.
А насколько много там общения с людьми?
Да я еще и не настолько много знаю чтобы куда то устраиваться, да особо и некуда в моем городе.(реально некуда)
У программистов естественно никакого общения с людьми.
Ну может кроме говноконтор, которые ищут заказы на фриланс биржах.
Там часто приходится по скайпику долго выяснять у глубокоуважаемых клиентов, что же они имеют ввиду под "надо сделать сайт", вызывая у оных раздражение: "ну ты ж программист, ты должен знать. ну сайт такой, красивый, чтобы вот тута была реклама, тут короче текст, а там такая хуйня с кнопками. ты программист или нет? за шо я деньги плачу, епты".
Думаю прилично. Хотя конечно погромисты в целом меньше пиздят, чем какие-нибудь менеджеры.
А насчет того, как заставить себя что-то делать, то хуй знает. Видать тебя в принципе все устраивает в твоей жизни, раз тебе так лень что-то делать. Ну или скорее недостаточно сильно неустраивает.
ОП профессиональный препод судя по всему, несколько быдло-кодеров, остальные полные нубы.
>У программистов естественно никакого общения с людьми.
Булшит. Общения меньше чем в остальных сферах, но коммуникация между программистами должна быть эффективной – поехавшие аутисты и мамкины социофобы никому не нужны, какие бы талантливые они не были. Разве что на каких-то совсем джуниор позициях, где все просто и понятно и от тебя ничего не зависит.
Я вот заканчиваю вуз на инженер-программиста и понял, что ничего не знаю (как ничего, все и понемногу). Душа лежит к сайтам, изучаю php потихоньку, смотрю в ДС-2 даже пару вакансий есть без опыта (раньше фигней всякой занимался, варезники делал, в вордпрессе разбирался, интересно было). Буду стремиться через полгода к этому. (к работе начинающим, а не к варезникам)
>>481737
Вот, к примеру, я только устроился. Вообще чувак говорил, что им нужен парень, который знает тонкости языка на уровне интерпретатора.
В основном e-commerce аутсорс, выхожу в начале месяця. Первый месяц буду делать учится, а дальше уже начнутся реальные вещи.
Совет нубам: почитайте про mysql серьезно, про движки(innoDB, myisam и т.п.).
Неделю где-то я писал по чуть-чуть ибо еще учеба по пол дня и вот сегодня я сел и писал код около 4х часов! Я устал, у меня болит шея, глаза. Это короче ад какой-то.
Я тут подумал, а нужно ли мне вообще это - становиться программистом?
Ну ладно, вот короче код: http://ideone.com/XEsVtM
Там еще небольшой косячек с пробелами, но я уже не могу править, настолько я устал. Проверь, ОП, пожалуйста.
почему не PostgreSQL?
Все профи говном поливают MySQL, как СУБД не предназначенная для работы с финансовыми операциями, а постгрес чтут.
>умение быстро разбираться в чужом коде;
Во всех почти вакансиях вижу. Как можно развить это умение и как это проверяют на собеседовании?
Не вводи Junior, вводи просто PHP, а еще лучше вообще web.
На гитхабе найди любой проект и попробуй разобраться как он работает. что делает каждая функция и т.д.
Всегда хуею с мухосранских вакансий в IT сфере. Денег нет нихуя, поэтому ищут человека-оркестра, который должен знать все и при этом за еду работать. И ведь находят же, что самое странное.
Заранее спасибо!
Имеется ввиду умение читать говнокод.
Скорее всего эта контора занимается "поддержкой" чужих проектов.
То есть нужно будет модернизировать старые сайты, написанные неумелыми программистами.
Научиться этому можно здесь в треде, где же еще.
Смотри код, который нубы выкладывают в этот тред.
Там же по заданию margin-right у желтого блока должен быть не меньше 10px в сжатом состоянии.
я не оп.
Всё адекватно.
Кто может - тот не хочет, а кто хочет - рад бы, но не может.
>Говно-проектов на PHP и так хватает уже.
А почему тогда так много вакансий именно на ПХП?
И вообще объясните пожалуйста, чем отличается PHP-программист от какого-нибудь Бэк-эндера или фул-стак разработчика можно ли попасть на знанием только PHP и какого-нибудь фреймворка?
>можно ли попасть на знанием
>можно ли попасть на работу со знанием
Что за клавиатура у ноута, вообще адъ какой-то.
Нет там никакого оркестра, стандартный стек веб-разработчика за неплохую для мухосранска зарплату.
>>480962
Анон, извини за задержку, как-то все руки не доходили проверить твое задание, проверяю сейчас. Если я долго не отвечаю, то не трать время, решай какие-то другие задачи или дописывай код, не жди меня.
У меня тут возникла такая мысль. Давай попробуем сделать сначала только часть задания, но зато сделаем ее идеально. Давай ты сначала сделаешь только просмотр и поиск студентов, без регистрации и редактирования (все что к ним относится пока нужно убрать в отдельную папку), исправишь все замечания, а потом добавишь регистрацию/редактирование. Так мне придется проверять меньше кода, а для тебя будет меньше исправлять. Хорошо?
Ну а те замечания, что я тут написал, сохрани в какой-нибудь файлик, чтобы не забыть про них. Когда ты вернешь назад регистрацию, тогда и исправишь.
Ну и еще, постарайся больше не создавать репозиториев. Если тебе надо переносить файлы, ты можешь скопировать/переместить их в другую папку для этого. Если у тебя какие-то сложности с гитом и что-то не работает, напиши подробно, что именно.
Далее замечания и советы.
--
При поиске хорошо бы выводить ссылку, которая отменяет поиск, примерно так:
> Список студентов подходящих под параметры: rrr. __Показать всех__
Если результат поиска пустой, то не стоит выводить таблицу, а стоит написать «Не найдено ни одного студента». Если есть всего одна страница результатов, то не надо выводить пагинацию. Если мы на первой странице, то ссыка «предыдущая страница» должна не показываться или быть неактивной, аналогично для последней страницы.
--
Непонятно, зачем нужен этот класс: https://github.com/Si0n/register3/blob/master/lib/Ini.php и какое отношение к инициализации имеет функция printPage. Я думаю, всю инициализацию (то что в loadLibs(), PDO.php, classloader.php) надо собрать в единственный файл без классов.
--
Функция autoload ( https://github.com/Si0n/register3/blob/master/lib/classLoader.php ) это плохой способ для автозагрузки так как нельзя создать больше одной такой функции и например сторонняя библиотека не может добавить свой автозагрузчик. Потому мануал советую использовать вместо нее spl_autoload_register: http://php.net/manual/ru/function.spl-autoload-register.php
Вот статья на хабре про это http://habrahabr.ru/post/136761/
--
То, что бросается в глаза, это то, что у нас в lib лежат файлы разных типов. С одной стороны там есть файлы с классами, с другой — файлы-скрипты, которые вызываются для обработки каких-то ситуаций (вроде такого https://github.com/Si0n/register3/blob/master/lib/check.php ). Плохо когда они файлы разного типа свалены все вместе в одну папку, я думаю, скрипты надо поместить например в папку scripts (или ты можешь назвать из controllers, так как они похожи на контроллеры).
Ну и по моему было бы проще файлы-контроллеры вынести на верхний уровень и вызывать напрямую из браузера, тогда файл index.php и switch в нем были бы не нужны. Мне кажется, так было бы проще, но если тебе хочется использовать один файл index.php как сейчас, то я не против, это тоже нормальный вариант.
Далее, надо переделать работу с формой регистрации. Я против того способа хранения ошибок в базе, что ты придумал. Он чрезмерно усложнен, так как ошибки можно отображать без использования базы данных, раз так, зачем ее использовать? Я думаю, работу с формой надо сделать общепринятым методом, как описано в моем уроке ( https://github.com/codedokode/pasta/blob/master/forms.md ) — ты его читал?
Вот еще недостатки подхода с базой:
— не сохраняются введенные значения, при ошибке форма очищается и надо все вводить заново
— куки общие для всех вкладок, значит твой подход нельзя будет использовать для тех форм, которые могут открыть в нескольких вкладках
Думаю, надо переделать ее на обычную работу с формами без хранения ошибок в базе. При ошибке надо не делать редирект, а надо сразу отображать форму (почитай мой урок).
--
Далее, смотри как выглядит страница твоей регистрации, если просто ее открыть: http://i.imgur.com/9OSsV6f.png
Включено ли у тебя отображение ошибок? Если нет, то смотришь ли ты логи? Ты по моему просто не включил вывод ошибок и потому их не замечаешь, а это плохо, как ты видишь.
В PHP по умолчанию выключено отображение ошибок в браузере, так как обычному пользователю сайта эта информация ни к чему. Но тебе, как программисту, надо видеть эти ошибки. Вот, как можно их просмотреть:
- ошибки сохраняются в лог ошибок. Можно открыть его и почитать. Если ты запускаешь код на локалхосте, у себя, то лог хранится в папке Апача (обычно она называется logs) и имеет название вроде error.log (в линуксе в папку /var/log/apache2 ). Если на хостинге — там либо есть файл error.log либо раздел в панели управления, где лог можно посмотреть
- также, ты можешь включить отображение ошибок. Открой файл php.ini, поставь там display_errors = On и error_reporting = E_ALL и перезапусти сервер. Теперь ошибки должны выводиться на экран.
Проверить, работает ли вывод ошибок, можно запустив скрипт содержающий обращение к несуществующей переменной вроде echo $sdgasdad; и проверив, выведется ошибка или нет. Если все верно, то должна вывестись.
--
В прошлый раз мы договаривались, что скрипты, которые вызываются из браузера, будут лежать в корневой папке. Но вот тут вот идет обращение к скрипту в папке lib:
> https://github.com/Si0n/register3/blob/master/template/edit.php#L1
> <form id="register" method="post" action="./lib/reg.php">
Это надо исправить.
--
Далее, шаблон не должен вызывать скрипты-контроллеры с логикой. Шаблон должен только выводить те данные, что ему передали, и он не должен подключать какие-то обработчики:
> https://github.com/Si0n/register3/blob/master/template/register.php#L2
> include('./lib/form_inspect.php');
Вот такого быть не должно. Тут надо переделать, что сначала запускается скрипт-обработчик, а потом из него подключаешь шаблон. Не наоборот.
--
> https://github.com/Si0n/register3/blob/master/index.php#L2
> include './template/header.php';
Это неправильно. Это например помешает выставлять куки или делать редирект так как после вывода HTML уже нельзя отправлять заголовки. Шапку надо подключать из шаблона, а не из index.php.
--
Также, в HTML у тебя бардак. Попробуй открыть исходный код главной страницы в браузере (Ctrl + U). Смотри, что там выводится в конце:
> <body>
Во-первых тут должен стоять закрывающий тег, во-вторых, где закрывающий тег html? Надо это исправить.
--
Там у меня робот нашел отличия в bootstrap.css, ты его не правил? Если правил то замени файлы на исходные, а свои изменения помести в отдельный файл, например с названием student.css и положи его отдельно от бутстрапа.
Вот что пишет робот:
Изменять файлы из стронних библиотек плохая идея по двум причинам. Во-первых, человек, разбирающийся в твоем коде, вряд ли сможет найти твои правки в куче кода. Он будет наивно думать что библиотека не изменена. Во-вторых, когда библиотеку захотят обновить, либо потеряются твои правки, либо эти правки придется переносить как-то вручную. Представь себе какой это объем труда. К тому же эти изменения могут еще и оказаться несовместимыми с новой версией библиотеки.
Никогда не меняй файлы внешних библиотек.
Или же ты просто используешь неофициальную или нестандартную сборку? Лучше использовать официальную.
Вот список изменений (в формате https://ru.wikipedia.org/wiki/Diff ):
> @@ -2916,7 +2916,7 @@
> .form-inline .input-group .input-group-addon,
> .form-inline .input-group .input-group-btn,
> .form-inline .input-group .form-control {
> - width: auto;
> + width: 100%;
> }
(там всего 1 строчка изменена, не знаю, может это просто сборка какая-то левая?)
--
Еще, сразу бросается в глаза древняя jquery 1.3, там уже давно 1.13 вышла. Неплохо бы обновиться.
--
Задал ли ты кодировку соединения с базой при работе через PDO? Это можно сделать либо параметром charset= при соединении либо командой SET NAMES в PDO::MYSQL_ATTR_INIT_COMMAND. Мануал: http://php.net/manual/ru/ref.pdo-mysql.connection.php
--
Похоже что ты не использовал тип YEAR для хранения года рождения, а ведь такой тип специально для этого придуман. Если ты про него не знал, то почитай про то какие типы есть в MySQL:
http://phpclub.ru/mysql/doc/column-types.html
--
В общем, что скажешь насчет идеи сделать и отполировать только вывод и поиск студентов? Если что-то непонятно, или какие-то вопросы, задавай. Например, если у тебя есть вопросы по тому как лучше сделать регистрацию или что-то еще.
>>480962
Анон, извини за задержку, как-то все руки не доходили проверить твое задание, проверяю сейчас. Если я долго не отвечаю, то не трать время, решай какие-то другие задачи или дописывай код, не жди меня.
У меня тут возникла такая мысль. Давай попробуем сделать сначала только часть задания, но зато сделаем ее идеально. Давай ты сначала сделаешь только просмотр и поиск студентов, без регистрации и редактирования (все что к ним относится пока нужно убрать в отдельную папку), исправишь все замечания, а потом добавишь регистрацию/редактирование. Так мне придется проверять меньше кода, а для тебя будет меньше исправлять. Хорошо?
Ну а те замечания, что я тут написал, сохрани в какой-нибудь файлик, чтобы не забыть про них. Когда ты вернешь назад регистрацию, тогда и исправишь.
Ну и еще, постарайся больше не создавать репозиториев. Если тебе надо переносить файлы, ты можешь скопировать/переместить их в другую папку для этого. Если у тебя какие-то сложности с гитом и что-то не работает, напиши подробно, что именно.
Далее замечания и советы.
--
При поиске хорошо бы выводить ссылку, которая отменяет поиск, примерно так:
> Список студентов подходящих под параметры: rrr. __Показать всех__
Если результат поиска пустой, то не стоит выводить таблицу, а стоит написать «Не найдено ни одного студента». Если есть всего одна страница результатов, то не надо выводить пагинацию. Если мы на первой странице, то ссыка «предыдущая страница» должна не показываться или быть неактивной, аналогично для последней страницы.
--
Непонятно, зачем нужен этот класс: https://github.com/Si0n/register3/blob/master/lib/Ini.php и какое отношение к инициализации имеет функция printPage. Я думаю, всю инициализацию (то что в loadLibs(), PDO.php, classloader.php) надо собрать в единственный файл без классов.
--
Функция autoload ( https://github.com/Si0n/register3/blob/master/lib/classLoader.php ) это плохой способ для автозагрузки так как нельзя создать больше одной такой функции и например сторонняя библиотека не может добавить свой автозагрузчик. Потому мануал советую использовать вместо нее spl_autoload_register: http://php.net/manual/ru/function.spl-autoload-register.php
Вот статья на хабре про это http://habrahabr.ru/post/136761/
--
То, что бросается в глаза, это то, что у нас в lib лежат файлы разных типов. С одной стороны там есть файлы с классами, с другой — файлы-скрипты, которые вызываются для обработки каких-то ситуаций (вроде такого https://github.com/Si0n/register3/blob/master/lib/check.php ). Плохо когда они файлы разного типа свалены все вместе в одну папку, я думаю, скрипты надо поместить например в папку scripts (или ты можешь назвать из controllers, так как они похожи на контроллеры).
Ну и по моему было бы проще файлы-контроллеры вынести на верхний уровень и вызывать напрямую из браузера, тогда файл index.php и switch в нем были бы не нужны. Мне кажется, так было бы проще, но если тебе хочется использовать один файл index.php как сейчас, то я не против, это тоже нормальный вариант.
Далее, надо переделать работу с формой регистрации. Я против того способа хранения ошибок в базе, что ты придумал. Он чрезмерно усложнен, так как ошибки можно отображать без использования базы данных, раз так, зачем ее использовать? Я думаю, работу с формой надо сделать общепринятым методом, как описано в моем уроке ( https://github.com/codedokode/pasta/blob/master/forms.md ) — ты его читал?
Вот еще недостатки подхода с базой:
— не сохраняются введенные значения, при ошибке форма очищается и надо все вводить заново
— куки общие для всех вкладок, значит твой подход нельзя будет использовать для тех форм, которые могут открыть в нескольких вкладках
Думаю, надо переделать ее на обычную работу с формами без хранения ошибок в базе. При ошибке надо не делать редирект, а надо сразу отображать форму (почитай мой урок).
--
Далее, смотри как выглядит страница твоей регистрации, если просто ее открыть: http://i.imgur.com/9OSsV6f.png
Включено ли у тебя отображение ошибок? Если нет, то смотришь ли ты логи? Ты по моему просто не включил вывод ошибок и потому их не замечаешь, а это плохо, как ты видишь.
В PHP по умолчанию выключено отображение ошибок в браузере, так как обычному пользователю сайта эта информация ни к чему. Но тебе, как программисту, надо видеть эти ошибки. Вот, как можно их просмотреть:
- ошибки сохраняются в лог ошибок. Можно открыть его и почитать. Если ты запускаешь код на локалхосте, у себя, то лог хранится в папке Апача (обычно она называется logs) и имеет название вроде error.log (в линуксе в папку /var/log/apache2 ). Если на хостинге — там либо есть файл error.log либо раздел в панели управления, где лог можно посмотреть
- также, ты можешь включить отображение ошибок. Открой файл php.ini, поставь там display_errors = On и error_reporting = E_ALL и перезапусти сервер. Теперь ошибки должны выводиться на экран.
Проверить, работает ли вывод ошибок, можно запустив скрипт содержающий обращение к несуществующей переменной вроде echo $sdgasdad; и проверив, выведется ошибка или нет. Если все верно, то должна вывестись.
--
В прошлый раз мы договаривались, что скрипты, которые вызываются из браузера, будут лежать в корневой папке. Но вот тут вот идет обращение к скрипту в папке lib:
> https://github.com/Si0n/register3/blob/master/template/edit.php#L1
> <form id="register" method="post" action="./lib/reg.php">
Это надо исправить.
--
Далее, шаблон не должен вызывать скрипты-контроллеры с логикой. Шаблон должен только выводить те данные, что ему передали, и он не должен подключать какие-то обработчики:
> https://github.com/Si0n/register3/blob/master/template/register.php#L2
> include('./lib/form_inspect.php');
Вот такого быть не должно. Тут надо переделать, что сначала запускается скрипт-обработчик, а потом из него подключаешь шаблон. Не наоборот.
--
> https://github.com/Si0n/register3/blob/master/index.php#L2
> include './template/header.php';
Это неправильно. Это например помешает выставлять куки или делать редирект так как после вывода HTML уже нельзя отправлять заголовки. Шапку надо подключать из шаблона, а не из index.php.
--
Также, в HTML у тебя бардак. Попробуй открыть исходный код главной страницы в браузере (Ctrl + U). Смотри, что там выводится в конце:
> <body>
Во-первых тут должен стоять закрывающий тег, во-вторых, где закрывающий тег html? Надо это исправить.
--
Там у меня робот нашел отличия в bootstrap.css, ты его не правил? Если правил то замени файлы на исходные, а свои изменения помести в отдельный файл, например с названием student.css и положи его отдельно от бутстрапа.
Вот что пишет робот:
Изменять файлы из стронних библиотек плохая идея по двум причинам. Во-первых, человек, разбирающийся в твоем коде, вряд ли сможет найти твои правки в куче кода. Он будет наивно думать что библиотека не изменена. Во-вторых, когда библиотеку захотят обновить, либо потеряются твои правки, либо эти правки придется переносить как-то вручную. Представь себе какой это объем труда. К тому же эти изменения могут еще и оказаться несовместимыми с новой версией библиотеки.
Никогда не меняй файлы внешних библиотек.
Или же ты просто используешь неофициальную или нестандартную сборку? Лучше использовать официальную.
Вот список изменений (в формате https://ru.wikipedia.org/wiki/Diff ):
> @@ -2916,7 +2916,7 @@
> .form-inline .input-group .input-group-addon,
> .form-inline .input-group .input-group-btn,
> .form-inline .input-group .form-control {
> - width: auto;
> + width: 100%;
> }
(там всего 1 строчка изменена, не знаю, может это просто сборка какая-то левая?)
--
Еще, сразу бросается в глаза древняя jquery 1.3, там уже давно 1.13 вышла. Неплохо бы обновиться.
--
Задал ли ты кодировку соединения с базой при работе через PDO? Это можно сделать либо параметром charset= при соединении либо командой SET NAMES в PDO::MYSQL_ATTR_INIT_COMMAND. Мануал: http://php.net/manual/ru/ref.pdo-mysql.connection.php
--
Похоже что ты не использовал тип YEAR для хранения года рождения, а ведь такой тип специально для этого придуман. Если ты про него не знал, то почитай про то какие типы есть в MySQL:
http://phpclub.ru/mysql/doc/column-types.html
--
В общем, что скажешь насчет идеи сделать и отполировать только вывод и поиск студентов? Если что-то непонятно, или какие-то вопросы, задавай. Например, если у тебя есть вопросы по тому как лучше сделать регистрацию или что-то еще.
>>480962
Кажется, ты не используешь строгий режим в MySQL. Зря. MySQL более тщательно проверяет твои запросы и вместо предупреждений (которые ты не увидишь) выдает ошибки при попытке вставить неправильные данные. Ну к примеру, если у тебя есть колонка типа varchar(200) и ты попытаешься вставить в нее строку из 300 символов, в нестрогом режиме MySQL молча отрежет лишнее (и в базе окажется обрезанная строка), а в строгом выдаст ошибку.
Использование строгого режима экономит твое время на исправление неправильно вставленных данных. Статья на хабре: http://habrahabr.ru/post/116922/
Включить строгий режим можно сделав при соединении с БД запрос SET sql_mode='STRICT_ALL_TABLES'. В PDO это удобно сделать опцией PDO::MYSQL_ATTR_INIT_COMMAND при создании объекта PDO.
В говноконторах как раз не налажено никакой коммуникации.
http://sqlfiddle.com/#!9/5b49e/2
Там какой-то подвох при использовании with rollup вместе с order by, но я сегодня уже не в состоянии разобраться.
Но наш тред учит именно хороших, добросовестных, разносторонних разработчиков. Конечно есть те кто хотят побыстрее выучиться, но в основном аноны стараются развиваться во всех направлениях, а не изучать допустим только PHP. Подумай сам, с кем ты хочешь работать, с неучами или с трудолюбивыми анонами из треда?
>>481751
Ну общение-то там только изредка чтобы уточнить зачем тут так сделано или что-то пояснить, но конечно совсем аутистом быть не стоит, да.
>>481765
С многопоточностью все печально, да, но с ней и в других популярных языках кроме Явы и C# тоже все плохо.
А с юникодом что не так? Все utf-8 используют, все работает.
>>481766
А не хочешь наши задачки и задания поделать (в Оп посте)? При должном упорстве мы тебя до нормального конкурентноспособного джуна дотянем.
>>481810
Чем именно не предназначена? Я наборот больше с MySQL сталкивался, она вроде работает быстрее и проще, а Postgres как я понимаю больше на число фич напирает, JSON там, массивы и прочие навороты. Ну и пиарят его как-то нездорово, я много раз видел (без всякой аргументации) мнения вроде «Postgres лучше MySQL». Чем лучше, никто не объясняет конечно.
>>481802
Посмотри внизу под программой ошибки:
> PHP Notice: Undefined variable: word in /home/i9EZvl/prog.php on line 103
Ты используешь несуществующую еще на тот момент переменную. Надо сначала ей что-нибудь присвоить.
> PHP Warning: Missing argument 2 for smallNumberToText(), called in /home/i9EZvl/prog.php on line 53 and defined in /home/i9EZvl/prog.php on line 61
Функция требует 2 аргумента, а ты передал один. Номера строк указаны.
Но наш тред учит именно хороших, добросовестных, разносторонних разработчиков. Конечно есть те кто хотят побыстрее выучиться, но в основном аноны стараются развиваться во всех направлениях, а не изучать допустим только PHP. Подумай сам, с кем ты хочешь работать, с неучами или с трудолюбивыми анонами из треда?
>>481751
Ну общение-то там только изредка чтобы уточнить зачем тут так сделано или что-то пояснить, но конечно совсем аутистом быть не стоит, да.
>>481765
С многопоточностью все печально, да, но с ней и в других популярных языках кроме Явы и C# тоже все плохо.
А с юникодом что не так? Все utf-8 используют, все работает.
>>481766
А не хочешь наши задачки и задания поделать (в Оп посте)? При должном упорстве мы тебя до нормального конкурентноспособного джуна дотянем.
>>481810
Чем именно не предназначена? Я наборот больше с MySQL сталкивался, она вроде работает быстрее и проще, а Postgres как я понимаю больше на число фич напирает, JSON там, массивы и прочие навороты. Ну и пиарят его как-то нездорово, я много раз видел (без всякой аргументации) мнения вроде «Postgres лучше MySQL». Чем лучше, никто не объясняет конечно.
>>481802
Посмотри внизу под программой ошибки:
> PHP Notice: Undefined variable: word in /home/i9EZvl/prog.php on line 103
Ты используешь несуществующую еще на тот момент переменную. Надо сначала ей что-нибудь присвоить.
> PHP Warning: Missing argument 2 for smallNumberToText(), called in /home/i9EZvl/prog.php on line 53 and defined in /home/i9EZvl/prog.php on line 61
Функция требует 2 аргумента, а ты передал один. Номера строк указаны.
Благодарю
>Это было очень тяжело
>до этого не кодил
Это норма. К тому же учти, что в оп-посте собраны задачи чуть ли не олимпиадного уровня, над ними можно ломать голову не одни сутки.
Зато очень помогает развивать мышление.
>нужно ли мне вообще это
Решать тебе. Лично я остаюсь в надежде, что мозгоебля будет только на этапе обучения. Как в пословицах, типа про горький корень знаний, и быдло-версия афоризма Ницше о катарсисе (нас ебут, а мы крепчаем).
>Лично я остаюсь в надежде, что мозгоебля будет только на этапе обучения
Вот только этап обучения никогда не закончится. Хотя с каждым годом обучаться все проще.
\t\t<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
video {margin: 5px; }
</style><body><table>";
$i = 0;
$k = 4; //По сколько штук в строке
$dir = './Webm';
$files = scandir($dir, 1);
sort($files, SORT_LOCALE_STRING); // сортируем массив
foreach ($files as $value) {
if ("webm" == substr($value, -4, 4)) {
echo '<td><video preload="metadata" width="320" height="240" controls><source src="/WebM/' . $value . '" type="video/mp4"></video>' . $value . '</td>';
$i++;
}
if ($i % $k == 0) {
echo "</tr>";
$i = 0;
}
}
?>
Блять, верняя часть пропала:
<?php
mb_internal_encoding("UTF-8");
ini_set('default_charset', 'utf-8');
echo mb_internal_encoding();
echo "
<style type=\"text/css\">
Рекомендуется использовать DataMapper вот из этого урока, но альтернативные варианты возможны: https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md
Главное чтобы запросы были собраны в отдельном классе, а не размазаны по приложению.
Апдейт задания про бд кинотеатра.
http://sqlfiddle.com/#!9/5b49e/3
>запрос, выводящий ошибки в расписании (фильмы накладываются друг на друга), отсортированные по возрастанию времени.
По какому времени? По началу первого фильма или по времени наложения?
Не понял, как требуется отсортировать.
Дальше, в третьей части нужно отсортировать по сумме с выводом подытогов.
Тут некая западлянка, потому что ERROR 1221 (HY000): Incorrect usage of CUBE/ROLLUP and ORDER BY
Людишки со стэковерфлоу http://stackoverflow.com/questions/1768547/sort-the-rollup-in-group-by
говорят, что достаточно обернуть запрос во временную таблицу,
SELECT * FROM (наш запрос с группировкой и роллапом) tmp ORDER BY 'колонка',
но у меня почему-то это не решает проблему. Вернее, ошибка уходит, но и сортировки нет.
Еще не знаю, как избавиться от NULL в строке подытогов.
Можно было бы использовать IFNULL(column, 'Итого'), если бы у меня была реальная колонка. Но у меня колонка "период" генерируется налету при помощи CASE ... WHEN. Я пробовал запихнуть эту огромную конструкцию в IFNULL, но что-то бестолку, все равно выбивает NULL.
> WHEN IF(HOUR(s.date) BETWEEN 18 AND 20, HOUR(s.date), 24) THEN 'с 18:00 до 21:00'
Не очень понимаю, что за странный синтаксис? Что за 24? Ты можешь написать так:
CASE WHEN HOUR(s.date) BETWEEN 18 AND 20 THEN ...
https://dev.mysql.com/doc/refman/5.0/en/control-flow-functions.html#operator_case
> По началу первого фильма или по времени наложения?
Я думаю, имеется в виду по времени наложения, но можно и по началу фильма.
> ORDER BY 'Сборы'
Лучше использовать англоязыные алиасы. По идее результаты запроса все равно идут куда-то в код который их выводит.
> IF(SUM(s.price) IS NULL, 0, SUM(s.price))
> IF( TRUNCATE(COUNT(t.id) / COUNT(DISTINCT s.id), 2) IS NULL
Есть IFNULL для этого
В 4-м запросе по моему ROLLUP не требуется.
А так, у тебя неплохо получается.
> Вернее, ошибка уходит, но и сортировки нет.
> ORDER BY 'Сборы'
Потому что ты сортируешь не по колонке с именем, а по строковой константе, одинаковой для всех рядов.
Имена колонок берутся в косые кавычки, а в прямых пишутся строковые литералы (константы).
> Еще не знаю, как избавиться от NULL в строке подытогов.
Потому что группировка вставляет этот null не обращаясь к CASE. Ты можешь перехватить этот NULL во внешнем запросе, а не во внутреннем.
Еще, я тебе хотел посоветовать после этих задач браться за индексы ( https://gist.github.com/codedokode/10539213#%D0%98%D0%BD%D0%B4%D0%B5%D0%BA%D1%81%D1%8B ). Браться нужно на практике, сделав таблицу из миллиона строк и пробуя на ней всякие запросы с индексами и без. Знание индексов и EXPLAIN нужно чтобы ты мог сказать «я умею оптимизировать запросы и проектировать базы данных».
Легко освоить, нет строгой формализации, после изучения ПХП будешь всю жизнь быдлокодить за еду, не в силах освоить нормальные ЯП.
Разговаривал недавно со знакомым, который выпускается с кафедры ИТ, говорит что с ПХП лучше не начинать, лучше взять сначал аболее сложный язык, типа C++ ну или Java на худой конец.
Хуйню написал
>>481862
>Посмотри внизу под программой ошибки:
Простите пожалуйста, всегда забываю смотреть внизу на ошибки! Вот, исправил все:
http://ideone.com/rnp5Wo
Оно записывается в базу, но только пустое
Не ведись на толстоту.
Покажи код.
role и avatar
Например роли у меня могут быть 1, 2 и 3. И мне нужно что бы по дефолту в поле аватар прописывались значения в зависимости от роли 1.png, 2.png или 3.png
Подскажите как это реализуется?
А не проще ли на выводе все это делать? Т.е. в php скрипте в зависимости от роли выводить определенный аватар.
Бамп вопросу
Ну у меня сейчас так и сделано.
В коде у меня просто уже 3 вот таких дублирующихся условия
http://ideone.com/
И потенциально будет еще больше.
https://www.youtube.com/watch?v=l7E6bY2FBYA
Но ошибка всё та же.
Может это дело в моем сервере все таки?
Подскажите, пожалуйста.
Ещё удивило, что он перейдя по ссылке http://symfony2.loc/app_dev.php ему открылся файл конфигурации, хотя путь должен быть http://symfony2.loc/symfony/web/app_dev.php
почему так? у меня так не работает.
а когда переходу по ссылке
http://symfony2.loc/symfony/web/app_dev.php
то комплюктер грузится на 100%
Ну и что тебя не устраивает? Если есть аватар, то выводишь его. Если нету, то выводишь дефолтный в зависимости от группы пользователя. Все просто и понятно.
Благодарю за ответ.
Ini.php я думал изначально использовать для загрузки шаблонов, но пока что отложил в сторону эту идею.
>Включено ли у тебя отображение ошибок? Если нет, то смотришь ли ты логи? Ты по моему просто не включил вывод ошибок и потому их не замечаешь, а это плохо, как ты видишь.
Не включена, но насколько я понял со скрина это ошибки из-за того что при первом входе переменные которые использованы в формах под "value= " ещё не объявлены, браузер их не показывал и я был спокоен, переделаю.
>Там у меня робот нашел отличия в bootstrap.css, ты его не правил? Если правил то замени файлы на исходные, а свои изменения помести в отдельный файл, например с названием student.css и положи его отдельно от бутстрапа.
Да, я когда разбирался ещё с бутстрапом и хотел изменить ширину форм ввода думал, что менять надо вручную. Перезагружу.
Вопрос у меня вот по проверке эмейла при изменении данных ранее зарегистрированного студента https://github.com/Si0n/register3/blob/master/lib/Student.php#L96
Так верно будет или нужен другой подход?
>PHP Parse error: syntax error, unexpected end of file in /home/S56muU/prog.php on line 20
unexpected end of file обычно говорит о том, что ты забыл закрыть блок (фигурные скобки)
Приучись когда пишешь блок сначала поставить скобки, а потом уже писать то что внутри.
Сначала нужно написать while(){}, а потом заполнять круглые и фигурные скобки.
В большинстве редакторов и тем более ide блоки закрываются автоматически.
Это кусок функции же, там половины скобок не хватает, у меня конкретный вопрос по доктрине
По этому :
$svqb = $statisticVoteRepository->createQueryBuilder('v')
// ->leftJoin('v.users', 'u')
->where('v.user = :user')->setParameter('user', $user)
;
InnoDB и все проблемы уходят. Профи без аргументации хуже нубов.
Вообще у меня в планах MySQL/MongoDB осовить прилично и этого мне хватит с головой.
Здравствуйте. Меня зовут Вячеслав, мне 22 года и я пхп программист. Я сижу на пхп с 18 лет. Первый раз я попробовал пхп с другом. Мы сидели, обсуждали веб-технологии и тут он сказал, что недавно пробовал пхп. Он предложил попробовать мне. Поначалу я не согласился, ведь это пхп, я слышал много плохих слухов про него, слышал, что он вызывает зависимость. Но друг настаивал, говорил, что в жизни нужно попробовать все и я сдался. Он предложил бесплатный скрипт, выводящий «Hello world!». Он казался совсем безобидным, но как потом оказалось, я уже не мог остановиться. Уже очень скоро благодаря пхп я попробовал свою первую cms. Это сейчас я понимаю, насколько опасным был этот шаг, но тогда я ничего не понимал, и мне это нравилось. Я не заметил, как после первой испробованной cms, мне уже захотелось написать свою. Дальше было только хуже. Я уже рискнул попробовать кое что потяжелее. Я решил попробовать свой первый фреймворк. Это было прекрасно. Но это была дорога в никуда. На тот момент родственники уже отчаялись мне помочь, а моя девушка узнав, что я использую пхп бросила меня. Я все больше отдалялся от своих друзей и родных, мое окружение составляли такие же пхп-программисты как и я. Мы собирались у одного в квартире, подключались к серверу и совместно программировали, используя пхп и фреймворки. Я попал в этот капкан пхп и теперь не могу самостоятельно избавиться от этого, моя жизнь сломана. Если бы мог вернуться в то время, я бы все исправил, и никогда не купился на эту уловку. Написано под воздействием тяжелой трудовой недели.
Бррр, от вас - тупых пидорасов - никакого толку.
Может кому еще пригодится http://ideone.com/AuzekD
http://ideone.com/xcf7jH
поподробнее, пожалуйста. Как это применить? тупо вставив в код - не получается, ошибку выдает.
http://php.net/manual/ru/function.preg-match-all.php
Так же как и preg_match. единственное отличие в том, что preg_match_all записывает в массив все совпадения с шаблоном, а не первый найденный.
Блин, дружище, пойми я полный ноль в ООП. И своё обучение я начал с уроков, которые приведены на сайте . Если я заменяю в своем коде preg_match на preg_match_all , то у меня выдается ошибка. Если не сложно, можешь показать как это работает? Лучше бы , конечно, решение было основано на той теории , которая дана в ранних уроках , а не заскакивая дальше
А при чем здесь ООП? Эта функция никоим образом к ооп не относится. Вот работа preg_match_all На практике:
http://ideone.com/CxAF89
это регулярки, а не ООП.
По поводу книг понятно, попробую что то поискать, пока делаю что то пробное, сейчас пока пользователь должен сам писать название и автора книги а также может загружать фотографии собственных книг.
Последняя часть задания про бд кинотеатра.
http://sqlfiddle.com/#!9/5b49e/5
>>481963
Почитал статьи (кроме хабра про оптимизацию, сохранил в закладки).
>Если ты все прочел внимательно, ответь на вопрос, может ли индекс (если да, то какой) ускорить такие запросы:
SELECT MAX(a) FROM table WHERE b = 2
Нужно делать составной индекс, причем в первой его части указывать именно b:
CREATE INDEX ON table (b, a)
SELECT FROM table WHERE name LIKE '%Иван%'
Нет, индекс не будет использоваться. Значение, которое использует LIKE, не должно начинаться с символа-шаблона.
SELECT FROM table WHERE b = 1 AND a < 10
Составной индекс на a и b, причем желательно прикинуть, какая часть условия возвращает меньшее кол-во записей (селективность), ее писать в левой части индекса. То есть если отдельный запрос ...where b=1 возвращает 10 записей, а ...where a=1 возвращает 200 строк, тогда ставим b в начало индекса.
CREATE INDEX ON table (b, a)
SELECT FROM table WHERE x <> 1
Если это условие отбрасывает только малую часть строк, то в индексе нет смысла, возможно даже ухудшение производительности.
SELECT FROM table WHERE x + y < 100
Индекс не будет использоваться.
--------------------------------------------------------
По поводу оптимизации и тестов реальной бд с большим кол-вом записей.
Насчет миллионов записей не знаю, пока нашел какую-то бд городов на 690 000 строк.
http://dev.maxmind.com/geoip/legacy/geolite/
Ну хорошо, тогда у меня в планах доделать задание про игру сапер на джаваскрипте, опыты с оптимизацией sql-запросов.
Затем приступить к большим заданиям по php. Сайт регистрации студентов я кажется уже делал пару месяцев назад, но многое забыл.
Так что переделаю заново для разминки, там на два дня максимум если не заморачиваться с версткой (запишу себе также на будущее осилить css-фреймворк).
Потом файлообменник. Там много пикантных моментов.
Последняя часть задания про бд кинотеатра.
http://sqlfiddle.com/#!9/5b49e/5
>>481963
Почитал статьи (кроме хабра про оптимизацию, сохранил в закладки).
>Если ты все прочел внимательно, ответь на вопрос, может ли индекс (если да, то какой) ускорить такие запросы:
SELECT MAX(a) FROM table WHERE b = 2
Нужно делать составной индекс, причем в первой его части указывать именно b:
CREATE INDEX ON table (b, a)
SELECT FROM table WHERE name LIKE '%Иван%'
Нет, индекс не будет использоваться. Значение, которое использует LIKE, не должно начинаться с символа-шаблона.
SELECT FROM table WHERE b = 1 AND a < 10
Составной индекс на a и b, причем желательно прикинуть, какая часть условия возвращает меньшее кол-во записей (селективность), ее писать в левой части индекса. То есть если отдельный запрос ...where b=1 возвращает 10 записей, а ...where a=1 возвращает 200 строк, тогда ставим b в начало индекса.
CREATE INDEX ON table (b, a)
SELECT FROM table WHERE x <> 1
Если это условие отбрасывает только малую часть строк, то в индексе нет смысла, возможно даже ухудшение производительности.
SELECT FROM table WHERE x + y < 100
Индекс не будет использоваться.
--------------------------------------------------------
По поводу оптимизации и тестов реальной бд с большим кол-вом записей.
Насчет миллионов записей не знаю, пока нашел какую-то бд городов на 690 000 строк.
http://dev.maxmind.com/geoip/legacy/geolite/
Ну хорошо, тогда у меня в планах доделать задание про игру сапер на джаваскрипте, опыты с оптимизацией sql-запросов.
Затем приступить к большим заданиям по php. Сайт регистрации студентов я кажется уже делал пару месяцев назад, но многое забыл.
Так что переделаю заново для разминки, там на два дня максимум если не заморачиваться с версткой (запишу себе также на будущее осилить css-фреймворк).
Потом файлообменник. Там много пикантных моментов.
> Ini.php я думал изначально использовать для загрузки шаблонов,
Тогда класс должен называться TemplateLoader а не Ini. То есть всегда старайся давать осмысленные названия и непонимания не будет.
> Включено ли у тебя отображение ошибок?
> Не включена
Тогда тебе надо либо его включить либо смотреть логи. Надо чтобы ты сам видел эти ошибки, а не думал что их нету.
> Вопрос у меня вот по проверке эмейла при изменении данных ранее зарегистрированного студента > https://github.com/Si0n/register3/blob/master/lib/Student.php#L96
> Так верно будет или нужен другой подход?
Можно и так но лучше писать SELCT COUNT(×) .. чтобы было видно что тебя интересует только наличие записи с таким email.
Еще непонятно, зачем делать 2 запроса. Мне кажется, тут что-то не так с логикой, потому что для проверки есть такой email или нет, достаточно 1 запроса. Чтобы при редактировании разрешить использовать свой же email ты можешь просто дописать условие:
WHERE id <> :id или WHERE password <> :password
Если у тебя есть id или код.
> bindParam(":password", $cookie);
Странно что одна и та же вещь называется 2 разными словами. Сделай, чтобы называлась одинаково, чтобы не было путаницы.
> AND pswrd= :password"
Вот это тоже неудачное сокращение так как его трудно запомнить. Лучше бы поменять имя колонки в таблице, а затем пройтись по коду поиском и заменой.
Также, в MySQL можно добавлять комментарий к колонкам таблиц с помощью слова COMMENT. Этот комментарий созхраняется в базе и помогает потом разобраться в ее структуре. Я советую для неочевидных колонок вроде password добавлять комментарий описыващий что именно там хранится, потому что это ведь не пароль, который мы вводим при регистрации, а что-то другое, верно?
Вот команда для добавления комментария к колонке:
ALTER TABLE `courses` CHANGE `courseid` `courseid` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'a new comment'
Вот пример как указать комментарий при создании таблицы: http://stackoverflow.com/a/199920
Кстати, если ты не очень хорошо знаешь SQL, у нас в ОП посте есть годные задания и ссылки по этой теме.
> Ini.php я думал изначально использовать для загрузки шаблонов,
Тогда класс должен называться TemplateLoader а не Ini. То есть всегда старайся давать осмысленные названия и непонимания не будет.
> Включено ли у тебя отображение ошибок?
> Не включена
Тогда тебе надо либо его включить либо смотреть логи. Надо чтобы ты сам видел эти ошибки, а не думал что их нету.
> Вопрос у меня вот по проверке эмейла при изменении данных ранее зарегистрированного студента > https://github.com/Si0n/register3/blob/master/lib/Student.php#L96
> Так верно будет или нужен другой подход?
Можно и так но лучше писать SELCT COUNT(×) .. чтобы было видно что тебя интересует только наличие записи с таким email.
Еще непонятно, зачем делать 2 запроса. Мне кажется, тут что-то не так с логикой, потому что для проверки есть такой email или нет, достаточно 1 запроса. Чтобы при редактировании разрешить использовать свой же email ты можешь просто дописать условие:
WHERE id <> :id или WHERE password <> :password
Если у тебя есть id или код.
> bindParam(":password", $cookie);
Странно что одна и та же вещь называется 2 разными словами. Сделай, чтобы называлась одинаково, чтобы не было путаницы.
> AND pswrd= :password"
Вот это тоже неудачное сокращение так как его трудно запомнить. Лучше бы поменять имя колонки в таблице, а затем пройтись по коду поиском и заменой.
Также, в MySQL можно добавлять комментарий к колонкам таблиц с помощью слова COMMENT. Этот комментарий созхраняется в базе и помогает потом разобраться в ее структуре. Я советую для неочевидных колонок вроде password добавлять комментарий описыващий что именно там хранится, потому что это ведь не пароль, который мы вводим при регистрации, а что-то другое, верно?
Вот команда для добавления комментария к колонке:
ALTER TABLE `courses` CHANGE `courseid` `courseid` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'a new comment'
Вот пример как указать комментарий при создании таблицы: http://stackoverflow.com/a/199920
Кстати, если ты не очень хорошо знаешь SQL, у нас в ОП посте есть годные задания и ссылки по этой теме.
А что именно не так? Объясни, что ты ожидаешь, и что происходит в реальности. Если происходят какие-то ошибки или исключения, то опиши какие.
Запустить этот кусок кода я все равно не могу.
Алсо, делать запросы в цикле в 99% случаев плохая идея. Базе гораздо больше нравится сделать один большой запрос чем много маленьких. Однозначно тут надо вынести запрос за цикл, чтобы он выполнялся 1 раз, а не для каждого юзера. Если это тестовое задание, я бы сделал вывод что кандидат плохо разбирается в доктрине и в написании SQL запросов. Если ты пока начинающий и только изучаешь доктрину, то это пока нормально, но в дальнейшем тебе надо научиться избегать такого кода.
И еще одна вещь. Построитель запросов (Query Builder) придуман для тех ситуаций когда у нас запрос меняется от каких-то условий и мы вынуждены собирать его по частям:
if (...) {
$query->addWhere(..);
}
У тебя запрос явно всегда одинаков. Это значит что тут выгоднее писать запрос на DQL, это быстрее, короче, читабельнее чем куча стрелок и скобок.
И еще одна мысль. Вот эта вот строчка
$users = $userRepository->findAll();
убьет твой скрипт если у тебя больше нескольких десятков тысяч юзеров. Доктрина очень плохо работает если загрузить так много объектов в память. Для массовой обработки больших объемов данных надо использовать поточную обработку (batch processing), выбирая пользователей пачками, там есть отдельнй раздел в мануале про это.
preg_match ищет только первое совпадение и все. preg_match_all ищет все совпадения. Она тут и нужна.
Посмотри урок про регулярки, там описана preg_match_all где-то ближе к концу. Также, почитай мануал по ней. Учти что она возвращает массив результатов в довольно сложном формате, как массив из массивов.
> SELECT FROM table WHERE b = 1 AND a < 10
> Составной индекс на a и b, причем желательно прикинуть, какая часть условия возвращает меньшее кол-во записей
Нет. Тут нужно поставить колонки в правильном порядке иначе индекс использован не будет. Вот смотри, 2 индекса: (a, b) и (b, a)
Давай напишем значения в них, я буду писать их через запятую:
(a, b)
1, 1
1, 2
1, 10
1, 100
5, 1
5, 2
--- (до этой линии a < 10)
13, 0
60, 1
60, 3
Здесь мы используем индекс не очень эффективно. Мы можем найти точку, где a < 10 (я обозначил ее линией) и взять все значения ниже ее (допустим это 80% всех записей в таблице, для таблицы в 1 млн записей это 800 000 записей). Но как ты видишь, мы вынуждены обойти их всех и вручную проверить каждое на условие b = 1 так как там записи соответстующие и не соответствующие условию идут вперемешку. Мы не можем просто взять сплошной кусок данных из индекса от сюда до туда.
И такой индекс:
(b, a)
0, 13
-------- (после это линии b = 1)
1, 1
1, 5
------ (до этой линии b = 1 AND a < 10)
1, 60
----- (до этой линии b = 1)
2, 1
2, 5
3, 60
10, 1
100, 1
Здесь мы можешь найти отрезок где b = 1, а затем на нем найти точку где a < 10 и получим сплошной кусок, содержащий только искомые строки.
Как видишь на таком индексе мы можем найти строки подходящие под оба условия, а первый индекс мы можем использовать только для поиска a < 10. Потому как я понимаю, второй индекс тут всегда лучше так как он позволяет искать по обоим условиям и находит меньше записей.
Тот пункт про селективность относится к ситуациям когда мы ищем по WHERE a = 1 AND b = 2, а если одно из условий «меньше» или мы имеем сортировку то у нас нет выбора в каком порядке ставить колонки.
> SELECT FROM table WHERE b = 1 AND a < 10
> Составной индекс на a и b, причем желательно прикинуть, какая часть условия возвращает меньшее кол-во записей
Нет. Тут нужно поставить колонки в правильном порядке иначе индекс использован не будет. Вот смотри, 2 индекса: (a, b) и (b, a)
Давай напишем значения в них, я буду писать их через запятую:
(a, b)
1, 1
1, 2
1, 10
1, 100
5, 1
5, 2
--- (до этой линии a < 10)
13, 0
60, 1
60, 3
Здесь мы используем индекс не очень эффективно. Мы можем найти точку, где a < 10 (я обозначил ее линией) и взять все значения ниже ее (допустим это 80% всех записей в таблице, для таблицы в 1 млн записей это 800 000 записей). Но как ты видишь, мы вынуждены обойти их всех и вручную проверить каждое на условие b = 1 так как там записи соответстующие и не соответствующие условию идут вперемешку. Мы не можем просто взять сплошной кусок данных из индекса от сюда до туда.
И такой индекс:
(b, a)
0, 13
-------- (после это линии b = 1)
1, 1
1, 5
------ (до этой линии b = 1 AND a < 10)
1, 60
----- (до этой линии b = 1)
2, 1
2, 5
3, 60
10, 1
100, 1
Здесь мы можешь найти отрезок где b = 1, а затем на нем найти точку где a < 10 и получим сплошной кусок, содержащий только искомые строки.
Как видишь на таком индексе мы можем найти строки подходящие под оба условия, а первый индекс мы можем использовать только для поиска a < 10. Потому как я понимаю, второй индекс тут всегда лучше так как он позволяет искать по обоим условиям и находит меньше записей.
Тот пункт про селективность относится к ситуациям когда мы ищем по WHERE a = 1 AND b = 2, а если одно из условий «меньше» или мы имеем сортировку то у нас нет выбора в каком порядке ставить колонки.
> SELECT FROM table WHERE x <> 1
> Если это условие отбрасывает только малую часть строк, то в индексе нет смысла,
Это условие по моему не использует индекс вообще, в MySQL по крайней мере. Хотя теоретически тут можно было бы сделать преобразование:
WHERE x < 1 OR x > 1
и такой запрос делает 2 поиска по индексу с объединением результатов. Но по моему MySQL не умеет делать такое преобразование и x <> 1 сведется к обходу всех строк таблицы. Ну и ты прав что если записей с x = 1 немного то использование индекса скорее замедлит выборку чем ускорит, так как записи будут читаться в порядке записанном в индексе вместо последовательного.
Задание «Grammar Nazi» про ошибки, из "Регулярные выражения". Проверьте чтоли кто-нибудь регексп. Спасибо.
Сборки для опытных программистов. Начинающему лучше ставить самому. Ну и по опыту анонов, в сборках бывают старые версии программ, отстуствуют какие-нибудь расширения и т д.
>>480319
У меня нет ресурсов для этого. И столько времени тоже. Но я слышал что есть подобные лагеря где изучают программирование, только не PHP.
>>480766
Ты немного переусложнил задачу. Там вообще предполагалось что входные данные идут в массиве, примерно так:
var cities = [{ name: ..., country: ...., population: .... }];
То есть парсить их из HTML не обязательно (но если ты так сделал то тоже хорошо).
Твой способ хранения не очень удачный:
> list[j-1]['1']
Что это за ерунда? Что за '1'? Тут надо использовать понятные словесные ключи, а не цифры. И кстати почему ты цифру строкой передаешь? В JS массивы это не ассоциативный массив как в PHP, а просто упорядоченный набор элементов от 0 до N и там строк-ключей не может быть. Строки-ключи есть в словарях (хешах), но зато там элементы не упорядочены.
Наконец, зачем ты написал свой алгоритм сортировки?А если написал свой алгоритм, почему не написал в комментарии название и ссылку на описание?
Тут лучше использовать стандартную функцию сортировки массива sort: https://learn.javascript.ru/array-methods
Она быстрее чем твоя пузырьковая сортировка.
> +getPopulation(table, i)
Лучше явно писать parseFloat(...) для преобразования в число
Ну и вывести надо не все города, а только первые N.
Сборки для опытных программистов. Начинающему лучше ставить самому. Ну и по опыту анонов, в сборках бывают старые версии программ, отстуствуют какие-нибудь расширения и т д.
>>480319
У меня нет ресурсов для этого. И столько времени тоже. Но я слышал что есть подобные лагеря где изучают программирование, только не PHP.
>>480766
Ты немного переусложнил задачу. Там вообще предполагалось что входные данные идут в массиве, примерно так:
var cities = [{ name: ..., country: ...., population: .... }];
То есть парсить их из HTML не обязательно (но если ты так сделал то тоже хорошо).
Твой способ хранения не очень удачный:
> list[j-1]['1']
Что это за ерунда? Что за '1'? Тут надо использовать понятные словесные ключи, а не цифры. И кстати почему ты цифру строкой передаешь? В JS массивы это не ассоциативный массив как в PHP, а просто упорядоченный набор элементов от 0 до N и там строк-ключей не может быть. Строки-ключи есть в словарях (хешах), но зато там элементы не упорядочены.
Наконец, зачем ты написал свой алгоритм сортировки?А если написал свой алгоритм, почему не написал в комментарии название и ссылку на описание?
Тут лучше использовать стандартную функцию сортировки массива sort: https://learn.javascript.ru/array-methods
Она быстрее чем твоя пузырьковая сортировка.
> +getPopulation(table, i)
Лучше явно писать parseFloat(...) для преобразования в число
Ну и вывести надо не все города, а только первые N.
У тебя там ошибка внизу:
> PHP Notice: Undefined variable: word in /home/mS3Zgt/prog.php on line 95
Ты используешь не существующую еще в тот момент переменную в 95 строке:
> $word = $word . $spelling[$value];
Мы сначала должны вычислить то, что справа от знака равно, и если переменной word еще нет, то получается ошибка.
По коду:
> if (($number % 100 >= 10) && ($number % 100 <= 20)) {
> $number = " рублей";
Тут лучше сразу писать return "рублей". И пробел наверно лучше где-то в другом месте добавлять.
> if (($million % 100 >= 10) && ($million % 100 <= 20)) {
> $mill = " миллионов";
> }
> elseif (($million % 10 == 1) || ($million % 10 >= 5)) {
Это копипаста кода из функции inclineWord, только слово другое. Копипаста — зло. Надо избавиться от копипасты и объединить этот код. Например, можно передавать в inclineWord варианты слов.
Соответственно тогда и слово «тысяч» можно будет склонять этой же функцией.
> $word = $word . ' ' . $spelling[$sotni] . ' ' . $spelling[$desyatki] . ' ' . $spelling[$mod2];
Это ненадежно так как десяток может и не быть. Лучше составлять фразу, складывая слова в массив, примерно так:
$words = пустой массив;
Если (в числе есть сотни) {
добавить в $words слово для сотен;
}
Если (десятки и единицы числа меньше 20) {
добавить в $words слово для десятков/единиц;
}
После чего ты можешь преобразовать массив в строку с помощью implode.
Ну и сам код толком не дописан. Тебе надо выносить повторяющиеся действия в функции. Например нам надо 3 раза склонять слова: миллионов, тысяч, рублей — это надо вынести в функцию склонения слов. Далее, нам надо сделать функцию для написания маленьких (3-значных) чисел. Далее, останется только сделать функцию, разбивающую число на миллионы/тысячи/единицы и вызывающую другие функции.
А ты все пытаешься писать одной длинной простыней. Это плохо, такой код читать невозможно. Надо разбивать на отдельные действия и выносить в функции.
У тебя там ошибка внизу:
> PHP Notice: Undefined variable: word in /home/mS3Zgt/prog.php on line 95
Ты используешь не существующую еще в тот момент переменную в 95 строке:
> $word = $word . $spelling[$value];
Мы сначала должны вычислить то, что справа от знака равно, и если переменной word еще нет, то получается ошибка.
По коду:
> if (($number % 100 >= 10) && ($number % 100 <= 20)) {
> $number = " рублей";
Тут лучше сразу писать return "рублей". И пробел наверно лучше где-то в другом месте добавлять.
> if (($million % 100 >= 10) && ($million % 100 <= 20)) {
> $mill = " миллионов";
> }
> elseif (($million % 10 == 1) || ($million % 10 >= 5)) {
Это копипаста кода из функции inclineWord, только слово другое. Копипаста — зло. Надо избавиться от копипасты и объединить этот код. Например, можно передавать в inclineWord варианты слов.
Соответственно тогда и слово «тысяч» можно будет склонять этой же функцией.
> $word = $word . ' ' . $spelling[$sotni] . ' ' . $spelling[$desyatki] . ' ' . $spelling[$mod2];
Это ненадежно так как десяток может и не быть. Лучше составлять фразу, складывая слова в массив, примерно так:
$words = пустой массив;
Если (в числе есть сотни) {
добавить в $words слово для сотен;
}
Если (десятки и единицы числа меньше 20) {
добавить в $words слово для десятков/единиц;
}
После чего ты можешь преобразовать массив в строку с помощью implode.
Ну и сам код толком не дописан. Тебе надо выносить повторяющиеся действия в функции. Например нам надо 3 раза склонять слова: миллионов, тысяч, рублей — это надо вынести в функцию склонения слов. Далее, нам надо сделать функцию для написания маленьких (3-значных) чисел. Далее, останется только сделать функцию, разбивающую число на миллионы/тысячи/единицы и вызывающую другие функции.
А ты все пытаешься писать одной длинной простыней. Это плохо, такой код читать невозможно. Надо разбивать на отдельные действия и выносить в функции.
Задания на список студентов и файлообменник в первом посте видел? Было бы полезно их решить. Ну и задачу на Yii 2 посмотреть.
Учти, те, кто учатся по старым и неправильным учебникам часто пишут плохой код — без ООП, без MVC, работают с базой устаревшим способом, не умеют использоать фреймворки. Эти задачи помогли бы тебе научиться всему этому.
Когда пора искать работу, не знаю, зависит от компании, где-то требования выше. где-то меньше. Где-то достаточно набыдлокодить простую страничку как в устаревших учебниках или видеокурсах, где-то нужно знание ООП и фреймворка какого-нибудь и нормальный код.
Ты бы мог параллельно искать работу и решать наши задачки на тот случай если твоих знаний недостаточно. Я даю комментарии и советы по решениям.
Сайт, который недолго делать. Ну тот же блог где 3 страницы — список постов, пост, добавление поста.
>>480858
Ну я бы советовал все же развиваться дальше. WP это довольно низкий уровень, это считай верстальщик с умением натягивать верстку на CMS, тебе это надоест скоро.
Развиваться можно, например решая наши задачи про список студентов и файлообменник из по-поста.
>>480865
Мне статья показалась довольно сумбурной и плохо объясняющей. Git book лучше и полезнее.
Ну и файлы удобнее добавлять через git add .
> Меня в основном общая структура и безопасность волнует, а не красота и поддерживаемость кода. Но и по ней тоже могу рекомендации учесть.
Нет. Меня такой подход не устраивает, потому что мне надо читать твой код и я хочу читать аккуратно и правильно написанный код. И точно того же захотят твои коллеги, руководитель и другие люди (например если ты захочешь что-то выложить в опенсорс, то вряд ли кто-то захочет исправлять баги и присылать пулл реквесты к некачественному коду). Потому красота и поддерживаемость важна не меньше. Впрочем, сам он у тебя не страшный, отступы есть, только вот разложен код по классам и методам неправильно.
Вот замечания по архитектуре кода:
> https://github.com/Nattpyre/randomwebm/blob/master/index.php
Весь HTML следует помещать отдельно от логики, в шаблоны, например в папочке templates. даже если у тебя сейчас одна страница, ты потом можешь захотеть добавить еще несколько. Как минимум в админке у тебя из-за того смесь логики и HTML получается.
> https://github.com/Nattpyre/randomwebm/blob/master/.htaccess#L3
Ты уверен что это вообще работает? startup_errors по моему это ошибки возникающие в процессе инициализации PHP и она делается при запуске Апача, соответственно твой htaccess на них никак не влияет.
> database.class.php
Суффикс class писали во времена когда классов было мало. Сейчас если ты используешь ООП то у тебя практически все на классах и писать этот суффикс излишне.
Есть рекомендации — PSR-0 (уже вроде устарел) и PSR-4, о том как называть классы. Они рекомендуют называть файл так же как класс, SomeClass.php без всяких суффиксов и я думаю, лучше делать как все, а не придумывать свои особенные способы называть файлы.
Саму папку обычно сейчас называют src, а твой стиль напоминает стиль наименования файлов в древних CMS.
Если ты будешь следовать рекомендациям, ты например сможешь подключить автозагрузку одной строчкой в composer.json, если ты используешь композер, а не писать очередной велосипедный автозагрузчик.
> https://github.com/Nattpyre/randomwebm/blob/master/classes/database.class.php
Что делает этот класс? Он не добавляет никакого функционала, а параметры соединения с базой принято выносить в файлик config.php
Причем я это вижу уже не первый раз. Кто-то в каком-то неправильном учебнике этому учит, а мне потом приходится переучивать.
Редактор лучше настроить на использование 4 пробелов вместо табов. Ну посмотри как код раскособочило: https://github.com/Nattpyre/randomwebm/blob/master/classes/message.class.php — тяжело читать. используй пробелы (тем более это рекомендуют стандарты PSR-1/2) и проблем не будет.
> https://github.com/Nattpyre/randomwebm/blob/master/classes/message.class.php
В этом классе все как-то смешано в кучу. Тут и работа с базой данных, и работа с GET-данными, тут же у тебя модель ( public $name; public $email;), и тут же захардкожен вызов Database:;connect. Что представляет собой объект Message? Информацию о сообщении? Тогда почему он работает с базой и с GET-параметрами? Я не понимаю, и ты, мне кажется, тоже не понимаешь. Такое ощущение, что это обычный процедурный код к которому для вида приписали class Message { в начале.
Я советую почитать урок про то, как можно работать с БД с использованием ООП: https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md
Также, ты в каждой функции делаешь новое соединение с БД. Гораздо лучше сделать так:
— отдельный класс-модель Message со свойствами name, email и тд
— отдельный класс для сохранения/загрузки Message из базы. В него в конструктор передается экземпляр mysqli через который он будет делать запросы.
— валидацию можно встроить в Message или в отдельный класс
— работу с GET параметрами, куками и прочими внешними данными унести в контроллер
> https://github.com/Nattpyre/randomwebm/blob/master/classes/message.class.php#L19
это неправильный код. Ты просто применяешь к данным все функции, про которые слышал, не пытаясь подумать, а какие и где функции надо применять.
Данные принято экранировать только там, где они используются. Если ты выводишь данные на странице, используй htmlspecialchars, если вставляешь в базу, используй real_escape+string (а лучше используй плейсхолдеры так как они специально для этого придуманы и я не понимаю, какая выгода изобретать велосипед вместо уже сделанных вещей. Я тебе советую переучиться на плейсхолдеры, а авторам старых учебников не доверять вообще).
Когда ты экранируешь данные там же где используешь, с первого взгляда видно, безопасен код или нет. Если же ты делаешь как учат в старых учебниках (пишем кучу функций типа strip_tags и надеемся что все хорошо) то понять безопасен код или нет можно только полностью проанализировав его. Твой код не очень большой. и наверно это можно сделать за полчаса (но мне лень), а в реальном коде где сотни файлов, такой анализ займет неделю минимум.
Я тебе советую переделать работу с БД на плейсхолдеры, и экранировать данные там где они используются.
Статьи: http://php.net/manual/ru/mysqli.quickstart.prepared-statements.php
http://habrahabr.ru/post/141127/
> https://github.com/Nattpyre/randomwebm/blob/master/classes/message.class.php#L14
не городи такие вложенные ифы. Их надо заменить на последовательно идущие ифы + return:
Если (что-то не передано) {
вернуть ошибку;
}
Если (много букв) {
вернуть ошибку;
}
,.....
> https://github.com/Nattpyre/randomwebm/blob/master/classes/message.class.php#L64
Тут непонятно экранируются данные или нет. У меня такое ощущение что нет. Надо использовать плейсхолдеры, и никогда не вставлять переменные прямо в текст запроса.
> https://github.com/Nattpyre/randomwebm/blob/master/classes/message.class.php#L75
Это 100% SQL инъекция
В общем, давай ты пока исправишь эти ошибки, а я тогда потом гляну код еще раз.
Я заметил, что ты пишешь: «Серьезно заняться этим делом я решил сравнительно недавно и это мой первый более-менее серьезный сайт. ». Я боюсь, что на «серьезный» в плане качества кода это пока не тянет. Но если ты исправишь все ошибки, то это будет совсем другое дело.
А, и еще, я вижу, ты сделал адаптивную версию. Это хорошо. Но я советую у видео убрать белые поля справа и слева, так как на узеньком мобильном экране это лишний расход свободного места. Также, меню изображено в виде прямоугольника, но 90% этого прямоугольника не кликабельно, кликабельна только кнопка. Это плохо, зачем тогда прямоугольник рисовать?
Также, у тебя при клике по табам меняется URL страницы, но если обновить страницу то выбранный таб теряется. Надо при загрузке страницы читать id таба из URL.
Надпись «play» на зеленой кнопке в моем фаерфоксе выпадает из нее куда-то вниз, а треугольник наоборот вверх.
> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js">
Я советую подключать библиотеки со своего сайта, от подключения сторонних скриптов только проблемы в виде задержек загрузки при проблемах на удаленном сервере.
> \t<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
В чем смысл этого скрипта? Он рассчитан на старые ИЕ, но где ты видел смартфон со старым ИЕ?
> \t<script src="js/less.min.js">
Стили надо компилировать при деплое на сервер, а не в браузере — как минимум это ускорит загрузку и заодно позволит увидеть. ошибки. Ну и клиенту не надо грузить бесполезный компилятор less.
> \ttextarea{
>\t\tresize:none;
Вот это неправильно. Браузер дает возможность сделать текстареа удобного размера, а ты ее отбираешь. Почему ты отбираешь удобные возможности, а не добавляешь новые? И справедливости ради текстареа у тебя какого-то лилипутского размера куда больше 2 предложений не влезает, тут как раз ресайз и нужен.
> "vendor/bootstrap.min.js"
Файл подключен 2 раза
И еще я заметил что сайт загружает 2720 Кб файлов, из них видео весит 1461 Кб, то есть сам сайт весит около 1260 Кб. По моему тут максимум килобайт 100-200 должно быть, это надо специально стараться чтобы такую тяжелую верстку для такого простого сайта с парой картинок сделать. У тебя только файл forbidden весит полмагабайта, советую почитать статьи про форматы картинок и оптимизацию, ты пишешь что ты верстальщик, а верстальщик должен в этом разбираться.
> Меня в основном общая структура и безопасность волнует, а не красота и поддерживаемость кода. Но и по ней тоже могу рекомендации учесть.
Нет. Меня такой подход не устраивает, потому что мне надо читать твой код и я хочу читать аккуратно и правильно написанный код. И точно того же захотят твои коллеги, руководитель и другие люди (например если ты захочешь что-то выложить в опенсорс, то вряд ли кто-то захочет исправлять баги и присылать пулл реквесты к некачественному коду). Потому красота и поддерживаемость важна не меньше. Впрочем, сам он у тебя не страшный, отступы есть, только вот разложен код по классам и методам неправильно.
Вот замечания по архитектуре кода:
> https://github.com/Nattpyre/randomwebm/blob/master/index.php
Весь HTML следует помещать отдельно от логики, в шаблоны, например в папочке templates. даже если у тебя сейчас одна страница, ты потом можешь захотеть добавить еще несколько. Как минимум в админке у тебя из-за того смесь логики и HTML получается.
> https://github.com/Nattpyre/randomwebm/blob/master/.htaccess#L3
Ты уверен что это вообще работает? startup_errors по моему это ошибки возникающие в процессе инициализации PHP и она делается при запуске Апача, соответственно твой htaccess на них никак не влияет.
> database.class.php
Суффикс class писали во времена когда классов было мало. Сейчас если ты используешь ООП то у тебя практически все на классах и писать этот суффикс излишне.
Есть рекомендации — PSR-0 (уже вроде устарел) и PSR-4, о том как называть классы. Они рекомендуют называть файл так же как класс, SomeClass.php без всяких суффиксов и я думаю, лучше делать как все, а не придумывать свои особенные способы называть файлы.
Саму папку обычно сейчас называют src, а твой стиль напоминает стиль наименования файлов в древних CMS.
Если ты будешь следовать рекомендациям, ты например сможешь подключить автозагрузку одной строчкой в composer.json, если ты используешь композер, а не писать очередной велосипедный автозагрузчик.
> https://github.com/Nattpyre/randomwebm/blob/master/classes/database.class.php
Что делает этот класс? Он не добавляет никакого функционала, а параметры соединения с базой принято выносить в файлик config.php
Причем я это вижу уже не первый раз. Кто-то в каком-то неправильном учебнике этому учит, а мне потом приходится переучивать.
Редактор лучше настроить на использование 4 пробелов вместо табов. Ну посмотри как код раскособочило: https://github.com/Nattpyre/randomwebm/blob/master/classes/message.class.php — тяжело читать. используй пробелы (тем более это рекомендуют стандарты PSR-1/2) и проблем не будет.
> https://github.com/Nattpyre/randomwebm/blob/master/classes/message.class.php
В этом классе все как-то смешано в кучу. Тут и работа с базой данных, и работа с GET-данными, тут же у тебя модель ( public $name; public $email;), и тут же захардкожен вызов Database:;connect. Что представляет собой объект Message? Информацию о сообщении? Тогда почему он работает с базой и с GET-параметрами? Я не понимаю, и ты, мне кажется, тоже не понимаешь. Такое ощущение, что это обычный процедурный код к которому для вида приписали class Message { в начале.
Я советую почитать урок про то, как можно работать с БД с использованием ООП: https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md
Также, ты в каждой функции делаешь новое соединение с БД. Гораздо лучше сделать так:
— отдельный класс-модель Message со свойствами name, email и тд
— отдельный класс для сохранения/загрузки Message из базы. В него в конструктор передается экземпляр mysqli через который он будет делать запросы.
— валидацию можно встроить в Message или в отдельный класс
— работу с GET параметрами, куками и прочими внешними данными унести в контроллер
> https://github.com/Nattpyre/randomwebm/blob/master/classes/message.class.php#L19
это неправильный код. Ты просто применяешь к данным все функции, про которые слышал, не пытаясь подумать, а какие и где функции надо применять.
Данные принято экранировать только там, где они используются. Если ты выводишь данные на странице, используй htmlspecialchars, если вставляешь в базу, используй real_escape+string (а лучше используй плейсхолдеры так как они специально для этого придуманы и я не понимаю, какая выгода изобретать велосипед вместо уже сделанных вещей. Я тебе советую переучиться на плейсхолдеры, а авторам старых учебников не доверять вообще).
Когда ты экранируешь данные там же где используешь, с первого взгляда видно, безопасен код или нет. Если же ты делаешь как учат в старых учебниках (пишем кучу функций типа strip_tags и надеемся что все хорошо) то понять безопасен код или нет можно только полностью проанализировав его. Твой код не очень большой. и наверно это можно сделать за полчаса (но мне лень), а в реальном коде где сотни файлов, такой анализ займет неделю минимум.
Я тебе советую переделать работу с БД на плейсхолдеры, и экранировать данные там где они используются.
Статьи: http://php.net/manual/ru/mysqli.quickstart.prepared-statements.php
http://habrahabr.ru/post/141127/
> https://github.com/Nattpyre/randomwebm/blob/master/classes/message.class.php#L14
не городи такие вложенные ифы. Их надо заменить на последовательно идущие ифы + return:
Если (что-то не передано) {
вернуть ошибку;
}
Если (много букв) {
вернуть ошибку;
}
,.....
> https://github.com/Nattpyre/randomwebm/blob/master/classes/message.class.php#L64
Тут непонятно экранируются данные или нет. У меня такое ощущение что нет. Надо использовать плейсхолдеры, и никогда не вставлять переменные прямо в текст запроса.
> https://github.com/Nattpyre/randomwebm/blob/master/classes/message.class.php#L75
Это 100% SQL инъекция
В общем, давай ты пока исправишь эти ошибки, а я тогда потом гляну код еще раз.
Я заметил, что ты пишешь: «Серьезно заняться этим делом я решил сравнительно недавно и это мой первый более-менее серьезный сайт. ». Я боюсь, что на «серьезный» в плане качества кода это пока не тянет. Но если ты исправишь все ошибки, то это будет совсем другое дело.
А, и еще, я вижу, ты сделал адаптивную версию. Это хорошо. Но я советую у видео убрать белые поля справа и слева, так как на узеньком мобильном экране это лишний расход свободного места. Также, меню изображено в виде прямоугольника, но 90% этого прямоугольника не кликабельно, кликабельна только кнопка. Это плохо, зачем тогда прямоугольник рисовать?
Также, у тебя при клике по табам меняется URL страницы, но если обновить страницу то выбранный таб теряется. Надо при загрузке страницы читать id таба из URL.
Надпись «play» на зеленой кнопке в моем фаерфоксе выпадает из нее куда-то вниз, а треугольник наоборот вверх.
> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js">
Я советую подключать библиотеки со своего сайта, от подключения сторонних скриптов только проблемы в виде задержек загрузки при проблемах на удаленном сервере.
> \t<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
В чем смысл этого скрипта? Он рассчитан на старые ИЕ, но где ты видел смартфон со старым ИЕ?
> \t<script src="js/less.min.js">
Стили надо компилировать при деплое на сервер, а не в браузере — как минимум это ускорит загрузку и заодно позволит увидеть. ошибки. Ну и клиенту не надо грузить бесполезный компилятор less.
> \ttextarea{
>\t\tresize:none;
Вот это неправильно. Браузер дает возможность сделать текстареа удобного размера, а ты ее отбираешь. Почему ты отбираешь удобные возможности, а не добавляешь новые? И справедливости ради текстареа у тебя какого-то лилипутского размера куда больше 2 предложений не влезает, тут как раз ресайз и нужен.
> "vendor/bootstrap.min.js"
Файл подключен 2 раза
И еще я заметил что сайт загружает 2720 Кб файлов, из них видео весит 1461 Кб, то есть сам сайт весит около 1260 Кб. По моему тут максимум килобайт 100-200 должно быть, это надо специально стараться чтобы такую тяжелую верстку для такого простого сайта с парой картинок сделать. У тебя только файл forbidden весит полмагабайта, советую почитать статьи про форматы картинок и оптимизацию, ты пишешь что ты верстальщик, а верстальщик должен в этом разбираться.
> } elseif ($_FILES['webmUpload']['error'] === 3) {
Не надо писать магические числа, там есть константы: https://php.net/manual/ru/features.file-upload.errors.php
> public function GetRandomWebm()
Там какой-то адски неэффективный запрос на выборку. Почитай статьи как эффективно выбрать случайную запись: http://hudson.su/2010/09/16/mysql-optimizaciya-order-by-rand/
Мне кажется для твоих задач подошел бы такой вариант, сделать индексированную колонку rand с числами от 1 до миллиарда, генерировать в PHP случайное число и выбирать по этой колонке.
Кстати задачи на SQL в оп-посте помогут тебе изучить MySQL гораздо лучше.
> $mysqliConnect->real_escape_string(trim(htmlspecialchars(strip_tags
Это кошмар какой-то. еще addslashes не хватает.
> \tpublic static function MoveToMainBase()
Вместо возни с 2 таблицами гораздо удобнее добавить колонку «одобрено модератором» и использовать ее при выборке.
Алсо в репозитории нет дампа базы — я бы и по нему замечания написал.
>>480890
Статьи, ссылки, пруфы будут? Как по мне, так в сочетании с солью надежность получается на практике хорошая.
>>480905
Это плохая идея называть файлы с помощью md5. Какая от этого выгода? Как ты будешь них потом ориентироваться? называй файлы нормальными понятными человеку именами и тебе самому же при возникновении какой-то проблемы будет проще разобраться.
> Название то конечно можно и другими функциями давать, а вот как проверять файлы на дублирование по содержимому - хз.
В базе сделать колонку «хеш» и искать по базе.
> LEFT OUTER JOIN post p4
> ON (p3.thread_id = p4.thread_id AND p3.id < p4.id)
Тут лучше все же сравнение делать по дате, а не по id. Для надежности на случай каких-то изменений, например если мы пост удалим и перевставим заново.
Ну и анон, ты по моему пару моментов не учел: посты повторяются, треды отсортированы как-то не так: http://sqlfiddle.com/#!9/a20fc/1
Мне кажется там надо добавить GROUP BY и может быть сортировку по MAX date.
Ну и если бы ты сделал 1 таблицу, в которой для оп-постов thread_id IS NULL то выбрать оп-посты было проще и не надо было бы плясок с MIN (date).
Ну и я тут для разминки мозгов решил сделать запрос для имиджборды с одной таблицей где ОП пост обозначается как thread_id IS NULL (что заставило писать условия джойна с OR и лишило шансов на оптимизацию запросов, что на практике будет работать сверхмедленно).
У меня всего 3 раза таблица используется и выглядит примерно так:
SELECT FROM (выбираем 10 верхних тредов и их дату обновления) JOIN (post LEFT JOIN post .... - выбираем тут оп-пост + 3 верхних поста) ON ... GROUP BY ... HAVING COUNT .. ORDER BY ...
Как минимум таблиц тут меньше получается.
Я советую названия постов делать в виде T1-3 чтобы сразу было видно номер треда и поста.
Вот что у меня выбирается:
Т4-1
Т4-2
Т4-3
Т3-1
Т2-1
Т2-3
Т2-4
Т2-5
Т1-1
Т1-4
Т1-5
Т1-6
Ну и я тут для разминки мозгов решил сделать запрос для имиджборды с одной таблицей где ОП пост обозначается как thread_id IS NULL (что заставило писать условия джойна с OR и лишило шансов на оптимизацию запросов, что на практике будет работать сверхмедленно).
У меня всего 3 раза таблица используется и выглядит примерно так:
SELECT FROM (выбираем 10 верхних тредов и их дату обновления) JOIN (post LEFT JOIN post .... - выбираем тут оп-пост + 3 верхних поста) ON ... GROUP BY ... HAVING COUNT .. ORDER BY ...
Как минимум таблиц тут меньше получается.
Я советую названия постов делать в виде T1-3 чтобы сразу было видно номер треда и поста.
Вот что у меня выбирается:
Т4-1
Т4-2
Т4-3
Т3-1
Т2-1
Т2-3
Т2-4
Т2-5
Т1-1
Т1-4
Т1-5
Т1-6
> Итак, какие теперь попробовать варианты структуры базы?
Вариант с 1 таблицей у меня прекрасно работает, правда запрос там абсолютно неэффективный, в плане запроса что-то вроде
posts ALL
...
posts ALL
То есть он выбирает весь миллион постов и для каждой строчки джойнит еще миллион постов, может быть отсеивая что-то через ON/WHERE.
Для эффективной выборки нужна денормализация. например:
— помечать 3 последних поста (и ОП пост?) в отдельной индексированной колонке is_last_post
— хранить в Оп-посте дату последнего бампа треда (чтобы по этой колонке сделать индекс и эффективно выбрать 10 верхних Оп постов)
— сделать отдельную таблицу displayed_posts (thread_id, post_id, is_op_post) для хранения ссылок на ОП-пост и 3 последних поста
Я думаю, было бы полезным упражнением попробовать написать сначала неоптимизированный, но простой запрос, а потом подумать какая денормализация позволит делать быстрые выборки. Ну например без даты бампа в ОП-посте и индекса по ней, выбрать 10 верхних тредов наверно эффективно не получится. Чтобы выборка была быстрой, там везде должны использоваться индексы, и надо обходить/джойнить как можно меньше рядов (заметь что сами джойны не особо тормозят когда ты приджойниваешь 1 строку по индексу, а когда ты например приджойниваешь много рядов то это уже проблема).
Тестировать это лучше на базе из миллиона постов, ее можно сгенерировать как PHP скриптом так и SQL-скриптом вроде такого:
http://stackoverflow.com/a/6205909
Там мы создаем процедуру и вызываем ее. В процедуре можно использовть циклы. Например удобно сделать процедуру которая получает на вход число тредов и постов в каждом и генерирует их с текстами вида T1-3 и увеличивающейся или рандомной датой. Рандомную дату можно получить умножив RAND на миллиард и преобразовав в дату с помощью FROM_UNIXTIME. Каждый тред желательно делать одной транзакцией для скорости.
Если будешь делать PHP скриптом то вставка одной или несколькими большами транзакциями (BEGIN; запросы; COMMIT) будет работать быстрее чем отдельными запросами.
> Итак, какие теперь попробовать варианты структуры базы?
Вариант с 1 таблицей у меня прекрасно работает, правда запрос там абсолютно неэффективный, в плане запроса что-то вроде
posts ALL
...
posts ALL
То есть он выбирает весь миллион постов и для каждой строчки джойнит еще миллион постов, может быть отсеивая что-то через ON/WHERE.
Для эффективной выборки нужна денормализация. например:
— помечать 3 последних поста (и ОП пост?) в отдельной индексированной колонке is_last_post
— хранить в Оп-посте дату последнего бампа треда (чтобы по этой колонке сделать индекс и эффективно выбрать 10 верхних Оп постов)
— сделать отдельную таблицу displayed_posts (thread_id, post_id, is_op_post) для хранения ссылок на ОП-пост и 3 последних поста
Я думаю, было бы полезным упражнением попробовать написать сначала неоптимизированный, но простой запрос, а потом подумать какая денормализация позволит делать быстрые выборки. Ну например без даты бампа в ОП-посте и индекса по ней, выбрать 10 верхних тредов наверно эффективно не получится. Чтобы выборка была быстрой, там везде должны использоваться индексы, и надо обходить/джойнить как можно меньше рядов (заметь что сами джойны не особо тормозят когда ты приджойниваешь 1 строку по индексу, а когда ты например приджойниваешь много рядов то это уже проблема).
Тестировать это лучше на базе из миллиона постов, ее можно сгенерировать как PHP скриптом так и SQL-скриптом вроде такого:
http://stackoverflow.com/a/6205909
Там мы создаем процедуру и вызываем ее. В процедуре можно использовть циклы. Например удобно сделать процедуру которая получает на вход число тредов и постов в каждом и генерирует их с текстами вида T1-3 и увеличивающейся или рандомной датой. Рандомную дату можно получить умножив RAND на миллиард и преобразовав в дату с помощью FROM_UNIXTIME. Каждый тред желательно делать одной транзакцией для скорости.
Если будешь делать PHP скриптом то вставка одной или несколькими большами транзакциями (BEGIN; запросы; COMMIT) будет работать быстрее чем отдельными запросами.
> Короче, лучше такого решения ничего не могу придумать. Из очевидных минусов это лишний (с точки зрения конечного результата) столбик, он мне нужен был для промежуточных вычислений. Но я не думаю, что это сильно увеличит трафик
Трафик не увеличит, но твой запрос на практике все равно применять не стоит, так как он неэффективный (там 2 ALL в execution plan). Ну задание и не требовало написать эффективный запрос, для начала хватит просто работающего.
Внутренние ORDER внутри JOIN не работают так как у тебя стоит на внешнем запросе GROUP BY p1.id а GROUP делает сортировку. Тебе надо в конце дописать ORDER по дате бампа треда и дате поста.
Кстати, ты еще бамплимит не реализовал :) На практике конечно удобно сделать денормализованную колонку «дата бампа» в ОП-посте (и наверно колонку для числа постов в треде), с ней легко реализовать бамплимит, просто не обновляя ее после 500-го поста.
Ну и можно на один джойн меньше сделать:
> FROM post p1
это можно убрать так как мы и так в других местах посты выбираем. Оп-пост можно выбрать в том же джойне что выбирает 3 последних поста.
> ORDER BY IF(p1.thread IS NULL, p1.id, p1.thread), p1.date
надо сортировать не по id треда, а по дате бампа треда.
Ну и thread стоило пометить как FOREIGN KEY для защиты от ошибок.
>>481316
Открой отладчик (Ctrl + Shift + I) в браузере и найди. Статья про отладчик: http://learn.javascript.ru/debugging-chrome
>>481330
Архив есть у ОПа. Там на самом деле особой полезной инфы нет, один флуд, а все более-менее информативные вещи уже собраны в гитхабе ОПа: https://gist.github.com/codedokode и https://github.com/codedokode/pasta/
Выкладывать их на отдельный блог нет смысла, так как они и так есть на гитхабе, а потом когда будет время, я их допилю и включу в учебник как дополнительные статьи/уроки.
Ну и они прекрасно гуглятся и индексируются: http://www.google.ru/search?sourceid=chrome&ie=UTF-8&q=inurl%3Acodedokode+site%3Agist.github.com+%D0%B1%D0%B0%D0%B7%D0%B0+%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85 + есть поиск на самом гитхабе.
Ищи лучше, это настройка типа magic_quotes ( http://www.google.ru/search?sourceid=chrome&ie=UTF-8&q=php+ini+magic+quotes ). Видимо она там включена.
>>481412
Это неправильное решение, так как куча копипасты. Сделай в цикле примерно так:
- прибавляем проценты и комиссию к остатку долга
- если остаток маленький, выплачиваем сколько осталось и уходим
- иначе платим 5000
Это задача сложная, на ней все спотыкаются.
> но в функции используется просто айди элемента myVideo?
В древних браузерах если в дереве DOM есть элемент с id, то для него создается одноименная глобальная переменная. Но ты не должен так делать, это дурная практика, дающая хрупкий код и надеюсь в будущем это уберут. В скрипте на сайте опечатка, там должно быть vid.play() и этот код работает только из-за того что новые браузеры пока еще поддерживают совместимость со старыми.
>>481488
> public function makeStep()
Что ты будешь делать если надо будет чуть поменять эту функцию в потомке? Она большая и монолитная, и чтобы поменять, тебе фактически придется копипастить ее.
Я бы разбил ее на вызовы функций:
ходы = найти возможные ходы();
ходы = оценить ходы();
лучший = выбрать лучший ход();
сделать (лучший ход);
Так она во-первых будет короче и читабельнее, во-вторых ее будет легко переопределить.
> Mouse
> protected function estimateStep($step)
> $price += ($horizontalDiff + $verticalDiff) 100;
Кошка может ходить по диагонали и такой подсчет может стоить мышке ее мышиной жизни. Тут лучше использвать функцию max()
> count($visibleCats) 3 < 60 ? $price -= count($visibleCats) * 3 : $price;
это зашифрованный оператор if. Расшифруй его обратно ради читабельности. ?: надо использовать как часть выражения, но не как замену if.
$x = .. ? .. : ..; // это ок
(...) ? $x = 1 : $x = 2; // это не ок
> protected function estimateStep($step)
Тут стоило бы добавить type hint
> Cat
> protected function findAvailableSteps(array $offsets)
> foreach ($availableSteps as $step) {
> if (!$this->field->positionIntersectsDogs($step)) {
> $result[] = $step;
при неудачном стечении обстоятельств мы можем получить пустой массив ходов, твой алгоритм не сломается?
> if ($nearestMouse->isProtected()) {
> $price = -1000;
не очень понятно почему мы так жестоко минусуем ход если эта ближайшая мышь далеко. Мне кажется мы должны исключать (не минусовать) только ход на клетку с защищенной мышью, но ходить рядом с этой мышкой и облизываться нам никто не запрещает (хотя немного минусануть конечно все равно стоит, потому что выгоднее идти к беззащитной мыши).
> if ($this->label === "@") {
лучше было завести флаг isSleeping, а в getLabel написать
return $this->isSleeping? '@' : 'K';
> $haystack = range(0, $this->size);
> if (in_array($x, $haystack)
лучше все же использовать больше-меньше, а то ты массивы создаешь на каждую проверку.
По ссылке https://ideone.com/W2zC1P на 15-16 ходах мышка почему-то ходит влево-вправо, а не бежит от кошки. Видимо, ошибка где-то.
Но вообще, я думаю, наверно хватит мучать эту задачу, внеси правки и переходи к задаче про список студентов из ОП-поста.
> но в функции используется просто айди элемента myVideo?
В древних браузерах если в дереве DOM есть элемент с id, то для него создается одноименная глобальная переменная. Но ты не должен так делать, это дурная практика, дающая хрупкий код и надеюсь в будущем это уберут. В скрипте на сайте опечатка, там должно быть vid.play() и этот код работает только из-за того что новые браузеры пока еще поддерживают совместимость со старыми.
>>481488
> public function makeStep()
Что ты будешь делать если надо будет чуть поменять эту функцию в потомке? Она большая и монолитная, и чтобы поменять, тебе фактически придется копипастить ее.
Я бы разбил ее на вызовы функций:
ходы = найти возможные ходы();
ходы = оценить ходы();
лучший = выбрать лучший ход();
сделать (лучший ход);
Так она во-первых будет короче и читабельнее, во-вторых ее будет легко переопределить.
> Mouse
> protected function estimateStep($step)
> $price += ($horizontalDiff + $verticalDiff) 100;
Кошка может ходить по диагонали и такой подсчет может стоить мышке ее мышиной жизни. Тут лучше использвать функцию max()
> count($visibleCats) 3 < 60 ? $price -= count($visibleCats) * 3 : $price;
это зашифрованный оператор if. Расшифруй его обратно ради читабельности. ?: надо использовать как часть выражения, но не как замену if.
$x = .. ? .. : ..; // это ок
(...) ? $x = 1 : $x = 2; // это не ок
> protected function estimateStep($step)
Тут стоило бы добавить type hint
> Cat
> protected function findAvailableSteps(array $offsets)
> foreach ($availableSteps as $step) {
> if (!$this->field->positionIntersectsDogs($step)) {
> $result[] = $step;
при неудачном стечении обстоятельств мы можем получить пустой массив ходов, твой алгоритм не сломается?
> if ($nearestMouse->isProtected()) {
> $price = -1000;
не очень понятно почему мы так жестоко минусуем ход если эта ближайшая мышь далеко. Мне кажется мы должны исключать (не минусовать) только ход на клетку с защищенной мышью, но ходить рядом с этой мышкой и облизываться нам никто не запрещает (хотя немного минусануть конечно все равно стоит, потому что выгоднее идти к беззащитной мыши).
> if ($this->label === "@") {
лучше было завести флаг isSleeping, а в getLabel написать
return $this->isSleeping? '@' : 'K';
> $haystack = range(0, $this->size);
> if (in_array($x, $haystack)
лучше все же использовать больше-меньше, а то ты массивы создаешь на каждую проверку.
По ссылке https://ideone.com/W2zC1P на 15-16 ходах мышка почему-то ходит влево-вправо, а не бежит от кошки. Видимо, ошибка где-то.
Но вообще, я думаю, наверно хватит мучать эту задачу, внеси правки и переходи к задаче про список студентов из ОП-поста.
Ты тот же анон у которого эта проблема была 2 дня назад или другой?
У тебя не слишком древний PHP? Какая версия? Не лучше ли вместо опенсервера установить Апач + PHP самому? Там будет нужное расширение Intl.
Аноны, вас же тут сидит куча народу, не хотите помочь известному опен сурс проекту и исправить этот баг? Нужно знание ООП, git, github, знание симфони не требуется.
надо сделать следующее:
— отключить в php.ini расширение intl, перезапустить Апач и убедиться что в phpinfo() его нету
— установить Симфони стандартным способом, скачав php-установщик и запустив его из консоли
— открыть скрипт web/config.php в браузере и убедиться что выпадает ошибка как в >>481554 либо белый экран.
— обрадовать/огорчить меня этим фактом
— если ошибки нет, выяснить почему
— если ошибка есть, надо ее исправить. Проблема в файле SymfonyRequirements: https://github.com/sensiolabs/SensioDistributionBundle/blob/master/Resources/skeleton/app/SymfonyRequirements.php#L648
Он пытается проверить есть ли поддержка языков кроме en, и в случае отсуствия расширения intl ( http://php.net/manual/ru/book.intl.php ) класс Collator (который симфони подсовывает вместо того что есть в расширении) выбрасывает исключение: https://github.com/symfony/Intl/blob/master/Collator/Collator.php#L79
Варианты решения:
— переделать код проверки, например вызывая ее только при наличии расширения intl (а в отсутствие его писать другое предупреждение про просьбу его установить)
— ловить исключение (мне не нравится идея)
Также, надо проверить, выводится ли что-то если display_errors стоит в off
После того как будет ясно как это исправить, мы напишем разработчикам симфони и попробуем уговорить принять наш пулл реквест.
Пулл реквест делается так:
— клонируешь репозиторий в свой гитхаб
— клонируешь свой гитзаб на свой компьютер
— исправляешь баг, коппитишь, пушишь
— в своем гитхабе делаешь PR
Что скажете? Есть добровольцы? исправлений там несколько строчек, но проблемы, над которыми придется поломать голову, скорее всего будут.
С английским, описанием бага и уговариванием разработчиков симфони я помогу.
Ты тот же анон у которого эта проблема была 2 дня назад или другой?
У тебя не слишком древний PHP? Какая версия? Не лучше ли вместо опенсервера установить Апач + PHP самому? Там будет нужное расширение Intl.
Аноны, вас же тут сидит куча народу, не хотите помочь известному опен сурс проекту и исправить этот баг? Нужно знание ООП, git, github, знание симфони не требуется.
надо сделать следующее:
— отключить в php.ini расширение intl, перезапустить Апач и убедиться что в phpinfo() его нету
— установить Симфони стандартным способом, скачав php-установщик и запустив его из консоли
— открыть скрипт web/config.php в браузере и убедиться что выпадает ошибка как в >>481554 либо белый экран.
— обрадовать/огорчить меня этим фактом
— если ошибки нет, выяснить почему
— если ошибка есть, надо ее исправить. Проблема в файле SymfonyRequirements: https://github.com/sensiolabs/SensioDistributionBundle/blob/master/Resources/skeleton/app/SymfonyRequirements.php#L648
Он пытается проверить есть ли поддержка языков кроме en, и в случае отсуствия расширения intl ( http://php.net/manual/ru/book.intl.php ) класс Collator (который симфони подсовывает вместо того что есть в расширении) выбрасывает исключение: https://github.com/symfony/Intl/blob/master/Collator/Collator.php#L79
Варианты решения:
— переделать код проверки, например вызывая ее только при наличии расширения intl (а в отсутствие его писать другое предупреждение про просьбу его установить)
— ловить исключение (мне не нравится идея)
Также, надо проверить, выводится ли что-то если display_errors стоит в off
После того как будет ясно как это исправить, мы напишем разработчикам симфони и попробуем уговорить принять наш пулл реквест.
Пулл реквест делается так:
— клонируешь репозиторий в свой гитхаб
— клонируешь свой гитзаб на свой компьютер
— исправляешь баг, коппитишь, пушишь
— в своем гитхабе делаешь PR
Что скажете? Есть добровольцы? исправлений там несколько строчек, но проблемы, над которыми придется поломать голову, скорее всего будут.
С английским, описанием бага и уговариванием разработчиков симфони я помогу.
Какая была версия PHP? Ты не тот анон что пару дней назад получал ту же ошибку с опенсервером?
Хорошо бы выяснить почему. Поставь в php.ini ограничение по времени max_execution_time = 3 и посмотри в каком месте скрипт прервется. Хорошо бы выяснить причину и исправить баг.
То есть история такая:
— проверка if (null === new Collator) была написана когда симфониевского класса-заменителя для Collator не было. Это логично: только встроенный в PHP класс может вернуть null из new, обычный класс так сделать не может
Эта проверка проверяла класс Collator из расширения, корректно ли он поддерживает другие языки кроме английского. Очевидно чтобы обнаруживать кривые версии расширения.
— в Симфони добавили класс Collator поддержиающий только язык en, для тех у кого нет Intl.
— все сломалось для тех у кого нет intl
Я думаю, должно выводиться нормальное предупреждение что без этого расширения многие функции не будут работать и стоит его установить. Ну и если расширения нет то эта проверка делаться не должна.
Ну и как мини-урок для анонов по пользованию гитхабом, смотрите, кнопкой Blame можно увидеть кто и когда добавил эту строчку в файл:
https://github.com/sensiolabs/SensioDistributionBundle/blame/master/Resources/skeleton/app/SymfonyRequirements.php#L648
Там стоит ссылка на коммит https://github.com/sensiolabs/SensioDistributionBundle/commit/0b9fc9dca302748e85deb067e45a63c42a1fb066
Видно что это сделано аж в 2012 году.
>Весь HTML следует помещать отдельно от логики
Эмм, т.е. вырезать весь HTML и вставлять его через include чтоле?
>Ты уверен что это вообще работает?
Да. Если ошибки не вырубить, то при загрузке больших файлов выдается php ошибка которую невозможно поймать, т.к. она появляется еще до загрузки страницы. А если вырубить, то просто ловим ее с выдаем сообщение, мол размер файла превышает максимально допустимый. А вообще у меня на сайте другой .htaccess стоит, так что можешь не обращать на него внимание.
>Суффикс class писали во времена когда классов было мало.
Ок, учту.
>Что делает этот класс?
Ну по сути это тот же config.php, просто названный по другому. Ок, переименую.
>Причем я это вижу уже не первый раз.
Ну лично я это подсмотрел у некоего AutoLineX. Где он это подсмотрел - не знаю.
>Редактор лучше настроить на использование 4 пробелов вместо табов.
У меня и так стоит 4 пробела в табе. Прост я все мелкие правки вношу прям на сайте в встроенном редакторе, наверное из-за этого так пидорасит.
>В этом классе все как-то смешано в кучу.
Ну тащемта я следовал тому уроку про основы ООП. Есть объект "сообщение", у которого есть определенные свойства и методы для работы с этим сообщением. Все верно, не? И никакой работы с GET запросами там нет, я один единственный раз с GET работаю в админке при логауте и все. А про DataMapper интересно, мне понравилось. Покурю эту тему и перепилю на этот лад.
>это неправильный код. Ты просто применяешь к данным все функции, про которые слышал, не пытаясь подумать, а какие и где функции надо применять.
Можешь объяснить почему надо делать именно так? Почему бы сразу при получении данных не фильтровать их и не помещать в базу уже отфильтрованные? Зачем всякий мусор хранить и каждый раз нагружать сервер обработкой этого мусора, если можно сделать это всего один раз? Алсо, вообще понятия не имею что такое плейсхолдеры. Надо погуглить.
>не городи такие вложенные ифы
Окей, переделаю.
>Тут непонятно экранируются данные или нет.
Ну я перед тем, как их внести в $this->something экранировал, посмотри выше по коду.
>Это 100% SQL инъекция
Инъекция от кого, лол? Эта функция для админки, куда имею доступ только я. И выводятся там уже почищенные данные из базы, так что второй раз их чистить при занесении в основную базу я не вижу смысла.
>на «серьезный» в плане качества кода это пока не тянет
Ну под "серьезным" я понимаю, что это не просто сверстанная страничка, а полноценно работающий сайт. Естественно, что я даже и не надеялся, что с первого раза все идеально будет.
>Надпись «play» выпадает
Я фиг знает, тестил на Мозилле, Опере, Хроме, Фаерфоксе и даже IE, везде норм работает на всех разрешениях. Мб это из-за ОСИ?
>Я советую подключать библиотеки со своего сайта
Ок.
>В чем смысл этого скрипта?
А хрен знает, это стандартный бутстраповский. Думаю да, можно удалить, т.к. все равно сайт работать не сможет на старых браузерах, так что поддерживать их хоть в чем-то смысла нет. Можно в принципе вообще уведомление выдавать, мол для пользования сайтом нужен более современный браузер.
>Стили надо компилировать при деплое на сервер
Точняк, совсем забыл про это. А ведь хотел это сделать, но чет из головы вылетело.
>Вот это неправильно. Браузер дает возможность сделать текстареа удобного размера, а ты ее отбираешь.
Окей, верну растягивание по вертикали. Просто если еще по горизонтали врубить, то можно всю верстку распидорасить.
>Файл подключен 2 раза
Это два разных файла на самом деле. Который в папке vendor находится нужен для работы плагина Form Validation. Я правда не понимаю, почему они название файла сделали таким, неужели так сложно переименовать?
>И еще я заметил что сайт загружает 2720 Кб файлов
Окей, постараюсь поужать картинки и прочее.
>>482624
>Не надо писать магические числа, там есть константы
Т.е. можно вместо чисел константы писать или что? Но ведь в ячейке хранится число, а не константа. Как проверять то?
>Там какой-то адски неэффективный запрос на выборку.
Лол, я из этой статьи и взял запрос. А то, что ты предлагаешь не очень, т.к. не учитывает дыры в таблицах. И чем больше этих дыр, тем хуже работает выдача случайной вебмки. Этот генератор псевдослучайных чисел сам по себе не очень, даже в таблице без дыр, а с ними вообще пиздец будет, я уже тестил на локалке, одна и та же вебмка 5 раз подряд выпадает и это из выборки почти в 30 штук.
>Это кошмар какой-то. еще addslashes не хватает.
А какие еще варианты, если я хочу удалить из текста все теги и код?
>Это плохая идея называть файлы с помощью md5. Какая от этого выгода? Как ты будешь них потом ориентироваться?
А зачем мне в них ориентироваться? Такой задачи не стоит. Пользователь по идее вообще не должен видеть названия файлов, разве что только при сохранении. Ну там уж пусть сам называет файл как ему удобно.
В общем создал список того, что нужно переделать и скоро приступлю к работе. Спасибо за критику, ОПчик :3
>Весь HTML следует помещать отдельно от логики
Эмм, т.е. вырезать весь HTML и вставлять его через include чтоле?
>Ты уверен что это вообще работает?
Да. Если ошибки не вырубить, то при загрузке больших файлов выдается php ошибка которую невозможно поймать, т.к. она появляется еще до загрузки страницы. А если вырубить, то просто ловим ее с выдаем сообщение, мол размер файла превышает максимально допустимый. А вообще у меня на сайте другой .htaccess стоит, так что можешь не обращать на него внимание.
>Суффикс class писали во времена когда классов было мало.
Ок, учту.
>Что делает этот класс?
Ну по сути это тот же config.php, просто названный по другому. Ок, переименую.
>Причем я это вижу уже не первый раз.
Ну лично я это подсмотрел у некоего AutoLineX. Где он это подсмотрел - не знаю.
>Редактор лучше настроить на использование 4 пробелов вместо табов.
У меня и так стоит 4 пробела в табе. Прост я все мелкие правки вношу прям на сайте в встроенном редакторе, наверное из-за этого так пидорасит.
>В этом классе все как-то смешано в кучу.
Ну тащемта я следовал тому уроку про основы ООП. Есть объект "сообщение", у которого есть определенные свойства и методы для работы с этим сообщением. Все верно, не? И никакой работы с GET запросами там нет, я один единственный раз с GET работаю в админке при логауте и все. А про DataMapper интересно, мне понравилось. Покурю эту тему и перепилю на этот лад.
>это неправильный код. Ты просто применяешь к данным все функции, про которые слышал, не пытаясь подумать, а какие и где функции надо применять.
Можешь объяснить почему надо делать именно так? Почему бы сразу при получении данных не фильтровать их и не помещать в базу уже отфильтрованные? Зачем всякий мусор хранить и каждый раз нагружать сервер обработкой этого мусора, если можно сделать это всего один раз? Алсо, вообще понятия не имею что такое плейсхолдеры. Надо погуглить.
>не городи такие вложенные ифы
Окей, переделаю.
>Тут непонятно экранируются данные или нет.
Ну я перед тем, как их внести в $this->something экранировал, посмотри выше по коду.
>Это 100% SQL инъекция
Инъекция от кого, лол? Эта функция для админки, куда имею доступ только я. И выводятся там уже почищенные данные из базы, так что второй раз их чистить при занесении в основную базу я не вижу смысла.
>на «серьезный» в плане качества кода это пока не тянет
Ну под "серьезным" я понимаю, что это не просто сверстанная страничка, а полноценно работающий сайт. Естественно, что я даже и не надеялся, что с первого раза все идеально будет.
>Надпись «play» выпадает
Я фиг знает, тестил на Мозилле, Опере, Хроме, Фаерфоксе и даже IE, везде норм работает на всех разрешениях. Мб это из-за ОСИ?
>Я советую подключать библиотеки со своего сайта
Ок.
>В чем смысл этого скрипта?
А хрен знает, это стандартный бутстраповский. Думаю да, можно удалить, т.к. все равно сайт работать не сможет на старых браузерах, так что поддерживать их хоть в чем-то смысла нет. Можно в принципе вообще уведомление выдавать, мол для пользования сайтом нужен более современный браузер.
>Стили надо компилировать при деплое на сервер
Точняк, совсем забыл про это. А ведь хотел это сделать, но чет из головы вылетело.
>Вот это неправильно. Браузер дает возможность сделать текстареа удобного размера, а ты ее отбираешь.
Окей, верну растягивание по вертикали. Просто если еще по горизонтали врубить, то можно всю верстку распидорасить.
>Файл подключен 2 раза
Это два разных файла на самом деле. Который в папке vendor находится нужен для работы плагина Form Validation. Я правда не понимаю, почему они название файла сделали таким, неужели так сложно переименовать?
>И еще я заметил что сайт загружает 2720 Кб файлов
Окей, постараюсь поужать картинки и прочее.
>>482624
>Не надо писать магические числа, там есть константы
Т.е. можно вместо чисел константы писать или что? Но ведь в ячейке хранится число, а не константа. Как проверять то?
>Там какой-то адски неэффективный запрос на выборку.
Лол, я из этой статьи и взял запрос. А то, что ты предлагаешь не очень, т.к. не учитывает дыры в таблицах. И чем больше этих дыр, тем хуже работает выдача случайной вебмки. Этот генератор псевдослучайных чисел сам по себе не очень, даже в таблице без дыр, а с ними вообще пиздец будет, я уже тестил на локалке, одна и та же вебмка 5 раз подряд выпадает и это из выборки почти в 30 штук.
>Это кошмар какой-то. еще addslashes не хватает.
А какие еще варианты, если я хочу удалить из текста все теги и код?
>Это плохая идея называть файлы с помощью md5. Какая от этого выгода? Как ты будешь них потом ориентироваться?
А зачем мне в них ориентироваться? Такой задачи не стоит. Пользователь по идее вообще не должен видеть названия файлов, разве что только при сохранении. Ну там уж пусть сам называет файл как ему удобно.
В общем создал список того, что нужно переделать и скоро приступлю к работе. Спасибо за критику, ОПчик :3
> Эмм, т.е. вырезать весь HTML и вставлять его через include чтоле?
Да, вынести в отдельный файл и инклудить. И заодно почистить копипасту, там есть куски HTML скопированные, вроде шапки по моему.
> Ну по сути это тот же config.php, просто названный по другому
> Можешь объяснить почему надо делать именно так?
Когда ты экранируешь данные там где они используются мы сразу видим есть защита или нет. В твоем случае это не видно и надо полностью анализировать как данные проходят через все функции. В твоем маленьком приложении это еще реально, на обычных сайтах где кода в 10-100 раз больше это нереально потому там куча дыр и уязвимостей.
> Почему бы сразу при получении данных не фильтровать их и не помещать в базу уже отфильтрованные?
Потому что фильтрация разная для разных целей. Если ты выводишь данные ты используешь htmlspecialchars, если вставляешь в базу то real-escape или плейсхолдеры, если в JSON то ничего делать не надо. Как ты это реализуешь? Будешь хранить по 3 варианта каждого поля?
Также, это корежит данные. Например strip_tags обрежет фразу «Если a<b то надо вызвать функцию», проверь сам. Твой подход приведет к тому что некоторые символы просто будут теряться или искажаться. А общепринятый подход к тому что все будет передаваться в точности.
Также, функции обрезки по длине не будут работать. если ты закодируешь специсмволы через htmkspecialchars то обрезка по длине может разрезать спецсимвол вроед & пополам.
По всем этим признакам кстати легко увидеть сайты которые неправильно обрабатывают данные.Я видел сайты которые зачем-то перед кавычками например бекслеши вставляют, итд.
> Зачем всякий мусор хранить
Откуда ты знаешь что это мусор? В названии могут быть самые разные символы, включая например значки, арабский шрифт или иероглифы. Кроме того как я понимаю, у тебя модерация и модератор всегда может не принять мусор.
> каждый раз нагружать сервер обработкой этого мусора,
зачем вообще нагружать сервер? Давай просто сделаем скрипт из одной строчки:
echo "Все сохранено успешно";
А если серьезно, ты мерял насколько именно это нагружает сервер и сколько процентов от времени работы скрипта приходится на экранирование? Если нет то советую сначала померять а потом мы сможем обсудить как можно этот процент снизить.
> если можно сделать это всего один раз
нельзя, я написал выше почему
> Эмм, т.е. вырезать весь HTML и вставлять его через include чтоле?
Да, вынести в отдельный файл и инклудить. И заодно почистить копипасту, там есть куски HTML скопированные, вроде шапки по моему.
> Ну по сути это тот же config.php, просто названный по другому
> Можешь объяснить почему надо делать именно так?
Когда ты экранируешь данные там где они используются мы сразу видим есть защита или нет. В твоем случае это не видно и надо полностью анализировать как данные проходят через все функции. В твоем маленьком приложении это еще реально, на обычных сайтах где кода в 10-100 раз больше это нереально потому там куча дыр и уязвимостей.
> Почему бы сразу при получении данных не фильтровать их и не помещать в базу уже отфильтрованные?
Потому что фильтрация разная для разных целей. Если ты выводишь данные ты используешь htmlspecialchars, если вставляешь в базу то real-escape или плейсхолдеры, если в JSON то ничего делать не надо. Как ты это реализуешь? Будешь хранить по 3 варианта каждого поля?
Также, это корежит данные. Например strip_tags обрежет фразу «Если a<b то надо вызвать функцию», проверь сам. Твой подход приведет к тому что некоторые символы просто будут теряться или искажаться. А общепринятый подход к тому что все будет передаваться в точности.
Также, функции обрезки по длине не будут работать. если ты закодируешь специсмволы через htmkspecialchars то обрезка по длине может разрезать спецсимвол вроед & пополам.
По всем этим признакам кстати легко увидеть сайты которые неправильно обрабатывают данные.Я видел сайты которые зачем-то перед кавычками например бекслеши вставляют, итд.
> Зачем всякий мусор хранить
Откуда ты знаешь что это мусор? В названии могут быть самые разные символы, включая например значки, арабский шрифт или иероглифы. Кроме того как я понимаю, у тебя модерация и модератор всегда может не принять мусор.
> каждый раз нагружать сервер обработкой этого мусора,
зачем вообще нагружать сервер? Давай просто сделаем скрипт из одной строчки:
echo "Все сохранено успешно";
А если серьезно, ты мерял насколько именно это нагружает сервер и сколько процентов от времени работы скрипта приходится на экранирование? Если нет то советую сначала померять а потом мы сможем обсудить как можно этот процент снизить.
> если можно сделать это всего один раз
нельзя, я написал выше почему
Окей, я понял про что ты. Скажи только, какие функции использовать при добавлении в базу кроме mysqlrealescape чтобы мой сайт не распидорасило. Или только ее достаточно, а остальное юзать уже при выводе?
> Ну по сути это тот же config.php, просто названный по другому
В конфиге нет кода, только переменные вроде
$dbname = '...';
Идея в том что для разворачивания проекта или смены настроек не надо трогать код.
> Ну тащемта я следовал тому уроку про основы ООП. Есть объект "сообщение", у которого есть определенные свойства и методы для работы с этим сообщением. Все верно, не?
да, верно, но там еще есть другие принципы. Например каждый класс должен заниматься своим делом и класс работающий с базой данных про глобальные переменные вроде GET даже знать не должен. Ну и модель лучше отделить от кода работы с базой данных, так как работа с базой тянет на отдельную задачу.
> Ну я перед тем, как их внести в $this->something экранировал, посмотри выше по коду.
Ну вот, а надо чтобы было сразу видно а не надо было изучать весь твой код и проверять все ли варианты ты проверил.
> Инъекция от кого, лол? Эта функция для админки, куда имею доступ только я. И выводятся там уже почищенные данные из базы, так что второй раз их чистить при занесении в основную базу я не вижу смысла.
Проще всегда чистить чем вспоминать где и как они почищены. Твой подход неправильный и небезопасный так как он полагается на всякие «если» вместо того чтобы гарантировать что инъекция невозможна. Плюс, завтра ты поменяешь код и окажется что эта функция вызывается еще откуда-нибудь.
Ну и у тебя наверно нет защиты от CSRF а это значит, заманив тебя на поддельную страницу можно отправить в админку любой запрос: https://github.com/codedokode/pasta/blob/master/security/xsrf.md
Я тебе советую не изобретать своих альтернативных способов защиты от уязвимостей, а использовать общепринятые, а если они чем-то плохи то аргументированно объясни чем именно.
> Я фиг знает, тестил на Мозилле, Опере, Хроме, Фаерфоксе и даже IE, везде норм работает на всех разрешениях. Мб это из-за ОСИ?
Я бы сделал скриншот, но сайт не открывается. Сделаю потом тогда.
> умаю да, можно удалить, т.к. все равно сайт работать не сможет на старых браузерах, так что поддерживать их хоть в чем-то смысла нет.
этот скрипт включает поддержку адаптивности для старых ИЕ, но я не понимаю зачем это нужно так как старые ИЕ все равно только на десктопе используются.
> Просто если еще по горизонтали врубить, то можно всю верстку распидорасить.
ты же верстальщик, сделай чтобы тянулось или хотя бы чтобы это ни на что не влияло. Ну и мое мнение, лучше растягивать слегка сломав верстку чем не иметь возможности растягивать вообще.
> Окей, постараюсь поужать картинки и прочее.
Если ты вдруг не знал, то отладчик в браузере Ctrl + Shift + I на вкладке Network показывает вес файлов.
> Т.е. можно вместо чисел константы писать или что? Но ведь в ячейке хранится число, а не константа.
Константа это и есть число.
Сделай echo UPLOAD_ERR_FORM_SIZE; или var_dump(UPLOAD_ERR_FORM_SIZE) и посмотри сам.
Алсо почитай мануал http://php.net/manual/ru/language.constants.php
Алсо замени числа на константы и посмотри насколько понятнее стал код.
> А то, что ты предлагаешь не очень, т.к. не учитывает дыры в таблицах.
Потому я предлагаю не использовать id а сделать колонку из случайных чисел которые по определению распределены примерно равномерно (по крайней мере на большом числе записей). Можно еще кроном раз в сутки или в неделю их менять для надежности.
Твой запрос будет тяжелым на большом числе записей, хотя это конечно лучше не гадать а проверять и смотреть EXPLAIN
> А какие еще варианты, если я хочу удалить из текста все теги и код?
А зачем их удалять? Если ты экранируешь все при выводе то они просто выведутся как текст. Ну и ты как модератор их же все равно не пропустишь наверно.
> А зачем мне в них ориентироваться? Такой задачи не стоит.
«А зачем мне исправлять ошибку если из за нее какие-то файлы не туда сохранились? пусть лежат как лежали». Это очень недальновидный подход, ведь разбираться в этих именах при проблеме придется только тебе, а не кому-то еще. Я вообще не понимаю это нездоровое влечение к именам из хешей, что в них вообще хорошего? даже просто id или дата загрузки уже лучше чем этот хеш.
> Пользователь по идее вообще не должен видеть названия файлов,
Это для тебя а не для пользователя
> разве что только при сохранении. Ну там уж пусть сам называет файл как ему удобно.
Если у тебя есть возможность сохранения, имена при сохранении надо давать нормальные. Почему пользователь должен вбивать имя файла если это может сделать железяка?
> Ну по сути это тот же config.php, просто названный по другому
В конфиге нет кода, только переменные вроде
$dbname = '...';
Идея в том что для разворачивания проекта или смены настроек не надо трогать код.
> Ну тащемта я следовал тому уроку про основы ООП. Есть объект "сообщение", у которого есть определенные свойства и методы для работы с этим сообщением. Все верно, не?
да, верно, но там еще есть другие принципы. Например каждый класс должен заниматься своим делом и класс работающий с базой данных про глобальные переменные вроде GET даже знать не должен. Ну и модель лучше отделить от кода работы с базой данных, так как работа с базой тянет на отдельную задачу.
> Ну я перед тем, как их внести в $this->something экранировал, посмотри выше по коду.
Ну вот, а надо чтобы было сразу видно а не надо было изучать весь твой код и проверять все ли варианты ты проверил.
> Инъекция от кого, лол? Эта функция для админки, куда имею доступ только я. И выводятся там уже почищенные данные из базы, так что второй раз их чистить при занесении в основную базу я не вижу смысла.
Проще всегда чистить чем вспоминать где и как они почищены. Твой подход неправильный и небезопасный так как он полагается на всякие «если» вместо того чтобы гарантировать что инъекция невозможна. Плюс, завтра ты поменяешь код и окажется что эта функция вызывается еще откуда-нибудь.
Ну и у тебя наверно нет защиты от CSRF а это значит, заманив тебя на поддельную страницу можно отправить в админку любой запрос: https://github.com/codedokode/pasta/blob/master/security/xsrf.md
Я тебе советую не изобретать своих альтернативных способов защиты от уязвимостей, а использовать общепринятые, а если они чем-то плохи то аргументированно объясни чем именно.
> Я фиг знает, тестил на Мозилле, Опере, Хроме, Фаерфоксе и даже IE, везде норм работает на всех разрешениях. Мб это из-за ОСИ?
Я бы сделал скриншот, но сайт не открывается. Сделаю потом тогда.
> умаю да, можно удалить, т.к. все равно сайт работать не сможет на старых браузерах, так что поддерживать их хоть в чем-то смысла нет.
этот скрипт включает поддержку адаптивности для старых ИЕ, но я не понимаю зачем это нужно так как старые ИЕ все равно только на десктопе используются.
> Просто если еще по горизонтали врубить, то можно всю верстку распидорасить.
ты же верстальщик, сделай чтобы тянулось или хотя бы чтобы это ни на что не влияло. Ну и мое мнение, лучше растягивать слегка сломав верстку чем не иметь возможности растягивать вообще.
> Окей, постараюсь поужать картинки и прочее.
Если ты вдруг не знал, то отладчик в браузере Ctrl + Shift + I на вкладке Network показывает вес файлов.
> Т.е. можно вместо чисел константы писать или что? Но ведь в ячейке хранится число, а не константа.
Константа это и есть число.
Сделай echo UPLOAD_ERR_FORM_SIZE; или var_dump(UPLOAD_ERR_FORM_SIZE) и посмотри сам.
Алсо почитай мануал http://php.net/manual/ru/language.constants.php
Алсо замени числа на константы и посмотри насколько понятнее стал код.
> А то, что ты предлагаешь не очень, т.к. не учитывает дыры в таблицах.
Потому я предлагаю не использовать id а сделать колонку из случайных чисел которые по определению распределены примерно равномерно (по крайней мере на большом числе записей). Можно еще кроном раз в сутки или в неделю их менять для надежности.
Твой запрос будет тяжелым на большом числе записей, хотя это конечно лучше не гадать а проверять и смотреть EXPLAIN
> А какие еще варианты, если я хочу удалить из текста все теги и код?
А зачем их удалять? Если ты экранируешь все при выводе то они просто выведутся как текст. Ну и ты как модератор их же все равно не пропустишь наверно.
> А зачем мне в них ориентироваться? Такой задачи не стоит.
«А зачем мне исправлять ошибку если из за нее какие-то файлы не туда сохранились? пусть лежат как лежали». Это очень недальновидный подход, ведь разбираться в этих именах при проблеме придется только тебе, а не кому-то еще. Я вообще не понимаю это нездоровое влечение к именам из хешей, что в них вообще хорошего? даже просто id или дата загрузки уже лучше чем этот хеш.
> Пользователь по идее вообще не должен видеть названия файлов,
Это для тебя а не для пользователя
> разве что только при сохранении. Ну там уж пусть сам называет файл как ему удобно.
Если у тебя есть возможность сохранения, имена при сохранении надо давать нормальные. Почему пользователь должен вбивать имя файла если это может сделать железяка?
Используй плейсхолдеры и база будет принимать любые данные (при условии что они нужного типа и длины). Ссылки про плейсхолдеры где-то в моем посте.
При выводе делай как описано в уроке https://github.com/codedokode/pasta/blob/master/security/xss.md
Кстати strip_tags не защищает от инъекции через атрибут тега так как там используются кавычки а не угловые скобки
> только ее достаточно, а остальное юзать уже при выводе?
Да только прочти сначала урок про XSS
>В конфиге нет кода, только переменные вроде
Т.е. в конфиге просто данные какие-то хранить, а подключение к базе в другом классе выполнять?
>да, верно, но там еще есть другие принципы.
Ну там ничего про это написано не было. И в тех уроках которые я смотрел тоже. И не было там никаких GETов, говорю же.
>Проще всегда чистить чем вспоминать где и как они почищены.
Кароч понятно, лучше перебдеть, чем недобдеть.
>Потому я предлагаю не использовать id
Не могу понять, чем это лучше текущего варианта. Он просто генерит случайное число от 1 до максимального количества строк в таблице и если строки с таким числом нет, то берет ближайшую к ней строку. Разве это тяжелая операция?
>А зачем мне исправлять ошибку если из за нее какие-то файлы не туда сохранились?
Не знаю, мне нравятся имена файлов в виде хешей. И мне удобно с ними. Так что пускай остаются такими. Следующим сайтом буду файлообменник делать, там уже иначе сделаю.
>Если у тебя есть возможность сохранения, имена при сохранении надо давать нормальные.
Что значит "нормальные"? Когда название файла говорит о его содержимом? Ну такое я чет нигде не видел. На том же Дваче вон названия у всех файлов вообще из одних цифр состоят, это нормальное название?
>>482653
>>482654
>>482656
Окей, гляну что это.
>В конфиге нет кода, только переменные вроде
Т.е. в конфиге просто данные какие-то хранить, а подключение к базе в другом классе выполнять?
>да, верно, но там еще есть другие принципы.
Ну там ничего про это написано не было. И в тех уроках которые я смотрел тоже. И не было там никаких GETов, говорю же.
>Проще всегда чистить чем вспоминать где и как они почищены.
Кароч понятно, лучше перебдеть, чем недобдеть.
>Потому я предлагаю не использовать id
Не могу понять, чем это лучше текущего варианта. Он просто генерит случайное число от 1 до максимального количества строк в таблице и если строки с таким числом нет, то берет ближайшую к ней строку. Разве это тяжелая операция?
>А зачем мне исправлять ошибку если из за нее какие-то файлы не туда сохранились?
Не знаю, мне нравятся имена файлов в виде хешей. И мне удобно с ними. Так что пускай остаются такими. Следующим сайтом буду файлообменник делать, там уже иначе сделаю.
>Если у тебя есть возможность сохранения, имена при сохранении надо давать нормальные.
Что значит "нормальные"? Когда название файла говорит о его содержимом? Ну такое я чет нигде не видел. На том же Дваче вон названия у всех файлов вообще из одних цифр состоят, это нормальное название?
>>482653
>>482654
>>482656
Окей, гляну что это.
> Не могу понять, чем это лучше текущего варианта. Он просто генерит случайное число от 1 до максимального количества строк в таблице и если строки с таким числом нет, то берет ближайшую к ней строку. Разве это тяжелая операция?
Я тебя не понимаю. 2 поста назад ты пишешь что при выборке по случайному id получаются повторы, но твой SQL код делает то же самое.
Я предлагаю другое. Ты видимо мой пост по диагонали прочел, я предложил сделать колонку и заполнять ее случайными числами и выбирать не по id (который может быть с дырками) а по этим числам.
> На том же Дваче
Это из вакабы, и там не случайные числа, а по моему время загрузки в виде таймстампа. Это не нормальное название, потому при каких-то проблемах эти файлы просто удалят не разбираясь.
> Что значит "нормальные"? Когда название файла говорит о его содержимом?
Для тебя это значит что когда ты откроешь папку с 10 000 файлов ты сможешь легко в ней ориентироваться.
Для пользователя, скачавшего файл, нормальное имя это «Смешное видео про котят.webm» а не «212312312313123» в которых потом не разобраться.
> Не знаю, мне нравятся имена файлов в виде хешей. И мне удобно с ними
Ок, это твое дело.
>>да, верно, но там еще есть другие принципы.
> Ну там ничего про это написано не было. И в тех уроках которые я смотрел тоже. И не было там никаких GETов, говорю же.
Значит их авторы сами ООП не осилили если такому учат.
> И не было там никаких GETов, говорю же.
Действительно, я ошибся. Там POST:
https://github.com/Nattpyre/randomwebm/blob/master/classes/message.class.php#L14
Алсо FILES:
https://github.com/Nattpyre/randomwebm/blob/master/classes/webm.class.php#L38
А, все понял про что ты. Просто я не знал, что такое индексация и поэтому как-то это слово мимо глаз прошло. Ну так то да, с индексацией быстрее работать будет. Ок, переделаю, спасибо за совет.
Мне лично все равно как файлы называются, честно. А для пользователя тут мне кажется нереально осмысленное имя дать, т.к. все видео без имени. Так что оставлю все как есть. Вернее можно конечно при модерации ручками каждому видео название давать, но это явно лишнее.
>>482667
Ну не нашел я нормальных учителей, чтобы грамотно от А до Я php научили. А хватая обрывки из различных статей в гугле цельной картины не получишь. Вот и приходится довольствоваться чем есть, набивая шишки об устаревшие данные и прочую фигню.
> Просто я не знал, что такое индексация и поэтому как-то это слово мимо глаз прошло. Ну так то да, с индексацией быстрее работать будет.
Не, ты не понял по моему, дело не в индексации, тем более что по id тоже есть индекс. дело в распределении id и случайных чисел, но это уже математика.
> Ну не нашел я нормальных учителей, чтобы грамотно от А до Я php научили. А хватая обрывки из различных статей в гугле цельной картины не получишь. Вот и приходится довольствоваться чем есть, набивая шишки об устаревшие данные и прочую фигню.
Да, есть такая проблема, хороших мануалов, тем более на русском, мало. Я обычно советую почитать сайт phptherightway, он есть на русском и там пытаются как раз описать некоторые вещи которым старые учебники и статьи не учат.
Ну как я понял там суть в том, что ID железно привязывается к строке, а это число rand нет и оно может спокойно меняться при удалении какой-либо строки и из-за этого дыр не будет, следовательно можно упростить запрос, убирая проверку на дыры.
>>482677
Да мне бы хотя бы базовые знания получить, чтобы на работу взяли джуниором. А там уже думаю натаскают. Тем более мне больше фрондэнд нравится, так что я думаю особо в php углубляться не буду.
спасибо ОП, наверное, я слишком тупой раз уж тебя даже доконал с этой задачей. А почему не нужно решать задачу по REST-сервису? Я уж было начал подтягивать теорию по этой части.
Она там не очень удачная, вызывает сложности, и ее лучше вообще переделать. Задача про студентов и файлообменник лучше.
Это олимпиадная хуйня. Там не думать надо, а знать алгоритм. Не зная алгоритма, ты ничего не решишь. А конкретный алгоритм тянет на научную статью с доказательством сложности и прочим матаном. Что-то пытаться вывести - это строить велосипед, который заведомо будет говнецом (если ты не всерос по матеше хотя бы). Фактически это математика + надрочка быстро писать алгоритмы (и копипастить). Ну и код таких олимпиадников ужасный, если не переучиваются. Я всю эту кухню изнутри уже прознал.
мимо другой анон, в группе одни олимпиадники
>Еще непонятно, зачем делать 2 запроса. Мне кажется, тут что-то не так с логикой, потому что для проверки есть такой email или нет, достаточно 1 запроса. Чтобы при редактировании разрешить использовать свой же email ты можешь просто дописать условие:
Там бы хватило одной, но я эту проверку использую как для регистрации так и для редактирования, то-есть проверка на существование эмейла в бд уже ничего не даст как как вернет true, поэтому и добавил проверку на существование эмейла и совпадение с паролем во втором случае.
Тогда лучше сделать выбор: если регистрация, то делаем один запрос, если редактирование то другой, а не оба сразу.
Но там же через if идет условие, и выполняется либо первая часть при регистрации либо низ при редактировании.
Ты мне скажи , как вывести данные? preg_match_all просто подсчитывает несовпадения и выводит только количество. А как сделать , чтобы выводилось конкретно то что не совпало ?
Как передать параметр при присваивании событию функции?
Вот у меня есть переменная levelOfDifficulty.
При событии на определенном элементе в эту переменную должно прийти значение:
selectEl.onchanche = function(){ lod = newValue; };
А если мне понадобится вынести функцию в библиотеку?
var lod = selectEl.value;
select.onchange = changeLOD;
function changeLOD(){ lod = newValue; }
Если оставить без параметра (в надежде на зымыкание),
то нельзя переименовать переменную в коде. Значит нужно
function changeLOD(lod){ lod = newValue; }
Эта функция требует параметр, как мне его передать?
Используй замыкание, алсо лучше использовать addEventListener.
...addEventListener(...function (e) {
callSomething(e, a, b, c, d);
});
Это если я правильно понял, что ты хочешь сделать. Не уверен что я правильно тебя понял, но если тебе надо какую-то переменную менять что тебе мешает менять ее в библиотеке?
Я имел ввиду ссылку на переменную.
Еще раз, допустим у нас есть переменная
var x = 0;
и функция в библиотеке
function changeValue(variable){
variable = newValue;
}
Я хочу, чтобы при срабатывании какого-то события менялось значение этой переменной.
var x = 0;
el.onclick = changeValue;
Как мне туда мой x передать?
Ну я пока оставлю тупо
var x = 0;
el.onclick = function(){x = el.value};
Но мне кажется это как-то некорректно. Функция может разрастись на много строк, ее нужно вынести в библиотеку, но тогда придется следить, чтобы имя переменной в глобальном коде и внутри функции совпадало. Что-то неуниверсально.
>У меня тут возникла такая мысль. Давай попробуем сделать сначала только часть задания, но зато сделаем ее идеально. Давай ты сначала сделаешь только просмотр и поиск студентов, без регистрации и редактирования (все что к ним относится пока нужно убрать в отдельную папку), исправишь все замечания, а потом добавишь регистрацию/редактирование. Так мне придется проверять меньше кода, а для тебя будет меньше исправлять. Хорошо?
Мне новый репозиторий создать для этого или старый как-то редактировать?
>что тебе мешает менять переменную в библиотеке
А если у меня десять переменных, каждую из которых нужно пропустить через одну и ту же функцию?
Не писать же каждый раз
var x = 0;
el1.onclick = function(){ x = el1.value; };
var y = 'hello world';
el2.onclick = function(){ y = el2.value; };
...
> Как мне туда мой x передать?
Никак не передать. Но ты можешь менять переменную которая в библиотеке.
И вообще, ты неправильно мыслишь, передавать надо не переменную, а функцию которая будет вызываться при изменении.
>>482806
Можно просто лишний код убрать в папку вроде old или как-то так. Потом достанешь обратно если понадобится.
>>482807
> А если у меня десять переменных, каждую из которых нужно пропустить через одну и ту же функцию?
То ты что-то делаешь неправильно. Зачем ставить 10 однотипных обработчиков событий когда можно поставить один на родительсвом элементе? Почитай на learn.javascript.ru про всплытие событий.
Ну ладно, проехали. Просто ты мне говорил в прошлый раз избегать конструкций типа
obj.method = function(){
....
много букв
....
};
было бы удобнее написать
obj.method = foo;
function foo(){......}
>можешь менять переменную которая в библиотеке
Не универсально как-то. Тогда в глобальном коде придется называть переменные так же, как и в функциях ради замыкания.
Или лезть в библиотеку и переименовывать переменные в функции.
Ну ладно, не будем вскрывать эту тему.
Мне просто не хочется потом переделывать охулиард замечаний к коду, поэтому я вбрасываю постепенно.
К такому куску кода ты наверняка придерешься:
var selectElement = document.getElementById("levelOfDifficulty");
var levelOfDifficulty = selectElement.value;
selectElement.onchange = function(){
levelOfDifficulty = selectElement.value;
};
Как исправить? Эту повторяющуюся строчку вынести в функцию?
> Просто ты мне говорил в прошлый раз избегать конструкций типа
наверно я говорил это про случаи когда большая вложенность, функции внутри функций внутри функций.
Ради одной строчки наверно смысла нет функцию создавать. Пиши пока так.
Но если у тебя много однотипных элементов, то надо как-то обрабатывать события одним обработчиком а не плодить 10 одинаковых.
Да, по умолчанию не хватает библиотеки intl.
На убунту решается одной строкой:
apt-get install php5-intl
Потом просит только прописать таймзону.
>— переделать код проверки, например вызывая ее только при наличии расширения intl
Не моего ума дело.
Паскаль был в школе, но первым серьезным языком стал С. Когда пришел в пхп, как будто руки связали. Так и хочется тип переменной объявить или память вручную выделить под массив.
Хочешь немного подзаработать (2к рублей) и одновременно помочь студенту?
Напиши на мыло qwertykraken@yandex.ru
Хуячил на паскале в универе, никакой радости не испытывал совсем. Только тысячи костылей и велосипедов, но признаю что в Lazarus и Delphi можно охуенно быстро делать GUI-приложения, впрочем, на C# тоже можно.
Впрочем, не буду отрицать что это возможно из-за самих задачек. Всё таки делать всякие унылые лабы где надо хуячить векторы-множества-массивы-интегралы-нарисуйте лемнискату Бернулли-етц.
Короче, от таких задачек уровня б, особенно когда осознаешь их бесполезность начинает гореть жопа.
Кек, дебилушка, я вообще мимокрок и ООП-макакич на джаве. Просто вспомнил прекрасные времена, когда ты хуячишь лабы на паскале и С++, а потом с удивлением узнаёшь что к реальным задачам они совсем никак не относятся и ты считай выучил только базовый синтаксис уровня кодеакадеми и если повезёт - бинарный поиск и не только сортировку пузырьком.
А ты наверное любитель навернуть ОЛИМПИАДНОГО ПРОГРАММИРОВАНИЯ с лопаты? Потому что типичный лабы которые делают в универе максимум на эту парашу и тянут.
Ну, орангутанги будут умнее большинства посетителей зк. Например, точно умнее байтоебов и рубистов. Да чего уж там, они и коллеги-шимпанзе могут даже в космос полететь, а у байтоебов переполнение.
Пытался под чужую структуру адаптировать, но хуйня получается.
>>482679-кун
Слушай, подскажи, как стать такой же джавомакакой? Подозреваю, что вузовские лабы - совсем не то. На чем тренироваться тогда?
сделай прототип можно даже не своей аппы. просто какой-нибудь.
чтобы у тебя был темплейт, который обрабатывается, и роут\контроллер, который роутиться в темплейт, а потом к нему добавишь модель, и возможность вносить изменения.Минимум. Все остальное выкинуть.
после этого у тебя будет просветление, и быстро захуячишь то что нужно для своей аппы.
Суть больших проблем, в том что сложно их решить когда они большие. если уложить их минимум, и постемено наращивать функционал то будет заебись...
научился из /pa доски.
Там сначала делают недоподобие фигуры, а потом уже добавляют цвета и детали и фотошоп.
Видео от Yakov Fain и Головача. Там очень много часов, но они реально полезны на 11 из 10
Стандартный набор книг:
Хорстманн К., Корнелл Г. - Java. Библиотека профессионала
Шилдт - Java 8. Полное руководство
Блох Джошуа - Java. Эффективное программирование
ну и библия.
Параллельно понятное дело писать код, много кода. Пилишь парочку пет-проектов на гитхабе и начинаешь штурмовать вакансии. PHP и Java лидеры среди trainee и junior вакансий.
Ой, перемкнуло меня что-то. Хотел написать "Философия Java", её имел ввиду.
Да. Сейчас устроился на 300. Учил джаву, потом подвернулся заказ на несколько десятков баксов на пыхе, сделал. Подал резюме на джине, пришло два офера, по одному из них устроился.
Круто тебе. Мне во первых, надо съебывать потому, что в провинции по анализу данных или биг дате ваканский не будет, во вторых, закончить универ, что бы попасть в джуниоры туда или хотя бы на последнем курсе быть.
Я прогал всегда просто так, а сейчас деньги понадобились
Сомневаюсь, опчик больше на филантропа похож. Мне опчик мог только ссылочками в своем учебнике и проверил два задания больших.
Я наверное неправильно ее делаю, но браузер пишет про переполнение стека. Погуглил, советуют делать через setTimeout.
Но у меня тогда люто тормозит браузер, один раз система вообще перезагрузилась.
jsfiddle вообще не видит рекурсию.
http://jsfiddle.net/7erbrfnL/
Задание сделать игру сапер, очевидно.
https://gist.github.com/codedokode/ce30e7a036f18f416ae0#3-%D0%A1%D0%B0%D0%BF%D0%B5%D1%80
Я уже понял, в чем проблема, но пока не знаю, как решить.
Суть в том, что если под кликнутой ячейкой нет мины, и на соседних ячейках тоже нет мин, нужно запустить проверку для соседних ячеек. Но соседняя ячейка вызывает проверку той, которая вызвала ее! А та снова соседнюю, и так они дергают друг друга бесконечно.
Нужно исключить ячейки, которые уже проверялись.
Надо подумать, массив что ли отдельный завести под них.
Апдейт.
http://jsfiddle.net/7erbrfnL/1/
Из недочетов не знаю, как сделать следующие вещи:
- сбросить стили, которые изменил джаваскрипт на те что были по умолчанию; без этого при нажатии на кнопку "новая игра" остаются "открытыми" ячейки из прошлого раунда.
Слишком рано выпрыгивает сообщение о победе (до того как откроются последние ячейки). И надо убрать возможность ставить флажки на открытых полях.
Исправлю как будет время.
Сначала добавь console.log который показывает какую клетку (координаты) ты обрабатываешь. Посмотри что он напишет.
Тебе надо останавливавть рекурсию. Например как-то помечать или запоминать проверенные клетки и не вызывать функцию для уже проверенной клетки второй раз.
>>483158
Прочти внимательно пост >>479601
Похвастаться знанием слов на английском можно в каком-нибудь треде.
Скорее всего, у них БД спроектированна по-особенному? Например, хранят данные для конкретного пользователя в отдельных кластерках.
> вконтакте хранит конкретных лайкнувших сущность?
как связи (кто -> что лайкнул). По id потом можно найти пользователя кто поставил лайк.
> Если делать индекс, получаем крайне неэффективную вставку лайка за log2(n) + балансировка дерева каждые m вставок
Почему это неэффективно? log2 от миллиарда это около 30: http://www.google.ru/search?sourceid=chrome&ie=UTF-8&q=log2(30)#newwindow=1&q=log2(1000000000)
Балансировка да, она меняет много страниц и требует прочесть/записать их на диск. Но если они уже в памяти то это другой вопрос.
Вообще конечно традиционные подходя для вконтакте не работают. Хотя бы потому что обычная БД дает на хорошем железе порядка тысяч чтений в секунду (оптимизированных запросов с индексом) и порядка сотен транзакций записи (если я не путаю), а с вконтактовской посещаемостью база умрет в первую же секунду.
Выдержать их высокую посещаемость можно при условии, если мы будем хранить данные разных пользователей на разных серверах (это называется шардинг). При этом ты должен адаптировать код, чтобы он знал к какому серверу обращаться. Отдельная сложность — выравнивание нагрузки: некоторые пользователи популярнее и получается что например один сервер больше загружен, а другой меньше. Для решения этой проблемы данные разбиваются на порции и порции переносятся с более загруженных серверов на менее загруженные (готового рещения разумеется нет, это все пишется самостоятельно).
Ну и вконтакте использует (не только MySQL), они еще пишут хранилища (и кеши) на Си для хранения/обработки многих вещей, включая лайки. Проблема тормозоа решается тем что все данные хранятся в памяти (а также сбрасываются на диск разумеется). Вот (составленное разработчиками вконтакте) описание подходов для хранения данных:
https://github.com/vk-com/kphp-kdb/blob/master/docs/ru/DBMS_Storage_Comparison.wiki
Вот пример движка для хранения (или кеширования) списков вроде списка участников группы: https://github.com/vk-com/kphp-kdb/blob/master/docs/ru/KittenDB_Lists.wiki
Вот движок для друзей: https://github.com/vk-com/kphp-kdb/blob/master/docs/ru/KittenDB_Friends.wiki
Вот что-то что может использоваться и для лайков: https://github.com/vk-com/kphp-kdb/blob/master/docs/ru/KittenDB_Search.wiki
Как ты видишь, он использует интерфейс Memcache, таким образом на стороне PHP можно использоать готовый клиент Memcache.
Но конечно сайтам меньше чем вконтакте не требуется обычно писать свои движки. Есть много готовых NoSQL движков, вроде Memcache, Redis, sphinx, которые можно использовать для этой же цели. Разумеется, для этого надо хорошо понимать, как они работают, надежно ли там хранятся данные и тд.
Если тебе будет интересно, мы можем это поизучать эти темы, но сначала стоит разобраться с MySQL.
> вконтакте хранит конкретных лайкнувших сущность?
как связи (кто -> что лайкнул). По id потом можно найти пользователя кто поставил лайк.
> Если делать индекс, получаем крайне неэффективную вставку лайка за log2(n) + балансировка дерева каждые m вставок
Почему это неэффективно? log2 от миллиарда это около 30: http://www.google.ru/search?sourceid=chrome&ie=UTF-8&q=log2(30)#newwindow=1&q=log2(1000000000)
Балансировка да, она меняет много страниц и требует прочесть/записать их на диск. Но если они уже в памяти то это другой вопрос.
Вообще конечно традиционные подходя для вконтакте не работают. Хотя бы потому что обычная БД дает на хорошем железе порядка тысяч чтений в секунду (оптимизированных запросов с индексом) и порядка сотен транзакций записи (если я не путаю), а с вконтактовской посещаемостью база умрет в первую же секунду.
Выдержать их высокую посещаемость можно при условии, если мы будем хранить данные разных пользователей на разных серверах (это называется шардинг). При этом ты должен адаптировать код, чтобы он знал к какому серверу обращаться. Отдельная сложность — выравнивание нагрузки: некоторые пользователи популярнее и получается что например один сервер больше загружен, а другой меньше. Для решения этой проблемы данные разбиваются на порции и порции переносятся с более загруженных серверов на менее загруженные (готового рещения разумеется нет, это все пишется самостоятельно).
Ну и вконтакте использует (не только MySQL), они еще пишут хранилища (и кеши) на Си для хранения/обработки многих вещей, включая лайки. Проблема тормозоа решается тем что все данные хранятся в памяти (а также сбрасываются на диск разумеется). Вот (составленное разработчиками вконтакте) описание подходов для хранения данных:
https://github.com/vk-com/kphp-kdb/blob/master/docs/ru/DBMS_Storage_Comparison.wiki
Вот пример движка для хранения (или кеширования) списков вроде списка участников группы: https://github.com/vk-com/kphp-kdb/blob/master/docs/ru/KittenDB_Lists.wiki
Вот движок для друзей: https://github.com/vk-com/kphp-kdb/blob/master/docs/ru/KittenDB_Friends.wiki
Вот что-то что может использоваться и для лайков: https://github.com/vk-com/kphp-kdb/blob/master/docs/ru/KittenDB_Search.wiki
Как ты видишь, он использует интерфейс Memcache, таким образом на стороне PHP можно использоать готовый клиент Memcache.
Но конечно сайтам меньше чем вконтакте не требуется обычно писать свои движки. Есть много готовых NoSQL движков, вроде Memcache, Redis, sphinx, которые можно использовать для этой же цели. Разумеется, для этого надо хорошо понимать, как они работают, надежно ли там хранятся данные и тд.
Если тебе будет интересно, мы можем это поизучать эти темы, но сначала стоит разобраться с MySQL.
Вот статьи по теме:
http://ruhighload.com/index.php/2009/05/06/%D1%88%D0%B0%D1%80%D0%B4%D0%B8%D0%BD%D0%B3-%D0%BF%D0%B0%D1%80%D1%82%D0%B8%D1%86%D0%B8%D0%BE%D0%BD%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D1%80%D0%B5%D0%BF%D0%BB%D0%B8%D0%BA%D0%B0%D1%86/
http://ruhighload.com/post/%D0%A0%D0%B5%D0%BF%D0%BB%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D1%8F+%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85
Нихуя, мне кажется что тут сидят все те же рожи уже мнго лет, и решают свои векторы и прочие файлообменники месяцами. А ньюфаги залетают на недельку, доходя до кредитов и сваливают дальше бороздить просторы вселенной.
>Почему это неэффективно? log2 от миллиарда это около 30:
То есть при каждой вставке мы условно 30 раз проходим по дереву. Удаление тоже ресурсоемкое. А ведь можно просто создать отдельный список, где хранить лайки конкретного объекта. Неэффективность заключается в том, что мы используем ненужные данные, а именно дерево всех лайков, когда нам требуется только его маленький кусочек. Такое дерево протеворечит логике построения. Так как отдельные его части никогда не будут выбраны вместе. Зачем их тогда так хранить?
Вот в случае друзей уже логично использовать одно дерево, т.к. приходится устанавливать обратные релейшены.
В общем, тема обширная, буду разбираться в ней, как изучу основы.
> То есть при каждой вставке мы условно 30 раз проходим по дереву.
Мы не проходим 30 раз по всему дереву, а делаем 30 шагов по нему, чтобы найти нужное место. И что значит неэффективно? Неэффективно это когда нужных страниц в памяти нет, а если они в памяти то это относительно быстро.
> А ведь можно просто создать отдельный список, где хранить лайки конкретного объекта.
А искать этот список из миллионов других списков как? А выделять память под него как?
Конечно, другие способы есть, вроде хеш-таблиц, но по ним нельзя искать с условиями вроде «больше» - «меньше» и я не знаю, насколько они эффективны когда их надо хранить на диске.
> Неэффективность заключается в том, что мы используем ненужные данные, а именно дерево всех лайков, когда нам требуется только его маленький кусочек.
Ну а ты предлагаешь хранить дерево всех списков. Ну и если подумать, индекс это и есть тот же список, там же значения по порядку идут.
Заметь, что «эффективность» тут понятие относительное. Если сайты с миллиардами просмотров в день, есть с тысячью. Есть эффективность выборки, вставки, удаления и часто надо жертвовать одной в пользу другой. Есть надежность, которой иногда жертвуют в пользу скорости. Есть кеширование, шардинг и т.д.
Ты делаешь несколько ошибок.Во-первых, ты скорее всего не знаешь сколько в абсолютных величинах занимают эти 30 шагов по дереву. Во-вторых, ты прицепился к тому, что (ошибочно) кажется тебе самым медленным местом и не видишь общей картины. такой подход вреден при оптимизации.
Если тебе любопытно, часто одна из самых медленных частей в вставке записи в таблицу это сброс данных на диск и ожидание подтверждения что данные физически записаны на поверхность. MySQL например по умолчанию дожидается этого прежде чем сообщить клиенту что данные записаны (отсюда ограничение на число записей в секунду). Среди NoSQL движков сейчас принято жертвовать надежностью и выставлять менее надежные настройки по умолчанию (я подозреваю ради более высоких результатов в тестах и обзорах, и ради пиара).
Кстати если ты понимаешь Си и посмотришь код разных движков от вконтакте, то деревья там много где используются.
То есть это хорошо, что ты интересуешься оптимизацией, но ты подходишь не с той стороны.
> То есть при каждой вставке мы условно 30 раз проходим по дереву.
Мы не проходим 30 раз по всему дереву, а делаем 30 шагов по нему, чтобы найти нужное место. И что значит неэффективно? Неэффективно это когда нужных страниц в памяти нет, а если они в памяти то это относительно быстро.
> А ведь можно просто создать отдельный список, где хранить лайки конкретного объекта.
А искать этот список из миллионов других списков как? А выделять память под него как?
Конечно, другие способы есть, вроде хеш-таблиц, но по ним нельзя искать с условиями вроде «больше» - «меньше» и я не знаю, насколько они эффективны когда их надо хранить на диске.
> Неэффективность заключается в том, что мы используем ненужные данные, а именно дерево всех лайков, когда нам требуется только его маленький кусочек.
Ну а ты предлагаешь хранить дерево всех списков. Ну и если подумать, индекс это и есть тот же список, там же значения по порядку идут.
Заметь, что «эффективность» тут понятие относительное. Если сайты с миллиардами просмотров в день, есть с тысячью. Есть эффективность выборки, вставки, удаления и часто надо жертвовать одной в пользу другой. Есть надежность, которой иногда жертвуют в пользу скорости. Есть кеширование, шардинг и т.д.
Ты делаешь несколько ошибок.Во-первых, ты скорее всего не знаешь сколько в абсолютных величинах занимают эти 30 шагов по дереву. Во-вторых, ты прицепился к тому, что (ошибочно) кажется тебе самым медленным местом и не видишь общей картины. такой подход вреден при оптимизации.
Если тебе любопытно, часто одна из самых медленных частей в вставке записи в таблицу это сброс данных на диск и ожидание подтверждения что данные физически записаны на поверхность. MySQL например по умолчанию дожидается этого прежде чем сообщить клиенту что данные записаны (отсюда ограничение на число записей в секунду). Среди NoSQL движков сейчас принято жертвовать надежностью и выставлять менее надежные настройки по умолчанию (я подозреваю ради более высоких результатов в тестах и обзорах, и ради пиара).
Кстати если ты понимаешь Си и посмотришь код разных движков от вконтакте, то деревья там много где используются.
То есть это хорошо, что ты интересуешься оптимизацией, но ты подходишь не с той стороны.
Если ты в JS не разбираешься то тебе надо изучить JS прежде чем писать аякс-запросы.
> Причем если в контролере написать echo $data, то все выводится, но контролер же не должен выводить значения.
Сделай функцию которая их выводит. Если это HTML то конечно он должен быть в шаблонах, а не в коде.
Шлешь ты такой жкверей аякс:
$.ajax({
url: 'users',
method: 'GET',
success: function($response) {
/Тут колбек обрабатывающий ответ с сервера, хз что за демонов ты вызываешь, присобачь ответ с сервера куда тебе надо, хотя все это один большой гавнокод ящитаю/
$('.target').append($response);
}
});
Некогда мне JS учить в данный момент. Потом как-нибудь. В общем сделал как ты сказал, создал метод, который вызывает основной метод и выводит результат его работы через echo. Немного костыльно конечно, но сойдет.
>>483270
Чет не хочет он выводить таким макаром. Ладно, потом переделаю если что. Не суть важно.
>делаем 30 шагов по нему, чтобы найти нужное место.
Ну это я и имел в виду.
>Ну а ты предлагаешь хранить дерево всех списков. Ну и если подумать, индекс это и есть тот же список, там же значения по порядку идут.
Нет, ты не понял. Я предлагаю использовать иерархическую БД для хранения личных данных объектов.
>Я предлагаю использовать иерархическую БД для хранения личных данных объектов.
Так это делается на обычной реляцiонной СУБД в три таблички.
Я не разбираюсь в IQ и не знаю, много это или мало, потому ответить не могу. Но если ты будешь решать наши задачки, мы будем давать подсказки и советы до тех пор пока ты не поймешь что к чему.
>>481819
Когда тебе дадут написанный до тебя проект и ты начнешь ныть что тут плохой код и надо переписать его, тебе вспомнят этот пункт. Ну и мое мнение, что про переписать обычно говорят всякие неучи. Выгоднее обычно не переписывать.
>>481824
Зарплату определяет рынок
>>481829
> font: 20px;
Почитай про свойство font http://htmlbook.ru/css/font и font-size http://htmlbook.ru/css/font-size
В остальном все верно.
Да, верно, для этого по идее надо padding на body поставить, проверим этот момент на второй задачке где как раз надо учесть разную ширину.
>>481869
Не хочешь начать с нашего учебника? Тоже вариант. Упомянутую книгу и курсы не смотрел так что не могу советовать.
>>481876
Надо проверить:
— что код сохранен в utf-8 без BOM
— что в HTML стоит meta charset
— что при соединеннии с базой ты указываешь charset или делаешь SET NAMES utf8
— что при создании таблицы ты указал кодировку utf8 (проверить можно командой SHOW CREATE TABLE t\G)
>>481879
> в оп-посте собраны задачи чуть ли не олимпиадного уровня,
Не хочу огорчать, но это не задачи олимпиадого уровня. Задачи олимпиадного уровня ты можешь почитать например на codeforces
>>481928
Поставь там var_dump и echo чтобы было видно что выполняется в каком порядке и чему равны переменные. Ну и код какой-то страшный, все вперемешку, и PHP, и HTML, тяжело же читать наверно.
Да, верно, для этого по идее надо padding на body поставить, проверим этот момент на второй задачке где как раз надо учесть разную ширину.
>>481869
Не хочешь начать с нашего учебника? Тоже вариант. Упомянутую книгу и курсы не смотрел так что не могу советовать.
>>481876
Надо проверить:
— что код сохранен в utf-8 без BOM
— что в HTML стоит meta charset
— что при соединеннии с базой ты указываешь charset или делаешь SET NAMES utf8
— что при создании таблицы ты указал кодировку utf8 (проверить можно командой SHOW CREATE TABLE t\G)
>>481879
> в оп-посте собраны задачи чуть ли не олимпиадного уровня,
Не хочу огорчать, но это не задачи олимпиадого уровня. Задачи олимпиадного уровня ты можешь почитать например на codeforces
>>481928
Поставь там var_dump и echo чтобы было видно что выполняется в каком порядке и чему равны переменные. Ну и код какой-то страшный, все вперемешку, и PHP, и HTML, тяжело же читать наверно.
> if (($number % 100 >= 10) && ($number % 100 <= 20)) {
> $number = " рублей";
Тут незачем заводить переменную и можно писать сразу return ....;
> if (($million % 10 == 1) && ($million != 11)) {
> $word = $word . " миллион ";
> if (($thousand % 10 == 1) && ($thousand != 11)) {
> $word = $word . " тысяча ";
Это почти копипаста кода из inclineWord (только случай с 11-19 ты забыл проверить). Копипаста алгоритма это зло и ее не должно быть. Напиши единую функцию для склонения слов, а варианты написания можно передавать в нее снаружи.
> \t$word = $spelling[$number];
> \treturn $word;
Тут незачем переменную word создавать, лучше сразу писать return
Вместо склеивания слов может быть удобнее завести массив и класть слова в него, а в конце объединить в строку с помощью implode.
http://jtest.ru/bazyi-dannyix/sql-dlya-nachinayushhix-chast-3.html
http://odiszapc.ru/doctrine/working-with-associations/
Ну а лучше всего это описано в оригинале документации:
http://doctrine-orm.readthedocs.org/en/latest/reference/association-mapping.html
http://doctrine-orm.readthedocs.org/en/latest/reference/working-with-associations.html
>>482081
Вынеси похожий код в функцию чтобы избежать дублирования
>>482055
> Например роли у меня могут быть 1, 2 и 3.
Надо использовать константы а не 1 2 3 ибо ничего потом не понять будет.
>>482087
> Ещё удивило, что он перейдя по ссылке http://symfony2.loc/app_dev.php ему открылся файл конфигурации, хотя путь должен быть
Потому что у него DocumentRoot туда указывает, на папку web, а у тебя куда-то не туда.
> хотя путь должен быть http://symfony2.loc/symfony/web/app_dev.php
Почему? Не должен быть.
>>482185
У ОПа есть, часть можно скачать по ссылке в оп-посте. Ценного там ничего нет, один флуд.
>>482419
Поищи статьи на эту тему или открой отладчик в браузере Ctrl + Shift + I и изучи как сделано на том сайте. Статья про отладчик: http://habrahabr.ru/post/143767/
http://jtest.ru/bazyi-dannyix/sql-dlya-nachinayushhix-chast-3.html
http://odiszapc.ru/doctrine/working-with-associations/
Ну а лучше всего это описано в оригинале документации:
http://doctrine-orm.readthedocs.org/en/latest/reference/association-mapping.html
http://doctrine-orm.readthedocs.org/en/latest/reference/working-with-associations.html
>>482081
Вынеси похожий код в функцию чтобы избежать дублирования
>>482055
> Например роли у меня могут быть 1, 2 и 3.
Надо использовать константы а не 1 2 3 ибо ничего потом не понять будет.
>>482087
> Ещё удивило, что он перейдя по ссылке http://symfony2.loc/app_dev.php ему открылся файл конфигурации, хотя путь должен быть
Потому что у него DocumentRoot туда указывает, на папку web, а у тебя куда-то не туда.
> хотя путь должен быть http://symfony2.loc/symfony/web/app_dev.php
Почему? Не должен быть.
>>482185
У ОПа есть, часть можно скачать по ссылке в оп-посте. Ценного там ничего нет, один флуд.
>>482419
Поищи статьи на эту тему или открой отладчик в браузере Ctrl + Shift + I и изучи как сделано на том сайте. Статья про отладчик: http://habrahabr.ru/post/143767/
Ох, спасибо.
Это вполне хороший вариант, лучше всешго наверно разрешить вводить название руками, но одновременно аяксом делать запрос на сервер и там искать книги по базе или через API.
>>482554
Неплохо для начала, но надо бы выводить ошибки списком, а не просто выплюнуть в пользователя массив в котором не очень легко разобарться.
Также, preg_match ищет только первое совпадение, тут нужен preg_match_all который ищет все (он вроде описан в уроке где-то в конце).
Также, у тебя нет флага i в регулярке и она не видит ошибок в больших буквах: http://ideone.com/Dgis0D
> [^,] а|
Это очень хрупкая регулярка так как если там будет 2 пробела то она не сработает. Лучше поставить чтобы было любое число пробелов.
Также программа видит ошибку там, где ее нет: http://ideone.com/Dgis0D
Для начала сойдет и такое, пока нагрузки небольшие.
>>483061
MVC это разделение кода на 3 части, каждая из которых занимается своим делом и не лезет в дело другой. Соответственно разбей свой код на эти 3 части и разнеси по файлам, отдельно контроллеры, отдельно классы относящиеся к модели, отдельно шаблоны.
>>483111
Поищи такие вакансии и посмотри какие там требования
>>483119
там аргументы уровня /b:
> It's also easy to get started with, which leads to a community with a large percentage of newbies making silly mistakes.
То что им легко пользоваться это преимущество.
> PHP has several problems with language design
Проблемы есть но помешать они могут только перфекционистам которые не хотят решать реальные задачи а хотят строить абстрактные деревья категорий. Стоит ли слушать людей от которых нет реальной пользы?
Ну и говоря про проблемы архитектуры, давайте вспомним скриптовый язык в котором надо вручную писать self в аргументах метода, где нет public/private и убогие питоноводы вынуждены писать переменные с подчеркиваний (что одно по моему перевешивает все недостатки php). Где куча методов начинающихся с 2 подчеркиваний. И не в этом ли языке надо вручную прописывать кодировку utf-8 в начале файла? Чем он лучше PHP?
Просто есть кучка бездельников которые толком ничего не программируют, а рассуждают какой язык лучше.
Норот начнёт нажимать на кнопки «это спам» и вскоре все сообщения будут отмечены как спам.
Но на уровне провайдера же не будет проблем, что с меня такая активность пошла?
> Слишком рано выпрыгивает сообщение о победе (до того как откроются последние ячейки
Я бы сказал, очень даже рано, у меня на 4-м ходу появилось хотя я ни одной пустой клеточки не открыл.
Советы и замечания:
> × {
>\tpadding: 0;
Это в общем плохая идея так как ты убиваешь полезные встроенные стили вроде отступов у абзацев, списков и тд. Надо знать браузерные стили а не пытаться с ними бороться.
> if(table.firstChild == tr){
> if(cell == tr.firstChild){
> neighbourCells = [id + 1, id + width, id + width + 1];
Ой, это какой-то нереально унылый код. Тебе самому не кажется, что тут что-то не так? Лучше сделать поиск ячеек циклом от x - 1 до x + 1 и от y - 1 до y + 1 с проверкой укладывается ли такая клеточка в доску. Ну или через Math.min/max вычислить нижнюю и верхнюю границу цикла.
> Array.prototype.shuffle = shuffle;
Я бы не советовал менять прототипы стандартных объектов, этим можно например сломать какой-то сторонний код или библиоеку. Делай свои функции, и не лезь в чужие объекты.
> startButton.addEventListener('click', dropOldTable);
> startButton.addEventListener('click', getMinesPositions);
> startButton.addEventListener('click', drawTable);
это хрупкий код так как полагается на порядок вызова (кто тебе гарантировал что он будет таким?). Нужен один обработчик который вызывает одну функцию.
> function dropOldTable(){
Вообще, так ли уж надо пересоздавать таблицу заново? Нельзя ли просто новые цифры проставить в существующую? Или проще пересоздавать?
> switch (levelOfDifficulty){
тут нужен default который например выкидывает исключение, это поможет тебе увидеть ошибку если она будет
> minesArray = minesArray.shuffle();
Твоя функция меняет значения в самом же массиве, потому = тут не нужно
Насчет массива мин, мне кажется 2-мерный массив был бы гораздо удобнее так как лучше соответствует форме поля. Как минимум искать соседние ячейки будет проще. Вместо перемешивания можно просто рандомно генерировать координаты и ставить туда мину.
> table.addEventListener('contextmenu', toggleFlag);
Не то событие. contextmenu это событие открытия меню (что очевидно из названия), оно например вызывается еще кнопкой справа от пробела. Тебе нужно событие mousedown.
> td.setAttribute('id', id);
Я думаю что незачем ставить id каждой ячейке, так как у таблицы есть массив table.rows, а у строки массив cells:
https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableElement/rows
Кстати есть и метод добавления строки: https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableElement/insertRow
> var id = +target.getAttribute('id');
Вот тут вместо id можно было бы использовать cellIndex/rowindex — там что-то такое у элемента td есть: https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableCellElement
Или как альтернатива, данные можно хранить в data-атрибутах вроде <td data-x="5">. id лучше стараться использовать пореже, так как они не должны повторяться, и я не уверен что можно использовать id состоящие только из цифр (то что в каком-то браузере это работает не значит что работает везде).
Вот тут http://stackoverflow.com/a/1077111 пишут id не может начинаться с цифры. Раз так, это надо исправить.
> function checkCell(e){
> table.removeEventListener('click', checkCell);
лучше не удалять обработчики, так как там легко ошибиться и получить ситуацию когда например у нас несколько одинаковых обработчиков на элементе. Лучше вообще ставить их только один раз и все. В твоей ситуации например обработчик на таблице менять незачем.
Если ты хочешь заблокировать клики после поражения/победы то лучше использовать переменную для этого.
> target.style.backgroundColor = '#c00';
Стили надо менять добавлением/удалением класса. Так как оформление должно быть в CSS файле, а не в яваскрипт коде.
> if(checkedCells.length === width * height - count){
Я не уверен что это правильное условие.
> var table = document.getElementById('field');
Это плохая идея копипастить эти getelementId. Почему бы один раз в начале не сохранить ссылки на нужные объекты и не использовать их постоянно?
> mineCount += minesArray[neighbourCells];
В массиве хранятся true/false. Нехорошо их складывать, это не числа.
> var target = e.target;
> if(target.innerHTML == ''){
> target.innerHTML = '⚑'
Эта проверка хрупкая, стоит там например оказаться пробелу как код перестанет работать. Лучше бы иметь data-атрибут на ячейке или иметь 2-мерный массив флажков.
> Слишком рано выпрыгивает сообщение о победе (до того как откроются последние ячейки
Я бы сказал, очень даже рано, у меня на 4-м ходу появилось хотя я ни одной пустой клеточки не открыл.
Советы и замечания:
> × {
>\tpadding: 0;
Это в общем плохая идея так как ты убиваешь полезные встроенные стили вроде отступов у абзацев, списков и тд. Надо знать браузерные стили а не пытаться с ними бороться.
> if(table.firstChild == tr){
> if(cell == tr.firstChild){
> neighbourCells = [id + 1, id + width, id + width + 1];
Ой, это какой-то нереально унылый код. Тебе самому не кажется, что тут что-то не так? Лучше сделать поиск ячеек циклом от x - 1 до x + 1 и от y - 1 до y + 1 с проверкой укладывается ли такая клеточка в доску. Ну или через Math.min/max вычислить нижнюю и верхнюю границу цикла.
> Array.prototype.shuffle = shuffle;
Я бы не советовал менять прототипы стандартных объектов, этим можно например сломать какой-то сторонний код или библиоеку. Делай свои функции, и не лезь в чужие объекты.
> startButton.addEventListener('click', dropOldTable);
> startButton.addEventListener('click', getMinesPositions);
> startButton.addEventListener('click', drawTable);
это хрупкий код так как полагается на порядок вызова (кто тебе гарантировал что он будет таким?). Нужен один обработчик который вызывает одну функцию.
> function dropOldTable(){
Вообще, так ли уж надо пересоздавать таблицу заново? Нельзя ли просто новые цифры проставить в существующую? Или проще пересоздавать?
> switch (levelOfDifficulty){
тут нужен default который например выкидывает исключение, это поможет тебе увидеть ошибку если она будет
> minesArray = minesArray.shuffle();
Твоя функция меняет значения в самом же массиве, потому = тут не нужно
Насчет массива мин, мне кажется 2-мерный массив был бы гораздо удобнее так как лучше соответствует форме поля. Как минимум искать соседние ячейки будет проще. Вместо перемешивания можно просто рандомно генерировать координаты и ставить туда мину.
> table.addEventListener('contextmenu', toggleFlag);
Не то событие. contextmenu это событие открытия меню (что очевидно из названия), оно например вызывается еще кнопкой справа от пробела. Тебе нужно событие mousedown.
> td.setAttribute('id', id);
Я думаю что незачем ставить id каждой ячейке, так как у таблицы есть массив table.rows, а у строки массив cells:
https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableElement/rows
Кстати есть и метод добавления строки: https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableElement/insertRow
> var id = +target.getAttribute('id');
Вот тут вместо id можно было бы использовать cellIndex/rowindex — там что-то такое у элемента td есть: https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableCellElement
Или как альтернатива, данные можно хранить в data-атрибутах вроде <td data-x="5">. id лучше стараться использовать пореже, так как они не должны повторяться, и я не уверен что можно использовать id состоящие только из цифр (то что в каком-то браузере это работает не значит что работает везде).
Вот тут http://stackoverflow.com/a/1077111 пишут id не может начинаться с цифры. Раз так, это надо исправить.
> function checkCell(e){
> table.removeEventListener('click', checkCell);
лучше не удалять обработчики, так как там легко ошибиться и получить ситуацию когда например у нас несколько одинаковых обработчиков на элементе. Лучше вообще ставить их только один раз и все. В твоей ситуации например обработчик на таблице менять незачем.
Если ты хочешь заблокировать клики после поражения/победы то лучше использовать переменную для этого.
> target.style.backgroundColor = '#c00';
Стили надо менять добавлением/удалением класса. Так как оформление должно быть в CSS файле, а не в яваскрипт коде.
> if(checkedCells.length === width * height - count){
Я не уверен что это правильное условие.
> var table = document.getElementById('field');
Это плохая идея копипастить эти getelementId. Почему бы один раз в начале не сохранить ссылки на нужные объекты и не использовать их постоянно?
> mineCount += minesArray[neighbourCells];
В массиве хранятся true/false. Нехорошо их складывать, это не числа.
> var target = e.target;
> if(target.innerHTML == ''){
> target.innerHTML = '⚑'
Эта проверка хрупкая, стоит там например оказаться пробелу как код перестанет работать. Лучше бы иметь data-атрибут на ячейке или иметь 2-мерный массив флажков.
> сбросить стили, которые изменил джаваскрипт на те что были по умолчанию;
Используй классы и соответственно убирай их.
> И надо убрать возможность ставить флажки на открытых полях.
Можно помечать открытые поля классом, data-атрибутом или хранить в массиве.
>>483196
Как минимум можно попробовать сортировать данные в обратном порядке и брать первые 10 вместо последних 10.
Алсо от нескольких тысяч запросы не становятся долгими, у тебя просто они наверно кривые и неоптимизироанные и не используют индекс.
Алсо есть такая статья http://use-the-index-luke.com/no-offset
> Я предлагаю использовать иерархическую БД для хранения личных данных объектов.
Какую именно иерархическую БД?
И что, в иерархической БД нет необходимости искать юзера по id? И как это будет реализовано? И как ты будешь обновлять данные о юзере например? как хранить? как выделять место для новых записей?
Алсо одни товарищи уже пытались сделать иерархическую Бд вместо использования нормализации и MySQL и вот что они получили: http://habrahabr.ru/post/231213/
Я тебе написал выше: ты смотришь на проблему близоруко. Ты думаешь что проблема в этом самом дереве, а проблема не в нем.
И если говорить про приложения масштаба вконтакте, там все равно нет готовых решений, там приходится писать кастомное решение специально под приложение.
>>483300
А в чем проблема кучи таблиц? Мы можем брать только те данные, которые нам нужны. Ну и таблицы имеют определенный набор колонок определенных типов, что удобно.
В этом треде не обсуждаются вредоносные программы и рассылка спама. Алсо, гугл/мейл/яндекс неплохо фильтрует спам и твои письма попадут разве что к тем, кто держит почту на своем сервере.
А если у тебя не спам, то погугли, на том же хабре куча статей про то как делать рассылки. первым пунктом там кстати идет то, что получатели должны явно подтвердить свой адрес, что должна быть отписка в один клик и так далее.
> Слишком рано выпрыгивает сообщение о победе
Это я тупо забыл дописать одну проверку. Теперь все корректнее.
>это какой-то нереально унылый код
Ну уж как могу. Чукча не математик. Мне сложно решать нестандартные задания, я хочу выучиться грамотно писать стандартные вещи на фреймворках.
Я рад, что оно у меня вообще заработало.
>contextmenu это событие открытия меню, тебе нужен mousedown
Так он же срабатывает и на левой, и на правой кнопке, если я не ошибаюсь? Писать еще проверку, какая кнопка была нажата? Да ну нафиг.
>у таблицы есть массив table.rows, а у строки массив cells
Да, вот про это я забыл, это было бы удобнее использовать в этой ситуации.
>есть и метод добавления строки insertRow
Кажется, он намного медленнее работать. Но может я ошибаюсь, не помню где это читал. Вообще лучше сам проверю. Сейчас сгенерирую таблицу 500 х 500, посмотрим кто лучше справится, appendChild или методы таблицы.
>Стили надо менять добавлением/удалением класса.
Да, вот это верно, учту на будущее.
В общем, я лучше соберусь с силами и четенько вызубрю learn.javascript, прежде чем браться за подобные задания.
У меня тогда несколько общих вопросов по этому коду
http://jsfiddle.net/7erbrfnL/2/
Я не совсем понимаю суть делегации. То, что мы можем назначить событие на всей таблице, а не привязывать его каждой ячейке в цикле, это хорошо. Но я не понимаю, как тогда при наступлении какого-то третьего события отключить первое на конкретной ячейке? Ну вот в этой игре сапер при выставлении флажка эту ячейку не должно быть возможности вскрыть левой кнопкой мыши. Аналогично при открытии клетки, где нет бомбы, нужно запретить ставить туда флажок.
Если бы события висели на ячейке, я бы их удалил. Но у меня событие на таблице, если я его там удалю, то кликабельными перестанут быть все ячейки, а не конкретная.
Как с этим быть?
>>483365
Нет тут больше никого, только я сижу как фуфел в выходной летний день. Гуляют они, суки, а я? Разъебал бы их всех.
Я тут сижу, но я только начал. А ОП няша, котиков ему.
insertRow + insertCell 31 секунда.
На jsfiddle может подвиснуть.
http://jsfiddle.net/mrej4Lao/
Интересная статья, прямо по моему вопросу.
Что ж, ладно, эта была просто идея. Одна из огромного потока, которая вышла на обсуждение.
> как тогда при наступлении какого-то третьего события отключить первое на конкретной ячейке?
if (на клетку уже нажали) {
return;
}
if (клетка уже открыта) {
return;
}
> Но у меня событие на таблице, если я его там удалю
Это неправильный подход, не надо ничего удалять
> Так он же срабатывает и на левой, и на правой кнопке, если я не ошибаюсь? Писать еще проверку, какая кнопка была нажата?
Напиши, не умрешь. Неправильно для проверки нажатия кнопки использовать метод открытия меню.
> Сейчас сгенерирую таблицу 500 х 500, посмотрим кто лучше справится, appendChild или методы таблицы.
Несколько лет назад лучше всего справлялась вставка таблицы через innerHTML, но это было давно. Проверь и этот метод тогда.
> что связи между таблицами можно организовать без внешних ключей
Потом люди которые будут разбираться в нагромождении несвязанных таблиц будут громко тебя материть. В то время как с ключами все связи видны. Некоторые программы даже умеют их рисовать в виде стрелочек.
> но внешние ключи будут гарантировать целостность данных в таблицах, да?
Да, и не только это: http://denis.in.ua/foreign-keys-in-mysql.htm
> то нельзя будет в первой таблице ссылать на несущетсвующию запись во второй?
Нельзя
Для JS тестов кстати есть специальный сайт: https://jsperf.com/
Делаешь там тест, вбрасываешь в /b, смотришь результаты.
Вот примеры тестов: https://jsperf.com/jquery-selectors-speed-test
Странно что разница есть, мне казалось insertRow это тот же createElement и есть.
Кстати может быть если добавлять строки/ячейки в не присоединенную к документу таблицу, тоже будет быстрее.
Да, то ли начиная с 5.5, то ли 5.4.
А можно еще $var = foo()[3], при условии что foo возвращает массив конечно.
Но лучше так пока не делать ради совместимости с 5.3.
Я так один раз выложил на бесплатный хостинг со старой версией php, были из-за этого проблемы.
a foo() - foo()?
AJAX.
Только сначала JS покури, потому что AJAX это один из встроенных объектов JS в браузере.
Ну или хочешь - помогу.
http://rutracker.org/forum/viewtopic.php?t=4625806
Где можно его скачать, нигде не нашёл.
О, спасибо, я уже решил проблему при помощи анкоров. Но ява скрипт выучить надо, хотя бы для того что бы написать такие диалоги без перезагрузки сервера (они же сильнее грузят память?), вот я только что спросил >>483577 не могу курс этот найти, по ПХП курс от этого препода мне очень сильно помог.
JavaScript (еще 4 по ссылкам там же)
http://nnm-club.me/forum/viewtopic.php?t=858374
PHP
http://nnm-club.me/?q=%F1%EF%E5%F6%E8%E0%EB%E8%F1%F2+php+2015&w=title
Тут недавно написал говноподелку и вывалил её на бесплатный хостинг.
Ну и сегодня вот решил прикрутить туда эту гостевуху, и что же. le_pizdec, товарищи
В то время как дома у меня все неплохо работает, то этот говнохостинг выдает мне примерно вот это:
call to undefined function: mysqli_fetch_all()
А я этой функцией собственно все комментарии с базы дергал. Что делать? Весь код гостевуху скинуть её не могу, поломал код к хуям весь, пытаясь переделать, что даже не забэкапил это дело.
Анон, помоги, почему не работает?
Нужно найти эмейл по виду you+me@some.domain-domain.com
И записать в массив. Что не так?
http://ideone.com/4xlYnC
Экранировать кто будет? Пушкин? У тебя предупреждение выдавает код
>PHP Warning: preg_match_all(): Compilation failed: range out of order in character class at offset 13 in /home/SEINYR/prog.php on line 5
Потому-что дефис не экранирован и регулярке дана команда искать от точки до (а вот тут она не знает до чего).
Потому что здесь мне кажется кроется самое большое обезьянничанье.
Вот я захотел включить ЧПУ у вордпресса.
Сначала мне пришлось скопировать какие-то буквы в файл .htaccess для подключения mod_rewrite.
Кстати, по поводу самого .htaccess, что и как там пишется? Я так понял этих файлов может быть много (в корневой директории сайта, в папках выше, еще черт знает где), вроде бы они друг друга каскадно перекрывают. В общем смутное представление.
Так вот, дальше. Модуль mod_rewrite на свежеустановленном апаче выключен, чтобы его включить я нагуглил заклинание
a2enmod rewrite.
Это еще не все, нужно еще прописать в apache2.conf (или httpd.conf, не пойму почему по разным ссылкам я нахожу разные имена этого файла: это версии для линукса и винды?) строку AllowOverride None.
Одним словом, каждый раз когда нужно чего-то там поправить приходится лезть в гугл, читать тонны бесполезных или устаревших комментариев по теме и не очень, пока не найдешь эти несчастные две-три строчки.
Мне такая ситуация не нравится, поэтому реквестирую какое-то человекопонятное руководство по этим делам (только не очередной справочник-документацию, пожалуйста, нненада). Желательно с примерами и кортинками)))
Сами сисадмины по каким материалам учатся? Не зазубривают же наизусть эти сотни строк конфига, не понимая их смысла.
>Не зазубривают же наизусть эти сотни строк конфига, не понимая их смысла.
Если ты не понимаешь их смысл, ты даун. Иди лучше в макдак работать.
http://codepad.org/nm9jPcpd
Что я пытался сделать - если сумма долга меньше или равна 5000, тогда берём переменную $monthlyPayment - $creditBalance и заканчиваем цикл breakom. Тогда, по идее, должен получиться нулевой баланс и остаток. Не взлетает. Больше идей нет. Не надо говорить, что я делаю не так, явно же что-то не то, просто направьте, в какую сторону думать, я хочу сам решить
Внес некоторые изменения, убрал часть неиспользуемых функций сайта (регистрация, редактирование) в папку old (туда же перенес шаблоны этих функций).
https://github.com/Si0n/register3
for ($month = 1; $month <= 20; $month ++) {
\t
\t$creditBalance = ( $creditBalance $percent ) + $servicePayment - $monthlyPayment;
\t$paymentTotal = $paymentTotal + $monthlyPayment;
\techo "{$month} месяц спустя: долг = {$creditBalance} руб, выплачено всего {$paymentTotal} руб. \n";
/ Если баланс отрицательный — хватит считать */
if ($creditBalance <= $monthlyPayment) {
($monthlyPayment = $monthlyPayment - $creditBalance);
echo "С меня хватит!\n";
break;
11 месяц спустя: долг = 4138.1720657184 руб, выплачено всего 55000 руб.
С меня хватит!
Почему он оставляет долг, а не вычитает оставшуюся сумму долга из платежа? Нихрена не пойму, куда смотреть
Стоит ли писать такие длинные запросы? Понять их хоть и можно, но приходится вдумываться в каждую строчку и вспоминать предыдущие.
Я бы цепанул это все одним запросом и разобрал бы уже в пхп.
Но ведь оставшаяся сумма долга это и будет $creditBalance, верно же? Тогда получается, чтоб вывести на ноль, надо из платежа 5000 взять оставшуюся сумму и как раз получается ноль.
То есть, как-то так: &monthlyPayment - &creditBalance. Или не так? Где ошибка?
Вот этой статье на хабре 2008 года еще можно доверять?
Я хочу что бы у меня сессия жила неделю, это нормально? Ну или хотя бы сутки.
if ($creditBalance <= $monthlyPayment) /* проверка суммы, если долг меньше суммы платежа, то тогда платёж должен составить 5000 - долг. Так ведь? {
($monthlyPayment = $monthlyPayment - $creditBalance);
echo "С меня хватит!\n";
break;
Просто сначала берешь и добавляешь к сумме долга месячный процент и плату за пользование и потом проверяешь, меньше ли эта сумма 5000. И если меньше, то платишь уже не 5к, а всю оставшуюся сумму.
>>483816
$creditBalance = ( $creditBalance * $percent ) + $servicePayment - $monthlyPayment; - это же и есть общая сумма долга, правильно?
Следовательно, проверяю остаток, на 11 месяц получается что-то вроде 4100, беру эти 4100 ($creditBalance) и заношу в банк 5000 от маминых завтраков, то есть 5000 ($monthlyPayment - $creditBalance), долг 0, остаток грубо 900 рублей
Нет, сумма долга это $creditBalance * $percent + $servicePayment. А платить уже надо после того, как ты проверишь сумму. Т.е. когда сумма остается меньше 5к, то ты просто делаешь сумму платежа равной сумме оставшегося долга и все.
Точно! Зачем я вносил 5000, а незачем было. Спасибо, кажись, нашёл ключ) Ну я второй день только сижу, и то с перерывами большими, думаю, простительно
Алсо, так и не понял я что с генерацией случайной вебм делать, так что пока оставил все по-старому. Разжуй чтоле, как это все дело организовать.
А так, вроде все ошибки исправил, про которые ты говорил.
Посоны, я вот понял основы mvc, поверхностно разобрался во многих популярных фрейморках. А на каком остановится, то для прокачки навыка? Понятно, что их выбирают по требованиям и личным вкусам, но все же?
Можешь объяснить, почему именно CodeIgniter? В чем его преимущества перед другими фреймворками?
Сколько фреймворков ты знаешь, кстати?
> что почитать по теме настройки серверов?
Главный источник информации — документация по Апачу: http://httpd.apache.org/docs/2.4/ , правда она на английском (может где-то есть перевод, но я совневаюсь, я нашел это: http://www.apache.ru/docs/apache-2.0/ но она достаточно старая и там не все переведено). Разумеется, чтобы читать документацию, надо бы в общих чертах понимать что такое клиент/сервер, протокол HTTP и как работает веб-сервер (нас например в универе полгода мучали этим на курсе по сетевым технологиям, но достаточно общего представления). Если ты это знаешь и ты прочтешь документацию, то у тебя будет больше знаний чем у 90% администраторов.
Сам Апач состоит из модулей, потому всю документацию читать не надо, только по тем модулям которые ты используешь.
Я ее в свое время читал. Если что, клиент — это тот, кто делает запрос (в случае веба это браузер), сервер — тот кто на него отвечает, веб-сервер соответственно программа принимающая запросы от браузера по протоколу HTTP и выдающая в ответ файлы и страницы.
Вот я еще тут нашел кое-что на русском: https://masterhost.ru/support/doc/apache/
Вот статья по mod_rewrite:
http://habrahabr.ru/company/sprinthost/blog/129560/
http://habrahabr.ru/post/75885/
> по поводу самого .htaccess, что и как там пишется?
Файл .htaccess меняет настройки Апача внутри папки в которой он лежит (и вложенных в нее папок). Менять можно не любые настройки, а только те, которые не запретил менять администратор в главном конфигурационном файле.
Это описано тут например: https://masterhost.ru/support/doc/apache/#htaccess
> или httpd.conf, не пойму почему по разным ссылкам я нахожу разные имена этого файла
В разных дистрибутивах линукса используются разные названия и пути для конфигов и логов. В Windows проще, там все лежит в самой папке Апача.
httpd расшифровывается как HTTP server daemon
apache это не совсем правильное название так как сейчас фонд Apache software разрабатывает не только веб-сервер, но и кучу других проектов: http://www.apache.org/#projects-list
> нужно еще прописать в apache2.conf (или httpd.conf, не пойму почему по разным ссылкам я нахожу разные имена этого файла: это версии для линукса и винды?) строку AllowOverride None.
описано тут http://www.apache.ru/docs/fishki.html#AllowOverride
None значит что никакие директивы в htaccess не разрешены.
Тебе наверно надо что-то другое прописать.
> Одним словом, каждый раз когда нужно чего-то там поправить приходится лезть в гугл, читать тонны бесполезных или устаревших комментариев по теме и не очень, пока не найдешь эти несчастные две-три строчки.
Официальную документацию почитать не пробовал? Английский понимаешь?
> Сами сисадмины по каким материалам учатся? Не зазубривают же наизусть эти сотни строк конфига, не понимая их смысла.
Хорошие читают доки, плохие зазубривают и копипастят. Вообще, многие админы, например программировать умеют и некоторые могут сами к Апачу модуль написать, не то что конфиг настроить — я с такими сталкивался. Администратор в компании Рамблер вообще свой высокопроизводительный сервер (nginx) написал.
Я в свое время перечитал тонны мануалов по линуксу, потому что было интересно в нем разобраться.
Алсо, вот у меня есть сборник ответов на некоторые вопросы по Апачу: https://gist.github.com/codedokode/10774100
Если есть какие-то еще вопросы, задавай.
> что почитать по теме настройки серверов?
Главный источник информации — документация по Апачу: http://httpd.apache.org/docs/2.4/ , правда она на английском (может где-то есть перевод, но я совневаюсь, я нашел это: http://www.apache.ru/docs/apache-2.0/ но она достаточно старая и там не все переведено). Разумеется, чтобы читать документацию, надо бы в общих чертах понимать что такое клиент/сервер, протокол HTTP и как работает веб-сервер (нас например в универе полгода мучали этим на курсе по сетевым технологиям, но достаточно общего представления). Если ты это знаешь и ты прочтешь документацию, то у тебя будет больше знаний чем у 90% администраторов.
Сам Апач состоит из модулей, потому всю документацию читать не надо, только по тем модулям которые ты используешь.
Я ее в свое время читал. Если что, клиент — это тот, кто делает запрос (в случае веба это браузер), сервер — тот кто на него отвечает, веб-сервер соответственно программа принимающая запросы от браузера по протоколу HTTP и выдающая в ответ файлы и страницы.
Вот я еще тут нашел кое-что на русском: https://masterhost.ru/support/doc/apache/
Вот статья по mod_rewrite:
http://habrahabr.ru/company/sprinthost/blog/129560/
http://habrahabr.ru/post/75885/
> по поводу самого .htaccess, что и как там пишется?
Файл .htaccess меняет настройки Апача внутри папки в которой он лежит (и вложенных в нее папок). Менять можно не любые настройки, а только те, которые не запретил менять администратор в главном конфигурационном файле.
Это описано тут например: https://masterhost.ru/support/doc/apache/#htaccess
> или httpd.conf, не пойму почему по разным ссылкам я нахожу разные имена этого файла
В разных дистрибутивах линукса используются разные названия и пути для конфигов и логов. В Windows проще, там все лежит в самой папке Апача.
httpd расшифровывается как HTTP server daemon
apache это не совсем правильное название так как сейчас фонд Apache software разрабатывает не только веб-сервер, но и кучу других проектов: http://www.apache.org/#projects-list
> нужно еще прописать в apache2.conf (или httpd.conf, не пойму почему по разным ссылкам я нахожу разные имена этого файла: это версии для линукса и винды?) строку AllowOverride None.
описано тут http://www.apache.ru/docs/fishki.html#AllowOverride
None значит что никакие директивы в htaccess не разрешены.
Тебе наверно надо что-то другое прописать.
> Одним словом, каждый раз когда нужно чего-то там поправить приходится лезть в гугл, читать тонны бесполезных или устаревших комментариев по теме и не очень, пока не найдешь эти несчастные две-три строчки.
Официальную документацию почитать не пробовал? Английский понимаешь?
> Сами сисадмины по каким материалам учатся? Не зазубривают же наизусть эти сотни строк конфига, не понимая их смысла.
Хорошие читают доки, плохие зазубривают и копипастят. Вообще, многие админы, например программировать умеют и некоторые могут сами к Апачу модуль написать, не то что конфиг настроить — я с такими сталкивался. Администратор в компании Рамблер вообще свой высокопроизводительный сервер (nginx) написал.
Я в свое время перечитал тонны мануалов по линуксу, потому что было интересно в нем разобраться.
Алсо, вот у меня есть сборник ответов на некоторые вопросы по Апачу: https://gist.github.com/codedokode/10774100
Если есть какие-то еще вопросы, задавай.
В самом новом PHP есть специальный синтаксис для этого: http://php.net/manual/ru/functions.arguments.php#functions.variable-arg-list.new
>>483578
> хотя бы для того что бы написать такие диалоги без перезагрузки сервера (они же сильнее грузят память?
дело не в памяти, а в том что страница не перезагружается, появляется ощущение более быстрой скорости работы и соответственно трафика меньше гоняется.
>>483590
Не знаю, никогда не сталкивался
>>483617
Там наверно не установлено или не включено расширение mysqli
> Весь код гостевуху скинуть её не могу, поломал код к хуям весь, пытаясь переделать, что даже не забэкапил это дело.
Осваивай гит чтобы такого не было (а для бекапа вполне подойдет тот же дропбокс).
> [a-zA-Z0-9[.]-\\+]
Скобки внутри скобок обозначают просто соответствующие символы. Квадратные скобки не вкладываются друг в друга. Соответственно символ ] закрывает скобки и получается:
[a-zA-Z0-9[.] (любые буквы, цифры, открывающая скобка или точка)
- (за ними идет один минус)
\\+ (за ними идет один плюс)
] (за ними идет одна скобка)
Соответственно твое выражение ищет строки вроде abc-+] — разумеется ничего потому и не находит.
Ты наверно хотел написать «буквы, цифры, точка, минус и плюс» (забыл про знак подчеркивания кстати):
[a-zA-Z0-9.\\-+]
Внутри квадратных скобок спецсимволами являются только ^ [ ] \ и их надо экранировать бекслешами, а плюс не обязательно (мануал: http://php.net/manual/ru/regexp.reference.character-classes.php ).
Есть удобный сайт для работы с регулярками, только там надо бекслеш писать один раз вместо двух, то есть не \\s а просто \s. Вот он: https://regex101.com/
Кстати сайт regex101 справа разбирает твою регулярку на части и объясняет каждую, правда по-англйиски.
Если ввести твою регулярку (исправив бекслеши), вот что получим: https://regex101.com/r/pR4pZ8/1
Там как раз видно как оно разбивается на части.
>>483756
Эта задача у всех сложности вызывает, некоторые ее по 3 дня решали.
Надо смотреть чему равен остаток долга и обрабатывать ситуацию, когда она маленький, а не выплачивать сразу же 5000 вот в этом месте: ... + $servicePayment - $monthlyPayment;
Попробуй переписать код внутри цикла примерно так:
- прибавляем проценты и комиссию к остатку долга (но 5000 пока не вычитаем)
- если остаток маленький, выплачиваем сколько осталось и уходим
- иначе платим 5000
«Платим» здесь значит уменьшаем долг и увеличиваем общую сумму выплаченного.
> Я бы цепанул это все одним запросом и разобрал бы уже в пхп.
Это не всегда разумно, например внутренний подзапрос выбирает 100 000 строк, а внешний отбирает 10. А ты будешь пересылать все эти 100 000 строк в PHP что неэффективно. Более того, SQL код скорее всего будет более простой и короткий, чем PHP так как SQL специально придуман для выборки данных.
То есть я не вижу выгоды исплоьзоать PHP. Если тебе это кажется лучше то потому что ты плохо знаешь SQL. В этом случае надо исправлять пробелы в знаниях, а не выбирать более плохой способ.
Ну и тут используется 4 таблицы, так что PHP тут ничем не поможет.
Касательно твоего запроса, это какая-то хрень, такие вещи лучше писать джойнами без вложенных подзапросов. Джойны и читаются лучше, и выполняются часто быстрее. Автор то ли про них не знает то ли думает что так будет проще объяснить.
Кстати, если ты интересуешься SQL, у нас в ОП-посте есть задачки. Никаких подзапросов и заданий уровня первоклассника — каждая из задач заставит тебя поломать голову. Алсо, еще есть задача про имиджборду: сделай таблицы в БД для имиджборды из 1 раздела и напиши запрос, который выведет 10 верхних тредов, в каждом треде ОП-пост + 3 последних поста. Сначала надо сделать все с нормализацией, потом денормализировать ради оптимизаций.
Сессия это временная хранилище, которое живет пока человек ходит по страницам. Если человек будет неделю не отходя от компьютера сидеть на твоем сайте, то сессия проживет неделю. А если он отойдет больше чем на полчаса-час, то да, умрет. Это так и задумано и ты не должен это менять (хотя бы по той причне что тогда на твоем сервере скопятся миллионы этих файлов сессий).
Если тебе надо что-то хранить долговременно, используй куки или базу данных в зависимости от того что ты хранишь.
>>483925
Микрофреймворки Slim, Sliex
Нормальные срединие фреймворки Yii2 (lavarel еще советуют, но его фанаты не совсем адекватны по моему)
Мощные большие фреймворки Symfony 2
Если ты ни на одном не писал то начать можно с микрофреймворков, у нас задание на него есть в оп посте.
>>483942
>>483945
Не используйте, он давно устарел, компания-разработчик его забросила, код написан еще под PHP4 и на новом PHP сыплет варнингами.
Или ты так новичков троллишь?
Хорошо. Только ты файл errors.sql не убрал еще в папку old, ну и я надеюсь что ты вообще в будущем от таблицы errors сможешь избавиться.
Также, там были замечания по SQL коду:
> Похоже что ты не использовал тип YEAR для хранения года рождения, а ведь такой тип специально для этого придуман. Если ты про него не знал, то почитай про то какие типы есть в MySQL:
Это надо исправить. pswrd хорошо бы переименовать тоже.
Теперь давай возьмемся за улучшение index.php. Сейчас там адская гора инклудов (мне кстати больше нравится require так как он завершает программу с фатальной ошибкой если не может найти файл). Надо сделать одно из двух:
1) либо расчистить инклуды, так, чтобы был максимум один инклуд в начале файла и один инклуд в каждой ветке switch
Также, я не виду смысла в двух почти одинаковых переменных $_GET['page'] и $_GET['action']. Их надо объединить в одну. А еще лучше, вместо них добавлять слово в URL, чтобы было:
http://localhost/index.php
http://localhost/index.php/dashboard
http://localhost/index.php/register
Все эти URL будут открывать index.php, а окончание будет лежать в $_SERVER['PATH_INFO']. Я думаю, что это смотрится чуть красивее чем index.php?page=dashboard
2) либо вместо switch в index.php на каждое действие сделать свой файл, например index.php, register.php, dashboard.php и тд. Соответственно $_GET['action'] вообще будет не нужен.
Ты можешь выбрать любой из двух вариантов или предложить свой.
Все эти лишние инклуды можно перенести в lib/Ini.php.
lib/Ini.php надо переименовать с маленькой буквы, с большой пишутся только классы. В Windows ты так просто не переименуешь, придется делать в 2 шага: переименовать из Ini.php во что-то другое, закоммитить, потом снова переименовать в ini.php
Подключение шаблонов шапки и футера лучше всего перенести в сами же шаблоны вроде dashboard.php (как это уже сделано в https://github.com/Si0n/register3/blob/master/template/main.php)
Далее, вот еще замечание, смотри, вот этот шаблон: https://github.com/Si0n/register3/blob/master/template/dashboard.php — в нем знак & выделен красным так как в HTML это спецсимвол и чтобы вставить знак амперсанда надо писать &
После этого тебе надо проверить сайт с включенным отображением ошибок, что ни на одной странице не выдается ошибка.
После этого тебе надо добавить поиск (если это еще не сделано) на страницу со списком студентов. Для поиска не надо делать отдельную страницу, я думаю, нужно просто в вывод списка добавить проверку: если указано слово то выбираем только записи содержащие это слово.
Ну и у тебя неправильно сделана постраничная навигация: https://github.com/Si0n/register3/blob/master/template/list.php#L18
Ты должен выбирать из базы только тех студентов которые отображаются, а не выбирать 1000 студентов ради того чтобы показать 10. Это неэффективно. Используй LIMIT (кстати если ты не очень хорошо знаешь SQL то у нас в оп-посте есть задания на него).
Также, вместо for тут лучше использовать foreach.
Также, лучше бы ты выбирал их базы не массив массивов, а массив объектов Student.
Ну вот, пока давай это сделаем, а дальше проверим что получилось и перейдем к регистрации/редактироанию.
Хорошо. Только ты файл errors.sql не убрал еще в папку old, ну и я надеюсь что ты вообще в будущем от таблицы errors сможешь избавиться.
Также, там были замечания по SQL коду:
> Похоже что ты не использовал тип YEAR для хранения года рождения, а ведь такой тип специально для этого придуман. Если ты про него не знал, то почитай про то какие типы есть в MySQL:
Это надо исправить. pswrd хорошо бы переименовать тоже.
Теперь давай возьмемся за улучшение index.php. Сейчас там адская гора инклудов (мне кстати больше нравится require так как он завершает программу с фатальной ошибкой если не может найти файл). Надо сделать одно из двух:
1) либо расчистить инклуды, так, чтобы был максимум один инклуд в начале файла и один инклуд в каждой ветке switch
Также, я не виду смысла в двух почти одинаковых переменных $_GET['page'] и $_GET['action']. Их надо объединить в одну. А еще лучше, вместо них добавлять слово в URL, чтобы было:
http://localhost/index.php
http://localhost/index.php/dashboard
http://localhost/index.php/register
Все эти URL будут открывать index.php, а окончание будет лежать в $_SERVER['PATH_INFO']. Я думаю, что это смотрится чуть красивее чем index.php?page=dashboard
2) либо вместо switch в index.php на каждое действие сделать свой файл, например index.php, register.php, dashboard.php и тд. Соответственно $_GET['action'] вообще будет не нужен.
Ты можешь выбрать любой из двух вариантов или предложить свой.
Все эти лишние инклуды можно перенести в lib/Ini.php.
lib/Ini.php надо переименовать с маленькой буквы, с большой пишутся только классы. В Windows ты так просто не переименуешь, придется делать в 2 шага: переименовать из Ini.php во что-то другое, закоммитить, потом снова переименовать в ini.php
Подключение шаблонов шапки и футера лучше всего перенести в сами же шаблоны вроде dashboard.php (как это уже сделано в https://github.com/Si0n/register3/blob/master/template/main.php)
Далее, вот еще замечание, смотри, вот этот шаблон: https://github.com/Si0n/register3/blob/master/template/dashboard.php — в нем знак & выделен красным так как в HTML это спецсимвол и чтобы вставить знак амперсанда надо писать &
После этого тебе надо проверить сайт с включенным отображением ошибок, что ни на одной странице не выдается ошибка.
После этого тебе надо добавить поиск (если это еще не сделано) на страницу со списком студентов. Для поиска не надо делать отдельную страницу, я думаю, нужно просто в вывод списка добавить проверку: если указано слово то выбираем только записи содержащие это слово.
Ну и у тебя неправильно сделана постраничная навигация: https://github.com/Si0n/register3/blob/master/template/list.php#L18
Ты должен выбирать из базы только тех студентов которые отображаются, а не выбирать 1000 студентов ради того чтобы показать 10. Это неэффективно. Используй LIMIT (кстати если ты не очень хорошо знаешь SQL то у нас в оп-посте есть задания на него).
Также, вместо for тут лучше использовать foreach.
Также, лучше бы ты выбирал их базы не массив массивов, а массив объектов Student.
Ну вот, пока давай это сделаем, а дальше проверим что получилось и перейдем к регистрации/редактироанию.
> Разжуй чтоле, как это все дело организовать.
Давай я предложу такой вариант:
— добавляем в таблицу колонку rand
— заполняем ее случайными числами от 0 до допустим миллиарда
— при вставке нового файла тоже генерируем аналогичное случайное число для него
— при желании, добавляем крон-задачу которая раз в N дней перегенерирует числа заново
Выборка делается так:
— генерируем в PHP случайное число от 0 до миллиарда
— выбираем файл у которого rand >= (этого числа) LIMIT 1
Идея в том что вместо id которые могут быть с дырами мы берем слуайные числа которые распределяются примерно равномерно, по крайней мере на большом числе записей.
Нелюбовь к оф.документации начинающих вызвана обычно даже не плохим знанием английского, а непоследовательностью изложения. Документация это справочник, а не учебник.
Инфа должна излагаться последовательно, то есть сначала самые азы (с примерами и объеснениями!). Потом более продвинутые вещи, где на ранее полученные знания наматываются более углубленные подробности. Я где-то читал, что для оптимального обучения для слушателей должно быть уже знакомо 30-70% излагаемого материала. Потому что если знакомо меньше 30%, это слишком напрягает, много новых терминов, тратятся умственные силы на осмысление напора новой информации.
В документациях никогда это не учитывается, информация сгруппирована тематически, а не по уровням сложности.
Ну и практически всегда статьи неупорядочены.
Возьмем например php.net. Замечательный справочник, я не спорю. Но это не учебник. Без твоего блога (польстить: отношение нпс +10) или видеоуроков от специалиста я бы просто не знал, откуда начинать это читать.
Ну хорошо, спасибо за ссылки. Вот это вроде бы коротко и ясно https://masterhost.ru/support/doc/apache/ , потом уже за тонкостями буду лезть на оф.сайт.
Пока глянь, правильно ли я прописал настройки для локального хоста (не хочу /var/www/, хочу держать сайты в домашней папке):
1. Создать структуру директорий, например:
/home/user/www/site.name/public_html
2. Скопировать файл 000-default.conf под именем site.name.conf
cp /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/site.name.conf
3. Прописать в site.name.conf
ServerAdmin admin@email.com
ServerName site.name
ServerAlias www.site.name
DocumentRoot /var/www/site.name/public_html
<Directory /home/inside/www/site.name/public_html>
\t\tRequire all granted
</Directory>
4. В файле hosts дописать
127.0.0.1 site.name
По линуксу есть что-то хорошее? inb4 читай документацию - да вот тут она как раз слишком простая, рассматривается десктопная убунту http://help.ubuntu.ru/manual/%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%82%D0%BA%D0%B0_%D0%B4%D0%B8%D1%81%D0%BA%D0%B0
описано только куда тыкать мышкой в юнити.
Я так подозреваю, что на серверах не только юнити, вообще нет рабочих столов. Какой-нибудь центос или федора. Поэтому хотелось бы ориентироваться в командах оболочки (оболочек, вдруг будет стоять что-то другое кроме баша) на более продвинутом уровне, чем десктопная убунту.
>>483999
>Никаких заданий уровня первоклассника — каждая из задач заставит тебя поломать голову.
Чувак, не все же извращенцы, большинству людей нравится когда все получается легко и просто.
Если у этого парня недостаточно знаний для решения подобного задания, это может вообще демотивировать. Мы же на сосаче, тут люди с ранимой психикой.
Я например думал о самовыпиле при решении задачи на бд имиджборды.
Нелюбовь к оф.документации начинающих вызвана обычно даже не плохим знанием английского, а непоследовательностью изложения. Документация это справочник, а не учебник.
Инфа должна излагаться последовательно, то есть сначала самые азы (с примерами и объеснениями!). Потом более продвинутые вещи, где на ранее полученные знания наматываются более углубленные подробности. Я где-то читал, что для оптимального обучения для слушателей должно быть уже знакомо 30-70% излагаемого материала. Потому что если знакомо меньше 30%, это слишком напрягает, много новых терминов, тратятся умственные силы на осмысление напора новой информации.
В документациях никогда это не учитывается, информация сгруппирована тематически, а не по уровням сложности.
Ну и практически всегда статьи неупорядочены.
Возьмем например php.net. Замечательный справочник, я не спорю. Но это не учебник. Без твоего блога (польстить: отношение нпс +10) или видеоуроков от специалиста я бы просто не знал, откуда начинать это читать.
Ну хорошо, спасибо за ссылки. Вот это вроде бы коротко и ясно https://masterhost.ru/support/doc/apache/ , потом уже за тонкостями буду лезть на оф.сайт.
Пока глянь, правильно ли я прописал настройки для локального хоста (не хочу /var/www/, хочу держать сайты в домашней папке):
1. Создать структуру директорий, например:
/home/user/www/site.name/public_html
2. Скопировать файл 000-default.conf под именем site.name.conf
cp /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/site.name.conf
3. Прописать в site.name.conf
ServerAdmin admin@email.com
ServerName site.name
ServerAlias www.site.name
DocumentRoot /var/www/site.name/public_html
<Directory /home/inside/www/site.name/public_html>
\t\tRequire all granted
</Directory>
4. В файле hosts дописать
127.0.0.1 site.name
По линуксу есть что-то хорошее? inb4 читай документацию - да вот тут она как раз слишком простая, рассматривается десктопная убунту http://help.ubuntu.ru/manual/%D1%80%D0%B0%D0%B7%D0%BC%D0%B5%D1%82%D0%BA%D0%B0_%D0%B4%D0%B8%D1%81%D0%BA%D0%B0
описано только куда тыкать мышкой в юнити.
Я так подозреваю, что на серверах не только юнити, вообще нет рабочих столов. Какой-нибудь центос или федора. Поэтому хотелось бы ориентироваться в командах оболочки (оболочек, вдруг будет стоять что-то другое кроме баша) на более продвинутом уровне, чем десктопная убунту.
>>483999
>Никаких заданий уровня первоклассника — каждая из задач заставит тебя поломать голову.
Чувак, не все же извращенцы, большинству людей нравится когда все получается легко и просто.
Если у этого парня недостаточно знаний для решения подобного задания, это может вообще демотивировать. Мы же на сосаче, тут люди с ранимой психикой.
Я например думал о самовыпиле при решении задачи на бд имиджборды.
> 1) либо расчистить инклуды, так, чтобы был максимум один инклуд в начале файла и один инклуд в каждой ветке switch
>Также, я не виду смысла в двух почти одинаковых переменных $_GET['page'] и $_GET['action']. Их надо объединить в одну. А еще лучше, вместо них добавлять слово в URL, чтобы было:
http://localhost/index.php
http://localhost/index.php/dashboard
http://localhost/index.php/register
>Все эти URL будут открывать index.php, а окончание будет лежать в $_SERVER['PATH_INFO']. Я думаю, что это смотрится чуть красивее чем index.php?page=dashboard
А где об этом можно почитать?
>Я например думал о самовыпиле при решении задачи на бд имиджборды.
Лол, вчера так же было, когда начал разбираться с аяксом. Никак не могу вдуплиться.
>для решения подобного задания
Лолчто? Задачи элементарные. Решаются любым школьником после прочтения мануала.
Качни например уроки от школы программирования
http://nnm-club.me/forum/viewtopic.php?t=858743
Там кратко объясняется и аякс, и json, и сокеты. Правда совсем уж поверхностно. Но для общего понимания что это такое, зачем оно нужно и как работает, самое то.
Потом уже можно надрачивать более сложные вещи.
Не слушай задротов и троллей.
Когда только начинаешь, всегда сложно. Потом с опытом конечно становится гораздо легче.
А ты уверен, что выборка будет примерно равномерной? А то вебмок пока что максимум тысяча будет, а скорее всего и того меньше. Достаточно ли это для того, чтобы не возникало ситуации, когда одни вебмки показываются в разы чаще других? Или крон задача решит эту проблему?
Алсо, что по сайту скажешь?
>>484045
>>484039
Хуя вы нервные. Я конечно тоже психую, когда не получается что-то понять, но чтобы выпиливаться из-за этого, это уже пиздец какой-то. Обычно бывает достаточно просто поспать и на утро понимание приходит само собой. Частенько бывает, что ебусь несколько часов с какой-нибудь темой и буквально вместо текста вижу фигу, а утром просыпаюсь, кофейка выпью и за полчаса во всем разбираюсь.
Ну меня просто вывело, то что ничего не работает и даже дамп базы данных загрузить не смог, ну я с психу спать завалился.
Вот вроде всё верно, а почему не загружает?
mysql> mysql -u root -padmin geo < C:\rocid.sql
ERROR 1049 (42000): Unknown database 'ocid.sql'
mysql> mysql -u root -padmin geo < "C:\rocid.sql"
-> ;
No connection. Trying to reconnect...
ERROR 1049 (42000): Unknown database 'ocid.sql'
ERROR:
Can't connect to the server
После этого все команды завершаются такой же ошибкой пока не перезагрузишь.
>Сложно? Ну ок, давай начнем с более простой задачи: просто выведи 5 самых популярных пользователей.
>Подсказка: эта задача решается без подзапросов
А теперь вообще ошибка.
mysql> mysql -u root -padmin geo < "C:\rocid.sql";
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use near 'mysql
-u root -padmin geo < "C:\rocid.sql"' at line 1
Ну общие понятия такие как переменные, функции, циклы и прочее у всех языков программирования есть. Огромная разница в том, что php это серверный язык, а Javascript клиентский. И задачи у них абсолютно разные.
Да и знать обычно требуют не чистый JS, а Jquery. А знать думаю будет достаточно на том уровне, чтобы мочь в большинство современных финтифлюшек, которые например при создании лендингов используются.
Погоди, а база geo у тебя вообще существует?
Создай ее сначала, прежде чем что-то туда заливать.
Она есть, я её создал.
Ты как-то недостаточно вежливо просишь помочь.
Поумоляй меня.
Кстати, столбец like_id тут не нужен, первичный ключ ведь может быть составным:
PRIMARY KEY(to_id, from_id)
> Нелюбовь к оф.документации начинающих вызвана обычно даже не плохим знанием английского, а непоследовательностью изложения.
Предполагается что ты в документации прочтешь сначала общее описание файлов конфигурации, а потом например документацию по интересующим тебя модулям или директивам. То есть по всем директивам которые у тебя тут упомянуты.
Ну и чем больше ты читаешь всякой документации, тем проще становится.
> описано только куда тыкать мышкой в юнити.
Почему, документация http://help.ubuntu.ru/wiki/apache2 описывает командную строку, просто наверно на русском документации меньше чем на английском. Никто, конечно, сервер не настраивает через графическую оболочку.
> Прописать в site.name.conf
> DocumentRoot /var/www/site.name/public_html
Путь неправильный
Алсо, у тебя нет команды a2ensite которая создаст в mods-enabled ссылку на этот конфиг.
> По линуксу есть что-то хорошее?
Надо искать учебники/статьи по командной строке, bash и утилитам. Плюс управление службами (команда service), пакетный менеджер для установки программ (где-то используют apt-get, где-то yum).
> оболочек, вдруг будет стоять что-то другое кроме баша)
Баш во всех дистрибутивах есть, так что не обязательно. там есть другие оболочки вроде csh и еще каких-то, но их ставят ради всяких фич.
> сли у этого парня недостаточно знаний для решения подобного задания, это может вообще демотивировать.
Надо не демотивироваться, а изучать недостающее, никто тебя один на один с заданием не оставит, мы всегда дадим совет или подсказку.
Каждый объект должен иметь айдишник. Что лайк, что сообщение.
Если нельзя лайкать несколько раз один и тот же объект (а такое возможно в случае премиум-акка), просто добавим уникальный индекс на пару.
>Ты как-то недостаточно вежливо просишь помочь.
Ну это уже совсем слив недоучки.
CakePHP тоже очень древний (я же написал вроде список актуальных фреймворков)
C PHPixie не сталкивался
>>484044
> А где об этом можно почитать?
Тут например
https://php.net/manual/ru/reserved.variables.server.php
Ну и это работает таким образом что Апач все, что идет после имени файла (и до знака вопроса), записывает в PATH_INFO. То есть вот это вот '/dashboard' попадает в PATH_INFO и ты можешь проверять его через switch например.
>>484045
А ты яваскрипт и HTTP знаешь? Если да, то по моему тут ничего сложного, аякс это и есть отправка HTTP запроса из яваскрипта.
>>484052
> А ты уверен, что выборка будет примерно равномерной?
А как случайная выборка вообще может быть равномерной? Она будет стремиться к равномерной по мере увеличения числа файлов. Случайная значит случайная, а не равномерная. Если тебе нужна строго равномерная выборка, не используй случайные числа.
> Или крон задача решит эту проблему?
Крон задача исправит ситуации когда какому-то файлу выпадает неудачное число.
> Алсо, что по сайту скажешь?
Пока мельком глянул, замечаний много, напишу позже
>>484055
> -u root
Надо писать вроде слитно -uroot
Алсо эту команду надо писать в командной строке cmd, а не в mysql. Это же по сути ты запускаешь mysql и перенаправляешь данные из файла ей на ввод (вместо клвиатуры). То есть дял Mysql это то же самое что если бы ты руками команды вводил.
CakePHP тоже очень древний (я же написал вроде список актуальных фреймворков)
C PHPixie не сталкивался
>>484044
> А где об этом можно почитать?
Тут например
https://php.net/manual/ru/reserved.variables.server.php
Ну и это работает таким образом что Апач все, что идет после имени файла (и до знака вопроса), записывает в PATH_INFO. То есть вот это вот '/dashboard' попадает в PATH_INFO и ты можешь проверять его через switch например.
>>484045
А ты яваскрипт и HTTP знаешь? Если да, то по моему тут ничего сложного, аякс это и есть отправка HTTP запроса из яваскрипта.
>>484052
> А ты уверен, что выборка будет примерно равномерной?
А как случайная выборка вообще может быть равномерной? Она будет стремиться к равномерной по мере увеличения числа файлов. Случайная значит случайная, а не равномерная. Если тебе нужна строго равномерная выборка, не используй случайные числа.
> Или крон задача решит эту проблему?
Крон задача исправит ситуации когда какому-то файлу выпадает неудачное число.
> Алсо, что по сайту скажешь?
Пока мельком глянул, замечаний много, напишу позже
>>484055
> -u root
Надо писать вроде слитно -uroot
Алсо эту команду надо писать в командной строке cmd, а не в mysql. Это же по сути ты запускаешь mysql и перенаправляешь данные из файла ей на ввод (вместо клвиатуры). То есть дял Mysql это то же самое что если бы ты руками команды вводил.
ОПу незачем решать задачу так как он в голове представляет решение, плюс другие аноны ее решали раньше.
>>484059
Есть хороший учебник на learn.javascript.ru, на русском. Есть наши задачки в ОП посте.
Твой подход «яваскрипт это PHP без доллара» тебе пользы не даст, так как практические задания ты так не сделаешь.
>>484083
А зачем я буду его писать? Я могу представить много случаев когда ни одного синглтона не нужно. Это вообще антипаттерн, зачем его везде пихать?
> многопоточность
Расскажи мне в какой ситуации я встречу многопоточность в программе на PHP
> Такого, чтобы в потомках ничего переопределять не приходилось.
Это же извращение какое-то, базовый класс для синглтона. Ты не ява-программист случаем?
Давай для начала ты продемонстрируешь свое умение писать многопоточнобезопасные синглтоны на яваскрипте, а потом поговорим.
Разница например в том что массив в JS это объект, он передается по ссылки, и тд, разница в областях видимости переменных/замыканиях и куча других тонкостей. Ну и сам по себе JS тебе ничего не дает, надо выучить DOM, библиотеки поверх DOM вроде jQuery.
>>484110
> Каждый объект должен иметь айдишник.
С чего ты это решил? Некоторые нормальные формы действительно требуют наличие первичного ключа, но он не обязан быть именно в виде 1 колонки. У нас тут есть естественный первичный ключ — пара id — и искуственный нам не нужен. Его добаляют когда не удается найти ествественный.
Я тебе советую прежде чем делать категоричные утверждения почитать теорию, ну и желательно как-то ссылками подкреплять, а не просто потому что тебе так кажется или в вашей компании так принято.
Алсо бывают таблицы вообще без первичного ключа, например логи, правда в innoDB к ним добавляется неявный первичный ключ потому их делают в MyISAM.
Да ничего страшного, там многие замечания уровня «Route должен называться FrontController». Ну и исправив их ты станешь пистаь более хороший код в будущем.
>С чего ты это решил?
Это решил не я. Это общая best practice, которой учатся в первый месяц джуниоры.
Ну и из первых ссылок в гугле.
http://code.tutsplus.com/tutorials/top-20-mysql-best-practices--net-7855
>8. Almost Always Have an id Field
>In every table have an id column that is the PRIMARY KEY, AUTO_INCREMENT and one of the flavors of INT. Also preferably UNSIGNED, since the value can not be negative.
А вообще, ты уводишь разговор. Не можешь решить свою же задачу? Смысл ты тогда кого-то обучаешь, если элементарных вещей не понимаешь?
У меня mysql ругается на MyISAM, как лечить?
ERROR 1064 (42000) at line 8: You have an error in your SQL syntax; check the ma
nual that corresponds to your MySQL server version for the right syntax to use n
ear 'TYPE=MyISAM' at line 9
Он ругается не на MyISAM, а на 'TYPE'. Кажется этот оператор устарел, сейчас используется ENGINE.
https://dev.mysql.com/doc/refman/5.1/en/storage-engine-setting.html
Как посчитать количество процентов?
Всё те же уроки опа. Гуглится что-то не очень
Я так понимаю циклом
$summ = 10000
$percent = 1.1
К примеру for ($summ; $summ<=100000; $summ*1.1)
Это я так вижу, чтоб каждый цикл увеличивалось на 1,1
То есть, должно получится что-то вроде 1. 11000, 2. 12100, 3.13200 и так далее. Так вот, чёт не получается. Почему?
Ты походу не понимаешь, как работает присваивание значения переменной в php (и вообще в программировании).
Смотри, значок = в php означает не равенство, а оператор присваивания.
То есть в переменную, имя которой пишется слева от = придет значение, которое пишется справа.
$x = 10 здесь в X придет число 10
$y = $z здесь в переменную придет то значение, которое на данный момент хранится в переменной $z. Кстати, если $z не была объявлена, произойдет ошибка.
Переменная - это ссылка на ячейку оперативной памяти компьютера. Представь себе память как шкаф с большим кол-вом ящиков.
Мы кладем что-то в ящик и подписываем название (кладем в ящик 10 долларов и пишем фломастером слово $summ).
Так и здесь: когда ты пишешь $x = 10, то в какую-то ячейку оперативной памяти компьютера кладется число 10. Чтобы мы могли обратиться потом к этой ячейке и взять значение, мы обозначаем ее $x. На самом деле у всех ячеек памяти есть номера типа 100010111101, но можно сойти с ума прописывать такие адреса памяти. Поэтому и придумали присваивать имена этим ячейкам, чтобы легче к ним обращаться.
Так вот, у тебя написано $summ1.1
Это значит, что из переменной будет взято ЗНАЧЕНИЕ, это значение умножится на 1.1, и оно улетит в пустоту.
Если ты ожидаешь, что переменная $summ увеличится на определенную величину, нужно писать так:
$summ = $summ + 100;
или
$summ = $summ1.1;
Слева от оператора присваивания идет ССЫЛКА, справа значение.
Интерпретатор php будет читать твой код $summ = $summ + 100
следующим образом:
1. Взять ячейку оперативной памяти с меткой $summ (если ее нет, она будет создана) и приготовиться записать в нее значение.
2. Вычислить значение выражения справа от знака =. В данном случае он возьмет текущее значение $summ и прибавит к нему сто.
3. Записать полученное значение в ячейку с именем $summ.
Да, и один процент это одна сотая, а не одна десятая.
$summ = $summ1.01
Есть еще короткий вариант $sum =1.01, но не забивай пока голову, если сложно.
Ты походу не понимаешь, как работает присваивание значения переменной в php (и вообще в программировании).
Смотри, значок = в php означает не равенство, а оператор присваивания.
То есть в переменную, имя которой пишется слева от = придет значение, которое пишется справа.
$x = 10 здесь в X придет число 10
$y = $z здесь в переменную придет то значение, которое на данный момент хранится в переменной $z. Кстати, если $z не была объявлена, произойдет ошибка.
Переменная - это ссылка на ячейку оперативной памяти компьютера. Представь себе память как шкаф с большим кол-вом ящиков.
Мы кладем что-то в ящик и подписываем название (кладем в ящик 10 долларов и пишем фломастером слово $summ).
Так и здесь: когда ты пишешь $x = 10, то в какую-то ячейку оперативной памяти компьютера кладется число 10. Чтобы мы могли обратиться потом к этой ячейке и взять значение, мы обозначаем ее $x. На самом деле у всех ячеек памяти есть номера типа 100010111101, но можно сойти с ума прописывать такие адреса памяти. Поэтому и придумали присваивать имена этим ячейкам, чтобы легче к ним обращаться.
Так вот, у тебя написано $summ1.1
Это значит, что из переменной будет взято ЗНАЧЕНИЕ, это значение умножится на 1.1, и оно улетит в пустоту.
Если ты ожидаешь, что переменная $summ увеличится на определенную величину, нужно писать так:
$summ = $summ + 100;
или
$summ = $summ1.1;
Слева от оператора присваивания идет ССЫЛКА, справа значение.
Интерпретатор php будет читать твой код $summ = $summ + 100
следующим образом:
1. Взять ячейку оперативной памяти с меткой $summ (если ее нет, она будет создана) и приготовиться записать в нее значение.
2. Вычислить значение выражения справа от знака =. В данном случае он возьмет текущее значение $summ и прибавит к нему сто.
3. Записать полученное значение в ячейку с именем $summ.
Да, и один процент это одна сотая, а не одна десятая.
$summ = $summ1.01
Есть еще короткий вариант $sum =1.01, но не забивай пока голову, если сложно.
Как переменные работают, это я понял. Да, как ящик, в который что-то ложишь, а потом,когда надо, забираешь. Пытаюсь что-то учить второй день. После обеда вчера открыл первый раз в жизни обучалку. До этого никогда с программированием дел не имел, максимум батники небольшие писал, ещё во времена win95. Просто меня греет мечта работать на удалёнке, пусть за копейки даже. Поэтому буду учить.
> Almost Always
Как видишь авторы туториала не столь категоричны. Имеется в виду, что id часто удобен когда тебе надо например передать id поста для редактирования. Но первичный ключ не обязан быть именно id.
Более того ниже написано:
> One possible exception to the rule are the "association tables", used for the many-to-many type of associations between 2 tables. For example a "posts_tags" table that contains 2 columns: post_id, tag_id, that is used for the relations between two tables named "post" and "tags". These tables can have a PRIMARY key that contains both id fields.
ты бы абзац до конца дочитал, клоун.
Ну и сама статья так себе, там полезные советы перемешаны с не очень полезными, мне кажется автор просто насобирал их из других статей не особо разобравшись:
> MyISAM is good for read-heavy applications, but it doesn't scale very well when there are a lot of writes.
В MyISAM нет ничего хорошего, нет внешних ключей и транзакций, это просто старый движок и выгоды от его использования почти никогда нет.
> Не можешь решить свою же задачу?
Я вообще-то написал что могу. И если бы ты разбирался в SQL достаточно хорошо ты бы тоже мог, так как способ решения там очевиден (джойн + группировка + сортировка, и этот метод там по моему еще к половине слуаев подходит).
И знаешь, странно, от человека который только изуает основы выслушивать такие категоричные заявления, что я не знаю как решить задачку для начинающих или как выбирать первичный ключ. И давать статьи для нубов с tutsplus в качестве аргументов. Если бы ты дал ссылку на учебник по реляционной алгебре или на определение нормальной формы, это другое дело.
> $summ × 1.1
Это значит умножить переменную на 1.1 но никуда не сохарнить результат. надо писать
$summ = $summ × 1.1
или
$summ ×= 1.1
ну и вместо 1.1 лучше сделать переменную с объясняющим названием, ради читабельности.
С виртуальными хостами разобрался, успешно пересадил сайты из /var/www себе в домашнюю папку.
Но оно все равно на меня ругается с правами.
Например gii генератор yii-фреймворка говорит, что не может сохранить файлы. В данном случае не критично, можно скопировать и сохранить вручную.
Я просто хочу понять, какой пользователь вызывает этот процесс? Это root, или какой-нибудь демон? Если я буду знать как его зовут, то добавлю его в группу своему пользователю и дам права на запись.
Но ведь сессия уже удобно зашифрована за меня и я уже использую сессии для сохранения данных. Вот у меня есть игра http://serdce-kamnya.comeze.com/
Вся статистика: игры, победы, ранг и все такое - хранится в сессии. Но если человек уходит со странички на пол часа или просто ничего не делает, то сессия погибает. Я понимаю что это изначально сделано неправильно и надо бы без обращения к серверу такие вещи обсчитывать, а просто яваскриптом, но я его пока не знаю. В процессе изучения обязательно создам альтернативную версию без обращения к серверу по кажому чиху, а только для того что бы подгружать новую картинку например. Собственно что бы не писать шифровалку / дешифровалку для куки просто хотелось изящно продлить жизнь сессии. Алсо там нет посещаемости такой, что бы засрать сервер этими сессиями.
Теперь пара слов о:
>CodeIgniter
>Не используйте, он давно устарел, компания-разработчик его забросила, код написан еще под PHP4 и на новом PHP сыплет варнингами.
Я тот кун который год просидел в твоем треде и месяц назад нашел наконец свою работу. На работе как раз пишем небольшой проект на Кодигнайтере, как узнали что месяц назад вышла новая версия фреймворка, то и перекатились на неё. Сайт разрабов не выглядит мертвым: http://www.codeigniter.com/
Алсо проблем не испытываем с варнингами и прочими делами.
>компания-разработчик его забросила, код написан еще под PHP4 и на новом PHP сыплет варнингами.
Может быть у тебя информация 1-2 летней давности? Они вроде как сменили хозяев, но разработка не завершилась. Ру-комьюнити как я понимаю мертво и все перекатились на то что ты перечислил, но англофорумы живы. Я не пришел его тут пиарить или типа того. Просто работаю на нем, пишу код каждый день. У меня альтернативы на работе пока не предвидится, но не вижу в нем ничего плохого. Ну и я не >>483942
Пересоздай таблицы в utf8.
Проверь кодировку редактора.
В html должен быть тег <meta charset="utf8">
При соединении с бд нужно устанавливать кодировку:
$dbh = new PDO('mysql:host=localhost;dbname=test;charset=UTF8', $user, $pass);
или mysqli_query("SET NAMES 'UTF8'");
Заливаю дамп. --default-character-set=utf8 с такой инструкцией ругается
ERROR 1366 (HY000) at line 22: Incorrect string value: '\xD0\x9C\xD0\xBE\xD1\x81
...' for column 'name' at row 1
В дампе какая кодировка стоит у таблиц (DEFAULT CHARSET=...), какая кодировка самого дампа (SET NAMES ...)? Можешь дамп или часть выложить?
Там в явном виде не задано.
Ну хорошо, это понятно. Переменные стараюсь так и так объявлять всегда и на всё.
Ну помножит он мне первый раз, скажем $summ1 = $summ*$percentб получится, к примеру, 110, дальше эти 110 мне надо ещё раз умножить на 1.1 и так далее раз 30-40, а то и 50. Я так понимаю, реализуется это циклом, а так как я ещё совсем зелёный, совершенно не могу правильный цикл написать. Не то, чтобы мозг взрывается от уроков опа, вроде доступно всё, но такое ощущение, что я чего-то не догоняю, какой-то буквально мелочи. Подскажите, как же таки зациклить, чтобы новое число на $percent умножалось каждый раз
http://ideone.com/hnM2cU
Ты можешь поместить эту команду внутрь цикла, а условием для повтора цикла поставить «пока сумма меньше миллиона». Или же просто можешь сделать цикл от 1 до например 100, а проверку на достижение миллиона сделать через if:
если (сумма больше или равна миллиону) {
написать сообщение;
выйти из цикла;
}
Я уверен подобное уже должно быть в симфони2, но перерыв мануал и гугл нашел только как данные формы записать в базу данных, а это всё же не то.
if($a>15 && $a<50) {
}
А, так ты заливаешь не свой дамп, а какую-то левую базу и даже не посмотрел, что там внутри.
Во-первых там прописана устаревшая форма объявления типа таблиц. Сейчас нельзя писать TYPE=MyISAM, нужно ENGINE=MyISAM. Да и MyISAM устарел, у него меньше возможностей чем InnoDB.
Замени type на engine и myisam на innodb в тех местах, где создаются таблицы.
Кодировку самого файла дампа тоже нужно сменить на utf8. Потому что мне sublime пишет opened as cp-1252, detected cp-1251 (document may be broken). Открой файл в своем редакторе и смени кодировку файла.
> --default-character-set=utf8
Это не нужно. И вообще
https://bugs.mysql.com/bug.php?id=52047
И не торопись, у меня заливалось 15 минут.
В связи с этим вопрос к ОПу как местному авторитету:
нужно ли временно отключать индексы при массированной вставке?
ALTER TABLE table1 DISABLE KEYS;
INSERT INTO table1 VALUES
...........
...........
ALTER TABLE table1 ENABLE KEYS;
Или в разных движках по разному?
Вот я в этом примере выставил InnoDB, и у меня все равно вставка жалких 10 000 строк заняла 15 минут. Что-то не похоже, что отключение индексов помогло.
Точно, в Химках. Еще и на дерево залазит, и оттуда всех нахуй шлет.
> https://github.com/Nattpyre/randomwebm/blob/master/config.php
Имей в виду, что в общем в фреймворках не принято делать настройки константами, а принято делать обычными переменными или массивами, так как константы глобально видимы. Ты не найдешь констант-настроек ни в Slim, ни в Yii (там вроде есть пара указывающих на пути к разным папкам, но они по моему от старых времен остались), ни в Симфони.
> https://github.com/Nattpyre/randomwebm/blob/master/app/core.php#L3
Если у тебя много классов, то вместо написания кучи реквайров стоит подумать про автозагрузчик. Для этого надо сделать имена файлов классов в соответствии с PSR-0 (без неймспейсов, с подчеркиваниями вроде Controller_News) или с PSR-4 (с неймспейсами) и написать сам автозагрузчик. Автозагрузчик это функция которую вызвыает PHP при обращении к несуществующему классу и которая может подключить файл с эти классом. Твой автозагрузчик должен состоять из такого кода:
определить имя файла по имени класса;
если (файл существует) { подключить его; }
Мануал: http://php.net/manual/ru/function.spl-autoload-register.php
http://habrahabr.ru/post/136761/
Обрати внимание, что в PHP даже есть готовая функция автозагрузки spl_autoload.
> https://github.com/Nattpyre/randomwebm/blob/master/app/core/route.php#L5
Это не роутер (и тем более не маршрут, а Route переводится именно так). Роутер это функция или класс которая анализирует URL и возвращает, какой контроллер/действие надо вызвать. То, что у тебя это FrontController: http://www.google.ru/search?sourceid=chrome&ie=UTF-8&q=%D0%BF%D0%B0%D1%82%D1%82%D0%B5%D1%80%D0%BD+frontcontroller
Алсо, не используй статические методы. Это в общем плохая штука, так как получается более сильно спутанный код, мы не можем создать несколько экземпляров с разными настройками и т.д. На твоем маленьком приложении конечно эти недостатки наверно и не проявятся, но если ты пишешь большее приложение или например библиотеку для массового использования то статические методы это плохо.
> но для упрощения сразу сделаем редирект на страницу 404
Страницу 404 надо показывать сразу, а не редиректить на нее. ЧТо за бред? Редирект значит что искомая страница есть, но по другому адресу. Код 404 значит что страницы нет. Следовательно, редиректа быть не должно.
Вот список кодов состояния: https://ru.wikipedia.org/wiki/%D0%A1%D0%BF%D0%B8%D1%81%D0%BE%D0%BA_%D0%BA%D0%BE%D0%B4%D0%BE%D0%B2_%D1%81%D0%BE%D1%81%D1%82%D0%BE%D1%8F%D0%BD%D0%B8%D1%8F_HTTP
Вот еще мнение блогера по этому поводу: https://www.artlebedev.ru/kovodstvo/sections/93/
> Наконец, самое важное, что должен учесть создатель сайта, — это сохранение ошибочного адреса в адресной строке. Когда сервер перебрасывает пользователя на заранее подготовленную страницу со своим отдельным адресом, не надо забывать высказать свое «фи» администратору ресурса
> header('HTTP/1.1 404 Not Found');
> header("Status: 404 Not Found");
> header('Location:'.$host.'404');
Это однозначно показывает что ты не знаешь что делают эти заголовки, и скорее всего надерагл их из каких-то сомнительных статей неграмотных авторов. Не делай так, а ознакомься для начала с мануалом: http://php.net/manual/ru/function.header.php
Ну и Location и код 404 не совместимы, скорее всего Location вызовет замену кода на один из 300-х.
Должен быть один заголовок выставляющий код 404, после которого должна выводиться сама страница ошибки.
> https://github.com/Nattpyre/randomwebm/blob/master/app/core/controller.php#L5
> class Controller {
> public $model;
MVC не предусматривает что один контроллер работает ровно с одной моделью. Более того, непонятно какая именно модель должна храниться тут. Надо, думаю, убрать это поле из базового класса, так как непонятно что оно знаичт? Что в твоих контроллерах нельзя использовать больше одной модели?
> public $model;
> public $view;
Почему public? Предполагается снаружи лезть в контроллер? Ты должен ставить наиболее закрытый тип доступа, а не наиболее открытый.
Ты этого скорее всего не чувствуешь, но если ты пишешь код то каждое слово что-то значит. Публичное свойство значит что предполагается читать/менять его снаружи и это вызывает закономерный вопрос: в какой такой ситуации нам может понадобиться снаружи лезть в контроллер?
> app/core/view.php
В твоем микрофреймворке незачем по моему делать класс View, хватило бы метода render в базовом контроллере. Но раз есть, пусть остается.
> function generate($content_view, $template_view, $data = null)
Почему для data значение по умолчанию null а не пустой массив? Всегда лучше когда аргумент имеет один тип значения а не несколько. Алсо, почему нет тайп хинта?
> https://github.com/Nattpyre/randomwebm/blob/master/app/core/model.php#L6
> public function get_data()
Зачем тут эта функция, которая мало того что ничего не делает, так еще и названа не по стандарту (принято называть doSomething)? И еще, ты должен чуть лучше продумывать названия, так как название get_data ничего не значит. Почти любая функция возвращает какие-то данные. Вот статья, почитай: http://learn.javascript.ru/write-unmain-code
Функция может называться getAllPosts, getPostById, это нормальные названия.
> include (SITE_PATH . DS . 'app' . DS . 'models' . DS . 'webm.php');
Ты бы мог использовать прямой слеш / который работает на всех платформах. Ну и еще, ты бы мог написать автозагрузчик и убрать кучу инклудов из кода. И кстати лучше использовать require вместо include так как для реквайр отстутсиве файла это фатальная ошибка.
> https://github.com/Nattpyre/randomwebm/blob/master/app/controllers/add.php#L27
> if($_FILES['webmUpload']['error'] === UPLOAD_ERR_INI_SIZE
Эту простыню хорошо бы сделать универсальной и вынести в функцию. Ведь если ты будешь загружать еще какой-то файл в другом месте, то она тебе тоже понадобится.
> https://github.com/Nattpyre/randomwebm/blob/master/app/models/webmmapper.php#L43
> public function checkWebm($name) {
Сделай название которое явно и недвусмысленно говорит что именно проверяет функция (наличие уже загруженного файла или является ли файл дубликатом)
> ("SELECT * FROM webms WHERE name='$name'
Никогда не вставляй переменные в запрос, используй плейсхолдеры. Это же SQL инъекция. Ну и выглядит как привет из 90-х и времен PHP4.
> WHERE name='
Странно что ты проверяешь на уникальность файл по имени. разве для этого не лучше сделать отдельное поле с хешем? Проверка по имени файла выглядит хрупкой, и она обязательно сломается если ты например решишь называть файлы по другому принципу. И если ты делаешь проверку по имени, то тут и в том месте где это имя генерируется должны быть объясняющие и предупреждающие комментарии.
> https://github.com/Nattpyre/randomwebm/blob/master/app/models/webmmapper.php#L9
Тут код раскособочило. Не используй табы.
> https://github.com/Nattpyre/randomwebm/blob/master/config.php
Имей в виду, что в общем в фреймворках не принято делать настройки константами, а принято делать обычными переменными или массивами, так как константы глобально видимы. Ты не найдешь констант-настроек ни в Slim, ни в Yii (там вроде есть пара указывающих на пути к разным папкам, но они по моему от старых времен остались), ни в Симфони.
> https://github.com/Nattpyre/randomwebm/blob/master/app/core.php#L3
Если у тебя много классов, то вместо написания кучи реквайров стоит подумать про автозагрузчик. Для этого надо сделать имена файлов классов в соответствии с PSR-0 (без неймспейсов, с подчеркиваниями вроде Controller_News) или с PSR-4 (с неймспейсами) и написать сам автозагрузчик. Автозагрузчик это функция которую вызвыает PHP при обращении к несуществующему классу и которая может подключить файл с эти классом. Твой автозагрузчик должен состоять из такого кода:
определить имя файла по имени класса;
если (файл существует) { подключить его; }
Мануал: http://php.net/manual/ru/function.spl-autoload-register.php
http://habrahabr.ru/post/136761/
Обрати внимание, что в PHP даже есть готовая функция автозагрузки spl_autoload.
> https://github.com/Nattpyre/randomwebm/blob/master/app/core/route.php#L5
Это не роутер (и тем более не маршрут, а Route переводится именно так). Роутер это функция или класс которая анализирует URL и возвращает, какой контроллер/действие надо вызвать. То, что у тебя это FrontController: http://www.google.ru/search?sourceid=chrome&ie=UTF-8&q=%D0%BF%D0%B0%D1%82%D1%82%D0%B5%D1%80%D0%BD+frontcontroller
Алсо, не используй статические методы. Это в общем плохая штука, так как получается более сильно спутанный код, мы не можем создать несколько экземпляров с разными настройками и т.д. На твоем маленьком приложении конечно эти недостатки наверно и не проявятся, но если ты пишешь большее приложение или например библиотеку для массового использования то статические методы это плохо.
> но для упрощения сразу сделаем редирект на страницу 404
Страницу 404 надо показывать сразу, а не редиректить на нее. ЧТо за бред? Редирект значит что искомая страница есть, но по другому адресу. Код 404 значит что страницы нет. Следовательно, редиректа быть не должно.
Вот список кодов состояния: https://ru.wikipedia.org/wiki/%D0%A1%D0%BF%D0%B8%D1%81%D0%BE%D0%BA_%D0%BA%D0%BE%D0%B4%D0%BE%D0%B2_%D1%81%D0%BE%D1%81%D1%82%D0%BE%D1%8F%D0%BD%D0%B8%D1%8F_HTTP
Вот еще мнение блогера по этому поводу: https://www.artlebedev.ru/kovodstvo/sections/93/
> Наконец, самое важное, что должен учесть создатель сайта, — это сохранение ошибочного адреса в адресной строке. Когда сервер перебрасывает пользователя на заранее подготовленную страницу со своим отдельным адресом, не надо забывать высказать свое «фи» администратору ресурса
> header('HTTP/1.1 404 Not Found');
> header("Status: 404 Not Found");
> header('Location:'.$host.'404');
Это однозначно показывает что ты не знаешь что делают эти заголовки, и скорее всего надерагл их из каких-то сомнительных статей неграмотных авторов. Не делай так, а ознакомься для начала с мануалом: http://php.net/manual/ru/function.header.php
Ну и Location и код 404 не совместимы, скорее всего Location вызовет замену кода на один из 300-х.
Должен быть один заголовок выставляющий код 404, после которого должна выводиться сама страница ошибки.
> https://github.com/Nattpyre/randomwebm/blob/master/app/core/controller.php#L5
> class Controller {
> public $model;
MVC не предусматривает что один контроллер работает ровно с одной моделью. Более того, непонятно какая именно модель должна храниться тут. Надо, думаю, убрать это поле из базового класса, так как непонятно что оно знаичт? Что в твоих контроллерах нельзя использовать больше одной модели?
> public $model;
> public $view;
Почему public? Предполагается снаружи лезть в контроллер? Ты должен ставить наиболее закрытый тип доступа, а не наиболее открытый.
Ты этого скорее всего не чувствуешь, но если ты пишешь код то каждое слово что-то значит. Публичное свойство значит что предполагается читать/менять его снаружи и это вызывает закономерный вопрос: в какой такой ситуации нам может понадобиться снаружи лезть в контроллер?
> app/core/view.php
В твоем микрофреймворке незачем по моему делать класс View, хватило бы метода render в базовом контроллере. Но раз есть, пусть остается.
> function generate($content_view, $template_view, $data = null)
Почему для data значение по умолчанию null а не пустой массив? Всегда лучше когда аргумент имеет один тип значения а не несколько. Алсо, почему нет тайп хинта?
> https://github.com/Nattpyre/randomwebm/blob/master/app/core/model.php#L6
> public function get_data()
Зачем тут эта функция, которая мало того что ничего не делает, так еще и названа не по стандарту (принято называть doSomething)? И еще, ты должен чуть лучше продумывать названия, так как название get_data ничего не значит. Почти любая функция возвращает какие-то данные. Вот статья, почитай: http://learn.javascript.ru/write-unmain-code
Функция может называться getAllPosts, getPostById, это нормальные названия.
> include (SITE_PATH . DS . 'app' . DS . 'models' . DS . 'webm.php');
Ты бы мог использовать прямой слеш / который работает на всех платформах. Ну и еще, ты бы мог написать автозагрузчик и убрать кучу инклудов из кода. И кстати лучше использовать require вместо include так как для реквайр отстутсиве файла это фатальная ошибка.
> https://github.com/Nattpyre/randomwebm/blob/master/app/controllers/add.php#L27
> if($_FILES['webmUpload']['error'] === UPLOAD_ERR_INI_SIZE
Эту простыню хорошо бы сделать универсальной и вынести в функцию. Ведь если ты будешь загружать еще какой-то файл в другом месте, то она тебе тоже понадобится.
> https://github.com/Nattpyre/randomwebm/blob/master/app/models/webmmapper.php#L43
> public function checkWebm($name) {
Сделай название которое явно и недвусмысленно говорит что именно проверяет функция (наличие уже загруженного файла или является ли файл дубликатом)
> ("SELECT * FROM webms WHERE name='$name'
Никогда не вставляй переменные в запрос, используй плейсхолдеры. Это же SQL инъекция. Ну и выглядит как привет из 90-х и времен PHP4.
> WHERE name='
Странно что ты проверяешь на уникальность файл по имени. разве для этого не лучше сделать отдельное поле с хешем? Проверка по имени файла выглядит хрупкой, и она обязательно сломается если ты например решишь называть файлы по другому принципу. И если ты делаешь проверку по имени, то тут и в том месте где это имя генерируется должны быть объясняющие и предупреждающие комментарии.
> https://github.com/Nattpyre/randomwebm/blob/master/app/models/webmmapper.php#L9
Тут код раскособочило. Не используй табы.
> https://github.com/Nattpyre/randomwebm/blob/master/app/models/webmmapper.php#L14
> die('Ошибка подключения к базе данных.');
Надо выбрасывать исключение, читай урок: https://gist.github.com/codedokode/65d43ca5ac95c762bc1a
Если ты хочешь ловить исключения и выводить страницу-заглушку то поставь обработчик исключений например в виде try/catch или set_exception_handler где-нибудь в FrontController.
> https://github.com/Nattpyre/randomwebm/blob/master/app/models/webmmapper.php#L74
> public function moveToMainBase ($name, $source)
Непонятно почему функция перемещения разбита на 2 функции которые надо вызывать отдельно. Почему бы ей как раз их и не вызывать?
> public function countWebms()
> $data = $data->fetch_assoc();
Функция судя по называнию должна возвращать число, а вместо этого возвращает массив. Думаю, надо переделать ее нормально чтобы пользователю функции не надо было разбирать этот массив. Кстати, в PDO есть fetchColumn который читает как раз ровно одну ячейку. Ну и вообще, по моему PDO удобнее.
Также, ты должен при использовании mysqli проверять каждую функцию, не вернула ли она ошибку. Иначе PHP продолжить выполнять скрипт дальше, скорее всего вернув неверные результаты. PDO умеет выбрасывать исключения (потому он по моему лучше), а mysqli нет.
Давай проверим, правильно ли ты реализоал обработку ошибок mysqli. Попробуй написать и выполнить такой код:
$this->db->query("asasdahsdahsdiahdiahdh");
Если у тебя все настроено правильно то скрипт должен прерваться выведя сообщение от MySQL о неправильном запросе. Если у тебя все сделано неправильно то никаких сообщений не будет и скрипт спрячет ошибку и будет выполняться дальше как будто бы все в порядке. Я не раз сталкивался с такими скриптами, и найти в них ошибку, если они ее не выводят, как ты наверно доагдываешься, непросто.
Потому ты должен как в мануале вокруг каждой функции поставить if проверяющий результат выполнения и выбрасывать исключение с подробностями ошибки если функция вернула false или аналогичное значение. Посмотри мануал:
http://php.net/manual/ru/mysqli.error.php
http://php.net/manual/ru/mysqli.quickstart.statements.php
Там всюду стоят ифы, только вместо die лучше использовать исключения, почему написано в моем уроке.
Кстати PDO уже умеет выбрасывать исключения если включить нужную настройку и с ним ифы писать не надо.
Я думаю разработчики mysqli планировали что ты будешь использовать его не напрямую, а через класс который умеет проверять ошибки и делать другие вещи. Если ты используешь напрямую то ставь ифы.
Я вижу что в одном месте иф у тебя есть: if($stmt->execute()) но этого недостаточно, так как никуда не сохраняются подробности ошибки.
> https://github.com/Nattpyre/randomwebm/blob/master/app/models/webm.php#L11
> include 'webmmapper.php';
Инклуды должны стоять в самом начале файла а не внутри конструктора. Почитай PSR-1 и 2.
> public function sendMessage($name, $email, $subject, $message)
Если ты читал мой урок про датамапперы то наверно заметил что аргументом там передается объект-модель, а не значения полей. Так получается удобнее, особенно когда полей много.
> https://github.com/Nattpyre/randomwebm/blob/master/app/models/login.php#L9
> $this->db = new mysqli(DB_HOST,
Ты не должен создавать новое соединение в каждом маппере, а должен использовать одно, которое можно передавать например через конструктор. Вот тут объяснено почему: https://gist.github.com/codedokode/e1d31a31b37d5f635057
> https://github.com/Nattpyre/randomwebm/blob/master/app/controllers/admin.php
тут слишком много кода. надо стараться делать тонкие контродлеры и толстые модели так как код в контроллерах нельзя повторно использовать, и потому его должно быть как можно меньше. Контроллер это что-то вроде начальника, который только командует другими, а сам ничего не делает.
Далее, не надо перемешивать сторонний код библиотек со своими файлами. Если ты используешь бутстрап то помести его в отдельную папку (например vendor/bootstrap) и не клади туда ничего другого. Иначе потом не понять где чей код и неудобно обновлять тот же бутстрап.
Вообще, у меня тут ощущение что я пересказываю то, что уже много раз объяснял, потому почитай еще примечания вот к этой задаче и посмотри, нет ли там того, что подходит к твоему коду: https://github.com/codedokode/pasta/blob/master/student-list.md#Комментарии-подводные-камни-и-советы
Валидацию надо выносить в отдельную функцию или класс. То что сейчас у тебя намертво вшито в контроллер и завязано на массив POST. Правильнее сделать где-то функцию которая получает на вход модель, например Message и возвращает список найденных в ней ошибок.
> <?php echo htmlspecialchars($data['name'], ENT_QUOTES);
Я советую сделать функцию с более коротким назанием, также вместо <?php echo можно использоать <?=
Остальное я проверю после исправления этих замечаний, вот еще порция советов от робота:
--------------
Кажется, ты не используешь строгий режим в MySQL. Зря. MySQL более тщательно проверяет твои запросы и вместо предупреждений (которые ты не увидишь) выдает ошибки при попытке вставить неправильные данные. Ну к примеру, если у тебя есть колонка типа varchar(200) и ты попытаешься вставить в нее строку из 300 символов, в нестрогом режиме MySQL молча отрежет лишнее (и в базе окажется обрезанная строка), а в строгом выдаст ошибку.
Использование строгого режима экономит твое время на исправление неправильно вставленных данных. Статья на хабре: http://habrahabr.ru/post/116922/
Включить строгий режим можно сделав при соединении с БД запрос SET sql_mode='STRICT_ALL_TABLES'.
В файле ./app/core/view.php:
В методе View#generate аргумент $data можно пометить тайп хинтом array.
Тайп хинты позволяют указать, что аргумент функции должен быть определенного типа (например, быть объектом определенного класса или его наследника). Тайп хинт делает код понятнее (так как видно какого типа переменная) и надежнее (так как PHP не позволит передать что-то неразрешенное и ты сразу увидишь ошибку). Используй их везде.
Мануал: http://php.net/manual/ru/language.oop5.typehinting.php
В файле ./app/views/templates/default/add.php:
Слеш в конце одиночного тега (<input type="hidden" name="MAX…8" />) используется только в XHTML и XML, в HTML он не ставится.
В проекте не хватает SQL дампа.
В файле ./app/views/templates/default/main.php:
> strlen(
Ты используешь функции, которые работают неправильно с нелатинскими символами в utf8. Они рассчитаны на однобайтные кодировки, а utf-8 многобайтная. Надо использовать функции вроде mb_strlen, которые корректно поддерживают utf-8. Даже если ты работаешь только с латинскими строками, лучше придерживаться единого стиля во всей программе и использовать mb-функции.
Подробнее про строки и utf-8: https://gist.github.com/codedokode/ff99e357e9860ea169b8
Ты используешь функции mb_xxx в своем коде, а указал ли ты для них используемую кодировку с помощью mb_internal_encoding(...)? Без этого эти функции могут неправильно обрабатывать строки.
> https://github.com/Nattpyre/randomwebm/blob/master/app/models/webmmapper.php#L14
> die('Ошибка подключения к базе данных.');
Надо выбрасывать исключение, читай урок: https://gist.github.com/codedokode/65d43ca5ac95c762bc1a
Если ты хочешь ловить исключения и выводить страницу-заглушку то поставь обработчик исключений например в виде try/catch или set_exception_handler где-нибудь в FrontController.
> https://github.com/Nattpyre/randomwebm/blob/master/app/models/webmmapper.php#L74
> public function moveToMainBase ($name, $source)
Непонятно почему функция перемещения разбита на 2 функции которые надо вызывать отдельно. Почему бы ей как раз их и не вызывать?
> public function countWebms()
> $data = $data->fetch_assoc();
Функция судя по называнию должна возвращать число, а вместо этого возвращает массив. Думаю, надо переделать ее нормально чтобы пользователю функции не надо было разбирать этот массив. Кстати, в PDO есть fetchColumn который читает как раз ровно одну ячейку. Ну и вообще, по моему PDO удобнее.
Также, ты должен при использовании mysqli проверять каждую функцию, не вернула ли она ошибку. Иначе PHP продолжить выполнять скрипт дальше, скорее всего вернув неверные результаты. PDO умеет выбрасывать исключения (потому он по моему лучше), а mysqli нет.
Давай проверим, правильно ли ты реализоал обработку ошибок mysqli. Попробуй написать и выполнить такой код:
$this->db->query("asasdahsdahsdiahdiahdh");
Если у тебя все настроено правильно то скрипт должен прерваться выведя сообщение от MySQL о неправильном запросе. Если у тебя все сделано неправильно то никаких сообщений не будет и скрипт спрячет ошибку и будет выполняться дальше как будто бы все в порядке. Я не раз сталкивался с такими скриптами, и найти в них ошибку, если они ее не выводят, как ты наверно доагдываешься, непросто.
Потому ты должен как в мануале вокруг каждой функции поставить if проверяющий результат выполнения и выбрасывать исключение с подробностями ошибки если функция вернула false или аналогичное значение. Посмотри мануал:
http://php.net/manual/ru/mysqli.error.php
http://php.net/manual/ru/mysqli.quickstart.statements.php
Там всюду стоят ифы, только вместо die лучше использовать исключения, почему написано в моем уроке.
Кстати PDO уже умеет выбрасывать исключения если включить нужную настройку и с ним ифы писать не надо.
Я думаю разработчики mysqli планировали что ты будешь использовать его не напрямую, а через класс который умеет проверять ошибки и делать другие вещи. Если ты используешь напрямую то ставь ифы.
Я вижу что в одном месте иф у тебя есть: if($stmt->execute()) но этого недостаточно, так как никуда не сохраняются подробности ошибки.
> https://github.com/Nattpyre/randomwebm/blob/master/app/models/webm.php#L11
> include 'webmmapper.php';
Инклуды должны стоять в самом начале файла а не внутри конструктора. Почитай PSR-1 и 2.
> public function sendMessage($name, $email, $subject, $message)
Если ты читал мой урок про датамапперы то наверно заметил что аргументом там передается объект-модель, а не значения полей. Так получается удобнее, особенно когда полей много.
> https://github.com/Nattpyre/randomwebm/blob/master/app/models/login.php#L9
> $this->db = new mysqli(DB_HOST,
Ты не должен создавать новое соединение в каждом маппере, а должен использовать одно, которое можно передавать например через конструктор. Вот тут объяснено почему: https://gist.github.com/codedokode/e1d31a31b37d5f635057
> https://github.com/Nattpyre/randomwebm/blob/master/app/controllers/admin.php
тут слишком много кода. надо стараться делать тонкие контродлеры и толстые модели так как код в контроллерах нельзя повторно использовать, и потому его должно быть как можно меньше. Контроллер это что-то вроде начальника, который только командует другими, а сам ничего не делает.
Далее, не надо перемешивать сторонний код библиотек со своими файлами. Если ты используешь бутстрап то помести его в отдельную папку (например vendor/bootstrap) и не клади туда ничего другого. Иначе потом не понять где чей код и неудобно обновлять тот же бутстрап.
Вообще, у меня тут ощущение что я пересказываю то, что уже много раз объяснял, потому почитай еще примечания вот к этой задаче и посмотри, нет ли там того, что подходит к твоему коду: https://github.com/codedokode/pasta/blob/master/student-list.md#Комментарии-подводные-камни-и-советы
Валидацию надо выносить в отдельную функцию или класс. То что сейчас у тебя намертво вшито в контроллер и завязано на массив POST. Правильнее сделать где-то функцию которая получает на вход модель, например Message и возвращает список найденных в ней ошибок.
> <?php echo htmlspecialchars($data['name'], ENT_QUOTES);
Я советую сделать функцию с более коротким назанием, также вместо <?php echo можно использоать <?=
Остальное я проверю после исправления этих замечаний, вот еще порция советов от робота:
--------------
Кажется, ты не используешь строгий режим в MySQL. Зря. MySQL более тщательно проверяет твои запросы и вместо предупреждений (которые ты не увидишь) выдает ошибки при попытке вставить неправильные данные. Ну к примеру, если у тебя есть колонка типа varchar(200) и ты попытаешься вставить в нее строку из 300 символов, в нестрогом режиме MySQL молча отрежет лишнее (и в базе окажется обрезанная строка), а в строгом выдаст ошибку.
Использование строгого режима экономит твое время на исправление неправильно вставленных данных. Статья на хабре: http://habrahabr.ru/post/116922/
Включить строгий режим можно сделав при соединении с БД запрос SET sql_mode='STRICT_ALL_TABLES'.
В файле ./app/core/view.php:
В методе View#generate аргумент $data можно пометить тайп хинтом array.
Тайп хинты позволяют указать, что аргумент функции должен быть определенного типа (например, быть объектом определенного класса или его наследника). Тайп хинт делает код понятнее (так как видно какого типа переменная) и надежнее (так как PHP не позволит передать что-то неразрешенное и ты сразу увидишь ошибку). Используй их везде.
Мануал: http://php.net/manual/ru/language.oop5.typehinting.php
В файле ./app/views/templates/default/add.php:
Слеш в конце одиночного тега (<input type="hidden" name="MAX…8" />) используется только в XHTML и XML, в HTML он не ставится.
В проекте не хватает SQL дампа.
В файле ./app/views/templates/default/main.php:
> strlen(
Ты используешь функции, которые работают неправильно с нелатинскими символами в utf8. Они рассчитаны на однобайтные кодировки, а utf-8 многобайтная. Надо использовать функции вроде mb_strlen, которые корректно поддерживают utf-8. Даже если ты работаешь только с латинскими строками, лучше придерживаться единого стиля во всей программе и использовать mb-функции.
Подробнее про строки и utf-8: https://gist.github.com/codedokode/ff99e357e9860ea169b8
Ты используешь функции mb_xxx в своем коде, а указал ли ты для них используемую кодировку с помощью mb_internal_encoding(...)? Без этого эти функции могут неправильно обрабатывать строки.
Дамп в кодировке cp1251. Раз так, поставь в самом начале файла SET NAMES 'cp1251' либо сконвертируй его в utf-8 и поставь SET NAMES 'utf8'
Во всех CREATE TABLE надо заменить TYPE на ENGINE и дописать DEFAULT CHARSET='utf8'
Праивльный ответ около 61270. У тебя перебор.
> ( $creditBalance $percent ) + $servicePayment
Эта строка повторяется 2 раза, надо избавиться от повтора, может как-то в переменную это вынести.
Сам алгоритм излишне усложнен. Ты явно скопипастил отдельно логику для последнего месяца, хотя можно сделать общий код для всех месяцев. Должно быть всего несколько действий, примерно так:
- прибавляем проценты и комиссию к остатку долга
- если остаток маленький, выплачиваем сколько осталось и уходим
- иначе платим 5000
«Платим» здесь значит уменьшаем долг и увеличиваем общую сумму выплаченного.
А у тебя в первой строке:
> $creditBalance = ( $creditBalance $percent ) + $servicePayment - $monthlyPayment;
ты уже платишь 5000 даже не проверив сначала чему равен долг.
Ты про доктрину? Для подстановки значений в запрос надо использовать плейсхолдеры, а для сборки запроса в зависимости от условий надо использовать Query Builder. В доктрине есть 2 QB, для обычных SQL запросов: http://doctrine-dbal.readthedocs.org/en/latest/reference/query-builder.html и для DQL: http://doctrine-orm.readthedocs.org/en/latest/reference/query-builder.html
Соответственно если твой запрос зависит от каких-то условий, то используй query builder:
if ($searchInCity) {
$qb->addWhere(city = :city');
$qb->setParameter('city', $city);
}
Если же запрос всегда одинаково выглядит то QB тебе не нужен.
> case в данной конструкции case должна равняться какому то определённому значению?
да
> Как записать например такое через switch-case
Использовать if/else
>>484547
> нужно ли временно отключать индексы при массированной вставке?
Можно, mysqldump это делает, но руками например в коде такие вещи делать не стоит, это только для дампов.
> и у меня все равно вставка жалких 10 000 строк заняла 15 минут.
Что-то долго, всего 10 вставок в секунду? У тебя что-то плохо настроено. Ну и если тебе надо делать массовые вставки из кода то там есть специальный раздел про это:
https://dev.mysql.com/doc/refman/5.5/en/optimizing-innodb-bulk-data-loading.html
https://dev.mysql.com/doc/refman/5.5/en/optimizing-myisam-bulk-data-loading.html
Например вставка одной транзакцией или использование multi insert может сильно ускорить процесс (обрати внимание, мануал первым делом именно это и советует).
Имей в виду также что отключать внешние ключи можно только когда есть 100% гарантия что ссылки там стоят правильные.
> Вся статистика: игры, победы, ранг и все такое - хранится в сессии.
Гораздо лучше использовать базу данных. Как ты со своими сессиями выведешь топ игроков? Я советую сразу перекатываться на базу данных таким образом:
— если человек пришел в первые, генерируем ему уникальный длинный id, сохраняем в куки и создаем запись в БД
— если человек пришел с id и такой есть в базе, испоьзуем его
Если не хочешь, ты можешь погуглить способы продлить сессию, но я бы советовал использовать базу.
> Алсо проблем не испытываем с варнингами и прочими делами.
Может у вас они просто не выводятся? Логи смотрите?
Я не знаю, я слышал что пилят 3-ю версию, но по моему она в том же стиле что и старая, стадартам вроде PSR не соответствует, в общем живет прошлым.
Ну и смотри код:
https://github.com/bcit-ci/CodeIgniter/blob/develop/index.php#L78
> error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED & ~E_STRICT & ~E_USER_NOTICE & ~E_USER_DEPRECATED);
\t\t}
Эта команда просто включает игнорирование нотисов и иначе чем быдоокодинг я это назвать не могу. надо исправлять ошибки
, а не отключать. А еще лучше как нормальные пацаны перейти на fail fast принцип работы: http://habrahabr.ru/post/218325/
Вообще кстати если не считать того что ты забыл UNIQUE KEY на таблицу лайков (или что лучше сделать пару id PRIMARY KEY) у тебя верно спроектированы таблицы. Ну и выбрать 5 лучших пользователей это действительно запрос с 1 джойном и группировкой: джойним пользователей на полученные лайки, группируем и сортируем по убыванию числа лайков.
Сама полная версия задачи решает запросом из 2 джойнов.
Анон, не пугай меня, ты ведь решил задачу? Там просто надо написать цикл for, внутри цикла поставить коману увеличения суммы на счете, и иф с проверкой что мы дошли до миллиона.
А ты знаком с unix разрешениями? А про ACL слышал?
> Я просто хочу понять, какой пользователь вызывает этот процесс? Это root, или какой-нибудь демон?
Апач (и запускаемый через него PHP код) работает от имени пользователя www-data, группа по моему та же.
Тебе наверно лучше себя добавить в группу www-data.
Также обрати внимание на опцию umask: она задает какие права надо выключать при создании файлов и каталогов: http://php.net/manual/ru/function.umask.php
По умолчанию она равна 0022 что значит создавать файл с правами 0755 то есть доступный на запись только владельцу. Если поменять права на 0002 или 0 то PHP будет создавать файлы с правами вроде 0775 или 0777
Ну и не забудь все существующие файлы поменять на 0666, папки на 0777 (или 0660, 0770 если ты не хочешь всем давать доступ к ним). У команды chmod есть опции для этого. Скорее всего сейчас файлы недоступны Апачу. Ну и ему надо дать право заходить в твою папку еще.
Заметь что проблема с разрешениями в linux есть когда код выполняется и апачем и пользователем, вот например гайд из симфони с какими-то нереальными костылями и использованием ACL: http://symfony.com/doc/2.0/book/installation.html#configuration-and-setup
>case 'development':
>error_reporting(-1);
\t\t
>case 'production':
error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED & ~E_STRICT & ~E_USER_NOTICE & ~E_USER_DEPRECATED);
Ну лан, быдлокод так быдлокод.
Спасибки!
Что нотисы произошедшие на продакшене внимания не заслуживают?
Алсо видел случаи когда туда вообще 0 (игнорироать любые ошибки) вписывают.
Вообще в PHP обработка ошибок изначально плохо сделана, были бы там с самого начала исключения, этой проблемы бы и не было.
только плейсхолдер это же типа вспомогательный текст внутри формы, который типа "введите имя..". или что-то еще?
Это конструкция в запросе куда вставляется значение параметра:
http://doctrine-orm.readthedocs.org/en/latest/reference/dql-doctrine-query-language.html#named-and-positional-parameters
Посмотри запросы тут, не самые первые а те что идет с setParameter
Вот есть у меня таблица tasks и таблица users
tasks выглядит примерно так:
id, user_id, executor_id, text
users:
id, name.
И вот я хочу что бы select мне вернул таблицу tasks, но в которой бы поля user_id и exec_id были бы подменены на имена соответствующие этим айдишникам в таблице users (users.name)
а, понял, значит к форме это не имеет отношения
а можно ли сделать как-то условие в запросе необязательным?
вот например
$query = $em->createQuery('SELECT u FROM ForumUser u WHERE u.username = :name');
$query->setParameter('name', 'Bob');
$users = $query->getResult(); // array of ForumUser objects
вот этот вариант мне подходит только когда name, установлен, а это необязательно.
неужели придется строить говноконструкцию с ифами, такого рода:
if(isset($_GET['name'])
{
$query = $em->createQuery('SELECT u FROM ForumUser u WHERE u.username = :name');
$query->setParameter('name', 'Bob');
$users = $query->getResult();
}
else
{
$query = $em->createQuery('SELECT u FROM ForumUser');
$users = $query->getResult();
}
или же можно как-то более цивилизовано?
а, понял, значит к форме это не имеет отношения
а можно ли сделать как-то условие в запросе необязательным?
вот например
$query = $em->createQuery('SELECT u FROM ForumUser u WHERE u.username = :name');
$query->setParameter('name', 'Bob');
$users = $query->getResult(); // array of ForumUser objects
вот этот вариант мне подходит только когда name, установлен, а это необязательно.
неужели придется строить говноконструкцию с ифами, такого рода:
if(isset($_GET['name'])
{
$query = $em->createQuery('SELECT u FROM ForumUser u WHERE u.username = :name');
$query->setParameter('name', 'Bob');
$users = $query->getResult();
}
else
{
$query = $em->createQuery('SELECT u FROM ForumUser');
$users = $query->getResult();
}
или же можно как-то более цивилизовано?
Алсо в Симфони ты должен GET переменные брать из Request а не напрямую.
Алсо надо стараться не писать запросы в контроллере.
>Имей в виду, что в общем в фреймворках не принято делать настройки константами
Ок, а где константы вообще применяются? Чет не вижу их почти.
>Если у тебя много классов, то вместо написания кучи реквайров стоит подумать про автозагрузчик.
Я в курсе про автозагрузчик и он изначально был в заданном шаблоне, но я переделал на свой лад, т.к. мне пока что тяжело все эти абстракции учитывать. Когда файлообменник делать буду, то сделаю уже с ним.
>Это не роутер (и тем более не маршрут, а Route переводится именно так).
Опять же, изначально этот файл роутом таки был.
>Алсо, не используй статические методы.
Учту.
>Страницу 404 надо показывать сразу, а не редиректить на нее.
Лол, да это коммент из шаблона, который я скачал. Специально его оставил, чтобы потом не забыть убрать и переделать, но все равно в итоге забыл. Спасибо, что напомнил.
>MVC не предусматривает что один контроллер работает ровно с одной моделью.
Это остатки от автозагрузчика. Подключение модели с таким же названием, как у контролера. Думаю да, не совсем разумно это делать.
>Почему public?
Честно, не обращал на это внимание. Исправлю.
>почему нет тайп хинта?
Это что вообще?
>Зачем тут эта функция, которая мало того что ничего не делает, так еще и названа не по стандарту
Опять же остатки то шаблона. Да-да, нужно лучше следить за этим и подчищать. В след. раз постараюсь сам с нуля все написать, чтобы ничего лишнего не оставалось.
>Эту простыню хорошо бы сделать универсальной и вынести в функцию.
Пока слишком абстрактно для меня.
>Сделай название которое явно и недвусмысленно говорит что именно проверяет функция
Ну мне сложно представить, что там другие могут себе представить при прочтении названия данной функции. Когда я ее писал, то для меня все вполне очевидно было. Ну ладно, попробую более конкретное название дать.
>Никогда не вставляй переменные в запрос, используй плейсхолдеры.
Так $name это же хеш загруженного файла. Я думал так заморачиваться имеет смысл только с данными, которые напрямую от пользователя идет, не?
>Странно что ты проверяешь на уникальность файл по имени. разве для этого не лучше сделать отдельное поле с хешем?
Мы уже говорили на эту тему.
>>484849
>Надо выбрасывать исключение
Хорошо, сделаю.
>Непонятно почему функция перемещения разбита на 2 функции которые надо вызывать отдельно.
Потому что все равно нужна функция удаления и я решил, что нет смысла копипастить удаление если можно одну и ту же функцию использовать два раза.
>Функция судя по называнию должна возвращать число, а вместо этого возвращает массив.
Ну ок. А с PDO я повозился немного и чет не врубился сразу, потом поизучаю как-нибудь, в след. раз.
>Также, ты должен при использовании mysqli проверять каждую функцию, не вернула ли она ошибку.
Ну я видел что в мануале выбрасывают эту ошибку, но я думал, что это излишне, т.к. ни у кого не видел, чтобы они это делали. Но если это так важно, то хорошо, добавлю проверку.
>Если ты читал мой урок про датамапперы то наверно заметил что аргументом там передается объект-модель
Опять же, пока слишком абстрактно для меня.
>Ты не должен создавать новое соединение в каждом маппере
Я пробовал одно на весь сайт сделать, но не получается почему-то. Как это сделать нормально?
>тут слишком много кода.
И как мне его сократить? На логин отдельный контроллер завести чтоли?
Ладно, остальное тоже прочитал и постараюсь исправить. Вообще, мне кажется ты переоцениваешь мои силы, заставляя сразу сходу абстрактные конструкции городить, которые что-то там получают, что-то там делают и что-то там возвращают. На данный момент для меня слишком сложно в голове все это держать, мне гораздо проще с какими-то конкретными данными и функциями работать. Я конечно понимаю, что желательно сразу на современные стандарты переучиться, но блин тяжело усвоить за месяц то, до чего некоторые по полгода допирают.
И вообще, мне это все понадобится, если я во фротнэнд планирую идти? Или можно уже начинать JS учить?
>Имей в виду, что в общем в фреймворках не принято делать настройки константами
Ок, а где константы вообще применяются? Чет не вижу их почти.
>Если у тебя много классов, то вместо написания кучи реквайров стоит подумать про автозагрузчик.
Я в курсе про автозагрузчик и он изначально был в заданном шаблоне, но я переделал на свой лад, т.к. мне пока что тяжело все эти абстракции учитывать. Когда файлообменник делать буду, то сделаю уже с ним.
>Это не роутер (и тем более не маршрут, а Route переводится именно так).
Опять же, изначально этот файл роутом таки был.
>Алсо, не используй статические методы.
Учту.
>Страницу 404 надо показывать сразу, а не редиректить на нее.
Лол, да это коммент из шаблона, который я скачал. Специально его оставил, чтобы потом не забыть убрать и переделать, но все равно в итоге забыл. Спасибо, что напомнил.
>MVC не предусматривает что один контроллер работает ровно с одной моделью.
Это остатки от автозагрузчика. Подключение модели с таким же названием, как у контролера. Думаю да, не совсем разумно это делать.
>Почему public?
Честно, не обращал на это внимание. Исправлю.
>почему нет тайп хинта?
Это что вообще?
>Зачем тут эта функция, которая мало того что ничего не делает, так еще и названа не по стандарту
Опять же остатки то шаблона. Да-да, нужно лучше следить за этим и подчищать. В след. раз постараюсь сам с нуля все написать, чтобы ничего лишнего не оставалось.
>Эту простыню хорошо бы сделать универсальной и вынести в функцию.
Пока слишком абстрактно для меня.
>Сделай название которое явно и недвусмысленно говорит что именно проверяет функция
Ну мне сложно представить, что там другие могут себе представить при прочтении названия данной функции. Когда я ее писал, то для меня все вполне очевидно было. Ну ладно, попробую более конкретное название дать.
>Никогда не вставляй переменные в запрос, используй плейсхолдеры.
Так $name это же хеш загруженного файла. Я думал так заморачиваться имеет смысл только с данными, которые напрямую от пользователя идет, не?
>Странно что ты проверяешь на уникальность файл по имени. разве для этого не лучше сделать отдельное поле с хешем?
Мы уже говорили на эту тему.
>>484849
>Надо выбрасывать исключение
Хорошо, сделаю.
>Непонятно почему функция перемещения разбита на 2 функции которые надо вызывать отдельно.
Потому что все равно нужна функция удаления и я решил, что нет смысла копипастить удаление если можно одну и ту же функцию использовать два раза.
>Функция судя по называнию должна возвращать число, а вместо этого возвращает массив.
Ну ок. А с PDO я повозился немного и чет не врубился сразу, потом поизучаю как-нибудь, в след. раз.
>Также, ты должен при использовании mysqli проверять каждую функцию, не вернула ли она ошибку.
Ну я видел что в мануале выбрасывают эту ошибку, но я думал, что это излишне, т.к. ни у кого не видел, чтобы они это делали. Но если это так важно, то хорошо, добавлю проверку.
>Если ты читал мой урок про датамапперы то наверно заметил что аргументом там передается объект-модель
Опять же, пока слишком абстрактно для меня.
>Ты не должен создавать новое соединение в каждом маппере
Я пробовал одно на весь сайт сделать, но не получается почему-то. Как это сделать нормально?
>тут слишком много кода.
И как мне его сократить? На логин отдельный контроллер завести чтоли?
Ладно, остальное тоже прочитал и постараюсь исправить. Вообще, мне кажется ты переоцениваешь мои силы, заставляя сразу сходу абстрактные конструкции городить, которые что-то там получают, что-то там делают и что-то там возвращают. На данный момент для меня слишком сложно в голове все это держать, мне гораздо проще с какими-то конкретными данными и функциями работать. Я конечно понимаю, что желательно сразу на современные стандарты переучиться, но блин тяжело усвоить за месяц то, до чего некоторые по полгода допирают.
И вообще, мне это все понадобится, если я во фротнэнд планирую идти? Или можно уже начинать JS учить?
>Напиши единую функцию для склонения слов, а варианты написания можно передавать в нее снаружи.
То есть будет функция inclineWord, а туда по надобности передается "тысяча" или "миллион"? Но тогда же опять же в функции придется копипастить алгоритм, или это все равно будет лучше?
Калькулятор:
http://ideone.com/t4MwpX#stdin
>Калькулятор:
Ой, забыл копипастнуть отформатированный код из Notepad'a, дико извиняюсь:
http://ideone.com/mZnZgN
Ну никто не мешает оставить тебе режим отображения ошибок и в продакшене. Я как понимаю речь идет о том, что сама возможность такого выбора - это зашквар? Ведь в крутых фреймворках возможности выбирать режимы отображения ошибок вообще нет. Там вхардкожено по умолчаниючто все включено. Ведь ребята которые кодят не под игнатером, они же не совершают ошибок, чего им бояться :3
и еще что-то типа того. Поэтому получается грязно и некрасиво. Почему так?
Второй вопрос:
в форме есть несколько чекбоксов, они отвечают к примеру за тороговую марку. Типа:
.тм1
.тм2
.тм3
И вот как мне сделать, чтобы когда я отмечаю сразу несколько типов, сохранялись оба? потому что вот если так как есть то параметр получается ?tm=tm1?tm2
Мне потом парсить этот параметр через str_replace?
Еще я сделал, чтобы было вот так ?tradeMark.1=Lubin&tradeMark.2=Solomeya и т.д
так вроде лучше, но все равно придется парсить. Может есть решение получше?
За ранее спасибо, оп, ты наставляешь меня на путь истинный, твои советы мудры, будто тебе сотни лет, альтруизм твой не знает границ.
думаю, можно как-то в массив записать, только пока не догнал как
Читай про объединения таблиц (разные виды JOIN).
https://ru.wikipedia.org/wiki/Join_(SQL)
http://www.mysql.ru/docs/man/JOIN.html
Нужно объединить все три таблицы tasks, users и executors в одну, а из результирующей таблицы выбрать только те столбики, которые необходимы.
В реляционных базах данных в каждом столбике таблицы должно быть одинаковое количество записей. Когда мы объединяем таблицы мы не можем просто взять и визуально прилепить к одной таблице по правому борту другую таблицу. У них элементарно может не совпадать кол-во строк. Поэтому на самом деле при объединении таблиц склеиваются не таблицы а записи в них по определенному правилу, условию (condition).
Вот у тебя есть в таблице task столбец user_id, и в таблице user наверняка есть id.
Значить нужно объединить эти две таблицы с условием, что для каждой записи выполняется tasks.user_ud = user.id.
В результате получим запись наподобие
task.id | task.user_id | user.id | user.name
14 | 8 | 8 | Василий
Из этой результирующей таблицы и выбираешь только те столбцы, которые нужны.
Есть хорошая книга по mysql авторства Люк Веллинг, Лора Томпсон.
Она очень старая 2004, но базовые вещие там понятно объясняются.
> Там вхардкожено по умолчаниючто все включено. Ведь ребята которые кодят не под игнатером, они же не совершают ошибок, чего им бояться :3
Ну так правильно, другие фреймворки используют fail fast и ошибка приводит к 503 странице и записи в лог, после чего исправляется. А кодеигнайтер игнорирует ошибку и показывает пользователю неправильные данные.
Ты странные вещи пишешь, как будто бы от того что ты не будешь обращать внимания на ошибку она ичезнет. Она все равно останется, просто ты о ней не узнаешь. А чтобы ошибки обнаруживались в процессе разработки, а не на продакшене, есть тестирование (ручное или автоматическое).
> Ведь в крутых фреймворках возможности выбирать режимы отображения ошибок вообще нет.
И хорошо что нет, ибо по моему опыту игнорирование части или всех ошибок приводит к снижению качества кода. Лучше бы такая система fail fast была в языке PHP изначально и выбора никакого не было вообще нигде. В других языках (Ява, Питон, Руби, C#, Яваскрипт) так и есть.
> все равно в url куча ненужной информации типа token?sieuf8e7f09w3ur23yr803923r
Посмотри HTML код формы и кто это добавляет
> в форме есть несколько чекбоксов, они отвечают к примеру за тороговую марку
PHP умеет работать с массивами в формах
http://php.net/manual/ru/faq.html.php#faq.html.arrays
http://php.net/manual/ru/language.variables.external.php
> Поэтому на самом деле при объединении таблиц склеиваются не таблицы а записи в них по определенному правилу, условию (condition).
При объединении таблиц A и B к каждой записи A приджойниваются все записи из B (так что получеатся A×B записей) после чего лишние отсеиваются с помощью WHERE или ON. Но если не писать условий то ты получишь все возможные сочетания записей.
О!! вот это мне и нужно было, видел такое на паре сайтов, но не знал как сделать. Спасибо!
>А ты знаком с unix разрешениями? А про ACL слышал?
Да я убунту поставил первый раз в жизни месяц назад.
Знаю пока только базовые вещи уровня первого lpiс.
Про права и маски в курсе, с acl и "unix разрешениями" не знаком.
Хочу найти книгу, чтобы объяснялись сами принципы работы линукс, файловые системы, службы, оболочки.
Я вот не понимаю, что такое оболочка? Это что-то типа фреймворка для работы с ядром?
Пока мне попадаются либо книги для домохозяек, где подробно описывается интерфейс всратого юнити, либо невнятные мануалы уровня "вбейте в командной строке следующую последовательность символов".
Хм, вот скачиваю очередную книжку http://rutracker.org/forum/viewtopic.php?t=5001603
Надеюсь, там будут все-таки объяснения. Хотя меня напрягает, что автор использует федору. Мне теперь из-за него виртуалбокс заводить? Ну ладно, основные вещи должны быть справедливы для всех дистрибутивов.
Ага, значит www-data, ок, добавлю своего пользователя к нему в группу.
Еще вопрос, ОП. Выше ты проверял задание, речь шла о роутере и фронт-контроллере.
Я тоже пока путаюсь в этих вещах.
Вот если у нас кусок кода анализирует урл и в зависимости от результатов запускает тот или иной контроллер->экшн, то это роутер или фк?
Своими словами, пожалуйста. Гугл выдает хуйню уровня http://design-pattern.ru/patterns/front-controller.html
> что такое оболочка?
Оболочка (shell) это программа которая принимает команды от пользователя и выполняет их. В твоей Ubuntu это скорее всего bash, но есть и другие --sh оболочки.
В linux принята философия, что каждая программа должна делать только одно дело, но делать его хорошо. А если нужно что-то более сложное, то ты объединяешь несколько программ вместе.
> unix разрешениями
Это и есть права из 3 цифр. ACL это более сложная система когда ты говоришь «пользователь A может читать и писать в это файл, а B только писать».
> Хотя меня напрягает, что автор использует федору.
Там различия не такие большие, может конфиги немного по другому называются, для установки пакетов другая команда используется, но на 95% все такое же.
> Вот если у нас кусок кода анализирует урл и в зависимости от результатов запускает тот или иной контроллер->экшн, то это роутер или фк?
Фронт контроллер (ты читал ссылки из гугла?) это первый контроллер который запускается, инициализирует приложение и затем запускается настоящий контроллер. В твоем случае это фронт контроллер в который намертво вшит роутер.
Я же вроде писал выше. роутер это функция которая на вход получает URL а на выходе допустим дает массив параметров или объект, описывающий какой контроллер надо вызвать и с какими аргументами.Но сам ничего не вызывает, потому что это не его задача. А ты конечно все смешал в одном классе, ну у тебя и приложение маленькое.
> Гугл выдает хуйню уровня
Вообще-то это выжимка из книги очень умного Мартина Фаулера который и описал этот паттерн. То есть почти первоисточник. Ну и не ленись, погугли, по этой теме много статей.
Сделать PHP скрипт очевидно (или можешь попробовать сделать это SQL командой). Этот же скрипт можно например будет запускать по крону для обновления цифр. Скрипт запускается из командной строки.
>Оболочка (shell) это программа которая принимает команды от пользователя и выполняет их.
То есть что-то типа посредника, да? Когда я вбиваю допустим ls -a /var, она разбирает эту строку, потом вызывает программу ls, передавая ей параметры.
Ну ладно, разберусь походу.
>у тебя и приложение маленькое
Тот код что ты комментировал - не мой. Я мимопроходил и заинтерсовался.
Мне теперь еще и талмуд Фаулера читать? А когда жить?
Блин, я от армии косил чтобы не терять полтора года жизни впустую. Так тут айти меня догнал(((
Ну это хоть не бесполезная трата времени.
В будущем даст плоды. Я надеюсь.
> Когда я вбиваю допустим ls -a /var, она разбирает эту строку, потом вызывает программу ls, передавая ей параметры.
Да. Оболочка bash например делает аж 7 шагов преобразований, подставляя имена файлов, значения переменных ит.д.
Ну например если ты пишешь
echo ×.txt
То оболочка находит все файлы в текущем каталоге, соответствующие маске ×.txt и заменяет маску на эти имена, а тольок потом вызывает программу echo (которая их выводит на экран)
Также оболочка умеет делать перенаправление ввода/вывода. Например команда
ls > 1.txt
Сохранит список файлов в файл 1.txt
> Мне теперь еще и талмуд Фаулера читать? А когда жить?
Тебе пока рановато его читать, так что это можешь отложить на будущее.
Заметь что таким образом благодаря оболочке командам не требуется ни работать с масками, ни уметь делать перенаправление — это за них делает оболочка и эти фичи работают с любой командой.
>Нужно объединить все три таблицы tasks, users и executors в одну
Проблема в том, что у меня нет таблицы executors, а есть только таблица юзеров. И я из неё хочу брать имена людей по адишникам.
В общем может неочень очевидно объяснил, но:
id, user_id, executor_id, text
ссылаются на одну и ту же таблицу юзеров (у них просто есть разные роли) и вот как мне дернуть что бы вместо user_id поставилось имя человека из users с этим id, а в executor_id имя другого человека с другим айдишником, но тоже из users
Ты можешь дважды объединить таблицу tasks с таблицей users, используя алиасы (псевдонимы).
Сначала приджойнить к tasks таблицу users as u1 при условии что tasks.user_id = u1.id, затем приджойнить users as u2 при условии tasks.executor_id = u2.id
(Оператор AS необязательный, кстати. Но я написал для лучшего понимания.)
Из этой таблицы выбираешь нужные колонки tasks.id, u1.name, u2.name.
Неплохой туториал, я считаю.
https://books.google.com.ua/books?id=4x3mk3mmNAYC&pg=PA123&dq=%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5+%D0%BE%D0%B1%D1%8A%D0%B5%D0%B4%D0%B8%D0%BD%D0%B5%D0%BD%D0%B8%D0%B9+%D0%B4%D0%BB%D1%8F+%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%BE%D0%B2+%D0%BA+%D0%BD%D0%B5%D1%81%D0%BA%D0%BE%D0%BB%D1%8C%D0%BA%D0%B8%D0%BC+%D1%82%D0%B0%D0%B1%D0%BB%D0%B8%D1%86%D0%B0%D0%BC&hl=ru&sa=X&ei=H5pkVfaPBeLOygPb4oDgAQ&ved=0CBwQ6AEwAA#v=onepage&q=%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%20%D0%BE%D0%B1%D1%8A%D0%B5%D0%B4%D0%B8%D0%BD%D0%B5%D0%BD%D0%B8%D0%B9%20%D0%B4%D0%BB%D1%8F%20%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%BE%D0%B2%20%D0%BA%20%D0%BD%D0%B5%D1%81%D0%BA%D0%BE%D0%BB%D1%8C%D0%BA%D0%B8%D0%BC%20%D1%82%D0%B0%D0%B1%D0%BB%D0%B8%D1%86%D0%B0%D0%BC&f=false
ОП, как избавляться от этого странного кодирования кириллицы в ссылках?
Я же не могу вакабе подсунуть urldecode.
Двачую. Тоже почитал бы. Сам только начал изучать, прочитал первую страницу учебника. Там сказано, что если понравится - постить котов.
Следующая задачка про волшебный кубик, на котором в 90% случаев выпадает 1 или 4.
http://ideone.com/IU38Zl
В 8 строчке переменные не взял в гнутые скобочки, не знаю как они называются, так не стоит делать? Это не тру? Пойду делать про кредит и айфон.
Под самим кодом на идеоне можно увидеть результат его выполнения и ошибки (stderr).
Он тебе пишет:
PHP Notice: Use of undefined constant anonDice1 - assumed 'anonDice1' in /home/RtuNg3/prog.php on line 15
PHP Notice: Use of undefined constant anonDice2 - assumed 'anonDice2' in /home/RtuNg3/prog.php on line 15
Английский понимаешь? Use of undefined constant - найдена неопределенная константа на 15 строке.
Ты значок $ забыл прописать перед переменными, поэтому интерпретатор решил, что это не переменная, а какая-то неизвестная константа.
Видел эту строку, но не обратил внимания, думал и так нормально работает. Пойду заново напишу кубик этот, чисто для себя, тот то все равно запорол уже, другое задание на нем сделал.
А, ты про новое и говорил. Поставил переменные. А ты можешь мне объяснить, как бы работал код будь он как раньше? Просто бы пропускал этот косячный момент?
> Ок, а где константы вообще применяются?
Один из сценариев это поля вроде ENUM где есть несколько вариантов значений:
class User
{
const GENDER_MALE = 'male';
const GENDER_FEMALE = 'female';
public $gender;
}
$user->gender = User::GENDER_MALE;
Надеюсь ты догадываешься что пишут пол строкой, без констант, $user->gender = 'male' только неучи и что с константами это совсем другой уровень.
Также константами можно обозначать гм.. константы:
define('GRAVITATION', 9.81); // ускорение свободного падения на Земле
> Я в курсе про автозагрузчик и он изначально был в заданном шаблоне, но я переделал на свой лад, т.к. мне пока что тяжело все эти абстракции учитывать
Но ты вместо этого наставил кучу инклудов, и это очень некрасиво. И ладно бы ты их в начале файла ставил, ты зачем-то их прямо по коду размазываешь и в конструктор пишешь. Как минимум вынеси инклуды в начало файла. Ну и лучше все же сделать автозагрузик, что так сложного? это функция из 8 строчек. Если для тебя 8 строчек написать сложно, ты файлообменник не осилишь.
> Подключение модели с таким же названием, как у контролера.
Это неправильно так как никто не говорит что контроллер и модель соотносятся как один-к-одному. Контроллер соответствует разделу на сайте, а модель сущности в базе данных и они не обязаны совпадать.
>>почему нет тайп хинта?
> Это что вообще
Тайп хинты позволяют указать, что аргумент функции должен быть определенного типа (например быть объектом определенного класса или его наследника). Тайп хинт делает код понятнее (так как видно какого типа переменная) и надежнее (так как PHP не позволит передать что-то неразрешенное и ты сразу увидишь ошибку). Используй их везде.
Мануал: http://php.net/manual/ru/language.oop5.typehinting.php
>>Эту простыню хорошо бы сделать универсальной и вынести в функцию.
> Пока слишком абстрактно для меня.
Там ничего абстрактного. Просто сделай функцию которая например получает код ошибки из error и возвращает текст. Это уже позволит вынести строк 10 из контроллера.
>>Сделай название которое явно и недвусмысленно говорит что именно проверяет функция
> Ну мне сложно представить, что там другие могут себе представить при прочтении названия данной функции. Когда я ее писал, то для меня все вполне очевидно было.
Очевидно потому что у тебя маленькое приложение, ты несколько дней назад это написал и ты пишешь его один. На практике вряд ли будет так же и одно из трех условий нарушится (например ты будешь читать написанный кем-то другим код или написанной полгода назад тобой код) и тут-то ты и будешь жалеть что функция не названа нормально. лучше сразу привыкать писать самодокументирующий код.
> Я думал так заморачиваться имеет смысл только с данными, которые напрямую от пользователя идет, не?
Все данные должны вставляться в запрос через плейсхолдеры. Это общепринятый подход и не надо к нему придумывать исключения из правил.
Как я проверю откуда приходит эта переменная? Я же тебе писал несколько дней назад, то что запрос безопасен, должно быть очевидно с первого взгляда и не должно требовать изучать код и выяснять откуда пришла переменная. Как можно нормально работать с кодом если некоторые функции в нем безопасные, а некоторые содержат мину замедленного действия? Сегодня у тебя name приходит не от пользователя, а завтра эту функцию вызовут в каокм-нибудь другом месте.
>>Странно что ты проверяешь на уникальность файл по имени. разве для этого не лучше сделать отдельное поле с хешем?
> Мы уже говорили на эту тему.
Я не помню этого (правда не помню), я смотрю на код и проверяю, правильный он или нет и где его можно улучшить.
И я потому и написал что лучше всего сделать отдельную колонку для хеша, а если это невозможно (хотя в твоем случае это не сложно) то надо оставлять поясняющий комментарий так как то, что имя совпадает с хешем, абсолютно неочевидно. Комемнтарий должен об этом говорить и предупреждать, чтобы другие люд например не пытались поменять алгоритм генерации имени, так как это сломает проверку на уникальность.
Ну вот ты сам станешь программистом, наткнешься на такой же неочевидный код и будешь ругать его автора. Надо писать как можно более понятный код, а там где невозможно, делать поясняющие комментарии.
>>Также, ты должен при использовании mysqli проверять каждую функцию, не вернула ли она ошибку.
> Ну я видел что в мануале выбрасывают эту ошибку, но я думал, что это излишне, т.к. ни у кого не видел, чтобы они это делали.
Значит авторы этих уроков — неучи, не умеющие обрабатывать ошибки. Скорее всего реальная причина в том, что это уроки 10-летней давности в которых устаревшие функции вроде mysql_query (которые при ошибке в БД выдают варнинг) заменены на mysqli_query (которые его не выдают) дописыванием одной буквы. Как мы видим, этого недостаточно. Ты зря учишься по такому материалу, эти уроки и 10 лет назад были плохие, а теперь они вообще по качеству ниже всякого разумного уровня.
> >Если ты читал мой урок про датамапперы то наверно заметил что аргументом там передается объект-модель
> Опять же, пока слишком абстрактно для меня.
Объект передать в функцию для тебя слишком абстрактно? Тогда тебе еще рановато делать файлообменники на ООП.
> Я пробовал одно на весь сайт сделать, но не получается почему-то. Как это сделать нормально?
$mapper = new WebmMapper($mysqli);
> И как мне его сократить? На логин отдельный контроллер завести чтоли?
Выноси код из контроллера в мапперы или классы-хелперы, чтобы в контроллере было немного кода. Твоя простыня кода делает несколько действий, каждое из которых можно сделать отдельной функцией. Ну как минимум для авторизации можно сделать класс с методами вроде залогнить, проверить залогиненность, разлогинить.
> И вообще, мне это все понадобится, если я во фротнэнд планирую идти? Или можно уже начинать JS учить?
Если ты на PHP писать не будешь, то наверно учить его нет смысла и есть смысл браться за изучение HTML/CSS (если у тебя есть пробелы) и JS/DOM и так далее.
А что значит фронтенд? Ты хочешь писать сложные клиентские приложения на Backbone/Angular и подобных фреймворках? Там абстракций еще больше (и вообще ангулар на мой взгляд какие-то неадекваты придумывали), и ООП тоже есть, и MVC в сильно извращенной форме, в сравнении с ними твой сайт с вебмками в разы проще. Яваскрипт может выглядеть простым на первый взгляд, но там есть свои подводные камни и на чистом яваскрипте никто ничего не пишет, надо учить кучу фреймворков и концепций.
> Ок, а где константы вообще применяются?
Один из сценариев это поля вроде ENUM где есть несколько вариантов значений:
class User
{
const GENDER_MALE = 'male';
const GENDER_FEMALE = 'female';
public $gender;
}
$user->gender = User::GENDER_MALE;
Надеюсь ты догадываешься что пишут пол строкой, без констант, $user->gender = 'male' только неучи и что с константами это совсем другой уровень.
Также константами можно обозначать гм.. константы:
define('GRAVITATION', 9.81); // ускорение свободного падения на Земле
> Я в курсе про автозагрузчик и он изначально был в заданном шаблоне, но я переделал на свой лад, т.к. мне пока что тяжело все эти абстракции учитывать
Но ты вместо этого наставил кучу инклудов, и это очень некрасиво. И ладно бы ты их в начале файла ставил, ты зачем-то их прямо по коду размазываешь и в конструктор пишешь. Как минимум вынеси инклуды в начало файла. Ну и лучше все же сделать автозагрузик, что так сложного? это функция из 8 строчек. Если для тебя 8 строчек написать сложно, ты файлообменник не осилишь.
> Подключение модели с таким же названием, как у контролера.
Это неправильно так как никто не говорит что контроллер и модель соотносятся как один-к-одному. Контроллер соответствует разделу на сайте, а модель сущности в базе данных и они не обязаны совпадать.
>>почему нет тайп хинта?
> Это что вообще
Тайп хинты позволяют указать, что аргумент функции должен быть определенного типа (например быть объектом определенного класса или его наследника). Тайп хинт делает код понятнее (так как видно какого типа переменная) и надежнее (так как PHP не позволит передать что-то неразрешенное и ты сразу увидишь ошибку). Используй их везде.
Мануал: http://php.net/manual/ru/language.oop5.typehinting.php
>>Эту простыню хорошо бы сделать универсальной и вынести в функцию.
> Пока слишком абстрактно для меня.
Там ничего абстрактного. Просто сделай функцию которая например получает код ошибки из error и возвращает текст. Это уже позволит вынести строк 10 из контроллера.
>>Сделай название которое явно и недвусмысленно говорит что именно проверяет функция
> Ну мне сложно представить, что там другие могут себе представить при прочтении названия данной функции. Когда я ее писал, то для меня все вполне очевидно было.
Очевидно потому что у тебя маленькое приложение, ты несколько дней назад это написал и ты пишешь его один. На практике вряд ли будет так же и одно из трех условий нарушится (например ты будешь читать написанный кем-то другим код или написанной полгода назад тобой код) и тут-то ты и будешь жалеть что функция не названа нормально. лучше сразу привыкать писать самодокументирующий код.
> Я думал так заморачиваться имеет смысл только с данными, которые напрямую от пользователя идет, не?
Все данные должны вставляться в запрос через плейсхолдеры. Это общепринятый подход и не надо к нему придумывать исключения из правил.
Как я проверю откуда приходит эта переменная? Я же тебе писал несколько дней назад, то что запрос безопасен, должно быть очевидно с первого взгляда и не должно требовать изучать код и выяснять откуда пришла переменная. Как можно нормально работать с кодом если некоторые функции в нем безопасные, а некоторые содержат мину замедленного действия? Сегодня у тебя name приходит не от пользователя, а завтра эту функцию вызовут в каокм-нибудь другом месте.
>>Странно что ты проверяешь на уникальность файл по имени. разве для этого не лучше сделать отдельное поле с хешем?
> Мы уже говорили на эту тему.
Я не помню этого (правда не помню), я смотрю на код и проверяю, правильный он или нет и где его можно улучшить.
И я потому и написал что лучше всего сделать отдельную колонку для хеша, а если это невозможно (хотя в твоем случае это не сложно) то надо оставлять поясняющий комментарий так как то, что имя совпадает с хешем, абсолютно неочевидно. Комемнтарий должен об этом говорить и предупреждать, чтобы другие люд например не пытались поменять алгоритм генерации имени, так как это сломает проверку на уникальность.
Ну вот ты сам станешь программистом, наткнешься на такой же неочевидный код и будешь ругать его автора. Надо писать как можно более понятный код, а там где невозможно, делать поясняющие комментарии.
>>Также, ты должен при использовании mysqli проверять каждую функцию, не вернула ли она ошибку.
> Ну я видел что в мануале выбрасывают эту ошибку, но я думал, что это излишне, т.к. ни у кого не видел, чтобы они это делали.
Значит авторы этих уроков — неучи, не умеющие обрабатывать ошибки. Скорее всего реальная причина в том, что это уроки 10-летней давности в которых устаревшие функции вроде mysql_query (которые при ошибке в БД выдают варнинг) заменены на mysqli_query (которые его не выдают) дописыванием одной буквы. Как мы видим, этого недостаточно. Ты зря учишься по такому материалу, эти уроки и 10 лет назад были плохие, а теперь они вообще по качеству ниже всякого разумного уровня.
> >Если ты читал мой урок про датамапперы то наверно заметил что аргументом там передается объект-модель
> Опять же, пока слишком абстрактно для меня.
Объект передать в функцию для тебя слишком абстрактно? Тогда тебе еще рановато делать файлообменники на ООП.
> Я пробовал одно на весь сайт сделать, но не получается почему-то. Как это сделать нормально?
$mapper = new WebmMapper($mysqli);
> И как мне его сократить? На логин отдельный контроллер завести чтоли?
Выноси код из контроллера в мапперы или классы-хелперы, чтобы в контроллере было немного кода. Твоя простыня кода делает несколько действий, каждое из которых можно сделать отдельной функцией. Ну как минимум для авторизации можно сделать класс с методами вроде залогнить, проверить залогиненность, разлогинить.
> И вообще, мне это все понадобится, если я во фротнэнд планирую идти? Или можно уже начинать JS учить?
Если ты на PHP писать не будешь, то наверно учить его нет смысла и есть смысл браться за изучение HTML/CSS (если у тебя есть пробелы) и JS/DOM и так далее.
А что значит фронтенд? Ты хочешь писать сложные клиентские приложения на Backbone/Angular и подобных фреймворках? Там абстракций еще больше (и вообще ангулар на мой взгляд какие-то неадекваты придумывали), и ООП тоже есть, и MVC в сильно извращенной форме, в сравнении с ними твой сайт с вебмками в разы проще. Яваскрипт может выглядеть простым на первый взгляд, но там есть свои подводные камни и на чистом яваскрипте никто ничего не пишет, надо учить кучу фреймворков и концепций.
Фигурные скобки.
На самом деле не обязательно. Но в некоторых случаях (когда дойдешь до массивов и объектов) из-за этого могут возникнуть проблемы.
Так что пока пиши их всегда, потом с опытом поймешь где они нужны, где нет.
Если хочешь, чтобы отсчет шел реально в секундах, можно сделать такой трюк: добавить цикл с проверкой времени.
http://ideone.com/DNaaeW
>>485789
Да, пропускал бы. У тебя написано условие if (anonDice1 == anonDice2), как сравнивать если неизвестно значение этих величин?
> intval($number);
Эта строка ничего не делает. Ну то есть она конечно преобразует number в число, но само число никуда не сохраняется. должно быть что-то вроде
$a = intval($a);
чтобы это работало.
Ну и вообще непонятно зачем это делать, у тебя вроде и так в number число хранится же.
> $number = 0;
>\t $op = $char;
Это повторяется несколько раз, попробуй избавиться от повтора.
Так, считает программа верно.
> все равно в url куча ненужной информации типа token?sieuf8e7f09w3ur23yr803923r
Это CSRF токен, прочти урок https://github.com/codedokode/pasta/blob/master/security/xsrf.md
>>485577
http://www.mediafire.com/download/5o7mmd25bvn2o9d/архив-тредов-с-марта-2015.zip
>>485686
Неплохо, но тут часть команд повторяется 2 раза:
> \t$paymentTotal+=$creditBalance;
> echo "{$month} месяц спустя: долг = {$creditBalance} руб, выплачено всего {$paymentTotal} руб. \n";
Нельзя ли избавиться от повторов? Например вынести сумму выплаты в переменную.
>>485676
Да нет в этом архиве ничего полезного, скачай сам и убедись.
>>485691
Да, все верно.
>>485720
> } elseif ($anonSum = $compSum) {
= значит сохранить число в переменную. Чтобы сравнить числа надо использоать ==. ну и тут можно было просто else написать так как это третий из трех возможных вариантов.
> ($anonDice1)+($anonDice2);
Тут скобки не требуются так как всего одна операция сложения, а скобки нужны когда не очень очевиден порядок выполнения действий.
>>485780
Фигурные скобки нужны чтобы например отдельить переменную от текста: length is {$size}cm
Если у тебя просто одна переменная и за ней \n то они не обязательны.
Подробно описано тут: http://php.net/manual/ru/language.types.string.php#language.types.string.parsing
> ?>
Это не обязательно писать в конце файла.
Задача решена верно.
> все равно в url куча ненужной информации типа token?sieuf8e7f09w3ur23yr803923r
Это CSRF токен, прочти урок https://github.com/codedokode/pasta/blob/master/security/xsrf.md
>>485577
http://www.mediafire.com/download/5o7mmd25bvn2o9d/архив-тредов-с-марта-2015.zip
>>485686
Неплохо, но тут часть команд повторяется 2 раза:
> \t$paymentTotal+=$creditBalance;
> echo "{$month} месяц спустя: долг = {$creditBalance} руб, выплачено всего {$paymentTotal} руб. \n";
Нельзя ли избавиться от повторов? Например вынести сумму выплаты в переменную.
>>485676
Да нет в этом архиве ничего полезного, скачай сам и убедись.
>>485691
Да, все верно.
>>485720
> } elseif ($anonSum = $compSum) {
= значит сохранить число в переменную. Чтобы сравнить числа надо использоать ==. ну и тут можно было просто else написать так как это третий из трех возможных вариантов.
> ($anonDice1)+($anonDice2);
Тут скобки не требуются так как всего одна операция сложения, а скобки нужны когда не очень очевиден порядок выполнения действий.
>>485780
Фигурные скобки нужны чтобы например отдельить переменную от текста: length is {$size}cm
Если у тебя просто одна переменная и за ней \n то они не обязательны.
Подробно описано тут: http://php.net/manual/ru/language.types.string.php#language.types.string.parsing
> ?>
Это не обязательно писать в конце файла.
Задача решена верно.
> как бы работал код будь он как раньше? Просто бы пропускал этот косячный момент?
Если ты забыл $ перед переменной то PHP всспримет ее как строку, то есть
$hello = 1;
echo hello;
Выведет слово hello а не цифру 1.
Соответственно сравнение if (anonDice1 == anonDice2) будет сравнивать строки, а не значения переменных, и оно никогда не сработает так как строки различаются.
Ну и конечно ошибок быть не должно. Там на ideone баг, чтобы увидеть ошибки, надо иногда перезагрузить страницу, сразу они не пишутся. Я им писал, сказали когда-нибудь исправят.
Ну блин, тут просто такая фигня, что когда с нуля все пишешь, то это одно дело. А когда пытаешься переделать какой-то существующий проект, то это в разы сложнее, начинаешь путаться в том, что ты уже сделал, а что еще нет и какая-то каша в итоге образуется. Думаю с файлообменником проще будет, надо только как следует всю структуру распланировать заранее, чтобы потом не приходилось переделывать.
Я в слишком быстром темпе информацию поглощаю, не успевая ее толком усвоить, но остановиться не могу, т.к. мне надо до конца лета съебать в Новосиб и устроиться там на работу.
Фронтэнд значит заниматься внешним видом сайта, а не его серверной частью. Насколько я знаю php там все равно надо знать. Вот я и хочу понять, на каком уровне мне стоит остановиться. О чем то большем, чем Jquery я думаю мне пока рано думать.
И я не говорю, что MVC или абстрактные структуры это что-то нереально сложное. Просто с наскока не так то просто их одолеть. И если джуном возьмут, то там уже можно будет спокойно со временем все осваивать под присмотром наставника, который будет давать полезную и актуальную информацию, а не устаревшее говно.
Кстати все уроки и статьи которые я читал были 2013-2015 годов и в комментариях к ним были сотни положительных камментов типа "Вот бы мне такую статью, когда я только начинал учить php". Это автор статьи семенит или что? Кому вообще верить?
>можно сделать такой трюк
Благодарю, вроде как вник, но не совсем. Есть вопросы по этой строчке.
>5. while($currentTime + 1 != time()){}
Когда время изменяется на секунду вперед и становится не равно time, то выводится сообщение? Но ведь time уже заложена в переменную $currentTime, как они могут различаться? Или в этой строчке time и тот time, что в переменной, разные и он текущее время постоянно сравнивает с сохраненным в переменной? Пока писал окончательно запутался, не уверен даже, что мой пост понятен будет лол.
> Фронтэнд значит заниматься внешним видом сайта,
Это верстальщик по моему. Кстати у нас и на HTMl/CSS и на JS есть задания.
> О чем то большем, чем Jquery я думаю мне пока рано думать.
Это и есть верстальщик, фронтенд-разработчик это более сложные вещи.
> Насколько я знаю php там все равно надо знать.
Да, но там часто требования в плане понимать php код и внести простые изменения.
> Кстати все уроки и статьи которые я читал были 2013-2015 годов и в комментариях к ним были сотни положительных камментов типа "Вот бы мне такую статью, когда я только начинал учить php". Это автор статьи семенит или что? Кому вообще верить?
Не знаю, но если автор не проверяет ошибки от команд работы с базой то это непраивльно. Ну и сам подумай, может ли начинающий правильно оценить качество материала?
>>485800
> while($currentTime + 1 != time()){}
Это неправильно. ты жжешь процессор делая миллионы итераций в цикле когда можно просто вызввать sleep() и поспать нужное число секунд не занимая процессор, не тратя энергию, не крутя вентиляторы итд.
Также если программа пропусти тнужную секунду цикл будет вечный.
Так что это неправильный код.
>>485834
Там цикл while c пустым телом. То есть он работает так:
Пока (время не изменилось) выполнять эту же проверку.
Соответственно он миллионы раз в цикле делает эту проверку пока время не изменится. Тут минимум 2 ошибки:
— есть команда sleep чтобы ждать нужное время. Цикл использовать непрваильно так как ты жжешь процессор, тратишь энергию зря, отнимаешь процессорное время у других программ на бессмысленный уикл
— если по каким-то причинам программа пропустит следующую секунду (например система будет занята чем-то более важным) то цикл никогда не прервется и ьудет выполняться вообще вечно.
То есть это абсолютно неправильный код и ты не должен так делать.
> Фронтэнд значит заниматься внешним видом сайта,
Это верстальщик по моему. Кстати у нас и на HTMl/CSS и на JS есть задания.
> О чем то большем, чем Jquery я думаю мне пока рано думать.
Это и есть верстальщик, фронтенд-разработчик это более сложные вещи.
> Насколько я знаю php там все равно надо знать.
Да, но там часто требования в плане понимать php код и внести простые изменения.
> Кстати все уроки и статьи которые я читал были 2013-2015 годов и в комментариях к ним были сотни положительных камментов типа "Вот бы мне такую статью, когда я только начинал учить php". Это автор статьи семенит или что? Кому вообще верить?
Не знаю, но если автор не проверяет ошибки от команд работы с базой то это непраивльно. Ну и сам подумай, может ли начинающий правильно оценить качество материала?
>>485800
> while($currentTime + 1 != time()){}
Это неправильно. ты жжешь процессор делая миллионы итераций в цикле когда можно просто вызввать sleep() и поспать нужное число секунд не занимая процессор, не тратя энергию, не крутя вентиляторы итд.
Также если программа пропусти тнужную секунду цикл будет вечный.
Так что это неправильный код.
>>485834
Там цикл while c пустым телом. То есть он работает так:
Пока (время не изменилось) выполнять эту же проверку.
Соответственно он миллионы раз в цикле делает эту проверку пока время не изменится. Тут минимум 2 ошибки:
— есть команда sleep чтобы ждать нужное время. Цикл использовать непрваильно так как ты жжешь процессор, тратишь энергию зря, отнимаешь процессорное время у других программ на бессмысленный уикл
— если по каким-то причинам программа пропустит следующую секунду (например система будет занята чем-то более важным) то цикл никогда не прервется и ьудет выполняться вообще вечно.
То есть это абсолютно неправильный код и ты не должен так делать.
> else
> echo "Ничья, победила дружба!";
Лучше ставить скобки даже если там одна команда. Это защищает от ошибок при правке кода.
Да, не подумал о таких тонкостях. Просто хотел показать, что в том месте нужно бы организовать задержку на секунду.
Не циклом так чем-то другим. Естественно, это не практический пример. Ну ладно.
Верстальщик это HTML/CSS в основном. Ну и jquery мб по-мелочи.
Понятное дело, что грамотному фронд-энду надо много что помимо всего этого знать, но я то сейчас про стартовые вакансии говорю.
Ну в том то и дело, что там типа шарящие люди с многолетним опытом комментарии оставляют. Это они такие никакущие или просто ты такой перфекционист? Может я приду в какую-нибудь фирму и все, чему я тут научился мне и не понадобится толком.
А я хотел про гнутые скобочки опять спросить, но не решился, спасибо, что сам ответил. Исправил и сразу вон чо.
> Ну в том то и дело, что там типа шарящие люди с многолетним опытом комментарии оставляют.
Не знаю. Я сам не читаю и не люблю туториалы для начинающих, а предпочитаю документацию.
Насчет перфекционизма, есть такое, но это не тот случай. Если ты не обрабатываешь ошибки от БД то ты либо дольше будешь искать причину ошибки (так как ты не видишь ее) либо вообще выпустишь код с ошибками (и потом тебе придется исправлять не только код, но и восстанавливать потерянные из-за этого данные). То есть нежелание проверять ошибки выльется в потерю времени на их исправление. любой человек с многолетним опытом наверняка имеет такие случаи в практике.
> Может я приду в какую-нибудь фирму и все, чему я тут научился мне и не понадобится толком.
Может не понадобится, напрмиер может ты не будешь работать с PHP, а только заниматься версткой, или может ты попадешь в дноконтору где никому нет дела до качества твоего кода (это вряд ли тебе понравится так как тебе придется разбираться в чужом коде аналогичного качества). Но мы стараемся поддерживать определенный уровень, чтобы те кто у нас учится выглядели лучше чем те кто учится по сомнительным урокам и видеокурсам.
>они такие никакущие или просто ты такой перфекционист
и то, и другое.
>шарящие люди с многолетним опытом комментарии оставляют
лол, так и представил себе жлоба в солнцезащитных очках на аве с подписью Николай Бакланов, успешный вебмастер с 10-летним опытом разработки на вордпресс и жумла-хуямла, гыгы.
мимо
Это говорил про другое задание, про один шестигранный кубик. Я просто это задание написал поверх того оказывается.
Я у мамы молодец.жпег
А если не секрет, то где ты работаешь и сколько лет вообще программированием занимаешься?
Я вижу, что для тебя программирование это больше, чем просто работа. Я вот не такой идейный, хотя несомненно определенный интерес к этому делу есть, но больше по фронтэндовой части. Бэкенд как-то не возбуждает и делаю я его только потому, что надо. Было бы конечно шикарно найти работенку, где им надо будет заниматься по-минимуму.
>>485876
:: для статических методов.
Двачую, мне тоже нравится программирование, но без фанатизма.
Большое удовольствие что-то создавать своими руками, сам процесс творчества.
Но выносящие мозг головоломки не по нраву. Хочется, чтобы все получалось легко.
ОП не скажет, где/как давно работает. Увлекается с детства, я спрашивал.
Работает либо преподом, либо ведущим кодером типа техлида каких-нибудь тестировщиков, поэтому ревью нашего говнокода не вызывает отторжения, ибо привычно.
Ебать я шерлок.
---------------------------------------
ОП, что скажешь об этих ребятах? http://www.templatemonster.com/
Из крупных фирм в моем городишке только представительство этой конторы, поэтому попытаюсь туда попасть к осени.
Занимаются в основном написанием коммерческих тем и плагинов для cms, но и чистое программирование вроде тоже в почете.
В вакансиях просят знать зенд фреймворк, например. Что меня немного огорчает, я уже нацелился на симфони.
Я как-то не умею гуглить полноценные отзывы, нахожу только хомячковые "классная фирма!", "респект", ")))00".
Почему у этого журнальчика нет удобной системы поиска, меню?
Как найти самые популярные статьи по заданной теме (php, например)?
> ОП не скажет, где/как давно работает.
Не скажет, скажу только что работаю с PHP и вебом, предпочитаю удаленную работу/фриланс и неполный рабочий день (но если ты начинающий то 8 часов в день для тебя должен быть минимум), хотя работал и в офисе, программирование мне нравится только если это хобби (например неплохо было бы написать распознавалку кандзей), перфекционизмом я вроде переболел. Думаю не пора ли перебираться на западный фриланс или вообще придумать что-нибудь, чтобы перестать программировать самому.
>>485880
> Было бы конечно шикарно найти работенку, где им надо будет заниматься по-минимуму.
Это реально если искать позицию верстальщика. Если ты хочешь быть фронтенд разработчиком то это ангулары, нода, гульп и еще куча библиотек которые еще бестолковее и беспорядочнее чем PHP.
>>485908
> Но выносящие мозг головоломки не по нраву.
А мне нравятся, но не всегда есть время на них.
> ОП, что скажешь об этих ребятах?
Не сталкивался с ними никак. Зенд это неплохо, это тоже MVC фреймворк, хоть и чуть более старый, и если в компании используют зенд то это хорошо — как минимум люди там знакомы с ООП/MVC а не изобретают велосипеды на кривом PHP.
> Как найти самые популярные статьи по заданной теме (php, например)?
В адресной строке браузера пишешь habr composer например если нужно по конкретному слову искать. Насчет поиска популярных статей по PHP, не знаю, я набрал habr php и получил такую ссылук: http://habrahabr.ru/hub/php/
Также на хабре есть еженедельный «дайджест новостей мира php» который я советую всем читать чтобы быть знакомыми с всякими новинками: http://habrahabr.ru/company/zfort/
весьма сложные задачи, как по мне и многое не понятно, есть ли другие курсы?
Что следует почитать по пхп, базам и программированию в целом, чтобы создать о себе хорошее впечатление. По пхп по большей части синтаксис знаю, а серьёзно на этом языке не кодил. Хотя от веба не далёк - делаю дипломную на JS.
Что советуете просмотреть до завтра? Думаю отношение будет лояльное, так как выпускник, первый раз и всё такое, но тем не менее. Уже согласился, а отказываться теперь как-то неудобно.
Мануал наверно перечитать, стажеров часто любят по синтаксису и особенностям языка гонять.
По базам данных: нормализация, транзакции, внешние ключи.
Есть, но если тебе этот учебник кажется сложным...
Лучше попробуй разработку на cms. Это тоже вполне прибыльное дело, и довольно несложное.
Ну это чисто совет. Программирование для гиков-энтузиастов, которые учатся годами.
Хороших курсов попросту нет.
Есть курс от учебного центра "Специалист", но он чудовищно растянут, плюс там совершенно не уделяется внимания практике, тупо лекции с пересказом официальных мануалов. Последовательное изложение, правда, это единственный плюс.
На рутрекере кажется копирасты закрыли раздачу, ищи на nnm-club.
я застрял на 2 задаче по массивам, можно было бы по легче задание дать
Если какая-то задача или урок вызывает сложность, запости код и напиши на чем запнулся, дадим подсказку может быть.
Сидят они в Москве, синтаксис знают, на джуниоров собеседуются...
А я сиди в мухосрани, да? Я тоже хочу!
"Без портфолио на 5-10 проектов просьба даже не беспокоить!"
Суки, мудачье, разъебал бы их всех...
На джуниоров собеседуются, синтаксис знают, а я? Делай за бесплатно файлообменники, да?
>Это реально если искать позицию верстальщика. Если ты хочешь быть фронтенд разработчиком то это ангулары, нода, гульп и еще куча библиотек которые еще бестолковее и беспорядочнее чем PHP.
Эмм? Но ведь это не бэкенд же вроде.
http://asm118.besaba.com
На пике код
Спасибо, не заметил
> Делай за бесплатно файлообменники, да?
То есть ты считаешь ОП должен тебе еще и доплачивать за изучение PHP?
Ну и если все так плохо имеет смысл поискать варианты удаленной работы или фриланс, но там конечно свои подвохи есть и со знаниями только синтаксиса ты далеко не уйдешь.
>countWebms
>Функция судя по называнию должна возвращать число
Лучше б объяснял, что имена методов (а не "функций") должны начинаться с глаголов, про предпочтительность автолоадера (и какого из, и почему) (про который я прочитал лишь мельком, и только пару постов назад), про camelCase-нотацию, ну и прочие "де-факто"-стандарты.
Напиши, с использованием phpDaemon-а и Thrift-а что-нибудь высоконагруженное, создай, при помощи CruiseControl (того, что на PHP переточен) стартап себе какой-нибудь выдуманый, Jmetere заюзай, придумай команду со SCRUM-ом себе, ну и так далее. После этого сотку на удаленке за полгода сможешь найти. Но, при учете, что будешь жестко ботанить всё время поиска.
>также вместо <?php echo можно использоать <?=
Плохой совет, ОП. До 5.4 это зависит от сервера.
> До 5.4 это зависит от сервера.
5.3 древний и я никому не советую его использовать. там замыканий например нет и короткого синтаксиса для массива. Но даже если он тебе попался, наверняка можно поменять одно значение в конфиге (которое по дефолту вроде включено: http://php.net/manual/ru/ini.core.php ).
Я думаю стоит ориентироваться хотя бы на версию 5.4, а лучше конечно использовать 5.5-5.6. Там и производительсность вроде выше.
Thrift же для связи с Си++/java/go/rust демонами, анону еще и это языки придется учить? Он еще MVC и простые фреймворки типа Yii толком не освоил.
Ну и мне не нравится твой подход, инструменты надо выбирать под задачу, а ты просто стремишься использовать технологию A, B, C потому что они тебе нравятся (а мне например не особо). Мне твой подход не нравится, так как я сталкивался с кодом который писали люди которые как раз увлекались всякиеи REST API и прочей новомодной хренью при этом толком не зная ООП и не умея писать аккуратный понятный поддерживаемый код. Потому сначала надо изучать более базовые вещи.
Ну и опытный разработчик эти вещи быстро освоит если понадобится. Что сложного в phpDaemon? К тому же сейчас вроде Ratchet есть. Я думаю, что важнее изучать какие-то общие концепции, например асинхронную работу с сокетами или реализацию очередей задач, а не конкретную библиотеку.
Объясни, для какой задачи именно ты предлагаешь использовать Thrift/phpDaemon?
Насчет сервера CI это конечно хорошая идея изучать такие вещи. Но прежде чем за него браться надо научиться правильно писать тесты. Опять же, странно что ты это не упомянул. Ну и для open source проекта мне кажется проще использоать Travis CI который бесплатный и не требует настройки и установки и сам соединяется с твоим гитхабом.
> придумай команду со SCRUM-ом себе
Это точно не нужно, мне кажется.
> Лучше б объяснял, что имена методов (а не "функций")
Привычка так писать. По идее же метод это функция у объекта (не уверен верно ли это с академической точки зрения).
> должны начинаться с глаголов,
Объясняется же во втором посте треда. Ну и countWebms соответвует этому правилу, count это глагол.
> про camelCase-нотацию
Там же написано. наши аноны к этом привыкают с первых же задач.
> про предпочтительность автолоадера (и какого из, и почему)
Я написал анону, что надо бы убрать гору инклудов и посоветовал называть файлы либо по PSR-0 с подчеркиваниями, либо по PSR-4 c неймспейсами.
Ну и если ты хочешь прокомментировать код анона, пожалуйста, комментируй. Но придерживайся правил из этого поста: >>479601 и помни что анон начинающий, а не опытный программист и многого не знает.
Открой вакансию фронтенд разработчика и прочти сам: http://hh.ru/vacancy/13405841?query=%D1%84%D1%80%D0%BE%D0%BD%D1%82%D0%B5%D0%BD%D0%B4
Те вакансии что требует максимум jQuery — это фактически вакансии верстальщиков. Но ты конечно можешь с верстки начать, а потом развиваться дальше.
Учите PHP, аноны. С хаскеллем вы никуда не уедете.
Ну а вообще, конечно, интересно получается, лет 5 назад я думал что php умрет и мы перейдем на руби. Сейчас я думаю точно также, но интуиция подсказывает что я и в этот раз могу ошибиться. Конечно, все технологии рано или поздно устаревают, но PHP использует огромное число людей и жить он мжет долго. Если бы еще не было этой ситуации с очернением php, было бы вообще замечательно. Хотя PHP по некоторым пунктам лучше Руби или Питона: есть нормальный ООП, есть тайп-хинты, есть JIT (HipHop VM), но всякие неучи почему-то любят делать сравнения не в его пользу. Вот переделают обработку ошибок на исключения и тогда вообще замечательно будет.
Ты невнимательно сообщение прочитал. Я сказал, что хочу как можно меньше бекендом заниматься, а то что ты скинул это не бекэнд.
Алсо, скинул вчера ссылку на свой сайт в webm тред, за несколько часов более двухсот уникальных посетителей и около 7к запросов к странице. И ничего, сервер норм себя чувствовал, никаких лагов замечено не было. В принципе я доволен результатом.
Кстати сжатие контента реально эффективным получилось, траффик был минимальный. Когда прошлую версию сайта вкидывал, то зашло в три раза меньше человек, но траффика почти в два раза больше было.
> за несколько часов более двухсот уникальных посетителей и около 7к запросов к странице.
Это же всего 1 запрос в секунду. Правда у тебя не свой сервер, а хостинг что добавляет неожиданности, но я бы не советовал особо обольщаться. То есть хорошо конечно что он не упал, но это не большая цифра.
> Кстати сжатие контента реально эффективным получилось, траффик был минимальный.
Это странно так как у тебя основной трафик должен быть видео, которое не сжать.
Ну если учесть характеристики их серверов, то думаю это вполне хороший результат. Мне интересно, сколько он выдержать сможет максимум. Правда скорее всего после того, как я это узнаю мой сайтец прикроют нафиг.
Ты можешь тестировать на своем компьютере. Хостеры любят всякий оверселлинг, то есть продавать больше ресурсов чем есть на сервере и тестировать надо либо на своем сервере либо на своем компьютере (и по моему опыту десктопные процессоры не плохие, они всего в 1.5-2 раза медленнее серверных, правда на сервере обычно 8-16-32 ядер в отличие от домашнего компьютера).
Для этого есть 2 простых тулзы и более сложные вещи. Я бы советовал тебе найти немного времени и познакомиться с этой темой, нагрузочное тестирование.
Первая идет в комплекте с Апачом и называется ab (apache benchmark). Он запускается из командной строки (гайд по ней https://gist.github.com/codedokode/10539568 ). Он просто шлет указанное число запросов на указанный URL указанное число раз, после чего выводит скорость обработки и число успешно/неудачно обработанных запросов. Если твой сервер при ошибке выдает код 200 (что неправильно и стоит переделать) то ab посчитает такой ответ верным.
Я советую ставить минимум несколько потоков, так как в один поток ты не сможешь задействовать все ядра процессора и даже на 1 ядре будет разница. Также, запускать утилиту конечно лучше на отдельном компьютере так как она тоже немного нагружает CPU.
Если тестируешь сервер, ты можешь упереться в ограничения скорости провайдером, я однажды наткнулся на это и долго не мог понять почему так мало запросов в секунду, а потом додумался посмотреть на трафик и увидел что скорость передачи данных как раз упирается в ограничения тарифа.
Более продвинутая утилита это siege. Она позволяет составить список URL, включая по моему POST запросы и шлет их в случайном порядке, таким образом имитируя пользователей ходящих по разным страницам.
Также есть интересная утилита от Гугла Skipfish которая ищет ошибки на сайте, проверяя все ссылки, она тоже шлет запросы с огромной скоростью.
Это простые средства тестирования. Есть и более продвинутые которые позволяют делать сложные планы тестирования, строить графики, создавать нагрузку с нескольких машин:
http://habrahabr.ru/company/yandex/blog/202020/
http://habrahabr.ru/company/pt/blog/204224/
http://www.google.ru/search?sourceid=chrome&ie=UTF-8&q=habr+%D0%BD%D0%B0%D0%B3%D1%80%D1%83%D0%B7%D0%BE%D1%87%D0%BD%D0%BE%D0%B5+%D1%82%D0%B5%D1%81%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5
Если ты захочешь изучить где тонкие места, не придумывай велосипедов. Изучать причину тормозов надо профайлером, для PHP это установка xdebug, запись лога и изучение его в KCacheGrind/WebCacheGrind.
Ты можешь тестировать на своем компьютере. Хостеры любят всякий оверселлинг, то есть продавать больше ресурсов чем есть на сервере и тестировать надо либо на своем сервере либо на своем компьютере (и по моему опыту десктопные процессоры не плохие, они всего в 1.5-2 раза медленнее серверных, правда на сервере обычно 8-16-32 ядер в отличие от домашнего компьютера).
Для этого есть 2 простых тулзы и более сложные вещи. Я бы советовал тебе найти немного времени и познакомиться с этой темой, нагрузочное тестирование.
Первая идет в комплекте с Апачом и называется ab (apache benchmark). Он запускается из командной строки (гайд по ней https://gist.github.com/codedokode/10539568 ). Он просто шлет указанное число запросов на указанный URL указанное число раз, после чего выводит скорость обработки и число успешно/неудачно обработанных запросов. Если твой сервер при ошибке выдает код 200 (что неправильно и стоит переделать) то ab посчитает такой ответ верным.
Я советую ставить минимум несколько потоков, так как в один поток ты не сможешь задействовать все ядра процессора и даже на 1 ядре будет разница. Также, запускать утилиту конечно лучше на отдельном компьютере так как она тоже немного нагружает CPU.
Если тестируешь сервер, ты можешь упереться в ограничения скорости провайдером, я однажды наткнулся на это и долго не мог понять почему так мало запросов в секунду, а потом додумался посмотреть на трафик и увидел что скорость передачи данных как раз упирается в ограничения тарифа.
Более продвинутая утилита это siege. Она позволяет составить список URL, включая по моему POST запросы и шлет их в случайном порядке, таким образом имитируя пользователей ходящих по разным страницам.
Также есть интересная утилита от Гугла Skipfish которая ищет ошибки на сайте, проверяя все ссылки, она тоже шлет запросы с огромной скоростью.
Это простые средства тестирования. Есть и более продвинутые которые позволяют делать сложные планы тестирования, строить графики, создавать нагрузку с нескольких машин:
http://habrahabr.ru/company/yandex/blog/202020/
http://habrahabr.ru/company/pt/blog/204224/
http://www.google.ru/search?sourceid=chrome&ie=UTF-8&q=habr+%D0%BD%D0%B0%D0%B3%D1%80%D1%83%D0%B7%D0%BE%D1%87%D0%BD%D0%BE%D0%B5+%D1%82%D0%B5%D1%81%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5
Если ты захочешь изучить где тонкие места, не придумывай велосипедов. Изучать причину тормозов надо профайлером, для PHP это установка xdebug, запись лога и изучение его в KCacheGrind/WebCacheGrind.
И разумеется, не забудь включить кеш опкодов в PHP (c версии 5.5 он встроен в PHP, до этого ставился отдельно) иначе цифры будут намного меньше, так как PHP каждый запрос будет заново компилировать твой код, что отстойно.
мне нужен какой-то сервис, который синхронизировал бы мой лоакльный проект с облаком. Желательно, чтобы с версиями файлов. До этого я пользовался cubby, но сейчас там ввели демо версию, скоро закончится срок.
Гугл драйв, яндекс диск и дропбокс не подходят, поскольку они не загружают на сервер изменения в файлах, а срабатывают только когда файл создается.
Спасибо заранее
Я из провинции, у меня нет в портфолио ни одного проекта и на удивление нормально сходил пособеседовался, хотя местами жутко обосрался. Не знаю что у тебя за ситуация, но ты это, не сиди на жопе ровно, а отписывайся в hr отделы шаражек. И сделай акк на фриланс бирже, тупо чтобы был - друг говорит, что ему предложения на фулл тайм даже туда приходили.
Не знаю что ты делаешь, но ты do it wrong.
Бобра, анон.
работатть пхп-девом или пройти курсы питона и кодить на питоне. Что посоветуете? А если в долгосрочной перспективе и что лучше, если хочу завести трактор?
Но здесь не только новички, так что я попробовал.
Ребят, извините за глупый вопрос, но пока нигде не встречал на него ответа. Как быть с ; в конце функций\методов? В каких случаях ставятся, в каких нет?
Алсо $mysqli = new mysqli("localhost", "my_user", "my_password", "test");
Что такое test? Что на его место ставить?
if(isset($cookies)){
if($cookies == 0){ $cookies='ASC'; }else{ $cookies='desc';}
$qb
->addOrderBy('c.price', ':value3')
->setParameter('value3', $cookies);
}
почему-то не работает, а вот например
if (isset($get['TM']) and count($get['TM']) > 1) {
$qb
->where('c.TM IN (:value)')
->setParameter('value', $get['TM']);
}
работает норм, в чем дело?
выдает: [Syntax Error] line 0, col 93: Error: Expected end of string, got ':value3'
(это я про симфони)
>Пожалуйста, обратите внимание на блок try/catch – всегда стоит оборачивать в него все свои PDO-операции и использовать механизм исключений (об этом чуть дальше).
Оооооох.
>Fatal error: Call to a member function setFetchMode() on a non-object
Сразу фэйл. Пытаюсь вывести результат запроса
$STH = $DBH->query('SELECT name, addr, city from folks');
# устанавливаем режим выборки
$STH->setFetchMode(PDO::FETCH_ASSOC);
while($row = $STH->fetch()) {
echo $row['name'] . "\n";
echo $row['addr'] . "\n";
echo $row['city'] . "\n";
}
Выдаёт ошибку на моменте
$STH->setFetchMode(PDO::FETCH_ASSOC);
Что за фигня такая!
>function setFetchMode() on a non-object
Я подозреваю, что ты не создал перед этим обьект класса PDO
>Я подозреваю, что ты не создал перед этим обьект класса PDO
Блеадь, на хабре сделали всё через жопу. Ну и нафиг его создават, когда можно было просто написать
$link = mysqli_connect($hostname, $username, $password, 'test');
Нет какой-то обьект класса создать надо... Мне короче немного бомбит как начинающему. Алсо все учебники про это не особо пишут.
Ты ООП знаешь? Работа с пдо это просто работа с обьектом класса и его методами, не вижу тут ничего сложного. Создание обьекта пдо практически ничем не отличается от обычного mysql_connect
$DBH = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
Всё, объект создан, с ним можно работать.
Я знаю, но в данном случае оно применено странно. Для примера хватило бы и моей интерпретации. Но нет, автор решил повыпендриваться, в итоге ньюфаги ничего не понимают.
И слава б-г не понимаешь ооп или не способен разбираться сам по ходу дела - вон из професии
Ты как себе это представляешь? Я этот код впервые вижу и ссылку твою раньше не читал. Естественно у меня возникнут некоторые вопросы. Если-бы их небыло - очевидно что я ы тут не сидел бы.
Всё, разобрался.
После скобок { и } не ставится. Перед } ставится:
function x() {
return 1;
}
Исключение — анонимные функции, там ставится после }
$f = function () {
...
};
Вообще ; ставится в конце каждой команды, а объявление функции это как бы не команда и потому после нее ставить не надо. А вот присваивание функции переменной — это уже команда и потому ставится точка с запятой.
Мануал почти ничего не говорит, и правда:
http://php.net/manual/ru/language.basic-syntax.instruction-separation.php
http://php.net/manual/ru/control-structures.intro.php
Устарели функции вроде mysql_query (без i). Те учебники что просто приписывают букву i тоже устарели (букву i приписать недостаточно, надо использовать плейсхолдеры и обрабатывать ошиюки). Вместо них надо использоать mysqli ( http://habrahabr.ru/post/141127/ ) и PDO ( http://m.habrahabr.ru/post/137664/ ).
mysqli не устарел.
Обрати внимание, с mysqli ты должен после каждой функции писать if для проверки и вывода ошибок иначе они не будут показываться и отлаживать код будет нереально.
С PDO это не требуется.
>>486574
> Что такое test? Что на его место ставить?
Открой мануал http://php.net/manual/ru/mysqli.construct.php
Имей в виду что new это создание объекта и тебе надо знать ООП.
> Только я не понял в чём собственно профит?
Профит в том что мы перестанем использовать устаревшие неподдерживаемые функции. Ну и как я помню там расширение mysql мало того что старое. оно еще и зависит от кода компании Oracle которая может в любой момент например поменять лицензию на него. А mysqli/pDO свободные.
Я уверен, что многое тут убого, но всё же, может, ты сможешь дать мне пару советов как улучшить код.
Я делал всё в контроллере и сейчас буду разносить всё туда, где ему место. Вот, например, я знаю, что всё что связано с базой данных не должно находиться в контроллере, но куда мне лучше этот код запихать? в папку Entity можно?
а вот этот кусок кода, например:
foreach ($type as $key => $value) {
if (isset($get['type'])) {
foreach ($get['type'] as $key2 => $value2) {
if ($value->id == $value2) {
$value->checked = 'checked';
}
}
}
}
его можно оставить в контроллере?
https://ideone.com/2TGpsW
Заранее огромное спасибо.
> ->addOrderBy('c.price', ':value3')
Я думаю плейсхоодеры вставляют в запрос только строки или числа а не имена полей или ключевые слова. То есть твоя кука вставляется как
ORDER BY c.price 'ASC'
а должно быть
ORDER BY c.price ASC
Придется вставлять напрямую без плейсхолдеров, не забудь 10 раз проверить что вставляемое значение может быть только ASC или DESC и ничем другим иначе это DQL инъекция.
Или же, что лучше, сделай так:
if (..) {
addOrderBy('c.price', 'ASC');
} else {
... addOrderBy('c.price', 'DESC')
}
Так будет безопаснее и проще.
ООП изучается в нашем учебнике (ссылка в оп посте) в последней главе, там все просто и понятно (потому аноны которые учатся по нашему учебнику проблем с PDO не испытывают). Он тебе все равно нужен будет.
Про исключения написано тут: https://gist.github.com/codedokode/65d43ca5ac95c762bc1a
Заметь что в статье совет про try/catch неправильный.
Также, у тебя по моему отключен вывод ошибок так как должно быть предупреждение про несуществующую переменную DBH. То есть тебе сначала надо научиться вообще ошибки просматривать, а потом уже за более сложные вещи браться.
В PHP по умолчанию выключено отображение ошибок в браузере, так как обычному пользователю сайта эта информация ни к чему. Но тебе, как программисту, надо видеть эти ошибки. Вот, как можно их просмотреть:
- ошибки сохраняются в лог ошибок. Можно открыть его и почитать. Если ты запускаешь код на локалхосте, у себя, то лог хранится в папке Апача (обычно она называется logs) и имеет название вроде error.log (в линуксе в папку /var/log/apache2 ). Если на хостинге — там либо есть файл error.log либо раздел в панели управления, где лог можно посмотреть
- также, ты можешь включить отображение ошибок. Открой файл php.ini, поставь там display_errors = On и error_reporting = E_ALL и перезапусти сервер. Теперь ошибки должны выводиться на экран.
Проверить, работает ли вывод ошибок, можно запустив скрипт содержающий обращение к несуществующей переменной вроде echo $sdgasdad; и проверив, выведется ошибка или нет. Если все верно, то должна вывестись.
Если ты рабоатешь с магенто то наверно зенд. Ну и симфони потом изучить тоже стоило бы.
>>486586
Все современные нормальные фреймворки исопльзуют ООП так что без него ты дальше верстальщика не пролезешь.
> Алсо все учебники про это не особо пишут.
Плохие устаревшие учебники. Наш пишет про ООП например.
>>486591
charset бы еще указать
>>486593
Ты должен сначала изучить ООП и исключения, потом браться за PDO.
>>486598
Никто тебя за вопросы и не ругает, я дал ссылки для изучения.
> - большим плюсом будет опыт работы с высоконагруженными системами.
Что нужно штудировать?
Вот спасибо, добра.
> Вот, например, я знаю, что всё что связано с базой данных не должно находиться в контроллере, но куда мне лучше этот код запихать? в папку Entity можно?
Ты доктрину используешь? Тогда создай свой репозиторий например NewsRepository и помести туда код работы с новостями.
Заметь что репозиторий надо зарегистрировать прописав у сущности аннотации с его именем:
http://doctrine-orm.readthedocs.org/en/latest/reference/working-with-objects.html#custom-repositories
http://stackoverflow.com/a/8148065
http://habrahabr.ru/post/130275/ (по русски! почему не нагуглил?)
http://symfony-gu.ru/documentation/ru/html/book/doctrine.html
После этого можно писать
$newsRepo = $this->getEntityManager()->getRepositry('AnonBundle:News');
если класс назван правильно и лежит в нужной папке. Традиционно их кладут в файл вроде Entity\Repository\NewsRepository.
Если не используешь доктрину а пишешь запросы руками (гм? это как-то не по симфониевски) то просто сделай класс-сервис NewsService например.
Класс в симфони принято прописывать как сервис в services.yml, чтобы его не надо было создавать руками а можно было писать
$this->container->get('news.service');
если класс назван правильно и лежит в нужной папке.
> Вот, например, я знаю, что всё что связано с базой данных не должно находиться в контроллере, но куда мне лучше этот код запихать? в папку Entity можно?
А где тут работа с базой данных? Не вижу. Этот код надо просто вынести в приватный метод в контроллере.
И что это такое? $get['type']? В Симфони надо использоать request, а не изобретать аналоги $_GET
> class filter
Не по PSR-1 и 2 названо, перечитай их, надо с большой буквы и разумеется каждый класс в своем файле
Класс Filter можно поместить например в FilterBundle\Helper\Filter
Более того, этот класс у тебя создает аналог _GET (нафига?) и я бы его вообще выкинул.
> namespace test
надо с большой буквы и не test а namespace Anon\Bundle\AnonBundle, по моему так, название компании и название бундла.
> public function buildSql($request)
Имя метода должно описывать что он делает, у тебя это не так
> ->from('test\FilterBundle\Entity\Production', 'c');
там же можно как-то сделать чтобы было
->from('FilterBundle:Production')
> if (isset($get['TM']) and count($get['TM']) > 1) {
работать с request гораздо удобнее:
if ($query->has('TM') ...)
> elseif (isset($get['TM']) and count($get['TM']) == 1) {
$qb
> ->setParameter('value', $get['TM']);
если у тебя в одной переменной может быть либо массив либо число то это бардак и такого лучше избегать. Я бы везде использовал IN()
> if ($value->id == $value2) {
Это у тебя через магические методы сделано? У доктриновских сущностей вроде нельзя делать публичные свойства, надо геттеры/сеттеры, хотя тут стоит перечитать документацию.
> $url = $this->get('request_stack')->getMasterRequest();
Костыли какие-то, чем тебе request не нравится?
> array(
> 'products' => $result,
> 'get' => $get,
> 'type' => $type,
> 'TM' => $TM,
> 'qb' => $qb,
> 'cookie' => $cookies,
> 'url' => $url)
Зачем в шаблон передавать query builder и get-переменные? Бардак. Передавай только то что нужно, а GET переменных в шаблоне быть не должно.
Анон, по моему тебе надо больше читать документацию по Симфони/Доктрине, ну и конечно соблюдать соглашения о названиях классов, ибо иначе бардак получается.
> Вот, например, я знаю, что всё что связано с базой данных не должно находиться в контроллере, но куда мне лучше этот код запихать? в папку Entity можно?
Ты доктрину используешь? Тогда создай свой репозиторий например NewsRepository и помести туда код работы с новостями.
Заметь что репозиторий надо зарегистрировать прописав у сущности аннотации с его именем:
http://doctrine-orm.readthedocs.org/en/latest/reference/working-with-objects.html#custom-repositories
http://stackoverflow.com/a/8148065
http://habrahabr.ru/post/130275/ (по русски! почему не нагуглил?)
http://symfony-gu.ru/documentation/ru/html/book/doctrine.html
После этого можно писать
$newsRepo = $this->getEntityManager()->getRepositry('AnonBundle:News');
если класс назван правильно и лежит в нужной папке. Традиционно их кладут в файл вроде Entity\Repository\NewsRepository.
Если не используешь доктрину а пишешь запросы руками (гм? это как-то не по симфониевски) то просто сделай класс-сервис NewsService например.
Класс в симфони принято прописывать как сервис в services.yml, чтобы его не надо было создавать руками а можно было писать
$this->container->get('news.service');
если класс назван правильно и лежит в нужной папке.
> Вот, например, я знаю, что всё что связано с базой данных не должно находиться в контроллере, но куда мне лучше этот код запихать? в папку Entity можно?
А где тут работа с базой данных? Не вижу. Этот код надо просто вынести в приватный метод в контроллере.
И что это такое? $get['type']? В Симфони надо использоать request, а не изобретать аналоги $_GET
> class filter
Не по PSR-1 и 2 названо, перечитай их, надо с большой буквы и разумеется каждый класс в своем файле
Класс Filter можно поместить например в FilterBundle\Helper\Filter
Более того, этот класс у тебя создает аналог _GET (нафига?) и я бы его вообще выкинул.
> namespace test
надо с большой буквы и не test а namespace Anon\Bundle\AnonBundle, по моему так, название компании и название бундла.
> public function buildSql($request)
Имя метода должно описывать что он делает, у тебя это не так
> ->from('test\FilterBundle\Entity\Production', 'c');
там же можно как-то сделать чтобы было
->from('FilterBundle:Production')
> if (isset($get['TM']) and count($get['TM']) > 1) {
работать с request гораздо удобнее:
if ($query->has('TM') ...)
> elseif (isset($get['TM']) and count($get['TM']) == 1) {
$qb
> ->setParameter('value', $get['TM']);
если у тебя в одной переменной может быть либо массив либо число то это бардак и такого лучше избегать. Я бы везде использовал IN()
> if ($value->id == $value2) {
Это у тебя через магические методы сделано? У доктриновских сущностей вроде нельзя делать публичные свойства, надо геттеры/сеттеры, хотя тут стоит перечитать документацию.
> $url = $this->get('request_stack')->getMasterRequest();
Костыли какие-то, чем тебе request не нравится?
> array(
> 'products' => $result,
> 'get' => $get,
> 'type' => $type,
> 'TM' => $TM,
> 'qb' => $qb,
> 'cookie' => $cookies,
> 'url' => $url)
Зачем в шаблон передавать query builder и get-переменные? Бардак. Передавай только то что нужно, а GET переменных в шаблоне быть не должно.
Анон, по моему тебе надо больше читать документацию по Симфони/Доктрине, ну и конечно соблюдать соглашения о названиях классов, ибо иначе бардак получается.
Ничего, надо иметь опыт работы очевидно. А так можешь начать с этого: http://www.insight-it.ru/highload/
и этого: http://ruhighload.com/post/%D0%A0%D0%B0%D0%B1%D0%BE%D1%82%D0%B0+%D1%81+%D0%B8%D0%BD%D0%B4%D0%B5%D0%BA%D1%81%D0%B0%D0%BC%D0%B8+%D0%B2+MySQL
А ты где живешь?
Та же проблема, вакансии типа "PHP-макака, лучше Бога знающая все тонкости языка, плюс дохуиллиард технологий и фреймворков, неплохим плюсом будет знание ебической хуиты и хуипиздической залупы, на должность джууниор разработчика, запрлата 10 тысяч рублей, если вы не талантливы, просьба не беспокоить"
"Дан рост школьника и рост его одноклассников. Надо найти, сколько человек в классе выше, чем наш герой."
Ну а в чем проблема? Ты не знаешь, как условия работают, или что?
http://ideone.com/lq5rCx
В Москвабадах действительно больше вакансий стажеров/джуниоров. В мухосранских конторах малый бюджет, у них нет возможности нанимать и обучать бестолочь. Поэтому обычно они ищут опытного человека, который сможет прийти и сразу начать показывать результат.
Но вы бы лучше не пиздели о том как плохо, а занялись делом.
я не понимаю как это сделать
спасибо, всё пересмотрю.
> А где тут работа с базой данных? Не вижу. Этот код надо просто вынести в приватный метод в контроллере.
ну вот query builder он же конструктор запросов, это же работа с базой.
> И что это такое? $get['type']? В Симфони надо использоать request, а не изобретать аналоги $_GET.
Ну я и использую $get = $request->query->all();
Просто переменную так назвал, чтобы было ясно к чему она
> namespace test
>надо с большой буквы и не test а namespace Anon\Bundle\AnonBundle, по моему так, название компании и название бундла.
но у меня же правильно
namespace test\FilterBundle\Controller;
>если у тебя в одной переменной может быть либо массив либо число то это бардак и такого лучше избегать. Я бы везде использовал IN()
Я тоже так думал, но почему-то не работает как следует. Уйму времени убил в попытках. Пришлось сделать как есть.
>Зачем в шаблон передавать query builder и get-переменные? Бардак. Передавай только то что нужно, а GET переменных в шаблоне быть не должно.
Та то я всё время дампы просматривал, пока делал. Убрать забыл.
Я вот не понимаю, а схуяли в IT сфере есть привязка к местоположению? Ну т.е. какая разница где контора находится, в ДС или в Воронеже? Ведь вся работа через интернет ведется.
Да и обладая знаниями для работы в мухосранских фирмах работать в этих самых фирмах только долбоеб будет. Ну я это я имею ввиду тех, кого какие-то дополнительные факторы в городе не удерживают.
Да блять потому что у нас в стране все через жопу Москву. Вне Москвы можно сказать вообще жизни нет. Это я тебе как житель урала говорю.
Хотя я бы лучше тут остался, зарплаты почти такие же как в ДС, а жить дешевле. Тем более не буду очередным понаехом, которых у вас я уверен итак пруд пруди.
Да я сам в мухосранске живу, бро. Переезжать планирую, но только не в Москву, а в Новосиб. А вообще в рашке ловить больше нехуй, все что можно было проебать - проебано. Валить надо при первой же возможности, пока не поздно.
Думаешь PHP-макаки кому-то нужны за бугром? Валить-то надо, да, вон рубль опять по пизде пошел.
В земляшке ловить нечего, планирую валить на Марс.
Ну php это стартовая точка. Нужны, почему нет? Там же тоже сайты делают. Хотя конечно там жесткая конкуренция с индусами и китайцами всякими. Но о русских погромистах репутация хорошая сложилась ( спасибо нашим предшественникам), так что при прочих равных думаю шансы выше у нас.
Нужны конечно. Вот вчера наткнулся на сайте, который регулярно посещаю, который вообще не про программирование.
http://www.gosumedia.net/php-web-developer/
Да не какая-то конкретная, просто иногда сижу на хх и мелькает вакансии на английском, я в них даже не захожу конечно, просто интересно как-то.
Такое впечатление, что такую документацию пишут для опытных программистов, которые уже работали с другими фреймворками и знают общие методики, подходы, или как это называется.
Вот допустим на этой странице http://yiiframework.ru/doc/guide/ru/basics.workflow
пункт 4:
>Создание класса контроллера для каждого типа пользовательского запроса. Классификация пользовательских запросов зависит от текущих требований. В общем случае, если класс модели используется пользователем, должен существовать соответствующий класс контроллера.
Я не понимаю, что подразумевают под "каждым типом пользовательского запроса". От каких "требований" зависит классификация этих запросов?
"Если класс модели используется пользователем, должен существовать соответствующий контроллер."
Как мне понять, что класс модели используется пользователем? Учитывая, что в yii всего два типа моделей (формы и AR), то здесь имеется ввиду что нужно создавать контроллер для каждой модели active record? Модель формы не "используется" пользователем? (или "используется"?)
Из всей этой галиматьи я пока делаю вывод, что для каждой AR-модели должен быть контроллер. Поправьте, если не так.
Что вообще может быть моделью? В случае yii, как я понял, это либо паттерн ActiveRecord, либо
Последнюю строку забыл удалить.
Тогда уже дополню:
Как вообще понимать "модель"? Да, модель это объект для работы с данными. Но моделей много, а не одна. Как мне знать, для каких объектов создавать модель? Кажется, для каждой таблицы бд, с которой будут выполняться crud-операции?
>5.3 древний
Заказчику это расскажи. А насчет замыканий - ну да, не в классическом смысле. Но анонимные функции есть, хоть и псевдоуказатель $this в них неlоступен явно (что решается одной строчкой присваивания и конструкцией use()).
>Поясните за mysqli
Сугубо личное мнение - кал и отстой. Юзай PDO, Люк! И вообще, все втемачные посоны с района давно перешли на Doctrine.
Логи Апача находятся там, где указаны в конфиге виртуального хоста, и имеют свойство пухнуть, аки жирна баба. Не люблю я в них копаться, в общем.
А юзаю я обычно, по старинке, стандартный код:
error_reporting(E_ALL | E_STRICT);
ini_set('display_errors', true);
Располагать как можне раньше, перед остальным кодом.
Там еще какая-то INI-директива есть, "display_startup_errors" вроде, но она мне никогда не пригождалась.
Нет, далеко не фак. Просто нужен чел, способный общаться по-аглицки. Ну и вся работа на нем будет.
Сколько я таких вакансий пересмотрел. Кстати, зарубежная удаленка дает отечественной сосать-сосать просто на раз-два.
>Я не понимаю, что подразумевают под "каждым типом пользовательского запроса".
>имеется ввиду что нужно создавать контроллер для каждой модели
Контроллер - это класс, группирующий действия по типу. Контроллер "Пробздунение по-всякому" объединяет в себе 3 действия: "ссать", "срать" и "пердеть". Модель одна - толчок где батя на карачках сидит. А вот действие "подойти к окну и заплакать" относится уже к другому контроллеру - "Сычевание". Там уже другая модель (которую хорошо бы декомпозировать) - сычевальня.
Как-то так.
Лень разбирать алгоритм, так что только по синтаксису:
- комментарии / / (шатаба, надеюсь, не съест здездочки) в конце строки не нужны. Юзай "//"
- комментарии на русском для меня - детектор быдлокода
- скобку от конструкции отделяй пробелом ("if(")
- а вот "++" не отделяй, и в цикле for лучше его использовать перед переменной (тем более, у тебя все условия для этого)
- про фигурные скобки и отсупы после тех же "if" не забывай
- уже определись, переносить на новую строку фигурную скобку после конструкции или нет
- использование двойных кавычек, заключение переменных в них в фигурные скобки - нахуй
- для переноса строки есть такая константа - PHP_EOL. Да, и ты не допускаешь, что код будет исполняться в браузере?
- есть хорошая практика - при сравнении, например, константу ставить на первое место. Т.е. не "$x === 3", а "3 === $x"
- зачем тебе "error_reporting(-1);"?
Все, что понял, учту. Я же новичок(например поэтому и пишу error_reporting(-1), так в книжке сказано). С этой задачей я вообще не справился, это решение друга. Я уже потом в своем решении убрал модульное число и в $paymentTotal = $paymentTotal - $creditBalance; минус заменил на плюс. Как все просто оказывается.
Вот сделал следующую задачу, тут уже сам.
W5.2 Некто кладет в банк 10000 р. Банк начисляет 10% годовых (то есть, каждый год на счету становится на 10% больше, чем в прошлом году). Напиши программу, считающую, через сколько лет в банке будет миллион? Сколько лет будет этому некто? Доживет ли некто до этого дня, если сегодня ему 16 лет? http://ideone.com/bcjEKX Проверь?
> - а вот "++" не отделяй, и в цикле for лучше его использовать перед переменной (тем более, у тебя все условия для этого)
++$mounth так что ли?
>++$mounth так что ли?
Ну да. Инициализируешь переменную нулем, на первой итерации получаешь единицу, проверку ведешь до "< 20".
>http://ideone.com/bcjEKX Проверь?
То же, еще и отсупы распидорасило. Всегда юзай 4 пробела, не табуляцию; в настройках редактора задай.
Ну и парочка дополнительных:
- вместо цикла for логичнее использовать while или do ... while
- вот это "$balance = $balance$percent;" сокращается до $balance = $percent;
Блядская вакаба. Короче, сокращается до оператора "звездочка-равно".
Я еще не знаю, что такое while, сейчас погуглю.
>Блядская вакаба. Короче, сокращается до оператора "звездочка-равно".
Действительно, из головы вылетело.
Вообще классно бы было, если бы ты в этом моем задании отступы поправил, что бы наглядный пример у меня был, я путаюсь в них еще. В любом случае спасибо.
Вроде все исправил, кроме отступов конечно. И объясни еще, в чем разница ++ перед и после переменной?
>И объясни еще, в чем разница ++ перед и после переменной?
Разница минимальная и несущественная. На производительность она никак не повлияет. Просто из 250-ти таких несущественных разниц (типа располагания константы или неприсваемой лексемы первой в сравнении) складываются "правила хорошего тона", и, в конце концов, стандарты программирования. Которые, в любом мало-мальски приличном проекте юзать придется.
Разница же идет на уровне оптимизации кода. Если в for(;;;) ты используешь пост-инкремент ($x++), то всю итерацию приходится (это делается автоматически) держать 2 переменные: исходную, и увеличенную на единицу. Или копия создается для использования в сравнении, не помню я (а волшебный эфир уже кончается). При пре-инкременте (++$x) же всё проще - увеличил значение, и забыл. Короче, юзай пре-инкремент - и будешь выглядеть олдфагом.
Кстати, вопрос иногда попадается на собеседованиях во всеразличные ёбнутые конторы. Наряду с тем, как обменять значения 2-х переменных не используя третью.
>W5.2 Некто кладет в банк 10000 р. Банк начисляет 10% годовых (то есть, каждый год на счету становится на 10% больше, чем в прошлом году). Напиши программу, считающую, через сколько лет в банке будет миллион? Сколько лет будет этому некто? Доживет ли некто до этого дня, если сегодня ему 16 лет?
Написал какое-то говно, но хуй знает. Соображаю плохо: обдолбался сильно. У меня 65 лет вышло, вроде еще не должен дуба врезать:
http://ideone.com/p6pV9X
Для тебя может и говно, а для меня "воу, вон как еще можно оказывается". В принципе понял твой код, схоронил себе на всякий. У меня тоже 65 лет получилось, та ссылка полетела. http://ideone.com/8HTpLg
Ну вот, теперь я тоже захотел обдолбаться.
Заведи переменную и положи в нее число 0. Затем внутри цикла напиши условие
если (этот школьник выше чем мы) {
увелчиить переменную на 1;
}
В итоге ты получишь ответ.
>>486739
Так и есть, там работают в основном нубы, студенты и те, у кого есть способности, развиваются и уезжают в столицу либо находят удаленную работу, а те, кто ленивый, не хочет расти, не любит читать докуменатцию и решать задаки, а только любит жаловаться на жизнь, те остаются и всю жизнь поправляют меню на сайте за минимальную зарплату.
Ааа! Спойлер! Бака, бака!
Я только до этой задачки дошел. Хорошо хоть прочитал и ничего не запомнил.
Разница в том что одна конструкция возвращает значение до увеличения, а другая после:
$a = 1;
echo $a++; // 1
$a = 1;
echo ++$a; // 2
Мануал http://php.net/manual/ru/language.operators.increment.php
То что написал другой анон, не точно. Ниже я написал почему.
>>487071
Твой ответ неправильный. Вопрос был, в чем разница между пост- и преинкрементом? Ответ: в том, что возвращается. То, что сейчас одна операция дает на один опкод больше, это детали реализации которые могут поменяться в любой момент.
> На производительность она никак не повлияет.
Молодец, верно написал. Я уж хотел написать 2 гневных абзаца про микрооптимизаторов.
> Просто из 250-ти таких несущественных разниц (типа располагания константы или неприсваемой лексемы первой в сравнении) складываются "правила хорошего тона", и, в конце концов, стандарты программирования. Которые, в любом мало-мальски приличном проекте юзать придется.
Покажи ссылку на стандарты, желательно чтобы это были PSR где говорится про преинкремент. Стандарты ставят своей целью сделать код наиболее читаемым, единообразным и понятным, чтобы уменьшить время (человека) на его разбор и снизить вероятность сделать ошибку. Никто в здравом уме не занимается микрооптимизациями.
Я например всегда пишу постинкремент просто по привычке. В учебниках по которым я учился цикл for писали так for (i = 0; i < 10; i++)
> типа располагания константы или неприсваемой лексемы первой в сравнении
Это делается по другой причине, для защиты от ошибки если напишешь = вместо ==. В других языках кстати проблема решается проще: там просто запрещено делать присваивание внутри условия.
> то всю итерацию приходится (это делается автоматически) держать 2 переменные: исходную, и увеличенную на единицу.
почему бы не проверить с помощью vld: http://ideone.com/BBEj32
> Короче, юзай пре-инкремент - и будешь выглядеть олдфагом.
будешь выглядеть диванным микрооптимизатором
> Кстати, вопрос иногда попадается на собеседованиях во всеразличные ёбнутые конторы. Наряду с тем, как обменять значения 2-х переменных не используя третью.
Значит в этой конторе тимлид диванный оптимизатор. Расскажи ему еще про строки в одиночных кавычках и ты точно принят.
Разница в том что одна конструкция возвращает значение до увеличения, а другая после:
$a = 1;
echo $a++; // 1
$a = 1;
echo ++$a; // 2
Мануал http://php.net/manual/ru/language.operators.increment.php
То что написал другой анон, не точно. Ниже я написал почему.
>>487071
Твой ответ неправильный. Вопрос был, в чем разница между пост- и преинкрементом? Ответ: в том, что возвращается. То, что сейчас одна операция дает на один опкод больше, это детали реализации которые могут поменяться в любой момент.
> На производительность она никак не повлияет.
Молодец, верно написал. Я уж хотел написать 2 гневных абзаца про микрооптимизаторов.
> Просто из 250-ти таких несущественных разниц (типа располагания константы или неприсваемой лексемы первой в сравнении) складываются "правила хорошего тона", и, в конце концов, стандарты программирования. Которые, в любом мало-мальски приличном проекте юзать придется.
Покажи ссылку на стандарты, желательно чтобы это были PSR где говорится про преинкремент. Стандарты ставят своей целью сделать код наиболее читаемым, единообразным и понятным, чтобы уменьшить время (человека) на его разбор и снизить вероятность сделать ошибку. Никто в здравом уме не занимается микрооптимизациями.
Я например всегда пишу постинкремент просто по привычке. В учебниках по которым я учился цикл for писали так for (i = 0; i < 10; i++)
> типа располагания константы или неприсваемой лексемы первой в сравнении
Это делается по другой причине, для защиты от ошибки если напишешь = вместо ==. В других языках кстати проблема решается проще: там просто запрещено делать присваивание внутри условия.
> то всю итерацию приходится (это делается автоматически) держать 2 переменные: исходную, и увеличенную на единицу.
почему бы не проверить с помощью vld: http://ideone.com/BBEj32
> Короче, юзай пре-инкремент - и будешь выглядеть олдфагом.
будешь выглядеть диванным микрооптимизатором
> Кстати, вопрос иногда попадается на собеседованиях во всеразличные ёбнутые конторы. Наряду с тем, как обменять значения 2-х переменных не используя третью.
Значит в этой конторе тимлид диванный оптимизатор. Расскажи ему еще про строки в одиночных кавычках и ты точно принят.
Пересчитай еще фигурные скобки внимательно.
>>486726
> \t$creditSum=39999;
> $payout=5000;
Это лучше вынести наружу из функции чтобы получилась универсальная функция, работающая с любыми суммами.
> \t}
> else{
Это надо писать в одну строчку } else {
Ну и else тут не нужен, можно без него.
Считает программа правильно.
> ну вот query builder он же конструктор запросов, это же работа с базой.
да, действительно. Ну тут есть 2 варианта:
— сделать в сервисе/хелпере функцию вроде
findProduction(array $tm, array $types)
Если параметров поиска много то лучше сделать класс для их хранения и функцию в виде
findProduction(ProductionFilter $filter)
Этот же класс ProductionFilter можно передать в шаблон для вывода значений в форме поиска.
— оставить это в контроллере.
Первый вариант покрасивее, так как дает нам тонкий контроллер и толстую модель, но когда спешат, часто делают второй вариант. Если код потом надо поддерживать и допиливать, лучше конечно первый вариант.
> Ну я и использую $get = $request->query->all();
> Просто переменную так назвал, чтобы было ясно к чему она
А лучше сделать переменную $query = $request->query. Ты взял и заменил объект ParameterBag с кучей полезных методов на убогий массив. Какая от этого выгода? Ты старым добрым массиво ориентироанным программированием хочешь заняться? Не надо. Открой лучше документацию и изучи объект query. Не надо в симфони возвращаться к старым привычкам и $_GET.
> но у меня же правильно
> namespace test\FilterBundle\Controller;
Нет, неправильно. В PSR-4 по моему написано что имена неймспейсов пишутся с большой буквы. Ну и смотри есть еще эту статью:
> http://symfony.com/doc/current/best_practices/creating-the-project.html
> Best Practice
> Create only one bundle called AppBundle for your application logic
> There is no need to prefix the AppBundle with your own vendor (e.g. AcmeAppBundle), because this application bundle is never going to be shared.
То есть рекомендут сделать просто namespace AppBundle. Заметь что там же дана рекомендуемая структура папок.
То что я писал выше про namespace Anon\Bundle\AnonBundle это относится к reusable bundles, то есть бандлы которые ты выпускаешь как библиотеки котрые можно применять на других сайтах, это описано тут:
http://symfony.com/doc/current/cookbook/bundles/best_practices.html
http://symfony.com/doc/current/bundles/SensioGeneratorBundle/commands/generate_bundle.html
То есть я немного неправильно насоветовал, но ты сделал еще непраильнее. Думаю стоит придерживаться рекомендации из официального мануала.
> Я тоже так думал, но почему-то не работает как следует. Уйму времени убил в попытках.
Сделай var_dump($get) и сдампь сгенерированный запрос через echo $qb->getDql() по моему. Надо искать причину ошибки а не уродовать код из-за того что ты что-то не знаешь.
> Та то я всё время дампы просматривал, пока делал.
var_dump проще поставить в контроллере.
> ну вот query builder он же конструктор запросов, это же работа с базой.
да, действительно. Ну тут есть 2 варианта:
— сделать в сервисе/хелпере функцию вроде
findProduction(array $tm, array $types)
Если параметров поиска много то лучше сделать класс для их хранения и функцию в виде
findProduction(ProductionFilter $filter)
Этот же класс ProductionFilter можно передать в шаблон для вывода значений в форме поиска.
— оставить это в контроллере.
Первый вариант покрасивее, так как дает нам тонкий контроллер и толстую модель, но когда спешат, часто делают второй вариант. Если код потом надо поддерживать и допиливать, лучше конечно первый вариант.
> Ну я и использую $get = $request->query->all();
> Просто переменную так назвал, чтобы было ясно к чему она
А лучше сделать переменную $query = $request->query. Ты взял и заменил объект ParameterBag с кучей полезных методов на убогий массив. Какая от этого выгода? Ты старым добрым массиво ориентироанным программированием хочешь заняться? Не надо. Открой лучше документацию и изучи объект query. Не надо в симфони возвращаться к старым привычкам и $_GET.
> но у меня же правильно
> namespace test\FilterBundle\Controller;
Нет, неправильно. В PSR-4 по моему написано что имена неймспейсов пишутся с большой буквы. Ну и смотри есть еще эту статью:
> http://symfony.com/doc/current/best_practices/creating-the-project.html
> Best Practice
> Create only one bundle called AppBundle for your application logic
> There is no need to prefix the AppBundle with your own vendor (e.g. AcmeAppBundle), because this application bundle is never going to be shared.
То есть рекомендут сделать просто namespace AppBundle. Заметь что там же дана рекомендуемая структура папок.
То что я писал выше про namespace Anon\Bundle\AnonBundle это относится к reusable bundles, то есть бандлы которые ты выпускаешь как библиотеки котрые можно применять на других сайтах, это описано тут:
http://symfony.com/doc/current/cookbook/bundles/best_practices.html
http://symfony.com/doc/current/bundles/SensioGeneratorBundle/commands/generate_bundle.html
То есть я немного неправильно насоветовал, но ты сделал еще непраильнее. Думаю стоит придерживаться рекомендации из официального мануала.
> Я тоже так думал, но почему-то не работает как следует. Уйму времени убил в попытках.
Сделай var_dump($get) и сдампь сгенерированный запрос через echo $qb->getDql() по моему. Надо искать причину ошибки а не уродовать код из-за того что ты что-то не знаешь.
> Та то я всё время дампы просматривал, пока делал.
var_dump проще поставить в контроллере.
> Вне Москвы можно сказать вообще жизни нет
Ну, у нас вообще-то еще северная столица есть. Зарплаты там может чуть поменьше, но я бы не сказал что жизни нет.
> зарплаты почти такие же как в ДС, а жить дешевле.
Не уверен если речь об IT сфере.
>>486751
думаю, разработчики нужны, ну и опытный разработчик легко разберется в других языках если надо.
>>486759
С индусами нет конкуренции, есть заказчики которым нужен индус/пакистанец/филиппинец (они честно пишут: please do not bid more than $2) и есть заказчики которым нужен нормальный разработчик.
>>486823
> и знают общие методики, подходы, или как это называется.
думаю да
> Я не понимаю, что подразумевают под "каждым типом пользовательского запроса".
Имеется в виду для каждого раздела сайта. Один раздел сайта = 1 контроллер обычно. То есть если у тебя есть раздел новостей, к нему делаешь контроллер новостей с действиями «посмотреть список новостей», «посмотреть новость».
> От каких "требований" зависит классификация этих запросов?
От требований заказчика. Какие он разделы на сайте захочет сделать, такие и надо делать.
> В общем случае, если класс модели используется пользователем, должен существовать соответствующий класс контроллера.
Это не очень правильно. Контроллер соответствует разделу на сайте, а модель сущности в базе данных и они не всегда соотносятся один к одному.
> Как мне понять, что класс модели используется пользователем?
Имеется в виду косвенно используется, например если у тебя есть модель новостей то скорее всего понадобится и раздел новостей и контроллер для их отображения (хотя может ты их просто сбоку выводишь на других страницах и тогда отдельный контроллер не нужен).
> то здесь имеется ввиду что нужно создавать контроллер для каждой модели active record?
Имеется в виду что если есть модель AR и сущность в базе, то скорее всего понадобится и контроллер для ее вывода но не обязательно.
Согласен что написано плохо. Вот еще моя мини-паста про MVC:
------------
Подход MVC заключается в том, что мы разбиваем приложение на 3 слабо связанных части: Модель (Model), Представление (View) и Контроллер (Controller).
Модель хранит и обрабатывает данные приложения, не взаимодействуя с внешним миром. Например, сохранение информации в БД, проверка правильности введенных данных — это задача Модели, но вывод информации — нет. Модель не должна обращаться к внешним переменным вроде $_GET/$_POST/$_SESSION/$_COOKIE и не должна ничего выводить.
Представление отображает данные. Оно не должно обращаться к внешним переменным или к базе данных, его задача просто выводить те данные, которые ему передал контроллер. Представление скорее всего будет содержать только шаблоны.
Контроллер отвечает за взаимодействие с внешним миром (пользователем) и управление всем процессом. Обычно контроллер разбирает параметры запроса из $_POST/$_GET, обращается к модели, чтобы получить какие-то данные или сделать какое-то действие, и в конце вызывает Представление, чтобы отобразить результат.
Если ты будешь искать в интернете информацию о MVC, учти что этот подход изначально придуман в 80-е годы для десктопных приложений (с окошечками и кнопочками), а не веб-приложений и «MVC для десктопа» чуть-чуть отличается от «MVC для веба», так как десктопные приложения в отличие от PHP-скрипта, не завершаются после вывода информации на экран, а продолжают работать. Но общие принципы те же.
Если следовать MVC, разделяя код на части, то он будет проще и надежнее.
> Вне Москвы можно сказать вообще жизни нет
Ну, у нас вообще-то еще северная столица есть. Зарплаты там может чуть поменьше, но я бы не сказал что жизни нет.
> зарплаты почти такие же как в ДС, а жить дешевле.
Не уверен если речь об IT сфере.
>>486751
думаю, разработчики нужны, ну и опытный разработчик легко разберется в других языках если надо.
>>486759
С индусами нет конкуренции, есть заказчики которым нужен индус/пакистанец/филиппинец (они честно пишут: please do not bid more than $2) и есть заказчики которым нужен нормальный разработчик.
>>486823
> и знают общие методики, подходы, или как это называется.
думаю да
> Я не понимаю, что подразумевают под "каждым типом пользовательского запроса".
Имеется в виду для каждого раздела сайта. Один раздел сайта = 1 контроллер обычно. То есть если у тебя есть раздел новостей, к нему делаешь контроллер новостей с действиями «посмотреть список новостей», «посмотреть новость».
> От каких "требований" зависит классификация этих запросов?
От требований заказчика. Какие он разделы на сайте захочет сделать, такие и надо делать.
> В общем случае, если класс модели используется пользователем, должен существовать соответствующий класс контроллера.
Это не очень правильно. Контроллер соответствует разделу на сайте, а модель сущности в базе данных и они не всегда соотносятся один к одному.
> Как мне понять, что класс модели используется пользователем?
Имеется в виду косвенно используется, например если у тебя есть модель новостей то скорее всего понадобится и раздел новостей и контроллер для их отображения (хотя может ты их просто сбоку выводишь на других страницах и тогда отдельный контроллер не нужен).
> то здесь имеется ввиду что нужно создавать контроллер для каждой модели active record?
Имеется в виду что если есть модель AR и сущность в базе, то скорее всего понадобится и контроллер для ее вывода но не обязательно.
Согласен что написано плохо. Вот еще моя мини-паста про MVC:
------------
Подход MVC заключается в том, что мы разбиваем приложение на 3 слабо связанных части: Модель (Model), Представление (View) и Контроллер (Controller).
Модель хранит и обрабатывает данные приложения, не взаимодействуя с внешним миром. Например, сохранение информации в БД, проверка правильности введенных данных — это задача Модели, но вывод информации — нет. Модель не должна обращаться к внешним переменным вроде $_GET/$_POST/$_SESSION/$_COOKIE и не должна ничего выводить.
Представление отображает данные. Оно не должно обращаться к внешним переменным или к базе данных, его задача просто выводить те данные, которые ему передал контроллер. Представление скорее всего будет содержать только шаблоны.
Контроллер отвечает за взаимодействие с внешним миром (пользователем) и управление всем процессом. Обычно контроллер разбирает параметры запроса из $_POST/$_GET, обращается к модели, чтобы получить какие-то данные или сделать какое-то действие, и в конце вызывает Представление, чтобы отобразить результат.
Если ты будешь искать в интернете информацию о MVC, учти что этот подход изначально придуман в 80-е годы для десктопных приложений (с окошечками и кнопочками), а не веб-приложений и «MVC для десктопа» чуть-чуть отличается от «MVC для веба», так как десктопные приложения в отличие от PHP-скрипта, не завершаются после вывода информации на экран, а продолжают работать. Но общие принципы те же.
Если следовать MVC, разделяя код на части, то он будет проще и надежнее.
> для каждой AR-модели должен быть контроллер
Часто это так, но не всегда.
> Что вообще может быть моделью?
Модель это класс хранящий информацию о какой-то сущности: новость, пост, коммменатий, пользователь. В Yii (и в веб приложениях вообще) как правило модель соответсвтует таблице в базе данных (но это не всегда так: например если ты работаешь с видео через API ютуба у тебя может быть модель видео для которой нет таблиц в базе и не используется AR). Модель формы это класс описывающий форму и он не всегда соответсвует напрямую сущности в БД. Например форма логина имеет некоторое отношение к таблице пользователей, но оно косвенное, так как в базе полей гораздо больше.
В MVC моделью называют все классы которые отвечают за хранение и обработку данных, вместе.
>>486826
> Как вообще понимать "модель"?
Там есть 2 значения: модель как класс-сущность и модель как одна из трех компонент MVC. Наверно ты из-за этого путаешься.
> Но моделей много, а не одна.
Одна модель это наверно когда говорят про компоненту MVC.
> Как мне знать, для каких объектов создавать модель?
Для тех объектов с которыми работает твое приложение. Если ты делаешь сайт с видео то сделай модели Видео, Пользователь, Комментарий.
> Кажется, для каждой таблицы бд, с которой будут выполняться crud-операции?
Обычно да, каждая модель имеет под собой таблицу в БД где ее можно сохранить. Но это не обязано быть всегда так, я привел выше пример с API. Также могут быть какие-то временные короткоживущие модели которые не сохраняются в базу.
Я не про это писал. Я писал что лучше использовать <?=
А если тебе не повезло и надо деплоить на древний PHP то у тебя есть куча вариантов:
— включить настройку в php.ini или htaccess
— пройтись поиском/заменой
Но глупо писать более длиннуюю конструкцию только потому что где-то кому-то не повезло с версией PHP. Мы все же надеемся что анон попадет в нормальную компанию использующую новую версию.
Что-то тебе знатно попец порвало, ОП. Давай мир: я эфир донюхал, и стал более мирным.
Кстати, от злости ты так и не заметил, что про позицию "константы" на первом месте писал не по причине пост/пре-инкрементного срача, а лишь как о хорошой практике. Которой, к сожалению, никто не следует.
Ну а если пишется "движок", для работы на любых самых сраных shared-хостингах? Облегчение жизни тупых юзверей напрямую связана с прибылью компании.
Хотя, времена уже не те. Уже и 5.3 вымер, пока я за диваном дрочил. Эх...
> и имеют свойство пухнуть, аки жирна баба. Не люблю я в них копаться, в общем.
На линуксе достаточно написать tail -f /var/log/message чтобы они сами выводились в консоли по мере поплолнения. Ну и там же работает logrotate который их архивирует и удаляет по расписанию.
Но суть не в этом. Суть в том что у тебя то ли отключен вывод ошибок то ли ты их не смотришь и из-за этого не увидел первоприину ошибки и потерял какое-то время. Потому я и советую либо включить вывод ошибок в php.ini либо смотреть логи.
Твой подход плохой так как при выгрузке на продакшен тебе надо как-то руками отключать этот код и вывод ошибок. Поставить настройку в php.ini гораздо проще.
> E_ALL | E_STRICT
Вот обработка ошибок в PHP это конечно ужасно. Я помню где-то еще видел константу E_REALLY_ALL, а сам ставлю обычно -1 чтобы уж точно все выводилось. Ну и обычно я в начало скрипта копипастю код который превращает все ошибки в исключения отсюда: http://php.net/manual/ru/class.errorexception.php (в нормальных фреймворках сделано так же)
Контроллер обычно отвечает за один раздел на сайте.
>>487044
> \tif($creditBalance > 0)
Тут нужны фигурные скобки {}
> \techo "{$month} месяц спустя: долг = {$creditBalance} руб, выплачено всего {$paymentTotal} руб. \n";
Это копипаста, попробуй убрать повторы.
> $creditBalance = abs($creditBalance);
> $paymentTotal = $paymentTotal - $creditBalance;
Это по моему выглядит как костыль и сложно понять, правльно или нет. Я думаю, надо сделать алгоритм проще. примерно так:
- прибавляем проценты и комиссию к остатку долга
- если остаток маленький, выплачиваем сколько осталось и уходим
- иначе платим 5000
«Платим» здесь значит уменьшаем долг и увеличиваем общую сумму выплаченного.
Надо смотреть чему равен остаток долга и обрабатывать ситуацию, когда она маленький, а не выплачивать сразу же 5000 вот в этом месте: ... + $servicePayment - $monthlyPayment;
>>487054
> комментарии на русском для меня - детектор быдлокода
Не согласен. Анон может не знать английского и в проектах только с русскоязычными разработчиками, которые не планируется выыкладывать на гитхаб, использоать русский вполне норм.
> и в цикле for лучше его использовать перед переменной (тем более, у тебя все условия для этого)
Почему лучше? Не понимаю.
> уже определись, переносить на новую строку фигурную скобку после конструкции или нет
Не переносить для if/for так как это написано в PSR.
> для переноса строки есть такая константа - PHP_EOL. Да, и ты не допускаешь, что код будет исполняться в браузере?
PHP_EOL только заменяет \n на \r\n под WIndows и в браузере никак не поможет. В браузере поможет Content-Type: text/plain; charset=utf-8
И по моему \n писать банально удобнее и переводит строку он на любой платформе (Win, Linux, Mac). Виндовый блокнот может его не поддерживать, ну и фиг с ним.
> зачем тебе "error_reporting(-1);"?
Дефолтные настройки PHP не показывают часть ошибок например нотисы. С обработкой ошибок в PHP по умолчанию все плохо.
Контроллер обычно отвечает за один раздел на сайте.
>>487044
> \tif($creditBalance > 0)
Тут нужны фигурные скобки {}
> \techo "{$month} месяц спустя: долг = {$creditBalance} руб, выплачено всего {$paymentTotal} руб. \n";
Это копипаста, попробуй убрать повторы.
> $creditBalance = abs($creditBalance);
> $paymentTotal = $paymentTotal - $creditBalance;
Это по моему выглядит как костыль и сложно понять, правльно или нет. Я думаю, надо сделать алгоритм проще. примерно так:
- прибавляем проценты и комиссию к остатку долга
- если остаток маленький, выплачиваем сколько осталось и уходим
- иначе платим 5000
«Платим» здесь значит уменьшаем долг и увеличиваем общую сумму выплаченного.
Надо смотреть чему равен остаток долга и обрабатывать ситуацию, когда она маленький, а не выплачивать сразу же 5000 вот в этом месте: ... + $servicePayment - $monthlyPayment;
>>487054
> комментарии на русском для меня - детектор быдлокода
Не согласен. Анон может не знать английского и в проектах только с русскоязычными разработчиками, которые не планируется выыкладывать на гитхаб, использоать русский вполне норм.
> и в цикле for лучше его использовать перед переменной (тем более, у тебя все условия для этого)
Почему лучше? Не понимаю.
> уже определись, переносить на новую строку фигурную скобку после конструкции или нет
Не переносить для if/for так как это написано в PSR.
> для переноса строки есть такая константа - PHP_EOL. Да, и ты не допускаешь, что код будет исполняться в браузере?
PHP_EOL только заменяет \n на \r\n под WIndows и в браузере никак не поможет. В браузере поможет Content-Type: text/plain; charset=utf-8
И по моему \n писать банально удобнее и переводит строку он на любой платформе (Win, Linux, Mac). Виндовый блокнот может его не поддерживать, ну и фиг с ним.
> зачем тебе "error_reporting(-1);"?
Дефолтные настройки PHP не показывают часть ошибок например нотисы. С обработкой ошибок в PHP по умолчанию все плохо.
Я прокомментировал выше некотоыре замечания анона.
> error_reporting(-1)
по умолчанию PHP не выводит некоторые предупреждения (E_NOTICE, E_STRICT, E_DEPRECATED) и эта строчка включает их вывод.
> ++$mounth так что ли?
По моему разницы нет.
> http://ideone.com/bcjEKX Проверь?
у меня выводит белую страницу
>>487065
> вместо цикла for логичнее использовать while или do ... while
Это он еще не проходил
>>487068
for тоже подойдет
> если бы ты в этом моем задании отступы поправил, что бы наглядный пример у меня был, я путаюсь в них еще.
Посмотри на примеры приавльно оформленного кода тут:
http://www.php-fig.org/psr/psr-2/ru/
http://www.php-fig.org/psr/psr-1/ru/
Почитай пост: >>479599
Ты можешь просто код через phpformatter пропустить.
Я прокомментировал выше некотоыре замечания анона.
> error_reporting(-1)
по умолчанию PHP не выводит некоторые предупреждения (E_NOTICE, E_STRICT, E_DEPRECATED) и эта строчка включает их вывод.
> ++$mounth так что ли?
По моему разницы нет.
> http://ideone.com/bcjEKX Проверь?
у меня выводит белую страницу
>>487065
> вместо цикла for логичнее использовать while или do ... while
Это он еще не проходил
>>487068
for тоже подойдет
> если бы ты в этом моем задании отступы поправил, что бы наглядный пример у меня был, я путаюсь в них еще.
Посмотри на примеры приавльно оформленного кода тут:
http://www.php-fig.org/psr/psr-2/ru/
http://www.php-fig.org/psr/psr-1/ru/
Почитай пост: >>479599
Ты можешь просто код через phpformatter пропустить.
>PHP_EOL только заменяет \n на \r\n под WIndows и в браузере никак не поможет
Ты невнимательно читаешь. Вопрос про браузер там тоже был. Да и, на мой взгляд, использование нативных констант вместо собственнных предположений, - путь более предпочтительный.
Я думаю что для значений лучше использовать переменные, а не константы. Мы ведь можем поменять условия задачи, а константы это оыбчно что-то неизменное.
> $capital ×= 1.1;
1.1 лучше поместить в переменную чтобы было понятное название, а не магическое число.
> echo 'Age: ' . ($age = $years + AGE_CURRENT) . PHP_EOL;
Это лучше сделать в виде 2 отдельных инструкций имхо. Ты добавляешь элемент неожиданности в код так как у тебя конструкция echo внезапно меняет значения переменных.
>>487079
Код нормальный.
>>487083
> Хорошо хоть прочитал и ничего не запомнил.
«ничего не понял» ты наверно хотел сказать?
>>487113
Ок, по моему использовать пре- или пост- инкремент в цикле — нет разницы, дело вкуса. Но про оптимизации думаю упоминать не стоит, тем более объясняя начинающему, это только его с толку собьет.
> что про позицию "константы" на первом месте писал не по причине пост/пре-инкрементного срача, а лишь как о хорошой практике. Которой, к сожалению, никто не следует.
ну тут есть еще момент что читается $a == 6 лучше чем 6 == $a по моему субъективному мнению. Мы же говорим «если a равно шести», а не «если шесть равно a».
>>487115
Если ты пишешь для 5.3 (на котором ты не можешь менять настройки) то это другой вопрос, но у анона который делает сайт наверно такого требования не было. Вообще, от таких хостингов надо бежать, какая выгода тебе тратить время на исправление их косяков?
Я думаю что для значений лучше использовать переменные, а не константы. Мы ведь можем поменять условия задачи, а константы это оыбчно что-то неизменное.
> $capital ×= 1.1;
1.1 лучше поместить в переменную чтобы было понятное название, а не магическое число.
> echo 'Age: ' . ($age = $years + AGE_CURRENT) . PHP_EOL;
Это лучше сделать в виде 2 отдельных инструкций имхо. Ты добавляешь элемент неожиданности в код так как у тебя конструкция echo внезапно меняет значения переменных.
>>487079
Код нормальный.
>>487083
> Хорошо хоть прочитал и ничего не запомнил.
«ничего не понял» ты наверно хотел сказать?
>>487113
Ок, по моему использовать пре- или пост- инкремент в цикле — нет разницы, дело вкуса. Но про оптимизации думаю упоминать не стоит, тем более объясняя начинающему, это только его с толку собьет.
> что про позицию "константы" на первом месте писал не по причине пост/пре-инкрементного срача, а лишь как о хорошой практике. Которой, к сожалению, никто не следует.
ну тут есть еще момент что читается $a == 6 лучше чем 6 == $a по моему субъективному мнению. Мы же говорим «если a равно шести», а не «если шесть равно a».
>>487115
Если ты пишешь для 5.3 (на котором ты не можешь менять настройки) то это другой вопрос, но у анона который делает сайт наверно такого требования не было. Вообще, от таких хостингов надо бежать, какая выгода тебе тратить время на исправление их косяков?
>Анон может не знать английского
Теперь пИздите меня ссаными тапками, но программист, не знающий элементарного английского, - это нонсенс.
И второй момент. Представь, что тебе попал китайский код от "программиста", который знал только китайский. Давайте же простим этого уёбка, оставивишего комментарии иероглифами.
> на мой взгляд, использование нативных констант вместо собственнных предположений, - путь более предпочтительный.
На мой взгляд нет, так как читается хуже и пишется дольше. Я считаю что разницу в переводах строк должен обрабатывать драйвер консоли (он это делает), а разницу в слешах в именах файлов слой работы с файлами (он это делает в windows).
Ты написал выше:
> для переноса строки есть такая константа - PHP_EOL. Да, и ты не допускаешь, что код будет исполняться в браузере?
Как EOL поможет в браузере?
Ну и наше задание не требует выполнять код в браузере, а только в консоли. Зачем нам может понадобиться выполнять консольный скрипт в браузере? Мы и HTML не используем.
> использование нативных констант вместо собственнных предположений
Давай посмотрим с другой стороны: по какой причине я должен обозначать перевод строки по-разному на разных платформах? Прчему я не могу писать \n? От разного формата перевода строк только проблемы, например файл созданный на одной платформе не прочитается корректно на другой.
На практике единственная разница в том что убогие редакторы вроде notepad не увидят переводы строк. Ну это имхо их проблема, тот же Sublime все прекрасно понимает.
Против константы:
— хуже читаемость
— дольше писать
— несовместимые файлы созданные на разных машинах
За константу:
— блокнот отображает файлы корректно
Гм, так ли нам важна поддержка блокнота?
> И второй момент. Представь, что тебе попал китайский код от "программиста", который знал только китайский
Я специально написал: если разработики русскоязычные и выкладывать код на гитхаб не планируется. Как мне попадет китайский код? Никогда не попадал.
Ну и смотри, у нас кроме кода есть еще HTML-шаблоны. В них тоже писать по-английски? Что ты будешь делать если тебе попадет HTML-шаблон от китайского сайта?
Что я хочу сказать:
— неопраданно дорого целиком сделать русскоязычный сайт на английском, включая шаблоны
— следовательно русские комментарии это ок в некоторых ситуациях
>Если ты пишешь для 5.3
Идея - в написании движка с минимальными системными требованиями. Мне довелось поработать с такими, и позиция руководства всегда - "чтобы работал на любом говне, исключить малейший элемент неожиданности". Так что да, min.sys.requirements в виде PHP 5.3 с отключеннной поддержкой короткого тега - вполне. Ну а хули - позднее статическое связывание поддерживает, а большего программистам выбить не удалось.
Всё, в основном, из-за того, что если какой-нибудь косорукий уебан с жопохостингом оставит на форуме негативный отзыв, - то будет потеря пользователей и прибыли. Всякое бывает. Так что у меня такая "личная" нелюбовь к частным (лишь возможным, а не всегда доступным) решениям.
>Ну и смотри, у нас кроме кода есть еще HTML-шаблоны. В них тоже писать по-английски? Что ты будешь делать если тебе попадет HTML-шаблон от китайского сайта?
А вот это уже обрабатывается другими средствами. Языковыми метками или gettext-ом, например.
Ну мы больше готовим анонов к светлому будущем в стране единорогов и фей.
>>487134
> А вот это уже обрабатывается другими средствами. Языковыми метками или gettext-ом, например.
Я же написал выше: если сайт рассчитан только на Россию то делать локализацию ради одного языка неоправданно дорого. Значит надо делать шаблоны по русски. А значит и комментарии можно.
Ну посмотри сам: программа анона выводит ответ на русском языке. От того что ты комментарии поменяешь на английский, китайцу она понятнее не станет.
Это копия, сохраненная 14 июня 2015 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.