Вы видите копию треда, сохраненную 7 сентября 2016 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
Добро пожаловать в наш уютный тред. Тут мы изучаем язык PHP (а также JS/CSS/HTML/SQL), решаем задачки и даже делаем простые сайты! Зачем? Кто-то хочет научиться программировать, кто-то - делать сайты, кто-то - просто размять мозги и заняться чем-то полезным.
Это не чат! Пожалуйста старайтесь постить только вопросы, решения и ответы по теме. Сколько лет вы не можете найти работу никому не интересно. Высказывайтесь одним большим постом, а не цепочкой мелких
Это тред для начинающих. Не написал за свою жизнь ни одной программы? Ты наш человек.
Устанавливать пока что ничего не требуется, разве что редактор кода вроде Sublime Text 3, Notepad++, Netbeans PHP или PhpStorm (с ним будет удобнее).
Предыдущий тред был тут: >>793705 (OP) (OP)
Что самое главное для программиста? Умение аккуратно оформлять код (читай второй пост прежде чем писать код).
Почему PHP? Потому что фейсбук и википедия на нем написаны, и вакансий море, и учить легко.
Правила: ведем себя воспитанно, помогаем новичкам, постим ссылки на решения задачек, ОП их проверяет и дает советы и замечания. ОП заходит редко, где-то раз в 2-3 дня, у него мало времени, не жди его, решай задачки дальше. ОП отвечает на все вопросы по его задачкам и учебнику, а вот насчет каких-то других вещей - только если останется время. Но в треде немало анонимных экспертов разного уровня, так что вряд ли вопрос останется без ответа.
У нас есть уроки по основам PHP, они собраны и выложены по адресу http://archive-ipq-co.narod.ru/ Это учебник для изучающих с нуля, то есть если ты вообще ничего не знаешь, то надо начать с него. Он простой и понятный (по крайней мере в начале). Там есть задачи, их надо решать обязательно (чтобы стать программистом, надо писать код — иначе никак). Пости ссылки на решения в тред, мы их проверим, напишем замечания и дадим советы по улучшению.
Если не знаешь как решать, запости код, напиши в каком месте остановился и попроси подсказку.
Ты прошел весь учебник? Молодец, но это были лишь основы языка PHP, этого недостаточно. Вот что в идеале надо изучить еще: ООП, как работает веб-сервер, HTML/CSS, SQL, PDO, работа с таблицами в БД, работа с формами, MVC, git, composer, JS, фреймворки, автоматизированное тестирование.
Надо переходить к более серьезным задачкам, которые научат тебя всему этому.
- для начала прочти урок https://github.com/codedokode/pasta/blob/master/soft/web-server.md
- установи Апач + PHP (советы выше и ниже) и читай туториал http://php.net/manual/ru/tutorial.php
- Учи HTML/CSS и SQL, PDO, хотя бы основы
- Далее простая, но полезная задача сделать список студентов, в ней много полезных советов: https://github.com/codedokode/pasta/blob/master/student-list.md
- Более сложная задача сделать файлообменник на микрофреймворке Slim: https://gist.github.com/codedokode/9424217
- Еще более сложная и долгая задача на Yii/Yii2: https://gist.github.com/codedokode/8733007
- После нее можно изучать автоматизированное тестирование
- Если ты все решил, переходи к Symfony 2/Doctrine 2
- Почитать про паттерны http://designpatternsphp.readthedocs.org/ru/latest/README.html (если ты не изучил ни одного фреймворка, то это будет рановато), тут с примерами кода http://designpatternsphp.readthedocs.org/ru/latest/README.html . Имей в виду что без примеров использования их учить бесполезно - не поймешь, хочешь увидеть примеры использования паттернов - ковыряй исходники Симфони, например Symfony Forms. Не заучивай паттерны - смотри код и думай, зачем тут они использованы.
Чтобы делать эти задания, тебе надо установить Апач + PHP (можно заодно сразу и MySQL) на компьютер. Вот полезные инструкции:
https://github.com/codedokode/pasta/blob/master/soft/php-install.md
https://github.com/codedokode/pasta/blob/master/soft/apache-install.md
Может тебе понадобится пользоваться командной строкой, вот гайд https://github.com/codedokode/pasta/blob/master/soft/cli.md
Решения задач лучше показать мне, особенно на ООП,так как сам ты вряд ли увидишь все ошибки. Пости свой код на гитхаб и вкидывай ссылку в тред по мере решения. Я прокомментирую и укажу на ошибки.
Также, у нас есть задачи которые позволят тебе изучить или подтянуть до нормального уровня знания JS/HTML/CSS/SQL. Решай их параллельно с задачами выше.
- HTML/CSS: https://github.com/codedokode/pasta/blob/master/html/html.md
- JS: https://gist.github.com/codedokode/ce30e7a036f18f416ae0
- SPA (сложно): https://github.com/codedokode/pasta/blob/master/js/spa.md
- Проверялка решений на JS: http://dkab.github.io/jasmine-tests/
- MySQL: https://gist.github.com/codedokode/10539213
Что почитать
- Мануал по PHP — http://www.php.net/manual/ru/langref.php
- Сайт phptherightway (перевод на русский: http://getjump.me/ru-php-the-right-way/ )
- По PHP: Профессиональное программирование на PHP Джордж Шлосснейгл
- По PHP: Мэтт Зандстра — PHP: Объекты, шаблоны, методики программирования
- JS: learn.javascript.ru
- Про Git: https://git-scm.com/book/ru/v1
Нужен ли ООП, фреймворки, MVC, git, composer? — Да, однозначно. Посмотри любую вакансию.
Сайт опять упал!!!!! — Не паникуй, а открой http://rghost.ru/6bfCY9lfl и получи личную немного устаревшую оффлайновую копию сайта (можно читать хоть на андроиде без интернета)
Оформляй код аккуратно!!! — например пропусти через phpformatter.com . Также, если ты пользуешься IDE вроде PhpStorm, Netbeans, Eclipse, то в них эта опция встроена, подробнее: https://gist.github.com/codedokode/8759492
ОП, сделай за меня мою работу или домашнее задание? — Это конечно, хорошая идея, но нет.
Подскажи сайты для поиска работы, я не умею гуглить? — hh.ru, geekjob.ru, moikrug.ru (склеен с brainstorage.me), fl.ru, upwork.com (бывший одеск). Имей в виду, что кроме фриланса есть еще постоянная удаленная работа (remote job) когда тебе не надо тратить время на поиск заказов и переговоры с неадекватными заказчиками.
Щас Оп сначала будет ныть, а потом просто зарепортит тред и сделает дубль. Ты понимаешь, что отбираешь у шизика смысл жизни?
При чем тут ныть? Надо переносить нормально со вторым и третьим постом со всеми пастами и прочим номером и тегом.
Нахуй браться переносить, если ты не можешь нормально сделать???
Кокой из тредов теперь легитимный? Посоны, мне нужна жс галерейка типа такой:
http://www.family.su/woman.html
+ в идеале, подписи запилить к каждой
увеличиваемой пикче.
+ очень опционально - форма заказа.
Сам вряд ли справлюсь. Подскажете какую-нибудь готовую и максимум лаконичную и понятную реализацию, просто готовый скрипт "встрой в страницу и забудь" или русскоязычный гайд по самостоятельному запилу подобного на жс? Попова не предлагать, там не то и еще большие азы.
Фак зе normalnost'
Только быдло может назвать шизиком того кто приносит пользу.
Только быдлу нужно никак не отличаться чтобы считаться нормальным.
И если нет , то почему?
http://sandbox.onlinephpfunctions.com/code/c98f0394d3bb13aa5a97fe2fdf38782e3dc3aa62
массив return , быстрофикс
1) Автозакрытие скобок и кавычек, но такое, чтоб если я сам дописывал скобки - автоматические "затирались".
2) Логические фигурные скобки
3) Список юзерский классов и методов сбоку
4) Чтоб ошибки отображал
5) Сворачивание блоков кода
6) Приятная подробная подсветка кода
Еще "проекты" и вкладки, но это везде есть)
netbeans , phpstorm
без отображения ошибок , про классы и методы не знаю, возможно достроить можно - sublime
антоны, какой минимум надо иметь в портфолио чтобы устроиться пхп разрабом на первую работу?
мне 24 года...
НетЕбинс достаточно толковая идешка, в тобой названные пункты вполне может, только надо немного повозиться с настройкой.
Но у меня есть несколько вопросов:
1). Какой уровень надо, чтобы устраиваться на работу в первый раз? Что знать, что уметь?
2). Мне искать стажировку или сразу должность джуниора?
зависит от студии/фирмы куда собираешься устраиваться.. кто-то берет новичков и прокачивает их за пару месяцев и потом берет на должность джуниора. У нас такая куйня практикуется.
В общем с чего-то начинать в любом случае надо. Если толком не умеешь ничего - то придется на дошираке пару месяцев посидь
пробовал.
из одной компании прислали задания на время, сделал около 70пр. Через неделю прислали письмо что мой результат ниже среднего по кандидатам на эту должность. Остальные компании просто игнорят.
Оп, посмотри первую задачку. Пипетки нет, извиняюсь.
http://codepen.io/Zeronsul/pen/GqBLBy
не торопись слазить с простой работы. осваивай жабу или хаскель в свободное время, андроид на жаве посмотри опять же. это все денежное, интересное и очень востребованное.
Я нубка конечно, но :: - вызов метода статичного класса? А в коде "new Singleton();" тоесть класс динамический.
Почему не ->
Аноны, можете помочь с задачкой? Я что-то вообще в тупике.
А что ты пытаешься сделать, непонятно же.
Суп, аноны. Ответьте ньюфагу, плиз.
Ноль в программировании является натуральным числом?
Ну не стукай, братишка.
Существуют два подхода к определению натуральных чисел — одни авторы причисляют ноль к натуральным числам[6], другие этого не делают. В российских школьных программах по математике не принято причислять ноль к натуральным числам, хотя это затрудняет некоторые формулировки (например, приходится различать деление с остатком и деление нацело). В качестве компромисса в источниках иногда рассматривают «расширенный натуральный ряд», включающий нуль[7].
А тебе зачем? В программировании все на английском языке, там такого слова нет. В программирование int (integer) и str(string), positive integer (понятно. что ноль не входит), whole, floats. Все гораздо яснее, чем на русском манязыке.
Да просто интересно стало. Конечно, ноль - целое число. Но если говорить о том, что с 0 начинается отсчет в программировании, тогда, если его можно посчитать (как и другие числа), то оно становится натуральным ТАМ. И как оно может быть целым, абсолютным или каким-либо еще в других сферах. Вот такой вот вопрос.
И чо мне делать? Оп прошлого треда сказал, мол, хтмл у тебя говно, делай задачки, потом покажешь мне.
Тот тред лежит на семисотых постах, а здесь не пишет никто. Чо делать-то?
> И чо мне делать?
Не думать, что у людей, которые "за спасибо" тебе (и не только тебе) помогают, всегда и на всех есть время. Делай следующие задачи.
> Тот тред лежит
Он по-прежнему активен.
Нафига зацикливать с половины фразы у которой есть пробелы и заглавные буквы? Помогити =(99
>>811794
Короче, на первой картинке не палиндром, на второй палиндром.
На третьей то, чего от меня хотел добиться оп
Че там делать то надо? Поясните же!
что я уже сделал: скачал экзешник компосера.
при установки он запрашивает php.exe (я указываю путь к денверу где лежит этот файл, но установщик ловит много ошибок и прекращает работу)
что мне делать? что он от меня хочет?
мне дополнительно установить апач и туда php? нихуя не пойму.
помоги аноно!
Не совсем понял суть проблемы. Вообще просто пиши понятный для себя код, решающий эту задачу, ну например:
к какому денверу, блджад
в денвере должна быть какая-то папка с модулями, найди ее, там должен быть твой пхп, в нем же php.exe
должно сработать, я этой хуйней давно не пользовался, адекватыши делают все ручками
но смысл компосера, что ты не делаешь все руками, а он делает это за тебя. тем более почти все мануалы прописаны под композер. например поставить Twig
На знаю как винде, на линуксе тебе нужно набрать команду вроде "пакетный_менеджер_нейм install composer" и ты уже можешь вызывать composer из командной строки. И удаляй денвер, ставь апач руками как написано у ОПа. У денвера протухшая версия PHP.
хорошо. поставлю апачь. спасибо!
хочу сделать межсерверник, но никак от задач не получается отойти..
Вообще ничего не понятно. Переформулируй.
Студенты из задач ОПа, файлообменник, тестхаб - всё это веб-приложения.
> Если нет профильного образования и вышки
ето вообще не важно, главное, чтобы ты был крут, да, и тогда попадешь на норм должность.
Фенк ю
http://ideone.com/xhKxwO
(ВОПРОС НЬЮФАГА). Здравствуйте, здравствуй двач, здравствуй /pr/ (я впервые тут), хочу научиться создавать сайты на php. В создании сайтов знаю всё, но по понемногу и на начальном уровне (т.е. js, jquery, php, mysql, html), в процессе обучения в виртуалке вроде даже клепал свои недосайты. Мой вопрос в том как перейти на нормальный уровень, к примеру как создавать более серьёзные проекты вроде качественных интернет магазинов куда из б.д. будут просто выгружаться тысячи товаров? И это пожалуй самый главный вопрос который меня интересует т.к. я не знаю как построить архитектуру сайта так, чтобы страницы создавались сами, не создавая самому в ручную тысячи файлов. Нужно ли мне для этого изучать MVC или может быть что-то другое, какие-то фреймворки может быть? Т.к. очевидно то что я не знаю ооп и вместе с этим я не могу понять и mvc, но вопрос опять же не в этом, а в том что по правильному ли я пути иду для озвученной цели, изучать ооп и MVC? И если да, то может быть подкинете мне информации откуда лучше будет начать изучение? Если вам не лень конечно же, если да, то можете как обычно в трёх буквах написать мне "пнх".
ОП явно не просто так открывает код, ОП хочет чтобы я сделал задуманное им для дальнейшего обучения. Нет?
Запили TestHub из ОП-поста.
Объясните пожалуйста, почему сработал preg_match без объявления массива $matches? Он получается его сам как глобальную переменную создает после во время выполнения?
Насколько я знаю, да. Это функция с побочным эффектом. Ты мануал-то по функции почитай.
В чем косяк? Это из задачи про вклад 10к по 10 % годовых.
В подсказке опа говорится, что сумма накопится через 49 лет. У меня же через 25, и еще этот пидор не хочет тормозить на миллионе.
> В подсказке опа говорится, что сумма накопится через 49 лет
Значит, ты неправильно считаешь. В твоих же интересах разобраться самому, почему так.
> и еще этот пидор не хочет тормозить на миллионе.
Потому что у тебя if ВНЕ цикла, ты неправильно расставил фигурные скобки. И цикл не "пидор", он делает лишь то, что ты ему сказал. Это как прийти в магазин и промямлить что-то невнятное продавщице, а потом материть её за то, что она не тот товар принесла.
С ней разобрался, спасибо. Еще вопрос по схожей функции - неправильно определяет позицию вхождения подстроки, хотя /u в регулярке поставил. В чем может быть проблема?
http://ideone.com/GIKozK
Там, в самом низу вывода есть сравнение сдвига и mb_substr на этот сдвиг.
Имею небольшой опыт работы с HTML+PHP+CSS+JS+JQUERY+MYSQL
Писал в универе:
1) сайтик с тестами с регой, куками, бд
2) Парсел сайтов на навличие кое-чего курл, пхпквери, хотел потрогать фантом жс, но серва нет на линупсе нет
3) одностраничники с хуевой версткой с версткой большие проблемы из-за отсутсвия опыта
4) Сайтик с формами, в который можно динамически добавить поля, суть которого в том, чтобы сгенерить строку js кода
5) еще какое-то говно, которое никому не нужно
Так вот, главные цели:
1) освежить знания
2) заполнить пробелы
3) научиться грамотно верстать
4) писать красивый код, с точки зрения чистоты и читабельности
5) научиться работать с популярными CMS
Вопрос: В правильный ли тред я попал и поможет ли мне инфа из ОП-поста?
Win10, Sublime, xampp
В разделе "веб-сервер" не работает ссылка, пикрелейтед
ОПа тут нет. Вот работающая ссылка: https://github.com/codedokode/pasta/blob/master/soft/php-install.md
А где он?
Бесплатно и что бы с пхп >= 5.5
Не могу понять что написано в библиотеке. Вообще подключить не могу ее. Я нюфаня, да. Говорит, что Method api not found in vkapi
Ничего не менял в исходниках гитхаба.
Моя пека PHP Version 5.5.9-1ubuntu4.17
Вывод вообще странный в браузере. Почему он вдруг функции PHP стал выводить, если не нашел метод? Почему ошибки нет? В php.ini после установки я ничего не трогал
https://github.com/LEMing/PHP_CLASS_FOR_VKAPI
Ссылку на гитхаб забыл. Я скопировал index.php и vkapi.class.php в одну директорию.
>>813541
Я в глаза долблюсь по ходу. Еще вчера лям был на 49 годах анона. А мне показалось 10 лямов, лол.
Сегодня доделал.
А,в глаза ебусь же
>Подсказка: не надо строить сложных выражений и предусматривать все возможные комбинации символов. Достаточно написать: сначала идет +7 или 8, за ними ровно 10 цифр, между которыми может быть любое число скобок, минусов, пробелов
Значит нужно делать несколько выражений
Для проверки на корректность телефона хватит одной регулярки, для замены на форматированный '89876543210' вид - двух.
Call to undefined function curl_init()
раскомментировал строку в php.ini extension=php_curl.dll
Теперь просит libssh2.dll. Хули делать? Я даже когда на ведроиде кодил там все было заебись, больше версий php и все работало. Денвер вообще уже лет 10 не обновлялся походу, нахуй их со своим 5.3.
Иль какой другой wamp посоветуйте, некогда мне в хуйне всякой разбираться.
Пока попробую старый easyphp воткнуть. Эти суки со своей обновой просто все разъебали, 1000 лишних нажатий теперь делать чтоб сервер запустить.
Так и знал, нахуй, что в 14 версии все заебись будет. Только на древнем пхп придется писать, но хули поделать
>на ведроиде кодил там все было заебись, больше версий php
ты на ведроиде запускал сервер php ? нахуя ?
Ставь Ubuntu в дуалбут и работай с нативным окружением. Нахуй эти канделябры с виртуальной машиной
vscale.io, это VPS
Самый дешевый тариф - 200 рублей в месяц. Может потянуть Symfony 2, например, только если composer не сильно будешь нагружать. А для flat php, чтобы просто поиграть - самое оно. Вордпресс тот же. Я лично сижу на 400 рублей в месяц, для фриланса хватает.
из ОП поста все нахуй выкинь, эти ребусы тебе не помогут ни на одном собеседовании
Ттакже не советую тебе идти на фулл стак разработку (когда пишешь код и на серверной части - PHP, и верстаешь). Это для рабов, которые будут выполнять все прихоти менеджеров, либо для отбитых фрилансеров. Также не советую идти в PHP фриланс. Изначально нацеливайся на крупные компании, которые качественно пишут код.
Не советую выбирать контору, которая работает с Битриксом, Wordpress, Joomla. Также не советую выбирать маркетинговые и SEO конторы. Как ознакомится с профессией эти места норм, но долга там нельзя засиживаться - ты будешь просто терять время, выполнять задачи уровня раба.
1) Выбирай платформу (CMS или framework, но лучше что-то сложнее сайта на Вордпрессе, Joomla тоже уже никто не юзает)
2) Выбирай дешевый VPS хостинг
3) Все устанавливай
4) Ставь целью - сделать контентный сайт со всей тривиальщиной (создание сущностей (таблиц через DBAL движок), добавление к ним полей разного типа - текст, ссылки на другие сущности, множественные поля, загрузка файлов).
5) любой вопрос, который у тебя возникает - гугли
Стремишься добиться того, что ты набьешь руку на создание всей тривиальщины, которую ты будешь юзать на работе 90%. Потом ищешь вакансию младшего разраба в компании, которая работает с этой платформой.
Собеседование:
Собеседование это не проверка твоих знаний, это
а) фейсконтроль. большинство начальников разраб-отделов просто ждут что ты скажешь им нужные слова, даже если они не совсем точные или не используемые в жизни
поэтому советую просто погуглить
"Вопросы на собеседовании для PHP разработчика"
гуглишь/вычитываешь эти вопросы, параллельно старайся делать так чтобы эта теория каким-то образом совпадала с тем, что ты учил на практике.
Обязательно пройди курс молодого бойца по MySQL - на младшего разраба верх вопросов будет это что такое транзакции и для чего нужны индексы
Также не лишни будем хотя бы знать определения популярных web технологий, чтобы не выглядить прохожим с улицы.
Также попробуй выполнить пару задач с использованием объектно ориентированного программирования. Добивайся того, чтобы логика твоих скриптов была структурирования. Прочитай что такое SOLID и старайся писать код по их рекомендациям
также для новичка полезно будет понять смысл паттернов
"Information Expert"
"Low coupling"
"High cohesive"
поможет понять, как структурировать объектный код
все это поможет тебе в разговоре с собеседующим
б) проверка твоей усидчивости и стабильности. разработка местами нудный процесс и собеседующий должен убедится что у тебя хватит выдержки и терпения выполнять задачи и инструкции по сдачи проектов
в) некоторые собеседующие любят видеть огонек в глазах разраба, чтобы видеть его заинтересованность в собственном труде.
И да - если ты устроишься непосредственно на работу - пойми, что собеседование и теория это одно, а работа с реальными проектами это другое. 90% времени разрабы кладут хуй на умные словечки и пишут быстрый код, который потом даже не рефакторя. Поэтому если у тебя будет коллеги по разработке - смотри как пишут код они, чтобы понять насколько качественный кокретно в этой конторе нужен код.
из ОП поста все нахуй выкинь, эти ребусы тебе не помогут ни на одном собеседовании
Ттакже не советую тебе идти на фулл стак разработку (когда пишешь код и на серверной части - PHP, и верстаешь). Это для рабов, которые будут выполнять все прихоти менеджеров, либо для отбитых фрилансеров. Также не советую идти в PHP фриланс. Изначально нацеливайся на крупные компании, которые качественно пишут код.
Не советую выбирать контору, которая работает с Битриксом, Wordpress, Joomla. Также не советую выбирать маркетинговые и SEO конторы. Как ознакомится с профессией эти места норм, но долга там нельзя засиживаться - ты будешь просто терять время, выполнять задачи уровня раба.
1) Выбирай платформу (CMS или framework, но лучше что-то сложнее сайта на Вордпрессе, Joomla тоже уже никто не юзает)
2) Выбирай дешевый VPS хостинг
3) Все устанавливай
4) Ставь целью - сделать контентный сайт со всей тривиальщиной (создание сущностей (таблиц через DBAL движок), добавление к ним полей разного типа - текст, ссылки на другие сущности, множественные поля, загрузка файлов).
5) любой вопрос, который у тебя возникает - гугли
Стремишься добиться того, что ты набьешь руку на создание всей тривиальщины, которую ты будешь юзать на работе 90%. Потом ищешь вакансию младшего разраба в компании, которая работает с этой платформой.
Собеседование:
Собеседование это не проверка твоих знаний, это
а) фейсконтроль. большинство начальников разраб-отделов просто ждут что ты скажешь им нужные слова, даже если они не совсем точные или не используемые в жизни
поэтому советую просто погуглить
"Вопросы на собеседовании для PHP разработчика"
гуглишь/вычитываешь эти вопросы, параллельно старайся делать так чтобы эта теория каким-то образом совпадала с тем, что ты учил на практике.
Обязательно пройди курс молодого бойца по MySQL - на младшего разраба верх вопросов будет это что такое транзакции и для чего нужны индексы
Также не лишни будем хотя бы знать определения популярных web технологий, чтобы не выглядить прохожим с улицы.
Также попробуй выполнить пару задач с использованием объектно ориентированного программирования. Добивайся того, чтобы логика твоих скриптов была структурирования. Прочитай что такое SOLID и старайся писать код по их рекомендациям
также для новичка полезно будет понять смысл паттернов
"Information Expert"
"Low coupling"
"High cohesive"
поможет понять, как структурировать объектный код
все это поможет тебе в разговоре с собеседующим
б) проверка твоей усидчивости и стабильности. разработка местами нудный процесс и собеседующий должен убедится что у тебя хватит выдержки и терпения выполнять задачи и инструкции по сдачи проектов
в) некоторые собеседующие любят видеть огонек в глазах разраба, чтобы видеть его заинтересованность в собственном труде.
И да - если ты устроишься непосредственно на работу - пойми, что собеседование и теория это одно, а работа с реальными проектами это другое. 90% времени разрабы кладут хуй на умные словечки и пишут быстрый код, который потом даже не рефакторя. Поэтому если у тебя будет коллеги по разработке - смотри как пишут код они, чтобы понять насколько качественный кокретно в этой конторе нужен код.
Спасибки адеквату
А и еще погугли всякие ребусы, то бишь задачки на сообразительность, которые спрашивают на собеседовании, это полный бред, но эти ребята задают такие вопросы.
Эти ответы нахуй не пригодятся на работе, но гнужны чтобы удачно пройти собеседование.
Возможно, это уже нагло с моей стороны, но можешь написать какие CMS и framework'и ты считаешь "сложнее"?
Проще говоря, какие предпочтительнее использовать?
Прост подумал, что мою формулировку "кмс сложнее вп и джумлы" гугл не поймет
Я бы на твоем месте установил бы фреймворк попроще, например Yii, прошел бы туторы.
В плане CMS полезнее и выгоднее для разработчика разобраться в Drupal. В последних его версиях. Возможно сначала будет сложновато, но в этой CMS хотя бы большинство современных наработок есть.
Но все равно нужно осознать что от разработки на CMS нужно отходить. Искать конторы, которые качественно работают на фреймворках.
Ты будешь хорошо знать технологии, только если ты используешь их на работе. Теория является тем, что структурируют твои практические навыки. Можно читать кучу книжек и сыпать терминами, но работать хорошо это не поможет.
И да, при всем при этом, не жди от PHP многого в плане качества разработки. Это все же язык, который разрабатывался для того, чтобы удобно выводить HTML текст.
Если ты хочешь угореть по серьезному ООП-программированию, лучше нацелится на другой язык. Разработывать web проекты можно и на Java и даже на C++ есть фреймворки.
Дело в том, что я охуенно знаю Java и тп, поэтому нужно как-то начать соответствуюше. Без лишней инфы.
Синтаксис, спецификация, тонкости, фреймворки.
Напишите программу, которая выводит на экран числа от 1 до 100. При этом вместо чисел, кратных трем, программа должна выводить слово «Fizz», а вместо чисел, кратных пяти — слово «Buzz». Если число кратно и 3, и 5, то программа должна выводить слово «FizzBuzz»
Забыл, что добавить, что для FizzBuzz нужно знать об операторе % (остаток от деления). Ну и решай след задачи из учебника.
Сейчас вот в учебнике по JS как раз этот ФизБаз предлагается. Но я застрял еще на этапе построения треугольника из # (не срабатывает команда .lenght) ну да ладно, это тред не о JS
> не срабатывает команда .lenght
Не lenght, а length! Я сам постоянно бугурчу из-за этой опечатки, а JS, сука, молчит как партизан.
Ебать я дебил
Спасибо, уважаемый!
Но у меня нет вышки, и вообще я из пту. Лол.
Там механизм последнего платежа есть: после цикла, в котором происходит погашение кредита, остается маленький непогашенный кусок (текущий баланс, то есть он меньше разового платежа в 5000, например), и вот после цикла прибавляешь к общему платежу школьника (посчитанному в цикле) значение этого самого баланса, ну и дополнительный месяц добавляешь к посчитанным, если надо. Все, готово.
Почему фриланс не советуешь?
Всмысле не помогут? Я вот с нуля начал, очень даже толково все задачки поставлены вчера застрял на регулярных выражениях нимношк
> Смогу ли я выучить php за месяца три, устроиться в ИТ
Нет.
> и во время работы учить java?
Ты работать будешь на работе, не? А после работы будешь приходить заёбанный, боясь к компу подойти, какие тут дополнительные занятия? Лучше сразу Java учи.
>>814349
Хуйню он какую-то несёт, сначала говорит, что ребусы из ОП-поста не помогут, а потом советует таки погуглить задачки на сообразительность, ведь их спрашивают на собеседованиях.
> "Information Expert"
> "Low coupling"
> "High cohesive"
> поможет понять, как структурировать объектный код
Без практики нихуя не поможет. А в ОП-посте как раз практика.
А, еще про хостинги поясни, за платные и бесплатные. Как там обстоят дела с заливом своего саета с нуля. Вот на юкоз зашел и нихуя не понял, например.
В защиту парня могу сказать, что уже имеется небольшой опыт, поэтому большинство задач скипнул, ибо реализуются совсем легко
А вот то, что у меня уже забылось сижу и читаю, включая интересные задачки, которые сходу в голове не решились.
И советовал он поискать типовые вопросы, задающиеся на собеседованиях типа "продай мне ручку" и тестовые задания типа "захуярь лендос на джумле"
>>813863
На счет фриланса тоже интересно, да
пик отклеился
> "захуярь лендос на джумле"
Вот это всё связанное с CMS это мартышкин труд. Можно устроится PHP-программистом на фреймворках и не пачкаться в Joomla-параше, если обладать достаточными навыками. На это и направлены задачи вроде TestHub'а из ОП-поста. Если нужно человеку нужно клепать лендинги/визитки/грабберы/блоги на CMS в 2 кнопки, то ему путь в /web, в /pr программирование.
Блять запости пример. И на ideone сразу скинь, заодно проверишь, к коде проблема или в денвере.
echo $hui, "\n"
или
echo "{$hui}\n"
или
echo $hui . PHP_EOL
>>814389
Ну так символ end of line игнорируется HTML, ты там либо код в <pre></pre> оборачивай, либо используй <br>
Символ конца строки используют для форматирования консольного вывода.
Я же тебе написал \n - символ конца строки - используется ТОЛЬКО для консольного вывода. То есть ты вбил в консоли php.exe script_name.php, и в консоли твоя строка "\nhui \n hui" преобразуется в
"hui
hui"
Это из-за особенностей HTML, он игнорит этот символ. 2 выхода: либо использовать <br>, либо дописать вверху файла header('Content-Type: text/plain');
Попробуй дописать это к тому файлу, который на скрине. Но тогда и все html-теги тоже будут видны.
+ Есть ещё такая функция: http://php.net/manual/en/function.nl2br.php
Ну яж неразбираюся, вон у опа все получается в задачках на идеоне, а у меня нет. Ну пояснил, спасибо, думаю в уроках про основы ксс и хтмл мне все расскажут
На ideone эмулируется консольный ввод-вывод, то есть когда ты тыкаешь на зелёную кнопку run, где-то там происходит вызов команды в консоли php script_name.php, а консольный выхлоп попадает на сайт в output. Ты если не работал с этим, то ничего не поймёшь, вины твоей в этом нет. Но я бы тебе советовал погуглить, как запускать скрипты из командной строки (у ОПа, вроде бы написано об этом).
Планирую начать проводить тренинги по этой теме и для проработки программы + самотренировки я бы взял какого-нибудь анона на прокачку. Фо фри, разумеется.
О себе: 6 лет+ пхп, полтора симфони, йоба-опенсорс контрибутор, сейчас поднимаю 130к чистыми со свободным графиком.
Ну давай, бери меня. Я готов заниматься 2 дня через 1.
Часов по 5 в день с перерывами. Ну или как тебе удобно.
smile_for_bright
Нет, поясни
Разобрался сам
А как лаконичнее?
http://ideone.com/R9wnfP
$summa += 0.1 * $summa
http://ideone.com/nzTmLC
В C++ класс является абстрактным только если имеет хотя бы один абстрактный метод, а если на PHP можно обойтись и без этого, то не значит, что нужно. Ну а вообще, если у класса не будет инстансов, а инстансы будут только у наследников, то класс-предок можно делать абстрактным.
у меня пеки не было полтора года нахуй, бомжевал
>Иль какой другой wamp посоветуйте, некогда мне в хуйне всякой разбираться.
http://open-server.ru/
Не понял вопрос. Тут 2 разных массива. return это команда возврата из функции, а не название массива.
>>807577
ОП не разбирается в жс галереях.
>>808390
Можно, но.... особенность этого счетчика в том что он глобальный и невозможно сделать 2 независимых счетчика так. Так что стоит подумть прежде чем делать.
И кстати пишется это кроче:
private static $counter = 1;
...
self::$couner ++;
И кстати Синглтон это класс объект коттрого нельзя создать дважды, у тебя не синглтон, анон правильно пишет.
>>809564
Это же опен сурс - всегда можно поправить. Алсо думаю эта проблема давно решена, нужен патч какой-нибудь или конфиг подправить.
Зато распространение легально и санкционированно.
>>809011
Если бы были студенты, файлообменник и testhub + знание SQL-нормализации -транзакций + большинство задач на HTML и JS решено - думаю, с руками оторвут.
>>809603
Погугли тестовые задания на пхп например.
>>809605
Странно что игнорят. может им с опытом человек нужен? Может с товим резюме что-то не так?
>>809752
Когда видишь что можешь еще что-то сделать, кроме своей работы, можешь попробовать об этом сказать.
>>810853
пересидим в нелегитимном один тред.
>>810168
Что-то переусложнено и цвета совсем не такие.Откуда например серый взялся ?
Надо упростить. Без box-sizing, попроще.
И что еще за spacer? Ты из 2000 вылез? Маргин же есть.
Контейнеры тоже убери.
>>810539
В классе могут быть одновременно и такие и такие методы и поля. Почитай теорию.
>>810853
Да, у него вообще не Синглтон. Как можно синглтон 2 раза создать?
Не понял вопрос. Тут 2 разных массива. return это команда возврата из функции, а не название массива.
>>807577
ОП не разбирается в жс галереях.
>>808390
Можно, но.... особенность этого счетчика в том что он глобальный и невозможно сделать 2 независимых счетчика так. Так что стоит подумть прежде чем делать.
И кстати пишется это кроче:
private static $counter = 1;
...
self::$couner ++;
И кстати Синглтон это класс объект коттрого нельзя создать дважды, у тебя не синглтон, анон правильно пишет.
>>809564
Это же опен сурс - всегда можно поправить. Алсо думаю эта проблема давно решена, нужен патч какой-нибудь или конфиг подправить.
Зато распространение легально и санкционированно.
>>809011
Если бы были студенты, файлообменник и testhub + знание SQL-нормализации -транзакций + большинство задач на HTML и JS решено - думаю, с руками оторвут.
>>809603
Погугли тестовые задания на пхп например.
>>809605
Странно что игнорят. может им с опытом человек нужен? Может с товим резюме что-то не так?
>>809752
Когда видишь что можешь еще что-то сделать, кроме своей работы, можешь попробовать об этом сказать.
>>810853
пересидим в нелегитимном один тред.
>>810168
Что-то переусложнено и цвета совсем не такие.Откуда например серый взялся ?
Надо упростить. Без box-sizing, попроще.
И что еще за spacer? Ты из 2000 вылез? Маргин же есть.
Контейнеры тоже убери.
>>810539
В классе могут быть одновременно и такие и такие методы и поля. Почитай теорию.
>>810853
Да, у него вообще не Синглтон. Как можно синглтон 2 раза создать?
В программировании нет натуральных чисел. В PHP например есть int и float и они определяются способом хранения в памяти компьюетра.
Компьютерные числа отличаются от математических тем, что они имеют пределы, и могут иметь ограниченную точность.
То есть математик на такие "числа" даже смотреть не станет.
Вот тебе интересная статья по теме https://habrahabr.ru/post/112953/
>>811042
В программировании характеристики числа определяются не математикой, а особенностями устройства процессора, памяти и тд. Какие было удобнее раелизовать в железе - те и реализовали.
>>811139
ОП пришел, давай задачи.
>>811690
Не знаю, расскажи потом.
>>811781
Копировать код с картинки не требуется. можно решать по-своему, лишь бы было верно и код был читабельный.
Убрать пробел проще через str_replace
Программа у тебя делает лишнее - получить первую половину слова можно без цикла.
>>812083
В денвере древний пхп, может дело в этом?
Вообще, пиши подробно какие именно ошибки выходят, вставь скриншотом или скопируй сюда. Как мы тебе поможем не видя проблемы?
Вообще лучше установить php и прописать в PATH. для начала прочти из ОП поста пасту про командную строку и про установку пхп. А денвер лучше вообще снести от греха подальше.
И конечно задавай вопросы если есть, по композеру. Важно его освоить.
В программировании нет натуральных чисел. В PHP например есть int и float и они определяются способом хранения в памяти компьюетра.
Компьютерные числа отличаются от математических тем, что они имеют пределы, и могут иметь ограниченную точность.
То есть математик на такие "числа" даже смотреть не станет.
Вот тебе интересная статья по теме https://habrahabr.ru/post/112953/
>>811042
В программировании характеристики числа определяются не математикой, а особенностями устройства процессора, памяти и тд. Какие было удобнее раелизовать в железе - те и реализовали.
>>811139
ОП пришел, давай задачи.
>>811690
Не знаю, расскажи потом.
>>811781
Копировать код с картинки не требуется. можно решать по-своему, лишь бы было верно и код был читабельный.
Убрать пробел проще через str_replace
Программа у тебя делает лишнее - получить первую половину слова можно без цикла.
>>812083
В денвере древний пхп, может дело в этом?
Вообще, пиши подробно какие именно ошибки выходят, вставь скриншотом или скопируй сюда. Как мы тебе поможем не видя проблемы?
Вообще лучше установить php и прописать в PATH. для начала прочти из ОП поста пасту про командную строку и про установку пхп. А денвер лучше вообще снести от греха подальше.
И конечно задавай вопросы если есть, по композеру. Важно его освоить.
Нет, Оп показвает код чтобы можно было увидеть как примерно выглядит решение. Если у тебя например вышло 100 строк, а у ОПа - 10 то что-то тут не так. Копировать код не требуется.
Ну и часто аноны просят показать им пример кода (чесно-честно я все сам решу, только одним глазком гляну), вот ОП и решил показать - как раз на один глазок хватит.
>>812118
Композер ставт библиотеки за тебя, но вот пхп он сам не поставит и не настроит. И прочитай про командную строку.
>>812325
Я не шарю.
>>812595
Но не в Германию и не в госкомпанию и не в бюрократическую корпорацию.
>>812800
Молодец, правильно.
>>815064 - HTML/CSS
>>815058 - вопросы по студентам (много) и ООП, MVC
>>812991 - ответы за 23 июля
>>812990 ответы за июль и немного по https://github.com/TheSidSpears/Students/
>>812987 - ответы на старые посты
>>812095 - старые посты
Если кого-то пропустил, напомните о себе тут.
Не флудите.
Аноны, вас то ли троллят, то ли это гайд для желающих найти низкооплачиваемую рутинную работу по перекраске меню на битриксе.
ЧТо за паттерн "information expert"? Первый раз слышу.
Есть лифт с компьютерным управлением. В нем есть такие датчики:
- кнопки вызова на 1, 2, 3, 4 этажах
- датчик положения (на каком этаже сейчас лифт)
- датчик, показывающий открыты ли двери
Состояние датчиков дано тебе в переменных, ну например:
$button1 = 0; // не нажата
$button2 = 1; // нажата кнопка на 2 этаже
Программа должна вывести команду, которая будет подана на управляющие механизмы. например "закрыть двери" или "двигаться вниз".
При желании можешь добавить еще датчики кнопок внутри лифта, датчик веса и тд.
Конструктор делается приватным, то есть недоступным из вне, наружу выставляется статический (принадлежащий классу) метод getInstance, который либо создаёт инстанс класса, помещает в статическое поле и возвращает этот инстанс, либо, если статическое поле не null, то возвращает содержимое этого статического поля. Об этом пишут абсолютно во всех туториалах по Singleton. Примерный код:
class Singleton
private static instance;
private function __construct() {}
public static function getInstance() {
if (null === self::instance) { // Это условие сработает только при первом вызове
self::instance = new Singleton();
}
return self::instance
}
>>813966
Читай phptherightway, лаконичнее вряд ли что-то найдёшь. Какой странный у тебя перекат (с Java на PHP).
Я знаю как делается синглтон, вопрос был не в этом. Я не понимаю как статический метод может отдавать один и тот же объект. Это ведь просто функция, только внутри класса. Это похоже на какое-то жсовское замыкание.
Я, наверное, неправильно сформулировал вопрос. Я не совсем понимаю почему запоминаются статические поля у класса.
http://ideone.com/mJ0Zmx
По моей логике в обоих случаях должно вывести 1, но выводится 1 и 2, как будто мы переопределяем сам класс, а не объект
Ты понимаешь что такое статическое поле и чем оно отличается от обычного? Статическое поле принадлежит не объекту, а классу. Оно существует в одном экземпляре независимо от того, сколько объектов этого класса создано.
Замыкания это другое, ты ищешь сложности там, где её нет.
Статический класс и статическое поле существуют на протяжении всей
жизни сценария.
> Я не совсем понимаю почему запоминаются статические поля у класса.
Удобно думать, что с классом проассоциирован ещё один объект, который хранит всё статические поля и методы (поэтому и говорят "принадлежит классу").
> По моей логике в обоих случаях должно вывести 1,
Так ты же не создал 2 разных объекта, а используешь "объект класса".
Если привыкнешь к нему, то перестанешь замечать. Зато не нужно var'ы ставить. В Ruby бесконечные end'ы коряво выглядят. Дело привычки.
В JS тоже недавно добавили знак доллара https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/template_strings
>Какой странный у тебя перекат (с Java на PHP)
Хочу работать кодером, а Java нужна только в аутсорс галерах в моей белорашке. А с пхп можно пойти в любую компанию со своим сайтом и колупать CMS
http://ideone.com/AgI48y
Халп. У меня тут непонятное что-то с задачкой. Проверил, вроде все правильно. Хотя, может, потомужто я нуфак-даун-аутист? В общем, смотрите сами.
Думаешь, смешно показывать скрин-обрубок? Побуду экстрасенсом, у тебя на 4-й строке, которую мы не видим, в конце нет символа ;
> смотрите сами.
Пушка.
Соре, думал, дело не в ней, в итоге и правда - забыл ; после error_reporting. Спасибо. Эхх, какой же я даун-аутист.
Лол, опять не мог понять, в чем дело, пока не заметил, что во второй раз пропустил точку с запятой. Это только я такой даун-аутист, или поначалу нормально это?
Поначалу нормально.
Переписал код для композер скрипта: http://ideone.com/j6DyCf . Оп посмотри позяз. Вроде работает правильно по пикрелейтеду. Алсо вопрос, как-то в composerjson можно будет передать в статический метод аргументы? Или придется без аргументов.
>>806594
> mkdir($path, 0700, true);
Обычно веб-сервер имеет права "другой" а в твоем случае файл доступен только владельцу.
Немного не понятно. У меня без второго и третьего аргумента ошибки получаются.
Программа выдаёт не значение, а ключ.
Как вообще выполнять там команды, когда нужны изменения? В папке console что-то надо делать?
Ещё поясните, пожалуйста, как установить этот фреймворк с папками backend и frontend просто на локалку. Ткните мордой неразумного, я не нахожу этого в документации.
Да здравствует легитимный тред, очередной, твой
Ткните меня пожалуйста где я обосрался.
http://ideone.com/M0JHZQ
Не забывай читать вывод ошибок, там можно найти что не так в твоем коде.
В данном случае у тебя опечатка на 13 и 16 строке кода.
На 13 $anodDice2 вместо $anonDice2
На 16 $anodDice1 вместо $anonDice1
PHP Notice: Undefined variable: anodDice2 in /home/KlDHJx/prog.php on line 13
PHP Notice: Undefined variable: anodDice1 in /home/KlDHJx/prog.php on line 16
anodDice2
Назовите причины использовать PHP в 2016 году для написания проектов с нуля использование готовой CMS - легитимный случай, но вопрос про написание проектов с нуля
Что конкретно тебе пояснять? Выделяешь отдельный раздел под линукс и ставишь туда. Единственный подводный камень: если будешь ставить в порядке линукс->виндоус, то учти, что загрузчик винды затрёт загрузчик линукса и сам линукс он не видит, поэтому нужно будет переставлять загрузчик линукса - GRUB (он видит загрузчик винды). Зачем тебе линукс?
>>815520
Хорошая статья по правам доступа к файлам: http://younglinux.info/rwx
Думаю, ОПу стоит добавить на неё ссылку в гайде по командной строке.
И тут ещё был анон, который ставил Yii2 в корень файловой системы, тоже почитай.
На серверной убунте привык уже, у меня там и пхп проектывисят и nodejs и mysql workbench настроен через ssh и дебаггер на phpstorm. Получается счас у меня проекты лежат в папках под виндой, запускаю виртуалку и маунт делаю папки с проектами в /var/www
И чем такой подход не устраивает? Виртуалку можно запускать в безголовом режиме, если тебе лень мышкой постоянно запускать её. А .bat-ник на хоткей повесить.
Мешают ограничения по правам. Буквально с сегодняшнего дня. Клонировал существующий проект на sailjs и npm i не может проинсталить, ошибки по поводу прав и названий файлов (в js треде постил). Попробовал чистый проект на sails поднять - те же ошибки. Потом ради интереса на винде попробовал то же самое и нормально запуталась
Запустилось* т9
Ну так выставь пользователю, с которого заходишь, больше полномочий. Такая проблема у тебя и на линуксе может возникнуть.
Через sudo su это первое что я попробовал, какие то проблемы именно с виртуалкой
Проблемы с полномочиями пользователя это не проблемы с виртуалкой. Запости здесь то, что ты в JS-треде запостил, может кто подскажет. Я с sails не работал.
Это описано в документации: https://getcomposer.org/doc/articles/scripts.md
Аргументы передавать нельзя. Но из функции-обработчика можно получить объект Composer и из него конфиг. Таким образом, нужные параметры можно закодировать в самом composer.json в ключе extra. Так поступают плагины к композеру, расширяющие его возможности.
Но я бы конечно еще подумал, стоит ли так делать. Надо делать как можно более простое решение, а не сложную навороченную систему.
Также, под линуксом вместо копирования файлов может быть выгоднее ставить симлинки (под новой виндой тоже есть симлинки, но с ними все сложно). Изучи-ка эту тему.
Вообще, проблема, которую ты затронул (установка сторонних клиентских библиотек) довольно важная. Я пока не знаю какого-то единого решения, знаю только что каждый решает ее по своему.
Более того, в теории тут можно получить определенную выгоду. Например, бутстрап или jquery UI состоят из отдельных компонентов и можно собрать маленькую версию библиотеки, включающую только нужные тебе в проекте вещи. И задавать, какие компоненты нам нужны, в конфиге, так что легко было бы добавлять или убирать их.
Если бы мы могли как-то это описать в конфиге, чтобы оно само скачивалось и компилировалось, было бы неплохо. Но это конечно усложнит установку, так как потребует как минимум Node.JS ставить и пакеты к ней.
Тут еще конечно возникает вопрос, а должен ли композер этим заниматься? По идее для установки клиентских библиотек есть bower, есть системы сборки и минификации вроде gulp, также есть assetic из Симфони, предназначенный примерно для того же.
Вот ссылка на Assetic: https://github.com/kriswallsmith/assetic Он немного сложный, но умеет делать то, что нам требуется.
Более того, композер позволяет писать к нему плагины. Которые могут запускаться во время установки библиотек и что-то делать, например, копировать файлы в публичную папку. Можно попробовать поискать такой плагин или написать самому. Если это распространенная задача, и такой плагин подошел бы ко многим проектам, то выгоднее сделать именно плагин к композеру, который можно повторно использовать, а не одноразовый класс, который подходит только к одному твоему проекту и который надо будет вручную добавлять и подправлять под каждый новый проект.
Но если решать это через композер, то возникает вопрос, где мы должны остановиться? Вот мы скачали библиотеку композером. далее, надо ее перенести в публичную папку - должен композер это делать? хорошо, а если мы хотим далее склеить несколько css файлов в один - должен композер это делать? А переписывать в файлах URL к картинкам кто должен? А минифицировать?
Так мы можем прийти к тому, что перенесем в композер половину bower и gulp (или половину assetic). правильно ли это?
Я тут погуглил и для начала, нашел такую штуку: https://github.com/fxpio/composer-asset-plugin
Это по сути аналог bower, который умеет читать данные из репозиториев bower и устанавливать его пакеты (если ты не в курсе - то bower это пакетный менеджер для фронтенда, т есть аналог композера для js и css библиотек).
У него есть свои проблемы:
- пока плагин может поставить только пользователь глобально, и нельзя прописать в composer.json для одного проекта
- он только скачивает, но не публикует библиотеки
В общем, я бы предложил рассмотреть такие варианты:
- посмотреть, может ли нам тут помочь Assetic
- написать или поискать плагин к композеру для публикации библиотек, в том числе с поддержкой симлинков
- если эти варианты не годятся, то пользоваться своим скриптом, вроде того что ты написал
Это описано в документации: https://getcomposer.org/doc/articles/scripts.md
Аргументы передавать нельзя. Но из функции-обработчика можно получить объект Composer и из него конфиг. Таким образом, нужные параметры можно закодировать в самом composer.json в ключе extra. Так поступают плагины к композеру, расширяющие его возможности.
Но я бы конечно еще подумал, стоит ли так делать. Надо делать как можно более простое решение, а не сложную навороченную систему.
Также, под линуксом вместо копирования файлов может быть выгоднее ставить симлинки (под новой виндой тоже есть симлинки, но с ними все сложно). Изучи-ка эту тему.
Вообще, проблема, которую ты затронул (установка сторонних клиентских библиотек) довольно важная. Я пока не знаю какого-то единого решения, знаю только что каждый решает ее по своему.
Более того, в теории тут можно получить определенную выгоду. Например, бутстрап или jquery UI состоят из отдельных компонентов и можно собрать маленькую версию библиотеки, включающую только нужные тебе в проекте вещи. И задавать, какие компоненты нам нужны, в конфиге, так что легко было бы добавлять или убирать их.
Если бы мы могли как-то это описать в конфиге, чтобы оно само скачивалось и компилировалось, было бы неплохо. Но это конечно усложнит установку, так как потребует как минимум Node.JS ставить и пакеты к ней.
Тут еще конечно возникает вопрос, а должен ли композер этим заниматься? По идее для установки клиентских библиотек есть bower, есть системы сборки и минификации вроде gulp, также есть assetic из Симфони, предназначенный примерно для того же.
Вот ссылка на Assetic: https://github.com/kriswallsmith/assetic Он немного сложный, но умеет делать то, что нам требуется.
Более того, композер позволяет писать к нему плагины. Которые могут запускаться во время установки библиотек и что-то делать, например, копировать файлы в публичную папку. Можно попробовать поискать такой плагин или написать самому. Если это распространенная задача, и такой плагин подошел бы ко многим проектам, то выгоднее сделать именно плагин к композеру, который можно повторно использовать, а не одноразовый класс, который подходит только к одному твоему проекту и который надо будет вручную добавлять и подправлять под каждый новый проект.
Но если решать это через композер, то возникает вопрос, где мы должны остановиться? Вот мы скачали библиотеку композером. далее, надо ее перенести в публичную папку - должен композер это делать? хорошо, а если мы хотим далее склеить несколько css файлов в один - должен композер это делать? А переписывать в файлах URL к картинкам кто должен? А минифицировать?
Так мы можем прийти к тому, что перенесем в композер половину bower и gulp (или половину assetic). правильно ли это?
Я тут погуглил и для начала, нашел такую штуку: https://github.com/fxpio/composer-asset-plugin
Это по сути аналог bower, который умеет читать данные из репозиториев bower и устанавливать его пакеты (если ты не в курсе - то bower это пакетный менеджер для фронтенда, т есть аналог композера для js и css библиотек).
У него есть свои проблемы:
- пока плагин может поставить только пользователь глобально, и нельзя прописать в composer.json для одного проекта
- он только скачивает, но не публикует библиотеки
В общем, я бы предложил рассмотреть такие варианты:
- посмотреть, может ли нам тут помочь Assetic
- написать или поискать плагин к композеру для публикации библиотек, в том числе с поддержкой симлинков
- если эти варианты не годятся, то пользоваться своим скриптом, вроде того что ты написал
Написано же: ты пытаешься что-то устанавливать на файловую систему, которая примонтироана в режиме "только для чтения"
Первым делом глянь вывод mount и посмотри, что у тебя куда примонтировано и правда ли что только для чтения.
И да, я не знаю что такое sails, но чтобы им пользоваться надо изучить хотя бы основы Линукса.
Также, есть вариант что файловая система просто не поддерживает симлинки, и при попытке его создать возвращает такой код ошибки.
Я тебя хочу предупредить: может быть все эти руби, питоны, ноде жс, монго и разрекламировани и имеют хороший пиар - но учти что они предназначены для линуксоидов которые хорошо в своей системе разбираются, умеют компилировать рукми и править скрипты сборки. Не знаю как сейчас, но когда node js появилась, она была точно не для начинающих, а для опытных разработчиков.
Если ты хочешь работать с этими модными технологиями, начни с более глубоко изучения линукса, освой консоль как следует. Это ненормально что человек пытается использовать ноду не не способен прочесть сообщение об ошибке и хотя бы выполнить команду mount.
А вот в случае c php все проще и с ним можно работать даже под виндой. PHP - язык для начинающих.
Проблема не в правах, а в непонимании как работает линукс и как настроено твое окружение и что происходит в процессе установки. Тебе надо научиться решать эти проблемы, а не пытаться убежать от них, поменяв окружение.
Советую выкинуть сборки с устаревшим софтом и ставить и настраивать все руками. Насчет проблемы с dll - наверно надо какую-то библиотеку установить и наверняка в документации это описано.
Также, есть вариант что эта библиотека установлена, просто динамический линкер не может ее найти так как она не в PATH.
Или я параноик и никто не будет его гулить?
Обычно гуглят не гитхаб, а имя и никнейм который ты используешь. Тогда да, могут найти посты на дваче, но я бы не волновался по этому поводу.
>но я бы не волновался по этому поводу
Как то не удобно, хотя мало кто поймет что тут происходит. Просто посты на тематическом форуме и немного трапов и аниме вокруг.
В /pr/ же нет трапов, тут в основном по теме посты, так что нормально. HRы обычно дальше страницы которую им выдал гугл не ходят.
А тогда начнутся вопросы по типу "А чего это у вас всё одним коммитом, хотим историю развития проекта посмотреть, как вы код рефакторили и так далее."
>>816004
Я тоже думал над этим. У меня такая идея: создать новый аккаунт на гитхабе, изменить во всех своих репозиториях автора коммитов со старого на новый, запушить от нового имени в новый репозиторий с новым именем. В результате даты коммитов и сами коммиты сохранены, но автор другой.
Как менять автора/email? Вот тут примеры:
- Вот здесь для отдельно коммита: http://stackoverflow.com/a/1320317
- Вроде бы готовая красная кнопка: https://help.github.com/articles/changing-author-info/
Я это не пробовал и опробую ещё не скоро, не хочу пока работать, но вроде бы это должно сработать.
Та да, видит HR ссылки на твой гитхаб, заходит сюда и видит пикрил.
У ОПа обычно нормальные картинки. Плюс мне ни разу ничего не сказали про это, был на шести собеседованиях.
Ладно, попробую без матов: идет жесткий кеш(паблишинг) со стороны Yii. Стандартный компонент и его свойство не помогли, Yii::app()->assetManager->publish($assets_path, false, -1, YII_DEBUG); и $this->getAssetsUrl() возвращают пустые папки(1-2 файла есть). За 2 узнал, что проблема может быть в симлинках, правах доступах и моей криворукости
ребятки, помогите. Не могу понять почему один код(с переменной flag) выводит простые числа правильно, а второй нет? Почему так?
ну потому-что 1 цикл у тебя на поиск непарных чисел, у тебя каждый раз будет идти break, только на непарных он будет выводить $i
>>816070
Дополню: тебе нужно выводить только тогда когда ты уже в самом конце цикла, как вариант пикрилейтед. Но нужно еще для 2 придумать что-то, но мне лень
Начнем с простого вопроса: ты изучил как работает система публикации статики в юи? Если нет, то начни с этого. Скорее всего там уже все сделано как нужно и надо просто переключить какую-нибудь опцию в конфиге.
не не, не напрягайся, бро, я все понял, огромное спасибо
если все сделано было как нужно, тогда после удаление содержимого из assets, оно б перегенерировало б все
Напишите, пожалуйста, средствами PHP, MySQL, JavaScript форму входа/регистрации нового пользователя. Продумайте самостоятельно необходимые поля. В результате заполнения формы пользователь должен предоставить информацию о себе. Использование различных PHP фреймворков не допускается. Клиент также не должен быть перегружен, максимум Bootstrap & jQuery.
1.Форма должна быть выполнена способом, понятным пользователю, содержать необходимые инструкции, комментарии и т.п. (usability).
2.Должна быть возможность переключения языка интерфейса формы на другой язык.
3.Скрипт должен содержать средства верификации и валидации полей, а также защиту от некорректного ввода данных, спецсимволов, попыток взлома и т.п.
4.Валидация и верификация полей должна проводиться как на клиентской стороне (средствами JavaScript), так и на серверной стороне (средствами PHP).
5.Структура базы данных должна быть обоснованной.
6.Кроме введения текстовых данных пользователь при регистрации должен иметь возможность загрузить графический файл форматов gif, jpg, png.
7.Вспомогательные тексты в форме (названия полей, подсказки, ошибки и пр.) должны быть сформулированы грамотно и понятно пользователю, выдержан деловой и уважительный стиль обращения.
8.Код должен быть написан понятно и аккуратно, с соблюдением табуляции и прочих элементов написания, без лишних элементов и функций, не имеющих отношения к функционалу тестового задания, снабжен понятными комментариями.
9.Обращаем внимание на то, что имеет значение не только техническая часть выполненного задания (коды), но и дизайнерская (внешний вид, логика оформления, полнота инструкций).
10.Пожалуйста, выполняя тестовое задание, обратите особое внимание на качество и безопасность кодов.
После входа должен отображаться профайл зарегистрировавшегося пользователя.
Ого, это где такие легкие тестовые дают? Я бы для начала сверстал простой дизайн, потом сделал бы регистрацию с серверной валидацией, потом логин к ней. Ну а дальше уже допиливать дизайн, смену языков и другие функции которые там просят реализовать.
Алсо
>Пожалуйста, выполняя тестовое задание, обратите особое внимание на качество и безопасность кодов.
Проиграл с безопасности и качества кодов.
А как лучше для них сделать вёрстку - в хтмл файле или просто echo "<html>.."; ?
А то уже сколько дней сижу и думаю как бы всё получше сделать но никак не могу придумать и не приступаю, чёт боюсь.
А ты студентов из ОП-поста хоть делал? Логику и отображение всегда лучше разделять.
Задача про студентов - это по сути и есть твое тестовое, только в задаче ОПа еще редактирование информации есть.
Задание тебе скинули или нам? Если у тебя с этим заданием проблемы, то на работе будет ещё сложнее, двач не поможет.
И хочешь верь, хочешь нет, но мой друг выполнял именно это задание где-то полтора года назад. Он сделал, как по мне, всё аккуратно и в полном соответствии заданию, а его просто проигнорили. Хотя, быть может, у тебя это уже другая фирма/студия, и они просто скопипастили задание.
змеиный_кейс или Змеиный_кейс?
И всё должно быть змеиным - как названия БД, так и таблицы и ячейки?
В гугле забанили?
Задачки хороши, но я бы и учебник какой-то параллельно почитал бы, как вообще вы учили пхп ?
Спасибо
Что почитать
- Мануал по PHP — http://www.php.net/manual/ru/langref.php
- Сайт phptherightway (перевод на русский: http://getjump.me/ru-php-the-right-way/ )
- По PHP: Профессиональное программирование на PHP Джордж Шлосснейгл
- По PHP: Мэтт Зандстра — PHP: Объекты, шаблоны, методики программирования
Спасибо.
https://github.com/TheSidSpears/Students
В большинстве случаев назвают с подчеркиванием, например:
TABLE students
COLUMN group_id (-> groups)
COLUMN birth_year
Хотя я видел и случаи с camelCase.
Также, ответил на оставшиеся посты в старом треде:
>>816227 - 2 задачи по HTML, за август
>>816228 - вопрос по JSON и файлообменнику
Если кого-то пропустил - напомните о себе тут (TheSidSpears, вижу)
SomeApprentice, там на твои посты тоже есть ответы в старом треде, если ты вдруг не видел. например >>815065 и >>815058
Допустим, у меня есть приложение на фронтенде - angularjs, php мне нужно только для выполнения CRUD операций с БД (ну и предварительной валидации, естественно). Мне лучше писать просто напрямую код, используя паттерн TableDataGateway? тот же Slim упростит или усложнит мне жизнь?
NodeJS -- самый топ.
Также, попробовал написать урок по MVC, пока как-то не очень получилось: https://github.com/codedokode/pasta/blob/master/arch/mvc.md
По сути это ничего к тому, что вы тут изучаете отношение не имеет, и вообще уровень дилетанта, но блять, я так подумал, что раз руководство осталось довольно, то значит в нашем мире ещё полно глупых ИП-шников, которым нужен простенький сайт, и которые готовы за него заплатить.
Вот я так и подумал, взять пару списаных машин на 3-их Ксеонах, воткнуть туда виртуализацию и спрятать в серверной, потом раскидать по группам Вконтакте объявления, мол обеспечиваю разработку и сопровождение сайтов. Лепить сайты под копирку на ссаном Вордпрессе и хостить на сраных Ксеонах, пиздя электричество и трафик у государства, получая профит. Ясен пень, ориентироваться на сайты уровня "Скорой компьютерной помощи в Мухосранскнейм" с низкой посещаемостью.
Взлетит не взлетит? Есть тут такие же долбоебы как я? Можно в принципе даже не заморачиваться с машинами, и тупо лить на хостинг уровня Таймвеба.
Взлетит, только будешь делать для такого же мелкого бизнеса. Денег на этом много не заработаешь. Компании посерьезнее уже заказывают у каких-то аутсорсеров то что им нужно (это обычно какие-то специальные вещи, которые ЦМС не предоставляют). С компаниями-аутсорсерами ты не сможешь конкурировать, совсем никак. Только если создашь свою компанию-аутсорсера, но это уже тема для другой доски.
Алсо, подумай о том что будешь делать когда твой заказчик скажет тебе реализовать определенную функцию, а в плагинах для вордпресса и джумлы ты такого не найдешь.
>Алсо, подумай о том что будешь делать когда твой заказчик скажет тебе реализовать определенную функцию, а в плагинах для вордпресса и джумлы ты такого не найдешь.
А без базовых знаний это будет сложно реализовать? Ну например, насилуя гугл запросами "how to create хуйнянейм in php?"
Зависит от сложности задачи и объема работы. Я думаю что реализовать будет совсем не сложно, а вот потом поддерживать то что ты написал - это уже задача не из легких. Почти во всех ЦМС используется ООП код и MVC паттерн, без понимания хотя бы этих вещей, ты будешь городить велосипеды, в которых через несколько месяцев ты сам разобраться не сможешь.
Ясно, понятно. Добра тебе. Займусь тогда для начала простыми решениями на ЦМСках, а параллельно буду надрачивать опыт создания с нуля. Авось взлетит через пару лет на достойный уровень.
Что за задача хоть была?
Решай продвинутые задачи, а потом Студентов.
А вот нихуя не выдает. В том-то и дело, что пустая страница. Ни ошибки, ни хоста. Отчего у меня складывается впечатление, что эта штука не работает совсем. Но почему - решительно не понимаю, ведь эту хрень я слизал с какой-то из статей, в которой все работало.
PHP 5.3 ~5.6
но ведь там 2016ый и PHP7, дружище, никто не любит ретроградов
>>816722
Не бойся, еще будут собеседования
Добавлю для понимания. Я репортил пару месяцев назад об устройстве на работку. На месте обнаружилось что внутри у них PHP 5.3, куча древних скриптов начала нулевых, использующихся по сей день. Вот и было принято решение как-то красиво это древнее дерьмо потихоньку перебирать, лучше на основе какого-нибудь фреймворка. Также до конца этого года есть планы по обновлению PHP до 5.6 максимум, а то и старше. Такие дела.
>>817079
>от и было принято решение как-то красиво это древнее дерьмо потихоньку перебирать, лучше на основе какого-нибудь фреймворка
Плохое решение, лучше бы начать рефакторинг всего и просто рядом писать все с нуля используя старые наработки.
Ибо завернув говно в красивую обертку ты получаешь еще больше говна и так программист за программистом, пока вся систем не развалится окончательно. Ты случайно не порталами недвижимости занимаешься?
>есть планы по обновлению PHP до 5.6 максимум
Странные планы, переход с 5.6 на 7 довольно прост, не лучше ли опять же начать сразу с семерки.
Попробуй донести это до руководства, потому что они захотят больше улучшений, а улучшать то что ты описал, явно будет физически больно.
Переписывание и имелось в виду, и чтобы не плодить опять сотни решений для базовых задач нужна база.
> Ты случайно не порталами недвижимости занимаешься?
Совсем мимо
> Странные планы, переход с 5.6 на 7 довольно прост
Админ звереет от упоминания любого апгрейда, поэтому на серваке крутится древний дистр, где даже официальных пакетов 5.6 нет
Также какого-то хуя вся система и файлы на сервере в кои8, как же разрывает от этого постоянно
public function getCount()
{
$pdo = $this->getPdo();
$query = $pdo->prepare("SELECT COUNT(*) FROM table");
$query->execute();
$result = $query->fetchColumn();
return $result; //string(3) "110"
}
С этим можно работать? По идее, php само преобразует в нужный формат, но не следует ли нам самим возвращать нужный тип данных?
Гугли PDO::PARAM_INT, как-то так. По поему диванному мнению, лучше уж явно преобразовывать (тем более, что PDO предоставляет возможность), чем позволять инструменту делать конверсию типов за тебя (привет JS).
У тебя $name каждый раз перезаписывается, а нужно, чтобы предыдущее значение "соединялось" с новым. Погугли конкатенацию в PHP.
Спасибо, буду смотреть на Yii и держаться
давайте сделаем вебинар где опытные пхп куны расскажут и покажут как делать например простой форум за 15 минут с регистрацией и коментами или как замутить свой онлайн магазин.
Зачем это нужно? Лучше самому решать задачи из ОП-поста, они будут полезнее форума или онлайн магазина. Плюс так ты большему научишься.
да толку с этих задач. основная их функция это научиться синтаксу и все. в прикладном плане они бесполезны...
И каким же образом будут полезен форум или онлайн магазин в прикладном плане? Тебе так хочется делать говно на вордпрессе для индусов и пакистанцев?
Да.
Интересует именно идентификация переменной, про {% if var is defined %} я знаю что писать вместо var
Для этого тебе нужно передавать твигу массив $_FILES. Но ООП подходом было бы вообще не трогать этот массив и использовать средства фреймворка, с которым работаешь.
<input type="hidden" name="act" value="create">
А на странице обработчике
if($_POST["act"]=="create") {
//выполняем определённое действие
}
if($_POST["act"]=="edit") {
//выполняем ещё какое-то действие
}
У меня вопрос, сильно ли это паливно делать скрытые поля таким образом и для таких целей? Так уже давно никто не делает?
Если страница занимается только обработкой этих форм, не проще ли передать интент через имя формы?
Да, наверное легче, это будет правильнее? Так можно делать с точки зрения безопасности?
Я думаю уроков по скачиванию и установке движка форума предостаточно. Это не требует каких-то особых навыков кроме компьютерной грамотности и может умения настраивать Апач или закчивать файлы по sftp.
Например https://www.google.ru/search?q=установка+форума+php&newwindow=1&gbv=1&sei=_oOrV4fnCoL_sQHmzo-YDQ
У нас обучение программированию.
Незачем в шаблоне лезть в _FILES. Ты явно делаешь что-то не так.
>>817434
Высыпаться и отдыхать, делать перерывы, не сидеть весь день за компьютером.
>>817452
> я хочу обрабатывать их все на одной отдельной странице, поэтому прописываю им повсюду в action её адрес. Так правильно делать?
скорее всего нет. Как ты при ошибке выведешь исходную форму? Плюс у разных форм логика обработки разная. Есть урок по обработке форм на моем гитхабе https://github.com/codedokode/pasta/blob/master/forms.md
>>817469
Можно через яваскриптовое АПИ наверно. Т е отслеживать установку точки пользователем на карте и запоминать координаты.
Твоя идея подразумевает то что для добавления комментария-корня и комментария-ребенка у тебя будет разный код? Или я что-то не так понял?
Можно сделать по другому - чтобы не делать два пути для добавления комментариев, можно сделать один /site.com/[fileId]/[addComment]/
Затем в форму добавления древовидного комментария (комментария к комментарию) добавлять hidden инпут с значением parendId = n. Где n - айди родителя.
Потом в контроллере просто проверяешь, есть ли в POST запросе элемент parentId. Если есть - значит это комментарий-ребенок, если нет - значит комментарий корень дерева. Таким образом код для добавления всех комментариев будет общий.
Нет, не разный код. Все ссылается на один метод контроллера run. Я хотел выстроить логику за счет отсутствия параметра (commentParentID). Hidden поле? Ого, сам бы не додумался, спасибо, попробую.
Выплыл первый подводный камень. У меня есть ссылка <a>Ответить</a> которое открывает спрятанную форму ответа на комментарий. Как шаблон поймет где открывать эту форму? Не очень красиво будет если под каждый комментарием она заранее будет. Наверное такие вещи через js решаются, да? Я его еще не изучил.
Есть несколько способов решения этой проблемы.
Первый способ будет выглядеть не очень красиво, но он будет работать в браузерах с выключенным javascript.
При выводе комментария делаешь ссылку под ним, которая будет выглядеть как-то так: site.com/fileId/?comment=n (где n - айди комментария).
Затем тебе этот n из ссылки нужно будет передавать в шаблон, и там уже выводить форму под нужным комментарием.
Проблемы этого способа очевидны: чтобы ответить на какой-то комментарий, пользователю придется каждый раз перезагружать страницу. Чтобы решить эту проблему, можно использовать JS.
Для этого тебе нужно будет изучить как работать с деревом DOM и как отправлять ajax запросы в JS. Тебе наверное с этим придется самому разобратся, потому что у ОПа нет уроков в которых это объясняется.
как будто то о чем я писал это не программирование...
и лучше бы фреймворки объяснили, хотя бы простые. то что у вас это скорее введение в алгоритмы
Как сделать поддомен вида backend.example.loc?
В httpd-vhosts.conf что надо прописать?
У меня там вот это для первого:
<VirtualHost звёздочка:80>
ServerAdmin web,s{masterANUSexwWiamplePUNCTUMg}!com
DocumentRoot "c:/Apache24/htdocs/new/frontend/web/"
ServerName example.loc
ErrorLog "c:/Apache24/htdocs/new/error_frontend.log"
CustomLog "c:/Apache24/htdocs/new/error_frontend.log" common
</VirtualHost>
При этом в httpd.conf раскомментирована работа httpd-vhosts.conf и если поставить проcто ServerName localhost, то все работает.
То всё работает по адресу localhost.
Любой другой не работает: local, host и т.п.
Забыл сказать, хотя уже понятно: нужно для разделения папок с фронтендом и бэкендом в приложении.
Мне нужно добавить в каждый из 50 файлов спойлер (или подкатегорию). Должно быть так: заходишь в одну из 50-и, а там еще три объекта с описанием.
Как мне это сделать, не зарываясь в книги?
Для того, чтобы динамически менять что-то на странице (раскрывать форму ответа при клике по ссылке "ответить"), нужен либо продвинутый CSS, либо яваскрипт.
На CSS это делается так: под каждым комментарием закладывается скрытая форма ответа и раскрывается при клике на кнопку (а не ссылку) "ответить". Но это очень неэффективно так как надо заложить в страницу много копий одной и той же формы, это только утяжеляет страницу.
На JS делается так: в страницу встраивается программа на JS, которая отслеживает нажатие кнопки "ответить" и перемещает форму ответа под нужный комментарий. Также, вписывает в скрытое поле формы id комменатрия на который дается ответ.
Но и без JS мы можем извернуться. Во-первых, мы можем сделать ответ на комментарий на отдельной странице. То есть "ответить" будет ссылкой вида /file/:fileId/reply/:parentId на которой выводится родительский комментарий и форма ответа под ним. Такая схема позволяет позже сделать "прогрессивное улучшение" с помощью яваскрипта. Если у пользователя есть яваскрипт, то клик по ссылке перехватывается, и вместо перехода на отдельную страницу под комментарием показывается форма ответа. А при отправке формы будет отправляться аякс-запрос на адрес со страницей комментирования.
Также, есть еще другой вариант. Мы можем сделать форму ответа внизу, а рядом с каждым комментарием сделать радиокнопку. Пользователь выбирает, на какой комментарий он хочет ответить, и заполняет форму. Если завернуть комментарий в label, то клик по любому месту комментария будет нажимать связанную с ним радиокнопку. Средствами CSS можно подсвечивать выбранный комментарий.
Хотя, наверно вариант с отдельной страницей все же получается попроще в реализации.
Я тебе советую учиться делать страницу именно с возможностью "прогрессивного улучшения" и работы без яваскрипта. Это может помочь тебе более правильно организовывать свой код.
>И ты ради этого учил программирование?
Надо и начинать с чего-нибудь, благо что нагрузка здесь минимальная
Уроков нет, но есть полезные задачи по JS https://gist.github.com/codedokode/ce30e7a036f18f416ae0
>>817543
Чтобы браться за фреймворки, надо сначала изучить много чего другого и как минимум сделать студентов. Нужно уверенно знать язык, ООП, некоторые паттерны вроде DI.
>>817566
Добавить новый поддомен в hosts, добавить новый виртуальный хост в конфиг апача.
https://www.google.ru/search?q=апач+добавить+виртуальный+хост&newwindow=1&gbv=1&sei=iRWsV-abI4HOsAHt3rXoBg
Я вот боюсь на такие работы идти, чтоб потом не облениться и не привыкнуть говнокодить и говночистить. Типа "и так не плохо кормят". Правда есть опасения, что большинство компаний всё-таки хотят быстрых результатов и болт кладут на то, чему ОП приучает. И соответственно, придётся попыхтеть, чтоб найти норм компанию, где будешь развиваться.
Есть и минус этого - мог бы уже идти на джуна в кусофт и т.п. шараги и получать хоть что-то, а так сижу дома и еще полгода минимум буду сидеть и учиться кодить забесплатно
>А сколько это будет длится?
Бесконечно долго, так как нужно работать и дела делать параллельно и возможно вообще дропнится, но попробовать хочу
Зря не пошёл. Посмотреть на различные решения написанные со смекалочкой стоит + сидишь на зарплате.
А когда рабочий день кончается (можно и в его время), по-прежнему, пилю всякие проектики для развития
Кое что поменял в коде, теперь расшифровывает не так как было.
Возможно. Но у меня помимо программирования другие увлечения. И я хочу программировать на работе, а вечером развиваться в других направлениях. Программировать дополнительно разве что на выходных, для того чтобы на месте не стоять, повышать скилл и зп
>>815058
>Это верно. Потому что тут ты меняешь тип метода, и соответственно придется менять места его использования. А вот если тип остается прежним, но например, меняется алгоритм хеширования (или исправляется ошибка в нем) - остальной код трогать не придется.
Но если мы не меняем тип, то остальной код тоже не придётся трогать. Не могу понять как инкапсуляция тут помогает.
>>815058
>> public function setProperty($property, $value) {
>Это вообще не очень хорошая вещь. Во-первых, она не проверяет имя поля и позволяет создать поле с любым именем. Во-вторых, она по большому счету нарушает инкапсуляцию. Потому что, если ты добавишь в сеттер setName() какую-то проверку, то она не будет вызвана в setProperty().
У меня есть похожие методы на этот которые обращаются к полям не через сеттеры. Их тоже следует исправить?
>>815058
>Ну иногда такие классы называют Сервис, иногда Хелпер.
Тогда я бы предпочел иметь Сервисы (классы отвечающие за внутреннюю логику) и Хелперы (классы содержащие вспомогательные методы) в разных директориях. Это не критично если я буду пользоваться таким подходом?
По хорошему, мне, наверно, следует перенести логику из контролеров в сервисы.
https://github.com/someApprentice/Students/blob/master/app/Model/Gateway/StudentGateway.php#L10
Я решил не раздувать код и сделать сортировку или получение определенного количество записей прям в функции getAllStudents(), потому что у неё одинаковый запрос. Следует ли её переименовать в связи тем что она теперь может получать не всех студентов?
>$limit = 2147483647
В мануале по mysql сказано о том что если нужно получить все записи, то нужно указать какое-то большое число
https://dev.mysql.com/doc/refman/5.7/en/select.html
>To retrieve all rows from a certain offset up to the end of the result set, you can use some large number for the second parameter. This statement retrieves all rows from the 96th row to the last:
>SELECT * FROM tbl LIMIT 95,18446744073709551615;
Это действительно так? Бывают ли на практике такие ситуации что нужно получить количество записей большее чем позволяет максимальное значение int?
https://github.com/someApprentice/Students/blob/master/app/Controller/Controller.php#L22
Для борьбы с sql инъекциями, я решил что удобней будет делать проверку на разрешенные колонки в методе получения запроса, чем в методе выполнения этого запроса. Так ведь тоже можно?
https://github.com/codedokode/pasta/blob/master/security/sql-injection.md#Методы-борьбы
>if (!in_array($sort, $allowed)) {
> $sort = $allowed[0];
>}
А почему $allowed[0] возвращает найденное значение? Я в мануале не нашел чтобы описывался такой синтаксис, и у меня не получилось сделать так же в моем условии https://github.com/someApprentice/Students/blob/master/app/Controller/Controller.php#L35
https://github.com/someApprentice/Students/blob/master/app/Controller/IndexAction.php#L38-L53
https://github.com/someApprentice/Students/blob/master/app/Controller/SearchAction.php#L29-L44
Это ведь тоже копипаста, верно? Я только что подумал что это код можно вынести в отдельный методов родителя контроллеров. Скоро исправлю.
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/LoginHelper.php#L55
Я помню как ты говорил, что методы можно делать статическими если всегда будут возвращать одно и то же значение и не имеют никаких зависимостей, но в этот метод передается и меняется класс Student. Не является ли это зависимостью?
Если мы инкапсулируем методы то не следует нам их сделать закрытыми?
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/LoginHelper.php#L61
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/LoginHelper.php#L68
Как закрыть эти методы? Если я пытаюсь обратиться к ним в статическом методе через $this, то я получаю ошибку о том что обращаюсь не в контексте объекта.
>>815058
>Это верно. Потому что тут ты меняешь тип метода, и соответственно придется менять места его использования. А вот если тип остается прежним, но например, меняется алгоритм хеширования (или исправляется ошибка в нем) - остальной код трогать не придется.
Но если мы не меняем тип, то остальной код тоже не придётся трогать. Не могу понять как инкапсуляция тут помогает.
>>815058
>> public function setProperty($property, $value) {
>Это вообще не очень хорошая вещь. Во-первых, она не проверяет имя поля и позволяет создать поле с любым именем. Во-вторых, она по большому счету нарушает инкапсуляцию. Потому что, если ты добавишь в сеттер setName() какую-то проверку, то она не будет вызвана в setProperty().
У меня есть похожие методы на этот которые обращаются к полям не через сеттеры. Их тоже следует исправить?
>>815058
>Ну иногда такие классы называют Сервис, иногда Хелпер.
Тогда я бы предпочел иметь Сервисы (классы отвечающие за внутреннюю логику) и Хелперы (классы содержащие вспомогательные методы) в разных директориях. Это не критично если я буду пользоваться таким подходом?
По хорошему, мне, наверно, следует перенести логику из контролеров в сервисы.
https://github.com/someApprentice/Students/blob/master/app/Model/Gateway/StudentGateway.php#L10
Я решил не раздувать код и сделать сортировку или получение определенного количество записей прям в функции getAllStudents(), потому что у неё одинаковый запрос. Следует ли её переименовать в связи тем что она теперь может получать не всех студентов?
>$limit = 2147483647
В мануале по mysql сказано о том что если нужно получить все записи, то нужно указать какое-то большое число
https://dev.mysql.com/doc/refman/5.7/en/select.html
>To retrieve all rows from a certain offset up to the end of the result set, you can use some large number for the second parameter. This statement retrieves all rows from the 96th row to the last:
>SELECT * FROM tbl LIMIT 95,18446744073709551615;
Это действительно так? Бывают ли на практике такие ситуации что нужно получить количество записей большее чем позволяет максимальное значение int?
https://github.com/someApprentice/Students/blob/master/app/Controller/Controller.php#L22
Для борьбы с sql инъекциями, я решил что удобней будет делать проверку на разрешенные колонки в методе получения запроса, чем в методе выполнения этого запроса. Так ведь тоже можно?
https://github.com/codedokode/pasta/blob/master/security/sql-injection.md#Методы-борьбы
>if (!in_array($sort, $allowed)) {
> $sort = $allowed[0];
>}
А почему $allowed[0] возвращает найденное значение? Я в мануале не нашел чтобы описывался такой синтаксис, и у меня не получилось сделать так же в моем условии https://github.com/someApprentice/Students/blob/master/app/Controller/Controller.php#L35
https://github.com/someApprentice/Students/blob/master/app/Controller/IndexAction.php#L38-L53
https://github.com/someApprentice/Students/blob/master/app/Controller/SearchAction.php#L29-L44
Это ведь тоже копипаста, верно? Я только что подумал что это код можно вынести в отдельный методов родителя контроллеров. Скоро исправлю.
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/LoginHelper.php#L55
Я помню как ты говорил, что методы можно делать статическими если всегда будут возвращать одно и то же значение и не имеют никаких зависимостей, но в этот метод передается и меняется класс Student. Не является ли это зависимостью?
Если мы инкапсулируем методы то не следует нам их сделать закрытыми?
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/LoginHelper.php#L61
https://github.com/someApprentice/Students/blob/master/app/Model/Helper/LoginHelper.php#L68
Как закрыть эти методы? Если я пытаюсь обратиться к ним в статическом методе через $this, то я получаю ошибку о том что обращаюсь не в контексте объекта.
Решил почитать Ваших уроков из ОП-поста. До регулярных выражений оно все было просто и понятно, но дошел я до задачи про номера и всё, уперся как баран в новые ворота.
Если автору уроков кажется, что фраза "сначала идет +7 или 8, за ними ровно 10 цифр, между которыми может быть любое число скобок, минусов, пробелов" интуитивно наталкивает на решение, то эта далеко не так.
Подскажите же шаблон, который находит точное количество одних элементов, при этом игнорирует наличие других.
А то я уже начинаю с катушек слетать
http://regexone.com/lesson/introduction_abcs
Не знаю что там в оп-посте, но вот ресурс, который мне пояснил за регулярки раз и навсегда. Я даже в букмарки добавил его.
Я решил так -http://ideone.com/chUPjC
Результат нужный получается, однако у меня чувство что мой алгоритм - алгоритм уровня /б
Вобще я нуб, на одну задачу дальше тебя ушёл. но вангую что это из-за Юникода.
В задачнике есть ссылка - "Почему функции вроде strlen() не работают с русским текстом и надо использовать mb_strlen()."
Байты, туда сюда. но сука - mb_strtr - вызывает ошибку.
Раз: https://yandex.ru/yandsearch?&clid=2186621&text=mb_strtr&lr=213 - поисковики такой ф-ии не знают. Вероятно, её на существует
Два: http://phpforum.su/index.php?showtopic=41776 - похожая проблема и ссылка на решение
Три: http://stackoverflow.com/questions/2758736/multibyte-strtr-mb-strtr - написание этой ф-ии вручную
Примерно полминуты времени
А ты попробуй подойти к решению постепенно.
Напиши сначала выражение которое значит "ровно одна цифра и любое число минусов, скобок , пробелов"
Затем возьми его в скобки и поставь конструкцию, задающую повторение предыдущего выражения 10 раз.
Посмотри внимательно на свой алгоритм шифрования. Ты заменяешь й на 11, но аа тоже будет заменено на 11. Как это расшифровать? Тут проблема не в коде, а в логике его автора.
>>817900
Попробуй найти описание функции mb_strtr в мануале php.net. Такая функция существует? Кстати в случае strtr обычная версия этой функции нормально работает с кирилицей.
>>817907
Это читал? https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md
>>817916
Лучше не использовать shuffle так как он портит порядок с лов в исходном массиве
По поводу способа с отдельной страницей. Это будет страница с обычной шапкой, но вместо предыдущего контента с информацией о файле будет эта форма? Это новый контроллер или новый метод предыдущего контроллера?
> но вместо предыдущего контента с информацией о файле будет эта форма?
Комментарий, на который отвечают (при желании можно еще его родителя добавить) и форма, да.
> Это новый контроллер или новый метод предыдущего контроллера?
Без разницы
Тоесть, ты предлагаешь что-то типа этого
http://ideone.com/1aN7OL ?
Хоспаде! Как же я был слеп!. Спасибо, Анон, я два дня буксовал на этом месте
$query = "SELECT COUNT(*) + 1
FROM comments
WHERE fileID = :fileID AND
commentID = :commentParentID";
array_shift
Пока что на ум приходит только
$query = "первые 3 строки";
if (empty($cPID))
$query .= "последняя строка";
!empty быстрофикс
Но это приведет к тому что для bindValue в pdo тоже придется вставлять логику.
>>818113
Так как поле состоит из клеточек, у тебя может появиться желание сделать двухмерный массив для хранения животных. Не советую так делать, ведь этот массив надо будет поддерживать в актуальном состоянии. Проще хранить обычный одномерный массив животных, находящихся на карте.
Не понятно, как после этого выводить на экран, да и как "двигать" животных по полю, если массив одномерный а поле двумерное
Вывести одномерный массив как двумерное поле не сложно. Но там речь идет о животных, а не о поле.
Когда-то мне ответили следующее:
> А зачем нам нужен двухмерный массив букв если удобнее просто хранить список животных? У них ведь есть координаты так что массив с буквами избыточен.
>У них ведь есть координаты так что массив с буквами избыточен.
Теперь дошло. Вот это мне и нужно было.
Добра
>Но у меня помимо программирования другие увлечения
Программистом тебе не стать, максимум говнокодером
Заскринил на память
Как подружить базу с кириллицей? Кодировка базы и таблицы: utf8_general_mysql500_ci
Ошибка только при кириллице, когда всё на латинице - отлично записывает
> А зачем нам нужен двухмерный массив букв если удобнее просто хранить список животных? У них ведь есть координаты так что массив с буквами избыточен.
А если мне нужно узнать, что находится в клетке с координатами, к примеру, (3, 5), то нужно использовать полный перебор одномерного массива. С двумерным массивом такой необходимости не возникнет.
Проверьте пожалуйста решение задач:
Еще один кредит https://github.com/enotocode/anothercredit
Экранирование https://github.com/enotocode/screening
Я тебя помню https://github.com/enotocode/anothercredit
http://ideone.com/ERzeV6
Это правильно? Или я уже вступил на путь говнокодера?
http://ideone.com/cbTM6J Доделал.Так лучше?
У опа на картинке замыленной очень много текста в ширь в коде. Я хз кароч.
http://ideone.com/x4jpom
$rand1 = array_rand($word1);
$rand2 = array_rand($word2);
$rand3 = array_rand($word3);
$rand4 = array_rand($word4);
$rand5 = array_rand($word5);
$finalWord1 = $word1[$rand1];
$finalWord2 = $word2[$rand2];
$finalWord3 = $word3[$rand3];
$finalWord4 = $word4[$rand4];
$finalWord5 = $word5[$rand5];
Неужели ты копипасты не видишь? Вот это всё в цикл оборачивай. И погугли конкатенацию строк в PHP.
А лучше прочитать следующий урок и оформить функцией.
Конкатенация склеит все время. А как сделать тогда рандом нескольких строк? Пробовал массивы в массив воткну
Ну подумай, не разжевывать же всё тебе. Почему одним анонам хватает предложения погуглить конкатенацию, а тебе нет?
Потому что я уже погуглил.
Разжуйте мне, если нетрудно, с каких хуёв $this->имяФункции отказывается работать? Перед этим делал в абстрактном классе - хуй там плавал, то же самое
Почитай про ООП, про магический метод __construct() в частности. А то в глаза ебешься.
Это разве не для добавления аргументов в класс? Ну да ладно, у меня вопрос состоит в другом, почему когда я пытаюсь передать значение метода переменной, при вызове метода происходит ошибка? Я неправильно его вызываю?
Во-первых, ты сам ответил на свой вопрос, во-вторых, и вызываешь ты неправильно. Метод должен получать аргумент, ты его методу не предоставляешь.
И разберись с наследованием, на кой ты переопределяешь метод в дочернем классе? У тебя щас каша в голове, ты не понимаешь что делаешь. Найди какую-нибудь книжку из разряда робина никсона для начинающих, там на пальцах разложено что куда и для чего.
>Заскринил на память
Заскринь ещё кое что себе за щеку
Ты просто не представляешь насколько глубока кроличья нора. Когда я начинал, то мне казалось, что пары книг и стандартного набора PHP-HTML-CSS-JS-MYSQL хватит до пенсии. Но, как выяснилось, это даже не начало. Дай бог 10% от нужных знаний, чтобы быть профессиональным программистом.
Ну уж не настолько хреново как у нашего товарища. Тут нужно понять смысл, я вот задачку про студентов так и делал, посмотрел примитив у никсона, понял в чем суть и начал наворачивать на этот скелет то что в своей задаче предлагает ОП.
Если человек осознает, что он ничего не знает, значит он уже не дурак. Удачи, бро.
Меня только это и утешает на пути к погромизму, кек.
В каждом представлении пишу {{ include('head.html') }}
Вызываю представление так: return $this->view->render($response, 'upload.html', $args);
});
Как правильно сделать так, чтобы файлы шапки и футера инклудились автоматически, без прописывания в каждом шаблоне?
Всё в порядке в PHP с рекурсией. Причем здесь рекурсия, там приоритет операторов важен, что ты вообще пытаешься сделать, скинь пример на ideone. Только что засунул (3+(6*2-1)-4) в var_dump и он мне выдал 10.
>>818866
Использовать Twig.
>>818792
Вряд ли ты в сети найдёшь статью, которая так же доступно и просто объясняет регулярки. Мне та статья очень сильна помогла с ними разобраться.
У нас есть два файла в /public: index.php и register.php. Когда пользователь обращается к нашему приложению localhost/path/studentslist/ запускается скрипт index.php, который запрашивает куки пользователя и сверяет хэш, если хэш не задан (или такого нет в базе), то он запускает скрипт register.php?
Register.php тоже, должен определить зарегистрирован пользователь или нет. Можно передать дополнительный параметр в url, или проверять хэш снова?
Каким образом запускается register.php, через require? Или редиректом?
В условиях задачи написано, что после регистрации пользователя, должен быть редирект, опять на "index.php"? А лист студентов (результат посика), просто подгружает шаблон, но адрес остается тот же "...index.php", то есть не перенаправляет пользователя на страницу "...list.php..."?
как передать контроллерам, где хранятся файлы классов из директории "../app", с помощью __autoload() или директивой include_path, в файле настроек *.ini? А как подключать файл настроек?
Да я уже разобрался с рекурсией. Нужно было просто нормально описать условие окончания рекурсии, то есть для каждой веточки проверяемых условий и не забыть написать return в соответствующих местах.
Теперь есть куда посылать задающих элементарные вопросы.
>>818984
Почитай доки, полазай по коду и посмотри как обрабатывается твой запрос.
>>818927
Файл ini для настроек которые будет менять конечный пользователь (который разворачивает твой проект на своем сайте). зачем ему менять названиее папки с классами?
Ее можно просто прописать в коде. Контроллерам передавать это название не требуется, используй автозагрузку классов.
Тебе надо разобраться с автозагрузкой, есть урок на гитхабе https://github.com/codedokode/pasta/blob/master/php/autoload.md
>>818923
> Когда пользователь обращается к нашему приложению localhost/path/studentslist/ запускается скрипт index.php, который запрашивает куки пользователя и сверяет хэш, если хэш не задан (или такого нет в базе), то он запускает скрипт register.php?
Вообще, это не обязательно. Я бы на главной выводил список, а переход на страницу регистрации/редактирования сделал по ссылке.
Чтобы определить, кто просматривает страницу, пользователь ли аноним, надо проверять куки по базе. для этого надо сделать отдельный метод. Удобно все, что связано с авторизацией (логин, разлогин, проверка) сразу вынести в отдельный класс.
> Каким образом запускается register.php, через require? Или редиректом?
Переход на форму авторизациии (при доступе к закрытой странице) и возврат лучше делать редиректами.
> А лист студентов (результат посика), просто подгружает шаблон, но адрес остается тот же "...index.php", то есть не перенаправляет пользователя на страницу "...list.php..."?
В задаче имелось в виду что на index.php как раз и выводится список.
>>818881
А урок ОПа по регуляркам разве не объясняет?
Алсо есть мануал http://php.net/manual/ru/pcre.pattern.php
>>818792
Если не понимаешь, надо перечитать еще раз, поискать другие уроки по теме, попросить у ОПа дополнительные задачи повышенной сложности.
Алсо есть такая статья (очень сложная) https://habrahabr.ru/post/171667/
>>818756
Все сразу знать не требуется.
>>818671
У меня ощущение, что ты учил какой-то другой язык программирования и пытаешься знания из него применить к пхп. Так не пойдет. В разных языках разный синтаксис и разные правила использования конструкций, даже если они одинаковов называются.
Перечитай внимательно учебник. Почитай официальный мануал, раздел про классы и объекты.
$rank это не обычная переменная, а поле и обращаться к ней в методе надо как $this->rank.
> public $salary = getSalary;
Там вообще писать нельзя. Справа при объявлении поля указывается его значение по умолчанию. Что такое getSalary? В данном случае пхп воспринимает это как константу (так как знака доллара или кавычек вокруг нее нет), которая нигде не объявлена, что и вызывает ошибку.
Теперь есть куда посылать задающих элементарные вопросы.
>>818984
Почитай доки, полазай по коду и посмотри как обрабатывается твой запрос.
>>818927
Файл ini для настроек которые будет менять конечный пользователь (который разворачивает твой проект на своем сайте). зачем ему менять названиее папки с классами?
Ее можно просто прописать в коде. Контроллерам передавать это название не требуется, используй автозагрузку классов.
Тебе надо разобраться с автозагрузкой, есть урок на гитхабе https://github.com/codedokode/pasta/blob/master/php/autoload.md
>>818923
> Когда пользователь обращается к нашему приложению localhost/path/studentslist/ запускается скрипт index.php, который запрашивает куки пользователя и сверяет хэш, если хэш не задан (или такого нет в базе), то он запускает скрипт register.php?
Вообще, это не обязательно. Я бы на главной выводил список, а переход на страницу регистрации/редактирования сделал по ссылке.
Чтобы определить, кто просматривает страницу, пользователь ли аноним, надо проверять куки по базе. для этого надо сделать отдельный метод. Удобно все, что связано с авторизацией (логин, разлогин, проверка) сразу вынести в отдельный класс.
> Каким образом запускается register.php, через require? Или редиректом?
Переход на форму авторизациии (при доступе к закрытой странице) и возврат лучше делать редиректами.
> А лист студентов (результат посика), просто подгружает шаблон, но адрес остается тот же "...index.php", то есть не перенаправляет пользователя на страницу "...list.php..."?
В задаче имелось в виду что на index.php как раз и выводится список.
>>818881
А урок ОПа по регуляркам разве не объясняет?
Алсо есть мануал http://php.net/manual/ru/pcre.pattern.php
>>818792
Если не понимаешь, надо перечитать еще раз, поискать другие уроки по теме, попросить у ОПа дополнительные задачи повышенной сложности.
Алсо есть такая статья (очень сложная) https://habrahabr.ru/post/171667/
>>818756
Все сразу знать не требуется.
>>818671
У меня ощущение, что ты учил какой-то другой язык программирования и пытаешься знания из него применить к пхп. Так не пойдет. В разных языках разный синтаксис и разные правила использования конструкций, даже если они одинаковов называются.
Перечитай внимательно учебник. Почитай официальный мануал, раздел про классы и объекты.
$rank это не обычная переменная, а поле и обращаться к ней в методе надо как $this->rank.
> public $salary = getSalary;
Там вообще писать нельзя. Справа при объявлении поля указывается его значение по умолчанию. Что такое getSalary? В данном случае пхп воспринимает это как константу (так как знака доллара или кавычек вокруг нее нет), которая нигде не объявлена, что и вызывает ошибку.
При объявлении поля справа можно писать только примитивное значение, например, число, строку или массив. Нельзя писать выражение или использовать $this.
>>818623
заводишь переменную для результата, кладешь в нее пустую строку. В цикле генерируешь случайный слог и приклеиваешь его к той переменной. Постепенно в ней соберется все имя целиком.
>>818520
> abstract class Creep
Нужно давать хороши названия класам и переменным, иначе код тяжело читать
> $salary += $salary * 0.25;
Можно использовать *=
> class Manager extends Creep
> {
>protected $salary = 500;
>protected $thirst = 20;
Тут есть проблема. Не очевидно что при наследовании надо переопределить именно эти поля и нет никакой проверки что они переопределены. Решить обе проблемы мжно использованием абстрактных методов.
> $numberOfCreeps = count($this->listOfCreeps);
> return $numberOfCreeps
лучше сразу return count(...)
> public function fillListOfCreeps($creep){
Здесь нужен тайп-хинт. Они улучшают твой код, делают его понятнее и защищают от ошибок.
> class Procurement extends Department
>{
>protected $name = 'Закупок';
если департаменты отличаются только названием, наверно незачем под каждый заводить новый класс. проще указывать название при создании.
> for($i = 0; $i < 9; $i++){
>$procurement->fillListOfCreeps($me1);
Тут есть небьольшая проблема. Ты читал уроке раздел про копирование объектов? Ты ведь добавляешь в массив 9 ссылок на один и тот же объект. Соответственно при решении второй части задачи, если ты например захочешь кому-то повысить зарплату. ты повысишь ее всем 9 работникам, так как это 9 ссылок на один объект.
заполнение также стоит чуть-чуть автоматизировать. Например сделать массив вида
['3me1', '2en1']
или
[
[3, Manager::class, 1],
[3, Engineer::class, 1],
...
]
и создавать работников в соответствии с закодированным там списком
Также, плохо перемешивать определение функций или классов и обычный код. Лучше сначала определить все классы а потом поставить код создания объектов.
Насчет неправильного расчета- а ты посчитай вручную и сравни. В учебнике цифры по моему взяты с потолка.
При объявлении поля справа можно писать только примитивное значение, например, число, строку или массив. Нельзя писать выражение или использовать $this.
>>818623
заводишь переменную для результата, кладешь в нее пустую строку. В цикле генерируешь случайный слог и приклеиваешь его к той переменной. Постепенно в ней соберется все имя целиком.
>>818520
> abstract class Creep
Нужно давать хороши названия класам и переменным, иначе код тяжело читать
> $salary += $salary * 0.25;
Можно использовать *=
> class Manager extends Creep
> {
>protected $salary = 500;
>protected $thirst = 20;
Тут есть проблема. Не очевидно что при наследовании надо переопределить именно эти поля и нет никакой проверки что они переопределены. Решить обе проблемы мжно использованием абстрактных методов.
> $numberOfCreeps = count($this->listOfCreeps);
> return $numberOfCreeps
лучше сразу return count(...)
> public function fillListOfCreeps($creep){
Здесь нужен тайп-хинт. Они улучшают твой код, делают его понятнее и защищают от ошибок.
> class Procurement extends Department
>{
>protected $name = 'Закупок';
если департаменты отличаются только названием, наверно незачем под каждый заводить новый класс. проще указывать название при создании.
> for($i = 0; $i < 9; $i++){
>$procurement->fillListOfCreeps($me1);
Тут есть небьольшая проблема. Ты читал уроке раздел про копирование объектов? Ты ведь добавляешь в массив 9 ссылок на один и тот же объект. Соответственно при решении второй части задачи, если ты например захочешь кому-то повысить зарплату. ты повысишь ее всем 9 работникам, так как это 9 ссылок на один объект.
заполнение также стоит чуть-чуть автоматизировать. Например сделать массив вида
['3me1', '2en1']
или
[
[3, Manager::class, 1],
[3, Engineer::class, 1],
...
]
и создавать работников в соответствии с закодированным там списком
Также, плохо перемешивать определение функций или классов и обычный код. Лучше сначала определить все классы а потом поставить код создания объектов.
Насчет неправильного расчета- а ты посчитай вручную и сравни. В учебнике цифры по моему взяты с потолка.
> ($properties,
А почему тут массив? У тебя же есть класс Comment? Хотя тут хватило бы просто передать fileId отдельной переменной. Не понимаю, зачем тут массив? Это ведь усложняет использование функции так как непонятно что в нем должно быть.
Насчет определения нового номера для комментария: надо проверять только число непосредственных детей, а не всех потомков. Запрос будет намного проще.
Также, такой запрос:
> CHAR_LENGTH (path) = 3";
не будет использовать индексы и будет перебирать все комментарии. Вместо него надо использовать parent_id IS NULL который можно оптимизировать с помощью индекса.
> SELECT CONCAT(path, '.00', :number)
на мой взгляд, операции с путями выгоднее делать в php. Можно сделать функцию, которая получает на вход номер родителя и генерирует номер ребенка.
Плюс, почему ты решил что там будет ровно 2 нуля? А если number = 100?
Также, нужно еще кое-что. В таблицу надо добавить уникальные индексы, запрещающие вставку одинаковых значений (например одинаковых fileId + path).
Также, а корректно ли работает твой код при параллельной вставке комментариев в несколько потоков? Вот один поток выбрал номер нового комментария, затем другой, затем первый вставляет новый комментарий, затем другой пытается вставить комментарий с тем же номером.
В цикле пишется то, что надо сделать несколько раз подряд. Но 4-е и 5-е слово надо сгенерировать только один раз, а не 2 раза, значит они должны быть не в цикле.
>>818335
Вместо 3 репозиториев наверно удобнее было сделать один с 3 папками.
> https://github.com/enotocode/anothercredit/blob/master/index.php#L20
Ты как шаман, который выполняет неведомые ему ритуалы чтобы изгнать злых духов. Надо применять все функции осознанно, понимая, что они делают а не лепить в надежде что они "очистят" строку.
Да и как вообще можно "очистить" строку? Термин какой-то религиозный, а не из области программирования.
Чтобы не было уязвимостей, надо экранировать данные правильным образом и в правильнмо месте, а не лепить все функции подряд.
В твоем случае данные это числа, потому достаточно сделать трим и преобразовать их в число.
Также, ты используешь массив $values, но тут всего 3 переменных и проще наверно хранить их в отдельных переменных.
> foreach($_GET as $key => $value) {
Ты проверяешь и валидируешь все элементы массива GET. Но надо проверять только нужные тебе 3 значения. Другие значения может быть нужны будут где-то в другом месте в будущем и не надо их трогать.
> return "Выплатить кредит невозможно так как ежемесячный прирост <strong>{$monthlyGrowth}</strong> р.
HTML теги должны быть в шаблоне. Функция должна возвращать не человеческий текст, а машинночитаемые значения. Например массив значений.
https://github.com/enotocode/anothercredit/blob/master/template.html#L12
Для ввода чисел есть тип type=number, он же позволяет указать минимальное и макс. значение. Не забудь в этом случае с помощью атрибута title указать подсказку, что можно вводить.
Процент кстати может быть дробный.
> <?php if (isset($result)): ?>
Не очень хорошо, когда переменная может быть, а может не быть. Лучше сделать чтобы она всегда была, просто иногда пустая.
> Экранирование https://github.com/enotocode/screening
Экранирование выводимых данных надо делать в шаблоне, чтобы сразу было видно что оно есть. А у тебя глядя только на шаблон это не понять. В реальных приложениях шаблоны огромные и код тоже объемный и проверить будет невозможно.
Вместо br в HTML принято заключать текстарею и кнопку в отдельные блоки.
https://github.com/enotocode/screening/blob/master/template.html#L19
Знак & надо кодировать особым образом в HTML коде.
Вообще, для этих 5 символов коды надо выучить наизусть: < > & ' "
> Я тебя помню https://github.com/enotocode/anothercredit
Ок, все верно.
В цикле пишется то, что надо сделать несколько раз подряд. Но 4-е и 5-е слово надо сгенерировать только один раз, а не 2 раза, значит они должны быть не в цикле.
>>818335
Вместо 3 репозиториев наверно удобнее было сделать один с 3 папками.
> https://github.com/enotocode/anothercredit/blob/master/index.php#L20
Ты как шаман, который выполняет неведомые ему ритуалы чтобы изгнать злых духов. Надо применять все функции осознанно, понимая, что они делают а не лепить в надежде что они "очистят" строку.
Да и как вообще можно "очистить" строку? Термин какой-то религиозный, а не из области программирования.
Чтобы не было уязвимостей, надо экранировать данные правильным образом и в правильнмо месте, а не лепить все функции подряд.
В твоем случае данные это числа, потому достаточно сделать трим и преобразовать их в число.
Также, ты используешь массив $values, но тут всего 3 переменных и проще наверно хранить их в отдельных переменных.
> foreach($_GET as $key => $value) {
Ты проверяешь и валидируешь все элементы массива GET. Но надо проверять только нужные тебе 3 значения. Другие значения может быть нужны будут где-то в другом месте в будущем и не надо их трогать.
> return "Выплатить кредит невозможно так как ежемесячный прирост <strong>{$monthlyGrowth}</strong> р.
HTML теги должны быть в шаблоне. Функция должна возвращать не человеческий текст, а машинночитаемые значения. Например массив значений.
https://github.com/enotocode/anothercredit/blob/master/template.html#L12
Для ввода чисел есть тип type=number, он же позволяет указать минимальное и макс. значение. Не забудь в этом случае с помощью атрибута title указать подсказку, что можно вводить.
Процент кстати может быть дробный.
> <?php if (isset($result)): ?>
Не очень хорошо, когда переменная может быть, а может не быть. Лучше сделать чтобы она всегда была, просто иногда пустая.
> Экранирование https://github.com/enotocode/screening
Экранирование выводимых данных надо делать в шаблоне, чтобы сразу было видно что оно есть. А у тебя глядя только на шаблон это не понять. В реальных приложениях шаблоны огромные и код тоже объемный и проверить будет невозможно.
Вместо br в HTML принято заключать текстарею и кнопку в отдельные блоки.
https://github.com/enotocode/screening/blob/master/template.html#L19
Знак & надо кодировать особым образом в HTML коде.
Вообще, для этих 5 символов коды надо выучить наизусть: < > & ' "
> Я тебя помню https://github.com/enotocode/anothercredit
Ок, все верно.
Да, надо. Тут всегда есть преимущества и недостатки. Например:
- на большом поле 2-мерный массив будет занимать много памяти (10 000 x 10 000 = 100 000 000 ячеек)
- нам надо писать код который будет отслеживать изменение координат животного и обновлять 2-мерный массив. Тут легко сделать ошибку.
- получение списка животных на поле требует полного обхода 2-мерного массива.
Если 2-мерные массивы и используют, то лишь как дополнение для ускоренной проверки на заполненность клетки. В играх также используют и другие оптимизации. Ну например, поле разбивают на "регионы" размером NxN клеток и делают массив таких регионов. Каждый элемент этого массива хранит находящихся рядом животных.
Пока у тебя 10-100 животных и игра состоит из пары десятков ходов, тебе оптимизации не нужны и можно использовать более простой способ хранения.
А без одномерного массива, чтобы предоставить ход всем животным, тебе придется обходить 2-мерный массив большего размера.
Кстати, при использовании инкапсуляции и разделении обязанностей, ты можешь добалвять такие оптимизации, трогая только один класс, а не переделывая весь код.
При создании таблицы или базы данных ты указал DEFAULT CHARSET=utf8? Может у тебя база данных для латиницы сделана.
То что ты указал SET NAMES - этим ты задаешь кодировку в которой ведется обмен данными, передача запросов и ответов. Но еще есть кодировка для хранения данных и она указывается при создании таблицы или базы данных.
>>818119
Вывести очень просто: создаем временный 2-мерный массив и заполняем буквами в соответствие с координатами животных.
>>818106
Давай вопросы. У нас целый тред для этого сделан.
>>818074
Да, придется.
>>818065
Если по-простому, то можно делать так:
$whereComment = '';
if (...) {
$whereComment = '....';
}
$sql = "SELECT ... $whereComment ... ";
+ условие для bindValue.
Если проект большой и серьезный, то обычно используют паттерн Query Builder - построитель запросов (читай мой урок по паттернам работы с БД). Там это делается так:
if (...) {
$query->addWhere('commentId = ?', $commentId);
}
Есть готовые библиотеки с Query Builder.
При создании таблицы или базы данных ты указал DEFAULT CHARSET=utf8? Может у тебя база данных для латиницы сделана.
То что ты указал SET NAMES - этим ты задаешь кодировку в которой ведется обмен данными, передача запросов и ответов. Но еще есть кодировка для хранения данных и она указывается при создании таблицы или базы данных.
>>818119
Вывести очень просто: создаем временный 2-мерный массив и заполняем буквами в соответствие с координатами животных.
>>818106
Давай вопросы. У нас целый тред для этого сделан.
>>818074
Да, придется.
>>818065
Если по-простому, то можно делать так:
$whereComment = '';
if (...) {
$whereComment = '....';
}
$sql = "SELECT ... $whereComment ... ";
+ условие для bindValue.
Если проект большой и серьезный, то обычно используют паттерн Query Builder - построитель запросов (читай мой урок по паттернам работы с БД). Там это делается так:
if (...) {
$query->addWhere('commentId = ?', $commentId);
}
Есть готовые библиотеки с Query Builder.
Можно сделать shuffle и брать первые 2 элемента перемешанного массива.
>>818023
Да, только вот \W у тебя на мой взгляд слишком "всеядная" и пропускает вообще любые символы. МОжет лучше все же указать конкретные символы.
>>817888
В общем-то это верное решение, но есть пара улучшений:
- тяжело читать сложное выражение в echo - лучше вынести отдельные слова в переменные
- первые 2 строчки генерируются одинаково и можно использовать цикл
>>817887
По аналогии с C#? Или что-то из музыки?
> Но если мы не меняем тип, то остальной код тоже не придётся трогать. Не могу понять как инкапсуляция тут помогает.
Допустим у нас есть класс:
class A
{
public $x;
public function setX($x)
{
$this->x = $x;
}
}
Тут как видишь полной инкапсуляции нет. Поле $x не защищено от прямого доступа снаружи. Посторонний код может обращаться к полю $x напрямую, а не через метод setX.
Это приводит к таким проблемам:
- допустим, мы хотим ограничить запись значений в поле, разрешив записывать только числа от 1 до 5. Нам придется искать обращения к полю по всему коду и копипастить туда код проверки. И нет гарантий что завтра где-то не появится новое обращение к полю без проверки.
- допустим мы захотим поменять логику и не хранить значение в классе, а передавать куда-то еще, сохранять в файл или в базу или куда-то еще. Опять же, нам придется обойти весь код, найти там все обращения к полю $x и поменять их на вызов какого-то метода.
В случае же инкапсуляции мы закрываем поле $x и оставляем доступ только к методу. И добавить проверку или поменять логику можно, меняя только один класс и не переделывая весь код. Который может быть очень большим по объему.
Вот представь что ты автор класса, а пользоваться будут им другие люди. Как ты без инкапсуляции гарантируешь, что в поле $x будут числа от 1 до 5, если они видят что поле публичное и могут записать туда любое число?
Ограничение доступа позволяет автору класса вводить ограничения, нужные для корректной работы класса.
Вообще, это относится не только к полям. Всегда лучше ограничивать область где доступно поле, функция, переменная, так как в этом случае проще анализировать код который с ней работает, так как меньше его объем.
Возвращаясь к твоему примеру. мы заключаем код, отвечающий за авторизацию, в класс для того, чтобы весь остальной код ничего не знал про то, как она реализована, а только вызывал нужный ему метод. И чем лучше сделано разделение, тем меньше придется переписывать при смене механизма авторизации.
>>Это верно. Потому что тут ты меняешь тип метода, и соответственно придется менять места его использования. А вот если тип остается прежним, но например, меняется алгоритм хеширования (или исправляется ошибка в нем) - остальной код трогать не придется.
> Но если мы не меняем тип, то остальной код тоже не придётся трогать. Не могу понять как инкапсуляция тут помогает.
Да, придется. А вот если мы смогли реализовать разделение обязанностей так, что при смене механизма авторизации не меняем тип передаваемых данных, то остальной код не придется трогать.
Ну и даже в случае, когда нам приходится менять тип передаваемых данных, инкапсуляция нам помогает, так как мы можем вписать проверку, что нам передали данные правильного типа и таким образом обнаружить код который мы забыли переделать и который передает данные в старом формате.
> У меня есть похожие методы на этот которые обращаются к полям не через сеттеры. Их тоже следует исправить?
Если они в том же классе, то не обязательно. Так как при каких-то изменениях в сеттерах мы их увидим. Но динамическим доступом к полям, когда имя поля определяется в ходе выполнения кода, лучше не злоупотреблять так как разбирать потом такой код сложнее.
> Тогда я бы предпочел иметь Сервисы (классы отвечающие за внутреннюю логику) и Хелперы (классы содержащие вспомогательные методы) в разных директориях.
Логично так и сделать.
> По хорошему, мне, наверно, следует перенести логику из контролеров в сервисы.
Смотря какую логику, важно чтобы сервис не был на самом деле переименованным контроллером.
> Следует ли её переименовать в связи тем что она теперь может получать не всех студентов?
Можно просто назвать getStudents или FindStudents.
>>$limit = 2147483647
> В мануале по mysql сказано о том что если нужно получить все записи, то нужно указать какое-то большое число
А ты его по памяти написать сможешь когда тебе будут нужны все студенты? лучше сделать условие что если $limit = 0 то конструкция LIMIT не вставляется. Правда, это не даст нам указывать OFFSET без LIMIT, но это почти никогда и не нужно.
> Это действительно так? Бывают ли на практике такие ситуации что нужно получить количество записей большее чем позволяет максимальное значение int?
Если тебе нужны все записи, проще не указывать LIMIT. Это число нужно только если тебе нужны все записи начиная с какой-то что на практике никогда не требуется.
> Для борьбы с sql инъекциями, я решил что удобней будет делать проверку на разрешенные колонки в методе получения запроса, чем в методе выполнения этого запроса. Так ведь тоже можно?
Это неправилньо. Вот я смотрю на код функции getAllStudents() https://github.com/someApprentice/Students/blob/master/app/Model/Gateway/StudentGateway.php#L10 и хочу проверить, безопасна ли она.
Я вижу что она подставляет переменную $order прямо в запрос и следовательно она небезопасна. Здесь уязвимость.
Или ты предлаагешь мне изучить весь код приложения, найти все места где вызывается эта функция (таких мест могут быть сотни) и каждое внимательно изучить? И даже если я так сделаю, где гарантия что завтра новичок не вызовет эту функцию без проверки?
Нужно использовать метод, который гарантирует отсутствие уязвимости, то есть проверять надо в самой функции. В твоем варианте гарантий никаких нет. Вот откуда человек должен узнать что он обязан фильтровать значение $order? даже в комментарии к функции это не написано, и даже если было бы написано, не факт что его прочтут.
Сейчас ты все держишь в голове, но это плохой способ. В реальности, если над проектом работает несколько человек то они всего этого знать не будут. И даже если ты работаешь один, ты легко можешь забыть о таких вещах когда каждый день пишешь код по 8 часов в день.
> А почему $allowed[0] возвращает найденное значение?
Так это просто берется первый элемент из массива разрешенных полей. Твой вариант тоже годится.
> Это ведь тоже копипаста, верно? Я только что подумал что это код можно вынести в отдельный методов родителя контроллеров. > Скоро исправлю.
Не стоит наверно. Уже были попытки как-то обобщить код, отвечающий за пагинацию, в других фреймоврках, но они как правило его делают только более запутанным.
> extract($this->getSortQuery());
Вот это плохая идея, так как глядя на код непонятно какие переменные создаются. Где гарантия что эта строчка не перезапишет одну из переменных, которая определена выше? ну например я правлю твой код и хочу добавить переменную, как мне выбрать ее имя чтобы она не конфликтовала с теми, что создаются в этой строчке? А что если завтра кто-то добавит в возвращаемый getSortQuery() массив новое поле и оно по имени будет совпадать с одной из переменных? Получается мы можем сломать контроллер, добавив новое поле в массив совсем в другом месте.
extract это потенциальный источник багов так как непонятно какие переменные она создает.
Также, у тебя в контроллере стоит 4 вызова render. Ты выносишь знание о структуре страницы в контроллер, но удобнее просто подключить один шаблон, а он уже пусть подключает что ему нужно.
> Я помню как ты говорил, что методы можно делать статическими если всегда будут возвращать одно и то же значение и не имеют никаких зависимостей, но в этот метод передается и меняется класс Student. Не является ли это зависимостью?
Нет. Зависимость это объект который нужен всему классу для работы и которая как правило передается при создании объекта. Студент тут это аргумент над которым делаются операции.
> Если мы инкапсулируем методы то не следует нам их сделать закрытыми?
Надо делать все внутренние методы (которые не предназначены для вызова снаружи) закрытыми. Ну то есть в классе для работы с БД у нас есть метод получения данных, есть метод сохранения данных, а всякие внутренние вспомогательные методы надо закрыть.
> Как закрыть эти методы? Если я пытаюсь обратиться к ним в статическом методе через $this, то я получаю ошибку о том что обращаюсь не в контексте объекта.
В статических методах нельзя использовать $this так как они вызываются на классе, а не на конкретном объекте и $this не имеет смысла. Увы, PHP вместо того чтобы запрещать такое, просто берет значение $this из вышележащего вызова метода. Это недоработка в PHP.
Также, у меня есть урок по MVC, если надо: https://github.com/codedokode/pasta/blob/master/arch/mvc.md
> Но если мы не меняем тип, то остальной код тоже не придётся трогать. Не могу понять как инкапсуляция тут помогает.
Допустим у нас есть класс:
class A
{
public $x;
public function setX($x)
{
$this->x = $x;
}
}
Тут как видишь полной инкапсуляции нет. Поле $x не защищено от прямого доступа снаружи. Посторонний код может обращаться к полю $x напрямую, а не через метод setX.
Это приводит к таким проблемам:
- допустим, мы хотим ограничить запись значений в поле, разрешив записывать только числа от 1 до 5. Нам придется искать обращения к полю по всему коду и копипастить туда код проверки. И нет гарантий что завтра где-то не появится новое обращение к полю без проверки.
- допустим мы захотим поменять логику и не хранить значение в классе, а передавать куда-то еще, сохранять в файл или в базу или куда-то еще. Опять же, нам придется обойти весь код, найти там все обращения к полю $x и поменять их на вызов какого-то метода.
В случае же инкапсуляции мы закрываем поле $x и оставляем доступ только к методу. И добавить проверку или поменять логику можно, меняя только один класс и не переделывая весь код. Который может быть очень большим по объему.
Вот представь что ты автор класса, а пользоваться будут им другие люди. Как ты без инкапсуляции гарантируешь, что в поле $x будут числа от 1 до 5, если они видят что поле публичное и могут записать туда любое число?
Ограничение доступа позволяет автору класса вводить ограничения, нужные для корректной работы класса.
Вообще, это относится не только к полям. Всегда лучше ограничивать область где доступно поле, функция, переменная, так как в этом случае проще анализировать код который с ней работает, так как меньше его объем.
Возвращаясь к твоему примеру. мы заключаем код, отвечающий за авторизацию, в класс для того, чтобы весь остальной код ничего не знал про то, как она реализована, а только вызывал нужный ему метод. И чем лучше сделано разделение, тем меньше придется переписывать при смене механизма авторизации.
>>Это верно. Потому что тут ты меняешь тип метода, и соответственно придется менять места его использования. А вот если тип остается прежним, но например, меняется алгоритм хеширования (или исправляется ошибка в нем) - остальной код трогать не придется.
> Но если мы не меняем тип, то остальной код тоже не придётся трогать. Не могу понять как инкапсуляция тут помогает.
Да, придется. А вот если мы смогли реализовать разделение обязанностей так, что при смене механизма авторизации не меняем тип передаваемых данных, то остальной код не придется трогать.
Ну и даже в случае, когда нам приходится менять тип передаваемых данных, инкапсуляция нам помогает, так как мы можем вписать проверку, что нам передали данные правильного типа и таким образом обнаружить код который мы забыли переделать и который передает данные в старом формате.
> У меня есть похожие методы на этот которые обращаются к полям не через сеттеры. Их тоже следует исправить?
Если они в том же классе, то не обязательно. Так как при каких-то изменениях в сеттерах мы их увидим. Но динамическим доступом к полям, когда имя поля определяется в ходе выполнения кода, лучше не злоупотреблять так как разбирать потом такой код сложнее.
> Тогда я бы предпочел иметь Сервисы (классы отвечающие за внутреннюю логику) и Хелперы (классы содержащие вспомогательные методы) в разных директориях.
Логично так и сделать.
> По хорошему, мне, наверно, следует перенести логику из контролеров в сервисы.
Смотря какую логику, важно чтобы сервис не был на самом деле переименованным контроллером.
> Следует ли её переименовать в связи тем что она теперь может получать не всех студентов?
Можно просто назвать getStudents или FindStudents.
>>$limit = 2147483647
> В мануале по mysql сказано о том что если нужно получить все записи, то нужно указать какое-то большое число
А ты его по памяти написать сможешь когда тебе будут нужны все студенты? лучше сделать условие что если $limit = 0 то конструкция LIMIT не вставляется. Правда, это не даст нам указывать OFFSET без LIMIT, но это почти никогда и не нужно.
> Это действительно так? Бывают ли на практике такие ситуации что нужно получить количество записей большее чем позволяет максимальное значение int?
Если тебе нужны все записи, проще не указывать LIMIT. Это число нужно только если тебе нужны все записи начиная с какой-то что на практике никогда не требуется.
> Для борьбы с sql инъекциями, я решил что удобней будет делать проверку на разрешенные колонки в методе получения запроса, чем в методе выполнения этого запроса. Так ведь тоже можно?
Это неправилньо. Вот я смотрю на код функции getAllStudents() https://github.com/someApprentice/Students/blob/master/app/Model/Gateway/StudentGateway.php#L10 и хочу проверить, безопасна ли она.
Я вижу что она подставляет переменную $order прямо в запрос и следовательно она небезопасна. Здесь уязвимость.
Или ты предлаагешь мне изучить весь код приложения, найти все места где вызывается эта функция (таких мест могут быть сотни) и каждое внимательно изучить? И даже если я так сделаю, где гарантия что завтра новичок не вызовет эту функцию без проверки?
Нужно использовать метод, который гарантирует отсутствие уязвимости, то есть проверять надо в самой функции. В твоем варианте гарантий никаких нет. Вот откуда человек должен узнать что он обязан фильтровать значение $order? даже в комментарии к функции это не написано, и даже если было бы написано, не факт что его прочтут.
Сейчас ты все держишь в голове, но это плохой способ. В реальности, если над проектом работает несколько человек то они всего этого знать не будут. И даже если ты работаешь один, ты легко можешь забыть о таких вещах когда каждый день пишешь код по 8 часов в день.
> А почему $allowed[0] возвращает найденное значение?
Так это просто берется первый элемент из массива разрешенных полей. Твой вариант тоже годится.
> Это ведь тоже копипаста, верно? Я только что подумал что это код можно вынести в отдельный методов родителя контроллеров. > Скоро исправлю.
Не стоит наверно. Уже были попытки как-то обобщить код, отвечающий за пагинацию, в других фреймоврках, но они как правило его делают только более запутанным.
> extract($this->getSortQuery());
Вот это плохая идея, так как глядя на код непонятно какие переменные создаются. Где гарантия что эта строчка не перезапишет одну из переменных, которая определена выше? ну например я правлю твой код и хочу добавить переменную, как мне выбрать ее имя чтобы она не конфликтовала с теми, что создаются в этой строчке? А что если завтра кто-то добавит в возвращаемый getSortQuery() массив новое поле и оно по имени будет совпадать с одной из переменных? Получается мы можем сломать контроллер, добавив новое поле в массив совсем в другом месте.
extract это потенциальный источник багов так как непонятно какие переменные она создает.
Также, у тебя в контроллере стоит 4 вызова render. Ты выносишь знание о структуре страницы в контроллер, но удобнее просто подключить один шаблон, а он уже пусть подключает что ему нужно.
> Я помню как ты говорил, что методы можно делать статическими если всегда будут возвращать одно и то же значение и не имеют никаких зависимостей, но в этот метод передается и меняется класс Student. Не является ли это зависимостью?
Нет. Зависимость это объект который нужен всему классу для работы и которая как правило передается при создании объекта. Студент тут это аргумент над которым делаются операции.
> Если мы инкапсулируем методы то не следует нам их сделать закрытыми?
Надо делать все внутренние методы (которые не предназначены для вызова снаружи) закрытыми. Ну то есть в классе для работы с БД у нас есть метод получения данных, есть метод сохранения данных, а всякие внутренние вспомогательные методы надо закрыть.
> Как закрыть эти методы? Если я пытаюсь обратиться к ним в статическом методе через $this, то я получаю ошибку о том что обращаюсь не в контексте объекта.
В статических методах нельзя использовать $this так как они вызываются на классе, а не на конкретном объекте и $this не имеет смысла. Увы, PHP вместо того чтобы запрещать такое, просто берет значение $this из вышележащего вызова метода. Это недоработка в PHP.
Также, у меня есть урок по MVC, если надо: https://github.com/codedokode/pasta/blob/master/arch/mvc.md
Кстати насчет этого:
$salt = substr(str_shuffle(
Это уменьшает число возможных вариантов и снижает надежность, так как у тебя буквы в хеше не могут повторяться. Лучше выбирать каждую букву случайно, допуская повторы.
Я затрудняюсь посчитать число вариантов, но для выборки N символов из M в комбинаторике есть формула, считающая число размещений: https://ru.wikipedia.org/wiki/Размещение (сравни формулы для размещений с повторами и без).
Правда, если ты берешь 44 символа, там наверно все равно много вариантов получается. Но не так много как есть брать их с повторениями.
> Вместо него надо использовать parent_id IS NULL
Это получается будут методы Adjacency List + Materialized Path? Я думал, раз я использую Materialized Path, то parent_id в базе быть не должно.
>- тяжело читать сложное выражение в echo - лучше вынести отдельные слова в переменные
- первые 2 строчки генерируются одинаково и можно использовать цикл
Спасибо за ответ. Буду думать как.
Сделано верно, тут к счастью расшифровывать обратно не нужно.
>>817630
На работе учиться будет труднее чем дома так там под это не отведено времени.
>>817619
Скриптом например, если ты умеешь их писать. А вообще, делать страницы методом копипасты плохая идея.
>>817467
Можно если полученное имя будет проверяться по списку разрешенных. Но лучше для каждой формы наверно свой обработчик.
Вообще, это поле избыточно, но здорово помогает например если из-за какой-то ошибки пути поломались и надо их перегенерировать. Я бы добавил это поле, так как без него ты замучаешься восстанавливать иерархию. И еще оно помогает использовать индексы, считать детей и тд.
Кстати, раз уже ты изучаешь деревья, тебе дополнительное задание: напиши класс для своего дерева, позволяющий
1) проверить валидность (ищет любые ошибки в структуре дерева)
2) исправить ошибки если возможно
Также, маленький скрипт для командной строки который будет вызвать этот класс. Если ты работаешь с деревьями, такая утилита тебе понадобится не раз. В готорвых библиотеках для работы с деревьями обычно есть и средства проверки для них.
Действует. Проблема с буквой ё только в том что она идет отдельно от остальных и при указании диапазона надо писать [а-яё]
Ты всегда можешь добавить тред в архивач, если до тебя его никто не добавил.
https://arhivach.org/thread/193343/ - текущий
https://arhivach.org/thread/191923/ - 79-й
Но я постараюсь добавлять теперь все треды.
>>819011
> А урок ОПа по регуляркам разве не объясняет?
Так я ему и говорю, что ничего доступнее, чем этот урок, он вряд ли найдёт. Я после них и написал свою первую регулярку, даже читером себя почувствовал из-за настолько хорошего объяснения: столько людей боятся одного упоминания регулярок, читают заумные мануалы и ничего понять не могут, а мне повезло встретить такую хорошую статью.
>>819044
Думаю, понял, это из-за особенностей игры, если поле большое, а у нас всего 2 кошки и мышки, то незачем держать всё поле, ведь остальные поля ничего не значат. Я делал игру попроще и там нужно было очень часто выполнять операцию получения объекта по координатам, + все элементы массива имели значение и были объектами. Так поле больше 50x50 дико тормозило из-за полного перебора одномерного массива. Помог мне двумерный массив, в нём ведь ведь операция получения по координатам за O(1) выполняется? В общем, точно быстрее, чем O(n).
>>819169
Но это ведь несложно проверить самому?
ФУ нахуй, решил. И хочется сказать - блядь, и над этим я думал 3 дня нахуй....
http://ideone.com/2B2ZdL
у тебя в каждой итерации цикла выводится либо ничего либо слово палидром.
Херня, потому что проверка if ($symbol != $symbolBack) внутри проверки if ($symbol == $symbolBack). Второе условие никогда не выполнится, если выполняется первое.
> При создании таблицы или базы данных ты указал DEFAULT CHARSET=utf8?
Ага, примерно в этом прблема была
> В каждом представлении пишу {{ include('head.html') }}
> Использовать Twig
Это ты GENIUS.jpg или такой синтаксис может использоваться еще чем-то помимо Twig?
>>818886
> наследование шаблонов
А вот это решение. Помог, спс
http://ideone.com/QXbkJ8
Ну движков много разных, ты же не уточнял какой у тебя. Значит ты используешь Twig, но при этом не читал доку. Магия копипаста.
>>819572
Одной регуляркой. Ты почему-то не используешь квантификаторы {n} и ?
Вместо [0-9] можно писать \d
Вместо того, чтобы 10 раз писать \Wж([0-9]), можно использовать (\Wж([0-9])){10} (ж - это звёздочка, её макаба скушает, если напишу)
[+][8] эквивалентно +8
Да блин, максимум не интересная тема же. Неделю прокрастинирую из-за этой хуйни. Завтра точно возьмусь, блять
>Вместо того, чтобы 10 раз писать \Wж([0-9]), можно использовать (\Wж([0-9])){10}
Я пытался много раз, все равно не получалось что-то, потом блять заметил что в одном из номеров пробел перед восьмеркой, начал заново все осваивать, в итоге хуй забил и 10 раз написал
Одну * макаба не кушает, кстати, только две, делая текст между ними курсивным.
>в итоге хуй забил и 10 раз написал
Вон и профессии, будущий говнокодер, за которым разгребай потом сиди!
Но я исправлюсь, чесна
> При этом способе path хранится в поле вроде TEXT или BINARY, по нему делается индекс.
У нас есть строка, мы сначала делаем все символы маленькими, потом убираем пробелы. Потом делим на два длину строки с приоритетом к меньшему.
Получается 13. То есть нам надо сравнивать символ с таким же, только с конца. То есть приписывать минус к каждому.
Но как делать с нулевым символом? Первый символ это 0, а последний это минус 1.
Ты можешь записать последний символ в виде мат. выражения.
>>819657
Ну а в том посте как раз 2 звёздочки (ж) на одной строке. Это предложение содержит по звёздочке слева и справа.
if (условие) {
переменная = значение1;
} else {
переменная = значение2;
}
...лучше писать
переменная = значение 2;
if (условие) {
переменная = значение1;
}
чтобы избавить от короткого элса?
В таких случаях удобно использовать тернарный оператор:
переменная = (условие) ? значение1 : значение;
Почему-то оно сразу же выходит из цикла, после первого раза. Хотя условием то задано, чтоб меньше равно половине длины строки, округленной в меньшую сторону.
Посмотрите, что здесь не так http://ideone.com/eG3n0o
1) Ты используешь функцию reverse, это слишком лёгкий путь.
2) Раз уж используешь reverse, то решение может быть гораздо проще: https://jsfiddle.net/ys6ht2ae/
bump
Решено верно. Можно лучше.
17 строка. Еще один if не нужен, ты же уже проверил равны ли символы.
Еще у тебя в цикле уже есть переменная $i, которая меняется при каждой итерации. Подумай как можно избавиться от строки 21 и переменной $a вообще.
Так http://ideone.com/BjD8az ?
Просто я кучу всего менял, в частности эти два случая т.к. не работало. А оказалось, что просто $ пропущенный не заметил. Надо же, невнимательность.
>>819033
Переписал методы по твоим советам, посмотри плиз. http://ideone.com/HWQzsC
Уникальные индексы и класс валидности дерева еще не начал писать.
> Также, а корректно ли работает твой код при параллельной вставке комментариев в несколько потоков? Вот один поток выбрал номер нового комментария, затем другой, затем первый вставляет новый комментарий, затем другой пытается вставить комментарий с тем же номером.
Ой, а это это сделать? Несколько потоков. Через несколько вкладок в браузере или еще какой-то стафф нужен. Правильно ли я понял, что поток - это как бы разные пользователи.
function foo (bar1, bar2, bar3)
{
action(bar1);
var = bar2 * 3;
bar3 = var;
}
Тоже самое с порядком свойств класса-модели и списком болей в дб. Делать ли определенный порядок атрибутов в HTML (типа вначале type, потом class, потом name)? Или даже более глубокая упорядоченность в виде методов и полей по алфавиту? Или это все слишком перфекционизм и не стоит так загоняться? Наверное в коммерческом коде или официальных библиотеках все по порядку, да?
Гут. Все станет лучше с опытом.
Тоже прямо сейчас занимаюсь вектором. Думаю стоит перестать охуевать с объема того что на тебя свалилось, перестать думать как сделать все и сразу, и, просто след
уя советам из задачника, прикинуть сколько у тебя будет сущностей. Написать одну из них, посмотреть чем это может тебе помочь дальше
Вообще лучше исходить из того, что сумма кредита во время работы цикла больше нуля, а при прекращении работы цикла должна быть равной нулю.
>>819998
Имеет всегда. Если нужно вывести и время, то можно вывести.
Нужно всё так устраивать, чтобы не было мучительно больно за бесцельно прожитые годы лишних переменных либо чтобы можно было каждый показатель вывести в итоге.
http://ideone.com/CqTQJ9
есть класс Core, который подключает файл с тремя функциями, и подключает еще один файл в котором я и хочу использовать эти три функции, но так и не пойму как настроить обращение к ним.
Должен быть varchar, а не text, ОП видимо ошибся. Для индекса нужна фиксированная длина записи.
>>819320
Решено верно.
>>819395
> $small = mb_strtolower($text);
> $noSpace = str_replace(" ", "", $small);
Тут не стоит заводить новую переменную, можно класть результат в тот же самый $text, а то у тебя получается 3 переменных для одного и того же.
> $symbolBack = mb_substr($noSpace, -$i, $halfLenght);
В случае если $i == 0 это выберет первый, а не последний символ (дял последнего надо -1)
> if ($symbol == $symbolBack) {
> echo $result;
Это тоже неправильно. Ты успел сравнить только 2 символа и уже делаешь вывод, палиндром это или нет
> if ($symbol != $symbolBack) {
Это вообще не сработает так как находится внутри противоположного по смыслу условия
Неправильно же. смотри, там внизу ошибка:
> PHP Notice: Use of undefined constant halfLength - assumed 'halfLength' in /home/h2krbR/prog.php on line 14
Использование необъявленной константы. Ты наверно переменную там хотел поставить?
Также, программа считает любое слово с четным числом букв палиндромом: http://ideone.com/HOy6vl
> for ($i = 0; $i <= halfLength; $i++) {
>$beginningLine = mb_substr($text, $halfLength);
Какой смысл делать N раз одно и то же действие с одним и тем же результатом? Что на первом, что на последнем шаге цикла $beginningLine получается тот же самый.
> if ($beginningLine == $endingLine) {
Их нельзя сравнивать так как они не совпадут.
>>819558
реально, если перечитать внимательно, но Зандстру тоже почитать бы неплохо.
>>819572
Слишком много регулярок. Достаточно 1-2 (для проверки и для упрощения номера).
Для повторов заданное число раз в регулярке есть конструкция вроде {N}.
>>819582
Это надо исправить, обращение к несуществующей еще переменной:
> PHP Notice: Undefined variable: summaHalf1 in /home/QtDbWL/prog.php on line 13
> PHP Notice: Undefined variable: summaHalf2 in /home/QtDbWL/prog.php on line 15
> $summaHalf1 = $summaHalf1.$half1;
У тебя эта переменная хранит копию текста и ее можно получить и без цикла. Ну и достаточно по идее только половину текста проверить, а не весь.
> $explodeText = explode (' ', $mbStrtolower);
> $implodeText = implode ('', $explodeText);
Есть же str_replace и strtr.
Неправильно же. смотри, там внизу ошибка:
> PHP Notice: Use of undefined constant halfLength - assumed 'halfLength' in /home/h2krbR/prog.php on line 14
Использование необъявленной константы. Ты наверно переменную там хотел поставить?
Также, программа считает любое слово с четным числом букв палиндромом: http://ideone.com/HOy6vl
> for ($i = 0; $i <= halfLength; $i++) {
>$beginningLine = mb_substr($text, $halfLength);
Какой смысл делать N раз одно и то же действие с одним и тем же результатом? Что на первом, что на последнем шаге цикла $beginningLine получается тот же самый.
> if ($beginningLine == $endingLine) {
Их нельзя сравнивать так как они не совпадут.
>>819558
реально, если перечитать внимательно, но Зандстру тоже почитать бы неплохо.
>>819572
Слишком много регулярок. Достаточно 1-2 (для проверки и для упрощения номера).
Для повторов заданное число раз в регулярке есть конструкция вроде {N}.
>>819582
Это надо исправить, обращение к несуществующей еще переменной:
> PHP Notice: Undefined variable: summaHalf1 in /home/QtDbWL/prog.php on line 13
> PHP Notice: Undefined variable: summaHalf2 in /home/QtDbWL/prog.php on line 15
> $summaHalf1 = $summaHalf1.$half1;
У тебя эта переменная хранит копию текста и ее можно получить и без цикла. Ну и достаточно по идее только половину текста проверить, а не весь.
> $explodeText = explode (' ', $mbStrtolower);
> $implodeText = implode ('', $explodeText);
Есть же str_replace и strtr.
Да, чтобы получить первый символ, надо указать позицию 0, а для последнего -1. Это особеность функции mb_substr. Аналогично, для второго символа с начала и с конца надо указать 1 или -2.
>>819834
раз уж ты разбил строку на массив символов, ты бы мог перевернуть его с помощью array_reverse и склеить обратно в перевернутую строку. Было бы проще.
А так, решено верно.
>>819840
Это с точки зрения логики может читаться хуже. В первом варианте сразу видно что у нас есть 2 варианта значения, а во втором примере видно что у нас есть одно значение по умолчанию, и другое как альтернатива. Хотя в общем. оба варианта годятся.
Если условие и выражения простые, то проще писать
переменная = условие ? a : b;
>>819855
Тогда if
>>819883
Можно называть поля кемелКейсом
>>819893
"Легкий путь" тоже годится если он верно работает.
>>819887
Для y пропущено var и будет создана или переопределена глобальная переменная. используй строгий режим чтобы такого избежать.
>>819912
> else if (mb_substr($text,$i,1) != mb_substr($text,$a,1)) {
Здесь нужен просто else без условия так как буквы либо совпадают, либо нет, третьего не дано.
$a можно убрать и получать нужную позицию из $i.
>>819964
Да, обычно веб-сервер многопоточный и может параллельно обрабатывать несколько запросов. И это позвовляет задействовать много ядер процессора, не одно.
Но это приносит и проблемы, связанные с тем что 2 параллеьно работающих скрипта могут сгенерировать один и тот же путь для вставляемого комментария.
Протестировать можно так: сделать консольный скрипт, который постоянно вставляет новые комментарии в одну и ту же ветку, и запустить несколько копий скрипта в нескольких консолях. затем проверить последовательность номеров. Если поставить уникальный индекс на (fileId, path) то вставка существующего path выдаст исключение.
Решение проблемы - блокировки. Начни например с википедии и прочитай про оптимистичные и пессимистичные блокировки, затем почитай где-нибудь про блокировки в mysql.
Вот у меня был где-то пост, где упоминаются блокировки: https://gist.github.com/codedokode/45f2961e7d68f7a2c501f4f893a45e17
В общем, подумай как тут нам могли бы помочь пессимистичные или оптимистичные блокировки.
>>819966
Скриншот явно неправильный так как видны повторяющиеся значения path.
>>819976
Нет. Порядок аргументов надо определять из того, в каком порядке тебе хотелось бы их передавать при вызове. Необязательные аргументы идут в конце.
> Тоже самое с порядком свойств класса-модели и списком болей в дб.
Я не знаю правил на это счет, обычно id идет первый, а остальные поля как угодно.
> Делать ли определенный порядок атрибутов в HTML (типа вначале type, потом class, потом name)?
Не надо. Это никак не улучшает читабельность.
> Или это все слишком перфекционизм и не стоит так загоняться? Наверное в коммерческом коде или официальных библиотеках все по порядку, да?
Порядок там не имеет никакого значения.
Насчет порядка, есть порядок в котором принято писать элементы класса:
- константы
- публ. поля
- непубличные поля
- конструктор(ы)
- магич. методы
- публичнеы методы
- непубличные
Да, чтобы получить первый символ, надо указать позицию 0, а для последнего -1. Это особеность функции mb_substr. Аналогично, для второго символа с начала и с конца надо указать 1 или -2.
>>819834
раз уж ты разбил строку на массив символов, ты бы мог перевернуть его с помощью array_reverse и склеить обратно в перевернутую строку. Было бы проще.
А так, решено верно.
>>819840
Это с точки зрения логики может читаться хуже. В первом варианте сразу видно что у нас есть 2 варианта значения, а во втором примере видно что у нас есть одно значение по умолчанию, и другое как альтернатива. Хотя в общем. оба варианта годятся.
Если условие и выражения простые, то проще писать
переменная = условие ? a : b;
>>819855
Тогда if
>>819883
Можно называть поля кемелКейсом
>>819893
"Легкий путь" тоже годится если он верно работает.
>>819887
Для y пропущено var и будет создана или переопределена глобальная переменная. используй строгий режим чтобы такого избежать.
>>819912
> else if (mb_substr($text,$i,1) != mb_substr($text,$a,1)) {
Здесь нужен просто else без условия так как буквы либо совпадают, либо нет, третьего не дано.
$a можно убрать и получать нужную позицию из $i.
>>819964
Да, обычно веб-сервер многопоточный и может параллельно обрабатывать несколько запросов. И это позвовляет задействовать много ядер процессора, не одно.
Но это приносит и проблемы, связанные с тем что 2 параллеьно работающих скрипта могут сгенерировать один и тот же путь для вставляемого комментария.
Протестировать можно так: сделать консольный скрипт, который постоянно вставляет новые комментарии в одну и ту же ветку, и запустить несколько копий скрипта в нескольких консолях. затем проверить последовательность номеров. Если поставить уникальный индекс на (fileId, path) то вставка существующего path выдаст исключение.
Решение проблемы - блокировки. Начни например с википедии и прочитай про оптимистичные и пессимистичные блокировки, затем почитай где-нибудь про блокировки в mysql.
Вот у меня был где-то пост, где упоминаются блокировки: https://gist.github.com/codedokode/45f2961e7d68f7a2c501f4f893a45e17
В общем, подумай как тут нам могли бы помочь пессимистичные или оптимистичные блокировки.
>>819966
Скриншот явно неправильный так как видны повторяющиеся значения path.
>>819976
Нет. Порядок аргументов надо определять из того, в каком порядке тебе хотелось бы их передавать при вызове. Необязательные аргументы идут в конце.
> Тоже самое с порядком свойств класса-модели и списком болей в дб.
Я не знаю правил на это счет, обычно id идет первый, а остальные поля как угодно.
> Делать ли определенный порядок атрибутов в HTML (типа вначале type, потом class, потом name)?
Не надо. Это никак не улучшает читабельность.
> Или это все слишком перфекционизм и не стоит так загоняться? Наверное в коммерческом коде или официальных библиотеках все по порядку, да?
Порядок там не имеет никакого значения.
Насчет порядка, есть порядок в котором принято писать элементы класса:
- константы
- публ. поля
- непубличные поля
- конструктор(ы)
- магич. методы
- публичнеы методы
- непубличные
Еще насчет аргументов: если в аргументах есть массив или функуия-колбек их обычно ставят в конец при прочих равных, так как массив или функция обычно переносится на несколько строк и писать после них аргументы неудобно.
>>819996
Вообще лучше к другому циклу.
>>819999
ООП тем и хорош что позволяет решать задачу по частям, ты пишешь первый класс и тестируешь, затем второй, затем еще , затем собираешь их вместе и снова проверяешь.
>>820023
Посмотри что внизу страницы:
PHP Notice: Undefined variable: comission in /home/STZ1Ve/prog.php on line 9
PHP Notice: Undefined variable: comission in /home/STZ1Ve/prog.php on line 11
PHP Notice: Undefined variable: paymentTotal in /home/STZ1Ve/prog.php on line 12
PHP Notice: Undefined variable: comission in /home/STZ1Ve/prog.php on line 9
Это надо исправить.
Ответ во втором банке должен быть около 61270. Попробуй также поставить сумму кредита в 4 000 - должно получиться 6123.
> $homoCreditTotal = computeProfitableCredit($homoCreditPercent,$homoCreditComission,$homoCreditFirstPaymentPrice,$payout,$creditSum);
тут в скобках наверно лучше сразу числа писать, а не переменные.
>>820054
Странная логика. Почему бы не подключать файл через require там, где нужны эти функции? А вообще, переходи на ООП с автозагрузкой.
Еще насчет аргументов: если в аргументах есть массив или функуия-колбек их обычно ставят в конец при прочих равных, так как массив или функция обычно переносится на несколько строк и писать после них аргументы неудобно.
>>819996
Вообще лучше к другому циклу.
>>819999
ООП тем и хорош что позволяет решать задачу по частям, ты пишешь первый класс и тестируешь, затем второй, затем еще , затем собираешь их вместе и снова проверяешь.
>>820023
Посмотри что внизу страницы:
PHP Notice: Undefined variable: comission in /home/STZ1Ve/prog.php on line 9
PHP Notice: Undefined variable: comission in /home/STZ1Ve/prog.php on line 11
PHP Notice: Undefined variable: paymentTotal in /home/STZ1Ve/prog.php on line 12
PHP Notice: Undefined variable: comission in /home/STZ1Ve/prog.php on line 9
Это надо исправить.
Ответ во втором банке должен быть около 61270. Попробуй также поставить сумму кредита в 4 000 - должно получиться 6123.
> $homoCreditTotal = computeProfitableCredit($homoCreditPercent,$homoCreditComission,$homoCreditFirstPaymentPrice,$payout,$creditSum);
тут в скобках наверно лучше сразу числа писать, а не переменные.
>>820054
Странная логика. Почему бы не подключать файл через require там, где нужны эти функции? А вообще, переходи на ООП с автозагрузкой.
Вектор антикризисный.
public и private расставил, но чувствую, что сделано это все скорее наугад, так и не понял куда protected нужно лепить.
Ну и есть подозрения за 3 антикризисный метод(Уже под полночь его мучил), возможно он хрень какую-то считает
"А мне приснилось - миром правит любовь,
А мне приснилось - миром правит мечта,
И над этим прекрасно горит звезда,
Я проснулся и понял - беда..."
Я аж серунькнул
for ($x=1000; $x < 1000000; $x+$x*10/100 )
{
$y=16;
$y++;
echo "В $y лет у него будет $x денег/n";
}
> "Легкий путь" тоже годится если он верно работает.
Ну здесь пару тредов назад вбрасывали видео собеседования на позицию Junior RoR, так там парню сразу сказали reverse не использовать.
> ты бы мог перевернуть его с помощью array_reverse и склеить обратно в перевернутую строку. Было бы проще
Такой подход почти всегда будет выполнять лишнюю работу и выполняться дольше, если слово не палиндром. Допустим, у нас есть очень длинное слово, начинающееся на A, кончающееся на B. Подход с циклом позволит на ранней стадии обнаружить несоответствие, на первой же итерации цикла вернётся false. В то время как подход с array_reverse будет впустую переворачивать длинющий массив. И чем длиннее слово, тем больше бесполезной работы array_reverse будет выполнять.
>>820133
На каждой итерации цикла переменной $y присваивается значение 16. Попробуй присвоить до начала цикла.
Ещё у тебя здесь $x+$x*10/100 нет никаких присвоений, то есть $x от итерации к итерации не меняется вообще никак, отсюда бесконечность.
Попробуй. Я лишь указал на то, почему цикл выполняется не так, как ты хочешь.
Пример: пользователь прикрепил 6 фото, потом поменял 3 на другие, как правильнее удалить старые и нужно ли это делать? Не совсем уверен, что необходимо хранить на сервере файлы о которых нет инфы в БД
Насчет эффективности, да, увы, в пхп эффективно работать со строкой посимвольно вообще не получится.
Это отчасти связано с тем что в utf8 символы имеют разную длину в байтах и отчасти с отсутствием строкового итератора.
Вот код mb_substr: https://github.com/php/php-src/blob/master/ext/mbstring/mbstring.c#L2890
mb_substr() имеет сложность O(N), он приходит от начала строки, считая символы пока не дойдет до N-го.
В случае, когда мы берем символы с конца строки, ей приходится пройти почти всю строку.
Потому общая сложность получается O(N^2).
Разбиение на массив символов позволяет снизить сложность до O(N), но ценой выделения большого массива.
Для того, чтобы это работало быстро, нам надо либо:
- использовать кодировку с фиксированной длиной символа
- чтобы у нас были итераторы или генераторы, позволяющие двигаться по строке и каждый раз получать следующий символ (если есть желание, и ты знаешь ООП или генераторы, можешь попробовать написать итератор или генератор. Конечно так быстро работать, как написанный на Си, он не будет, но может на огромных строках разница будет)
О, кстати, аноны, никто не хочет написать итератор или генератор, двигающийся по строке и выдающий символы по одному? Затем написать микробенчмарк и сравнить на большой строке:
- использование mb_substr
- использование preg_split
- использование вашей реализации
Построить графики вида "зависимость времени от длины входной строки".
Разберетесь в кодировке utf-8, научитесь работать с генераторами или итераторами, оценивать сложность алгоритмов.
Насчет эффективности, да, увы, в пхп эффективно работать со строкой посимвольно вообще не получится.
Это отчасти связано с тем что в utf8 символы имеют разную длину в байтах и отчасти с отсутствием строкового итератора.
Вот код mb_substr: https://github.com/php/php-src/blob/master/ext/mbstring/mbstring.c#L2890
mb_substr() имеет сложность O(N), он приходит от начала строки, считая символы пока не дойдет до N-го.
В случае, когда мы берем символы с конца строки, ей приходится пройти почти всю строку.
Потому общая сложность получается O(N^2).
Разбиение на массив символов позволяет снизить сложность до O(N), но ценой выделения большого массива.
Для того, чтобы это работало быстро, нам надо либо:
- использовать кодировку с фиксированной длиной символа
- чтобы у нас были итераторы или генераторы, позволяющие двигаться по строке и каждый раз получать следующий символ (если есть желание, и ты знаешь ООП или генераторы, можешь попробовать написать итератор или генератор. Конечно так быстро работать, как написанный на Си, он не будет, но может на огромных строках разница будет)
О, кстати, аноны, никто не хочет написать итератор или генератор, двигающийся по строке и выдающий символы по одному? Затем написать микробенчмарк и сравнить на большой строке:
- использование mb_substr
- использование preg_split
- использование вашей реализации
Построить графики вида "зависимость времени от длины входной строки".
Разберетесь в кодировке utf-8, научитесь работать с генераторами или итераторами, оценивать сложность алгоритмов.
В твоем случае удобнее всего удалять при замене фото. То есть алгоритм такой:
- загружаем новый файл фото
- одной транзакцией или запросом в БД заменяем указатель на новое фото
- удаляем старый файл
При таком подходе конечно могут все равно остаться неудаленные файлы (например если скрипт упал до их удаления), их можно убрать собираемым по крону сборщиком мусора.
>>820136
Если попросят, значит надо будет решать другим способом, хотя конечно мне не очень нравится такой подход. Если им не нравится мой алгоритм, пусть назовут свой и я его реализую.
Потому я не люблю такие требования. Лучше задачу так переделать, чтобы совсем просто ее было бы не решить.
На сервере:
1) перенести переменные сессии из файла сессий 1 в файл сессий 2
2) удалить файл сессий 1
3) передать браузеру id второй сессии
Пробовал:
$session = $_SESSION;
session_unset(); // чистим переменные чисто (обычно из файла тоже удаляются)
session_regenerate_id(); //изменяем id сессии (данные из первой сессии копируются в новую
$_SESSION = $session;
но, кажется, не работает....
Я не уверен что такое вообще можно делать. Изучи внимательно механизм сессий по мануалу, посмотри какие там функции есть. да и не очень понятно зачем это вообще нужно.
в общем, в данном контексте session_unset не выполняет свою функцию. если ее удалить, ничего не изменится. regenerate_id будет создавать новый файл сессии и будет получаться 2 одинаковых...
У меня есть таблица "один ко многим" для хранения пользовательских картинок, сперва очищаются все записи связанные с этим юзером, потом записываются новые из переданного массива. Вижу только возможность получить перед удалением данные по фотографиям юзера, и потом удалить те которые вернет array_diff между новыми и старыми.
Допустим, пользователь хочет войти на сайт. Для пущей безопасности надо ему новую сессию выдать в куках.
Но у меня же в старой сессии какие-то данные еще лежат! Их надо в новую сессию перекинуть, а из старой удалить, чтоб тот, кто спиздил старую куку сессии не смог их прочитать.
На самом деле, я не знаю, какие еще данные могут храниться в сессии помимо данных авторизации, но все же хотелось бы на всякий случай знать, как такое сделать.
Как работают сессии на уровне PHP я не знаю, и знать не хочу.
Принудительно очищай сессию каждых n-минут например.
session_unset() в паре с regenerate_id() все таки бесполезен. Ладно, хрен с ним. И в правду наверно нельзя такое сделать со стандартным механизмом сессий. Всем спасибо
Хрен еще разберешь, как regenerate_id влияет на старые данные сессии. Если делать все в строгом порядке и тестить, то, надеюсь, ничего не случится.
Неправильно так как при ошибке у тебя пользователь останется без картинок вообще. Лучше писать код так, чтобы при падении скрипта в любом месте, пользователь бы ничего не терял.
Для этого нужно писать код так, как я написал выше.
Для новых фотографий по той же причине лучше делать новые имена файлов.
>>820168
> Как работают сессии на уровне PHP я не знаю, и знать не хочу.
То есть ты не хочешь читать мануал. Я тоже.
>>820174
зачем вы вообще сессии используете для авторизации? Они же удаляются через 30 минут неактивности. в видеокурсах так советуют?
А как по другому? Я наперед не знаю точно сколько фото загрузить пользователь, как я могу делать update фото если количество фото вероятно не совпадает с новым переданным количеством.
Пикрелейтед структура таблицы
Да, пожалуй начну потихоньку писать. Только остается страх перед тем, что я настрочу какой то объем кода и скомпоновать не смогу толково либо вообще изначально неверно напишу.
>зачем вы вообще сессии используете для авторизации?
А что ты предлагаешь? Фреймворки со своими сессиями для моих микропроектов слишком громоздко, php авторизация только в админке.
>Они же удаляются через 30 минут неактивности
Разве это не фиксится конфигами?
>в видеокурсах так советуют
За свою жизнь только 1 раз смотрел видеокурсы по CSS какой-то тупой пизды, которая только показала как нахуячить, а как работает не объяснила, сучка. А в комментах все нахваливают. Инфобизнесмены ебаные
>class 'html' not found
В Yii2, что это может быть?
Что-то не так с Composerом?
Не подключаются ещё и ассеты, какая же боль...
Вангователи, с чем это может быть связано?
Как же жжёт пониже спины...
$stmt = $pdo->prepare("insert into students_list ...
?
Спасибо )
Регистр букв или неймспейс
>>820244
> В задаче про студентов, какой класс отвечает за сохранение объекта-модели-студента в базу данных - AbiturientDataGateway? В нем должен быть метод, который принимает класс Abiturient в качестве аргумента, и сохраняет его в базу данных?
Да
> А как осуществляется сохранение, нужен специальный класс для работы с PDO, или в методе сохранения просто используется код вида:
> $stmt = $pdo->prepare("insert into students_list ...
Просто используется, отдельный класс не нужен.
> никто не хочет написать итератор или генератор, двигающийся по строке и выдающий символы по одному?
Попробовал написать исходя из того, как понял: http://ideone.com/f6jjuw
> использование вашей реализации
Не додумался. Мануал по строковым функциям просмотрел, нашёл разве что mb_split, но это тот же preg_split по сути.
> Разберетесь в кодировке utf-8
Видимо, я неправильно понял задание, так как не понял, где мне здесь знание utf-8 пригодится.
>если есть желание, и ты знаешь ООП или генераторы, можешь попробовать написать итератор или генератор
Ну допустим я понимаю как заимлементить SPL Iterator, но я не понимаю зачем здесь ООП, если функция-генератор уже является итерируемой.
Да, ты написал генератор, но этот генератор внутри использует медленный mb_substr или охочий до памяти preg_split. Идея была в том, чтобы написать генератор который читает строку побайтово (за счет substr или за счет $string{$x}). По первому байту utf-8 символа можно определить, сколько в нем байт.
> так как не понял, где мне здесь знание utf-8 пригодится.
Когда будешь определять длину символа в байтах по первому байту.
> Ну допустим я понимаю как заимлементить SPL Iterator, но я не понимаю зачем здесь ООП, если функция-генератор уже является итерируемой.
генераторы не всегда были, плюс итераторы можно как-то комбинировать. Хотя да, генератор пишется проще и короче. Может он медленнее работает?
Насчет разных длин строк - лучше брать длины не 1, 50, 100, а например 100, 500, 1000, 5000, 10000, 50 000, 100 000. И потом, построив график зависимости времени от размера строки ты можешь наглядно увидеть сложность алгоритма (для удобства построения графика можно выдавать данные в CSV формате который понимают программы электронных таблиц)
Вот тебе пример разбора строки побайтово:
$s = "тест test";
for ($i = 0; $i < strlen($s); $i++) {
$code = ord($s{$i});
printf("%03d 0x%02x\n", $code, $code);
}
Этот цикл можно еще чуть оптимизировать:
- вынести strlen($s) в переменную
К сожалению $s{$i} выделяет память под новую 1-байтную строку каждый раз и хорошо бы получать сразу код этого байта не тратя время на выделение памяти.
>Регистр букв или неймспейс
Нет, к сожалению...
Вот это у меня в шаблоне:
<?php
use yii\helpers\Html;
use yii\bootstrap\Nav;
\frontend\assets\MainAsset::register($this);
?>
<?php $this->beginPage() ?>
<!DOCTYPE html>
<html lang="en">
<head>
<title><?=$this->title ?> </title>
<meta charset="<?= Yii::$app->charset ?>">
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<?= Html::csrfMetaTags() ?>
<?php $this->head() ?>
</head>
И ладно бы с этим, у меня почему-то не подключаются CSS и JS - страница отображается на голом HTML.
Даже не понимаю, что там может быть не так.
Голова разболелась дико от такой-то несправедливости.
Вот так выглядит исходный код страницы - куда девается информация из MainAsset - непонятно.
Там вот это у меня стоит:
<?
namespace frontend\assets;
use yii\web\AssetBundle;
use yii\web\View;
class MainAsset extends AssetBundle{
public $basePath = '@webroot';
//public $baseUrl = '@web';
public $css = [
'source/style.css',
'source/owl-carousel/owl.carousel.css',
'source/owl-carousel/owl.theme.css',
'source/slitslider/css/style.css',
'source/slitslider/css/custom.css'
];
public $js = [
'source/script.js',
'source/owl-carousel/owl.carousel.js',
'source/slitslider/js/modernizr.custom.79639.js',
'source/slitslider/js/jquery.ba-cond.min.js',
'source/slitslider/js/jquery.slitslider.js',
'source/js/google_analytics_auto.js'
];
public $depends = [
'yii\web\YiiAsset', // yii.js, jquery.js
'yii\bootstrap\BootstrapAsset', // bootstrap.css
'yii\bootstrap\BootstrapPluginAsset' // bootstrap.js
];
public $jsOptions = [
'position' => View::POS_HEAD,
];
}
Даже не понимаю, что там может быть не так.
Голова разболелась дико от такой-то несправедливости.
Вот так выглядит исходный код страницы - куда девается информация из MainAsset - непонятно.
Там вот это у меня стоит:
<?
namespace frontend\assets;
use yii\web\AssetBundle;
use yii\web\View;
class MainAsset extends AssetBundle{
public $basePath = '@webroot';
//public $baseUrl = '@web';
public $css = [
'source/style.css',
'source/owl-carousel/owl.carousel.css',
'source/owl-carousel/owl.theme.css',
'source/slitslider/css/style.css',
'source/slitslider/css/custom.css'
];
public $js = [
'source/script.js',
'source/owl-carousel/owl.carousel.js',
'source/slitslider/js/modernizr.custom.79639.js',
'source/slitslider/js/jquery.ba-cond.min.js',
'source/slitslider/js/jquery.slitslider.js',
'source/js/google_analytics_auto.js'
];
public $depends = [
'yii\web\YiiAsset', // yii.js, jquery.js
'yii\bootstrap\BootstrapAsset', // bootstrap.css
'yii\bootstrap\BootstrapPluginAsset' // bootstrap.js
];
public $jsOptions = [
'position' => View::POS_HEAD,
];
}
Спасибо, бро, я ведь так ошибался уже и забыл совсем.
Вот что сейчас выдаёт:
<-----
При этом вроде бы всё прописано правильно (namespace, названия файлов, классов).
Непонятно всё теперь уже с этой стороны.
Может всё-таки неправильно неймспейсы указал? Попробуй прописывать неймспейс по частям и смотри на то, что PHPStrom автодополнеяет/не автодополняет.
Братишка, дай я тебя расцелую!
Я же просто тормоз...
В шаблоне не работали короткие теги, а в других местах же работают - я так подумал...
Точнее, не подумал совсем.
Спасибо тебе, проблема решена!
Namespace были в порядке, но теги теперь буду ставить только <?php ?>.
Странно, я думал, что в РНР7 всё это должно работать...
Их поддержка включается в конфиге PHP: http://stackoverflow.com/questions/2185320/how-to-enable-php-short-tags
Спасибо! Уже включаю сейчас.
Как же снять этот остаток? Хоть подскажите в какую сторону гуглить.
Я тупой, не получается.
http://ideone.com/r6Ecla
Хочу поделиться историей успеха, анон.
Благодаря треду и урокам, выучил умных слов и стал понимать принципы программирования. Устроился на работу в ДС(образование у меня 9 классов и я из мухосрани) на хорошую должность(не связанную с программированием, больше упор в администрировние), но благодоря тому, что работают вокруг меня люди хоть и с высшем образованием, но ленивые пиздец. Я начал писать замену уже существующим системам которые использовались. Начальству понравилось, внедрили сэкономили миллионы(я не шучу), заменил своими поделками кучу корп систем, написанных крутыми конторами за 100500 тысяч евро. В итоге я стал жаловаться на нагрузку(лол) и мне выделили бюджет на 1го программиста, ну разумеется я стал начальником отдела разработки который сделали под меня. Пока все. Сроку у меня на это ушло год. Всем спасибо анончики, хочу от себя дать совет, по больше задавайте вопросов на спец сайтах которые индексируются и побольше на них отвечайте, так вы помогаете не только себе, но и будущим поколениям.
Всё считает правильно, вполне нормальное решение.
>>820493
В цикле должно быть два условия: при одном цикл продолжается и выводит месячную выплату и остаток на тот момент (когда остаток кредита больше месячной выплаты), при другом выводит в последний раз весь остаток (когда остаток становится меньше месячной выплаты).
Непременное и важное условие для работы уже этих условий: перед проверкой, больше или меньше месячной платы этот остаток, он уже должен быть с прибавленными 3-мя процентами и 1000 рублей за обслуживание.
Мои поздравления, братишка!
Я сам работаю в издательстве, так могу сказать, что история, аналогичная твоей, и у нас в компании происходила. Правда, не со мной, но так же был рад за умного парнишку (я тогда ещё и не изучал программирование, это было два года назад).
Потому что часто программисты, учившиеся в вузах, прекращают обучение во время работы, садятся на готовые кривые решения, предпочитают поддерживать кривые имеющиеся системы, а не делать качественную свою, учитывающую всю специфику. Вот он не был таким, сейчас вполне себе неплохо себя чувствует, сэкономив компании миллионы и став довольно большим человеком буквально через пару лет после вуза.
Трудолюбие и постоянное развитие в любом случае приносят свои плоды рано или поздно.
Верю в это и живу с этим.
Малаца, рад за тебя. И спасибо за вдохновение.
Реализую загрузку файлов с сервера. Сейчас у меня так: показать download.html с Location -> location перенаправляет на файл и он открывается в браузере.
Хочу: ф-ия возвращает не проходной и ненужный download.html, а сразу файл, в http Header которого будет прописан 'Content-Disposition':'attachment' И который будет загружаться.
Как это можно реализовать?
Мой ПК не может в стриминг :/
Ну до лучших времен значит.
>>820694
Мои поздравления. Сколько же прогеров вырастил ОП и этот тред ?
>Мои поздравления. Сколько же прогеров вырастил ОП и этот тред ?
Можно провести перепись тех кто устроился программистом
Без Js будет сложно если на фулстак идти. А так походи по собеседованиям, поищи может за еду возьмут.
>Вообще, это относится не только к полям. Всегда лучше ограничивать область где доступно поле, функция, переменная, так как в этом случае проще анализировать код который с ней работает, так как меньше его объем.
А что определяет какую функцию мы должны заинкапсулировать? Ведь можно прямо внутри функции ограничивать пришедшие аргументы.
>- допустим мы захотим поменять логику и не хранить значение в классе, а передавать куда-то еще, сохранять в файл или в базу или куда-то еще. Опять же, нам придется обойти весь код, найти там все обращения к полю $x и поменять их на вызов какого-то метода.
Но ведь и в случае инкапсуляции нам придётся пройтись по всему коду и поменять функцию setX().
>>819083
>> Тогда я бы предпочел иметь Сервисы (классы отвечающие за внутреннюю логику) и Хелперы (классы содержащие вспомогательные методы) в разных директориях.
>Логично так и сделать.
>
>> По хорошему, мне, наверно, следует перенести логику из контролеров в сервисы.
>Смотря какую логику, важно чтобы сервис не был на самом деле переименованным контроллером.
Я бы хотел перенести, например, вот этот код https://github.com/someApprentice/Students/blob/master/app/Controller/LoginAction.php#L48-L51 в $AuthService->login(). Иначе у меня просто не будет Сервисов.
>>819083
>>>$limit = 2147483647
>> В мануале по mysql сказано о том что если нужно получить все записи, то нужно указать какое-то большое число
>А ты его по памяти написать сможешь когда тебе будут нужны все студенты? лучше сделать условие что если $limit = 0 то конструкция LIMIT не вставляется. Правда, это не даст нам указывать OFFSET без LIMIT, но это почти никогда и не нужно.
Можно принимаемые аргументы перенести в конец, и при вызове функции их не указывать.
С П А С И Б О
Нет, там всё верно: 61270 с копейками.
Проверьте аэродром плес
Делаешь цикл, рандомишь массив, склеиваешь слоги. Закрываешь массив, выводишь echo.
А ты знаешь, вообще, как добавить в существующий массив еще один элемент? Если нет, перечитай примеры кода в уроке про массивы.
Бляяяяяяяяя, ты про $name[]?
implode клеит массив. А тебе нужно склеить текст. Конкатенацию в РНР погугли.
Всё, нашел.
File | New Project From Existing Files - My web server is on remote host, files are accessible via FTP/SFTP/FTPS
А вообще нужно сделать локальную копию проекта.
Анон, ты охуенен. Лучи добра тебе.
http://ideone.com/okP4KS
Попробовал ретурн с конкатенацией.
Почему то нули от прошлого числа залезли на следующее.
>>821180
Сколько угодно, но return выходит из функции и код после нее очевидно не будет выполняться.
>return
В задаче про айпад что я скинул выше, я склеил переменные в ретурне, нули полезли на другие числа. Массив пробовать юзать?
Я же там комментарии оставил.
Ну вот смотри, в цикле for мы находимся с первого месяца до того момента, пока кредитный баланс не достигнет нуля.
Условие в for я не указал. Долго ломал голову, какое условие бы поставить, а потом вспомнил, что оно не обязательно.
Начисление процентов с комиссией и вычет денег я разделил на две разные операции.
В if проверяю, сколько осталось платить. Если меньше, чем доступная нам сумма, то этот остаток суммирую с тем, сколько уже заплатил, а остатку присваиваю ноль. Если зашёл в тело if, то использую break и цикл заканчивает работу и программа тоже.
В else тоже сравниваю сколько осталось платить и сколько у меня есть денег. Из остатка вычитаю доступную сумму, а уже потраченным деньгам эту сумму прибавляю.
Ну и вывожу всю инфу красивенько.
Анон, помоги, пожалуйста.
Допустим, я меняю стиль сайта под себя, чтоб мне было удобнее (с помощью Stylish для Chrome). Я хочу, чтоб какой-то элемент, в данном случае строчку "реклама" не было видно.
По идее надо сделать так:
.left_menu_nav{
visibility: hidden;
}
Но тогда скрывается вся панелька полностью. А как мне тут обратиться именно к элементу Реклама "/ads"?
И Реклама, и Блог, и Разработчикам находятся в одном классе и к ним приписана лишь ссылка. Как обратиться к нужному элементу, чтоб сделать его hidden?
>По идее надо сделать так
Таким образом ты всем элементам у которых указан класс .left_menu_nav ставишь visibility hidden. Из-за этого все скрывается.
В идеале конечно было бы задавать элементу свойство по айди, он (айди) в отличии от класса уникален, но так как в твоем случае айди у элемента не указан, придется применить другой способ.
В CSS есть такая вещь - attribute selectors, которая позволяет выбрать определенный элемент используя какую-то информацию о нем. В твоем случае мы знаем что нужно скрыть ссылку, которая ведет на /ads, поэтому сделать можно как-то так:
.left_menu_nav_wrap a[href^="/ads"] {
visibility: hidden;
}
Стиль выше скроет все элементы <a> во всех элементах с классом .left_menu_nav_wrap. Это не идеальное решение, но я думаю тебе подойдет.
Про селекторы почитать можно тут:
https://developer.mozilla.org/en/docs/Web/CSS/Attribute_selectors
http://www.w3schools.com/cssref/sel_attr_end.asp
Спасибо огромное! Долго искал ответ, из-за херовых знаний в этой области не знал, как запрос в гугле формулировать.
привет милый, у меня уже нервные тики начинаются, следую я значит твоим гайдам, пишу код <?php
error_reporting (-1);
$dollards = 200; / количество долларов /
$exchangeRate = 64.90; / курс доллара /
$roubles = 12980; / обменный курс /
echo "$dollars долларов можно обменять на $roubles рублей"; а у меня итог с ошибкой выдается, ну как с ошибкой, ideone говорит что ошибок нет, а конечный результат : stdout copy
долларов можно обменять на 12980 рублей то есть не пишется что именно 200 ДОЛЛАРОВ! уже дрожь в коленах, сухость на языке, не могу терпеть больше, желание убивать... подскажи, молю.
блять, какой же я хуево развитый еблан. не актуально, 200 доллардсов всем итт
>>821013
Забыл спросить
>>819083
>Также, у тебя в контроллере стоит 4 вызова render. Ты выносишь знание о структуре страницы в контроллер, но удобнее просто подключить один шаблон, а он уже пусть подключает что ему нужно.
А как это реализовать? Сделать отдельный шаблон в котором будет вызываться render нужных элементов? Для этого нужно будет передавать Viewer который находиться в свойствах контроллера. Я такого не разу не делал, по моему это усложнение.
Или сделать один шаблон который содержит в себе все элементы (т.е. они не вызываются с помощью render, а приписаны в ручную)? Если да, то не будет ли это лишней копипастой?
>>82138
Спасибо.
Ты совсем у мамы даун?
$tag='%Колонка редактора%';
...
$stmt = mysqli_prepare($mysqli, "select id,title,author,date,abstruct,icon,tags from res where tags like ? order by -date;");
$stmt->bind_param("s", $tag);
И мне приходит адекватный ответ. НО пишу так
$tag='%'.$_GET['tag'].'%';
И мне приходит пустой массив. При этом, я конечно же пробовал делать echo $tag и внешне он выглядит как надо. Че за херота вообще? Проблема какая-то странная! Запрос выполняется, в переменной то что надо! Что я упустил?
Разобрался в чем херня. Ебаная кодировка
ну почему нет-то? Это всего лишь набор правил цсс
Второй вопрос косвенно касается первого. Вот это свойство downloadLink, как его получить? У меня есть модель File, так вот я там некоторые свойства не храню в классе. но их можно получить. К примеру есть метод getThumnailPath() с кодом ниже:
public getThumnailPath() {
return $this->uploadPath "/" . "thumbnails";
}
Т.е. есть свойство uploadPath, но нет свойства thumbnailPath, т.к. я думаю оно излишне и его можно собрать из других свойств. Можно ли так делать? Или надо получать такие значения через какой нибудь FileHelper.
ControllerDownload::NAMEOFACTION понятнее будет, забыл что это называется action. Может как-то из слима возможно достать? Знаю пока только что аргументы можно получить.
Ты праивльно начала мыслить, но свернул не в ту сторону. То, что нехорошо по коду дублировать код составления URL это верно. Но URL страницы ведь не из одной константы состоит. Вместо вынесения константы надо просто сделать где-то метод, который генерирует этот УРЛ.
> У меня есть модель File, так вот я там некоторые свойства не храню в классе. но их можно получить. К примеру есть метод getThumnailPath() с кодом ниже:
Модель не всегда может получить нужный путь. Ну например чтобы узнать где файл хранится на диске, надо знать путь к папке с файлами, но модель его может не знать. Потому генерацию таких путей возможно стоит вынести во внешний сервис который знает нужные пути.
>>822573
Можно делать. Но возможно твоя проблема просто в том что у тебя весь код написан стеной. а не разбит на функции?
>>822489
Если твой макет внешне похож на типичную бутстрап-страницу (шрифты, формы, кнопки, блоки, меню, оформление ссылок и тд) то его можно использовать. Если не похож - то не понимаю, какой смысл тащить огромную библиотеку из которой ты ничего не используешь и в которой тебе придется переопределять все стили.
Что-то непонятно, что ты хочешь. Если у тебя урл вида localhost/downloads/fileID то downloads будет контроллером, у которого будет экшн, который будет обрабатывать скачку файла.
я смотрел способ через str_replace, но он не гарантирует, что перед знаками не будет пробелов, а с помощью регулярок не могу придумать, как это описать.
в общем, кто знает, подскажите.
Ответ на любой вопрос
http://ideone.com/dGLHaC
Генератор имён готовый
http://ideone.com/j0wiZB
В тылу врага - шифровка
http://ideone.com/0ddCh5
1337 - шифровка
http://ideone.com/gMlhjC
На словах ты Лев Толстой
http://ideone.com/CL7D0o
Разбиение строки на символы
http://ideone.com/mtlMmY
Палиндром
http://ideone.com/fGPWl9
Айпад в кредит
http://ideone.com/zsbANa
ссылку на сайт, или на тему, которую я натянул, или просто на отрезок моего кода.
Алсо могу поставить сайт на Codeigniter, но что там мне выставлять? собственно верстка же не мое, такчто там только пара классов и строк кода?
вот ссылка на гитхаб. актуальны, только три последних проекта.
https://github.com/DmitryNeposidjaka
Анончик, критикуй сколько хочешь, только ссаными тряпками не гони.
И вообще прошу пояснить как устроится джуном.
Все плохо. Решай учебник ОПа.
Проекты уж слишком маленькие. Решай учебник ОПа и попробуй устроиться на стажировку куда-нибудь.
Патцоны, если покупать домен на год, то по мере роста популярности сайта, будет и рости цена домена???????????????
Гитхаб, хероку. Правда регистрация таки нужна.
http://sqlfiddle.com/#!15/75a3cd
Сначала не совсем понимал как сделать ответы к вопросом, в итоге решил сделать отдельной таблицой answers. Если тип вопроса - выбрать ответ из списка то все варианты из списка будут в этой таблице. Если тип - ввести текст или номер, в этой таблице будет лежать правильный ответ на вопрос.
Таблица attemts сделана для того чтобы зарегистрированные пользователи не могли бесконечно проходить тест, каждому тесту можно задать максимальное количество раз пересдачи. Тут я не уверен, нужен ли такой функционал вообще? И как быть с незарегистрированными пользователями? Отслеживать по IP не очень хорошая идея потому что IP может быть один, а устройств несколько.
Про индексы знаю, тут они нужны будут в основном для внешних ключей? Для поиска по тестам хочу Sphinx взять, он получше и быстрее обычного поиска через LIKE.
$root = str_replace('\', '/', $_SERVER['DOCUMENT_ROOT']);
?? '\' - тут типа ошибка. Как фиксить и какого хуя вообще?
Блять, как я апазорился. Мало того что не то экранирую, так еще и в документ_руте слеши всегда обычные.
Недавно начал осваивать похап, пытаюсь написать простой парсер, но что-то ошибка. Подскажите-ка.
Я так понимаю, что оно для локальных файлов (4 строка), недавно сам делал парсер, глянь вот эту небольшую либу. http://simplehtmldom.sourceforge.net/manual.htm
За мануал, конечно, спасибо, но функция, которую я использовал, должна уметь открывать ссылки и выводить мне джейсон.
Вот, глянь.
http://php.net/manual/ru/function.file-get-contents.php
Так что я все еще хочу найти ошибку.
Кантора тебе с головой хватит, у него очень хороший учебник. Ещё плюсы:
- для сложных задач есть тесты, то есть твоё решение проверяется не тобой, а автотестами (ты же можешь что-то не учесть при решении и не заметить). А если твоё решение прошло все автотесты, то ты точно будешь уверен, что поставленная задача решена верно.
- комментаторы частенько предлагают интересные решения или объясняют сложные вещи. Периодически предлагают интересные задачки по теме. Из последних, на которые я натыкался: написать функцию sum, которая используется так:
sum(2)(3)(10); // Ответ 15
sum(1)(0)(22)(7)(30); // Ответ 60
Количество вызовов произвольное. Нужно понимать замыкания и рекурсию.
> решаю первые 16 задач из урока опа https://gist.github.com/codedokode/ce30e7a036f18f416ae0. Но как-то тяжеловато
Мне тоже тяжело даются "простые задачи на JS", 4-ю вообще перечитывал раз 15, настолько туго шло, но небольшими шагами добрался уже до 11-й задачи. Мой совет: решай все задачи Кантора, смотри как задачу решили другие люди, у них можно многому научится.
>>823943
> Я так понимаю, что оно для локальных файлов (4 строка),
Неправда, я же тебе скрин вбрасывал и показывал, что у меня file_get_contents работал для API контакта (если ты тот анон). Просто у тебя, скорее всего, опция allow_url_fopen отключена в PHP.
>>823853
Без urlencode работает.
Решать все? Попробую, я наоборот половину пропускал и не очень много времени тратил на решение, если совсем никаких идей - сразу готовое решение открывал. Там некоторые очень сложные бывают.
> смотри как задачу решали другие люди
Комментарии читать т.е.? Это делать до спойлера готового решения или после.
Алсо после какой части учебника ты пошел решать задачи опа? Я например быстро полез в задачи опа и на четвертой завис, потому что до apply еще не дошел в учебнике.
> Решать все?
Я все решаю и пихаю в автотесты, если есть. Там бывает такое, что на одну статью 9-11 задач, геморно, но толк есть от их решения.
> Там некоторые очень сложные бывают.
У меня немного задротский подход к сложным для меня задачам.
Кантор очень сложные задачи обычно подробно комментирует. То есть если идей у тебя вообще нет, то открывай спойлер, скорее всего там сначала в нескольких словах описан общий алгоритм решения. Если после прочтения алгоритма всё равно не смог решить, то тогда уже смотри его код, что уж там. Но тогда дай себе обещание завтра решить эту задачу, не подглядывая в решение. Бывает только кажется что понял, это неосознанный самообман. Надёжнее перепроверить себя через пару дней.
> Это делать до спойлера готового решения или после.
После того, как сам решил. Ну и так можно оценить преимущества/недостатки твоего кода по сравнению с кодом комментаторов. Вариться только в своём соку тоже не ок.
>>824235
А, я тогда гуглил "calling function with dynamic params js", разбирался в apply позже. Для решения первых 10-и задач хватит этих тем (скопировал с learn.javascript.ru):
Структуры данных
Замыкания, область видимости
Методы объектов и контекст вызова
Ну так ты читай ошибку: "Unable to find the wrapper "https" - did you forget to enable it when you configured PHP?"
PHP говорит с тобой, объясняя проблему в максимально понятной для человека форме. Попробуй применить технику пикрилейтед - раз всё так плохо.
Я к тому, что ошибка не в этом, потому-что ошибка с гет_контент так и осталась.
Убирание урленкода только новую ошибку породило.
Боюсь, что у тебя все не очень, т.к. вместо нормально подсказки ты рандомно тыкнул пальцем в небо и после этого спустился до оскорблений, даже не предположив, что я это уже гуглил и решения из гугла не работают в данном случае.
Объясняю, у тебя PHP без поддержки OpenSSL. Тебе нужно просто подключить это расширение. Тебе сам PHP разжевал эту пустяковую проблему, но ты слишком ленив, чтобы самостоятельно разобраться с ней.
Сообщение об ошибке абсолютно верное. Для начала открой раздел мануала про врапперы и изучи:
http://php.net/manual/ru/intro.stream.php
http://php.net/manual/ru/wrappers.php
http://php.net/manual/ru/function.file-get-contents.php
затем почитай про эту настройку
http://php.net/manual/ru/filesystem.configuration.php#ini.allow-url-fopen
Затем проверь через phpinfo() например, в каком состоянии у тебя разные настройки, какие врапперы доступны.
Ну и использовать file_get_contents для работы с АПИ не очень удобно. Если ты хочешь делать все серьезно, то лучше исплоьзовать библиотеку-http клиент вроде guzzle.
Вот этот нормально объяснил, спасибо.
По поводу фреймворка, мне хотелось бы сначала основы освоить.
Какие бы функции "из коробки" ты бы посоветовал для работы с апи вообще и в данной ситуации?
>>824316
А ты иди нахуй, хуйло хамовитое.
Guzzle это не фреймворк. Клиент АПИ удобно реализовывать в виде класса, так что тебе пригодилось бы хорошее понимание ООП.
Он кстати скорее всего правильную причину назвал.
В форме можно сделать выпадающий список или радио батан, value опций может быть как строкой "GENDER_MALE/GENDER_FEMALE", так и "0/1". А как хранить в студенте, и как преобразовать строку в константу?
Объявлять константу через define (GENDER_MALE, $gender), где $gender это значение "1/0" переданное формой, которое мы преобразовываем в число. То есть в классе только одна константа GENDER_MALE, значение которой = 1/0 (true/false)?
А как это хранить в базе? С помощью типа enum('1','0')?
Нужно ли валидировать значение полученное из формы с помощью выпадающего списка или радио батана?
> Он кстати скорее всего правильную причину назвал.
Конечно же нет, я раскомментировал строку с опенссл еще во время установки, почему решил не тратить время на общение с ретардом.
> затем почитай про эту настройку
Только что проверил allow_url_fopen, она тоже включена. Еще идеи есть?
Опять же, если хранить пол как $gender = GENDER_MALE, где значение константы 1|0, зачем вообще константа, если можно хранить $gender = 1?
Нагуглил способ - использовать функцию-хелпер для сборки запроса. Так можно делать http://phpfaq.ru/pdo#insert ?
Почему в мануале нет упоминания о том, что в PDOStatement::execute() аргументом можно передать объект?
Можно как-то сократить код, написав "этот код исполнять в любом $app->get"?
Если что, код: http://ideone.com/4txkUQ
Для такого обычно ООП используют. Сделай общий класс контроллера, потом все нужные контроллеры унаследуй от него.
Смотреть настройки надо не в php.ini, а в выводе phpinfo(). Там же надо смотреть список доступных врапперов.
>>824462
В чем разница между селектом и радиокнопками? Селект занимает меньше места, но за это приходится платить большим временем доступа и тем, что опции не видны сразу. С другой стороны, селект позволяет искать элемент по первой букве.
В случае с полом, у нас всего 2 опции, так что экономить место не нужно и подойдет селект.
Хранить в БД лучше в виду енума с значениям вроде male/female, в PHP сделать константы для них.
> Объявлять константу через define (GENDER_MALE, $gender)
Это вообще неправильно. Константа она на то и константа что всегда имеет одинаковое значение.
> С помощью типа enum('1','0')?
В значениях энумов нельзя использовать числа. Точнее можно, но большая вероятность что mysql примет их за порядковый номер элемента. См. мануал.
>>824606
Можно разве что чуть разнести код, вынеся преобразование объекта в массив в отдельный метод. Также вместо ручного указания каждого геттера сделать массив и в цикле получать значения каждого поля.
>Почему в мануале нет упоминания о том, что в PDOStatement::execute() аргументом можно передать объект
наверно потому что это плохая идея. Кто-то добавит в класс лишнее поле и твой execute сломается из-за того что передано лишнее значение.
Это неприавльно, что из-за добавления в класса одного поля код ломается где-то совсем в другом месте.
>>824620
Там по моему можно в начале кода (не в обработчике роута) просто олин раз во view передать нужную переменную напрямую.
>>824621
Переусложнение.
Смотреть настройки надо не в php.ini, а в выводе phpinfo(). Там же надо смотреть список доступных врапперов.
>>824462
В чем разница между селектом и радиокнопками? Селект занимает меньше места, но за это приходится платить большим временем доступа и тем, что опции не видны сразу. С другой стороны, селект позволяет искать элемент по первой букве.
В случае с полом, у нас всего 2 опции, так что экономить место не нужно и подойдет селект.
Хранить в БД лучше в виду енума с значениям вроде male/female, в PHP сделать константы для них.
> Объявлять константу через define (GENDER_MALE, $gender)
Это вообще неправильно. Константа она на то и константа что всегда имеет одинаковое значение.
> С помощью типа enum('1','0')?
В значениях энумов нельзя использовать числа. Точнее можно, но большая вероятность что mysql примет их за порядковый номер элемента. См. мануал.
>>824606
Можно разве что чуть разнести код, вынеся преобразование объекта в массив в отдельный метод. Также вместо ручного указания каждого геттера сделать массив и в цикле получать значения каждого поля.
>Почему в мануале нет упоминания о том, что в PDOStatement::execute() аргументом можно передать объект
наверно потому что это плохая идея. Кто-то добавит в класс лишнее поле и твой execute сломается из-за того что передано лишнее значение.
Это неприавльно, что из-за добавления в класса одного поля код ломается где-то совсем в другом месте.
>>824620
Там по моему можно в начале кода (не в обработчике роута) просто олин раз во view передать нужную переменную напрямую.
>>824621
Переусложнение.
Открой список вакансий в своем городе и почитай.
>Мало контрибьюшнов
>1 каммит
>1 аплоад за год, и тот в июле
>4 проекта уровня лабораторная работа или "мне бяло нечего делать, я тут ковырялся в коде и случайно закамитил"
>Камиты которые не описывают сути камита
>код без коментариев
>функции из 1 строки (зачем писать функцию из 3 строк обьявления и 1 строки действия когда просто действие будет быстрее?)
>Именование подпапок и каталогов 1 2 3 - нет смысла
>footer.php "<?php" - подключаемый файл содержит это.
Няша, я не хочу тебя оскорбить, но теперь быстро и уверенно иди читать как работать с гитхабом и что зачем надо камитить, и что надо в камиты писать. Это для начала.
>>812156
> https://github.com/never3ver/students_list/blob/master/students_students.sql
По cookie стоит сделать уникальнй индекс чтобы показать что они не повторяются.
> https://github.com/never3ver/students_list/blob/master/app/StudentsDataGateway.php#L12
Такие длинные строки стоит переносить.
> https://github.com/never3ver/students_list/blob/master/app/StudentsDataGateway.php#L67
Если слово для поиска не задано, то лучше бы и не добавлять в запрос условие LIKE.
> https://github.com/never3ver/students_list/blob/master/public/index.php#L35
Тут лучше бы инклудить только один файл, а уже футер подключать из него.
> https://github.com/never3ver/students_list/blob/master/templates/index.html#L4
> <?php if (!isset($_COOKIE['name'])):
View не должен лезть в куки. И вообще, определять залогинен ли пользователь, должен класс отвечающий за авторизацию.
При пагинации сортировка теряется? Так не должно быть.
> https://github.com/never3ver/students_list/blob/master/templates/pagination.html#L15
тут условия в пагинации выглядят избыточными. Мне кажется, хватило бы только проверки, является ли $i текущей страницей или нет.
У тебя много шаблонов, стоило бы те их них, которые отвечают за мелкие кусочки (вроде пагинации) вынести в подпапку.
> require_once __DIR__ . '/../templates/header.html'
не очень понятно, зачем тут '../templates' если эту часть можно убрать.
> https://github.com/never3ver/students_list/blob/master/app/Helper.php#L6
> public static function highlightText($word, $text) {
Если слово не указано, то эта функция возвращает текст без экранирования, возможна XSS.
> preg_replace("/$word/ui",
Это тоже неправильно. ты подставляешь текст от пользовтеля как регулярку, но что если он содержит специсмволы? Например знак вопроса. Как минимум может быть ошибка из-за неверного синтаксиса в регулярке. Надо использовать preg_quote чтобы заэкранировать специсмволы, чтобы любые символы воспринимались регуляркой как обычные.
> https://github.com/never3ver/students_list/blob/master/templates/header.html
тут не помешал бы тег meta charset с кодировкой. В поле поиска хорошо бы выводить введенное ранее в него значение.
https://github.com/never3ver/students_list/blob/master/templates/registerButton.html
тут лучше использовать не форму, а ссылку, которая стилизована в виде кнопки. В бутстрапе это есть.
> https://github.com/never3ver/students_list/blob/master/public/styles.css#L17
> .cell {
Тут не надо было заводить класс, можно было просто написать .table > tr > td {} или .table td {}
> https://github.com/never3ver/students_list/blob/master/app/StudentValidator.php#L14
написано что имя может содержать апострофы и дефисы, но в регулярке их нет. В регулярке нет привязки к краям строки потому вместо имени можно вписывать что угодно, лишь бы там была одна буква.
Выражение для проверки email кривое. Оно например не пропустит многогуровневый домен вроде iQg vanANUSZ\feduPUNCTUMr4A\u или ivag'HnANUSунивеQ 1рситетPUNCTUM:8"рф
Статьи по теме: https://www.google.ru/search?q=habr+проверки+email+регуляркой&newwindow=1&gbv=1&sei=-Fm6V4LdD4KsswGhl6HQAg
> if ($this->gateway->isEmailUnique($email) || $email == $oldEmail) {
при редактировании надо искать уникальный email везде, кроме самого студента. Это удобно делать, отсеивая записи по id.
Число баллов по ЕГЭ по моему в сумме для 3 предметов может доходить до 300.
> $errors = FALSE;
> $errors['name'] = "Имя может...
Как-то странно смотрится добавление элемента не в массив, а в false.
https://github.com/never3ver/students_list/blob/master/app/Authorization.php
Странно, что этот класс может ставить куку name, но читает ее файл regedit.php. Логично работу с этой кукой инкапсулировать в этом классе, а не в нескольких разных местах кода.
https://github.com/never3ver/students_list/blob/master/public/regedit.php#L11
> if (isset($_COOKIE['name'])) {
Вот это мне кажется должно быть в классе авторизации.
> header("Refresh: 0; url = index.php");
Что за странные костыли? Прочитай про HTTP код ответа 3xx и заголовок Location.
После редиректа не надо выводить форму.
https://github.com/never3ver/students_list/blob/master/templates/editForm.html#L40
для поля с типом email не надо указывать регулярку - оно само умеет проверять.
https://github.com/never3ver/students_list/blob/master/templates/editForm.html#L49
Для поля с типом number указывается не регулярка, а min/max/step
https://github.com/never3ver/students_list/blob/master/templates/editForm.html#L68
> <?= ((!property_exists($student, "local")
Это странный код, как в классе может отсутстовать поле?
https://github.com/never3ver/students_list/blob/master/app/init.php#L3
Конфиг логично подключать без once.
Не помешало бы добавить в репозиторий краткий README с описанием, что это за проект и как его установить.
Центрирование данных в полях ввода по моему выглядит ужасно, поля слишком маленькие.
Не надо использовать для верстки формы таблицу, в бутстрапе есть стили для такой формы.
При клике по словам "мужской"/"женский" должна выбираться соответствующая опция. Гугли label.
После регистрации надо бы выводить над списком уведомление "Вы успешно зарегистрированы.", после обновления профиля "Данные успешно обновлены".
После регистрации и захода в редактирование у меня не отображается фамилия, год и номер группы. В базе запись есть, просто оно теряется при выборке из БД и записи данных в объект. Выясни, почему. Ну и конечно стоило более тщательно тестировать свое приложение, чтобы такие явные баги не допускать.
Вместо огромной кнопки "редактировать" лучше наверно поставить ссылку.
Из положительных моментов могу отметить лаконичность, довольно небольшой по объему код получился.
>>812156
> https://github.com/never3ver/students_list/blob/master/students_students.sql
По cookie стоит сделать уникальнй индекс чтобы показать что они не повторяются.
> https://github.com/never3ver/students_list/blob/master/app/StudentsDataGateway.php#L12
Такие длинные строки стоит переносить.
> https://github.com/never3ver/students_list/blob/master/app/StudentsDataGateway.php#L67
Если слово для поиска не задано, то лучше бы и не добавлять в запрос условие LIKE.
> https://github.com/never3ver/students_list/blob/master/public/index.php#L35
Тут лучше бы инклудить только один файл, а уже футер подключать из него.
> https://github.com/never3ver/students_list/blob/master/templates/index.html#L4
> <?php if (!isset($_COOKIE['name'])):
View не должен лезть в куки. И вообще, определять залогинен ли пользователь, должен класс отвечающий за авторизацию.
При пагинации сортировка теряется? Так не должно быть.
> https://github.com/never3ver/students_list/blob/master/templates/pagination.html#L15
тут условия в пагинации выглядят избыточными. Мне кажется, хватило бы только проверки, является ли $i текущей страницей или нет.
У тебя много шаблонов, стоило бы те их них, которые отвечают за мелкие кусочки (вроде пагинации) вынести в подпапку.
> require_once __DIR__ . '/../templates/header.html'
не очень понятно, зачем тут '../templates' если эту часть можно убрать.
> https://github.com/never3ver/students_list/blob/master/app/Helper.php#L6
> public static function highlightText($word, $text) {
Если слово не указано, то эта функция возвращает текст без экранирования, возможна XSS.
> preg_replace("/$word/ui",
Это тоже неправильно. ты подставляешь текст от пользовтеля как регулярку, но что если он содержит специсмволы? Например знак вопроса. Как минимум может быть ошибка из-за неверного синтаксиса в регулярке. Надо использовать preg_quote чтобы заэкранировать специсмволы, чтобы любые символы воспринимались регуляркой как обычные.
> https://github.com/never3ver/students_list/blob/master/templates/header.html
тут не помешал бы тег meta charset с кодировкой. В поле поиска хорошо бы выводить введенное ранее в него значение.
https://github.com/never3ver/students_list/blob/master/templates/registerButton.html
тут лучше использовать не форму, а ссылку, которая стилизована в виде кнопки. В бутстрапе это есть.
> https://github.com/never3ver/students_list/blob/master/public/styles.css#L17
> .cell {
Тут не надо было заводить класс, можно было просто написать .table > tr > td {} или .table td {}
> https://github.com/never3ver/students_list/blob/master/app/StudentValidator.php#L14
написано что имя может содержать апострофы и дефисы, но в регулярке их нет. В регулярке нет привязки к краям строки потому вместо имени можно вписывать что угодно, лишь бы там была одна буква.
Выражение для проверки email кривое. Оно например не пропустит многогуровневый домен вроде iQg vanANUSZ\feduPUNCTUMr4A\u или ivag'HnANUSунивеQ 1рситетPUNCTUM:8"рф
Статьи по теме: https://www.google.ru/search?q=habr+проверки+email+регуляркой&newwindow=1&gbv=1&sei=-Fm6V4LdD4KsswGhl6HQAg
> if ($this->gateway->isEmailUnique($email) || $email == $oldEmail) {
при редактировании надо искать уникальный email везде, кроме самого студента. Это удобно делать, отсеивая записи по id.
Число баллов по ЕГЭ по моему в сумме для 3 предметов может доходить до 300.
> $errors = FALSE;
> $errors['name'] = "Имя может...
Как-то странно смотрится добавление элемента не в массив, а в false.
https://github.com/never3ver/students_list/blob/master/app/Authorization.php
Странно, что этот класс может ставить куку name, но читает ее файл regedit.php. Логично работу с этой кукой инкапсулировать в этом классе, а не в нескольких разных местах кода.
https://github.com/never3ver/students_list/blob/master/public/regedit.php#L11
> if (isset($_COOKIE['name'])) {
Вот это мне кажется должно быть в классе авторизации.
> header("Refresh: 0; url = index.php");
Что за странные костыли? Прочитай про HTTP код ответа 3xx и заголовок Location.
После редиректа не надо выводить форму.
https://github.com/never3ver/students_list/blob/master/templates/editForm.html#L40
для поля с типом email не надо указывать регулярку - оно само умеет проверять.
https://github.com/never3ver/students_list/blob/master/templates/editForm.html#L49
Для поля с типом number указывается не регулярка, а min/max/step
https://github.com/never3ver/students_list/blob/master/templates/editForm.html#L68
> <?= ((!property_exists($student, "local")
Это странный код, как в классе может отсутстовать поле?
https://github.com/never3ver/students_list/blob/master/app/init.php#L3
Конфиг логично подключать без once.
Не помешало бы добавить в репозиторий краткий README с описанием, что это за проект и как его установить.
Центрирование данных в полях ввода по моему выглядит ужасно, поля слишком маленькие.
Не надо использовать для верстки формы таблицу, в бутстрапе есть стили для такой формы.
При клике по словам "мужской"/"женский" должна выбираться соответствующая опция. Гугли label.
После регистрации надо бы выводить над списком уведомление "Вы успешно зарегистрированы.", после обновления профиля "Данные успешно обновлены".
После регистрации и захода в редактирование у меня не отображается фамилия, год и номер группы. В базе запись есть, просто оно теряется при выборке из БД и записи данных в объект. Выясни, почему. Ну и конечно стоило более тщательно тестировать свое приложение, чтобы такие явные баги не допускать.
Вместо огромной кнопки "редактировать" лучше наверно поставить ссылку.
Из положительных моментов могу отметить лаконичность, довольно небольшой по объему код получился.
>Также вместо ручного указания каждого геттера сделать массив и в цикле получать значения каждого поля.
Реализовав интерфейс ArrayAccess в классе Abiturient? Или массив названий свойств, превращая их в вызов метода getPropertyName()?
> функции из 1 строки (зачем писать функцию из 3 строк обьявления и 1 строки действия когда просто действие будет быстрее?)
Затем, что название функции более читабельно. Это на практике часто используется, оцени читабельность:
$className = camelize($className);
function camelize($str) {
return preg_replace_callback('/-(.)/', function ($match) { return strtoupper($match[1]); }, $str)
}
против
$className = preg_replace_callback('/-(.)/', function ($match) { return strtoupper($match[1]); }, $str);
Первый код читается проще, так как не нужно разбираться во внутренностях camelize(), и так понятно, что слово преобразуется в camel case. Во втором случае не понятно, нужно разбираться в preg_replace_callback.
Да и банально, может у него там код повторяется в нескольких местах? Логично вынести такой код в функцию в таком случае.
Есть обыкновенная HTML форма, в нее заполняется некая информация и затем она отправляется POST'ом на эту же страницу (index.php), где ее обрабатывает скрипт PHP (пишет в файл и все такое). Проблема в том, что если вернуться назад кнопкой "назад", все поля остаются заполненными и ее можно отправить снова. Хоть бесконечно надрачивать Enter и Backspace отправляю по 300к форм в секунду. Пробовал делать перезагрузку страницы после обработки формы, пробовал рандомный id ей присваивать (бесполезно, ведь загружается из кэша старая страница со старым id), пробовал гуглить - нихуя. Какие есть мысли? Встречал на других сайтах, в основном, банках, ошибку "страница просрочена" при попытке вернутся назад после отправки формы, т. е. ошибку, не позволяющую вернуться на предыдущую страницу вообще. Гуглил, но ничего не нашел. Прошу помощи, господа.
перепостил сюда, а то в вашем сральнике на объективную критику не обижаются не разберешься
Тоже столкнулся с такой проблемой, для себя решил с помощью импровизированной невидимой "капчи" с использованием $_SESSION.
Ты же понимаешь что это не до конца решает проблему? Твой способ можно легко обойти, если каждый раз получать новую сессию.
Лол тогда можно сказать и "Ты же понимаешь, что любой способ можно легко обойти если заставить бота 300к раз в секунду заполнять одно и тоже в поля и сабмитить форму". То, что ты ищешь, скорее всего не имеет отношения к PHP.
Спасибо.
>После регистрации и захода в редактирование у меня не отображается фамилия, год и номер группы.
Вот это очень странно, у меня все норм.
Попробуй создать новую пустую базу данных, загрузить в нее дамп с гитхаба, и переключить конфиг на эту базу. Затем протестируй.
Если не увидишь бага на новой созданной базе - я напишу в чем причина.
У тебя просто скорее всего либо база создана не из дампа и отличается, либо код отличается от того что на гитхабе.
{% include "file.php" %} и банальное <?php?> отказываются работать. В интернетах пишут, что для реализации какой-нибудь даже самой банальной функции придется пилить свое расширение для твига. Но я ни за что не поверю, что все так сложно. Т
А зачем тебе php код в шаблоне? Шаблоны как раз придуманы чтобы там никакой особой логики не было.
Почитай про архитектуру MVC. Основная суть которой заключается в разделении приложения на три части - M - Модель, V - Представление (View) и C - Контроллер. Так вот в твоем случае Twig у тебя представление, он отвечает только за вывод того что ему передали на экран.
>он отвечает только за вывод того что ему передали на экран.
Теперь ты понял вопрос? Как передать ему то, что он будет выводить на экран?
Ох, окей. Я-то думал шаблонизировать через твиг можно спокойно и без соблюдения модели мвц. Добра тебе, буду курить мануалы по MVC
При вызове template->render() передавай массив который будет соответствовать переменным в шаблоне.
В документации это более подробно описано с примерами
http://twig.sensiolabs.org/doc/api.html#basics
>template->render() передавай массив который будет соответствовать переменным в шаблоне.
Но ведь это убирает всё веселье из программирования.
Спасибо анон.
Чот ты вообще либо наркоман, либо ты не понял что я написал.
>>825497
Логику приложения ты должен реализовать где-то в другом месте, цель у твига - рендерить то что ему передали. Можно это делать и без соблюдения MVC, просто реализовать логику в одном файле, и в конце вызывать рендер шаблона, но обычно такой код будет плохим и его сложно поддерживать, через 2 месяца ты и сам не поймешь как оно там работает.
Если что - мы с ним разные аноны. Спасибо.
Конечно нужно сортировать только текущий результат. Как ты себе представляешь полную сортировку всей базы, если там например миллион записей?
>Как ты себе представляешь полную сортировку всей базы, если там например миллион записей?
Пузырьком ))
Все, нашел причину. Я переименовывал имена полей в базе и забыл заново сдампить, моя невнимательность, залил актуальный дамп.
Наверное существует способ и для сортировки миллиона записей. Я вообще мало, что представляю, как всегда гуглил бы пока не нашел способ. И в данной задаче записей не миллион.
>>825576 (OP)
>>825576 (OP)
ПЕРЕКАТ
Итак, 500 сообщений набрали, перекатились, нас уже на видно ньюфагам, и те, вместо поиска (который кстати не ищет 3 букву PHP) создают новые треды.
Перекатывайся в старый, уютненький, ламповый тред. Я там приготовил оп пост и оп пасты. Всё для твоего комфорта, няша.
>>825576 (OP)
>>825576 (OP)
>>825576 (OP)
И как это работает? При возврате на предыдущую страницу ты видишь чистую форму? Или заполненную, но которую просто не примет сервер при попытке отправить? Если второе, то хуйня собачья, я тоже так могу, а хочется красивое решение.
Сортируется вся база. То есть если ты жмешь на сортировку по баллам, ты хочешь увидеть лучших или худших во всей базе (с учетом введенного слова для поиска), а не только на текущей странице.
При нажатии на сортировку текущий номер страниц сбрасывается и мы оказываемся на первой. Но если мы пользуемся пагинацией то сортировка и введенное поисковое слово сохраняются.
>>825532
Индексы либо какой-то алгоритм сортировки который испоьзует mysql
>>825581
Посидим еще пару (-другую) дней и перекатимся. Пока мало ответов на посты.
Так спасибо конечно. Правда ты нумерацию нечаянно сломал, 80-й тред был этот. Так как предыдущий 79. Придется этот называть 79.5.
>Правда ты нумерацию нечаянно сломал, 80-й тред был этот. Так как предыдущий 79. Придется этот называть 79.5.
На самом деле очень долго думал как нумеровать, 80 или 81, но у этого заголовок было вообще без нумерации, и перекатили его без копипаст, назвал 80 тредом. Дальше буду знать.
Кто подскажет по PDO?
Ты только что решил 10 часов моих страданий. Одно из полей БД НЕ ИМЕЛО ЗНАЧЕНИЯ ПО ДЕФОЛТУ! Из-за этого он отказывался работать.
Зачем? Зачем они это сделали? Я ведь даже не упоминал это поле в запросе. Ну что за бред...
Спасибо тебе анон. Ты лучший!
Сейчас поднял тот скрипт - в двух браузерах при нажатии на "Назад" форма чистая. Причем в коде только PHP и HTML.
Если у поля стоит NOT NULL и нет значения по умолчанию то это значит что оно обязательно для заполнения. Это наоборот хорошо, позволяет защититься от ошибки, что ты забыл заполнить это поле.
>>825869
У европейцев ноты тоже вроде буквами обозначаются.
>>825171
>>825276
После обработки POST-формы надо делать редирект. Таким образом, если пользователь случайно нажмет "обновить страницу", форма не переотправится.
От намеренной переотправки надо защищаться на сервере, например введя счетчик частоты отправки формы, сравнивая значения в форме с предыдущими итд.
Сессия бесполезная вещь так как злонамеренный пользователь удалит сессионную куку.
>Если у поля стоит NOT NULL и нет значения по умолчанию то это значит что оно обязательно для заполнения.
Чтоб 10 раз не спорить. Алсо Mysql, Mysqli - туда всё добавляют без проблем.
По такому скриншоту трудно что-то однозначно понять. Что значит пустая ячейка в поле значение по умолчанию? Лучше сделать SHOW CREATE TABLE x .
Это значит что параметр по умолчанию не задан. Ну просто он там не нужен, ест такие параметры, которые если есть - запиши, если нет - пусть будет пустое поле. 10 лет с БД работаю, никогда и нигде проблем небыло. А тут види-те ли укажи что по дефолту, а то не буду работать.
Ещё подводный камень кстати. Date формат. работал работал, а потом резко решил не принимать формат даты 0000.00.00 00.00, Собственно и пофигу, перенастроил бы и дальше бы работал. Вот только этот формат был заполнен как дефолтный! И работал в БД до того как я PDO подключил. Вот уж загадка загадок что там у PDO и Mysql произошло.
Самофикс, формат даты другой немного, но если хотите подробностей - на скриншоте видно какой на самом деле. Уж простите, не помню всех этих нулей.
По студентам и авторизации, я подумал еще, и вложенность if увеличилась, когда подгружаем список студентов, нужно еще отслеживать сортировку. А еще получается, что нужно проверять авторизацию пользователя в обоих контроллерах index.php и register.php. И каждый раз, как обновляется страница, например при сортировке. Значить дублируется код, и + запрос в базу каждое обновление страницы.
Нужно ли действительно проверять авторизацию пользователя в каждом контроллере?
Как избавиться от запроса в базу при каждый раз при обновлении страницы?
Как обойти трехуровневую вложенность if?
После отправки заголовка браузеру, скрипт php перестаёт работать. Все переменные затираются. Правильно? То-есть отправка заголовка header ("location..") скрипт как-бы перезагружается? Сохранить(кэшировать) значения переменных можно только в куки пользователя?
Сессии ещё есть.
Почитай урок https://github.com/codedokode/pasta/blob/master/soft/web-server.md например
Каждый запрос от браузера обрабатывается отдельной копией программы (отдельным процессом) который ничего не знает про остальные.
https://github.com/TheSidSpears/Students
https://github.com/TheSidSpears/FileHosting
ОП, занятой месяц выдался?
Поставить аддон к браузеру. Xdebug helper для хрома например. Ну и нужно понимать как работать с xdebug.
Пока временно забил на проблемы с опенссл(или не опен ссл).
Смог вывести жсон с апи в форме массива, только массив какой-то странный и я не ебу как с ним работать.
На команды для обычных массивов он реагирует.
Что я делаю не так? Может мне вообще не нужен массив тут и надо зайти с другой стороны?
<?php
$url = "http://api.fixer.io/latest";
$urlContent = file_get_contents($url);
$jsonDecoded = json_decode($urlContent, true);
// header for showing content as text in browser
header("Content-Type: text/plain");
echo "Rates for {$jsonDecoded['base']} on {$jsonDecoded['date']}: \n";
foreach ($jsonDecoded['rates'] as $money => $rate) {
echo "$money - $rate\n";
}
>>815064
>Перечитай про боксовую модель: https://developer.mozilla.org/ru/docs/Web/CSS/box_model или http://htmlbook.ru/samlayout/blochnaya-verstka/blochnaya-model
>
>Ты забыл что width задает не внешнюю ширину, а внутреннюю.
Исправил: https://jsfiddle.net/9ygm244j/1/
>>815064
>
>> .container {
>> padding: 10px;
>> font-size: 0px;
>> display:table;
>не понял, зачем это? Зачм таблица без table-row или table-cell? Также не понял, зачем ты таблице ставишь паддинг, который есть только у ее ячеек. Это какой-то хак для решения проблемы пробелов? Стоило тогда добавить комментарий, а то совсем неочевидно. Ну и конечно изучи и другие методы борьбы.
>
>А так, верно.
Добавил комментарий в месте хака проблемы с пробелами: https://jsfiddle.net/211Le60v/6/
>Ну и конечно изучи и другие методы борьбы.
Да, я изучил их все. Например, здесь https://jsfiddle.net/5g31m30j/2/ для борьбы с проблемой пробелов, я убрал переносы на новую строку между элементами.
>>815064
>
>А вот тут многовато ошибок:
>
>- li { margin: 5px 0px; } меняет стиль всех элементов списков, а на странице могут быть и другие списки. Надо ставить стили точечно, чтобы это применялось только к меню. То же относится к ul, nav
>- ты жестко прописал размеры body. Это не годится. Верстка должна растягиваться под ширину страницы.
>- font-family: 'Trebuchet MS'; - надо указывать в конце списка один из встроенных шрифтов (вроде sans-serif)
>- h1 должен быть не жирным
>- article { width: 230px; } - статья должна занимать всю оставшуюся ширину, а не 230px
>- nav:after {} - он тут не нужен. Он применяется к не-float элементам, которые содержат внутри float элементы. А у тебя nav и так float и ему clearfix не нужен.
Все сломалось: https://jsfiddle.net/L5orb28e/6/ . Такое поведение перестает происходить если контенту задать ширину равной ширине страницы минус занимаемая ширина колонки меню: https://jsfiddle.net/L5orb28e/7/ . Однако, если продолжать сжимать окно, контент рано или поздно съедит вниз. Почему так происходит?
>.navigation-menu-li
>.navigation-menu-ul > li
Ведь можно использовать оба из этих варианта?
>>815064
>
>Высота кнопки и поля ввода не совпадают. Ты учел что кнопки и поля ввода по умолчанию имеют разный box-sizing, для одного задается внутреняя высота, для другого - внешняя. надо либо менять box-sizing либо пересчитывать высоту с учетом этого. Читай подсказки (хотя бы после того как решил).
>
>Ну и на практике стили вроде input {...} будут конфликтовать с другими инпутами на странице - лучше применять стили более точечно.
Исправил: https://jsfiddle.net/5g31m30j/2/
>>815064
>> А можно подсказку как сделать чтобы примечание не растягивала контейнер в котором оно содержится? У меня пока получилось только так https://jsfiddle.net/tsuh4gjw/4/
>float не растягивает родительский контейнер (а также position: absolute) так как вырывается из потока.
Я не правильно выразился, я не могу понять как сделать чтобы примечание было всегда на уровне второго абзаца.
>>815064
>
>- Текст не должен затекать под желтый блок слева.
>- div {} - будет применяться ко всем дивам на странице, плохо, сломает верстку. Верстать надо так, чтобы твою верстку можно было вставить на любую страницу и не было никаких конфликтов.
Исправил: https://jsfiddle.net/kxdx27f1/3/
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-10
https://jsfiddle.net/a70nha0k/ (Если блок с картинкой не отображается, значит картинки нет на сервере)
А как сделать чтобы числа в квадратных скобках выравнивались слева от абзаца? Мне удалось выровнить их с помощь абсолютного позиционирования, но подозреваю что этот вариант не правильный, потому что размер контентной части элемента может быть любым.
>обрати внимание, размер картинки должен определяться так: если картинка большая — она ужимается до ширины окна (с учетом полей конечно), маленькая — выводится как есть.
Большая картинка должна ужиматься именно до ширины окна, а не до ширины блока в котором она содержиться? Учитывая что по условию задачи размер тела максимально может быть 500 пикселей. Даже если представить что за место тела может быть любой блочный элемент, это довольно странно задавать дочернему элементу ширину большую чем ширину родительскому. Или это такой подвох в задании?
>z-index: 1;
Не уверен что это свойство нужно, т.к. элемент которому мы задаем это свойство всегда будет находиться ниже по коду другого абсолютно позиционированного элемента em:before.
>>815064
>
>- между кнопками должна быть линия в 1px а не 2 пикселя
>- кнопки высоковаты
>- body { font-size: 0px; display: table; } - это не позволяет вставить твой блок на произвольную страницу. мы ведь не будем там сбрасывать шрифт на body.
>- "inputbox left" - это неудобно, подписывать каждый блок. И что если у нас не 3, а больше кнопок? переписывать CSS? Нужно более универсальное решение. Есть же :first-child например. Погугли "css псевдоклассы"
>- для анимации наверно лучше бы подошло более простое правило transition - изучи его. Или нет?
Исправил: https://jsfiddle.net/fp8o0exq/5/
>>815064
>Перечитай про боксовую модель: https://developer.mozilla.org/ru/docs/Web/CSS/box_model или http://htmlbook.ru/samlayout/blochnaya-verstka/blochnaya-model
>
>Ты забыл что width задает не внешнюю ширину, а внутреннюю.
Исправил: https://jsfiddle.net/9ygm244j/1/
>>815064
>
>> .container {
>> padding: 10px;
>> font-size: 0px;
>> display:table;
>не понял, зачем это? Зачм таблица без table-row или table-cell? Также не понял, зачем ты таблице ставишь паддинг, который есть только у ее ячеек. Это какой-то хак для решения проблемы пробелов? Стоило тогда добавить комментарий, а то совсем неочевидно. Ну и конечно изучи и другие методы борьбы.
>
>А так, верно.
Добавил комментарий в месте хака проблемы с пробелами: https://jsfiddle.net/211Le60v/6/
>Ну и конечно изучи и другие методы борьбы.
Да, я изучил их все. Например, здесь https://jsfiddle.net/5g31m30j/2/ для борьбы с проблемой пробелов, я убрал переносы на новую строку между элементами.
>>815064
>
>А вот тут многовато ошибок:
>
>- li { margin: 5px 0px; } меняет стиль всех элементов списков, а на странице могут быть и другие списки. Надо ставить стили точечно, чтобы это применялось только к меню. То же относится к ul, nav
>- ты жестко прописал размеры body. Это не годится. Верстка должна растягиваться под ширину страницы.
>- font-family: 'Trebuchet MS'; - надо указывать в конце списка один из встроенных шрифтов (вроде sans-serif)
>- h1 должен быть не жирным
>- article { width: 230px; } - статья должна занимать всю оставшуюся ширину, а не 230px
>- nav:after {} - он тут не нужен. Он применяется к не-float элементам, которые содержат внутри float элементы. А у тебя nav и так float и ему clearfix не нужен.
Все сломалось: https://jsfiddle.net/L5orb28e/6/ . Такое поведение перестает происходить если контенту задать ширину равной ширине страницы минус занимаемая ширина колонки меню: https://jsfiddle.net/L5orb28e/7/ . Однако, если продолжать сжимать окно, контент рано или поздно съедит вниз. Почему так происходит?
>.navigation-menu-li
>.navigation-menu-ul > li
Ведь можно использовать оба из этих варианта?
>>815064
>
>Высота кнопки и поля ввода не совпадают. Ты учел что кнопки и поля ввода по умолчанию имеют разный box-sizing, для одного задается внутреняя высота, для другого - внешняя. надо либо менять box-sizing либо пересчитывать высоту с учетом этого. Читай подсказки (хотя бы после того как решил).
>
>Ну и на практике стили вроде input {...} будут конфликтовать с другими инпутами на странице - лучше применять стили более точечно.
Исправил: https://jsfiddle.net/5g31m30j/2/
>>815064
>> А можно подсказку как сделать чтобы примечание не растягивала контейнер в котором оно содержится? У меня пока получилось только так https://jsfiddle.net/tsuh4gjw/4/
>float не растягивает родительский контейнер (а также position: absolute) так как вырывается из потока.
Я не правильно выразился, я не могу понять как сделать чтобы примечание было всегда на уровне второго абзаца.
>>815064
>
>- Текст не должен затекать под желтый блок слева.
>- div {} - будет применяться ко всем дивам на странице, плохо, сломает верстку. Верстать надо так, чтобы твою верстку можно было вставить на любую страницу и не было никаких конфликтов.
Исправил: https://jsfiddle.net/kxdx27f1/3/
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-10
https://jsfiddle.net/a70nha0k/ (Если блок с картинкой не отображается, значит картинки нет на сервере)
А как сделать чтобы числа в квадратных скобках выравнивались слева от абзаца? Мне удалось выровнить их с помощь абсолютного позиционирования, но подозреваю что этот вариант не правильный, потому что размер контентной части элемента может быть любым.
>обрати внимание, размер картинки должен определяться так: если картинка большая — она ужимается до ширины окна (с учетом полей конечно), маленькая — выводится как есть.
Большая картинка должна ужиматься именно до ширины окна, а не до ширины блока в котором она содержиться? Учитывая что по условию задачи размер тела максимально может быть 500 пикселей. Даже если представить что за место тела может быть любой блочный элемент, это довольно странно задавать дочернему элементу ширину большую чем ширину родительскому. Или это такой подвох в задании?
>z-index: 1;
Не уверен что это свойство нужно, т.к. элемент которому мы задаем это свойство всегда будет находиться ниже по коду другого абсолютно позиционированного элемента em:before.
>>815064
>
>- между кнопками должна быть линия в 1px а не 2 пикселя
>- кнопки высоковаты
>- body { font-size: 0px; display: table; } - это не позволяет вставить твой блок на произвольную страницу. мы ведь не будем там сбрасывать шрифт на body.
>- "inputbox left" - это неудобно, подписывать каждый блок. И что если у нас не 3, а больше кнопок? переписывать CSS? Нужно более универсальное решение. Есть же :first-child например. Погугли "css псевдоклассы"
>- для анимации наверно лучше бы подошло более простое правило transition - изучи его. Или нет?
Исправил: https://jsfiddle.net/fp8o0exq/5/
>>815065
>> Как на глаз определить тень и шрифт?
>Для начала, надо попробовать определить радиус тени (на котором она плавно переходит в прозрачность). Если присмотреться, то видно что на картинке тень несимметричная: она большая сверху, маленькая снизу и равная по сторонам. Значит, тень смещена вниз, а справа или слева ее ширина. По ней мы подбираем радиус (будет примерно пикселя 3 я думаю). подобрав радиус, подбираем прозрачность черного, чтобы с краев тень совпадала по прозрачности с картинкой.
>
>Ну и напоследок подбираем вертикальное смещение тени, просто на глаз двигая тень вниз.
>
>Если ты не понимаешь некоторые термины, то изучи какие есть параметры у теней. Заметь что для внутренних (inset) теней одним параметром меньше.
>
>Шрифт -какой-то из стандартных. Погугли какие распространенные шрифты есть, по моему тут Arial.
Я зря потратил ваше время спросив об этом - у меня слишком мало опыта чтобы определять такие вещи на взгляд. Извините.
В боевых задачах мне тоже может прийтись определять стили на глаз или всё можно будет посмотреть в .psd шаблоне?
>Также, как насчет клавиатурной навигации?
Теперь она работает.
>> Я пока не знаю javascript, можно я доделаю это позже? Можно пока подсказку как сделать чтобы в старых браузерах просто выводился набор чекбоксов?
>Гм... тут надо использовать в селекторе CSS правила которые не понимают старые браузеры (напрмер какие-то псевдоклассы из CSS3). То есть условно говоря, если старый браузер не понимает n-th-child() то мы можем записать так:
>
>.inputbox { правила для старых браузеров }
>.inputbox:n-th-child(...) { переопределяем правило для новых }
Поскольку я, зачастую, использую обращение через дочерние селекторы E > F, мне не приходиться переопределять правила. Единственное исключение это фикс пробелов в родительском контейнере, который я переопределил с помощью .buttons[class="buttons"]. Казалось бы, селектор не имеет смысла, а оказывается, что это с помощью этого хинта можно переопределять правила для новых браузеров.
Посмотреть как выводиться набор чекбоксов в IE6 остальные браузеры не нашел в сервисе можно здесь: https://www.browserstack.com/screenshots/9ed0ab72d90b74731e1e322918d35072313553d9
>> А можно еще подсказку как и это сделать?
>Скрыть чекбокс можно и не через display: none, а например: через visibility: hidden, через overflow:hidden c задвижением за край видимой области, через абс. поз. за край видимой области (left: -10000px) - но тут есть свои недостатки. Ты кстати должен знать эти варианты.
Через visibility: hidden и overflow: hidden почему-то не получилось.
https://jsfiddle.net/gpysbfar/
https://jsfiddle.net/gpysbfar/1/
Можно подсказку что я упустил?
>>815065
>Хорошо бы хотя бы от id в CSS избавиться
>Есть еще такая проблема: активная вкладка при наведении мыши становится серой - мне кажется это неправильно.
Исправил: https://jsfiddle.net/tb7k9dw9/4/
Посмотреть как выводиться в IE6: https://www.browserstack.com/screenshots/9f6a23a7d2634a0cc4b1be7a668f024aae54af68
>Кстати есть еще такая интересная статья по вкладкам: http://chikuyonok.ru/2009/04/dl-tabs/
Но там же делается решение через JS - если пользователь отключит его, то всё сломается.
В любом случае, я взял на вооружение этот метод, потому что наверняка в боевых задачах будет требоваться чтобы это через JS было сделанно, хоть мне и не нравиться такой подход.
>> #first-tab:checked + .tab-label[for="first-tab"] + #second-tab + .tab-label[for="second-tab"] + #third-tab + .tab-label[for="third-tab"] + #fourth-tab + .tab-label[for="fourth-tab"]
>В новых браузерах есть селектор ~. Нагугли и прочитай про все новые псевдоклассы и селекторы из CSS3. В старых браузерах он правда не работает, для них можно наверно просто вкладки вертикально вывести как блоки.
Я пробовал использовать такой селектор, но в нашем случае такой вариант не подходит по следующим причинам:
1. Если заключить инпутбокс в лейбел, то через него не получиться обращаться к следующим инпутбоксам https://jsfiddle.net/khxu17s0/
2. Если придерживаться метода где мы связываем инпутбокс и лейбел через for, то через этот селектор становиться трудно обратиться к контентному боксу, т.к. первый инпутбокс может оказаться родственным и для остальных контентных блоков https://jsfiddle.net/khxu17s0/1/
>>>сверстай блок так, чтобы блок с вкладками можно было вложить в страницу блока вкладок
>> Нужно чтобы можно было скопировать вкладки в контентную страницу? Может лучше чтобы в контентной странице был свой элемент со вкладками? Так для это следует задать ему собственные атрибуты и стили. Зачем делать по два раза одно и тоже? Я что-то недопонял?
>
>да, чтобы внутри мог быть свой блок с вкладками и он не конфликтовал с родительским.
Я не понял в чем подвох этой задачи - я просто добавил тот же самый табер только с новыми стилями.
><taber>
А можно создавать свои элементы?
Почему плохо использовать id?
Почему нужно поддерживать старые браузеры?
>>815065
>> Как на глаз определить тень и шрифт?
>Для начала, надо попробовать определить радиус тени (на котором она плавно переходит в прозрачность). Если присмотреться, то видно что на картинке тень несимметричная: она большая сверху, маленькая снизу и равная по сторонам. Значит, тень смещена вниз, а справа или слева ее ширина. По ней мы подбираем радиус (будет примерно пикселя 3 я думаю). подобрав радиус, подбираем прозрачность черного, чтобы с краев тень совпадала по прозрачности с картинкой.
>
>Ну и напоследок подбираем вертикальное смещение тени, просто на глаз двигая тень вниз.
>
>Если ты не понимаешь некоторые термины, то изучи какие есть параметры у теней. Заметь что для внутренних (inset) теней одним параметром меньше.
>
>Шрифт -какой-то из стандартных. Погугли какие распространенные шрифты есть, по моему тут Arial.
Я зря потратил ваше время спросив об этом - у меня слишком мало опыта чтобы определять такие вещи на взгляд. Извините.
В боевых задачах мне тоже может прийтись определять стили на глаз или всё можно будет посмотреть в .psd шаблоне?
>Также, как насчет клавиатурной навигации?
Теперь она работает.
>> Я пока не знаю javascript, можно я доделаю это позже? Можно пока подсказку как сделать чтобы в старых браузерах просто выводился набор чекбоксов?
>Гм... тут надо использовать в селекторе CSS правила которые не понимают старые браузеры (напрмер какие-то псевдоклассы из CSS3). То есть условно говоря, если старый браузер не понимает n-th-child() то мы можем записать так:
>
>.inputbox { правила для старых браузеров }
>.inputbox:n-th-child(...) { переопределяем правило для новых }
Поскольку я, зачастую, использую обращение через дочерние селекторы E > F, мне не приходиться переопределять правила. Единственное исключение это фикс пробелов в родительском контейнере, который я переопределил с помощью .buttons[class="buttons"]. Казалось бы, селектор не имеет смысла, а оказывается, что это с помощью этого хинта можно переопределять правила для новых браузеров.
Посмотреть как выводиться набор чекбоксов в IE6 остальные браузеры не нашел в сервисе можно здесь: https://www.browserstack.com/screenshots/9ed0ab72d90b74731e1e322918d35072313553d9
>> А можно еще подсказку как и это сделать?
>Скрыть чекбокс можно и не через display: none, а например: через visibility: hidden, через overflow:hidden c задвижением за край видимой области, через абс. поз. за край видимой области (left: -10000px) - но тут есть свои недостатки. Ты кстати должен знать эти варианты.
Через visibility: hidden и overflow: hidden почему-то не получилось.
https://jsfiddle.net/gpysbfar/
https://jsfiddle.net/gpysbfar/1/
Можно подсказку что я упустил?
>>815065
>Хорошо бы хотя бы от id в CSS избавиться
>Есть еще такая проблема: активная вкладка при наведении мыши становится серой - мне кажется это неправильно.
Исправил: https://jsfiddle.net/tb7k9dw9/4/
Посмотреть как выводиться в IE6: https://www.browserstack.com/screenshots/9f6a23a7d2634a0cc4b1be7a668f024aae54af68
>Кстати есть еще такая интересная статья по вкладкам: http://chikuyonok.ru/2009/04/dl-tabs/
Но там же делается решение через JS - если пользователь отключит его, то всё сломается.
В любом случае, я взял на вооружение этот метод, потому что наверняка в боевых задачах будет требоваться чтобы это через JS было сделанно, хоть мне и не нравиться такой подход.
>> #first-tab:checked + .tab-label[for="first-tab"] + #second-tab + .tab-label[for="second-tab"] + #third-tab + .tab-label[for="third-tab"] + #fourth-tab + .tab-label[for="fourth-tab"]
>В новых браузерах есть селектор ~. Нагугли и прочитай про все новые псевдоклассы и селекторы из CSS3. В старых браузерах он правда не работает, для них можно наверно просто вкладки вертикально вывести как блоки.
Я пробовал использовать такой селектор, но в нашем случае такой вариант не подходит по следующим причинам:
1. Если заключить инпутбокс в лейбел, то через него не получиться обращаться к следующим инпутбоксам https://jsfiddle.net/khxu17s0/
2. Если придерживаться метода где мы связываем инпутбокс и лейбел через for, то через этот селектор становиться трудно обратиться к контентному боксу, т.к. первый инпутбокс может оказаться родственным и для остальных контентных блоков https://jsfiddle.net/khxu17s0/1/
>>>сверстай блок так, чтобы блок с вкладками можно было вложить в страницу блока вкладок
>> Нужно чтобы можно было скопировать вкладки в контентную страницу? Может лучше чтобы в контентной странице был свой элемент со вкладками? Так для это следует задать ему собственные атрибуты и стили. Зачем делать по два раза одно и тоже? Я что-то недопонял?
>
>да, чтобы внутри мог быть свой блок с вкладками и он не конфликтовал с родительским.
Я не понял в чем подвох этой задачи - я просто добавил тот же самый табер только с новыми стилями.
><taber>
А можно создавать свои элементы?
Почему плохо использовать id?
Почему нужно поддерживать старые браузеры?
"советы": http://artgorbunov.ru/bb/soviet/
Техногрет: http://www.artlebedev.ru/tools/technogrette/
Яндекс-субботники: https://events.yandex.ru/events/yasubbotnik/
Задача про vertical align
В задаче на vertical align ( https://jsfiddle.net/211Le60v/6/ ) у крайнего левого желтого блока слева отступ от края больше 10 px Мне сразу бросилось в глаза. Надо исправить.
Задача про сайт ООО
> Все сломалось
Тебе надо научиться делать многоколоночные лейауты на флоатах. Если ты что-то забыл, перечитай учебник на softwaremaniac, а также можешь поискать примеры готовых лейаутов на флоатах.
А также есть статья http://chikuyonok.ru/2010/01/liquid-site-markup/
Суть там довольно проста. Левую колонку с меню мы загоняем влево с помощью float left. Правую колонку - вправо с помощью float:right. Но как задать ей ширину "вся страница минус 230px"? Никак, потому задаем ей 100%, а внутрь ставим блок с отступом 230px слева, а уже в него кладем текст. Но при таком подходе она пересекается по шиине с левой колонкой и проваливается вниз под нее. Для решения этой проблемы делаем ее внешнюю ширину меньше за счет отрицательного левого маргина. Например, -100%, в результате чего она начинает занимать 0px места и никому не мешает.
> Однако, если продолжать сжимать окно, контент рано или поздно съедит вниз. Почему так происходит?
Потому что флоаты проваливаются вниз, если на текущей высоте для них мало места и оно занято другими флоатами. Для решения этой проблемы часто используется втягивание границы внутрь с помощью отрицательного маргина. Изучи, как положительные и отрицательные маргины ведут себя на флоатах с разных сторон.
> .main-content {
> min-width: 230px;
> float: right;
Ты не разобрался в том, как работают флоаты, а ставишь свойства наугад. Так не получится. Надо именно разобраться.
В твоем случае ширина флоата не задана и потому определяется из содержимого и ширины родителя. Так как текста много, то флоат растягивается по ширине на 100%, и так как перед ним идет блок с меню, который занял часть ширины, он проваливается под него.
min-width тут вообще непонятно зачем так как 230px это ширина левой колонки, а не правой.
Попробуй добавить флоатам фоновые цвета чтобы видеть их границы и размеры.
>>.navigation-menu-li
>>.navigation-menu-ul > li
> Ведь можно использовать оба из этих варианта?
Второй лучше тем что не требует ставить класс на каждый li, а только один раз на ul.
Задача про инпут и кнопку
> Исправил: https://jsfiddle.net/5g31m30j/2/
В моем хромиуме кнопка на 2px ниже по высоте. Потому что у инпута есть паддинг 1px и border 2px, а у кнопки только border 2px. Тебе надо явно задавать паддинг и величину бордера либо же использовать другой box-sizing который их включает в себя.
Задача про Короля Лир
> Я не правильно выразился, я не могу понять как сделать чтобы примечание было всегда на уровне второго абзаца.
Там надо использовать флоат для выноса примечания влево. Тогда он автоматически будет на нужной высоте (подогнать точнее можно еще играя с line-height и margin-top).
Задача про верстку форума
> .post > p {
> margin-left: 72px;
Что если кроме абзацев <p> в тексте справа будут еще заголовки, таблицы, списки, цитаты, изображения? Надо чтобы все работало.
Задача про текст и кота
> А как сделать чтобы числа в квадратных скобках выравнивались слева от абзаца?
Ну тут нам нужно вырвать текст из общего потока. Значит, всего 2 варианта: либо абс. поз, либо флоат. У каждого есть преимущества и недостатки. Ну например с абс. поз., если 2 выноски будут на одной высоте то они наложатся друг на друга.
> А как сделать чтобы числа в квадратных скобках выравнивались слева от абзаца?
> потому что размер контентной части элемента может быть любым.
А это не важно, так как ширина поля слева фиксированна и мы можем привязаться к ней. Мы можем просто создать блок фиксированной шириной с поле и внутри него уже делать выравнивание. Или же в случае абс. поз. мы можем исплоьзовать привязку не к левому (left) а к правому краю (right: 100%) + margin-right который загонит примечание в нужное место.
Вот этот трюк - использование right:100% + margin-right - стоит освоить.
Я советую тебе сделать оба варианта, и через абс. поз. и через флоат, и сравнить.
Также у тебя я там опять вижу p { position: relative} - ты забываешь что текст может содержать не только абзацы. И зуже того, ты этот стиль вообще ко всем p на странице применяешь и можешь что-то сломать если к твоей верстке добавить другие элементы.
> Большая картинка должна ужиматься именно до ширины окна, а не до ширины блока в котором она содержиться?
До ширины блока в котором содержится. На поля она залезать не должна.
> Учитывая что по условию задачи размер тела максимально может быть 500
Это там только для примера поставлено. При проверке я убираю фиксированную ширину и проверяю на разной ширине окна.
> Даже если представить что за место тела может быть любой блочный элемент, это довольно странно задавать дочернему элементу ширину большую чем ширину родительскому.
Ты прав. Картинка ограничена шириной родителя а не всей страницы.
>>z-index: 1;
> Не уверен что это свойство нужно, т.к. элемент которому мы задаем это свойство всегда будет находиться ниже по коду другого абсолютно позиционированного элемента
ну если не нужно и все работает - можно не ставить.
Задача про радиокнопки
> Исправил: https://jsfiddle.net/fp8o0exq/5/
Теперь клавиатурная навигация работает, но есть проблема - непонятно есть ли фокус на кнопках или нет. Когда ты двигаешься по обычной не стилизованной форме с помощью tab (проверь), текущий элемент выделяется. Но твои кнопки никак не выделяются когда на них попадает фокус нажатием tab.
Задача про vertical align
В задаче на vertical align ( https://jsfiddle.net/211Le60v/6/ ) у крайнего левого желтого блока слева отступ от края больше 10 px Мне сразу бросилось в глаза. Надо исправить.
Задача про сайт ООО
> Все сломалось
Тебе надо научиться делать многоколоночные лейауты на флоатах. Если ты что-то забыл, перечитай учебник на softwaremaniac, а также можешь поискать примеры готовых лейаутов на флоатах.
А также есть статья http://chikuyonok.ru/2010/01/liquid-site-markup/
Суть там довольно проста. Левую колонку с меню мы загоняем влево с помощью float left. Правую колонку - вправо с помощью float:right. Но как задать ей ширину "вся страница минус 230px"? Никак, потому задаем ей 100%, а внутрь ставим блок с отступом 230px слева, а уже в него кладем текст. Но при таком подходе она пересекается по шиине с левой колонкой и проваливается вниз под нее. Для решения этой проблемы делаем ее внешнюю ширину меньше за счет отрицательного левого маргина. Например, -100%, в результате чего она начинает занимать 0px места и никому не мешает.
> Однако, если продолжать сжимать окно, контент рано или поздно съедит вниз. Почему так происходит?
Потому что флоаты проваливаются вниз, если на текущей высоте для них мало места и оно занято другими флоатами. Для решения этой проблемы часто используется втягивание границы внутрь с помощью отрицательного маргина. Изучи, как положительные и отрицательные маргины ведут себя на флоатах с разных сторон.
> .main-content {
> min-width: 230px;
> float: right;
Ты не разобрался в том, как работают флоаты, а ставишь свойства наугад. Так не получится. Надо именно разобраться.
В твоем случае ширина флоата не задана и потому определяется из содержимого и ширины родителя. Так как текста много, то флоат растягивается по ширине на 100%, и так как перед ним идет блок с меню, который занял часть ширины, он проваливается под него.
min-width тут вообще непонятно зачем так как 230px это ширина левой колонки, а не правой.
Попробуй добавить флоатам фоновые цвета чтобы видеть их границы и размеры.
>>.navigation-menu-li
>>.navigation-menu-ul > li
> Ведь можно использовать оба из этих варианта?
Второй лучше тем что не требует ставить класс на каждый li, а только один раз на ul.
Задача про инпут и кнопку
> Исправил: https://jsfiddle.net/5g31m30j/2/
В моем хромиуме кнопка на 2px ниже по высоте. Потому что у инпута есть паддинг 1px и border 2px, а у кнопки только border 2px. Тебе надо явно задавать паддинг и величину бордера либо же использовать другой box-sizing который их включает в себя.
Задача про Короля Лир
> Я не правильно выразился, я не могу понять как сделать чтобы примечание было всегда на уровне второго абзаца.
Там надо использовать флоат для выноса примечания влево. Тогда он автоматически будет на нужной высоте (подогнать точнее можно еще играя с line-height и margin-top).
Задача про верстку форума
> .post > p {
> margin-left: 72px;
Что если кроме абзацев <p> в тексте справа будут еще заголовки, таблицы, списки, цитаты, изображения? Надо чтобы все работало.
Задача про текст и кота
> А как сделать чтобы числа в квадратных скобках выравнивались слева от абзаца?
Ну тут нам нужно вырвать текст из общего потока. Значит, всего 2 варианта: либо абс. поз, либо флоат. У каждого есть преимущества и недостатки. Ну например с абс. поз., если 2 выноски будут на одной высоте то они наложатся друг на друга.
> А как сделать чтобы числа в квадратных скобках выравнивались слева от абзаца?
> потому что размер контентной части элемента может быть любым.
А это не важно, так как ширина поля слева фиксированна и мы можем привязаться к ней. Мы можем просто создать блок фиксированной шириной с поле и внутри него уже делать выравнивание. Или же в случае абс. поз. мы можем исплоьзовать привязку не к левому (left) а к правому краю (right: 100%) + margin-right который загонит примечание в нужное место.
Вот этот трюк - использование right:100% + margin-right - стоит освоить.
Я советую тебе сделать оба варианта, и через абс. поз. и через флоат, и сравнить.
Также у тебя я там опять вижу p { position: relative} - ты забываешь что текст может содержать не только абзацы. И зуже того, ты этот стиль вообще ко всем p на странице применяешь и можешь что-то сломать если к твоей верстке добавить другие элементы.
> Большая картинка должна ужиматься именно до ширины окна, а не до ширины блока в котором она содержиться?
До ширины блока в котором содержится. На поля она залезать не должна.
> Учитывая что по условию задачи размер тела максимально может быть 500
Это там только для примера поставлено. При проверке я убираю фиксированную ширину и проверяю на разной ширине окна.
> Даже если представить что за место тела может быть любой блочный элемент, это довольно странно задавать дочернему элементу ширину большую чем ширину родительскому.
Ты прав. Картинка ограничена шириной родителя а не всей страницы.
>>z-index: 1;
> Не уверен что это свойство нужно, т.к. элемент которому мы задаем это свойство всегда будет находиться ниже по коду другого абсолютно позиционированного элемента
ну если не нужно и все работает - можно не ставить.
Задача про радиокнопки
> Исправил: https://jsfiddle.net/fp8o0exq/5/
Теперь клавиатурная навигация работает, но есть проблема - непонятно есть ли фокус на кнопках или нет. Когда ты двигаешься по обычной не стилизованной форме с помощью tab (проверь), текущий элемент выделяется. Но твои кнопки никак не выделяются когда на них попадает фокус нажатием tab.
> у меня слишком мало опыта чтобы определять такие вещи на взгляд.
Если не пробовать, опыт не появится.
> В боевых задачах мне тоже может прийтись определять стили на глаз или всё можно будет посмотреть в .psd шаблоне?
можно, но в фотошопе свои параметры теней и все равно немного придется подбирать на глаз. Потому стоит практиковаться.
>>Также, как насчет клавиатурной навигации?
> Теперь она работает.
А фокус не показывается.
> который я переопределил с помощью .buttons[class="buttons"]. Казалось бы, селектор не имеет смысла, а оказывается, что это с помощью этого хинта можно переопределять правила для новых браузеров.
Можно просто .buttons[class]
> остальные браузеры не нашел в сервисе
Странно. У меня на этой странице https://www.browserstack.com/screenshots выводится огромный список с разными названиями браузеров. При нажатии на название или номер версии он выделяется.
Правда эта зараза теперь регистрацию требует.
Сгенерировал для примера: https://www.browserstack.com/screenshots/a0522e08ed4dfb1d70c4e2664da8b367522debf9
> Через visibility: hidden и overflow: hidden почему-то не получилось.
Странно, по ссылке с visibility радиокнопки не видны.
> left: -10000;
10000 чего? Единица измерения не указана. Проверил бы код css валидатором - сразу бы увидел ошибку.
Задача про вкладки
> >Кстати есть еще такая интересная статья по вкладкам: http://chikuyonok.ru/2009/04/dl-tabs/
> Но там же делается решение через JS
Там JS только для переключения вкладок, так как в то время css3 плохо поддерживался. Можно наверно и без него. Обратить внимание надо не на то как вкладки показываются, а на оригинальный способ чередования вкладок и заголовков.
> 2. Если придерживаться метода где мы связываем инпутбокс и лейбел через for, то через этот селектор становиться трудно обратиться к контентному боксу, т.к. первый инпутбокс может оказаться родственным и для остальных контентных блоков https://jsfiddle.net/khxu17s0/1/
Ну так ты можешь связать заголовок и тело вкладки классом или data-атрибутом и учитывать его в CSS правиле. То есть:
<input data-tab="tab1">....<div data-tab="tab1">...
>Я не понял в чем подвох этой задачи - я просто добавил тот же самый табер только с новыми стилями.
Если у тебя неаккуратно написаны стили то может быть какой-то стиль с внешего блока повлияет на внутренний. Потому важно писать css правила так, чтобы они влияли только на нужные элементы.
> А можно создавать свои элементы?
Стандарт ничего не говорит, по факту создавать можно, но это плохая идея. Так как у обычных элементов есть определения, что они значат, есть документация, а твои элементы непонятно что значат, в каких ситуациях их можно использовать итд. Плохая идея.
> Почему плохо использовать id?
Потому что на странице не может быть 2 элемента с одинаковым id. Допустим ты в форме логина сделал у кнопки id и все - на страницу нельзя поместить 2 таких формы логина.
> Почему нужно поддерживать старые браузеры?
- потому что кто-то ими пользуется
- потому что есть устройства где нельзя обновить браузер (смарт ТВ, старые смартфоны) или где у пользователя нет прав (рабочий компьютер, компьютер в отеле и тд)
- потому что это учит тебя делать более "железобетонную" верстку
- потому что веб-стандарты задумывались так, чтоьбы страницы могли отображаться на максимальном числе устройств
На практике конечно на это часто забивают так как это стоит денег (рабочее время верстальщика) и так как многие верстальщики очень малограмотные и просто не умеют верстать хорошо (в верстальщики часто идут те кто не осилил программирование). Но твое время пока ничего не стоит, так что не беспокойся по этому поводу.
Если я на что-то не ответил - напомни. И желательно пиши номера или названия задач в ответе, а то трудно ориентироваться.
> у меня слишком мало опыта чтобы определять такие вещи на взгляд.
Если не пробовать, опыт не появится.
> В боевых задачах мне тоже может прийтись определять стили на глаз или всё можно будет посмотреть в .psd шаблоне?
можно, но в фотошопе свои параметры теней и все равно немного придется подбирать на глаз. Потому стоит практиковаться.
>>Также, как насчет клавиатурной навигации?
> Теперь она работает.
А фокус не показывается.
> который я переопределил с помощью .buttons[class="buttons"]. Казалось бы, селектор не имеет смысла, а оказывается, что это с помощью этого хинта можно переопределять правила для новых браузеров.
Можно просто .buttons[class]
> остальные браузеры не нашел в сервисе
Странно. У меня на этой странице https://www.browserstack.com/screenshots выводится огромный список с разными названиями браузеров. При нажатии на название или номер версии он выделяется.
Правда эта зараза теперь регистрацию требует.
Сгенерировал для примера: https://www.browserstack.com/screenshots/a0522e08ed4dfb1d70c4e2664da8b367522debf9
> Через visibility: hidden и overflow: hidden почему-то не получилось.
Странно, по ссылке с visibility радиокнопки не видны.
> left: -10000;
10000 чего? Единица измерения не указана. Проверил бы код css валидатором - сразу бы увидел ошибку.
Задача про вкладки
> >Кстати есть еще такая интересная статья по вкладкам: http://chikuyonok.ru/2009/04/dl-tabs/
> Но там же делается решение через JS
Там JS только для переключения вкладок, так как в то время css3 плохо поддерживался. Можно наверно и без него. Обратить внимание надо не на то как вкладки показываются, а на оригинальный способ чередования вкладок и заголовков.
> 2. Если придерживаться метода где мы связываем инпутбокс и лейбел через for, то через этот селектор становиться трудно обратиться к контентному боксу, т.к. первый инпутбокс может оказаться родственным и для остальных контентных блоков https://jsfiddle.net/khxu17s0/1/
Ну так ты можешь связать заголовок и тело вкладки классом или data-атрибутом и учитывать его в CSS правиле. То есть:
<input data-tab="tab1">....<div data-tab="tab1">...
>Я не понял в чем подвох этой задачи - я просто добавил тот же самый табер только с новыми стилями.
Если у тебя неаккуратно написаны стили то может быть какой-то стиль с внешего блока повлияет на внутренний. Потому важно писать css правила так, чтобы они влияли только на нужные элементы.
> А можно создавать свои элементы?
Стандарт ничего не говорит, по факту создавать можно, но это плохая идея. Так как у обычных элементов есть определения, что они значат, есть документация, а твои элементы непонятно что значат, в каких ситуациях их можно использовать итд. Плохая идея.
> Почему плохо использовать id?
Потому что на странице не может быть 2 элемента с одинаковым id. Допустим ты в форме логина сделал у кнопки id и все - на страницу нельзя поместить 2 таких формы логина.
> Почему нужно поддерживать старые браузеры?
- потому что кто-то ими пользуется
- потому что есть устройства где нельзя обновить браузер (смарт ТВ, старые смартфоны) или где у пользователя нет прав (рабочий компьютер, компьютер в отеле и тд)
- потому что это учит тебя делать более "железобетонную" верстку
- потому что веб-стандарты задумывались так, чтоьбы страницы могли отображаться на максимальном числе устройств
На практике конечно на это часто забивают так как это стоит денег (рабочее время верстальщика) и так как многие верстальщики очень малограмотные и просто не умеют верстать хорошо (в верстальщики часто идут те кто не осилил программирование). Но твое время пока ничего не стоит, так что не беспокойся по этому поводу.
Если я на что-то не ответил - напомни. И желательно пиши номера или названия задач в ответе, а то трудно ориентироваться.
Вкусно, но можешь объяснить что ты именно сделал или сказать, где про это можно прочитать?
Алсо, что за тип данных у нас получился в $money и $rate?
Это базовая работа с массивами в PHP. Везде можно почитать. В учебнике ОПа например хорошо разжевано. Просто в ячейке 'rates' лежит еще один массив.
$rate будет float. $money и так очевидно.
доброго всем дня/утра/етс
помогите, всю голову сломал уже, объясните пожалуйста почему этот код выводит именно 123.. а не наоборот ..321? что происходит в этой вот строке return prnt($n-1).$n ?
помогите! Голову сломал уже. Объясните пожалуйста тугодуму почему код выводит числа именно в правильной последовательности (123..), а не наоборот (..321)
чувак, я просто, у меня просто, прям слов нет, добра тебе
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-4
>Задача про vertical align
>В задаче на vertical align ( https://jsfiddle.net/211Le60v/6/ ) у крайнего левого желтого блока слева отступ от края больше 10 px Мне сразу бросилось в глаза. Надо исправить.
Исправил: https://jsfiddle.net/211Le60v/7/
>>828506
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-6
>Задача про сайт ООО
>min-width тут вообще непонятно зачем так как 230px это ширина левой колонки, а не правой.
В шаблоне задания под контентной частью написано 100% - 230px. Если я неправильно понял что 230 пикселей, это максимальная ширина, а не минимальная, то всё легко решается: https://jsfiddle.net/0u3x5rsw/ . Если же это минимальная ширина, то я не знаю как решить эту задачу, кроме как заключить колонки в враппер и задать ему минимальную ширину равную размеру этих колонок https://jsfiddle.net/0u3x5rsw/1/ . Вот у меня есть вопросы которые сейчас ставят меня в ступор:
>> Однако, если продолжать сжимать окно, контент рано или поздно съедит вниз. Почему так происходит?
>Потому что флоаты проваливаются вниз, если на текущей высоте для них мало места и оно занято другими флоатами.
>В твоем случае ширина флоата не задана и потому определяется из содержимого и ширины родителя. Так как текста много, то флоат растягивается по ширине на 100%, и так как перед ним идет блок с меню, который занял часть ширины, он проваливается под него.
https://jsfiddle.net/g7qpu8wc/
Если сжимать тело по ширине до 171px то, даже не смотря на то что контентному блоку нужно как минимум 230px, контентный блок не будет провалиться. Но если ширина тела станет 170px или меньше, то элемент сразу проваливается. Это совершенно не с чем не связанное число, даже если не брать это во внимание на практике, мне всё равно не понятно подобное поведение.
https://jsfiddle.net/d5w519yd/
https://jsfiddle.net/d5w519yd/1/
Что отличает отступы в -29px и -30px?
https://jsfiddle.net/e026k5w4/
https://jsfiddle.net/cyeobyc3/
http://htmlbook.ru/css/calc
Почему в первом примере, при очень сильном сжатии, флоат проваливается вниз? Так быть не должно т.к. мы используем функцию calc, которая всегда должна высчитывать всю страницу минус 230px. Что отличает эту функцию в первом примере от второго?
>А также есть статья http://chikuyonok.ru/2010/01/liquid-site-markup/
>Изучи, как положительные и отрицательные маргины ведут себя на флоатах с разных сторон.
Loading...
>>828506
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-7
>Задача про инпут и кнопку
>В моем хромиуме кнопка на 2px ниже по высоте. Потому что у инпута есть паддинг 1px и border 2px, а у кнопки только border 2px. Тебе надо явно задавать паддинг и величину бордера либо же использовать другой box-sizing который их включает в себя.
Исправил: https://jsfiddle.net/5g31m30j/3/
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-8
Задача про Короля Лир
А такое решение считается правильным https://jsfiddle.net/zxm89tLg/1/ ? Если нет, то я сделал как вы советовали: https://jsfiddle.net/tsuh4gjw/5/
>>828506
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-9
>Задача про верстку форума
>> .post > p {
>> margin-left: 72px;
>Что если кроме абзацев <p> в тексте справа будут еще заголовки, таблицы, списки, цитаты, изображения? Надо чтобы все работало.
Исправил: https://jsfiddle.net/kxdx27f1/4/
Критично то что теперь появился небольшой отступ перед p?
А можно было использовать универсальный селектор https://jsfiddle.net/gd3yn87t/ ?
>>828506
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-10
>Задача про текст и кота
Coming soon...
>>828506
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-11
>Задача про радиокнопки
>> Исправил: https://jsfiddle.net/fp8o0exq/5/
>Теперь клавиатурная навигация работает, но есть проблема - непонятно есть ли фокус на кнопках или нет. Когда ты двигаешься по обычной не стилизованной форме с помощью tab (проверь), текущий элемент выделяется. Но твои кнопки никак не выделяются когда на них попадает фокус нажатием tab.
Странно, у меня работает фокус. Прикладываю webm для наглядности...
Скажите свою версию браузера, чтобы я мог это починить?
>Странно. У меня на этой странице https://www.browserstack.com/screenshots выводится огромный список с разными названиями браузеров. При нажатии на название или номер версии он выделяется.
Некоторые селекторы и псевдоклассы который мы используем появляются как минимум с 6 версии IE и 3.5 версии Оперы, остальные же браузеры поддерживают их с первых версий. В том списке браузеры уже гораздо старше.
http://htmlbook.ru/css/active
http://htmlbook.ru/css/hover
http://htmlbook.ru/css/focus
http://htmlbook.ru/css/selector/child
>> Через visibility: hidden и overflow: hidden почему-то не получилось.
>Странно, по ссылке с visibility радиокнопки не видны.
Да, но их нельзя использовать с помощью клавиатурной навигации.
>> left: -10000;
>10000 чего? Единица измерения не указана. Проверил бы код css валидатором - сразу бы увидел ошибку.
Даже после исправления инпуты не исчезли: https://jsfiddle.net/gpysbfar/2/
>>828510
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-12
>Задача про вкладки
>> >Кстати есть еще такая интересная статья по вкладкам: http://chikuyonok.ru/2009/04/dl-tabs/
>> Но там же делается решение через JS
>Там JS только для переключения вкладок, так как в то время css3 плохо поддерживался. Можно наверно и без него. Обратить внимание надо не на то как вкладки показываются, а на оригинальный способ чередования вкладок и заголовков.
Да, причем, насколько я понял, в этом способе необязательно использовать именно <dl>, <dt> и <dd>, а можно заменить их например на <div class="taber">, <h2> и <article>. По-моему так наглядней выглядит.
>> 2. Если придерживаться метода где мы связываем инпутбокс и лейбел через for, то через этот селектор становиться трудно обратиться к контентному боксу, т.к. первый инпутбокс может оказаться родственным и для остальных контентных блоков https://jsfiddle.net/khxu17s0/1/
>Ну так ты можешь связать заголовок и тело вкладки классом или data-атрибутом и учитывать его в CSS правиле. То есть:
>
><input data-tab="tab1">....<div data-tab="tab1">...
Мы же не полностью одобряем уникальные идентификаторы.
В любом случае я сделал и это: https://jsfiddle.net/tb7k9dw9/5/
>> Почему нужно поддерживать старые браузеры?
>- потому что кто-то ими пользуется
>- потому что есть устройства где нельзя обновить браузер (смарт ТВ, старые смартфоны) или где у пользователя нет прав (рабочий компьютер, компьютер в отеле и тд)
Но почему мы должны поощрять использование устаревших технологий? Нужно наоборот мотивировать пользователей или поставщиков оборудования использовать современные технологии.
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-4
>Задача про vertical align
>В задаче на vertical align ( https://jsfiddle.net/211Le60v/6/ ) у крайнего левого желтого блока слева отступ от края больше 10 px Мне сразу бросилось в глаза. Надо исправить.
Исправил: https://jsfiddle.net/211Le60v/7/
>>828506
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-6
>Задача про сайт ООО
>min-width тут вообще непонятно зачем так как 230px это ширина левой колонки, а не правой.
В шаблоне задания под контентной частью написано 100% - 230px. Если я неправильно понял что 230 пикселей, это максимальная ширина, а не минимальная, то всё легко решается: https://jsfiddle.net/0u3x5rsw/ . Если же это минимальная ширина, то я не знаю как решить эту задачу, кроме как заключить колонки в враппер и задать ему минимальную ширину равную размеру этих колонок https://jsfiddle.net/0u3x5rsw/1/ . Вот у меня есть вопросы которые сейчас ставят меня в ступор:
>> Однако, если продолжать сжимать окно, контент рано или поздно съедит вниз. Почему так происходит?
>Потому что флоаты проваливаются вниз, если на текущей высоте для них мало места и оно занято другими флоатами.
>В твоем случае ширина флоата не задана и потому определяется из содержимого и ширины родителя. Так как текста много, то флоат растягивается по ширине на 100%, и так как перед ним идет блок с меню, который занял часть ширины, он проваливается под него.
https://jsfiddle.net/g7qpu8wc/
Если сжимать тело по ширине до 171px то, даже не смотря на то что контентному блоку нужно как минимум 230px, контентный блок не будет провалиться. Но если ширина тела станет 170px или меньше, то элемент сразу проваливается. Это совершенно не с чем не связанное число, даже если не брать это во внимание на практике, мне всё равно не понятно подобное поведение.
https://jsfiddle.net/d5w519yd/
https://jsfiddle.net/d5w519yd/1/
Что отличает отступы в -29px и -30px?
https://jsfiddle.net/e026k5w4/
https://jsfiddle.net/cyeobyc3/
http://htmlbook.ru/css/calc
Почему в первом примере, при очень сильном сжатии, флоат проваливается вниз? Так быть не должно т.к. мы используем функцию calc, которая всегда должна высчитывать всю страницу минус 230px. Что отличает эту функцию в первом примере от второго?
>А также есть статья http://chikuyonok.ru/2010/01/liquid-site-markup/
>Изучи, как положительные и отрицательные маргины ведут себя на флоатах с разных сторон.
Loading...
>>828506
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-7
>Задача про инпут и кнопку
>В моем хромиуме кнопка на 2px ниже по высоте. Потому что у инпута есть паддинг 1px и border 2px, а у кнопки только border 2px. Тебе надо явно задавать паддинг и величину бордера либо же использовать другой box-sizing который их включает в себя.
Исправил: https://jsfiddle.net/5g31m30j/3/
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-8
Задача про Короля Лир
А такое решение считается правильным https://jsfiddle.net/zxm89tLg/1/ ? Если нет, то я сделал как вы советовали: https://jsfiddle.net/tsuh4gjw/5/
>>828506
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-9
>Задача про верстку форума
>> .post > p {
>> margin-left: 72px;
>Что если кроме абзацев <p> в тексте справа будут еще заголовки, таблицы, списки, цитаты, изображения? Надо чтобы все работало.
Исправил: https://jsfiddle.net/kxdx27f1/4/
Критично то что теперь появился небольшой отступ перед p?
А можно было использовать универсальный селектор https://jsfiddle.net/gd3yn87t/ ?
>>828506
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-10
>Задача про текст и кота
Coming soon...
>>828506
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-11
>Задача про радиокнопки
>> Исправил: https://jsfiddle.net/fp8o0exq/5/
>Теперь клавиатурная навигация работает, но есть проблема - непонятно есть ли фокус на кнопках или нет. Когда ты двигаешься по обычной не стилизованной форме с помощью tab (проверь), текущий элемент выделяется. Но твои кнопки никак не выделяются когда на них попадает фокус нажатием tab.
Странно, у меня работает фокус. Прикладываю webm для наглядности...
Скажите свою версию браузера, чтобы я мог это починить?
>Странно. У меня на этой странице https://www.browserstack.com/screenshots выводится огромный список с разными названиями браузеров. При нажатии на название или номер версии он выделяется.
Некоторые селекторы и псевдоклассы который мы используем появляются как минимум с 6 версии IE и 3.5 версии Оперы, остальные же браузеры поддерживают их с первых версий. В том списке браузеры уже гораздо старше.
http://htmlbook.ru/css/active
http://htmlbook.ru/css/hover
http://htmlbook.ru/css/focus
http://htmlbook.ru/css/selector/child
>> Через visibility: hidden и overflow: hidden почему-то не получилось.
>Странно, по ссылке с visibility радиокнопки не видны.
Да, но их нельзя использовать с помощью клавиатурной навигации.
>> left: -10000;
>10000 чего? Единица измерения не указана. Проверил бы код css валидатором - сразу бы увидел ошибку.
Даже после исправления инпуты не исчезли: https://jsfiddle.net/gpysbfar/2/
>>828510
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-12
>Задача про вкладки
>> >Кстати есть еще такая интересная статья по вкладкам: http://chikuyonok.ru/2009/04/dl-tabs/
>> Но там же делается решение через JS
>Там JS только для переключения вкладок, так как в то время css3 плохо поддерживался. Можно наверно и без него. Обратить внимание надо не на то как вкладки показываются, а на оригинальный способ чередования вкладок и заголовков.
Да, причем, насколько я понял, в этом способе необязательно использовать именно <dl>, <dt> и <dd>, а можно заменить их например на <div class="taber">, <h2> и <article>. По-моему так наглядней выглядит.
>> 2. Если придерживаться метода где мы связываем инпутбокс и лейбел через for, то через этот селектор становиться трудно обратиться к контентному боксу, т.к. первый инпутбокс может оказаться родственным и для остальных контентных блоков https://jsfiddle.net/khxu17s0/1/
>Ну так ты можешь связать заголовок и тело вкладки классом или data-атрибутом и учитывать его в CSS правиле. То есть:
>
><input data-tab="tab1">....<div data-tab="tab1">...
Мы же не полностью одобряем уникальные идентификаторы.
В любом случае я сделал и это: https://jsfiddle.net/tb7k9dw9/5/
>> Почему нужно поддерживать старые браузеры?
>- потому что кто-то ими пользуется
>- потому что есть устройства где нельзя обновить браузер (смарт ТВ, старые смартфоны) или где у пользователя нет прав (рабочий компьютер, компьютер в отеле и тд)
Но почему мы должны поощрять использование устаревших технологий? Нужно наоборот мотивировать пользователей или поставщиков оборудования использовать современные технологии.
https://github.com/anotherCodeMunkey/studentsList
в settings.php параметры для подключения к бд
>>826978
Для начала, старые замечания по задаче из поста >>812990
-----------
ПО поводу этого скрипта: https://github.com/TheSidSpears/Students/blob/master/cmd.php
Всю работу с таблицей студентов (выборку студентов) удобнее бы собрать в одном классе, и использовать твой класс работы с БД, а не писать функцию.
> $validator=new StudentValidator($student,$container,$student->getId());
Тут мне не нравится то, что студент передается в конструтор, отдельно зачем-то его id. Контейнер передавать в валидатор неправильно, это же нарушение принципа DI. Студента логичнее передавать не в конструктор, а в функицю валидации. задача конструктора - инициализировать объект. Лучше сделать многоразовый валидатор.
>> перечитай урок про DI. Это service locator и это плохая вещь.
> Убрал где можно. Но как я понимаю в контроллеры всё равно контейнер придётся передавать целиком, так?
да, есть те, кто считает что контроллер тоже надо делать как сервис, но это получается сложнее, и не очень понятно, а нужно ли оно. Проще в контроллер передавать контейнер. Контроллер это все равно не повторно используемый код и его вызвать откуда-то нельзя.
> Я подразумеваю, что всё что нельзя редактировать пользователю, то protected. А get_object_vars возвращает только public свойства. Разве не элегантно?
Нет, это плохо так как не очевидно. Легко добавить публичное поле и внезапно оно становится доступно для редактирвоания пользователем. Это неправильно, надо чтобы все было безопасно по умолчанию, а не превращать код в минное поле.
> потому что этот класс используется только так и никак иначе. Создать, проверить на ошибки, вернуть ошибки. Верно так делать? Это сокращает работу с классом до одной строки: $validErrors=new StudentValidator($student,$this->c['table'],$id);
Нет, лучше чтобы валидация делалась в методе validate. Логично ведь что валидация это функция, которая принимает на вход модель и возвращает список ошибок. Это позволяет например проверить нескольких студентов одним валидатором. мне кажется так будет удобнее. Хотя конечно твой подход тоже имеет право на жизнь, но мне кажется что лучше для валидации иметь отдельный метод, а не нагружать этим конструктор.
----------
Также, я заметил, что у тебя мало комментариев. Хорошо бы завести привычку писать комментарий хотя бы перед классами, объясняя, зачем он нужен.
Насчет этого: https://github.com/TheSidSpears/Students/blob/master/composer.json#L10 - на мой взгляд, тут надо было перейти на неймспейсы из PSR-4, а не добавлять кучу папок в автозагрузку. Соответственно, при использовании PSR-4 папки должны назвыаться в соответсиве с неймспейсами, вплоть до регистра букв.
> https://github.com/TheSidSpears/Students/blob/master/students.sql#L31
Тут для hash праивльнее использовать varchar с указанием длины. К тому же по полю типа text не получится сделать индекс.
https://github.com/TheSidSpears/Students/blob/master/app/Router.php
Роутер сделан на мой взгляд неправильно. УРЛ который он анализирует, должен быть входным аргументом, а ты самостоятельно его берешь из SERVER. У хорошей функции есть входные аргументы и результат, а твоя функция сама лезет в какой-то суперглобальный массив и что-то оттуда берет, хотя необходимости в этом никакой нет.
Класс отформатирован неряшливо, не в соответствие с PSR (например скобка после имени класса должна стоять на новой строке).
В роутере содержится копипаста, например:
> $parsedUrl=parse_url($_SERVER['REQUEST_URI']);
> $explodePath=explode('/', $parsedUrl['path']);
> $module=$explodePath[count($explodePath)-1];
Далее, роутер берет на себя функции фронт-контроллера, выводя шаблон:
> include(Util::getAbsolutePath('/public/error_pages/403.php'));
> exit;
Тут сплошное нарушение принципов ООП:
- ответственность не разделена между роутером и фронт-контроллером и роутер занимается не своим делом (обработкой ошибок). По сути роутер у тебя содердит код которому место в фронт-контроллере.
- УРЛ не передается как входной параметр
- задача роутера - получить и разобрать УРЛ - но я у тебя в классе не вижу функции которая бы это делала
Плюс, из УРЛ берется только последний сегмент. Получается в адрес можно приписать что угодно и получить валидный УРЛ. Это, конечно, неправильно. Если тебе надо чтобы сайт работал в подпапке, надо либо автоматически выделять путь к ней либо прописать его в конфиг.
https://github.com/TheSidSpears/Students/blob/master/app/controllers/ViewController.php#L31
Не очень понятно, зачем явно указывать имена переменных. Разве не проще извлечь все ключи из массива? Для этого кстати есть функция extract.
https://github.com/TheSidSpears/Students/blob/master/app/controllers/ViewController.php#L26
Этот код, который отвечает за добавление путей к стилям, на мой взгляд, не должен быть в функции. Функция ведь называется showView а не showViewAndAddCssPaths. Алсо, добавлять префикс проще вызывая функцию-хелпер в шаблоне.
https://github.com/TheSidSpears/Students/blob/master/app/controllers/ViewController.php#L15
Здесь странный код. А что если условие не выоплняется? Выводится белая пустя страница? И вообще, так обычно не делают. Лучше из фронт контроллера сразу вызывать нужный метод, хотя бы потому что так проще получается.
https://github.com/TheSidSpears/Students/blob/master/app/controllers/MainController.php#L8
Этот конструктор ничего не меняет и потому его можно тут не указывать.
> public function parseRequest(){
> parent::parseRequest();
> }
То же самое. Перечитай про наследование классов. Эту функцию нет смысла переопределять.
> $this->mainCode();
Название функции должно начинаться с глагола. И обозначать что она делает.
> $this->viewName='pages/main';
> //Из локальных в глобальные, чтобы передать в packViewVars()
> foreach ($this->keysOfViewVars as $key) {
> $this->$key=$$key;
> }
Я думаю, лучше вместо неявных заданий имен шаблона явно вызывать метод showView(), передавая ему имя и переменные. У тебя все как-то запутанно: какие-то поля создаются, а можно просто вызвать функцию и передать ей нужные аругменты. Зачем усложнять - непонятно.
> $register_ok
В PSR переменные пишут кемелкейсом. Более того, у тебя есть и переменные с кемелкейсом, и с подчеркиванием. Смотрится ужасно.
Насчет переменных, которые нужны в каждом шаблоне (например, которые выводятся в шапке). Можно сделать в базовом контроллере метод для их получения.
>>826978
Для начала, старые замечания по задаче из поста >>812990
-----------
ПО поводу этого скрипта: https://github.com/TheSidSpears/Students/blob/master/cmd.php
Всю работу с таблицей студентов (выборку студентов) удобнее бы собрать в одном классе, и использовать твой класс работы с БД, а не писать функцию.
> $validator=new StudentValidator($student,$container,$student->getId());
Тут мне не нравится то, что студент передается в конструтор, отдельно зачем-то его id. Контейнер передавать в валидатор неправильно, это же нарушение принципа DI. Студента логичнее передавать не в конструктор, а в функицю валидации. задача конструктора - инициализировать объект. Лучше сделать многоразовый валидатор.
>> перечитай урок про DI. Это service locator и это плохая вещь.
> Убрал где можно. Но как я понимаю в контроллеры всё равно контейнер придётся передавать целиком, так?
да, есть те, кто считает что контроллер тоже надо делать как сервис, но это получается сложнее, и не очень понятно, а нужно ли оно. Проще в контроллер передавать контейнер. Контроллер это все равно не повторно используемый код и его вызвать откуда-то нельзя.
> Я подразумеваю, что всё что нельзя редактировать пользователю, то protected. А get_object_vars возвращает только public свойства. Разве не элегантно?
Нет, это плохо так как не очевидно. Легко добавить публичное поле и внезапно оно становится доступно для редактирвоания пользователем. Это неправильно, надо чтобы все было безопасно по умолчанию, а не превращать код в минное поле.
> потому что этот класс используется только так и никак иначе. Создать, проверить на ошибки, вернуть ошибки. Верно так делать? Это сокращает работу с классом до одной строки: $validErrors=new StudentValidator($student,$this->c['table'],$id);
Нет, лучше чтобы валидация делалась в методе validate. Логично ведь что валидация это функция, которая принимает на вход модель и возвращает список ошибок. Это позволяет например проверить нескольких студентов одним валидатором. мне кажется так будет удобнее. Хотя конечно твой подход тоже имеет право на жизнь, но мне кажется что лучше для валидации иметь отдельный метод, а не нагружать этим конструктор.
----------
Также, я заметил, что у тебя мало комментариев. Хорошо бы завести привычку писать комментарий хотя бы перед классами, объясняя, зачем он нужен.
Насчет этого: https://github.com/TheSidSpears/Students/blob/master/composer.json#L10 - на мой взгляд, тут надо было перейти на неймспейсы из PSR-4, а не добавлять кучу папок в автозагрузку. Соответственно, при использовании PSR-4 папки должны назвыаться в соответсиве с неймспейсами, вплоть до регистра букв.
> https://github.com/TheSidSpears/Students/blob/master/students.sql#L31
Тут для hash праивльнее использовать varchar с указанием длины. К тому же по полю типа text не получится сделать индекс.
https://github.com/TheSidSpears/Students/blob/master/app/Router.php
Роутер сделан на мой взгляд неправильно. УРЛ который он анализирует, должен быть входным аргументом, а ты самостоятельно его берешь из SERVER. У хорошей функции есть входные аргументы и результат, а твоя функция сама лезет в какой-то суперглобальный массив и что-то оттуда берет, хотя необходимости в этом никакой нет.
Класс отформатирован неряшливо, не в соответствие с PSR (например скобка после имени класса должна стоять на новой строке).
В роутере содержится копипаста, например:
> $parsedUrl=parse_url($_SERVER['REQUEST_URI']);
> $explodePath=explode('/', $parsedUrl['path']);
> $module=$explodePath[count($explodePath)-1];
Далее, роутер берет на себя функции фронт-контроллера, выводя шаблон:
> include(Util::getAbsolutePath('/public/error_pages/403.php'));
> exit;
Тут сплошное нарушение принципов ООП:
- ответственность не разделена между роутером и фронт-контроллером и роутер занимается не своим делом (обработкой ошибок). По сути роутер у тебя содердит код которому место в фронт-контроллере.
- УРЛ не передается как входной параметр
- задача роутера - получить и разобрать УРЛ - но я у тебя в классе не вижу функции которая бы это делала
Плюс, из УРЛ берется только последний сегмент. Получается в адрес можно приписать что угодно и получить валидный УРЛ. Это, конечно, неправильно. Если тебе надо чтобы сайт работал в подпапке, надо либо автоматически выделять путь к ней либо прописать его в конфиг.
https://github.com/TheSidSpears/Students/blob/master/app/controllers/ViewController.php#L31
Не очень понятно, зачем явно указывать имена переменных. Разве не проще извлечь все ключи из массива? Для этого кстати есть функция extract.
https://github.com/TheSidSpears/Students/blob/master/app/controllers/ViewController.php#L26
Этот код, который отвечает за добавление путей к стилям, на мой взгляд, не должен быть в функции. Функция ведь называется showView а не showViewAndAddCssPaths. Алсо, добавлять префикс проще вызывая функцию-хелпер в шаблоне.
https://github.com/TheSidSpears/Students/blob/master/app/controllers/ViewController.php#L15
Здесь странный код. А что если условие не выоплняется? Выводится белая пустя страница? И вообще, так обычно не делают. Лучше из фронт контроллера сразу вызывать нужный метод, хотя бы потому что так проще получается.
https://github.com/TheSidSpears/Students/blob/master/app/controllers/MainController.php#L8
Этот конструктор ничего не меняет и потому его можно тут не указывать.
> public function parseRequest(){
> parent::parseRequest();
> }
То же самое. Перечитай про наследование классов. Эту функцию нет смысла переопределять.
> $this->mainCode();
Название функции должно начинаться с глагола. И обозначать что она делает.
> $this->viewName='pages/main';
> //Из локальных в глобальные, чтобы передать в packViewVars()
> foreach ($this->keysOfViewVars as $key) {
> $this->$key=$$key;
> }
Я думаю, лучше вместо неявных заданий имен шаблона явно вызывать метод showView(), передавая ему имя и переменные. У тебя все как-то запутанно: какие-то поля создаются, а можно просто вызвать функцию и передать ей нужные аругменты. Зачем усложнять - непонятно.
> $register_ok
В PSR переменные пишут кемелкейсом. Более того, у тебя есть и переменные с кемелкейсом, и с подчеркиванием. Смотрится ужасно.
Насчет переменных, которые нужны в каждом шаблоне (например, которые выводятся в шапке). Можно сделать в базовом контроллере метод для их получения.
>>826978
https://github.com/TheSidSpears/Students/blob/master/app/controllers/ERController.php
тут используются табы вместо пробелов и из-за этого гигантские отступы.
https://github.com/TheSidSpears/Students/blob/master/app/controllers/ERController.php#L85
> or ($_COOKIE['token']!=$_POST['token']
Тут лучше использовать строгое сравнение.
https://github.com/TheSidSpears/Students/blob/master/app/controllers/ERController.php
Здесь в контроллере много усложнений. Ну например вместо того чтобы вернуть результат из функции setToken() и сохранить в переменной, ты его прописываешь в поле, а где-то в другой функции берешь из этого поля. Но это только усложняет код. Во-первых, явно не видно что откуда и куда передается. во-вторых, чтобы это работало, функции надо вызывать в определенном порядке, а как понять, в каком?
Ты пишешь код в контроллере в таком стиле, что в нем становится тяжело разобраться.
> protected $validModules=array('edit','edit_ok','register','register_ok');
Я бы упростил и просто проверял наличие метода с именем "модуля".
Не уверен, что праивльно помещать права доступа в роутер. Не лучше ли их прописывать в самом методе или в контроллере? У тебя ведь нет такого, что надо давать доступ к одному модулю с разными правами.
> if(!$this->checkToken()){
> //Попытка взлома
> header(' ', true, 400);
Во-первых, ты не показываешь страницу ошибки, а выводишь ту же форму (или так и задумано?), во-вторых, наверно надо сделать метод для вывода страницы ошибки.
https://github.com/TheSidSpears/Students/blob/master/app/controllers/ERController.php
В этом контроллере на мой взгляд неправильно сделано редактирование студента. Ты создаешь нового студента и заполняешь данными из POST, в то время как надо редактировать взятого из базы. В твоем случае проще что-то потерять, и непонятно почему для одного и того же студента создается 2 отдельных объекта. Опять же, все как-то переусложнено. Надо просто взять студента из БД, поменять нужные поля, проверить и сохранить обратно.
Также, надо удалять неиспользуемый код. Если у тебя больше не передается имя шаблона в контроллер - надо это убрать, надо убрать страницы register_ok если они не используются.
> https://github.com/TheSidSpears/Students/blob/master/app/db/StudentDataGateway.php#L34
> WHERE CONCAT(`name`,' ',`sname`,' ',`group_num`,' ',`points`,' ',`gender`,' ',`email`,' ',`b_year`,' ',`is_resident`) LIKE '%$search%'");
Надо подставлять данные через плейсхолдеры. Это SQL инъекция.
https://github.com/TheSidSpears/Students/blob/master/app/db/StudentDataGateway.php#L63
Надо бы запретить сортировать по hash. Это дает информацию о том в каком порядке они идут. Хотя это не получится использовать для взлома, но все равно, надо внимательнее относиться к безопасности.
https://github.com/TheSidSpears/Students/blob/master/app/db/StudentDataGateway.php#L96
> public function getStudentByHash($hashFromCookie){
Непонятно почему тут возвращается массив, а не объект.
https://github.com/TheSidSpears/Students/blob/master/app/db/StudentDataGateway.php#L117
> public function checkEmail($email,$id=NULL){
Для проверки наличия email не надо выбирать данные, а достаточно посчитать количество строк.
https://github.com/TheSidSpears/Students/blob/master/app/helpers/JSONLoader.php#L21
> throw new ConfigException("Ошибка в $filename");
Сюда надо бы добавить подробности ошибки разбора JSON
https://github.com/TheSidSpears/Students/blob/master/app/helpers/TableUrlMaker.php
Здесь неудачно выбраны аругменты конструктора. Ты передаешь сюда роутер. Зачем? Разбирать УРЛ? Нет, тебе нужно только имя модуля - значит надо передавать только его.
https://github.com/TheSidSpears/Students/blob/master/app/helpers/Util.php#L29
> $reg=preg_quote("/$find/ui");
Неправильно - preq_quote заэкранирует слеши и превратит их в \/. preg_quote экранирует все символы, которые могли бы иметь специальное значение, и ограничители (слеши) конечно тоже заэкраниурет. И неправильно передавать в эту функцию флаги.
> public function validate(Student $s,$id=NULL){
id наверно можно брать из самого студента
> <a href='<?=Router::url('edit')?>'>Редактировать</a>
Название метода должно начинаться с глагола. Плюс, не очень понятно почему метод статический - он разве не зависит от конфигурации роутера?
Вот это вот: https://github.com/TheSidSpears/Students/blob/master/app/views/pages/register.php выглядит как переусложнение. Проще сделать один шаблон для регистрации и редактирования и в нем через if выводить нужную часть.
В общем, надо упрощать код, и поработать над форматированием, именами функций и переменных.
>>826978
https://github.com/TheSidSpears/Students/blob/master/app/controllers/ERController.php
тут используются табы вместо пробелов и из-за этого гигантские отступы.
https://github.com/TheSidSpears/Students/blob/master/app/controllers/ERController.php#L85
> or ($_COOKIE['token']!=$_POST['token']
Тут лучше использовать строгое сравнение.
https://github.com/TheSidSpears/Students/blob/master/app/controllers/ERController.php
Здесь в контроллере много усложнений. Ну например вместо того чтобы вернуть результат из функции setToken() и сохранить в переменной, ты его прописываешь в поле, а где-то в другой функции берешь из этого поля. Но это только усложняет код. Во-первых, явно не видно что откуда и куда передается. во-вторых, чтобы это работало, функции надо вызывать в определенном порядке, а как понять, в каком?
Ты пишешь код в контроллере в таком стиле, что в нем становится тяжело разобраться.
> protected $validModules=array('edit','edit_ok','register','register_ok');
Я бы упростил и просто проверял наличие метода с именем "модуля".
Не уверен, что праивльно помещать права доступа в роутер. Не лучше ли их прописывать в самом методе или в контроллере? У тебя ведь нет такого, что надо давать доступ к одному модулю с разными правами.
> if(!$this->checkToken()){
> //Попытка взлома
> header(' ', true, 400);
Во-первых, ты не показываешь страницу ошибки, а выводишь ту же форму (или так и задумано?), во-вторых, наверно надо сделать метод для вывода страницы ошибки.
https://github.com/TheSidSpears/Students/blob/master/app/controllers/ERController.php
В этом контроллере на мой взгляд неправильно сделано редактирование студента. Ты создаешь нового студента и заполняешь данными из POST, в то время как надо редактировать взятого из базы. В твоем случае проще что-то потерять, и непонятно почему для одного и того же студента создается 2 отдельных объекта. Опять же, все как-то переусложнено. Надо просто взять студента из БД, поменять нужные поля, проверить и сохранить обратно.
Также, надо удалять неиспользуемый код. Если у тебя больше не передается имя шаблона в контроллер - надо это убрать, надо убрать страницы register_ok если они не используются.
> https://github.com/TheSidSpears/Students/blob/master/app/db/StudentDataGateway.php#L34
> WHERE CONCAT(`name`,' ',`sname`,' ',`group_num`,' ',`points`,' ',`gender`,' ',`email`,' ',`b_year`,' ',`is_resident`) LIKE '%$search%'");
Надо подставлять данные через плейсхолдеры. Это SQL инъекция.
https://github.com/TheSidSpears/Students/blob/master/app/db/StudentDataGateway.php#L63
Надо бы запретить сортировать по hash. Это дает информацию о том в каком порядке они идут. Хотя это не получится использовать для взлома, но все равно, надо внимательнее относиться к безопасности.
https://github.com/TheSidSpears/Students/blob/master/app/db/StudentDataGateway.php#L96
> public function getStudentByHash($hashFromCookie){
Непонятно почему тут возвращается массив, а не объект.
https://github.com/TheSidSpears/Students/blob/master/app/db/StudentDataGateway.php#L117
> public function checkEmail($email,$id=NULL){
Для проверки наличия email не надо выбирать данные, а достаточно посчитать количество строк.
https://github.com/TheSidSpears/Students/blob/master/app/helpers/JSONLoader.php#L21
> throw new ConfigException("Ошибка в $filename");
Сюда надо бы добавить подробности ошибки разбора JSON
https://github.com/TheSidSpears/Students/blob/master/app/helpers/TableUrlMaker.php
Здесь неудачно выбраны аругменты конструктора. Ты передаешь сюда роутер. Зачем? Разбирать УРЛ? Нет, тебе нужно только имя модуля - значит надо передавать только его.
https://github.com/TheSidSpears/Students/blob/master/app/helpers/Util.php#L29
> $reg=preg_quote("/$find/ui");
Неправильно - preq_quote заэкранирует слеши и превратит их в \/. preg_quote экранирует все символы, которые могли бы иметь специальное значение, и ограничители (слеши) конечно тоже заэкраниурет. И неправильно передавать в эту функцию флаги.
> public function validate(Student $s,$id=NULL){
id наверно можно брать из самого студента
> <a href='<?=Router::url('edit')?>'>Редактировать</a>
Название метода должно начинаться с глагола. Плюс, не очень понятно почему метод статический - он разве не зависит от конфигурации роутера?
Вот это вот: https://github.com/TheSidSpears/Students/blob/master/app/views/pages/register.php выглядит как переусложнение. Проще сделать один шаблон для регистрации и редактирования и в нем через if выводить нужную часть.
В общем, надо упрощать код, и поработать над форматированием, именами функций и переменных.
Vertical align
> Исправил: https://jsfiddle.net/211Le60v/7/
Теперь верно.
Задача про ООО
> В шаблоне задания под контентной частью написано 100% - 230px. Если я неправильно понял что 230 пикселей, это максимальная ширина, а не минимальная, то всё легко решается:
"100% - 230px" значит "контент растягивается на всю ширину страницы, за исключением 230px которые отведены под меню и отступы". Ну то есть слева меню фиксированной ширины (200px по моему), а справа все оставшееся место занимает контент.
> max-width: 230px;
Там нет такого ограничения. Контент занимает все место справа что осталось от меню.
> width: calc(100% - 200px);
Это конечно хорошо, но работает пока не везде (в ИЕ8 например не работает или в старом андроиде: http://caniuse.com/#feat=calc ), надо бы что-то с этим сделать. Хотя бы сделать width 100% для не поддерживающий браузеров. Или обойтись без calc.
> margin-right: -100%;
Это нужно в методе без calc с враппером, про который я писал. В случае поддержки calc это скорее вредит и делает код менее надежным (ну например если мы по ошибке увеличим ширину левой колонки, забыв поменять ширину правой, левая заедет под контент, контент не перенесется на новую строку из-за этого маргина).
> <li class="navigation-menu-li">
Я думаю что удобнее не ставить тут класс, а просто писать .navigation-ul > li в CSS
> Если сжимать тело по ширине до 171px то, даже не смотря на то что контентному блоку нужно как минимум 230px, контентный блок не будет провалиться. Но если ширина тела станет 170px или меньше, то элемент сразу проваливается. Это совершенно не с чем не связанное число, даже если не брать это во внимание на практике, мне всё равно не понятно подобное поведение.
Скорее всего это ширина самой длинной строчки в меню. Так как у меню не задана ширина и у него стоит float: left то его ширина определяется алгоритмом shrink-to-fit (я написал урок по теме: https://github.com/codedokode/pasta/blob/master/html/shrink-to-fit.md ) из ширины содержимого и родителя. Так как самая широкая строчка имеет ширину 170px то и блок меню получает такую ширину. И соответственно при ужатии меньше 170px второй флоат переносится так как первый уже занимает все доступное место.
Флоаты по умолчанию выстраиваются в строку, но только пока есть свободное место. Если места нет то очередной флоат переносится на новую строку. Попробуйте сделать на отдельной странице штук 10 флоатов разных цветов и размеров (разной высоты и ширины) и посмотрите, как они выстраиваются когда меняется ширина родителя. Потом еще можно заменить float на display: inline-block и сравнить их поведение.
> Что отличает отступы в -29px и -30px?
Там стоит ширина блоков 50% и 55%. Видимо -30px достаточно, чтобы сдвинуть блок на 5% левее и уложиться в ширину родителя, а 29px недостаточно.
Вообще, я советую научиться пользоваться отладчиком в браузере (Ctrl + Shift + I или F12) - он показывает размеры и отступы у элементов, примененные CSS правила итд. Попробуйте им воспользоваться.
> Почему в первом примере, при очень сильном сжатии, флоат проваливается вниз? Так быть не должно т.к. мы используем функцию calc, которая всегда должна высчитывать всю страницу минус 230px. Что отличает эту функцию в первом примере от второго?
calc работает как надо и при очень узкой шиине родителя должен выдавать 0, что можно увидеть в отладчике на вкладке Computed (отрицательной ширина быть не может). Но несмотря на это, флоат переносится на новую строку так как меню заняло всю ширину родителя.
Разница между первым и вторым примерами (ее нелегко было найти, но я нашел) в том, что во втором примере слова короткие и как бы ты не сжимал ширину на сайте jsfiddle, ее хватает чтобы эти слова поместились и осталось немного места справа (почитайте мой урок про shrink-to-fit). Если заменить хотя бы одно слово FIRST на более длинное слово, то второй блок начнет переноситься.
То есть проблема в том что на jsfiddle нельзя ужать окошко меньше определенного размера и слово FIRST влезает в этот размер.
Задача про инпут и кнопку
> Исправил: https://jsfiddle.net/5g31m30j/3/
По прежнему нехорошо. Там не указан паддинг для поля ввода и расчет на то, что он будет равен 1px + бордер = 2px. Но где гарантия что во всех браузерах такие значения стоят по умолчанию? Вообще, тут по моему проще задавать не внутреннюю высоту, а внешнюю, которая уже включает в себя паддинги и бордеры.
Задача про Короля Лир
> А такое решение считается правильным https://jsfiddle.net/zxm89tLg/1/ ?
Тут есть проблема, что невозможно догадаться что тут есть примечания и надо навести мышь чтобы их увидеть. И даже если догадаться, надо тратить усилия, наводя мышь на каждый абзац. Плюс, есть мобильные устройства где нет мыши. Не вижу выгоды от скрытия примечаний так как поля все равно не используются.
Неудобно хранить текст примечания в атрибуте, так как нельзя добавить в него другие теги.
> Если нет, то я сделал как вы советовали: https://jsfiddle.net/tsuh4gjw/5/
Если в текст добавить другие теги то все разваливается: https://jsfiddle.net/tsuh4gjw/6/ Почитайте внимательно подсказки к задаче.
Задача про верстку форума
> Исправил: https://jsfiddle.net/kxdx27f1/4/
> Критично то что теперь появился небольшой отступ перед p?
Не критично. Но я считаю, что тег content не требуется. Можно сверстать без него.
> А можно было использовать универсальный селектор
Это практически всегда плохая идея. Плюс, он действует только на теги и не действует на текст вне тегов или псевдоэлементы.
Почитайте примечания к задаче.
Задача про радиокнопки
> Странно, у меня работает фокус. Прикладываю webm для наглядности...
А, теперь вижу. Я просто не догадался что тень обозначает фокус. А можно вместо нее сделать например синее свечение вокруг элемента, как это сделано в Хроме для инпутов под фокусом?
В общем, действительно, элемент под фокусом выделяется, я просто не догадался, что это фокус, так как нажатая кнопка выделяется тем же способом. То есть если мы открываем страницу и ставим табом фокус на элементе, то кнопка выглядит нажатой хотя она еще не нажата. Нужны разные стили для нажатой и сфокусированной кнопки.
> Скажите свою версию браузера, чтобы я мог это починить?
Хромиум (Хром должен вести себя так же).
> .inputbox > input {
> position: absolute;
> left: -10000px;
Вот у этого метода конечно есть подвох - что если завтра кто-то поставит наш элемент на гигантскую страницу которая шире этих 10 000 px? Может лучше сделать родителя c overflow: hidden и тогда не придется так далеко загонять? Или все же не стоит? Я в принципе не настаиваю.
> Некоторые селекторы и псевдоклассы который мы используем появляются как минимум с 6 версии IE и 3.5 версии Оперы, остальные же браузеры поддерживают их с первых версий. В том списке браузеры уже гораздо старше.
да, это селекторы из CSS2.1. По идее все старые браузеры поддерживают HTML4 и CSS2.1, но по факту в IE6 и 7 была куча багов с ними. Но в IE8 все более-менее терпимо, и я думаю это минимальная версия ИЕ на которую стоит ориентироваться. То есть если использовать CSS2.1 то условно говоря это будет работать везде.
У меня есть урок по ИЕ: https://gist.github.com/codedokode/855e3970124687b26a1c
Vertical align
> Исправил: https://jsfiddle.net/211Le60v/7/
Теперь верно.
Задача про ООО
> В шаблоне задания под контентной частью написано 100% - 230px. Если я неправильно понял что 230 пикселей, это максимальная ширина, а не минимальная, то всё легко решается:
"100% - 230px" значит "контент растягивается на всю ширину страницы, за исключением 230px которые отведены под меню и отступы". Ну то есть слева меню фиксированной ширины (200px по моему), а справа все оставшееся место занимает контент.
> max-width: 230px;
Там нет такого ограничения. Контент занимает все место справа что осталось от меню.
> width: calc(100% - 200px);
Это конечно хорошо, но работает пока не везде (в ИЕ8 например не работает или в старом андроиде: http://caniuse.com/#feat=calc ), надо бы что-то с этим сделать. Хотя бы сделать width 100% для не поддерживающий браузеров. Или обойтись без calc.
> margin-right: -100%;
Это нужно в методе без calc с враппером, про который я писал. В случае поддержки calc это скорее вредит и делает код менее надежным (ну например если мы по ошибке увеличим ширину левой колонки, забыв поменять ширину правой, левая заедет под контент, контент не перенесется на новую строку из-за этого маргина).
> <li class="navigation-menu-li">
Я думаю что удобнее не ставить тут класс, а просто писать .navigation-ul > li в CSS
> Если сжимать тело по ширине до 171px то, даже не смотря на то что контентному блоку нужно как минимум 230px, контентный блок не будет провалиться. Но если ширина тела станет 170px или меньше, то элемент сразу проваливается. Это совершенно не с чем не связанное число, даже если не брать это во внимание на практике, мне всё равно не понятно подобное поведение.
Скорее всего это ширина самой длинной строчки в меню. Так как у меню не задана ширина и у него стоит float: left то его ширина определяется алгоритмом shrink-to-fit (я написал урок по теме: https://github.com/codedokode/pasta/blob/master/html/shrink-to-fit.md ) из ширины содержимого и родителя. Так как самая широкая строчка имеет ширину 170px то и блок меню получает такую ширину. И соответственно при ужатии меньше 170px второй флоат переносится так как первый уже занимает все доступное место.
Флоаты по умолчанию выстраиваются в строку, но только пока есть свободное место. Если места нет то очередной флоат переносится на новую строку. Попробуйте сделать на отдельной странице штук 10 флоатов разных цветов и размеров (разной высоты и ширины) и посмотрите, как они выстраиваются когда меняется ширина родителя. Потом еще можно заменить float на display: inline-block и сравнить их поведение.
> Что отличает отступы в -29px и -30px?
Там стоит ширина блоков 50% и 55%. Видимо -30px достаточно, чтобы сдвинуть блок на 5% левее и уложиться в ширину родителя, а 29px недостаточно.
Вообще, я советую научиться пользоваться отладчиком в браузере (Ctrl + Shift + I или F12) - он показывает размеры и отступы у элементов, примененные CSS правила итд. Попробуйте им воспользоваться.
> Почему в первом примере, при очень сильном сжатии, флоат проваливается вниз? Так быть не должно т.к. мы используем функцию calc, которая всегда должна высчитывать всю страницу минус 230px. Что отличает эту функцию в первом примере от второго?
calc работает как надо и при очень узкой шиине родителя должен выдавать 0, что можно увидеть в отладчике на вкладке Computed (отрицательной ширина быть не может). Но несмотря на это, флоат переносится на новую строку так как меню заняло всю ширину родителя.
Разница между первым и вторым примерами (ее нелегко было найти, но я нашел) в том, что во втором примере слова короткие и как бы ты не сжимал ширину на сайте jsfiddle, ее хватает чтобы эти слова поместились и осталось немного места справа (почитайте мой урок про shrink-to-fit). Если заменить хотя бы одно слово FIRST на более длинное слово, то второй блок начнет переноситься.
То есть проблема в том что на jsfiddle нельзя ужать окошко меньше определенного размера и слово FIRST влезает в этот размер.
Задача про инпут и кнопку
> Исправил: https://jsfiddle.net/5g31m30j/3/
По прежнему нехорошо. Там не указан паддинг для поля ввода и расчет на то, что он будет равен 1px + бордер = 2px. Но где гарантия что во всех браузерах такие значения стоят по умолчанию? Вообще, тут по моему проще задавать не внутреннюю высоту, а внешнюю, которая уже включает в себя паддинги и бордеры.
Задача про Короля Лир
> А такое решение считается правильным https://jsfiddle.net/zxm89tLg/1/ ?
Тут есть проблема, что невозможно догадаться что тут есть примечания и надо навести мышь чтобы их увидеть. И даже если догадаться, надо тратить усилия, наводя мышь на каждый абзац. Плюс, есть мобильные устройства где нет мыши. Не вижу выгоды от скрытия примечаний так как поля все равно не используются.
Неудобно хранить текст примечания в атрибуте, так как нельзя добавить в него другие теги.
> Если нет, то я сделал как вы советовали: https://jsfiddle.net/tsuh4gjw/5/
Если в текст добавить другие теги то все разваливается: https://jsfiddle.net/tsuh4gjw/6/ Почитайте внимательно подсказки к задаче.
Задача про верстку форума
> Исправил: https://jsfiddle.net/kxdx27f1/4/
> Критично то что теперь появился небольшой отступ перед p?
Не критично. Но я считаю, что тег content не требуется. Можно сверстать без него.
> А можно было использовать универсальный селектор
Это практически всегда плохая идея. Плюс, он действует только на теги и не действует на текст вне тегов или псевдоэлементы.
Почитайте примечания к задаче.
Задача про радиокнопки
> Странно, у меня работает фокус. Прикладываю webm для наглядности...
А, теперь вижу. Я просто не догадался что тень обозначает фокус. А можно вместо нее сделать например синее свечение вокруг элемента, как это сделано в Хроме для инпутов под фокусом?
В общем, действительно, элемент под фокусом выделяется, я просто не догадался, что это фокус, так как нажатая кнопка выделяется тем же способом. То есть если мы открываем страницу и ставим табом фокус на элементе, то кнопка выглядит нажатой хотя она еще не нажата. Нужны разные стили для нажатой и сфокусированной кнопки.
> Скажите свою версию браузера, чтобы я мог это починить?
Хромиум (Хром должен вести себя так же).
> .inputbox > input {
> position: absolute;
> left: -10000px;
Вот у этого метода конечно есть подвох - что если завтра кто-то поставит наш элемент на гигантскую страницу которая шире этих 10 000 px? Может лучше сделать родителя c overflow: hidden и тогда не придется так далеко загонять? Или все же не стоит? Я в принципе не настаиваю.
> Некоторые селекторы и псевдоклассы который мы используем появляются как минимум с 6 версии IE и 3.5 версии Оперы, остальные же браузеры поддерживают их с первых версий. В том списке браузеры уже гораздо старше.
да, это селекторы из CSS2.1. По идее все старые браузеры поддерживают HTML4 и CSS2.1, но по факту в IE6 и 7 была куча багов с ними. Но в IE8 все более-менее терпимо, и я думаю это минимальная версия ИЕ на которую стоит ориентироваться. То есть если использовать CSS2.1 то условно говоря это будет работать везде.
У меня есть урок по ИЕ: https://gist.github.com/codedokode/855e3970124687b26a1c
> Даже после исправления инпуты не исчезли: https://jsfiddle.net/gpysbfar/2/
Потому что left применяется только к позиционированным элементам.
> Да, причем, насколько я понял, в этом способе необязательно использовать именно <dl>, <dt> и <dd>, а можно заменить их например на <div class="taber">, <h2> и <article>. По-моему так наглядней выглядит.
Согласен, поисковый робот может например увидеть это как текст с подзаголовками.
>><input data-tab="tab1">....<div data-tab="tab1">...
> Мы же не полностью одобряем уникальные идентификаторы.
разница между data-tab и id в том что data-tab уникальны только в пределах виджета, а id должны быть уникальны на всей странице.
> В любом случае я сделал и это: https://jsfiddle.net/tb7k9dw9/5/
А где адаптивность? Если у нас очень узкий экран то табы надо либо выводить в столбик либо выводить в раскрытом виде. Сейчас, если сделать экран узким то подписи табов просто вываливаются из них. Надо это исправить, ширина вкладки должна определяться текстом и вомзожно ограничением на макс/мин ширину.
> id="first-tab" data-tab="first"
Вот 2 идентификатора это многовато .... нельзя ли оставить только один? желательно бы не-id если это не сложно (если сложно то ладно, что поделать, пусть будет id).
И еще один совет. Если мы встраиваем наш виджет в страницу, то есть ненулевая вероятность, что там уже есть класс с названием вроде content или wrapper. Чтобы избежать конфиликтов (а заодно станет понятно, откуда этот класс), надо добавить ко всем классам общий префикс, например .taber-content. Также, можете почитать про систему имен классов в БЭМ.
> Но почему мы должны поощрять использование устаревших технологий? Нужно наоборот мотивировать пользователей или поставщиков оборудования использовать современные технологии.
Пользователи и так знают что новые бразуеры лучше. Специально мотивировать их не надо. Но не всегда есть возможность, навыки, права или время обновить его.
Плюс, в рамках обучения мы должны стремиться идти "сложным" путем, а не "простым". Если вы будете по работе заниматься версткой - другой вопрос.
Ну и вообще, лучше когда страница доступна везде (пусть и не в очень красивом виде), чем просто не отображается.
Очень высокопосещаемые сайты вроде Гугла или Яндекса доступны и в старых браузерах. Так как для них даже 2% это довольно много человек.
> Даже после исправления инпуты не исчезли: https://jsfiddle.net/gpysbfar/2/
Потому что left применяется только к позиционированным элементам.
> Да, причем, насколько я понял, в этом способе необязательно использовать именно <dl>, <dt> и <dd>, а можно заменить их например на <div class="taber">, <h2> и <article>. По-моему так наглядней выглядит.
Согласен, поисковый робот может например увидеть это как текст с подзаголовками.
>><input data-tab="tab1">....<div data-tab="tab1">...
> Мы же не полностью одобряем уникальные идентификаторы.
разница между data-tab и id в том что data-tab уникальны только в пределах виджета, а id должны быть уникальны на всей странице.
> В любом случае я сделал и это: https://jsfiddle.net/tb7k9dw9/5/
А где адаптивность? Если у нас очень узкий экран то табы надо либо выводить в столбик либо выводить в раскрытом виде. Сейчас, если сделать экран узким то подписи табов просто вываливаются из них. Надо это исправить, ширина вкладки должна определяться текстом и вомзожно ограничением на макс/мин ширину.
> id="first-tab" data-tab="first"
Вот 2 идентификатора это многовато .... нельзя ли оставить только один? желательно бы не-id если это не сложно (если сложно то ладно, что поделать, пусть будет id).
И еще один совет. Если мы встраиваем наш виджет в страницу, то есть ненулевая вероятность, что там уже есть класс с названием вроде content или wrapper. Чтобы избежать конфиликтов (а заодно станет понятно, откуда этот класс), надо добавить ко всем классам общий префикс, например .taber-content. Также, можете почитать про систему имен классов в БЭМ.
> Но почему мы должны поощрять использование устаревших технологий? Нужно наоборот мотивировать пользователей или поставщиков оборудования использовать современные технологии.
Пользователи и так знают что новые бразуеры лучше. Специально мотивировать их не надо. Но не всегда есть возможность, навыки, права или время обновить его.
Плюс, в рамках обучения мы должны стремиться идти "сложным" путем, а не "простым". Если вы будете по работе заниматься версткой - другой вопрос.
Ну и вообще, лучше когда страница доступна везде (пусть и не в очень красивом виде), чем просто не отображается.
Очень высокопосещаемые сайты вроде Гугла или Яндекса доступны и в старых браузерах. Так как для них даже 2% это довольно много человек.
Насчет 2 идентификаторов в задаче с табами - если убрать один из них сложно, то пусть остаются.
Ну не стукай. Исправил и сделал пагинацию.
Вот отсюда взял его, из последней версииhttp://windows.php.net/downloads/pecl/releases/imagick/3.4.3rc1/.
Установил даже ImageMagick - без толку.
У меня не работает captcha в браузере: "Изображение по такому-то пути не может быть показано, так как содержит ошибки".
Что делать, как дальше жить?
Вообще вот такая ошибка вылезает:
Invalid Configuration – yii\base\InvalidConfigException
Either GD PHP extension with FreeType support or ImageMagick PHP extension with PNG support is required.
Сейчас буду разбираться ещё с GD PHP.
Ну такое дело - за что ни возьмёшься - нужно знать целую кучу всего. Как я уже начинаю это всё ненавидеть...
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-6
>Задача про ООО
>> width: calc(100% - 200px);
>Это конечно хорошо, но работает пока не везде (в ИЕ8 например не работает или в старом андроиде: http://caniuse.com/#feat=calc ), надо бы что-то с этим сделать. Хотя бы сделать width 100% для не поддерживающий браузеров. Или обойтись без calc.
А как переопределить это правило только для новых браузеров? Селекторы, которые я использую для фикса старых браузеров, да и вообще все селекторы, как раз начинают работать с 7-8 версии IE и с первых версий андройда.
Пусть пока будет так: https://jsfiddle.net/0u3x5rsw/3/
>>828506
>А также есть статья http://chikuyonok.ru/2010/01/liquid-site-markup/
>Суть там довольно проста. Левую колонку с меню мы загоняем влево с помощью float left. Правую колонку - вправо с помощью float:right. Но как задать ей ширину "вся страница минус 230px"? Никак, потому задаем ей 100%, а внутрь ставим блок с отступом 230px слева, а уже в него кладем текст. Но при таком подходе она пересекается по шиине с левой колонкой и проваливается вниз под нее. Для решения этой проблемы делаем ее внешнюю ширину меньше за счет отрицательного левого маргина. Например, -100%, в результате чего она начинает занимать 0px места и никому не мешает.
>...а внутрь ставим блок с отступом 230px слева, а уже в него кладем текст. Но при таком подходе она пересекается по шиине с левой колонкой и проваливается вниз под нее. Для решения этой проблемы делаем ее внешнюю ширину меньше за счет отрицательного левого маргина. Например, -100%, в результате чего она начинает занимать 0px места и никому не мешает.
А у меня получилось без внутреннего блока сделать, и, причем, у меня ничего не пересекается и не проваливается: https://jsfiddle.net/xx82knpf/ https://jsfiddle.net/xx82knpf/1/
https://jsfiddle.net/0u3x5rsw/
>> margin-right: -100%;
>Это нужно в методе без calc с враппером, про который я писал. В случае поддержки calc это скорее вредит и делает код менее надежным (ну например если мы по ошибке увеличим ширину левой колонки, забыв поменять ширину правой, левая заедет под контент, контент не перенесется на новую строку из-за этого маргина).
Без этого свойства при очень сильном сжатии бокс провалиться под левую колонку.
>например если мы по ошибке увеличим ширину левой колонки, забыв поменять ширину правой, левая заедет под контент, контент не перенесется на новую строку из-за этого маргина
Мы можем забыть что-то поменять и не используя функцию calc, например, так же, поменять ширину левой колонки и забыть поменять левый маргин у правой.
>>830052
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-7
>Задача про инпут и кнопку
>По прежнему нехорошо. Там не указан паддинг для поля ввода и расчет на то, что он будет равен 1px + бордер = 2px.
Исправил: https://jsfiddle.net/5g31m30j/4/
Почему у одинаковых элементов разные свойства? Где можно узнать о свойстве каждого?
>>830052
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-8
>Задача про Короля Лир
>Если в текст добавить другие теги то все разваливается: https://jsfiddle.net/tsuh4gjw/6/
Исправил: https://jsfiddle.net/tsuh4gjw/8/ Что-то я совсем...
>>830052
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-9
>Задача про верстку форума
>Не критично. Но я считаю, что тег content не требуется. Можно сверстать без него.
А можно подсказку как?
>>830052
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-11
>Задача про радиокнопки
>> Странно, у меня работает фокус. Прикладываю webm для наглядности...
>А, теперь вижу. Я просто не догадался что тень обозначает фокус. А можно вместо нее сделать например синее свечение вокруг элемента, как это сделано в Хроме для инпутов под фокусом?
Конечно: https://jsfiddle.net/fp8o0exq/6/
>>830053
>> Даже после исправления инпуты не исчезли: https://jsfiddle.net/gpysbfar/2/
>Потому что left применяется только к позиционированным элементам.
До сих пор не понял в чём смысл: https://jsfiddle.net/gpysbfar/4/
Контент находиться за пределами лейбла, но не скрывается.
>>815065
>> Как на глаз определить тень и шрифт?
>Для начала, надо попробовать определить радиус тени (на котором она плавно переходит в прозрачность). Если присмотреться, то видно что на картинке тень несимметричная: она большая сверху, маленькая снизу и равная по сторонам. Значит, тень смещена вниз, а справа или слева ее ширина. По ней мы подбираем радиус (будет примерно пикселя 3 я думаю). подобрав радиус, подбираем прозрачность черного, чтобы с краев тень совпадала по прозрачности с картинкой.
>Ну и напоследок подбираем вертикальное смещение тени, просто на глаз двигая тень вниз.
Вроде получилось: https://jsfiddle.net/fp8o0exq/7/
>>830053
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-12
>Задача про вкладки
>> В любом случае я сделал и это: https://jsfiddle.net/tb7k9dw9/5/
>А где адаптивность? Если у нас очень узкий экран то табы надо либо выводить в столбик либо выводить в раскрытом виде. Сейчас, если сделать экран узким то подписи табов просто вываливаются из них. Надо это исправить, ширина вкладки должна определяться текстом и вомзожно ограничением на макс/мин ширину.
Исправил: https://jsfiddle.net/tb7k9dw9/6/
> id="first-tab" data-tab="first"
Вот 2 идентификатора это многовато .... нельзя ли оставить только один? желательно бы не-id если это не сложно (если сложно то ладно, что поделать, пусть будет id).
Можно хотя бы подсказку как это сделать?
>Попробуйте
Вы можете обращаться ко мне на 'ты'. Вас называть на 'Вы' я начал в знак уважения вас как учителя.
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-6
>Задача про ООО
>> width: calc(100% - 200px);
>Это конечно хорошо, но работает пока не везде (в ИЕ8 например не работает или в старом андроиде: http://caniuse.com/#feat=calc ), надо бы что-то с этим сделать. Хотя бы сделать width 100% для не поддерживающий браузеров. Или обойтись без calc.
А как переопределить это правило только для новых браузеров? Селекторы, которые я использую для фикса старых браузеров, да и вообще все селекторы, как раз начинают работать с 7-8 версии IE и с первых версий андройда.
Пусть пока будет так: https://jsfiddle.net/0u3x5rsw/3/
>>828506
>А также есть статья http://chikuyonok.ru/2010/01/liquid-site-markup/
>Суть там довольно проста. Левую колонку с меню мы загоняем влево с помощью float left. Правую колонку - вправо с помощью float:right. Но как задать ей ширину "вся страница минус 230px"? Никак, потому задаем ей 100%, а внутрь ставим блок с отступом 230px слева, а уже в него кладем текст. Но при таком подходе она пересекается по шиине с левой колонкой и проваливается вниз под нее. Для решения этой проблемы делаем ее внешнюю ширину меньше за счет отрицательного левого маргина. Например, -100%, в результате чего она начинает занимать 0px места и никому не мешает.
>...а внутрь ставим блок с отступом 230px слева, а уже в него кладем текст. Но при таком подходе она пересекается по шиине с левой колонкой и проваливается вниз под нее. Для решения этой проблемы делаем ее внешнюю ширину меньше за счет отрицательного левого маргина. Например, -100%, в результате чего она начинает занимать 0px места и никому не мешает.
А у меня получилось без внутреннего блока сделать, и, причем, у меня ничего не пересекается и не проваливается: https://jsfiddle.net/xx82knpf/ https://jsfiddle.net/xx82knpf/1/
https://jsfiddle.net/0u3x5rsw/
>> margin-right: -100%;
>Это нужно в методе без calc с враппером, про который я писал. В случае поддержки calc это скорее вредит и делает код менее надежным (ну например если мы по ошибке увеличим ширину левой колонки, забыв поменять ширину правой, левая заедет под контент, контент не перенесется на новую строку из-за этого маргина).
Без этого свойства при очень сильном сжатии бокс провалиться под левую колонку.
>например если мы по ошибке увеличим ширину левой колонки, забыв поменять ширину правой, левая заедет под контент, контент не перенесется на новую строку из-за этого маргина
Мы можем забыть что-то поменять и не используя функцию calc, например, так же, поменять ширину левой колонки и забыть поменять левый маргин у правой.
>>830052
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-7
>Задача про инпут и кнопку
>По прежнему нехорошо. Там не указан паддинг для поля ввода и расчет на то, что он будет равен 1px + бордер = 2px.
Исправил: https://jsfiddle.net/5g31m30j/4/
Почему у одинаковых элементов разные свойства? Где можно узнать о свойстве каждого?
>>830052
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-8
>Задача про Короля Лир
>Если в текст добавить другие теги то все разваливается: https://jsfiddle.net/tsuh4gjw/6/
Исправил: https://jsfiddle.net/tsuh4gjw/8/ Что-то я совсем...
>>830052
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-9
>Задача про верстку форума
>Не критично. Но я считаю, что тег content не требуется. Можно сверстать без него.
А можно подсказку как?
>>830052
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-11
>Задача про радиокнопки
>> Странно, у меня работает фокус. Прикладываю webm для наглядности...
>А, теперь вижу. Я просто не догадался что тень обозначает фокус. А можно вместо нее сделать например синее свечение вокруг элемента, как это сделано в Хроме для инпутов под фокусом?
Конечно: https://jsfiddle.net/fp8o0exq/6/
>>830053
>> Даже после исправления инпуты не исчезли: https://jsfiddle.net/gpysbfar/2/
>Потому что left применяется только к позиционированным элементам.
До сих пор не понял в чём смысл: https://jsfiddle.net/gpysbfar/4/
Контент находиться за пределами лейбла, но не скрывается.
>>815065
>> Как на глаз определить тень и шрифт?
>Для начала, надо попробовать определить радиус тени (на котором она плавно переходит в прозрачность). Если присмотреться, то видно что на картинке тень несимметричная: она большая сверху, маленькая снизу и равная по сторонам. Значит, тень смещена вниз, а справа или слева ее ширина. По ней мы подбираем радиус (будет примерно пикселя 3 я думаю). подобрав радиус, подбираем прозрачность черного, чтобы с краев тень совпадала по прозрачности с картинкой.
>Ну и напоследок подбираем вертикальное смещение тени, просто на глаз двигая тень вниз.
Вроде получилось: https://jsfiddle.net/fp8o0exq/7/
>>830053
https://github.com/codedokode/pasta/blob/master/html/html.md#Задание-12
>Задача про вкладки
>> В любом случае я сделал и это: https://jsfiddle.net/tb7k9dw9/5/
>А где адаптивность? Если у нас очень узкий экран то табы надо либо выводить в столбик либо выводить в раскрытом виде. Сейчас, если сделать экран узким то подписи табов просто вываливаются из них. Надо это исправить, ширина вкладки должна определяться текстом и вомзожно ограничением на макс/мин ширину.
Исправил: https://jsfiddle.net/tb7k9dw9/6/
> id="first-tab" data-tab="first"
Вот 2 идентификатора это многовато .... нельзя ли оставить только один? желательно бы не-id если это не сложно (если сложно то ладно, что поделать, пусть будет id).
Можно хотя бы подсказку как это сделать?
>Попробуйте
Вы можете обращаться ко мне на 'ты'. Вас называть на 'Вы' я начал в знак уважения вас как учителя.
>>А где адаптивность? Если у нас очень узкий экран то табы надо либо выводить в столбик либо выводить в раскрытом виде. Сейчас, если сделать экран узким то подписи табов просто вываливаются из них. Надо это исправить, ширина вкладки должна определяться текстом и вомзожно ограничением на макс/мин ширину.
>Исправил: https://jsfiddle.net/tb7k9dw9/6/
Исправил правило при котором при сильном сжатии контентная часть становиться меньше вкладок: https://jsfiddle.net/tb7k9dw9/7/
>В роутере содержится копипаста, например:
> $parsedUrl=parse_url($_SERVER['REQUEST_URI']);
> $explodePath=explode('/', $parsedUrl['path']);
> $module=$explodePath[count($explodePath)-1];
Мне сделать для explode('/', $parsedUrl['path']) и $explodePath[count($explodePath)-1] отдельные ф-ии типа explodeUrl($url) и lastPart($url) ? Пока я непойму как избавиться от копипасты так, чтобы в итоге это не занимало больше строк и не было 2 однострочных ф-ий, которые вызываются по 2 раза
> protected $validModules=array('edit','edit_ok','register','register_ok');
> Я бы упростил и просто проверял наличие метода с именем "модуля".
А как проверить наличие модуля в дочернем класе? Что-то method_exists, function_exists и is_callable не работают
Сына, это ты?
>>832455
> копипаста
Ок, я невнимательно посмотрел, там строчки не совсем повтряются (а на вид выглядит как копипаста, что сбивает с толку). Но в любом случае, там в роутере есть 2 более серьезные проблемы:
- функционал роутера и фронтконтроллера не разделен и код размазан между 2 классами
- у роутера нет четко определенных входных параметров, ты по середине кода берешь и лезешь в глобальный массив $_SERVER вместо того чтобы использовать явно переданные аргументы. Никакой необходимости в этом нет.
> А как проверить наличие модуля в дочернем класе? Что-то method_exists, function_exists и is_callable не работают
Должны работать если использовать правильно.
И у тебя названия немного странные - ты метод называешь почему-то "модулем", модулем обычно называют несколько файлов вместе. А метод в контроллере обычно называют "действие" (action).
Я обнаружил интересный баг в Хромиуме. Если открыть страницу в широкой вкладке и сузить ее, то адаптивность работает нормально - табы выстраиваются вертикально. А вот если страницу открыть в узкой вкладке и растянуть ее, то табы так и остаются вертикальными и не выстраиваются горизонтально. Подозреваю, это баг в Хромиуме. В фаерфоксе бага нет. Исправлять не требуется.
Это вот мне не нравится:
> max-width: calc(100% + 2px); /2px - is size of border wrapper/
width это внутренняя ширина элемента, к которой потом еще прибавляются паддинги и бордеры. Если она будет больше 100% то возможно она будет шире окна браузера, что вызовет появление горизонтальной прокрутки. Это явно ошибка какая-то.
И я не понимаю, зачем вообще нужен max-width. Ведь блочный элемент, если у него не заданы width и max-width, по умолчанию растягивается (с учетом бордеров и паддингов) на всю ширину родителя (урок https://github.com/codedokode/pasta/blob/master/html/shrink-to-fit.md ). Значит, тут надо просто вместе с display block поставить для width/max-width значения auto и все. Точнее, только для max-width, так как width нигде не задан.
И еще одно замечание. Текст в блоках с содержимым вкладки примыкает к бордеру. Это некрасиво, создается ощущение что тексту там тесно. Ведь во всех книгах и журналах у текста есть поля справа и слева. Так же должно быть и тут - у тела вкладки должны быть поля, хотя бы 5-10px и у заголовка вкладки тоже должны быть небольшие поля, чтобы буквы не прилипали к краю вплотную. Если присмотреться, поля вокруг текста есть везде - и на кнопках, и в полях ввода.
В остальном, все верно.
Насчет удаления атрибутов с id, я придумал такой вариант:
Можно попробовать для связи табов и вкладок использовать их номера. CSS3 позволяет указать в стилях что-то вроде "N-й по счету элемент типа E" - и соответственно можно попробовать привязать первый инпут и первый label к первому телу вкладки, второй ко второму итд.:
- http://css.yoksel.ru/nth-child/
- https://developer.mozilla.org/ru/docs/Web/CSS/:nth-child
- (и еще одна статья, которая не имеет отношения к вкладкам, но которая показывает что можно сделать из одного дива: https://habrahabr.ru/company/paysto/blog/251933/ )
Важно, что эти селекторы умеют искать либо N-й элемент среди всех детей, либо N-й по счету одинаковый тег, но не могут например искать N-й элемент с определенным классом.
Тогда заголовки и вкладки должны идти строго по порядку (обычно так и есть).
Тогда data-tab нам не нужен и нужен только id. Как от него избавиться, я увы, не знаю. Если положить input внутрь label то не получится использовать селектор ~.
Я пытался придумать еще вариант с использованием псевдокласса :target, но он тоже требует уникальных id и еще хуже чем радиокнопки, так как не поддерживает несколько блоков с вкладками.
Я обнаружил интересный баг в Хромиуме. Если открыть страницу в широкой вкладке и сузить ее, то адаптивность работает нормально - табы выстраиваются вертикально. А вот если страницу открыть в узкой вкладке и растянуть ее, то табы так и остаются вертикальными и не выстраиваются горизонтально. Подозреваю, это баг в Хромиуме. В фаерфоксе бага нет. Исправлять не требуется.
Это вот мне не нравится:
> max-width: calc(100% + 2px); /2px - is size of border wrapper/
width это внутренняя ширина элемента, к которой потом еще прибавляются паддинги и бордеры. Если она будет больше 100% то возможно она будет шире окна браузера, что вызовет появление горизонтальной прокрутки. Это явно ошибка какая-то.
И я не понимаю, зачем вообще нужен max-width. Ведь блочный элемент, если у него не заданы width и max-width, по умолчанию растягивается (с учетом бордеров и паддингов) на всю ширину родителя (урок https://github.com/codedokode/pasta/blob/master/html/shrink-to-fit.md ). Значит, тут надо просто вместе с display block поставить для width/max-width значения auto и все. Точнее, только для max-width, так как width нигде не задан.
И еще одно замечание. Текст в блоках с содержимым вкладки примыкает к бордеру. Это некрасиво, создается ощущение что тексту там тесно. Ведь во всех книгах и журналах у текста есть поля справа и слева. Так же должно быть и тут - у тела вкладки должны быть поля, хотя бы 5-10px и у заголовка вкладки тоже должны быть небольшие поля, чтобы буквы не прилипали к краю вплотную. Если присмотреться, поля вокруг текста есть везде - и на кнопках, и в полях ввода.
В остальном, все верно.
Насчет удаления атрибутов с id, я придумал такой вариант:
Можно попробовать для связи табов и вкладок использовать их номера. CSS3 позволяет указать в стилях что-то вроде "N-й по счету элемент типа E" - и соответственно можно попробовать привязать первый инпут и первый label к первому телу вкладки, второй ко второму итд.:
- http://css.yoksel.ru/nth-child/
- https://developer.mozilla.org/ru/docs/Web/CSS/:nth-child
- (и еще одна статья, которая не имеет отношения к вкладкам, но которая показывает что можно сделать из одного дива: https://habrahabr.ru/company/paysto/blog/251933/ )
Важно, что эти селекторы умеют искать либо N-й элемент среди всех детей, либо N-й по счету одинаковый тег, но не могут например искать N-й элемент с определенным классом.
Тогда заголовки и вкладки должны идти строго по порядку (обычно так и есть).
Тогда data-tab нам не нужен и нужен только id. Как от него избавиться, я увы, не знаю. Если положить input внутрь label то не получится использовать селектор ~.
Я пытался придумать еще вариант с использованием псевдокласса :target, но он тоже требует уникальных id и еще хуже чем радиокнопки, так как не поддерживает несколько блоков с вкладками.
> А как переопределить это правило только для новых браузеров? Селекторы, которые я использую для фикса старых браузеров, да и вообще все селекторы, как раз начинают работать с 7-8 версии IE и с первых версий андройда.
Я имел в виду что можно написать например так:
.content {
width: 100%; / старые браузеры второе правило проигнорируют и возьмут первое /
width: calc(...); / новые прочитают оба правила, но возьмут второе /
}
> Пусть пока будет так:https://jsfiddle.net/0u3x5rsw/3/
> <div class="wrapper">
Враппер не нужен - минимальную ширину можно задать на элементе html или body.
Также, если присмотреться, левая граница меню не совпадает с левой границей заголовка - меню сдвинуто на 5-10px вправо, некрасиво.
В остальном, все верно.
> А у меня получилось без внутреннего блока сделать, и, причем, у меня ничего не пересекается и не проваливается: https://jsfiddle.net/xx82knpf/
О, вот это правильный подход, наверно так и надо сделать, единственное, не надо указывать контенту ширину 100%, так как он из-за этого уезжает за край экрана. Не надо ему указывать ширину так как блоки по умолчанию сами растягиваются на ширину родителя.
>>> margin-right: -100%;
> Без этого свойства при очень сильном сжатии бокс провалиться под левую колонку.
Ну да, а если указать, то при очень сильном сжатии блоки наедут друг на друга и текст будет не прочитать. Лучше пусть проваливается. Вообще, проблема очень маленькой ширины решается указанием на html разумного min-width. И я не считаю это проблемой, так как для маленькой ширины обычно делают адаптивную версию, где все блоки идут вертикально. То есть margin можно указывать, можно не указывать, получается разницы нет, если у нас будет адаптивная версия.
> Задание 7
> Исправил: https://jsfiddle.net/5g31m30j/4/
Теперь верно.
> Почему у одинаковых элементов разные свойства? Где можно узнать о свойстве каждого?
В стандарте CSS написано что элементы форм не обязаны подчиняться стандарту CSS и браузеры могут их выводить как хотят. Я однажды просто сделал страницу с разными элементами форм, открыл ее в разных браузерах и померял. У всех браузеров эти паддинги, бордеры и особенности отображения примерно одинаковые. Например у инпута обычно везде паддинг 1px и бордер 2px. У кнопок и селектов width обозначает не внутреннюю, а наружную ширину. Если не задавать фон и бордер то элемент выводится как принято в операционной системе, а если указать - то как задано в CSS.
Я подозреваю, что это поведение скопировано с каких-то древних браузеров, чтобы не ломать старые сайты. То есть оно не задано в стандарте, но все равно браузеры используют примерно одинаковые стили по умолчанию.
В браузерах есть так называемый встроенный CSS, задающий вид элементов по умолчанию (в том числе элементов форм). Его можно найти в исходном коде браузера. Вот вопрос на эту тему: http://stackoverflow.com/questions/6867254/browsers-default-css-for-html-elements/6867287#6867287
И там же есть ссылки:
- для фаерфокса https://dxr.mozilla.org/mozilla-central/source/layout/style/res/html.css
- для хрома https://chromium.googlesource.com/chromium/blink/+/master/Source/core/css/html.css
Советую посмотреть по диагонали. Учить наизусть не надо, но стоит понимать, что в браузере есть какие-то дефолтные отступы, поля итд. Эти стили копируют то, как отображали теги древние браузеры, еще до появления CSS.
Вот к примеру стиль:
> table[align="left"] {
> float: left;
> }
До появления CSS таблицу можно было зафлоатить влево атрибутом <table align="left">, а сейчас этот атрибут поддерживается через встроенный CSS.
А в стилях Хрома можно увидеть:
> .... input[type="submit" i], ... button {
> box-sizing: border-box
Задача про Короля Лир
> Исправил: https://jsfiddle.net/tsuh4gjw/8/
Что-то ничего не исправилось. Заголовок по прежнему вырван влево. Тут надо просто поставить на body поля слева и все.
>>Задача про верстку форума
>>Не критично. Но я считаю, что тег content не требуется. Можно сверстать без него.
> А можно подсказку как?
Просто в блоке сделать поля слева (паддинг) размером под картинку, тогда все содержимое окажется сдвинуто вправо и не надо будет заворачивать его в обертку.
>Задача про радиокнопки
Теперь все верно.
> Неисчезающие инпуты
> До сих пор не понял в чём смысл: https://jsfiddle.net/gpysbfar/4/
> Контент находиться за пределами лейбла, но не скрывается.
О, еще одна хорошая головоломка, но я нашел ответ. label по умолчанию имеет display: inline, а как известно, у inline-элементов нет собственных размеров - их размер и форма совпадает с содержимым. Потому инлайн-элемент не имеет форму прямоугольника, а может например растягиваться на несколько строк в вслед за содержащимся в нем текстом. Возможно потому на нем не работает overflow.
Если дать label display: block или inlne-block, все сразу же начинает работать.
Кстати в выражении left: -50% проценты тоже считаются не от родителя-label (у которого нет собственных размеров), а от ширины ближайшего блочного элемента.
Если посмотреть стандарт: https://www.w3.org/TR/CSS22/visufx.html#overflow то там написано про overflow:
> Applies to: block containers and boxes that establish a formatting context
> Применяется к: блокам-контейнерам (?) и боксам, задающим контекст форматирования
Как я понимаю, это значит что к inline элементам overflow применять нельзя. Ну и это смысла не имеет так как у них собственной формы и границ нет.
задача про радиокнопки
> Вроде получилось: https://jsfiddle.net/fp8o0exq/7/
тут есть проблема: если двигать по кнопкам синюю рамку, то ширина кнопки при появлении рамки меняется и правая кнопка сдвигается на 1-2 пикслея вправо. Это некрасиво. Надо либо компенсировать лишний пиксель в бордере отрицательным маргином, либо сделать у всех кнопок border 1px и отрицательный маргин, чтобы они слегка наезжали друг на друга.
Такие проблемы, кстати, надо замечать. Если кликать по левой и средней кнопке, и смотреть на правую, видно как она двигается.
Тень вроде выглядит похоже. Единственная проблема - если кнопка вжата, на ней есть тень, и на ней кликнуть, то тень пропадает, пока на кнопке фокус. Видимо потому, что тень переиспользуется для рамки. но у элемента может быть несколько теней - надо просто грамотно прописать правила. Или же можно попробовать сделать рамку с помощью свойства outline: http://htmlbook.ru/css/outline
> А как переопределить это правило только для новых браузеров? Селекторы, которые я использую для фикса старых браузеров, да и вообще все селекторы, как раз начинают работать с 7-8 версии IE и с первых версий андройда.
Я имел в виду что можно написать например так:
.content {
width: 100%; / старые браузеры второе правило проигнорируют и возьмут первое /
width: calc(...); / новые прочитают оба правила, но возьмут второе /
}
> Пусть пока будет так:https://jsfiddle.net/0u3x5rsw/3/
> <div class="wrapper">
Враппер не нужен - минимальную ширину можно задать на элементе html или body.
Также, если присмотреться, левая граница меню не совпадает с левой границей заголовка - меню сдвинуто на 5-10px вправо, некрасиво.
В остальном, все верно.
> А у меня получилось без внутреннего блока сделать, и, причем, у меня ничего не пересекается и не проваливается: https://jsfiddle.net/xx82knpf/
О, вот это правильный подход, наверно так и надо сделать, единственное, не надо указывать контенту ширину 100%, так как он из-за этого уезжает за край экрана. Не надо ему указывать ширину так как блоки по умолчанию сами растягиваются на ширину родителя.
>>> margin-right: -100%;
> Без этого свойства при очень сильном сжатии бокс провалиться под левую колонку.
Ну да, а если указать, то при очень сильном сжатии блоки наедут друг на друга и текст будет не прочитать. Лучше пусть проваливается. Вообще, проблема очень маленькой ширины решается указанием на html разумного min-width. И я не считаю это проблемой, так как для маленькой ширины обычно делают адаптивную версию, где все блоки идут вертикально. То есть margin можно указывать, можно не указывать, получается разницы нет, если у нас будет адаптивная версия.
> Задание 7
> Исправил: https://jsfiddle.net/5g31m30j/4/
Теперь верно.
> Почему у одинаковых элементов разные свойства? Где можно узнать о свойстве каждого?
В стандарте CSS написано что элементы форм не обязаны подчиняться стандарту CSS и браузеры могут их выводить как хотят. Я однажды просто сделал страницу с разными элементами форм, открыл ее в разных браузерах и померял. У всех браузеров эти паддинги, бордеры и особенности отображения примерно одинаковые. Например у инпута обычно везде паддинг 1px и бордер 2px. У кнопок и селектов width обозначает не внутреннюю, а наружную ширину. Если не задавать фон и бордер то элемент выводится как принято в операционной системе, а если указать - то как задано в CSS.
Я подозреваю, что это поведение скопировано с каких-то древних браузеров, чтобы не ломать старые сайты. То есть оно не задано в стандарте, но все равно браузеры используют примерно одинаковые стили по умолчанию.
В браузерах есть так называемый встроенный CSS, задающий вид элементов по умолчанию (в том числе элементов форм). Его можно найти в исходном коде браузера. Вот вопрос на эту тему: http://stackoverflow.com/questions/6867254/browsers-default-css-for-html-elements/6867287#6867287
И там же есть ссылки:
- для фаерфокса https://dxr.mozilla.org/mozilla-central/source/layout/style/res/html.css
- для хрома https://chromium.googlesource.com/chromium/blink/+/master/Source/core/css/html.css
Советую посмотреть по диагонали. Учить наизусть не надо, но стоит понимать, что в браузере есть какие-то дефолтные отступы, поля итд. Эти стили копируют то, как отображали теги древние браузеры, еще до появления CSS.
Вот к примеру стиль:
> table[align="left"] {
> float: left;
> }
До появления CSS таблицу можно было зафлоатить влево атрибутом <table align="left">, а сейчас этот атрибут поддерживается через встроенный CSS.
А в стилях Хрома можно увидеть:
> .... input[type="submit" i], ... button {
> box-sizing: border-box
Задача про Короля Лир
> Исправил: https://jsfiddle.net/tsuh4gjw/8/
Что-то ничего не исправилось. Заголовок по прежнему вырван влево. Тут надо просто поставить на body поля слева и все.
>>Задача про верстку форума
>>Не критично. Но я считаю, что тег content не требуется. Можно сверстать без него.
> А можно подсказку как?
Просто в блоке сделать поля слева (паддинг) размером под картинку, тогда все содержимое окажется сдвинуто вправо и не надо будет заворачивать его в обертку.
>Задача про радиокнопки
Теперь все верно.
> Неисчезающие инпуты
> До сих пор не понял в чём смысл: https://jsfiddle.net/gpysbfar/4/
> Контент находиться за пределами лейбла, но не скрывается.
О, еще одна хорошая головоломка, но я нашел ответ. label по умолчанию имеет display: inline, а как известно, у inline-элементов нет собственных размеров - их размер и форма совпадает с содержимым. Потому инлайн-элемент не имеет форму прямоугольника, а может например растягиваться на несколько строк в вслед за содержащимся в нем текстом. Возможно потому на нем не работает overflow.
Если дать label display: block или inlne-block, все сразу же начинает работать.
Кстати в выражении left: -50% проценты тоже считаются не от родителя-label (у которого нет собственных размеров), а от ширины ближайшего блочного элемента.
Если посмотреть стандарт: https://www.w3.org/TR/CSS22/visufx.html#overflow то там написано про overflow:
> Applies to: block containers and boxes that establish a formatting context
> Применяется к: блокам-контейнерам (?) и боксам, задающим контекст форматирования
Как я понимаю, это значит что к inline элементам overflow применять нельзя. Ну и это смысла не имеет так как у них собственной формы и границ нет.
задача про радиокнопки
> Вроде получилось: https://jsfiddle.net/fp8o0exq/7/
тут есть проблема: если двигать по кнопкам синюю рамку, то ширина кнопки при появлении рамки меняется и правая кнопка сдвигается на 1-2 пикслея вправо. Это некрасиво. Надо либо компенсировать лишний пиксель в бордере отрицательным маргином, либо сделать у всех кнопок border 1px и отрицательный маргин, чтобы они слегка наезжали друг на друга.
Такие проблемы, кстати, надо замечать. Если кликать по левой и средней кнопке, и смотреть на правую, видно как она двигается.
Тень вроде выглядит похоже. Единственная проблема - если кнопка вжата, на ней есть тень, и на ней кликнуть, то тень пропадает, пока на кнопке фокус. Видимо потому, что тень переиспользуется для рамки. но у элемента может быть несколько теней - надо просто грамотно прописать правила. Или же можно попробовать сделать рамку с помощью свойства outline: http://htmlbook.ru/css/outline
>И я не понимаю, зачем вообще нужен max-width. Ведь блочный элемент, если у него не заданы width и max-width, по умолчанию растягивается (с учетом бордеров и паддингов) на всю ширину родителя (урок https://github.com/codedokode/pasta/blob/master/html/shrink-to-fit.md ). Значит, тут надо просто вместе с display block поставить для width/max-width значения auto и все. Точнее, только для max-width, так как width нигде не задан.
>И я не понимаю, зачем вообще нужен max-width.
Чтобы вкладки с большим названием не растягивались на всё занимаемое им пространство.
Почему-то свойство max-width не переопределяться и вкладки сжимаются до 200px: https://jsfiddle.net/obdgvxfk/ . Если его не использовать то всё работает отлично https://jsfiddle.net/obdgvxfk/1/ .
>И еще одно замечание. Текст в блоках с содержимым вкладки примыкает к бордеру. Это некрасиво, создается ощущение что тексту там тесно. Ведь во всех книгах и журналах у текста есть поля справа и слева. Так же должно быть и тут - у тела вкладки должны быть поля, хотя бы 5-10px и у заголовка вкладки тоже должны быть небольшие поля, чтобы буквы не прилипали к краю вплотную. Если присмотреться, поля вокруг текста есть везде - и на кнопках, и в полях ввода.
Добавил поля: https://jsfiddle.net/tb7k9dw9/8/
>Насчет удаления атрибутов с id, я придумал такой вариант:
>Можно попробовать для связи табов и вкладок использовать их номера. CSS3 позволяет указать в стилях что-то вроде "N-й по счету элемент типа E" - и соответственно можно попробовать привязать первый инпут и первый label к первому телу вкладки, второй ко второму итд.:
Сделал: https://jsfiddle.net/1ax6k6hw/
>Тогда data-tab нам не нужен и нужен только id. Как от него избавиться, я увы, не знаю. Если положить input внутрь label то не получится использовать селектор ~.
Я тоже об этом говорю. Такой способ хорош только в случаях если мы в ручную делаем шаблон, а не генерируем его динамически.
>>833459
>Я имел в виду что можно написать например так:
>
>.content {
>width: 100%; / старые браузеры второе правило проигнорируют и возьмут первое /
>width: calc(...); / новые прочитают оба правила, но возьмут второе /
>}
Ах да, я забыл что свойства выполняются в приоритете.
>.content {
>width: 100%; / старые браузеры второе правило проигнорируют и возьмут первое /
>width: calc(...); / новые прочитают оба правила, но возьмут второе /
>}
>
>> Пусть пока будет так:https://jsfiddle.net/0u3x5rsw/3/
>> <div class="wrapper">
>Враппер не нужен - минимальную ширину можно задать на элементе html или body.
>Также, если присмотреться, левая граница меню не совпадает с левой границей заголовка - меню сдвинуто на 5-10px вправо, некрасиво.
Исправил: https://jsfiddle.net/0u3x5rsw/6/ https://jsfiddle.net/xx82knpf/2/
>>833459
>Задача про Короля Лир
>
>> Исправил: https://jsfiddle.net/tsuh4gjw/8/
>Что-то ничего не исправилось. Заголовок по прежнему вырван влево. Тут надо просто поставить на body поля слева и все.
Исправил: https://jsfiddle.net/tsuh4gjw/9/
>>833459
>> Неисчезающие инпуты
>> До сих пор не понял в чём смысл: https://jsfiddle.net/gpysbfar/4/
>> Контент находиться за пределами лейбла, но не скрывается.
>О, еще одна хорошая головоломка, но я нашел ответ. label по умолчанию имеет display: inline, а как известно, у inline-элементов нет собственных размеров - их размер и форма совпадает с содержимым. Потому инлайн-элемент не имеет форму прямоугольника, а может например растягиваться на несколько строк в вслед за содержащимся в нем текстом.
А почему лейбел не растягивается на ширину сместившихся влево инпута?
>> Applies to: block containers and boxes that establish a formatting context
>> Применяется к: блокам-контейнерам (?) и боксам, задающим контекст форматирования
Если что, я умею читать английский.
>>830052
>Задача про радиокнопки
>> .inputbox > input {
>> position: absolute;
>> left: -10000px;
>Вот у этого метода конечно есть подвох - что если завтра кто-то поставит наш элемент на гигантскую страницу которая шире этих 10 000 px? Может лучше сделать родителя c overflow: hidden и тогда не придется так далеко загонять? Или все же не стоит? Я в принципе не настаиваю.
Исправил: https://jsfiddle.net/fp8o0exq/6/
>>833459
>> Вроде получилось: https://jsfiddle.net/fp8o0exq/7/
>тут есть проблема: если двигать по кнопкам синюю рамку, то ширина кнопки при появлении рамки меняется и правая кнопка сдвигается на 1-2 пикслея вправо. Это некрасиво. Надо либо компенсировать лишний пиксель в бордере отрицательным маргином, либо сделать у всех кнопок border 1px и отрицательный маргин, чтобы они слегка наезжали друг на друга.
Исправлено: https://jsfiddle.net/fp8o0exq/9/
>>833459
>Тень вроде выглядит похоже. Единственная проблема - если кнопка вжата, на ней есть тень, и на ней кликнуть, то тень пропадает, пока на кнопке фокус. Видимо потому, что тень переиспользуется для рамки. но у элемента может быть несколько теней - надо просто грамотно прописать правила.
Я тоже увидел это, но не уделил этому нужного внимания. Исправил: https://jsfiddle.net/fp8o0exq/8/
Еще я подумал, что можно было задать несколько теней с помощью box-sizing, но у них тогда бы был общий радиус теней https://jsfiddle.net/L69xmtwh/
>Или же можно попробовать сделать рамку с помощью свойства outline: http://htmlbook.ru/css/outline
Но ему же нельзя задать смещение по оси или размытие, или радиус углов если мы хотим использовать его за место бордера.
>И я не понимаю, зачем вообще нужен max-width. Ведь блочный элемент, если у него не заданы width и max-width, по умолчанию растягивается (с учетом бордеров и паддингов) на всю ширину родителя (урок https://github.com/codedokode/pasta/blob/master/html/shrink-to-fit.md ). Значит, тут надо просто вместе с display block поставить для width/max-width значения auto и все. Точнее, только для max-width, так как width нигде не задан.
>И я не понимаю, зачем вообще нужен max-width.
Чтобы вкладки с большим названием не растягивались на всё занимаемое им пространство.
Почему-то свойство max-width не переопределяться и вкладки сжимаются до 200px: https://jsfiddle.net/obdgvxfk/ . Если его не использовать то всё работает отлично https://jsfiddle.net/obdgvxfk/1/ .
>И еще одно замечание. Текст в блоках с содержимым вкладки примыкает к бордеру. Это некрасиво, создается ощущение что тексту там тесно. Ведь во всех книгах и журналах у текста есть поля справа и слева. Так же должно быть и тут - у тела вкладки должны быть поля, хотя бы 5-10px и у заголовка вкладки тоже должны быть небольшие поля, чтобы буквы не прилипали к краю вплотную. Если присмотреться, поля вокруг текста есть везде - и на кнопках, и в полях ввода.
Добавил поля: https://jsfiddle.net/tb7k9dw9/8/
>Насчет удаления атрибутов с id, я придумал такой вариант:
>Можно попробовать для связи табов и вкладок использовать их номера. CSS3 позволяет указать в стилях что-то вроде "N-й по счету элемент типа E" - и соответственно можно попробовать привязать первый инпут и первый label к первому телу вкладки, второй ко второму итд.:
Сделал: https://jsfiddle.net/1ax6k6hw/
>Тогда data-tab нам не нужен и нужен только id. Как от него избавиться, я увы, не знаю. Если положить input внутрь label то не получится использовать селектор ~.
Я тоже об этом говорю. Такой способ хорош только в случаях если мы в ручную делаем шаблон, а не генерируем его динамически.
>>833459
>Я имел в виду что можно написать например так:
>
>.content {
>width: 100%; / старые браузеры второе правило проигнорируют и возьмут первое /
>width: calc(...); / новые прочитают оба правила, но возьмут второе /
>}
Ах да, я забыл что свойства выполняются в приоритете.
>.content {
>width: 100%; / старые браузеры второе правило проигнорируют и возьмут первое /
>width: calc(...); / новые прочитают оба правила, но возьмут второе /
>}
>
>> Пусть пока будет так:https://jsfiddle.net/0u3x5rsw/3/
>> <div class="wrapper">
>Враппер не нужен - минимальную ширину можно задать на элементе html или body.
>Также, если присмотреться, левая граница меню не совпадает с левой границей заголовка - меню сдвинуто на 5-10px вправо, некрасиво.
Исправил: https://jsfiddle.net/0u3x5rsw/6/ https://jsfiddle.net/xx82knpf/2/
>>833459
>Задача про Короля Лир
>
>> Исправил: https://jsfiddle.net/tsuh4gjw/8/
>Что-то ничего не исправилось. Заголовок по прежнему вырван влево. Тут надо просто поставить на body поля слева и все.
Исправил: https://jsfiddle.net/tsuh4gjw/9/
>>833459
>> Неисчезающие инпуты
>> До сих пор не понял в чём смысл: https://jsfiddle.net/gpysbfar/4/
>> Контент находиться за пределами лейбла, но не скрывается.
>О, еще одна хорошая головоломка, но я нашел ответ. label по умолчанию имеет display: inline, а как известно, у inline-элементов нет собственных размеров - их размер и форма совпадает с содержимым. Потому инлайн-элемент не имеет форму прямоугольника, а может например растягиваться на несколько строк в вслед за содержащимся в нем текстом.
А почему лейбел не растягивается на ширину сместившихся влево инпута?
>> Applies to: block containers and boxes that establish a formatting context
>> Применяется к: блокам-контейнерам (?) и боксам, задающим контекст форматирования
Если что, я умею читать английский.
>>830052
>Задача про радиокнопки
>> .inputbox > input {
>> position: absolute;
>> left: -10000px;
>Вот у этого метода конечно есть подвох - что если завтра кто-то поставит наш элемент на гигантскую страницу которая шире этих 10 000 px? Может лучше сделать родителя c overflow: hidden и тогда не придется так далеко загонять? Или все же не стоит? Я в принципе не настаиваю.
Исправил: https://jsfiddle.net/fp8o0exq/6/
>>833459
>> Вроде получилось: https://jsfiddle.net/fp8o0exq/7/
>тут есть проблема: если двигать по кнопкам синюю рамку, то ширина кнопки при появлении рамки меняется и правая кнопка сдвигается на 1-2 пикслея вправо. Это некрасиво. Надо либо компенсировать лишний пиксель в бордере отрицательным маргином, либо сделать у всех кнопок border 1px и отрицательный маргин, чтобы они слегка наезжали друг на друга.
Исправлено: https://jsfiddle.net/fp8o0exq/9/
>>833459
>Тень вроде выглядит похоже. Единственная проблема - если кнопка вжата, на ней есть тень, и на ней кликнуть, то тень пропадает, пока на кнопке фокус. Видимо потому, что тень переиспользуется для рамки. но у элемента может быть несколько теней - надо просто грамотно прописать правила.
Я тоже увидел это, но не уделил этому нужного внимания. Исправил: https://jsfiddle.net/fp8o0exq/8/
Еще я подумал, что можно было задать несколько теней с помощью box-sizing, но у них тогда бы был общий радиус теней https://jsfiddle.net/L69xmtwh/
>Или же можно попробовать сделать рамку с помощью свойства outline: http://htmlbook.ru/css/outline
Но ему же нельзя задать смещение по оси или размытие, или радиус углов если мы хотим использовать его за место бордера.
>>813627
не знаю, может АПИ поменялось? Надо разбираться, читать документацию, так не сказать.
>>813630
В общем, верно, хотя правильнее было бы написать не if ($balance > 1000000), а "больше или равно".
>>813681
А что именно непонятно? Там надо сделать цикл, и сравнивать буквы с конца и с начала попарно:
первую буква с начала - с первой с конца
вторую с начала - со второй с конца
...
И если хоть одна не совпала, то слово не палиндром.
Ответ неправильный. Получается около 61270. Ты забыл прибавить в последнем месяце процент и комиссию.
Попробуй переписать код внутри цикла примерно так:
- прибавляем проценты и комиссию к остатку долга (!не вычитаем ничего пока!)
- если остаток маленький, выплачиваем сколько осталось и уходим
- иначе платим 5000
«Платим» здесь значит уменьшаем долг и увеличиваем общую сумму выплаченного.
>>814990
Да, если например он используется только как базовый класс для наследования. Обычно в абстрактные методы выносят то, чего нет в базовом классе и что надо обязательно реализровать в наследнике.
У тебя на самом деле есть абстрактные методы, просто ты их не видишь. Сейчас у тебя при наследовании надо переопределить поля с зарплатой, кофе итд. Но где гарантия что тот, кто наследует класс, не забудет это сделать? Надо заменить эти поля на абстрактные методы и тогда забыть их переопределить будет невозможно.
Ну и названия надо бы выбирать более соответствующие, а то код нелегко понять будет.
>>815468
Молодец, верно.
>>815525
Права 0700 значат что только владелец файла имеет к нему доступ, а другие - нет. Но веб-сервер обычно и есть "другой" и надо разрешить ему читать файл.
Почитай про права в линуксе.
>>815732
Верно.
>>815603
Придется почитать документацию. Также надо бы почитать нашу инструкцию по командной строке из ОП поста.
>>815731
Погугли
Вот например аж в 2003 году его обсуждают http://xpoint.ru/forums/programming/PHP/thread/19487.xhtml
>>815935
Не знаю
>>816242
Не знаю
Ответ неправильный. Получается около 61270. Ты забыл прибавить в последнем месяце процент и комиссию.
Попробуй переписать код внутри цикла примерно так:
- прибавляем проценты и комиссию к остатку долга (!не вычитаем ничего пока!)
- если остаток маленький, выплачиваем сколько осталось и уходим
- иначе платим 5000
«Платим» здесь значит уменьшаем долг и увеличиваем общую сумму выплаченного.
>>814990
Да, если например он используется только как базовый класс для наследования. Обычно в абстрактные методы выносят то, чего нет в базовом классе и что надо обязательно реализровать в наследнике.
У тебя на самом деле есть абстрактные методы, просто ты их не видишь. Сейчас у тебя при наследовании надо переопределить поля с зарплатой, кофе итд. Но где гарантия что тот, кто наследует класс, не забудет это сделать? Надо заменить эти поля на абстрактные методы и тогда забыть их переопределить будет невозможно.
Ну и названия надо бы выбирать более соответствующие, а то код нелегко понять будет.
>>815468
Молодец, верно.
>>815525
Права 0700 значат что только владелец файла имеет к нему доступ, а другие - нет. Но веб-сервер обычно и есть "другой" и надо разрешить ему читать файл.
Почитай про права в линуксе.
>>815732
Верно.
>>815603
Придется почитать документацию. Также надо бы почитать нашу инструкцию по командной строке из ОП поста.
>>815731
Погугли
Вот например аж в 2003 году его обсуждают http://xpoint.ru/forums/programming/PHP/thread/19487.xhtml
>>815935
Не знаю
>>816242
Не знаю
Slim наверно упростит. Для работы с БД можно также попробовать взять доктрину, но не знаю что там со скоростью будет, надо мерять.
>>817000
Трудно сказать. Для начала включи отображение ошибок или изучи логи PHP, проверяй результат каждого обращения к mysqli.
>>816942
Через IN.
>>817137
По моему все результаты из БД возвращаются как строка. Нужно число - используй intval/floatval.
>>818469
Выглядит верно
>>819183
Мне больше нравится intval(), но вообще без разницы.
> так и не понял куда protected нужно лепить.
Когда надо разрешить наследникам класса доступ.
Название класса Creep неудачное и сбивает с толку.
Также, есть ошибка: базовый класс не должен ничего знать о наследниках. И потому он не может обращаться к полям вроде $this->salary которых в нем нет.
Также, базовую ставку, потребление кофе лучше было сделать абстрактными методами, чтобы было очевидно что их надо переопределить.
> //массив с работниками записанный строками
> protected $textArray = array();
Это лишнее в классе департамента. Это не его задача - создавать новых работников. Лучше сделать чтобы он просто позволял добавлять объекты-работников, а создавать их где-то отдельно.
Список полей в классе должен идти до конструктора, а не вперемешку с методами.
> //Забиваем массив с работниками массивами с работниками одного вида и типа
> $this->listOfCreeps[] = array_fill(0, intval($numberOfCreeps), $worker);
Это не создает N копий-работников, а копирует ссылку на один и тот же объект N раз. И если ты например поменяешь зарплату одному такому "работнику", она изменится у всех так как это ссылки на один и тот же объект. Перечитай урок по ООП, про копирование и клонирование объектов.
Новые объекты создаются только через new или clone. Во всех остальных случаях создается просто новая ссылка на существующий объект.
Вместо разбора строк через mb_substr гораздо удобнее сделать это через preg_match.
В switch надо добавить default.
Аникризисные меры логичнее вынести в отдельный класс, а не лепить в департамент. А то можно нарушить принцип, что каждый класс должен выполнять свою задачу. Задача департамента - хранить список работников.
Антикризисные методы у тебя написаны в виде большой стены кода. Подумай, как разбить их на отдельные методы, каждый из которых делает какую-то одну задачу. Ну наример:
- отбор кандидатов по критерию
- сортировка (чтобы первыми шли работники определенного ранга)
- взятие определенного процента
- увольнение
> //Меняем базовую ставку и потребление кофе
> Analyst::setSalary(1100);
Это меняет голобально зарплату всех аналитиков во всех фирмах. Надо бы менять только в данной.
Также, ты используешь ::, то есть статический вызов. Так можно вызывать только статические методы, а не обычные. И в статических методах нет $this. У тебя фактически в качестве $this передается департамент и строчка $this->salary = $num; добавляет не в работнике, а в департаменте свойство salary. То есть абсолютно неправильно.
> if(!$creep instanceof Analyst && $creep->getBossAligment() == 1){
> $this->listOfCreeps[] = array_fill(0, 1, new Analyst(3, 1))
надо не создавать нового аналитика, а брать уже работающего.
> class Procurement extends Department
Этот департамент ничем кроме названия не отличается, тут можно и без наследования обойтись.
В конце вместо того, чтобы каждый раз создавать новую компанию, лучше создать ее 1 раз и сделать несколько копий.
> так и не понял куда protected нужно лепить.
Когда надо разрешить наследникам класса доступ.
Название класса Creep неудачное и сбивает с толку.
Также, есть ошибка: базовый класс не должен ничего знать о наследниках. И потому он не может обращаться к полям вроде $this->salary которых в нем нет.
Также, базовую ставку, потребление кофе лучше было сделать абстрактными методами, чтобы было очевидно что их надо переопределить.
> //массив с работниками записанный строками
> protected $textArray = array();
Это лишнее в классе департамента. Это не его задача - создавать новых работников. Лучше сделать чтобы он просто позволял добавлять объекты-работников, а создавать их где-то отдельно.
Список полей в классе должен идти до конструктора, а не вперемешку с методами.
> //Забиваем массив с работниками массивами с работниками одного вида и типа
> $this->listOfCreeps[] = array_fill(0, intval($numberOfCreeps), $worker);
Это не создает N копий-работников, а копирует ссылку на один и тот же объект N раз. И если ты например поменяешь зарплату одному такому "работнику", она изменится у всех так как это ссылки на один и тот же объект. Перечитай урок по ООП, про копирование и клонирование объектов.
Новые объекты создаются только через new или clone. Во всех остальных случаях создается просто новая ссылка на существующий объект.
Вместо разбора строк через mb_substr гораздо удобнее сделать это через preg_match.
В switch надо добавить default.
Аникризисные меры логичнее вынести в отдельный класс, а не лепить в департамент. А то можно нарушить принцип, что каждый класс должен выполнять свою задачу. Задача департамента - хранить список работников.
Антикризисные методы у тебя написаны в виде большой стены кода. Подумай, как разбить их на отдельные методы, каждый из которых делает какую-то одну задачу. Ну наример:
- отбор кандидатов по критерию
- сортировка (чтобы первыми шли работники определенного ранга)
- взятие определенного процента
- увольнение
> //Меняем базовую ставку и потребление кофе
> Analyst::setSalary(1100);
Это меняет голобально зарплату всех аналитиков во всех фирмах. Надо бы менять только в данной.
Также, ты используешь ::, то есть статический вызов. Так можно вызывать только статические методы, а не обычные. И в статических методах нет $this. У тебя фактически в качестве $this передается департамент и строчка $this->salary = $num; добавляет не в работнике, а в департаменте свойство salary. То есть абсолютно неправильно.
> if(!$creep instanceof Analyst && $creep->getBossAligment() == 1){
> $this->listOfCreeps[] = array_fill(0, 1, new Analyst(3, 1))
надо не создавать нового аналитика, а брать уже работающего.
> class Procurement extends Department
Этот департамент ничем кроме названия не отличается, тут можно и без наследования обойтись.
В конце вместо того, чтобы каждый раз создавать новую компанию, лучше создать ее 1 раз и сделать несколько копий.
Ты можешь сначала сохранить загруженные фото, добавить их как новые, удалить старые из таблицы, удалить старые с диска. Тогда при ошибке ничего не потерятся. Если операции с БД завернуть в транзакцию то тогда вообще либо операция выполнится целиком либо не выполнится и останутся старые фото.
Надо выбирать наиболее безопасный порядок действий.
>>820218
Волков бояться - в лес не ходить.
>>820232
Даже если использовать сессии, зачем их менять при логине? И зачем их выдавать неавторизованным пользователям? Чем больше ты хранишь в сессии тем ты дальше от принципа REST и тем больше потенциальных проблем себе создаешь.
>>820253
Неплохо, хотя если посмотреть, обе ветки ифа довольно похожи и их можно было бы объединить.
>>820453
Попробуй переписать код внутри цикла примерно так:
- прибавляем проценты и комиссию к остатку долга (!не вычитаем ничего пока!)
- если остаток маленький, выплачиваем сколько осталось и уходим
- иначе платим 5000
«Платим» здесь значит уменьшаем долг и увеличиваем общую сумму выплаченного.
Ты можешь сначала сохранить загруженные фото, добавить их как новые, удалить старые из таблицы, удалить старые с диска. Тогда при ошибке ничего не потерятся. Если операции с БД завернуть в транзакцию то тогда вообще либо операция выполнится целиком либо не выполнится и останутся старые фото.
Надо выбирать наиболее безопасный порядок действий.
>>820218
Волков бояться - в лес не ходить.
>>820232
Даже если использовать сессии, зачем их менять при логине? И зачем их выдавать неавторизованным пользователям? Чем больше ты хранишь в сессии тем ты дальше от принципа REST и тем больше потенциальных проблем себе создаешь.
>>820253
Неплохо, хотя если посмотреть, обе ветки ифа довольно похожи и их можно было бы объединить.
>>820453
Попробуй переписать код внутри цикла примерно так:
- прибавляем проценты и комиссию к остатку долга (!не вычитаем ничего пока!)
- если остаток маленький, выплачиваем сколько осталось и уходим
- иначе платим 5000
«Платим» здесь значит уменьшаем долг и увеличиваем общую сумму выплаченного.
> $text = str_replace("[]", "", $text);
Интересно, а это-то зачем? Так, решено верно.
>>820849
Сразу посоветую получение пути к файлу вынести в отдельный метод.
Также, если ты выдаешь заголовок location, то непонятно зачем рендерить download.html, так как пользователь эту страницу скорее всего не увидит.
Также, заголовок content-dispoistion должен отдаваться не со страницей, а вместе с файлом. У тебя же (если убрать location) он приведет к тому что браузер сохранит саму HTML страницу.
> Хочу: ф-ия возвращает не проходной и ненужный download.html, а сразу файл, в http Header которого будет прописан 'Content-Disposition':'attachment' И который будет загружаться.
> Как это можно реализовать?
Ну самый простой способ это прочитать file_get_contents файл в переменную и вывести через усрщ (после заголовков). Но это требует загрузить файл целиком в память, а echo не совсем соответствует идеям Слима.
Вот тут http://www.slimframework.com/docs/objects/response.html#the-response-body написано как можно задать, чтобы тело ответа читалось бы из файла постепенно.
Ну и если еще оптимизировать, то хорошо бы отдавать файлы без особого участия PHP. Для этого надо настроить веб-сервер, например в случае Апача можно использовать расширение X-Sendfile. С ним PHP только отдает заголовок с именем файла и завершается, а веб-сервер уже дальеш отдает файл. Или пойти еще дальше и настроить правила в .htaccess так, чтобы файл отдавался по ссылке сразу вообще без обращения к PHP.
>>817655
Попробуй. Пусть люди увидят хороший ООП код на Симфони например.
>>820948
>$small = mb_strtolower($text);
>$nospace = str_replace(" ", "", $small);
тут можно было не заводить новые переменные, а класть строку назад в $text
> $symbolback = mb_substr ($nospace, $halflenght, -1);
Неприавльно же, это всегда берет одну и ту же строку, на каждом шаге цикла, независимо от того чему равно $i.
Вот как результат, любое слово с нес=четным числом букв считается палиндромом: http://ideone.com/LpQYin
>>821013
> А что определяет какую функцию мы должны заинкапсулировать? Ведь можно прямо внутри функции ограничивать пришедшие аргументы.
Разбиение кода на функции обычно делают по тому принципу, что одна функция делает какое-то одно действие. Разбивают так, чтобы с одной стороны не было огромных функций, с другой чтобы каждая строчка не была бы отдельной функцией. Так, на словах, а не на конкретном примере, объяснить не очень просто. Лучше всего наверно учиться этому, рассматривая код каких-нибудь фреймворков вроде Слим или Симфони.
насчет "вообще это относится не только к полям" - я имел в виду, что лучше когда переменная или поле доступна только в ограниченной области кода, а не во всей программе, так как тогда проще изучить код который с ней работает. То есть глобальная доступная везде переменная - не очень хорошо, так как ее могут менять откуда угодно, а локальная, существующая внутри 10 строчной функции - хорошо, так как код который с ней работает, помещается на 1 экране.
>>- допустим мы захотим поменять логику и не хранить значение в классе, а передавать куда-то еще, сохранять в файл или в базу или куда-то еще. Опять же, нам придется обойти весь код, найти там все обращения к полю $x и поменять их на вызов какого-то метода.
> Но ведь и в случае инкапсуляции нам придётся пройтись по всему коду и поменять функцию setX().
Вообще-то, нет. Нам достаточно поменять только содержимое функции setX().
>Я бы хотел перенести, например, вот этот код https://github.com/someApprentice/Students/blob/master/app/Controller/LoginAction.php#L48-L51 в $AuthService->login(). Иначе у меня просто не будет Сервисов.
Что-то мне не нравится идея "делать, чтобы было". Пусть будут только хелперы или только сервисы, без разницы, лишь бы код был вынесен в отдельные классы, которые можно вызвать из другого места, а не записан весь в контроллере.
> Можно принимаемые аргументы перенести в конец, и при вызове функции их не указывать.
Да, можно, если есть значения по умолчанию.
> $text = str_replace("[]", "", $text);
Интересно, а это-то зачем? Так, решено верно.
>>820849
Сразу посоветую получение пути к файлу вынести в отдельный метод.
Также, если ты выдаешь заголовок location, то непонятно зачем рендерить download.html, так как пользователь эту страницу скорее всего не увидит.
Также, заголовок content-dispoistion должен отдаваться не со страницей, а вместе с файлом. У тебя же (если убрать location) он приведет к тому что браузер сохранит саму HTML страницу.
> Хочу: ф-ия возвращает не проходной и ненужный download.html, а сразу файл, в http Header которого будет прописан 'Content-Disposition':'attachment' И который будет загружаться.
> Как это можно реализовать?
Ну самый простой способ это прочитать file_get_contents файл в переменную и вывести через усрщ (после заголовков). Но это требует загрузить файл целиком в память, а echo не совсем соответствует идеям Слима.
Вот тут http://www.slimframework.com/docs/objects/response.html#the-response-body написано как можно задать, чтобы тело ответа читалось бы из файла постепенно.
Ну и если еще оптимизировать, то хорошо бы отдавать файлы без особого участия PHP. Для этого надо настроить веб-сервер, например в случае Апача можно использовать расширение X-Sendfile. С ним PHP только отдает заголовок с именем файла и завершается, а веб-сервер уже дальеш отдает файл. Или пойти еще дальше и настроить правила в .htaccess так, чтобы файл отдавался по ссылке сразу вообще без обращения к PHP.
>>817655
Попробуй. Пусть люди увидят хороший ООП код на Симфони например.
>>820948
>$small = mb_strtolower($text);
>$nospace = str_replace(" ", "", $small);
тут можно было не заводить новые переменные, а класть строку назад в $text
> $symbolback = mb_substr ($nospace, $halflenght, -1);
Неприавльно же, это всегда берет одну и ту же строку, на каждом шаге цикла, независимо от того чему равно $i.
Вот как результат, любое слово с нес=четным числом букв считается палиндромом: http://ideone.com/LpQYin
>>821013
> А что определяет какую функцию мы должны заинкапсулировать? Ведь можно прямо внутри функции ограничивать пришедшие аргументы.
Разбиение кода на функции обычно делают по тому принципу, что одна функция делает какое-то одно действие. Разбивают так, чтобы с одной стороны не было огромных функций, с другой чтобы каждая строчка не была бы отдельной функцией. Так, на словах, а не на конкретном примере, объяснить не очень просто. Лучше всего наверно учиться этому, рассматривая код каких-нибудь фреймворков вроде Слим или Симфони.
насчет "вообще это относится не только к полям" - я имел в виду, что лучше когда переменная или поле доступна только в ограниченной области кода, а не во всей программе, так как тогда проще изучить код который с ней работает. То есть глобальная доступная везде переменная - не очень хорошо, так как ее могут менять откуда угодно, а локальная, существующая внутри 10 строчной функции - хорошо, так как код который с ней работает, помещается на 1 экране.
>>- допустим мы захотим поменять логику и не хранить значение в классе, а передавать куда-то еще, сохранять в файл или в базу или куда-то еще. Опять же, нам придется обойти весь код, найти там все обращения к полю $x и поменять их на вызов какого-то метода.
> Но ведь и в случае инкапсуляции нам придётся пройтись по всему коду и поменять функцию setX().
Вообще-то, нет. Нам достаточно поменять только содержимое функции setX().
>Я бы хотел перенести, например, вот этот код https://github.com/someApprentice/Students/blob/master/app/Controller/LoginAction.php#L48-L51 в $AuthService->login(). Иначе у меня просто не будет Сервисов.
Что-то мне не нравится идея "делать, чтобы было". Пусть будут только хелперы или только сервисы, без разницы, лишь бы код был вынесен в отдельные классы, которые можно вызвать из другого места, а не записан весь в контроллере.
> Можно принимаемые аргументы перенести в конец, и при вызове функции их не указывать.
Да, можно, если есть значения по умолчанию.
> PHP Warning: implode(): Invalid arguments passed in /home/.../prog.php on line 32
надо исправить. Пишет что что-то не то передано в функцию. Проверь через var_dump что туда передается.
>>821608
Я сделал тот что на archive-ipq-co narod ru
>>821641
Да просто в шаблоне вызывать require или render для подключения вспомогательных шаблонов.
>>822945
Тебе надо искать что-то вроде "запятая, за ней буква" и заменять это на "запятая, пробел, буква". Букву можно подставить через $1.
> PHP Notice: Undefin ed variable:
Это надо исправить.
> return .... .= ....;
не надо писать несколько действий (присваивание и ретурн) в 1 строку, надо разбить это на 2 команды. Также, конкатенация склеивает строки, а не складывает числа. Отсюда и нули.
Название функции должно начинаться с глагола.
> $text = str_replace("[]", "", $text);
> Интересно, а это-то зачем? Так, решено верно.
А это нужно для вот этого:
> $text = preg_replace($regexp, "$1[$2]$3[$4]", $text);
$2 и $4 заключены в квадратные скобки, но значения в них могут быть пустыми и в этом случае в тексте будут появлятся лишние "[]". Поэтому, я решил после этой строки вставить чистку пустых квадратных скобок, но мне кажется, есть, наверное, более красивое решение этого.
Извиняюсь, если ответил не в том треде, в котором надо.
Главное выложи записи потом где-нибудь.
Вы видите копию треда, сохраненную 7 сентября 2016 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.