Вы видите копию треда, сохраненную 1 октября 2015 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
Почему PHP? Потому что фейсбук и википедия на нем написаны, и вакансий море, и учить легко.
Это тред для начинающих. Не написал за свою жизнь ни одной программы? Ты наш человек.
Устанавливать пока что ничего не требуется, разве что редактор кода вроде Sublime Text 3, Notepad++, Netbeans PHP или PhpStorm (с ним будет удобнее).
Предыдущий тред был тут: >>531765 (OP)
Что самое главное для программиста? Умение аккуратно оформлять код (читай второй пост).
Правила: ведем себя воспитанно, помогаем новичкам, постим ссылки на решения задачек, ОП их проверяет и дает советы и замечания. ОП отвечает даже на самые нубские вопросы. ОП заходит где-то раз в день-два, не жди его, решай задачки дальше.
У нас есть уроки по основам 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, то рассказать об этом стоит в каком-нибудь другом треде.
Ах да. Если тебе кажется, что что-то в учебнике или задачах можно сделать лучше — пиши, обратная связь всегда очень полезна.
Если тебе лень выравнивать код руками, закачай его на 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: >>535405
проверить макет http://maketi.esy.es/
превьюшки (пока не готовы вроде) https://github.com/MindiMakridi/RESTFUL
http://help.ubuntu.ru/wiki/%D1%80%D0%B0%D0%B7%D0%B4%D0%B5%D0%BB%D1%8B_%D0%B8_%D1%84%D0%B0%D0%B9%D0%BB%D0%BE%D0%B2%D1%8B%D0%B5_%D1%81%D0%B8%D1%81%D1%82%D0%B5%D0%BC%D1%8B_linux#структура_файловой_системы (рус)
https://ru.wikipedia.org/wiki/FHS
http://www.pathname.com/fhs/pub/fhs-2.3.html (англ подробно)
http://www.opennet.ru/docs/RUS/file-sys/
https://help.ubuntu.com/community/LinuxLogFiles
А нет, не забыл, извини.
>думаю, найденных ошибок и замечаний тебе вполне хватит для начала
Еще бы. Только я почувствую, что начинает получаться, как ты спускаешь на землю.
Я наверное лучше продолжу работу над заданиями из треда в фоновом режиме, а параллельно буду учить фреймворки. Потому что с такими темпами можно возиться годами над учебными задачами. Устроюсь на самую грязную работу, а в свободное время буду повышать мастерство. Иначе я так с голода помру, пока мой код достигнет "хорошего" уровня.
>Если ты делаешь древовидные комменты, то в таблице стоит сделать ссылку на родительский комментарий как минимум.
Не знал, что в таблице можно делать внешний ключ на саму себя. Хм, проверил, работает. И на NULL в parent_id не реагирует, я думал что внешний ключ обязан указывать на уникальное значение. Наверное, это какой-нибудь паттерн, когда внешний ключ указывает на колонку в той же таблице? На схеме, которую генерирует workbench, подобная связь обозначена кружком. Где об этом можно почитать доступным языком?
Хорошо, исправил (внесением изменений в дамп базы). Но я слышал, что так делать некошерно, и лучше использовать миграции.
Из внятных мануалов нашел http://www.elisdn.ru/blog/52/db-migrations-in-frameworks
Пробегись по статье, если хочешь и как будет время, и прокомментируй. Вдруг там неправильные или устаревшие подходы к этому вопросу, как обычно.
>подобная связь обозначена кружком
Черточкой она обозначается у тебя, кружок показывает необязательность связи. Гугли нотацию Crow's Foot
>while ($row = $result->fetch_assoc())
Какое условие у этого цикла? Если fetch_assoc() возвращает false прекратить?
1) базы данных
2) социальные и профессиональные проблемы в информатике
Мне нужно это выучить и сдать.
Посоветуй книгу, чтобы там это было и желательно это было связано с вебом или конкретно пыхой. Если нет такой, то просто тогда посоветуй книгу, чтобы там это было.
Если сказали, значит надо сдать. Хотя это не критично, надеюсь можно будет обойтись знанием статьи на хабре.
Вообще не знаю как академ разницы сдаются.
Хочешь кодить - умей гуглить
http://php.net/manual/en/mysqli-result.fetch-assoc.php
Returns an associative array that corresponds to the fetched row or NULL if there are no more rows.
NULL в bolean будет false.
Спаасибо
Бот на C# каком-нибудь или Java, юзает апи внутриигровой для приема-передачи вещей и бабла, потом коннектится к PHP скрипту, который какой-нибудь SOAP, XML-RPC или просто по POST json в body принимает. Задача бота - принимать шмот и бабки, слать в скрипт инфу о приемке, принимать инфу о совершенном обмене с сайта, на сайте же все через обычные базы данных и транзакции работает. Писал подобного бота, только не для CS, а для другой игры, обычно готовую библиотеку уже можно нарыть. Если библиотеки нет, то включаешь сниффер и вручную выискивать пакеты, какие от клиента идут, что может быть сложнее, особенно если шифрования всякие стоят. В самых запущенных случаях напрямую к игровому клиенту подключаются через hookи или чтение/запись памяти.
Разбиваем текст на части по четыре слова, берём первый четыре слова, это будет первый элемент массива, потом отнимаем первое слово и добавляем в конец следующее слово это будет следующим элемент массива и так делаем со всем текстом.
Делаем запрос при помощи средств simple_html_dom.php к гуглу, для каждого элемента массива, после каждого такого запроса, начинаем парсить полученный результат, так находим краткое описание сайта:
$html->find('.g div.s span.st');
Далее запускаем цикл foreach (вводим счётчик например $i) в котором, просматриваем такое описание для каждого запроса из 10. После чего начинаем искать в нём наш текущий запрос(элемент массива) при помощи регулярных выражений, если находим полное совпадение, то учитывая текущую итерацию (что бы узнать порядковый номер этого краткого описания) начинаем парсить урл данного сайта, при помощи такой команды:
$urls = $html->find('.g div.s div.kv cite', $i);
Теперь мы можем получить ссылку сайта где нашли совпадение, а также закинуть например в массив сам поисковой запрос на котором было это совпадение, перекрасив для наглядности его в красный цвет. Теперь осталось при помощи регулярок вытащить из массива запросы которые не уникальны и вставить их в первоначальный текст, они будут выделены красным цветом. Под текстом можно вывести урлы тех сайтов на которых было найдено совпадение. Уникальность можно подсчитать отношением красных слов к общему количеству слов и умножить на 100%.
Но у меня возникают некоторые проблемы:
1. Когда текст больше 500 символов то скрипт не успевает всё обработать.
2. Не уверен что данный алгоритм правильный, все подобные скрипты дают разные результаты
Где можно найти алгоритм проверки текста на уникальность, или этого нигде нет и надо придумывать свой?
http://ideone.com/fTk0iZ
Слушай, я не знаю, зачем ты это писал и логику, но проверить палиндром ли, можно проще гораздо. Просто циклом иди по длине строки и сравнивай с противоположных концов буквы.
Кстати, а где ошибка-то?
http://628808.plitka12.web.hosting-test.net/bank/
https://github.com/hiigara123/ATM-machine
Класс лежит в /inc/Computer.php
Визуализация показывает, какие варианты перебирались. Либо все возможные, либо до момента успеха.
Правильное решение подразумевает что ты понимаешь и можешь объяснить каждую строчку. Если ты не понимаешь, то твой код слишком запутанный и требует упрощения. Если сам автор не понимает код, как его поймет другой человек?
Я гляну код позже и скажу что в нем поменять. Как минимум прооблема что ты смешал в одном файле обработку входных данных (POST), вывод данных в html и саму логику алогритма. Лучше бы это было в разных местах. Ну и конечно класс там больше мешает, это не ООП а просто процедурный код засунут в класс.
Я не знаю что там человек делал но на запись MySQL у него работает куда быстрее и стабильнее.
Темы которые тебе дали не имеют ни к PHP ни к веб разработке никакого отношения. Базы данных конечно используются, но мы же понимаем что у вас будут спрашивать определения и реляционную теорию а не практические вещи.
Следовательно к нашему треду это все не имеет отношения.
По базам данных могу посоветовать поискать вузовский учебник. Погугли по какой книге в нормальных вузах эти темы изучают, я сам не знаю.
>>536905
Никак не делается. Ты же не дизайнер чтобы тебе портфолио делать.
Я одно время выкладывал небольшие аккуратные скриншоты кода в порфтолио на фриланс сайте. Понятно что смысла от них ноль, так как для заказчика весь код на одно лицо, но хотя бы видно что человек над чем-то работал.
>>536969
Если возвращает лживое (то есть приводящееся к false) значение. Эти значения есть в мануале: http://php.net/manual/ru/language.types.boolean.php
> А чтобы устроиться на фирму, даже символически, за 8-10к работать, нужен год ежедневного 4-6 часового самообучения.
замкнутый круг
Во-первых, это лукавство, за год обучения по 6 часов можно изучить очень много. Можно пройти весь наш курс со всеми задачами и у вас еще время останется.
Во-вторых, а что, на другие профессии надо учиться меньше? Допустим ты хочешь стать рабочим на Уралвагонзаводе, что тебя возьмут сразу со школы? Нет, не возьмут, отправят в техникум или училище а это минимум года 2-3. Для неквалифиированной работы. Почему для программирования надо меньше изучать?
Ну и наконец, изучение программирование это не то же самое что изучение особенностей токарного станка. Ты можешь спокойно им заниматься дома, в конфортных условиях, бесплатно. Никто тебе не запрещает например после или вместо школьных уроков изучать его. Я знаю людей которые уже после школы работали по этой специальности. Возможно ли такое в других профессиях? Конечно нет.
И даже в случае с выбором вакансий, в программировании обычно все проще. В то время как завод у вас в городе всего один, и тот может быть не в лучшем состоянии, мелких IT компаний скорее всего гораздо больше. Хотя для меня это не проблема, в нашем городе чего-чего, а заводов хоть отбавляй, еще с царских времен стоят.
Ну и насчет компаний и собеседований - они хотят брать тех кто с первого дня будет делать полезную работу и приносить прибыль. Зачем платить человеку который ничего полезного не делает?
Потому анон, прекращай ныть. Не нравится программирование, у тебя всегда есть на выбор другие профессии. Может быть их получать тебе понравится больше.
ps. то за идиот придумал скрывать форму ответа если попасть по ctrl и пробелу одновременно? постоянно попадаю.
>>536988
Документацию читать не пробовал? Если там ничего не понятно, то скорее всего тебе надо изучить еще другие темы например HTTP, JSON и что там используется.
Кстати, а если попал на подобное, как защититься от взлома компьютера?
>>536831
>Заодно пусть этот метод передает животному ссылку на $world, и ее не надо будет передавать в каждый метод. Ее проще хранить в поле у животного.
>поле
В смысле в свойстве?
>https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/Animal.php#L28
>public function overviewWorld(World $world) {
>Это должно быть где-то в World, например там может быть метод «получить карту в радиусе N».Но зачем нам этот метод? Зачем нам массив сложной непонятной структуры, если мы можем просто сделать у World метод «получить список животных в определенном радиусе»?
Потому что мир не может думать за место мышек. У них должно быть свое представление о мире. Понимаю что для изучения программирования такой подход не очень подходит, но пусть будет все реалистично. Это же не очень критично будет?
>https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/Animal.php#L44
>public function searchTheAnimal(World $world, Animal $animal) {
>Назначение метода непонятно. Зачем искать животное в массиве если его координаты хранятся в свойствах x и y?
Этот метод предназначен чтобы найти чтобы найти других животных в обозримой видимости.
>protected $map = array();
>В чем смысл этого поля? зачем хранить огромный массив клеток? Ведь теперь мы должны как-то остлеживать что если у животного поменялись координаты, надо перенести его из одной клеточки в другую. Тут ошибку сделать проще простого. По моему если убрать этот массив, все сразу станет проще.
Мне просто сложно представить этот мир. В принципе, я с тобой полностью согласен. Я подумаю над этим.
>https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/World.php#L35
>public function moveAnimal(array $from, array $to) {
>Зачем тут массивы? Почему не $x1, $y1,$x2, $y2?
А так понятно будет?
По моему так удобней - сразу видно какие координаты что значат. Почему так не правильно?
>Также, чем getCoordinate() удобнее чем getX() и getY()? По моему ты тут вводишь лишний массив без которого все только проще.
Ну использование одного метода избавляет от лишней писанины, плюс я не уверен что когда-нибудь потребуется отдельно X и отдельно Y.
>https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/World.php#L43
>$to['y'] = $to['y'] - ($to['y'] - $this->m);
>Что это значит? По моему, если сократить то получается $to['y'] = $this->m;
>Но дело даже не в этом. Смотри, пользователь тебя просит поставить животное на конкретную клетку. Почему ты пытаешься что-то добавлять от себя и поставить его на другую клетку? Где тут логика? Если переданы неверные координаты, надо выкидывать исключение чтобы программист разобрался и исправил программу, а не молча подменять числа в надежде что это сработает. А если та клетка занята? А если той клетки тоже нет? Твоя программа вместо того чтобы сразу сказать что в ней ошибка, пытается это скрыть. ты ведь этим только себе жизнь усложняешь, это тебе же дольше эту ошибку искать придется.
Ну суть этого метода заключается в том, что животное может сгенерировать координату которая выходит за пределы карты. Этот метод всего лишь не дает им выйти за пределы карты. Так же я думал еще, с помощью этого метода сделать такую фичу: если животное пытается выйти за пределы карты, то оно ударяется об стенку, получает сотрясение и пропускает один ход о_х
>https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/Cat.php#L21
>Вот тут 8 почти одинаковых скопированных условий. Копипаста это верный путь к ошибкам и опечаткам. Где гарантия что там их нет? Надо заменить копипасту на цикл. Можно сделать либо 2 вложенных цикла (по x и по y), можно сделать массив направлений и сделать цикл по нему.
>Код надо бы переделать на работу с любым количеством котов и мышей. Кстати, алгоритм оценки ходов прост, понятен, легко работает с любым количеством животных.
Мне не понятно как это сделать. Я подумаю над тем что именно мне не понятно, и позже задам вопрос.
>>536831
>Заодно пусть этот метод передает животному ссылку на $world, и ее не надо будет передавать в каждый метод. Ее проще хранить в поле у животного.
>поле
В смысле в свойстве?
>https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/Animal.php#L28
>public function overviewWorld(World $world) {
>Это должно быть где-то в World, например там может быть метод «получить карту в радиусе N».Но зачем нам этот метод? Зачем нам массив сложной непонятной структуры, если мы можем просто сделать у World метод «получить список животных в определенном радиусе»?
Потому что мир не может думать за место мышек. У них должно быть свое представление о мире. Понимаю что для изучения программирования такой подход не очень подходит, но пусть будет все реалистично. Это же не очень критично будет?
>https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/Animal.php#L44
>public function searchTheAnimal(World $world, Animal $animal) {
>Назначение метода непонятно. Зачем искать животное в массиве если его координаты хранятся в свойствах x и y?
Этот метод предназначен чтобы найти чтобы найти других животных в обозримой видимости.
>protected $map = array();
>В чем смысл этого поля? зачем хранить огромный массив клеток? Ведь теперь мы должны как-то остлеживать что если у животного поменялись координаты, надо перенести его из одной клеточки в другую. Тут ошибку сделать проще простого. По моему если убрать этот массив, все сразу станет проще.
Мне просто сложно представить этот мир. В принципе, я с тобой полностью согласен. Я подумаю над этим.
>https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/World.php#L35
>public function moveAnimal(array $from, array $to) {
>Зачем тут массивы? Почему не $x1, $y1,$x2, $y2?
А так понятно будет?
По моему так удобней - сразу видно какие координаты что значат. Почему так не правильно?
>Также, чем getCoordinate() удобнее чем getX() и getY()? По моему ты тут вводишь лишний массив без которого все только проще.
Ну использование одного метода избавляет от лишней писанины, плюс я не уверен что когда-нибудь потребуется отдельно X и отдельно Y.
>https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/World.php#L43
>$to['y'] = $to['y'] - ($to['y'] - $this->m);
>Что это значит? По моему, если сократить то получается $to['y'] = $this->m;
>Но дело даже не в этом. Смотри, пользователь тебя просит поставить животное на конкретную клетку. Почему ты пытаешься что-то добавлять от себя и поставить его на другую клетку? Где тут логика? Если переданы неверные координаты, надо выкидывать исключение чтобы программист разобрался и исправил программу, а не молча подменять числа в надежде что это сработает. А если та клетка занята? А если той клетки тоже нет? Твоя программа вместо того чтобы сразу сказать что в ней ошибка, пытается это скрыть. ты ведь этим только себе жизнь усложняешь, это тебе же дольше эту ошибку искать придется.
Ну суть этого метода заключается в том, что животное может сгенерировать координату которая выходит за пределы карты. Этот метод всего лишь не дает им выйти за пределы карты. Так же я думал еще, с помощью этого метода сделать такую фичу: если животное пытается выйти за пределы карты, то оно ударяется об стенку, получает сотрясение и пропускает один ход о_х
>https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/Cat.php#L21
>Вот тут 8 почти одинаковых скопированных условий. Копипаста это верный путь к ошибкам и опечаткам. Где гарантия что там их нет? Надо заменить копипасту на цикл. Можно сделать либо 2 вложенных цикла (по x и по y), можно сделать массив направлений и сделать цикл по нему.
>Код надо бы переделать на работу с любым количеством котов и мышей. Кстати, алгоритм оценки ходов прост, понятен, легко работает с любым количеством животных.
Мне не понятно как это сделать. Я подумаю над тем что именно мне не понятно, и позже задам вопрос.
С помощью кликджека компьютер не взломают, только доступ к личным данным получить. К вкшечке, например.
Пацантре, вот немного упоролся по ПХП. Начал изучать рекомендованные уроки. Задача 5.2, про вкладчика. ideone выдаёт ошибку и фраза "вкладчик подох" пишется овер 9000 раз. В чем косяк?
<?php
error_reporting (-1);
$balance=10000;
$percent=0.1;
for ($year=1; $balance<1000000; $year++) {
if ($year<20) {
\t$balance=$balance+($balance*$percent);
\techo "После $year лет баланс $balance рублей \n";
}
else {
\techo "Вкладчик подох. \n";
\tbreack;
}
breack;
}
Да, и сразу вопрос. Почему я вставил код, а макаба мои четыре пробела отобразила как "\t"?
break написано с ошибкой
>>537338
Узнают твой id в соцсетях или поставят от твоего имени лайк. Суть кликджекинга в том что на страницу сайта подключается виджет +1 от соцсети, только он делается прозрачным и двигается за мышью. Когда ты кликнешь, ты кликнешь в виджет и если ты залогинен в соцсети то поставшь лайк по которому тебя (зная время и к какому посту поставлен лайк) легко вычислить тебя.
Но пароль например таким образом не украсть, если конечно на самой соцсети нет уязвимости.
Есть расширение для файерфокса, которое ловит попытки клинкуть по прозрачному ифрейму, по моему NoScript.
У меня например на недоверенных сайтах вообще JS отключен.
>>537323
Компьютер так не взломать.
>>537151
Узнать можно с помощью кликджекинга или найдя уязвимость в соцсети.
Вот например на яндексе есть JS скрипт который отдает мыло пользователя. Но хитрюги проверяют реферрер и отдают данные только для яндексовских проектов. Если найти проект где можно как-то с помощью XSS или может редиректов подключить этот скрипт, может быть возможно получить эту информацию и на своем сайте. Подробности я пожалуй писать не буду, кто понимает тот и сам найдет.
>>537010
Никак. Используй кодировку utf8 без ВOM, а с BOM PHP нормально не работает.
Теоретически там можно покрутить настройки апача или нгинкса но я думаю что правильнее убрать BOM.
break написано с ошибкой
>>537338
Узнают твой id в соцсетях или поставят от твоего имени лайк. Суть кликджекинга в том что на страницу сайта подключается виджет +1 от соцсети, только он делается прозрачным и двигается за мышью. Когда ты кликнешь, ты кликнешь в виджет и если ты залогинен в соцсети то поставшь лайк по которому тебя (зная время и к какому посту поставлен лайк) легко вычислить тебя.
Но пароль например таким образом не украсть, если конечно на самой соцсети нет уязвимости.
Есть расширение для файерфокса, которое ловит попытки клинкуть по прозрачному ифрейму, по моему NoScript.
У меня например на недоверенных сайтах вообще JS отключен.
>>537323
Компьютер так не взломать.
>>537151
Узнать можно с помощью кликджекинга или найдя уязвимость в соцсети.
Вот например на яндексе есть JS скрипт который отдает мыло пользователя. Но хитрюги проверяют реферрер и отдают данные только для яндексовских проектов. Если найти проект где можно как-то с помощью XSS или может редиректов подключить этот скрипт, может быть возможно получить эту информацию и на своем сайте. Подробности я пожалуй писать не буду, кто понимает тот и сам найдет.
>>537010
Никак. Используй кодировку utf8 без ВOM, а с BOM PHP нормально не работает.
Теоретически там можно покрутить настройки апача или нгинкса но я думаю что правильнее убрать BOM.
У тебя должно было вывестись сообщение об ошибке.
Может они у тебя не отображаются?
В PHP по умолчанию выключено отображение ошибок в браузере, так как обычному пользователю сайта эта информация ни к чему. Но тебе, как программисту, надо видеть эти ошибки. Вот, как можно их просмотреть:
- ошибки сохраняются в лог ошибок. Можно открыть его и почитать. Если ты запускаешь код на локалхосте, у себя, то лог хранится в папке Апача (обычно она называется logs) и имеет название вроде error.log (в линуксе в папку /var/log/apache2 ). Если на хостинге — там либо есть файл error.log либо раздел в панели управления, где лог можно посмотреть
- также, ты можешь включить отображение ошибок. Открой файл php.ini, поставь там display_errors = On и error_reporting = E_ALL и перезапусти сервер. Теперь ошибки должны выводиться на экран.
Проверить, работает ли вывод ошибок, можно запустив скрипт содержающий обращение к несуществующей переменной вроде echo $sdgasdad; и проверив, выведется ошибка или нет. Если все верно, то должна вывестись.
>Для поиска по всем колонкам можно применить оператор LIKE к соединенным через пробел значениям столбцов.
это как? ничего кроме
>Другой вариант — искать в нескольких колонках через OR, например name LIKE '%hello%' OR surname LIKE '%hello%', но такой способ не сработает при поиске и по имени, и по фамилии одновременно по фразе вроде «Иван Иванов».
мне в голову не приходит. В гугле только такой и встречается. Я знаю что есть какой-то "полнотекстовый поиск", но это пока использовать не хочу.
>не сработает при поиске и по имени, и по фамилии одновременно по фразе вроде «Иван Иванов»
это тоже проблема, получается поиск только по одному слову
WHERE CONCAT(name, ' ', surname) LIKE '%иван%иванов%'
В этом случае если несколько слов то они должны идти в том же порядке в запросе.
Спасибо, но я пока всего-лишь пишу в ideone.com и там же выполняю. Там есть какие-то коды ошибок.
Там есть баг что ошибки не показываются сразу, а только если перезагрузить страницу. Попробуй открыть страницу с программой заново и внизу будут ошибки, в поле stderr
вроде дошло, ф-я CONCAT осуществляет стандартную для ЯП конкатенацию, в этом случае над значениями полей каждой записи, далее сверяет через LIKE с шаблоном. Придется искомую строку парсить на наличие пробелов, чтобы распознать, что в ней содержится несколько слов.
>Узнают твой id в соцсетях или поставят от твоего имени лайк.
ВК уже давно требует подтверждения при таких действиях, не прокатит.
Спасибо. Добра.
лол, не, будет два вида шаблонов:
"%word1%word2%" - для строки с разделением слов через пробел
"%word1word2%" - для строки без пробела вида "ИванИванов", т.к. где его ставить мы не знаем.
Если пользователь ввел 2 слова слитно, значит это не 2 слова, а одно.
Вообще там поиск примитивный и больше ориентирован на сценарий когда мы вводим просто часть имени или фамилии чтобы по ним отфильтровать список. Например чтобы найти себя или знакомого.
Хотя если ты сделаешь чтобы искал слова в любом порядке, это будет плюсом. Например можно конструировать такой запрос:
WHERE CONCAT(...) LIKE '%слово1%'
AND CONCAT(...) LIKE '%слово2%'
AND CONCAT(...) LIKE '%слово3%'
Для чего? Если для локалхоста то Апач + PHP как модуль так как проще всего настраивать и все прекрасно работает.
ну вот я уже год кодю по четыре часа в день, что-то я не вижу никакого прогресса или чтобы я где-то работал.
Без разницы в целом.
Ты не написал ни что ты умеешь ни много ли раз ты пробовал устроиться на работу. Разумеется цель не просто потратить определенное время, а получить определенный уровень знаний.
>>537452
Тогда наверно проще Апач, но если хочешь можешь и nginx + fpm настроить, Апач там лишний.
>>535405
Задача про правописание, http://ideone.com/BRxyii
> "/\S+[^,]\s(а|но)/u"
Эта регулярка сработает на «длинный нос» так как нос начинается с «но»
> [,.!?:;]\S+
Эта на многоточие
> foreach($regexps as $i => $regexp)
Где фигурная скобка { после foreach? Как догадываться где начинается и заканчивается цикл? Надо ставить фигурные скобки.
Также, тело цикла надо писать с отступом чтобы оно сразу выделялось.
Задача на номера телефонов: http://ideone.com/HyfBsZ
Задачу про номера телефонов надо проверить на большом числе телефонов, чтобы убедиться что твой код правильный. Но руками подставлять номера — долго и скучно. Пусть работает робот, а не человек!
Для этого давай добавим в программу тесты, чтобы сразу было видно, верно все работает или нет. Сделай 2 списка номеров (правильные и нет), добавь их в программу и напиши цикл, который их по очереди прогоняет через регулярку и проверяет что они определяются как надо (если нет — надо вывести какой именно номер не распознается правильно).
Вот список номеров:
Правильные: array('84951234567', '+74951234567', '8-495-1-234-567', ' 8 (8122) 56-56-56', '8-911-1234567', '8 (911) 12 345 67', '8-911 12 345 67', '8 (911) - 123 - 45 - 67', '+ 7 999 123 4567', '8 ( 999 ) 1234567', '8 999 123 4567');
Неправильные: array('02', '84951234567 позвать люсю', '849512345', '849512345678',
'8 (409) 123-123-123', '7900123467', '5005005001', '8888-8888-88',
'84951a234567', '8495123456a',
'+1 234 5678901', // неверный код страны
'+8 234 5678901', // либо 8 либо +7
'7 234 5678901' // нет +
);
> function checkAndModifyNumber($numberRegexp,$number,$charRegexp){
Я думаю, передавать надо только номер, а регулярки поместить внутрь функции. Так как это по сути часть ее логики и нет надобности вызывать ее с другими регулярками.
Автозамена http://ideone.com/pVKdWf
Все верно сделано.
Поиск email http://ideone.com/MfScps
Не ищет email с цифрами например 001@001.example.ru
> [a-zA-Z_+-]+(.[a-zA-Z_+-])
> [a-z]+(.[a-z-])
Точка тут значит любой символ, и он будет искать даже недопустимые email (например содержащие пробел)
Чтобы искать символ точки, его надо экранировать: \.
Ты не написал ни что ты умеешь ни много ли раз ты пробовал устроиться на работу. Разумеется цель не просто потратить определенное время, а получить определенный уровень знаний.
>>537452
Тогда наверно проще Апач, но если хочешь можешь и nginx + fpm настроить, Апач там лишний.
>>535405
Задача про правописание, http://ideone.com/BRxyii
> "/\S+[^,]\s(а|но)/u"
Эта регулярка сработает на «длинный нос» так как нос начинается с «но»
> [,.!?:;]\S+
Эта на многоточие
> foreach($regexps as $i => $regexp)
Где фигурная скобка { после foreach? Как догадываться где начинается и заканчивается цикл? Надо ставить фигурные скобки.
Также, тело цикла надо писать с отступом чтобы оно сразу выделялось.
Задача на номера телефонов: http://ideone.com/HyfBsZ
Задачу про номера телефонов надо проверить на большом числе телефонов, чтобы убедиться что твой код правильный. Но руками подставлять номера — долго и скучно. Пусть работает робот, а не человек!
Для этого давай добавим в программу тесты, чтобы сразу было видно, верно все работает или нет. Сделай 2 списка номеров (правильные и нет), добавь их в программу и напиши цикл, который их по очереди прогоняет через регулярку и проверяет что они определяются как надо (если нет — надо вывести какой именно номер не распознается правильно).
Вот список номеров:
Правильные: array('84951234567', '+74951234567', '8-495-1-234-567', ' 8 (8122) 56-56-56', '8-911-1234567', '8 (911) 12 345 67', '8-911 12 345 67', '8 (911) - 123 - 45 - 67', '+ 7 999 123 4567', '8 ( 999 ) 1234567', '8 999 123 4567');
Неправильные: array('02', '84951234567 позвать люсю', '849512345', '849512345678',
'8 (409) 123-123-123', '7900123467', '5005005001', '8888-8888-88',
'84951a234567', '8495123456a',
'+1 234 5678901', // неверный код страны
'+8 234 5678901', // либо 8 либо +7
'7 234 5678901' // нет +
);
> function checkAndModifyNumber($numberRegexp,$number,$charRegexp){
Я думаю, передавать надо только номер, а регулярки поместить внутрь функции. Так как это по сути часть ее логики и нет надобности вызывать ее с другими регулярками.
Автозамена http://ideone.com/pVKdWf
Все верно сделано.
Поиск email http://ideone.com/MfScps
Не ищет email с цифрами например 001@001.example.ru
> [a-zA-Z_+-]+(.[a-zA-Z_+-])
> [a-z]+(.[a-z-])
Точка тут значит любой символ, и он будет искать даже недопустимые email (например содержащие пробел)
Чтобы искать символ точки, его надо экранировать: \.
http://php.net/manual/en/function.is-array.php
Посмотри в рубрике see also про проверку других типов.
Задача на исправление ошибок http://ideone.com/2WdKog
Ты неудачно сделал хранение регулярок и выражений для замены в 2 разных массивах. Так легко запутаться что чему соответствует. Лучше писать так:
$rules = [
регулярка => замена,
регулярка => замена
];
> [^,\w](а|но)
Ищет любое слово начинающееся с «но»
> /([,.!?:;])(\S+
Ищет многоточие
> $1ординально
придерусь: правильно писать «кардинально»
Задача про опечатки http://ideone.com/tJujsL
Комментарии принято писать либо над либо справа от строки, их не пишут снизу.
> $langRegexps[LANG_RUS]
Если ты берешь элемент из массива не по числу, а по константе, то надо и класть его туда так же:
$langRegexps = array(
LANG_RUS => '/...../u'
LANG_ENG => ....
);
Иначе кто-нибудь добавить в массив элемент и удивится почему все сломалось.
Определение языка текста сделано на мой взгляд неправильно. Ведь текст может содержать слова из разных языков. Ты должен искать опечатки примерно так:
- ищем все слова, где за латинской буквой идет русская или наоборот, то есть слова содержащие буквы разных языков в одном слове.
- в этих словах определяем язык слова (например по первой букве) и выделяем все буквы других алфавитов
Задача про пунктуацию http://ideone.com/4nb3tt
Твой код выглядит хрупким. Он неявно полагается на то, что массив предложений и массив знаков-разделителей между ними будут совпадать. Но гарантировано ли это? Что если например мы имеем текст вида
.... много думал ???
preg_split даст тут 1 элемент
$punctuationMarks даст 2 элемента
Надо либо убирать PREG_SPLIT_NO_EMPTY либо попробовать другой подход. Например, мы можем захватывать в preg_split и знаки препинания, если поместить регулярку в круглые скобки и написать так:
\t$sentences = preg_split('/([.?!]+)/', $text, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
Черта | объединяет флаги
Флаг CAPTURE говорит что надо сохранять текст соответствующий заключенным в скобки частям регулярки
> \t$text = preg_replace('/^.(.×)/u', $firstLetter.'$1', $text);
Слишком мощную вещь используешь. Чтобы взять текст начиная со второй буквы достаточно mb_substr($text, 1)
Разгадываю капчу, чувствую себя индусом которого наняли за копейки (точнее за бесплатно) распознавать картинки.
Задача на исправление ошибок http://ideone.com/2WdKog
Ты неудачно сделал хранение регулярок и выражений для замены в 2 разных массивах. Так легко запутаться что чему соответствует. Лучше писать так:
$rules = [
регулярка => замена,
регулярка => замена
];
> [^,\w](а|но)
Ищет любое слово начинающееся с «но»
> /([,.!?:;])(\S+
Ищет многоточие
> $1ординально
придерусь: правильно писать «кардинально»
Задача про опечатки http://ideone.com/tJujsL
Комментарии принято писать либо над либо справа от строки, их не пишут снизу.
> $langRegexps[LANG_RUS]
Если ты берешь элемент из массива не по числу, а по константе, то надо и класть его туда так же:
$langRegexps = array(
LANG_RUS => '/...../u'
LANG_ENG => ....
);
Иначе кто-нибудь добавить в массив элемент и удивится почему все сломалось.
Определение языка текста сделано на мой взгляд неправильно. Ведь текст может содержать слова из разных языков. Ты должен искать опечатки примерно так:
- ищем все слова, где за латинской буквой идет русская или наоборот, то есть слова содержащие буквы разных языков в одном слове.
- в этих словах определяем язык слова (например по первой букве) и выделяем все буквы других алфавитов
Задача про пунктуацию http://ideone.com/4nb3tt
Твой код выглядит хрупким. Он неявно полагается на то, что массив предложений и массив знаков-разделителей между ними будут совпадать. Но гарантировано ли это? Что если например мы имеем текст вида
.... много думал ???
preg_split даст тут 1 элемент
$punctuationMarks даст 2 элемента
Надо либо убирать PREG_SPLIT_NO_EMPTY либо попробовать другой подход. Например, мы можем захватывать в preg_split и знаки препинания, если поместить регулярку в круглые скобки и написать так:
\t$sentences = preg_split('/([.?!]+)/', $text, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
Черта | объединяет флаги
Флаг CAPTURE говорит что надо сохранять текст соответствующий заключенным в скобки частям регулярки
> \t$text = preg_replace('/^.(.×)/u', $firstLetter.'$1', $text);
Слишком мощную вещь используешь. Чтобы взять текст начиная со второй буквы достаточно mb_substr($text, 1)
Разгадываю капчу, чувствую себя индусом которого наняли за копейки (точнее за бесплатно) распознавать картинки.
А зачем это? В хорошей программе переменная должна содержать данные одного типа, известного на этапе написания. Соответственно писать такие условия не требуется.
>В хорошей программе переменная должна содержать данные одного типа, известного на этапе написания. Соответственно писать такие условия не требуется.
Переменную задаю не я, а wordpress, она периодически объект, а периодически - нет.
Статические методы принадлежат классу, а не объекту. Значит, их однозначно нужно предпочитать, если есть возможность не создавать экземпляр объекта.
Но если создание объекта необходимо, делать ли его "сомнительные" методы статическими или обычными? Какими соображениями руководствоваться при выборе?
Статические методы используются редко, когда методу не нужен $this. Например, функция форматирования объема файла может быть статической. Обычно это маленькие вспомогательные функции.
Если у тебя большинство таких то скорее всего ты плохо понял ООП или плохо спроектировал классы.
Такие вещи лучше конечно разбирать на конкретных примерах, есть класс с такими-то полями и методами, как тут лучше сделать?
>Статические методы используются когда методу не нужен $this.
Ок, принимаю за аксиому.
Ну например ты мне написал повыкидывать все статические методы из LoginManager.
>LoginManager надо сделать нормальным, не статическим классом
http://pastebin.com/11PAUhyc
Переписал класс, но некоторые методы, которые не используют $this, по-моему вполне можно было оставить статическими. Например logout и authorizeUser
https://github.com/nsdvw/file-sharing/blob/master/app/Auth/LoginManager.php
(смотри git diff 23cb558..2024969 app/Auth , если ты скачивал мой репо, я же не знаю как ты проверяешь, прямо с гитхаба или клонируешь себе)
Ваши аргументы?
----------------------------------------
Какой логикой руководствоваться при выборе имени для переменной? Может есть какой-нибудь мануал на эту тему, типа алгоритм подбора грамотного имени.
Или придет с опытом? (статью с learn.javascript, пронизанную попоболью какого-то тестировщика, не предлагать: там говорится как не нужно делать, но не говорится как нужно)
Например мне необходимо преобразовать объект в массив, а затем упаковать в json. Допустим, метод назову $obj->toJson(), а как назвать промежуточный массив, который используется как локальная переменная этого метода?
$x = array();
foreach($this as $key=>$value) {
$x[$key] = $value;
}
return json_encode($x);
Как именовать X?
----------------------------------------
Почему многие сайты люто тормозят? Это связано с тем, что они сделаны на несвежих смс?
Там картинки что ли не поджимаются, или нет кеширования?
Как вообще это проанализировать? Ну типа последовательность действий, что нужно сделать чтобы понять с клиента, почему тормозит сайт? Наверное, что-то в инспекторе во вкладке network, я там еще не лазил, не знаю на что смотреть и в какой последовательности.
Вот например крупный украинский сайт с объявлениями https://auto.ria.com/
У меня секунд по 15 загружаются страницы.
>Статические методы используются когда методу не нужен $this.
Ок, принимаю за аксиому.
Ну например ты мне написал повыкидывать все статические методы из LoginManager.
>LoginManager надо сделать нормальным, не статическим классом
http://pastebin.com/11PAUhyc
Переписал класс, но некоторые методы, которые не используют $this, по-моему вполне можно было оставить статическими. Например logout и authorizeUser
https://github.com/nsdvw/file-sharing/blob/master/app/Auth/LoginManager.php
(смотри git diff 23cb558..2024969 app/Auth , если ты скачивал мой репо, я же не знаю как ты проверяешь, прямо с гитхаба или клонируешь себе)
Ваши аргументы?
----------------------------------------
Какой логикой руководствоваться при выборе имени для переменной? Может есть какой-нибудь мануал на эту тему, типа алгоритм подбора грамотного имени.
Или придет с опытом? (статью с learn.javascript, пронизанную попоболью какого-то тестировщика, не предлагать: там говорится как не нужно делать, но не говорится как нужно)
Например мне необходимо преобразовать объект в массив, а затем упаковать в json. Допустим, метод назову $obj->toJson(), а как назвать промежуточный массив, который используется как локальная переменная этого метода?
$x = array();
foreach($this as $key=>$value) {
$x[$key] = $value;
}
return json_encode($x);
Как именовать X?
----------------------------------------
Почему многие сайты люто тормозят? Это связано с тем, что они сделаны на несвежих смс?
Там картинки что ли не поджимаются, или нет кеширования?
Как вообще это проанализировать? Ну типа последовательность действий, что нужно сделать чтобы понять с клиента, почему тормозит сайт? Наверное, что-то в инспекторе во вкладке network, я там еще не лазил, не знаю на что смотреть и в какой последовательности.
Вот например крупный украинский сайт с объявлениями https://auto.ria.com/
У меня секунд по 15 загружаются страницы.
LoginManager сделан неправильно, это видно например по тому что ты там скопипастил код соединения с Бд и руками создаешь маппер, в то время как в соответствии с принципами Dependency Injection правильно передавать маппер через конструктор.
Если тебе интересно почитать про DI: https://gist.github.com/codedokode/e1d31a31b37d5f635057 (урок старый и там могут быть мелкие неточности)
Так как мы передаем маппер через конструктор то очевидно что методы работающие с ним должны быть нестатическими.
> Переписал класс, но некоторые методы, которые не используют $this, по-моему вполне можно было оставить статическими. Например logout и authorizeUser
Это да, они не используют $this, но правильнее их сделать все же динамическими, так как например метод проверки залогиненности у тебя динамический, а это методы примерно того же уровня. Ну и может быть им завтра понадобится что-нибудь из $this. Может ты завтра например при разлогинивании будешь в базе что-то помечать.
Если тебе будет проще понять, давай представим что у нас появилось несколько объектов LoginManager. Допустим они отвечают за авторизацию в разных зонах сайта (или допустим один отвечает за настоящую авторизацию, а другой тестовый и не ставит куки). Согласись, в этом случае статический метод logout не говорит нам о том к какому объекту он относится и выглядит неуместно.
Статические методы не для того, вот например получение хеша из пароля можно сделать статическим так как это маленький не использующий данные в полях объекта метод.
То есть критерий тут не только использование $this, а логика в общем: принадлежит ли метод отдельному объекту или классу. Как он должен себя вести когда объектов несколько? Когда объектов нет?
> Какой логикой руководствоваться при выборе имени для переменной? Может есть какой-нибудь мануал на эту тему, типа алгоритм подбора грамотного имени.
Код пишется для людей. Выбирать надо было чтобы понятно что в ней.
> Допустим, метод назову $obj->toJson(), а как назвать промежуточный массив, который используется как локальная переменная этого метода?
можно назвать $properties (свойства) или $jsonData (данные для JSON). Иногда пишут $data или $array но мне кажется эти названия ничего не говорят и из лучше избегать. Любая переменная хранит какие-то данные.
LoginManager сделан неправильно, это видно например по тому что ты там скопипастил код соединения с Бд и руками создаешь маппер, в то время как в соответствии с принципами Dependency Injection правильно передавать маппер через конструктор.
Если тебе интересно почитать про DI: https://gist.github.com/codedokode/e1d31a31b37d5f635057 (урок старый и там могут быть мелкие неточности)
Так как мы передаем маппер через конструктор то очевидно что методы работающие с ним должны быть нестатическими.
> Переписал класс, но некоторые методы, которые не используют $this, по-моему вполне можно было оставить статическими. Например logout и authorizeUser
Это да, они не используют $this, но правильнее их сделать все же динамическими, так как например метод проверки залогиненности у тебя динамический, а это методы примерно того же уровня. Ну и может быть им завтра понадобится что-нибудь из $this. Может ты завтра например при разлогинивании будешь в базе что-то помечать.
Если тебе будет проще понять, давай представим что у нас появилось несколько объектов LoginManager. Допустим они отвечают за авторизацию в разных зонах сайта (или допустим один отвечает за настоящую авторизацию, а другой тестовый и не ставит куки). Согласись, в этом случае статический метод logout не говорит нам о том к какому объекту он относится и выглядит неуместно.
Статические методы не для того, вот например получение хеша из пароля можно сделать статическим так как это маленький не использующий данные в полях объекта метод.
То есть критерий тут не только использование $this, а логика в общем: принадлежит ли метод отдельному объекту или классу. Как он должен себя вести когда объектов несколько? Когда объектов нет?
> Какой логикой руководствоваться при выборе имени для переменной? Может есть какой-нибудь мануал на эту тему, типа алгоритм подбора грамотного имени.
Код пишется для людей. Выбирать надо было чтобы понятно что в ней.
> Допустим, метод назову $obj->toJson(), а как назвать промежуточный массив, который используется как локальная переменная этого метода?
можно назвать $properties (свойства) или $jsonData (данные для JSON). Иногда пишут $data или $array но мне кажется эти названия ничего не говорят и из лучше избегать. Любая переменная хранит какие-то данные.
в мухосрани. а что я уметь могу? сайт могу сделать.
Умею сделать бложик, медленно выдрачиваю ООП и фреймворки, как в твоих методичках. Устраиваться пробовал еще верстальщиком - нахуй послали, а больше контор то и нет, на фрилансе тоже нахуй шлют, короче фпизду программирование - бесполезно, так только для себя развлечение от скуки, не более. Не понимаю, как вы ПРАХРАМИСТАМИ работаете, вы наверное совсем поехавшие.
> Почему многие сайты люто тормозят?
Отличный вопрос. Вообще, ответ зависит от многих факторов начиная с времени суток и заканчивая установленным у тебя софтом. И я дам тебе не рыбу, а удочку.
Освой инспектор в Хроме или ФФ (Ctrl + SHift + I):
https://developer.chrome.com/devtools (англ подробно)
http://habrahabr.ru/post/143767/ (рус кратко)
Там есть вкладка Network. Если внимательно в ней разобраться и изучить огромное число кнопочек и ручек, то ты будешь поражен мощью этого инструмента. Например, он позволяет имитировать медленное соединение (в Хроме).
Открыв эту вкладку, перезагрузи сайт с очисткой кеша (Ctrl + F5), для верности можешь еще поставить галочку «disable cache» в инспекторе.
В процессе загрузки сайта инспектор построит график, указав все загруженные файлы и время их загрузки. Изучи его и определи причину тормозов, если не справишься, можешь запостить скриншотом.
Помни несколько вещей:
- браузер ограничивает число параллельных соединений (и скачиваемых файлов) на 1 домен, это то ли 6 то ли 8 соединений. Это делается для защиты от перегрузки сервера. Не знаю, действует ли лимит на одну вкладку или на весь браузер. Лимит рекомендован каким-то стандартом.
- возможно также есть лимит соединений на 1 вкладку в сумме, он не менее 20-30
- некоторые файлы блокируют загрузку других файлов. К примеру, синхронные (по умолчанию они такие) скрипты блокирют разбор HTML кода ниже (а следовательно загрузку упомянутых там файлов) до тех пор пока они не будут загружены. Если такой скрипт через document.write вставляет еще один скрипт то разбор HTML тоже блокируется
- загрузка CSS файлов и веб шрифтов не блокирует разбор HTML или загрузку файлов, но блокирует отображение страницы: CSS целиком, шрифты — текст написанный ими
- загрузка картинок и файлов внутри ифреймов ничего не блокирует на главной странице, но большое их число приводит к заполнению лимита на число соединений.
статьи:
http://habrahabr.ru/post/182310/
http://webo.in/articles/habrahabr/56-non-blocking-javascript/
http://webo.in/articles/habrahabr/15-yahoo-best-practices/ (очень хороший сайт, хотя некоторые статьи староваты, рекомендую к изучению)
http://speedupyourwebsite.ru/ (хорошая книга)
Вообще это отдельный предмет с названием «клиентская оптимизация» и я советую почитать чтобы иметь хотя бы общее представление о ней.
Алсо по моему опыту тормозят чаще всего внешние скрипты: яндекс-карты, реклама и виджеты соцсетей.
Если хочешь, могу дать тебе домашнее задание: возьми страницу любого сайта, который тормозит из-за внешних скриптов и сохрани на диск (или сделай ее сам используя популярные сторонние виджеты). Убедись что она работает и тормозит по-прежнему. Переделай ее на асинхронную неблокирующую загрузку всех скриптов (HTML можно упростить вырезав например ненужные статьи). Оцени выигрыш в времени до отображения на экране.
> Почему многие сайты люто тормозят?
Отличный вопрос. Вообще, ответ зависит от многих факторов начиная с времени суток и заканчивая установленным у тебя софтом. И я дам тебе не рыбу, а удочку.
Освой инспектор в Хроме или ФФ (Ctrl + SHift + I):
https://developer.chrome.com/devtools (англ подробно)
http://habrahabr.ru/post/143767/ (рус кратко)
Там есть вкладка Network. Если внимательно в ней разобраться и изучить огромное число кнопочек и ручек, то ты будешь поражен мощью этого инструмента. Например, он позволяет имитировать медленное соединение (в Хроме).
Открыв эту вкладку, перезагрузи сайт с очисткой кеша (Ctrl + F5), для верности можешь еще поставить галочку «disable cache» в инспекторе.
В процессе загрузки сайта инспектор построит график, указав все загруженные файлы и время их загрузки. Изучи его и определи причину тормозов, если не справишься, можешь запостить скриншотом.
Помни несколько вещей:
- браузер ограничивает число параллельных соединений (и скачиваемых файлов) на 1 домен, это то ли 6 то ли 8 соединений. Это делается для защиты от перегрузки сервера. Не знаю, действует ли лимит на одну вкладку или на весь браузер. Лимит рекомендован каким-то стандартом.
- возможно также есть лимит соединений на 1 вкладку в сумме, он не менее 20-30
- некоторые файлы блокируют загрузку других файлов. К примеру, синхронные (по умолчанию они такие) скрипты блокирют разбор HTML кода ниже (а следовательно загрузку упомянутых там файлов) до тех пор пока они не будут загружены. Если такой скрипт через document.write вставляет еще один скрипт то разбор HTML тоже блокируется
- загрузка CSS файлов и веб шрифтов не блокирует разбор HTML или загрузку файлов, но блокирует отображение страницы: CSS целиком, шрифты — текст написанный ими
- загрузка картинок и файлов внутри ифреймов ничего не блокирует на главной странице, но большое их число приводит к заполнению лимита на число соединений.
статьи:
http://habrahabr.ru/post/182310/
http://webo.in/articles/habrahabr/56-non-blocking-javascript/
http://webo.in/articles/habrahabr/15-yahoo-best-practices/ (очень хороший сайт, хотя некоторые статьи староваты, рекомендую к изучению)
http://speedupyourwebsite.ru/ (хорошая книга)
Вообще это отдельный предмет с названием «клиентская оптимизация» и я советую почитать чтобы иметь хотя бы общее представление о ней.
Алсо по моему опыту тормозят чаще всего внешние скрипты: яндекс-карты, реклама и виджеты соцсетей.
Если хочешь, могу дать тебе домашнее задание: возьми страницу любого сайта, который тормозит из-за внешних скриптов и сохрани на диск (или сделай ее сам используя популярные сторонние виджеты). Убедись что она работает и тормозит по-прежнему. Переделай ее на асинхронную неблокирующую загрузку всех скриптов (HTML можно упростить вырезав например ненужные статьи). Оцени выигрыш в времени до отображения на экране.
Что ты изучал год по 4 часа в день если до ООП только дошел? У меня например в учебнике ООП это 7й или 8й урок по счету.
Я хочу тебя огорчить, но если человек не знает ООП, это то же самое что он не знает PHP. Не верь тому кто скажет что это не так и ООП не нужен. Работодателям он нужен.
Почти то же можно сказать про фреймворки.
Насчет фриланса, а ты не пробовал понять почему не получашеь заказы, сравнивать себя и свою страницу с страницами других фрилансеров?
Насчет того что тебя не взяли верстальщиком, может стоит HTMl/CSS/JS до нормального уровня выучить? И сверстать несколько сайтов на фрилансе.
Ты копируй такие квесты со ссылками себе на сайт или на гитхаб, а то как-то жалко что они тут тонут.
Лично я сейчас по уши перегружен, не знаю когда и за что хвататься.
Если и дойду до этого задания, то когда тред будет уже в бамплимите.
Кстати, ты мог бы и настоящую книгу написать, тем более что писать ничего не нужно, только собрать и систематизировать ценную информацию, разбрызганную по интернету.
> я же не знаю как ты проверяешь
гитхаб, там все красиво выводится. Если код ок то скачиваю и запускаю и смотрю глазами.
> смотри git diff 23cb558..2024969
В гитхабе можно ссылку сделать, нажав зеленую кнопку со стрелочками: https://github.com/nsdvw/file-sharing/compare/master@%7B4day%7D...master
> public $loggedUser = null;
лучше сделать метод getLoggedUser(), а свойство закрыть, чтобы проверка логина происходила не в конструкторе а только при первом обращении.
Для setcookie надо указывать path иначе можно поиметь веселые проблемы с пропадающей на части страниц авторизацией: https://www.google.ru/search?q=cookie+path&oq=cookie+path&aqs=chrome..69i57j0l5.1805j0j7&sourceid=chrome&es_sm=0&ie=UTF-8
Функцию с вложенными if стоит переписать по принципу
Если (...) {
выход
}
Если (...) {
выход
}
Если (...) {
выход
}
верунть результат;
Время выставления куки сделать переменной с понятным именем.
Стоит также проверять, если id в куках пустой (получится 0 после intval) то не лезть в базу.
А, и насчет проверки, все же код в index.php был ужасный. Ты и сам наверняка это видел. Не может хороший код так выглядеть.
Сейчас LoginManager изменился в лучшую сторону, прямо как день и ночь.
> я же не знаю как ты проверяешь
гитхаб, там все красиво выводится. Если код ок то скачиваю и запускаю и смотрю глазами.
> смотри git diff 23cb558..2024969
В гитхабе можно ссылку сделать, нажав зеленую кнопку со стрелочками: https://github.com/nsdvw/file-sharing/compare/master@%7B4day%7D...master
> public $loggedUser = null;
лучше сделать метод getLoggedUser(), а свойство закрыть, чтобы проверка логина происходила не в конструкторе а только при первом обращении.
Для setcookie надо указывать path иначе можно поиметь веселые проблемы с пропадающей на части страниц авторизацией: https://www.google.ru/search?q=cookie+path&oq=cookie+path&aqs=chrome..69i57j0l5.1805j0j7&sourceid=chrome&es_sm=0&ie=UTF-8
Функцию с вложенными if стоит переписать по принципу
Если (...) {
выход
}
Если (...) {
выход
}
Если (...) {
выход
}
верунть результат;
Время выставления куки сделать переменной с понятным именем.
Стоит также проверять, если id в куках пустой (получится 0 после intval) то не лезть в базу.
А, и насчет проверки, все же код в index.php был ужасный. Ты и сам наверняка это видел. Не может хороший код так выглядеть.
Сейчас LoginManager изменился в лучшую сторону, прямо как день и ночь.
Еще придирка. В хорошем коде все методы и функции должны возвращать точный, актуальный результат. В идеале в твоем случае после разлогинивания или залогинивания класс LoginManager должен возвращать изменившуюся информацию про текущего юзера.
То есть можно завести какое-то внутреннее поле и его менять.
Для этого боженька создал ебук в которых продают сейчас все издания, начиная от амазонов и заканчивая пактам. А бумажная книга сделана для любителей скорее, ничего не мешает тебе регулярно обновлять электронную, особенно во всяких приложениях.
Поэтому книги уже давно не устаревают, добро пожаловать в 2015 год, где киндлы и планшеты на андроиде есть у каждого индуса и азиата из деревни.
> class Captcha extends Form
По моему неправильно, капча это элемент формы, а не разновидность формы или улучшенный вариант.
Можно было бы писать class FormWithCpatcha extends Form.
Надо сделать капчу элементом формы, а класс Captcha сделать независимым от формы.
> public function fromForm(CommentForm $form)
Форма должна работать с моделью, а не наоборот. модель не должна знать ничего о форме хотя бы потому что таких форм может быть несколько.
Удобно в объекте формы хранить модельку и прямо в ней хранить введенные значения (хотя в форме может быть больше элементов, например поля ввода пароля — их придется хранить отдельно).
> foreach ($this as $propertyName => $propertyValue) {
Лучше сделать массив со списокм разрешенных к экспорту полей, а то у тебя тут вообще все без разбора выдается.
> noise.jpg
Почитай-ка про форматы картинок и их особенности. А то получается анекдот из 1 слова.
> $title = 'FileSharing — page not found';
Сделай-ка метод $app->setPageTitle() чтобы он формировал заголовок по шаблону. Не руками же копипастить название сайта.
> $app->loginManager->logout();
> $app->loginManager->loggedUser = null;
У тебя пробелы в понимании ООП. Объект должен сам менять свои свойства в этом случае, ты не должен это делать снаружи. Рекомендую вообще закрыть свойство loggedUser от доступа (это называется инкапсуляция, объект прячет свое внутреннее состояние и предоставляет только методы для работы с ним. Также как автомат по продаже кофе дает тебе кнопки и щель для денег но не дает доступа к внутреннему механизму).
Логаут надо делать через ПОСТ с редиректом после. Можно передавать скрытым полем адрес страницы для возврата, но в этом случае сделай проверку что это твоя страница а то получишь открытый редиректор, а это может быть плохо для SEO например.
> if ($_SERVER['REQUEST_METHOD'] === 'GET') {
Исплоьзуй app->request
> if ($loginForm->validate()) {
> if (!$user = $app->userMapper->findByEmail($loginForm->email)) {
Может проверку email тоже в форму засунуть?
> array(
+ 'loginError'=>$loginError,
+ 'loginEmail'=>$loginEmail,
+ 'loginPassword'=>$loginPassword,
Передавай объект формы а не 3 переменных.
> exit( ) ;
Неправильно, надо делать return или app->stop() иначе некоторые модули Слима не вызовутся. У него же луковичная архитектура.
> if $loginManager->loggedUser === null}
Лучше бы метод isLoggedIn() для читабельности
> class Captcha extends Form
По моему неправильно, капча это элемент формы, а не разновидность формы или улучшенный вариант.
Можно было бы писать class FormWithCpatcha extends Form.
Надо сделать капчу элементом формы, а класс Captcha сделать независимым от формы.
> public function fromForm(CommentForm $form)
Форма должна работать с моделью, а не наоборот. модель не должна знать ничего о форме хотя бы потому что таких форм может быть несколько.
Удобно в объекте формы хранить модельку и прямо в ней хранить введенные значения (хотя в форме может быть больше элементов, например поля ввода пароля — их придется хранить отдельно).
> foreach ($this as $propertyName => $propertyValue) {
Лучше сделать массив со списокм разрешенных к экспорту полей, а то у тебя тут вообще все без разбора выдается.
> noise.jpg
Почитай-ка про форматы картинок и их особенности. А то получается анекдот из 1 слова.
> $title = 'FileSharing — page not found';
Сделай-ка метод $app->setPageTitle() чтобы он формировал заголовок по шаблону. Не руками же копипастить название сайта.
> $app->loginManager->logout();
> $app->loginManager->loggedUser = null;
У тебя пробелы в понимании ООП. Объект должен сам менять свои свойства в этом случае, ты не должен это делать снаружи. Рекомендую вообще закрыть свойство loggedUser от доступа (это называется инкапсуляция, объект прячет свое внутреннее состояние и предоставляет только методы для работы с ним. Также как автомат по продаже кофе дает тебе кнопки и щель для денег но не дает доступа к внутреннему механизму).
Логаут надо делать через ПОСТ с редиректом после. Можно передавать скрытым полем адрес страницы для возврата, но в этом случае сделай проверку что это твоя страница а то получишь открытый редиректор, а это может быть плохо для SEO например.
> if ($_SERVER['REQUEST_METHOD'] === 'GET') {
Исплоьзуй app->request
> if ($loginForm->validate()) {
> if (!$user = $app->userMapper->findByEmail($loginForm->email)) {
Может проверку email тоже в форму засунуть?
> array(
+ 'loginError'=>$loginError,
+ 'loginEmail'=>$loginEmail,
+ 'loginPassword'=>$loginPassword,
Передавай объект формы а не 3 переменных.
> exit( ) ;
Неправильно, надо делать return или app->stop() иначе некоторые модули Слима не вызовутся. У него же луковичная архитектура.
> if $loginManager->loggedUser === null}
Лучше бы метод isLoggedIn() для читабельности
верстку фронтенд жиквери макеты верстал синтаксис пхп шарп читал документацию сделал несколько сайтов знаешь ли для этого ни фреймворки не ооп не нужны были.
>>537551
Я тебе уже объяснял, что я сверстал несколько сайтов. На фрилансе без опыта и звездочек и реальных висящих в инторнете сайтов-магазинов, сделанных тобой, заказы не получишь.
бляя я с тебя поражаюсь, велосипед на велосипеде, вот зачем так усложнять? возьми да пропиши в инпуте required, нахуя целый отдельный конструктор для этого создавать, куча лишних функций и методов, неудивительно, что у тебя сайт подвисать начинает при таких усложнениях.
По моему ты скатываешься в троллинг. Ты не можешь принять, что есть люди которым нравится программирование или которых восхищяют возможности которые дает веб? Тебя никто не заставляет его изучать.
Его код вообще-то позволяет прописывать required автоматически и получить и серверную и клиентскую валидацию.
А ты по моему плохо разбираешься в этой теме если считаешь что серверная валидация не нужна.
Ну куда ты летишь? Я еще твои старые замечания не исправил (((
Обработал только 60 строк из 200.
Подожди, я разгребу все замечания, потом выложу на проверку сразу все.
>app->stop()
Вот как он называется. Я знал, что должен быть такой метод, да не нашел, потому прибил exitом.
серверная не нужна.
http://www.proklondike.com/books/dbobshee/homonenko_db_2009.html
Эта книга пойдёт? Что по поводу второго социальные и профессиональные проблемы информатики посоветуешь?
Я поступил в Польшу на магистратуру программирования, но хочу сразу скатываться в веб. Не знаю получу ли я там знания нужные для веба, планирую сам ещё учить это все.
По-моему скатываешь в тралинг только ты. Вон воркач почитай, там с двемя макетами на цсс и хтмпл, сверстанными за неделю, в ДС находят работу, а я уже столько дохуя знаю, пиздец, аж сам себе поражаюсь, насколько я умный, а придется идти в продаваны.
Никак.
Возможно, но я не знаю С. И вот ещё одна проблема но это уже вполне решаема средствами ПХП. Предположим что проверяем такой текст:
$text = "Несмотря на то, что многие работники опасаются";
Мы его разбили по четыре слова методом описанным выше, получилось такое:
1 элемент массива - Несмотря на то, что
2 элемент массива - на то, что многие
3 элемент массива - то, что многие работники
4 элемент массива - что многие работники опасаются
Проверяя уникальность, методом который указан выше, обнаружили что не уникальными является первый и второй элемент:
1 элемент массива - Несмотря на то, что
2 элемент массива - на то, что многие
Мы сохраним их в отдельный массив, и покрасим эти словосочетания в первоначальном тексте. А сделаем это путём поиска в первоначальном тексте, и замены на такие же словосочетания но с тегами "<font color='red'>".СЛОВОСОЧЕТАНИЕ."</font>". Но ничего не выходит, так как после первой замены в тексте уже будут присутствовать теги то есть он будет таким:
<font color='red'>Несмотря на то, что</font> многие работники опасаются
И в итоге следующий элемент ("на то, что многие") мы уже просто не сможем найти потому что эта строка в первоначальном шаблоне будет выглядеть вот так ("на то, что</font> многие"). Чистить теги смысла нет, так как наша цель закрасить тег. Многие другие варианты перепробованы, реально помогла бы регулярка которая сравнивает текст без учёта тегов. Но как её написать я что то не понимают
Вообще надо что бы например в такой строке:
<font color="red">Несмотря на то что</font> многие работники опасаются"
Регулярка нашла:
на то что многие
И заменила на:
<font color="red">на то что многие</font>
Только вот надо учитывать что тег <font> в первоначальном шаблоне может быть находится между любыми словами.
Ну и где твои проекты, умный? Назови парочку сложнее laba1.cpp
connect_error это поле, а не метод: http://php.net/manual/ru/mysqli.connect-error.php
Также, он содержит только информацию об ошибке соединения. А информация об ошибке запроса хранится в error: http://php.net/manual/ru/mysqli.error.php
Спасибо
Нашел время проверить твой макет.
В меню вверху (HOME PORTFOLIO) у тебя слишком жирный шрифт. У тебя там стоит вес 900, а должен быть более легкий. Посмотри, какой стоит в макете. Это видно невооруженным глазом.
То же самое с кнопкой «See Portfolio», у тебя там стоит 900.
В ИЕ10 вокруг ссылок синие рамки: https://www.browserstack.com/screenshots/14c5de63bad958d3b9d1c48d6d8dcce78bc11626
Я вроде бы в прошлый раз говорил, что в ИЕ в браузере по умолчанию стоит правило типа a img { border: ... } которое лечится прописыванием аналогичного в CSS, только со значением none. ИЕ кстати это делает с благой целью: точно так же как ссылки подчеркивают, чтобы показать, что по ним можно кликнуть. Увы, это в наш макет не вписывается.
> Наш соцсетьнейм
Там дриббл и пинтерест :) С дриббблом рекомендую ознакомиться, там удобно например искать по ключевым словам варианты как может выглядеть та или иная штука в интерфейсе: https://dribbble.com/
Также, у тебя разброд и шатание в плане использования классов и идентификаторов, нет никакой единой системы. В большом проекте это 100% приведет к бардаку. Почитай хотя бы про БЭМ:
http://frontender.info/MindBEMding/
https://ru.bem.info/method/definitions/
Там идея в том, что мы стараемся делать каждый блок на странице максимально независимым, так, что при его переносе или использовании на другом сайте нам не придется почти ничего менять. Для этого мы пишем CSS с учетом определенных правил.
Соответственно полезно следовать какому-то единому подходу в выборе наименований.
Это может быть сложновато для начинающего, но попробуй хотя бы общую идею понять.
Сам БЭМ целиком у них сложный, он включает не только подход к именованию классов, они пытаются вообще сделать полностью независимые компоненты (то есть компонент который содержит HTML, CSS и JS для своей работы). Сейчас разрабатывается стандарт Web Components http://habrahabr.ru/post/210058/ который будет делать примерно то же, только немного по-другому. Но общая идея та же: мы один раз делаем например, виджет для отображения таблицы с сортировкой или для выбора цвета и получаем универсальный компонент который можно подключить на любую страницу.
> @media all and (max-width: 720px) {
> .portfolio-text-buttons-and-works input:nth-of-type(1):checked ~ #wrapper_portfolio_works > .graphic,
> width: 49% !important;}
Почему такой сложный селектор на 6 строк? Тут что-то не так. Ты ведь всего лишь меняешь ширину картинки, почему нельзя написать что-то вроде .portfolio-images > a { width: 49%; } (названия выдуманы)? Я думаю, тут какая-то ошибка.
Опять же, по поводу nth-of-type, я тебе кажется говорил в прошлый раз что это плохой подход так как малейшие перестановки кнопок местами все сломают.
> .android-with-text, .pc-with-text, .phone-with-text, .clock-with-text {width: 50% !important;}
Здесь тоже вместо перечисления конкретных блоков можно было сделать как-то через родителя выборку, например .advantages-block > .advantage { ... }
> #header-words a {font-size: 16px !important;}
> h1 {font-size: 30pt !important;
Когда задаешь font-size задвавай и line-height
> <h1>We are <span class="bold900">Webpaint</span></h1>
Как-то не очень красиво. Что это за стили в имени класса? Красивее сделать так <h1>We are <strong>Webpaint</strong></h1> так как тег strong обозначает смысловое выделение текста.
Я также просил тебя объединить однотипные маленькие картинки (например андроид, pc, часы) в CSS-спрайт чтобы познакомиться с этой техникой.
> .android-with-text {
> .pc-with-text {
> .phone-with-text {
Тут сплошная копипаста. Так не пойдет. Программист не должен такое писать. Ты просто раздуваешь объем кода, какой смысл мне (или твоим коллегам) читать одно и то же 4 раза подряд?
Также у тебя много копипасты и в других местах. Например, Get In Touch и Our Featured Works это h2 и можно было бы не повторять CSS код для них, а сделать один стиль для всех тегов h2. Также можно было сделать один класс для идущих за ними подзаголовоков тонким шрифтом.
Вообще, у тебя многовато CSS для такого простого макета. Я подозреваю причина как раз в копипасте.
> .portfolio-text-buttons-and-works input:nth-of-type(1):checked ~ #wrapper_portfolio_works > .graphic,
Тут надо вместо nth-of-type использовать идентификатор кнопки с названием. Привязываться к номеру элемента нанадежно.
> .portfolio-text-buttons-and-works input:nth-of-type(1):checked + label > span,
> .portfolio-text-buttons-and-works input:nth-of-type(2):checked + label > span,
> .portfolio-text-buttons-and-works input:nth-of-type(3):checked + label > span,
Это можно написать короче, без перечисления каждой кнопки, одно универсальное правило.
Ну и весит страница в общем 1.2Мб, многовато. Я не помню, говорил ли я тебе что картинки портфолио надо делать в PNG? Просто мне сейчас пришла мысль что если их делать в JPEG с высоким качеством то весить они будут меньше, а выглядеть может быть будут примерно так же (это конечно надо проверять, может и не будут). Тогда мы бы могли сэкономить на весе страницы, так как картинки портфолио там чуть ли не половину этого мегабайта весят.
В общем, я вижу, что ты что-то понимаешь и сверстать страницу можешь, но CSS код у тебя пока не идеален. Вряд ли твой воображаемый коллега обрадуется от необходимости в нем разбираться и разгребать горы копипасты. Его конечно можно было написать лаконичнее и аккуратнее.
Ну и что касается форматирования, ты писал что долго исправлять, я думаю это неверно, так как есть автоматизированные средства форматирования, бери любой: https://www.google.ru/search?q=css+beautify&oq=css+beautify&aqs=chrome..69i57j0l5.3720j0j7&sourceid=chrome&es_sm=0&ie=UTF-8
Дальше, думаю, тебе стоит поизучать JS и/или PHP.
Нашел время проверить твой макет.
В меню вверху (HOME PORTFOLIO) у тебя слишком жирный шрифт. У тебя там стоит вес 900, а должен быть более легкий. Посмотри, какой стоит в макете. Это видно невооруженным глазом.
То же самое с кнопкой «See Portfolio», у тебя там стоит 900.
В ИЕ10 вокруг ссылок синие рамки: https://www.browserstack.com/screenshots/14c5de63bad958d3b9d1c48d6d8dcce78bc11626
Я вроде бы в прошлый раз говорил, что в ИЕ в браузере по умолчанию стоит правило типа a img { border: ... } которое лечится прописыванием аналогичного в CSS, только со значением none. ИЕ кстати это делает с благой целью: точно так же как ссылки подчеркивают, чтобы показать, что по ним можно кликнуть. Увы, это в наш макет не вписывается.
> Наш соцсетьнейм
Там дриббл и пинтерест :) С дриббблом рекомендую ознакомиться, там удобно например искать по ключевым словам варианты как может выглядеть та или иная штука в интерфейсе: https://dribbble.com/
Также, у тебя разброд и шатание в плане использования классов и идентификаторов, нет никакой единой системы. В большом проекте это 100% приведет к бардаку. Почитай хотя бы про БЭМ:
http://frontender.info/MindBEMding/
https://ru.bem.info/method/definitions/
Там идея в том, что мы стараемся делать каждый блок на странице максимально независимым, так, что при его переносе или использовании на другом сайте нам не придется почти ничего менять. Для этого мы пишем CSS с учетом определенных правил.
Соответственно полезно следовать какому-то единому подходу в выборе наименований.
Это может быть сложновато для начинающего, но попробуй хотя бы общую идею понять.
Сам БЭМ целиком у них сложный, он включает не только подход к именованию классов, они пытаются вообще сделать полностью независимые компоненты (то есть компонент который содержит HTML, CSS и JS для своей работы). Сейчас разрабатывается стандарт Web Components http://habrahabr.ru/post/210058/ который будет делать примерно то же, только немного по-другому. Но общая идея та же: мы один раз делаем например, виджет для отображения таблицы с сортировкой или для выбора цвета и получаем универсальный компонент который можно подключить на любую страницу.
> @media all and (max-width: 720px) {
> .portfolio-text-buttons-and-works input:nth-of-type(1):checked ~ #wrapper_portfolio_works > .graphic,
> width: 49% !important;}
Почему такой сложный селектор на 6 строк? Тут что-то не так. Ты ведь всего лишь меняешь ширину картинки, почему нельзя написать что-то вроде .portfolio-images > a { width: 49%; } (названия выдуманы)? Я думаю, тут какая-то ошибка.
Опять же, по поводу nth-of-type, я тебе кажется говорил в прошлый раз что это плохой подход так как малейшие перестановки кнопок местами все сломают.
> .android-with-text, .pc-with-text, .phone-with-text, .clock-with-text {width: 50% !important;}
Здесь тоже вместо перечисления конкретных блоков можно было сделать как-то через родителя выборку, например .advantages-block > .advantage { ... }
> #header-words a {font-size: 16px !important;}
> h1 {font-size: 30pt !important;
Когда задаешь font-size задвавай и line-height
> <h1>We are <span class="bold900">Webpaint</span></h1>
Как-то не очень красиво. Что это за стили в имени класса? Красивее сделать так <h1>We are <strong>Webpaint</strong></h1> так как тег strong обозначает смысловое выделение текста.
Я также просил тебя объединить однотипные маленькие картинки (например андроид, pc, часы) в CSS-спрайт чтобы познакомиться с этой техникой.
> .android-with-text {
> .pc-with-text {
> .phone-with-text {
Тут сплошная копипаста. Так не пойдет. Программист не должен такое писать. Ты просто раздуваешь объем кода, какой смысл мне (или твоим коллегам) читать одно и то же 4 раза подряд?
Также у тебя много копипасты и в других местах. Например, Get In Touch и Our Featured Works это h2 и можно было бы не повторять CSS код для них, а сделать один стиль для всех тегов h2. Также можно было сделать один класс для идущих за ними подзаголовоков тонким шрифтом.
Вообще, у тебя многовато CSS для такого простого макета. Я подозреваю причина как раз в копипасте.
> .portfolio-text-buttons-and-works input:nth-of-type(1):checked ~ #wrapper_portfolio_works > .graphic,
Тут надо вместо nth-of-type использовать идентификатор кнопки с названием. Привязываться к номеру элемента нанадежно.
> .portfolio-text-buttons-and-works input:nth-of-type(1):checked + label > span,
> .portfolio-text-buttons-and-works input:nth-of-type(2):checked + label > span,
> .portfolio-text-buttons-and-works input:nth-of-type(3):checked + label > span,
Это можно написать короче, без перечисления каждой кнопки, одно универсальное правило.
Ну и весит страница в общем 1.2Мб, многовато. Я не помню, говорил ли я тебе что картинки портфолио надо делать в PNG? Просто мне сейчас пришла мысль что если их делать в JPEG с высоким качеством то весить они будут меньше, а выглядеть может быть будут примерно так же (это конечно надо проверять, может и не будут). Тогда мы бы могли сэкономить на весе страницы, так как картинки портфолио там чуть ли не половину этого мегабайта весят.
В общем, я вижу, что ты что-то понимаешь и сверстать страницу можешь, но CSS код у тебя пока не идеален. Вряд ли твой воображаемый коллега обрадуется от необходимости в нем разбираться и разгребать горы копипасты. Его конечно можно было написать лаконичнее и аккуратнее.
Ну и что касается форматирования, ты писал что долго исправлять, я думаю это неверно, так как есть автоматизированные средства форматирования, бери любой: https://www.google.ru/search?q=css+beautify&oq=css+beautify&aqs=chrome..69i57j0l5.3720j0j7&sourceid=chrome&es_sm=0&ie=UTF-8
Дальше, думаю, тебе стоит поизучать JS и/или PHP.
> Я наверное лучше продолжу работу над заданиями из треда в фоновом режиме, а параллельно буду учить фреймворки. Потому что с такими темпами можно возиться годами над учебными задачами
Это конечно твое дело, как и в каком порядке что изучать, но я думаю, стоит уделить внимание замечаниям что я написал. Как минимум осознать что там написано.
> И на NULL в parent_id не реагирует, я думал что внешний ключ обязан указывать на уникальное значение.
NULL не нарущает уникальность так как NULL это не конкретное значение, а «неизвестно». В уникальной колонке может быть сколько угодно NULL.
Что касается внешних ключей то в них может быть как разрешен так и запрещен NULL, это ты решаешь сам при создании таблицы. Ну к примеру у комментария может и не быть родителя, в таком случае мы ставим в parent_id NULL.
> Наверное, это какой-нибудь паттерн, когда внешний ключ указывает на колонку в той же таблице?
Нет, просто связь таблицы с самой собой.
> На схеме, которую генерирует workbench, подобная связь обозначена кружком. Где об этом можно почитать доступным языком?
Анон выше вроде написал название этой системы обозначений.
> Хорошо, исправил (внесением изменений в дамп базы). Но я слышал, что так делать некошерно, и лучше использовать миграции.
Да. Миграции это способ зафиксировать изменения структуры базы данных в репозитории. Чтобы можно было вернуться к любой ревизии и воссоздать базу данных в нужном состоянии.
Также миграции это средство обмена изменениями в БД с коллегами. Ну сам представь, как без миграций разрабоитчики узнают о том что ты добавил поле? Будешь к каждому лично подходить и объяснять что поменять? Не думаю что это эффективно.
Там в статье упомянута идея писать в скайп-чат об изменениях, но я думаю, это быстро начнет раздражать так как отвлекает.
Чтобы использовать миграции надо либо фреймворк с их поддержкой либо стороннюю программу для них. Слим не поддерживает миграции, Yii2 поддерживает.
Вообще, я как-то привык пользоваться миграциями и не представляю как без них, сидеть и вручную переносить изменения с одной базы в другую мне неохота.
То что описано в посте это упрощенная система миграций из Юи 2. Только плохо что они используют устаревшие функции mysql. ЛУчше бы PDO.
> Для примера не будем брать PDO, «свелосипедим» свой класс на основе MySQL:
Это плохая идея так как непонятно зачем писать то что уже есть и сделано лучше. А в остальном статья неплохая, хотя я бы подсократил объем и сразу перешел к миграциям вместо того чтобы придумывать всякие странные варианты.
От себя добавлю что часто пишут миграции только в одну сторону, так как откат обычно не требуется. Иногда фреймворк позволяет автоматически сгенерировать обратную миграцию, если ты пишешь не SQL запросы а вызваешь методы фреймворка для добавления колонок и таблиц.
Но в общем статья хорошая и подробная. Используются фреймфорки и ООП что тоже хорошо.
> Я наверное лучше продолжу работу над заданиями из треда в фоновом режиме, а параллельно буду учить фреймворки. Потому что с такими темпами можно возиться годами над учебными задачами
Это конечно твое дело, как и в каком порядке что изучать, но я думаю, стоит уделить внимание замечаниям что я написал. Как минимум осознать что там написано.
> И на NULL в parent_id не реагирует, я думал что внешний ключ обязан указывать на уникальное значение.
NULL не нарущает уникальность так как NULL это не конкретное значение, а «неизвестно». В уникальной колонке может быть сколько угодно NULL.
Что касается внешних ключей то в них может быть как разрешен так и запрещен NULL, это ты решаешь сам при создании таблицы. Ну к примеру у комментария может и не быть родителя, в таком случае мы ставим в parent_id NULL.
> Наверное, это какой-нибудь паттерн, когда внешний ключ указывает на колонку в той же таблице?
Нет, просто связь таблицы с самой собой.
> На схеме, которую генерирует workbench, подобная связь обозначена кружком. Где об этом можно почитать доступным языком?
Анон выше вроде написал название этой системы обозначений.
> Хорошо, исправил (внесением изменений в дамп базы). Но я слышал, что так делать некошерно, и лучше использовать миграции.
Да. Миграции это способ зафиксировать изменения структуры базы данных в репозитории. Чтобы можно было вернуться к любой ревизии и воссоздать базу данных в нужном состоянии.
Также миграции это средство обмена изменениями в БД с коллегами. Ну сам представь, как без миграций разрабоитчики узнают о том что ты добавил поле? Будешь к каждому лично подходить и объяснять что поменять? Не думаю что это эффективно.
Там в статье упомянута идея писать в скайп-чат об изменениях, но я думаю, это быстро начнет раздражать так как отвлекает.
Чтобы использовать миграции надо либо фреймворк с их поддержкой либо стороннюю программу для них. Слим не поддерживает миграции, Yii2 поддерживает.
Вообще, я как-то привык пользоваться миграциями и не представляю как без них, сидеть и вручную переносить изменения с одной базы в другую мне неохота.
То что описано в посте это упрощенная система миграций из Юи 2. Только плохо что они используют устаревшие функции mysql. ЛУчше бы PDO.
> Для примера не будем брать PDO, «свелосипедим» свой класс на основе MySQL:
Это плохая идея так как непонятно зачем писать то что уже есть и сделано лучше. А в остальном статья неплохая, хотя я бы подсократил объем и сразу перешел к миграциям вместо того чтобы придумывать всякие странные варианты.
От себя добавлю что часто пишут миграции только в одну сторону, так как откат обычно не требуется. Иногда фреймворк позволяет автоматически сгенерировать обратную миграцию, если ты пишешь не SQL запросы а вызваешь методы фреймворка для добавления колонок и таблиц.
Но в общем статья хорошая и подробная. Используются фреймфорки и ООП что тоже хорошо.
>В меню вверху (HOME PORTFOLIO) у тебя слишком жирный шрифт. У тебя там стоит вес 900, а должен быть более легкий. Посмотри, какой стоит в макете. Это видно невооруженным глазом.
>То же самое с кнопкой «See Portfolio», у тебя там стоит 900.
Но ведь я делал все по макету в фотошопе. Там шрифт этих надписей Lato Black, а его вес именно 900. Еще может быть вес кажется таким что и сами размеры в принципе возможно неправильны? Я ведь рассказывал как-то про странные pt в фотошопе, которые не равны реальным pt и что я их заменял на px.
>В ИЕ10 вокруг ссылок синие рамки: https://www.browserstack.com/screenshots/14c5de63bad958d3b9d1c48d6d8dcce78bc11626
Хорошо хоть не ночью этот фильм ужасов увидел. Это как я понял можно не устанавливая кучу браузеров там посмотреть отображение в них моего сайта? Интересный сайт, разберусь ка с ним как-нибудь.
>Дальше, думаю, тебе стоит поизучать JS и/или PHP.
Пойду по JS, но пока не закончу HTML\CSS не начну. Пока вот еще во время проверки макета свободное время было я английский начал учить. Видел тут разговоры у вас про некий memrise, неплохой в принципе сайт, начал там базовый курс. Но вот что меня напугало, так это что какой-то анон тут за два дня 1.5к слов выучил, а я всего 200, не могу же я быть таким необучаемым. Хотя после первых 50 уже там все непонятные слова были, т.к. уровень английского у меня на нуле. Ну не знаю, может повлияло то, что я каждые 50 по несколько раз перепроходил чтобы наверняка запомнить.
И вот еще что, не знаю будет ли от этого польза, но не думаю, что станет хуже. Я думаю начать подписываться в треде. Зачем? Чтобы было яснее кто спрашивает. Как бы понятнее, что этот анон уже изучил, какие статьи ему уже были даны и все такое. Ну в теории вроде должно работать. С этого момента буду подписывать себя как Лунев.
И да, как обычно, все ссылки сохранил и к работе сразу же приступаю. Хотя сейчас, признаюсь, будет сложнее, чем раньше.
Это я про memrise говорил, сейчас английский временно подзабросил, хочешь скооперируемся как-нибудь, у меня тоже на нуле, только на дуолинго уроков 7 сделано. Я бампаю атмегой16 и корейским кинцом, если что.
>какой-то анон тут за два дня 1.5к слов выучил
ты не так понял.
Речь шла о читерстве в попытке выиграть конкурс.
>Если уже знаешь много слов, то можно спокойно набампать по несколько тысяч слов в день в нубских курсах.
Естественно незнакомые слова учить сложнее.
Закончил с исправлениями, относящимися к php. (Там еще сто строк замечаний по js, не успел с ними разобраться)
Есть вопросы.
>так как логаут изменяет состояние системы, его надо делать через POST
Я не знаю, как сделать запрос постом, могу только из сабмита формы. А у меня там ссылка. Как при переходе по ссылке сделать запрос через POST, а не GET?
>$file->size = ViewHelper::formatSize($file->size);
>Это неправльно. Почему одно и то же поле хранит значение в разных форматах? Как в таком коде ориентироваться, когда непонятно в каком формате там лежит значение? Так быть не должно.
Да как раз наоборот: в базе размер файла естественно у меня хранится в байтах, но при выводе в представление нужно преобразовать это число в human-readable, подобно тому что делает опция -h у команды ls в юниксах.
Наверное, тебе не понравилось, что я перезаписываю свойство объекта, который не должен меняться. А что делать? Создавать ради этой мелочи новый класс? Типа унаследовать File, принять экземпляр File в конструктор и пропустить через функцию форматирования?
>$user->fromForm($registerForm);
>Это как-то не очень правильно, получается у нас модель пользователя должна знать о форме его редактирования.
Так удобно ведь, как иначе мне создавать объект User? Можно передавать массив с полями, но ты же меня от этого отговаривал, когда я таким образом передавал кучу переменных в представление. Или здесь не тот случай? В общем, я не понял, что ты хочешь.
>https://github.com/nsdvw/file-sharing/blob/master/public_html/index.php#L255
> if ($file->isImage()) {
> тут же всего лишь выбор шаблона для отображения? Тогда это логичнее прямо в шаблоне и делать.
Разве? Какие-то условные конструкции, бизнес-логика, все это перенести в представление? Мне не очень нравится такая идея, пусть лучше я определю название подключаемого подшаблона в контроллере, и передам эту строку на рендер.
> https://github.com/nsdvw/file-sharing/blob/master/views/video_player.tpl
> https://github.com/nsdvw/file-sharing/blob/master/views/audio_player.tpl
> Эти файлы явно сделаны методом копипасты. от нее надо избавиться.
Не понимаю, там совершенно разный код.
В остальном поисправлял, стало действительно гораздо свободнее.
>>537886
>я думаю, стоит уделить внимание замечаниям что я написал. Как минимум осознать что там написано.
Я и не отказываюсь, твои ревью бесценны, только меня удручает количество убитого времени, поэтому я переосмысливаю приоритеты.
Закончил с исправлениями, относящимися к php. (Там еще сто строк замечаний по js, не успел с ними разобраться)
Есть вопросы.
>так как логаут изменяет состояние системы, его надо делать через POST
Я не знаю, как сделать запрос постом, могу только из сабмита формы. А у меня там ссылка. Как при переходе по ссылке сделать запрос через POST, а не GET?
>$file->size = ViewHelper::formatSize($file->size);
>Это неправльно. Почему одно и то же поле хранит значение в разных форматах? Как в таком коде ориентироваться, когда непонятно в каком формате там лежит значение? Так быть не должно.
Да как раз наоборот: в базе размер файла естественно у меня хранится в байтах, но при выводе в представление нужно преобразовать это число в human-readable, подобно тому что делает опция -h у команды ls в юниксах.
Наверное, тебе не понравилось, что я перезаписываю свойство объекта, который не должен меняться. А что делать? Создавать ради этой мелочи новый класс? Типа унаследовать File, принять экземпляр File в конструктор и пропустить через функцию форматирования?
>$user->fromForm($registerForm);
>Это как-то не очень правильно, получается у нас модель пользователя должна знать о форме его редактирования.
Так удобно ведь, как иначе мне создавать объект User? Можно передавать массив с полями, но ты же меня от этого отговаривал, когда я таким образом передавал кучу переменных в представление. Или здесь не тот случай? В общем, я не понял, что ты хочешь.
>https://github.com/nsdvw/file-sharing/blob/master/public_html/index.php#L255
> if ($file->isImage()) {
> тут же всего лишь выбор шаблона для отображения? Тогда это логичнее прямо в шаблоне и делать.
Разве? Какие-то условные конструкции, бизнес-логика, все это перенести в представление? Мне не очень нравится такая идея, пусть лучше я определю название подключаемого подшаблона в контроллере, и передам эту строку на рендер.
> https://github.com/nsdvw/file-sharing/blob/master/views/video_player.tpl
> https://github.com/nsdvw/file-sharing/blob/master/views/audio_player.tpl
> Эти файлы явно сделаны методом копипасты. от нее надо избавиться.
Не понимаю, там совершенно разный код.
В остальном поисправлял, стало действительно гораздо свободнее.
>>537886
>я думаю, стоит уделить внимание замечаниям что я написал. Как минимум осознать что там написано.
Я и не отказываюсь, твои ревью бесценны, только меня удручает количество убитого времени, поэтому я переосмысливаю приоритеты.
надо джумлу обновить с 1.5 до 3.4.3, плагины с этой задачей не справляются, выдают ошибку, решил вручную экспортировать записи из бд на чистую джумлу. В ходе столкнулся с тем, что есть одна колонка которая с уникальным ключом (что-то вроде алиаса вида 'column_content-10018', и мне её просто неоткуда экспортировать, в старом дереве таблиц не было ни самой такой таблицы ни колонок и вот вопрос, можно ли при (INSERT table_name (n1, n2, n3...) SELECT n1, n2. n3 ... FROM table_name2) как нибудь заполнять это значение инкрементом как в пхп ("column_content-'".$i++.'"') или как быть? просто 1000+ записей и каждую вручную обрабатывать придется как минимум день. извините за сумбурность мысли, целый день с этой джумлой провозился, голова уже не соображает
Инъекции - уязвимость пыхи, а не базы данных. Так что придется обмазаться.
Ну и да, ты опоздал лет на 10.
Например у меня $app->post(
'/file',
и тут же должен открыться $app->get(
'/file/:id',
Я делаю redirect, но оно подвисает и пока загружается иногда видно пустую страницу /file
кароче соорудил такое:
$sql = "SELECT id, name, surname, sex, stgroup, email, points, birth, phone, nonresident FROM students WHERE
CONVERT(CONCAT(name, ' ', surname, ' ', stgroup, ' ', email, ' ', points, ' ', birth, ' ', phone, ' ', nonresident) using utf8)
LIKE '{$string}'";
С русскими символами все окей, регистр не влияет, а вот с английскими все плохо - поиск вобще перестал работать.
это линукс?
Привет, аноны. Делаю задачу с php narod.
Суть - программка, которая исправляет текст, делает буквы заглавными и делает знаки препинания норм. Но у меня он не хочет исправлять элементы массива при его переборе. Почему это так. Как исправить каждый элемент массива.
<?php
error_reporting(-1);
mb_internal_encoding('utf-8');
$text = "ну что. не смотрел еще black mesa.я собирался скачать ,но все как-то некогда было.";
// Для тестов
// $text = 'roses are red,and violets are blue.whatever you do i'll keep it for you.';
// $text = 'привет.есть 2 функции,preg_split и explode ,не понимаю,в чем между ними разница.';
/ Делает первую букву в строке заглавной /
function makeFirstLetterUppercase($text) {
\t
$text1 = preg_split('/[.]/', $text, -1);
foreach ($text1 as $number => $string )
{
$firstChar = mb_substr($string, 0, 1);
$firstChar = mb_strtoupper($firstChar);
$elseChars = mb_substr($string, 1);
\t$string = $firstChar.$elseChars.". ";
}
$text2 = implode(" ", $text1);
return $text2;
}
Привет, аноны. Делаю задачу с php narod.
Суть - программка, которая исправляет текст, делает буквы заглавными и делает знаки препинания норм. Но у меня он не хочет исправлять элементы массива при его переборе. Почему это так. Как исправить каждый элемент массива.
<?php
error_reporting(-1);
mb_internal_encoding('utf-8');
$text = "ну что. не смотрел еще black mesa.я собирался скачать ,но все как-то некогда было.";
// Для тестов
// $text = 'roses are red,and violets are blue.whatever you do i'll keep it for you.';
// $text = 'привет.есть 2 функции,preg_split и explode ,не понимаю,в чем между ними разница.';
/ Делает первую букву в строке заглавной /
function makeFirstLetterUppercase($text) {
\t
$text1 = preg_split('/[.]/', $text, -1);
foreach ($text1 as $number => $string )
{
$firstChar = mb_substr($string, 0, 1);
$firstChar = mb_strtoupper($firstChar);
$elseChars = mb_substr($string, 1);
\t$string = $firstChar.$elseChars.". ";
}
$text2 = implode(" ", $text1);
return $text2;
}
Невозможна, но доступ к базе осуществляется через уязвимости в архитектуре скрипта на php.
> Почему опоздал?
Сейчас каждый второй говносайт на цмс, а там инъекцию очень сложно найти. Ооочень сложно.
У мен есть на примете самописный, есть инъекция. Не понимаю как заменить данные в таблице. В питоновебе с таким не сталкивался.
Каждое слово не получается, так как может случайно оказаться в четырёх словах может оказаться два одинаковых и одно из них будет относится к уникальным. Я вообще не против скооперироваться, напиши свою почту.
Суть в том, что для хеширования там используется метод CPasswordHelper::hashPassword($password), где каждый раз генерируется случайная соль и хешируется вместе с паролем через crypt. Таким образом hashPassword всегда дает уникальную строку.
Чудо в том, что соль-то никуда не сохраняется, а метод CPasswordHelper::verifyPassword($password, $hashFromDb) каким-то образом действительно корректно работает.
Откуда он правильную соль берет?
Вот я в файлообменнике делал так: в базу сохранял и соль, и соленый хеш. Затем проверял ( sha1($record->salt . $form->password) === $record->hash ).
Здесь же соль вроде бы генерируется каждый раз новая и уникальная, никуда не сохраняется, но тем не менее verifyPassword выдает верный результат. Я не понимаю, как это происходит и что сулит. Не хочу быть обезьянкой и пользоваться апи, не понимая, как оно работает. Но самостоятельно разобраться не могу.
Я смотрел исходный код, честно, но там какая-то дикая мешанина из base64_encode, crypt, preg_match, sprintf и прочих функций, не могу уловить логику, что там вообще происходит.
Тогда да, данные заменяются через sql-запросы. Посмотри как раскручивают sql-инъекции. Довольно много статей на эту тему.
Есть ещё всякие помощники, вроде havij, которые сами раскручивают.
Ты понял, да не все. Попробуй сделать запросы:
SELECT name, COLLATION(name) FROM students;
SELECT birth, COLLATION(birth) FROM students;
SELECT points, COLLATION(points) FROM students;
SELECT COLLATION(CONCAT(name, points)) FROM students;
Вот тут мануал если понимаешь английский:
https://dev.mysql.com/doc/refman/5.7/en/charset-general.html
https://dev.mysql.com/doc/refman/5.7/en/charset-collation-expressions.html
https://dev.mysql.com/doc/refman/5.7/en/charset-collate.html
https://dev.mysql.com/doc/refman/5.0/en/cast-functions.html
Там внизу написано:
> For implicit conversion of a numeric or temporal value to a string, such as occurs for the argument 1 in the expression CONCAT(1, 'abc'), the result is a character (nonbinary) string that has a character set and collation determined by the character_set_connection and collation_connection system variables.
Может быть еще можно поиграться с переменной collation_connection.
Если не понимаешь то суть в том что у нетекстовых колонок стоит что-то вроде binary collation (сравнивать как есть) и когда ты их используешь с CONCAT то это collation переносится на результат CONCAT.
Решения:
- попробовать явно указать CONCAT(...) COLLATE ... LIKE ...
- явно преобразовывать дату в строку с указанием collation перед тем как склеивать
- не искать по дате/баллам
- поменять collation_connection при соединении с БД, предварительно разобравшись за что она отвечает и не будет ли побочных эффектов. Дописать комментарий в коде об этом.
- сделать нечувствительность к регистру вручную:
WHERE LOWER(CONCAT(...)) LIKE LOWER(...)
В общем воспринимай эту проблему как возможность получше изучить особенности работы со строками в MySQL.
Я решил потестировать явное преобразование под linux:
SELECT COLLATION(NOW()); // binary
SELECT COLLATION(CONCAT('a', NOW())); // utf8_general_ci
SELECT COLLATION(CAST(NOW() AS CHAR)); // utf8_general_ci
SHOW VARIABLES LIKE 'collation_connection'; // utf8_general_ci
SELECT 'a' = 'A'; // 1
Похоже все же дело в этой переменной.
Тут https://dev.mysql.com/doc/refman/5.1/en/charset-connection.html пишут:
> collation_connection is important for comparisons of literal strings. For comparisons of strings with column values, collation_connection does not matter because columns have their own collation, which has a higher collation precedence.
Ты понял, да не все. Попробуй сделать запросы:
SELECT name, COLLATION(name) FROM students;
SELECT birth, COLLATION(birth) FROM students;
SELECT points, COLLATION(points) FROM students;
SELECT COLLATION(CONCAT(name, points)) FROM students;
Вот тут мануал если понимаешь английский:
https://dev.mysql.com/doc/refman/5.7/en/charset-general.html
https://dev.mysql.com/doc/refman/5.7/en/charset-collation-expressions.html
https://dev.mysql.com/doc/refman/5.7/en/charset-collate.html
https://dev.mysql.com/doc/refman/5.0/en/cast-functions.html
Там внизу написано:
> For implicit conversion of a numeric or temporal value to a string, such as occurs for the argument 1 in the expression CONCAT(1, 'abc'), the result is a character (nonbinary) string that has a character set and collation determined by the character_set_connection and collation_connection system variables.
Может быть еще можно поиграться с переменной collation_connection.
Если не понимаешь то суть в том что у нетекстовых колонок стоит что-то вроде binary collation (сравнивать как есть) и когда ты их используешь с CONCAT то это collation переносится на результат CONCAT.
Решения:
- попробовать явно указать CONCAT(...) COLLATE ... LIKE ...
- явно преобразовывать дату в строку с указанием collation перед тем как склеивать
- не искать по дате/баллам
- поменять collation_connection при соединении с БД, предварительно разобравшись за что она отвечает и не будет ли побочных эффектов. Дописать комментарий в коде об этом.
- сделать нечувствительность к регистру вручную:
WHERE LOWER(CONCAT(...)) LIKE LOWER(...)
В общем воспринимай эту проблему как возможность получше изучить особенности работы со строками в MySQL.
Я решил потестировать явное преобразование под linux:
SELECT COLLATION(NOW()); // binary
SELECT COLLATION(CONCAT('a', NOW())); // utf8_general_ci
SELECT COLLATION(CAST(NOW() AS CHAR)); // utf8_general_ci
SHOW VARIABLES LIKE 'collation_connection'; // utf8_general_ci
SELECT 'a' = 'A'; // 1
Похоже все же дело в этой переменной.
Тут https://dev.mysql.com/doc/refman/5.1/en/charset-connection.html пишут:
> collation_connection is important for comparisons of literal strings. For comparisons of strings with column values, collation_connection does not matter because columns have their own collation, which has a higher collation precedence.
Допустим в C#, как вариант? Очень искушают з/п
Числа и даты в MySQL преобразуется в строку (перед склеиванием) и им присваивается collation из collation_connection. у меня на линуксе она регистронезависимая у тебя очевидно регистрозависимая.
Задать ее можно через SET NAMES COLLATE
Если понимаешь английский, почитай мануал по ссылкам и разберись.
>>537928
Я могу ошибаться, но посмотри какой шрифт на жирной надписи Webpaint. Мне кажется 900 это на ней, а в меню меньше.
Если открыть архив с веб шрифтами то там много степеней веса:
Lato-Hairline.ttf
Lato-Thin.ttf
Lato-Light.ttf
Lato-Regular.ttf (regular это 400)
Lato-Medium.ttf
Lato-Semibold.ttf
Lato-Bold.ttf (это 700)
Lato-Heavy.ttf
Lato-Black.ttf (это очевидно 900)
Попробуй поставить 700 вместо 900 в меню и на кнопках и сравнить на глаз. Мне кажется что там должен быть менее жирный шрифт, у меня в Хроме он такой жирный что буквы вытекают из своих границ.
Я не могу посмотреть в фотошопе, так как у меня lato не установлен и фотошоп заменяет его при попытке кликнуть.
Хотя может там и 900, я попробовал поставить 700 и надписи стали тоньше чем в фотошопе. В общем, посмотри на глаз.
> Еще может быть вес кажется таким что и сами размеры в принципе возможно неправильны?
Может быть так как фотошоп и разные браузеры в разных ОС используют разные алгоритмы рендеринга. Разные алгоритмы исплоьзуются так как есть рендерить честно то на маленьких размерах шрифты получаются мыльными (так как пиксели на экране большие и глаз это видит). Потому используется хинтинг, то есть прижимание линий шрифта к границам пикселей, что приводит к искажению формы но увеличению резкости границ.
Это все работает на маленьких размерах букв, на больших размерах или на экранах с высокой плотностью пикселей (ретина) искажений меньше.
А в древних ОС типа XP вообще по умолчанию отключено сглаживание шрифта и буквы там ступенчатые, то есть там нет полузакрашенных пикселей:
http://habrahabr.ru/post/166291/
Я помню, раньше мне даже приходилось ставить в браузере цвет чуть светлее или темнее, чтобы компенсировать изменение жирности текста, чтобы он выглядел ближе к макету. но подвох в том что разные ОС используют разные алгоритмы и ты можешь приблизить к макету только одну из них.
Вот еще интересная статья про алгоритмы рендеринга, и то как можно повысить качество рендеринга шрифтов (не в браузере а на уровне ОС): http://www.antigrain.com/research/font_rasterization/index.html
Увы, она на английском, но зато очень много интересной информации содержит.
В CSS есть свойства влияющие на алгоритм рендеринга:
https://developer.mozilla.org/en-US/docs/Web/CSS/text-rendering
http://habrahabr.ru/post/122269/
Не используй их.
Вывод: шрифты рендерятся по-разному. Не рассчиытвай на попиксельное соответствие и совпадение размеров и формы букв на разных ОС.
Числа и даты в MySQL преобразуется в строку (перед склеиванием) и им присваивается collation из collation_connection. у меня на линуксе она регистронезависимая у тебя очевидно регистрозависимая.
Задать ее можно через SET NAMES COLLATE
Если понимаешь английский, почитай мануал по ссылкам и разберись.
>>537928
Я могу ошибаться, но посмотри какой шрифт на жирной надписи Webpaint. Мне кажется 900 это на ней, а в меню меньше.
Если открыть архив с веб шрифтами то там много степеней веса:
Lato-Hairline.ttf
Lato-Thin.ttf
Lato-Light.ttf
Lato-Regular.ttf (regular это 400)
Lato-Medium.ttf
Lato-Semibold.ttf
Lato-Bold.ttf (это 700)
Lato-Heavy.ttf
Lato-Black.ttf (это очевидно 900)
Попробуй поставить 700 вместо 900 в меню и на кнопках и сравнить на глаз. Мне кажется что там должен быть менее жирный шрифт, у меня в Хроме он такой жирный что буквы вытекают из своих границ.
Я не могу посмотреть в фотошопе, так как у меня lato не установлен и фотошоп заменяет его при попытке кликнуть.
Хотя может там и 900, я попробовал поставить 700 и надписи стали тоньше чем в фотошопе. В общем, посмотри на глаз.
> Еще может быть вес кажется таким что и сами размеры в принципе возможно неправильны?
Может быть так как фотошоп и разные браузеры в разных ОС используют разные алгоритмы рендеринга. Разные алгоритмы исплоьзуются так как есть рендерить честно то на маленьких размерах шрифты получаются мыльными (так как пиксели на экране большие и глаз это видит). Потому используется хинтинг, то есть прижимание линий шрифта к границам пикселей, что приводит к искажению формы но увеличению резкости границ.
Это все работает на маленьких размерах букв, на больших размерах или на экранах с высокой плотностью пикселей (ретина) искажений меньше.
А в древних ОС типа XP вообще по умолчанию отключено сглаживание шрифта и буквы там ступенчатые, то есть там нет полузакрашенных пикселей:
http://habrahabr.ru/post/166291/
Я помню, раньше мне даже приходилось ставить в браузере цвет чуть светлее или темнее, чтобы компенсировать изменение жирности текста, чтобы он выглядел ближе к макету. но подвох в том что разные ОС используют разные алгоритмы и ты можешь приблизить к макету только одну из них.
Вот еще интересная статья про алгоритмы рендеринга, и то как можно повысить качество рендеринга шрифтов (не в браузере а на уровне ОС): http://www.antigrain.com/research/font_rasterization/index.html
Увы, она на английском, но зато очень много интересной информации содержит.
В CSS есть свойства влияющие на алгоритм рендеринга:
https://developer.mozilla.org/en-US/docs/Web/CSS/text-rendering
http://habrahabr.ru/post/122269/
Не используй их.
Вывод: шрифты рендерятся по-разному. Не рассчиытвай на попиксельное соответствие и совпадение размеров и формы букв на разных ОС.
http://ideone.com/dtGKwz
Насчет английского, я бы не концентрировался только на заучивании слов. Мне кажется, стоит еще тексты читать (со словарем) и фильмы смотреть с субтитрами. Текст хорош тем что ты во-первых запоминаешь не слова, а целые конструкции, во-вторых можно догадываться о смысле слов по окружающим словам и по ситуации (если речь о фильме). Ну и по моему текст читать или фильм смотреть интереснее получается.
>>537986
> Я не знаю, как сделать запрос постом, могу только из сабмита формы
Сделать форму, кнопку и средствами CSS поменять ее внешний вид чтобы она была похожа на ссылку. В бутстрапе есть готовый класс для этого (button-link или как-то так, не помню).
Аналогично, есть возможность сделать чтобы ссылка выглядела как кнопка. Ты должен уметь и то и другое.
Ну или JS, но мне кажется тут чистым CSS все решается.
> Да как раз наоборот: в базе размер файла естественно у меня хранится в байтах, но при выводе в представление нужно преобразовать это число в human-readable, подобно тому что делает опция -h у команды ls в юниксах.
делай это в шаблоне:
<?= ViewHelper::formatSize($file->size) ?>
Не должно быть такого что в поле значение может храниться в разных форматах. Как можно надежно писать код когда ты не знаешь в каком виде там данные? Ты усложняешь жизнь тому кто будет поддерживать этот код. Не надо так.
Это же относится и к паролю и хешу пароля. Они не должны смешиваться так как это разные вещи.
> Типа унаследовать File, принять экземпляр File в конструктор и пропустить через функцию форматирования?
Нет, просто преобразовывать данные только в момент вывода а не заранее. Либо сделать метод $file->getHumanReadableSize() но по моему это лишнее.
> Так удобно ведь, как иначе мне создавать объект User?
$user = $form->getUser( ) ;
$user = $form->user;
Причем у тебя по моему идет дублирование полей: у тебя есть User со свойствами типа name/email и RegisterForm c такими же свойствами. Зачем? Сделай чтобы внутри RegisterForm был объект User:
class RegisterForm
{
public $user;
public $password;
...
Заметь что password мы храним отдельно так как в юзере нет такого поля (там есть поле для хеша, но это не то же самое).
Фактически ведь RegisterForm это форма для заполнения свойств User, потому логично что внутри нее будет модель User.
Заметь что таким образом мы получили возможность использовать эту же форму для редактирования данных пользователя, нам достаточно просто в нее засунуть существующий объект User вместо пустого.
> В общем, я не понял, что ты хочешь.
Если то, что выше не очень понятно, задавай уточняющие вопросы.
> Разве? Какие-то условные конструкции, бизнес-логика, все это перенести в представление? Мне не очень нравится такая идея, пусть лучше я определю название подключаемого подшаблона в контроллере, и передам эту строку на рендер.
Да нет там логики, один if/else это не логика. Просто мне кажется что тут наоборот, ты выносишь детали представления из него в контроллер.
> Не понимаю, там совершенно разный код.
Ок, действительно разный. Пусть тогда остается.
Насчет английского, я бы не концентрировался только на заучивании слов. Мне кажется, стоит еще тексты читать (со словарем) и фильмы смотреть с субтитрами. Текст хорош тем что ты во-первых запоминаешь не слова, а целые конструкции, во-вторых можно догадываться о смысле слов по окружающим словам и по ситуации (если речь о фильме). Ну и по моему текст читать или фильм смотреть интереснее получается.
>>537986
> Я не знаю, как сделать запрос постом, могу только из сабмита формы
Сделать форму, кнопку и средствами CSS поменять ее внешний вид чтобы она была похожа на ссылку. В бутстрапе есть готовый класс для этого (button-link или как-то так, не помню).
Аналогично, есть возможность сделать чтобы ссылка выглядела как кнопка. Ты должен уметь и то и другое.
Ну или JS, но мне кажется тут чистым CSS все решается.
> Да как раз наоборот: в базе размер файла естественно у меня хранится в байтах, но при выводе в представление нужно преобразовать это число в human-readable, подобно тому что делает опция -h у команды ls в юниксах.
делай это в шаблоне:
<?= ViewHelper::formatSize($file->size) ?>
Не должно быть такого что в поле значение может храниться в разных форматах. Как можно надежно писать код когда ты не знаешь в каком виде там данные? Ты усложняешь жизнь тому кто будет поддерживать этот код. Не надо так.
Это же относится и к паролю и хешу пароля. Они не должны смешиваться так как это разные вещи.
> Типа унаследовать File, принять экземпляр File в конструктор и пропустить через функцию форматирования?
Нет, просто преобразовывать данные только в момент вывода а не заранее. Либо сделать метод $file->getHumanReadableSize() но по моему это лишнее.
> Так удобно ведь, как иначе мне создавать объект User?
$user = $form->getUser( ) ;
$user = $form->user;
Причем у тебя по моему идет дублирование полей: у тебя есть User со свойствами типа name/email и RegisterForm c такими же свойствами. Зачем? Сделай чтобы внутри RegisterForm был объект User:
class RegisterForm
{
public $user;
public $password;
...
Заметь что password мы храним отдельно так как в юзере нет такого поля (там есть поле для хеша, но это не то же самое).
Фактически ведь RegisterForm это форма для заполнения свойств User, потому логично что внутри нее будет модель User.
Заметь что таким образом мы получили возможность использовать эту же форму для редактирования данных пользователя, нам достаточно просто в нее засунуть существующий объект User вместо пустого.
> В общем, я не понял, что ты хочешь.
Если то, что выше не очень понятно, задавай уточняющие вопросы.
> Разве? Какие-то условные конструкции, бизнес-логика, все это перенести в представление? Мне не очень нравится такая идея, пусть лучше я определю название подключаемого подшаблона в контроллере, и передам эту строку на рендер.
Да нет там логики, один if/else это не логика. Просто мне кажется что тут наоборот, ты выносишь детали представления из него в контроллер.
> Не понимаю, там совершенно разный код.
Ок, действительно разный. Пусть тогда остается.
Ответьте на вопрос внутри кода пожалуйста ^.^
Можно написать PHP скрипт который перенесет записи и проставит что нужно. Я думаю на PHP это делать удобнее чем средствами SQL.
1000 записей это немного.
>>538018
Глупости. SQL инъекции возможны в любом языке при желании и средства борьбы с ними (использование плейсхолдеров) не привязаны к языку.
>>538004
Нельзя работать с кодом на PHP не зная PHP.
А с какого языка ты пришел? Как там борются с SQL инъекциями и работают с БД?
>>538073
Ты пишешь чушь. Возможность инъекции не зависит от языка а зависит от используемых методоы работы с БД.
>>538038
$app->map, смотри мануал
Также можно вынести код в функцию и вызывать ее.
> Например у меня $app->post(
> '/file',
> и тут же должен открыться $app->get(
> '/file/:id',
Теоретически это наверно возможно но делать так не стоит, так как это порождает путаницу. Если речь об отправке формы то лучше отправлять ее на тот же адрес по которому она выводится.
>>538039
> LIKE '{$string}'";
Нельзя вставлять переменные в SQL код, это SQL инъекция, используй плейсхолдеры.
>>538052
Нельзя вставлять переменные в SQL код, это SQL инъекция, используй плейсхолдеры.
>>538061
Код лучше постить на ideone.
> Но у меня он не хочет исправлять элементы массива при его переборе.
Потому что $string это не значение элемента массива, а его копия. Ты меняешь только копию. Менять массив надо так:
$array[$key] = ....;
Также, не называй переменные text1, text2.
В данном случае это массив предложений и надо называть его sentences.
>>538093
Это тред не для обсуждения взлома сайтов. Иди лучше домашнюю работу сделай, у вас же уже каникулы закончились.
Можно написать PHP скрипт который перенесет записи и проставит что нужно. Я думаю на PHP это делать удобнее чем средствами SQL.
1000 записей это немного.
>>538018
Глупости. SQL инъекции возможны в любом языке при желании и средства борьбы с ними (использование плейсхолдеров) не привязаны к языку.
>>538004
Нельзя работать с кодом на PHP не зная PHP.
А с какого языка ты пришел? Как там борются с SQL инъекциями и работают с БД?
>>538073
Ты пишешь чушь. Возможность инъекции не зависит от языка а зависит от используемых методоы работы с БД.
>>538038
$app->map, смотри мануал
Также можно вынести код в функцию и вызывать ее.
> Например у меня $app->post(
> '/file',
> и тут же должен открыться $app->get(
> '/file/:id',
Теоретически это наверно возможно но делать так не стоит, так как это порождает путаницу. Если речь об отправке формы то лучше отправлять ее на тот же адрес по которому она выводится.
>>538039
> LIKE '{$string}'";
Нельзя вставлять переменные в SQL код, это SQL инъекция, используй плейсхолдеры.
>>538052
Нельзя вставлять переменные в SQL код, это SQL инъекция, используй плейсхолдеры.
>>538061
Код лучше постить на ideone.
> Но у меня он не хочет исправлять элементы массива при его переборе.
Потому что $string это не значение элемента массива, а его копия. Ты меняешь только копию. Менять массив надо так:
$array[$key] = ....;
Также, не называй переменные text1, text2.
В данном случае это массив предложений и надо называть его sentences.
>>538093
Это тред не для обсуждения взлома сайтов. Иди лучше домашнюю работу сделай, у вас же уже каникулы закончились.
Идея MVC в том что модель (в том числе код работы с базой) не знает ничего про HTTP запросы и POST переменные. Это задача контроллера.
Логика примерно такая, в контроллере создаем модельку и заполняем ее:
$post = new Post;
$post->text = isset($_POST['text']) ? strval($_POST['text']) : '';
...
А потом проверяем и если все ок, сохраняем через дата маппер:
if ($validator->isValid($
$postMapper->save($post);
} else {
....
>>538138
> Чудо в том, что соль-то никуда не сохраняется, а метод CPasswordHelper::verifyPassword($password, $hashFromDb) каким-то образом действительно корректно работает.
Соль вписывается в начало хеша, сдампь его и посмотри. Так делают с древних времен.
Ну и глянь код + мануал
> https://github.com/yiisoft/yii/blob/1.1.16/framework/utils/CPasswordHelper.php#L94
http://php.net/manual/ru/function.crypt.php
Также имей в виду что Юи 2 новее и лучше бы изучать и его. также в новом PHP появились готовые функции для надежного хеширования пароля и проверки хеша, изучи их.
Если какое-то конкретное место в коде непонятно, давай ссылку, объясню.
Идея MVC в том что модель (в том числе код работы с базой) не знает ничего про HTTP запросы и POST переменные. Это задача контроллера.
Логика примерно такая, в контроллере создаем модельку и заполняем ее:
$post = new Post;
$post->text = isset($_POST['text']) ? strval($_POST['text']) : '';
...
А потом проверяем и если все ок, сохраняем через дата маппер:
if ($validator->isValid($
$postMapper->save($post);
} else {
....
>>538138
> Чудо в том, что соль-то никуда не сохраняется, а метод CPasswordHelper::verifyPassword($password, $hashFromDb) каким-то образом действительно корректно работает.
Соль вписывается в начало хеша, сдампь его и посмотри. Так делают с древних времен.
Ну и глянь код + мануал
> https://github.com/yiisoft/yii/blob/1.1.16/framework/utils/CPasswordHelper.php#L94
http://php.net/manual/ru/function.crypt.php
Также имей в виду что Юи 2 новее и лучше бы изучать и его. также в новом PHP появились готовые функции для надежного хеширования пароля и проверки хеша, изучи их.
Если какое-то конкретное место в коде непонятно, давай ссылку, объясню.
Вот вдогонку еще ссылка про рендеринг шрифтов: http://www.joelonsoftware.com/items/2007/06/12.html
>>538282
Можно наверно.
>>538305
> $Bar->foo и $Foo - это один и тот же объект или два разных?
Сделай var_dump и посмотри на идентификаторы объектов и станет ясно.
Я могу сказать что в такой ситуации:
$a = new A;
$b = $a;
И $b и $a содержат ссылку на один и тот же объект. Чтобы при копировании создвался новый объект надо явно использовать оператор clone:
$b = clone $a;
Также, метод getFoo должен называться setFoo
Также, переменные пишут с маленькой буквы.
Вот вдогонку еще ссылка про рендеринг шрифтов: http://www.joelonsoftware.com/items/2007/06/12.html
>>538282
Можно наверно.
>>538305
> $Bar->foo и $Foo - это один и тот же объект или два разных?
Сделай var_dump и посмотри на идентификаторы объектов и станет ясно.
Я могу сказать что в такой ситуации:
$a = new A;
$b = $a;
И $b и $a содержат ссылку на один и тот же объект. Чтобы при копировании создвался новый объект надо явно использовать оператор clone:
$b = clone $a;
Также, метод getFoo должен называться setFoo
Также, переменные пишут с маленькой буквы.
там надо переписать код примерно так:
- прибавляем проценты и комиссию к остатку долга
- если остаток маленький, выплачиваем сколько осталось и уходим
- иначе платим 5000
«Платим» здесь значит уменьшаем долг и увеличиваем общую сумму выплаченного.
А у тебя анон каким-то чудесным образом в последний месяц платит 5000 + остаток, хотя у него нет таких денег.
Ответ должен получиться около 61270.
> If ($creditbalance = 0)
Это никогда не сработает так как = это сохранение значения в переменную и получается эквивалент
if (0)
Который никогда не сработает (так как 0 при преобразовании в булев тип дает false).
>Также, метод getFoo должен называться setFoo
Почему? Я же не меняю значение, а хочу получить его. А понял, это из-за путаницы в одинаковых названиях классов и переменных?
Ты меняешь.
getFoo это такой метод:
public function getFoo()
{
return $this->foo;
}
Используется так:
$foo = $bar->getFoo();
Это получение foo из объекта.
А то что у тебя это set. Ты же его используешь в стиле
$bar->setFoo($foo);
Это явно не получение, а установка свойства foo в указанное значение.
Получение или установка надо определять со стороны внешнего наблюдателя. А не со стороны объекта.
Если там 3 строки то лучше 2 функции. Если много то можно сделать одну сложную функцию, а к ней 2 функции-фасада, вызывающих ее с нужными параметрами.
Понятно, спасибо тебе большое ^.^
>выплачиваем сколько осталось и уходим
С этим проблема, как задать это "сколько осталось"?
>>538318
>Это никогда не сработает так как = это сохранение значения в переменную и получается эквивалент
>if (0)
>Который никогда не сработает (так как 0 при преобразовании в булев тип дает false).
Тупанул, там двойное равно нужно
http://ideone.com/dtGKwz
В итоге получается только остановиться на сумме долга <5000к. Не пойму как удалить остаток, чтоб написало, мол должен 0 и сколько всего заплатил.
> С этим проблема, как задать это "сколько осталось"?
У тебя есть переменная, хранящая текущий долг банку. В начале месяца долг увеличивается на процент и комиссию. Если на каком-то месяце долг стал меньше 5000, например равен 1234 то мы выплачиваем 1234 рубля и выходим из цикла.
Твой код неправильный. Он делает так:
- прибавляем процент, комиссию к сумме долга, платим 5000
- если долг меньше 5000 то доплачиваем еще сколько-то, но ведь анон не может за месяц выплатить больше 5000
Причем ты доплачиваешь даже больше чем надо:
>\t$paymentTotal = $paymentTotal + $monthlyPayment + $paymentLeft;
Ты выплачиваешь остаток долга + непонятно откуда взявшиеся 5000.
Ты взял за основу неправильный код из учебника, а надо его переделать либо писать самому.
Если тебе не очень понятно как он работает, то добавь там echo который выводит значения всех переменных на каждом шаге.
В общем, у тебя код действительно запутанный и проще наверно стереть его и написать заново, чем разобраться.
if($creditBalance = 0)
А ю факин киддин ми! Вы хоть учебники по синтаксису читаете перед решением говнозадач от говноопа?
Почитай PSR для начала. Нас интересует общепринятый стиль оформления кода, а не как принято писать в вашей подвальной вебстудии.
Это не подвальный стиль а простая логика и читабельность. Хотя-бы сразу видно где for начинается и где кончается. Для тех кто писал больше чем 15 строчек кода - это важно весьма полезно.
Мануал читал? bindParam это двухсторонняя привязка и используется например для вызова хранимых процедур которые могут менять значение переменной.
bindParam принимает только переменную, но не выражение.
Ты вряд ли их используешь так что тебе нжен bindValue.
Урок читал? Если нет то прочти теорию с начала: https://gist.github.com/codedokode/65d43ca5ac95c762bc1a
исключения нужны для завершения работы функции в случае непредвиденной ошибки, не дающей возможности получить правильный результат.
Да, читал, но мне все равно не понятно. Мне что к каждой функции применять исключение?
Давай на конкретных примерах кода разбираться. Покажи пример функции и что ты хочешь/не хочешь туда добавлять.
Они работают как возврат из нескольких функций сразу, такой вот дальний оператор возврата.
Нужны в задачах доступа к файлам и СУБД, больше почти нигде нинужны.
Вот канонiчный пример, хоть и не на Пыхе.
> У меня самого нет ВО. Ни разу, ни единого никто даже не спросил. Работал в Яндексе, Островке, сейчас в Букинге.
По моему этим все сказано.
(однако предупрежу что в эти компании кого попало не берут, даже пройти все наши задачи будет недостаточно, а уж сомнительные видеокурсы и кодеакадеми тем более).
Сегодня будем разбираться с задачей про взвешивание монет. Такие задачи периодически встречаются на олимпиадах, мы конечно начнем с простых их версий.
Задача 1. Дано 12 монет, среди них одна фальшивая, которая тяжелее настоящей. Вы можете взвешивать монеты на весах с 2 чашами. За сколько взвешиваний можно ее найти?
Задача 2. Дано 12 монет, среди них одна фальшивая, известно что она отличается по весу от настоящей, но неизвестно в какую сторону. За сколько взвешиваний можно ее найти?
Задача 3. Попробуйте найти обобщенное решение для задач выше, то есть определите сколько нужно взвешиваний не только для 12 монет, а для произвольного числа монет. ну то есть нам дано 100 или 200 монет, сколько нужно взвешиваний в каждом случае?
Если вы решали олимпиадные задачки, пишите под спойлером или не пишите вообще. Это задачка для начинающих, а не опытных программистов. Не бойтесь, это не задача с олимпиад, а максимально упрощенная ее версия.
Аноны, пишите ваши рассуждения, желательно под спойлером. Задачки несложные, тут при желании все 12 вариантов можно на бумаге расписать.
Потом, если вы решите, мы посмотрим и может быть дадим вам более сложные ее варианты. Главное тут понять общий принцип решения таких задач.
>>538376
Покажи код.
>>538377
Странный язык и странный код. Также ты по моему не все понял, исключения нужны для обработки исключительных сиутаций, а выход из нескольких функций это не их назначение, а способ обработки этих ситуаций.
Вот, вот здесь ты сделал мне замечание
https://github.com/someApprentice/Cat-and-Mouse/blob/91a5e7159e0668b6bac1d638adb6295113b6dff8/Classes/World.php#L36
>>536831
> https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/World.php#L36
> if (!isset($from['x']) and !isset($from['y']) and !isset($to['x']) and !isset($to['y'])) {
> return false
>Ты пишешь return false, а ты везде проверяешь что вернула эта функция? А если программист забудет написать проверку? В мире ООП у нас для ошибок есть исключения, почитай урок: https://gist.github.com/codedokode/65d43ca5ac95c762bc1a
Я сейчас исправил это, но все равно хочется разобраться почему не правильно было.
https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/World.php#L55
https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/Mouse.php#L111
В мире исключений проверка что переданы все верные параметры делается так:
if (!isset($from['x']) and !isset($from['y']) and !isset($to['x']) and !isset($to['y'])) {
throw new Exception("Missing x or y from to or from array");
}
По умолчанию исключение завершает программу и выводится его текст.
Исключение лучше чем return false так как:
— программисты обычно не проверяют результат возврата функции и ошибка будет игнорироваться. Недопустимо игнорировать ошибки в программе. Исключение не позволит это сделать.
— не надо загрязнять программу ифами с проверкой результата функции
Но я напомню, что по моему там проще сделать вместо 2 массивов 4 обычных переменных и проверка станет ненужной.
>Задача 1. Дано 12 монет, среди них одна фальшивая, которая тяжелее настоящей. Вы можете взвешивать монеты на весах с 2 чашами. За сколько взвешиваний можно ее найти?
Для начала возьмем монету которая заведомо не является фальшивой. Это любая из двух монет, которые равны на весах. Так, берем эти монетки. Всего монет 12. Одну откладываем, она нам не нужна((12 - 1) монет осталось), другую оставим себе и будем сравнивать с ней((11 - 1) монет осталось). Осталось 10 монет. Фальшивая та, которая качнет весы в свою сторону. Значит кол-во сравнений от 1 до 10, в зависимости от того какой по счету будет фальшивая монета.
Решение в лоб, и далеко не оптимальное, проиграл сам с себя.
Я наверно плохо написал условие, задача найти такое число взвешиваний которое позволит гарантированно определить монету. То есть ответ должен быть не «от 1 до 10», а 10.
Также, ты пишешь
> Это любая из двух монет, которые равны на весах.
Это нужно одно взвешивание, ты его учел?
Я подскажу что твой подход довольно неэффективен. Мы например можем поделить монеты на группы по 6, сравнить их и определить в какой фальшивая монета. За одно взвешивание мы уменьшили число монет в 2 раза и свели задачу к задаче на 6 монет.
Давай подумаем еще. И старайся писать под спойлером если тебе придет в голову хорошая мысль.
вот этот шаг можно викинуть
>Для начала возьмем монету которая заведомо не является фальшивой. Это любая из двух монет, которые равны на весах.
возможно что простой перебор может оказаться быстрее, все дело в том в какой последовательности производить сравнение и в каком месте окажется искомый элемент. Снова проиграл с себя.
http://wiki.webmoney.ru/projects/webmoney/wiki/%D0%98%D0%BD%D1%82%D0%B5%D1%80%D1%84%D0%B5%D0%B9%D1%81_X1
Поясните, как проводить оплату от одного кошелька на другой через сайт. Я в XML плохо разбираюсь. Вкратце можете описать пример, как это все должно быть реализовано??
а, не, вру. Еще третье взвешивание - две монеты из полученных трех.
Понятно, меньше return false больше исключений.
Я пока помогу с теоретической оценкой. Мы можем определить теоретический предел, меньше которого ответ быть не может. Ну например невозможно гарантированно определить монету за 1 взвешивание. Почему?
Смотрите, у задачи 1 существует ровно 12 исходов. Одна из 12 монет фальшивая. Одно взвешивание (любого числа монет) дает нам 3 исхода: левая чаша тяжелее, правая тяжелее или они равны. Очевидно что информации тут недостаточно.
Два взвешивания дают нам 3 × 3 = 3 ^ 2 = 9 исходов. 9 меньше чем 12, потому эта информация также не дает нам возможности указать на фальшивую монету.
Таким образом за 1 или 2 взвешивания нельзя гарантированно определить фальшивую монету в заадче 1.
Не буду скрывать, я не сам это придумал, а прочел, но я впечатлен, мы не решая задачу можем уже сделать оценку каким должен быть ответ. Разве это не блестящая идея?
Ты должен рассматривать наихудший случай. То есть если ты взвешиваешь монеты по одной, рассматривай случай когда фальшивая попадется последней, а не первой.
>>538398
Если ты плохо разбираешься в XML то начни с его изучения. Нет никакого смысла пересказывать то что описано где-то еще.
Если у тебя есть конкретный вопрос то это другое дело, но мануалы тут мы не пересказываем.
>>538399
Два взвешивания не дадут нужного объема информации так как они дают только 3×3 = 9 вариантов исходов.
>Я подскажу что твой подход довольно неэффективен. Мы например можем поделить монеты на группы по 6, сравнить их и определить в какой фальшивая монета. За одно взвешивание мы уменьшили число монет в 2 раза и свели задачу к задаче на 6 монет.
порисовал, действительно если разделить на 2 группы по шесть, кол-во взвешиваний равно от 1 до 6, то есть гарантированно за 6 взвешиваний можно найти фальшивку.
код был примерно таким
$sql=$app->db->prepare("SELECT shit from shit values (':shit')");
$sql->bindValus(':shit', $shit, PARAM bla bla INT);
$sql->execute();
Это пиар. Дроны в настоящее время не имеют никакой выгоды, кроме привлечения внимания журналистов.
Также, я считаю плохо что сейчас эта сфера никак не регулируется. Очевидно, что дроны не должны летать где попало, так как представляют опасность жизни и здоровью, создают риск катастроф, например при полете около аэропортов (такие случаи уже есть, чего-чего а идиотов среди населения планеты предостаточно). Также очевидно должны быть методы выявления владельца аппарата для привелечения его к ответственности.
Однако есть области, где использование беспилотных аппаратов может принести пользу. Это например доставка товаров в труднодоступную местность (Сибирь, тундра, степи, пустыни). Летящий на небольшой высоте над ненаселенной местностью дрон там никому не вредит. А над Москвой например летать конечно они не должны, да и проблем с доставкой там нету.
Также их можно использовать для охраны государственной границы.
А почему ты не пишешь текст ошибки? Ты думаешь мы тут телепаты и сами догадаемся? PDO выбрасывает исключение при ошибке и там есть подробности которые ты почему-то не привел.
кавычки вокруг плейсхолдера в запросе лишние.
Также, код работы с БД надо выносить в отдельный класс, а ты этого не делаешь.
>Насчет английского, я бы не концентрировался только на заучивании слов. Мне кажется, стоит еще тексты читать (со словарем) и фильмы смотреть с субтитрами. Текст хорош тем что ты во-первых запоминаешь не слова, а целые конструкции, во-вторых можно догадываться о смысле слов по окружающим словам и по ситуации (если речь о фильме). Ну и по моему текст читать или фильм смотреть интереснее получается.
Я и не концентрируюсь. Просто только начал еще. Да и уровень владения языком даже ниже самой убогой школьной программы, я в школе и не учил не было учителя в школе, только в 11 классе появился, но это была молодая девушка только с универа, а в универе только на первом курсе небольшой курс юридического английского, который к 3 курсу уже весь забылся. Совсем ничего в общем. Я на memrise решил хотя бы базовый курс пройти, а потом уже искать уроки, где обучали бы временам и всему такому, т.к. совсем не ориентируюсь в этом. Для просмотра фильмов на английском я еще не готов. Но обязательно это буду делать в будущем.
>Задача 1
За 3 взвешивания.
>Задача 2
За 4 взвешивания.
>Задача 3
Тут сомнения. Пока так: 1) отсыпаем максимальную часть от данного числа монет, которая делится на 3^n (в худшем случае фальшивая монета окажется в большем куске, этот случай и рассматриваем далее); 2) берём эту часть, делим на 3 горсти; 3) 2 горсти кладём на весы, 1 у нас; 4) смотрим на весы: на одном уровне -- фальшивка у нас, на разных -- где-то на весах; 5) дополнительным взвешиванием выясняем, в какую сторону отличается вес фальшивки; 6) делим на 3 горсти, 2 взвешиваем, 1 у нас 7) весы наравне -- фальшивка у нас, весы на разном уровне -- используя полученную на шаге #5 информацию о весе фальшивки, определяем горсть, в которой она находится; 8) если число монет в горсти больше одной, повторить действия с пункта #6 до текущего.
P. S. То есть в 3-й задаче ответ такой: при самом неблагоприятном исходе число взвешиваний равно n (степень тройки) плюс один.
Плейсхолдеры вместо переменных ставит - вот чо пишет.
PHPformatter не помог.
http://ideone.com/Wl3Y9D
Спасибо за совет, буду стараться делать больше отступов
Ты по первой задаче не пояснил.
По третьей задаче, ты написал для случая, когда неизвестен вес фальшивой монеты, а если известен?
№1
В первой всё как в третьей, но вес фальшивки известен. Отбросили 3 монеты, осталось 9. Делим на три кучи, взвешиваем две из них. В худшем случае чаши весов на одном уровне, тогда надо удостовериться, что фальшивая монета у нас (1 доп. взвешивание). В зависимости от исхода, далее взвешиваем 3 наши монеты или 3 отброшенные на первом шаге. В принципе, тут можно и в лоб пойти: разделить всё на три кучи, взвесить две кучи, останется 4 монеты (не делится на три), что так же потребует одного дополнительного взвешивания. Итого 3 в обоих случаях.
№3
Если известен, то n+1, если неизвестен, то n+2.
>№3
>Если известен, то n+1, если неизвестен, то n+2.
То есть в случае, когда отличие веса монеты известно, его выяснять не требуется. Выяснение занимает одно взвешивание (пункт #5).
Кроме времен там учить нечего, да и те элементарны в виде таблички 3х4. Попробуй игрулю типа ведьмака на английском пройти, прочти что-нибудь простенькое на русском а потом то же самое на английском, например Andy Weir "The Marsian". Книжка дурацкая, но язык очень простой, для обучения самое то.
Если тебе интересно, как называется функция которая определяет в какую степень надо возвести A чтобы получить B, то это логарифм числа B по основанию A. Ты наверно его имел в виду под n.
Ответ на первую задачу верный, со второй в общем все сложнее, там есть хитрые способы приблизиться к теоретически возможному минимуму (минимум определяется через объем иенформации (число вариантов исходов) которую мы получаем от взвешиваний).
Я попозже тогда распишу, а пока тебе дам ссылочки с правильными ответами:
http://www.ega-math.narod.ru/Quant/Shestpl.htm
http://habrahabr.ru/post/243461/
>>538418
Тут у тебя ошибочка в рассуждениях:
> 4) смотрим на весы: на одном уровне -- фальшивка у нас, на разных -- где-то на весах;
Если весы показывают разный вес, то есть 2 варианта: фальшивка либо в третьей куче, либо в куче которую мы отбросили на первом этапе.
Мне кажется в качестве простого текста подойдет какая-нибудь сказка. Их же для детей пишут и сложных слов там не должно быть.
По поводу Йоты — прочел статью, доставляют не домой, а только в определенные пункты выдачи, причем перед этим надо еще приехать с паспортом. То есть чистый пиар, выдавать сим-карты из имеющегося запаса было бы быстрее и проще.
Нужно принять из формы csv-файл и заполнить данными базу. Но вот чёт не догоню как файл начать парсить. На сайте есть форма как с первого примера отсюда http://php.net/manual/ru/features.file-upload.post-method.php
И есть функция для разбора файла. Когда файлик лежит в одной папке со скриптами и я скармливаю функции его имя, то всё работает. А как ему указать, что надо парсить файл из формы? Я пыхонуб если что.
>Тут у тебя ошибочка в рассуждениях:
>
>> 4) смотрим на весы: на одном уровне -- фальшивка у нас, на разных -- где-то на весах;
>Если весы показывают разный вес, то есть 2 варианта: фальшивка либо в третьей куче, либо в куче которую мы отбросили на первом этапе.
Да, поэтому я исправил итог с n+1 на n+2 (>>538423). Одно взвешивание на то, чтобы удостовериться, что фальшивка у нас, а не в отброшенной куче.
>которая делится на 3^n
И тут и имел в виду, что число монет в части должно быть равно тройке в n-ой степени. Ну и теперь я вижу, что такой ответ будет неверным для больших чисел. Но на 100 и 200 вполне работает.
путин_шутка_про_курск
Не знаю, у меня дико тормозит не только выдача, даже переход на гугл и в почту, не сразу появляются подсказки аяксового живого поиска.
О, и капчу ждал секунд десять. Может это только у меня, не знаю.
Возможно, из-за переноса серверов в связи с новыми законами http://megamozg.ru/post/18996/
>Сделать форму, кнопку и средствами CSS поменять ее внешний вид чтобы она была похожа на ссылку
Поставил background:none, border:none, padding:0. Но при выделении остается какая-то рамка. Как от нее избавиться, какое свойство за это отвечает?
Определенно что-то с гуглом (пик2), только у меня, или не только у меня.
Бамп! Ну же, анончики, молю!
Проблема с гуглом скорее всего из-за твоего браузера, расширений браузера, компьютера или роутера.
> Но при выделении остается какая-то рамка. Как от нее избавиться, какое свойство за это отвечает?
Насчет рамки, в моем Хроме рамкой выделяются и ссылки и элементы форм, если по ним перемещаться с помощью Tab. Например на этой странице так получается. Не вижу смысла с ней бороться, это же специально сделано для клавиатурной навигации.
Кажется, я плохо понимаю архитектуру, не знаю куда совать этот кусок кода:
Если (у пользователя нет куки с токеном) {
$token = генерируем случайный код;
сохраняем код в куки пользователю;
} иначе {
$token = код из куки;
Продлеваем время жизни куки;
}
Кстати, разве "сохраняем код в куки" и "продлеваем жизнь куки" не одно и тоже (setcookie)? Почему бы не вынести за скобки.
Но неважно, я просто не понимаю, где это прописывать.
Если в каждом слимовском маршруте, то получится море копипаста, что никак не устроит.
Прямо в шаблоне устанавливать куки тоже весьма странно.
Если перед запуском приложения, то во-первых этот токен будет генерироваться даже когда он нафиг не нужен и на конкретной странице нет никакой формы; а во-вторых меня как-то коробит, что в бутстрапном файле валяется кусок левого кода, не имеющего отношения к объекту приложения. Чувствую, что это неправильно.
В общем, проблему вижу, но не знаю как решить.
https://github.com/nsdvw/file-sharing/blob/master/public_html/index.php#L46-L60
Вот тут если тру ставишь
$app = new \Slim\Slim([
'templates.path' => 'app/views/',
'cookies.encrypt' => false,
'cookies.secret_key' => 'my_secret_key',
'cookies.cipher' => MCRYPT_RIJNDAEL_256,
'cookies.cipher_mode' => MCRYPT_MODE_CBC
]);
$app->
Хочу написать более менее универсальную функцию валидации данных через ajax, нужно каким-то образом отлавливать какое именно поле было изменено
Что-то, чтобы в переменную инпут попадал только один, только что измененный инпут.
var input = $('[type = input]');
input.blur(function () {
var value = input.val();
var type = input.attr("name");
$.ajax({
method: "POST",
url: "../../controllers/ajaxController.php",
data: {value: value, query: query}
})
.done(function (msg) {
$("#emailAlert").remove();
input.after(msg);
});
});
вопрос снят, я почти правильно сделал.
$files=$app->db->query("DELETE * FROM files where token = $id");
Задача:
Наверняка ты помнишь задачу про любителя телефонов от Эппл, который больше года потом вынужден был экономить на завтраках, чтобы расплатиться по кредиту. Так вот, у этой истории есть продолжение. Я знаю, вы его ждали. Итак, сделав последнюю выплату по кредиту, наш школьник собрался было идти домой и направился к ст.м. Площадь Восстания, как вдруг его взгляд привекла реклама нового планшета Apple New Ipad 32Gb (всего за 39999 р). Понятно, что вскоре наш незадачливый любитель яблок уже держал в руках и поглаживал новый девайс аки кота-манула и чуть слышно шептал «моя прелесть». Поскольку денег у нашего героя уже не было, он решил воспользоваться услугой «покупка в кредит без первого вноса». Кредит предлагают 3 банка, и все на разных условиях: 1. кредит за 4% и (мелким шрифтом) 500 р комиссии в месяц от HomoCredit; 2. кредит за 3% и 1000 р комиссии в месяц от того же банка (Softbank), что и в первой задаче; 3. нереально вкусное предложение от StrawberryBank за 2% в месяц, без комиссии, но с платой в размере 7777 р за открытие счета (эту сумма прибавляется к сумме долга)
Задание: определи наиболее выгодный кредит. Платить школьник, как и прежде, может не более 5000 р. в месяц. Сначала начисляются проценты и комиссия, а только потом происходит выплата.
Линк на код: ideone.com/Prpv5i
Для вёрстки бери tw. bootstrap - клёвая вещь, экономит уйму времени.
Для скриптов для тренировки может лучше сделай фреймворк сам, или возьми что-то вроде Zend (лол), Symphony, Codeigniter (самый простой) или Laravel.
$id в кавычки помести.
Что ещё интересно - процедурный вариант скрипта работает на 30-40% быстрее, кажется об этом говорили кодеры VK, объясняя, почему у них сайт написан в процедурном стиле. Мне говорили, что нет смысла делать это в ООП. В данной задаче я и не нашёл особого преимущества в ООП, разве что мне так удобнее организовывать код.
Класс inc/AtmMachine.php
https://github.com/hiigara123/ATM-machine
Скрипт в работе:
http://628808.plitka12.web.hosting-test.net/bank/
> Zend (лол), Symphony, Codeigniter (самый простой) или Laravel
Но какой же выбрать из них? С прицелом на будущее бы, чтобы заодно полезный освоить. Какой чаще в вакансиях требуется?
>Какой чаще в вакансиях требуется?
Symphony, так вышло.
Я проекты делаю на Laravel - лучшее, что было написано на PHP, из того, что я видел.
Алиса и Хоббит, например. Но лучше учить по играм (желательно с озвучкой).
Отписал
Алсо дайте пример использования дата маппера, как в него переменные за пределом класса пихать?
Как отправлять шаттл в космос через ПХП? Везде вижу только использование ай-пи уже готового сервиса, а что надо что бы написать свой такой сервис? Надо иметь какой-то особенный космодром? Его можно же найти?
http://www.sitepoint.com/integrating-the-data-mappers/
Что ты носишься с этими дата-мапперами? Их трудно изучить в отрыве от реального, причём, большого проекта, где записываются много типов данных.
Оп-хуй же сказал файлообменник через дата маппер писать... Так-то я не вижу необходимости в перегрузке мелкого сайта таким кодом, но он сказал НАДО. (тем более со встроенным в слиме $app->db сложно это в маппер запихать).
Если это твой первый раз, то почему бы и нет. Найди попроще пример и внедри себе. Обучение не должно быть "эффективным" на 100%
Codeigniter вроде как умирает (хотя весной вышла 3я версия). И делает его там чуть ли не один человек. Я думаю, его не надо. Хотя там очень простой и понятный мануал, мне его посоветовали для вкатывания во фреймворки, так я в нём и застрял.
мимокрок-быдлоадмин
Посоны, решил выбрать пхп как самый нуб-энтри-язык ага. Говнокодером (если потяну) становиться ни разу не собираюсь. Предыдущая работа наебнулась медным тазом, и надо срочно что то предпринимать для быстрого старта.
Собственно такой вопрос - количество школьников еще не сильно превысило количество работы? Насколько актуальна сейчас и будет в ближайшие пару лет профессия пхпшника и прочее. Ответьте пожалуйста.
миможертваэкономическогокризиса
>Собственно такой вопрос - количество школьников еще не сильно превысило количество работы?
Работаю веб-макакой в мухосранской веб студии, практически каждый день приходят ньюбаи выпрашивающие работу за жрать, лишь бы опыт какой.
>>536866 (OP)
>- Проверялка решений на JS: http://dkab.github.io/jasmine-tests/
А гдеб посмотреть варианты решения других анонов?
>Работаю веб-макакой в мухосранской веб студии, практически каждый день приходят ньюбаи выпрашивающие работу за жрать, лишь бы опыт какой.
И насколько они ньюбаи?
Сначала убери этот сельский выговор php, это уже хороший маркер говнокодера.
>количество школьников еще не сильно превысило количество работы?
Хуй знает. Анон правильно заметил, что на собеседования приходит довольно много народу. Но в моей шараге 70% приходили полные неадекваты, прочитавшие 3 статьи по SEO и считавшие, что их работа будет жмакать на кнопки в админке. Я отослал резюме в 3 компании и все 3 меня приняли, главное имей что показать, я показал сайты, которые сделал для себя и для знакомых. Количество вакансий и заказов на фрилансе растёт, значит спрос растёт точно, насчёт предложения не знаю.
Да, можно, с помощью cron http://mblogm.ru/blog/cron-for-php-scripts/.
Он стоит обычно на всех хостингах.
http://ideone.com/3glT9y
Есть мнение, что ты проебал с последним платежом. У меня вообще так получилось:
ideone.com/8ymjJc
Проебал вынести в переменные цену айпада и ежемесячный платёж, ну да похуй.
Ты переусложнил
for($i=1;$i<=100;++$i)
echo ($i%3?$i%5?$i:'':'Fizz').($i%5?'':'Buzz')."<br>";
Поставь openserver и не мучайся. Апач собирать под виндой только отбитый долбоеб будет.
http://pastebin.com/0ZfQ4ems
if ($this->statement === null) {
throw new PDOException(
"There is no PDOStatement object for use.");
}
return $this->statement;
}
$this->statement = $this->connection->prepare($sql,
$options);
Вот это вот проверяет есть ли ошибка да?
Мозгов? У меня нет Шлюза для СМС рассылки и ещё СМС центра. Как получить к ним доступ, кто то же предлагает такие услуги?
Уже никак. Сейчас для этого есть ВК.
Кто-нибудь может просто простенький пример дата маппера написать, чтобы там только функция SELECT была, и как потом его в контроллере вызвать? плз.
>Как получить к ним доступ, кто то же предлагает такие услуги?
DasuppaStudios рассылают через SMS Online, например.
Их много, например.
помогите плизки. почему скрипт не работает
ЗДРАВСТВУЙ ДОРОГОЙ ДРУГ! НЕ СПЕШИ ЗАКРЫВАТЬ ВКЛАДКУ… Я СЕЙЧАС РАССКАЖУ О …
Мы не в курсе, спам-рассылками занимаются лузеры, которых не берут в хорошие конторы.
Но у меня
>onSubmit="return validate(this)"
...
function validate(form) {
fail += validateForename(form.forename.value)
\t\t\tfail += validateSurname(form.surname.value)
\t\t\tfail += validateUsername(form.username.value)
\t\t\tfail += validatePassword(form.password.value)
\t\t\tfail += validateAge(form.age.value)
\t\t\tfail += validateEmail(form.email.value)
\t\t\tif(fail == "")
\t\t\t\treturn true
\t\t\telse {
\t\t\t\talert(fail)
\t\t\t\treturn false
\t\t\t}
\t\t}
стандартный эффект от столкновения с ООП
Да, это я видел, у них есть свои API, но их услуги платные что то в районе 50 коп. за смс. А как самому предоставлять подобные услуги? Надо договариваться с мобильным оператором?
Т.е. проблема видно в том, что по git clone /путь/в/линухе, он мне скопировал только мою ветку, где всего пара файлов, а хотелось бы все ветки.
Некоторое время назад я искал нормальный плагин автоматической перелинковки для вордпресс и не нашёл то что искал. Поэтому решил написать свой, но только сейчас об этом вспомнил. Была идея плагина, но я её забыл, поэтому хочу узнать какого плагина для автоматической перелинковки в вордпресс, вам не хватает (или всего хватает)? Суть плагина который я придумал но забыл, заключалась в использовании вероятности. То есть ты вводишь определённое словосочетание, и выставляешь несколько ссылок (допустим не больше 10) на которые можно его залинковать. Также можешь выставить вероятность, например вероятность определённой ссылки будет 0,5, а остальных 0,2 и 0,3. В итоге плагин пробегается по всем записям в базе данных и меняет указанное словосочетании на ссылку, с учётом вероятности. Такое надо вообще? Или такое уже есть давно?
С нуля дело бы не пошло, написать хорошую CMS я тогда не мог (и сейчас не могу), но я был знаком с codeigniter тогда и с wordpress, вот на них и сделал свои первые сайты. Затем в говношараге я освоил prestashop и большую часть сайтов уже делал на нём.
Раньше было не дно, но сейчас рубль укатился в пиздень, цены либо упали либо остались такими же, ты просто будешь получать в два раза меньше как минимум работая на рашкоконтору, а битриксом кроме рашки больше никто не пользуется. Обидно хуярить битрикс за ту же сумму, за которую вчерашний школьник натягивает темплейт на вордпресс и продаёт заказчику из канады.
Я хотел склепать на yii для пробы простой сайт с объявлениями. Но оказалось, что база у такого проектика не очень простая.
Во-первых, древовидные категории товаров. Прочитал твою статью, выбрал естественно самый простой способ (Adjacency List).
В принципе подойдет, удаление или перемещение ветки относительно несложное, глубина дерева максимум 3 уровня.
Но я не знаю как поступить с уникальными свойствами для каждой конкретной категории объявления. Например у автомобиля есть свойство объем двигателя, год выпуска, а у квартиры количество комнат и площадь, у одежды размер, а у вакансии зарплата и тип занятости (полная, неполная).
Первый вопрос, как хранить подобные свойства? О паттернах для таблиц читал, но поскольку это голая теория я не могу понять как применить на практике.
Если я выберу Single Table Inharitance, то получается все эти уникальные свойства придется делать ее колонками, и для большинства записей они будут выставлены в null.
Мало того, непонятно что тогда делать с моделями. Создавать одну модель? Но тогда будет сложно создавать новую запись, ведь непонятно какие из этих десятков столбцов дать юзеру на заполнение в форме. Будет странно, если пользователь, продающий щенков бульдога, увидит поля "коробка передач", "площадь" и т.д.
Нет, это определенно не годится.
Class Table Inharitance, если я правильно понял, подразумевает создание одной обобщенной таблицы, где хранятся общие для всех объявлений свойства (заголовок, описание, прикрепленные фото, контактные данные и т.д.), и отдельной таблицы для каждой комбинации уникальных свойств. То есть одна запись будет разбита на две таблицы. Меня смущает необходимость джойнить и инсертить сразу две таблицы соответственно при каждой вставке и выборке.
Concrete Table Inheritance отличается от Class TI тем, что не создается отдельная таблица для общих свойств, но для комбинаций уникальных по прежнему создается по таблице.
Вроде бы из этих трех вариантов самый гуманный. Хотя я по прежнему не могу прикинуть, какое же количество таблиц у меня получится в итоге. И какие названия им давать? По именам категорий не получится, потому что у некоторых категорий вообще нет уникальных свойств, а у некоторых комбинации этих свойств могут совпасть (например у меня есть категории "аренда квартир" и "продажа квартир", у них идентичный набор свойств "площадь", "кол-во комнат", "этаж").
Да, пожалуй остановлюсь на этом варианте, а имена таблицам буду давать, конкатенируя через подчеркивание их уникальные характеристики. Надеюсь, у меня не получится полсотни таблиц. Или это нормально? На некоторых cms я видел и по 150 таблиц, но не думаю, что там удачные решения.
Стоп, но опять-таки, что будет при создании новой записи? По задумке сначала пользователь должен увидеть форму, содержащую только общие свойства объявления. А когда он выберет из списка категорию, тогда должны аяксом подгрузиться все остальные необходимые поля. Но какой таблицы? Как связать категорию с таблицей типа Concrete TI? Как я уже говорил, для некоторых категорий набор характеристик совпадает, и я не могу давать таблицам имена по категориям.
Тогда снова кажется более симпатичным вариант с Class TI. Ведь он как раз содержит нужные мне таблицы: одну с общими данными, а вторую с уникальными для каждой конкретной категории. Тогда после выбора пользователем категории из списка должны подгрузиться поля нужной таблицы.
Но мы снова упираемся в количество. У меня 9 или 10 категорий первого уровня, около 120 второго, и черт знает сколько третьего. Там только пород кошек и собак около сотни (мне кстати пришлось писать парсер, не буду же я руками это все вбивать в базу?).
Уникальные свойства впрочем касаются именно категорий второго уровня. Например, я хочу чтобы пользователь выбрал из списка "Недвижимость"->"Аренда квартир", и тогда появится форма для поиска, где в выпадающем списке будут категории третьего уровня (квартиры посуточно, с почасовой оплатой, долгосрочно), а также поля для площади, кол-ва комнат и этажа.
Так что уникальные поля относятся к категориям именно второго уровня.
Третий уровень категорий если честно вообще не похож на категории. Уже думал сделать их не категориями, а свойствами. В некоторых случаях это явно свойства, например марка автомобиля это не категория, а свойство товара. Но тогда мне придется создавать по таблице на каждое такое свойство. Впрочем, это не так важно.
Так что выбрать-то? Class TI требует создания >100 таблиц и моделей, но легкий action create. Concrete TI сэкономит раз в пять кол-во таблиц и моделей, но я понятия не имею, что делать с формой создания нового объявления, как указать нужные для заполнения поля.
Я хотел склепать на yii для пробы простой сайт с объявлениями. Но оказалось, что база у такого проектика не очень простая.
Во-первых, древовидные категории товаров. Прочитал твою статью, выбрал естественно самый простой способ (Adjacency List).
В принципе подойдет, удаление или перемещение ветки относительно несложное, глубина дерева максимум 3 уровня.
Но я не знаю как поступить с уникальными свойствами для каждой конкретной категории объявления. Например у автомобиля есть свойство объем двигателя, год выпуска, а у квартиры количество комнат и площадь, у одежды размер, а у вакансии зарплата и тип занятости (полная, неполная).
Первый вопрос, как хранить подобные свойства? О паттернах для таблиц читал, но поскольку это голая теория я не могу понять как применить на практике.
Если я выберу Single Table Inharitance, то получается все эти уникальные свойства придется делать ее колонками, и для большинства записей они будут выставлены в null.
Мало того, непонятно что тогда делать с моделями. Создавать одну модель? Но тогда будет сложно создавать новую запись, ведь непонятно какие из этих десятков столбцов дать юзеру на заполнение в форме. Будет странно, если пользователь, продающий щенков бульдога, увидит поля "коробка передач", "площадь" и т.д.
Нет, это определенно не годится.
Class Table Inharitance, если я правильно понял, подразумевает создание одной обобщенной таблицы, где хранятся общие для всех объявлений свойства (заголовок, описание, прикрепленные фото, контактные данные и т.д.), и отдельной таблицы для каждой комбинации уникальных свойств. То есть одна запись будет разбита на две таблицы. Меня смущает необходимость джойнить и инсертить сразу две таблицы соответственно при каждой вставке и выборке.
Concrete Table Inheritance отличается от Class TI тем, что не создается отдельная таблица для общих свойств, но для комбинаций уникальных по прежнему создается по таблице.
Вроде бы из этих трех вариантов самый гуманный. Хотя я по прежнему не могу прикинуть, какое же количество таблиц у меня получится в итоге. И какие названия им давать? По именам категорий не получится, потому что у некоторых категорий вообще нет уникальных свойств, а у некоторых комбинации этих свойств могут совпасть (например у меня есть категории "аренда квартир" и "продажа квартир", у них идентичный набор свойств "площадь", "кол-во комнат", "этаж").
Да, пожалуй остановлюсь на этом варианте, а имена таблицам буду давать, конкатенируя через подчеркивание их уникальные характеристики. Надеюсь, у меня не получится полсотни таблиц. Или это нормально? На некоторых cms я видел и по 150 таблиц, но не думаю, что там удачные решения.
Стоп, но опять-таки, что будет при создании новой записи? По задумке сначала пользователь должен увидеть форму, содержащую только общие свойства объявления. А когда он выберет из списка категорию, тогда должны аяксом подгрузиться все остальные необходимые поля. Но какой таблицы? Как связать категорию с таблицей типа Concrete TI? Как я уже говорил, для некоторых категорий набор характеристик совпадает, и я не могу давать таблицам имена по категориям.
Тогда снова кажется более симпатичным вариант с Class TI. Ведь он как раз содержит нужные мне таблицы: одну с общими данными, а вторую с уникальными для каждой конкретной категории. Тогда после выбора пользователем категории из списка должны подгрузиться поля нужной таблицы.
Но мы снова упираемся в количество. У меня 9 или 10 категорий первого уровня, около 120 второго, и черт знает сколько третьего. Там только пород кошек и собак около сотни (мне кстати пришлось писать парсер, не буду же я руками это все вбивать в базу?).
Уникальные свойства впрочем касаются именно категорий второго уровня. Например, я хочу чтобы пользователь выбрал из списка "Недвижимость"->"Аренда квартир", и тогда появится форма для поиска, где в выпадающем списке будут категории третьего уровня (квартиры посуточно, с почасовой оплатой, долгосрочно), а также поля для площади, кол-ва комнат и этажа.
Так что уникальные поля относятся к категориям именно второго уровня.
Третий уровень категорий если честно вообще не похож на категории. Уже думал сделать их не категориями, а свойствами. В некоторых случаях это явно свойства, например марка автомобиля это не категория, а свойство товара. Но тогда мне придется создавать по таблице на каждое такое свойство. Впрочем, это не так важно.
Так что выбрать-то? Class TI требует создания >100 таблиц и моделей, но легкий action create. Concrete TI сэкономит раз в пять кол-во таблиц и моделей, но я понятия не имею, что делать с формой создания нового объявления, как указать нужные для заполнения поля.
Но это впс, на ispsystem и на весте все было ок, а вот это я поставил на ispmanager и вот такая вот фигня.
Я бы вообще не создавал таблицы под свойства и категории. В таком случае, если я захочу поменять, удалить или добавить категорию мне не нужно будет создавать или удалять таблицы.
Грубо говоря: таблица с категориями, таблица с объявлениями, таблица с корреляцией между объявлениями и категориями.
Суть проблемы в том, что у объявлений, относящихся к разным категориям, разные свойства.
У квартиры есть площадь и кол-во комнат, у авто коробка передач и год выпуска например.
При хранении этих данных в одной таблице Объявление мы должны будем сделать колонки для всех возможных свойств, большинство из которых будут null. (Паттерн STI)
А главное, при создании нового объявления пользователь должен видеть только относящиеся к категории поля для заполнения. Пользователь, желающий продать авто, не должен видеть графу "площадь", "кол-во комнат" и еще 20 не относящихся к категории свойств.
Создание и удаление таблиц не проблема, нужно только один раз прописать нужные действия в административной панели.
>При хранении этих данных в одной таблице Объявление мы должны будем сделать колонки для всех возможных свойств
nope
Смотри:
id | value
1 | 3 комнаты (свойства квартиры)
2 | 46 м.кв. (свойства квартиры)
3 | 1996 (свойство автомобиля)
Всё в одной таблице.
Что за ерунда? Хранить в одной колонке разные свойства? И как ты узнаешь, что там хранится: год, площадь или кол-во комнат? (только не говори, что так и сохранять "кв.м.")
И мне нужна одна запись для объявления, а у тебя получается или только одно значение на выбор (либо площадь, либо кол-во комнат), или две записи для одного объявления таблице? Как тогда понять, какие айди относятся к одному объявлению?
Ладно, я думаю ты троллишь, а я не в настроении для шуток. Пойду посплю, может завтра оп-вахтер объявится.
>Что за ерунда?
Мнение эксперта?
>И как ты узнаешь, что там хранится
Через корелляционную таблицу, как бы 80% цмс на них работает.
>Ладно, я думаю ты троллишь
После последнего твоего поста у меня именно такое чувство о тебе.
> Но я не знаю как поступить с уникальными свойствами для каждой конкретной категории объявления.
Очевидный entity-attribute-value очевиден.
> Через корелляционную таблицу, как бы 80% цмс на них работает.
Штоа? Или ты так по незнанию обозвал выше приведенный паттерн?
Вроде вот дан набор инструментов, но я абсолютно не понимаю как их применять, идеи не приходят мне в голову.
Неужели я настолько тупой и совершенно не могущий в абстрактное мышление?
Может есть смысл задрочить алгоритмы какие-нибудь? Что бы научиться строить эти цепочки действий, даже простейшие.
Думай ищи копай
Офигенно, даже не знал про такое.
Лул, архитектура таблиц уровня /b
Задача 1.
12/2 = 6 монет на каждой чаше, смотрим какая перевешивает, берем ее. 6/2 = 3 на каждой чаше, опять смотрим что перевешивает, берем. Теперь 3 осталось, берем любые 2, кладем на весы. Если не перевешивает, то фальшивая та, которая не на весах. Если перевешивает, то фальшивая которая перевесила. Итого всего 3 взвешивания произвели.
Задача 2
Кладем на каждую чашу по 6, смотрим. Одна из чаш перевесила. Берем ее, делим, на каждой чаше по 3. Если ничего не перевешивает, значит фальшивая была в другой шестерке и она легче настоящих. Если опять перевешивает, то фальшивая в нашей шестерке и она тяжелее настоящей. Если фальшивая легче, придется взвесить еще монетки в другой шестерке. Дальше как в задаче 1. Итого 3-4 взвешивания, в зависимости от того сразу попали в нужную шестерку или нет.
Задача 3.
Так же все, делить на два, взвешивать. Количество взвешиваний будет определяться тем, сколько раз число можно поделить на 2, плюс прибавляем 1 взвешивание в конце для второй задачки.
http://ideone.com/CGDOnA
Строки 18 и 19, как их исправить, чтобы буквы правильные брались? Если сначала строки ноль - это первый символ, то в конце минус первый.
Все норм, братиш, у меня так же. Я взял таймаут на некоторое время(2-3 дня), вот сейчас вернулся, думаю начать снова.
У тебя $i = 1, а строка начинается с 0.
Можно создавать классы для разного количества монет.
foreach ($array1 as &$value) {
$value= "some data";
}
Или как лучше заполнять такие массивы?
$size = 10;
$arr = '[';
while ($size != 0) {
$arr .= 'null, ';
$size -=1;
}
$arr .= '];';
eval('$array = ' . $arr);
Так правильно.
Чётко, братиш))
Код на фуллскрин версию:
https://jsfiddle.net/heeret/8Lwqq4e7/embedded/result/
Код на обычную:
https://jsfiddle.net/heeret/8Lwqq4e7/
#button-all:checked ~ #wrapper_portfolio_works > .graphic,
#button-all:checked ~ #wrapper_portfolio_works > .illustration,
#button-all:checked ~ #wrapper_portfolio_works > .motion {...}
Задача: сократить 3 строки до одной.
Ведь знаю, что как-то можно это сократить, но не могу додуматься.
Ты неясно выразился, поэтому я не сразу понял, тем более в три ночи.
А неплохой способ, хотя со своими недостатками.
И там не одна таблица, естественно, а минимум пять вспомогательных.
У меня получилось так
property (таблица, где хранятся значения уникальных полей; плохо то что нельзя четко указать тип, придется использовать варчар)
-- id
-- value
category_property (сводная таблица, в которой перечислены возможные типы уникальных полей для каждой категории)
-- cat_id
-- prop_type_id
property_type (названия уникальных полей; пожалуй можно пожертвовать нормализацией и перенести их в предыдущую таблицу, избыточность на 100-1000 записей не страшна)
-- id
-- name
(например 31.Кузов;32.Тип занятости)
property_list (Список вариантов значений для каждого типа поля; некоторые поля могут принимать только значение из приведенного списка; прочие, которые не указаны, должны вбиваться пользователем в текстовое поле)
-- prop_type_id
-- variant
(31.Седан;31.Хэтчбек;31.Минивен;...32.На полную ставку;32.Неполная занятость.)
ad_property (собственно таблица с перечислением уникальных свойств для объявления)
-- ad_id
-- prop_id
Таким образом, логика отображения формы создания нового объявления будет такой:
1. Пользователю отображаются поля из таблицы Ad (то есть общие для всех типов
объявлений) и список категорий.
2. Пользователь выбирает категорию из списка.
3. По айди категории выбираем все записи из таблицы category_property.
4. Проверяем для каждого типа свойства, есть ли для него список значений в таблице
property_list
5. Если есть, то собираем все значения для данного типа свойства и выводим в представлении
select. Например кузов автомобиля должен выбираться из списка.
6. Если для данного типа свойства не найдено значений в таблице porperty_list,
выводим в представлении для данного свойства текстовое поле. Обычно это поля типа цена,
размер (одежды), площадь (квартиры) и т.д.
Недостаток в такой схеме в том, что уникальные поля хранятся в одном столбце, и нет возможности указать тип. Одним словом, будет сложность с валидацией формы.
И невозможен ORM, придется использовать DAO. Сложность выборки и вставки.
Но пока действительно трудно придумать что-то лучшее.
>>540068
>ты так по незнанию обозвал выше приведенный паттерн
Я тоже не знал, пошел гуглить.
Ты неясно выразился, поэтому я не сразу понял, тем более в три ночи.
А неплохой способ, хотя со своими недостатками.
И там не одна таблица, естественно, а минимум пять вспомогательных.
У меня получилось так
property (таблица, где хранятся значения уникальных полей; плохо то что нельзя четко указать тип, придется использовать варчар)
-- id
-- value
category_property (сводная таблица, в которой перечислены возможные типы уникальных полей для каждой категории)
-- cat_id
-- prop_type_id
property_type (названия уникальных полей; пожалуй можно пожертвовать нормализацией и перенести их в предыдущую таблицу, избыточность на 100-1000 записей не страшна)
-- id
-- name
(например 31.Кузов;32.Тип занятости)
property_list (Список вариантов значений для каждого типа поля; некоторые поля могут принимать только значение из приведенного списка; прочие, которые не указаны, должны вбиваться пользователем в текстовое поле)
-- prop_type_id
-- variant
(31.Седан;31.Хэтчбек;31.Минивен;...32.На полную ставку;32.Неполная занятость.)
ad_property (собственно таблица с перечислением уникальных свойств для объявления)
-- ad_id
-- prop_id
Таким образом, логика отображения формы создания нового объявления будет такой:
1. Пользователю отображаются поля из таблицы Ad (то есть общие для всех типов
объявлений) и список категорий.
2. Пользователь выбирает категорию из списка.
3. По айди категории выбираем все записи из таблицы category_property.
4. Проверяем для каждого типа свойства, есть ли для него список значений в таблице
property_list
5. Если есть, то собираем все значения для данного типа свойства и выводим в представлении
select. Например кузов автомобиля должен выбираться из списка.
6. Если для данного типа свойства не найдено значений в таблице porperty_list,
выводим в представлении для данного свойства текстовое поле. Обычно это поля типа цена,
размер (одежды), площадь (квартиры) и т.д.
Недостаток в такой схеме в том, что уникальные поля хранятся в одном столбце, и нет возможности указать тип. Одним словом, будет сложность с валидацией формы.
И невозможен ORM, придется использовать DAO. Сложность выборки и вставки.
Но пока действительно трудно придумать что-то лучшее.
>>540068
>ты так по незнанию обозвал выше приведенный паттерн
Я тоже не знал, пошел гуглить.
Что значит "~"?
В данном случае это способ распространить влияние чекнутого инпута на класс в диве, который находится после этого инпута.
Статья вот. http://htmlbook.ru/css/selector/sibling
Многие говорят, что это антипаттерн, и рекомендуют использовать таки Class или Concrete TI, с чего я и начал размышление.
http://www.askdev.ru/question/3120/%D0%98%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D1%8C-%D0%BB%D0%B8-EAV-%D0%BC%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C-%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85/
http://www.slideshare.net/billkarwin/sql-antipatterns-strike-back
Для yii кстати есть вроде какая-то библиотека для работы с подобной структурой базы http://yiiframework.ru/forum/viewtopic.php?t=20075
Ок, придется все это читать и хотя бы попробовать понять.
а напиши это через if чтобы я понял.
А еще у мея есть почта, codedokode () gmail.com на случай если все опять сломается.
Пока проверю старые задачи.
Сопсна ПЕРВОЕ взвешивание по 6 монет на ВТОРОЕ взвешивание берём те 6 монет которые показали перевес. ТРЕТЬЕ взвешивание будет решающим ибо мы взвешиваем жве монеты и если они показывают одинаковый вес то автоматически третья монета - перевес, если одна монет легче на весах то та что тяжелее наша. Для третьей задачки в ход вступает теория вероятностей.
А, блин её уже решили ж же.
>>536894
Я тут думал, надо ли мне проверять только генерацию превьюшек или другие файлы? Потом решил, что у нас все же учебная задача и немного внимания стоит уделить и вспомогательным файлам.
> https://github.com/MindiMakridi/RESTFUL/blob/master/upload.php#L30
> } while (file_exists("images/$fileName" && $i<=20));
У тебя здесь ограничение числа попыток создать файл, но при его превышении это никак не обрабатывается. Алсо, в виде for это было бы компактнее.
> https://github.com/MindiMakridi/RESTFUL/blob/master/createThumb.php#L11
> preg_match("#^/thumbnails/(crop|scale)/([0-9]+x[0-9]+)/#u", $_SERVER['REQUEST_URI'], $matches);
Теоретически URL может и не соответствовать выражению (например скрипт вызван напрямую) и потому preg_match всегда стоит писать внутри if
>$url = parse_url($url);
> $url = $url['path'];
Это делается удобнее, подробности в мануале: $path = parse_url($url, PHP_URL_PATH);. Заметь, что я использую разные переменные для разных вещей.
> https://github.com/MindiMakridi/RESTFUL/blob/master/lib/Thumbnail.php#L39
> switch($size[2]){
Здесь нужен default. Это ошибка, если дана картинка неподдерживаемого формата. И лучше всего сразу заявить об этом, выбросив исключение. А ты молча игнорируешь ошибку, и вывалится она где-то позже, вот на этом этапе:
> $imgCreateFunc = "imagecreatefrom".$this->extension;
Когда получится имя несуществующей функции. Это надо переделать:
— почитать урок по исключениям: https://gist.github.com/codedokode/65d43ca5ac95c762bc1a
— сделать свой класс исключений обозначающих ошибку или невозможность генерации превью, например PreviewGenerationException (да, длинновато но зато понятно без комментариев).
— выбрасвать это исключение в классе при любых ошибках вместо игнорирования или возврата false (исключение лучше так как проверить результат можно забыть, а вот про исключение не забудешь — оно завершит программу). Также исключение позволяет нам указать конкретную причину ошибки в нем.
— ловить его в createThumb.php и при ловле выдавать код 500 и ошибку, используя try/catch вместо if (...)
Также, мне не нравится идея генерировать имя функции так:
> $imgCreateFunc = "imagecreatefrom".$this->extension;
Как-то это не очень надежно, ведь определение расширения у тебя в обном месте, а эта строчка в другом. Вдруг какой-нибудь программист добавит новое расширение, а на то как оно используется, не обратит внимание? Я думаю, тогда в классе можно сделать поле imgCreateFunc и присваиваеть ему значение в том же switch где и определяется расширение. Аналогично сделать поле для функции сохранения файла.
Ну и плюс, с твоим подходом поиск по imagecreatefromjpg не найдет эту функцию. Лучше бы избегать таких трюков.
> "images/$this->fileName"
Это скопипащено несколько раз, сделай метод возвращающий путь к файлу. Лучше используй абсолютные пути (идущие от корня диска) вместо относительных, например, сделав поле хранящее путь к папке хранилища картинок. Определять этот путь можно в createThumb.php через _ _ DIR _ _ и передавать в конструктор класса.
А с относительными путями твой код сильно зависит от текущей директории, ведь пути отсчитываются от нее.
> if($width>$height){
> $scale = $this->thumbWidth/$width;
Я боюсь что это неправильный алгоритм определения масштаба. Допустим у нас mode = scale, 10×100 и картинка размером 200×500. Мы должны ее уменьшить до 10×25, в 20 раз. Но твой алгоритм выберет уменьшение в 5 раз, так как будет смотреть по большей стороне картинки.
Считать надо по-другому. Надо найти scaleX и scaleY и выбрать из них наименьшее.
> if($scale>1){
> return false;
Я думаю, тут надо не возвращать false, а просто сделать scale = 1 то есть не менять размер картинки.
По моему, ты ориентировался на создание квадратных превьюшек с равной шириной и высотой. Я сужу об этом например по вот этому месту:
> $cropHeight = $height;
> $cropWidth = $cropHeight;
Тут ты формируешь квадрат с одинаковой высотой и шириной. Будет ли твой алгоритм работать если мы высокую узкую картинку пытаемся уменьшить до низкой, но широкой превьюшки в режиме crop?
Давай тогда разберем детально алгоритм масштабирования, а ты сравнишь его со своим и либо исправишь свой либо скажешь что у меня ошибка.
maxWidth, maxHeight = заданные пользователем ограничения, width/height = ширина/высота исходной картинки
Для scale:
- определяем scaleX (= maxWidth / width), scaleY, выбираем наименьшее как scale
- если scale > 1 то делаем его равным 1 (не увеличиваем крошечные картинки)
- зная scale, вычисляем размер превьюшки outputWidth = floor(scale × width)
- масштабируем картинку
Для crop:
- определяем scale как написано выше и проверяем чтобы оно не было больше 1
- вычисляем возможный размер превьюшки до обрезки newWidth = floor(scale × width)
- вычисляем реальный размер получившейся превьюшки outputWidth как наименьшее из newWidth и maxWidth (обрезаем то, что не поместилось)
- вычисляем ширину вырезаемой части clipWidth на исходной картинке через scale и outputWidth
- вычисляем отступ на исходной картинке из clipWidth и width
- масштабируем картинку
Как я понимаю, у тебя вычисления немного другие, и значит у кого-то из нас ошибка. Было бы хорошо если ты сам сравнил алгоритмы и либо нашел ошибку у меня либо у себя. Одна из них, как я выше написал, в определении scale. Если что-то в алгоритме выше непонятно, уточняй.
В условии задачи написано что может быть задано только одно ограничение. В этом случае надо поменять алгоритм выбора scale (оно считается только по одной стороне) и алгоритм обрезки (не обрезаем ту сторону для которой нет ограничения).
Еще одно замечание по поводу реализации ООП: у тебя есть 2 метода, createThumbnail и showThumbnail. Что если мы вызовем showThumbnail не вызвав предварительно create? На уровне кода никакого запрета нет, это же публичный метод.
Это надо исправить:
- либо выбрасывать исключение если превьюшка не создана, а мы вызываем show
- либо в этом случае автоматически вызывать create (этот вариант наверно лучше)
> https://github.com/MindiMakridi/RESTFUL/blob/master/lib/Thumbnail.php#L156
> $mode = "scale"
Я бы сделал режимы константами, вроде Thumbnail::MODE_SCALE. Так и код читабельнее и опечататься не получится (PHP выдаст ошибку). Вообще, когда у тебя есть выбор из нескольких значений, обычно используют константы.
> https://github.com/MindiMakridi/RESTFUL/blob/master/templates/main.html#L9
Придирка: не стоит в шаблон помещать работу с файлами. Стоит все нужные данные получить в скрипте-контроллере index.php, а в шаблон передать массив массивов ссылок на картинки и превьюшки.
Вообще, у тебя неплохо все сделано, надо просто разобраться с тонкостями алгоритма и исправить мелкие замечания. Я думаю, после этого все будет готово и ты можешь делать следующую задачу, про студентов (или может ты ее уже начал делать не дожидаясь меня, что правильнее).
>>536894
Я тут думал, надо ли мне проверять только генерацию превьюшек или другие файлы? Потом решил, что у нас все же учебная задача и немного внимания стоит уделить и вспомогательным файлам.
> https://github.com/MindiMakridi/RESTFUL/blob/master/upload.php#L30
> } while (file_exists("images/$fileName" && $i<=20));
У тебя здесь ограничение числа попыток создать файл, но при его превышении это никак не обрабатывается. Алсо, в виде for это было бы компактнее.
> https://github.com/MindiMakridi/RESTFUL/blob/master/createThumb.php#L11
> preg_match("#^/thumbnails/(crop|scale)/([0-9]+x[0-9]+)/#u", $_SERVER['REQUEST_URI'], $matches);
Теоретически URL может и не соответствовать выражению (например скрипт вызван напрямую) и потому preg_match всегда стоит писать внутри if
>$url = parse_url($url);
> $url = $url['path'];
Это делается удобнее, подробности в мануале: $path = parse_url($url, PHP_URL_PATH);. Заметь, что я использую разные переменные для разных вещей.
> https://github.com/MindiMakridi/RESTFUL/blob/master/lib/Thumbnail.php#L39
> switch($size[2]){
Здесь нужен default. Это ошибка, если дана картинка неподдерживаемого формата. И лучше всего сразу заявить об этом, выбросив исключение. А ты молча игнорируешь ошибку, и вывалится она где-то позже, вот на этом этапе:
> $imgCreateFunc = "imagecreatefrom".$this->extension;
Когда получится имя несуществующей функции. Это надо переделать:
— почитать урок по исключениям: https://gist.github.com/codedokode/65d43ca5ac95c762bc1a
— сделать свой класс исключений обозначающих ошибку или невозможность генерации превью, например PreviewGenerationException (да, длинновато но зато понятно без комментариев).
— выбрасвать это исключение в классе при любых ошибках вместо игнорирования или возврата false (исключение лучше так как проверить результат можно забыть, а вот про исключение не забудешь — оно завершит программу). Также исключение позволяет нам указать конкретную причину ошибки в нем.
— ловить его в createThumb.php и при ловле выдавать код 500 и ошибку, используя try/catch вместо if (...)
Также, мне не нравится идея генерировать имя функции так:
> $imgCreateFunc = "imagecreatefrom".$this->extension;
Как-то это не очень надежно, ведь определение расширения у тебя в обном месте, а эта строчка в другом. Вдруг какой-нибудь программист добавит новое расширение, а на то как оно используется, не обратит внимание? Я думаю, тогда в классе можно сделать поле imgCreateFunc и присваиваеть ему значение в том же switch где и определяется расширение. Аналогично сделать поле для функции сохранения файла.
Ну и плюс, с твоим подходом поиск по imagecreatefromjpg не найдет эту функцию. Лучше бы избегать таких трюков.
> "images/$this->fileName"
Это скопипащено несколько раз, сделай метод возвращающий путь к файлу. Лучше используй абсолютные пути (идущие от корня диска) вместо относительных, например, сделав поле хранящее путь к папке хранилища картинок. Определять этот путь можно в createThumb.php через _ _ DIR _ _ и передавать в конструктор класса.
А с относительными путями твой код сильно зависит от текущей директории, ведь пути отсчитываются от нее.
> if($width>$height){
> $scale = $this->thumbWidth/$width;
Я боюсь что это неправильный алгоритм определения масштаба. Допустим у нас mode = scale, 10×100 и картинка размером 200×500. Мы должны ее уменьшить до 10×25, в 20 раз. Но твой алгоритм выберет уменьшение в 5 раз, так как будет смотреть по большей стороне картинки.
Считать надо по-другому. Надо найти scaleX и scaleY и выбрать из них наименьшее.
> if($scale>1){
> return false;
Я думаю, тут надо не возвращать false, а просто сделать scale = 1 то есть не менять размер картинки.
По моему, ты ориентировался на создание квадратных превьюшек с равной шириной и высотой. Я сужу об этом например по вот этому месту:
> $cropHeight = $height;
> $cropWidth = $cropHeight;
Тут ты формируешь квадрат с одинаковой высотой и шириной. Будет ли твой алгоритм работать если мы высокую узкую картинку пытаемся уменьшить до низкой, но широкой превьюшки в режиме crop?
Давай тогда разберем детально алгоритм масштабирования, а ты сравнишь его со своим и либо исправишь свой либо скажешь что у меня ошибка.
maxWidth, maxHeight = заданные пользователем ограничения, width/height = ширина/высота исходной картинки
Для scale:
- определяем scaleX (= maxWidth / width), scaleY, выбираем наименьшее как scale
- если scale > 1 то делаем его равным 1 (не увеличиваем крошечные картинки)
- зная scale, вычисляем размер превьюшки outputWidth = floor(scale × width)
- масштабируем картинку
Для crop:
- определяем scale как написано выше и проверяем чтобы оно не было больше 1
- вычисляем возможный размер превьюшки до обрезки newWidth = floor(scale × width)
- вычисляем реальный размер получившейся превьюшки outputWidth как наименьшее из newWidth и maxWidth (обрезаем то, что не поместилось)
- вычисляем ширину вырезаемой части clipWidth на исходной картинке через scale и outputWidth
- вычисляем отступ на исходной картинке из clipWidth и width
- масштабируем картинку
Как я понимаю, у тебя вычисления немного другие, и значит у кого-то из нас ошибка. Было бы хорошо если ты сам сравнил алгоритмы и либо нашел ошибку у меня либо у себя. Одна из них, как я выше написал, в определении scale. Если что-то в алгоритме выше непонятно, уточняй.
В условии задачи написано что может быть задано только одно ограничение. В этом случае надо поменять алгоритм выбора scale (оно считается только по одной стороне) и алгоритм обрезки (не обрезаем ту сторону для которой нет ограничения).
Еще одно замечание по поводу реализации ООП: у тебя есть 2 метода, createThumbnail и showThumbnail. Что если мы вызовем showThumbnail не вызвав предварительно create? На уровне кода никакого запрета нет, это же публичный метод.
Это надо исправить:
- либо выбрасывать исключение если превьюшка не создана, а мы вызываем show
- либо в этом случае автоматически вызывать create (этот вариант наверно лучше)
> https://github.com/MindiMakridi/RESTFUL/blob/master/lib/Thumbnail.php#L156
> $mode = "scale"
Я бы сделал режимы константами, вроде Thumbnail::MODE_SCALE. Так и код читабельнее и опечататься не получится (PHP выдаст ошибку). Вообще, когда у тебя есть выбор из нескольких значений, обычно используют константы.
> https://github.com/MindiMakridi/RESTFUL/blob/master/templates/main.html#L9
Придирка: не стоит в шаблон помещать работу с файлами. Стоит все нужные данные получить в скрипте-контроллере index.php, а в шаблон передать массив массивов ссылок на картинки и превьюшки.
Вообще, у тебя неплохо все сделано, надо просто разобраться с тонкостями алгоритма и исправить мелкие замечания. Я думаю, после этого все будет готово и ты можешь делать следующую задачу, про студентов (или может ты ее уже начал делать не дожидаясь меня, что правильнее).
Предлагайте свои идеи, только давайте без сервисов которые требуют отдать номер телефона Дурову.
>>537007
Я тут не буду писать очевидные вещи что ты должен знать что такое циклы, функции, классы, и уметь написать простую программу на уровне задач из моего учебника или SQL-запрос. Я напишу про вещи которые любят спрашивать сверх этого.
PHP: перечитай мануал, любят спрашивать тонкости языки типа преобразования одного типа в другой или правил сравнения типов (сработает ли if ("foo" == 0) { } или if ("1 person" == true) ? ). По ООП любят вопросы из серии «что выведет эта дебильная программа где мы переопределяем в наследнике приватный метод публичным с тем же именем», опять же спасает чтение мануала.
По теории могут спросить чем отличается абстрактный класс от интерфейса или как переопределить приватный метод в наследнике (правильный ответ: никак).
Любят спросить что выведет написанная программа, не запуская ее.
Если требуют знания фреймворков, могут спросить как реализовать штуку X (например древовидные категории, хотя это продвинутый вопрос) в фрейморке.
MySQL и SQL вообще: любят вопросы по теории баз данных и SQL: транзакции, внешние ключи, нормализация, виды джойнов, индексы (это у более продвинутых). Могут попросить сделать хитрый SQL запрос типа найти в таблице записи которые встречаются больше N раз или найти записи которые есть в одной таблице и нет в другой.
JS: тонкости вроде преобразования типов, чему равно [] + {} + "hello", вопросы по прототипам, вопросы по замыканиям, вопросы по передаче значений по ссылке (объекты всегда передаются по ссылке, примитивы копируются). Некоторые подвохи освещены в моих задачах по JS, некоторые в learn.javascript.ru
HTML/CSS: тут подвохи вряд ли будут, разве что могут спросить как реализовать ту или иную вещь (например вертикальное выравнивание или прибитый к низу футер) и обычно там много вариантов.
Наконец у нас есть набор задач с собеседований самого разного уровня: https://github.com/codedokode/pasta/blob/master/interview-tasks.md
Кстати, аноны, если вам на собеседовании давали какие-то задачи, можете поделиться, я их добавлю в список.
>>537007
Я тут не буду писать очевидные вещи что ты должен знать что такое циклы, функции, классы, и уметь написать простую программу на уровне задач из моего учебника или SQL-запрос. Я напишу про вещи которые любят спрашивать сверх этого.
PHP: перечитай мануал, любят спрашивать тонкости языки типа преобразования одного типа в другой или правил сравнения типов (сработает ли if ("foo" == 0) { } или if ("1 person" == true) ? ). По ООП любят вопросы из серии «что выведет эта дебильная программа где мы переопределяем в наследнике приватный метод публичным с тем же именем», опять же спасает чтение мануала.
По теории могут спросить чем отличается абстрактный класс от интерфейса или как переопределить приватный метод в наследнике (правильный ответ: никак).
Любят спросить что выведет написанная программа, не запуская ее.
Если требуют знания фреймворков, могут спросить как реализовать штуку X (например древовидные категории, хотя это продвинутый вопрос) в фрейморке.
MySQL и SQL вообще: любят вопросы по теории баз данных и SQL: транзакции, внешние ключи, нормализация, виды джойнов, индексы (это у более продвинутых). Могут попросить сделать хитрый SQL запрос типа найти в таблице записи которые встречаются больше N раз или найти записи которые есть в одной таблице и нет в другой.
JS: тонкости вроде преобразования типов, чему равно [] + {} + "hello", вопросы по прототипам, вопросы по замыканиям, вопросы по передаче значений по ссылке (объекты всегда передаются по ссылке, примитивы копируются). Некоторые подвохи освещены в моих задачах по JS, некоторые в learn.javascript.ru
HTML/CSS: тут подвохи вряд ли будут, разве что могут спросить как реализовать ту или иную вещь (например вертикальное выравнивание или прибитый к низу футер) и обычно там много вариантов.
Наконец у нас есть набор задач с собеседований самого разного уровня: https://github.com/codedokode/pasta/blob/master/interview-tasks.md
Кстати, аноны, если вам на собеседовании давали какие-то задачи, можете поделиться, я их добавлю в список.
Аноны, напомню, у нас есть задачка на логику, >>538385 попробуйте порешать. а я напишу потом ответ и способы решения.
Пока проверю старые задачи.
>>537244
> Комментировать каждый кусок кода как-то не хочется, удержать весь класс в голове не получается
Его и не надо удерживать. Надо разбивать на отдельные функции так, что они будут помещаться на 1 экране.
> Когда я пытаюсь отладить рекурсию, мозг просто утекает.
Надо мыслить на уровне одного вызова функции, не залезая в рекурсию. Ну то есть в стиле «если число купюр больше нуля, то мы вызываем себя с числом купюр на 1 меньшим».
Давай начнем с архитектуры. Во-первых, у тебя очень странный ViewModel. Этим словом обычно называют класс, который хранит отображаемые на экране данные (и логику работы с ними). Ну то есть в твоем случае он должен хранить информацию о номиналах и числе купюр которое ты выводишь. Но он не должен содержать HTML код или пытаться вывести эти купюры. Более того, ViewModel не используют в языках типа PHP, его используют в JS в сочетании с data binding (привязка данных в объекте к данным на экране).
Таким образом, весь HTML оттуда надо убрать. Это задача View, то есть шаблона, генерировать HTML код.
Я подозреваю что после этого окажется что и сам класс, в общем-то больше не нужен.
Как передать информацию о проверенных комбинациях купюр? Ну я вижу тут такой вариант: массив массивов с комбинациями.
Далее, перейдем к этому файлу:
> https://github.com/hiigara123/ATM-machine/blob/master/inc/ViewController.php
С большой буквы обычно называют файл с классом, а этот файл можно назвать controller.php или просто init.php
Теперь перейдем к модели банкомата.
Тут https://github.com/hiigara123/ATM-machine/blob/master/inc/AtmMachine.php надо убрать жестко прописанные в коде запасы купюр, сумму и работу с _GET (это задача контроллера). Всю эту информацию надо передавать снаружи, через аргументы функции. В классе будет 1-2 публичных функции: одна для расчета выдачи и может быть вторая, для получения отладочной информации о проверенных комбинациях купюр.
К сожалению, код действительно не очень читабельный, возмодно из-за того что сложно было придумать хорошие названия для функций и переменных. Например возьмем эту строку:
> $diff = ($draw != $this->notes) ? $this->diff($draw) : $this->notes;
Эти названия ничего не говорят. diff это наверное разница, но почему тогда ты вызвыаешь функцию diff с одним параметром? Как можно найти разницу от одного аргумента? И что делает сравнение в первых скобках?
Стоит очевидно подписать комментарии хотя бы к функциям.
> $qnt
не стоит сокращать названия, это ухудшает читабельность. У тебя же есть автодополнение в редакторе.
> if(in_array($fill, $this->steps))
Ты учел что по умолчанию используется нестрогое сравнение массивов? Подходит ли оно для твоих целей? И по моему, это тут вообще не нужно, при правильном подходе одна комбинация не выпадет 2 раза.
> while(($this->getSumm($draw) + $nom <= $this->summ_requested) && $qnt > 0){
Нужно использовать деление вместо цикла
> return $this->recurse($fill, $note, 3);
У функции всего 2 аргумента
В общем, предалагаю переписать код. Для начала надо определить аргументы и результат функции. Я думаю, на вход она должна получать запас купюр, требуюмую сумму и текущую комбинацию, а на выходе давать либо желаемый набор, либо null если найти его не получилось.
Комбинации купюр являются размещениями с повторением: https://ru.wikipedia.org/wiki/%D0%A0%D0%B0%D0%B7%D0%BC%D0%B5%D1%89%D0%B5%D0%BD%D0%B8%D0%B5#.D0.A0.D0.B0.D0.B7.D0.BC.D0.B5.D1.89.D0.B5.D0.BD.D0.B8.D0.B5_.D1.81_.D0.BF.D0.BE.D0.B2.D1.82.D0.BE.D1.80.D0.B5.D0.BD.D0.B8.D1.8F.D0.BC.D0.B8
Алгоритм который тут нужен это алгоритм перебора всех возможных размещений. В простейшем случае (без рекурсии) он работает так:
- берем начальное размещение 0 0 0 0
- увеличиваем число младших купюр на 1: 0 0 0 1
- когда оно дойдет до максимума, напрмиер 0 0 0 99 то сбрасываем его и увеличиваем на 1 число более старших купюр: 0 0 1 0
- и так до 99 99 99 99
Здесь вместо 99 конечно должно быть меньшее из имещегося числа купюр и максимаьно возможного (то есть дающего сумму не больше требуемой)
Он может быть как рекурсивным так и нерекурсивным. В случае рекурсивной реализации, можно сделать например так:
функция перебора одной купюры (запас, желаемая сумма, текущая комбинация, номер банкноты)
- определяем максимально возможное число банкнот данного номинала исходя из запаса и суммы
- перебираем число банкнот данного номинала от 0 до N (или от N до 0 - это может быть быстрее)
- на каждом шаге цикла вызываем себя передавая (номер банкноты + 1) для перебора более младших купюр, и собираем возвращенные результаты
- выбираем их полученных результатов один и возвращаем его
То есть один вызов функции перебирает купюру одного номинала.
Твой алгоритм менее понятен. Что делает рекурсивная функция, что она полчает на вход и что дает на выходе? Где гарантия что ты переберешь все возможные комбинации купюр? Ты вообще можешь описать свой алгоритм?
Если ты используешь алгоритм счетчика который я описал выше, то тебе не нужна рекурсия, а нужен просто цикл.
Возможно, тут стоит просто стереть код и написать заново. Он какой-то уж очень запутанный получается.
Я почитал свой пост, он тоже не очень понятен местами, так что задавай уточняющие вопросы, если что.
Аноны, напомню, у нас есть задачка на логику, >>538385 попробуйте порешать. а я напишу потом ответ и способы решения.
Пока проверю старые задачи.
>>537244
> Комментировать каждый кусок кода как-то не хочется, удержать весь класс в голове не получается
Его и не надо удерживать. Надо разбивать на отдельные функции так, что они будут помещаться на 1 экране.
> Когда я пытаюсь отладить рекурсию, мозг просто утекает.
Надо мыслить на уровне одного вызова функции, не залезая в рекурсию. Ну то есть в стиле «если число купюр больше нуля, то мы вызываем себя с числом купюр на 1 меньшим».
Давай начнем с архитектуры. Во-первых, у тебя очень странный ViewModel. Этим словом обычно называют класс, который хранит отображаемые на экране данные (и логику работы с ними). Ну то есть в твоем случае он должен хранить информацию о номиналах и числе купюр которое ты выводишь. Но он не должен содержать HTML код или пытаться вывести эти купюры. Более того, ViewModel не используют в языках типа PHP, его используют в JS в сочетании с data binding (привязка данных в объекте к данным на экране).
Таким образом, весь HTML оттуда надо убрать. Это задача View, то есть шаблона, генерировать HTML код.
Я подозреваю что после этого окажется что и сам класс, в общем-то больше не нужен.
Как передать информацию о проверенных комбинациях купюр? Ну я вижу тут такой вариант: массив массивов с комбинациями.
Далее, перейдем к этому файлу:
> https://github.com/hiigara123/ATM-machine/blob/master/inc/ViewController.php
С большой буквы обычно называют файл с классом, а этот файл можно назвать controller.php или просто init.php
Теперь перейдем к модели банкомата.
Тут https://github.com/hiigara123/ATM-machine/blob/master/inc/AtmMachine.php надо убрать жестко прописанные в коде запасы купюр, сумму и работу с _GET (это задача контроллера). Всю эту информацию надо передавать снаружи, через аргументы функции. В классе будет 1-2 публичных функции: одна для расчета выдачи и может быть вторая, для получения отладочной информации о проверенных комбинациях купюр.
К сожалению, код действительно не очень читабельный, возмодно из-за того что сложно было придумать хорошие названия для функций и переменных. Например возьмем эту строку:
> $diff = ($draw != $this->notes) ? $this->diff($draw) : $this->notes;
Эти названия ничего не говорят. diff это наверное разница, но почему тогда ты вызвыаешь функцию diff с одним параметром? Как можно найти разницу от одного аргумента? И что делает сравнение в первых скобках?
Стоит очевидно подписать комментарии хотя бы к функциям.
> $qnt
не стоит сокращать названия, это ухудшает читабельность. У тебя же есть автодополнение в редакторе.
> if(in_array($fill, $this->steps))
Ты учел что по умолчанию используется нестрогое сравнение массивов? Подходит ли оно для твоих целей? И по моему, это тут вообще не нужно, при правильном подходе одна комбинация не выпадет 2 раза.
> while(($this->getSumm($draw) + $nom <= $this->summ_requested) && $qnt > 0){
Нужно использовать деление вместо цикла
> return $this->recurse($fill, $note, 3);
У функции всего 2 аргумента
В общем, предалагаю переписать код. Для начала надо определить аргументы и результат функции. Я думаю, на вход она должна получать запас купюр, требуюмую сумму и текущую комбинацию, а на выходе давать либо желаемый набор, либо null если найти его не получилось.
Комбинации купюр являются размещениями с повторением: https://ru.wikipedia.org/wiki/%D0%A0%D0%B0%D0%B7%D0%BC%D0%B5%D1%89%D0%B5%D0%BD%D0%B8%D0%B5#.D0.A0.D0.B0.D0.B7.D0.BC.D0.B5.D1.89.D0.B5.D0.BD.D0.B8.D0.B5_.D1.81_.D0.BF.D0.BE.D0.B2.D1.82.D0.BE.D1.80.D0.B5.D0.BD.D0.B8.D1.8F.D0.BC.D0.B8
Алгоритм который тут нужен это алгоритм перебора всех возможных размещений. В простейшем случае (без рекурсии) он работает так:
- берем начальное размещение 0 0 0 0
- увеличиваем число младших купюр на 1: 0 0 0 1
- когда оно дойдет до максимума, напрмиер 0 0 0 99 то сбрасываем его и увеличиваем на 1 число более старших купюр: 0 0 1 0
- и так до 99 99 99 99
Здесь вместо 99 конечно должно быть меньшее из имещегося числа купюр и максимаьно возможного (то есть дающего сумму не больше требуемой)
Он может быть как рекурсивным так и нерекурсивным. В случае рекурсивной реализации, можно сделать например так:
функция перебора одной купюры (запас, желаемая сумма, текущая комбинация, номер банкноты)
- определяем максимально возможное число банкнот данного номинала исходя из запаса и суммы
- перебираем число банкнот данного номинала от 0 до N (или от N до 0 - это может быть быстрее)
- на каждом шаге цикла вызываем себя передавая (номер банкноты + 1) для перебора более младших купюр, и собираем возвращенные результаты
- выбираем их полученных результатов один и возвращаем его
То есть один вызов функции перебирает купюру одного номинала.
Твой алгоритм менее понятен. Что делает рекурсивная функция, что она полчает на вход и что дает на выходе? Где гарантия что ты переберешь все возможные комбинации купюр? Ты вообще можешь описать свой алгоритм?
Если ты используешь алгоритм счетчика который я описал выше, то тебе не нужна рекурсия, а нужен просто цикл.
Возможно, тут стоит просто стереть код и написать заново. Он какой-то уж очень запутанный получается.
Я почитал свой пост, он тоже не очень понятен местами, так что задавай уточняющие вопросы, если что.
>>537215
>>537246
Ошибка тут:
> $symbol1 = mb_substr($text1, $i, 1);
Это берет 1 букву
> $symbol2 = mb_substr($text1, $i, -1);
Это берет подстроку от $i до предпоследней буквы
И тут:
> if ($symbol1 == $symbol2) {
> echo "Результат проверки - {$resultFalse}";
> break;
По одному символу нельзя определить палиндром или нет, надо проверить половину строки.
>>537337
>>поле
> В смысле в свойстве?
Ну да
> Потому что мир не может думать за место мышек.
Мир возвращает список животных в радиусе от точки в моем предложении, он не думает за мышек. Он лишь хранит информацию кто где находится и предоставляет поиск и фильтрацию по ней.
> У них должно быть свое представление о мире. Понимаю что для изучения программирования такой подход не очень подходит, но пусть будет все реалистично. Это же не очень критично будет?
Можно, но тогда тебе придется сделать класс «ПредставлениеОМире», например WorldView, который будет служить как бы окном в World, у которого будут свойства координаты и радиус зрения, координаты придется обновлять каждый ход. У тебя будет один мир World, и у каждого животного отдельный объект WorldView. WorldView будет при вызове метода «получить всех видимых дивотных» например вызывать World и фильтровать полученный список животных по расстоянию.
Тебе оно нужно, лишний класс и необходимость постоянно обновлять координаты в нем? По моему проще встроить это ограничение радиуса зрения в World и просто передавать его в функции.
Заметь что в моем подходе информация о мире по прежнему хранится в однм-единственном месте — в World. Здесь нет дублирования информации и вызываемых этим проблем (необходимость обновлять все копии данных).
>>public function searchTheAnimal(World $world, Animal $animal) {
>>Назначение метода непонятно. Зачем искать животное в массиве если его координаты хранятся в свойствах x и y?
> Этот метод предназначен чтобы найти чтобы найти других животных в обозримой видимости.
А почему бы не поместить этот метод в World? По моему туда он впишется лучше. И почему
И еще у меня такой вопрос: почему ты выбираешь юолее неудобные способы хранения вместо более простых? Например World может хранить список животных в обычном одномерном массиве. Зачем делать сложный двухмерный массив в котором сложнее их искать и которй надо постоянно обновлять при перемещениях? Приведи свои аргументы в пользу этого списка тогда.
Аналогично я не понимаю, почему результат «список животных которых я вижу» ты сделал в виде сложног одвухмерного массива а не просто массива вида [object Cat, object Cat, object Mouse] ? По моему ты только усложняешь код.
>>public function moveAnimal(array $from, array $to) {
>>Зачем тут массивы? Почему не $x1, $y1,$x2, $y2?
>А так понятно будет?
>По моему так удобней - сразу видно какие координаты что значат. Почему так не правильно?
Мне кажется без массивов код будет проще и короче, но я не наставиваю, можно и как у тебя оставить.
>>Также, чем getCoordinate() удобнее чем getX() и getY()? По моему ты тут вводишь лишний массив без которого все только проще.
> Ну использование одного метода избавляет от лишней писанины, плюс я не уверен что когда-нибудь потребуется отдельно X и отдельно Y.
Использование одного метода раздувает код так как вместо $x или $fromX ты пишешь $coordinate['x'] или $from['x']. Но можно оставить твой вариант, я не против. Кстати как третий вариант, можно сделать класс Point cо свойствами x, y но это будет наверно уже многовато для простой задачи.
> Ну суть этого метода заключается в том, что животное может сгенерировать координату которая выходит за пределы карты. Этот метод всего лишь не дает им выйти за пределы карты.
Суть может быть и в этом, но метод написан неправильно, он не ограничивает передвижение:
> $to['y'] = $to['y'] - ($to['y'] - $this->m);
Эта строка сохраняет в $to['y'] значение $this->m (это видно если раскрыть скобки) которое очевидно находится за предалами карты.
> Так же я думал еще, с помощью этого метода сделать такую фичу: если животное пытается выйти за пределы карты, то оно ударяется об стенку, получает сотрясение и пропускает один ход о_х
Неверный подход. Если ты сгенерировал координаты за пределами карты значит в программе ошибка и лучше как можно раньше завершить программу, напрмер выбросив исключение, а не пытаться скрыть факт ошибки. Ведь скрывая его, ты лишь затрудняешь себе поиск причин этой ошибки.
>>Код надо бы переделать на работу с любым количеством котов и мышей. Кстати, алгоритм оценки ходов прост, понятен, легко работает с любым количеством животных.
> Мне не понятно как это сделать. Я подумаю над тем что именно мне не понятно, и позже задам вопрос.
Предлагаю такой алгоритм выбора хода животного:
- сгенерировать массив всех возможных ходов включая стоять на месте. Ход это фактически тройка значений (x, y, число очков)
- для каждого хода, оценить его в баллах. Например ход на клетку с которой рядом мышь, для кота ценнее чем ход на клетку от которой мыши далеко.
- выбрать ход с максимальной оценкой
Если что-то в нем непонятно, задай вопрос. По моему, так довольно простой алгоритм.
>>537215
>>537246
Ошибка тут:
> $symbol1 = mb_substr($text1, $i, 1);
Это берет 1 букву
> $symbol2 = mb_substr($text1, $i, -1);
Это берет подстроку от $i до предпоследней буквы
И тут:
> if ($symbol1 == $symbol2) {
> echo "Результат проверки - {$resultFalse}";
> break;
По одному символу нельзя определить палиндром или нет, надо проверить половину строки.
>>537337
>>поле
> В смысле в свойстве?
Ну да
> Потому что мир не может думать за место мышек.
Мир возвращает список животных в радиусе от точки в моем предложении, он не думает за мышек. Он лишь хранит информацию кто где находится и предоставляет поиск и фильтрацию по ней.
> У них должно быть свое представление о мире. Понимаю что для изучения программирования такой подход не очень подходит, но пусть будет все реалистично. Это же не очень критично будет?
Можно, но тогда тебе придется сделать класс «ПредставлениеОМире», например WorldView, который будет служить как бы окном в World, у которого будут свойства координаты и радиус зрения, координаты придется обновлять каждый ход. У тебя будет один мир World, и у каждого животного отдельный объект WorldView. WorldView будет при вызове метода «получить всех видимых дивотных» например вызывать World и фильтровать полученный список животных по расстоянию.
Тебе оно нужно, лишний класс и необходимость постоянно обновлять координаты в нем? По моему проще встроить это ограничение радиуса зрения в World и просто передавать его в функции.
Заметь что в моем подходе информация о мире по прежнему хранится в однм-единственном месте — в World. Здесь нет дублирования информации и вызываемых этим проблем (необходимость обновлять все копии данных).
>>public function searchTheAnimal(World $world, Animal $animal) {
>>Назначение метода непонятно. Зачем искать животное в массиве если его координаты хранятся в свойствах x и y?
> Этот метод предназначен чтобы найти чтобы найти других животных в обозримой видимости.
А почему бы не поместить этот метод в World? По моему туда он впишется лучше. И почему
И еще у меня такой вопрос: почему ты выбираешь юолее неудобные способы хранения вместо более простых? Например World может хранить список животных в обычном одномерном массиве. Зачем делать сложный двухмерный массив в котором сложнее их искать и которй надо постоянно обновлять при перемещениях? Приведи свои аргументы в пользу этого списка тогда.
Аналогично я не понимаю, почему результат «список животных которых я вижу» ты сделал в виде сложног одвухмерного массива а не просто массива вида [object Cat, object Cat, object Mouse] ? По моему ты только усложняешь код.
>>public function moveAnimal(array $from, array $to) {
>>Зачем тут массивы? Почему не $x1, $y1,$x2, $y2?
>А так понятно будет?
>По моему так удобней - сразу видно какие координаты что значат. Почему так не правильно?
Мне кажется без массивов код будет проще и короче, но я не наставиваю, можно и как у тебя оставить.
>>Также, чем getCoordinate() удобнее чем getX() и getY()? По моему ты тут вводишь лишний массив без которого все только проще.
> Ну использование одного метода избавляет от лишней писанины, плюс я не уверен что когда-нибудь потребуется отдельно X и отдельно Y.
Использование одного метода раздувает код так как вместо $x или $fromX ты пишешь $coordinate['x'] или $from['x']. Но можно оставить твой вариант, я не против. Кстати как третий вариант, можно сделать класс Point cо свойствами x, y но это будет наверно уже многовато для простой задачи.
> Ну суть этого метода заключается в том, что животное может сгенерировать координату которая выходит за пределы карты. Этот метод всего лишь не дает им выйти за пределы карты.
Суть может быть и в этом, но метод написан неправильно, он не ограничивает передвижение:
> $to['y'] = $to['y'] - ($to['y'] - $this->m);
Эта строка сохраняет в $to['y'] значение $this->m (это видно если раскрыть скобки) которое очевидно находится за предалами карты.
> Так же я думал еще, с помощью этого метода сделать такую фичу: если животное пытается выйти за пределы карты, то оно ударяется об стенку, получает сотрясение и пропускает один ход о_х
Неверный подход. Если ты сгенерировал координаты за пределами карты значит в программе ошибка и лучше как можно раньше завершить программу, напрмер выбросив исключение, а не пытаться скрыть факт ошибки. Ведь скрывая его, ты лишь затрудняешь себе поиск причин этой ошибки.
>>Код надо бы переделать на работу с любым количеством котов и мышей. Кстати, алгоритм оценки ходов прост, понятен, легко работает с любым количеством животных.
> Мне не понятно как это сделать. Я подумаю над тем что именно мне не понятно, и позже задам вопрос.
Предлагаю такой алгоритм выбора хода животного:
- сгенерировать массив всех возможных ходов включая стоять на месте. Ход это фактически тройка значений (x, y, число очков)
- для каждого хода, оценить его в баллах. Например ход на клетку с которой рядом мышь, для кота ценнее чем ход на клетку от которой мыши далеко.
- выбрать ход с максимальной оценкой
Если что-то в нем непонятно, задай вопрос. По моему, так довольно простой алгоритм.
Спроси разработчиков
>>537457
> } elseif ((($number % 10) > 1) && (($number % 10) < 5) && ((($number % 100) < 12) || (($number % 100) > 14))) {
Очень сложно как-то.
> $number % 10
> $number % 100
Это повторяется часто, вынеси в переменную
> foreach ($spelling as $delimeter => $string) {
В чем смысл делить на все числа в массиве подряд? Я что-то не очень понимаю как это вообще должно работать. А раз я не понимаю, я не могу убедиться что код 100% правильный. Попробуй тогда ты объяснить почему он гарантированно работает для любых чисел. А лучше переписать код чтобы он был понятен и очевиден.
Я думаю, тут логичнее завести массив вроде [100, 10, 1] и делить на него.
> if (($count = $number / $delimeter) >= 1) {
Ты зачем-то запутываешь код. Тут ведь можно написать if ($number >= $delimeter), зачем путать читателя?
> if (isset($return)) {
Это неправильно. Не должно быть такого что переменная может быть, а может и не быть, как в таких условиях писать надежный код и провеять его? Надо в начале функции присвоить ей какое-то значение.
>>537583
> сделал несколько сайтов знаешь ли для этого ни фреймворки не ооп не нужны были.
Но в вакансиях обычно требуется это и на сайтах используется и ООП и фреймворки. Чем ты гордишься, тем что не соответствуешь требованиям работодателей? Или тем что нагородил велосипедов с процедурной лапшой когда можно было сделать проще и быстрее (я код конечно не видел, так что это предположение)?
И я скажу сразу, в 99% случаев «ООП не нужен» говорят те, кто его не осилил.
> Я тебе уже объяснял, что я сверстал несколько сайтов. На фрилансе без опыта и звездочек и реальных висящих в инторнете сайтов-магазинов, сделанных тобой, заказы не получишь.
Возможно, давно туда не заходил.
>>537614
> Как сделать так что бы пока работает скрипт (а он работает долго) остальные люди его не запускали? Это кажется называется многопоточность, или нет?
Это называется блокировка. И я советую тебе бросить заниматься ерундой, сайтов проверки на уникальность много и все они занимаются тем что постоянно пытаются перехитрить поисковики, потому что за автоматизированные запросы они банят. Какой смысл делать еще один? Ты будешь тратить время не на улучшение алгоритма а на постоянный обход банов.
Если ты хочешь сделать все правильно (а наш тред учит как делать правильно), то ты должен написать своего бота, который будет обходить интернет и составлять огромную базу всех найденных текстов и искать по ней (для работы бота понадобится много серверов и широкий интернет-канал, это довольно дорого). На практике никто конечно своего бота писать не хочет, а все пытаются перехитрить поисковики.
У Яндекса по моему есть поисковое АПИ, но там какие-то ограничения действуют.
Что касается алгоритмов проверки уникальности, попробуй погуглить например.
>>537629
Такие комментарии не добавляют пользы. Тред не место для самоутверждения.
>>537642
> а я уже столько дохуя знаю, пиздец, аж сам себе поражаюсь
Критерий не то что ты думаешь о своих знаниях или какой ты умный, а что ты умеешь делать. Если ты ООП пока не осилил, то ты например не можешь работать с ООП кодом и твоя ценность в этом плане нулевая. А что касается другого раздела /wrk, я там не сижу и ничего прокомментировать не могу.
>>537814
> что должен возвращать метод search в моем мэппере? просто массив массивов как в mysqli, или же массив объектов с заполненными свойствами? Последнее логичнее, раз уж мы взялись за шаблоны и загружаем в таблицу объект, хотя я хз.
Лучше массив объектов.
Спроси разработчиков
>>537457
> } elseif ((($number % 10) > 1) && (($number % 10) < 5) && ((($number % 100) < 12) || (($number % 100) > 14))) {
Очень сложно как-то.
> $number % 10
> $number % 100
Это повторяется часто, вынеси в переменную
> foreach ($spelling as $delimeter => $string) {
В чем смысл делить на все числа в массиве подряд? Я что-то не очень понимаю как это вообще должно работать. А раз я не понимаю, я не могу убедиться что код 100% правильный. Попробуй тогда ты объяснить почему он гарантированно работает для любых чисел. А лучше переписать код чтобы он был понятен и очевиден.
Я думаю, тут логичнее завести массив вроде [100, 10, 1] и делить на него.
> if (($count = $number / $delimeter) >= 1) {
Ты зачем-то запутываешь код. Тут ведь можно написать if ($number >= $delimeter), зачем путать читателя?
> if (isset($return)) {
Это неправильно. Не должно быть такого что переменная может быть, а может и не быть, как в таких условиях писать надежный код и провеять его? Надо в начале функции присвоить ей какое-то значение.
>>537583
> сделал несколько сайтов знаешь ли для этого ни фреймворки не ооп не нужны были.
Но в вакансиях обычно требуется это и на сайтах используется и ООП и фреймворки. Чем ты гордишься, тем что не соответствуешь требованиям работодателей? Или тем что нагородил велосипедов с процедурной лапшой когда можно было сделать проще и быстрее (я код конечно не видел, так что это предположение)?
И я скажу сразу, в 99% случаев «ООП не нужен» говорят те, кто его не осилил.
> Я тебе уже объяснял, что я сверстал несколько сайтов. На фрилансе без опыта и звездочек и реальных висящих в инторнете сайтов-магазинов, сделанных тобой, заказы не получишь.
Возможно, давно туда не заходил.
>>537614
> Как сделать так что бы пока работает скрипт (а он работает долго) остальные люди его не запускали? Это кажется называется многопоточность, или нет?
Это называется блокировка. И я советую тебе бросить заниматься ерундой, сайтов проверки на уникальность много и все они занимаются тем что постоянно пытаются перехитрить поисковики, потому что за автоматизированные запросы они банят. Какой смысл делать еще один? Ты будешь тратить время не на улучшение алгоритма а на постоянный обход банов.
Если ты хочешь сделать все правильно (а наш тред учит как делать правильно), то ты должен написать своего бота, который будет обходить интернет и составлять огромную базу всех найденных текстов и искать по ней (для работы бота понадобится много серверов и широкий интернет-канал, это довольно дорого). На практике никто конечно своего бота писать не хочет, а все пытаются перехитрить поисковики.
У Яндекса по моему есть поисковое АПИ, но там какие-то ограничения действуют.
Что касается алгоритмов проверки уникальности, попробуй погуглить например.
>>537629
Такие комментарии не добавляют пользы. Тред не место для самоутверждения.
>>537642
> а я уже столько дохуя знаю, пиздец, аж сам себе поражаюсь
Критерий не то что ты думаешь о своих знаниях или какой ты умный, а что ты умеешь делать. Если ты ООП пока не осилил, то ты например не можешь работать с ООП кодом и твоя ценность в этом плане нулевая. А что касается другого раздела /wrk, я там не сижу и ничего прокомментировать не могу.
>>537814
> что должен возвращать метод search в моем мэппере? просто массив массивов как в mysqli, или же массив объектов с заполненными свойствами? Последнее логичнее, раз уж мы взялись за шаблоны и загружаем в таблицу объект, хотя я хз.
Лучше массив объектов.
> https://github.com/never3ver/vector/blob/master/Classes/Company.php
Вот это неправильно, что тут всюду статические методы. Теоретически, у нас одна компания в задаче. Но ведь нет никаких причин почему их не может быть несколько. Ну и даже если компания одна, у нас может быть несколько ее версий: что будет, если мы выберем один вариант или другой. Потому использовать статические методы абсолютно неправильно тут. Должны быть обычные, динамические методы.
Список департаментов это свойство компании, не надо его передавать в каждый метод.
И уж тем более нет никакого смысла передавать массив департаментов, а отдельно еще их число.
> https://github.com/never3ver/vector/blob/master/Classes/Employee.php
> abstract protected function getBasicSalary();
Эти функции нигде не вызываются. Какой в них тогда смысл? Я думаю, должно быть в конструкторе что-то такое:
$this->basicSalary = $this->getBasicSalary();
А сама функция содержит 1 строчку вроде return 500;
Если бы базовая зарплата была неизменной, то свойство было бы не нужно — хватило бы только метода.
> https://github.com/never3ver/vector/blob/master/Classes/Employee.php#L24
> $salary = $this->salary;
Я не вижу где в классе определено свойство salary. Ты не можешь обращаться к свойствам которых нет в классе, так как класс ничего не должен знать о своих потомках.
> public function isLeader() {
> if ($this->leader == true){
можно просто return $this->leader;
> https://github.com/never3ver/vector/blob/master/Classes/Department.php#L10
> public $engineers = [];
Я думаю, неправильно заводить отдельные свойства для каждой профессии. Это усложняет код (увольнения и найма) который должен теперь поддерживать 2 массива в актуальном состоянии и это не позволяет нам добавлять новые профессии не меняя старый код.
> public $managersToPromote;
> public function fireEmployeeAnticrisis($class, $anticrisis)
> public function raiseSalaryOfEmployee($class)
> public function promoteEmployeeToLeader($class)
Это все относится к антикризисным действиям и должно быть в другом классе, не в Department. В департаменте можно оставить только общие методы вроде найти всех сотрудников определенной профессии.
> https://github.com/never3ver/vector/blob/master/Classes/Department.php#L32
надо указывать 0 в качестве начального значения для array_reduce иначе при пустом массиве работников функция вернет NULL а не 0.
> https://github.com/never3ver/vector/blob/master/Classes/Department.php#L113
> $employee->anticrisis == true) {
У Employee нет свойства anticrisis
Везде, где функции принимают на вход массив или объект, надо поставить тайп-хинты. Тайп хинты позволяют указать, что аргумент функции должен быть определенного типа (например быть объектом определенного класса или его наследника). Тайп хинт делает код понятнее (так как видно какого типа переменная) и надежнее (так как PHP не позволит передать что-то неразрешенное и ты сразу увидишь ошибку). Используй их везде.
Мануал: http://php.net/manual/ru/language.oop5.typehinting.php
> https://github.com/never3ver/vector/blob/master/Classes/Department.php#L94
> $highest = $key;
> $this->employees[$highest]->setLeader();
Не надо хранить ключ массива, храни сам объект-сотрудника в переменной. Объекты ведь копируются по ссылке.
> https://github.com/never3ver/vector/blob/master/Anticrisis.php
Что-то многовато тут кода. Код никак не организован, не собран в функции, а сделан простыней. Я думаю, АнтикризисныйМенеджмент логично сделать классом, содержащим 3 метода (на каждй вариант). Каждый метод принимает на вход компанию и делает что-то с ней.
> function cloneDepartmentArray($target, array $source) // клонируем массив департаментов
Мне кажется методы клонироания должны быть в департаменте и компании, а не тут.
> foreach ($department->employees as $employee) {
> if (get_class($employee) == "Engineer") {
лучше в департаменте сделать метод поиска по классу.
Я бы сократил эту копипасту напрмер через массив:
$people = [
// содержательный комментарий
[ 5, 'Manager', 1 ]
[ 3, 'Engineer', 2 ]
];
$boss = new Engineer(...);
fillDepartment($department, $people, $boss);
> https://github.com/never3ver/vector/blob/master/Classes/Company.php
Вот это неправильно, что тут всюду статические методы. Теоретически, у нас одна компания в задаче. Но ведь нет никаких причин почему их не может быть несколько. Ну и даже если компания одна, у нас может быть несколько ее версий: что будет, если мы выберем один вариант или другой. Потому использовать статические методы абсолютно неправильно тут. Должны быть обычные, динамические методы.
Список департаментов это свойство компании, не надо его передавать в каждый метод.
И уж тем более нет никакого смысла передавать массив департаментов, а отдельно еще их число.
> https://github.com/never3ver/vector/blob/master/Classes/Employee.php
> abstract protected function getBasicSalary();
Эти функции нигде не вызываются. Какой в них тогда смысл? Я думаю, должно быть в конструкторе что-то такое:
$this->basicSalary = $this->getBasicSalary();
А сама функция содержит 1 строчку вроде return 500;
Если бы базовая зарплата была неизменной, то свойство было бы не нужно — хватило бы только метода.
> https://github.com/never3ver/vector/blob/master/Classes/Employee.php#L24
> $salary = $this->salary;
Я не вижу где в классе определено свойство salary. Ты не можешь обращаться к свойствам которых нет в классе, так как класс ничего не должен знать о своих потомках.
> public function isLeader() {
> if ($this->leader == true){
можно просто return $this->leader;
> https://github.com/never3ver/vector/blob/master/Classes/Department.php#L10
> public $engineers = [];
Я думаю, неправильно заводить отдельные свойства для каждой профессии. Это усложняет код (увольнения и найма) который должен теперь поддерживать 2 массива в актуальном состоянии и это не позволяет нам добавлять новые профессии не меняя старый код.
> public $managersToPromote;
> public function fireEmployeeAnticrisis($class, $anticrisis)
> public function raiseSalaryOfEmployee($class)
> public function promoteEmployeeToLeader($class)
Это все относится к антикризисным действиям и должно быть в другом классе, не в Department. В департаменте можно оставить только общие методы вроде найти всех сотрудников определенной профессии.
> https://github.com/never3ver/vector/blob/master/Classes/Department.php#L32
надо указывать 0 в качестве начального значения для array_reduce иначе при пустом массиве работников функция вернет NULL а не 0.
> https://github.com/never3ver/vector/blob/master/Classes/Department.php#L113
> $employee->anticrisis == true) {
У Employee нет свойства anticrisis
Везде, где функции принимают на вход массив или объект, надо поставить тайп-хинты. Тайп хинты позволяют указать, что аргумент функции должен быть определенного типа (например быть объектом определенного класса или его наследника). Тайп хинт делает код понятнее (так как видно какого типа переменная) и надежнее (так как PHP не позволит передать что-то неразрешенное и ты сразу увидишь ошибку). Используй их везде.
Мануал: http://php.net/manual/ru/language.oop5.typehinting.php
> https://github.com/never3ver/vector/blob/master/Classes/Department.php#L94
> $highest = $key;
> $this->employees[$highest]->setLeader();
Не надо хранить ключ массива, храни сам объект-сотрудника в переменной. Объекты ведь копируются по ссылке.
> https://github.com/never3ver/vector/blob/master/Anticrisis.php
Что-то многовато тут кода. Код никак не организован, не собран в функции, а сделан простыней. Я думаю, АнтикризисныйМенеджмент логично сделать классом, содержащим 3 метода (на каждй вариант). Каждый метод принимает на вход компанию и делает что-то с ней.
> function cloneDepartmentArray($target, array $source) // клонируем массив департаментов
Мне кажется методы клонироания должны быть в департаменте и компании, а не тут.
> foreach ($department->employees as $employee) {
> if (get_class($employee) == "Engineer") {
лучше в департаменте сделать метод поиска по классу.
Я бы сократил эту копипасту напрмер через массив:
$people = [
// содержательный комментарий
[ 5, 'Manager', 1 ]
[ 3, 'Engineer', 2 ]
];
$boss = new Engineer(...);
fillDepartment($department, $people, $boss);
Теперь к делу. Закончил исправлять ошибки в макете.
>>537876
>>537928
>>538284
>В верхнем блоке 5 слов были слишком жирными.
Нет, переставление жирности с 900 на 700 не помогло. Хотя на глаз, действительно, 900 многовато, но все-таки делал по шрифту указанному в PSD. Исправилось тем, что чуть увеличил расстояние между буквами. Стало более-менее уже похоже.
>В ИЕ10 вокруг ссылок синие рамки
Вылечил.
>Также, у тебя разброд и шатание в плане использования классов и идентификаторов, нет никакой единой системы. В большом проекте это 100% приведет к бардаку. Почитай хотя бы про БЭМ: ...
Вот уж здесь у меня проблемы это точно. Вообще не умею давать названия идам и классам. Да и расставлял сами иды и классы без разбора. С начала создания макета я использовал только классы, а иды начал использовать позже. Исправил это. Теперь где надо ид, там ид, где класс, там класс.
Так же прочитал статьи про БЭМ, думаю, что буду использовать. Попробовал реализовать. Хотя в моем макете это получилось как-то громоздко, хотя и старался использовать только там где нужно. А вообще я не могу понять на что ориентироваться. Если на все подряд вешать, то как бы облегчит понимание кода, но это уже детский сад какой-то, потому что и так вроде понятно. С другой стороны, я не знаю как видел бы этот код новичок и реально ли ему помогло бы в понимании его. Еще может сказывается, что макет небольшой и на нем БЭМ не совсем обязателен, а вот в большом проекте польза будет сразу видна.
>> @media all and (max-width: 720px) {
>> .portfolio-text-buttons-and-works input:nth-of-type(1):checked ~ #wrapper_portfolio_works > .graphic,
>> width: 49% !important;}
>Почему такой сложный селектор на 6 строк? Тут что-то не так. Ты ведь всего лишь меняешь ширину картинки, почему нельзя написать что-то вроде .portfolio-images > a { width: 49%; } (названия выдуманы)? Я думаю, тут какая-то ошибка.
.portfolio-images > a не написать т.к. размер подобным образом обнулен, а вот изменять его нужно только для конкретного чекнутого инпута. Вот и получаются эти 6 строк. Хотя длину их сократить удалось.
>Опять же, по поводу nth-of-type, я тебе кажется говорил в прошлый раз что это плохой подход так как малейшие перестановки кнопок местами все сломают.
Сменил на классы без проблем. Я почему-то думал что :checked применяется только к кнопкам, а на класс не повесить.
>> .android-with-text, .pc-with-text, .phone-with-text, .clock-with-text {width: 50% !important;}
>Здесь тоже вместо перечисления конкретных блоков можно было сделать как-то через родителя выборку, например .advantages-block > .advantage { ... }
Не совсем понял. В смысле повесить дополнительный класс на каждый див с этими айдишниками и применять уже к нему, а не к ним?
В общем повесил просто на див #advantages-block div
>> #header-words a {font-size: 16px !important;}
>> h1 {font-size: 30pt !important;
>Когда задаешь font-size задвавай и line-height
Зачем? В body я задал, этого вроде хватает.
>> <h1>We are <span class="bold900">Webpaint</span></h1>
>Как-то не очень красиво. Что это за стили в имени класса? Красивее сделать так <h1>We are <strong>Webpaint</strong></h1> так как тег strong обозначает смысловое выделение текста.
Уже делал strong, но там жирность была недостаточно большая. Потом переделал на класс. Установить нужную жирность для strong как-то не догадался изначально.
> .android-with-text {
> .pc-with-text {
> .phone-with-text {
>Тут сплошная копипаста. Так не пойдет. Программист не должен такое писать. Ты просто раздуваешь объем кода, какой смысл мне (или твоим коллегам) читать одно и то же 4 раза подряд?
Вот это побудило меня прошерстить весь код и сокращать все что можно. Статистика по сокращениям в самом конце.
>Также у тебя много копипасты и в других местах. Например, Get In Touch и Our Featured Works это h2 и можно было бы не повторять CSS код для них, а сделать один стиль для всех тегов h2.
У них только одна строка общая font-size и еще 6-7 оригинальных. Не стоит того.
>Также можно было сделать один класс для идущих за ними подзаголовоков тонким шрифтом.
Так вроде бы так и было изначально. Там копипасты нету, я ничего не исправлял.
> .portfolio-text-buttons-and-works input:nth-of-type(1):checked + label > span,
> .portfolio-text-buttons-and-works input:nth-of-type(2):checked + label > span,
> .portfolio-text-buttons-and-works input:nth-of-type(3):checked + label > span,
Это можно написать короче, без перечисления каждой кнопки, одно универсальное правило.
До того момента как пошел сокращать все, что найду, я даже не перечитывал старый код. Когда я начинал делать макет, я был ну уж совсем нубом и видимо тогда сокращение в этом месте не казалось настолько очевидным.
>Ну и весит страница в общем 1.2Мб, многовато. Я не помню, говорил ли я тебе что картинки портфолио надо делать в PNG? Просто мне сейчас пришла мысль что если их делать в JPEG с высоким качеством то весить они будут меньше, а выглядеть может быть будут примерно так же (это конечно надо проверять, может и не будут). Тогда мы бы могли сэкономить на весе страницы, так как картинки портфолио там чуть ли не половину этого мегабайта весят.
1.2 Мб? Разве? Папка сайта весила 2.84 Мб.
В PNG я делал сам. Так как вырезал картинки в тот момент еще в паинте, а там рука набита все сразу в PNG сохранять фотошопа в то время у меня еще не было. Переделал в Jpeg. Качество вроде бы никак не изменилось. А вот вес изображений из портфолио уменьшился с 1.02 Мб до 280 кб. Остальные изображения оставил в PNG, т.к. там вес 1-2 кб, думаю роли играть не будет, а белые точки на картинке уже не нужны.
Насчет шрифтов. Удалил ненужные шрифты. Теперь их общий вес 1.11 Мб против 1.62 Мб.
В общем вес уменьшился с 2.84 до 1.59. И это учитывая, что скачиваться будет не все, например из папки шрифтов только некоторая часть.
>Вообще, у тебя многовато CSS для такого простого макета. Я подозреваю причина как раз в копипасте.
Ну а насчет этого вот что. Я прошерстил весь ксс от начала до конца и искал что можно сократить. В итоге получилось на 20% меньше. Было 509 строк, стало 420. Да и сократил не только количество строк, но и длинну некоторых. Это все вручную, форматтерами не пользовался.
Так же еще немного подшаманил блок портфолио. Раньше там было по 4 работы на каждую категорию и поэтому они были все отцентрированы, но стоило поставить 3 5 и 4 то 3 и 5 были неотцентрованы. Сейчас я перемешал все работы, выставил различное количество на категории и все всегда по центру.
И еще я бы хотел сделать плавный переход до якоря по кнопке SEE PORTFOLIO. Сейчас он происходит рывком. И хотел бы это сделать с помощью CSS без скриптов. Такое возможно?
Теперь к делу. Закончил исправлять ошибки в макете.
>>537876
>>537928
>>538284
>В верхнем блоке 5 слов были слишком жирными.
Нет, переставление жирности с 900 на 700 не помогло. Хотя на глаз, действительно, 900 многовато, но все-таки делал по шрифту указанному в PSD. Исправилось тем, что чуть увеличил расстояние между буквами. Стало более-менее уже похоже.
>В ИЕ10 вокруг ссылок синие рамки
Вылечил.
>Также, у тебя разброд и шатание в плане использования классов и идентификаторов, нет никакой единой системы. В большом проекте это 100% приведет к бардаку. Почитай хотя бы про БЭМ: ...
Вот уж здесь у меня проблемы это точно. Вообще не умею давать названия идам и классам. Да и расставлял сами иды и классы без разбора. С начала создания макета я использовал только классы, а иды начал использовать позже. Исправил это. Теперь где надо ид, там ид, где класс, там класс.
Так же прочитал статьи про БЭМ, думаю, что буду использовать. Попробовал реализовать. Хотя в моем макете это получилось как-то громоздко, хотя и старался использовать только там где нужно. А вообще я не могу понять на что ориентироваться. Если на все подряд вешать, то как бы облегчит понимание кода, но это уже детский сад какой-то, потому что и так вроде понятно. С другой стороны, я не знаю как видел бы этот код новичок и реально ли ему помогло бы в понимании его. Еще может сказывается, что макет небольшой и на нем БЭМ не совсем обязателен, а вот в большом проекте польза будет сразу видна.
>> @media all and (max-width: 720px) {
>> .portfolio-text-buttons-and-works input:nth-of-type(1):checked ~ #wrapper_portfolio_works > .graphic,
>> width: 49% !important;}
>Почему такой сложный селектор на 6 строк? Тут что-то не так. Ты ведь всего лишь меняешь ширину картинки, почему нельзя написать что-то вроде .portfolio-images > a { width: 49%; } (названия выдуманы)? Я думаю, тут какая-то ошибка.
.portfolio-images > a не написать т.к. размер подобным образом обнулен, а вот изменять его нужно только для конкретного чекнутого инпута. Вот и получаются эти 6 строк. Хотя длину их сократить удалось.
>Опять же, по поводу nth-of-type, я тебе кажется говорил в прошлый раз что это плохой подход так как малейшие перестановки кнопок местами все сломают.
Сменил на классы без проблем. Я почему-то думал что :checked применяется только к кнопкам, а на класс не повесить.
>> .android-with-text, .pc-with-text, .phone-with-text, .clock-with-text {width: 50% !important;}
>Здесь тоже вместо перечисления конкретных блоков можно было сделать как-то через родителя выборку, например .advantages-block > .advantage { ... }
Не совсем понял. В смысле повесить дополнительный класс на каждый див с этими айдишниками и применять уже к нему, а не к ним?
В общем повесил просто на див #advantages-block div
>> #header-words a {font-size: 16px !important;}
>> h1 {font-size: 30pt !important;
>Когда задаешь font-size задвавай и line-height
Зачем? В body я задал, этого вроде хватает.
>> <h1>We are <span class="bold900">Webpaint</span></h1>
>Как-то не очень красиво. Что это за стили в имени класса? Красивее сделать так <h1>We are <strong>Webpaint</strong></h1> так как тег strong обозначает смысловое выделение текста.
Уже делал strong, но там жирность была недостаточно большая. Потом переделал на класс. Установить нужную жирность для strong как-то не догадался изначально.
> .android-with-text {
> .pc-with-text {
> .phone-with-text {
>Тут сплошная копипаста. Так не пойдет. Программист не должен такое писать. Ты просто раздуваешь объем кода, какой смысл мне (или твоим коллегам) читать одно и то же 4 раза подряд?
Вот это побудило меня прошерстить весь код и сокращать все что можно. Статистика по сокращениям в самом конце.
>Также у тебя много копипасты и в других местах. Например, Get In Touch и Our Featured Works это h2 и можно было бы не повторять CSS код для них, а сделать один стиль для всех тегов h2.
У них только одна строка общая font-size и еще 6-7 оригинальных. Не стоит того.
>Также можно было сделать один класс для идущих за ними подзаголовоков тонким шрифтом.
Так вроде бы так и было изначально. Там копипасты нету, я ничего не исправлял.
> .portfolio-text-buttons-and-works input:nth-of-type(1):checked + label > span,
> .portfolio-text-buttons-and-works input:nth-of-type(2):checked + label > span,
> .portfolio-text-buttons-and-works input:nth-of-type(3):checked + label > span,
Это можно написать короче, без перечисления каждой кнопки, одно универсальное правило.
До того момента как пошел сокращать все, что найду, я даже не перечитывал старый код. Когда я начинал делать макет, я был ну уж совсем нубом и видимо тогда сокращение в этом месте не казалось настолько очевидным.
>Ну и весит страница в общем 1.2Мб, многовато. Я не помню, говорил ли я тебе что картинки портфолио надо делать в PNG? Просто мне сейчас пришла мысль что если их делать в JPEG с высоким качеством то весить они будут меньше, а выглядеть может быть будут примерно так же (это конечно надо проверять, может и не будут). Тогда мы бы могли сэкономить на весе страницы, так как картинки портфолио там чуть ли не половину этого мегабайта весят.
1.2 Мб? Разве? Папка сайта весила 2.84 Мб.
В PNG я делал сам. Так как вырезал картинки в тот момент еще в паинте, а там рука набита все сразу в PNG сохранять фотошопа в то время у меня еще не было. Переделал в Jpeg. Качество вроде бы никак не изменилось. А вот вес изображений из портфолио уменьшился с 1.02 Мб до 280 кб. Остальные изображения оставил в PNG, т.к. там вес 1-2 кб, думаю роли играть не будет, а белые точки на картинке уже не нужны.
Насчет шрифтов. Удалил ненужные шрифты. Теперь их общий вес 1.11 Мб против 1.62 Мб.
В общем вес уменьшился с 2.84 до 1.59. И это учитывая, что скачиваться будет не все, например из папки шрифтов только некоторая часть.
>Вообще, у тебя многовато CSS для такого простого макета. Я подозреваю причина как раз в копипасте.
Ну а насчет этого вот что. Я прошерстил весь ксс от начала до конца и искал что можно сократить. В итоге получилось на 20% меньше. Было 509 строк, стало 420. Да и сократил не только количество строк, но и длинну некоторых. Это все вручную, форматтерами не пользовался.
Так же еще немного подшаманил блок портфолио. Раньше там было по 4 работы на каждую категорию и поэтому они были все отцентрированы, но стоило поставить 3 5 и 4 то 3 и 5 были неотцентрованы. Сейчас я перемешал все работы, выставил различное количество на категории и все всегда по центру.
И еще я бы хотел сделать плавный переход до якоря по кнопке SEE PORTFOLIO. Сейчас он происходит рывком. И хотел бы это сделать с помощью CSS без скриптов. Такое возможно?
>>537928
Там на главной ее сразу не найдешь, потому прямая ссыка на нужный (и бесплатный) раздел: https://www.browserstack.com/screenshots
Но если ты всерьез планируешь заниматься версткой, все же придется делать виртуальные машины для каждой версии ИЕ или брать готовые с сайта http://dev.modern.ie/tools/
>>538035
С точки зрения БД это не инъекция, а вполне легитимный SQL запрос. Она принципиально не может его отличить от других запросов.
>>538506
Это не приведение типов, а приведение collation. Ну и логично что резльтат функции зависит от ее аргументов.
>>538541
> Кажется, я плохо понимаю архитектуру, не знаю куда совать этот кусок кода:
Желательно кусок кода вынести в отдельную функцию или класс. Совать его надо в скрипт обработки формы, в самое начало наверно.
> Кстати, разве "сохраняем код в куки" и "продлеваем жизнь куки" не одно и тоже (setcookie)? Почему бы не вынести за скобки.
Одно и то же, но слова-то разные потому написано отдельно
> Если в каждом слимовском маршруте, то получится море копипаста, что никак не устроит.
> Прямо в шаблоне устанавливать куки тоже весьма странно.
Либо только в формах, либо в начале index.php либо ты можешь сделать slim middleware.
Слим использует луковичную архитектуру, когда ты можешь обернуть всю работу приложения (точнее обработку запроса) внутрь функции. То есть эта твоя функция может сделать что-то до обработки запроса и после. Причем она может вызвать следующий слой (в данном случае сам Слим), а может не вызвать. В данном случае она может до обработки запроса выставить куку, а в POST запросе проверить ее на совпадение с токеном из формы и сохранить куда-то результат этой проверки (еще можно вообще отвергать такой запрос, но это запутает пользователя, ведь при ошибке мы должны показать форму повтрно).
Кстати, раз мы заговорили про middleware, не хочешь ли ты в рамках его изучения решить простую задачку: сделать middleware, которое при добавлении в любое прилжение позволяет делать транслит. При запросе страницы с параметром ?translit=on или off оно включает или выключает режим транслита и сохраняет выбор в куке. При включенном режиме транслита сгенерированная приложением html-страница транслитерируется.
Это middleware должно быть полностью независимо от приложения, чтобы его можно например было подключить к любому слимовскому проекту.
Если понимаешь английский, документация:
Для нового слима: http://www.slimframework.com/docs/concepts/middleware.html
Для v2 (у тебя вроде он): http://docs.slimframework.com/middleware/overview/
Если нет то посмотри примеры кода. Там надо лишь создать класс унаследованный от слимовского и сделать в нем функцию call. А тут http://docs.slimframework.com/middleware/how-to-use/ есть пример похожего middleware, меняющего текст на странице.
Не забудь что обрабатывать надо только ответы с типом text/html иначе можно например сломать бинарные данные в картинке при попытке ее обработать.
Для нового Слима есть готовая защита от CSRF в виде Middleware но она какая-то запутанная по моему, посмотри сам: https://github.com/slimphp/Slim-Csrf/blob/master/src/Guard.php Что-то оно мне не нравится.
>>538545
Не знаю, а как ты определил что он генерируется заново? Напиши чуть подробнее.
>>538974
Пиши текст ошибки. Также есть шанс что ты просто передал не тот id. Также, не вставляй переменные в запрос, используй плейсхолдеры, я по моему тебе не первый раз говорю. И если ты делаешь файлообменник то $app->db->query это недопустимо, весь SQL должен быть в отдельном классе.
>>538992
Не очень удачный выбор, магазин обычно очень сложная вещь и требует много времени. Также, если ты совсем начинающий то тебе лучше начинать с более простых вещей вроде списка студентов или файлообменника из ОП поста. Если не совсем начинающий и прекрасно знаешь ООП, MVC, работу с формами, базой данных, то Юи 2 подойдет.
>>537928
Там на главной ее сразу не найдешь, потому прямая ссыка на нужный (и бесплатный) раздел: https://www.browserstack.com/screenshots
Но если ты всерьез планируешь заниматься версткой, все же придется делать виртуальные машины для каждой версии ИЕ или брать готовые с сайта http://dev.modern.ie/tools/
>>538035
С точки зрения БД это не инъекция, а вполне легитимный SQL запрос. Она принципиально не может его отличить от других запросов.
>>538506
Это не приведение типов, а приведение collation. Ну и логично что резльтат функции зависит от ее аргументов.
>>538541
> Кажется, я плохо понимаю архитектуру, не знаю куда совать этот кусок кода:
Желательно кусок кода вынести в отдельную функцию или класс. Совать его надо в скрипт обработки формы, в самое начало наверно.
> Кстати, разве "сохраняем код в куки" и "продлеваем жизнь куки" не одно и тоже (setcookie)? Почему бы не вынести за скобки.
Одно и то же, но слова-то разные потому написано отдельно
> Если в каждом слимовском маршруте, то получится море копипаста, что никак не устроит.
> Прямо в шаблоне устанавливать куки тоже весьма странно.
Либо только в формах, либо в начале index.php либо ты можешь сделать slim middleware.
Слим использует луковичную архитектуру, когда ты можешь обернуть всю работу приложения (точнее обработку запроса) внутрь функции. То есть эта твоя функция может сделать что-то до обработки запроса и после. Причем она может вызвать следующий слой (в данном случае сам Слим), а может не вызвать. В данном случае она может до обработки запроса выставить куку, а в POST запросе проверить ее на совпадение с токеном из формы и сохранить куда-то результат этой проверки (еще можно вообще отвергать такой запрос, но это запутает пользователя, ведь при ошибке мы должны показать форму повтрно).
Кстати, раз мы заговорили про middleware, не хочешь ли ты в рамках его изучения решить простую задачку: сделать middleware, которое при добавлении в любое прилжение позволяет делать транслит. При запросе страницы с параметром ?translit=on или off оно включает или выключает режим транслита и сохраняет выбор в куке. При включенном режиме транслита сгенерированная приложением html-страница транслитерируется.
Это middleware должно быть полностью независимо от приложения, чтобы его можно например было подключить к любому слимовскому проекту.
Если понимаешь английский, документация:
Для нового слима: http://www.slimframework.com/docs/concepts/middleware.html
Для v2 (у тебя вроде он): http://docs.slimframework.com/middleware/overview/
Если нет то посмотри примеры кода. Там надо лишь создать класс унаследованный от слимовского и сделать в нем функцию call. А тут http://docs.slimframework.com/middleware/how-to-use/ есть пример похожего middleware, меняющего текст на странице.
Не забудь что обрабатывать надо только ответы с типом text/html иначе можно например сломать бинарные данные в картинке при попытке ее обработать.
Для нового Слима есть готовая защита от CSRF в виде Middleware но она какая-то запутанная по моему, посмотри сам: https://github.com/slimphp/Slim-Csrf/blob/master/src/Guard.php Что-то оно мне не нравится.
>>538545
Не знаю, а как ты определил что он генерируется заново? Напиши чуть подробнее.
>>538974
Пиши текст ошибки. Также есть шанс что ты просто передал не тот id. Также, не вставляй переменные в запрос, используй плейсхолдеры, я по моему тебе не первый раз говорю. И если ты делаешь файлообменник то $app->db->query это недопустимо, весь SQL должен быть в отдельном классе.
>>538992
Не очень удачный выбор, магазин обычно очень сложная вещь и требует много времени. Также, если ты совсем начинающий то тебе лучше начинать с более простых вещей вроде списка студентов или файлообменника из ОП поста. Если не совсем начинающий и прекрасно знаешь ООП, MVC, работу с формами, базой данных, то Юи 2 подойдет.
> for(; 0<1; )
Для вечного цикла можно писать for (;;) или while (true) что более узнаваемо.
Код у тебя непраивльный вот тут:
> $creditSum = ($creditSum x $percent) + $comission - $payout;
Ты всегда платишь ровно 5000. Но в последний месяц надо платить не 5000 а сколько осталось. Алгоритм должен быть такой:
- прибавляем проценты и комиссию к остатку долга
- если остаток маленький, выплачиваем сколько осталось и уходим
- иначе платим 5000
«Платим» здесь значит уменьшаем долг и увеличиваем общую сумму выплаченного.
Ответ во втором банке получается около 61270.
>>539101
Бутстрап можно взять для админки, для сайта уж очень приевшийся. да и что там верстать? Список товаров легко верстается и руками.
> может лучше сделай фреймворк сам
Это месяцы, если не годы. Глупо, надо изучить сначала то, что есть.
> или возьми что-то вроде Zend (лол), Symphony, Codeigniter (самый простой) или Laravel.
Зенд не очень популяен, Симфони хороший но может быть сложным для наичнающего, кодеигнайтер безнадежное старье.
>>539109
> Что ещё интересно - процедурный вариант скрипта работает на 30-40% быстрее, кажется об этом говорили кодеры VK, объясняя, почему у них сайт написан в процедурном стиле.
Такой большой разницы быть не должно, дело наверно в чем-то другом.
>>539145
Не очень понимаю твой вопрос, и видимо ты сам плохо знаешь HTTP раз не можешь его верно сформулировать. Если ты имел в виду как передать значение из PHP скрипта в JS в ответе на аякс-запрос то очевидно JSON'ом, в PHP есть функции для его создания.
>>539148
> Алсо дайте пример использования дата маппера,
Тут есть какие-то куски кода: https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md
> Алсо дайте пример использования дата маппера, как в него переменные за пределом класса пихать?
Какие именно переменные? Через конструктор или аргументы метода но зависит от ситуации, а ты подробности не пишешь.
>>539172
Чтобы написать такой сервис надо заключить договор с оператором состовой связи и получить доступ к центру обмена сообщениями (SMSC).
Также есть вариант подключиь сотовый телефон к компьютеру и отправлять сообщения через него.
>>539216
Комментарии по статье:
- автор велосипедист. Нет никакого смысла писать свой адаптер для работы с БД, есть много библиотек, например Doctrine DBAL (не путай с Doctrine ORM). Написанный автором адаптер обладает неудачным, плохо продуманным интерфейсом, например методы Select/insert очень примитивные и неудобные.
- подход, когда мы передаем в метод кусок SQL (метод update и delete) дурной и ведет к SQL инъекциям
- автор считает DataMapper чем-то сложным и энтерпрайзным, это не так на мой взгляд. Если ты используешь библиотеку вроде Doctrine ORM то тебе мапперы писать вообще не надо — она их предоставляет готовые.
- интерфейсы дял маппера писать не обязательно
- идея делать один маппер зависимым от другого (PostMapper от CommentMapper) может привести к проблемам когда они окажутся взаимно зависимы
- идея делать вот такой анализ переданного аргумента в общем плохая:
> public function delete($id) {
> if ($id instanceof PostInterface) {
надо сделать 2 отдельных функции
> $this->adapter->delete($this->entityTable, "id = $id");
Это быдлокод и SQL инъекция
- в плюс автору можно дать то, что он использует модели и мапперы, но на мой взгляд это можно было сделать проще и написать в конце мысль что писать свои мапперы не надо, а надо взять готовую библиотеку
Если тебе что-то непонятно в этом паттерне, задавай конкретные вопросы.
>>539227
Почему проект должен быть сложным? Маппер это всего лишь класс который отображает объекты на строки базы данных.
>>539322
А как бы ты сделал без мапперов? Писать SQL запросы в index.php и гонять туда-сюда массивы вместо объектов это быдлокод, предупреждаю сразую
> (тем более со встроенным в слиме $app->db сложно это в маппер запихать).
В слим ничего такого не встроено.
>>539384
Он плохой, он еще во времена PHP4 писался и там куча дурных вещей.
>>539389
Без кода не скажем
>>539393
Актуальность можно посмотреть на hh.ru
>>539397
> А гдеб посмотреть варианты решения других анонов?
Боюсь что нигде, но можно запостить тут код для проверки и я скажу если что не так.
> for(; 0<1; )
Для вечного цикла можно писать for (;;) или while (true) что более узнаваемо.
Код у тебя непраивльный вот тут:
> $creditSum = ($creditSum x $percent) + $comission - $payout;
Ты всегда платишь ровно 5000. Но в последний месяц надо платить не 5000 а сколько осталось. Алгоритм должен быть такой:
- прибавляем проценты и комиссию к остатку долга
- если остаток маленький, выплачиваем сколько осталось и уходим
- иначе платим 5000
«Платим» здесь значит уменьшаем долг и увеличиваем общую сумму выплаченного.
Ответ во втором банке получается около 61270.
>>539101
Бутстрап можно взять для админки, для сайта уж очень приевшийся. да и что там верстать? Список товаров легко верстается и руками.
> может лучше сделай фреймворк сам
Это месяцы, если не годы. Глупо, надо изучить сначала то, что есть.
> или возьми что-то вроде Zend (лол), Symphony, Codeigniter (самый простой) или Laravel.
Зенд не очень популяен, Симфони хороший но может быть сложным для наичнающего, кодеигнайтер безнадежное старье.
>>539109
> Что ещё интересно - процедурный вариант скрипта работает на 30-40% быстрее, кажется об этом говорили кодеры VK, объясняя, почему у них сайт написан в процедурном стиле.
Такой большой разницы быть не должно, дело наверно в чем-то другом.
>>539145
Не очень понимаю твой вопрос, и видимо ты сам плохо знаешь HTTP раз не можешь его верно сформулировать. Если ты имел в виду как передать значение из PHP скрипта в JS в ответе на аякс-запрос то очевидно JSON'ом, в PHP есть функции для его создания.
>>539148
> Алсо дайте пример использования дата маппера,
Тут есть какие-то куски кода: https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md
> Алсо дайте пример использования дата маппера, как в него переменные за пределом класса пихать?
Какие именно переменные? Через конструктор или аргументы метода но зависит от ситуации, а ты подробности не пишешь.
>>539172
Чтобы написать такой сервис надо заключить договор с оператором состовой связи и получить доступ к центру обмена сообщениями (SMSC).
Также есть вариант подключиь сотовый телефон к компьютеру и отправлять сообщения через него.
>>539216
Комментарии по статье:
- автор велосипедист. Нет никакого смысла писать свой адаптер для работы с БД, есть много библиотек, например Doctrine DBAL (не путай с Doctrine ORM). Написанный автором адаптер обладает неудачным, плохо продуманным интерфейсом, например методы Select/insert очень примитивные и неудобные.
- подход, когда мы передаем в метод кусок SQL (метод update и delete) дурной и ведет к SQL инъекциям
- автор считает DataMapper чем-то сложным и энтерпрайзным, это не так на мой взгляд. Если ты используешь библиотеку вроде Doctrine ORM то тебе мапперы писать вообще не надо — она их предоставляет готовые.
- интерфейсы дял маппера писать не обязательно
- идея делать один маппер зависимым от другого (PostMapper от CommentMapper) может привести к проблемам когда они окажутся взаимно зависимы
- идея делать вот такой анализ переданного аргумента в общем плохая:
> public function delete($id) {
> if ($id instanceof PostInterface) {
надо сделать 2 отдельных функции
> $this->adapter->delete($this->entityTable, "id = $id");
Это быдлокод и SQL инъекция
- в плюс автору можно дать то, что он использует модели и мапперы, но на мой взгляд это можно было сделать проще и написать в конце мысль что писать свои мапперы не надо, а надо взять готовую библиотеку
Если тебе что-то непонятно в этом паттерне, задавай конкретные вопросы.
>>539227
Почему проект должен быть сложным? Маппер это всего лишь класс который отображает объекты на строки базы данных.
>>539322
А как бы ты сделал без мапперов? Писать SQL запросы в index.php и гонять туда-сюда массивы вместо объектов это быдлокод, предупреждаю сразую
> (тем более со встроенным в слиме $app->db сложно это в маппер запихать).
В слим ничего такого не встроено.
>>539384
Он плохой, он еще во времена PHP4 писался и там куча дурных вещей.
>>539389
Без кода не скажем
>>539393
Актуальность можно посмотреть на hh.ru
>>539397
> А гдеб посмотреть варианты решения других анонов?
Боюсь что нигде, но можно запостить тут код для проверки и я скажу если что не так.
> 'use stript'
Опечатка, также нет точки с запятой. Видимо у тебя руки на автомате script пишут, у меня тоже такое бывает.
Задание 1
выглядит верно, если робот принимает то ок
Задание 2
> arResult
Советую писать просто result, ибо читабельность страдает
> if(typeof(fn) == 'function') {
> return false;
Вот это неправильно. Ты усложняешь код. Теперь тот кто вызывает твою функцию обязан писать каждый раз if чтобы проверить не вернула ли она false, причем большинство забьют на это дело и ошибки будут игнорироваться. Ты закладываешь мину замедленного действия этим. При ошибке надо выбрасывать исключпение с понятным текстом. Статья по теме:
https://gist.github.com/codedokode/65d43ca5ac95c762bc1a
http://habrahabr.ru/post/218325/
В остальном, верно
задание 3
То же самое по поводу false, используй исключения.
> if([].constructor !== Array
Во-первых вместо того чтобы городить странную конструкцию достаточно использовать оператор instanceof который именно для такой цели предназначен. Во-вторых эта проверка не сработает если массив был создан в другом окне или фрейме (так как там window.Array это другой объект), это известный подвох в JS:
http://bolknote.ru/2012/04/28/~3644 (старая статья!)
https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray (работает только в новых бразерах с ES5)
В остальном, верно, если робот не жалуется.
задание 4
> a.constructor !== Function
Лучше через typeof или instanceof
В остальном, верно.
задание 5
> var func = arguments[0],
Func лучше писать в скобках в определении функции ради читабельности чтобы сразу было его видно
> if(arguments[0].constructor === Function && arguments.length > 0) {
Ты молча игноируешь ошибку, а надо выбрасывать исключение
> [].concat.call
Это не требуется так как у тебя оба массива настоящие и у них есть метод concat.Трюк с [].slice используется потому что arguments это не массив и у него нет метода slice, потому мы берем метод у массива и вместо this подсовываем arguments (и да, это разрешено стандартом и работает везде).
В остальном верно, если робот не против.
задание 6
Что-то отступов слишком много, может надо код отрефаторить? Огромный if в который заключено все тело функции, надо перевернуть и вынести ее из него.
При ошибке надо выбрасывать исключение, а не игнорировать.
> arg = [].shift.call(arguments);
Это опасная тропинка, я не помню, разрешено ли модифицировать arguments, и безопаснее сделать из нее массив и работать с ним.
> if(typeof(arg) === 'undefined') {
typeof не нужен для сравнения тут, можно сравнить напрямую
> [].concat.call(arg
Можно просто arg.concat
В общем, тут надо уменьшить вложенность и не модицифировать arguments.
задание 7
То же по поводу исключений
> [].slice.call(arguments, 0));
Тут slice не нужен, apply принимает объект arguments напрямую.
задание 8
То же самое по поводу исключеий. Более того, я бы вообще тут не делал проверку, тогда метод будет работать не только с настоящими массивами, а со всем у чего есть метод forEach.
> if(e.constructor === Object) {
Это неверно. Никто не сказал что тебе будут передаваться только созданные через литерал { ... } объекты. А что если я передам что-то вроде var x = new X; x.prop = y; ?
задание 9
> var result = new Array;
> return arr.filter(fn)
Это ты умно придумал, а в чем же задача? ну не знаю, если тебе не жалко старые браузеры без поддержки Es5, давай оставим так.
Задача 10
Ну ок, пусть будет так, хотя можно бы добавить еще проверку через hasOwnProperty: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty
> 'use stript'
Опечатка, также нет точки с запятой. Видимо у тебя руки на автомате script пишут, у меня тоже такое бывает.
Задание 1
выглядит верно, если робот принимает то ок
Задание 2
> arResult
Советую писать просто result, ибо читабельность страдает
> if(typeof(fn) == 'function') {
> return false;
Вот это неправильно. Ты усложняешь код. Теперь тот кто вызывает твою функцию обязан писать каждый раз if чтобы проверить не вернула ли она false, причем большинство забьют на это дело и ошибки будут игнорироваться. Ты закладываешь мину замедленного действия этим. При ошибке надо выбрасывать исключпение с понятным текстом. Статья по теме:
https://gist.github.com/codedokode/65d43ca5ac95c762bc1a
http://habrahabr.ru/post/218325/
В остальном, верно
задание 3
То же самое по поводу false, используй исключения.
> if([].constructor !== Array
Во-первых вместо того чтобы городить странную конструкцию достаточно использовать оператор instanceof который именно для такой цели предназначен. Во-вторых эта проверка не сработает если массив был создан в другом окне или фрейме (так как там window.Array это другой объект), это известный подвох в JS:
http://bolknote.ru/2012/04/28/~3644 (старая статья!)
https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray (работает только в новых бразерах с ES5)
В остальном, верно, если робот не жалуется.
задание 4
> a.constructor !== Function
Лучше через typeof или instanceof
В остальном, верно.
задание 5
> var func = arguments[0],
Func лучше писать в скобках в определении функции ради читабельности чтобы сразу было его видно
> if(arguments[0].constructor === Function && arguments.length > 0) {
Ты молча игноируешь ошибку, а надо выбрасывать исключение
> [].concat.call
Это не требуется так как у тебя оба массива настоящие и у них есть метод concat.Трюк с [].slice используется потому что arguments это не массив и у него нет метода slice, потому мы берем метод у массива и вместо this подсовываем arguments (и да, это разрешено стандартом и работает везде).
В остальном верно, если робот не против.
задание 6
Что-то отступов слишком много, может надо код отрефаторить? Огромный if в который заключено все тело функции, надо перевернуть и вынести ее из него.
При ошибке надо выбрасывать исключение, а не игнорировать.
> arg = [].shift.call(arguments);
Это опасная тропинка, я не помню, разрешено ли модифицировать arguments, и безопаснее сделать из нее массив и работать с ним.
> if(typeof(arg) === 'undefined') {
typeof не нужен для сравнения тут, можно сравнить напрямую
> [].concat.call(arg
Можно просто arg.concat
В общем, тут надо уменьшить вложенность и не модицифировать arguments.
задание 7
То же по поводу исключений
> [].slice.call(arguments, 0));
Тут slice не нужен, apply принимает объект arguments напрямую.
задание 8
То же самое по поводу исключеий. Более того, я бы вообще тут не делал проверку, тогда метод будет работать не только с настоящими массивами, а со всем у чего есть метод forEach.
> if(e.constructor === Object) {
Это неверно. Никто не сказал что тебе будут передаваться только созданные через литерал { ... } объекты. А что если я передам что-то вроде var x = new X; x.prop = y; ?
задание 9
> var result = new Array;
> return arr.filter(fn)
Это ты умно придумал, а в чем же задача? ну не знаю, если тебе не жалко старые браузеры без поддержки Es5, давай оставим так.
Задача 10
Ну ок, пусть будет так, хотя можно бы добавить еще проверку через hasOwnProperty: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty
Скрипт запускаешь через командную строку или крон
>>539586
Не надо ничего компилировать. Есть екзешники, посмотри на apachelounge как описано тут: https://gist.github.com/codedokode/10774100
Не бери сборки, ставь руками.
>>539606
ищи причину ошибки, в логах или включи их отображение.
В PHP по умолчанию выключено отображение ошибок в браузере, так как обычному пользователю сайта эта информация ни к чему. Но тебе, как программисту, надо видеть эти ошибки. Вот, как можно их просмотреть:
- ошибки сохраняются в лог ошибок. Можно открыть его и почитать. Если ты запускаешь код на локалхосте, у себя, то лог хранится в папке Апача (обычно она называется logs) и имеет название вроде error.log (в линуксе в папку /var/log/apache2 ). Если на хостинге — там либо есть файл error.log либо раздел в панели управления, где лог можно посмотреть
- также, ты можешь включить отображение ошибок. Открой файл php.ini, поставь там display_errors = On и error_reporting = E_ALL и перезапусти сервер. Теперь ошибки должны выводиться на экран.
Проверить, работает ли вывод ошибок, можно запустив скрипт содержающий обращение к несуществующей переменной вроде echo $sdgasdad; и проверив, выведется ошибка или нет. Если все верно, то должна вывестись.
>>539607
Во втором банке ответ около 61268. также посмотри внизу, там ошибка:
> PHP Notice: Undefined variable: paid in /home/nUNdce/prog.php on line 7
Надо переменную создать сначала а потом только использловать.
>>539639
Не надо openserver, есть билды на apachelounge.
>>539696
alert очень раздражает, лучше рядом с полем выводить красным ошибку
>>539700
Иногда надо выбрать одно значение (например сумму всех значений) или одномерный массив (все id которые соответствуют условиям).
>>539701
Откуда этот код? Вопрос наверно лучше автору задать.
Метод prepare ничего не проверяет, он создает подготовленный запрос. Это в мануале PHP описано.
>>539703
за парсинг и рассылку спама на Западе можно получить штраф или присесть. У нас вряд ли, но почтовики просто внесут тебя в спам и твои письма никуда не дойдут.
Адреса должны собираться у пользователей, добровольно. Например ты можешь предложить скидку всем кто подпишется на рассылку. Также ты должен использовать подтверждение адреса и не слать людям которые его не подтвердили. Зайди на любой интернет-магазин вроде lamoda и посмотри как они это делают.
>>539706
Для этого нужно как минимум юрлицо. Никто такой доступ человеку с улицы не даст.
>>539710
Покажи код и задай вопрос что именно тебе непонятно. Начинающему конечно сложно самому во всем разобраться, но я готов подсказать. Начать можно с примеров отсюда: https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md
>>539797
В моей почте например весь спам идет прямиком в одноименную папку и я его не открываю.
>>539854
Да
>>539952
git clone /x/y . по идее должен работать
> а там всего несколько файлов склонировалось с моими свежими изменениями в моей ветке,
А ты их закоммитил? Клонируется же репозиторий (то что в .git) а не файлы в рабочей папке.
>>539956
Нет, копируется репозиторий, то есть все что закоммичено.
Скрипт запускаешь через командную строку или крон
>>539586
Не надо ничего компилировать. Есть екзешники, посмотри на apachelounge как описано тут: https://gist.github.com/codedokode/10774100
Не бери сборки, ставь руками.
>>539606
ищи причину ошибки, в логах или включи их отображение.
В PHP по умолчанию выключено отображение ошибок в браузере, так как обычному пользователю сайта эта информация ни к чему. Но тебе, как программисту, надо видеть эти ошибки. Вот, как можно их просмотреть:
- ошибки сохраняются в лог ошибок. Можно открыть его и почитать. Если ты запускаешь код на локалхосте, у себя, то лог хранится в папке Апача (обычно она называется logs) и имеет название вроде error.log (в линуксе в папку /var/log/apache2 ). Если на хостинге — там либо есть файл error.log либо раздел в панели управления, где лог можно посмотреть
- также, ты можешь включить отображение ошибок. Открой файл php.ini, поставь там display_errors = On и error_reporting = E_ALL и перезапусти сервер. Теперь ошибки должны выводиться на экран.
Проверить, работает ли вывод ошибок, можно запустив скрипт содержающий обращение к несуществующей переменной вроде echo $sdgasdad; и проверив, выведется ошибка или нет. Если все верно, то должна вывестись.
>>539607
Во втором банке ответ около 61268. также посмотри внизу, там ошибка:
> PHP Notice: Undefined variable: paid in /home/nUNdce/prog.php on line 7
Надо переменную создать сначала а потом только использловать.
>>539639
Не надо openserver, есть билды на apachelounge.
>>539696
alert очень раздражает, лучше рядом с полем выводить красным ошибку
>>539700
Иногда надо выбрать одно значение (например сумму всех значений) или одномерный массив (все id которые соответствуют условиям).
>>539701
Откуда этот код? Вопрос наверно лучше автору задать.
Метод prepare ничего не проверяет, он создает подготовленный запрос. Это в мануале PHP описано.
>>539703
за парсинг и рассылку спама на Западе можно получить штраф или присесть. У нас вряд ли, но почтовики просто внесут тебя в спам и твои письма никуда не дойдут.
Адреса должны собираться у пользователей, добровольно. Например ты можешь предложить скидку всем кто подпишется на рассылку. Также ты должен использовать подтверждение адреса и не слать людям которые его не подтвердили. Зайди на любой интернет-магазин вроде lamoda и посмотри как они это делают.
>>539706
Для этого нужно как минимум юрлицо. Никто такой доступ человеку с улицы не даст.
>>539710
Покажи код и задай вопрос что именно тебе непонятно. Начинающему конечно сложно самому во всем разобраться, но я готов подсказать. Начать можно с примеров отсюда: https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md
>>539797
В моей почте например весь спам идет прямиком в одноименную папку и я его не открываю.
>>539854
Да
>>539952
git clone /x/y . по идее должен работать
> а там всего несколько файлов склонировалось с моими свежими изменениями в моей ветке,
А ты их закоммитил? Клонируется же репозиторий (то что в .git) а не файлы в рабочей папке.
>>539956
Нет, копируется репозиторий, то есть все что закоммичено.
Ну да, сделать чтобы на страницу вели ссылки с других страниц, по аналогии с википедией где в тексте стоят ссылки на другие страницы. только там их люди ставят осмысленно, а тут от балды и человеку это только помешает читать текст.
>>539980
Это только для мусорных сайтов нужно, если текст человек пишет он лучше наверно ссылки расставит.
>>539993
Задавал бы вопросы или писал что конкретно непонятно. Начинающему сложно разобраться, но я готов подсказать.
>>540016
По идее надо смотреть в инспекторе в браузере (Ctrl + Shift + I) или анализировать трафик и смотреть что именно там в ответе не так.
>>540031
Ты близоруко смотришь. Если бы интернетом пользовалась кучка специалистов, программисты бы были маловостребованы. Именно благодаря тому что интернетом пользуется каждая домохозяйка, мы можем зарабатывать деньги на нем.
>>540036
> Во-первых, древовидные категории товаров. Прочитал твою статью, выбрал естественно самый простой способ (Adjacency List).
Зря. Во-первых так ты ничему не научишься, во-вторых для категорий часто нужна выборка детей, выборка дерева и там идеально подходит Nested Sets. Может даже есть готовый плагин для Юи.
> Но я не знаю как поступить с уникальными свойствами для каждой конкретной категории объявления.
Entity Attribute Value
> Если я выберу Single Table Inharitance, то получается все эти уникальные свойства придется делать ее колонками, и для большинства записей они будут выставлены в null.
Я думаю тут нужно EAV, а не наследование так как видов сущностей много, менеджеры могут добавлять новые свойства и характеристики, не лезть же им в базу напрямую.
> Надеюсь, у меня не получится полсотни таблиц. Или это нормально?
В твоем случае нет.
> А когда он выберет из списка категорию, тогда должны аяксом подгрузиться все остальные необходимые поля
Тут можно и без аякса, категорий немного, список полей можно заложить прямо в страницу в виде JSON, будет проще и надежнее.
> Так что выбрать-то?
EAV конечно
>>540043
Единицы измерения только надо отдельно хранить, ты нарушаешь нормализацию (надо хранить атомарные значения а не составные)
>>540046
EAV гугли
>>540069
А это сложная задача. Ты хоть что-то написал? Для начала разбей строку на символы и в цикле перебирай по одному символу. Затем сделай переменную для хранения текущего числа и в нее заноси по одной встреченные цифры. А после этого покажи код и продолжим дальше.
> Может есть смысл задрочить алгоритмы какие-нибудь? Что бы научиться строить эти цепочки действий, даже простейшие.
Наверно есть смысл решать задачи, а если непонятно, попросить тут подсказку. Позже можно будет и за алгоритмы взятья, если захочешь.
>>540138
Прибавлять или вычитать единицу?
>>540189
Смотри в мануале функции range(), array_fill_keys(), array_fill()
>>540193
> [] +=
тут что-то лишнее
>>540216
А, я видел. А что же он пугливый такой-то.
Ну да, сделать чтобы на страницу вели ссылки с других страниц, по аналогии с википедией где в тексте стоят ссылки на другие страницы. только там их люди ставят осмысленно, а тут от балды и человеку это только помешает читать текст.
>>539980
Это только для мусорных сайтов нужно, если текст человек пишет он лучше наверно ссылки расставит.
>>539993
Задавал бы вопросы или писал что конкретно непонятно. Начинающему сложно разобраться, но я готов подсказать.
>>540016
По идее надо смотреть в инспекторе в браузере (Ctrl + Shift + I) или анализировать трафик и смотреть что именно там в ответе не так.
>>540031
Ты близоруко смотришь. Если бы интернетом пользовалась кучка специалистов, программисты бы были маловостребованы. Именно благодаря тому что интернетом пользуется каждая домохозяйка, мы можем зарабатывать деньги на нем.
>>540036
> Во-первых, древовидные категории товаров. Прочитал твою статью, выбрал естественно самый простой способ (Adjacency List).
Зря. Во-первых так ты ничему не научишься, во-вторых для категорий часто нужна выборка детей, выборка дерева и там идеально подходит Nested Sets. Может даже есть готовый плагин для Юи.
> Но я не знаю как поступить с уникальными свойствами для каждой конкретной категории объявления.
Entity Attribute Value
> Если я выберу Single Table Inharitance, то получается все эти уникальные свойства придется делать ее колонками, и для большинства записей они будут выставлены в null.
Я думаю тут нужно EAV, а не наследование так как видов сущностей много, менеджеры могут добавлять новые свойства и характеристики, не лезть же им в базу напрямую.
> Надеюсь, у меня не получится полсотни таблиц. Или это нормально?
В твоем случае нет.
> А когда он выберет из списка категорию, тогда должны аяксом подгрузиться все остальные необходимые поля
Тут можно и без аякса, категорий немного, список полей можно заложить прямо в страницу в виде JSON, будет проще и надежнее.
> Так что выбрать-то?
EAV конечно
>>540043
Единицы измерения только надо отдельно хранить, ты нарушаешь нормализацию (надо хранить атомарные значения а не составные)
>>540046
EAV гугли
>>540069
А это сложная задача. Ты хоть что-то написал? Для начала разбей строку на символы и в цикле перебирай по одному символу. Затем сделай переменную для хранения текущего числа и в нее заноси по одной встреченные цифры. А после этого покажи код и продолжим дальше.
> Может есть смысл задрочить алгоритмы какие-нибудь? Что бы научиться строить эти цепочки действий, даже простейшие.
Наверно есть смысл решать задачи, а если непонятно, попросить тут подсказку. Позже можно будет и за алгоритмы взятья, если захочешь.
>>540138
Прибавлять или вычитать единицу?
>>540189
Смотри в мануале функции range(), array_fill_keys(), array_fill()
>>540193
> [] +=
тут что-то лишнее
>>540216
А, я видел. А что же он пугливый такой-то.
Ответ очевиден: вместо того чтобы перечислять все категории картинок, надо справа написать «все картинки», как-то так:
#button-all:checked ~ #wrapper_portfolio_works > li
(я не помню какая именно там верстка и каким тегом сделаны блоки с картинками)
Аналогично у тебя еще в нескольких местах можно упростить код.
>>540233
> плохо то что нельзя четко указать тип, придется использовать варчар)
Можно сделать так:
id
int_value
char_value
datetime_value
+ поле type ENUM 'int', 'char', 'datetime' в одной из таблиц.
Но тут надо подумать и оценить сложность поддержки этого на стороне PHP. Если не очень сложно, то можно так сделать.
Я должен также заметить что в EAV у нас много таблиц и сложные запросы с джойнами. Придется поломать голову чтобы выбирать данные эффективно. Проблемы с производительностью, если они будут, впрочем, реально решить кешированием.
> таблица property_type
Сюда еще наверно стоит добавить единицу измерения (кв.м., лс, литры) и тип значения (число, текст, выбор из вариантов)
> ad_property (собственно таблица с перечислением уникальных свойств для объявления)
В чем ее смысл? Почему не добавить ad_id в таблицу property? Одно заполненное свойство используется несколькими объявлениями?
> И невозможен ORM, придется использовать DAO. Сложность выборки и вставки.
Почему? Распиши-ка подробнее.
> уникальные поля хранятся в одном столбце
Не понял, какие именно
> нет возможности указать тип.
Есть, ценой усложнения кода, смотри выше.
> Одним словом, будет сложность с валидацией формы.
Я думаю, на стороне PHP это как-то можно инкапсулировать в класс, может быть в класс Объявление добавить нужные методы.
Также, если типов объявлений немного то эффективнее не делать аякс-запрос при выборе категории, а заложить данные о полях и их типах в страницу в виде JSON и выбирать из него. Это может быть простейший список, вида
{ id категории: [ список типов полей ] }
Не стоит городить аякс запросы там, где проще «впечь» данные в страницу.
>>540240
По поводу первой статьи и презентации на которую она ссылается. У нас есть 2 аргмента в пользу EAV и против table inheritance:
- получается много таблиц с огромным числом колонок. Это бардак, так как сложно работать с огромным числом однотипных таблиц.
- невозможно добавлять новые типы полей без изменения БД
Второй аргумент тут важнее, table inheritance используется там где типы и число полей фиксированно, но у нас это не так.
Причем в презентации это тоже упоминается: http://www.slideshare.net/slideshow/embed_code/key/3edboR53WfTlbt?startSlide=31
Далее, на askdev приведены аргументы:
> EAV задумывалась как гибкая модель хранения данных, сам заказчик может добавлять аттрибуты, не прибегая к помощи разработчиков. На практике же заказчики не особо горят желанием ковыряться в системе и что-то там добавлять. Все-равно это делает программист. И тут вместо простого alter table add column приходится распутывать цепочку черти-чего. Все инструменты работы с базами данных заточены на отображение плоской структуры, а тут нужно отображать дерево.
Изменения надо делать не в БД напрямую, а через класс или интерфейс админки.
> Но самое ужасное, заказчики предъявляют требования на логику поведения тех или иных объектов. В системе появляются хранимые функции, триггеры и прочее. Только вместо нормальной логики они содержат зубодробильные конструкции типа where attribute_id = 86024327 and root_entity_id = 87641055
не надо делать триггеры, это надо делать на стороне PHP и там это реализуется вполне нормально.
> EAV - это выворачивание реляционной модели наизнанку.
Зато мы избавляемся от лишней сложности.
> Для yii кстати есть вроде какая-то библиотека
Это хорошо, но внимательно изучи документацию и код, чтобы знать как она работает. Ну и жаль что она для Юи 1, лучше конечно 2-ю версию изучать.
Ответ очевиден: вместо того чтобы перечислять все категории картинок, надо справа написать «все картинки», как-то так:
#button-all:checked ~ #wrapper_portfolio_works > li
(я не помню какая именно там верстка и каким тегом сделаны блоки с картинками)
Аналогично у тебя еще в нескольких местах можно упростить код.
>>540233
> плохо то что нельзя четко указать тип, придется использовать варчар)
Можно сделать так:
id
int_value
char_value
datetime_value
+ поле type ENUM 'int', 'char', 'datetime' в одной из таблиц.
Но тут надо подумать и оценить сложность поддержки этого на стороне PHP. Если не очень сложно, то можно так сделать.
Я должен также заметить что в EAV у нас много таблиц и сложные запросы с джойнами. Придется поломать голову чтобы выбирать данные эффективно. Проблемы с производительностью, если они будут, впрочем, реально решить кешированием.
> таблица property_type
Сюда еще наверно стоит добавить единицу измерения (кв.м., лс, литры) и тип значения (число, текст, выбор из вариантов)
> ad_property (собственно таблица с перечислением уникальных свойств для объявления)
В чем ее смысл? Почему не добавить ad_id в таблицу property? Одно заполненное свойство используется несколькими объявлениями?
> И невозможен ORM, придется использовать DAO. Сложность выборки и вставки.
Почему? Распиши-ка подробнее.
> уникальные поля хранятся в одном столбце
Не понял, какие именно
> нет возможности указать тип.
Есть, ценой усложнения кода, смотри выше.
> Одним словом, будет сложность с валидацией формы.
Я думаю, на стороне PHP это как-то можно инкапсулировать в класс, может быть в класс Объявление добавить нужные методы.
Также, если типов объявлений немного то эффективнее не делать аякс-запрос при выборе категории, а заложить данные о полях и их типах в страницу в виде JSON и выбирать из него. Это может быть простейший список, вида
{ id категории: [ список типов полей ] }
Не стоит городить аякс запросы там, где проще «впечь» данные в страницу.
>>540240
По поводу первой статьи и презентации на которую она ссылается. У нас есть 2 аргмента в пользу EAV и против table inheritance:
- получается много таблиц с огромным числом колонок. Это бардак, так как сложно работать с огромным числом однотипных таблиц.
- невозможно добавлять новые типы полей без изменения БД
Второй аргумент тут важнее, table inheritance используется там где типы и число полей фиксированно, но у нас это не так.
Причем в презентации это тоже упоминается: http://www.slideshare.net/slideshow/embed_code/key/3edboR53WfTlbt?startSlide=31
Далее, на askdev приведены аргументы:
> EAV задумывалась как гибкая модель хранения данных, сам заказчик может добавлять аттрибуты, не прибегая к помощи разработчиков. На практике же заказчики не особо горят желанием ковыряться в системе и что-то там добавлять. Все-равно это делает программист. И тут вместо простого alter table add column приходится распутывать цепочку черти-чего. Все инструменты работы с базами данных заточены на отображение плоской структуры, а тут нужно отображать дерево.
Изменения надо делать не в БД напрямую, а через класс или интерфейс админки.
> Но самое ужасное, заказчики предъявляют требования на логику поведения тех или иных объектов. В системе появляются хранимые функции, триггеры и прочее. Только вместо нормальной логики они содержат зубодробильные конструкции типа where attribute_id = 86024327 and root_entity_id = 87641055
не надо делать триггеры, это надо делать на стороне PHP и там это реализуется вполне нормально.
> EAV - это выворачивание реляционной модели наизнанку.
Зато мы избавляемся от лишней сложности.
> Для yii кстати есть вроде какая-то библиотека
Это хорошо, но внимательно изучи документацию и код, чтобы знать как она работает. Ну и жаль что она для Юи 1, лучше конечно 2-ю версию изучать.
>>540247
> Для третьей задачки в ход вступает теория вероятностей.
А можно подробнее?
Нам нужен именно чат или борда (борда наверно лучше, но там могут быть свои правила, свои авторитеты которые нам будут не рады и тд).
>запасной тред например на доброчане
Про него не слышал, но перекатился бы спокойно на любую другую борду. Да и думаю другие аноны пассивные так же сделали бы.
>чат вроде gitter (читать можно без регистрации, писать через github аккаунт)
С другой стороны это бы было дополнительным стимулом для анонов разбираться с гитом, который им в будущем понадобится как, например, мне.
Но все-таки у меня лично душа к другой борде лежит.
Не затерялась бы моя паста в этом потоке твоих, ОП, паст. А то там и Лунев отклеился, да и по размеру и стилистике схожа.
>>540260
> Во втором банке ответ около 61268.
Проценты на остаток же.
>также посмотри внизу, там ошибка:
> PHP Notice: Undefined variable: paid in /home/nUNdce/prog.php on line 7
сделал
Опчик, ты долго еще сегодня тут будешь? Я не осилил первую задачу на регулярные выражения про телефонный номер. Только через костыль в виде вытягивания цифр номера после кода в отдельную переменную с последующим пересчетом
С центрированием переключение портфолио стало выглядеть гораздо интереснее.
Надо разобраться с такими проблемами:
- CSS спрайты (чтобы увидеть что ты их понял и умеешь делать): спрайт с андроидом, спрайт с соц иконками, спрайт с телефоном и картой.
- во всех анимациях надо перечислить конкретные свойства которые анимируются во избежание нежелательных эффектов
- в портфолио мне не нравится что меняется ширина внутреннего элемента (img) а не внешнего (a). Точнее, у тебя там по умолчанию меняется ширина обоих. Есть ли причина почему мы не можем анимировать внешний элемент, а для img просто поставить max-width: 100%? По моему тут нет никакой особой причины, просто ты сам запутался.
> Хотя на глаз, действительно, 900 многовато, но все-таки делал по шрифту указанному в PSD.
Ок, значит виноваты особенности рендеринга, винда видимо утолщает жирный шрифт (но так как большинство пользователей под ней сидят, эти особенности игнорировать неправильно). Пусть тогда 900 будет.
> Вообще не умею давать названия идам и классам.
Привыкай, что поделать. Советую использовать схему «блок-элемент», например .menu__item. На больших проектах можно в начало добавлять префиксом название страницы или раздела, например «личный кабинет» — member area — префикс ma-....
> Теперь где надо ид, там ид, где класс, там класс.
Я советую в следующий раз отказываться от id в верстке. Преимуществ у них нет, недостатки есть (не могут повторяться, нельзя дать 2 id). Лишний шанс получить ошибки в верстке из-за повторений. Правил вроде «если класс встречается 1 раз то заменяем на id» нету, и делать так нехорошо, так как сегодня у тебя один блок, а завтра их может оказаться два, и что ты будешь делать?
> <h2 id="greeting-block--h2"
h2 достаточно уникальный селектор и можно было не давать ему id, а писать:
.greeting-block h2 { ... }
> greeting-block--see-portfolio-button
Я подумал, можно было писать просто b-greeting, b- как раз обозначает block (на сайте БЭМ раньше это было написано, не знаю, есть ли сейчас). А g- обозначает глобальные классы вроде выделения цветом или крупного шрифта. А l- значит layout, элементы отвечающий за общую компоновку страницы.
> light-gray-advantages-block
light-gray тут лишнее, надо в HTML описывать назначение блока а не его внешний вид который может менять при редизайне или смене темы оформления (если они есть на сайте).
> <h4 class="advantages-block--android-with-text--h4">
Не, это стоило сверстать так:
div.b-advantages
.....div.b-advantage--item.item-android
............h4 (без классов)
.....div.b-advantage--item.item-pc
............h4
Вместо b-advantages можно конечно писать advantages-block. Как видишь, мы пометили все 4 блока общим классом чтобы применить к нему общие стили.
Можно сделать и без этого, используя селектор
.b-advantages > div
Обрати внимание на > — он обязателен, так как див распространенный элемент и верстальщик всегда может внутрь блока добавить новый див и он тогда попадет под этот селектор.
> .see-portfolio-button, .portfolio-block--button:hover, .see-portfolio-button:hover, .portfolio-block--button, .social-icons > a, .social-icons > a:hover {
> Ну на 15 строк меньше стало. Стоит того ведь?
Думаю, да. Но плохо что ты указал длительность анимации но не указал свойства которые анимируются. Нужно их перечислять чтобы анимировались только они, а не любые свойства.
> #contacts-block--p1, #contacts-block--p2
Тут стоило не ставить на них никакие id, а для отступа просто сделать класс вроде .offset-left
> #contacts-block--p1:before {
> content: url(../img/kap.png);
Тут кстати спрайт почему-то ты не сделал. Не разобрался со спрайтами?
> #advantages-block div {
Нужно использовать ... > div, так как див распространенный тег и если кто-нибудь добавить внутрь колонки .advantages-block--android-with-text еще пару дивов, то эти стили к ним применятся (хотя не должны).
> background-image: url(../img/android.png);
То же самое, это бы спрайтом сделать надо.
> content: " ";
Можно без пробела, "". Пробел был нужен в каких-то древних браузерах.
> #portfolio-block:after {
> display: block;
> content: " ";
> clear: both;
Для таких вещей лучше наверно сделать класс с названием clearfix (или g-clearfix чтобы подчеркнуть что он глобальный).
> #portfolio-block--button-all:checked ~ #portfolio-block--wrapper > .graphic,
> #portfolio-block--button-all:checked ~ #portfolio-block--wrapper > .illustration,
> #portfolio-block--button-all:checked ~ #portfolio-block--wrapper > .motion
Это можно заменить на:
#portfolio-block--button-all:checked ~ #portfolio-block--wrapper > a
> footer {
> width: 100%;
Блоки и так растягиваются на ширину родителя по умолчанию, это писать не нужно
> <span class="contacts-block--social-icons-text">
текст можно скрыть гораздо проще, без добавления спана:
- поставить color совпадающий с фоном + overflow hidden чтобы текст не вышел за границу блока
- поставить большой text-indent + nowrap (чтобы не переносился) + overflow hidden
- поставить color: rgba() с прозрачностью + overflow hidden
> 1.2 Мб? Разве? Папка сайта весила 2.84 Мб.
Я смотрю на вкладке Network. Сколько файлов лежит на диске, не имеет значения, важно сколько нужно для отображения страницы (если быть еще точнее, сколько нужно скачать для отображения первого экрана).
> .portfolio-images > a не написать т.к. размер подобным образом обнулен, а вот изменять его нужно только для конкретного чекнутого инпута. Вот и получаются эти 6 строк.
По моему ты что-то путаешь. У тебя есть стиль
.portfolio-block--work { width: 0; }
Это не запрещает нам написать перекрывающий его стиль
#portfolio-block--button-all:checked ~ #portfolio-block .portfolio-block--work { width: 100%; }
Ведь этот селектор применяется только при нажатой кнопке, и он переопределит ширину. Объясни, почему по твоему так делать нельзя или неправильно? По умолчанию картинка скрыта, но если кнопка нажата, то показывается.
Ну и напомню, что надо разобраться что именно ты анимируешь, элемент a или img.
> #portfolio-block a {
> width: 0;
Угадаешь сам что здесь неправильно? Подсказка: попробуй в подзаголовок в блоке портфолио добавить ссылку.
Когда ты пишешь селектор, ты должен делать его максимально узким, чтобы он выбирал только нужные элеименты, и был защищен от изменений верстки в будущем. В данном случае, он должен выбирать не все ссылки в секции портфолио, а только ссылки внутри блока с картинками.
>Я почему-то думал что :checked применяется только к кнопкам, а на класс не повесить.
Это просто условие в селекторе, оно вообще может использоваться отдельно (разумеется писать так не стоит, это просто пример):
:checked { background: red; }
:checked.class#id { ... }
(ссылка на стандарт на англ с описанием синтаксиса: http://www.w3.org/TR/css3-selectors/#selector-syntax )
> В смысле повесить дополнительный класс на каждый див с этими айдишниками и применять уже к нему, а не к ним?
> В общем повесил просто на див #advantages-block div
Либо класс либо использовать > div
>>Когда задаешь font-size задвавай и line-height
> Зачем? В body я задал, этого вроде хватает.
Точно, ты прав тут. Наследуются значения, заданные в px или без единицы измерения. А вот если указать em или % то наследуется вычисленное значение и получаются артефакты: https://developer.mozilla.org/en-US/docs/Web/CSS/line-height#Prefer_unitless_numbers_for_line-height_values
Я думал, там всегда только пиксельное значение наследуется.
>>Также у тебя много копипасты и в других местах. Например, Get In Touch и Our Featured Works это h2 и можно было бы не повторять CSS код для них, а сделать один стиль для всех тегов h2.
> У них только одна строка общая font-size и еще 6-7 оригинальных. Не стоит того.
Это странно, на макете заголовки выглядят одинаково. Ну ладно, пусть так будет.
> И еще я бы хотел сделать плавный переход до якоря по кнопке SEE PORTFOLIO. Сейчас он происходит рывком. И хотел бы это сделать с помощью CSS без скриптов. Такое возможно?
Нет, CSS задает вид страницы, а не особенности ее прокрутки. Если хочешь делать на скриптах, тогда убедись что кнопка «назад» работает как раньше — так как многие скрипты ее ломают (они перехатывают клик по ссылки и переход не сохраняется в историю навигации). Жутко бесит. По идее плавную прокрутку должен конечно делать браузер, а не каждый сайт.
С центрированием переключение портфолио стало выглядеть гораздо интереснее.
Надо разобраться с такими проблемами:
- CSS спрайты (чтобы увидеть что ты их понял и умеешь делать): спрайт с андроидом, спрайт с соц иконками, спрайт с телефоном и картой.
- во всех анимациях надо перечислить конкретные свойства которые анимируются во избежание нежелательных эффектов
- в портфолио мне не нравится что меняется ширина внутреннего элемента (img) а не внешнего (a). Точнее, у тебя там по умолчанию меняется ширина обоих. Есть ли причина почему мы не можем анимировать внешний элемент, а для img просто поставить max-width: 100%? По моему тут нет никакой особой причины, просто ты сам запутался.
> Хотя на глаз, действительно, 900 многовато, но все-таки делал по шрифту указанному в PSD.
Ок, значит виноваты особенности рендеринга, винда видимо утолщает жирный шрифт (но так как большинство пользователей под ней сидят, эти особенности игнорировать неправильно). Пусть тогда 900 будет.
> Вообще не умею давать названия идам и классам.
Привыкай, что поделать. Советую использовать схему «блок-элемент», например .menu__item. На больших проектах можно в начало добавлять префиксом название страницы или раздела, например «личный кабинет» — member area — префикс ma-....
> Теперь где надо ид, там ид, где класс, там класс.
Я советую в следующий раз отказываться от id в верстке. Преимуществ у них нет, недостатки есть (не могут повторяться, нельзя дать 2 id). Лишний шанс получить ошибки в верстке из-за повторений. Правил вроде «если класс встречается 1 раз то заменяем на id» нету, и делать так нехорошо, так как сегодня у тебя один блок, а завтра их может оказаться два, и что ты будешь делать?
> <h2 id="greeting-block--h2"
h2 достаточно уникальный селектор и можно было не давать ему id, а писать:
.greeting-block h2 { ... }
> greeting-block--see-portfolio-button
Я подумал, можно было писать просто b-greeting, b- как раз обозначает block (на сайте БЭМ раньше это было написано, не знаю, есть ли сейчас). А g- обозначает глобальные классы вроде выделения цветом или крупного шрифта. А l- значит layout, элементы отвечающий за общую компоновку страницы.
> light-gray-advantages-block
light-gray тут лишнее, надо в HTML описывать назначение блока а не его внешний вид который может менять при редизайне или смене темы оформления (если они есть на сайте).
> <h4 class="advantages-block--android-with-text--h4">
Не, это стоило сверстать так:
div.b-advantages
.....div.b-advantage--item.item-android
............h4 (без классов)
.....div.b-advantage--item.item-pc
............h4
Вместо b-advantages можно конечно писать advantages-block. Как видишь, мы пометили все 4 блока общим классом чтобы применить к нему общие стили.
Можно сделать и без этого, используя селектор
.b-advantages > div
Обрати внимание на > — он обязателен, так как див распространенный элемент и верстальщик всегда может внутрь блока добавить новый див и он тогда попадет под этот селектор.
> .see-portfolio-button, .portfolio-block--button:hover, .see-portfolio-button:hover, .portfolio-block--button, .social-icons > a, .social-icons > a:hover {
> Ну на 15 строк меньше стало. Стоит того ведь?
Думаю, да. Но плохо что ты указал длительность анимации но не указал свойства которые анимируются. Нужно их перечислять чтобы анимировались только они, а не любые свойства.
> #contacts-block--p1, #contacts-block--p2
Тут стоило не ставить на них никакие id, а для отступа просто сделать класс вроде .offset-left
> #contacts-block--p1:before {
> content: url(../img/kap.png);
Тут кстати спрайт почему-то ты не сделал. Не разобрался со спрайтами?
> #advantages-block div {
Нужно использовать ... > div, так как див распространенный тег и если кто-нибудь добавить внутрь колонки .advantages-block--android-with-text еще пару дивов, то эти стили к ним применятся (хотя не должны).
> background-image: url(../img/android.png);
То же самое, это бы спрайтом сделать надо.
> content: " ";
Можно без пробела, "". Пробел был нужен в каких-то древних браузерах.
> #portfolio-block:after {
> display: block;
> content: " ";
> clear: both;
Для таких вещей лучше наверно сделать класс с названием clearfix (или g-clearfix чтобы подчеркнуть что он глобальный).
> #portfolio-block--button-all:checked ~ #portfolio-block--wrapper > .graphic,
> #portfolio-block--button-all:checked ~ #portfolio-block--wrapper > .illustration,
> #portfolio-block--button-all:checked ~ #portfolio-block--wrapper > .motion
Это можно заменить на:
#portfolio-block--button-all:checked ~ #portfolio-block--wrapper > a
> footer {
> width: 100%;
Блоки и так растягиваются на ширину родителя по умолчанию, это писать не нужно
> <span class="contacts-block--social-icons-text">
текст можно скрыть гораздо проще, без добавления спана:
- поставить color совпадающий с фоном + overflow hidden чтобы текст не вышел за границу блока
- поставить большой text-indent + nowrap (чтобы не переносился) + overflow hidden
- поставить color: rgba() с прозрачностью + overflow hidden
> 1.2 Мб? Разве? Папка сайта весила 2.84 Мб.
Я смотрю на вкладке Network. Сколько файлов лежит на диске, не имеет значения, важно сколько нужно для отображения страницы (если быть еще точнее, сколько нужно скачать для отображения первого экрана).
> .portfolio-images > a не написать т.к. размер подобным образом обнулен, а вот изменять его нужно только для конкретного чекнутого инпута. Вот и получаются эти 6 строк.
По моему ты что-то путаешь. У тебя есть стиль
.portfolio-block--work { width: 0; }
Это не запрещает нам написать перекрывающий его стиль
#portfolio-block--button-all:checked ~ #portfolio-block .portfolio-block--work { width: 100%; }
Ведь этот селектор применяется только при нажатой кнопке, и он переопределит ширину. Объясни, почему по твоему так делать нельзя или неправильно? По умолчанию картинка скрыта, но если кнопка нажата, то показывается.
Ну и напомню, что надо разобраться что именно ты анимируешь, элемент a или img.
> #portfolio-block a {
> width: 0;
Угадаешь сам что здесь неправильно? Подсказка: попробуй в подзаголовок в блоке портфолио добавить ссылку.
Когда ты пишешь селектор, ты должен делать его максимально узким, чтобы он выбирал только нужные элеименты, и был защищен от изменений верстки в будущем. В данном случае, он должен выбирать не все ссылки в секции портфолио, а только ссылки внутри блока с картинками.
>Я почему-то думал что :checked применяется только к кнопкам, а на класс не повесить.
Это просто условие в селекторе, оно вообще может использоваться отдельно (разумеется писать так не стоит, это просто пример):
:checked { background: red; }
:checked.class#id { ... }
(ссылка на стандарт на англ с описанием синтаксиса: http://www.w3.org/TR/css3-selectors/#selector-syntax )
> В смысле повесить дополнительный класс на каждый див с этими айдишниками и применять уже к нему, а не к ним?
> В общем повесил просто на див #advantages-block div
Либо класс либо использовать > div
>>Когда задаешь font-size задвавай и line-height
> Зачем? В body я задал, этого вроде хватает.
Точно, ты прав тут. Наследуются значения, заданные в px или без единицы измерения. А вот если указать em или % то наследуется вычисленное значение и получаются артефакты: https://developer.mozilla.org/en-US/docs/Web/CSS/line-height#Prefer_unitless_numbers_for_line-height_values
Я думал, там всегда только пиксельное значение наследуется.
>>Также у тебя много копипасты и в других местах. Например, Get In Touch и Our Featured Works это h2 и можно было бы не повторять CSS код для них, а сделать один стиль для всех тегов h2.
> У них только одна строка общая font-size и еще 6-7 оригинальных. Не стоит того.
Это странно, на макете заголовки выглядят одинаково. Ну ладно, пусть так будет.
> И еще я бы хотел сделать плавный переход до якоря по кнопке SEE PORTFOLIO. Сейчас он происходит рывком. И хотел бы это сделать с помощью CSS без скриптов. Такое возможно?
Нет, CSS задает вид страницы, а не особенности ее прокрутки. Если хочешь делать на скриптах, тогда убедись что кнопка «назад» работает как раньше — так как многие скрипты ее ломают (они перехатывают клик по ссылки и переход не сохраняется в историю навигации). Жутко бесит. По идее плавную прокрутку должен конечно делать браузер, а не каждый сайт.
Ок, будем считать это предложением. Борда конечно мне нравится больше тем, что не нужна регистрация. Зато в слаке видно кто онлайн и можно раздавать банхаммеры. А слак работает без скачивания и установки приложения?
>>540314
Зайду ближе к ночи еще наверно.
>> Во втором банке ответ около 61268.
> Проценты на остаток же.
Может мы что-то недопонимаем? Во втором банке общая сумма выплат за айпад будет 61268. Не 59 000.
> Я не осилил первую задачу на регулярные выражения про телефонный номер. Только через костыль в виде вытягивания цифр номера после кода в отдельную переменную с последующим пересчетом
В регулярках есть такая штука как повторение. Например возьмем почтовый индекс (ровно 6 цифр):
/^\d{6}$/u
В твоем случае между цифрами могут быть лишние символы. Надо писать так:
(1 цифра, за ней любое число пробелов, минусов, скобок) × 10 раз
Про кнопку понял. Видимо при сокращении CSS что-то задел и не заметил. А насчет меню не понял. Это про 5 слов HOME PORTFOLIO ABOUT BLOG CONTACT? Сейчас смотрю - все работает.
>А слак работает без скачивания и установки приложения?
Да. Честно говоря, я и не знаю, существует ли приложение.
Как вариант ещё есть слоудоска на доброчане. Из тамошнего /u/ погонят скорее всего.
Нам частота постов на доброчане никак не помешает — если мы туда перекатимся то она резко возрастет :)
Пока соберем возможные варианты, а потом выберем один (или два) и поместим в шапку чтобы все знали.
> И невозможен ORM, придется использовать DAO. Сложность выборки и вставки.
> Почему? Распиши-ка подробнее.
Я еще слабо ориентируюсь в терминах, может быть я не совсем понимаю суть ORM, но мне она видится как описание сущностей из бд через php классы, грубо говоря. Но если есть куча вспомогательных таблиц, данные из которых нужно джойнить при выборке и вставлять одновременно в несколько таблиц, то тут уже не получится легкого дефолтного способа yii, одним методом модели: $model = Model::findByPk(1); $model->attributes = $_POST['modelForm']; $model->save().
При сложной схеме придется запросы писать руками через конструктор DAO, я это имел ввиду.
Ну это я пишу постфактум. Разобрался с библиотекой eavactiverecord для yii, очень хороша. Она как раз предоставляет методы, с помощью которых мы можем обращаться с моделью так, как будто она "простая", то есть представляет одну таблицу, а не сложную структуру связанных таблиц.
База выглядит так:
https://github.com/iAchilles/eavactiverecord/wiki/ER-Diagram
Для каждого типа данных (INT, VARCHAR, MONEY и т.д.) своя таблица.
Также таблицы для Атрибутов, Наборов атрибутов и связи атрибут_набор.
> ad_property (собственно таблица с перечислением уникальных свойств для объявления)
> В чем ее смысл? Почему не добавить ad_id в таблицу property? Одно заполненное свойство используется несколькими объявлениями?
Да, например свойство "объем двигателя" принадлежит и категории легковых авто, и мотоциклов.
Но уже неважно, я переключился на схему из библиотеки eavactiverecord.
>если типов объявлений немного то эффективнее не делать аякс-запрос при выборе категории, а заложить данные о полях и их типах в страницу в виде JSON и выбирать из него
Вообще многовато, особенно если в "категории" занести например породы кошек или собак, марки автомобилей, бытовой техники.
Так что может быть несколько тысяч категорий. Если каждая строка всего по 20 байт, то может занять около 50кб. В принципе терпимо, но все равно лишний трафик.
Зато избавляет от избыточности. Сейчас попробую объяснить.
Мне нужно, чтобы в форме создания нового объявления отображались только общие поля (заголовок и описание, файловые инпуты подгрузки картинок). А при выборе категории появлялись специфические для данной категории поля. Следовательно, мне придется привязать имя набора (eav_set_id, см.схему базы) к таблице категорий, тогда как эта колонка уже есть в таблице Entity (в моем случае таблица объявлений). Колонка дублируется.
Если же сделать как ты говоришь и зашить весь список категорий в страницу, то это утяжелит ее на несколько десятков килобайт, зато не нужен будет запрос и повторение данных в базе. Даже не знаю. Пожалуй так действительно лучше.
И еще момент. Как быть с теми атрибутами, значения которых задаются списком? Например "состояние" (новый, б.у.).
Решил проблему созданием таблицы атрибут_вариант, но опять-таки сталкиваемся с избыточностью (или как это по-умному называется, когда значения повторяются в разных таблицах или в строках одной таблицы).
И у меня тут трагедия с подключением твига к yii.
Не регистрируются скрипты, и все.
Может, я его неправильно поставил? Пожалуйста, попробуй повторить мои шаги, потому что я уже заколебался, сегодня целый день просидел над этой фигней.
1. Ставлю твиг, yii и twig-renderer через композер по инструкции: https://packagist.org/packages/yiiext/twig-renderer
2. Во-первых, у меня почему-то не работает метод Controller->render
Ошибки не выдает, слим вместо html выдает пару строчек пережеванного php
beginContent('//layouts/main'); ?>
endContent(); ?>
Эти строки я вижу в браузере. Самое забавное, что js срабатывает, но ничего не рендерится, кроме этих строчек. Очевидно проблема в том что некоторые виджеты могут возвращать html или сразу отдавать его через echo.
Заработал только renderPartial. Но с ним не работают скрипты, их просто нет в доме.
3. В представлении есть виджеты, которые подключают ресурсы (стили и js) из ядра фреймворка. Должны подключать, но не подключают.
Особенно меня огорчает, что не работает клиентская и аякс-валидация, просто отсутствуют скрипты.
{% set form = this.beginWidget('CActiveForm', {
\t'id':'login-form',
\t'enableClientValidation':true,
\t'enableAjaxValidation':true,
\t'clientOptions':{'validateOnSubmit':true}
}, true) %}
Гуглил уже все что можно, самое досадное что как будто больше ни у кого этой проблемы не возникало, ничего не нашел.
Скорее всего проблема связана с тем, что методы, которые вызываются в шаблоне, должны возвращать строку, а не объект или другие типы.
Поэтому многие функции оборачиваются в void, например
{{void(App.clientScript.registerScriptFile(...))}}
Но я не знаю, каким образом виджет производит подключение этих скриптов, и что мне заворачивать в void. Если что, виджет CActiveForm должен подключить скрипт yiiactiveform.js из ядра фреймворка.
Самое забавное, что включен jquery. Хотя я его не подключал, и
нигде в коде страницы не вижу ничего похожего на <script scr="jquery.min.js">
Чувствую себя полным дегенератом.
> И невозможен ORM, придется использовать DAO. Сложность выборки и вставки.
> Почему? Распиши-ка подробнее.
Я еще слабо ориентируюсь в терминах, может быть я не совсем понимаю суть ORM, но мне она видится как описание сущностей из бд через php классы, грубо говоря. Но если есть куча вспомогательных таблиц, данные из которых нужно джойнить при выборке и вставлять одновременно в несколько таблиц, то тут уже не получится легкого дефолтного способа yii, одним методом модели: $model = Model::findByPk(1); $model->attributes = $_POST['modelForm']; $model->save().
При сложной схеме придется запросы писать руками через конструктор DAO, я это имел ввиду.
Ну это я пишу постфактум. Разобрался с библиотекой eavactiverecord для yii, очень хороша. Она как раз предоставляет методы, с помощью которых мы можем обращаться с моделью так, как будто она "простая", то есть представляет одну таблицу, а не сложную структуру связанных таблиц.
База выглядит так:
https://github.com/iAchilles/eavactiverecord/wiki/ER-Diagram
Для каждого типа данных (INT, VARCHAR, MONEY и т.д.) своя таблица.
Также таблицы для Атрибутов, Наборов атрибутов и связи атрибут_набор.
> ad_property (собственно таблица с перечислением уникальных свойств для объявления)
> В чем ее смысл? Почему не добавить ad_id в таблицу property? Одно заполненное свойство используется несколькими объявлениями?
Да, например свойство "объем двигателя" принадлежит и категории легковых авто, и мотоциклов.
Но уже неважно, я переключился на схему из библиотеки eavactiverecord.
>если типов объявлений немного то эффективнее не делать аякс-запрос при выборе категории, а заложить данные о полях и их типах в страницу в виде JSON и выбирать из него
Вообще многовато, особенно если в "категории" занести например породы кошек или собак, марки автомобилей, бытовой техники.
Так что может быть несколько тысяч категорий. Если каждая строка всего по 20 байт, то может занять около 50кб. В принципе терпимо, но все равно лишний трафик.
Зато избавляет от избыточности. Сейчас попробую объяснить.
Мне нужно, чтобы в форме создания нового объявления отображались только общие поля (заголовок и описание, файловые инпуты подгрузки картинок). А при выборе категории появлялись специфические для данной категории поля. Следовательно, мне придется привязать имя набора (eav_set_id, см.схему базы) к таблице категорий, тогда как эта колонка уже есть в таблице Entity (в моем случае таблица объявлений). Колонка дублируется.
Если же сделать как ты говоришь и зашить весь список категорий в страницу, то это утяжелит ее на несколько десятков килобайт, зато не нужен будет запрос и повторение данных в базе. Даже не знаю. Пожалуй так действительно лучше.
И еще момент. Как быть с теми атрибутами, значения которых задаются списком? Например "состояние" (новый, б.у.).
Решил проблему созданием таблицы атрибут_вариант, но опять-таки сталкиваемся с избыточностью (или как это по-умному называется, когда значения повторяются в разных таблицах или в строках одной таблицы).
И у меня тут трагедия с подключением твига к yii.
Не регистрируются скрипты, и все.
Может, я его неправильно поставил? Пожалуйста, попробуй повторить мои шаги, потому что я уже заколебался, сегодня целый день просидел над этой фигней.
1. Ставлю твиг, yii и twig-renderer через композер по инструкции: https://packagist.org/packages/yiiext/twig-renderer
2. Во-первых, у меня почему-то не работает метод Controller->render
Ошибки не выдает, слим вместо html выдает пару строчек пережеванного php
beginContent('//layouts/main'); ?>
endContent(); ?>
Эти строки я вижу в браузере. Самое забавное, что js срабатывает, но ничего не рендерится, кроме этих строчек. Очевидно проблема в том что некоторые виджеты могут возвращать html или сразу отдавать его через echo.
Заработал только renderPartial. Но с ним не работают скрипты, их просто нет в доме.
3. В представлении есть виджеты, которые подключают ресурсы (стили и js) из ядра фреймворка. Должны подключать, но не подключают.
Особенно меня огорчает, что не работает клиентская и аякс-валидация, просто отсутствуют скрипты.
{% set form = this.beginWidget('CActiveForm', {
\t'id':'login-form',
\t'enableClientValidation':true,
\t'enableAjaxValidation':true,
\t'clientOptions':{'validateOnSubmit':true}
}, true) %}
Гуглил уже все что можно, самое досадное что как будто больше ни у кого этой проблемы не возникало, ничего не нашел.
Скорее всего проблема связана с тем, что методы, которые вызываются в шаблоне, должны возвращать строку, а не объект или другие типы.
Поэтому многие функции оборачиваются в void, например
{{void(App.clientScript.registerScriptFile(...))}}
Но я не знаю, каким образом виджет производит подключение этих скриптов, и что мне заворачивать в void. Если что, виджет CActiveForm должен подключить скрипт yiiactiveform.js из ядра фреймворка.
Самое забавное, что включен jquery. Хотя я его не подключал, и
нигде в коде страницы не вижу ничего похожего на <script scr="jquery.min.js">
Чувствую себя полным дегенератом.
Вон например, в роутерах я не понимаю, как переменную передать в темплейт. Т.е. пока что я только массив, выводимый сокл запросом научился передавать, а вот просто перменную не передает и все.
> Но если есть куча вспомогательных таблиц, данные из которых нужно джойнить при выборке и вставлять одновременно в несколько таблиц, то тут уже не получится легкого дефолтного способа yii, одним методом модели
У модели должны быть методы вроде «получить свойства объявления», «добавить свойство», «добавить много свойств» и тд, которые скрывают реализацию этой системы. И отдельный класс, управляющий общим списком возможных свойств и их особенностей, для админки.
> При сложной схеме придется запросы писать руками через конструктор DAO, я это имел ввиду.
Не факт, там будет выборка по id объявления всех свойств, на стороне PHP их уже можно например разобрать в массив или объекты.
> Она как раз предоставляет методы, с помощью которых мы можем обращаться с моделью так, как будто она "простая", то есть представляет одну таблицу, а не сложную структуру связанных таблиц.
Так и надо
> База выглядит так:
А там реально сделать внешние ключи, например между Объявлениями и их свойствами? Отстуствие ключей это большой недостаток.
> Вообще многовато, особенно если в "категории" занести например породы кошек или собак, марки автомобилей, бытовой техники.
Ок, тогда можно аяксом.
> Так что может быть несколько тысяч категорий.
Не вздумай делать селект с тысячью опций.
> то это утяжелит ее на несколько десятков килобайт, зато не нужен будет запрос и повторение данных в базе
Не, если тысячи, выгоднее наверно делать запрос. Мой вариант больше годится когда категорий 10-20.
> И еще момент. Как быть с теми атрибутами, значения которых задаются списком? Например "состояние" (новый, б.у.).
Я думал, что мы в странице где-то либо поместим HTMl код всех полей ввода и скроем ненужные либо поместим JSON данные по которым поля можно сгенерировать. Но раз категорий много, выгоднее запрашивать либо описание свойств либо HTML с сервера аякс-запросом. При этом не забудь что возможна ситуация смены категории. Сохранятся ли введенные данные?
> Решил проблему созданием таблицы атрибут_вариант, но опять-таки сталкиваемся с избыточностью (или как это по-умному называется, когда значения повторяются в разных таблицах или в строках одной таблицы).
Тут очевидно надо как-то добавить 2 таблицы:
— набор вариантов выбора
— таблица с выбранным вариантом для данного объявления, вида (entity, entity_id, attribute_id, selected_option_id). Причем пару (attribute_id, selected_option_id) можно сделать внешним ключом на таблицу вариантов.
> Ошибки не выдает, слим вместо html выдает пару строчек пережеванного php
Открой исходный код страницы (Ctrl +U) и смотри его
> Скорее всего проблема связана с тем, что методы, которые вызываются в шаблоне, должны возвращать строку, а не объект или другие типы.
> Поэтому многие функции оборачиваются в void, например
void там чтобы результат не выводился
> Самое забавное, что включен jquery. Хотя я его не подключал, и
нигде в коде страницы не вижу ничего похожего
В Yii есть система ассетов, которая склеивает скрипты в один: http://yiiframework.ru/doc/cookbook/ru/core.assets
Я думаю, ее можно временно отключить настройкой в конфиге.
> Пожалуйста, попробуй повторить мои шаги, потому что я уже заколебался, сегодня целый день просидел над этой фигней.
Ты бы код привел, для начала свой composer.json, а также что надо сделать после установки.
> Но если есть куча вспомогательных таблиц, данные из которых нужно джойнить при выборке и вставлять одновременно в несколько таблиц, то тут уже не получится легкого дефолтного способа yii, одним методом модели
У модели должны быть методы вроде «получить свойства объявления», «добавить свойство», «добавить много свойств» и тд, которые скрывают реализацию этой системы. И отдельный класс, управляющий общим списком возможных свойств и их особенностей, для админки.
> При сложной схеме придется запросы писать руками через конструктор DAO, я это имел ввиду.
Не факт, там будет выборка по id объявления всех свойств, на стороне PHP их уже можно например разобрать в массив или объекты.
> Она как раз предоставляет методы, с помощью которых мы можем обращаться с моделью так, как будто она "простая", то есть представляет одну таблицу, а не сложную структуру связанных таблиц.
Так и надо
> База выглядит так:
А там реально сделать внешние ключи, например между Объявлениями и их свойствами? Отстуствие ключей это большой недостаток.
> Вообще многовато, особенно если в "категории" занести например породы кошек или собак, марки автомобилей, бытовой техники.
Ок, тогда можно аяксом.
> Так что может быть несколько тысяч категорий.
Не вздумай делать селект с тысячью опций.
> то это утяжелит ее на несколько десятков килобайт, зато не нужен будет запрос и повторение данных в базе
Не, если тысячи, выгоднее наверно делать запрос. Мой вариант больше годится когда категорий 10-20.
> И еще момент. Как быть с теми атрибутами, значения которых задаются списком? Например "состояние" (новый, б.у.).
Я думал, что мы в странице где-то либо поместим HTMl код всех полей ввода и скроем ненужные либо поместим JSON данные по которым поля можно сгенерировать. Но раз категорий много, выгоднее запрашивать либо описание свойств либо HTML с сервера аякс-запросом. При этом не забудь что возможна ситуация смены категории. Сохранятся ли введенные данные?
> Решил проблему созданием таблицы атрибут_вариант, но опять-таки сталкиваемся с избыточностью (или как это по-умному называется, когда значения повторяются в разных таблицах или в строках одной таблицы).
Тут очевидно надо как-то добавить 2 таблицы:
— набор вариантов выбора
— таблица с выбранным вариантом для данного объявления, вида (entity, entity_id, attribute_id, selected_option_id). Причем пару (attribute_id, selected_option_id) можно сделать внешним ключом на таблицу вариантов.
> Ошибки не выдает, слим вместо html выдает пару строчек пережеванного php
Открой исходный код страницы (Ctrl +U) и смотри его
> Скорее всего проблема связана с тем, что методы, которые вызываются в шаблоне, должны возвращать строку, а не объект или другие типы.
> Поэтому многие функции оборачиваются в void, например
void там чтобы результат не выводился
> Самое забавное, что включен jquery. Хотя я его не подключал, и
нигде в коде страницы не вижу ничего похожего
В Yii есть система ассетов, которая склеивает скрипты в один: http://yiiframework.ru/doc/cookbook/ru/core.assets
Я думаю, ее можно временно отключить настройкой в конфиге.
> Пожалуйста, попробуй повторить мои шаги, потому что я уже заколебался, сегодня целый день просидел над этой фигней.
Ты бы код привел, для начала свой composer.json, а также что надо сделать после установки.
Основы ООП у меня в учебнике в ОП посте. Неймспейсы отлично описаны в мануале и на хабре: https://www.google.ru/search?q=php+%D0%BD%D0%B5%D0%B9%D0%BC%D1%81%D0%BF%D0%B5%D0%B9%D1%81%D1%8B&oq=php+%D0%BD%D0%B5%D0%B9%D0%BC%D1%81%D0%BF%D0%B5%D0%B9%D1%81%D1%8B&aqs=chrome..69i57j0l5.3840j0j7&sourceid=chrome&es_sm=93&ie=UTF-8
Интерфейсы, увы, нет. Но у меня есть паста про них:
------
Интерфейс это набор требований к классу. «требование» здесь значит требование чтобы в классе был определенный метод.
Если класс реализует интерфейс, в нем обязаны быть эти методы.Обычно интерфйес представляет собой какое-то умение: классы, реализующие этот интерфейс, умеют что-то делать.
Допустим мы делаем сайт где можно ставить лайки постам и комментам. Допустим у нас есть классы User, Post и Comment.
Вот у нас есть пост и коммент, мы можем увеличить число лайков, допустим методом increaseLikeCount и узнавать сколько у них лайков методом getLikeCount, то есть у них есть что-то общее, но как описать это в коде? Как сказать что эти 2 класса в отличие от других умеют работать с лайками?
Второй пример, мы хотим сделать функцию, которая допустим ставит лайк от определенного пользователя определенному посту или комментарию:
function addLike(User $user, $object) ...
Мы сказали что $user должен быть объектом класса User, а как сказать что $object должен быть классом, умеющим работать с лайками?
Обе проблемы решают интерфейсы. Объявим интерфейс Likeable, который представляет собой умение получать лайки. Опишем какие методы обязаны реализовать такие классы:
interface Likeable
{
public function increaseLikeCount( );
public function getLikeCount( );
}
Теперь укажем в коде что посты и комменты можно лайкать:
class Post implements Likeable { ... }
class Comment implements Likeable { ... }
на этом этапе php проверит, не забыли ли мы реализовать в классах упомянутые методы. Если забыли — выдаст ошибку. Как удобно!
Ну и теперь мы можем использовать интерфейс чтобы указать какие аргументы принимает функция addLike:
function addLike(User $user, Likeable $object) { ... }
заметь что благодаря интферйесам наш код стал расиряем. Допустим завтра мы добавим класс Photo который тоже можно лайкать. Если он будет реализовывать интерфейс Likeable то функция вроде addLike сможет работать и с ним без переписывания кода.
В общем интерфейс представляет какую-то способность класса и требует от него реализовать определенные методы.
-----
По SQL запросам: изучи PDO (есть статья на хабре), после этого можешь прочесть про более высокоуровневые методы работы с базой: https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md
Ну а отточить все это на практике можно сделав и показав на проверку наши задачи про студентов и файлообменник, в ОП посте.
Основы ООП у меня в учебнике в ОП посте. Неймспейсы отлично описаны в мануале и на хабре: https://www.google.ru/search?q=php+%D0%BD%D0%B5%D0%B9%D0%BC%D1%81%D0%BF%D0%B5%D0%B9%D1%81%D1%8B&oq=php+%D0%BD%D0%B5%D0%B9%D0%BC%D1%81%D0%BF%D0%B5%D0%B9%D1%81%D1%8B&aqs=chrome..69i57j0l5.3840j0j7&sourceid=chrome&es_sm=93&ie=UTF-8
Интерфейсы, увы, нет. Но у меня есть паста про них:
------
Интерфейс это набор требований к классу. «требование» здесь значит требование чтобы в классе был определенный метод.
Если класс реализует интерфейс, в нем обязаны быть эти методы.Обычно интерфйес представляет собой какое-то умение: классы, реализующие этот интерфейс, умеют что-то делать.
Допустим мы делаем сайт где можно ставить лайки постам и комментам. Допустим у нас есть классы User, Post и Comment.
Вот у нас есть пост и коммент, мы можем увеличить число лайков, допустим методом increaseLikeCount и узнавать сколько у них лайков методом getLikeCount, то есть у них есть что-то общее, но как описать это в коде? Как сказать что эти 2 класса в отличие от других умеют работать с лайками?
Второй пример, мы хотим сделать функцию, которая допустим ставит лайк от определенного пользователя определенному посту или комментарию:
function addLike(User $user, $object) ...
Мы сказали что $user должен быть объектом класса User, а как сказать что $object должен быть классом, умеющим работать с лайками?
Обе проблемы решают интерфейсы. Объявим интерфейс Likeable, который представляет собой умение получать лайки. Опишем какие методы обязаны реализовать такие классы:
interface Likeable
{
public function increaseLikeCount( );
public function getLikeCount( );
}
Теперь укажем в коде что посты и комменты можно лайкать:
class Post implements Likeable { ... }
class Comment implements Likeable { ... }
на этом этапе php проверит, не забыли ли мы реализовать в классах упомянутые методы. Если забыли — выдаст ошибку. Как удобно!
Ну и теперь мы можем использовать интерфейс чтобы указать какие аргументы принимает функция addLike:
function addLike(User $user, Likeable $object) { ... }
заметь что благодаря интферйесам наш код стал расиряем. Допустим завтра мы добавим класс Photo который тоже можно лайкать. Если он будет реализовывать интерфейс Likeable то функция вроде addLike сможет работать и с ним без переписывания кода.
В общем интерфейс представляет какую-то способность класса и требует от него реализовать определенные методы.
-----
По SQL запросам: изучи PDO (есть статья на хабре), после этого можешь прочесть про более высокоуровневые методы работы с базой: https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md
Ну а отточить все это на практике можно сделав и показав на проверку наши задачи про студентов и файлообменник, в ОП посте.
> Хоть некоторые вещи со слим фреймворком легко делать, но в плане некоторых вещей мне на нем сложнее сайт сделать, чем если бы на голом пхп писал.
Ты мало внимания уделил документации. Не беда, задай вопрос тут.
> Вон например, в роутерах я не понимаю, как переменную передать в темплейт
Изучи как работает метод $app->render:
http://docs.slimframework.com/view/rendering/
также, есть метод appendData для каких-то глобальных вещей, нужных во всех роутах:
http://docs.slimframework.com/view/data/
> Т.е. пока что я только массив, выводимый сокл запросом научился передавать, а вот просто перменную не передает и все.
Показывай код и что пишет в сообщении об ошибке.
> . Т.е. пока что я только массив, выводимый сокл запросом
В окончательном решении должен быть наверно объект, а не массив. У нас же MVC и мы хотим нормальные объекты-модели а не костыли из массивов в которых вечно путаешься.
Алсо, если вдруг ты делаешь файлообменник на слиме и пропустил список студентов, то это плохо. Ведь там изучаются многие важные вещи.
Раз ты делаешь задачу на номера....
-----
Задачу про номера телефонов надо проверить на большом числе телефонов, чтобы убедиться что твой код правильный. Но руками подставлять номера — долго и скучно. Пусть работает робот, а не человек!
Для этого давай добавим в программу тесты, чтобы сразу было видно, верно все работает или нет. Сделай 2 списка номеров (правильные и нет), добавь их в программу и напиши цикл, который их по очереди прогоняет через регулярку и проверяет что они определяются как надо (если нет — надо вывести какой именно номер не распознается правильно).
Вот список номеров:
Правильные: array('84951234567', '+74951234567', '8-495-1-234-567', ' 8 (8122) 56-56-56', '8-911-1234567', '8 (911) 12 345 67', '8-911 12 345 67', '8 (911) - 123 - 45 - 67', '+ 7 999 123 4567', '8 ( 999 ) 1234567', '8 999 123 4567');
Неправильные: array('02', '84951234567 позвать люсю', '849512345', '849512345678',
'8 (409) 123-123-123', '7900123467', '5005005001', '8888-8888-88',
'84951a234567', '8495123456a',
'+1 234 5678901', // неверный код страны
'+8 234 5678901', // либо 8 либо +7
'7 234 5678901' // нет +
);
>А там реально сделать внешние ключи, например между Объявлениями и их свойствами?
В принципе можно повесить, только я не представляю, зачем они нужны.
https://github.com/iAchilles/eavactiverecord/wiki/ER-Diagram
В таблицах со значениями (eav_attribute_varchar например) есть колонка entity_id, но внешним ключом она не является. Хотя можно и повесить.
> Так что может быть несколько тысяч категорий.
> Не вздумай делать селект с тысячью опций.
Задумывались раскрывающиеся списки. То есть вывести таблицей категории первого уровня, затем при клике на одну из них откроется вложенный список и т.д.
>Открой исходный код страницы (Ctrl +U) и смотри его
До этого я додумался. Но нет, там ничего нет. В смысле в том месте, где в "чистом" yii подключается js, при использовании твига в качестве шаблонизатора ничего нет.
>В Yii есть система ассетов, которая склеивает скрипты в один
Но папка assets пустая. Тем не менее jquery подключен.
>Ты бы код привел, для начала свой composer.json, а также что надо сделать после установки.
https://packagist.org/packages/yiiext/twig-renderer
1. Create file protected/composer.json if absent
Создал в папке protected файл composer.json (содержимое скопировал без изменений).
2. Composer install
3. Add the following to your config file 'components' section
Скопировал конфиг, кроме extensions и lexerOptions
4. Переписал views/layouts/main.php и views/site/login.php
5. Поскольку метод render не работает (выдает куски php вместо html), заменил render на renderPartial в SiteController экшн login.
При переходе по site/login все рендерится как и положено, но нет скриптов, вообще.
Гитхаб, хотя такое стыдно выкладывать https://github.com/nsdvw/classifieds
Ок, спасибо, вроде всё просто. Запилю, скорее всего послезавтра завтра на проверку, времени на посидеть за прогой не будет, код выложу.
$app->render('Homepage.php', ['files'=>$files]);
Вот у меня есть массив $files и его просто прекрасно передает. Но допустим мне нужно передать переменную $id (id страницы), которую я получаю из такого урл /page/:id'. Дописываю в рендер $app->render('Homepage.php', ['files'=>$files], ['id' => $id]); И нихуя не передается, ее значение NULL. Прям хоть создавай класс и делай там REQUEST_URL. $id мне нужна кстати для ссылок на предыдущую и следующую страницу.
И зачем там два массива в качестве второго и третьего аргумента метода render, если должен быть один?
Т.е. если я вывожу список файлов, то все, другую переменную не вывести. Ну вот об этом я и говорил, что во многих вещах слим хоть и удобнее, но во многих всасывает. Придется значит реквест_урл делать.
Я их открывал, они какие-то устаревшие и примеры на каком-то допотомном php что ли.
Я их открывал, они какие-то устаревшие и примеры на каком-то допотомном php что ли.
> В принципе можно повесить, только я не представляю, зачем они нужны.
Это плохо. Значит, ты не изучал внимательно теорию по базам данных. Прочитай для начала например статью: http://denis.in.ua/foreign-keys-in-mysql.htm
База без связей это гора мусора.
> есть колонка entity_id, но внешним ключом она не является. Хотя можно и повесить.
Нужно посмотреть, возможно ли это сделать. Там по задумке, как я понимаю, она может ссылаться на разные типы сущностей, для чего есть поле entity. Это разумеется не совместимо с внешними ключами.
> Задумывались раскрывающиеся списки. То есть вывести таблицей категории первого уровня, затем при клике на одну из них откроется вложенный список и т.д.
Есть еще вариант селекта с автодополнением + аякс:
https://select2.github.io/examples.html
https://harvesthq.github.io/chosen/
(какой лучше? надо сравнивать, я использовал оба но забыл какие у них недостатки, но помню что они есть)
> В смысле в том месте, где в "чистом" yii подключается js, при использовании твига в качестве шаблонизатора ничего нет.
Они там и не должны быть наверно, метод registerScriptFile только добавляет скрипт в
список.
Более того, твиг позволяет сделать специальный тег для этого, например можно вместо void ... писать
{% add_script 'some-script.js' %}
для этого, конечно, надо создать и зарегистрировать этот тег сначала.
Ты разобрался как работают ассеты? Статья какая-то короткая и ничего не рассказывает.
Метод publish вызывал?
> Но папка assets пустая. Тем не менее jquery подключен.
Он в каком-нибудь конфиге добавлен.
Также, я еще раз тебе напомню, что лучше бы ты изучал Юи 2, а не этот древний велосипед первой версии, второй намного лучше.
Повторить проблему сейчас попробую. Брр, руками придется фреймворк сначала ставить.
> В принципе можно повесить, только я не представляю, зачем они нужны.
Это плохо. Значит, ты не изучал внимательно теорию по базам данных. Прочитай для начала например статью: http://denis.in.ua/foreign-keys-in-mysql.htm
База без связей это гора мусора.
> есть колонка entity_id, но внешним ключом она не является. Хотя можно и повесить.
Нужно посмотреть, возможно ли это сделать. Там по задумке, как я понимаю, она может ссылаться на разные типы сущностей, для чего есть поле entity. Это разумеется не совместимо с внешними ключами.
> Задумывались раскрывающиеся списки. То есть вывести таблицей категории первого уровня, затем при клике на одну из них откроется вложенный список и т.д.
Есть еще вариант селекта с автодополнением + аякс:
https://select2.github.io/examples.html
https://harvesthq.github.io/chosen/
(какой лучше? надо сравнивать, я использовал оба но забыл какие у них недостатки, но помню что они есть)
> В смысле в том месте, где в "чистом" yii подключается js, при использовании твига в качестве шаблонизатора ничего нет.
Они там и не должны быть наверно, метод registerScriptFile только добавляет скрипт в
список.
Более того, твиг позволяет сделать специальный тег для этого, например можно вместо void ... писать
{% add_script 'some-script.js' %}
для этого, конечно, надо создать и зарегистрировать этот тег сначала.
Ты разобрался как работают ассеты? Статья какая-то короткая и ничего не рассказывает.
Метод publish вызывал?
> Но папка assets пустая. Тем не менее jquery подключен.
Он в каком-нибудь конфиге добавлен.
Также, я еще раз тебе напомню, что лучше бы ты изучал Юи 2, а не этот древний велосипед первой версии, второй намного лучше.
Повторить проблему сейчас попробую. Брр, руками придется фреймворк сначала ставить.
В массив больше одной переменной не помещается что ли?
->render('viewName', array('foo'=>$firstValue, 'bar'=>$secondValue, ...) );
Да в теории-то и вкратце я знаю, а мне нужны практические большие куски кода и чтобы подробно объяснялось, что делает каждая строчка. Как запихивать функции в классы, как их вытаскивать потом.
Вот например, какой у чувака крутой код, только я не особо понимаю, что в нем написано и для чего и как это выводится, а ведь это только один класс из всех использованных. Аж до слез.
class Paginator
{
public $numOfPages;
public $currentPage;
protected $queryTemplate;
public function __construct($currentPage, $numOfPages, $queryTemplate)
{
$this->currentPage = $currentPage;
$this->numOfPages = $numOfPages;
$this->queryTemplate = $queryTemplate;
}
public function getNextPageLink()
{
$current = $this->currentPage;
$next = ($current == $this->numOfPages) ? $current : $current + 1;
return $this->getPageLink($next);
}
public function getPreviousPageLink()
{
$current = $this->currentPage;
$previous = ($current == 1) ? $current : $current - 1;
return $this->getPageLink($previous);
}
public function getPaginationSet($width)
{
$current = $this->currentPage;
$numOfPrevious = abs(1 - $current);
$numOfPrevious = ($numOfPrevious > $width) ? $width : $numOfPrevious;
$numOfNext = $this->numOfPages - $current;
$numOfNext = ($numOfNext > $width) ? $width : $numOfNext;
if ($numOfNext < $width) {
$numOfPrevious += $width - $numOfNext;
$numOfPrevious = ($numOfPrevious > abs(1 - $current)) ? abs(1 - $current) : $numOfPrevious;
}
if ($numOfPrevious < $width) {
$numOfNext += $width - $numOfPrevious;
$numOfNext = ($numOfNext > ($this->numOfPages - $current)) ? $this->numOfPages - $current : $numOfNext;
}
$set = array();
if ($numOfPrevious > 0) {
for ($i = 0; $i < $numOfPrevious; $i++) {
$page = $current - $numOfPrevious + $i;
$set[] = array('page' => $page, 'link' => $this->getPageLink($page), 'active' => false);
}
}
$set[] = array('page' => $current, 'link' => $this->getPageLink($current), 'active' => true);
if ($numOfNext > 0) {
for ($i = 1; $i <= $numOfNext; $i++) {
$page = $current + $i;
$set[] = array('page' => $page, 'link' => $this->getPageLink($page), 'active' => false);
}
}
return $set;
}
protected function getPageLink($pageNumber) {
$link = Util::evalParamsInQueryTemplate($this->queryTemplate, array('page' => $pageNumber));
$link = "?" . $link;
return $link;
}
}
Да в теории-то и вкратце я знаю, а мне нужны практические большие куски кода и чтобы подробно объяснялось, что делает каждая строчка. Как запихивать функции в классы, как их вытаскивать потом.
Вот например, какой у чувака крутой код, только я не особо понимаю, что в нем написано и для чего и как это выводится, а ведь это только один класс из всех использованных. Аж до слез.
class Paginator
{
public $numOfPages;
public $currentPage;
protected $queryTemplate;
public function __construct($currentPage, $numOfPages, $queryTemplate)
{
$this->currentPage = $currentPage;
$this->numOfPages = $numOfPages;
$this->queryTemplate = $queryTemplate;
}
public function getNextPageLink()
{
$current = $this->currentPage;
$next = ($current == $this->numOfPages) ? $current : $current + 1;
return $this->getPageLink($next);
}
public function getPreviousPageLink()
{
$current = $this->currentPage;
$previous = ($current == 1) ? $current : $current - 1;
return $this->getPageLink($previous);
}
public function getPaginationSet($width)
{
$current = $this->currentPage;
$numOfPrevious = abs(1 - $current);
$numOfPrevious = ($numOfPrevious > $width) ? $width : $numOfPrevious;
$numOfNext = $this->numOfPages - $current;
$numOfNext = ($numOfNext > $width) ? $width : $numOfNext;
if ($numOfNext < $width) {
$numOfPrevious += $width - $numOfNext;
$numOfPrevious = ($numOfPrevious > abs(1 - $current)) ? abs(1 - $current) : $numOfPrevious;
}
if ($numOfPrevious < $width) {
$numOfNext += $width - $numOfPrevious;
$numOfNext = ($numOfNext > ($this->numOfPages - $current)) ? $this->numOfPages - $current : $numOfNext;
}
$set = array();
if ($numOfPrevious > 0) {
for ($i = 0; $i < $numOfPrevious; $i++) {
$page = $current - $numOfPrevious + $i;
$set[] = array('page' => $page, 'link' => $this->getPageLink($page), 'active' => false);
}
}
$set[] = array('page' => $current, 'link' => $this->getPageLink($current), 'active' => true);
if ($numOfNext > 0) {
for ($i = 1; $i <= $numOfNext; $i++) {
$page = $current + $i;
$set[] = array('page' => $page, 'link' => $this->getPageLink($page), 'active' => false);
}
}
return $set;
}
protected function getPageLink($pageNumber) {
$link = Util::evalParamsInQueryTemplate($this->queryTemplate, array('page' => $pageNumber));
$link = "?" . $link;
return $link;
}
}
Посмотри на определение функции render: https://github.com/slimphp/Slim/blob/2.x/Slim/Slim.php#L751
Ты видишь здесь возможность передать несколько массивов? Массив может быть только один, вторым аргументом. Но зато мы можем в него добавить несколько элементов с разными именами.
> а мне нужны практические большие куски кода и чтобы подробно объяснялось, что делает каждая строчка. Как запихивать функции в классы, как их вытаскивать потом.
А ты ООП в моем учебнике (или в любом другом нормальном) изучал? задачи на ООО Вектор и кризис делал? Если нет то сначала надо их решать. Если ты пропускаешь темы то ничего хорошего не выйдет. Нельзя браться за список студентов не выучив ООП на более простых примерах.
Ссылка на учебник, если что, в ОП посте, глава так и назвается «ООП и пасты».
>руками придется фреймворк сначала ставить
Нет, все зависимости в composer.json, там прописан гитхаб.
Ставил одной командой composer install все вместе, yii, twig и twig-renderer.
>лучше бы ты изучал Юи 2, а не этот древний велосипед первой версии
Я не думаю, что они так сильно отличаются.
Первый я уже немного знал, решил подтянуть. Нужно доучить до конца первый, тогда возьмусь за второй.
Собственно, как закончу с этим сайтом объявлений, так сразу.
Черт, с утра ничего не ел, а тут торты на капче.
>торты на капче
А меня почему-то не заставляют ничего выбирать. Просто галку поставить достаточно.
>Что касается поведенческих факторов, уже известно, что будут использовать информацию о времени, проведенной на странице и IP пользователя. Другие критерии оценки не раскрываются, поскольку спамеры быстро создадут робота, который обманывает No-CAPTCHA.
http://geektimes.ru/post/242398/
Починил кнопку SEE PORTFOLIO. В html был id а в css класс.
>- CSS спрайты (чтобы увидеть что ты их понял и умеешь делать): спрайт с андроидом, спрайт с соц иконками, спрайт с телефоном и картой.
Но ведь спрайт это просто одно большое изображение, которое объединяет несколько маленьких. И я не понимаю как применить это в случае с 4 картинками: андроид, монитор...
Ведь там от 720px до 1100px между ними длина белого пространства меняется. Пойду наверное перечитывать статьи, судя по всему я опять не прав.
>- во всех анимациях надо перечислить конкретные свойства которые анимируются во избежание нежелательных эффектов
Это как идти строить ковчег на случай потопа? Или такое реально встречается часто? Сделаю если надо, но я проблем с этим не видел хотя что я вообще видел?
>- в портфолио мне не нравится что меняется ширина внутреннего элемента (img) а не внешнего (a). Точнее, у тебя там по умолчанию меняется ширина обоих. Есть ли причина почему мы не можем анимировать внешний элемент, а для img просто поставить max-width: 100%? По моему тут нет никакой особой причины, просто ты сам запутался.
Мозг нашептывает: "не лезь, поломаешь еще." Придется все-таки разобраться.
>Я советую в следующий раз отказываться от id в верстке. Преимуществ у них нет, недостатки есть (не могут повторяться, нельзя дать 2 id). Лишний шанс получить ошибки в верстке из-за повторений. Правил вроде «если класс встречается 1 раз то заменяем на id» нету, и делать так нехорошо, так как сегодня у тебя один блок, а завтра их может оказаться два, и что ты будешь делать?
Еще после прочтения статьи о классах и идах на 2й или 3й день моего обучения я подумал что буду использовать только классы и даже так ведь и делал. Потом уже начал исправлять, ближе к концу. Думал не зря же они все-таки придуманы.
И да делал все как раз по типу: класс встретился 1 раз? Будет идом.
> <h2 id="greeting-block--h2"
>h2 достаточно уникальный селектор и можно было не давать ему id, а писать:
.greeting-block h2 { ... }
Понял. Опять разбираться в новом. Как раз такие комбинации в CSS я и не использовал до этого, и не разбирался в них.
> greeting-block--see-portfolio-button
>Я подумал, можно было писать просто b-greeting, b- как раз обозначает block (на сайте БЭМ раньше это было написано, не знаю, есть ли сейчас). А g- обозначает глобальные классы вроде выделения цветом или крупного шрифта. А l- значит layout, элементы отвечающий за общую компоновку страницы.
greeting-block в b-greeting
Я даже помню читал комментарии под статьей о БЭМ и там кто-то писал что b- вообще можно не использовать, лишние символы. Но вот названия типа smbd-block я использовал с самого начала и как-то так и решил оставить.
> content: " ";
>Можно без пробела, "". Пробел был нужен в каких-то древних браузерах.
Прекращай колдовать. Я отчетливо помню момент когда нашел клеарфикс. Там было строк 6-8. И я удалял все ненужные, которые не влияют на отображение в хроме. Пробел был обязателен. Сейчас удаляю все пробелы и ничего не меняется. Магия какая-то.
Починил кнопку SEE PORTFOLIO. В html был id а в css класс.
>- CSS спрайты (чтобы увидеть что ты их понял и умеешь делать): спрайт с андроидом, спрайт с соц иконками, спрайт с телефоном и картой.
Но ведь спрайт это просто одно большое изображение, которое объединяет несколько маленьких. И я не понимаю как применить это в случае с 4 картинками: андроид, монитор...
Ведь там от 720px до 1100px между ними длина белого пространства меняется. Пойду наверное перечитывать статьи, судя по всему я опять не прав.
>- во всех анимациях надо перечислить конкретные свойства которые анимируются во избежание нежелательных эффектов
Это как идти строить ковчег на случай потопа? Или такое реально встречается часто? Сделаю если надо, но я проблем с этим не видел хотя что я вообще видел?
>- в портфолио мне не нравится что меняется ширина внутреннего элемента (img) а не внешнего (a). Точнее, у тебя там по умолчанию меняется ширина обоих. Есть ли причина почему мы не можем анимировать внешний элемент, а для img просто поставить max-width: 100%? По моему тут нет никакой особой причины, просто ты сам запутался.
Мозг нашептывает: "не лезь, поломаешь еще." Придется все-таки разобраться.
>Я советую в следующий раз отказываться от id в верстке. Преимуществ у них нет, недостатки есть (не могут повторяться, нельзя дать 2 id). Лишний шанс получить ошибки в верстке из-за повторений. Правил вроде «если класс встречается 1 раз то заменяем на id» нету, и делать так нехорошо, так как сегодня у тебя один блок, а завтра их может оказаться два, и что ты будешь делать?
Еще после прочтения статьи о классах и идах на 2й или 3й день моего обучения я подумал что буду использовать только классы и даже так ведь и делал. Потом уже начал исправлять, ближе к концу. Думал не зря же они все-таки придуманы.
И да делал все как раз по типу: класс встретился 1 раз? Будет идом.
> <h2 id="greeting-block--h2"
>h2 достаточно уникальный селектор и можно было не давать ему id, а писать:
.greeting-block h2 { ... }
Понял. Опять разбираться в новом. Как раз такие комбинации в CSS я и не использовал до этого, и не разбирался в них.
> greeting-block--see-portfolio-button
>Я подумал, можно было писать просто b-greeting, b- как раз обозначает block (на сайте БЭМ раньше это было написано, не знаю, есть ли сейчас). А g- обозначает глобальные классы вроде выделения цветом или крупного шрифта. А l- значит layout, элементы отвечающий за общую компоновку страницы.
greeting-block в b-greeting
Я даже помню читал комментарии под статьей о БЭМ и там кто-то писал что b- вообще можно не использовать, лишние символы. Но вот названия типа smbd-block я использовал с самого начала и как-то так и решил оставить.
> content: " ";
>Можно без пробела, "". Пробел был нужен в каких-то древних браузерах.
Прекращай колдовать. Я отчетливо помню момент когда нашел клеарфикс. Там было строк 6-8. И я удалял все ненужные, которые не влияют на отображение в хроме. Пробел был обязателен. Сейчас удаляю все пробелы и ничего не меняется. Магия какая-то.
Какой-то я тупенький, не правда ли?
Кажется я нашел ошибку, хотя это было нелегко, а инструкции неточные (например ты не написал что сначала надо склонировать твой репозиторий).
У тебя используется лейаут //layouts/column1 (в components/Controller.php)
Он сделан на PHP, потому твиг просто выводит его как есть.
Насчет добавления скриптов — это скорее всего работа менеджера статических ресурсов (ассетов) который видит что ты не указал место в шапке для их подклюения и просто вставляет их в страницу. JQUery либо прописан по умолчанию в каком-то конфиге либо в каком-то виджете. Думаю, его реально найти по имени в исходном коде.
Я взял и запустил поиск по файлам:
d:\host3.dev,-×.js,-×.css,-×.txt,-×.log,-CHANGELOG
И нашел.
Например в файле https://github.com/yiisoft/yii/blob/master/framework/web/widgets/CActiveForm.php#L343 в функции run() мы видим подключение jQuery и добавление на страницу фрагментов JS кода.
Разберись как работают лейауты.
Замени расширение на twig чтобы не путаться
Разберись с CAssetsManager, либо найди статьи либо разбирай исходный код, но знать надо назубок как он работает, если что, задавай вопросы.
И если ты взял основу кода откуда-то (например код в сomponents) то нужно как минимум разобраться в нем.
Также, пустую папку runtime надо добавить в гит
Также, у тебя как я понимаю сейчас невозможно воссоздать базу данных так как миграции неполные.
Кажется я нашел ошибку, хотя это было нелегко, а инструкции неточные (например ты не написал что сначала надо склонировать твой репозиторий).
У тебя используется лейаут //layouts/column1 (в components/Controller.php)
Он сделан на PHP, потому твиг просто выводит его как есть.
Насчет добавления скриптов — это скорее всего работа менеджера статических ресурсов (ассетов) который видит что ты не указал место в шапке для их подклюения и просто вставляет их в страницу. JQUery либо прописан по умолчанию в каком-то конфиге либо в каком-то виджете. Думаю, его реально найти по имени в исходном коде.
Я взял и запустил поиск по файлам:
d:\host3.dev,-×.js,-×.css,-×.txt,-×.log,-CHANGELOG
И нашел.
Например в файле https://github.com/yiisoft/yii/blob/master/framework/web/widgets/CActiveForm.php#L343 в функции run() мы видим подключение jQuery и добавление на страницу фрагментов JS кода.
Разберись как работают лейауты.
Замени расширение на twig чтобы не путаться
Разберись с CAssetsManager, либо найди статьи либо разбирай исходный код, но знать надо назубок как он работает, если что, задавай вопросы.
И если ты взял основу кода откуда-то (например код в сomponents) то нужно как минимум разобраться в нем.
Также, пустую папку runtime надо добавить в гит
Также, у тебя как я понимаю сейчас невозможно воссоздать базу данных так как миграции неполные.
> Но ведь спрайт это просто одно большое изображение, которое объединяет несколько маленьких. И я не понимаю как применить это в случае с 4 картинками: андроид, монитор...
делаешь отдельный блок допустим размером 20×20 и выводишь туда нужную часть картинки за счет background-position.
Дивы в HTML добавлять не надо, старайся использовать псевдоэлементы для этого.
Почитай например:
https://learn.javascript.ru/css-sprite
http://webo.in/articles/habrahabr/08-all-about-css-sprites/
http://marahtanov.ru/edu/webp/reports/css_sprite.html
> Это как идти строить ковчег на случай потопа?
Ты в своем коде анимируешь все свойства во всех случаях их изменения. А тебе надо допустим менять только цвет фона при наведении. Логично описать это в CSS чтобы при изменениях в верстке ничего больше не анимировалось (например размер шрифта, паддинг или ширина).
> Мозг нашептывает: "не лезь, поломаешь еще."
Значит обязательно нужно лезть. Что это за верстаьщик который CSS боится?
> И да делал все как раз по типу: класс встретился 1 раз? Будет идом.
Не, не стоит так делать наверно. id они больше для использования в скриптах, в верстке от них только проблемы. Ну еще их используют в ссылках-якорях для прокрутки к нужному месту. И еще, некоторые их используют на крупных не повторяющихся блоках вроде сайдбар, шапка, хотя по мне так проще и выгоднее везде использовать классы.
> Как раз такие комбинации в CSS я и не использовал до этого, и не разбирался в них.
Прочти где-нибудь про синтаксис CSS селекторов ибо это важно. Это же основы и ты должен был по идее это изучить уже давным-давно.
A B
значит элемент B лежащий внутри A, причем и A и B могут быть составлены из разных условий: классы, ид, псевдоклассы и тд
Вот тут например можно почитать:
http://css.yoksel.ru/css-selectors/ (обзор)
http://htmlbook.ru/samcss (подробнее)
https://htmlacademy.ru/courses/4/run/10 (там много чего)
> Я даже помню читал комментарии под статьей о БЭМ и там кто-то писал что b- вообще можно не использовать, лишние символы. Но вот названия типа smbd-block я использовал с самого начала и как-то так и решил оставить.
Можно и так
> И я удалял все ненужные, которые не влияют на отображение в хроме. Пробел был обязателен. Сейчас удаляю все пробелы и ничего не меняется. Магия какая-то.
Надо CSS изучать внимательно тогда магии не будет. Очевидно ты что-то другое удалил.
Насчет клеарфикса, код тут и менять в нем не стоит ничего (разве что кроме поддержки ИЕ6):
http://webknowledge.ru/novaya-mikro-versiya-haka-clearfix/
Там и пробел упомянут:
> Включаемый с помощью свойства content пробел это один из способов обхода бага в Opera, связанного с атрибутом conteteditable, включенным где-либо в другом месте в документе.
contenteditable это атрибут, превращающий любой элемент в область редактирования (можешь попробовать выставить его отладчиком на body и кликнуть к любой текст)
У тебя нет contenteditable и старая Опера давно уже не используется так что это стало неактуальным.
> Но ведь спрайт это просто одно большое изображение, которое объединяет несколько маленьких. И я не понимаю как применить это в случае с 4 картинками: андроид, монитор...
делаешь отдельный блок допустим размером 20×20 и выводишь туда нужную часть картинки за счет background-position.
Дивы в HTML добавлять не надо, старайся использовать псевдоэлементы для этого.
Почитай например:
https://learn.javascript.ru/css-sprite
http://webo.in/articles/habrahabr/08-all-about-css-sprites/
http://marahtanov.ru/edu/webp/reports/css_sprite.html
> Это как идти строить ковчег на случай потопа?
Ты в своем коде анимируешь все свойства во всех случаях их изменения. А тебе надо допустим менять только цвет фона при наведении. Логично описать это в CSS чтобы при изменениях в верстке ничего больше не анимировалось (например размер шрифта, паддинг или ширина).
> Мозг нашептывает: "не лезь, поломаешь еще."
Значит обязательно нужно лезть. Что это за верстаьщик который CSS боится?
> И да делал все как раз по типу: класс встретился 1 раз? Будет идом.
Не, не стоит так делать наверно. id они больше для использования в скриптах, в верстке от них только проблемы. Ну еще их используют в ссылках-якорях для прокрутки к нужному месту. И еще, некоторые их используют на крупных не повторяющихся блоках вроде сайдбар, шапка, хотя по мне так проще и выгоднее везде использовать классы.
> Как раз такие комбинации в CSS я и не использовал до этого, и не разбирался в них.
Прочти где-нибудь про синтаксис CSS селекторов ибо это важно. Это же основы и ты должен был по идее это изучить уже давным-давно.
A B
значит элемент B лежащий внутри A, причем и A и B могут быть составлены из разных условий: классы, ид, псевдоклассы и тд
Вот тут например можно почитать:
http://css.yoksel.ru/css-selectors/ (обзор)
http://htmlbook.ru/samcss (подробнее)
https://htmlacademy.ru/courses/4/run/10 (там много чего)
> Я даже помню читал комментарии под статьей о БЭМ и там кто-то писал что b- вообще можно не использовать, лишние символы. Но вот названия типа smbd-block я использовал с самого начала и как-то так и решил оставить.
Можно и так
> И я удалял все ненужные, которые не влияют на отображение в хроме. Пробел был обязателен. Сейчас удаляю все пробелы и ничего не меняется. Магия какая-то.
Надо CSS изучать внимательно тогда магии не будет. Очевидно ты что-то другое удалил.
Насчет клеарфикса, код тут и менять в нем не стоит ничего (разве что кроме поддержки ИЕ6):
http://webknowledge.ru/novaya-mikro-versiya-haka-clearfix/
Там и пробел упомянут:
> Включаемый с помощью свойства content пробел это один из способов обхода бага в Opera, связанного с атрибутом conteteditable, включенным где-либо в другом месте в документе.
contenteditable это атрибут, превращающий любой элемент в область редактирования (можешь попробовать выставить его отладчиком на body и кликнуть к любой текст)
У тебя нет contenteditable и старая Опера давно уже не используется так что это стало неактуальным.
Показывает таблицы (имена), соответствующие выражению в LIKE. Ты знаешь оператор LIKE? Если нет то изучи его сначала: http://www.sql-tutorial.ru/ru/book_predicate_like.html
Сейчас капчу аж 4 раза заполнял.
Вот откуда были эти странные строки
beginContent('//layouts/main'); ?>
endContent(); ?>
Если честно, даже не знал, что используется какой-то третий файл. Думал, что сначала берется layout (main в данном случае), а потом в него подставляется вложенный шаблон. А тут еще какой-то третий файл column1, пока не пойму на что он нужен и что с ним делать.
Спасибо, буду разбираться.
function createQuestions($text, $points, $answers, $correctAnswer) {
$questions=array($q->text=>$text, $q->points=$points, $q->answers=array($answers), $this->correctAnswer=$correctAnswer);
$q = new Question;
$questions[] = $q;
return $questions;
}
CreateQuestions('Name a town', 5, ['a'=>'Paris', 'b'=>'Moscow', 'c'=>'London'], 'c');
Вроде регулярное выражение правильно записал, а все равно выдает "неправильный номер"
сильно ли я наговнокодил?
<?php
error_reporting(-1);
$regexp = '/^(8|+7)([s-()]){0,3}[0-9]{1]([s-()]){0,1}[0-9]{1}([s-()]){0,1}[0-9]{1}([s-()]){0,1}[0-9]{1}([s-()]){0,1}[0-9]{1}([s-()]){0,1}[0-9]{1}([s-()]){0,1}[0-9]{1}([s-()]){0,1}[0-9]{1}([s-()]){0,1}[0-9]{1}([s-()]){0,1}[0-9]{1}$/';
$text = "8-911-50-656-56";
if (preg_match($regexp,$text)){
\techo "Ваш номер подошел!";
\t}
\telse {
\t\techo "Вы ввели неправильный номер";
\t}
https://ideone.com/RhOXGM
>$regexp = '/^(8|+7)([s-()]){0,3}[0-9]{1]([s-()]){0,1}[0-9]{1}([s-()]){0,1}[0-9]{1}([s-()]){0,1}[0-9]{1}([s-()]){0,1}[0-9]{1}([s-()]){0,1}[0-9]{1}([s-()]){0,1}[0-9]{1}([s-()]){0,1}[0-9]{1}([s-()]){0,1}[0-9]{1}([s-()]){0,1}[0-9]{1}$/'
Я тот еще нубас, но где закрывающая для этой скобки?
>$regexp = '/^(8|+7)([s-()]){0,3}[0-9] { 1]([s-()]){0,1}[0-9]{1}([s-()]){0,1}[0-9]{1}([s-()]){0,1}[0-9]{1}([s-()]){0,1}[0-9]{1}([s-()]){0,1}[0-9]{1}([s-()]){0,1}[0-9]{1}([s-()]){0,1}[0-9]{1}([s-()]){0,1}[0-9]{1}([s-()]){0,1}[0-9]{1}$/'
бля, не очень заметно вышло... короче для этой
бля пиздец, нахуй ты такое на ночь постишь, нуб ебаный. пойди погугли, там есть спец. символы, чтобы выбирать опр. кол-во цифр.
нихуя себе ты внимательный, но все равно не помогло
>>540521
Задание
Дан текст, который по идее должен быть номером телефона в виде 8-(911)-506 56 56 (т.е. человек может ввести не только цифры, но и скобки, минусы, может что-то еще). Но в реальности, пользователь может вместо номера написать что угодно. Напиши скрипт для проверки правильности введенного номера («8(911)-506 56 56» — правильный номер, «8-911-50-656-56» — правильный, «89115065656» — праивльный, «02» — неправильный, «89115065656 позвать Люду» — неправильный).
Вот тебе задание, гений. Я хочу ввести номер
8(911)-5-0-6 5-6 5-6 и должно ответить, что я все правильно ввел.
К примеру. Запости мне, пожалуйста, свое коротенькое решение.
Зачем тебе буква s в квадратных скобках? Регулярка будет искать букву s в номере. Ты наверное хотел поставить там спецсимвол \\s?
ты прав, исправил, один хуй не помогло
Он прав, можно сократить твою гигантскую регулярку. Если у тебя в коде есть конструкция вроде [0-9]{1} (зачем тут 1? Оно по дефолту будет искать его 1 раз, если не указано число повторений) (\\s-\\(\\)]{0,1} повторяется много раз, то можно взять всё это в скобки и указать число повторений: ([0-9]{1}(\\s\\-\\(\\)]{0,1} ){n}
Что такое s? Наверное ты хотел написать \s, т.е. пробельный символ. (А в идеоне наверное даже два обратных слеша)
C минусом в квадратных скобках нужно быть осторожным, потому что если он стоит между двумя символами, то означает интервал.
Например [4-7] означает одну любую цифру из набора от четырех до семи (4 или 5 или 6 или 7).
Так что [s-(] может быть по ошибке принято за интервал. Лучше минус поставить в начало или конец [\s()-].
{0,1} вместо этого можно написать квантификатор ?
{1} Это еще зачем? Символ в шаблоне всегда ищется ровно один раз, если рядом не стоит дополнительный модификатор.
И кол-во повторов можно указывать не только для одного символа, но и для группы. (abcd){5} равняется abcdabcdabcdabcdabcd
У тебя девять раз повторяется фрагмент ([s-()]){0,1}[0-9]{1}
Это можно записать как ([\s()-]?[0-9]){9}
Вместо [0-9] можно еще написать \d. Так тоже правильно, просто короче.
Еще много полезных вещей тут например http://www.php.su/lessons/?lesson_17
ну ладно, подскажи тогда, что какую цифру ставить вместо n учитывая то, что цифр всего может быть 11, а вот пробелов и прочих символов 1 или 2, а может и не быть?
>>540543
да эти регулярные выражения такая жопа запутанная, помню такой счастливый решил освоить веб программирование, читал, решал задачки, пока не дошел до регулярных выражений, сидел ебался, ебался с ними и в общем подзабил, сейчас вот опять начал пытаться учить и те же грабли.
Спасибо, что доходчиво все обьяснил. Надо будет почитать.
Открыл статьи про спрайты. Черт возьми, это же так просто! А я думал все намного сложнее.
)))
Объясни, что делает эта строчка:
> $questions=array($q->text=>$text, $q->points=$points, $q->answers=array($answers), $this->correctAnswer=$correctAnswer);
Мне просто кажется что она не очень правильная. Ты пробовал код запускать?
Ну и по моему ты обращаешься к еще не созданной переменной тут:
> $q->text=>$text
А переменная $q создается только в следующей строчке.
Вот короче код с вопросами на ООП.
На локалке вот это выдает. Только у меня вопрос, во-первых, почему вопросы нормально не считаются? Во-вторых, как объединить подсчет ответов для двух вопросов? Или это нужно самому дописывать?
1. Name a town
Variants of answer:
a. Paris
b. Moscow
c. London
1. Name an artist
Variants of answer:
a. Sergei
b. Danila
c. Tolyan
Right answers: 1 from 1, Points: 5 from 5
Right answers: 1 from 1, Points: 7 from 7
В чем вопрос? Как изменить запись в базе? Командой update.
http://phpclub.ru/mysql/doc/update.html
Сам код раскидай хотя бы по функциям, ужасно же выглядит, все одним полотном. Как ты потом там будешь искать, если понадобится что-то изменить?
Расширение mysql устарело больше десяти лет назад. Лучше использовать mysqli или pdo.
бля, код как земля, нахуй иди.
Это мои самые первые попытки, учту и исправлюсь, инфу брал отсюда http://intop24.ru/article_15_lesson_5.php не как не пойму что хотят от меня в последних 2 строках (проверить есть ли переменная могу, запрос составить тоже), создать еще 1 форму и отправить методом POST? Можешь прояснить еще лучше с кодом, там не больше 3 строк наверняка.
Для действий, изменяющих данные на сервере (изменение, удаление) надо использовать метод POST, метод GET используется только для не меняющих состояние сервера действий.
У тебя удаление сделано через GET (переход по ссылке).
Далее, не подставляй переменные в SQL запрос, это SQl инъекция.
HTML код должен быть в отдельном файле: http://www.phpinfo.su/articles/practice/shablony_v_php.html
> $addRow = mysql_query('INSERT INTO question (id, task)
тут код обрывается на полуслове
mysql_ функции устарели уже 10 лет назад, зачем ты читаешь такое старье?
При выводе данных надо использовать htmlspecialchars() иначе можно получить XSS (злоумышленник может вставить любой HTML код на страницу)
Обработку форм лучше делать как описано тут: https://github.com/codedokode/pasta/blob/master/forms.md
В общем, по хорошему тут надо каждую строчку переписать.
Если ты плохо знаешь язык SQL, стоит его подучить. У нас в первом посте есть ссылка на задачки и и на теорию по SQL.
Также, у нас есть задачки на список студентов и файлообменник, которые тебе помогут научиться писать нормальный современный код. То, что ты пишешь и чему там учат в учебнике, никуда не годится. Его автор сам застрял в прошлом.
О боже, какой восторг!
Оно заработало! Аякс-валидация, скрипты ядра, пользовательские скрипты и доп.стили.
Да, дело было в том, что yii использует довольно странную систему наследования, которая не очень вяжется с твиговской. Придется их как-то совмещать.
Там в классе Controller есть свойство public $layout='//layouts/column1', в котором определяется макет.
На самом деле я бы хотел вообще нафиг отключить эти дурацкие "макеты" и использовать твиговское наследование, но пока не знаю как.
Если использовать renderPartial вместо render как раз будет рендериться только шаблон в обход макета, но как раз из-за этого сдохли все мои ассеты.
Целый день на это убил. С одной стороны узнал много нового. Разобрался как подключаются ресурсы (не api для дергания за ниточку, а именно где они хранятся, как публикуются и т.д.). Неплохо потренировался в написании шаблонов под yii.
Но все же день потерян, и я сегодня засну без чувства выполненного долга, потому что "научился подключать twig к yii" - это мало.
Слушай, а сколько времени уходит на написание одного проекта в среднем? Ну например сайт объявлений уровня авито?
Может я зря убиваюсь, и такое делает команда сеньоров в течение полугода.
Хотя ты тут джунам предлагаешь аналоги ютубов писать, так что меня терзают сомнения.
> во-первых, почему вопросы нормально не считаются?
Найди место, где выводится номер вопроса. Найди переменную, в которой он хранится. Посмотри, чему она равна и как определяется ее значение.
Также, у тебя сделано не совсем правильно. надо сделать не 2 отдельных массива для каждого вопроса, а один массив с вопросами. То есть функцию printQuestions надо вызвать только 1 раз, а не 2.
Также, $answers должен быть массивом, а у тебя это не так.
> Во-вторых, как объединить подсчет ответов для двух вопросов? Или это нужно самому дописывать?
да, самому
> На самом деле я бы хотел вообще нафиг отключить эти дурацкие "макеты" и использовать твиговское наследование, но пока не знаю как.
Можно сделать лейаут из единственной команды, выводящей основной шаблон. Но тут стоит посмотреть, может в Юи что-то еще на лейауты завязано.
Алсо нашел такой пост по теме (там правда Юи 2): http://www.yiiframework.ru/forum/viewtopic.php?t=17125#p100902 - там отключаются лейауты.
>Если использовать renderPartial вместо render
Это неправильно, он не для этого предназначен. И вообще, если в фреймворке есть метод для чего-то не надо его заменять на другой. Ты же всегда можешь в базовом классе контроллера его переопределить как тебе надо.
> Слушай, а сколько времени уходит на написание одного проекта в среднем?
Не знаю, я в последнее время был на проектах которые годами тянутся (т.е уже давно работают). А начальный прототип можно при желании за 2-3 недели в одно лицо сделать (без заморочек с EAV конечно), а практике обычно дольше выходит.
Ну и проекты бывают разные, бывают сайты за 3000 рублей который за день или два полностью делаются, готовый шаблон, готовая CMS.
Ты не должен пока этим особо заморачиваться так как ты пока учишься, а не работаешь.
Если тебя интересует как писать быстрее, то это: максимальное использование готового кода, хорошее знание нужных технологий, чтобы знать как делается та или иная вещь без гугления и ошибочных решений.
> Ну например сайт объявлений уровня авито?
У Авито постоянная команда которая постоянно его поддерживает. Так что он еще до конца не дописан. Ты можешь и сам посмотреть их вакансии и почитать про историю создания:
https://www.avito.ru/company/job
https://www.avito.ru/company/job/people
Там человек пишет что он с 2009 года делался, но у меня есть смутное подозрение что он был и раньше, просто в 2009 году его купили нынешние владельцы. Не помню уже точно, увы. По моему он и раньше был.
> Хотя ты тут джунам предлагаешь аналоги ютубов писать
Я ведь предлагаю написать не аналог хранящий миллионы видео и обеспечивающий терабайты трафика, а сайт-игрушку. Это не то же самое. Там конечно много подводных камней, но это только идет на пользу — человек лучше будет разбираться в разных аспектах веб-платформы.
По поводу того, то ты делаешь, я тебе рекомендую как минимум периодически код показывть на проверку. А то есть риск что ты толком Юи не выучишь, а только научишься каким-то простым вещам увиденным в туториалах (типа добавить контроллер и модель). Это конечно лучше чем ничего, но ты сообразительный, можешь и большего добиться.
Ну и подумай насчет Юи 2, он новый и со временем будет вытеснять Юи, есть ли смысл изучать старую версию вместо новой?
> На самом деле я бы хотел вообще нафиг отключить эти дурацкие "макеты" и использовать твиговское наследование, но пока не знаю как.
Можно сделать лейаут из единственной команды, выводящей основной шаблон. Но тут стоит посмотреть, может в Юи что-то еще на лейауты завязано.
Алсо нашел такой пост по теме (там правда Юи 2): http://www.yiiframework.ru/forum/viewtopic.php?t=17125#p100902 - там отключаются лейауты.
>Если использовать renderPartial вместо render
Это неправильно, он не для этого предназначен. И вообще, если в фреймворке есть метод для чего-то не надо его заменять на другой. Ты же всегда можешь в базовом классе контроллера его переопределить как тебе надо.
> Слушай, а сколько времени уходит на написание одного проекта в среднем?
Не знаю, я в последнее время был на проектах которые годами тянутся (т.е уже давно работают). А начальный прототип можно при желании за 2-3 недели в одно лицо сделать (без заморочек с EAV конечно), а практике обычно дольше выходит.
Ну и проекты бывают разные, бывают сайты за 3000 рублей который за день или два полностью делаются, готовый шаблон, готовая CMS.
Ты не должен пока этим особо заморачиваться так как ты пока учишься, а не работаешь.
Если тебя интересует как писать быстрее, то это: максимальное использование готового кода, хорошее знание нужных технологий, чтобы знать как делается та или иная вещь без гугления и ошибочных решений.
> Ну например сайт объявлений уровня авито?
У Авито постоянная команда которая постоянно его поддерживает. Так что он еще до конца не дописан. Ты можешь и сам посмотреть их вакансии и почитать про историю создания:
https://www.avito.ru/company/job
https://www.avito.ru/company/job/people
Там человек пишет что он с 2009 года делался, но у меня есть смутное подозрение что он был и раньше, просто в 2009 году его купили нынешние владельцы. Не помню уже точно, увы. По моему он и раньше был.
> Хотя ты тут джунам предлагаешь аналоги ютубов писать
Я ведь предлагаю написать не аналог хранящий миллионы видео и обеспечивающий терабайты трафика, а сайт-игрушку. Это не то же самое. Там конечно много подводных камней, но это только идет на пользу — человек лучше будет разбираться в разных аспектах веб-платформы.
По поводу того, то ты делаешь, я тебе рекомендую как минимум периодически код показывть на проверку. А то есть риск что ты толком Юи не выучишь, а только научишься каким-то простым вещам увиденным в туториалах (типа добавить контроллер и модель). Это конечно лучше чем ничего, но ты сообразительный, можешь и большего добиться.
Ну и подумай насчет Юи 2, он новый и со временем будет вытеснять Юи, есть ли смысл изучать старую версию вместо новой?
тут http://www.yiiframework.com/doc/api/1.1/CController#layout-detail написано что false отключает лейауты для контроллера, а вот тут http://www.yiiframework.com/doc/api/1.1/CWebApplication#layout-detail написано что можно отключить их сразу на уровне приложения.
тут http://www.yiiframework.com/doc/api/1.1/CController#layout-detail написано что false отключает лейауты для контроллера, а вот тут http://www.yiiframework.com/doc/api/1.1/CWebApplication#layout-detail написано что можно отключить их сразу на уровне приложения.
Кстати я сам на Юи ни одного сайта не написал, только пару раз проверял анонов которые на нем задания делали.
Кто их знает, может конечно разработчики включили для отладки, и забыли отключить, а может дело и не в этом.
яндекс - зашквар уровня мейлсру. Все начиная от блевотного дизайна и организации страниц до наглого подсвовывание яндекс-настроек для бразуера в сторонних программах для скачки. Я на фаерфоксе яндекс-вирус цепанул, так это говно теперь в каждой жопе затычка в поиске вылезает постоянно. Нахуй в жизни в эту контору не пойду работать, яндекс надо хуесосить просто бесконечно.
ты такой интересный, мне иногда кажется, что ты отвечаешь не для того, чтобы по существу что-то ответить и донести какую-то инфу, а просто чтобы унизить собеседника. Т.е. по сути ты нихуя не пишешь полезного, а просто пытаешься как петух распустить хвост и сделать вид, что ты что-то знаешь, чего оппонент не знает.
Вот смотри - вот этот кусок говна - код который - написан в твоем же говноучебнике, значит это ты должен знать, почему эта ебаная переменная $i не прибавляется ++
Мне кажется, ты какой-то ебанутый графоман, которому нравится писать просто ради слагания слов в буквы и провоцирования собеседника на написание таких же бесполезных полотен, которые тешат твой маленький нестоящий хуй,м?
function printQuestions($questions)
{
$i = 1; // номер вопроса
foreach ($questions as $question) {
echo "<br>{$i} . {$question->text}<br>";
echo "Variants of answer:<br>";
foreach ($question->answers as $letter => $answer) {
echo " {$letter} . {$answer}<br>";
}
$i++;
}
>стоит посмотреть, может в Юи что-то еще на лейауты завязано
Да, там походу именно в layout подключаются вшитые скрипты (поэтому у меня не работала аякс-валидация), а может происходят и другие вещи, о которых я пока не знаю, так что наверное пока не стоит их трогать.
>но ты сообразительный, можешь и большего добиться.
Я уже знаю, ты это пишешь тем кто сильно тупит, но очень старается.
Но все равно приятно.
>я тебе рекомендую как минимум периодически код показывть на проверку
У меня пока проблема с проектированием базы. Даже в таком простом (как я думал) проекте понадобилось реализовать два неслабых паттерна бд: eav и nested sets.
А так думаю за неделю справлюсь, yii мне кажется несложным. Большую часть такого сайта можно вообще сделать в генераторе кода gii. Что есть на сайте объявлений?
1. Аутентификация (идет в коробке с фреймворком, нужно только прописать пару строчек в UserIdentity)
2. Регистрация. Первое время я сильно тупил, как сегодня с этими скриптами в layout, но потом до меня таки дошло, что это банальный user/create.
3. Главная страница. Там должна быть пара простых виджетов (топ-объявления, новые объявления - обычный виджет ListView).
Строка поиска, тут все понятно. Впрочем придется повозиться с полнотекстовым поиском, ведь в InnoDb он доступен только с версии 5.6, обновиться что ли? Или не стоит? В дистрибутивах убунты 5.5, почему-то не спешат обновляться. (Кстати, а что по поводу версий php? Не рекомендуешь обновляться?)
Выбор категории 1-2 уровня (вложенным списком, раскрывается по клику на родительской)
4. Результат поиска, список объявлений. Опять ListView.
Здесь еще доп.форма поиска с указанием "подкатегорий", или как их назвать (например "Авто"->"Легковые" выбираем на главной и попадаем сюда, где выбираем "Марку" и может быть модель), специфических для категории характеристик-фильтров (объем двигателя, год выпуска и т.д.)
5. Просмотр отдельного объявления, DetailView с жадной загрузкой зависимостей.
6. В админке стандартные crud.
По отдельности я многие возможности фреймворка знаю, делал хелловорлды.
В общем, вроде не вижу ничего сложного. У меня больше сложностей с проектированием базы.
Возвращаясь к js.
А что вот это за штуковина:
<script type="text/javascript">
/<![CDATA[/
// тут код на jqeury
/]]>/
</script>
Что за странная конструкция CDATA? Где об этом почитать и по каким тегам гуглить?
Из того что мне выпало из гугла
http://bortvlad.ru/html-verstka/cdata/
Сказано только, что это какая-то хрень для xml и вообще не стоит вскрывать эту тему.
https://ru.wikipedia.org/wiki/Cdata
С википедии удалена. Совпадение? А нет, удалили дубль https://ru.wikipedia.org/wiki/CDATA
Здесь тоже говорят, что эта штука для xml.
Суть в том, что именно в таком виде yii-виджеты типа CActiveForm добавляют скрипты, поэтому мне любопытно зачем так сделано, почему не обычный тег <script>?
>стоит посмотреть, может в Юи что-то еще на лейауты завязано
Да, там походу именно в layout подключаются вшитые скрипты (поэтому у меня не работала аякс-валидация), а может происходят и другие вещи, о которых я пока не знаю, так что наверное пока не стоит их трогать.
>но ты сообразительный, можешь и большего добиться.
Я уже знаю, ты это пишешь тем кто сильно тупит, но очень старается.
Но все равно приятно.
>я тебе рекомендую как минимум периодически код показывть на проверку
У меня пока проблема с проектированием базы. Даже в таком простом (как я думал) проекте понадобилось реализовать два неслабых паттерна бд: eav и nested sets.
А так думаю за неделю справлюсь, yii мне кажется несложным. Большую часть такого сайта можно вообще сделать в генераторе кода gii. Что есть на сайте объявлений?
1. Аутентификация (идет в коробке с фреймворком, нужно только прописать пару строчек в UserIdentity)
2. Регистрация. Первое время я сильно тупил, как сегодня с этими скриптами в layout, но потом до меня таки дошло, что это банальный user/create.
3. Главная страница. Там должна быть пара простых виджетов (топ-объявления, новые объявления - обычный виджет ListView).
Строка поиска, тут все понятно. Впрочем придется повозиться с полнотекстовым поиском, ведь в InnoDb он доступен только с версии 5.6, обновиться что ли? Или не стоит? В дистрибутивах убунты 5.5, почему-то не спешат обновляться. (Кстати, а что по поводу версий php? Не рекомендуешь обновляться?)
Выбор категории 1-2 уровня (вложенным списком, раскрывается по клику на родительской)
4. Результат поиска, список объявлений. Опять ListView.
Здесь еще доп.форма поиска с указанием "подкатегорий", или как их назвать (например "Авто"->"Легковые" выбираем на главной и попадаем сюда, где выбираем "Марку" и может быть модель), специфических для категории характеристик-фильтров (объем двигателя, год выпуска и т.д.)
5. Просмотр отдельного объявления, DetailView с жадной загрузкой зависимостей.
6. В админке стандартные crud.
По отдельности я многие возможности фреймворка знаю, делал хелловорлды.
В общем, вроде не вижу ничего сложного. У меня больше сложностей с проектированием базы.
Возвращаясь к js.
А что вот это за штуковина:
<script type="text/javascript">
/<![CDATA[/
// тут код на jqeury
/]]>/
</script>
Что за странная конструкция CDATA? Где об этом почитать и по каким тегам гуглить?
Из того что мне выпало из гугла
http://bortvlad.ru/html-verstka/cdata/
Сказано только, что это какая-то хрень для xml и вообще не стоит вскрывать эту тему.
https://ru.wikipedia.org/wiki/Cdata
С википедии удалена. Совпадение? А нет, удалили дубль https://ru.wikipedia.org/wiki/CDATA
Здесь тоже говорят, что эта штука для xml.
Суть в том, что именно в таком виде yii-виджеты типа CActiveForm добавляют скрипты, поэтому мне любопытно зачем так сделано, почему не обычный тег <script>?
Зая, ты страдаешь хуйнёй.
А вообще, чтобы получить нужный тебе результат надо использовать цикл for:
for ($i = 1; $i <= count($questions); $i++) {
//выводишь свои вопросы
}
>полотно
>полсотни строчек для программиста(!)
Я так один раз зашел в /po и написал три предложения по пятнадцать слов, мне тоже сказали про какую-то простыню.
Может кто подскажет как множество условий грамотно обрабатывать?
Если одновременно выбраны А и B, то их суммарная стоимость уменьшается на 10% (для каждой пары А и B)
Если одновременно выбраны D и E, то их суммарная стоимость уменьшается на 5% (для каждой пары D и E)
Если одновременно выбраны E,F,G, то их суммарная стоимость уменьшается на 5% (для каждой тройки E,F,G)
Если одновременно выбраны А и один из [K,L,M], то стоимость выбранного продукта уменьшается на 5%
Если пользователь выбрал одновременно 3 продукта, он получает скидку 5% от суммы заказа
Если пользователь выбрал одновременно 4 продукта, он получает скидку 10% от суммы заказа
Если пользователь выбрал одновременно 5 продуктов, он получает скидку 20% от суммы заказа
Описанные скидки 5,6,7 не суммируются, применяется только одна из них
Продукты A и C не участвуют в скидках 5,6,7
Каждый товар может участвовать только в одной скидке. Скидки применяются последовательно в порядке описанном выше.
Спасибо. Читаю про исключения.
Сейчас начал изучать, читаю манул на yiiframework.ru, но там, скорее, справочные данные, а я хотел бы пошаговую инструкцию с установкой, простейшими примерами, советами и практиками.
Что посоветуете?
Спасибо.
Обломись.
О, хороший вопрос пришел.
Во-первых, надо начать что современные браузеры кроме языка HTML понимают XML-синтаксис для HTML5 (тот же язык, но с небольшими отличиями), а также XHTML который является отдельным языком, чем-то вроде альтернативы HTML4 c XML-синтаксисом. XML это универсальный язык представления данных в виде текста с тегами, наличием тегов он похож на HTML, потому нашлись сторонники сделать альтернативные версии HTML и как мы видим они даже смогли внести их в стандарт HTML5.
https://ru.wikipedia.org/wiki/XHTML
http://htmlbook.ru/xhtml/sintaksis-xhtml
> что такое CDATA
Это конструкция языка XML (и основанного на нем XHTML), которая позволяет вставить произвольный текст, не экранируя в нем символы <, >, &
Как известно, в XML (а также в HTML) эти символы в тексте должны заменяться на мнемоники:
> >
< <
& &
< и > надо заменять так как они используются в тегах
& надо заменять так как он используется в мнемониках
В PHP даже есть функция htmlspecialchars делающая такие замены в тексте. Чуть-чуть про нее упомянуто в уроке по XSS: https://github.com/codedokode/pasta/blob/master/security/xss.md
HTML-Мнемоники это коды, начинающиеся с &, для вставки разных символов: https://ru.wikipedia.org/wiki/%D0%9C%D0%BD%D0%B5%D0%BC%D0%BE%D0%BD%D0%B8%D0%BA%D0%B8_%D0%B2_HTML Они работают и в HTML и в XML (и XHTML).
Таким образом чтоб написать текст вроде <3 надо писать в HTML коде <3
(внезапно, многие туториалы почему-то не заостряют на этом внимание, а зря. Наши задачи по HTML/CSS разумеется заостряют)
Ну так вот, синтаксис CDATA дает альтернативный способ вставить в код произвольный текст, не заменяя символы: https://ru.wikipedia.org/wiki/CDATA
Дальше — интереснее.
Во-первых, внимательный читатель заметит что CDATA это часть XML (универсального языка представления данных в виде текста с тегами) и HTML5, но не HTML4. Но дело в том, что современные браузеры кроме HTML4 понимают еще XML-синтаксис для HTML5, а также сам XHTML.
Так как современные браузеры все равно понимают HTML5/XHTML, то они понимают и CDATA даже в HTML4 коде, хотя по стандарту его там нет. И до HTML5 браузеры поддерживающме HTML4 + XHTML тоже понимали CDATA в любом синтаксисе.
Таким образом CDATA поддерживается почти всеми браузерами в обоих режимах (HTML и XML), кроме старых ИЕ (это предположение, не уверен на 100%) которые не поддерживают XHTML и может каких-нибудь еще древних браузеров.
Разобрались с CDATA, вернемся к скриптам.
Согласно правилам HTML (не XML или XHTML!), как исключение, в содержимом тегов script или style мнемоники не распознаются и описанные выше замены символов делать нельзя — они будут восприняты как есть (стандарт: http://www.w3.org/TR/html5/scripting-1.html#restrictions-for-contents-of-script-elements там специально рассматриваются сложные случаи когда в скрипте встречаются куски HTML).
В правилах XML и XHTML ничего подобного нет. Там ты обязан заменять символы.
Это создает противоречие: невозможно написать скрипт или стили, содержащий эти 3 символа так, чтобы он был корректным одновременно в HTML и XHTML. HTML требует писать символы как есть, XHTML требует их заменять.
CDATA является решением: он позволяет вставить символы как есть, но работает только в XML синтаксисе. Честный HTML4-парсер воспримет его как часть скрипта. Потому мы делаем финт ушами и комментируем эту конструкцию, чтобы яваскрипт воспринимал его как комментарий.
XHTML-парсер понимает CDATA, интерпретирует его и передает движку яваскрипт такой текст:
/× ×/
текст скрипта как есть
/× ×/
HTML-парсер не парсит CDATA, а считает его частью JS кода но благодаря комментариям это не влияет на его работу
/× <![CDATA[ ×/
текст как есть
/× ]]> ×/
Замечу также что по правилам HTML скрипт не должен содержать последовательности </script, <script, <!-- и -->
По правилам XML скрипт не должен содержать ]]> которое воспринимается как конец CDATA.
Таким образом этот синтаксис позволят сделать код скрипта работающим в HTML- и XHTML режиме браузера. Разработчики Юи либо хотели чтобы их скрипты были совместимы с обоими языкми, либо просто откуда-то скопировали эту конструкцию. Я думаю, первое.
Наконец, напишу еще интересную вещь. XHTML одно время очень активно пиарили и пытались продвинуть на замену HTML. Несмотря на активное продвижение XHTML (его пихали в каждую статью и учебник), в реальности почти никто не переключал браузеры в этот режим. Люди (авторы учебников и читатели) писали похожий на XHTML код, однако давали его браузеру под видом HTML и браузер воспринимал его как HTML с ошибками. Так как HTML очень прощающий язык и браузер игнорирует и исправляет ошибки синтаксиса, это работало.
Когда принимали стандарт HTML5, его расширили так, чтобы некоторые XHTML-конструкции, которых не было в HTML (например слеш тут: <br /> в HTML4 это ошибка, которую браузер игнорирует, в HTML5 слеш ничего не значит, в XML/XHTML он значит самозакрывающийся тег) не считались больше ошибкой, а игнорировались, добавили CDATA, а для скучающих по XML/XHTML сделали альтернативный XML-синтаксис HTML5 (которым также никто не пользуется).
Фанаты XML незадолго до HTML5, сделали XHTML2 которым никто не пользуется (так как вышел HTML5) и на котором никтогда не бывший популярным XHTML умер окончательно. Привычка ставить слеши в конце одиночных тегов также потихоньку начинает вымирать.
Много подробностей (про XHTML и почему люди его не использовали на самом деле, хотя писали в его стиле) в этой статье: http://softwaremaniacs.org/blog/2005/12/19/xhtml-you-say/ (это самая важная ссылка в посте, ее точно стоит прочесть)
Там же упомянут этот способ вставить скрипт.
краткое содержание:
- был альтернативный язык, похожий на HTML, но с XML синтаксисом, который начали поддерживать браузеры - XHTML. За счет похожести синтаксиса XHTML-код могли парсить и HTML4 браузеры, думая что это просто HTML с ошибками.
- он был неплох в общем-то, приучал к порядку, но на практике никто его не использовал так как люди толком не знали как настроить сервер для отдачи правильных заголовков, а те кто знали, не рисковали пользоваться из-за строгого подхода к ошибкам (XHTML не прощает ошибки и отказывается отображать страницу в отличие от HTML). Пользовались им разве что продвинутые разработчики компаний вроде Яндекса.
- верстальщики в массе своей малограмотны, не хотят разбираться в деталях и пишут код как в туториалах
- сторонники XHTML везде пропихивали его синтаксис, он был во многих учебниках и люди учили его даже не осознавая что это не HTML. Некоторые осознавали, но он им казался красивее.
- разработчики Юи решили (как и многие другие фреймворки) поддерживать и XHTML, и HTML
- так как браузеры воспринимают содержимое script/style по-разному в HTML- и XML- режиме парсинга, они используют такой сложный синтаксис
- все это описано тут более простыми словами http://softwaremaniacs.org/blog/2005/12/19/xhtml-you-say/
------------
А, еще иногда можно увидеть HTML-комментарий внутри script:
<script><!--
текст скрипта
// --></script>
Это совсем другая история. Это защита от древнейших браузеров (созданных ранее 1995 года), которые не знают про тег script и выводят его содержимое на экран. Комментарий заставляет их это не делать, а современные браузеры игнорируют открывающий комментарий внутри script.
Особо рьяные совмещают этот синтаксис с CDATA в адски сложную конструкцию которую я по памяти не напишу, а составлять ее с нуля мне лень.
О, хороший вопрос пришел.
Во-первых, надо начать что современные браузеры кроме языка HTML понимают XML-синтаксис для HTML5 (тот же язык, но с небольшими отличиями), а также XHTML который является отдельным языком, чем-то вроде альтернативы HTML4 c XML-синтаксисом. XML это универсальный язык представления данных в виде текста с тегами, наличием тегов он похож на HTML, потому нашлись сторонники сделать альтернативные версии HTML и как мы видим они даже смогли внести их в стандарт HTML5.
https://ru.wikipedia.org/wiki/XHTML
http://htmlbook.ru/xhtml/sintaksis-xhtml
> что такое CDATA
Это конструкция языка XML (и основанного на нем XHTML), которая позволяет вставить произвольный текст, не экранируя в нем символы <, >, &
Как известно, в XML (а также в HTML) эти символы в тексте должны заменяться на мнемоники:
> >
< <
& &
< и > надо заменять так как они используются в тегах
& надо заменять так как он используется в мнемониках
В PHP даже есть функция htmlspecialchars делающая такие замены в тексте. Чуть-чуть про нее упомянуто в уроке по XSS: https://github.com/codedokode/pasta/blob/master/security/xss.md
HTML-Мнемоники это коды, начинающиеся с &, для вставки разных символов: https://ru.wikipedia.org/wiki/%D0%9C%D0%BD%D0%B5%D0%BC%D0%BE%D0%BD%D0%B8%D0%BA%D0%B8_%D0%B2_HTML Они работают и в HTML и в XML (и XHTML).
Таким образом чтоб написать текст вроде <3 надо писать в HTML коде <3
(внезапно, многие туториалы почему-то не заостряют на этом внимание, а зря. Наши задачи по HTML/CSS разумеется заостряют)
Ну так вот, синтаксис CDATA дает альтернативный способ вставить в код произвольный текст, не заменяя символы: https://ru.wikipedia.org/wiki/CDATA
Дальше — интереснее.
Во-первых, внимательный читатель заметит что CDATA это часть XML (универсального языка представления данных в виде текста с тегами) и HTML5, но не HTML4. Но дело в том, что современные браузеры кроме HTML4 понимают еще XML-синтаксис для HTML5, а также сам XHTML.
Так как современные браузеры все равно понимают HTML5/XHTML, то они понимают и CDATA даже в HTML4 коде, хотя по стандарту его там нет. И до HTML5 браузеры поддерживающме HTML4 + XHTML тоже понимали CDATA в любом синтаксисе.
Таким образом CDATA поддерживается почти всеми браузерами в обоих режимах (HTML и XML), кроме старых ИЕ (это предположение, не уверен на 100%) которые не поддерживают XHTML и может каких-нибудь еще древних браузеров.
Разобрались с CDATA, вернемся к скриптам.
Согласно правилам HTML (не XML или XHTML!), как исключение, в содержимом тегов script или style мнемоники не распознаются и описанные выше замены символов делать нельзя — они будут восприняты как есть (стандарт: http://www.w3.org/TR/html5/scripting-1.html#restrictions-for-contents-of-script-elements там специально рассматриваются сложные случаи когда в скрипте встречаются куски HTML).
В правилах XML и XHTML ничего подобного нет. Там ты обязан заменять символы.
Это создает противоречие: невозможно написать скрипт или стили, содержащий эти 3 символа так, чтобы он был корректным одновременно в HTML и XHTML. HTML требует писать символы как есть, XHTML требует их заменять.
CDATA является решением: он позволяет вставить символы как есть, но работает только в XML синтаксисе. Честный HTML4-парсер воспримет его как часть скрипта. Потому мы делаем финт ушами и комментируем эту конструкцию, чтобы яваскрипт воспринимал его как комментарий.
XHTML-парсер понимает CDATA, интерпретирует его и передает движку яваскрипт такой текст:
/× ×/
текст скрипта как есть
/× ×/
HTML-парсер не парсит CDATA, а считает его частью JS кода но благодаря комментариям это не влияет на его работу
/× <![CDATA[ ×/
текст как есть
/× ]]> ×/
Замечу также что по правилам HTML скрипт не должен содержать последовательности </script, <script, <!-- и -->
По правилам XML скрипт не должен содержать ]]> которое воспринимается как конец CDATA.
Таким образом этот синтаксис позволят сделать код скрипта работающим в HTML- и XHTML режиме браузера. Разработчики Юи либо хотели чтобы их скрипты были совместимы с обоими языкми, либо просто откуда-то скопировали эту конструкцию. Я думаю, первое.
Наконец, напишу еще интересную вещь. XHTML одно время очень активно пиарили и пытались продвинуть на замену HTML. Несмотря на активное продвижение XHTML (его пихали в каждую статью и учебник), в реальности почти никто не переключал браузеры в этот режим. Люди (авторы учебников и читатели) писали похожий на XHTML код, однако давали его браузеру под видом HTML и браузер воспринимал его как HTML с ошибками. Так как HTML очень прощающий язык и браузер игнорирует и исправляет ошибки синтаксиса, это работало.
Когда принимали стандарт HTML5, его расширили так, чтобы некоторые XHTML-конструкции, которых не было в HTML (например слеш тут: <br /> в HTML4 это ошибка, которую браузер игнорирует, в HTML5 слеш ничего не значит, в XML/XHTML он значит самозакрывающийся тег) не считались больше ошибкой, а игнорировались, добавили CDATA, а для скучающих по XML/XHTML сделали альтернативный XML-синтаксис HTML5 (которым также никто не пользуется).
Фанаты XML незадолго до HTML5, сделали XHTML2 которым никто не пользуется (так как вышел HTML5) и на котором никтогда не бывший популярным XHTML умер окончательно. Привычка ставить слеши в конце одиночных тегов также потихоньку начинает вымирать.
Много подробностей (про XHTML и почему люди его не использовали на самом деле, хотя писали в его стиле) в этой статье: http://softwaremaniacs.org/blog/2005/12/19/xhtml-you-say/ (это самая важная ссылка в посте, ее точно стоит прочесть)
Там же упомянут этот способ вставить скрипт.
краткое содержание:
- был альтернативный язык, похожий на HTML, но с XML синтаксисом, который начали поддерживать браузеры - XHTML. За счет похожести синтаксиса XHTML-код могли парсить и HTML4 браузеры, думая что это просто HTML с ошибками.
- он был неплох в общем-то, приучал к порядку, но на практике никто его не использовал так как люди толком не знали как настроить сервер для отдачи правильных заголовков, а те кто знали, не рисковали пользоваться из-за строгого подхода к ошибкам (XHTML не прощает ошибки и отказывается отображать страницу в отличие от HTML). Пользовались им разве что продвинутые разработчики компаний вроде Яндекса.
- верстальщики в массе своей малограмотны, не хотят разбираться в деталях и пишут код как в туториалах
- сторонники XHTML везде пропихивали его синтаксис, он был во многих учебниках и люди учили его даже не осознавая что это не HTML. Некоторые осознавали, но он им казался красивее.
- разработчики Юи решили (как и многие другие фреймворки) поддерживать и XHTML, и HTML
- так как браузеры воспринимают содержимое script/style по-разному в HTML- и XML- режиме парсинга, они используют такой сложный синтаксис
- все это описано тут более простыми словами http://softwaremaniacs.org/blog/2005/12/19/xhtml-you-say/
------------
А, еще иногда можно увидеть HTML-комментарий внутри script:
<script><!--
текст скрипта
// --></script>
Это совсем другая история. Это защита от древнейших браузеров (созданных ранее 1995 года), которые не знают про тег script и выводят его содержимое на экран. Комментарий заставляет их это не делать, а современные браузеры игнорируют открывающий комментарий внутри script.
Особо рьяные совмещают этот синтаксис с CDATA в адски сложную конструкцию которую я по памяти не напишу, а составлять ее с нуля мне лень.
Вакаба съела мнемоники! Читать надо так:
-----
Как известно, в XML (а также в HTML) эти символы в тексте должны заменяться на мнемоники:
> & gt ;
< & lt ;
& & amp ;
< и > надо заменять так как они используются в тегах
& надо заменять так как он используется в мнемониках
В этом тестовом задании, которое ты должен решать своей головой, надо очевидно сделать систему вычисления скидок, а каждую скидку сделать отдельным классом (или функцией, но по моему задача на ООП). А также сделать класс ВычислительСкидки который будет применять объекты-ПравилаСкидок по очереди к НаборуПродуктов.
>>540693
Юи 2
А, вспомнил, популярность XHTML обеспечивалась еще тем, что был шаблонизатор XSLT, тоже на основе XML, и он на выходе легко генерировал XHTML. Его использовали например в Яндексе, Студии Лебедева, ну и вообще все серьезные разработчики. Несерьезные просто его не осиливали и писали кривые кишащие уязвимостями самописные скрипты на PHP.
Но это было давно, твиг конечно гораздо удобнее и писать меньше приходится.
Я понял. Ты не изучал PHP ни по моему учебнику, ни по другому нормальному учебнику. Ты прочел несколько туториалов и что-то запомнил, но в общем сам язык не знаешь.
Тогда тебе надо вернуться еще раньше, например решить все задачи из раздела «Повторим», которые как раз проверяют знание массивов/функций/циклов и тд. Тебе пока рано браться за ООП.
Если не нравится мой учебник, ты можешь взять любой другой.
По поводу переменной:
Ты в начале функции присваиваешь ей значение 1:
$i = 1;
Оно и выводится.
В конце функции ты увеличиваешь $i на один, но это не имеет никакого смысла. $i это локальная (созданная в функции) переменная, она доступна только внутри функции и она уничтожается при выходе из функции. При втором вызове функции создастся новая, другая переменная $i, и ей снова присвоится один. И выведется.
Тебе надо не вызывать функцию 2 раза , передавая по 1 вопросу, а сделать массив из 2 вопросов и вызывать функцию 1 раз.
И почему ты думаешь, что я тебя хотел унизить? Я лишь хотел чтобы ты сам нашел причину ошибки. Впрочем, если ты не знал про локальные переменные, то возможно ты бы и не смог ее найти сам.
У нас анонимная доска и я не знаю, что ты знаешь, а что нет, какие темы изучил, а какие пропустил. Глава про ООП предполагает что ты изучил функции и как работают переменные в них.
В твоем случае, тебе надо вернуться назад и разобраться с более простыми вещами прежде чем браться за ООП.
> Вот смотри - вот этот кусок говна - код который - написан в твоем же говноучебнике
Я сейчас открыл учебник и код там другой. Например $i++ стоит внутри цикла, а не снаружи. Это ты его неправильно переписал или переделал, возможно по невнимательности.
Более того, у меня ощущение что я зря пишу эту пасту. Если бы ты не пропускал темы, а изучал все с самого начала, ты бы такие вопросы не задавал. Ну так вернись и изучи, я тут не буду пол-учебника заново расписывать для тебя лично.
Я понял. Ты не изучал PHP ни по моему учебнику, ни по другому нормальному учебнику. Ты прочел несколько туториалов и что-то запомнил, но в общем сам язык не знаешь.
Тогда тебе надо вернуться еще раньше, например решить все задачи из раздела «Повторим», которые как раз проверяют знание массивов/функций/циклов и тд. Тебе пока рано браться за ООП.
Если не нравится мой учебник, ты можешь взять любой другой.
По поводу переменной:
Ты в начале функции присваиваешь ей значение 1:
$i = 1;
Оно и выводится.
В конце функции ты увеличиваешь $i на один, но это не имеет никакого смысла. $i это локальная (созданная в функции) переменная, она доступна только внутри функции и она уничтожается при выходе из функции. При втором вызове функции создастся новая, другая переменная $i, и ей снова присвоится один. И выведется.
Тебе надо не вызывать функцию 2 раза , передавая по 1 вопросу, а сделать массив из 2 вопросов и вызывать функцию 1 раз.
И почему ты думаешь, что я тебя хотел унизить? Я лишь хотел чтобы ты сам нашел причину ошибки. Впрочем, если ты не знал про локальные переменные, то возможно ты бы и не смог ее найти сам.
У нас анонимная доска и я не знаю, что ты знаешь, а что нет, какие темы изучил, а какие пропустил. Глава про ООП предполагает что ты изучил функции и как работают переменные в них.
В твоем случае, тебе надо вернуться назад и разобраться с более простыми вещами прежде чем браться за ООП.
> Вот смотри - вот этот кусок говна - код который - написан в твоем же говноучебнике
Я сейчас открыл учебник и код там другой. Например $i++ стоит внутри цикла, а не снаружи. Это ты его неправильно переписал или переделал, возможно по невнимательности.
Более того, у меня ощущение что я зря пишу эту пасту. Если бы ты не пропускал темы, а изучал все с самого начала, ты бы такие вопросы не задавал. Ну так вернись и изучи, я тут не буду пол-учебника заново расписывать для тебя лично.
Ок, я понял.
К слову в статье на open.net про древовидные структуры что-то поломалось в разметке, там сами мнемоники выводятся как есть
> $this->hasOne
http://www.opennet.ru/docs/RUS/hierarchical_data/
Статья очень старая. То что в статье про доктрину, относится к Doctrine 1. Для doctrine 2 есть расширение, реализующее популярные способы хранения деревьев: https://github.com/Atlantic18/DoctrineExtensions
мимоисправил
Насколько хорошая идея использовать сервер с юи2 на борте для этих целей? Легко ли будет подключить мобильные приложения (у них, конечно, "представление" будет своё и от сервака не нужно).
можно ли в yii CRUD сгенерировать по двум таблицам? Если да, то как?
Искал - не нашел
Делаешь RESTful API и похуй, что будет на бэкенде, выбирай, где тебе удобнее роутами манипулировать. Yii подойдёт, наверняка и плагин есть, чтобы быстро это RESTful API захуярить.
Нельзя, надо писать руками.
$questions[1] = CreateQuestions('Name a town', 5, ['a'=>'Paris', 'b'=>'Moscow', 'c'=>'London'], 'c');
$questions[2] = CreateQuestions('Name an artist', 7, ['a'=>'Sergei', 'b'=>'Danila', 'c'=>'Tolyan'], 'b');
printQuestions($questions);
Нахуй твои говнозадачки, которые лишь трата времени и решаются как два пальца об асфальт, не всрались в создании сайтов.
Попробуй поискать по запросу "сохранение связанных данных".
Хули ты их тогда решить не можешь?
Это задачи-детектор кстати, кто не может их решить, в жизни не напишет ничего круче "гостевухи с менюхой".
Все у меня написано как в твоем туториале, в глаза не долбись. У тебя там даже одна ошибка, слово answers неправильно написано хехе.
" select 1 from table where id = '$id' ",
тоесть сразу ставить переменную прошедшую валидацию, а не биндить?
Что решать, я вон уже сделал questions одним массивом, все равно не выводится. Если ОП ставит ебанутые условия, нихуя не объясняет и сам пишет самопальный говнокод, то это его проблемы, а не мои. Я лишь спросил есть ли норм учебник по ооп с пояснением, а меня отправили чужой велосипед дописывать с заранее неправильной постановкой вопроса и условий, вообще ахуеть.
Почему? Переменные ведь уже "очищены".
>Я лишь спросил есть ли норм учебник по ооп с пояснением
Все написанно в шапке
>Если ОП ставит ебанутые условия
Условия как условия, задача как и остальные решаются без мозгоебли.
не оп
А как я узнаю, что вводимые пользователем данные где-то там в коде проходят через класс валидатор?
Ты мне предлагаешь ползать по твоему коду и отслеживать всю историю жизни переменной $id, как она обрабатывалась?
Класс валидатора может будет писать вообще третий программист команды, который спокойно его грохнет, и у тебя появится инъекция.
Защищать данные нужно перед сохранением в базу.
Аналогично при выводе в шаблоне пропускать через escape.
ок, спасибо.
лел
ясно
Нет. Экранирование данных должно быть в том же месте где они используются то есть в маппере. Никто не будет лазать по всему твоему коду и изучать откуда они пришли. Более того, в будущем кто-то может вызвать твою функцию передав ей непроверенные данные.
Так что используй плейсхолдеры.
Кстати, в новом PHP может быть будет опция по автоматическому поиску SQL инъекций (PHP будет помечать пришедшие извне данные специальной меткой и бить тревогу если они проникли в SQL запрос, такое изменение хочет сделать один из разработчиков гугла: https://wiki.php.net/rfc/sql_injection_protection )
Насчет $i++, действительно, оно на месте, из-за того что отступы тут не выводятся, а ты потерял 1 закрывающую скобку, трудно это увидеть.
> но все равно не выводится. хотя по отдельности массивы выводятся.
Какую ошибку пишет PHP? Если никакую, то включи display_errors сначала.
Также, попробуй сдампить $questions и посмотреть что в ней.
Мне кажется, тебе надо сначала с массивами разобраться, прежде чем за ООП браться. Потому что ты явно создаешь массив неправильного вида.
Кстати, ты про конструкцию $array[] = слышал? Почему не используешь?
Также, имена функций пишутся с маленькой буквы. На работу программы это не влияет, но читать удобнее код оформленный стандартно.
>>540773
А как делается круд по одной таблице? Наследованием какого-то класса или виджета? Если так то можно посмотреть его код, может можно унаследоваться и переопеделить места, отвечающие за чтение/запись в БД.
Вообще, я подозреваю, что можно, просто надо сделать связь между моделями в ActiveRecord.
>>540836
Верно, это детектор. Те, кто хорошо знают язык, их решат за 5 минут, кто не знает, будет мучаться, но зато мы видим что именно он не знает и можем направить изучать теорию.
>>540857
Это хорошо что как в туториале. А теперь посмотри на структуру своего массива и на код функций и подумай какой массив они ожидают получить и какой ты им даешь.
Ну и мне кажется, ты просто плохо основы знаешь и тебе надо почитать про массивы, foreach и порешать задачки из раздела «повторим» например.
Там надо сделать примерно так:
- генерируем случайный номер поста и кладем в переменную
- определяем последнюю цифру и кладем в переменную
- в зависимости от нее с помощью if выводим какую-нибудь надпись
На каком пункте сложности?
Это все я проанализировал и понял уже. Я не понимаю как это писать. Сейчас возникла идея просто перечитать первый и второй урок.
еще в хтаксес вот это стоит, менял на палочку - не помогло.
через нетбинс выбрасывает на индекс.пхп если что
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [QSA,L]
Так получилось, что ты ответил на пост в тот момент, когда я уже переписал код и заменил его на гитхабе. Вот мой актуальный пост >>539109
Про алгоритм: задача стоит - если возможно, выдать сумму наибольшими (номиналами) купюрами. Кажется, это называется жадным алгоритмом.
Шаги такие:
1. Заполняем выдачу крупнейшими возможными купюрами, пока их сумма не станет равна запрошенной.
2. Если не сходиться - убираем одну вторую с конца по номиналу наименьшую купюру и повторяем пункт 1.
>Где гарантия что ты переберешь все возможные комбинации купюр?
Я старался этого избежать. Моя первая версия, которая перебирала все варианты, работала слишком медленно. Я проверил на нём все возможные запросы - не нашёл тех, которые он не находит. Если ты знаешь такие - сообщи, пожалуйста.
>Нужно использовать деление вместо цикла
Про какое деление ты говоришь?
>Давай начнем с архитектуры. Во-первых, у тебя очень странный ViewModel.
Я согласен с тобой, я подумал тогда, что если я всё сделаю как ты говоришь сейчас, у меня получиться маленькая ЦМС, что дальше чем просто нахождение алгоритма.
>К сожалению, код действительно не очень читабельный
Есть какие-то стандарты комментирования методов и свойств? Я вижу иного что-то вроде такого
/
comment
/, как такие комментарии лучше писать?
Кстати да, я не заметил сразу, рекурсия в моём случае действительно не нужна, т.к. она всегда возвращает саму-себя.
Так получилось, что ты ответил на пост в тот момент, когда я уже переписал код и заменил его на гитхабе. Вот мой актуальный пост >>539109
Про алгоритм: задача стоит - если возможно, выдать сумму наибольшими (номиналами) купюрами. Кажется, это называется жадным алгоритмом.
Шаги такие:
1. Заполняем выдачу крупнейшими возможными купюрами, пока их сумма не станет равна запрошенной.
2. Если не сходиться - убираем одну вторую с конца по номиналу наименьшую купюру и повторяем пункт 1.
>Где гарантия что ты переберешь все возможные комбинации купюр?
Я старался этого избежать. Моя первая версия, которая перебирала все варианты, работала слишком медленно. Я проверил на нём все возможные запросы - не нашёл тех, которые он не находит. Если ты знаешь такие - сообщи, пожалуйста.
>Нужно использовать деление вместо цикла
Про какое деление ты говоришь?
>Давай начнем с архитектуры. Во-первых, у тебя очень странный ViewModel.
Я согласен с тобой, я подумал тогда, что если я всё сделаю как ты говоришь сейчас, у меня получиться маленькая ЦМС, что дальше чем просто нахождение алгоритма.
>К сожалению, код действительно не очень читабельный
Есть какие-то стандарты комментирования методов и свойств? Я вижу иного что-то вроде такого
/
comment
/, как такие комментарии лучше писать?
Кстати да, я не заметил сразу, рекурсия в моём случае действительно не нужна, т.к. она всегда возвращает саму-себя.
Подготовил бэкап сайта+БД через akeeba. Скачал akeeba kickstart. Когда тренировался разворачивать сайт из akeeba бэкапа akeeba кикстартом на денвере под виндой - в первый раз словил крокозябры-иероглифы при запуске и в процессе работы кикстарта. Решение было: докинуть в директорию к будущему разворачиваемому сайту .htaccess со строчкой AddDefaultCharset UTF-8.
Надо ли будет так же заливать .htaccess со строчкой AddDefaultCharset UTF-8 и на хостинг? Или там уже и так прописана UTF-8 и kickstart корректно отработает в верной кодировке?
И ещё вопрос, высвечивается обновление до 3.4.х джумлы. Можно ли безболезненно обновлять свой сайт, реализованный на 3.3.х или лучше не стоит?
> 2. Если не сходиться - убираем одну вторую с конца по номиналу наименьшую купюру и повторяем пункт 1.
Вот это не очень понятно. Ты перебираешь только комбинации вида
A B C D X E
где A B C D всегда постоянные, а меняется только X и видимо E, которое от нее зависит? Я правильно понял?
Зачем тогда рекурсия? Для перебора одного числа хватит обычного цикла.
> Я проверил на нём все возможные запросы - не нашёл тех, которые он не находит. Если ты знаешь такие - сообщи, пожалуйста.
Я пока не понял алгоритм. Можно конечно заглянуть в код, но я думаю на словах объяснить короче и понятнее.
>>Нужно использовать деление вместо цикла
> Про какое деление ты говоришь?
твой цикл while можно заменить на деление. Чтобы найти сколько надо 500-рублевых купюр для суммы в 2450 достточно одно число поделить на другое.
> Я согласен с тобой, я подумал тогда, что если я всё сделаю как ты говоришь сейчас, у меня получиться маленькая ЦМС,
Нет, я предлагаю убрать лишние классы, а не добавлять. Это сейчас странный велосипед который ни соответствует ни MVC ни какому-либо другому принципу и где код раскидан без логики.
Я предлагаю убрать все классы кроме AtmMachine. То есть упростить код. А весь HTML поместить в существующий шаблон.
> Есть какие-то стандарты комментирования методов и свойств?
Комментарий пишется либо сверху либо справа (если есть место). В твоем случае помог бы краткий комментарий с описанием алгоритма.
>>541047
Зачем подготавливать бекапы? Не проще залить файлы по SFTP, а дамп залить из командной строки SSH?
> 2. Если не сходиться - убираем одну вторую с конца по номиналу наименьшую купюру и повторяем пункт 1.
Вот это не очень понятно. Ты перебираешь только комбинации вида
A B C D X E
где A B C D всегда постоянные, а меняется только X и видимо E, которое от нее зависит? Я правильно понял?
Зачем тогда рекурсия? Для перебора одного числа хватит обычного цикла.
> Я проверил на нём все возможные запросы - не нашёл тех, которые он не находит. Если ты знаешь такие - сообщи, пожалуйста.
Я пока не понял алгоритм. Можно конечно заглянуть в код, но я думаю на словах объяснить короче и понятнее.
>>Нужно использовать деление вместо цикла
> Про какое деление ты говоришь?
твой цикл while можно заменить на деление. Чтобы найти сколько надо 500-рублевых купюр для суммы в 2450 достточно одно число поделить на другое.
> Я согласен с тобой, я подумал тогда, что если я всё сделаю как ты говоришь сейчас, у меня получиться маленькая ЦМС,
Нет, я предлагаю убрать лишние классы, а не добавлять. Это сейчас странный велосипед который ни соответствует ни MVC ни какому-либо другому принципу и где код раскидан без логики.
Я предлагаю убрать все классы кроме AtmMachine. То есть упростить код. А весь HTML поместить в существующий шаблон.
> Есть какие-то стандарты комментирования методов и свойств?
Комментарий пишется либо сверху либо справа (если есть место). В твоем случае помог бы краткий комментарий с описанием алгоритма.
>>541047
Зачем подготавливать бекапы? Не проще залить файлы по SFTP, а дамп залить из командной строки SSH?
> Кстати да, я не заметил сразу, рекурсия в моём случае действительно не нужна, т.к. она всегда возвращает саму-себя.
Раз не нужна так замени ее на цикл, зачем код усложнять?
http://ideone.com/s0S86Q
Плиз поясните, что там происходит, зачем нужны "39" и что за "%с%s%c"?
http://php.net/manual/ru/function.printf.php
http://php.net/manual/ru/function.sprintf.php
Тут нет ответа на твой вопрос?
Так и сделаю.
>Вот это не очень понятно.
Вот визуализация этого алгоритма.
http://628808.plitka12.web.hosting-test.net/bank/?summ_requested=6600
>где A B C D всегда постоянные
Они не постоянные. Убирается вторая с конца купюра, далее стек заполняется наиболее крупными-возможными, кроме, естественно, той, которая была убрана.
если у меня index.php, то ссылки urlFor('page') пишутся вот так index.php/page и все стили ломается нахуй ибо в хедере путь другой.
$symbol2 = mb_substr($text, -($i+1), 1); спасибо, прозрел
Ты не считаешь проценты по кредиту в месяце, если осталось платить <= 5000, хотя они все равно начислятся.
пример:
index.php
путь к файлу
<script src="bootstrap/js/bootstrap.js"></script>
index.php/page
путь к файлу
<script src="../bootstrap/js/bootstrap.js"></script>
index.php/page/id
путь к файлу
<script src="../../bootstrap/js/bootstrap.js"></script>
нахуй так жить?
Угощайтесь господа похопешнике.
Есть три selecta на вьюшке, и они взаимосвязаны.
Т.е. в первом выбирается элемент, далее во втором выбираются элементы, которые входят в группу выбранную ранее, и в третьем листе появляется выбор из элементов находящихся в прошлом листе.
(машины (катера, самолеты) -> жигули(ауди, бмв, порш) -> красная 2109)
Как такое провернуть?
можно создать глобальную переменную $siteUrl и всегда задавать расположение относительно её.
Например <script src="<?php echo $siteurl?>/view/bootstrap/js/bootstrap.js"></script>
и так далее
передавать через конструктор, описано тут: https://gist.github.com/codedokode/e1d31a31b37d5f635057
>>541085
Покажи код (htaccess + index.php), дело явно не в этом и редиректов там не должно быть.
>>541140
Нет
>>541121
http://stackoverflow.com/a/17685660
Нашел такой ответ, но ругается что не хватает скобок на закрытие .
Не надо искать ответ, надо изучить JS, DOM, jQuery и написать код самому. Код по ссылке не решает твою задачу целиком.
>Вообще, я подозреваю, что можно, просто надо сделать связь между моделями в ActiveRecord.
Агаа, наверное, мудрейший имеет в виду GridView?!
10/10
Про кнопку download знаю, но мне лень потом распаковывать архив. Неужели нет команды для скачивания только последней версии?
http://archive-ipq-co.narod.ru/l1/functions.html
Решаz задачку про айпады, встал на непонятной мне ошибке. в цикле, при расчете кредитного баланса, этот баланс увеличивается, а не уменьшается. Все глаза стер, пока проблему искал. Помоги Анон!
http://ideone.com/eHBnDx
3 процента в месяц это 1.03, 0 процентов это 1.00. Ты написал просто 0. Умнажаешь сумму кредита на 0 в первой итерации цикла, получаешь 0.
Это читал
https://getcomposer.org/doc/faqs/how-do-i-install-a-package-to-a-custom-path-for-my-framework.md
но не понял.
> As a package consumer you can set or override the install path for a package that requires composer/installers by configuring the installer-paths extra.
То есть это сработает только для тех пакетов, у которых автор указал зависимость от composer/installers?
http://www.yiiframework.com/wiki/653/displaying-sorti..
И таблицы действительно объединяются, в и тоге выполняется запрос
SELECT `book`.* FROM `book` LEFT JOIN `author` ON `book`.`author` = `author`.`id` LIMIT 20
Но почему-то не хочет отображать данные по вызову
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
[
'attribute' => 'author',
'value' => 'author.name'
],
['class' => 'yii\grid\ActionColumn'],
],
]); ?>
Хотя данные 100% передаются.
Прикреплю ссылку на гитхаб, если не сложно, может, если не сложно, глянешь в чем там дело https://github.com/underpantsGnomes/test
Суть такова: есть таблица книги и таблица авторы.
Создал модель и для той и для той, потом модель library, которая их по идее должна связать.
В ней методы getBook() и getAuthor()
Затем от нее наследуется модель librarySearch, в которой есть метод search(), склеивающий таблицы. Вроде всё правильно, но хз, чет не работает, может я неправильно обращаюсь к значению в index.php просто?
http://www.yiiframework.com/wiki/653/displaying-sorti..
И таблицы действительно объединяются, в и тоге выполняется запрос
SELECT `book`.* FROM `book` LEFT JOIN `author` ON `book`.`author` = `author`.`id` LIMIT 20
Но почему-то не хочет отображать данные по вызову
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
[
'attribute' => 'author',
'value' => 'author.name'
],
['class' => 'yii\grid\ActionColumn'],
],
]); ?>
Хотя данные 100% передаются.
Прикреплю ссылку на гитхаб, если не сложно, может, если не сложно, глянешь в чем там дело https://github.com/underpantsGnomes/test
Суть такова: есть таблица книги и таблица авторы.
Создал модель и для той и для той, потом модель library, которая их по идее должна связать.
В ней методы getBook() и getAuthor()
Затем от нее наследуется модель librarySearch, в которой есть метод search(), склеивающий таблицы. Вроде всё правильно, но хз, чет не работает, может я неправильно обращаюсь к значению в index.php просто?
Взгляни мой вариант https://gist.github.com/anonymous/b0a3fa00d8266c6bc51d в нем последний платеж без процентов начисляется, не исправлял мб поможет
0 из 10
>Если что-то в нем непонятно, задай вопрос. По моему, так довольно простой алгоритм.
Да, действительно, все оказывается очень просто. Сейчас буду думать над твоими текущими замечаниями.
Что касается прошлых - почти все исправил. Осталось только придумать как работать со списком животных вместо двумерного массива и написать алгоритм выбора хода животного.
https://github.com/someApprentice/Cat-and-Mouse
По моему, никак. Там можно поменять имя папки vendor на другое, но суть в том что все зависимости ставятся в одну папку, так и задумано, нельзя отдельно указывать папки для библиотек. Соответственно все, что ставится через композер должно работать по такой системе.
А почему это понадобилось? Ты явно делаешь что-то не так.
>>541352
Ты не написал ни что ты хотел сделать (как должен выглядеть грид), ни какая ошибка выводится при запуске твоего кода. Придется привлекать телепатов.
Начнем с ответа на твой вопрос. Для того, чтобы выводить в гриде данные из несколько таблиц, надо сделать следующее:
1) связать их модели
2) в конфигурации грида в $columns прописать ссылку на поле из другой модели, например: 'author.name'
Читал ли ты документацию по гриду, например: http://www.yiiframework.com/doc-2.0/yii-grid-gridview.html#$columns-detail ? Там это написано.
И тут: https://github.com/yiisoft/yii2/blob/master/docs/guide/output-data-widgets.md#grid-columns
Про то как делать связи между моделями, написано тут: https://github.com/yiisoft/yii2/blob/master/docs/guide/db-active-record.md#working-with-relational-data-
Ссылки на английском, но для тех что на гитхабе скорее всего есть аналогичные на русском в соседней папке.
Если у тебя не работает то потому что модели (все) написаны неправильно.
К коду вообще много вопросов. Почему классы с маленькой буквы?
Почему поле author в модели книги объявлено? Разве это надо делать? Отношения недостаточно?
Я не понимаю зачем нужен BookSearch, почему у тебя 3 модели (book, bookSearch, library) к одной таблице привязаны (books)?
Что такое library и как оно связано с книгами и авторами? Ерунда какая-то.
Должно быть 1 класс = 1 таблица. Тебе надо изучить сначала что такое active record вообще: https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md
И документацию по active record для Юи 2.
> делал вроде бы всё как тут показывают
Это туториал, он только показывает какие классы и функции использовать, а документацию по ним ты должен сам прочесть. Туториал не замена документации. Если ты не понимаешь как работает Active Record и Grid, то ничего не получится. Надо сесть и разобраться.
По моему, никак. Там можно поменять имя папки vendor на другое, но суть в том что все зависимости ставятся в одну папку, так и задумано, нельзя отдельно указывать папки для библиотек. Соответственно все, что ставится через композер должно работать по такой системе.
А почему это понадобилось? Ты явно делаешь что-то не так.
>>541352
Ты не написал ни что ты хотел сделать (как должен выглядеть грид), ни какая ошибка выводится при запуске твоего кода. Придется привлекать телепатов.
Начнем с ответа на твой вопрос. Для того, чтобы выводить в гриде данные из несколько таблиц, надо сделать следующее:
1) связать их модели
2) в конфигурации грида в $columns прописать ссылку на поле из другой модели, например: 'author.name'
Читал ли ты документацию по гриду, например: http://www.yiiframework.com/doc-2.0/yii-grid-gridview.html#$columns-detail ? Там это написано.
И тут: https://github.com/yiisoft/yii2/blob/master/docs/guide/output-data-widgets.md#grid-columns
Про то как делать связи между моделями, написано тут: https://github.com/yiisoft/yii2/blob/master/docs/guide/db-active-record.md#working-with-relational-data-
Ссылки на английском, но для тех что на гитхабе скорее всего есть аналогичные на русском в соседней папке.
Если у тебя не работает то потому что модели (все) написаны неправильно.
К коду вообще много вопросов. Почему классы с маленькой буквы?
Почему поле author в модели книги объявлено? Разве это надо делать? Отношения недостаточно?
Я не понимаю зачем нужен BookSearch, почему у тебя 3 модели (book, bookSearch, library) к одной таблице привязаны (books)?
Что такое library и как оно связано с книгами и авторами? Ерунда какая-то.
Должно быть 1 класс = 1 таблица. Тебе надо изучить сначала что такое active record вообще: https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md
И документацию по active record для Юи 2.
> делал вроде бы всё как тут показывают
Это туториал, он только показывает какие классы и функции использовать, а документацию по ним ты должен сам прочесть. Туториал не замена документации. Если ты не понимаешь как работает Active Record и Grid, то ничего не получится. Надо сесть и разобраться.
> box-sizing: border-box;
зачем? И почему нет вендорных префиксов (-moz, -webkit)? Они нужны для поддержки старых chrome/safari/firefox.
> сделал через margin-left: auto ,
Так и надо, правильно.
Отступ слева и справа лучше делать через паддинг на body, а не margin на содержимом.
В остальном все верно.
основы пхп, включая ООП(только как содать обьекты, наследовать и т.д. никакого проектирования и теории), кратко HTTP, куки, сессии, немного про работу с mysqli. Конкретно о фреймворках и либах на четвертом курсе, но так получилось что целиком он записан не в одном году не был, как говорят аноны подача в нем не очень удачная.
Никакие. Там даже ооп начинается только на третьем курсе, да и то какое-то чисто формальное.
Паттерны бегло рассматриваются на последнем.
Эти курсы для полных нубов, которые никогда в жизни ни на чем не кодили.
>>541399
По поводу смены папки вендор на кастомную, это я пытаюсь подключить пару библиотек к первому yii. Одна из библиотек должна лежать в extensions, другая в components.
Уже разобрался, в yii можно прописать в конфигах путь к классам через странную точечную нотацию типа application.vendor.yiiext.mypackage.MyClass
>зачем?
а почему нет? У меня была проблема с тем, что не понятно как вычислить 34% -10 px, тогда я бы мог задать отступ вручную. На htmlbook сказано:
>Предположим, что ширина контента задана как 90%, если сюда приплюсовать поля и границы, заданные в пикселах, то нельзя вычислить суммарную ширину блока, поскольку проценты напрямую в пикселы не переводятся (в CSS3 так суммировать можно, только поддерживается эта возможность далеко не всеми браузерами). В итоге может получиться так, что общая ширина блока превысит ширину веб-страницы, что приведёт к появлению горизонтальной полосы прокрутки. Выходов из подобной ситуации два — поменять алгоритм блочной модели и воспользоваться вложенными слоями.
Можно еще проще? Как? Откровенно говоря, мне эта возня с версткой не очень нравится и я не хочу в этом утонуть. Классы для модели(задача на студентов) у меня почти написаны.
>нет вендорных префиксов (-moz, -webkit)
Я не подумал об этом
>Если у тебя не работает то потому что модели (все) написаны неправильно.
Но они же все сгенерированы через gii, кроме
librarySearch
>Почему классы с маленькой буквы?
Каюсь, еще не приучил себя.
>Почему поле author в модели книги объявлено? Разве это надо делать? Отношения недостаточно?
Дело в том, что таблицы связаны внешним ключом. После того, как я их связал и сгенерировал модель заново, уже с внешним ключом, тогда гии почему-то объявил в ней author и метод getAuthor. До этого не было.
>Я не понимаю зачем нужен BookSearch, почему у тебя 3 модели (book, bookSearch, library) к одной таблице привязаны (books)?
на BookSearch не стоит обращать внимания, извиняюсь, я забыл её удалить.
>Что такое library и как оно связано с книгами и авторами? Ерунда какая-то.
Наверное, сейчас скажу хуйню, но, то ли я не правильно понял, но мне показалось, что в том туториале чувак создал связующую модель для двух моделей(страны, города), поэтому я решил, что так норм делать.
Спасибо большое за ссылки, обещаю всё прочесть прежде чем что-то дальше делать, не сердись на меня.
Получается курс гдлится для изучения самого языка PHP, но после него надо учиться писать приложения: изучать MVC, фреймворки.
>>541408
> По поводу смены папки вендор на кастомную, это я пытаюсь подключить пару библиотек к первому yii. Одна из библиотек должна лежать в extensions, другая в components.
Невозможно. Надо как-то по другому делать, где-то я видел статьи как именно:
http://www.yiiframework.com/wiki/392/creating-yii-applications-with-composer/ (2012 год!)
http://shanedowling.com/yii-with-composer
Не знаю, насколько они актуальны. Юи 1 плохо совместим с композером, возможно что поменяв конфиг Юи что-то можно сделать.
>>541411
> У меня была проблема с тем, что не понятно как вычислить 34% -10 px
Сделать паддинг на боди 10px и margin 34%. Так как проценты считаются от внутренней ширины родителя (без паддинга).
> Но они же все сгенерированы через gii
Значит не весь код от gii праивльный. Тем более что скорее всего ты просто не так что-то делал.
Да и зачем gii, там 20 строк, их руками написать быстрее.
> Дело в том, что таблицы связаны внешним ключом. После того, как я их связал и сгенерировал модель заново, уже с внешним ключом, тогда гии почему-то объявил в ней author и метод getAuthor. До этого не было.
Либо разберись как правильно пользоваться гии, либо пиши руками.
> но мне показалось, что в том туториале чувак создал связующую модель для двух моделей(страны, города), поэтому я решил, что так норм делать.
У него другая база.
Должно быть 1 таблица = 1 модель AR.
В использовании гии нет ничего плохого но ты просто должен понимать каждую строчку в сгенерированном коде и при необходимости быть готовым что-то подправить.
ну не знаю что там можно не так сделать, указываешь название таблицы и всё.
http://geektimes.ru/post/262180/comments/#comment_8798146
http://geektimes.ru/post/262180/comments/#comment_8797982
Это зонд почище винды. Та хотя бы не имела доступ к вашему номеру телефона, переписке, местоположению.
Тем более что как мы помним из более ранних новостей, то же приложение фейсбук записывало GPS координаты при отправке любых сообщений.
Купить дорогой смартфон и получить шпионские программы от разведки США бесплатно — отличное предложение.
>Сделать паддинг на боди 10px и margin 34%. Так как проценты считаются от внутренней ширины родителя (без паддинга)
теперь все ясно, я просто зациклился на маргинах вокруг блоков, сейчас по быстренькому набросаю...
с box-sizing(поправил): http://jsfiddle.net/v2fqdxja/6/
вариант со слоями: http://jsfiddle.net/v2fqdxja/7/
Подскажите, нужно по фасту вернуть выбранное значение из вьюшки в php файлик. А с post функцией разобраться не могу.
Если выбирать между вложенными дивами (усложнение верстки) и box-sizing лучше второе, если не требуется поддерживать совсем древние браузеры.
А зачем вложенные дивы? Чтобы компенсировать 1px бордер? Можно было им пренебречь.
Ладно, в любом случае с заданием ты разобрался, давай дальше двигаться.
Ну и ты можешь сразу по несклоько задач решать и постить чтобы время не тратить.
а за тобой прям всем так охота пошпионить, ты такая важная личность, всем интересно, как ты ездишь в тай сосать хуи у трапов - такая-то сверхсекретная инфа.
Спасибо, а вообще, насколько разумны такие действия:
есть готовый сайт-одностраничник, к которому я хочу приделать приложение (логин, заказ, статистика). Причём приложение должно работать в том же окне, все действия должны грузиться айаксом.
Для этой цели я хочу поставить юи, чтобы она работала с авторизацией, БД и прочей бизнес-логикой, а выход возвращала в одностраничник, где уже яваскрипт будет обрабатывать представление.
Помимо этого планируется приложения для андроида, с тем же функционалом, для которого хочу использовать ту же схему.
Всё правильно делаю?
Не знаю, мало ли какие подводные камни, вдруг вообще для такого использовать юи избыточно или даже ошибочно.
Норм будет.
Ещё вопрос: как перевести сайт на хттпС?
Да, тупо сказал. В общем, мне нужна авторизация на удалённом сайте/приложении, я так понимаю, надо использовать RESTful API, но смутно понимаю, как именно его использовать. Есть ли простой пример приложения с авторизацией?
Не знаю, расскажи подробнее, пожалуйста.
молодец
class AbiturientsMapper
{
protected $pdo;
protected $fields = array('name', 'surname', 'birthyear', 'sex', 'local', 'email', 'summaryExamMark', 'groupNumber', 'token');
public function __construct(PDO $pdo)
{
$this->pdo = $pdo;
}
public function save(Abiturient $abiturient)
{
if (!empty($abiturient->id)) {
$stmt = $this->pdo->prepare("UPDATE abiturients SET name = :name, surname = :surname, sex = :sex, birthyear = :birthyear, local = :local, email = :email, summaryExamMark = :summaryExamMark, groupNumber = :groupNumber WHERE token = :token");
} else {
$stmt = $this->pdo->prepare("INSERT INTO abiturients (name, surname, sex, birthyear, local, email, summaryExamMark, groupNumber, token) VALUES (:name, :surname, :sex, :birthyear, :local, :email, :summaryExamMark, :groupNumber, :token)");
}
foreach ($this->fields as $key => $fieldName)
{
$placeholder = ':' . $fieldName;
switch ($fieldName) {
case 'birthyear':
case 'summaryExamMark':
$dataType = PDO::PARAM_INT;
$value = intval($abiturient->$fieldName);
break;
default:
$dataType = PDO::PARAM_STR;
$value = strval($abiturient->$fieldName);
break;
}
$stmt->bindValue($placeholder, $value, $dataType);
}
$stmt->execute();
}
class AbiturientsMapper
{
protected $pdo;
protected $fields = array('name', 'surname', 'birthyear', 'sex', 'local', 'email', 'summaryExamMark', 'groupNumber', 'token');
public function __construct(PDO $pdo)
{
$this->pdo = $pdo;
}
public function save(Abiturient $abiturient)
{
if (!empty($abiturient->id)) {
$stmt = $this->pdo->prepare("UPDATE abiturients SET name = :name, surname = :surname, sex = :sex, birthyear = :birthyear, local = :local, email = :email, summaryExamMark = :summaryExamMark, groupNumber = :groupNumber WHERE token = :token");
} else {
$stmt = $this->pdo->prepare("INSERT INTO abiturients (name, surname, sex, birthyear, local, email, summaryExamMark, groupNumber, token) VALUES (:name, :surname, :sex, :birthyear, :local, :email, :summaryExamMark, :groupNumber, :token)");
}
foreach ($this->fields as $key => $fieldName)
{
$placeholder = ':' . $fieldName;
switch ($fieldName) {
case 'birthyear':
case 'summaryExamMark':
$dataType = PDO::PARAM_INT;
$value = intval($abiturient->$fieldName);
break;
default:
$dataType = PDO::PARAM_STR;
$value = strval($abiturient->$fieldName);
break;
}
$stmt->bindValue($placeholder, $value, $dataType);
}
$stmt->execute();
}
Итак начнем как обычно...
http://maketi.esy.es/
> <h2 id="greeting-block--h2"
>h2 достаточно уникальный селектор и можно было не давать ему id, а писать:
>.greeting-block h2 { ... }
Разобрался с этим. Раньше наотрез отказывался делать в ксс что-то подобное, но оно оказалось очень легким. Переписал в двух местах таким способом.
> light-gray-advantages-block
>light-gray тут лишнее, надо в HTML описывать назначение блока а не его внешний вид который может менять при редизайне или смене темы оформления (если они есть на сайте).
Сменил. Знаю, что осталось еще одно похожее, а именно light-gray-text но вроде там можно и не менять.
> <h4 class="advantages-block--android-with-text--h4">
>Не, это стоило сверстать так: ...
Да, убрал этот класс. Заменил способом, описанным выше. Оставил просто h4.
>Обрати внимание на > — он обязателен, так как див распространенный элемент и верстальщик всегда может внутрь блока добавить новый див и он тогда попадет под этот селектор.
Да, эти мысли были еще когда сам такое поставил без >, но решил не трогать. Добавил в нужных местах.
>плохо что ты указал длительность анимации но не указал свойства которые анимируются. Нужно их перечислять чтобы анимировались только они, а не любые свойства.
Вот с этим не разобрался.
То есть вместо transition писать transition-width?
Статья на htmlbook дала только <transition-property> <transition-duration> <transition-timing-function> <transition-delay> то есть не совсем то, что нужно.
> #contacts-block--p1, #contacts-block--p2
>Тут стоило не ставить на них никакие id, а для отступа просто сделать класс вроде .offset-left
Ну не знаю, мне кажется удобнее все-таки их оставить.
> #contacts-block--p1:before {
> content: url(../img/kap.png);
>Тут кстати спрайт почему-то ты не сделал. Не разобрался со спрайтами?
Да. Но уже разобрался со спрайтами, они оказались вообще не тем о чем я думал. Я думал это просто одно большое изображение, которое полностью отображается, а не его частички.
> background-image: url(../img/android.png);
>То же самое, это бы спрайтом сделать надо.
Вот тут столкнулся с проблемой. Ширина там такая, что влезают все 4 изображения из спрайта. Если выставить для фона высоту и ширину, то не часть спрайта отображается, а весь спрайт просто уменьшается до этого размера. В общем тут не придумал как сделать через спрайт.
> #portfolio-block--button-all:checked ~ #portfolio-block--wrapper > .graphic,
> #portfolio-block--button-all:checked ~ #portfolio-block--wrapper > .illustration,
> #portfolio-block--button-all:checked ~ #portfolio-block--wrapper > .motion
>Это можно заменить на:
>#portfolio-block--button-all:checked ~ #portfolio-block--wrapper > a
Я потратил миллионы лет на обдумывание почему же это работает и в конце понял какой же я аутист и почему работает тоже понял, конечно.
> <span class="contacts-block--social-icons-text">
>текст можно скрыть гораздо проще, без добавления спана:
>- поставить color совпадающий с фоном + overflow hidden чтобы текст не вышел за границу блока
>- поставить большой text-indent + nowrap (чтобы не переносился) + overflow hidden
>- поставить color: rgba() с прозрачностью + overflow hidden
Поставил overflow hidden и все, текста и так не видно. В общем все работает.
> Работы в портфолио
Разобрался наконец с работами в портфолио.
Я бы описал это как детский страх, который ты побеждаешь во взрослой жизни и понимаешь "и вот этого я боялся?".
Все оказалось очень простым. Сделал картинку на 100%. Удалил полностью кучу лишних строк с ее изменениями.
Оставил только изменение размера <a>, сократив 6 до 4 строк. Теперь все смотрится лаконично.
>Надо разобраться с такими проблемами:
>- CSS спрайты (чтобы увидеть что ты их понял и умеешь делать): спрайт с андроидом, спрайт с соц иконками, спрайт с телефоном и картой.
>спрайт с соц иконками
Вот здесь я бы даже поспорил и сказал, что сделанное по моей технологии было лучше чем спрайт.
Напомню что было у меня - 1 картинка и наложенные на нее 5 кружочков прозрачных ссылок.
Почему это лучше спрайта? Потому что в спрайте мы прописываем фон-картинку к каждой ссылке. При моем же способе была как и в спрайте 1 картинка, но вот ксс намного короче, т.к. присутствовал только ксс 1 картинки, и ксс ссылок (один на все ссылки). При спрайте же много ксс на каждую ссылку. И если в данном случае где 5 картинок это не сильно заметно, но представим какого-нибудь поехавшего заказчика, который решил повставлять абсолютно все соцсети, штук 20-30. И что лучше, написать 2 строки к картинке и 2 строки к ссылкам или писать 20-30 разных правил к каждой частичке спрайта?
Итак начнем как обычно...
http://maketi.esy.es/
> <h2 id="greeting-block--h2"
>h2 достаточно уникальный селектор и можно было не давать ему id, а писать:
>.greeting-block h2 { ... }
Разобрался с этим. Раньше наотрез отказывался делать в ксс что-то подобное, но оно оказалось очень легким. Переписал в двух местах таким способом.
> light-gray-advantages-block
>light-gray тут лишнее, надо в HTML описывать назначение блока а не его внешний вид который может менять при редизайне или смене темы оформления (если они есть на сайте).
Сменил. Знаю, что осталось еще одно похожее, а именно light-gray-text но вроде там можно и не менять.
> <h4 class="advantages-block--android-with-text--h4">
>Не, это стоило сверстать так: ...
Да, убрал этот класс. Заменил способом, описанным выше. Оставил просто h4.
>Обрати внимание на > — он обязателен, так как див распространенный элемент и верстальщик всегда может внутрь блока добавить новый див и он тогда попадет под этот селектор.
Да, эти мысли были еще когда сам такое поставил без >, но решил не трогать. Добавил в нужных местах.
>плохо что ты указал длительность анимации но не указал свойства которые анимируются. Нужно их перечислять чтобы анимировались только они, а не любые свойства.
Вот с этим не разобрался.
То есть вместо transition писать transition-width?
Статья на htmlbook дала только <transition-property> <transition-duration> <transition-timing-function> <transition-delay> то есть не совсем то, что нужно.
> #contacts-block--p1, #contacts-block--p2
>Тут стоило не ставить на них никакие id, а для отступа просто сделать класс вроде .offset-left
Ну не знаю, мне кажется удобнее все-таки их оставить.
> #contacts-block--p1:before {
> content: url(../img/kap.png);
>Тут кстати спрайт почему-то ты не сделал. Не разобрался со спрайтами?
Да. Но уже разобрался со спрайтами, они оказались вообще не тем о чем я думал. Я думал это просто одно большое изображение, которое полностью отображается, а не его частички.
> background-image: url(../img/android.png);
>То же самое, это бы спрайтом сделать надо.
Вот тут столкнулся с проблемой. Ширина там такая, что влезают все 4 изображения из спрайта. Если выставить для фона высоту и ширину, то не часть спрайта отображается, а весь спрайт просто уменьшается до этого размера. В общем тут не придумал как сделать через спрайт.
> #portfolio-block--button-all:checked ~ #portfolio-block--wrapper > .graphic,
> #portfolio-block--button-all:checked ~ #portfolio-block--wrapper > .illustration,
> #portfolio-block--button-all:checked ~ #portfolio-block--wrapper > .motion
>Это можно заменить на:
>#portfolio-block--button-all:checked ~ #portfolio-block--wrapper > a
Я потратил миллионы лет на обдумывание почему же это работает и в конце понял какой же я аутист и почему работает тоже понял, конечно.
> <span class="contacts-block--social-icons-text">
>текст можно скрыть гораздо проще, без добавления спана:
>- поставить color совпадающий с фоном + overflow hidden чтобы текст не вышел за границу блока
>- поставить большой text-indent + nowrap (чтобы не переносился) + overflow hidden
>- поставить color: rgba() с прозрачностью + overflow hidden
Поставил overflow hidden и все, текста и так не видно. В общем все работает.
> Работы в портфолио
Разобрался наконец с работами в портфолио.
Я бы описал это как детский страх, который ты побеждаешь во взрослой жизни и понимаешь "и вот этого я боялся?".
Все оказалось очень простым. Сделал картинку на 100%. Удалил полностью кучу лишних строк с ее изменениями.
Оставил только изменение размера <a>, сократив 6 до 4 строк. Теперь все смотрится лаконично.
>Надо разобраться с такими проблемами:
>- CSS спрайты (чтобы увидеть что ты их понял и умеешь делать): спрайт с андроидом, спрайт с соц иконками, спрайт с телефоном и картой.
>спрайт с соц иконками
Вот здесь я бы даже поспорил и сказал, что сделанное по моей технологии было лучше чем спрайт.
Напомню что было у меня - 1 картинка и наложенные на нее 5 кружочков прозрачных ссылок.
Почему это лучше спрайта? Потому что в спрайте мы прописываем фон-картинку к каждой ссылке. При моем же способе была как и в спрайте 1 картинка, но вот ксс намного короче, т.к. присутствовал только ксс 1 картинки, и ксс ссылок (один на все ссылки). При спрайте же много ксс на каждую ссылку. И если в данном случае где 5 картинок это не сильно заметно, но представим какого-нибудь поехавшего заказчика, который решил повставлять абсолютно все соцсети, штук 20-30. И что лучше, написать 2 строки к картинке и 2 строки к ссылкам или писать 20-30 разных правил к каждой частичке спрайта?
> плейсхолдер конструируется по значению $fields?
Ага.
>И если они совпадают
Где ты там такое увидел? Проверки на совпадение нет. Код подразумевает, что модель абитуриента содержит необходимые поля, пригодные для записи в базу. Если ты заглянешь в класс AbiturientService, то увидишь, что перед передачей в маппер абитуриент пропускается через валидатор, который проверяет наличие значений в необходимых полях и их пригодность для записи в БД.
>извне при создании объекта задается переменная $abiturients->$Fieldname, которая заменяе плейсхолдер?
В метод save маппера передаётся уже готовый объект-абитуриент со всеми необходимыми значениями. Да, значения для подстановки в запрос берутся из этого объекта.
Смысл спрайтов в том, что запрос делается только один раз.
В случае десятков мелких картинок браузер каждый раз будет запрашивать этот ресурс с сервера. Это увеличивает время загрузки.
>ксс
Контр-страйк?
>Смысл спрайтов в том, что запрос делается только один раз.
Ну смысл глаз чтобы ими читать внимательно.
Я же сказал, что изображение у меня тоже одно.
Так в каком из классово методом пост берутся эти значения и заносятся в объект абитуриент? Где у тебя пост и присваивание $abiturien->name и т.п.?
>Смысл спрайтов в том, что запрос делается только один раз.
Байтоёб, возвращайся в 2003, когда кто-то ещё считал количество запросов при заходе на сайт, и костыли свои спрайтовые себе в жопу помести.
я пол-года занимался версткой в ворк-треде, почему этот ебанько считает, что он нитакойкакфсе и имеет право мозолить всем глаза в неподходящим треде? Пусть еще в Руби тред пойдет и пишет там про макеты или в js-тред.
ОП разрешил - я остался. Почитай старые треды.
Я раз в пару дней накатываю одну огромную пасту в одном посте и такой же ответ получаю. А ты уже наблевал тут больше постов чем я.
Что, возбуждает в интернете хамить человеку, который одним пальцем переломил бы тебе хребет в реале? Встает пиписька?
В UserpageController.
Байты посчитай сначала, ебанько.
Хорошая идея.
Ты всем этот вопрос задаёшь?
криво все выезжает, по жопе бы за такое надавал.
> Напомню что было у меня - 1 картинка и наложенные на нее 5 кружочков прозрачных ссылок.
> Почему это лучше спрайта
Это хуже так как ограничивает нас. Например мы не можем средствами CSS увеличить расстояние между кружками, или например перестраивать их как-то. Или например сделать поворот одного кружка (через transform) при наведении.
Да и сложно ли поменять тут на спрайт? надо просто сделать 5 разных background-position , а все остальные свойства будут общими для всех кружков.
> При спрайте же много ксс на каждую ссылку.
Нет, там все стили общие только backgroubd-position надо писать индивидуально для каждой ссылки.
> И что лучше, написать 2 строки к картинке и 2 строки к ссылкам или писать 20-30 разных правил к каждой частичке спрайта?
Когда у тебя 30 кружков может появиться необходимость переносить из на новую строчку при узкой ширине экрана. Что ты будешь делать?
тебя тоже зарепортил, версткопидр.
Твоё поведение умиляет. Нет, я не гей. Вроде бы :3
Кыш отсюда
>>541532
Ты разбираешь код, а ты само задание не смотрел? Там много комментариев и ссылок на разные уроки где все подробно разъясняется.
>>541533
Нет ты
>>541535
Потому что ты полгода учишь то что за 4 недели учится.
Алсо мы изучаем тут разработку веб-приложений. Верстка это часть кода приложения. Что делается в руби треде и еще где-то меня мало интересует.
Алсо я не собираюсь вести 5 тредов по каждой отдельной технологии, делать мне больше нечего.
>>541538
Много ты хребтов переломал, воен диванный?
>>541546
Сначала вопросы должны получить ответы.
Кыш отсюда
>>541532
Ты разбираешь код, а ты само задание не смотрел? Там много комментариев и ссылок на разные уроки где все подробно разъясняется.
>>541533
Нет ты
>>541535
Потому что ты полгода учишь то что за 4 недели учится.
Алсо мы изучаем тут разработку веб-приложений. Верстка это часть кода приложения. Что делается в руби треде и еще где-то меня мало интересует.
Алсо я не собираюсь вести 5 тредов по каждой отдельной технологии, делать мне больше нечего.
>>541538
Много ты хребтов переломал, воен диванный?
>>541546
Сначала вопросы должны получить ответы.
ПИДОРЫ И ОСОБЕННО ВЕРСТКОПИДОРЫ LEAVE
ага
Тихо.
И еще можно ли через апи вконтакте взломать акк?
ебало себе взломай
Гуглил, варианты есть, но не работают.
1. Вебсокеты.
2. Даже не знаю.
>>541769
События чего? Если состояния ответа, то onreadystatechange плюс дополнительные события типа onprogress (для всяких индикаторов прогресса например)
https://learn.javascript.ru/ajax-xmlhttprequest
ОП, проверь пожалуйста.
https://github.com/never3ver/vector
Ты писал
>Не надо хранить ключ массива, храни сам объект-сотрудника в переменной. Объекты ведь копируются по ссылке.
Когда это все было в классе Department:
https://github.com/never3ver/vector/blob/a12c454b3bd4152878a28ae0338ac1554e62b660/Classes/Department.php#L90
то я переделывал и копирование объекта по ссылке работало. Сейчас я всё засунул в Anticrisis, и теперь копирование не работает, получается только с ключом массива.
https://github.com/never3ver/vector/blob/master/Classes/Anticrisis.php#L64
Что я упускаю?
> и теперь копирование не работает
Что значит не работает? выводится ошибка какая-то?
Также ты можешь перед и после кода поставить var_dump и посмотреть что в каких переменных хранится и меняется ли что-нибудь.
> Сейчас я всё засунул в Anticrisis, и теперь копирование не работает, получается только с ключом массива.
Значит ты неправильно перенес или неправильно проверял. Тут не требуется использовать ключ массива, нужно хранить в переменной сам объект и код получится чуть короче и проще.
Ну и по обеим ссылкам код с использованием индекса массива, а где код с хранением в переменной самого объекта?
>Пусть в этом файле страница форума
В хтмле? Покажи мне хоть один реальный пример такого форума.
ON DELETE RESTRICT означает, что ничего не нужно делать при удалении связанной записи
А что прописать, чтобы значение выставлялось в NULL при удалении связанной записи?
>>541792
двач написан не на php, а на перле
>>541786
В настройках php можно выставить, чтобы он обрабатывал и html файлы, будто это php.
SET NULL
Все, сам разобрался, ложная тревога.
И как продолжение вопроса. Код html нужно писать отдельно от php, вставляя в html лишь переменные и всякие специальные конструкции которые разрешены php, а сам код php то есть весь функционал писать в отдельном файле. Но как связать эти два файла причем мне нужно чтобы всегда вызывалась готовая html страница. То есть я должен запрашивать первую_страницу_форума.html. Но где сам код php находится-то?
Но здесь получается мы должны вызывать через template.PHP
именно php а не html
Ты ошибаешься в своих рассуждениях. Ты думаешь что при обращении к серверу путь в URL используется как путь к реально лежащему на диске файлу.
Но это не обязательно так. Можно перенастроить сервер как угодно. В частности, динамические сайты обычно настроены так что любые обращения к несуществующим файлам приводят к запуску основного скрипта index.php. Он анализирует URL (в данном случае извлекает из него номер треда), затем идет в базу, находит в ней все посты относящтиеся к этому треду, затем с помощью шаблона генерирует страницу (не сохраняя на диск) и отдает браузеру.
То есть никаких файлов нет, а страницы генерируются на лету php скриптом на основе данных в базе. Это называется динамический сайт, в противоположность статическому в котором все файлы хранятся на диске и которые может менять только веб-мастер.
>>541799
> ON DELETE RESTRICT означает, что ничего не нужно делать при удалении связанной записи
Нет, это значит что операция удаления записи, у которой есть связанные запрещена. Например ты можешь таким образом запретить удалять из базы пользователя если у него есть хоть один комментарий.
> А что прописать, чтобы значение выставлялось в NULL при удалении связанной записи?
http://denis.in.ua/foreign-keys-in-mysql.htm
>>541815
Обычно в index.php
Если бы ты решал наше задание на файлообменник, ты бы узнал как такое делать. Но до этого задания надо изучить PHP, HTML/CSS, ООП, сделать задание про студентов. Ссылки в ОП посте, если что.
html это не чистый html, а PHP-файл с включниями html. Там оба файла по сути PHP файлы. Вызывать надо разумеется файл-контроллер, а не шаблон, так как иначе в шаблоне будет обращение к несуществующим переменным.
Вот блин, тогда получается что ссылки на все треды типа https://2ch.hk/pr/res/536866.html на самом деле не указывают на файл (так как его нет) а по сути являются уникальными именами для будущей генерируемой страницы? То есть грубо говоря в базе есть ссылка и посты связанные с ней?
В базе нет ссылки, только идентификатор (число) 536866. Зачем хранить ссылку если они различаются только цифрами?
Спасибо, что бы я без вас делал. Может посоветуете литературу по проектированию динамических сайтов
Я тот анон, который макет делает. Смотрю ты курс HTML\CSS начал, ты бы на будущее сохранил мои пасты про макет и ответы ОПа на них. Много полезной инфы на последнее задание бы получил.
>>541863\t
Чеченские боевики захватили этот тред и теперь по новым правилам верстка тут легальна как и была раньше, ньфаг, а тралям смертная казнь.
Открыл задачу про увеличивающийся див, посмотрел его код и узнал как прописывать только нужные действия для transition. Так же 3 задача неплохая, я бы код в разы длиннее сделал.
Решать их не буду, но код решения посмотрю, может чего нового еще узнаю. Спасибо :3
if ($this->isPost() && !empty($token)) {
$values = $_POST;
$values['token'] = $token;
$abiturient->fillFields($values);
$errors = $service->trySave($abiturient);
if (empty($errors)) {
$fmHandler = $this->container->getFlashMessageHandler();
$fmHandler->setFlashMessage('success');
header("Location: {$this->uri}");
exit;
}
Кто "он"? Зачем ты читаешь чужой говнокод, если не можешь написать свой?
$_POST это обыкновенный служебный массив, который php (программа-интерпретатор) формирует из данных, пришедших при запросе методом post.
$y = array('a', 'b', 'c');
$x = $y;
Переменной $x присваиваем значение, хранящееся в переменной $y.
То же самое в $values = $_POST.
И что за "values"? Какой баран дает такие имена переменным?
Да ты сам виноват, что тред скатился в говно. Берешь на себя лидерские обязательства, так следи за ситуацией.
А вообще людям просто скучно, если подобное задевает, то наверное выбрана не та борда.
Это нормально что ты не можешь понять так как ты не делал все предыдущие задания и не пытался писать код сам. Разобраться в чужом коде часто сложнее чем написать свой.
Я хочу предупредить. Ты можешь изучать код сколько хочешь, но если хочешь действительно научиться писать такой же, тебе придется изучить все, что изучают другие перед этим заданием, а также внимательно прочесть примечания к нему.
Если ты просто возьмешь готовое решение и перепишешь его своими словами, единственное чему ты научишься это переписывать код своими словами. Программирование это не конвейер где достаточно посмотреть как делают другие и делать так же.
Я нигде ни разу не читал, что можно методом пост вот так вот в некий класс с массивом $values заносить данные. Что это за паттерн вообще такой? Где он описан?
Да и что ты доебался до меня со своими задачками? Изучать что? Что я не знаю, что есть в твоих задачках? Массивом elseif сторону кубика не смогу найти? функцией for по массиву пройтись не смогу? Калькулятор или регулярку написать? Реально у тебя в задачах нет ничего такого, что я бы не знал.
Мануал читал? http://php.net/manual/ru/reserved.variables.post.php
POST это почти обычный массив и никто не запрещает его скопировать в другую переменную.
При чем тут метод POST?
>>541957
Ну может ты чего-то не знаешь. Тогда решение предыдущих задачек тебе бы помогло. Если ты все знаешь то конечно решать незачем.
Помни что если ты скопируешь код или напишешь по аналогии с готовым то это ничего тебе не даст и ничего не значит. Это лишь докажет что у тебя недостаточно знаний — если бы их было достаточно ты бы написал все с нуля.
Потому что от программиста обычно требуется писать новый код, а не переписывать существующий. Так что навыки можно получить только если пишешь с нуля.
Я хотел лишь донести эту мысль. Разумеется, что решать и что изучать это уже твое дело. Мы никому не ставим сроки и не навязываем план обучения. Кто как хочет тот так и учится.
Данные из поста принять, например.
>>541950
$_POST это обыкновенный массив, переменная.
В строке $values = $_POST в переменную с замечательным названием $values приходит значение, которое хранится в переменной $_POST, что-то вроде array('name'=>'Вася', 'password'=>'qwerty').
Массив $_POST, как и $_GET и прочие глобальные создается на основе пользовательских данных. (Глобальными они называются потому что доступны из любой области видимости)
У тебя на странице есть форма с полями-инпутами 'name' и 'password'.
<form method="POST" action="index.php">
<input type="text" name="name">
<input type="text" name="password">
<input type="submit">
</form>
При отправке формы запустится index.php, внутри которого будет доступен служебный массив $_POST, который будет выглядеть следующим образом:
array('name'=>'имя которое ввел пользователь', 'password' => 'пароль').
Хотя вообще это уебанство, ведь если форм на странице несколько, получится бардак, нужно давать имена инпутам иначе, но не буду писать чтобы не перегружать.
Читай о глобальных массивах
http://on-line-teaching.com/php/global.arrays.htm
Как бы ты сделал, если часть данных берётся из кук (какой-нибудь идентификатор например), часть из $_POST и их вместе надо перегнать в маппер для записи/обновления в БД? Дописывать данные в $_POST как-то неправильно.
Я мимопроходил и скажу что маппер не работает с массивами потому данные ни из POST ни из кук вы туда передать все равно не можете. Передать в маппер надо объект-модель.
Создал бы объект, у которого в одно поле положу $_COOKIE['id'], а в другое данные из $_POST. А этот объект передал бы в метод маппера.
$model = new Model($_COOKIE['id'], $_POST['formName']);
$mapper = new Mapper($connection);
$mapper->save($model);
Данные из массивов кук или постов мы присваиваем, а не перезаписываем.
Ты понимаешь, что происходит, когда $a = $b? Слева название переменной, а справа ЗНАЧЕНИЕ. Значение переменной $b копируется в переменную $a.
>Передать в маппер надо объект-модель.
Ну в том коде так и делается. Объект-модель создаётся на основе собранного массива и передаётся в маппер.
>Значение переменной $b копируется в переменную $a.
Ну так это и нужно. Потом добавляется значение из кук. С помощью полученного массива заполняем модель.
Принципиальной разницы между этим и твоим примером нет. Модели совсем не обязательно в данном случае знать откуда что пришло, её поведение от этого не зависит.
в массив, да мало ли что там еще с этим методом пост может прийти, чтобы вот прямо так в array заносить..
Любой, кто стремится учиться, достоин некоторого уважения.
Помню в морровинде встретил нпс, крестьянин в гильдии магов Альд'руна, кажется.
"Я здесь учусь, в школе. Я хочу научиться читать."
Это было так мило.
Я подумал над твоими замечаниями и у меня появились вопросы.
>> У них должно быть свое представление о мире. Понимаю что для изучения программирования такой подход не очень подходит, но пусть будет все реалистично. Это же не очень критично будет?
>Можно, но тогда тебе придется сделать класс «ПредставлениеОМире», например WorldView, который будет служить как бы окном в World, у которого будут свойства координаты и радиус зрения, координаты придется обновлять каждый ход. У тебя будет один мир World, и у каждого животного отдельный объект WorldView. WorldView будет при вызове метода «получить всех видимых дивотных» например вызывать World и фильтровать полученный список животных по расстоянию.
>
>Тебе оно нужно, лишний класс и необходимость постоянно обновлять координаты в нем? По моему проще встроить это ограничение радиуса зрения в World и просто передавать его в функции.
>
>Заметь что в моем подходе информация о мире по прежнему хранится в однм-единственном месте — в World. Здесь нет дублирования информации и вызываемых этим проблем (необходимость обновлять все копии данных).
Но у меня же почти тоже самое получается, только метод находиться не в World а в Animal. Почему для представления мира нужно делать отдельный класс? Ведь нужно всего лишь одно свойство $map, которое можно просто обрезать и вернуть животному. У каждого из нас есть целый мир! Или ты не согласен, няша?
>И еще у меня такой вопрос: почему ты выбираешь юолее неудобные способы хранения вместо более простых? Например World может хранить список животных в обычном одномерном массиве.
Мне нравится такой подход, но мне не нравится, что при определении обзора отдельного животного придется обращаться к другим животным чтобы узнать их координату. Мне кажется так не бывает.
foreach ($map as $value) {
if (__$value->x__ ...)
>Приведи свои аргументы в пользу этого списка тогда.
Ну, так мы имеем самостоятельную карту которая изначально содержит все координаты с которыми можно потом легко работать, например можно определить обзор и содержащих в этом обзоре животных не обратившись к ним ведь это получается, все равно что, забраться в их мозг и достать информацию от туда.
>> Ну суть этого метода заключается в том, что животное может сгенерировать координату которая выходит за пределы карты. Этот метод всего лишь не дает им выйти за пределы карты.
>Суть может быть и в этом, но метод написан неправильно, он не ограничивает передвижение:
>
>> $to['y'] = $to['y'] - ($to['y'] - $this->m);
>Эта строка сохраняет в $to['y'] значение $this->m (это видно если раскрыть скобки) которое очевидно находится за предалами карты.
>
>> Так же я думал еще, с помощью этого метода сделать такую фичу: если животное пытается выйти за пределы карты, то оно ударяется об стенку, получает сотрясение и пропускает один ход о_х
>Неверный подход. Если ты сгенерировал координаты за пределами карты значит в программе ошибка и лучше как можно раньше завершить программу, напрмер выбросив исключение, а не пытаться скрыть факт ошибки. Ведь скрывая его, ты лишь затрудняешь себе поиск причин этой ошибки.
>Если ты сгенерировал координаты за пределами карты значит в программе ошибка
Так бывает. У меня было кот который разгонялся и не успевал затормозить на линолеуме, и ударялся в стену.
Понимаю что попытка сделать все реалистично намного усложняет код, но хочется сделать какое-то подобие ИИ. У тебя, случайно, не складывается ощущение, что я больше чепухой занимаюсь?
Я подумал над твоими замечаниями и у меня появились вопросы.
>> У них должно быть свое представление о мире. Понимаю что для изучения программирования такой подход не очень подходит, но пусть будет все реалистично. Это же не очень критично будет?
>Можно, но тогда тебе придется сделать класс «ПредставлениеОМире», например WorldView, который будет служить как бы окном в World, у которого будут свойства координаты и радиус зрения, координаты придется обновлять каждый ход. У тебя будет один мир World, и у каждого животного отдельный объект WorldView. WorldView будет при вызове метода «получить всех видимых дивотных» например вызывать World и фильтровать полученный список животных по расстоянию.
>
>Тебе оно нужно, лишний класс и необходимость постоянно обновлять координаты в нем? По моему проще встроить это ограничение радиуса зрения в World и просто передавать его в функции.
>
>Заметь что в моем подходе информация о мире по прежнему хранится в однм-единственном месте — в World. Здесь нет дублирования информации и вызываемых этим проблем (необходимость обновлять все копии данных).
Но у меня же почти тоже самое получается, только метод находиться не в World а в Animal. Почему для представления мира нужно делать отдельный класс? Ведь нужно всего лишь одно свойство $map, которое можно просто обрезать и вернуть животному. У каждого из нас есть целый мир! Или ты не согласен, няша?
>И еще у меня такой вопрос: почему ты выбираешь юолее неудобные способы хранения вместо более простых? Например World может хранить список животных в обычном одномерном массиве.
Мне нравится такой подход, но мне не нравится, что при определении обзора отдельного животного придется обращаться к другим животным чтобы узнать их координату. Мне кажется так не бывает.
foreach ($map as $value) {
if (__$value->x__ ...)
>Приведи свои аргументы в пользу этого списка тогда.
Ну, так мы имеем самостоятельную карту которая изначально содержит все координаты с которыми можно потом легко работать, например можно определить обзор и содержащих в этом обзоре животных не обратившись к ним ведь это получается, все равно что, забраться в их мозг и достать информацию от туда.
>> Ну суть этого метода заключается в том, что животное может сгенерировать координату которая выходит за пределы карты. Этот метод всего лишь не дает им выйти за пределы карты.
>Суть может быть и в этом, но метод написан неправильно, он не ограничивает передвижение:
>
>> $to['y'] = $to['y'] - ($to['y'] - $this->m);
>Эта строка сохраняет в $to['y'] значение $this->m (это видно если раскрыть скобки) которое очевидно находится за предалами карты.
>
>> Так же я думал еще, с помощью этого метода сделать такую фичу: если животное пытается выйти за пределы карты, то оно ударяется об стенку, получает сотрясение и пропускает один ход о_х
>Неверный подход. Если ты сгенерировал координаты за пределами карты значит в программе ошибка и лучше как можно раньше завершить программу, напрмер выбросив исключение, а не пытаться скрыть факт ошибки. Ведь скрывая его, ты лишь затрудняешь себе поиск причин этой ошибки.
>Если ты сгенерировал координаты за пределами карты значит в программе ошибка
Так бывает. У меня было кот который разгонялся и не успевал затормозить на линолеуме, и ударялся в стену.
Понимаю что попытка сделать все реалистично намного усложняет код, но хочется сделать какое-то подобие ИИ. У тебя, случайно, не складывается ощущение, что я больше чепухой занимаюсь?
Аноны, я просто предупрежу:
1) тщательно обговаривайте все условия и фичи до начала работы
2) помните что аноним с двача может легко взять сделанную работу и не заплатить
forphp1@gmail.com
1) Сделал, но задание не очень четко прописано. Нужно ли ограничивать высоту, нужно ли юзать overflow со значением hidden. Вот https://jsfiddle.net/y27jxv2g/1/
2) Опять не ясно
>Задание 3
>из тегов можно использовать только <em>
А вкладывать em в em можно? Не пойму как мне выделить сердечко красным. Сами символы в jsfiddle отличаются(сердечко не такое, жирное тоже не подходит, кавычки больше), вот как выглядит сейчас https://jsfiddle.net/77fjzq38/
Надо ли увеличивать сердечко и уменьшить кавычки? Или задание заключается в том чтобы посмотреть как работают html entities, и догадаться как выделить сердечко?
Ну так он же тоже живой человек наверное, придет да ответит, учи пока что-нибудь другое. Я вот английский учу в перерывах между ответами.
nu tak norm
мы тута
>ты можешь таким образом запретить удалять из базы пользователя если у него есть хоть один комментарий.
Это понял, но почему я не могу очистить таблицу, если в ней нет записей с помощью truncate table? Даже пустую не получается, создаю две пустые таблицы parent и child, у child ключ на parent, пытаюсь truncate table parent, говорит Cannot truncate a table referenced in a foreign key constraint
Насколько я понимаю, это происходит от того, что при truncate таблица фактически удаляется и создается заново, поэтому ломается индекс ключа?
update
Уже нагуглил команду foreign_key_checks = 0; (только не забыть потом выставить обратно в true, когда завершим операции)
Масахиро Томито даже написал багрепорт https://bugs.mysql.com/bug.php?id=58788
Японцу верю, это же не индус какой-нибудь.
Впрочем можно еще вместо truncate table использовать delete from в связке с alter table tbl_name auto_increment = 1, чтобы сбросить счетчик.
ай эм вери велл
Я работу нашел, копаюсь каждый день в говнокоде от разных васянов. Чувствую, как тупею.
Я подозреваю, разработчики просто поленились писать код, который тщательно проверит все связи. Потому они просто запретили делать TRUNCATE на таблицах со связами.
Можно еще попробовать DELETE FROM table но так как порядок удаления тут непредсказуем, то она вполне может тоже запнуться на какой-нибудь записи.
Вообще, есть 2 подхода к проверке связей при удалении/изменении:
1) проверять при выполнении каждого запроса (или даже при модификации отдельной записи), так что ни один запрос не может нарушить связи между записями
2) проверять только при коммите транзакции. А в ее процессе связи могут нарушаться.
В MySQL используется подход 1, потому мы и не можем удалить все данные в таблице, замкнутой на себя.
Если тиы подключаешь какую-то систему то обычно у ней есть документация, ее и читай. Или ты свой банк открываешь?
>>542213
> Нужно ли ограничивать высоту, нужно ли юзать overflow со значением hidden.
Но overflow hidden не ограничивает высоту. overflow лишь определяет что делать с текстом и содержимым, не влезающим в блок: вывести или обрезать.
Высоту ограничивают и задают свойства height/max-height.
задание сделано верно, только для box-sizing надо писать вендорные префиксы -moz, -webkit. Ну или не использовать его тут.
> А вкладывать em в em можно?
Можно но не нужно.
> Не пойму как мне выделить сердечко красным
Выделить его каким-нибудь тегом и прописать ему в css свойство color
>вот как выглядит сейчас
Непонятно зачем заключать весь текст в em, что нам это дает?
> Надо ли увеличивать сердечко и уменьшить кавычки?
нет
> Или задание заключается в том чтобы посмотреть как работают html entities, и догадаться как выделить сердечко?
да
Если тиы подключаешь какую-то систему то обычно у ней есть документация, ее и читай. Или ты свой банк открываешь?
>>542213
> Нужно ли ограничивать высоту, нужно ли юзать overflow со значением hidden.
Но overflow hidden не ограничивает высоту. overflow лишь определяет что делать с текстом и содержимым, не влезающим в блок: вывести или обрезать.
Высоту ограничивают и задают свойства height/max-height.
задание сделано верно, только для box-sizing надо писать вендорные префиксы -moz, -webkit. Ну или не использовать его тут.
> А вкладывать em в em можно?
Можно но не нужно.
> Не пойму как мне выделить сердечко красным
Выделить его каким-нибудь тегом и прописать ему в css свойство color
>вот как выглядит сейчас
Непонятно зачем заключать весь текст в em, что нам это дает?
> Надо ли увеличивать сердечко и уменьшить кавычки?
нет
> Или задание заключается в том чтобы посмотреть как работают html entities, и догадаться как выделить сердечко?
да
Также, не жди меня, делай другие задачи.
>>542121
код лучше бы постить на ideone, так как там виден и результат выполнения.
По задаче:
> for ($i = 0; $i < $length; $i++) {
Тут лучше использовать foreach, он специально сделан для перебора массивов. И не придется писать везду $text[$i]
> function makeFirstLetterUppercase($text) {
По задумке эта функция должна была работать только с одним предложением, а у тебя они еще точки ставит, то есть то что делает функция не соответствует названию. Я бы тогда назвал ее например normalizeSentences или как-то так.
> "/[\\s]+,|,[\\s]+|([,])/u"
Эта регулярка слишком сложная да еще и не работает вот в этом случае: http://ideone.com/wsvpEt
Ее надо упростить, например сделав такое выражение:
любое число пробелов, запятая, любое число пробелов
>>542144
Тут я вижу 2 цикла, и ты разбиваешь текст на предложения 2 раза. Я думаю, лучше делать это 1 раз.
Также, не используй одну переменную для разных целей:
> $text[$i] = preg_split("/[\\s]|[,]|[;]/u", $text[$i], 0, PREG_SPLIT_NO_EMPTY);
> $text[$i] = implode(" ", array_reverse($text[$i])) . ".";
Тут ты в 1 переменной хранишь и предложение в виде строки, и в виде массива слов. Для массива слов надо было сделать отдельную переменную.
Также, не жди меня, делай другие задачи.
>>542121
код лучше бы постить на ideone, так как там виден и результат выполнения.
По задаче:
> for ($i = 0; $i < $length; $i++) {
Тут лучше использовать foreach, он специально сделан для перебора массивов. И не придется писать везду $text[$i]
> function makeFirstLetterUppercase($text) {
По задумке эта функция должна была работать только с одним предложением, а у тебя они еще точки ставит, то есть то что делает функция не соответствует названию. Я бы тогда назвал ее например normalizeSentences или как-то так.
> "/[\\s]+,|,[\\s]+|([,])/u"
Эта регулярка слишком сложная да еще и не работает вот в этом случае: http://ideone.com/wsvpEt
Ее надо упростить, например сделав такое выражение:
любое число пробелов, запятая, любое число пробелов
>>542144
Тут я вижу 2 цикла, и ты разбиваешь текст на предложения 2 раза. Я думаю, лучше делать это 1 раз.
Также, не используй одну переменную для разных целей:
> $text[$i] = preg_split("/[\\s]|[,]|[;]/u", $text[$i], 0, PREG_SPLIT_NO_EMPTY);
> $text[$i] = implode(" ", array_reverse($text[$i])) . ".";
Тут ты в 1 переменной хранишь и предложение в виде строки, и в виде массива слов. Для массива слов надо было сделать отдельную переменную.
Для начала, я тебе хочу рассказать про такую штуку, как инкапсуляция. У этого слова есть разные определения, в том числе такие что ничего не понять, потому объясню простыми словами.
Суть инкапсуляции в том, что класс скрывает (инкапслирует) в себе логику работы с данными, а наружу выставляет методы. Пользователю этих методов не важно, как класс устроен внутри, как он хранит данные, ему достаточно вызвать нужный метод чтобы получить результат.
Это упрощает понимание кода: тебе не надо читать и разбирать код класса, достаточно прочитать название метода (и может быть комментарий к нему).
В твоем случае, мы можем инкапсулировать список животных внутри класса World. В этом случае другим классам не надо знать, как он там хранится, они просто вызывают методы вроде «найти всех кошек вокруг определенной точки» или «проверить можно ли сходить на клеточку x, y». Даже если мы поменяем способ хранения животных, нам придется править только один класс с World, все остальные останутся неизменными. Так инкапсуляция упрощает твою жизнь.
Инкапсуляция это хорошо. Так как весь код, который занимается одной задачей, оказывается заключен внутри одного класса. Противоположный случай это когда код (или знание о его внутреннем устройстве) вылезает из класса и размазывается по всей программе.
Так вот, когда ты выносишь список животных из класса World и делаешь так, что мышка допустим сама копается в каком-то массиве невнятного вида, ты как раз нарушаешь принцип инкапсуляции. Ты выносишь код работы с картой из класса World и размазываешь его по всему приложению. А ООП как раз был придуман чтобы каждый класс занимался своим делом.
> Почему для представления мира нужно делать отдельный класс?
Почему нет? Потому что это отдельная сущность:
- у мира есть свойства (размеры, список находящихся в нем животных)
- у мира есть методы (получить список животных в определенном районе, проверить можно ли ходить на данную клетку)
Эти методы и свойства должны где-то располагаться. Логично поместить их в отдельный класс.
> У каждого из нас есть целый мир!
Ну так дай каждому животному ссылку на общий объект World.
Делать свой мир для каждого можно, я не против, но считаю это лишним усложнением. Но ты можешь это сделать — сделай класс WorldView (представление о мире в голове животного) и передай каждому животному свой экземпляр. WorldView будет прослойкой между животным и общим классом World.
Почему класс WorldView? Потому что у класса есть методы, а вот передавать туда-сюда массивы сложной структуры это верный путь к усложнению кода и нарушению инкапсуляции.
Заметь что я все равно предлагаю чтобы сам World был в одном экземпляре. Почему? Потому, что если у нас будет 20 животных и 20 списков у каждого в голове, мы замучаемся их поддерживать и обновлять.
Я конечно против навязывания какой-то точки зрения. Если ты хочешь сделать каждому животному свой мир, почему бы не попробовать? Сделай, посмотрим код.
Касательно того, как хранить данные. Я считаю хранить плоский массив животных проще чем двухмерный, так как его например можно перебрать всего 1 циклом. Также, в 2 мерном массиве тебе надо перемещать животных при перемещении, это усложняет код, а в 1-мерном не нужно.
> но мне не нравится, что при определении обзора отдельного животного придется обращаться к другим животным чтобы узнать их координату. Мне кажется так не бывает.
Обзором должен заниматься класс World который хранит список животных. Логично что если он хранит список животных, то он же и отвечает на вопросы «кто находится в этой области карты».
> У меня было кот который разгонялся и не успевал затормозить на линолеуме, и ударялся в стену.
Вот если ты сделаешь на карте скользкие места и будешь рассчитывать как заносит кота при беге, тогда можно сделать и стену. Но в нашем случае поверхность не скользкая, котов не заносит и вылететь за пределы карты они не могут — они просто не должны рассматривать такие варианты ходов.
> Понимаю что попытка сделать все реалистично намного усложняет код, но хочется сделать какое-то подобие ИИ. У тебя, случайно, не складывается ощущение, что я больше чепухой занимаюсь?
Нет, ты просто вносишь в модель (модель мира с кошками и мышками) лишние детали, которые не влияют на результат, но усложняют код. Будет ли список животных храниться в одном месте или в голове каждого животного — это не влияет на результат программы, а просто делает код сложнее.
Потому надо отбрасывать ненужные детали. Если мы рассчитываем орбиту спутника в космосе, нам неважно какой он формы (и даже какой он массы) — важна только его начальная скорость.
Мы разбиваем код на классы не для реалистичности. Мы делаем это для уменьшения его сложности, чтобы его написание и поддержка занимали меньше времени, чтобы он был понятнее и труднее было допустить ошибку.
Для начала, я тебе хочу рассказать про такую штуку, как инкапсуляция. У этого слова есть разные определения, в том числе такие что ничего не понять, потому объясню простыми словами.
Суть инкапсуляции в том, что класс скрывает (инкапслирует) в себе логику работы с данными, а наружу выставляет методы. Пользователю этих методов не важно, как класс устроен внутри, как он хранит данные, ему достаточно вызвать нужный метод чтобы получить результат.
Это упрощает понимание кода: тебе не надо читать и разбирать код класса, достаточно прочитать название метода (и может быть комментарий к нему).
В твоем случае, мы можем инкапсулировать список животных внутри класса World. В этом случае другим классам не надо знать, как он там хранится, они просто вызывают методы вроде «найти всех кошек вокруг определенной точки» или «проверить можно ли сходить на клеточку x, y». Даже если мы поменяем способ хранения животных, нам придется править только один класс с World, все остальные останутся неизменными. Так инкапсуляция упрощает твою жизнь.
Инкапсуляция это хорошо. Так как весь код, который занимается одной задачей, оказывается заключен внутри одного класса. Противоположный случай это когда код (или знание о его внутреннем устройстве) вылезает из класса и размазывается по всей программе.
Так вот, когда ты выносишь список животных из класса World и делаешь так, что мышка допустим сама копается в каком-то массиве невнятного вида, ты как раз нарушаешь принцип инкапсуляции. Ты выносишь код работы с картой из класса World и размазываешь его по всему приложению. А ООП как раз был придуман чтобы каждый класс занимался своим делом.
> Почему для представления мира нужно делать отдельный класс?
Почему нет? Потому что это отдельная сущность:
- у мира есть свойства (размеры, список находящихся в нем животных)
- у мира есть методы (получить список животных в определенном районе, проверить можно ли ходить на данную клетку)
Эти методы и свойства должны где-то располагаться. Логично поместить их в отдельный класс.
> У каждого из нас есть целый мир!
Ну так дай каждому животному ссылку на общий объект World.
Делать свой мир для каждого можно, я не против, но считаю это лишним усложнением. Но ты можешь это сделать — сделай класс WorldView (представление о мире в голове животного) и передай каждому животному свой экземпляр. WorldView будет прослойкой между животным и общим классом World.
Почему класс WorldView? Потому что у класса есть методы, а вот передавать туда-сюда массивы сложной структуры это верный путь к усложнению кода и нарушению инкапсуляции.
Заметь что я все равно предлагаю чтобы сам World был в одном экземпляре. Почему? Потому, что если у нас будет 20 животных и 20 списков у каждого в голове, мы замучаемся их поддерживать и обновлять.
Я конечно против навязывания какой-то точки зрения. Если ты хочешь сделать каждому животному свой мир, почему бы не попробовать? Сделай, посмотрим код.
Касательно того, как хранить данные. Я считаю хранить плоский массив животных проще чем двухмерный, так как его например можно перебрать всего 1 циклом. Также, в 2 мерном массиве тебе надо перемещать животных при перемещении, это усложняет код, а в 1-мерном не нужно.
> но мне не нравится, что при определении обзора отдельного животного придется обращаться к другим животным чтобы узнать их координату. Мне кажется так не бывает.
Обзором должен заниматься класс World который хранит список животных. Логично что если он хранит список животных, то он же и отвечает на вопросы «кто находится в этой области карты».
> У меня было кот который разгонялся и не успевал затормозить на линолеуме, и ударялся в стену.
Вот если ты сделаешь на карте скользкие места и будешь рассчитывать как заносит кота при беге, тогда можно сделать и стену. Но в нашем случае поверхность не скользкая, котов не заносит и вылететь за пределы карты они не могут — они просто не должны рассматривать такие варианты ходов.
> Понимаю что попытка сделать все реалистично намного усложняет код, но хочется сделать какое-то подобие ИИ. У тебя, случайно, не складывается ощущение, что я больше чепухой занимаюсь?
Нет, ты просто вносишь в модель (модель мира с кошками и мышками) лишние детали, которые не влияют на результат, но усложняют код. Будет ли список животных храниться в одном месте или в голове каждого животного — это не влияет на результат программы, а просто делает код сложнее.
Потому надо отбрасывать ненужные детали. Если мы рассчитываем орбиту спутника в космосе, нам неважно какой он формы (и даже какой он массы) — важна только его начальная скорость.
Мы разбиваем код на классы не для реалистичности. Мы делаем это для уменьшения его сложности, чтобы его написание и поддержка занимали меньше времени, чтобы он был понятнее и труднее было допустить ошибку.
Так метод fillFields у объекта возьмет из массива $values только нужные поля. И он по моему применяет к ним strval() то есть преобразует любые данные в строку (а в POST могут содержаться только строки либо массивы).
>>541974
Насколько я знаю, распределенной сеть должна была быть чтобы сохранять связность при нанесении например ядерного удара. Если бы все коммуникации проходили через центральную точку, любые проблемы на ней нарушили бы работу сети. Но я не знаю, правда это или легенда.
>>541861
А зачем? На сайтах обычно есть защита от автоматических регистраций, а ее обход в нашем треде все равно не обсуждается.
Понимаю твои страдания. Сам не смог ничего найти пошел на khanacademy по совету анона. Правда мне с полного дна начинать надо было, там операции с дробями, деление столбиком вот это все.
Основы математики вроде бы называются алгебра.
Вот первая же ссылка: http://www.bymath.net/studyguide/alg/alg_topics.html объясняет про всякие там многочлены. Там конечно кратко, но зато по делу.
Задачи на алгебру ты можешь найти в ЕГЭ по математике, там и уравнения, и многочлены.
Если что, я могу пояснить непонятные места.
Вот, может быть тебе поможет список разделов математики: https://ru.wikipedia.org/wiki/%D0%A0%D0%B0%D0%B7%D0%B4%D0%B5%D0%BB%D1%8B_%D0%BC%D0%B0%D1%82%D0%B5%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B8#.D0.9C.D0.B0.D1.82.D0.B5.D0.BC.D0.B0.D1.82.D0.B8.D0.BA.D0.B0_.D0.BA.D0.B0.D0.BA_.D1.83.D1.87.D0.B5.D0.B1.D0.BD.D0.B0.D1.8F_.D0.B4.D0.B8.D1.81.D1.86.D0.B8.D0.BF.D0.BB.D0.B8.D0.BD.D0.B0
Глядя на него, ты можешь определить в каком порядке ее изучать.
Ну и так как алгебру изучают в школе, может тебе просто школьный учебник за 8-9 класс скачать?
Ведь мы специально закрываем доступ к свойству, так зачем нужна подобная странная конструкция, чтобы получить этот доступ?
class A
{
private $bar;
public function __set($name, $value)
{
$this->$name = $value;
}
public function __get($name)
{
return $this->$name;
}
}
$a = new A;
$a->bar = 'hello world';
echo $a->bar;
Код плохой так как нет никаких проверок имени поля. И не несет никакого смысла.
Вообще если в языке есть фича это не значит что ты ее должен использовать. Ее используют в разных фреймворках о которых ты пока скорее всего не знаешь. И так как не знаешь то долго получится обяъснять все это.
Я лучше расскажу на примере не этих методов, а на примере метода __call.
Доктрина использует его чтобы автоматически обрабатывать вызовы вроде
$repository->findOneByName($name)
В репозитории конечно такого метода нет, но за счет __call вызов обрабатывается, и доктрина понимает что ты хочешь найти сущность у которой поле name равно переданному значению.
Так как ты не знаком с доктриной то можешь не понять этот пример.
Если ты не уверен что методы нужны так и не используй. Они в основном в фреймворках используются в отдельных случаях и не надо их везде использовать.
В общем, эти магические методы нужны для тех случаев когда тебе надо написать какой-то универсальный код, и ты заранее не знаешь например какие поля будут и потому не можешь их описать в коде явно.
А код примера который ты привел конечно бредовый и не дает объяснения чем это лучше чем public $bar (ничем не лучше, лишняя писанина).
Также их можно использовать для переделки сущестсующего кода.
Например у тебя был класс с публичными свойствами
class X
{
public $a;
public $b;
}
А теперь ты хочешь чтобы обращения к полям делались через методы вроде getA/setA. С помощью магических методов ты можешь это сделать, позволив существующему коду сохранить видимость что поля публичные.
В общем, эти магические методы редко когда нужны обычно используются в фреймворках.
Ну я потому и спросил, что не понимаю смысла в том, чтобы закрывать свойства, а затем давать к ним доступ.
Подозреваю, что смысл этих методов в другом, это как заглушка, чтобы при обращении к несуществующему методу или свойству не выбрасывался notice, exception или что-либо еще.
Я учу первый yii, там это зашито в CComponent, от которого наследуется почти все.
Кажется, там они используются для того чтобы позволить обращаться к закрытым системным свойствам, например Yii::app()->user->id вместо Yii::app()->getUser()->getId().
То есть это работает только в одну сторону, писать естественно туда никто не разрешит, сеттера нет, но через геттер мы получаем закрытое свойство.
public function __get($name)
{
$getter = 'get'.$name;
if (method_exists($this, $getter)) return $this->$getter();
}
Получается, эта штука чисто ради красоты.
Заметил, что если возникает сложность, то помогает выложить ее на письме.
Пока писал вопрос, вроде сам разобрался.
Имей только в виду что авторы Юи те еще велосипедисты и у них там есть много чего нелогичного. В Юи 2 вроде с архитектурой получше стало.
> это как заглушка, чтобы при обращении к несуществующему методу или свойству не выбрасывался notice, exception или что-либо еще.
А смысл в чем? Чтобы при опечатке в коде разработчик об этом не узнал? Нет, они чтобы создавать свойства список которых неизвестен на этапе написания кода и которые потому нельзя обозначать как обычно.
> Я учу первый yii, там это зашито в CComponent, от которого наследуется почти все.
Это в общем плохая идея, наследовать все от одного класса.
> Получается, эта штука чисто ради красоты.
Если там код как у тебя то это плохой код так как при неправильном написании имени свойства ($app->asdadad ) он не выдает никакой ошибки что усложняет отладку.
> писать естественно туда никто не разрешит, сеттера нет
только у PHP есть неприятная особенность, при записи в несуществующее свойство он создает новое свойство, а не выдает ошибку:
class A {}
$a = new A;
$a->asdasda = 1;
echo $a->asdasda; // 1
Подозреваю это из-за того что ООП в PHP делался как попало и для части разработчиков объект это этакий массив с методами. Жаль.
Не, там сеттеры тоже есть.
И даже защита от записи лишних свойств.
https://github.com/yiisoft/yii/blob/1.1.16/framework/base/CComponent.php#L148
Не совсем понимаю, как это работает, но в целом понемногу проясняется.
Второй yii буду учить после первого. Не вижу в вакансиях второго, больше просят первый, потому что на нем уже много написано, а большинство контор занимается чисткой старых проектов, а не написанием новых.
Я мечтаю работать над новым интересным проектом в коллективе энтузиастов, но нужно считаться с реальностью и готовиться около года проработать над унылыми проектами в компании офисных обезьян, чтобы получить чертов стаж, потому что без него никто не возьмет на серьезный проект.
Что поделать, в свободное время буду повышать скиллы и стремиться к лучшему.
Это битовая операция XOR, «исключающее или», то есть числа представляются в двоичном виде и над их битами (ноликами и единичками) делается нужная операция:
https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8#.D0.98.D1.81.D0.BA.D0.BB.D1.8E.D1.87.D0.B0.D1.8E.D1.89.D0.B5.D0.B5_.D0.98.D0.9B.D0.98_.28XOR.29
https://ru.wikipedia.org/wiki/%D0%A1%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%BC%D0%BE%D0%B4%D1%83%D0%BB%D1%8E_2
http://www.lyceum95.ru/inform/binar_ss.htm
кроме ^ есть еще битовые операции | и & (не путай с логическими && и || )
Прочел
https://github.com/yiisoft/yii2/blob/e042a90fd22f2cde8fe898bab5db82c0083bf297/docs/guide-ru/output-data-widgets.md#Отображение-зависимых-моделей
и
https://github.com/yiisoft/yii2/blob/master/docs/guide-ru/db-active-record.md#Доступ-к-связным-данным-
Я знаю, что, скорее всего наговнокодил и буду признателен, если укажешь на ошибки.
На данный момент таблицы таки выводятся, однако есть одна проблема.
Запрос в итоге такой:
SELECT `book`., `author`. FROM `book` LEFT JOIN `author` ON `book`.`author` = `author`.`id` LIMIT 20
И если его просто выполнить в пхпМайАдмин, например, то получится пикрелейтед, всё правильно.
Но если отобразить его через гридвью то почему-то выводит так как на втором пикрелейтед, то есть, почему-то только уникальные значения столбца authorName. Может подскажешь где я что не так сделал?
Ещё хотел спросить не зашквар ли делать так как я сделал в модели Library:
$query = Book::find()
->addSelect(['book.','author.']);
Потому что иначе отображались только строки из таблицы book.
И правильно ли я передаю данные из модели Library? целесообразно ли вообще создавать эту модель?
Ссылка на гитхаб https://github.com/underpantsGnomes/test
Заранее большое спасибо.
Прочел
https://github.com/yiisoft/yii2/blob/e042a90fd22f2cde8fe898bab5db82c0083bf297/docs/guide-ru/output-data-widgets.md#Отображение-зависимых-моделей
и
https://github.com/yiisoft/yii2/blob/master/docs/guide-ru/db-active-record.md#Доступ-к-связным-данным-
Я знаю, что, скорее всего наговнокодил и буду признателен, если укажешь на ошибки.
На данный момент таблицы таки выводятся, однако есть одна проблема.
Запрос в итоге такой:
SELECT `book`., `author`. FROM `book` LEFT JOIN `author` ON `book`.`author` = `author`.`id` LIMIT 20
И если его просто выполнить в пхпМайАдмин, например, то получится пикрелейтед, всё правильно.
Но если отобразить его через гридвью то почему-то выводит так как на втором пикрелейтед, то есть, почему-то только уникальные значения столбца authorName. Может подскажешь где я что не так сделал?
Ещё хотел спросить не зашквар ли делать так как я сделал в модели Library:
$query = Book::find()
->addSelect(['book.','author.']);
Потому что иначе отображались только строки из таблицы book.
И правильно ли я передаю данные из модели Library? целесообразно ли вообще создавать эту модель?
Ссылка на гитхаб https://github.com/underpantsGnomes/test
Заранее большое спасибо.
https://jsfiddle.net/77fjzq38/1/
Задание 4:
https://jsfiddle.net/eyne5m4r/3/
Почему background для body распространился за padding и border?
> Почему background для body распространился за padding и border?
background по умолчанию рисуется и под паддингом и под бордером (переопределяется в новых CSS3 браузерах через background-clip по моему).
А почему вылез за бордер? Потому что фон веб-страницы определяется либо фоном body либо html (в зависимости от того какой установлен). Вот он и вылез.
Как происходит в случае с аяксом установка сессии и кук?
Да, помогай давай
ну, очевидно, что так же, только без перезагрузки страницы, сессии и куки возвращает аякс запрос
То есть юи2 установит куки юзеру при аякс-запросе или это надо делать самому уже на яваскрипте? Если на яваскрипте, то что стоит писать в куки, кэшированный пароль?
понял, в чем была проблема. оказывается, нежелательно иметь два столбца с одинаковым именем, иначе может случится что-то хуевое.
spl_autoload_extensions(".php");
spl_autoload_register();
даже анус твоей мамки, сфотографированный на мой телефон, можно представить в двоичной системе. И так оно и делается.
Поправил, но при попытки заменить цикл на foreach программа не работает, что я делаю не правильно? http://ideone.com/dDmiZ2
http://helloneo.esy.es/
Версия: хз какая.
Git: https://github.com/Integer64/myTestSite.dev/tree/master/CatMouse
Вопрос: Оп проверь. Переделал выбор хода, убрал все лишнее св-ва и методы. Есть еще какие-либо замечания?
Подключаю скрипт из файл через registerScriptFile с содержимым
console.log($("#selected-item"));
$("#selected-item").on("click", function(){
console.log(this);
});
Первый вывод в консоль срабатывает, а вот обработчик события почему-то не вешается.
Не понимаю, что там за фигня с регистрацией событий в yii.
Как написать в html nested dropdown list.
Я новичок, и в программировании донышко. Если вам не сложно, подскажите как или где посмотреть, гит хаб я уже весь просмотреть. Очень нужна помощь.
Выкладывай сюда решения. Оп регулярно проверяет задания, относящиеся к треду.
Само собой больше никто этим заниматься бесплатно не будет.
Ты можешь своими словами и по-русски объяснить, что тебе нужно (по-русски не потому что мы не любим английский, а чтобы проверить что ты сам понимаешь что тебе нужно сделать)?
>>543464
Можно вкидывать его в тред, но прочитай второй пост в треде про форматирование кода сначала. Если кода много, лучше всего выкладывать его на гитхаб, если мало то на ideone или подобный сервис.
Ну и к жесткой критике тогда будь готов.
Отладчиком в браузере посмотреть почему ломается верстка на маленькой ширине экрана и дописать нужные стили.
Я никогда до этого не верстал, подробнее пожалуйста если можно, что за отладчик?
Ctrl + Shift + I в браузере:
http://habrahabr.ru/post/143767/ (старая статья)
https://developer.chrome.com/devtools (англ, подробно)
Если ты никогда не верстал, то тебе надо начать с изучения HTML и CSS и инспектор вряд ли поможет.
Во-первых, у тебя жестко прописаны номиналы и число купюр, причем в куче мест. Это неправильно. У тебя есть массив купюр на входе — из него и бери данные, а не пиши число 500 в 3 разных местах.
Надо чтобы в идеале мы могли поменять массив с номиналами и запасом купюр и все работало.
Во-вторых, тут не нужен цикл. Тут нужен «жадный» алгоритм, который использует деление и работает так:
- допустим надо выдать 17600
- делим 17600 / 5000 = 3 (после округления). Допустим, у нас есть только 2 купюры по 5000, потому берем их, остается сумма 7600
- делим 7600 / 1000 получаем 7
- и так далее, идем от крупных к самым мелким купюрам
- если в конце остался ненулевой остаток, значит сумму выдать мы не можем
Этот «жадный» алгоритм разумеется не сработает на номиналах 5000, 2000, 1000, 500, 200, 100, но ты хотя бы с ним реши для начала.
Также, если твоему алгоритму дать сумму которую он не может набрать, например 20 или 99999000 то он зависнет в цикле навсегда.
Пример: http://ideone.com/cryeXg (ideone ограничивает время выполнения и объем выводимого текста и прибил твою программу за превышение одного из этих лимитов).
Когда ты пишешь цикл, ты всегда должен делать какие-то меры защиты от вечного зацикливания.
Например, здесь ты можешь при достижении момента, когда перебраны все купюры (то есть выдано максимальное число каждой и больше нечего выдавать) писать ошибку и выходить из цикла. Достаточно поставить один else и цикл перестанет быть бесконечным.
Учитывая что тред больше не поднимается по бампу - тут мод вернул 500 постов лимита. Так что нет, не рановато.
Естественно это не ОП,
У него два поста а не один и он подписывает себе напоминания о том что еще проверить.
Я имел ввиду, что ждем когда придет ОП и решит перекатываемся или еще здесь побудем.
Если бы в новом треде уже сидели другие аноны, которые бы задавали вопросы, то перекатились бы, а на то что наш тред в бамплимите ОПу дела вроде бы нету.
Он сам скорее всего попозже тред запилит.
>>543681
>>543668
переделал. http://ideone.com/tXcVb3 решение не полное (нет отладки для исключительных ситуаций и т. д. работает только если вводить заведомо верное число) интересует верно ли я написал функцию, что можно нужно добавить/удалить??? в общем правильно ли я реализовал "жадный алгоритм";
> https://github.com/Integer64/myTestSite.dev/blob/master/CatMouse/classes/Animal.php#L17
> construct($fieldOfVision, $cruisingRange, $name, Field $field)
По моему тут можно все упростить. Во-первых, первые 2 параметра зависят только от вида животного и можно их прописать в самих животных, например сделать в Animal абстрактные методы getFieldOfVision и getruisingRange. Далее, $field можно передавать в момент добавления животного на карту, карта вызывает метод $animal->setField(...);
Таким образом у нас получится более простой конструктор.
> https://github.com/Integer64/myTestSite.dev/blob/master/CatMouse/classes/Animal.php#L59
> $xMin = $location["x"] - $fieldOfVision < 0 ? 0 : $location["x"] - $fieldOfVision;
> $xMax = $location["x"] + $fieldOfVision;
Ограничение по координатам удобнее делать с помощью min()/max(). Также непонятно, почему минимальное значение ограничивается, а максимальное нет.
> return ["x" => $xRange, "y" => $yRange];
По моему тут проще 1-мерный массив с 4 элементами сделать, чем вложенный. Воообще, надо избегать массивов сложной структуры, с ними неудобно работать.
> https://github.com/Integer64/myTestSite.dev/blob/master/CatMouse/classes/Animal.php#L70
> public function lookAround()
Это по моему логичнее перенести в Field, метод получающий животных в определенной области
> $listOfAnimals = clone $this->getField()->getListOfAnimals();
Непонятно зачем тут клонирование
> $this->setSeeAnimals($seeAnimals);
На мой взгляд, это свойство не нужно. Оно устаревает каждый ход и непонятно например актуальное оно сейчас или нет. следовательно, от этого свойства надо избавиться чтобы избежать путаницы, а список животных передавать в обычной переменной.
> namespace Application\CatMouse\models;
Application по моему тут лишнее, смысла оно не добавляет, можно его смело убирать. Обычно в начало неймспейса ставят компанию-разработчика (если она есть) и название программы.
> https://github.com/Integer64/myTestSite.dev/blob/master/CatMouse/models/Cat.php#L20
> if ($this->countTurns > 8) {
> $this->sleep = false;
Тут надо было сделать не так, надо если sleep == true сбрасывать его. А то у тебя цифра 8 аж 3 или 4 раза повторяется, это плохо.
> $listWhereWeCanGo = $this->whereWeCanWalk();
Не стоит назвать одно и то же чуть-чуть по разному, это только вносит путаницу
> https://github.com/Integer64/myTestSite.dev/blob/master/CatMouse/models/Cat.php#L41
> $listWithPoints[] = [$cell, $points];
Лучше $points класть в тот же массив чтобы был одномерный массив, а не городить сложные вложенные структуры
> $c[] = $cell;
> $p[] = $points;
Эти массивы не нужно создавать отдельно, так как их всегда можно получить через array_column()
Вместо запутанной функции multisort лучше наверно использовать usort который позволяет передать любую функцию сортировки. Мне этот вариант нравится тем что не надо иметь несколько параллельных массивов.
> $maxPoints = $listWithPoints[0][1];
Почему не $listWithPoints[0]['points']; ? Это как минимум читабельнее. Также, а что если массив пуст?
> $listWithMaxPoints[] = [$item[0], $item[1]];
Непонятно зачем нам тут число очков если оно одинаковое у всех элементов
> https://github.com/Integer64/myTestSite.dev/blob/master/CatMouse/models/Cat.php#L17
> public function walk()
Тут большая простыня и много общего с логикой движения мыши. Всю общую логику надо вынести в отдельные функции. Ну к примеру сортировка и выбор наилучшего (наилучших ходов) — это однозначно надо вынести отдельно.
> $rand = mt_rand(0, count($listWithMaxPoints) - 1);
Есть array_rand для выбора случайного ключа
> https://github.com/Integer64/myTestSite.dev/blob/master/CatMouse/models/Cat.php#L84
> $field->checkCells($cell);
Название непонятно. Например почему там написано «cells», то есть «клетки», а не «клетка»? И что значит «проверить»? Эта функция должна называться как-то вроде getAnimalAtCell(...)
> https://github.com/Integer64/myTestSite.dev/blob/master/CatMouse/models/Cat.php#L93
> private function appraisal($cell)
нужен тайп хинт, также название переменной неудачное, она должна называться «координаты», а не «ячейка». также, название функции должно начинаться с глагола, сделайЧтоТо(), а у тебя тут существительное
> https://github.com/Integer64/myTestSite.dev/blob/master/CatMouse/models/Cat.php#L113
> $pointsCell += $startPoints - $distance;
Неудачная функция оценки. Так как startPoints = 100 то посчитаем очки для 2 клеток:
- клетка A, в 2 ходах от нее 1 мышь: 98 очков
- клетка B, в 7 ходах от нее 3 мыши: 93 + 93 + 93 = 279 очков
Получается выбирается невыгодный ход.
(в моих рассуждениях допущена ошибка, попробуй ее найти)
> https://github.com/Integer64/myTestSite.dev/blob/master/CatMouse/models/Cat.php#L133
> return false;
Зачем писать return false если ты никогда не проверяешь результат вызова функции? Для кого написан этот return?
Посказка: в таких случаях надо использовать исключения.
> https://github.com/Integer64/myTestSite.dev/blob/master/CatMouse/models/Mouse.php#L19
> $this->setFieldOfVision((int)floor($fieldOfVision / 2));
Это создает путаницу. Почему величина которая назвается одинаково, в одном случае обозначает радиус, а в другом диаметр? Должны быть либо разные названия, либо надо сразу передавать радиус.
Учел ли ты что мышь не ходит по диагонали? Я думаю, генерацию списка ходов надо сделать внутри животного так как у разных животных разные правила хода. Либо же добавить в generateCells опцию, указывающую брать ли клетки по диагонали или нет.
> https://github.com/Integer64/myTestSite.dev/blob/master/CatMouse/models/Field.php#L78
тут идет куча копипасты, в которой легко допустить ошибку. Замени это на 2 цикла от -1 до 1 либо на обход массива с комбинациями -1 и 1.
> https://github.com/Integer64/myTestSite.dev/blob/master/CatMouse/models/Field.php#L102
Способ поиска дублей какой-то сложный. Если переписать код на работу с циклами, то можно просто не добавлять в массив ходов недоступные элементы (а ты в случае если элемент за краями карты, заменяешь его координаты) и дубликатов не появится.
> $arr = array_diff_assoc($value, $checkValue);
Если ты сравниваешь 2 массива с x и y то проще использовать ==: http://php.net/manual/ru/language.operators.array.php
> https://github.com/Integer64/myTestSite.dev/blob/master/CatMouse/models/Game.php#L9
> construct($numberOfTurns, Field $field)
Я думаю что число ходов логично передавать не в конструктор, а в функцию делающую эти ходы. Тогда ее можно например вызвать несколько раз.
> https://github.com/Integer64/myTestSite.dev/blob/master/CatMouse/models/Game.php#L28
> $listOfAnimals = clone $this->field->getListOfAnimals();
зачем тут clone?
> https://github.com/Integer64/myTestSite.dev/blob/master/CatMouse/models/Game.php#L35
> private function printField()
Этот алгоритм проще сделать по-другому: создаем пустой 2-мерный массив. затем обходим массив животных и проставляем в 2-мерный массив их буквы в нужной точек. После чего выводим его. Будет значительно короче, и потребует меньше шагов.
Для создания массива есть array_fill, для вывода echo implode().
Ну и вместо continue 2 надо в такой ситуации ставить break — получается проще.
> https://github.com/Integer64/myTestSite.dev/blob/master/CatMouse/classes/Animal.php#L17
> construct($fieldOfVision, $cruisingRange, $name, Field $field)
По моему тут можно все упростить. Во-первых, первые 2 параметра зависят только от вида животного и можно их прописать в самих животных, например сделать в Animal абстрактные методы getFieldOfVision и getruisingRange. Далее, $field можно передавать в момент добавления животного на карту, карта вызывает метод $animal->setField(...);
Таким образом у нас получится более простой конструктор.
> https://github.com/Integer64/myTestSite.dev/blob/master/CatMouse/classes/Animal.php#L59
> $xMin = $location["x"] - $fieldOfVision < 0 ? 0 : $location["x"] - $fieldOfVision;
> $xMax = $location["x"] + $fieldOfVision;
Ограничение по координатам удобнее делать с помощью min()/max(). Также непонятно, почему минимальное значение ограничивается, а максимальное нет.
> return ["x" => $xRange, "y" => $yRange];
По моему тут проще 1-мерный массив с 4 элементами сделать, чем вложенный. Воообще, надо избегать массивов сложной структуры, с ними неудобно работать.
> https://github.com/Integer64/myTestSite.dev/blob/master/CatMouse/classes/Animal.php#L70
> public function lookAround()
Это по моему логичнее перенести в Field, метод получающий животных в определенной области
> $listOfAnimals = clone $this->getField()->getListOfAnimals();
Непонятно зачем тут клонирование
> $this->setSeeAnimals($seeAnimals);
На мой взгляд, это свойство не нужно. Оно устаревает каждый ход и непонятно например актуальное оно сейчас или нет. следовательно, от этого свойства надо избавиться чтобы избежать путаницы, а список животных передавать в обычной переменной.
> namespace Application\CatMouse\models;
Application по моему тут лишнее, смысла оно не добавляет, можно его смело убирать. Обычно в начало неймспейса ставят компанию-разработчика (если она есть) и название программы.
> https://github.com/Integer64/myTestSite.dev/blob/master/CatMouse/models/Cat.php#L20
> if ($this->countTurns > 8) {
> $this->sleep = false;
Тут надо было сделать не так, надо если sleep == true сбрасывать его. А то у тебя цифра 8 аж 3 или 4 раза повторяется, это плохо.
> $listWhereWeCanGo = $this->whereWeCanWalk();
Не стоит назвать одно и то же чуть-чуть по разному, это только вносит путаницу
> https://github.com/Integer64/myTestSite.dev/blob/master/CatMouse/models/Cat.php#L41
> $listWithPoints[] = [$cell, $points];
Лучше $points класть в тот же массив чтобы был одномерный массив, а не городить сложные вложенные структуры
> $c[] = $cell;
> $p[] = $points;
Эти массивы не нужно создавать отдельно, так как их всегда можно получить через array_column()
Вместо запутанной функции multisort лучше наверно использовать usort который позволяет передать любую функцию сортировки. Мне этот вариант нравится тем что не надо иметь несколько параллельных массивов.
> $maxPoints = $listWithPoints[0][1];
Почему не $listWithPoints[0]['points']; ? Это как минимум читабельнее. Также, а что если массив пуст?
> $listWithMaxPoints[] = [$item[0], $item[1]];
Непонятно зачем нам тут число очков если оно одинаковое у всех элементов
> https://github.com/Integer64/myTestSite.dev/blob/master/CatMouse/models/Cat.php#L17
> public function walk()
Тут большая простыня и много общего с логикой движения мыши. Всю общую логику надо вынести в отдельные функции. Ну к примеру сортировка и выбор наилучшего (наилучших ходов) — это однозначно надо вынести отдельно.
> $rand = mt_rand(0, count($listWithMaxPoints) - 1);
Есть array_rand для выбора случайного ключа
> https://github.com/Integer64/myTestSite.dev/blob/master/CatMouse/models/Cat.php#L84
> $field->checkCells($cell);
Название непонятно. Например почему там написано «cells», то есть «клетки», а не «клетка»? И что значит «проверить»? Эта функция должна называться как-то вроде getAnimalAtCell(...)
> https://github.com/Integer64/myTestSite.dev/blob/master/CatMouse/models/Cat.php#L93
> private function appraisal($cell)
нужен тайп хинт, также название переменной неудачное, она должна называться «координаты», а не «ячейка». также, название функции должно начинаться с глагола, сделайЧтоТо(), а у тебя тут существительное
> https://github.com/Integer64/myTestSite.dev/blob/master/CatMouse/models/Cat.php#L113
> $pointsCell += $startPoints - $distance;
Неудачная функция оценки. Так как startPoints = 100 то посчитаем очки для 2 клеток:
- клетка A, в 2 ходах от нее 1 мышь: 98 очков
- клетка B, в 7 ходах от нее 3 мыши: 93 + 93 + 93 = 279 очков
Получается выбирается невыгодный ход.
(в моих рассуждениях допущена ошибка, попробуй ее найти)
> https://github.com/Integer64/myTestSite.dev/blob/master/CatMouse/models/Cat.php#L133
> return false;
Зачем писать return false если ты никогда не проверяешь результат вызова функции? Для кого написан этот return?
Посказка: в таких случаях надо использовать исключения.
> https://github.com/Integer64/myTestSite.dev/blob/master/CatMouse/models/Mouse.php#L19
> $this->setFieldOfVision((int)floor($fieldOfVision / 2));
Это создает путаницу. Почему величина которая назвается одинаково, в одном случае обозначает радиус, а в другом диаметр? Должны быть либо разные названия, либо надо сразу передавать радиус.
Учел ли ты что мышь не ходит по диагонали? Я думаю, генерацию списка ходов надо сделать внутри животного так как у разных животных разные правила хода. Либо же добавить в generateCells опцию, указывающую брать ли клетки по диагонали или нет.
> https://github.com/Integer64/myTestSite.dev/blob/master/CatMouse/models/Field.php#L78
тут идет куча копипасты, в которой легко допустить ошибку. Замени это на 2 цикла от -1 до 1 либо на обход массива с комбинациями -1 и 1.
> https://github.com/Integer64/myTestSite.dev/blob/master/CatMouse/models/Field.php#L102
Способ поиска дублей какой-то сложный. Если переписать код на работу с циклами, то можно просто не добавлять в массив ходов недоступные элементы (а ты в случае если элемент за краями карты, заменяешь его координаты) и дубликатов не появится.
> $arr = array_diff_assoc($value, $checkValue);
Если ты сравниваешь 2 массива с x и y то проще использовать ==: http://php.net/manual/ru/language.operators.array.php
> https://github.com/Integer64/myTestSite.dev/blob/master/CatMouse/models/Game.php#L9
> construct($numberOfTurns, Field $field)
Я думаю что число ходов логично передавать не в конструктор, а в функцию делающую эти ходы. Тогда ее можно например вызвать несколько раз.
> https://github.com/Integer64/myTestSite.dev/blob/master/CatMouse/models/Game.php#L28
> $listOfAnimals = clone $this->field->getListOfAnimals();
зачем тут clone?
> https://github.com/Integer64/myTestSite.dev/blob/master/CatMouse/models/Game.php#L35
> private function printField()
Этот алгоритм проще сделать по-другому: создаем пустой 2-мерный массив. затем обходим массив животных и проставляем в 2-мерный массив их буквы в нужной точек. После чего выводим его. Будет значительно короче, и потребует меньше шагов.
Для создания массива есть array_fill, для вывода echo implode().
Ну и вместо continue 2 надо в такой ситуации ставить break — получается проще.
Чтобы прописать путь к стилям, надо всего лишь укзать путь от корня сайта:
/mysite/css/style.css
Если у тебя путь mysite может меняеться (сайт можно установить в разные папки), его можно прописать в конфиг. В случае с фреймворком обычно есть функция для его автоматического определения, напримпер в Slim это getRootUri()
>>543227
Любой код, который сюда постят, подвергается критике. Наверно ты и сам это знаешь. Так что немного полюбовавшись, перейдем сразу к коду.
Самая плохая вещь в программировании это копипаста. Любой ценой надо ее избегать. У тебя же код весь одна сплошная копипаста.
Единицы и нули, и столбики для них можно было генерировать скриптом.
Раскрытие столбиков можно сделать CSS-анимацией (которую тоже можно генерировать скриптом чтобы не копипастить 50 похожих CSS правил).
Всю копипасту в явакрипт коде разумеется можно заменить на цикл по массиву, который хранит время и параметры событий.
Ну и наконец, насчет самой картинки, тут бы стоило еще подключить «компьютерный» шрифт с более широкими буквами. В самом фильме, по моему, в качестве символов на экране использовались перевернутые символы японских алфафитов. Вот я нашел какую-то картинку: http://vignette2.wikia.nocookie.net/matrix/images/8/84/Matrix.png/revision/latest?cb=20110307094037 и непонятные символы там это перевернутая хирагана и катакана (это вполне реально воссоздать, а для переворота можно исплоьзовать transform или transform-3d).
>>543185
> но при попытки заменить цикл на foreach программа не работает
Ты меняешь не элемент массива а лишь его копию в переменной value:
> foreach ($text as $value) {
....
> $value = implode(" ", array_reverse($words)) . ".";
$value это не элемент массива, а переменная хранящая копию значения. От того что ты ее меняешь, массив не изменится. Надо либо писать $text[$key]= ... либо создавать новый массив и класть измененные данные в него.
>>543127
Есть такое понятие как кодировка. Это таблица где написано какой символ каким кодом кодируется. Древние кодировки были маленькие и содержали по 128 или 256 символов (так как 1 ячейка памяти хранит 1 байт, а 1 байт может содержать одно из 256 значений):
https://ru.wikipedia.org/wiki/ASCII
https://ru.wikipedia.org/wiki/Windows-1251
256 символов это мало так как ты не можешь исплоьзовать в одном документе символы разных языков. Потому вскоре люди перешли на Юникод, где символов десятки тысяч. Цель Юникода - собрать и пронумеровать все символы всех существовавших алфавитов, так чтобы с его помощью можно было написать любой текст на любом языке мира. Вот таблица кодов Юникода:
http://unicode-table.com/ru/ (заметь что первые 128 символов тут тоже совпадают с древней кодировкой ASCII).
https://ru.wikipedia.org/wiki/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4
Первоначально планировалось что в Юникоде будет не больше 65536 символов (тогда их код занимал бы в памяти ровно 2 байта), но этого не хватило и пришлось расширить диапазон до 4 байт, что позволяет закодировать до 4 млрд символов. Последние добавления в юникод например включают набор смайликов.
Однако тратить на каждый символ по 4 байта, если ты используешь в основном латинницу, расточительно, потому для Юникода появилось несколько способов записи кодов в виде байт:
UTF-32 (1 символ = ровно 4 байта или 32 бита)
UTF-16 (большинство символов занимает 2 байта, но некоторые редкие 4 байта): https://ru.wikipedia.org/wiki/UTF-16
UTF-8 (латинница и ASCII занимают 1 байт, кириллица 2, а самые редкие символы до 6 байт): https://ru.wikipedia.org/wiki/UTF-8
Заметь что кодировка тут одна — юникод, это просто разные способы записывать один и те же коды символов в виде последовательности байт.
> Вообще все знаки и происходящее в компе, систему ввода и вывода можно представить в виде двоичного числа, да?
Можно в виде двоичного, можно в виде обычных десятичных чисел — это не имеет значения, так как это одно и то же число, просто по-разному записанное. Но да, в компьютере вся информация представлена внутри в виде чисел, компьтер это же автоматизированный калькулятор и ни с чем другим, кроме чисел, он работать не умеет. А при выводе на экран например эти числа кодируют яркость свечения точек и мы видим картинку.
>>543057
Молодец, возьми пирожок
Чтобы прописать путь к стилям, надо всего лишь укзать путь от корня сайта:
/mysite/css/style.css
Если у тебя путь mysite может меняеться (сайт можно установить в разные папки), его можно прописать в конфиг. В случае с фреймворком обычно есть функция для его автоматического определения, напримпер в Slim это getRootUri()
>>543227
Любой код, который сюда постят, подвергается критике. Наверно ты и сам это знаешь. Так что немного полюбовавшись, перейдем сразу к коду.
Самая плохая вещь в программировании это копипаста. Любой ценой надо ее избегать. У тебя же код весь одна сплошная копипаста.
Единицы и нули, и столбики для них можно было генерировать скриптом.
Раскрытие столбиков можно сделать CSS-анимацией (которую тоже можно генерировать скриптом чтобы не копипастить 50 похожих CSS правил).
Всю копипасту в явакрипт коде разумеется можно заменить на цикл по массиву, который хранит время и параметры событий.
Ну и наконец, насчет самой картинки, тут бы стоило еще подключить «компьютерный» шрифт с более широкими буквами. В самом фильме, по моему, в качестве символов на экране использовались перевернутые символы японских алфафитов. Вот я нашел какую-то картинку: http://vignette2.wikia.nocookie.net/matrix/images/8/84/Matrix.png/revision/latest?cb=20110307094037 и непонятные символы там это перевернутая хирагана и катакана (это вполне реально воссоздать, а для переворота можно исплоьзовать transform или transform-3d).
>>543185
> но при попытки заменить цикл на foreach программа не работает
Ты меняешь не элемент массива а лишь его копию в переменной value:
> foreach ($text as $value) {
....
> $value = implode(" ", array_reverse($words)) . ".";
$value это не элемент массива, а переменная хранящая копию значения. От того что ты ее меняешь, массив не изменится. Надо либо писать $text[$key]= ... либо создавать новый массив и класть измененные данные в него.
>>543127
Есть такое понятие как кодировка. Это таблица где написано какой символ каким кодом кодируется. Древние кодировки были маленькие и содержали по 128 или 256 символов (так как 1 ячейка памяти хранит 1 байт, а 1 байт может содержать одно из 256 значений):
https://ru.wikipedia.org/wiki/ASCII
https://ru.wikipedia.org/wiki/Windows-1251
256 символов это мало так как ты не можешь исплоьзовать в одном документе символы разных языков. Потому вскоре люди перешли на Юникод, где символов десятки тысяч. Цель Юникода - собрать и пронумеровать все символы всех существовавших алфавитов, так чтобы с его помощью можно было написать любой текст на любом языке мира. Вот таблица кодов Юникода:
http://unicode-table.com/ru/ (заметь что первые 128 символов тут тоже совпадают с древней кодировкой ASCII).
https://ru.wikipedia.org/wiki/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4
Первоначально планировалось что в Юникоде будет не больше 65536 символов (тогда их код занимал бы в памяти ровно 2 байта), но этого не хватило и пришлось расширить диапазон до 4 байт, что позволяет закодировать до 4 млрд символов. Последние добавления в юникод например включают набор смайликов.
Однако тратить на каждый символ по 4 байта, если ты используешь в основном латинницу, расточительно, потому для Юникода появилось несколько способов записи кодов в виде байт:
UTF-32 (1 символ = ровно 4 байта или 32 бита)
UTF-16 (большинство символов занимает 2 байта, но некоторые редкие 4 байта): https://ru.wikipedia.org/wiki/UTF-16
UTF-8 (латинница и ASCII занимают 1 байт, кириллица 2, а самые редкие символы до 6 байт): https://ru.wikipedia.org/wiki/UTF-8
Заметь что кодировка тут одна — юникод, это просто разные способы записывать один и те же коды символов в виде последовательности байт.
> Вообще все знаки и происходящее в компе, систему ввода и вывода можно представить в виде двоичного числа, да?
Можно в виде двоичного, можно в виде обычных десятичных чисел — это не имеет значения, так как это одно и то же число, просто по-разному записанное. Но да, в компьютере вся информация представлена внутри в виде чисел, компьтер это же автоматизированный калькулятор и ни с чем другим, кроме чисел, он работать не умеет. А при выводе на экран например эти числа кодируют яркость свечения точек и мы видим картинку.
>>543057
Молодец, возьми пирожок
Молодец, возьми пирожок
>>542903
Задание 3
В условии сказано что можно использовать в разметке только тег em, а span нельзя
Вместо кодов удобне использовать более понятные мнемоники: & amp; для амперсанда, & lt; и & gt; для скобок, и & rarr; для стрелки вправо. Они описаны например тут: https://ru.wikipedia.org/wiki/%D0%9C%D0%BD%D0%B5%D0%BC%D0%BE%D0%BD%D0%B8%D0%BA%D0%B8_%D0%B2_HTML
А то читать коды как-то тяжеловато.
Задание 4
Один из блоков должен быть прижат к нижнему краю. Также, расстояние между блоками не равно 10px, почитай статью которая упомянута в примечниях к задаче:
> если тебе никак не удается добиться, чтобы расстояние между блоками по горизонтали было ровно 10px, прочти статью: http://css-live.ru/articles/zagadochnye-otstupy-mezhdu-inlajn-blokami.html
>>542901
Ты уже поменял код, но если глянуть в старый код, то я не понимаю что такое Library. Я написал в прошлый раз что 1 класс AR соответствует одной таблице, у тебя 2 таблицы и 3 класса, значит то ли ты не понял что такое ActiveRecord то ли еще что-то.
> И правильно ли я передаю данные из модели Library? целесообразно ли вообще создавать эту модель?
Какой таблице она соответствует? Зачем она вообще нужна? По моему ты не понимаешь что такое ActiveRecord.
> Потому что иначе отображались только строки из таблицы book.
Значит надо выяснить почему а не городить лишние классы.
>>542790
Нет, так что придется почитать документацию. Ну и ты сам-то понимешь, зачем тебе это? Не проще обычные API ключи например использовать?
>>542775
> Я мечтаю работать над новым интересным проектом в коллективе энтузиастов, но нужно считаться с реальностью и готовиться около года проработать над унылыми проектами в компании офисных обезьян,
Ишь ты какой хитрый. Обычно за интересные проекты платят меньше чем за неинтересные, так как на них желающих больше, пример: геймдев.
> Что поделать, в свободное время буду повышать скиллы и стремиться к лучшему.
Здравая мысль.
>>542656
Читай хабр, новости из мира PHP, смотри всякие новые библиотеки и может даже другие языки, делай какие-нибудь небольшие хооби-проекты в свободное время.
>>541978
Ну ок, хорошо, разбирай.
>>541855
> Нужно ли ограничивать высоту,
Нет
> нужно ли юзать overflow со значением hidden
нет
В задании не хватает вендорных префиксов для box-sizing, а так же при большой ширине окна зеленый блок должен центрироваться, а не прижиматься влево (поколдуй с маргинами).
>>541847
Не знаю, это надо фреймворки учить. Можешь для начала в нашем треде изчить ООП и решить задачи про студентов и файлообменники, это даст тебе основы.
Молодец, возьми пирожок
>>542903
Задание 3
В условии сказано что можно использовать в разметке только тег em, а span нельзя
Вместо кодов удобне использовать более понятные мнемоники: & amp; для амперсанда, & lt; и & gt; для скобок, и & rarr; для стрелки вправо. Они описаны например тут: https://ru.wikipedia.org/wiki/%D0%9C%D0%BD%D0%B5%D0%BC%D0%BE%D0%BD%D0%B8%D0%BA%D0%B8_%D0%B2_HTML
А то читать коды как-то тяжеловато.
Задание 4
Один из блоков должен быть прижат к нижнему краю. Также, расстояние между блоками не равно 10px, почитай статью которая упомянута в примечниях к задаче:
> если тебе никак не удается добиться, чтобы расстояние между блоками по горизонтали было ровно 10px, прочти статью: http://css-live.ru/articles/zagadochnye-otstupy-mezhdu-inlajn-blokami.html
>>542901
Ты уже поменял код, но если глянуть в старый код, то я не понимаю что такое Library. Я написал в прошлый раз что 1 класс AR соответствует одной таблице, у тебя 2 таблицы и 3 класса, значит то ли ты не понял что такое ActiveRecord то ли еще что-то.
> И правильно ли я передаю данные из модели Library? целесообразно ли вообще создавать эту модель?
Какой таблице она соответствует? Зачем она вообще нужна? По моему ты не понимаешь что такое ActiveRecord.
> Потому что иначе отображались только строки из таблицы book.
Значит надо выяснить почему а не городить лишние классы.
>>542790
Нет, так что придется почитать документацию. Ну и ты сам-то понимешь, зачем тебе это? Не проще обычные API ключи например использовать?
>>542775
> Я мечтаю работать над новым интересным проектом в коллективе энтузиастов, но нужно считаться с реальностью и готовиться около года проработать над унылыми проектами в компании офисных обезьян,
Ишь ты какой хитрый. Обычно за интересные проекты платят меньше чем за неинтересные, так как на них желающих больше, пример: геймдев.
> Что поделать, в свободное время буду повышать скиллы и стремиться к лучшему.
Здравая мысль.
>>542656
Читай хабр, новости из мира PHP, смотри всякие новые библиотеки и может даже другие языки, делай какие-нибудь небольшие хооби-проекты в свободное время.
>>541978
Ну ок, хорошо, разбирай.
>>541855
> Нужно ли ограничивать высоту,
Нет
> нужно ли юзать overflow со значением hidden
нет
В задании не хватает вендорных префиксов для box-sizing, а так же при большой ширине окна зеленый блок должен центрироваться, а не прижиматься влево (поколдуй с маргинами).
>>541847
Не знаю, это надо фреймворки учить. Можешь для начала в нашем треде изчить ООП и решить задачи про студентов и файлообменники, это даст тебе основы.
> https://github.com/never3ver/vector/blob/master/Classes/Company.php#L11
> $target[$key] = clone $department;
> $clonedDepartment = $target[$key];
Вот этот код не там, где он должен быть. Что если тебе понадобится клонировать департамент где-то еще, ты снова скопипастишь этот цикл клонирования сотрудников?
Надо сделать чтобы было достаточно одной команды clone, а остальное делал сам департамент. Для этого надо определить в нем магический метод __clone() который вызывается при клонировании: http://php.net/manual/ru/language.oop5.cloning.php
Также, надо сделать чтобы компанию можно было склонировать через clone. Это позволит тебе легко создать несколько клонов компании для экспериментов.
> https://github.com/never3ver/vector/blob/master/Classes/Anticrisis.php#L26
> uasort($engineers, array("self","sortForuasort"));
По моему можно просто писать 'self::sortForUASort' вместо массива
> https://github.com/never3ver/vector/blob/master/Classes/Anticrisis.php#L36
> unset($department->employees[$key]);
это неправильно. Ты не должен лезть снаружи во внутреннее устройство департамента. У департамента должен быть метод уволитьСотрудника(сотрудник). Чтобы впредь такого не было, сделай-ка свойство «сотрудники» закрытым от доступа снаружи, то есть private или protected.
Также, почитай мою вдохновляющую пасту про инкапсуляцию: >>542689
> $engineers[$i]->setCheck();
Это в общем тоже неправильно. Почему check это свойство сотрудника? Это не его свойство. Вместо того чтобы помечать их, просто складывай кандидатов на увольнение в отдельный массив.
> if (get_class($employee) == "Analyst") {
Лучше наверно использовать instanceof, хотя оно отреагирует и на наследников класса.
> https://github.com/never3ver/vector/blob/master/Classes/Company.php#L11
> $target[$key] = clone $department;
> $clonedDepartment = $target[$key];
Вот этот код не там, где он должен быть. Что если тебе понадобится клонировать департамент где-то еще, ты снова скопипастишь этот цикл клонирования сотрудников?
Надо сделать чтобы было достаточно одной команды clone, а остальное делал сам департамент. Для этого надо определить в нем магический метод __clone() который вызывается при клонировании: http://php.net/manual/ru/language.oop5.cloning.php
Также, надо сделать чтобы компанию можно было склонировать через clone. Это позволит тебе легко создать несколько клонов компании для экспериментов.
> https://github.com/never3ver/vector/blob/master/Classes/Anticrisis.php#L26
> uasort($engineers, array("self","sortForuasort"));
По моему можно просто писать 'self::sortForUASort' вместо массива
> https://github.com/never3ver/vector/blob/master/Classes/Anticrisis.php#L36
> unset($department->employees[$key]);
это неправильно. Ты не должен лезть снаружи во внутреннее устройство департамента. У департамента должен быть метод уволитьСотрудника(сотрудник). Чтобы впредь такого не было, сделай-ка свойство «сотрудники» закрытым от доступа снаружи, то есть private или protected.
Также, почитай мою вдохновляющую пасту про инкапсуляцию: >>542689
> $engineers[$i]->setCheck();
Это в общем тоже неправильно. Почему check это свойство сотрудника? Это не его свойство. Вместо того чтобы помечать их, просто складывай кандидатов на увольнение в отдельный массив.
> if (get_class($employee) == "Analyst") {
Лучше наверно использовать instanceof, хотя оно отреагирует и на наследников класса.
> //переворачиваем массив,
Лучше сделать сортировку чтобы гарантированно был нужный порядок, выбери одну из функций http://php.net/manual/ru/array.sorting.php
> PHP Notice: Undefined variable: result in /home/52tc2F/prog.php on line 32
Обращаешься к несущестующей переменной, надо исправить
Сам алгоритм верный, добавь только еще проверки на правильность суммы и дай нормальное название функции.
Оп, по поводу
> $listOfAnimals = clone $this->getField()->getListOfAnimals();
Столкнулся с таким эффектом.
Если в for each SplObjectStorage у элемента попытаться получить этот же SplObjectStoroge и попробовать пройти по нему через for each , чтобы найти животных в поле зрения, часть кода просто не выполняется: животные перестают двигать, никаких ошибок не появляется.
С костылем ввиде clone такого эффекта нет.
Могу предположить что я просто перемудрил, и руки у меня не оттуда.
А что если поставить там echo и посмотреть что именно происходит то есть сколько шагов выполняется для каждого цикла?
Надо бы разобраться если это какая-то особенность или баг SplObjectStorage.
Также можно сделать отдельно маленькую тестовую программку и проверить можно ли делать вложенный foreach по тому же SplObjectStorage
Попробуй, но как я помню. Как только создается второй цикл, все что после него не выполняется, или внутри него не выполняется. Надо потестить.
>И при чем тут Юи, тут обычный jQuery, он от фреймворка никак не зависит
Ну как же, я говорю о подключении внешних скриптов, а этим занимается какой-то странный менеджер ресурсов.
В yii скрипт подключается через Yii::app()->clientScript->registerScriptFile.
Суть такова.
Содержимое хелловорлдного скрипта:
console.log($("#selected-item"));
$("#selected-item").on("click", function(){
console.log(this);
});
Первый консоль.лог срабатывает, но при клике на элементе ничего не происходит. Сообщения об ошибке тоже нет.
Сам скрипт успешно подключается, т.е. появляется тэг <script scr="myscript.js"></script> в конце страницы, то есть после элемента, на которое навешивается событие. Так что дело не в том, что элемента не существует на момент срабатывания скрипта.
Ну ладно, я пока зашил скрипт в тело страницы, потом покажу уже на гитхабе, чем сейчас пытаться объяснять на пальцах.
я не понимаю, зачем нам неймспейсы. читал на лурке, что пхп кодеры искренне не понимают неймспейсы из-за require.
> Первый консоль.лог срабатывает
И что он выводит? Анон, из тебя надо клещами все вытягивать.
И на этот вопрос ты не ответил:
> И не выполняешь ли ты скрипт до того как элемент появится на странице?
Посмотри в браузере в коде страницы (Ctrl + U) где расположен скрипт: до или после элемента #selected-item. Если до то логично что он не может найти его так как этот элемент еще не создан.
>>544291
Лурк это развлекательный ресурс и их цель рассмешить читателя, а не обучить. Про реквайры это скорее юмор.
Вот моя паста по теме:
---------
Чтобы разобраться в PSR-4 и пространствах имен, надо понять, почему они появились и какую задачу решают.
Пространства имен решают проблему слишком длинных имен классов. Длинные имена появляются по 2 причинам:
— борьба с конфликтом имен. Представь что Вася и Петя каждый пишет свои библиотеки и оба решают использовать класс с одинаковым названием, например User. Или функцию getUser(). Если мы попробуем подключить в проекте обе этих библиотеки, будет ошибка так как не может быть 2 классов с одинаковыми именами. Чтобы этого избежать, библиотеки приписывают к классам и функциям свое название в начало:
Petya_User
petyaGetUser()
Vasya_User
vasyaGetUser()
Zend_Mail
sfController
Если не приписывать в начало имя библиотеки то конфликт обязательно будет так как в мире тысячи библиотек и в каких-нибудь двух обязательно будут совпадающие названия.
— большие библиотеки и фрейморки состоят из вложенных друг в друга модулей и компонент и имена классов получаются длиными:
Zend_Db_Table_Row_Abstract — это класс фреймворка Zend Framework 1, модуль Db.
sfDatabaseConfigHandler — класс фреймворка Symfony1, модуль Database
В общем, до неймспейсов мы имели длинные имена классов. Длинные имена это плохо, так как они увеличивают длину строк и снижают читаемость.
Неймспейсы решают эту проблему тем что вводят возможность помещать класс (и функции) в неймспейсы:
\Symfony\Routing\Router
\Doctrine\ORM\Mapping\Id
\Petya\User
\Vasya\User
При этом ты можешь как и раньше писать длинное имя класса со всеми неймспейсами, а можешь создать синоним через
use \Symfony\Routing\Router;
и писать просто Router.
По умолчанию, если ты не указываешь неймспейс то твои классы создаются в глобальном неймспейсе.
Сам PHP не требует чтобы имя класса совпадало с именем файла, а неймспейсов с именами папок. Ему без разницы где хранится класс. Но когда ты пишешь автозагрузчик, тебе нужны какие-то правила, как узнать по полному имени класса путь к файлу с ним, чтобы подключить. И желательно чтобы правила были общие, чтобы каждый не придумывал свой велосипед.
Эту проблему (как назвать файл с классом) решает PSR-4. Это договоренность, что мы кладем класс с неймспейсом
MyLibrary\A\B\C\D
в файл
my-library/src/A/B/C/D.php
Если ты придерживаешься этого стандарта, то во-первых, ты молодец, во-вторых ты можешь не писать свой автозагрузчик, а взять любой готовый автозагручик PSR-4 (например встроенный в композер). Единственное, что тебе надо указать — это корневой неймспейс твоего проекта и корневую папку.
То есть если ты укажешь корневой неймспейс MyLibrary, а папку my-library/src то автозагрузчик будет искать файлы в неймспейсе MyLIbrary в этой папке.
Давай повторим еще раз:
— длинные имена классов это неизбежность, так как библиотек тысячи, в них бывает много классов и эти имена должны быть уникальными
— PSR-4 это договоренность о том, как называть и куда класть файлы с классами, чтобы их мог найти автозагрузчик и чтобы все использовали готовый автозагрузчик и не изобретали свой.
Что скажешь? Хорошее решение или эти проблемы можно было решить как-то лучше?
Теперь, зная это, я надеюсь ты без труда сможешь привести свой проект к стандарту PSR-4 и настроить автозагрузку классов через встроенный в композер автозагрузчик. И больше никогда не писать автозагрузчики.
Кстати, до PSR-4 был PSR-0. Он ориентирован на старые проекты, где не было неймспейсов, а имена папок разделялись подчеркиваниями, вот так:
Класс Zend_Db_Table_Row_Abstract
Файл Zend/Db/Table/Row/Abstract.php
PSR-0 устарел и я думаю, не стоит к нему возвращаться. Но композер поддерживает и его тоже.
> Первый консоль.лог срабатывает
И что он выводит? Анон, из тебя надо клещами все вытягивать.
И на этот вопрос ты не ответил:
> И не выполняешь ли ты скрипт до того как элемент появится на странице?
Посмотри в браузере в коде страницы (Ctrl + U) где расположен скрипт: до или после элемента #selected-item. Если до то логично что он не может найти его так как этот элемент еще не создан.
>>544291
Лурк это развлекательный ресурс и их цель рассмешить читателя, а не обучить. Про реквайры это скорее юмор.
Вот моя паста по теме:
---------
Чтобы разобраться в PSR-4 и пространствах имен, надо понять, почему они появились и какую задачу решают.
Пространства имен решают проблему слишком длинных имен классов. Длинные имена появляются по 2 причинам:
— борьба с конфликтом имен. Представь что Вася и Петя каждый пишет свои библиотеки и оба решают использовать класс с одинаковым названием, например User. Или функцию getUser(). Если мы попробуем подключить в проекте обе этих библиотеки, будет ошибка так как не может быть 2 классов с одинаковыми именами. Чтобы этого избежать, библиотеки приписывают к классам и функциям свое название в начало:
Petya_User
petyaGetUser()
Vasya_User
vasyaGetUser()
Zend_Mail
sfController
Если не приписывать в начало имя библиотеки то конфликт обязательно будет так как в мире тысячи библиотек и в каких-нибудь двух обязательно будут совпадающие названия.
— большие библиотеки и фрейморки состоят из вложенных друг в друга модулей и компонент и имена классов получаются длиными:
Zend_Db_Table_Row_Abstract — это класс фреймворка Zend Framework 1, модуль Db.
sfDatabaseConfigHandler — класс фреймворка Symfony1, модуль Database
В общем, до неймспейсов мы имели длинные имена классов. Длинные имена это плохо, так как они увеличивают длину строк и снижают читаемость.
Неймспейсы решают эту проблему тем что вводят возможность помещать класс (и функции) в неймспейсы:
\Symfony\Routing\Router
\Doctrine\ORM\Mapping\Id
\Petya\User
\Vasya\User
При этом ты можешь как и раньше писать длинное имя класса со всеми неймспейсами, а можешь создать синоним через
use \Symfony\Routing\Router;
и писать просто Router.
По умолчанию, если ты не указываешь неймспейс то твои классы создаются в глобальном неймспейсе.
Сам PHP не требует чтобы имя класса совпадало с именем файла, а неймспейсов с именами папок. Ему без разницы где хранится класс. Но когда ты пишешь автозагрузчик, тебе нужны какие-то правила, как узнать по полному имени класса путь к файлу с ним, чтобы подключить. И желательно чтобы правила были общие, чтобы каждый не придумывал свой велосипед.
Эту проблему (как назвать файл с классом) решает PSR-4. Это договоренность, что мы кладем класс с неймспейсом
MyLibrary\A\B\C\D
в файл
my-library/src/A/B/C/D.php
Если ты придерживаешься этого стандарта, то во-первых, ты молодец, во-вторых ты можешь не писать свой автозагрузчик, а взять любой готовый автозагручик PSR-4 (например встроенный в композер). Единственное, что тебе надо указать — это корневой неймспейс твоего проекта и корневую папку.
То есть если ты укажешь корневой неймспейс MyLibrary, а папку my-library/src то автозагрузчик будет искать файлы в неймспейсе MyLIbrary в этой папке.
Давай повторим еще раз:
— длинные имена классов это неизбежность, так как библиотек тысячи, в них бывает много классов и эти имена должны быть уникальными
— PSR-4 это договоренность о том, как называть и куда класть файлы с классами, чтобы их мог найти автозагрузчик и чтобы все использовали готовый автозагрузчик и не изобретали свой.
Что скажешь? Хорошее решение или эти проблемы можно было решить как-то лучше?
Теперь, зная это, я надеюсь ты без труда сможешь привести свой проект к стандарту PSR-4 и настроить автозагрузку классов через встроенный в композер автозагрузчик. И больше никогда не писать автозагрузчики.
Кстати, до PSR-4 был PSR-0. Он ориентирован на старые проекты, где не было неймспейсов, а имена папок разделялись подчеркиваниями, вот так:
Класс Zend_Db_Table_Row_Abstract
Файл Zend/Db/Table/Row/Abstract.php
PSR-0 устарел и я думаю, не стоит к нему возвращаться. Но композер поддерживает и его тоже.
> Первый консоль.лог срабатывает
> И что он выводит?
>console.log($("#selected-item"));
Очевидно что выводит дом-элемент, которому присвоен айди #selected-item. Команда console.log($("#айди")) выводит в консоль тот элемент, который должна вывести, поэтому я написал, что срабатывает, выполняется то, что от него ожидается.
>И на этот вопрос ты не ответил:
> И не выполняешь ли ты скрипт до того как элемент появится на странице?
Третья строка снизу:
>>544173
>Сам скрипт успешно подключается, т.е. появляется тэг <script scr="myscript.js"></script> в конце страницы, то есть после элемента, на которое навешивается событие. Так что дело не в том, что элемента не существует на момент срабатывания скрипта.
Что-то ты последнее время невнимательный, на тебя непохоже.
Забей на вопрос, я пока зашил скрипт в самом шаблоне, потом как допишу страницу покажу гитхаб.
>>541500
> как перевести сайт на хттпС?
Сделать запрос на создание сертификата, сгененрировав ключи, купить сертификат (за деньги), установить на сервере, включить на сервере поддержку https. Подробный план зависит от того какой сервер. Этим должен заниматься системный администратор или человек с хорошим знанием линукса. Если ты используешь хостинг, то у тебя просто может не быть нужных прав.
В интернете легко нагуглить статьи вроде http://habrahabr.ru/post/195808/ но я бы не советовал тебе им следовать. Где гарантия что там все настроено правильно и не оставлен например какой-нибудь уязвимый шифр? Чтобы правильно все настроить, надо как минимум иметь представление что делает каждая настройка и какие шифры и протоколы на сегодняшний день считаются безопасными.
> при отправке/получении данных через айакс как работать с сессиями, если сайт, который получает данные, сам юи не использует?
А при чем тут Юи? Если ты имел в виду что у тебя 2 сайта на разных доменах (1 для авторизации, а другой куда ты шлешь запросы) то ни куки ни сессии работать так просто не будут, так как куки передаются только на тот домен который их выдал (исключение если оба домена это поддомены одного домена и в куках правильно проставлено свойство domain).
Ну и насчет отправки и получения кук, куки посылаются и получаются вместе с аякс-запросами. Правда, если это происходит в ифрейме и домен другой, то может не работать (так называемые third party куки).
> я так понимаю, надо использовать RESTful API, но смутно понимаю, как именно его использовать. Есть ли простой пример приложения с авторизацией?
Вообще-то REST и сессии противоречат друг другу, так как REST это отсуствие хранение данных на сервере между запросами. Что касается авторизации — сделай какой-нибудь токен который выдается клиенту при авторизации и передается при всех запросах. А от сессий конечно придется отказаться.
> есть готовый сайт-одностраничник, к которому я хочу приделать приложение (логин, заказ, статистика). Причём приложение должно работать в том же окне, все действия должны грузиться айаксом.
> Для этой цели я хочу поставить юи, чтобы она работала с авторизацией, БД и прочей бизнес-логикой, а выход возвращала в одностраничник, где уже яваскрипт будет обрабатывать представление.
Зачем эти извращения? Зачем приложение в том же окне на сайте? Какой смысл быть авторизованным в окне внутри другого сайта? Сделай просто отдельную страницу и без всяких там аяксов и не усложняй себе жизнь.
> Помимо этого планируется приложения для андроида, с тем же функционалом, для которого хочу использовать ту же схему.
В андроиде есть WebView который по сути является браузером и в котором можно открыть что угодно. Хотя я не понимаю зачем тогда вообще писать приложение если в андроиде и так есть браузер с которого можно зайти на твой сайт и который скорее всего лучше и удобнее чем приложение.
>>541444
А ты не ной, а изучай что не изучил и повышай свой уровень, ну и параллельно ищи заказы или работу. Под лежачий камень вода не течет.
>>541441
Прежде чем браться за написание скриптов на jQuery, надо изучить JS, DOM, XMLHTTPRequest (и основы HTTP) и тогда таких проблем возникать не будет.
По твоему коду непонятно в чем проблема, вроде данные должны отсылаться на сервер. Открой инспектор (Ctrl + shift +I) в браузере и проверь там что отправляется и приходит в ответ.
Но вообще ты поступил неправильно. Если при приеме на работу ты сказал что знаешь jQUery ты очевидно соврал работодателю. Если ты не изучишь JS, DOM, XMLHTTPRequest (и осноавы HTTP) и jQUery то и дальше с тобой будут происходить такие вещи. Потому рекомендую для начала прочесть learn.javascript.ru от начала и до конца, если ты его еще не прочел, а дальше думаю ты сам сообразишь что читать. По крайней мере будешь знать как отлаживать такие ошибки.
Ну и еще.
> $(".SubGroup option:selected").val();
Можно написать $(".SubGroup").val(); Надо изучать и понимать jQuery.
>>541500
> как перевести сайт на хттпС?
Сделать запрос на создание сертификата, сгененрировав ключи, купить сертификат (за деньги), установить на сервере, включить на сервере поддержку https. Подробный план зависит от того какой сервер. Этим должен заниматься системный администратор или человек с хорошим знанием линукса. Если ты используешь хостинг, то у тебя просто может не быть нужных прав.
В интернете легко нагуглить статьи вроде http://habrahabr.ru/post/195808/ но я бы не советовал тебе им следовать. Где гарантия что там все настроено правильно и не оставлен например какой-нибудь уязвимый шифр? Чтобы правильно все настроить, надо как минимум иметь представление что делает каждая настройка и какие шифры и протоколы на сегодняшний день считаются безопасными.
> при отправке/получении данных через айакс как работать с сессиями, если сайт, который получает данные, сам юи не использует?
А при чем тут Юи? Если ты имел в виду что у тебя 2 сайта на разных доменах (1 для авторизации, а другой куда ты шлешь запросы) то ни куки ни сессии работать так просто не будут, так как куки передаются только на тот домен который их выдал (исключение если оба домена это поддомены одного домена и в куках правильно проставлено свойство domain).
Ну и насчет отправки и получения кук, куки посылаются и получаются вместе с аякс-запросами. Правда, если это происходит в ифрейме и домен другой, то может не работать (так называемые third party куки).
> я так понимаю, надо использовать RESTful API, но смутно понимаю, как именно его использовать. Есть ли простой пример приложения с авторизацией?
Вообще-то REST и сессии противоречат друг другу, так как REST это отсуствие хранение данных на сервере между запросами. Что касается авторизации — сделай какой-нибудь токен который выдается клиенту при авторизации и передается при всех запросах. А от сессий конечно придется отказаться.
> есть готовый сайт-одностраничник, к которому я хочу приделать приложение (логин, заказ, статистика). Причём приложение должно работать в том же окне, все действия должны грузиться айаксом.
> Для этой цели я хочу поставить юи, чтобы она работала с авторизацией, БД и прочей бизнес-логикой, а выход возвращала в одностраничник, где уже яваскрипт будет обрабатывать представление.
Зачем эти извращения? Зачем приложение в том же окне на сайте? Какой смысл быть авторизованным в окне внутри другого сайта? Сделай просто отдельную страницу и без всяких там аяксов и не усложняй себе жизнь.
> Помимо этого планируется приложения для андроида, с тем же функционалом, для которого хочу использовать ту же схему.
В андроиде есть WebView который по сути является браузером и в котором можно открыть что угодно. Хотя я не понимаю зачем тогда вообще писать приложение если в андроиде и так есть браузер с которого можно зайти на твой сайт и который скорее всего лучше и удобнее чем приложение.
>>541444
А ты не ной, а изучай что не изучил и повышай свой уровень, ну и параллельно ищи заказы или работу. Под лежачий камень вода не течет.
>>541441
Прежде чем браться за написание скриптов на jQuery, надо изучить JS, DOM, XMLHTTPRequest (и основы HTTP) и тогда таких проблем возникать не будет.
По твоему коду непонятно в чем проблема, вроде данные должны отсылаться на сервер. Открой инспектор (Ctrl + shift +I) в браузере и проверь там что отправляется и приходит в ответ.
Но вообще ты поступил неправильно. Если при приеме на работу ты сказал что знаешь jQUery ты очевидно соврал работодателю. Если ты не изучишь JS, DOM, XMLHTTPRequest (и осноавы HTTP) и jQUery то и дальше с тобой будут происходить такие вещи. Потому рекомендую для начала прочесть learn.javascript.ru от начала и до конца, если ты его еще не прочел, а дальше думаю ты сам сообразишь что читать. По крайней мере будешь знать как отлаживать такие ошибки.
Ну и еще.
> $(".SubGroup option:selected").val();
Можно написать $(".SubGroup").val(); Надо изучать и понимать jQuery.
И на старуху бывает проруха, тут все таки 700 постов, мог и не заметить что-то.
Но давай все же я научу что делать в таких ситуациях. А в таких ситуациях надо доставать отладчик (Ctrl + Shift + I в браузере) и смотреть, нет ли ошибок в консоли. Может какая ошибка в синтаксисе. Также можно поставить точку останова внутри функции и посмотреть, сработает она или нет.
Если что, вот урок по использованию отладчика: http://learn.javascript.ru/debugging-chrome
Ну и еще вопрос, а на какой элемент ты пытаешься повесить обработчик? Может на нем стоит другой обработчик который перехватывает событие и предотвращает дальнейшую его обработку? Список обработчиков можно увидеть в отладчике на вкладке Elements где-то в уголке.
Нет, насколько я знаю. В гите есть экспорт файлов, но для этого сначала надо склонировать репозиторий. Так что качай zip, та же винда (или например тотал коммандер) умеет заходить в zip архивы не распаковывая их и не создавая лишних файлов. Говорят, правда, линукс и мак так не умеют, что же, посочувствуем пользователям этих без сомнения продвинутых операционных систем.
>>541190
Рассмотрим 3 варианта авторизации:
- сессии (сессия = кука + файл с данными на сервере)
- только куки
- http-авторизация (то браузерное окошко ввода пароля которое иногда выскакивает на страницах)
Идея авторизации через сессии в том что ты стаившь в сессию переменную что пользователь залогинен, и проверяешь ее. Помни, что сессии это временное место хранения данных и они удаляются по умолчанию через полчаса неактивности. Также, с сессиями связаны блокировки:
http://habrahabr.ru/post/232305/
заметь что блокировки сделаны как раз из благих побуждений: чтобы 2 скрипта, работающие с одной сессией, не повредили ее.
В случае авторизации через куки мы выставляем в куки id пользователя + какой-то секретный трудно угадываемый ключ, например:
- хеш пароля (злоумышленник его не знает)
- специальный длинный случайный код, который генерируется при регистрации пользователя и хранится в базе. Этот вариант позволяет не хранить даже хеш пароля у пользователя
- цифровую подпись id пользователя, подписанную секретным ключом сервера (плохой вариант так как она не меняется при смене пароля пользователем)
Что важно помнить:
- при смене пользователем пароля старые коды должны становиться недейтсвительными. Ну к примеру, пользователь подозревает что его куки украли и хочет сменой пароля защититься от их использования.
- для кук надо стаивть флаг httpOnly, который делает куку недоступной яваскрипту и защищает от ее воровства через XSS уязвимость
Что надо еще помнить: авторизацию (передачу пароля на сервер) надо делать через https, иначе есть варианты украсть этот пароля, например владелец wifi-точки видит проходящие через нее данные, сотрудник провайдера и всяческие госконтроли видят проходящие данные, если они не зашифрованы. А так как куки тоже позволяют получить доступ в аккаунт пользователя, лучше вообще для залогиненных пользователей использовать только https-соединение.
HTTP-авторизация это не вариант, она не позволяет удобно разлогиниться/залогиниится, не позволяет влиять на дизайн окна ввода пароля.
Некоторые пытаются увеличить защищенность кук или сессии, запоминая IP адрес с которого залогинился пользователь, и проверяя его каждый раз. Помни, что это создаст неудобства, так как например пользователь с мобильным устройством может переключиться с 3G на WiFi и получить совсем другой IP. Также, в мобильных сетях при разрыве соединения и повторной его установке пользователю обычно выдается новый IP.
>>540603
Если что, поиск еще можно сделать через sphinx, он позволяет не грузить зря базу, быстро работает, изучишь заодно этот движок, у меня и урок есть: https://gist.github.com/codedokode/10539366
Нет, насколько я знаю. В гите есть экспорт файлов, но для этого сначала надо склонировать репозиторий. Так что качай zip, та же винда (или например тотал коммандер) умеет заходить в zip архивы не распаковывая их и не создавая лишних файлов. Говорят, правда, линукс и мак так не умеют, что же, посочувствуем пользователям этих без сомнения продвинутых операционных систем.
>>541190
Рассмотрим 3 варианта авторизации:
- сессии (сессия = кука + файл с данными на сервере)
- только куки
- http-авторизация (то браузерное окошко ввода пароля которое иногда выскакивает на страницах)
Идея авторизации через сессии в том что ты стаившь в сессию переменную что пользователь залогинен, и проверяешь ее. Помни, что сессии это временное место хранения данных и они удаляются по умолчанию через полчаса неактивности. Также, с сессиями связаны блокировки:
http://habrahabr.ru/post/232305/
заметь что блокировки сделаны как раз из благих побуждений: чтобы 2 скрипта, работающие с одной сессией, не повредили ее.
В случае авторизации через куки мы выставляем в куки id пользователя + какой-то секретный трудно угадываемый ключ, например:
- хеш пароля (злоумышленник его не знает)
- специальный длинный случайный код, который генерируется при регистрации пользователя и хранится в базе. Этот вариант позволяет не хранить даже хеш пароля у пользователя
- цифровую подпись id пользователя, подписанную секретным ключом сервера (плохой вариант так как она не меняется при смене пароля пользователем)
Что важно помнить:
- при смене пользователем пароля старые коды должны становиться недейтсвительными. Ну к примеру, пользователь подозревает что его куки украли и хочет сменой пароля защититься от их использования.
- для кук надо стаивть флаг httpOnly, который делает куку недоступной яваскрипту и защищает от ее воровства через XSS уязвимость
Что надо еще помнить: авторизацию (передачу пароля на сервер) надо делать через https, иначе есть варианты украсть этот пароля, например владелец wifi-точки видит проходящие через нее данные, сотрудник провайдера и всяческие госконтроли видят проходящие данные, если они не зашифрованы. А так как куки тоже позволяют получить доступ в аккаунт пользователя, лучше вообще для залогиненных пользователей использовать только https-соединение.
HTTP-авторизация это не вариант, она не позволяет удобно разлогиниться/залогиниится, не позволяет влиять на дизайн окна ввода пароля.
Некоторые пытаются увеличить защищенность кук или сессии, запоминая IP адрес с которого залогинился пользователь, и проверяя его каждый раз. Помни, что это создаст неудобства, так как например пользователь с мобильным устройством может переключиться с 3G на WiFi и получить совсем другой IP. Также, в мобильных сетях при разрыве соединения и повторной его установке пользователю обычно выдается новый IP.
>>540603
Если что, поиск еще можно сделать через sphinx, он позволяет не грузить зря базу, быстро работает, изучишь заодно этот движок, у меня и урок есть: https://gist.github.com/codedokode/10539366
Вы видите копию треда, сохраненную 1 октября 2015 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.