Это копия, сохраненная 6 февраля 2015 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
Это тред для начинающих. Не написал за свою жизнь ни одной программы? Ты наш человек.
Требуемые знания: умение читать. Устанавливать пока что ничего не требуется, разве что редактор кода вроде Sublime Text 3, Notepad++, Netbeans PHP или PhpStorm (необязательно).
Предыдущий тред был тут: >>416970
У нас есть уроки по основам PHP, они собраны и выложены по адресу http://archive-ipq-co.narod.ru Если ты ньюфаг, просто решай задачки оттуда, они там реально простые, и пости сюда ссылки на решения, мы посмотрим и скажем, правильно или нет и дадим совет, если можно что-то улучшить. Если не совсем ньюфаг, напиши, что ты знаешь, что нет, что хочешь изучить, я дам тебе какую-нибудь задачку посложнее. После прохождения учебника напиши, ОП даст тебе более сложные задания.
Есть еще у нас задачки на HTML, JS, MySQL.
Правила: ведем себя воспитанно, помогаем новичкам, постим ссылки на решения задачек, ОП их проверяет и дает советы и замечания.
ОП, как всегда, помогает и дает советы, отвечает на самые нубские и простые вопросы. У ОПа есть почта, так что даже если он не появляется в треде уже неделю, вы всегда можете написать ему что-то хорошее. ОП обычно занят, но где-то раз в сутки в треде появляется.
Оформляй код аккуратно!!! например пропусти через phpformatter.com . Также, если ты пользуешься IDE вроде PhpStorm, Netbeans, Eclipse, то в них эта опция встроена, подробнее: https://gist.github.com/codedokode/8759492
Что почитать?
Мануал по PHP — http://www.php.net/manual/ru/langref.php
Сайт phptherightway
По PHP: Профессиональное программирование на PHP Джордж Шлосснейгл
По PHP: Мэтт Зандстра — PHP: Объекты, шаблоны, методики программирования
JS: learn.javascript.ru
HTML/CSS: Путь верстальщика: https://gist.github.com/codedokode/58ebc90bd006baf4b35c
MySQL: https://gist.github.com/codedokode/10539213
Слишком простые задачи? Напиши что знаешь, что хочешь изучить и придумаем тебе задачку посложнее.
Сайт опять упал!!!!! Не паникуй, а открой http://rghost.net/45000175
Не поздно ли в мои 40 становиться программистом? Ох, это будет сложно, но если ты покажешь лучшие знания, чем моложежь, то шансы есть.
Где архивы предыдущих тредов? Известно, где, на mediafire: http://www.mediafire.com/download/gza5360wdzqd743/threads-archive-pr-1..17.zip (189Мб, треды 1-17 из pr), http://www.mediafire.com/download/kgzl1f9366gc6ed/threads-archive-11..20.zip (72 Мб, треды 11-20 из b). Также один анон выложил все на дропбокс: https://www.dropbox.com/sh/4sb69jrx9qwrpcw/-nY5ia__VC (ок, он иногда не работает)
Как начать пользоваться командной строкой — gist.github.com/anonymous/9378956452c8e4a72ac8
ОП, сделай за меня мою работу или домашнее задание? — Это конечно, хорошая идея, но нет.
Расскажи про поиск работы, фриланс etc Информация о фрилансе есть в /wrk . Также, походи по сайтам вроде hh.ru, hantim.ru, geekjob, fl.ru, посмотри, поизучай ситуацию. Имей в виду, кроме фриланса, где ты 2 дня ищешь заказ, полдня обсуждаешь за бесплатно суть работы, день делаешь и еще 2 дня слушаешь от заказчика что он о тебе думает, есть удаленная работа — продаешься в рабство, и занимаешься только программированием, задачи тебе будут подкидывать наготово. Ищется по слову «удаленно» на перечисленных сайтах. Зарплата на удаленной работе может быть меньше чем в офисе в столице, но больше чем в твоей деревне. На одеске зарабатывают больше, чем на русском фрилансе.
В общем, давайте начинать уже!
Как и чем отформатировать код
Важно писать код не как попало, а аккуратно, как принято. Почему? Ну потому, что другой человек, который будет смотреть твой код, вряд ли обрадуется, когда ему придется разбирать слипшиеся строчки, разбросанные в беспорядке скобки и написанные русскими словами названия переменных. Особенно плохо будет если это, например, код тестового задания, которое ты сделал, чтобы устроиться на работу. Ты же не хочешь, чтобы тебя называли быдлокодером?
Не бойся, сделать код аккуратным совсем не сложно. Самый универсальный способ — вставить его на сайт http://phpformatter.com и нажать кнопку Format. Робот сам выровняет твой код в лучших традициях.
Если ты используешь для редактирования кода IDE, то все еще проще (а если не используешь, то почему бы не начать?):
- Eclipse PDT — жми Ctrl + Shift + F для автоматического форматирования кода.
- Netbeans for PHP — жми Alt+Shift+F
- Zend Studio — жми Ctrl + A (выделить все), затем Ctrl + Shift + F
- PhpStorm — жми Ctrl+Alt+L
- PHPDesigner — поищи нужную опцию в меню, она там есть. Или жми Ctrl + Shift + F1
- Komodo IDE — правая кнопка -> Format Using...
Вот так, нажатием одной кнопки ты можешь сделать жизнь гораздо проще.
Как видишь, c IDE жизнь может быть намного проще (еще в них есть автодополнение, автоматическая проверка кода и подсветка ошибок, навигация по файлам и функциям и много чего еще).
Подробнее: https://gist.github.com/codedokode/8759492
Основные правила
Если ты вдруг решил выровнять код вручную, запомни эти правила:
- переменные и функции пишутся с маленькой буквы, подчеркивание не используется, используется camelCase, пример: $x, $numberOfPeople, printResults()
- название функции начинается с глагола, в стиле «сделайЧтоТо»
- не знаешь английский (неужели такое бывает?) Не беда, в 21 веке есть решение этой проблемы. Не пиши транслитом, открой лучше Гугл Транслейт или slovari.yandex.ru и найди название для переменной там
- в именах классов используется CamelCase, первая буква большая, «_» может использоваться
- мы предпочитаем подстановку переменных вместо конкатенации строк: "I am $age years old" — хорошо, 'I am ' . $age . ' years old' — плохо
- мы используем для отступов 4 пробела, а не табы (нужно настроить редактор, чтобы при нажатии Tab он вставлял 4 пробела)
Как и чем отформатировать код
Важно писать код не как попало, а аккуратно, как принято. Почему? Ну потому, что другой человек, который будет смотреть твой код, вряд ли обрадуется, когда ему придется разбирать слипшиеся строчки, разбросанные в беспорядке скобки и написанные русскими словами названия переменных. Особенно плохо будет если это, например, код тестового задания, которое ты сделал, чтобы устроиться на работу. Ты же не хочешь, чтобы тебя называли быдлокодером?
Не бойся, сделать код аккуратным совсем не сложно. Самый универсальный способ — вставить его на сайт http://phpformatter.com и нажать кнопку Format. Робот сам выровняет твой код в лучших традициях.
Если ты используешь для редактирования кода IDE, то все еще проще (а если не используешь, то почему бы не начать?):
- Eclipse PDT — жми Ctrl + Shift + F для автоматического форматирования кода.
- Netbeans for PHP — жми Alt+Shift+F
- Zend Studio — жми Ctrl + A (выделить все), затем Ctrl + Shift + F
- PhpStorm — жми Ctrl+Alt+L
- PHPDesigner — поищи нужную опцию в меню, она там есть. Или жми Ctrl + Shift + F1
- Komodo IDE — правая кнопка -> Format Using...
Вот так, нажатием одной кнопки ты можешь сделать жизнь гораздо проще.
Как видишь, c IDE жизнь может быть намного проще (еще в них есть автодополнение, автоматическая проверка кода и подсветка ошибок, навигация по файлам и функциям и много чего еще).
Подробнее: https://gist.github.com/codedokode/8759492
Основные правила
Если ты вдруг решил выровнять код вручную, запомни эти правила:
- переменные и функции пишутся с маленькой буквы, подчеркивание не используется, используется camelCase, пример: $x, $numberOfPeople, printResults()
- название функции начинается с глагола, в стиле «сделайЧтоТо»
- не знаешь английский (неужели такое бывает?) Не беда, в 21 веке есть решение этой проблемы. Не пиши транслитом, открой лучше Гугл Транслейт или slovari.yandex.ru и найди название для переменной там
- в именах классов используется CamelCase, первая буква большая, «_» может использоваться
- мы предпочитаем подстановку переменных вместо конкатенации строк: "I am $age years old" — хорошо, 'I am ' . $age . ' years old' — плохо
- мы используем для отступов 4 пробела, а не табы (нужно настроить редактор, чтобы при нажатии Tab он вставлял 4 пробела)
Что значит «в конец»? В таблицах нет какого-то особого порядка в котором идут записи.
Если ты спрашивал про поле AUTO_INCREMENT то каждый следующий сгенеирированный id больше предыдущего.
задам тупые вопросы, не агритесь сильно.
меня интересует какие языки вообще для чего предназначены? хочу программировать попробовать в качестве хобби.
Для хобби подойдет джваскрипт, поскольку простой и ничего не надо устанавливать, интерпретатор встроен прямо в твой браузер. Из минусов - придется подучить хтмл-разметку.
Си очень простой язык, просто низкоуровневый.
> Из минусов - придется подучить хтмл-разметку
Это ещё почему?
Во-первых, есть Node и Node-Webkit.
Во-вторых, чтобы решать алгоритмические задачки, ничего кроме ввода-вывода не нужно.
В-третьих, чтобы выводить что-то в канвас или в какой-нибудь элемент с textContent, никаких знаний хтмл не нужно вообще.
>>420045
> Херасе простой. Один из самых кривых и сложных языков программирования
Ну и что в нём сложного? Объекты? Функции? Замыкания? ок, это может быть
мимо-js-гуру
кстати, уже два урока нихрена не понимаю, что я делаю.
Все проще. У доски есть массив животные[] который хранит все объекты-животные на ней. Они добавляются туда когда ты ставишь животное на доску и удаляются когда например когда ты убираешь съеденнную мышку. Больше ничего с этим массивом делать не требуется.
То есть я предлагаю не хранить вообще массив клеточек, а только массив животных. Ну хотя если ты хочешь, можешь сделать дополнительно массив клеточек и передвигать животных в нем.
Ну я заполнил массив объектами(животными), а пустые места просто звездочками, чтобы графически проследить. Но я так и не понял, какой алгоритм перемещения?
Ты не понял что я советовал. Должен быть либо один обычный массив с животными без всяких звездочек либо массив с животными + двухмерный массив с клеточками карты.
массив массивов
После этого набрал 2 тестовых задания и с ними тоже справиться не могу. Вроде бы и учу кроме пхп параллельно и другие нужные для веба технологии, но вообще нигде не прогрессирую сейчас. Из головы все мигом выветривается, вот например делал 1 тестовое задание, понаписал кучу кода, по моим меркам, потом неделю его не трогал, а как снова заглянул, даже вспомнить не могу что и как, и удивляюсь, что неужели это я писал, ведь выглядит сложно для меня. Такие дела. Вернулся сейчас к последней задаче из учебника на которой остановился - калькулятор, и сижу на ней. В плане так же повторить всё что делал до этого более менее вменяемое включая регулярки опять же.
Как с этим говном справиться? Нужна какая-то система видимо, ну и перестать хвататься за всё. Спасибо что выслушали моё нытье. Всем спокойной ночи.
>PHP Parse error: syntax error, unexpected '{' in /home/VUsJpz/prog.php on line 18
у тебя в той строчке стоит else (условие) {
А так не должно быть, после else не нужно условие а сразу идут скобки, если у тебя есть второе условие альтернативное первому указанному после if () {, то используй elseif () {
Из меня наверное не очень объяснятель, вот просто исправил синтаксис твой не проверяя логику: http://ideone.com/BLxobc
Но лучше иди про условия главу перечитай прямо сейчас, и напиши с нуля задачу.
Что-то у тебя вообще не так всё.
Я вот сам нубас, но эту задачу за 2 дня через кучу багета и подсказок с тредика прошел. Там суть, что начальный код изменить нужно немного.
Суть, что сначала капает кредит, потом оцениваешь, можешь-ли ты заплатить полную сумму, или-же не полную, и аж потом платишь.
Активная часть кода у меня в 12 строк влезла.
А ты сначала начал платить, потом сам себе 0 в оплату поставил, а потом опять начал платить, как-то так.
Мне прямым текстом не подсказывали, но я смог дотупить до решения - ты тоже сможешь.
>Привет, Оп. Я ньюфаг ничего незнающий. И я вот по основам учусь, что есть в опике. Но вот с циклами незадача. Укажешь на ошибки? http://ideone.com/jr5j6g
>
>- напиши код, который каждый месяц только увеличивает долг (и выводит его на экран)
>- допиши к нему код, который каждый месяц пишет, большой сейчас долг (школьник не может его выплатить разом) или маленький (меньше 5000 и его можно выплатить за один раз)
>- допиши код, который каждый месяц пишет, сколько надо заплатить в этом месяце (с учетом того что больше 5000 школьник заплатить не может)
>- наконец, допиши код, который платит эту сумму, уменьшая долг и считает сколько всего выплачено
Это мне помогло, попробуй и ты по этому алгоритму сделать.
Есть языки работающие в браузере (JS + HTML/CSS), есть серверные (чтобы делать динамические сайты) вроде PHP, Ruby, Python, есть языки для десктопных приложений вроде C++, есть мало где использующиеся языки типа Си (некоторые на них микрконтроллеры программируют, но я слышал что С++ на них тоже давно уже запускается), есть языки для мобильных приложений (Java, Obj-C), есть языки из маковской экосистемы (Obj-C), языки для написания крупных и корпоративных приложений (C#/.NET, Java), и есть применяющиеся энтузиастами новые языки для обкатки новых подходов в программировании вроде Haskell, Scala, D, Rust, Go.
>>420009
Ruby и Python используются примерно так же как и PHP — для серверных приложений, разве что у них отступы вместо скобочек и синтаксис лаконичнее.
>>420029
Ну ладно, посмотрим что получится.
>>420059
> есть Node
Какое отношение серверный язык имеет к верстке? Думаю, никакого.
> чтобы решать алгоритмические задачки, ничего кроме ввода-вывода не нужно.
Поддержки JS может не быть на сайте где проверяются решения
>>420079
Если ты не понимаешь ООП, у меня есть простой урок: http://archive-ipq-co.narod.ru/l1/pasta.html
Насчет codeacademy, он ничего не пишет? Там код проверки решений довольно кривой и иногда глючит. Сохрани текст программы и попробуй перезагрузить страницу.
Алсо ты по моему echo забыл
>>420100
Если у тебя будет не 2мерная карта а просто обычный массив с животными то ход делать очень просто:
для каждого животного которое есть на карте:
животное->сделатьХод()
Есть языки работающие в браузере (JS + HTML/CSS), есть серверные (чтобы делать динамические сайты) вроде PHP, Ruby, Python, есть языки для десктопных приложений вроде C++, есть мало где использующиеся языки типа Си (некоторые на них микрконтроллеры программируют, но я слышал что С++ на них тоже давно уже запускается), есть языки для мобильных приложений (Java, Obj-C), есть языки из маковской экосистемы (Obj-C), языки для написания крупных и корпоративных приложений (C#/.NET, Java), и есть применяющиеся энтузиастами новые языки для обкатки новых подходов в программировании вроде Haskell, Scala, D, Rust, Go.
>>420009
Ruby и Python используются примерно так же как и PHP — для серверных приложений, разве что у них отступы вместо скобочек и синтаксис лаконичнее.
>>420029
Ну ладно, посмотрим что получится.
>>420059
> есть Node
Какое отношение серверный язык имеет к верстке? Думаю, никакого.
> чтобы решать алгоритмические задачки, ничего кроме ввода-вывода не нужно.
Поддержки JS может не быть на сайте где проверяются решения
>>420079
Если ты не понимаешь ООП, у меня есть простой урок: http://archive-ipq-co.narod.ru/l1/pasta.html
Насчет codeacademy, он ничего не пишет? Там код проверки решений довольно кривой и иногда глючит. Сохрани текст программы и попробуй перезагрузить страницу.
Алсо ты по моему echo забыл
>>420100
Если у тебя будет не 2мерная карта а просто обычный массив с животными то ход делать очень просто:
для каждого животного которое есть на карте:
животное->сделатьХод()
Ну здравствуй анон. Давай посмотрим код.
> else ($creditBalance > $monthlyPayment) {
Тут надо либо elseif либо else без условий. Посмотри внимательно урок про игру в кубики. там вроде есть пример if/elseif.
>>420125
Если ты дошел только до регулярок то этого мало вообще-то. Надо бы пройти учебник до конца + решить пару доплоьнительных задач тогда у тебя будет гораздо больше практики и навыков.
Если у тебя какие-то сложности с задачей, пости код и напиши на чем остановился, я дам подсказку.
По поводу мотивации, я ничем помочь не могу — мы никаких сроков не ставим и не мотивируем и каждый у нас учится в таком темпе, как ему удобно.
Ну и если тебе кажется что ты что-то забыл из старых уроков, можеешь попросить дополнительную задачку на любую тему.
> есть мало где использующиеся языки типа Си
http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html
>>420143
Сука, бомбануло так, что решил угробить себе жизнь, зашкворившись об ваш клуб PHP-шников.
> есть серверные
> Ruby, Python
Нет. Это языки общего назначения. Можно использовать как замену PHP на сервере, так и на клиенте. Можно автоматизировать простенькие задачи, типа массового переименования файлов (собственно, Ruby для этого и проектировался изначально). У них только две беды: 1) они динамически типизированы; 2) под них есть только интерпретаторы. На самом деле, это гибридные интерпретаторы, так называемые виртуальные машины, но от этого скорости исполнения не прибавляется, и не исчезает необходимость ставить эту самую виртуальную машину.
> C++
> языки для десктопных приложений
Нет, блядь. Это тоже язык общего назначения. Есть компиляторы в высокооптимизированный машинный код под многие платформы. У него только две беды: 1) он затачивался исключительно под нужды промышленности информационных технологий, то есть, для обучения программированию не подходит даже близко; 2) он проектировался мудаком-наркоманом с немного предсказуемым результатом.
> есть мало где использующиеся языки типа Си
Сука, вторично бомбануло. Анончик ниже правильно ссылку дал, C был, есть и будет самым распространённым языком в мире. Есть компиляторы в высокооптимизированный машинный код практически подо всё, что может включаться. Так что это самый кроссплатформенный язык на планете («write once, compile everywhere»). У него только две беды: 1) семантически он довольно близок к Ассемблеру; 2) у него хуёвые средства абстракции. Вместе эти две беды делают его непригодным ни для чего, кроме прошивок для микроконтроллеров, ядер операционок и низкоуровневых библиотек расширения других ЯП. Собственно, он и создавался Керниганом и Ритчи как язык для написания операционных систем. Нет, на нем можно, конечно, написать и гуёвину и даже серверное приложение (и запускать его через FCGI или unix domain sockets), но написание на нем очень быстро превращается в жонглирование указателями и segmentation fault-ами. Даже быстрее, чем на C++. Алсо, так как он семантически близок к Ассемблеру, скомпилированные программы получаются предельно производительными. Если уметь.
> Java
> для мобильных приложений
Анус твой — для мобильных приложений! Java выпускается в трех редакциях: 1) Java ME, которая действительно нужна только для мобилок; 2) Java SE, которая есть платформа общего назначения, но на которой в силу её недостатков можно писать только кровавый энтерпрайз с ебическими требованиями («86 ГБ памяти хватит всем!»); 3) Java EE, которая суть Java SE с дополнительными библиотеками для так называемых серверов приложений (application servers). Бед у неё только две: 1) очень тяжелые и тормозные виртуальные машины, принципиально неоптимизируемые из-за косяков в спецификации языка; 2) многословность, превращающая даже самую простую утилитку для раздербанивания списка покупок в громадную кучу AbstractSingletonFactoryProxyBean-ов. Алсо, её хвалёная кроссплатформенность — это миф, C++ и C имеют компиляторы под такие кофемолки, на которые ВМ Java в принципе не влезет.
> Obj-C
Это тоже язык общего назначения, но компиляторы, библиотеки и инфраструктура есть только под Apple-овские девайсы и только под GUI. Собственно, вкупе с низкоуровневостью (из-за которой Apple-овцы решились на запиливание Swift) это и есть его первая беда.
> C#/.NET
> для написания крупных и корпоративных приложений
И опять нет. C# и вообще весь .NET — это платформа для написания программ общего назначения. Была запилен как замена для Java (потому что у Java есть фатальный недостаток, Луркоморье тебе в помощь). Минусов два: 1) виртуальная машина (хоть и шустрая); 2) нормальная инфраструктура есть только под сперму. Впрочем, если не нужны шибко развесистые GUI и ограничиваться только десктопом, то имеющейся инфраструктуры хватит с головой.
А PHP — говно ссаное, да.
>>420143
Сука, бомбануло так, что решил угробить себе жизнь, зашкворившись об ваш клуб PHP-шников.
> есть серверные
> Ruby, Python
Нет. Это языки общего назначения. Можно использовать как замену PHP на сервере, так и на клиенте. Можно автоматизировать простенькие задачи, типа массового переименования файлов (собственно, Ruby для этого и проектировался изначально). У них только две беды: 1) они динамически типизированы; 2) под них есть только интерпретаторы. На самом деле, это гибридные интерпретаторы, так называемые виртуальные машины, но от этого скорости исполнения не прибавляется, и не исчезает необходимость ставить эту самую виртуальную машину.
> C++
> языки для десктопных приложений
Нет, блядь. Это тоже язык общего назначения. Есть компиляторы в высокооптимизированный машинный код под многие платформы. У него только две беды: 1) он затачивался исключительно под нужды промышленности информационных технологий, то есть, для обучения программированию не подходит даже близко; 2) он проектировался мудаком-наркоманом с немного предсказуемым результатом.
> есть мало где использующиеся языки типа Си
Сука, вторично бомбануло. Анончик ниже правильно ссылку дал, C был, есть и будет самым распространённым языком в мире. Есть компиляторы в высокооптимизированный машинный код практически подо всё, что может включаться. Так что это самый кроссплатформенный язык на планете («write once, compile everywhere»). У него только две беды: 1) семантически он довольно близок к Ассемблеру; 2) у него хуёвые средства абстракции. Вместе эти две беды делают его непригодным ни для чего, кроме прошивок для микроконтроллеров, ядер операционок и низкоуровневых библиотек расширения других ЯП. Собственно, он и создавался Керниганом и Ритчи как язык для написания операционных систем. Нет, на нем можно, конечно, написать и гуёвину и даже серверное приложение (и запускать его через FCGI или unix domain sockets), но написание на нем очень быстро превращается в жонглирование указателями и segmentation fault-ами. Даже быстрее, чем на C++. Алсо, так как он семантически близок к Ассемблеру, скомпилированные программы получаются предельно производительными. Если уметь.
> Java
> для мобильных приложений
Анус твой — для мобильных приложений! Java выпускается в трех редакциях: 1) Java ME, которая действительно нужна только для мобилок; 2) Java SE, которая есть платформа общего назначения, но на которой в силу её недостатков можно писать только кровавый энтерпрайз с ебическими требованиями («86 ГБ памяти хватит всем!»); 3) Java EE, которая суть Java SE с дополнительными библиотеками для так называемых серверов приложений (application servers). Бед у неё только две: 1) очень тяжелые и тормозные виртуальные машины, принципиально неоптимизируемые из-за косяков в спецификации языка; 2) многословность, превращающая даже самую простую утилитку для раздербанивания списка покупок в громадную кучу AbstractSingletonFactoryProxyBean-ов. Алсо, её хвалёная кроссплатформенность — это миф, C++ и C имеют компиляторы под такие кофемолки, на которые ВМ Java в принципе не влезет.
> Obj-C
Это тоже язык общего назначения, но компиляторы, библиотеки и инфраструктура есть только под Apple-овские девайсы и только под GUI. Собственно, вкупе с низкоуровневостью (из-за которой Apple-овцы решились на запиливание Swift) это и есть его первая беда.
> C#/.NET
> для написания крупных и корпоративных приложений
И опять нет. C# и вообще весь .NET — это платформа для написания программ общего назначения. Была запилен как замена для Java (потому что у Java есть фатальный недостаток, Луркоморье тебе в помощь). Минусов два: 1) виртуальная машина (хоть и шустрая); 2) нормальная инфраструктура есть только под сперму. Впрочем, если не нужны шибко развесистые GUI и ограничиваться только десктопом, то имеющейся инфраструктуры хватит с головой.
А PHP — говно ссаное, да.
>Во-во. Я бы C советовал.
Оче толсто.
>>420059
>Во-первых, есть Node и Node-Webkit.
Надо устанавливать и не сказать, чтобы это было легко. К тому же тащит в систему всякое говно, которое тебе может и совсем не нужно, особенно если для хобби. Если уж устанавливать то уж какой нибудь Delphi, моментальные красивые формочки, попробуй, базарю захочешь еще.
>Во-вторых, чтобы решать алгоритмические задачки, ничего кроме ввода-вывода не нужно.
Ну тащем-то да, Ctrl+Shift+I и вперед, наверное, самый оптимальный вариант.
>В-третьих, чтобы выводить что-то в канвас или в какой-нибудь элемент с textContent, никаких знаний хтмл не нужно вообще.
Как минимум нужно знать, что этот твой канвас существует, что на него можно что-то выводить и т.д.
А когда я в прикрепленном треде спрашивал подобное расписать по всем языкам, то никто не ответил. Зато он пхп тред мониторит, ты посмотри на него, причем похоже только что бы макать других в говно, плюс
>А PHP — говно ссаное, да.
вот без этого конечно никуда. Больше нечего было сказать? Или не можешь?
>А PHP — говно ссаное, да.
Никто ни разу не сказал почему.
Зашквар и всё тут.
Алсо включу зануду и скажу, что говно выссать нельзя.
>>420005
Если я освою джаваскрипт, а потом захочу обычную джаву освоить, мне будет легче, чем если бы я с нуля сразу джаву начал?
Не ругайтесь, если сморозил глупость, я ньюфаг просто и вообще из вёрстка-треда.
Одно дело промолчать, другое дело — написать хуйню. В первом случае ньюфаг может, наконец, перестать маяться хуйнёй, заказывая консалтинг на Харкаче (!), и начать изучать самому (ведь ему всё равно придётся, если он действительно решил изучить ремесло программиста); во-втором случае будет страдать сам, забивая гвозди микроскопом, и компенсировать свои страдания, заставляя других забивать гвозди так же.
> Одно дело промолчать, другое дело — написать хуйню. В первом случае ньюфаг может, наконец, перестать маяться хуйнёй, заказывая консалтинг на Харкаче (!), и начать изучать самому
всё верно
> Delphi,
Pascal изначально был придуман для обучения, а не для реализации каких-то практических задач. Дельфи устарел лет 15 назад и нигде кроме бывшего СССР не был попуоярен. Не советую тратить на него время.
Ну и вдобавок, дельфи намертво завязан на WinAPI как я понимаю. Используйте лучше С++/Qt если не боитесь c++
Лол. Ты сам до этого додумался, или повторяешь за всеми мантру "делфи нинужон!11"?
>Pascal изначально был придуман для обучения, а не для реализации каких-то практических задач
Проиграл с толстяка.
>Если ты дошел только до регулярок то этого мало вообще-то.
Я прошел дважды все регулярки и сделал все кроме калькулятора задачи из повторим, а так же пилил и некоторые другие вещи.
>Надо бы пройти учебник до конца + решить пару доплоьнительных задач тогда у тебя будет гораздо больше практики и навыков.
Да, надо. Плюс еще очень много чего нужно сделать. А как я могу показывать вам сложные и большие задачи если они уже не влазят в 1 файл (на ideone), значит время регаться на гитхабе и учиться им пользоваться?
>>419758
Ты просил проверить задачу про регистрацию студентов. Хорошо, конечно, что она что-то выводит, но код требует сербезной переделки. Сейчас у тебя все свалено в кучу, надо разложить по отдельным файлам. Вот список того что надо исправить:
По базе данных:
> `sex` varchar(4) COLLATE utf8_unicode_ci DEFAULT NULL,
Погугли по слвоам MySQL ENUM
Также, почитай какие есть типы колонок в MySQL:
http://phpclub.ru/mysql/doc/column-types.html (рус, кратко)
http://dev.mysql.com/doc/refman/5.6/en/data-types.html (англ, подробно)
> `groupindex` int(11) DEFAULT NULL,
Номер группы не надо делать числом, вдруг будет группа 2106M или 212-20?
> `birthdate` int(11) DEFAULT NULL,
Тут надо использовать более подходящий тип
Обычно в базе с помощью NOT NULL помечают обязательные поля, а DEFAULT NULL - те, которые можно не заполнять. У тебя все почему-то помечены как необязательные.
По коду:
Каждый класс должен быть в своем файле, и в это файле не должно быть ничего постороннего. Классы пишутся с большой буквы, и файл должен называться как и класс: Student -> Student.php. Файлы классов можно положить в папку с названием app или lib.
Вот такого быть не должно:
> $isRegistered = "<a href='register.php' class=\"navigation\">Зарегистрироваться</a>";
Весь HTML-код должен быть помещен в шаблоны, как описано тут: http://www.phpinfo.su/articles/practice/shablony_v_php.html
Файлы шаблонов стоит называть с расширением .phtml, .php или .tpl и поместить в отдельную папку templates.
> if(isset($_COOKIE['studentscookie']['name'])){
Проверку, регистрировался ли пользователь ранее, надо вынести в отдельную функцию или метод. Чтобы было например
$id = getUserId( );
if ($id) ...
Работу с БД надо вынести в отдельный класс или функции. Чтобы SQL-код не был размазан по всему приложению, а находился в одном месте. Чтобы можно было написать что-то вроде
$students = $mapper->find($text);
Для поиска студентов по строке текста. Или хотя бы так:
$students = findStudents($text);
Вот мой урок про способы работы с базой данных: https://gist.github.com/codedokode/c4cbc4d7dc8e45ea074a (он может быть сложным для начинающего, что поделать).
> WHERE name LIKE '%$search%'
Тут нужно использовать плейсхолдер, а не вставлять переменную напрямую. Тем более что это данные от пользователя и вставляя их ты получаешь SQL-инъекцию (это такая уязвимость).
> header('Location: http://www.students.ru/profile.php');
Лучше не вписывать имя хоста явно, а вынести в конфиг или брать из $_SERVER['HTTP_HOST']
> try{
> $DBH= new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
Лучше сделать функцию типа getPdo(). Также, try/catch тут не нужен, при ошибке текст исключения и так выведется если включено display_errors. Вот если что мой урок про исключения: https://gist.github.com/codedokode/65d43ca5ac95c762bc1a
Ну и настройки надо вынести в отдельный файл config.php, где ничего кроме них не должно быть.
В общем, давай пока с этим разберемся, а дальше посмотрим. Если есть вопросы, задавай, если все ясно, пиши код.
>>419758
Ты просил проверить задачу про регистрацию студентов. Хорошо, конечно, что она что-то выводит, но код требует сербезной переделки. Сейчас у тебя все свалено в кучу, надо разложить по отдельным файлам. Вот список того что надо исправить:
По базе данных:
> `sex` varchar(4) COLLATE utf8_unicode_ci DEFAULT NULL,
Погугли по слвоам MySQL ENUM
Также, почитай какие есть типы колонок в MySQL:
http://phpclub.ru/mysql/doc/column-types.html (рус, кратко)
http://dev.mysql.com/doc/refman/5.6/en/data-types.html (англ, подробно)
> `groupindex` int(11) DEFAULT NULL,
Номер группы не надо делать числом, вдруг будет группа 2106M или 212-20?
> `birthdate` int(11) DEFAULT NULL,
Тут надо использовать более подходящий тип
Обычно в базе с помощью NOT NULL помечают обязательные поля, а DEFAULT NULL - те, которые можно не заполнять. У тебя все почему-то помечены как необязательные.
По коду:
Каждый класс должен быть в своем файле, и в это файле не должно быть ничего постороннего. Классы пишутся с большой буквы, и файл должен называться как и класс: Student -> Student.php. Файлы классов можно положить в папку с названием app или lib.
Вот такого быть не должно:
> $isRegistered = "<a href='register.php' class=\"navigation\">Зарегистрироваться</a>";
Весь HTML-код должен быть помещен в шаблоны, как описано тут: http://www.phpinfo.su/articles/practice/shablony_v_php.html
Файлы шаблонов стоит называть с расширением .phtml, .php или .tpl и поместить в отдельную папку templates.
> if(isset($_COOKIE['studentscookie']['name'])){
Проверку, регистрировался ли пользователь ранее, надо вынести в отдельную функцию или метод. Чтобы было например
$id = getUserId( );
if ($id) ...
Работу с БД надо вынести в отдельный класс или функции. Чтобы SQL-код не был размазан по всему приложению, а находился в одном месте. Чтобы можно было написать что-то вроде
$students = $mapper->find($text);
Для поиска студентов по строке текста. Или хотя бы так:
$students = findStudents($text);
Вот мой урок про способы работы с базой данных: https://gist.github.com/codedokode/c4cbc4d7dc8e45ea074a (он может быть сложным для начинающего, что поделать).
> WHERE name LIKE '%$search%'
Тут нужно использовать плейсхолдер, а не вставлять переменную напрямую. Тем более что это данные от пользователя и вставляя их ты получаешь SQL-инъекцию (это такая уязвимость).
> header('Location: http://www.students.ru/profile.php');
Лучше не вписывать имя хоста явно, а вынести в конфиг или брать из $_SERVER['HTTP_HOST']
> try{
> $DBH= new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
Лучше сделать функцию типа getPdo(). Также, try/catch тут не нужен, при ошибке текст исключения и так выведется если включено display_errors. Вот если что мой урок про исключения: https://gist.github.com/codedokode/65d43ca5ac95c762bc1a
Ну и настройки надо вынести в отдельный файл config.php, где ничего кроме них не должно быть.
В общем, давай пока с этим разберемся, а дальше посмотрим. Если есть вопросы, задавай, если все ясно, пиши код.
Это индекс по числу упоминаний в гугле: http://www.tiobe.com/index.php/content/paperinfo/tpci/programminglanguages_definition.html
Причем там много странностей:
Поиск в ютубе для С дает 682000, а PHP 640 000 результатов
Поиск в Гугле для С дает 93M результатов, для PHP 157M.
И при этом PHP в их рейтинге намного ниже С. Конечно, я писал запрос без плюсов и без кавычек, но результатов-то больше.
Ну и плюс:
> Yandex: SOURCES_NOT_PARSABLE
В общем, странный индекс.
>>420159
Давай у тебя еще раз бомбанет. Я там не написал подробно, для чего придуман PHP. А придуман он для разработки популярных высоконагруженных масштабируемых сайтов, например Вконтакте, Википедия, Фейсбук. Не удивлюсь если это самый популярный язык в вебе (как и наш тред самый популярный после ньюфаг-треда).
> Это языки общего назначения.
Любой Тьюринг-полный язык позволяет написать на нем что угодно. Но все же у языков есть ниша. Например, приложения под айфон обычно пишутся на Obj-C, а PHP обычно используется для разработки веб-приложений.
> под них есть только интерпретаторы
Ты не любитель переставлять байты? Тогда ты изначально загоняешь себя в рамки требованием к похожести на Си. Php не компилируется и это не мешает создавать на нем сайты.
Кстати, для PHP есть JIT интерпретатор — HipHop VM. Понятно, что динамические языки компилировать бесползено, а вот JIT подход позволяет неплохо их ускорить — например Гугл ускорил JS за счет JIT в v8.
> скомпилированные программы получаются предельно производительными. Если уметь.
На практике использование более оптимального алгоритма дает больший выигрыш чем перестановка команд местами.
> Анус твой — для мобильных приложений!
Я упомянул ее еще в ентерпайзных приложениях. А под мобильными я имел в виду конечно не давно умерший ME, а Android.
> Бед у неё только две: 1) очень тяжелые и тормозные виртуальные машины
Тяжелые они только в том плане что медленно запускаются (что для серверных приложений нормально), а работают они нормально: https://www.techempower.com/benchmarks/ при том что в яве есть и JIT и умные сборщики мусора и инструменты для профайлинга и анализа.
(заметь там в топе С++, а не Си. Потому что что-то сложнее лабы1 написать на Си нереально. Вот вконтактовцы писали — и на это больно смотреть: https://github.com/vk-com/kphp-kdb )
> многословность, превращающая даже самую простую утилитку для раздербанивания списка покупок в громадную кучу AbstractSingletonFactoryProxyBean-ов.
Это есть, да, но она все же лаконичнее чем ее предшественник Си++. Как я понимаю, ради более удобного синтаксиса там делаются языки поверх JVM вроде Скалы.
> Минусов два: 1) виртуальная машина
Ты опять скатываешься в байтолюбство. Насколько я понимаю, с VM там код получается компактнее, надежнее (никаких проблем с указателями, а ведь писать корпоративный софт будут миллионы индусов) и переносимее, а для MS это важно так как проданный проприетарный код никто не будет перекомпилировать под новые платформы.
Это индекс по числу упоминаний в гугле: http://www.tiobe.com/index.php/content/paperinfo/tpci/programminglanguages_definition.html
Причем там много странностей:
Поиск в ютубе для С дает 682000, а PHP 640 000 результатов
Поиск в Гугле для С дает 93M результатов, для PHP 157M.
И при этом PHP в их рейтинге намного ниже С. Конечно, я писал запрос без плюсов и без кавычек, но результатов-то больше.
Ну и плюс:
> Yandex: SOURCES_NOT_PARSABLE
В общем, странный индекс.
>>420159
Давай у тебя еще раз бомбанет. Я там не написал подробно, для чего придуман PHP. А придуман он для разработки популярных высоконагруженных масштабируемых сайтов, например Вконтакте, Википедия, Фейсбук. Не удивлюсь если это самый популярный язык в вебе (как и наш тред самый популярный после ньюфаг-треда).
> Это языки общего назначения.
Любой Тьюринг-полный язык позволяет написать на нем что угодно. Но все же у языков есть ниша. Например, приложения под айфон обычно пишутся на Obj-C, а PHP обычно используется для разработки веб-приложений.
> под них есть только интерпретаторы
Ты не любитель переставлять байты? Тогда ты изначально загоняешь себя в рамки требованием к похожести на Си. Php не компилируется и это не мешает создавать на нем сайты.
Кстати, для PHP есть JIT интерпретатор — HipHop VM. Понятно, что динамические языки компилировать бесползено, а вот JIT подход позволяет неплохо их ускорить — например Гугл ускорил JS за счет JIT в v8.
> скомпилированные программы получаются предельно производительными. Если уметь.
На практике использование более оптимального алгоритма дает больший выигрыш чем перестановка команд местами.
> Анус твой — для мобильных приложений!
Я упомянул ее еще в ентерпайзных приложениях. А под мобильными я имел в виду конечно не давно умерший ME, а Android.
> Бед у неё только две: 1) очень тяжелые и тормозные виртуальные машины
Тяжелые они только в том плане что медленно запускаются (что для серверных приложений нормально), а работают они нормально: https://www.techempower.com/benchmarks/ при том что в яве есть и JIT и умные сборщики мусора и инструменты для профайлинга и анализа.
(заметь там в топе С++, а не Си. Потому что что-то сложнее лабы1 написать на Си нереально. Вот вконтактовцы писали — и на это больно смотреть: https://github.com/vk-com/kphp-kdb )
> многословность, превращающая даже самую простую утилитку для раздербанивания списка покупок в громадную кучу AbstractSingletonFactoryProxyBean-ов.
Это есть, да, но она все же лаконичнее чем ее предшественник Си++. Как я понимаю, ради более удобного синтаксиса там делаются языки поверх JVM вроде Скалы.
> Минусов два: 1) виртуальная машина
Ты опять скатываешься в байтолюбство. Насколько я понимаю, с VM там код получается компактнее, надежнее (никаких проблем с указателями, а ведь писать корпоративный софт будут миллионы индусов) и переносимее, а для MS это важно так как проданный проприетарный код никто не будет перекомпилировать под новые платформы.
> Если я освою джаваскрипт, а потом захочу обычную джаву о
У этих языков из похожего только название. Яваскрипт это не упрощенная версия Явы, а отдельный язык. Но второй язык учить всегда проще, чем первый.
>>420206
Спасибо на добром слове. Ты можешь заходить решать какие-нибудь задачки, у нас тут много всего изучается: PHP, HTML/CSS, JS, SQL.
>>420229
> return $this->isWinner = 1;
Не надо писать так, надо писать в 2 строчки так как тут 2 отделбных действия: изменение значения свойства и return.
> while ($player->isWinner == 0) {
Это ошибка, ты обращаешься к несуществующей на тот момент переменной. Наверно, надо проверять это не до цикла, а в цикле после каждого хода:
бесконечно повторять {
для каждого игрока {
- сделать ход
- если игрок победил, выходим из функции
}
}
Вот и PHP тебе говорит про ошибку внизу:
> PHP Notice: Undefined variable: player in /home/tqO7cS/prog.php on line 132
> return $player->name;
> break;
return выходит из функции (и из цикла соответственно) так что break не нужен.
> создал сам массив с клетками (может не надо было двумерный можно наверное было обойтись и одномерным) не пойму как влепить в него позиции игроков для отображения
Карта двухмерная, потому массив удобнее тоже двумерный. Влепить очень просто — после того, как сделал пустую карту. обходишь в цикле игроков и выставляешь на нее:
для каждого игрока:
- определить его координаты и символ
- поставить в указанные координаты указанный символ
В этом случае правда символ игрока заменит цифру, которая в клеточке, это годится? Если нет то можно клеточку с игроком сделать строкой вида 45(#)
> foreach (range($x 10 + 1, $x 10 + 10) as $point) {
Ерунда какая-то. Почему нельзя сделать цикл по j от 0 до 9? И зачем ты кладешь цифры
> unset($line);
Лучше класть в line пустой массив
> Если я освою джаваскрипт, а потом захочу обычную джаву о
У этих языков из похожего только название. Яваскрипт это не упрощенная версия Явы, а отдельный язык. Но второй язык учить всегда проще, чем первый.
>>420206
Спасибо на добром слове. Ты можешь заходить решать какие-нибудь задачки, у нас тут много всего изучается: PHP, HTML/CSS, JS, SQL.
>>420229
> return $this->isWinner = 1;
Не надо писать так, надо писать в 2 строчки так как тут 2 отделбных действия: изменение значения свойства и return.
> while ($player->isWinner == 0) {
Это ошибка, ты обращаешься к несуществующей на тот момент переменной. Наверно, надо проверять это не до цикла, а в цикле после каждого хода:
бесконечно повторять {
для каждого игрока {
- сделать ход
- если игрок победил, выходим из функции
}
}
Вот и PHP тебе говорит про ошибку внизу:
> PHP Notice: Undefined variable: player in /home/tqO7cS/prog.php on line 132
> return $player->name;
> break;
return выходит из функции (и из цикла соответственно) так что break не нужен.
> создал сам массив с клетками (может не надо было двумерный можно наверное было обойтись и одномерным) не пойму как влепить в него позиции игроков для отображения
Карта двухмерная, потому массив удобнее тоже двумерный. Влепить очень просто — после того, как сделал пустую карту. обходишь в цикле игроков и выставляешь на нее:
для каждого игрока:
- определить его координаты и символ
- поставить в указанные координаты указанный символ
В этом случае правда символ игрока заменит цифру, которая в клеточке, это годится? Если нет то можно клеточку с игроком сделать строкой вида 45(#)
> foreach (range($x 10 + 1, $x 10 + 10) as $point) {
Ерунда какая-то. Почему нельзя сделать цикл по j от 0 до 9? И зачем ты кладешь цифры
> unset($line);
Лучше класть в line пустой массив
А, я понял, зачем ты кладешь цифры в массив. Так подписаны клеточки. Все равно, заполнять лучше без range, а примерно так:
для i от 0 до 9 {
для j от 0 до 9 {
k = посчитать номер клеточки;
положить k в массив;
}
}
>>420254
Проиграй еще и с википедии: https://ru.wikipedia.org/wiki/%D0%9F%D0%B0%D1%81%D0%BA%D0%B0%D0%BB%D1%8C_(%D1%8F%D0%B7%D1%8B%D0%BA_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F)
Я считаю, это глупость и учиться лучше на используемых реально языках. Я бы выбрал Питон за его логичность и однозначность синтаксиса.
>>420294
> время регаться на гитхабе и учиться им пользоваться?
Да. Есть книга по гиту: http://git-scm.com/book/ru/v1
А гитхаб это лишь публичный git репозиторий для проектов.
Ты наверно сейчас тогда будешь калькулятор и задачи на ООП делать? Если что-то непонятно, покажи код и задай вопрос или попроси подсказку.
А, я понял, зачем ты кладешь цифры в массив. Так подписаны клеточки. Все равно, заполнять лучше без range, а примерно так:
для i от 0 до 9 {
для j от 0 до 9 {
k = посчитать номер клеточки;
положить k в массив;
}
}
>>420254
Проиграй еще и с википедии: https://ru.wikipedia.org/wiki/%D0%9F%D0%B0%D1%81%D0%BA%D0%B0%D0%BB%D1%8C_(%D1%8F%D0%B7%D1%8B%D0%BA_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F)
Я считаю, это глупость и учиться лучше на используемых реально языках. Я бы выбрал Питон за его логичность и однозначность синтаксиса.
>>420294
> время регаться на гитхабе и учиться им пользоваться?
Да. Есть книга по гиту: http://git-scm.com/book/ru/v1
А гитхаб это лишь публичный git репозиторий для проектов.
Ты наверно сейчас тогда будешь калькулятор и задачи на ООП делать? Если что-то непонятно, покажи код и задай вопрос или попроси подсказку.
> Почему вам НЕ стоит использовать AngularJs
Я не пользовался Ангуларом, но читал документацию, и у меня возникали те же мысли. Ангулар это какая-то вещь в себе, которая пытается контролировать каждый ваш шаг.
С другой стороны, у него удобный синтаксис. Я подумал, может кто-то хочет попробовать сделать шаблонизатор с дата-байнлингом с синтаксисом ангулара, при этом выкинув все остальное, что там навязывается в довесок? То есть все эти их сервисы, контроллеры, наследованием скоупов и сами скоупы? Этакий knockout c синтаксисом ангулара, не фреймворк а просто шаблонизатор, который можно использовать сам по себе или вместе с Backbone. Назовем его например Bracketed. Заодно исправим все упомянутые в статье недостатки.
Насчет дата-байндинга, надо посмотреть, как его реализовать. То, что сделао в ангулар, очень медленное и никуда не годится, можно использовать либо подход knockout, либо как-то интегрировать с событиями изменений моделей в том же backbone (как?).
В общем не знаю, смогу ли я сформулировать задачу в этом году, наверно это уже в январе будет. Ну и задача довольно сложная, нужно хорошее знание яваскрипта и желание копаться в исходниках angular и knockout (и понимание самих этих библиотек), так как мы из них будем брать код.
Мне кажется то, что получится, могло бы быть вполне популярно при дложном пиаре.
У меня есть форма, к которой я перед отправкой с помощью JS добавляю скрытые поля с доп. данными, так: <input type="hidden" name="field_array[]" value="name">; на странице есть список, я прохожу по нему циклом и на каждой итерации добавляю вот это скрытое поле.
Но теперь у меня появилась необходимость для каждого такого элемента списка добавлять не одно значение, а 3, они у меня закреплены у элемента списка атрибутом data-value, но это, наверное, можно как–то иначе сделать. То есть, нужно уже не одно скрытое поле добавлять, а три, и так, чтобы они были связаны друг с другом при получении на сервере, как это сделать?
Например, вот добавлял я на каждой итерации цикла инпут с названием кино (где атрибут value="название_кино"), а теперь нужно название, имя режиссёра и год выпуска. Таким образом, должен получиться двумерный массив или вроде того.
Спасибо!
Я слышал, что когда–то должен выйти Ангъюлар 2 и он очень сильно будет отличаться от оригинального, настолько, что даже знания по первому мало пригодятся, считай, новый фреймворк.
Это паста, причем старая.
Звучит как то сложно. С наскоку вижу только добавлять все это дело единой строкой в value, а потом обратно распарсивать на отдельные элементы.
Я об этом подумал, но это какая–то идиотия. А что сложно, в смысле, что я делаю что–то не то и должен быть какой–то более простой способ передать доп. данные на сервер вместе с формой?
> индекс по числу упоминанй в гугле
> Поиск в Гугле для С дает 93M результатов, для PHP 157M.
Это говорит о том, что пыходауны чаще остальных практикуют GDD (Google-driven development).
На количество кода на конкретном ЯП тоже смотреть бессмысленно, потому что больше всего кода до сих пор написано на COBOL.
Количество программ (включая сайты, ибо сайт — тоже программа, только запускающаяся через жопу) мне кажется наиболее адекватным индексом.
> PHP
> высоконагруженных
> масштабируемых
Вот тут я просрался по полной. Пиздуй читать, как «масштабировали» ВКонтакте, и как разрабатывается Google. А Википедия вообще высоконагруженным проектом не является.
> Не удивлюсь если это самый популярный язык в вебе (как и наш тред самый популярный после ньюфаг-треда).
И не удивляйся. Чем тупее и ленивее человек, тем выше вероятность, что он возьмет что попроще и спросит у кого-нибудь конкретный вопрос, вместо того чтобы читать доки самому. Я также не удивлюсь, если http://php.net/manual/en/ никто из этого треда в глаза не видел.
> Любой Тьюринг-полный язык позволяет написать на нем что угодно. Но все же у языков есть ниша.
Давай я переформулирую это для тебя: на любом полном по Тьюрингу языке можно написать любую функцию, но делать это лучше на том ЯП, на котором это будет быстрее и проще. Я ранжировал ЯП в соответствии с этой концепцией.
> Ты любитель переставлять байты [без «не»?]? Тогда ты изначально загоняешь себя в рамки требованием к похожести на Си.
Логика уровня PHP-треда. Нет, спасибо, я предпочитаю OCaml.
> Php не компилируется и это не мешает создавать на нем гостевухи.
Поправил. Алсо, как одно соотносится с другим?
> Кстати, для PHP есть JIT интерпретатор…
Я сравнивал ЯП с точностью до наличия JIT-ирующих VM и компиляторов. И да, HipHop VM положение не спасает (погугли, по-моему, им удалось ускорить выполнение всего лишь где-то в 2 раза, плюс HHVM JIT справляется только с каким-то подмножеством PHP, в остальном сваливается в обычную интерпретацию), потому что семантика PHP многократно уёбищнее семантики Java.
А YARV даже JIT-ить не пришлось.
> На практике использование более оптимального алгоритма дает больший выигрыш чем перестановка команд местами.
…Если речь не идет о highload.
> Тяжелые они [VM Java]
…потому, что жрут много памяти. Пидорасы из Sun и Oracle предпочли послать нахуй менеджер памяти ядра, тупо отхавав у него максимум RAM, и перевелосипедить свой менеджер памяти со сборщиком мусора и шлюхами. Алсо, уже на старте в память грузится просто ебическое количество классов и ресурсов.
> Это есть, да, но она все же лаконичнее чем ее предшественник Си++.
Нет. У Java средства абстракции по гибкости примерно как у C. Просто для пидорения scalable robust yoba enterprise solutions этих средств зачастую достаточно (ибо enterprise solutions сами по себе есть примитивные CRUD-ы, просто очень большие). Но если вылезать за рамки use case-ов, предусмотренных Sun и Oracle, начинается ад, боль и унижение.
> ради более удобного синтаксиса там делаются языки поверх JVM вроде Скалы.
Получается CCAHNHA, которая сворачивает голову JIT и выдает перлы вроде выбрасывания исключения при выполнении return из лямбды. JVM, в отличие от .NET, заточена только и исключительно под Java, и любая попытка скомпилировать в байткод JVM что-то, отличное от «public static cherez static» или «AbstractSingletonFactoryProxyBean» приводит к длиннющей лапше опкодов, после JIT-а не укладывающихся ни в какой кеш и ссущих на голову branch predictor-у.
> C#
> Насколько я понимаю, с VM там [в C#] код получается <…> переносимее
В теории — да, как и у Oracle. На практике переносимость получилась еще хуже, чем у Oracle — только в пределах семейства ШИНДОШС. То есть, это даже не все десктопы.
> индекс по числу упоминанй в гугле
> Поиск в Гугле для С дает 93M результатов, для PHP 157M.
Это говорит о том, что пыходауны чаще остальных практикуют GDD (Google-driven development).
На количество кода на конкретном ЯП тоже смотреть бессмысленно, потому что больше всего кода до сих пор написано на COBOL.
Количество программ (включая сайты, ибо сайт — тоже программа, только запускающаяся через жопу) мне кажется наиболее адекватным индексом.
> PHP
> высоконагруженных
> масштабируемых
Вот тут я просрался по полной. Пиздуй читать, как «масштабировали» ВКонтакте, и как разрабатывается Google. А Википедия вообще высоконагруженным проектом не является.
> Не удивлюсь если это самый популярный язык в вебе (как и наш тред самый популярный после ньюфаг-треда).
И не удивляйся. Чем тупее и ленивее человек, тем выше вероятность, что он возьмет что попроще и спросит у кого-нибудь конкретный вопрос, вместо того чтобы читать доки самому. Я также не удивлюсь, если http://php.net/manual/en/ никто из этого треда в глаза не видел.
> Любой Тьюринг-полный язык позволяет написать на нем что угодно. Но все же у языков есть ниша.
Давай я переформулирую это для тебя: на любом полном по Тьюрингу языке можно написать любую функцию, но делать это лучше на том ЯП, на котором это будет быстрее и проще. Я ранжировал ЯП в соответствии с этой концепцией.
> Ты любитель переставлять байты [без «не»?]? Тогда ты изначально загоняешь себя в рамки требованием к похожести на Си.
Логика уровня PHP-треда. Нет, спасибо, я предпочитаю OCaml.
> Php не компилируется и это не мешает создавать на нем гостевухи.
Поправил. Алсо, как одно соотносится с другим?
> Кстати, для PHP есть JIT интерпретатор…
Я сравнивал ЯП с точностью до наличия JIT-ирующих VM и компиляторов. И да, HipHop VM положение не спасает (погугли, по-моему, им удалось ускорить выполнение всего лишь где-то в 2 раза, плюс HHVM JIT справляется только с каким-то подмножеством PHP, в остальном сваливается в обычную интерпретацию), потому что семантика PHP многократно уёбищнее семантики Java.
А YARV даже JIT-ить не пришлось.
> На практике использование более оптимального алгоритма дает больший выигрыш чем перестановка команд местами.
…Если речь не идет о highload.
> Тяжелые они [VM Java]
…потому, что жрут много памяти. Пидорасы из Sun и Oracle предпочли послать нахуй менеджер памяти ядра, тупо отхавав у него максимум RAM, и перевелосипедить свой менеджер памяти со сборщиком мусора и шлюхами. Алсо, уже на старте в память грузится просто ебическое количество классов и ресурсов.
> Это есть, да, но она все же лаконичнее чем ее предшественник Си++.
Нет. У Java средства абстракции по гибкости примерно как у C. Просто для пидорения scalable robust yoba enterprise solutions этих средств зачастую достаточно (ибо enterprise solutions сами по себе есть примитивные CRUD-ы, просто очень большие). Но если вылезать за рамки use case-ов, предусмотренных Sun и Oracle, начинается ад, боль и унижение.
> ради более удобного синтаксиса там делаются языки поверх JVM вроде Скалы.
Получается CCAHNHA, которая сворачивает голову JIT и выдает перлы вроде выбрасывания исключения при выполнении return из лямбды. JVM, в отличие от .NET, заточена только и исключительно под Java, и любая попытка скомпилировать в байткод JVM что-то, отличное от «public static cherez static» или «AbstractSingletonFactoryProxyBean» приводит к длиннющей лапше опкодов, после JIT-а не укладывающихся ни в какой кеш и ссущих на голову branch predictor-у.
> C#
> Насколько я понимаю, с VM там [в C#] код получается <…> переносимее
В теории — да, как и у Oracle. На практике переносимость получилась еще хуже, чем у Oracle — только в пределах семейства ШИНДОШС. То есть, это даже не все десктопы.
Я не понимаю до конца что у тебя за страница, но полагаю самым правильном данном случае создать силами твоего же скрипта на основе анализа списка нормальный json и отправить его серверу. Ну то есть создать массив, в нем хранить элементы списка, соответсвенно отслеживать изменение списка, как то так.
>На количество кода на конкретном ЯП тоже смотреть бессмысленно, потому что больше всего кода до сих пор написано на COBOL.
Ну так хуле, чем в итоге будем измерять ЯП? Попугаями?
Ты не понял. Он решил, что ты тут с пхп гавном разбираешься и на автомате унизил с сажей. Это залетный пидор из хаскель треда, он тут часто появляется.
Добавляй по 3 поля с номерами чтобы их связать, в чем проблема?
input director[0] = 'Кубрик'
input name[0] = 'Одиссея'
input year[0] = '2004'
input director[1] = 'Лукас'
...
Алсо, ты же эти данные скорее всего вводишь в поля ввода. Что тебе мешает эти поля поместить в форму чтобы не надо было добавлять скрытые поля?
Алсо еще вариант закодировать все это в JSON и слать одним полем.
>>420392
При чем тут PHP? При использовании другого серверного языка вроде Си++ решение потребует меньше кода?
>>420398
> Это говорит о том, что пыходауны чаще остальных практикуют GDD
Ты же сам этот тест на основе гугла и привел в пример, а теперь отрицаешь этот подход. Ну ты смешной.
> больше всего кода до сих пор написано на COBOL.
Пруф? По моему это городская легенда.
> Количество программ (включая сайты, ибо сайт — тоже программа, только запускающаяся через жопу) мне кажется наиболее адекватным индексом.
Тогда веб языки будут в огромном перевесе. Ибо на 1 Си++ программиста приходится человек 50-100 из веба.
> Пидорасы из Sun и Oracle предпочли послать нахуй менеджер памяти ядра, тупо отхавав у него максимум RAM, и перевелосипедить свой менеджер памяти со сборщиком мусора и шлюхами
Если бы ты был чуть умнее и опытнее ты бы понял почему. Сервер не десктоп и лучше всего когда серверное приложение потребляет один и тот же объем памяти. Это позволяет администратору распределить ресурсы и не бояться что сервер баз данных вытолкает сервер приложений в своп. Практиечски все серверные приложения потому потребяют память фиксированно в соответствии с конфигом.
В случае Явы такой подход дает еще возможность выбирать между ускорением работы и объемом памяти: ты можешь тратить меньше памяти но чаще собирать мусор.
Насчет отдачи памяти ядру (и придуманного тобой менеджера памяти ядра), в Линукс это традиционно не принято. Там не так давно появился вызов для отдачи блока памяти (большого) обратно системе, а до этого выделение памяти делалось только в одну сторону через sbrk. Кстати, ява умеет дефрагментировать кучу, что позволяет как я понимаю, в теории более эффективно использовать эту самую память и даже возвращать лишнюю.
> уже на старте в память грузится просто ебическое количество классов и ресурсов.
Это предположение, но может это делается чтобы не было задержек на их загрузку во время работы приложения?
> У Java средства абстракции по гибкости примерно как у C.
Неверно. В Яве есть объекты, коллекции, куча библиотек и не надо описывать одну функцию в 2 файлах (это вообще маразм какой-то, это было сделано 50 лет назад из-за нехватки ресурсов и до сих пор эти убогие покорно пишут по 2 раза одно и то же). И компилируется Ява быстрее так как можно компилировать только изменившийся модуль в то время как убогий Си требует препроцессором собрать все файлы в один огромный, и так для каждого файла. Страшно представить как это работает на боьших проектах.
Да и еще, как я понимаю, в Си толком не работает автодополнение и навигация по коду, кроме может быть каких-нибудь платных IDE, так как там синтаксис к этому не располагает.
Ну и еще там есть препроцессор для отстреливания себе ног.
Не, Ява однозначно лучше. Я когда-то во время учебы на ней что-то писал и писать на ней легче и быстрее даже без IDE.
> scalable robust yoba enterprise solutions
Очевидно там есть свои проблемы, во-первых, большой объем кода и унаследованный код, во-вторых, низкая квалификация сотрудников так как умные ребята в ентерпрайз не идут, к тому же низкая мотивация так как в сообществах вроде /pr к таким сотрудникам поддерживается презрительное отношение. Я не удивлюсь если окажется что средний ентерпрайз программист это какой-нибудь переучившийся менеджер по продажам или клерк, который программирование ненавидит и терпит только ради денег.
Ну а слои абстракции и SOA появляются из-за нежелания разбираться в коде предшественников.
Но на Си все это будет писать во много раз дольше, из-заотстутвия ООП код будет представлять обой несколько километров лапши из функций и глобальных переменных, а приложение написанное низкоквалифицированными сотрудниками будет большую часть времени лежать в сегфолте. У меня такое ощущение что ты не разбираешься в ентерпрайзной разработки и у тебя нет такого опыта. У меня тоже нет, но я умею смотреть с чужой точки зрения.
> на голову branch predictor-у.
Ну вот видно что ты все не можешь выкинуть из головы перестановку байтов. Это близорукость которая помешает видеть проект целиком. вполне возможно что бизнес-требование не поместиться к кеш предиктора, а как можно скорее наладить учет чего-нибудь и интегрироать в корпоративную систему.
Ну и еще раз напомню что тут https://www.techempower.com/benchmarks/ в тесте, имитирующем аспекты работы реального веб приложения, Ява занимает со 2 по 7 место (отставая от 1 места лишь на 15%). Вполне неплохо.
Добавляй по 3 поля с номерами чтобы их связать, в чем проблема?
input director[0] = 'Кубрик'
input name[0] = 'Одиссея'
input year[0] = '2004'
input director[1] = 'Лукас'
...
Алсо, ты же эти данные скорее всего вводишь в поля ввода. Что тебе мешает эти поля поместить в форму чтобы не надо было добавлять скрытые поля?
Алсо еще вариант закодировать все это в JSON и слать одним полем.
>>420392
При чем тут PHP? При использовании другого серверного языка вроде Си++ решение потребует меньше кода?
>>420398
> Это говорит о том, что пыходауны чаще остальных практикуют GDD
Ты же сам этот тест на основе гугла и привел в пример, а теперь отрицаешь этот подход. Ну ты смешной.
> больше всего кода до сих пор написано на COBOL.
Пруф? По моему это городская легенда.
> Количество программ (включая сайты, ибо сайт — тоже программа, только запускающаяся через жопу) мне кажется наиболее адекватным индексом.
Тогда веб языки будут в огромном перевесе. Ибо на 1 Си++ программиста приходится человек 50-100 из веба.
> Пидорасы из Sun и Oracle предпочли послать нахуй менеджер памяти ядра, тупо отхавав у него максимум RAM, и перевелосипедить свой менеджер памяти со сборщиком мусора и шлюхами
Если бы ты был чуть умнее и опытнее ты бы понял почему. Сервер не десктоп и лучше всего когда серверное приложение потребляет один и тот же объем памяти. Это позволяет администратору распределить ресурсы и не бояться что сервер баз данных вытолкает сервер приложений в своп. Практиечски все серверные приложения потому потребяют память фиксированно в соответствии с конфигом.
В случае Явы такой подход дает еще возможность выбирать между ускорением работы и объемом памяти: ты можешь тратить меньше памяти но чаще собирать мусор.
Насчет отдачи памяти ядру (и придуманного тобой менеджера памяти ядра), в Линукс это традиционно не принято. Там не так давно появился вызов для отдачи блока памяти (большого) обратно системе, а до этого выделение памяти делалось только в одну сторону через sbrk. Кстати, ява умеет дефрагментировать кучу, что позволяет как я понимаю, в теории более эффективно использовать эту самую память и даже возвращать лишнюю.
> уже на старте в память грузится просто ебическое количество классов и ресурсов.
Это предположение, но может это делается чтобы не было задержек на их загрузку во время работы приложения?
> У Java средства абстракции по гибкости примерно как у C.
Неверно. В Яве есть объекты, коллекции, куча библиотек и не надо описывать одну функцию в 2 файлах (это вообще маразм какой-то, это было сделано 50 лет назад из-за нехватки ресурсов и до сих пор эти убогие покорно пишут по 2 раза одно и то же). И компилируется Ява быстрее так как можно компилировать только изменившийся модуль в то время как убогий Си требует препроцессором собрать все файлы в один огромный, и так для каждого файла. Страшно представить как это работает на боьших проектах.
Да и еще, как я понимаю, в Си толком не работает автодополнение и навигация по коду, кроме может быть каких-нибудь платных IDE, так как там синтаксис к этому не располагает.
Ну и еще там есть препроцессор для отстреливания себе ног.
Не, Ява однозначно лучше. Я когда-то во время учебы на ней что-то писал и писать на ней легче и быстрее даже без IDE.
> scalable robust yoba enterprise solutions
Очевидно там есть свои проблемы, во-первых, большой объем кода и унаследованный код, во-вторых, низкая квалификация сотрудников так как умные ребята в ентерпрайз не идут, к тому же низкая мотивация так как в сообществах вроде /pr к таким сотрудникам поддерживается презрительное отношение. Я не удивлюсь если окажется что средний ентерпрайз программист это какой-нибудь переучившийся менеджер по продажам или клерк, который программирование ненавидит и терпит только ради денег.
Ну а слои абстракции и SOA появляются из-за нежелания разбираться в коде предшественников.
Но на Си все это будет писать во много раз дольше, из-заотстутвия ООП код будет представлять обой несколько километров лапши из функций и глобальных переменных, а приложение написанное низкоквалифицированными сотрудниками будет большую часть времени лежать в сегфолте. У меня такое ощущение что ты не разбираешься в ентерпрайзной разработки и у тебя нет такого опыта. У меня тоже нет, но я умею смотреть с чужой точки зрения.
> на голову branch predictor-у.
Ну вот видно что ты все не можешь выкинуть из головы перестановку байтов. Это близорукость которая помешает видеть проект целиком. вполне возможно что бизнес-требование не поместиться к кеш предиктора, а как можно скорее наладить учет чего-нибудь и интегрироать в корпоративную систему.
Ну и еще раз напомню что тут https://www.techempower.com/benchmarks/ в тесте, имитирующем аспекты работы реального веб приложения, Ява занимает со 2 по 7 место (отставая от 1 места лишь на 15%). Вполне неплохо.
Ах да, насчет этого твоего Си. Говорят большие проекты вроде Фаерфокса, вебкита или Опенофиса надо несколько дней компилировать? Как в таких условиях вообще заниматься разработкой?
>>420408
Я вижу, код работает и получается победитель, но выглядит он пока ужасно. Надо много чего переделать, но зато в итоге он будет гораздо аккуратнее. Давай разберемся, что именно не так.
Вывод надо бы покрасивее сделать. Тебе надо предусмотреть скажем что под одну клетку поля мы отводим ровно 5 символов и добивать пробелами до нужного числа. У тебя есть padRight но что-то она не работает как надо.
Может быть даже стоит отвести под клетку 2 строчки: на одной число, на другой игроки. Также, можно обозначать на поле переходы с помощью букв (2 клетки связанные переходом помечаем одной и той же буквой).
Если ты сделаешь вывод в несколько строк, то надо будет наверно сделать несколько функций вроде вывестиПервуюСтрочку, вывестиВторуюСтрочку.
Подумай, в общем, как это отобразить чтобы вся нужная информация поместилась.
Не используй глобальные переменные. Все, что нужно, можно передать и так в функцию. Ну или сделать объект класса Game который будет хранить в себе нужные функции.
Насчет переходов с клетки на клетку: плохо что ты сделал все огромным свичем. Ведь мы не можем легко менять эти переходы и не можем их отображать. Лучше бы сделать массив переходов и проверять по нему. Массив может выглядеть например так:
$jumps = array(
array('from' => 10, 'to' => 16),
...
);
Более того, непраивльно что координаты переходов описаны внутри игрока. Ведь это не свойство игрока, а свойство карты. Соответственно правильнее поместить их в объект-карту, а игрок будет передавать ей свои координаты и спрашивать куда с них можно перейти.
> $this->x = 2;
> $this->y = 4;
> $this->position = 42;
Как я понимаю, position вычисляется из x и y? Если так, незачем вообще хранить это свойство, надо сделать метод getPosition который будет ее считать. Запомни: меньше свойств — меньше геморроя с их обновлением.
Функция getMove слишком огромная. В ней находится огромный if, из-за чего ее тяжело читать. Надо либо сократить код внутри него либо вынести в отдельный метод. Переделай функцию чтобы она занимала не более 15 строк.
Ну вот пример, как эту функцию можно сделать короче:
move() {
step = случайное число;
сдвинутьсяНа(step);
}
сдвинутьсяНа(step) {
увеличить x;
если x переполнился, увеличить y;
если (карта->можноСделатьпереход) {
сделатьПереход;
}
}
> $zone[$i][$j] = $k++;
Это ненадежно. Лучше вычислять k из i и j.
Если что-то непонятно, справшивай. Если понятно, пиши код.
>>420408
Я вижу, код работает и получается победитель, но выглядит он пока ужасно. Надо много чего переделать, но зато в итоге он будет гораздо аккуратнее. Давай разберемся, что именно не так.
Вывод надо бы покрасивее сделать. Тебе надо предусмотреть скажем что под одну клетку поля мы отводим ровно 5 символов и добивать пробелами до нужного числа. У тебя есть padRight но что-то она не работает как надо.
Может быть даже стоит отвести под клетку 2 строчки: на одной число, на другой игроки. Также, можно обозначать на поле переходы с помощью букв (2 клетки связанные переходом помечаем одной и той же буквой).
Если ты сделаешь вывод в несколько строк, то надо будет наверно сделать несколько функций вроде вывестиПервуюСтрочку, вывестиВторуюСтрочку.
Подумай, в общем, как это отобразить чтобы вся нужная информация поместилась.
Не используй глобальные переменные. Все, что нужно, можно передать и так в функцию. Ну или сделать объект класса Game который будет хранить в себе нужные функции.
Насчет переходов с клетки на клетку: плохо что ты сделал все огромным свичем. Ведь мы не можем легко менять эти переходы и не можем их отображать. Лучше бы сделать массив переходов и проверять по нему. Массив может выглядеть например так:
$jumps = array(
array('from' => 10, 'to' => 16),
...
);
Более того, непраивльно что координаты переходов описаны внутри игрока. Ведь это не свойство игрока, а свойство карты. Соответственно правильнее поместить их в объект-карту, а игрок будет передавать ей свои координаты и спрашивать куда с них можно перейти.
> $this->x = 2;
> $this->y = 4;
> $this->position = 42;
Как я понимаю, position вычисляется из x и y? Если так, незачем вообще хранить это свойство, надо сделать метод getPosition который будет ее считать. Запомни: меньше свойств — меньше геморроя с их обновлением.
Функция getMove слишком огромная. В ней находится огромный if, из-за чего ее тяжело читать. Надо либо сократить код внутри него либо вынести в отдельный метод. Переделай функцию чтобы она занимала не более 15 строк.
Ну вот пример, как эту функцию можно сделать короче:
move() {
step = случайное число;
сдвинутьсяНа(step);
}
сдвинутьсяНа(step) {
увеличить x;
если x переполнился, увеличить y;
если (карта->можноСделатьпереход) {
сделатьПереход;
}
}
> $zone[$i][$j] = $k++;
Это ненадежно. Лучше вычислять k из i и j.
Если что-то непонятно, справшивай. Если понятно, пиши код.
Насчет большого метода getMove. Давай я тебе приведу аналогию с рецептами, как выглядит твой код и как должен выглядеть.
Вот хороший рецепт (как должен выглядеть код):
- налить в кастрюлю литр воды
- положить 200 гр мяса
- насыпать ложку соли
...
А вот как выглядит твой код сейчас, если провести аналогию:
- взять металлическую кастрюлю
- поднести ее к раковине
- поднести руку к ручке крана холодной воды
- повернуть ручку на 180°
- подставить кастрюлю под струю воды
...
То есть надо уметь разбивать большие поледовательности команд на шаги, и выносить подробности в отдельные функции.
Во-первых, friends - это же объект. А bill и steve, получается - свойства объекта? Но что же тогда firstName и lastName? Свойства свойств? И что делает функция list? Я не понимат. Я вообще не понимат, что делает in в for. Может кто доступно объяснить?
>А bill и steve, получается - свойства объекта?
yep
>Но что же тогда firstName и lastName? Свойства свойств?
yep
>Но что же тогда firstName и lastName? Свойства свойств?
выводит свойства friends
>Я вообще не понимат, что делает in в for
http://javascript.ru/for..in
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in
http://deone.com/BlvWit
https://github.com/sqghub/TestHub/blob/master/migrations/m141219_140813_create_tables.php
Что думаешь?
> Ты же сам этот тест на основе гугла и привел в пример
Теги: ad hominem, нерепрезентативная выборка
> > больше всего кода до сих пор написано на COBOL.
> Пруф?
Я бы рад, не будь он весь проприетарным и написанным «под ключ». Но я охотно верю в эту легенду, потому что он неебически многословен, и проекты на нем писались в основном «под ключ», то есть, все стандартные решения велосипедились с нуля.
> Тогда [по количеству программ и сайтов] веб языки будут в огромном перевесе.
Верю. Ибо ебанутая эпоха тормозных веб-приложений.
> Ибо на 1 Си++ программиста приходится человек 50-100 из веба.
А это тут причем?
> Сервер не десктоп и лучше всего когда серверное приложение потребляет один и тот же объем памяти.
А если бы ты был чуть умнее и опытнее, то понимал бы, что если в конфиге (или, еще правильнее, в квотах) прописано «-Xmx:16GB», то это не значит, что JVM не будет потреблять больше 16 GB. Это значит, что она упадёт, если будет пробит потолок в 16 GB. К уёбищности аллокаторов и уебанству кодеров, не могущих объявить память как буфер, это не имеет никакого отношения.
> > уже на старте в память грузится просто ебическое количество классов и ресурсов.
> Это предположение, но может это делается чтобы не было задержек на их загрузку во время работы приложения?
Нет, сама JRE написана в энтерпрайз-стиле с абстрактными фабриками фасолин, так что все эти классы ей нужны для работы.
> В Яве есть объекты, коллекции, куча библиотек и не надо описывать одну функцию в 2 файлах…
…и больше ничего.
> в Си толком не работает автодополнение и навигация по коду
Работает. В C++ и в динамически типизированных ЯП она невозможна в принципе.
> Не, Ява однозначно лучше.
…для scalable enterprise robust yoba solutions. Для пердоления драйверов C таки удобнее.
> > scalable robust yoba enterprise solutions
> Очевидно там есть свои проблемы
Да нет там никаких проблем. Есть просто куча мудаков-недоучек с зашкаливающим ЧСВ, узнавших из GoF про один-два молотка-паттерна, смотрящих на весь мир, как на гвоздь и страдающих синдромом NIH в тяжёлой форме.
> Я не удивлюсь если окажется что средний ентерпрайз программист это какой-нибудь переучившийся менеджер по продажам или клерк, который программирование ненавидит и терпит только ради денег.
Я бы тоже не удивился, но оказывается, что нет. По закону Питера эти пидорасы идут в проджект-менеджеры. Даже не в тимлиды.
> Но на Си все это будет писать во много раз дольше, из-заотстутвия ООП
Нет. Из-за гуманитарного склада ума кодеров. А ООП можно реализовать в любом ЯП, полном по Тьюрингу (по крайней мере, его самое необходимое подмножество).
> Ну вот видно что ты все не можешь выкинуть из головы перестановку байтов.
Если среда разработки не позволяет оптимизировать код на всех уровнях абстракции вплоть до использования кешей процессора, то это не среда, а слабанная в срочном порядке на коленке студентом-гуманитарием за еду или взятая с GitHub-оподобной помойки нахуяченная чисто из спортивного интереса, без всякой мысли о её сопровождении или вообще каком-либо использовании запускалка для софта.
> Ты же сам этот тест на основе гугла и привел в пример
Теги: ad hominem, нерепрезентативная выборка
> > больше всего кода до сих пор написано на COBOL.
> Пруф?
Я бы рад, не будь он весь проприетарным и написанным «под ключ». Но я охотно верю в эту легенду, потому что он неебически многословен, и проекты на нем писались в основном «под ключ», то есть, все стандартные решения велосипедились с нуля.
> Тогда [по количеству программ и сайтов] веб языки будут в огромном перевесе.
Верю. Ибо ебанутая эпоха тормозных веб-приложений.
> Ибо на 1 Си++ программиста приходится человек 50-100 из веба.
А это тут причем?
> Сервер не десктоп и лучше всего когда серверное приложение потребляет один и тот же объем памяти.
А если бы ты был чуть умнее и опытнее, то понимал бы, что если в конфиге (или, еще правильнее, в квотах) прописано «-Xmx:16GB», то это не значит, что JVM не будет потреблять больше 16 GB. Это значит, что она упадёт, если будет пробит потолок в 16 GB. К уёбищности аллокаторов и уебанству кодеров, не могущих объявить память как буфер, это не имеет никакого отношения.
> > уже на старте в память грузится просто ебическое количество классов и ресурсов.
> Это предположение, но может это делается чтобы не было задержек на их загрузку во время работы приложения?
Нет, сама JRE написана в энтерпрайз-стиле с абстрактными фабриками фасолин, так что все эти классы ей нужны для работы.
> В Яве есть объекты, коллекции, куча библиотек и не надо описывать одну функцию в 2 файлах…
…и больше ничего.
> в Си толком не работает автодополнение и навигация по коду
Работает. В C++ и в динамически типизированных ЯП она невозможна в принципе.
> Не, Ява однозначно лучше.
…для scalable enterprise robust yoba solutions. Для пердоления драйверов C таки удобнее.
> > scalable robust yoba enterprise solutions
> Очевидно там есть свои проблемы
Да нет там никаких проблем. Есть просто куча мудаков-недоучек с зашкаливающим ЧСВ, узнавших из GoF про один-два молотка-паттерна, смотрящих на весь мир, как на гвоздь и страдающих синдромом NIH в тяжёлой форме.
> Я не удивлюсь если окажется что средний ентерпрайз программист это какой-нибудь переучившийся менеджер по продажам или клерк, который программирование ненавидит и терпит только ради денег.
Я бы тоже не удивился, но оказывается, что нет. По закону Питера эти пидорасы идут в проджект-менеджеры. Даже не в тимлиды.
> Но на Си все это будет писать во много раз дольше, из-заотстутвия ООП
Нет. Из-за гуманитарного склада ума кодеров. А ООП можно реализовать в любом ЯП, полном по Тьюрингу (по крайней мере, его самое необходимое подмножество).
> Ну вот видно что ты все не можешь выкинуть из головы перестановку байтов.
Если среда разработки не позволяет оптимизировать код на всех уровнях абстракции вплоть до использования кешей процессора, то это не среда, а слабанная в срочном порядке на коленке студентом-гуманитарием за еду или взятая с GitHub-оподобной помойки нахуяченная чисто из спортивного интереса, без всякой мысли о её сопровождении или вообще каком-либо использовании запускалка для софта.
> Ах да, насчет этого твоего Си. Говорят большие проекты вроде Фаерфокса, вебкита или Опенофиса надо несколько дней компилировать? Как в таких условиях вообще заниматься разработкой?
Компилируется только один раз. Потом просто перекомпилируются изменившиеся модули.
>несколько дней
Бред, полная сборка любого из названных тобой проектов на обычной домашней ЭВМ займёт не больше нескольких часов, не говоря уже о том, что билд-серверы куда мощнее обычных ПК и что по ходу разработки полностью проекты никто не пересобирает без особой необходимости.
О, крутая штука. Только я бы еще добавил пояснение между формой и кнопкой о том, что произойдет при нажатии кнопки. Например:
> После нажатия кнопки ваш код будет протестирован на правильность.
или, может стоит написать перед формой что в коде должна быть определенная функция. Или стоит сделать проверку на наличие функции и выводить предупреждение вроде такого:
> Ваш код должен состоять из функции с именем sequence. Именно она будет тестироваться.
Или может добавить ссылку «как проверяется код» раскрывающую блок с пояснениями.
Так как люди могут туда вписать что угодно, например код с console.log и не пониамть, почему не работает. Ну и когда первый раз открываешь не очень ясно что именно надо сделать.
И я бы сделал сигнализацию об ошибках более явной — например добавил галочки/крестик перед пунктом при правильном/неправильном прохождении теста (это можно сделать даже css через generated content). А то не очень ясно что значит результат.
Для исключений хорошо бы выводить информацию о нем, а не просто «произошла какая-то ошибка»:
> encountered a declaration exception
В цифры 1 2 3 4 трудно попасть мышью, я бы добавил к ним невидимый паддинг справа/слева который тоже кликабелен и делает площадь ссылки больше. Чтобы было видно что паддинг относится к ссылке можно подсвечивать его при наведении.
Если вдруг ты хочешь чтобы JS код подсвечивался, то можно попробовать прикрутить CodeMirror или что-то похожее, только там надо все лишнее отключить.
Более подробно я наверно позже проверю (я вижу там код какой-то есть), тут у меня перед Новым годом по работе завал и другие дела.
Ну и наверно я ссылку на эту форму потом в задачи добавлю.
Но вообще, очень хорошо сделано.
О, крутая штука. Только я бы еще добавил пояснение между формой и кнопкой о том, что произойдет при нажатии кнопки. Например:
> После нажатия кнопки ваш код будет протестирован на правильность.
или, может стоит написать перед формой что в коде должна быть определенная функция. Или стоит сделать проверку на наличие функции и выводить предупреждение вроде такого:
> Ваш код должен состоять из функции с именем sequence. Именно она будет тестироваться.
Или может добавить ссылку «как проверяется код» раскрывающую блок с пояснениями.
Так как люди могут туда вписать что угодно, например код с console.log и не пониамть, почему не работает. Ну и когда первый раз открываешь не очень ясно что именно надо сделать.
И я бы сделал сигнализацию об ошибках более явной — например добавил галочки/крестик перед пунктом при правильном/неправильном прохождении теста (это можно сделать даже css через generated content). А то не очень ясно что значит результат.
Для исключений хорошо бы выводить информацию о нем, а не просто «произошла какая-то ошибка»:
> encountered a declaration exception
В цифры 1 2 3 4 трудно попасть мышью, я бы добавил к ним невидимый паддинг справа/слева который тоже кликабелен и делает площадь ссылки больше. Чтобы было видно что паддинг относится к ссылке можно подсвечивать его при наведении.
Если вдруг ты хочешь чтобы JS код подсвечивался, то можно попробовать прикрутить CodeMirror или что-то похожее, только там надо все лишнее отключить.
Более подробно я наверно позже проверю (я вижу там код какой-то есть), тут у меня перед Новым годом по работе завал и другие дела.
Ну и наверно я ссылку на эту форму потом в задачи добавлю.
Но вообще, очень хорошо сделано.
>Ну и наверно я ссылку на эту форму потом в задачи добавлю.
Мы сделаем свой кодакадеми, с аниме и залетными с хаскельтреда?
А, еще, «неправильно» пишется слитно.
>>420538
В объекте (или хеше, словаре) можно хранить что угодно, в том числе другой объект. То есть свойством может быть не только число или строка, но и другой объект, массив, функция. Посмотри на такой код:
// делаем один объект
var person = { name: 'Ivan', age: 20 };
// делаем второй объект и помещаем внутрь него первый
var smth = { man: person };
// Делаем массив и помещаем внутрь него person
var arr = [ person ];
// обращаемся к разным полям так:
person.name
person['name']
smth.man.name
smth.man.age
arr[0].name
arr[0]['name']
Ну и хочу тебе посоветовать параллельно читать сайт learn.javascript.ru гле вроде неплохо все объясняетя. И могу также предложить свои задачки на JS: https://gist.github.com/codedokode/ce30e7a036f18f416ae0
Проверить первые 4 можно тут: http://dkab.github.io/jasmine-tests
> Я вообще не понимат, что делает in в for.
for .. in это цикл по всем свойствам объекта. Он выполняется столько раз сколько есть свойств у объекта (вложенные не считаютя, только свойства первого уровня так сказать), и в переменную firstName каждый раз кладется имя свойства. ну например
for (k in person) {
console.log(k);
}
Выведет 2 строки (не обязательно в том же порядке, порядок может быть любой):
name
age
> И что делает функция list?
Выводит ключи объекта friend, то есть bill и steve
Если на кодеакадеми непонятно, читай параллельно learn.javascript.ru
А, еще, «неправильно» пишется слитно.
>>420538
В объекте (или хеше, словаре) можно хранить что угодно, в том числе другой объект. То есть свойством может быть не только число или строка, но и другой объект, массив, функция. Посмотри на такой код:
// делаем один объект
var person = { name: 'Ivan', age: 20 };
// делаем второй объект и помещаем внутрь него первый
var smth = { man: person };
// Делаем массив и помещаем внутрь него person
var arr = [ person ];
// обращаемся к разным полям так:
person.name
person['name']
smth.man.name
smth.man.age
arr[0].name
arr[0]['name']
Ну и хочу тебе посоветовать параллельно читать сайт learn.javascript.ru гле вроде неплохо все объясняетя. И могу также предложить свои задачки на JS: https://gist.github.com/codedokode/ce30e7a036f18f416ae0
Проверить первые 4 можно тут: http://dkab.github.io/jasmine-tests
> Я вообще не понимат, что делает in в for.
for .. in это цикл по всем свойствам объекта. Он выполняется столько раз сколько есть свойств у объекта (вложенные не считаютя, только свойства первого уровня так сказать), и в переменную firstName каждый раз кладется имя свойства. ну например
for (k in person) {
console.log(k);
}
Выведет 2 строки (не обязательно в том же порядке, порядок может быть любой):
name
age
> И что делает функция list?
Выводит ключи объекта friend, то есть bill и steve
Если на кодеакадеми непонятно, читай параллельно learn.javascript.ru
> \twhile ($amount >= $nominal) {
> $amount -= $nominal;
Повторяющееся вычитание заменяется делением (а сложение — умножением), забыл?
Избавься от внутреннего цикла while.
> после небольшого гугления начал делать простым жадным перебором:
Для простого вариант его хватит. Для сложного гугли «задача сдача банкомат» или «задача о ранце»
>>420557
Ну норм. Я вижу ты Concrete TI реализовал? ну ок, давай посмотрим что выйдет.
Главное чтобы ты из этого извлек понимание какие есть способы реализовать наследование и какие у каждого плюсы и минусы и мог от себя все это рассказать (а не пересказывать учебник).
Ну и отучайся все же от переделок миграций. Что закоммичено, не вырубишь и топором.
Напомню также что в SQL при создании таблиц можно указывать комментарии как к полям, так и к таблицам там где что-то неочевидно.
Например для погрешности можно прокомментировать что это погрешность и в чем она задается — абсолютно или в процентах.
> name` VARCHAR(6500)
Издеваешься? Давай более реалистичное значение
> `added_date` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
По моему по дефолту проставляется только колонка типа TIMESTAMP так как TIMESTAMP привязан к часовому поясу а DATETIME нет. Изучи-ка различия между TIMESTAMP и DATETIME.
> `allow_errors` BOOLEAN,
нужно добавлять NOT NULL DEFAULT X а то у тебя получается 3 значения для поля
> `type` INT(11) UNSIGNED NOT NULL,
Используй ENUM. Что-то у меня ощущение что ты плохо знаешь типы MySQL, перечитай-ка:
http://dev.mysql.com/doc/refman/5.0/en/data-types.html (англ)
http://phpclub.ru/mysql/doc/column-types.html
Дальше тогда модель делай, с учетом всех связей, а потом к этой модели интерфейс для редактирования теста.
> \twhile ($amount >= $nominal) {
> $amount -= $nominal;
Повторяющееся вычитание заменяется делением (а сложение — умножением), забыл?
Избавься от внутреннего цикла while.
> после небольшого гугления начал делать простым жадным перебором:
Для простого вариант его хватит. Для сложного гугли «задача сдача банкомат» или «задача о ранце»
>>420557
Ну норм. Я вижу ты Concrete TI реализовал? ну ок, давай посмотрим что выйдет.
Главное чтобы ты из этого извлек понимание какие есть способы реализовать наследование и какие у каждого плюсы и минусы и мог от себя все это рассказать (а не пересказывать учебник).
Ну и отучайся все же от переделок миграций. Что закоммичено, не вырубишь и топором.
Напомню также что в SQL при создании таблиц можно указывать комментарии как к полям, так и к таблицам там где что-то неочевидно.
Например для погрешности можно прокомментировать что это погрешность и в чем она задается — абсолютно или в процентах.
> name` VARCHAR(6500)
Издеваешься? Давай более реалистичное значение
> `added_date` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
По моему по дефолту проставляется только колонка типа TIMESTAMP так как TIMESTAMP привязан к часовому поясу а DATETIME нет. Изучи-ка различия между TIMESTAMP и DATETIME.
> `allow_errors` BOOLEAN,
нужно добавлять NOT NULL DEFAULT X а то у тебя получается 3 значения для поля
> `type` INT(11) UNSIGNED NOT NULL,
Используй ENUM. Что-то у меня ощущение что ты плохо знаешь типы MySQL, перечитай-ка:
http://dev.mysql.com/doc/refman/5.0/en/data-types.html (англ)
http://phpclub.ru/mysql/doc/column-types.html
Дальше тогда модель делай, с учетом всех связей, а потом к этой модели интерфейс для редактирования теста.
Кодеакадеми? Судя по комменту анона выше, объясняют там так себе. Мы сделаем гораздо лучше. только вот инвестиции многомиллионные и известность в отличие от них мы не получим
>Мы сделаем гораздо лучше.
Так-то у нас уже лучше!
Ну и объясняют там нормально. Просто в силу того, что задания проверяет не человек, а компьютер, задания приходится делать в формате теста, что накладывает целый ряд ограничений и тележку нюансов подкидывает. Один из нюансов - достаточно сомнительная ценность педагогического тестирования для отработки практических навыков.
>Главное чтобы ты из этого извлек понимание какие есть способы реализовать наследование и какие у каждого плюсы и минусы и мог от себя все это рассказать (а не пересказывать учебник).
Самое смешное, что наследования у меня то и нет. А вообще эти три паттерна достаточно простые для понимания.
>Ну и отучайся все же от переделок миграций. Что закоммичено, не вырубишь и топором.
Я понимаю, но я же не меняю базу данных, а делаю лишь первый скелет. Уже после перейду на миграции.
>Издеваешься? Давай более реалистичное значение
Я, честно говоря, не знаю, какое взять.
>По моему по дефолту проставляется только колонка типа TIMESTAMP так как TIMESTAMP привязан к часовому поясу а DATETIME нет.
В uppu у меня тоже было `date` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP. Проставляется она.
>нужно добавлять NOT NULL DEFAULT X а то у тебя получается 3 значения для поля
Оу, я как-то забыл, что еще и нуль вставить можно.
>Дальше тогда модель делай, с учетом всех связей
Да там связей на десять строчек кода, я сделал уже.
>а потом к этой модели интерфейс для редактирования теста.
Я сейчас думаю над тем, как сделать вывод теста для правки, после его отправки на сервер и не прохождения валидации. Но у меня там отвратительно вышла форма через кривой яваскрипт, так что я почти в тупике здесь. Может быть посоветуешь, как лучше выводить форму при создании теста?
> Самое смешное, что наследования у меня то и нет.
Почему? Видно 3 типа ответов, которые явно наследуются от общего предка. Не знаю, как ты это в коде будешь реализовывать, посмотрим.
> Я, честно говоря, не знаю, какое взять.
Ну под заголовок можно отвести 200 символов с учетом того что больше 150 там вряд ли будет. Ну можно попробовать придумать какое-нибудь длинное название типа
> Электродинамика и переходные незатухающие процессы в незамкнутом волноводе с фрауэнгоферовским рассеянием при температуре абсолютного нуля
Но вообще, я думаю что так длинно вряд ли кто-то стал бы писать.
> Может быть посоветуешь, как лучше выводить форму при создании теста?
Храни данные в элементах форм и используй поля с ключами:
input type=hidden name="questionId[1]" value="100"
textarea name="questionName[1]" value="текст вопроса 1"
input type=radio name="questionType[1]" ...
Ну или может questions[name][1]
PHP поддерживает массивы но стоит проверить не упремся ли мы в ограничение на число элементов в POST и не будем ли терять из-за этого данные.
А добавлять/удалять/перетаскивать вопросы яваскриптом конечно (но если хочется хардкора может попробовать сделать фоллбек на отправку обычной формы при отсутствии/ошибке в JS).
Это называется стемминг — приведение слова к основе. Стеммеры бывают на основе алгоритма (гугли стеммер Портера для русского) которые просто отрезают окончания по шаблону или умные на основе словаря - гугли phpmorphy.
Стемминг встроен в поисковые движки типа sphinx
Подробнее
google: стемминг
google: phpmorphy
http://aot.ru/
http://habrahabr.ru/post/49421/
> то есть если в тексте есть слова "база", "базы" и "базами"
Еще есть «базочка», «базушка», «базонька» и прочие забавные формы.
О, спасибо, это то что я давно искал! Совет просто бесценный!
>Храни данные в элементах форм и используй поля с ключами:
Пока что все так и выглядит.
>PHP поддерживает массивы но стоит проверить не упремся ли мы в ограничение на число элементов в POST и не будем ли терять из-за этого данные.
А сколько это ограничение? И что нас спасет в этом случае? Не аякс же?
Ну и да. Я в ожидании критики моего яваскрипта.
http://php.net/manual/ru/info.configuration.php#ini.max-input-vars
http://php.net/manual/ru/info.configuration.php#ini.max-input-nesting-level (это вроде не грозит)
Проверить лучше всего экспериментально сгенерировав и отправив гигантскую форму.
Код проверю но уже наверно завтра.
>http://php.net/manual/ru/info.configuration.php#ini.max-input-nesting-level (это вроде не грозит)
Я планирую максимальную вложенность ~3.
>Вообще, работа с формами обычно строится по такому алгоритму. Он позволяет при ошибке снова показать форму с введенными значениями:
>
>------------
>
>$values = значения по умолчанию (пустые);
>$errors = пустой массив;
>
>Если (форма отправлена через POST) {
>Читаем значения полей в $values;
>
>Если (все заполнено верно) {
>Делаем требуемое действие (например вставляем запись в БД);
>Редиректим куда-нибудь;
>Выходим;
>}
>
>Кладем ошибки в $errors;
>}
>
>Выводим форму($values, $errors);
>
>-------------
Подскажи как здесь быть, конкретно вот здесь:
>Если (все заполнено верно) {
Делаю вот таким вот образом:
$name = preg_match('/^[\\w\\.]+$/', $_FILES["file"]["name"]) ? $_FILES["file"]["name"] : '';
$extension = $upload->getExtension($_FILES["file"]["name"]) ? $upload->getExtension($_FILES["file"]["name"]) : '';
$size = (($_FILES["file"]["size"] / 1024) < 20000000) ? $size : '';
$temp = isset($_FILES["file"]["tmp_name"]) ? $_FILES["file"]["tmp_name"] : '';
Дальше не знаю как сделать по лаконичней, либо проверять самостоятельно, складывая значения в массив а потом искать пустые значения, либо пилить новую функцию вида проверитьЗначения($name, $extension, $size, $temp) где выполняется тоже самое и возвращается массив $errors. Все это очень не красиво, на мой взгляд. Посоветуй как сделать красивей и понятней.
>Вообще, работа с формами обычно строится по такому алгоритму. Он позволяет при ошибке снова показать форму с введенными значениями:
>
>------------
>
>$values = значения по умолчанию (пустые);
>$errors = пустой массив;
>
>Если (форма отправлена через POST) {
>Читаем значения полей в $values;
>
>Если (все заполнено верно) {
>Делаем требуемое действие (например вставляем запись в БД);
>Редиректим куда-нибудь;
>Выходим;
>}
>
>Кладем ошибки в $errors;
>}
>
>Выводим форму($values, $errors);
>
>-------------
Подскажи как здесь быть, конкретно вот здесь:
>Если (все заполнено верно) {
Делаю вот таким вот образом:
$name = preg_match('/^[\\w\\.]+$/', $_FILES["file"]["name"]) ? $_FILES["file"]["name"] : '';
$extension = $upload->getExtension($_FILES["file"]["name"]) ? $upload->getExtension($_FILES["file"]["name"]) : '';
$size = (($_FILES["file"]["size"] / 1024) < 20000000) ? $size : '';
$temp = isset($_FILES["file"]["tmp_name"]) ? $_FILES["file"]["tmp_name"] : '';
Дальше не знаю как сделать по лаконичней, либо проверять самостоятельно, складывая значения в массив а потом искать пустые значения, либо пилить новую функцию вида проверитьЗначения($name, $extension, $size, $temp) где выполняется тоже самое и возвращается массив $errors. Все это очень не красиво, на мой взгляд. Посоветуй как сделать красивей и понятней.
Сделай себе отдельный класс для этой формы. И отдельные методы для получения полей из поста и валидации.
И будет у тебя что-то вроде.
форма = новая форма
Если (это пост) {
форма->взять поля из пост;
ошибки = форма->валидация
Если (все верно) {бла бла бла}
}
Вывод формы (форма, ошибки);
Это снова я. Оказывается, двухмерный массив можно отправлять формой с клиентской стороны таким образом:
<input type="hidden" name="list_name[' + i + '][]" value="' + currentListElementsValue + '">
Где i — автоувеличивающийся индекс цикла. То есть, вместо list_name[], как обычно принято делать при комбинировании информации одного типа, в начале вставляется индекс, а потом вот эта фича PHP с добавлением квадратных скобок в конце. Я понятия не имел, что так можно делать.
Посчитал два банка, потом понял, что на 0 умножать нельзя. С третьим банком проблема. Сейчас думаю, как её решить.
Начал проверять, а оно, скорее всего, не считает проценты.
http://ideone.com/AAWmgo
Не понимаю, что там не так.
Ну да, ведь проценты через запятую назначил. Переделал задачу, проверьте, если не влом.
?
я на земляшке
В гривнах?
Работать на работе по 9 часов в день, причем это должна быть не говноработа. А у тебя должен быть просто поток постепенноусложняющихся задач на ней, и так же крутой коллектив, в котором уже будут сидеть дружелюбные к тебе гуру пхп и смежных областей, к которым ты будешь обращаться каждый день и спрашивать у них кучу всякой хуйни. Далее после прихода домой ты будешь читать хорошие годные технические книжки и статьи и делать параллельно какие-нибудь штуки, осваивать новые для себя технологии. Сон и повторять по новой 6 дней в неделю. Через 9 месяцев ты все это дропаешь и уебываешь в ДС, там в рассказе с умными людьми показываешь на реальных примерах какой ты ниибаться спец и получаешь свои 100к к след зиме.
Жаль. Я уже было вдохновился.
>>420801
Плюс/минус и карму. Добавление картинок и видео с ютуба. Алсо, советую залить код на гитхаб и показать нам для проверки.
>>420695
Этот анон >>420737 примерно прав. Хотя сумма, которую ты указал, стремительно обесценивается, но вряд ли работодатель даст такую зарплату человеку без опыта.
Открой сайт с вакансиями вроде hh.ru, geekjob, brainstorage и посмотри какие требования предъявляются к разработчикам (также можешь в /wrk открыть одеск-тред и почитать мнения там).
>>420729
Нет такой книги. Есть книги по основам PHP, многие плохие и устаревшие, есть неплохие книги которые указаны в ОП-посте, есть сайт phptherightway. Но книги как написать CMS нет, единственный способ это выучить php и разобрать код каких-нибудь существующих CMS вроде вордпресса.
Да и зачем вдруг тебе понабобилось писать свою? Их же сотни уже написаны. И CMS это инструмент для непрограммистов. для тех кто сайты делает выбирая галочки в админке. Программисты делают сайты на фреймворках вроде Silex, Yii2, Symfony 2.
>>420670
> PHP Notice: Undefined variable: paymentTotal in /home/DKY5mW/prog.php on line 10
У тебя ошибка - обращение к несуществующей переменной. Надо ее исправить. В остальном вроде выглядит нормально.
>>420669
Это подробнее расписано на learn.javascript.ru. В переменную key на каждом шаге цикла помещается имя очередного ключа (свойства) объекта.
>>420607
> Подскажи как здесь быть, конкретно вот здесь:
> >Если (все заполнено верно) {
> Делаю вот таким вот образом:
Не надо писать все длинной портянкой. Сделай проверку через функцию или метод объекта. Чтобы это выглядело вроде
if (validateForm(...))
или
if ($form->validate(...))
Проверка правильности файла наверно будет из нескольких шагов вроде:
Если (файл не загрузился) то ...
Если (файл слишком большой ) то ...
Если (файл не того типа) то ...
Сохраняем файл.
разумеется, эта проверка должна быть в отдельной функции или методе объекта. И конечно хорошо бы написать код так, чтобы эту же фнукцию можно было использовать где-то еще, чтобы она была универсальной.
Ничего страшного, если ты где-то ошибешься, это всегда можно поправить.
>>420801
Плюс/минус и карму. Добавление картинок и видео с ютуба. Алсо, советую залить код на гитхаб и показать нам для проверки.
>>420695
Этот анон >>420737 примерно прав. Хотя сумма, которую ты указал, стремительно обесценивается, но вряд ли работодатель даст такую зарплату человеку без опыта.
Открой сайт с вакансиями вроде hh.ru, geekjob, brainstorage и посмотри какие требования предъявляются к разработчикам (также можешь в /wrk открыть одеск-тред и почитать мнения там).
>>420729
Нет такой книги. Есть книги по основам PHP, многие плохие и устаревшие, есть неплохие книги которые указаны в ОП-посте, есть сайт phptherightway. Но книги как написать CMS нет, единственный способ это выучить php и разобрать код каких-нибудь существующих CMS вроде вордпресса.
Да и зачем вдруг тебе понабобилось писать свою? Их же сотни уже написаны. И CMS это инструмент для непрограммистов. для тех кто сайты делает выбирая галочки в админке. Программисты делают сайты на фреймворках вроде Silex, Yii2, Symfony 2.
>>420670
> PHP Notice: Undefined variable: paymentTotal in /home/DKY5mW/prog.php on line 10
У тебя ошибка - обращение к несуществующей переменной. Надо ее исправить. В остальном вроде выглядит нормально.
>>420669
Это подробнее расписано на learn.javascript.ru. В переменную key на каждом шаге цикла помещается имя очередного ключа (свойства) объекта.
>>420607
> Подскажи как здесь быть, конкретно вот здесь:
> >Если (все заполнено верно) {
> Делаю вот таким вот образом:
Не надо писать все длинной портянкой. Сделай проверку через функцию или метод объекта. Чтобы это выглядело вроде
if (validateForm(...))
или
if ($form->validate(...))
Проверка правильности файла наверно будет из нескольких шагов вроде:
Если (файл не загрузился) то ...
Если (файл слишком большой ) то ...
Если (файл не того типа) то ...
Сохраняем файл.
разумеется, эта проверка должна быть в отдельной функции или методе объекта. И конечно хорошо бы написать код так, чтобы эту же фнукцию можно было использовать где-то еще, чтобы она была универсальной.
Ничего страшного, если ты где-то ошибешься, это всегда можно поправить.
for это не функция. for это оператор.
Функция это то что определено со словом function, например:
function x(y) {
return y + 1;
}
>fopen это функция или оператор?
>Руководство по PHP > Справочник функций > Расширения для работы с файловой системой > Функции для работы с файловой системой > Файловая система
Сложный был вопрос, да.
Я уже изменил его, но там, помимо всего прочего было описание класса:
class test{
public function test(){
echo "ТЕСТ";
}
}
Сейчас сделал еще один отдельный файл под класс и все работает, однако я не понимаю, почему не работало когда класс был в PDO.
>Я уже изменил его, но там, помимо всего прочего было описание класса:
Думаю, что проблема где-то здесь.
Но по адресу yii/requirements/index.php высветило:
Проверка на соответствие требованиям Yii
И другое в таком же стиле, проблема с кодировкой видимо, где надо исправить, не подскажете?
Локалка это:php my squl apache
Спасибо.
Ну а когда ты будешь браться? После того, как запорешь несколько проектов на работе? Когда они будут прогорать по срокам, а ты не будешь мочь реализовывать какие бы то ни было изменения в ТЗ, когда проект уже будет готов? Учи ООП и фреймворки, да. Можешь впрочим учить один битрикс и всё, так мало что надо знать, но лучше ничего кроме сайтов-визиток, блогов и максимально стандартных интерет-магазинов на нём не делать. И какие, блядь, в синтаксисе глубины могут быть?
Ооп - это не синтаксис, ооп - это парадигма. Он наоборот может в синтаксис, но не может в парадигму.
> Своим современным значением в научно-технической области термин «парадигма» обязан, по-видимому, Томасу Куну и его книге «Структура научных революций»
лолблядь
по делу кто может ответить?
Первую строчку не осилил что ли?
>Клуб любителей изучать PHP 41
>что есть "парадигма"?
Вся суть всего.
> Клуб любителей изучать PHP 41
А вы никак не связаны с этим клубом https://2ch.hk/biz/res/636913.html ?
У меня там членский билет.
Модели: вот тут вот есть такой код
https://github.com/sqghub/TestHub/blob/master/models/Question.php#L54
Ты там в цикле вставляешь записи по одной. Это стоит хотя бы в транзакцию завернуть, чтобы не было полусохраненных ответов. Ну и еще, ты не удаляешь старые вопросы по моему. Ну и конечно надо бы посмотреть, а не умеет ли Юи сам сохранять и удалять связанные записи, может ты пишешь то что уже сделано.
Вот тут https://github.com/yiisoft/yii2/blob/master/docs/guide/db-active-record.md#working-with-relationships описаны функции link/unlink для создания связей. Может они подойдут?
Также написано вроде возможность подключить транзакции уже есть: https://github.com/yiisoft/yii2/blob/master/docs/guide/db-active-record.md#transactional-operations (может это даже включено по умолчанию).
В идеале конечно надо бы сохранять только изменившиеся, но с ActiveRecord по моему это малореально (надо как-то добавлять флаг наличия изменений), а вот та же доктрина это умеет.
Далее, вот тут ты определяешь отношение в зависимости от типа вопроса:
https://github.com/sqghub/TestHub/blob/master/models/Question.php#L24
Будет ли это работать, если мы загрузили вопрос из БД, поменяли его тип, поменяли ответы и сохраняем? Это все надо проверить. В идеале, этот класс стоит покрыть тестами для таких случаев (например на phpunit, если ты с ним знаком). Ну или хотя бы вручную пока протестировать.
Еще, ты определяешь свойство
> private $answers = [ ];
Но как я понимаю из документации https://github.com/yiisoft/yii2/blob/master/docs/guide/db-active-record.md#working-with-relational-data там обращение к answers должно перехватываться Юи, и добавляя поле ты возможно ломаешь этот механизм.
В общем, опять же надо проверить, работает ли загрузка вопроса из БД, ответов, и их удаление и сохранение. Там документация скудная, так что если что сразу лезь в исходники Юи и смотри там.
> https://github.com/sqghub/TestHub/blob/master/controllers/TestController.php#L33
Я бы вынес questionTypes и questionTypeLabels в модель, то есть можно сделать метод getAllQuestionTypes и например getQuestionLabel($type). Тогда эти названия можно будет в нескольких местах использовать.
> return $this->render('createTest.twig', [
Это у тебя скопипастено 2 раза, лучше сделать без копипасты, например:
если (пост) {
обрабатываем пост данные;
редиректим если ок;
}
выводим форму;
https://github.com/sqghub/TestHub/blob/master/controllers/TestController.php#L60
> $question = new Question( );
Ты каждый раз пересоздаешь вопросы, хотя при редактировании теста наверно надо будет не создавать новый вопрос а править существующий (чтобы не менялся его id). Для этого в POST данных при редактировании стоит передавать тот самый id вопроса.
> as $questionNumber => $formQuestion
Советую номер передавать отдельным скрытым или видимым инпутом — а то ты намучаешься при переупорядочивании вопросов переименовывать все эти поля.
Насчет правильного ответа, надо понимать что там где множественный ответ может быть выбрано несколько правильных ответов.
По яваскрипту:
Тут есть другие варианты решения. Например, можно посмотреть в сторону knockout. Это шаблонизатор с дата биндингом, то есть при изменении например типа вопроса в объекте, он сам будет менять DOM и не нужен будет весь этот код с кучей getElementById.
Второй вариант использовать jQuery ради экономии времени на код работы с DOM — он будет чуть короче (но суть особо не поменяется).
Пока в принципе можно так оставить.
Ну или еще один вариант — вообще не делать объекты Question/Answer, а просто сделать несколько отдельных функций вроде поменятьТипВопроса, добавитьВопрос и писать в HTML разметке так:
<button onclick="addQuestion(...)" type="button">Добавить Вопрос</button>
То есть не делать на стороне JS ООП-модель. Если логика простая то это может сработать.
Ну и еще, надо выносить код работы с DOM в функции. Например вместо тяжело читаемого
> document.getElementById('questions[' + this.number + '][number]')
сделать метод вроде getQuestionNode()
> if (source.id == ("questions[" + this.question.number + "][answers][" + this.number + "][delButton]")) {
Лучше ставить обработчик на саму кнопку:
onEvent(this.getDeleteButton(), 'click', function () { ... });
> function extend(Child, Parent) {
Тут стоит использовать более хороший Object.create если он есть в браузере, а если нет то хак с функцией.
> this.number = question.answers.length + 1;
Инкапсуляцию по моему нарушаешь, ты сделал выделение нового номера ответа не в классе Вопрос, а вынес наружу. Лучше сделать метод question.getNextAnswerNumber() или сделать чтобы при вызове question.addAnswer он сам проставлялся.
> var answerHtml = document.getElementById("questionType" + typeNumber).innerHTML;
> answerHtml = answerHtml.replace(/questionNumber/g, question.number);
Это надо вынести в функцию такого вида:
html = renderTemplate(tpl, { a: 1, b: 2 });
> this.node.onclick = function (event) {
> this.parent.clickFunction(event);
События всплывают, может не обязательно на каждом вопросе обработчик ставить? А хватит одного на весь тест?
Но вообще хорошо что ты ООП используешь, это да.
> document.getElementById('questions[' + this.number + '][number]').innerHTML = newNumber;
Тут лучше сделать по-другому: при создании вопроса находить нужные DOM элементы и сохранять в свойства.
> document.getElementById("questions").getAttribute("count");
Не надо передавать данные через аттрибуты. Вместо этого лучше непосредственно передавать данные в шаблоне, например в виде JSON:
var questions = <?= json_encode($questions) ?>;
initTest(questions);
Остальное я еще проверю, когда будет время.
Шаблоны:
https://github.com/sqghub/TestHub/blob/master/views/test/createTest.twig#L30
ЧТобы не копипастить шаблон вопроса 2 раза, вынеси его в макрос.
Модели: вот тут вот есть такой код
https://github.com/sqghub/TestHub/blob/master/models/Question.php#L54
Ты там в цикле вставляешь записи по одной. Это стоит хотя бы в транзакцию завернуть, чтобы не было полусохраненных ответов. Ну и еще, ты не удаляешь старые вопросы по моему. Ну и конечно надо бы посмотреть, а не умеет ли Юи сам сохранять и удалять связанные записи, может ты пишешь то что уже сделано.
Вот тут https://github.com/yiisoft/yii2/blob/master/docs/guide/db-active-record.md#working-with-relationships описаны функции link/unlink для создания связей. Может они подойдут?
Также написано вроде возможность подключить транзакции уже есть: https://github.com/yiisoft/yii2/blob/master/docs/guide/db-active-record.md#transactional-operations (может это даже включено по умолчанию).
В идеале конечно надо бы сохранять только изменившиеся, но с ActiveRecord по моему это малореально (надо как-то добавлять флаг наличия изменений), а вот та же доктрина это умеет.
Далее, вот тут ты определяешь отношение в зависимости от типа вопроса:
https://github.com/sqghub/TestHub/blob/master/models/Question.php#L24
Будет ли это работать, если мы загрузили вопрос из БД, поменяли его тип, поменяли ответы и сохраняем? Это все надо проверить. В идеале, этот класс стоит покрыть тестами для таких случаев (например на phpunit, если ты с ним знаком). Ну или хотя бы вручную пока протестировать.
Еще, ты определяешь свойство
> private $answers = [ ];
Но как я понимаю из документации https://github.com/yiisoft/yii2/blob/master/docs/guide/db-active-record.md#working-with-relational-data там обращение к answers должно перехватываться Юи, и добавляя поле ты возможно ломаешь этот механизм.
В общем, опять же надо проверить, работает ли загрузка вопроса из БД, ответов, и их удаление и сохранение. Там документация скудная, так что если что сразу лезь в исходники Юи и смотри там.
> https://github.com/sqghub/TestHub/blob/master/controllers/TestController.php#L33
Я бы вынес questionTypes и questionTypeLabels в модель, то есть можно сделать метод getAllQuestionTypes и например getQuestionLabel($type). Тогда эти названия можно будет в нескольких местах использовать.
> return $this->render('createTest.twig', [
Это у тебя скопипастено 2 раза, лучше сделать без копипасты, например:
если (пост) {
обрабатываем пост данные;
редиректим если ок;
}
выводим форму;
https://github.com/sqghub/TestHub/blob/master/controllers/TestController.php#L60
> $question = new Question( );
Ты каждый раз пересоздаешь вопросы, хотя при редактировании теста наверно надо будет не создавать новый вопрос а править существующий (чтобы не менялся его id). Для этого в POST данных при редактировании стоит передавать тот самый id вопроса.
> as $questionNumber => $formQuestion
Советую номер передавать отдельным скрытым или видимым инпутом — а то ты намучаешься при переупорядочивании вопросов переименовывать все эти поля.
Насчет правильного ответа, надо понимать что там где множественный ответ может быть выбрано несколько правильных ответов.
По яваскрипту:
Тут есть другие варианты решения. Например, можно посмотреть в сторону knockout. Это шаблонизатор с дата биндингом, то есть при изменении например типа вопроса в объекте, он сам будет менять DOM и не нужен будет весь этот код с кучей getElementById.
Второй вариант использовать jQuery ради экономии времени на код работы с DOM — он будет чуть короче (но суть особо не поменяется).
Пока в принципе можно так оставить.
Ну или еще один вариант — вообще не делать объекты Question/Answer, а просто сделать несколько отдельных функций вроде поменятьТипВопроса, добавитьВопрос и писать в HTML разметке так:
<button onclick="addQuestion(...)" type="button">Добавить Вопрос</button>
То есть не делать на стороне JS ООП-модель. Если логика простая то это может сработать.
Ну и еще, надо выносить код работы с DOM в функции. Например вместо тяжело читаемого
> document.getElementById('questions[' + this.number + '][number]')
сделать метод вроде getQuestionNode()
> if (source.id == ("questions[" + this.question.number + "][answers][" + this.number + "][delButton]")) {
Лучше ставить обработчик на саму кнопку:
onEvent(this.getDeleteButton(), 'click', function () { ... });
> function extend(Child, Parent) {
Тут стоит использовать более хороший Object.create если он есть в браузере, а если нет то хак с функцией.
> this.number = question.answers.length + 1;
Инкапсуляцию по моему нарушаешь, ты сделал выделение нового номера ответа не в классе Вопрос, а вынес наружу. Лучше сделать метод question.getNextAnswerNumber() или сделать чтобы при вызове question.addAnswer он сам проставлялся.
> var answerHtml = document.getElementById("questionType" + typeNumber).innerHTML;
> answerHtml = answerHtml.replace(/questionNumber/g, question.number);
Это надо вынести в функцию такого вида:
html = renderTemplate(tpl, { a: 1, b: 2 });
> this.node.onclick = function (event) {
> this.parent.clickFunction(event);
События всплывают, может не обязательно на каждом вопросе обработчик ставить? А хватит одного на весь тест?
Но вообще хорошо что ты ООП используешь, это да.
> document.getElementById('questions[' + this.number + '][number]').innerHTML = newNumber;
Тут лучше сделать по-другому: при создании вопроса находить нужные DOM элементы и сохранять в свойства.
> document.getElementById("questions").getAttribute("count");
Не надо передавать данные через аттрибуты. Вместо этого лучше непосредственно передавать данные в шаблоне, например в виде JSON:
var questions = <?= json_encode($questions) ?>;
initTest(questions);
Остальное я еще проверю, когда будет время.
Шаблоны:
https://github.com/sqghub/TestHub/blob/master/views/test/createTest.twig#L30
ЧТобы не копипастить шаблон вопроса 2 раза, вынеси его в макрос.
>>420949
Наверно так же как и на другеи версии Windows. У меня есть кое что
https://gist.github.com/codedokode/10774100
https://gist.github.com/codedokode/7054af4a03865c4cc863
>>420966
ООП нужен и фреймворки тоже. без них только самая примитивная работа. У меня есть урок по ООП
http://archive-ipq-co.narod.ru/l1/pasta.html
Также ООП описан в книгах Зандстры и Шлосснейгла из ОП поста
Я решил написать скрипт который будет рассчитывать сколько будет приносить серебра птицы, например на 50 день, или на 300 день. С учётом того что как только мы набираем нужную сумму для покупки птицы, мы сразу же её покупаем (птиц пять видов, цены на все разные). И вот мне показалось что я уже всё написал: http://ideone.com/odXis7 и результат мне показался правильным. Но потом я заметил как это часто бывает недочёты, а недочёты заключаются в том что каждый день я покупаю только один вид птиц, и если у меня остаётся определённые деньги от покупки птиц которых не хватает на птицу того вида которого я покупаю в этот день, но хватает на птицу другого вида, я её покупаю. И не знаю как исправить свой скрипт, варианта исправления есть три:
1) Попробовать через рекурсию
2) Попробовать сделать при помощи ООП
3) Сделать всё через функции и при том или ином случае в функциях ссылаться на другие функции.
Извини если я не понятно объяснил, чувствую что объяснил недостаточно понятно, но мне главное бы узнать какой путь выбрать, через который это можно реализовать. Вот код того что я написал: http://ideone.com/odXis7 может быть он лучше пояснить что я хочу сказать.
Одним словом, каждый день у меня есть некоторая сумма, которая хранится в переменной $gold и зависит от количества птиц которые я уже купил. И вот у меня есть варианты покупки птиц в зависимости от размера этого $gold.
Допусти на 90-ый день у меня $gold=24000 серебра, я могу купить 4 птицы по 5000 серебра каждая (делаю я это через блоки if в которых проверяется значение $gold), у меня остаётся 4000 серебра, я могу купить ещё 4 птицы стоимостью по 1000 серебра, но скрипт этого не делает а переходит $i++ в цикле.
Раньше был аналогичный хайп, назывался golden eggs. Не помню сколько прожил правда. Может запилить такой?
Сначала пишешь это несколько месяцев, отлаживаешь, разбираешься с серыми и черными схемами работы с баблом. Потом рекламируешь везде, тратишь на это кучу денег, сил и времени. Во время работы борешься не покладая рук с ботами и "халявщиками". Потом упускаешь момент и все бабло уходит, пирамида рушится с нулевым балансом. Ты с ужасом понимаешь, что просрал год времени, минимум несколько сот тыр, потратил много сил и не приобрел абсолютно ничего: ни денег, ни сколько-нибудь полезного опыта. В резюме годовая дыра, сам ты - лысеющий задрот в обносках с нервно бегающими глазками, не способный сложить три слова на собеседовании и ничего полезного не умеющий. Собеседующие хмурят брови и раз за разом ты слышишь сакраментальную фразу.
>>421113
Всё очень просто решается:
нужно изменить порядок if-блоков, в которых происходит покупка птиц, т.е.
начать нужно с самой дорогой птицы:
if ($gold >= price5) { //Купить 5 птицу/ц }
if ($glod >= price4) { //Купить 4 птицу/ц }
if ($glod >= price3) { //Купить 3 птицу/ц }
И т.д.
"&& $gold<$price4" и аналогичные хуевины следует убрать из if-блоков, так как в них нет необходимости.
Ну и еще рекомендую, во-первых нуучится использовать массивы, которые бы позволили в данном конкретном случае заменить все эти if-блоки одним.
Таблица 1 | Таблица 2 | Что–нибудь общее для связи
Всех с новым годом, ребят. Вот попытался накатать задачу про считалочку, оказалась сложной для меня, и пока что вкидываю хоть сколько-то рабочую версию. Как думаете, можно ли избавиться от некоторых костылей в ней?
http://ideone.com/0kHLTr
Первое задания из курса html/css. Что-то неверно?
Ха, Спасибо, оказывается всё намного проще чем я думал. У меня прям глаза открылись. Часто так бывает что всё намного проще чем думаешь, не знаю как с этим бороться, я уже и пробовал рекурсию как-то применить или даже ООП попробовать.
>во-первых нуучится использовать массивы, которые бы позволили в данном конкретном случае заменить все эти if-блоки одним.
Извини, если не сложно можешь намекнуть как это сделать? Сделать три массива 1 с количество птиц, 2 с суммой которую они приносят, 3 с их ценой. А потом просто в одном блоке (если $gold больше 1000) просто выполнять математические действия начиная с самой дорогой птицы?
не было ни у кого такого?
Там же можно деление с округлением вниз исплоьзовать:
24 000 / 5 000 = 4 птицы
(первый раз слышу про игру где надо покупать каких-то птиц)
>>421250
Если у тебя есть несколько видов птиц с разными свойствами, логично информацию о них хранить в массиве массивов по типу такого
array(
'bird1' => array('price' => 2000, 'profit' => 100, 'weight' => 6),
'bird2' => ...
);
А информацию о купленных птицах в обычном массиве вида
array(
'bird1' => 20,
'bird2' => 5
);
Если же у птиц есть какие-то индивидуальные свойства типа возраста, настроения, веса, и т.д. то придется на каждую птицу отдельный элемент массива, а лучше объект, заводить.
Для локальной разработки он не обязателен. В новом php 5.5 и выше кстати кешер уже встроен, надо только в конфиге включить.
Ну и искать надо не абы где, а на http://windows.php.net/downloads/pecl/releases/ и искать по соответсвию с версией php и Апача. Например если Апач ts (многопоточный) то и версия должна быть ts а не nts. И компилятор желательно тот же.
Расшифровка обозначений:
php_apcu-4.0.7-5.5-nts-vc11-x64.zip
apcu — нгазвание расширения
4.0.7 - версия
5.5 - версия php
nts/ts — однопоточный/многопоточный (под виндой и апачем нужен наверно ts)
vc11 — версия компилятора (желательно та же что у Апача)
x64 — под 64 битную ОС
> margin-right:34%-10px;
Это не работает, это ошибка. Нельзя писать выражения (точнее можно но с помощью CSS3 и функции calc, гугли по словам "css3 calc". Но в этой задаче calc использовать нельзя).
> left:10px;
left используется только с позиционированием. Тут оно ничего не делает.
Не ставь свойства наугад, а ставь осознанно. Там дана ссылка к задаче http://softwaremaniacs.org/blog/2005/08/27/css-layout-flow/ — убедись что прочел и понял то что там написано.
> \t\tmargin-left:34%;
>\t\tmargin-top:10px;
>\t\twidth:66%;
У тебя в сумме получилось больше 100% и одно из свойств будет не применено.
Почитай ссылку выше и исправь ошибки.
Мне интересно, куда можно идти 1 января днем? Я был на улице, город как будто вымер, все закрыто. Алсо, лужи и слякоть везде.
>>421190
Да. Например, таблица связывающая Пост и Теги может содержать дополнительно Дату простановки тега.
>>421216
И тебя с новым годом, анон. Версия работает, да.
> for ($i=1; $i <= $words; $i++, $girl++) {
Этот цикл можно заменить на сложение же.
> while (count($girls)>3) {
Тут надо поставить не цифру 3, а число слогов.
> $girl--;
Хорошо бы переделать чтобы жтого не было, например не прибавлять лишнюю единицу изначально.
Warning: imagettftext() [function.imagettftext]: Invalid font filename in Z:\home\test_sait\www\pChart1\pChart\pChart.class on line 566
Пишет что ошибка именно в скачанном файле как я понимаю.
>> \t\tmargin-left:34%;
>>\t\tmargin-top:10px;
>>\t\twidth:66%;
Так ведь top - отступ сверху, зачем его сумировать к ширине и отступу слева?
http://jsfiddle.net/q72b4btd/2/
Уже решил проблему, кстати, анончики не у кого нет документации на русском для pChart?
Офигеть. Дай угадаю, надо сделать один элемент, который будет отсупать 10рх от границ экрана, а внутри него запилить два блока, так? Других идей нет, как сделать 34 и 66 + 10 рх
Алсо, хотелось спросить по поводу второй задачи, а как там без width сделать, хех?
Спасибо тебе ещё раз. Оказывается если бы эта пирамида rich-birds.com реально выдавала бы деньги (и если я не ошибся в расчётах) то примерно через 300 дней, без начальных вложений реальных денег, можно было бы получать 1500-2000 рублей в день, а через год можно выйти на 19000 рублей (там экспоненциальный рост). Но только эта пирамида денег не платит. Вот скрипт если вдруг кому интересно http://ideone.com/RSSLq9 там можно даже график посмотреть, но он закомментирован.
>Это стоит хотя бы в транзакцию завернуть, чтобы не было полусохраненных ответов.
Это да.
>Ну и еще, ты не удаляешь старые вопросы по моему.
Эту функцию я планирую использовать только при создании. Хотя можно и при редактировании, только там при создании этого массива нужно будет делать связку из взять из базы -> проставить новые атрибуты -> save. Save работает как инсерт для новых записей и как апдейт для тех, что взяли из бд.
>описаны функции link/unlink для создания связей
Я так понял, они нужны при добавлении связи для связанных уже по hasOne/hasMany классов. Т.е. классы уже связаны, а линк/анлинк нужен для уже объектов.
>Далее, вот тут ты определяешь отношение в зависимости от типа вопроса:
>Будет ли это работать, если мы загрузили вопрос из БД, поменяли его тип, поменяли ответы и сохраняем?
Ну и изврат. Я считаю, что при смене типа вопроса при редактировании, мы просто создадим новый объект нужного типа, а старый удалим.
>В идеале, этот класс стоит покрыть тестами для таких случаев
Тут еще и на класс не похоже толком. Надо бы со сценариями разобраться, чтобы реализовать нормально создание/редактирование.
>там обращение к answers должно перехватываться Юи, и добавляя поле ты возможно ломаешь этот механизм.
Я думаю оно перехватывается для имеющихся методов. К тому же можно всегда определить гет/сет и пользоваться ими даже внутри класса.
>Я бы вынес questionTypes и questionTypeLabels в модель
Я подумывал об этом, честно говоря. Но тогда уж и лейблы, и типы с именами констант запихнуть в один массив.
>если (пост) {
Дело в том, что в блоке "если пост" кода больше, чем в остальном. Это я так перевернул по странному.
>Ты каждый раз пересоздаешь вопросы, хотя при редактировании теста наверно надо будет не создавать новый вопрос а править существующий (чтобы не менялся его id). Для этого в POST данных при редактировании стоит передавать тот самый id вопроса.
Пока что это создание нового теста, а не редактирование уже имеющегося, т.е. у вопросов нет id. А в редактировании все равно new Question() делать придется, только в нем каждый раз будет $question -> findOne и затем save.
>Насчет правильного ответа, надо понимать что там где множественный ответ может быть выбрано несколько правильных ответов.
Они там в пост запихиваются по разному. В Множественного выбора стоит чек на ответах, а в случае одного - передается номер верного ответа. И обрабатываются по разному тоже. А хранятся в одной таблице, потому что поля-то, по сути, одни.
>По яваскрипту:
>Например, можно посмотреть в сторону knockout.
Это как-то очень круто. Или рано. Или и то, и другое.
>Ну или еще один вариант — вообще не делать объекты Question/Answer, а просто сделать несколько отдельных функций
Думал об этом, но в итоге пришел к выводу, что объектами проще.
>Ну и еще, надо выносить код работы с DOM в функции.
Даже для функций в одну строчку?
>Лучше ставить обработчик на саму кнопку:
>onEvent(this.getDeleteButton(), 'click', function () { ... });
ВОУ, А ТАК МОЖНО!?
Это же круто. Правда надо прерывать всплытие в каждой функции. Этим я займусь.
>Тут стоит использовать более хороший Object.create если он есть в браузере, а если нет то хак с функцией.
Ну я это взял как универсальное решение прямо из учебника.
>Инкапсуляцию по моему нарушаешь, ты сделал выделение нового номера ответа не в классе Вопрос, а вынес наружу. Лучше сделать метод question.getNextAnswerNumber() или сделать чтобы при вызове question.addAnswer он сам проставлялся.
Унесу в addAnswer. Это, пожалуй, логичнее будет.
>События всплывают, может не обязательно на каждом вопросе обработчик ставить? А хватит одного на весь тест?
Ну там жирный обработчик получится. Нужно кнопку добавления/удаления вопроса/варианта ответа обрабатывать. Или мало-ли что я еще там добавлю. Ну и я подумал, что логично будет клики по объекту в объекте и объявить.
>Но вообще хорошо что ты ООП используешь, это да.
Да у меня по-другому не получилось как-то. Но иногда чувствуется, что ооп-то кастрированное.
>Остальное я еще проверю, когда будет время.
Есть еще такая идея. Может быть не разбираться со всей этой фигней, вроде нумерации вопросов/ответов в именах и иже с ними, а просто добавлять дивы. Меньше проблем будет потом, когда перетаскивание и все такое буду делать. А в пост отправлять не то, что есть в формах, а собирать данные скриптом в json-строку и получать на сервере готовый массив по сути. Раз уж страница с выключеным js не работает, то гулять на полную с ним, а?
>ЧТобы не копипастить шаблон вопроса 2 раза, вынеси его в макрос.
С ним можно впихнуть что-то в середине шаблона?
>Это стоит хотя бы в транзакцию завернуть, чтобы не было полусохраненных ответов.
Это да.
>Ну и еще, ты не удаляешь старые вопросы по моему.
Эту функцию я планирую использовать только при создании. Хотя можно и при редактировании, только там при создании этого массива нужно будет делать связку из взять из базы -> проставить новые атрибуты -> save. Save работает как инсерт для новых записей и как апдейт для тех, что взяли из бд.
>описаны функции link/unlink для создания связей
Я так понял, они нужны при добавлении связи для связанных уже по hasOne/hasMany классов. Т.е. классы уже связаны, а линк/анлинк нужен для уже объектов.
>Далее, вот тут ты определяешь отношение в зависимости от типа вопроса:
>Будет ли это работать, если мы загрузили вопрос из БД, поменяли его тип, поменяли ответы и сохраняем?
Ну и изврат. Я считаю, что при смене типа вопроса при редактировании, мы просто создадим новый объект нужного типа, а старый удалим.
>В идеале, этот класс стоит покрыть тестами для таких случаев
Тут еще и на класс не похоже толком. Надо бы со сценариями разобраться, чтобы реализовать нормально создание/редактирование.
>там обращение к answers должно перехватываться Юи, и добавляя поле ты возможно ломаешь этот механизм.
Я думаю оно перехватывается для имеющихся методов. К тому же можно всегда определить гет/сет и пользоваться ими даже внутри класса.
>Я бы вынес questionTypes и questionTypeLabels в модель
Я подумывал об этом, честно говоря. Но тогда уж и лейблы, и типы с именами констант запихнуть в один массив.
>если (пост) {
Дело в том, что в блоке "если пост" кода больше, чем в остальном. Это я так перевернул по странному.
>Ты каждый раз пересоздаешь вопросы, хотя при редактировании теста наверно надо будет не создавать новый вопрос а править существующий (чтобы не менялся его id). Для этого в POST данных при редактировании стоит передавать тот самый id вопроса.
Пока что это создание нового теста, а не редактирование уже имеющегося, т.е. у вопросов нет id. А в редактировании все равно new Question() делать придется, только в нем каждый раз будет $question -> findOne и затем save.
>Насчет правильного ответа, надо понимать что там где множественный ответ может быть выбрано несколько правильных ответов.
Они там в пост запихиваются по разному. В Множественного выбора стоит чек на ответах, а в случае одного - передается номер верного ответа. И обрабатываются по разному тоже. А хранятся в одной таблице, потому что поля-то, по сути, одни.
>По яваскрипту:
>Например, можно посмотреть в сторону knockout.
Это как-то очень круто. Или рано. Или и то, и другое.
>Ну или еще один вариант — вообще не делать объекты Question/Answer, а просто сделать несколько отдельных функций
Думал об этом, но в итоге пришел к выводу, что объектами проще.
>Ну и еще, надо выносить код работы с DOM в функции.
Даже для функций в одну строчку?
>Лучше ставить обработчик на саму кнопку:
>onEvent(this.getDeleteButton(), 'click', function () { ... });
ВОУ, А ТАК МОЖНО!?
Это же круто. Правда надо прерывать всплытие в каждой функции. Этим я займусь.
>Тут стоит использовать более хороший Object.create если он есть в браузере, а если нет то хак с функцией.
Ну я это взял как универсальное решение прямо из учебника.
>Инкапсуляцию по моему нарушаешь, ты сделал выделение нового номера ответа не в классе Вопрос, а вынес наружу. Лучше сделать метод question.getNextAnswerNumber() или сделать чтобы при вызове question.addAnswer он сам проставлялся.
Унесу в addAnswer. Это, пожалуй, логичнее будет.
>События всплывают, может не обязательно на каждом вопросе обработчик ставить? А хватит одного на весь тест?
Ну там жирный обработчик получится. Нужно кнопку добавления/удаления вопроса/варианта ответа обрабатывать. Или мало-ли что я еще там добавлю. Ну и я подумал, что логично будет клики по объекту в объекте и объявить.
>Но вообще хорошо что ты ООП используешь, это да.
Да у меня по-другому не получилось как-то. Но иногда чувствуется, что ооп-то кастрированное.
>Остальное я еще проверю, когда будет время.
Есть еще такая идея. Может быть не разбираться со всей этой фигней, вроде нумерации вопросов/ответов в именах и иже с ними, а просто добавлять дивы. Меньше проблем будет потом, когда перетаскивание и все такое буду делать. А в пост отправлять не то, что есть в формах, а собирать данные скриптом в json-строку и получать на сервере готовый массив по сути. Раз уж страница с выключеным js не работает, то гулять на полную с ним, а?
>ЧТобы не копипастить шаблон вопроса 2 раза, вынеси его в макрос.
С ним можно впихнуть что-то в середине шаблона?
Хм, отправилось. А в /а/ и /дев/ не отправляется.
Хочу совета спросить. Как его искать? Одним выражением, или-же несколькими?
Аноны есть кто работал с PChart? Почему по осям не подписываются цифры, даже в примерах которые шли вместе с библиотекой, во всех браузерах такое.
>в общем как и вся винда - максимум юзабельности из коробки
> phpstorm
> xdebug
Категория: выебанные и обоссаные
Анон, в шапке написано что можно почитать
>>По PHP: Профессиональное программирование на PHP Джордж Шлосснейгл
>>По PHP: Мэтт Зандстра — PHP: Объекты, шаблоны, методики программирования
Но в первой книге 2006 года написано, что она на версию 5.0, вторая как раз на последнюю вроде. Стоит ли читать первую, не сильно она устарела, или сразу обмазываться второй?
Алсо полный ньюфаг в пхп, прочитал в гугле, что во второй порог вхождения для новичка высокий и надо знать хотя бы ООП и сам язык более менее. Таки начинать с первой?
Судя по всему там используется метод ->drawScale но пробовал по разному но не выходит.
Странно как то график отобразился здесь, одним словом там по Оси Х примерно 200 значений, надо изменить шаг, что бы был не 1 а хотя бы 10
Немчура
когда читал вторую уже понимал более-менее ооп, но некоторые страницы приходилось перечитывать по 5 раз чтобы понять суть.
http://jsfiddle.net/dh4s5q7c/
Обдумываю, как её решить. Допустим, я смогу проверить на те ошибки, что заданы. А как вывести сообщение, что именно в том месте ошибка - не знаю. Сейчас гуглить буду.
preg_replace('/(ж|ш)(ы)/', '[$2]', $string).
Как то так, давно уже с регулярками дела не имел, может чего путаю - гугли сохраняющие скобки(есть и не сохраняющие кстати)
Прости, наебал. http://ideone.com/1w3yzQ
Вот работающая регулярка. Я же сказал - гугли сохраняющие скобки regexp узнаешь что за $2
Нашел такую штуку:
>preg_replace('/\.(?!\.)/')
Если сменить те точки на любой другой знак - он и заменится в исходном тексте. А зачем тогда скобки, знак вопроса и восклицания?
Что-то я не понимаю.
Гугл молчит по этому поводу. Там это само собой разумеющееся, а я не понимаю. Удалил тот код, попробовал свой поставить - а он даже близко не подходит.
Про скобки нашел, что они за вложенные выражения отвечают. Погуглил вложенные выражения - а они вообще не относятся к тексту вроде-бы. Так что не знаю, зачем поставили их. Про тот знак вопроса и восклицания - ничего не понимаю. Вторую точку можно на рандомный знак менять -- ничего не изменится. Если убрать её -- код работать не будет. Наверное, это я дурак, и очевидные вещи не могу понять.
Всех с наступившим.
Я переделал задачку свою, я вдруг проснулся после Нового года и подумал - зачем мне там координаты X и Y если у меня есть номер позиции от 1 до 100 и массив с такими же элементами, я могу просто размещать игроков прямо в элементы при совпадении. Плюс переделал код по советам.
http://ideone.com/KMw0OT
Платить за это два доллара? Да ну нахуй.
Учитель из меня тот еще, но попробую объяснить. $0, $1, $2 это особые переменные создаваемые в процессе прогона строки через регулярку. $0 соответствует всему регулярному выражению, а $1, $2 и так далее соответствуют скобкам в порядке их открывания. В случае если регулярка /he(l)l(o)/, а строка hello, то в $0 будет - "hello", в $1- "l". http://ideone.com/o8fTAw
В общем если тебе нужно сохранить какой то кусок символов, для того что бы потом выделить его скобками например как в примере с жы шы то просто ставишь скобки, и у тебя появляется переменная(которая обрати внимание обязательно должна быть в кавычках как и регулярка). Если же содержимое скобки сохранять в переменную не надо то используются такие скобки (?:наша_регулярка). Вообще есть еще такие ништяки как вперед смотрящие и назад утверждения. Вообще, вот годная книга на эту тему, в сочетании с объяснениями опа разобраться труда не составит http://rutracker.org/forum/viewtopic.php?t=32748
Какая то запутанная фигня. Но ни чего сложного для понимания.
Возможно у тебя пробел в теории.
http://htmlbook.ru/css/checked
http://htmlbook.ru/samcss/sosednie-selektory
Чуть поправил.
http://jsfiddle.net/dh4s5q7c/1/
Какая то запутанная фигня. Но ни чего сложного для понимания.
Возможно у тебя пробел в теории.
http://htmlbook.ru/css/checked
http://htmlbook.ru/samcss/sosednie-selektory
Чуть поправил.
http://jsfiddle.net/dh4s5q7c/1/
Выбираю 1-3 задачки на день и решаю, как решил - значит остальное время занимаюсь другими делами.
>>422171
Шаманизм не нужен. Давно введены в CSS родственные селекторы.
http://htmlbook.ru/css/selector/sibling
http://jsfiddle.net/avLdmruy/
http://ideone.com/m5GTZH
Правда тут уже версия со спиралью, но думаю что по ней тоже можно оценить / критиковать, там различия в 2 строчках.
А то моя мега-связка CI+Kohana+ZF что-то перестает мне вкусные заказы подбрасывать
Неплохо.
> \tfor ($x=0; $x<$dx; $x++) {
> echo " {$screen[$y][$x]} ";
тут можно цикл заменить на implode
> for ($i=0; $i<$length; $i++) {
> $letters[] = mb_substr($phrase, $i, 1);
Так тоже можно, но вообще строку разбить на массив символов можно таким хаком:
$letters = preg_split("//u", $text, null, PREG_SPLIT_NO_EMPTY);
Это работает за счет того, что пустая регулярка соответствует промежуткам между буквами и разбивает по ним строку на буквы. Флаг в конце нужен чтобы удалить 2 пустых элемента в начале и конце массива.
Обрати внимание на флаг u. Он говорит что текст в utf-8 и заставляет разбивать строку именно на буквы по границам utf-8 символов, а не на куски по 1 байту.
$0 это даже не настоящая переменная, так как ты не можешь написать например
echo $0;
Это просто конструкция, похожая из-за знака доллара на переменную. Когда preg_replace видит такую конструкцию в строке, он ее заменяет на часть исходной строки.
>>422107
Вот советы и замечания, напишу кратко.
> global $desk;
Вот это нехорошо. Глобаьные переменные нельзя вообще использовать, тем более в учебных прораммах. Если твоему классу Игрок нужен доступ к объекту доски, надо передавать эту доску ему через конструктор и сохранять в свойство.
Также, вот этот код
> oreach ($desk->cases as $key => $value) {
> if ($this->position == $key) {
Стоит перенести в Desk и сделать методом такого вида:
$target = $desk->getJumpPosition($pos)
То есть мы передаем ему текущую позицию, а он возвращает позицию, на которую можно перейти (если можно). Все же эти переходы это часть карты и пусть она (объект-карта) их и проверяет.
> if (100 - $lastPosition < $roll) {
Если записать условие в виду $lastposition + $roll > 100 то понять будет гораздо проще.
> for ($i = 0; $i <= 99; $i++) {
> $zone[] = $k++;
Есть функция range для этого
Функцию getShow можно сделать частью объекта-карты, то есть карта умеет создавать строку, изображающую ее.
> foreach ($zone as &$square) {
> foreach ($players as $player) {
Непонятно зачем тут 2 цикла. Можно же просто обойти игроков, для каждлго понять в какой он клеточке и вписать его в эту клеточку.
> global $round;
> global $players;
Это надо передавать явно, а не использовать глобальные переменные.
> } while ($player->isWinner == 0);
это условие не сработат так как там стоит return выше, а если бы ретурна не было, оно было бы неприавльным так как проверяет только последнего игрока. а не всех.
$0 это даже не настоящая переменная, так как ты не можешь написать например
echo $0;
Это просто конструкция, похожая из-за знака доллара на переменную. Когда preg_replace видит такую конструкцию в строке, он ее заменяет на часть исходной строки.
>>422107
Вот советы и замечания, напишу кратко.
> global $desk;
Вот это нехорошо. Глобаьные переменные нельзя вообще использовать, тем более в учебных прораммах. Если твоему классу Игрок нужен доступ к объекту доски, надо передавать эту доску ему через конструктор и сохранять в свойство.
Также, вот этот код
> oreach ($desk->cases as $key => $value) {
> if ($this->position == $key) {
Стоит перенести в Desk и сделать методом такого вида:
$target = $desk->getJumpPosition($pos)
То есть мы передаем ему текущую позицию, а он возвращает позицию, на которую можно перейти (если можно). Все же эти переходы это часть карты и пусть она (объект-карта) их и проверяет.
> if (100 - $lastPosition < $roll) {
Если записать условие в виду $lastposition + $roll > 100 то понять будет гораздо проще.
> for ($i = 0; $i <= 99; $i++) {
> $zone[] = $k++;
Есть функция range для этого
Функцию getShow можно сделать частью объекта-карты, то есть карта умеет создавать строку, изображающую ее.
> foreach ($zone as &$square) {
> foreach ($players as $player) {
Непонятно зачем тут 2 цикла. Можно же просто обойти игроков, для каждлго понять в какой он клеточке и вписать его в эту клеточку.
> global $round;
> global $players;
Это надо передавать явно, а не использовать глобальные переменные.
> } while ($player->isWinner == 0);
это условие не сработат так как там стоит return выше, а если бы ретурна не было, оно было бы неприавльным так как проверяет только последнего игрока. а не всех.
Скобки в регулярке нужны, во-первых, чтобы сгруппировать символы, смотри:
abc+ значит «a», за ней «b», за ней 1 или больше «с». То есть соответствует строкам abc, abcc, abccc, abccccccc
Теперь добавим скобки:
a(bc)+ значит «a», за ней одна или больше пар букв «bc» то есть это строки abc, abcbc, abcbcbc, abcbcbcbcbc
Другой пример:
abc|d|e значит «или abc, или d или e»
Добавим скобки:
ab(c|d|e) — это значит буквы «ab», за ними либо c либо d либо e. То есть соответтсвует строкам abc, abd, abe.
Как видишь скобки меняют смысл выражения, группируя символы вместе.
Также, скобки имеют второе значение. Когда происходит поиск текста соответствующего регулярке, тот текст, что попадает в скобки, запоминается. Ты можешь при замене через preg-replace подставлять этот запомненный текст в выражение для замены. Например:
ab(c|d|e) — напомню, она ищет строки abc, abd, abe
После того как регулярка найдет текст, она запомнит то, что попало в скобки (то есть одну из букв c, d, e). Если ты в выраждении для замены напишешь $1 то вместо этого подставится текст запомненный первой парой скобок:
$text = "hhhh abd hhhh";
// заменяет строки abc, abd, abe на cxy, dxy, exy cоответственно
$result = preg_replace('/ab(c|d|e)/u', '$1xy', $text);
echo $result; // hhhhhh dxy hhhhh
То есть $1 заменилось на букву, которая попала в скобки.
Если у тебя больше пар скобок, то $2 соответствует вторым скобкам, $3 третьим, и тд. А $0 соответствует всему найденному регуляркой тексту.
Попробуй выполнить этот пример на ideone и поменять там что-нибудь чтобы понять как эти $1, $2 работают.
Если что-то непонятно, задавай вопросы.
Скобки в регулярке нужны, во-первых, чтобы сгруппировать символы, смотри:
abc+ значит «a», за ней «b», за ней 1 или больше «с». То есть соответствует строкам abc, abcc, abccc, abccccccc
Теперь добавим скобки:
a(bc)+ значит «a», за ней одна или больше пар букв «bc» то есть это строки abc, abcbc, abcbcbc, abcbcbcbcbc
Другой пример:
abc|d|e значит «или abc, или d или e»
Добавим скобки:
ab(c|d|e) — это значит буквы «ab», за ними либо c либо d либо e. То есть соответтсвует строкам abc, abd, abe.
Как видишь скобки меняют смысл выражения, группируя символы вместе.
Также, скобки имеют второе значение. Когда происходит поиск текста соответствующего регулярке, тот текст, что попадает в скобки, запоминается. Ты можешь при замене через preg-replace подставлять этот запомненный текст в выражение для замены. Например:
ab(c|d|e) — напомню, она ищет строки abc, abd, abe
После того как регулярка найдет текст, она запомнит то, что попало в скобки (то есть одну из букв c, d, e). Если ты в выраждении для замены напишешь $1 то вместо этого подставится текст запомненный первой парой скобок:
$text = "hhhh abd hhhh";
// заменяет строки abc, abd, abe на cxy, dxy, exy cоответственно
$result = preg_replace('/ab(c|d|e)/u', '$1xy', $text);
echo $result; // hhhhhh dxy hhhhh
То есть $1 заменилось на букву, которая попала в скобки.
Если у тебя больше пар скобок, то $2 соответствует вторым скобкам, $3 третьим, и тд. А $0 соответствует всему найденному регуляркой тексту.
Попробуй выполнить этот пример на ideone и поменять там что-нибудь чтобы понять как эти $1, $2 работают.
Если что-то непонятно, задавай вопросы.
Надо разобраться полностью с регулярками, удалять и менять код наугад не дает тебе никакой пользы. Если что-то непонтяно, давай уточнять, можем даже какую-нибудь маленькую простую задачку для понимания решить.
Алсо, вот официальный мануал про скобки, не уверен правда что там понятно объяснено:
http://php.net/manual/ru/regexp.reference.subpatterns.php
http://php.net/manual/ru/function.preg-replace.php
> А как вывести сообщение, что именно в том месте ошибка - не знаю.
Допустим ты написал регулярку, которая ищет сочетания жы и шы. Ты можешь сделать preg_match_all с этой регуляркой. Эта функция находит все места в тексте которые соответствуют регулярке (то есть места с ошибками) и возвращает массив с ними. Тебе достаточно пройтись по нему циклом и вывести с помощью echo.
Советую также глянуть мануал по этой функции.
>>421982
Псевдокласс :checked соответвуте нажатому input. То есть тут
input {
стили применяются ко всем инпутам;
}
а тут
input:checked {
стили применяются только к нажатым инпутам;
}
Насчет знака +, это селектор соседей, то есть
a + b { стили }
Применит стили к b только если его предыдущий сосед это a. Соответственно
a + b + c + d { .. }
Применяет стили к d если если прыдыдущий сосед в DOM это c, предыдущий для с это b, предыдущий сосед для b это a.
Если тебе не очень понятно «предыдущий сосед», то почитай тут про DOM и как узлы в нем относятся друг к другу: http://learn.javascript.ru/traversing-dom#parentnode-previoussibling-и-nextsibling
previousNode из той статтьи это и есть «предыдущий сосед».
Ну например вот в этом дереве правило a + b { стили } применится только к одному из тегов b:
<x>...</x>
<b>сюда не применится</b>
<a> ... <x> ... </x> ... </a>
<b> сюда применится </b>
<a> ... </a>
<d> ... </d>
<b> сюда нет </b>
> А как вывести сообщение, что именно в том месте ошибка - не знаю.
Допустим ты написал регулярку, которая ищет сочетания жы и шы. Ты можешь сделать preg_match_all с этой регуляркой. Эта функция находит все места в тексте которые соответствуют регулярке (то есть места с ошибками) и возвращает массив с ними. Тебе достаточно пройтись по нему циклом и вывести с помощью echo.
Советую также глянуть мануал по этой функции.
>>421982
Псевдокласс :checked соответвуте нажатому input. То есть тут
input {
стили применяются ко всем инпутам;
}
а тут
input:checked {
стили применяются только к нажатым инпутам;
}
Насчет знака +, это селектор соседей, то есть
a + b { стили }
Применит стили к b только если его предыдущий сосед это a. Соответственно
a + b + c + d { .. }
Применяет стили к d если если прыдыдущий сосед в DOM это c, предыдущий для с это b, предыдущий сосед для b это a.
Если тебе не очень понятно «предыдущий сосед», то почитай тут про DOM и как узлы в нем относятся друг к другу: http://learn.javascript.ru/traversing-dom#parentnode-previoussibling-и-nextsibling
previousNode из той статтьи это и есть «предыдущий сосед».
Ну например вот в этом дереве правило a + b { стили } применится только к одному из тегов b:
<x>...</x>
<b>сюда не применится</b>
<a> ... <x> ... </x> ... </a>
<b> сюда применится </b>
<a> ... </a>
<d> ... </d>
<b> сюда нет </b>
У тебя конечно пока все не идельно и надо много чего исправить, но ты можешь вспомнить поговорку «тяжело в учении, легко в бою». Так что давай тяжело потрудимся над исправлением ошибок.
По SQL коду
> `sex` enum('М','Ж')
Принято для ENUM использовать латинницу, так как это что-то вроде константы. Например MALE/FEMALE или M/F
> sname
Непросто догадаться что это фамилия, потому стоит добавить комментарий к колонке:
`sname` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 'Фамилия студента' ....
> DEFAULT NULL,
Обычно NOT NULL значит что поле обязательно для заполнения, а NULL что необязательно. У тебя имя и фамилию необязатаельно указывать?
> ENGINE=MyISAM
Лучше использовать тип хранилища InnoDB. Она новее и имеет больше возможностей, поддерживает внешние ключи и транзакции. Подробное сравнение:
http://itif.ru/otlichiya-myisam-innodb/
По коду:
> $student = new student;
Имена классов принято писать с первой большой буквы.
Класс должен быть описан в файле, совпадающем с его именем. Например класс Student уместно положить в файл Student.php. В одном файле должен описываться ровно один класс. Класс StudentMapper должен быть в файле StudentMapper.php
В файле с классом не должно быть постороннего кода вроде такого: https://github.com/MindiMakridi/Students/blob/master/lib/DataMapper.php#L105
> https://github.com/MindiMakridi/Students/blob/master/lib/DataMapper.php#L22
> ORDER BY $sort");
Это SQL инъекция (опасная уязвимость в программе). Ты подставляешь данные от пользователя в запрос и в результате пользователь может составить любой запрос, и получить любые данные из базы. Должно быть не так. Во-первых, ты должен отдельно передавать имя поля и направление сортировки, во-вторых, в самой функции перед подстановкой ты должен проверять что эти переменные содержат одно из значений из разрешенного списка полей (а не что угодно).
> https://github.com/MindiMakridi/Students/blob/master/lib/DataMapper.php#L26
Это непраивльно с точки зрения архитектуры. Класс DataMapper умеет делать только одну вещь: загружать студентов из базы и сохранять ихз в базу. Ни при каких обстоятельствах он не должен ничего выводить на экран. Также, весь HTML код должен располагаться в шаблонах. За их пределами не должно быть ни одного echo.
Разумеется, Mapper также не должен обращаться к кукам.
> public function showStudents($sort, $class){
Здесь тоже архитектурная ошибка: ты не должен передавть аргумент class. Зачем его передавать? Эта функция создает только студентов и никакие другие объекты она создавать не должна.
Также, ошибка, ты создал 2 класса, обозначающих одно и то же: student и profile. Они оба содержат информацию о студенте. Раз так, надо объединить их в один класс, соответствующий студенту, незачем делать 2 класса для одной и той же сущности.
> https://github.com/MindiMakridi/Students/blob/master/lib/profileclass.php#L3
Есди ты хочешь сделать константу, делай не глобальную константу, а константу внутри класса: http://php.net/manual/ru/language.oop5.constants.php
https://github.com/MindiMakridi/Students/blob/master/lib/profileclass.php#L16 — тут слишком длинная строка, запиши массив вертикально на несколько строк.
Также, в файле profileclass съехало форматирование, надо пропустить его через phpformatter.com ибо читать тяжело (и другие файлы где съехало форматирование тоже). Если ты используешь IDE, там есть горячие клавиши для форматирования: https://gist.github.com/codedokode/8759492
> https://github.com/MindiMakridi/Students/blob/master/index.php#L38
Я думаю, лушче тут оставить только один include, а первый файл подключить из main.html
> https://github.com/MindiMakridi/Students/blob/master/lib/functions.php#L4
Не надо тут писать return $x = $y; Надо писать либо так:
return $y;
либо так:
$x = $y;
return $x;
То есть не надо складывать 2 команды в одну строку.
> https://github.com/MindiMakridi/Students/blob/master/lib/DataMapper.php#L59
Здесь ты передаешь информацию о студенте в массиве. Но у нас же есть класс (точнее 2 класса) описывающих студента. Значит, незачем использовать массив, надо передавать объект класса Student.
> https://github.com/MindiMakridi/Students/blob/master/templates/main.html#L14
Шаблон предназначен для вывода переданных ему данных. Он не должен лезть в другие данные типа POST/GET и тем более не должен ничего загружать из базы — это не его задача. Это должно делаться в index.php
Это https://github.com/MindiMakridi/Students/blob/master/templates/template.html#L2 тоже надо вынести из шаблона куда-нибудь в index.php или аналогичный файл.
> <?php echo
Это лучше писать короче как <?= $x ?> (короткие теги используются только для вывода, а для остального исплоьзуй длинные <?php)
Шаблоны Students/templates/profile.html и Students/templates/register.html содержат копипасту. Надо избавиться от дублирования похожего кода, так как это очень плохая вещь, и объединить их в один файл без повторов.
Куки выставляются, как известно, отдачей HTTP-заголовка Set-Cookie. Заголовки в протоколе HTTP идут до тела ответа, потому если ты вывел хоть один пробел, заголовок (и куки) выставить уже нельзя. Потому вот эта строчка: https://github.com/MindiMakridi/Students/blob/master/profile.php#L46 работать не будет.
Кстати, там еще странное место где ты копируешь данные из объекта в массив. Тут лучше сделать чтобы функция сразу принимала на вход объект. То есть везде где у нас есть Студент, логично представлять его в виде объекта.
Пока как-то так. Жду исправлений и вопросов если что-то непонятно. Это наверно непросто все исправить, но зато твой код станет гораздо лучше, а это самое важное.
У тебя конечно пока все не идельно и надо много чего исправить, но ты можешь вспомнить поговорку «тяжело в учении, легко в бою». Так что давай тяжело потрудимся над исправлением ошибок.
По SQL коду
> `sex` enum('М','Ж')
Принято для ENUM использовать латинницу, так как это что-то вроде константы. Например MALE/FEMALE или M/F
> sname
Непросто догадаться что это фамилия, потому стоит добавить комментарий к колонке:
`sname` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 'Фамилия студента' ....
> DEFAULT NULL,
Обычно NOT NULL значит что поле обязательно для заполнения, а NULL что необязательно. У тебя имя и фамилию необязатаельно указывать?
> ENGINE=MyISAM
Лучше использовать тип хранилища InnoDB. Она новее и имеет больше возможностей, поддерживает внешние ключи и транзакции. Подробное сравнение:
http://itif.ru/otlichiya-myisam-innodb/
По коду:
> $student = new student;
Имена классов принято писать с первой большой буквы.
Класс должен быть описан в файле, совпадающем с его именем. Например класс Student уместно положить в файл Student.php. В одном файле должен описываться ровно один класс. Класс StudentMapper должен быть в файле StudentMapper.php
В файле с классом не должно быть постороннего кода вроде такого: https://github.com/MindiMakridi/Students/blob/master/lib/DataMapper.php#L105
> https://github.com/MindiMakridi/Students/blob/master/lib/DataMapper.php#L22
> ORDER BY $sort");
Это SQL инъекция (опасная уязвимость в программе). Ты подставляешь данные от пользователя в запрос и в результате пользователь может составить любой запрос, и получить любые данные из базы. Должно быть не так. Во-первых, ты должен отдельно передавать имя поля и направление сортировки, во-вторых, в самой функции перед подстановкой ты должен проверять что эти переменные содержат одно из значений из разрешенного списка полей (а не что угодно).
> https://github.com/MindiMakridi/Students/blob/master/lib/DataMapper.php#L26
Это непраивльно с точки зрения архитектуры. Класс DataMapper умеет делать только одну вещь: загружать студентов из базы и сохранять ихз в базу. Ни при каких обстоятельствах он не должен ничего выводить на экран. Также, весь HTML код должен располагаться в шаблонах. За их пределами не должно быть ни одного echo.
Разумеется, Mapper также не должен обращаться к кукам.
> public function showStudents($sort, $class){
Здесь тоже архитектурная ошибка: ты не должен передавть аргумент class. Зачем его передавать? Эта функция создает только студентов и никакие другие объекты она создавать не должна.
Также, ошибка, ты создал 2 класса, обозначающих одно и то же: student и profile. Они оба содержат информацию о студенте. Раз так, надо объединить их в один класс, соответствующий студенту, незачем делать 2 класса для одной и той же сущности.
> https://github.com/MindiMakridi/Students/blob/master/lib/profileclass.php#L3
Есди ты хочешь сделать константу, делай не глобальную константу, а константу внутри класса: http://php.net/manual/ru/language.oop5.constants.php
https://github.com/MindiMakridi/Students/blob/master/lib/profileclass.php#L16 — тут слишком длинная строка, запиши массив вертикально на несколько строк.
Также, в файле profileclass съехало форматирование, надо пропустить его через phpformatter.com ибо читать тяжело (и другие файлы где съехало форматирование тоже). Если ты используешь IDE, там есть горячие клавиши для форматирования: https://gist.github.com/codedokode/8759492
> https://github.com/MindiMakridi/Students/blob/master/index.php#L38
Я думаю, лушче тут оставить только один include, а первый файл подключить из main.html
> https://github.com/MindiMakridi/Students/blob/master/lib/functions.php#L4
Не надо тут писать return $x = $y; Надо писать либо так:
return $y;
либо так:
$x = $y;
return $x;
То есть не надо складывать 2 команды в одну строку.
> https://github.com/MindiMakridi/Students/blob/master/lib/DataMapper.php#L59
Здесь ты передаешь информацию о студенте в массиве. Но у нас же есть класс (точнее 2 класса) описывающих студента. Значит, незачем использовать массив, надо передавать объект класса Student.
> https://github.com/MindiMakridi/Students/blob/master/templates/main.html#L14
Шаблон предназначен для вывода переданных ему данных. Он не должен лезть в другие данные типа POST/GET и тем более не должен ничего загружать из базы — это не его задача. Это должно делаться в index.php
Это https://github.com/MindiMakridi/Students/blob/master/templates/template.html#L2 тоже надо вынести из шаблона куда-нибудь в index.php или аналогичный файл.
> <?php echo
Это лучше писать короче как <?= $x ?> (короткие теги используются только для вывода, а для остального исплоьзуй длинные <?php)
Шаблоны Students/templates/profile.html и Students/templates/register.html содержат копипасту. Надо избавиться от дублирования похожего кода, так как это очень плохая вещь, и объединить их в один файл без повторов.
Куки выставляются, как известно, отдачей HTTP-заголовка Set-Cookie. Заголовки в протоколе HTTP идут до тела ответа, потому если ты вывел хоть один пробел, заголовок (и куки) выставить уже нельзя. Потому вот эта строчка: https://github.com/MindiMakridi/Students/blob/master/profile.php#L46 работать не будет.
Кстати, там еще странное место где ты копируешь данные из объекта в массив. Тут лучше сделать чтобы функция сразу принимала на вход объект. То есть везде где у нас есть Студент, логично представлять его в виде объекта.
Пока как-то так. Жду исправлений и вопросов если что-то непонятно. Это наверно непросто все исправить, но зато твой код станет гораздо лучше, а это самое важное.
Я погуглил по «pchart tick interval», «tick step» и вот что нашел:
http://stackoverflow.com/a/11170944
http://stackoverflow.com/questions/10436596/pchart-x-axis-too-many-ticks
Посмотри там примеры кода, может поможет?
>>421662
Для обеих книг хорошо бы знать основы PHP, так как книги только напоминают про них, но не обучают им особо. Можешь пройти мой учебник из ОП поста например.
Насчет ООП, в принципе он там объясняется, у Зандстры, довольно подробно.
>>421658
> Но в первой книге 2006 года написано, что она на версию 5.0
Это верно, книга устаревает. Но многие принципы, которые там описаны, до сих пор актуальны. Может стоит поискать более новое переиздание той же книги?
>>421582
С Апачем проще так как большинство используют php именно так и легче найти ответы на вопросы. а с IIS я никогда не работал.
>>421575
Это задача на понимание регулярок, так что давай для интереса сделаем ее чисто на регулярке? Без str_replace?
Также, задачу надо протестировать на большом числе номеров.
Вот список номеров:
Правильные: array('84951234567', '+74951234567', '8-495-1-234-567', ' 8 (8122) 56-56-56', '8-911-1234567', '8 (911) 12 345 67', '8-911 12 345 67', '8 (911) - 123 - 45 - 67', '+ 7 999 123 4567', '8 ( 999 ) 1234567', '8 999 123 4567');
Неправильные: array('02', '84951234567 позвать люсю', '849512345', '849512345678',
'8 (409) 123-123-123', '7900123467', '5005005001', '8888-8888-88',
'84951a234567', '8495123456a',
'+1 234 5678901', // неверный код страны
'+8 234 5678901', // либо 8 либо +7
'7 234 5678901' // нет +
);
Сделай чтобы программа брала по очереди номера и проверяла их.
Я погуглил по «pchart tick interval», «tick step» и вот что нашел:
http://stackoverflow.com/a/11170944
http://stackoverflow.com/questions/10436596/pchart-x-axis-too-many-ticks
Посмотри там примеры кода, может поможет?
>>421662
Для обеих книг хорошо бы знать основы PHP, так как книги только напоминают про них, но не обучают им особо. Можешь пройти мой учебник из ОП поста например.
Насчет ООП, в принципе он там объясняется, у Зандстры, довольно подробно.
>>421658
> Но в первой книге 2006 года написано, что она на версию 5.0
Это верно, книга устаревает. Но многие принципы, которые там описаны, до сих пор актуальны. Может стоит поискать более новое переиздание той же книги?
>>421582
С Апачем проще так как большинство используют php именно так и легче найти ответы на вопросы. а с IIS я никогда не работал.
>>421575
Это задача на понимание регулярок, так что давай для интереса сделаем ее чисто на регулярке? Без str_replace?
Также, задачу надо протестировать на большом числе номеров.
Вот список номеров:
Правильные: array('84951234567', '+74951234567', '8-495-1-234-567', ' 8 (8122) 56-56-56', '8-911-1234567', '8 (911) 12 345 67', '8-911 12 345 67', '8 (911) - 123 - 45 - 67', '+ 7 999 123 4567', '8 ( 999 ) 1234567', '8 999 123 4567');
Неправильные: array('02', '84951234567 позвать люсю', '849512345', '849512345678',
'8 (409) 123-123-123', '7900123467', '5005005001', '8888-8888-88',
'84951a234567', '8495123456a',
'+1 234 5678901', // неверный код страны
'+8 234 5678901', // либо 8 либо +7
'7 234 5678901' // нет +
);
Сделай чтобы программа брала по очереди номера и проверяла их.
На проверку номера лучше одним, это не очень сложно, а код плучается простой и компактный.
>>421462
Насчет яваскрипта, я еще немного подумал, и все же не уверен, нужны ли нам там класссы Вопрос/Ответ. Я думаю так: у нас вся информация о вопросах/ответов фактически хранится в множестве инпутов. Стоит ли делать класс который ее будет дублировать, писать сложные методы для синхронизации этой информации в обе стороны(между классом и формой)? Не проще ли тут сделать несколько функций типа ПереключитьТипВопроса, ДобавитьВариантОтвета, без построения дерева всех вопросов и ответов?
Классы имели бы смысл если бы там хранилилсь дополнительные данные, которых нет в инпутах или сложная логика.
Ну и насчет сложной работы с id, это надо как-то убирать в функции вроде такой:
var deletBtn = getQuestionDeleteButton(questionNode);
Ну и искать наверно все же удоюнее не по сложному id, а по классу. Для этого конечно придется написать функцию поиска в DOM элемента с определенным классом. То есть например все кнопки удаления у нас помечены классом
js-delete-button (js значит что это не для CSS а для JS класс)
И когда мы хотим получить кнопку удаления в определенном вопросе. то пишем так:
var deletBtn = findFirstByClass(question, 'js-delete-button');
В новых браузерах для поиска по классу есть querySelector и getElementsByClassName, в старых IE придется обходить все узлы-потомки и сравнивать класс.
В jQuery это пишется например так (аналогично примеру выше):
var deleteBtn = $('.js-delete-button', question);
То есть ищем узел с определенным классом внутри узла-вопроса.
> Эту функцию я планирую использовать только при создании. Хотя можно и при редактировании
В создании и редактировании обычно много общего кода и проще сделать общий метод и для того и другого.
> Я так понял, они нужны при добавлении связи для связанных уже по hasOne/hasMany классов. Т.е. классы уже связаны, а линк/анлинк нужен для уже объектов.
Я так понимаю, что link для связи один-ко-многим проставляет в одном объекте (или в табице БД?) id другого то есть как раз связывает их.
Глянь в исходники, может там можно понять?
> Я считаю, что при смене типа вопроса при редактировании, мы просто создадим новый объект нужного типа, а старый удалим.
Ну редактирвоать существующий удобнее:
- не меняется id, если он например где-то уже используется
- не надо копировать поля вопроса типа количесва баллов из старого в новый
- это логичнее, редактировать существующую запись
> Я думаю оно перехватывается для имеющихся методов.
Если ты создал свойство answers то при обращении к нему из класса перехват работать не будет. Он же на магических методах вроде _ _ get основан: http://php.net/manual/ru/language.oop5.overloading.php#object.get
> Даже для функций в одну строчку?
У тебя там раз 10 скопирован код склеивания id с номером вопроса. Это копипаста логики, и ее не должно быть — жолжна быть функция например вычисляющая id для элемента.
> Ну я это взял как универсальное решение прямо из учебника.
Ты либо не так понял, либо это старая статья. В новых браузерах Object.crеate лучше, так как он не создает лишних промежуточных объектов.
> Может быть не разбираться со всей этой фигней, вроде нумерации вопросов/ответов в именах и иже с ними, а просто добавлять дивы.
Да это е так сложно, по моему. делаешь скрытое или видимое поле «Номер вопроса» и при смене порядка вопросов перепроставляешь все эти поля заново по возрастанию. Соответственно в PHP скрипт для каждого вопроса приходит его порядковый номер и он может их отсортировать.
> а собирать данные скриптом в json-строку и получать на сервере готовый массив по сути
Так это как раз усложнение. Если ты используешь форму, то тебе не надо писать код сбора значений из нее и преобразования в массив. И тебе не нужны объекты, не нужно синхронизировать данные между полями ввода и объектами. По моему, кода меньше писать надо.
Ну и при ошибке в JS скрипте форма все равно отправится и данные не потеряются.
Ну вообще, давай посомтрим что ты там в коде напишешь, и еще тогда подумаем, делай пока как считаешь правильным.
На проверку номера лучше одним, это не очень сложно, а код плучается простой и компактный.
>>421462
Насчет яваскрипта, я еще немного подумал, и все же не уверен, нужны ли нам там класссы Вопрос/Ответ. Я думаю так: у нас вся информация о вопросах/ответов фактически хранится в множестве инпутов. Стоит ли делать класс который ее будет дублировать, писать сложные методы для синхронизации этой информации в обе стороны(между классом и формой)? Не проще ли тут сделать несколько функций типа ПереключитьТипВопроса, ДобавитьВариантОтвета, без построения дерева всех вопросов и ответов?
Классы имели бы смысл если бы там хранилилсь дополнительные данные, которых нет в инпутах или сложная логика.
Ну и насчет сложной работы с id, это надо как-то убирать в функции вроде такой:
var deletBtn = getQuestionDeleteButton(questionNode);
Ну и искать наверно все же удоюнее не по сложному id, а по классу. Для этого конечно придется написать функцию поиска в DOM элемента с определенным классом. То есть например все кнопки удаления у нас помечены классом
js-delete-button (js значит что это не для CSS а для JS класс)
И когда мы хотим получить кнопку удаления в определенном вопросе. то пишем так:
var deletBtn = findFirstByClass(question, 'js-delete-button');
В новых браузерах для поиска по классу есть querySelector и getElementsByClassName, в старых IE придется обходить все узлы-потомки и сравнивать класс.
В jQuery это пишется например так (аналогично примеру выше):
var deleteBtn = $('.js-delete-button', question);
То есть ищем узел с определенным классом внутри узла-вопроса.
> Эту функцию я планирую использовать только при создании. Хотя можно и при редактировании
В создании и редактировании обычно много общего кода и проще сделать общий метод и для того и другого.
> Я так понял, они нужны при добавлении связи для связанных уже по hasOne/hasMany классов. Т.е. классы уже связаны, а линк/анлинк нужен для уже объектов.
Я так понимаю, что link для связи один-ко-многим проставляет в одном объекте (или в табице БД?) id другого то есть как раз связывает их.
Глянь в исходники, может там можно понять?
> Я считаю, что при смене типа вопроса при редактировании, мы просто создадим новый объект нужного типа, а старый удалим.
Ну редактирвоать существующий удобнее:
- не меняется id, если он например где-то уже используется
- не надо копировать поля вопроса типа количесва баллов из старого в новый
- это логичнее, редактировать существующую запись
> Я думаю оно перехватывается для имеющихся методов.
Если ты создал свойство answers то при обращении к нему из класса перехват работать не будет. Он же на магических методах вроде _ _ get основан: http://php.net/manual/ru/language.oop5.overloading.php#object.get
> Даже для функций в одну строчку?
У тебя там раз 10 скопирован код склеивания id с номером вопроса. Это копипаста логики, и ее не должно быть — жолжна быть функция например вычисляющая id для элемента.
> Ну я это взял как универсальное решение прямо из учебника.
Ты либо не так понял, либо это старая статья. В новых браузерах Object.crеate лучше, так как он не создает лишних промежуточных объектов.
> Может быть не разбираться со всей этой фигней, вроде нумерации вопросов/ответов в именах и иже с ними, а просто добавлять дивы.
Да это е так сложно, по моему. делаешь скрытое или видимое поле «Номер вопроса» и при смене порядка вопросов перепроставляешь все эти поля заново по возрастанию. Соответственно в PHP скрипт для каждого вопроса приходит его порядковый номер и он может их отсортировать.
> а собирать данные скриптом в json-строку и получать на сервере готовый массив по сути
Так это как раз усложнение. Если ты используешь форму, то тебе не надо писать код сбора значений из нее и преобразования в массив. И тебе не нужны объекты, не нужно синхронизировать данные между полями ввода и объектами. По моему, кода меньше писать надо.
Ну и при ошибке в JS скрипте форма все равно отправится и данные не потеряются.
Ну вообще, давай посомтрим что ты там в коде напишешь, и еще тогда подумаем, делай пока как считаешь правильным.
Если width не указывать то он равен auto и для блочных элементов это значит занять всю доступную ширину (за вычетом маргинов). Тебе явно надо прочесть и понять например эту статью:
http://softwaremaniacs.org/blog/2005/08/27/css-layout-flow/
http://softwaremaniacs.org/blog/2005/07/08/css-boxes/
>>421328
С помощью width: auto, блочный бокс занимает в этом случае всю ширину не знаятую маргинами.
Ну или сделать родительский блок и на нем паддинг нужного размера.
Задавай вопросы. если что непонятно.
>Также, ошибка, ты создал 2 класса, обозначающих одно и то же: student и profile.
>Здесь ты передаешь информацию о студенте в массиве. Но у нас же есть класс (точнее 2 класса) описывающих студента. Значит, незачем использовать массив, надо передавать объект класса Student
Так мне удалять класс Student или нет? Если да, то наверное массив все-таки нужен?
>Шаблоны Students/templates/profile.html и Students/templates/register.html содержат копипасту. Надо избавиться от дублирования похожего кода, так как это очень плохая вещь, и объединить их в один файл без повторов.
Я пока представляю как это сделать только вставкой внутрь тегов переменных пхп, но как мне кажется это будет очень хреново выглядеть, а верстальщик вообще повесится, когда увидит подобное.
C куки не знаю, что делать. Как мне их впихнуть в начале кода, чтобы все работало?
Кстати, слышал про такую штуку - Smarty. Ей вообще пользуются, или уже неактуально?
Да, я помню этот хинт из твоего учебника, но решил здесь воспользоваться вот этим способом для нубов, просто потому что лень было открывать учебник в поисках решения через preg_split
Ну я к тому, что должно входить в этот начальный уровень? Вот берем php, что мне нужно знать, чтобы был этот начальный уровень?
Пройти учебник ОПа, например (есть подозрения, что ты даже не открывал его). Если осилишь, можно пробовать ходить на собеседования.
В идеале: хотя бы половину из того, что пишет оп здесь http://archive-ipq-co.narod.ru/tsuzuke.html
открывал, как раз и хочу его пройти.
Есть еще пол года времени, думаю хоть что-то выучить, сраная бизнес-информатика.
Кстати это еще скромные требования в той вакансии.
Я из Украины, тут ситуация похуже: или ищут суперопытного мидла/сеньора, или контент-манагеры с гребанными cms.
Планирую в феврале пойти поумолять кого-нибудь взять меня джуниором за еду. Буду работать за копейки, лишь бы получить реальный опыт.
> Так мне удалять класс Student или нет?
Объединить классы profile и student в один класс Student
> Если да, то наверное массив все-таки нужен?
Не нужен
> Я пока представляю как это сделать только вставкой внутрь тегов переменных пхп,
> но как мне кажется это будет очень хреново выглядеть, а верстальщик вообще повесится, когда увидит подобное.
Верстальщик тут ты, так что все ок. Ты попробуй или покажи хотя бы кусочек кода, а я скажу правильно или нет.
Вообще, идея у меня такая: мы передаем в шаблон объект Студент (чтобы из него брать информацию для заполнения полей) и список ошибок, если они есть.
При редактировании передаем взятого из базы студента. При создании нового − создаем нового пустого (и потому поля тоже будут пустые). При отправке формы с ошибками мы из POST данные переносим в студента и передаем его + список ошибок.
> C куки не знаю, что делать. Как мне их впихнуть в начале кода, чтобы все работало?
Перенести вывод шаблона в самый конец
> Кстати, слышал про такую штуку - Smarty. Ей вообще пользуются, или уже неактуально?
Это шаблонизатор. Им пользуются, но есть более новые и удобные вроде twig. Лучше его изучать. Если есть желание, можно потом переделать эту задачу на использование твига или сделать следующую, на файлообменник, с твигом. Думаю, лучше в следующем задании его использовать.
>>422463
Тогда ок. Я написал на тот случай, если ты не знал.
> Так мне удалять класс Student или нет?
Объединить классы profile и student в один класс Student
> Если да, то наверное массив все-таки нужен?
Не нужен
> Я пока представляю как это сделать только вставкой внутрь тегов переменных пхп,
> но как мне кажется это будет очень хреново выглядеть, а верстальщик вообще повесится, когда увидит подобное.
Верстальщик тут ты, так что все ок. Ты попробуй или покажи хотя бы кусочек кода, а я скажу правильно или нет.
Вообще, идея у меня такая: мы передаем в шаблон объект Студент (чтобы из него брать информацию для заполнения полей) и список ошибок, если они есть.
При редактировании передаем взятого из базы студента. При создании нового − создаем нового пустого (и потому поля тоже будут пустые). При отправке формы с ошибками мы из POST данные переносим в студента и передаем его + список ошибок.
> C куки не знаю, что делать. Как мне их впихнуть в начале кода, чтобы все работало?
Перенести вывод шаблона в самый конец
> Кстати, слышал про такую штуку - Smarty. Ей вообще пользуются, или уже неактуально?
Это шаблонизатор. Им пользуются, но есть более новые и удобные вроде twig. Лучше его изучать. Если есть желание, можно потом переделать эту задачу на использование твига или сделать следующую, на файлообменник, с твигом. Думаю, лучше в следующем задании его использовать.
>>422463
Тогда ок. Я написал на тот случай, если ты не знал.
Я думаю надо знать указанные технологии на уровне «сделать простой сайтик вроде такого»: https://gist.github.com/codedokode/d7e7f11449fc3bcb24b4
Также, могут на собеседовании поспрашивать теоретические вопросы вроде «что выведет этот код» или «что такое транзакция». Насчет PHP, стоит просто прочесть раздел «справочник по языку» в мануале php чтобы знать ответы на каверзные вопросы.
Ну и ООП надо знать, и хорошо бы иметь опыт работы с каким-нибудь фреймворком (в задании на файлообменник мы например используем Слим, в задании на testHub - Yii 2).
Вообще, у меня ощущение что там требования будут не очень высокие, так как грамотного человека найти сложно. Те, кто прошел мой учебник и дополнительные задания, наверняка бы прошли собеседования.
Имей в виду, что если ты кроме работы не будшь читать документацию и что-то изучать, скорее всего много знаний у тебя не отложится.
Это я понимаю. Но и без опыта практической работы сложно надеяться куда-то устроиться.
Согласитесь, что если меня на собеседовании попросят написать к примеру корзину магазина или rss-ленту, а я скажу, что умею только решать задачки про японских девочек со считалочкой, то, как говорят в Одессе, с меня таки смеяться будут!
Если я напишу примитивный интернет-магазин на пхп и аякс, можно ли будет это гордо называть портфолио?
з.ы. я Вам на почту отписался как раз с просьбой подбросить какое-нибудь заданьице, а также глянуть на чатик, который я наваял.
>так как грамотного человека найти сложно. Те, кто прошел мой учебник и дополнительные задания, наверняка бы прошли собеседования.
Звучит обнадеживающе.
А вот вам пример вакансии, травмирующей психику бедного хикки:
Junior(!) PHP Developer
Требуется:
PHP 5/LAMP
HTML, CSS
ООП
Zend Framework
SQL development
Linux command line
JavaScript, Ajax/JSON, jQuery
PHPUnit; Subversion (SVN)
Приветствуется:
- опыт работы с любой системой распределения версий
- опыт администрирования Linux / FreeBSD.
- базовые навыки работы с графическими редакторами
- английский на уровне чтения тех.документации
- любовь к спорту: футболу, страйкболу (и играть, и смотреть)
/ ну это вообще бомба, у меня корпоративный дух в пятки ушел /
Мама, роди меня обратно! Шо такое sql development, php unit, subversion?
Пойду выпью свои капли...
ОП, а что особенного в твоем учебнике? Чем он лучше например Котерова/Костарева? Не развожу срач, мне интересно.
> а я скажу, что умею только решать задачки про японских девочек со считалочкой
Да, верно, но в учебнике даются только основы php. Никто не говорил что достаточно пройти лишь учебник. После учебника мы даем дополнительные задания вроде такого
https://gist.github.com/codedokode/d7e7f11449fc3bcb24b4
или такого
https://gist.github.com/codedokode/9424217
Это, согласись, уже ближе к rss лентам и корзинам. Также, мы даем дополнительные задания на изучение HTML/CSS, JS и SQL.
Вообще, примерный план должен быть такой (на мой взгляд), чтобы задания шли по возрастающей сложности и не браться сразу за сложные вещи:
- учебник (основы PHP и ООП)
- задание на список студентов (учимся работать с формами, БД, выводить данные)
- задание на файлообменник (изучаем MVC и микрофреймворк Slim, учимся работать с файлами, может быть изучаем шаблонизатор Twig)
- какое-нибудь задание на большой фреймворк вроде Yii/Yii2/Symfony
- автоматизированное тестирование
- задания на HTML/CSS/JS/SQL (можно делать параллельно с другими) чтобы подтянуть их уровень
Это дает в итоге на мой взгляд неплохие знания (если показывать мне решения и исправляь замечания конечно) и это даже наверно выше чем требования во многих компаниях на джуниора/стажера.
> Если я напишу примитивный интернет-магазин на пхп и аякс, можно ли будет это гордо называть портфолио?
Наверно, но я бы назвал это «вот пример веб-приложения которое я сделал»
> я Вам на почту отписался
Ок, я там подробнее отвечу потом. Насчет заданий, что насчет 2 примеров заданий выше? Задание на список студентов выглядит просто, но даже на нем можно много разных интересных вещей изучить. А на файлообменник посложнее.
> а я скажу, что умею только решать задачки про японских девочек со считалочкой
Да, верно, но в учебнике даются только основы php. Никто не говорил что достаточно пройти лишь учебник. После учебника мы даем дополнительные задания вроде такого
https://gist.github.com/codedokode/d7e7f11449fc3bcb24b4
или такого
https://gist.github.com/codedokode/9424217
Это, согласись, уже ближе к rss лентам и корзинам. Также, мы даем дополнительные задания на изучение HTML/CSS, JS и SQL.
Вообще, примерный план должен быть такой (на мой взгляд), чтобы задания шли по возрастающей сложности и не браться сразу за сложные вещи:
- учебник (основы PHP и ООП)
- задание на список студентов (учимся работать с формами, БД, выводить данные)
- задание на файлообменник (изучаем MVC и микрофреймворк Slim, учимся работать с файлами, может быть изучаем шаблонизатор Twig)
- какое-нибудь задание на большой фреймворк вроде Yii/Yii2/Symfony
- автоматизированное тестирование
- задания на HTML/CSS/JS/SQL (можно делать параллельно с другими) чтобы подтянуть их уровень
Это дает в итоге на мой взгляд неплохие знания (если показывать мне решения и исправляь замечания конечно) и это даже наверно выше чем требования во многих компаниях на джуниора/стажера.
> Если я напишу примитивный интернет-магазин на пхп и аякс, можно ли будет это гордо называть портфолио?
Наверно, но я бы назвал это «вот пример веб-приложения которое я сделал»
> я Вам на почту отписался
Ок, я там подробнее отвечу потом. Насчет заданий, что насчет 2 примеров заданий выше? Задание на список студентов выглядит просто, но даже на нем можно много разных интересных вещей изучить. А на файлообменник посложнее.
> sql development
думаю это значит «работа с базами данных», скорее всего не с любыми а MySQL или PostgreSQL. У нас есть задания на MySQL c полезными ссылками: https://gist.github.com/codedokode/10539213
> php unit
Инструмент для написания юнит тестов под PHP. Юнит-тесты — это маленькие программки, которые тестируют твой код автоматизированно. Ну например, если ты написал код корзины для магазина, можно написать к нему тест, проеряющий что при добавлении товара увеличивается число и сумма товаров в корзине.
Там вообще есть много видов тестирования. Вот мой урок про автоматизированное тестирование: https://gist.github.com/codedokode/a455bde7d0748c0a351a
> subversion
Древняя система контроля версий. Она помогает хранить исторю изменений кода и организовать совместную работу над ним. В SVN есть репозиторий, в котором хранятся все версии кода, ты берешь код оттуда, делаешь изменения и сохраняешь новую версию. В репозитории можно легко увидеть историю изменений, кто что поменял и можно получить старую версию (если например оказалось что новая версия содержит ошибки).
Подробнее: http://svnhowto.com
https://ru.wikipedia.org/wiki/Subversion
SVN довольно старый, сейчас чаще использут git, по нему есть хорошая книга: http://git-scm.com/book/ru/v1
Кстати, гит тебе пришлось бы освоить при выполнении наших дополнительных задач так как там надо код загружать на гитхаб.
В общем, не надо пугаться, все это реально изучить. Да и там вряд ли требуются глубокие знания.
Алсо, странно сочтается «требуется знать SVN» и «приветствуется опыт работы с любой системой распределения версий».
Так что я думаю, часть требований тут необязательна.
> ну это вообще бомба, у меня корпоративный дух в пятки ушел
Норм же, побегать, по мячу попинать, мне бы понравилось. Насчет стракбола, я не пробовал, это конечно вряд ли понравится, мне просто пейнтбол нравится больше. Тем более вряд ли это обязательно.
Насчет linux command line, можно установить debian (или ubuntu если все плохо) в VirtualBox и там осваивать команды bash + базовые команды вроде cat/grep и тд.
>>422700
Другие учебники могут быть устаревшими (и в них изучают какой-нибудь друвний php4 и mysq функции), они могут не ояснять нормально ООП, или содержать плохие примеры кода, например с уязвимостями или просто неправильный код. Ну и еще я проверяю решения и даю замечания и советы.
И еще мне кажется, что в моем учебнике неоторые объяснения понятнее (правда к концу учебника уровень понятности снижается). Глава про ООП у мня на мой же взгляд неплохая.
А так, ты можешь и по другому учебнику учить, я не против, я даже задачи могу проверить. Лишь бы не слишком старый был.
>>422709
https://gist.github.com/codedokode/10539213
Я уже учил по другому, но думаю полистать твой. Может обнаружу для себя что-то новое.
Если ты обнаружишь что-то новое в задачках на условия/циклы/основы ооп - то ты очень плохо читал предыдущий учебник.
$STH = $this->DBH->prepare("SELECT name, sname, groupindex, points FROM students ORDER BY :sort");
\t
\t$STH->bindparam(":sort", $sort);
\t
\t
\t$STH->execute();
В $sort поле, по которому сортируем. Оно передается методу.
>Это непраивльно с точки зрения архитектуры. Класс DataMapper умеет делать только одну вещь: загружать студентов из базы и сохранять ихз в базу. Ни при каких обстоятельствах он не должен ничего выводить на экран
fetch никуда не сохраняет данные, вернуть их через return я тоже не могу, потому-что он отдаст мне только первую строку. Как же без echo внутри метода выводить всю таблицу?
А еще вангую, что bindparam содержимое $sort в кавычках вставит в запрос.
>fetch никуда не сохраняет данные
http://php.net/manual/ru/pdostatement.fetch.php#refsect1-pdostatement.fetch-returnvalues
Можно еще привязать поля результата выборки к локальным переменным, с которыми и манипулировать. Например, в этом кусочке у меня фетчится результат выборки последних записей в базе данных чатика и массив наполняется объектами, потом массив преобразуется в json-строку:
mysqli_stmt_execute($this->stmt);
mysqli_stmt_bind_result($this->stmt, $id, $name, $msg, $date);
while(mysqli_stmt_fetch($this->stmt)){
$this->response[] = new Post($id, $name, $msg, date('d-m-Y H:i:s', $date));
}
//...
echo json_encode($db->response);
Извиняюсь за суржик из проц. и ооп-стиля.
>>422710
Аригато! Не видел, что есть еще дополнительные уроки в блоге на гитхабе.
Этого должно хватить на пару дней.
>Запомнить пользователя можно с помощью кук, ставить на 10 лет. Надо использовать какой-то код, чтобы нельзя было отредактировать чужие данные.
Я так понимаю, base64 для сайта вуза за глаза хватит? Тем более вроде бы даже md5 можно расшифровать. Какую технику сейчас используется для безопасности?
Мне уже много раз говорили, что глобальные переменные это плохо, но никто не пишет почему :<
Напиши в гугле "почему глобальные переменные плохо" и читай любую ссылку.
Ну например, чтобы если вдруг захочется взять и вынести какую-нибудь функцию в отдельную библиотеку. В этом суть юникс-вея - писать маленькие программы, которые могут принимать что-то на вход и так же выдают на выход. Как видишь, никаким глобальным переменным тут места не остается.
Ну так это на одну итерацию. Короче, я так понял, нужно создавать массив, и в каждой итерации добавлять в этот массив данные. Но, если таблица большая, не многовато ли будет для массива?
>Короче, я так понял, нужно создавать массив, и в каждой итерации добавлять в этот массив данные.
http://php.net/manual/ru/pdostatement.fetchall.php
Ты же даже не пытаешься, да?
Константы класса тебя чем-то не устраивают?
ОП, думаю как реализовать прохождение теста, а конкретней - отображение вопросов при прохождении, на тестхабе. Понравилось как это сделал яндекс https://ege.yandex.ru/chemistry/game/#question=1. То есть, как я понял, применяется AJAX и hash-навигация. Пока что не нашел ничего нормального и нового почитать по этой теме. И да, что-то мне подсказывает, IE будет против таких замечательных технологий. Можешь что-то посоветовать, какие-то статьи хотя бы.
https://gist.github.com/codedokode/8733007
>Хочу сделать за выходные
У меня для тебя плохие новости.
>Стоит ли делать класс который ее будет дублировать, писать сложные методы для синхронизации этой информации в обе стороны(между классом и формой)?
Сложные методы для синхронизации номера вопроса и его айди в $_POST['questions'].
Я забил на это и переделал все без классов. Ну и по мелочи изменения в контроллере и моделях.
https://github.com/sqghub/TestHub
http://ideone.com/e3aBs4
> } while ($player->isWinner == 0);
Я не придумал как можно зациклить бесконечно, сделал так, но чтобы изнутри цикл завершался так как мне нужно.
что тебе непонятно?
Накатил PHPStorm 8.0.2 потому что только в нем заработал удаленный xdebug без проброса портов, так как он прямо таки заточен под эту хуйню, подсунул серийник из кегена для 7-й версии и все работает.
Вопрос такой, не наебнется ли активация если разрешать программе обновляться? А то ссу чето после боев с Adobe.
Оба. Начать можно с фронтенда.
>>422737
Или там плохо объяснялось. Ну и у нас задачи, которые я проверяю, а в учебнике никто тебе советы и замечания не даст.
>>422768
bindParam предназначен для вставки чисел и текстовых строк, а не имен полей. При подстановке параметр заключается в кавычки то есть в запросе будет
ORDER BY 'name'
вместо правильного
ORDER BY name
Потому придется вставлять переменную прямл в запрос, но перед этим ты должен проверить ее по белому списку, что она содержит одно из разрешенных значений, а не что-то другое (если не проверять будет уязвимость).
> fetch никуда не сохраняет данные
Сохраняй в массив в цикле (примеры наверно есть в мануале) или используй fetchAll. Плюс, у тебя есть класс Студент и ты должен каждую полученную строку преобразовать в объект Студент и вернуть из функции массив студентов.
>>422782
> Можно еще привязать поля результата выборки к локальным переменным,
Да, можно, но по моему проще получить массив и с ним делать что надо. Вообще, как я понимаю, возможность записывать результат в переменные придумана там в первую очередь для возврата значений из хранимых процедур (в БД можно создавать свои функции и процедуры и они могут возвращать результат).
Ну и насчет json_encode примененного прямо к массиву Post — я не уверен, надежно ли это? Завтра у тебя там появится какое-то поле в классе Post которое не должен видеть пользователь и что ты будешь делать? Я бы сделал у Post метод toArray который возвращает только разрешенные поля в нужном виде.
Ну и плюс, ты зря дату хранишь строкой — лучше хранить таймстампом или объектом DateTime, так с ней удобнее работать.
> Этого должно хватить на пару дней.
У тебя все в порядке с самооценкой, я смотрю. Решения покажешь?
> Я так понимаю, base64 для сайта вуза за глаза хватит? Тем более вроде бы даже md5 можно расшифровать. Какую технику сейчас используется для безопасности?
Ты неправильно мыслишь. base64 это не шифрование, это просто способ закодировать произвольные данные с помощью 64 символов.
Насчет расшифровки md5 — расшифровать можно, но не в любом случае. Если ты закодировал простую строку типа abcdef12 то можно, а если сложную то очень долго, годами и столетиями.
Если речь о сайте про регистрацию абитуриентов то там надо применить надежную защиту. Я бы сделал так: при регистрации мы генерируем длинный уникальный код (например 32 символа), и сохраняем его в базу и в куки. Также, в куки кладем id абитуриента. Соответственно когда абитуриент заходит на сайт повтороно, по паре id + секретный код из кук мы можем определить что это именно он. Злоумышленник не сможет притвориться кем-то еще так как не знает секретный код.
> fetch никуда не сохраняет данные
Сохраняй в массив в цикле (примеры наверно есть в мануале) или используй fetchAll. Плюс, у тебя есть класс Студент и ты должен каждую полученную строку преобразовать в объект Студент и вернуть из функции массив студентов.
>>422782
> Можно еще привязать поля результата выборки к локальным переменным,
Да, можно, но по моему проще получить массив и с ним делать что надо. Вообще, как я понимаю, возможность записывать результат в переменные придумана там в первую очередь для возврата значений из хранимых процедур (в БД можно создавать свои функции и процедуры и они могут возвращать результат).
Ну и насчет json_encode примененного прямо к массиву Post — я не уверен, надежно ли это? Завтра у тебя там появится какое-то поле в классе Post которое не должен видеть пользователь и что ты будешь делать? Я бы сделал у Post метод toArray который возвращает только разрешенные поля в нужном виде.
Ну и плюс, ты зря дату хранишь строкой — лучше хранить таймстампом или объектом DateTime, так с ней удобнее работать.
> Этого должно хватить на пару дней.
У тебя все в порядке с самооценкой, я смотрю. Решения покажешь?
> Я так понимаю, base64 для сайта вуза за глаза хватит? Тем более вроде бы даже md5 можно расшифровать. Какую технику сейчас используется для безопасности?
Ты неправильно мыслишь. base64 это не шифрование, это просто способ закодировать произвольные данные с помощью 64 символов.
Насчет расшифровки md5 — расшифровать можно, но не в любом случае. Если ты закодировал простую строку типа abcdef12 то можно, а если сложную то очень долго, годами и столетиями.
Если речь о сайте про регистрацию абитуриентов то там надо применить надежную защиту. Я бы сделал так: при регистрации мы генерируем длинный уникальный код (например 32 символа), и сохраняем его в базу и в куки. Также, в куки кладем id абитуриента. Соответственно когда абитуриент заходит на сайт повтороно, по паре id + секретный код из кук мы можем определить что это именно он. Злоумышленник не сможет притвориться кем-то еще так как не знает секретный код.
Недостатки становятся видны только когда кода много.
Глобальную переменную можно прочесть и изменить из любого места программы. Это делает код спутанным (код из одного места программы лезет в переменную совсем в другом месте). Например, чтобы переименовать эту переменную, придется искать ее в куче мест. Если ты захочешь поменять что-то связанное с переменной, то придется менять код в куче мест. Чтобы понять почему в эту переменную пишется что-то не то, придется найти и изучить все места где она меняется.
Также, в большой программе будет много переменных и если они все будут глобальными то она превратится в спутанный клубок взаимосвязей.
Если функция использует глобальные переменные:
$x = someFunction($a, $b, $c);
то труднее понять что окажется в $x, так как это зависит не только от a, b, c а еще и от других переменных.
Тестировать автоматизированми тестами такой код разумеется тоже становится сложнее если вообще возможно.
Потому, чтобы не запутаться по мере увеличения программы, ее стараются разбивать на маленькие независимые блоки: функции (при процедурном подходе) или классы (при ООП подходе). Без глобальных переменных.
> не многовато ли будет для массива?
нет
>>422818
hash-навигация это хорошо, так как при перезагрузке страницы не пропадает текущий номер вопроса.
Но использовать яваскрипт не обязательно, ты можешь просто сделать вопрос формой, которая постит ответ на URL вроде
/test/123456/q/12
То естьa action формы содержит id теста и номер вопроса.
В новых браузерах можно обойтись без хеша, а менять яваскриптом сам URL например /test/q/23 (а также получать событие когда пользователь переходит вперед/назад) — это называется HTML 5 History: http://habrahabr.ru/post/123106/
> IE будет против таких замечательных технологий
hash навигация работает во всех старых IE. Она вообще везде работает. Также как и классические формы.
Посоветовать, не знаю, можешь html 5 history api глянуть, но вообще тут можно сделать так, чтобы и без JS работало.А при наличии JS — работало лучше. Например, чтобы шел отсчет времени (а без JS оно бы обновлялось только при отправки формы).
Мне кажется полезно было бы реализовать «graceful degradation» то есть если нет JS все работает по простой схеме, если есть то с улучшенным удобством. Это позволяет нам сделать сайт более надежным на случай ошибки в JS или проблемах с интернетом. Ну и полезно усложнять себе жизнь.
Бамп
Только вот не уверен что хорошо объединять в одну кнопки «пропустить» и «ответить» — это может путать пользователя.
(алсо я прошел тест по химии и набрал 13%. Не мой это предмет)
Советы и замечания
> 'test' => new Test(),
> 'questionTemplate' => new Question(),
> 'answerTemplates' => Answer::getAnswersTemplates(),
> 'questionTypes' => Question::getQuestionTypes(),
> 'questionTypeLabels' => Question::getQuestionTypeLabels(),
Что-то слишком много переменных. Я думаю, можно перенести часть кода в Test (например сделать в нем метод test->getQuestionTemplate()). Также, если getQuestionTypes будет не-статическим, его тоже можно вызывать из шаблона. Ну это так, мысли, делать так не обязательно.
> <link href="/css/test-create.css" rel="stylesheet">
Запиши на будущее: разобраться со статикой (assets) в Юи. Там есть что-то встроенное чтобы подключить CSS файл к странице, есть возможности склеивания статики и много чего еще.
> id="questionType{{ questionTypes.QUESTION_WITH_ONE_CHOICE }}"
> set answerTemplatePath = "answer_type_#{questionTypes.QUESTION_WITH_ONE_CHOICE}.twig" %}
Здесь наверно не стоило использовать константу, а просто название. А то у тебя получается имя файла от значения константы зависит. И понять что значит 1 или 2, трудно. Лучше answer_type_with_one_choice.twig. Но если это сложно переделать, можешь оставить как есть.
> function addForeword(event) {
> div.innerHTML = '{{ form.field
Не стоит наверно так сложно делать, лучше наверно просто сделать див и прописать ему display:none или класс вроде js-hidden, который снимается при нажатии на кнопку. Это же меньше кода потребует и проще устроено. И можно легко сделать скрытие при повторном нажатии на ссылку.
Ну и если ты не знаком с jQuery, я советую с ней познакомиться и параллельно решить мои задачки на нее. Я не говорю, что ее обязательно тут использовать, но она очень часто используется и лучше ее знать.
// Насчет расчета curId, там нет ошибок вроде того что мы удалили первые 5 вопросов из 10, осталось 5 вопросов но у них id = 6 ... 10?
В TestController я бы перенумеровывал вопросы заново. А то от пользователя может придти (в том числе из-за какой-то ошибки) несколько вопросов с одинаковым номером или без номеров или с текстом вместо номера. Надежнее наверно отсортировать массив и перепроставить номера на стороне сервера. Также, стоит код разобра вопросов из POST вынести в отдельный метод/методы, а не писать все в один метод.
Вот тут вот нехорошо, магические числа пошли:
Достучаться до константы из твига вроде можно функцией constant: http://twig.sensiolabs.org/doc/tests/constant.html
тут лучше кнопку в div завернуть
Насчет смены типа вопроса. Можно сделать еще так: разбить вопрос на несколько блоков, при смене типа вопроса менять css класс на вопросе, и из-за смена класса блоки будут скрываться/появляться. Но не знаю, будет ли это проще чем сейчас? Если нет то наверно не стоит делать.
Еще: ты удаляешь ответы при смене типа вопроса. Но мне кажется лучше, когда при смене с множественного на одиночный варианты ответов сохраняются те же (можно их копировать яваскриптом), а при смене с числового на вопрос с выбором и обратно введенный ранее ответ не теряется. Это можно сделать при использовании схемы со скрытием блоков (вместо удаления из DOM) и разных именах input для разных типов ответов. То есть на мой взгляд, скрытие вместо удаления выгоднее. Это дает нам сохранение введенных данных и проще реализуется: надо всего лишь поменять один класс. Обычно в формах, где надо скрыть/показать поля так и делают.
> var span = event.toElement;
Странное какое-то свойство. Оно стандартное (тут http://www.quirksmode.org/dom/w3c_events.html написано оно относится к mouseover)? Если ты хочешь получить ссылку на span надо писать либо
var span = event.target || event.srcElement; // w3c и старые IE соответсвенно
Либо же передавать ее через this:
<span onclick="addForeword(this)"
> function getElementsByClass(node, className) {
В новых браузерах есть querySelector, querySelectorAll, getElementsByClassName, стоит их тоже использовать если они доступны.
Для получения нового id лучше сделать функцию, а не лезть в переменную.
Также, плохо что переменные curId и curNumber инициализируются не в файле create-test.js (где они используются), а в другом месте. Это усложняет код. Лучше создавать их там же, и сделать функцию вроде init которую можно вызвать из шаблона чтобы задать начальные значения.
Насчет массива questionsData, а он нужен? Я вижу что там немало строк написано чтобы поддерживать его в актуальном состоянии, но если эта информация есть в DOM, может проще ее брать из инпутов чем поддерживать массив? А то у нас появляется лишняя проблема: синхронизировать этот массив с изменениями в DOM. Хотя без него, конечно, придется как-то считать questionsCount.
> event.toElement.parentNode.insertBefore
Лучше наверно сделать div-плейсхолдер, который обозначает место вставки нового вопроса. Или использовать существующий див.
> https://github.com/sqghub/TestHub/blob/2a3f0471563b410adc8cfbc967ebddc22d7df801/models/Test.php#L29
Там есть удобная функция transaction http://www.yiiframework.com/doc-2.0/yii-db-connection.html для этого.
Вообще, похоже, что TestHub получилась довольно сложной задачей. Может быть на уровне опытного джуниора, может даже чуть выше. Ну что поделать, тяжело в учении. Ты пока что хорошо справляешься.
Советы и замечания
> 'test' => new Test(),
> 'questionTemplate' => new Question(),
> 'answerTemplates' => Answer::getAnswersTemplates(),
> 'questionTypes' => Question::getQuestionTypes(),
> 'questionTypeLabels' => Question::getQuestionTypeLabels(),
Что-то слишком много переменных. Я думаю, можно перенести часть кода в Test (например сделать в нем метод test->getQuestionTemplate()). Также, если getQuestionTypes будет не-статическим, его тоже можно вызывать из шаблона. Ну это так, мысли, делать так не обязательно.
> <link href="/css/test-create.css" rel="stylesheet">
Запиши на будущее: разобраться со статикой (assets) в Юи. Там есть что-то встроенное чтобы подключить CSS файл к странице, есть возможности склеивания статики и много чего еще.
> id="questionType{{ questionTypes.QUESTION_WITH_ONE_CHOICE }}"
> set answerTemplatePath = "answer_type_#{questionTypes.QUESTION_WITH_ONE_CHOICE}.twig" %}
Здесь наверно не стоило использовать константу, а просто название. А то у тебя получается имя файла от значения константы зависит. И понять что значит 1 или 2, трудно. Лучше answer_type_with_one_choice.twig. Но если это сложно переделать, можешь оставить как есть.
> function addForeword(event) {
> div.innerHTML = '{{ form.field
Не стоит наверно так сложно делать, лучше наверно просто сделать див и прописать ему display:none или класс вроде js-hidden, который снимается при нажатии на кнопку. Это же меньше кода потребует и проще устроено. И можно легко сделать скрытие при повторном нажатии на ссылку.
Ну и если ты не знаком с jQuery, я советую с ней познакомиться и параллельно решить мои задачки на нее. Я не говорю, что ее обязательно тут использовать, но она очень часто используется и лучше ее знать.
// Насчет расчета curId, там нет ошибок вроде того что мы удалили первые 5 вопросов из 10, осталось 5 вопросов но у них id = 6 ... 10?
В TestController я бы перенумеровывал вопросы заново. А то от пользователя может придти (в том числе из-за какой-то ошибки) несколько вопросов с одинаковым номером или без номеров или с текстом вместо номера. Надежнее наверно отсортировать массив и перепроставить номера на стороне сервера. Также, стоит код разобра вопросов из POST вынести в отдельный метод/методы, а не писать все в один метод.
Вот тут вот нехорошо, магические числа пошли:
Достучаться до константы из твига вроде можно функцией constant: http://twig.sensiolabs.org/doc/tests/constant.html
тут лучше кнопку в div завернуть
Насчет смены типа вопроса. Можно сделать еще так: разбить вопрос на несколько блоков, при смене типа вопроса менять css класс на вопросе, и из-за смена класса блоки будут скрываться/появляться. Но не знаю, будет ли это проще чем сейчас? Если нет то наверно не стоит делать.
Еще: ты удаляешь ответы при смене типа вопроса. Но мне кажется лучше, когда при смене с множественного на одиночный варианты ответов сохраняются те же (можно их копировать яваскриптом), а при смене с числового на вопрос с выбором и обратно введенный ранее ответ не теряется. Это можно сделать при использовании схемы со скрытием блоков (вместо удаления из DOM) и разных именах input для разных типов ответов. То есть на мой взгляд, скрытие вместо удаления выгоднее. Это дает нам сохранение введенных данных и проще реализуется: надо всего лишь поменять один класс. Обычно в формах, где надо скрыть/показать поля так и делают.
> var span = event.toElement;
Странное какое-то свойство. Оно стандартное (тут http://www.quirksmode.org/dom/w3c_events.html написано оно относится к mouseover)? Если ты хочешь получить ссылку на span надо писать либо
var span = event.target || event.srcElement; // w3c и старые IE соответсвенно
Либо же передавать ее через this:
<span onclick="addForeword(this)"
> function getElementsByClass(node, className) {
В новых браузерах есть querySelector, querySelectorAll, getElementsByClassName, стоит их тоже использовать если они доступны.
Для получения нового id лучше сделать функцию, а не лезть в переменную.
Также, плохо что переменные curId и curNumber инициализируются не в файле create-test.js (где они используются), а в другом месте. Это усложняет код. Лучше создавать их там же, и сделать функцию вроде init которую можно вызвать из шаблона чтобы задать начальные значения.
Насчет массива questionsData, а он нужен? Я вижу что там немало строк написано чтобы поддерживать его в актуальном состоянии, но если эта информация есть в DOM, может проще ее брать из инпутов чем поддерживать массив? А то у нас появляется лишняя проблема: синхронизировать этот массив с изменениями в DOM. Хотя без него, конечно, придется как-то считать questionsCount.
> event.toElement.parentNode.insertBefore
Лучше наверно сделать div-плейсхолдер, который обозначает место вставки нового вопроса. Или использовать существующий див.
> https://github.com/sqghub/TestHub/blob/2a3f0471563b410adc8cfbc967ebddc22d7df801/models/Test.php#L29
Там есть удобная функция transaction http://www.yiiframework.com/doc-2.0/yii-db-connection.html для этого.
Вообще, похоже, что TestHub получилась довольно сложной задачей. Может быть на уровне опытного джуниора, может даже чуть выше. Ну что поделать, тяжело в учении. Ты пока что хорошо справляешься.
Зато ты получишь бесплатные советы и замечания по коду.
>>422875
> зациклить бесконечно,
do { } while (true);
> for ($i = 0; $i <= 99; $i++)
> $zone = range(1, 100, 1);
for по моему тут лишний
Ну и еще хорошо бы при выводе карты добивать там пробелами чтобы она была ровной (а у тебя первый ряд съехал).
И еще, тут
> foreach ($this->zone as &$square) {
> foreach ($this->players as $player) {
Первый цикл по моему лишний. Незачем обходить все клетки на поле, можно взять позицию игрока и по ней определить ключ клетки в массиве.
А так, вообще, общее впечатление от программы хорошее, видно что все работает.
Она сложная если не знать алгоритма. Я советую почитать статью в вики, где есть список алгоритмов. Дейкстра например несложный:
http://ru.wikipedia.org/wiki/%D0%9F%D0%BE%D0%B8%D1%81%D0%BA_%D0%BF%D1%83%D1%82%D0%B8
Тебе надо лишь реализовать этот алгоритм на php.
>>422886
Кошкомышки сложнее.
>>422905
Тут описано: http://habrahabr.ru/post/137664/ (prepared statements)
>>422936
Я на вопросы про взлом программ не отвечаю (да у меня и phpstorm нет). Может кто из анонов знает.
Кстати, у jetBrains можно (или уже нет?) получить бесплатную лицензионную тестовую версию, но она может быть с багами так как самая новая.
>>422941
Не знаю. Почему одни люди пытаются поставить себя выше чем другие? Может у них психологические проблемы какие-то?
У php есть конечно недостатки, но для нчинающего язык вполне подходит, и на него очень много вакансий.
Она сложная если не знать алгоритма. Я советую почитать статью в вики, где есть список алгоритмов. Дейкстра например несложный:
http://ru.wikipedia.org/wiki/%D0%9F%D0%BE%D0%B8%D1%81%D0%BA_%D0%BF%D1%83%D1%82%D0%B8
Тебе надо лишь реализовать этот алгоритм на php.
>>422886
Кошкомышки сложнее.
>>422905
Тут описано: http://habrahabr.ru/post/137664/ (prepared statements)
>>422936
Я на вопросы про взлом программ не отвечаю (да у меня и phpstorm нет). Может кто из анонов знает.
Кстати, у jetBrains можно (или уже нет?) получить бесплатную лицензионную тестовую версию, но она может быть с багами так как самая новая.
>>422941
Не знаю. Почему одни люди пытаются поставить себя выше чем другие? Может у них психологические проблемы какие-то?
У php есть конечно недостатки, но для нчинающего язык вполне подходит, и на него очень много вакансий.
> не удаётся подсчитать в функции все необходимые суммы баллов
Это потому что у тебя есть класс Quest (Вопрос) объект которого представляет один вопрос. И разумеется этот объект-вопрос может посчитать только число баллов за себя, он не может приплюсовать баллы за другие вопросы так как за них отвечают другие объекты. Так что ничего не поделать, надо считать сумму отдельно, а не внутри класса.
> PHP Notice: Undefined variable: totalPoints in /home/2y8gpV/prog.php on line 51
У тебя там ошибка, ты не задал для переменной начальное значение
Ну и не стоит сокращать названия, тяжело становится читать код. Если тебе неудобно писать большие решения на ideone то скачай редактор или IDE с функцией автодополнения и пиши там.
Также, пропусти код через phpformatter.com, а то все куда-то съехало.
В остальном, вроде все верно.
Википидор, что ли? Какая мерзость...
>// Насчет расчета curId, там нет ошибок вроде того что мы удалили первые 5 вопросов из 10, осталось 5 вопросов но у них id = 6 ... 10?
Это не ошибка. Я отвязал id вопросов от их номеров. За номер вопроса другая переменная отвечает. И просто инпут.
>В TestController я бы перенумеровывал вопросы заново.
Это и планируется. Просто я вчера только с js разбирался.
>Также, стоит код разобра вопросов из POST вынести в отдельный метод/методы, а не писать все в один метод.
Вот только к чему приткнуть этот метод?
>Достучаться до константы из твига вроде можно функцией constant
Только для сравнения. С статическими методами и константами класса твиг не дружит (как где-то написали, это шаблонизатор и оно ему не надо).
>Но не знаю, будет ли это проще чем сейчас?
Никакой разницы. Просто классы четырем блокам проставить.
Но тогда же мне на сервер приедет массив с хламом по каждому типу вопроса, так?
>Лучше наверно сделать div-плейсхолдер, который обозначает место вставки нового вопроса.
Да, наверное так и сделаю.
>Там есть удобная функция transaction
Что-то я профукал её.
>Ты пока что хорошо справляешься.
Неправда. Я пока с яваскриптом воюю, а вместо php кода у меня одна заглушка сплошная.
'w' Открывает файл только для записи; помещает указатель в начало файла и обрезает файл до нулевой длины. Если файл не существует - пробует его создать.
'w+' Открывает файл для чтения и записи; помещает указатель в начало файла и обрезает файл до нулевой длины. Если файл не существует - пытается его создать.
В описании разница только в одном слове, да и те синонимы. А в чем различия на самом деле?
> почему "трупогромисты" так хейтят пхп и за яп не считают? Выебываются?
Потому что на пыхе много таких вот "программистов", хотя это и не вина языка.
>>423033
'w'\tOpen for writing only; place the file pointer at the beginning of the file and truncate the file to zero length. If the file does not exist, attempt to create it.
'w+'\tOpen for reading and writing; place the file pointer at the beginning of the file and truncate the file to zero length. If the file does not exist, attempt to create it.
Вот еще с одной проблемой столкнулся. Когда я поставил в setFetchMode строку с именем класса вместо функции getClassName мне стал выдавать ошибку Object of class student could not be converted to string. Не понимаю с чего бы это? И так и так там была строка с именем класса, только до этого она вставлялась из переменной, а сейчас я пишу её напрямую.
Спасибо, доделал. Попробую со своими скудными знаниями в html запилить какую-никакую оболочку
А все разобрался, дело вообще в другом было.
Пиздец я засиделся. Минуту вчтитывался прежде чем запостить, а сейчас увидел что первый только пишет.
А ты конечно мудак, мда. Раз выебываешься здесь, среди чайников.
Я конечно мудак, с этим я согласен. Но документацию надо глазами читать а не жопой. Не можешь осилить английский язык - пиздуй из профессии. Deal with it.
Ты конечно извини меня за грубость выражений. Вообще ты няша, и я когда то был точно таким нубом и точно так же тупил.
Он русский не осилил, а не английский. Так, между прочим.
Спасибо за ответ, а как например подсчитать другие параметры, например общее количество возможных балов и т.д.? Надо менять класс? И если не сложно можешь досказать как реализовать данный тест интерактивно на ПХП? Я примерно понимаю как сделать все вопросы на одной странице при помощи форм, но как в ООП сделать переход от вопроса к вопросу на странице (например при помощи action в форме) насколько я понимаю при переходе на другую страницу вся ООП конструкция просто исчезнет.
Переделал, но не выходит запускать следующий раунд кнопкой, игра начинается с нуля видимо потому, что заново создаются объекты http://ideone.com/pUZhed и index.html http://codepad.org/1hYdoEkB
как запускать игру кнопкой чтобы использовало те данные которые остались после предыдущего раунда?
http://jsbin.com/qozajoyawe/1/edit
> Вот только к чему приткнуть этот метод?
в контроллере сделать методы типа parseQuestions, parseAnswers
> С статическими методами и константами класса твиг не дружит (как где-то написали, это шаблонизатор и оно ему не надо).
Да, наверно там предполагается что все что нужно ты явно передашь. Но в любм случае писать число 3 вместо константы неправильно.
> Но тогда же мне на сервер приедет массив с хламом по каждому типу вопроса, так?
Придет, да, но хлам к тебе может придти в любом случае, из-за ошибки или злонамеренных действий. Потому ты должен брать из POST только то что нужно, а не все подряд.
Мне просто показалось что скрывать/показывать элементы проще чем писать код добавления/удаления из DOM. И данные не теряются при переключении.
>в контроллере сделать методы типа parseQuestions, parseAnswers
А я его в тест унес.
>Мне просто показалось что скрывать/показывать элементы проще чем писать код добавления/удаления из DOM. И данные не теряются при переключении.
С этим разберусь чуть позже. Меня немного подташнивает от js, честно говоря.
Я там немного пораскидал хлам из контроллера. И по мелочи методов сделал.
Покажи код
>>423045
Если ты хочешь чтобы это в браузере работало и двигалось, придется JS освоить (у меня есть и задачки на него если что).
>>423057
Понять действительно трудно. Я сам раза 2 или 3 перечитал прежде чем заметил разницу. Тут стоило бы различающуюся часть выделить например жирным шрифтом иначе трудно заметить.
Так что ты не прав. Документаию надо писать для людей, а не для роботов.
>>423062
> а как например подсчитать другие параметры, например общее количество возможных балов и т.д.?
Сделать функцию для этого. Или сделать класс Тест который содержит массив вопросов и считает что надо для них.
> насколько я понимаю при переходе на другую страницу вся ООП конструкция просто исчезнет.
Верно. Но сохранять вопросы и не требуется так как мы всегда можем сздать их заново. А вот сохранять ответы пользователя и номер текущего вопроса — надо. Для этого можно использовать файлы, куки, сессию, базу данных. В данной задаче удобнее всего использовать сессию. Или же выводить все вопросы сразу, чтобы пользователь отправлял все ответы одновременно, тогда сохранять ничего не требуется.
> как реализовать данный тест интерактивно на ПХП?
Если делать по такой схеме: появляется страница с вопросами, ты выбираешь ответы и жмешь «проверить» то не очень сложно. Если ты хочешь чтобы вопросы появлялись по одному, а в конце выводлились итоги то чуть сложнее.
Потому, что когда ты загружаешь страницу в браузере, на сервере запускается скрипт, генерирует страницу и завершается.Все переменные удаляются. Соответственно, если ты вводишь ответы по одному, то надо куда-то (например в сессию) сохранять номер текущего вопроса и предыдущие ответы, чтобы на самой последней странице мы могли их проверить. Потому сделать вариант когда все вопросы на одной странице, проще.
Тебе надо знать основы HTML ( http://htmlbook.ru/samhtml ), формы, и как из php выводить html и читать данные форм:
http://php.net/manual/ru/language.basic-syntax.phpmode.php
http://php.net/manual/ru/tutorial.php
Также, тебе понадобится веб-сервер, например, Апач. Так как именно он взаимодействует с браузером, принимая и отвечая на запросы. Вот инструкция по установке:
https://gist.github.com/codedokode/10774100
https://gist.github.com/codedokode/7054af4a03865c4cc863
Если что-то непонятно, спрашивай, я подскажу.
Покажи код
>>423045
Если ты хочешь чтобы это в браузере работало и двигалось, придется JS освоить (у меня есть и задачки на него если что).
>>423057
Понять действительно трудно. Я сам раза 2 или 3 перечитал прежде чем заметил разницу. Тут стоило бы различающуюся часть выделить например жирным шрифтом иначе трудно заметить.
Так что ты не прав. Документаию надо писать для людей, а не для роботов.
>>423062
> а как например подсчитать другие параметры, например общее количество возможных балов и т.д.?
Сделать функцию для этого. Или сделать класс Тест который содержит массив вопросов и считает что надо для них.
> насколько я понимаю при переходе на другую страницу вся ООП конструкция просто исчезнет.
Верно. Но сохранять вопросы и не требуется так как мы всегда можем сздать их заново. А вот сохранять ответы пользователя и номер текущего вопроса — надо. Для этого можно использовать файлы, куки, сессию, базу данных. В данной задаче удобнее всего использовать сессию. Или же выводить все вопросы сразу, чтобы пользователь отправлял все ответы одновременно, тогда сохранять ничего не требуется.
> как реализовать данный тест интерактивно на ПХП?
Если делать по такой схеме: появляется страница с вопросами, ты выбираешь ответы и жмешь «проверить» то не очень сложно. Если ты хочешь чтобы вопросы появлялись по одному, а в конце выводлились итоги то чуть сложнее.
Потому, что когда ты загружаешь страницу в браузере, на сервере запускается скрипт, генерирует страницу и завершается.Все переменные удаляются. Соответственно, если ты вводишь ответы по одному, то надо куда-то (например в сессию) сохранять номер текущего вопроса и предыдущие ответы, чтобы на самой последней странице мы могли их проверить. Потому сделать вариант когда все вопросы на одной странице, проще.
Тебе надо знать основы HTML ( http://htmlbook.ru/samhtml ), формы, и как из php выводить html и читать данные форм:
http://php.net/manual/ru/language.basic-syntax.phpmode.php
http://php.net/manual/ru/tutorial.php
Также, тебе понадобится веб-сервер, например, Апач. Так как именно он взаимодействует с браузером, принимая и отвечая на запросы. Вот инструкция по установке:
https://gist.github.com/codedokode/10774100
https://gist.github.com/codedokode/7054af4a03865c4cc863
Если что-то непонятно, спрашивай, я подскажу.
Код ужасно отформатирован и трудно понять что к какому циклу относится. Тебе надо было пропустить его через сайт phpformatter.com
Также, я вижу ты поставил много комментариев. Но если бы ты давал понятные названия переменным (а не c или h) то может быть эти комментарии и не потребовались бы.
Насчет выбора варианта, какую дверь открыть: надо делать проще. Копируем массив всех вариантов в новую переменную. Удаляем из него (array_diff) правильный ответ. Удаляем из него выбранный игроком ответ. Остается 1 ли 2 элемента. Выбираем случайно любой из них (например с помощью array_rand).
Ну и соответственно, выиграет игрок при смене ответа или нет определяется просто:
- если игрок изначально угадал дверь то при смене ответа он проиграет
- если игрок не угадал дверь то при смене ответа он выигрывает
То есть цикл вот этот:
> for($j=0; $j<=2; $j++) {
> if($option!=$allOption[$j] &&
> $select!=$allOption[$j]) {
> $change=$allOption[$j];
По моему не нужен вообще.
В общем, переименуй переменные, отформатируй код, убери лишние циклы и я думаю, код сократится раза в 2.
Так, считает твоя программа вроде правильно, но точнее трудно сказать из-за запутанного кода.
> //Обнулим все переменные
это не требуется так как команда «=» вот тут
> $p1=$replace/$exp;
Удаляет старое значение p1 и заменяет новым
Аналогично, массив очищать не надо. Вместо этого надо написать в начале цикла forOpt = array( );
Вот какие можно поставить имена:
$h -> experimentCount
exp -> testsCount
replace -> winIfReplace/winIfChange
noReplace -> loseIfChange
forOpt -> удалить или переименовать нормально
p1/p2 -> winIfChangeProbability/loseIfChangeProbability
> if($correct!=$option) {
> if($correct==$option) {
Вместо второго if можно поставить else
Код ужасно отформатирован и трудно понять что к какому циклу относится. Тебе надо было пропустить его через сайт phpformatter.com
Также, я вижу ты поставил много комментариев. Но если бы ты давал понятные названия переменным (а не c или h) то может быть эти комментарии и не потребовались бы.
Насчет выбора варианта, какую дверь открыть: надо делать проще. Копируем массив всех вариантов в новую переменную. Удаляем из него (array_diff) правильный ответ. Удаляем из него выбранный игроком ответ. Остается 1 ли 2 элемента. Выбираем случайно любой из них (например с помощью array_rand).
Ну и соответственно, выиграет игрок при смене ответа или нет определяется просто:
- если игрок изначально угадал дверь то при смене ответа он проиграет
- если игрок не угадал дверь то при смене ответа он выигрывает
То есть цикл вот этот:
> for($j=0; $j<=2; $j++) {
> if($option!=$allOption[$j] &&
> $select!=$allOption[$j]) {
> $change=$allOption[$j];
По моему не нужен вообще.
В общем, переименуй переменные, отформатируй код, убери лишние циклы и я думаю, код сократится раза в 2.
Так, считает твоя программа вроде правильно, но точнее трудно сказать из-за запутанного кода.
> //Обнулим все переменные
это не требуется так как команда «=» вот тут
> $p1=$replace/$exp;
Удаляет старое значение p1 и заменяет новым
Аналогично, массив очищать не надо. Вместо этого надо написать в начале цикла forOpt = array( );
Вот какие можно поставить имена:
$h -> experimentCount
exp -> testsCount
replace -> winIfReplace/winIfChange
noReplace -> loseIfChange
forOpt -> удалить или переименовать нормально
p1/p2 -> winIfChangeProbability/loseIfChangeProbability
> if($correct!=$option) {
> if($correct==$option) {
Вместо второго if можно поставить else
А вообще, сама задача неплохая. Только код надо улучшить.
>>423085
Чтобы сохранять данные между запусками скрипта, надо использовать куки, файлы, сессии, базу данных. В твоем случае удобнее всего использовать сессию.
Сессия - это хранилище данных на сервере, которое для тебя выглядит как массив $_SESSION. В начале выполнения скрипта по команде session_start() php загружает данные из хранилища в массив _SESSION (а если сессии пока не существует, то он создает пустой массив), а в конце сохраняет из массива в хранилище. Сессия уникальна для каждого пользователя (точнее для каждого браузера, если у пользователя открыта игра в 2 браузерах то будет 2 сессии), так как использует куку чтобы хранить id сесиии.
Кука нужна, так как на сервере в хранилище хранятся данные разных пользователей и надо как-то их различать. Для этого у каждой сессии есть свой уникальный id и при создании новой сессии php выставляет куку PHPSESSID с ним. Кука сохраняется в браузере. Когда пользователь второй раз зайдет на страницу, его браузер передает на сервер эту куку, а php по идентификатору в ней находит сессию именно этого пользователя.
Так как session_start при создании сессии выставляет куки (а куки нельзя ставить если начался вывод данных), эта команда должна идти до того как выведется хоть одна буква или символ, в самом начале программы.
В общем, данные сессий хранятся на сервере (по умолчанию в файлах в временной папке), а идентификатор сессии хранится у пользователя в браузере в куке PHPSESSID.
Неактивные в течение 15-30 минут сессии удаляются. Сессия — это временное, а не постоянное хранилище данных.
Мануал:
http://php.net/manual/ru/book.session.php
Если есть какие-то вопросы, задавай.
В общем тебе надо создавать сессию и в нее сохранять ник игрока, и позиции игроков (проще всего сохранить сам массив игроков целиком. PHP сериализует его сам с помощью serialize при сохранении сессии, и сам восстановит в следующий раз).
То есть если сессия пуста, значит игрок только что зашел в игру и надо показать стартовую страницу и спросить его ник.
Если не пуста, значит игра уже начата, надо достать из сессии массив игроков, сделать следующий ход, отобразить карту.
Работу с POST/GET не стоит класть в модель так как это не ее задача, взаимодействовать с пользователем. Это должно быть в контроллере или классе-помощнике контроллера.
> Меня немного подташнивает от js, честно говоря.
Задачки на js порешал бы. У нас там для первых 4 даже автоматическая проверялка есть.
Код гляну попозже тогда.
>Задачки на js порешал бы. У нас там для первых 4 даже автоматическая проверялка есть.
Я делал их. Первых штук 16.
>Это должно быть в контроллере или классе-помощнике контроллера.
Тогда уж в контроллере надо сделать массив нужных значений, а разгребать их в объект уже в модели.
Спасибо, не знал про array_diff, если бы знал может сразу написал бы компактнее код.
Исправил код. Правда столбцы до сих пор выводятся через echo в перемешку с хтмл кодом. Могу еще конечно вставлять foreach для каждой ячейки, больше я не знаю как вывести это таблицей.
А хотя нет, я щас подумал, через foreach в каждой ячейке не получится. Так что то, как я сделал, это единственный известный мне способ вывода таблицы. Жду предложений.
> <?php include "/templates/template.html"; ?>
Я бы переименовал template в header, так как у тебя сейчас это именно хеадер. Под темплейтом понимают несколько другое.
> foreach ($table as $student) { ... }
В шаблонах используй альтернативный синтаксис управляющих структур.
> <?php echo
Желательно использовать <?=
Мимо джун
>Желательно использовать <?=
Я так делал и у меня ошибку выдавало. Видимо я что-то не так делаю, либо это нужно настраивать в php.ini
> Начиная с PHP 5.4 короткий тег echo <?= всегда распознается и действует, несмотря на значение опции short_open_tag.
Ответ на твой вопрос - нет, но только с версии 5.4 и выше. Для более ранних версий - да.
А это был не вопрос.
Тут всё ясно как бы в массиве $bacon храним кодировку, в переменной $word текст для раскодирования:
$bacon=array('a'=>'AAAAA', 'b'=>'AAAAB', 'c'=>'AAABA', 'd'=>'AAABB', 'e'=>'AABAA', 'f'=>'AABAB');
$word="the jOs to kIll fAr";
Здесь удаляем пробелы в слове для раскодировки и добавляем пробелы после каждой пятой буквы
$word=str_replace(" ","",$word);
$word=wordwrap($word,5," ",true);
Все большие и маленькие буквы меняем на В и А, что бы представить слово в шифре Бэкона
$word=preg_replace("![A-Z]!", "B", $word);
$word=preg_replace("![a-z]!", "A", $word);
Начинается хуета, добавляем в конец строки " B", так как будем разбивать на массив по пробелу полученную строку
что бы все элементы попали в массив полученный через explode. Также меняем в массиве $bacon ключи и значения местами
$word.=" B";
$word1=explode(" ",$word);
$bacon=array_flip($bacon);
$baconWord="";
Теперь записываем в переменную $baconWord элементы массива которые можно найти по ключу который можно найти через массив $word1
for($i=0; $i<count($word1); $i++) {
$baconWord.=$bacon[$word1[$i]];
}
echo $baconWord;
Это очень тупой код, но я не знаю как справиться иначе, несмотря на то что работает скрипт очень лажовый. Можешь подсказать анон если не сложно, как можно написать этот код более компактнее
Тут всё ясно как бы в массиве $bacon храним кодировку, в переменной $word текст для раскодирования:
$bacon=array('a'=>'AAAAA', 'b'=>'AAAAB', 'c'=>'AAABA', 'd'=>'AAABB', 'e'=>'AABAA', 'f'=>'AABAB');
$word="the jOs to kIll fAr";
Здесь удаляем пробелы в слове для раскодировки и добавляем пробелы после каждой пятой буквы
$word=str_replace(" ","",$word);
$word=wordwrap($word,5," ",true);
Все большие и маленькие буквы меняем на В и А, что бы представить слово в шифре Бэкона
$word=preg_replace("![A-Z]!", "B", $word);
$word=preg_replace("![a-z]!", "A", $word);
Начинается хуета, добавляем в конец строки " B", так как будем разбивать на массив по пробелу полученную строку
что бы все элементы попали в массив полученный через explode. Также меняем в массиве $bacon ключи и значения местами
$word.=" B";
$word1=explode(" ",$word);
$bacon=array_flip($bacon);
$baconWord="";
Теперь записываем в переменную $baconWord элементы массива которые можно найти по ключу который можно найти через массив $word1
for($i=0; $i<count($word1); $i++) {
$baconWord.=$bacon[$word1[$i]];
}
echo $baconWord;
Это очень тупой код, но я не знаю как справиться иначе, несмотря на то что работает скрипт очень лажовый. Можешь подсказать анон если не сложно, как можно написать этот код более компактнее
К примеру, для задания https://gist.github.com/codedokode/d7e7f11449fc3bcb24b4
я бы написал классы таким образом
http://ideone.com/QhfaPC
Правильно, или лучше как-то по-другому?
гугли ЧПУ
Вроде бы изменил http://ideone.com/ba5QRf но от того куска кода так и не смог избавиться, не получается ничего другого кроме метода исключения, иначе у меня считает либо просто количество вариантов не равных выбранному, а если удалить из общего массива вариант который был удалён ведущим, то не знаю как в блоках if сделать указать условие что бы он правильно всё считал.
JS. Почему по твоему у него миллион библиотек?
> Первых штук 16.
Это на сам яваскрипт? Вообще, многовато, конечно, я потом переделаю, чтобы их было меньше. Я там не так давно еще задачи на DOM сократил и добавил jQuery и jQuery UI, так что если ты хочешь их освоить, задачи есть.
Там раньше было штук 10 задач на DOM, но это конечно перебор, они по времени занимают больше чем я думал, да и сейчас почти везде используют jQUery, так что в дальнейшем я наверно их еще упрощу или сокращу.
> Тогда уж в контроллере надо сделать массив нужных значений, а разгребать их в объект уже в модели.
Ну вот, ты опять пытаешься перенести разбор данных из запроса в модель. Ты можешь сделать так, если хочешь, но мне кажется что имеющегося setAttributes вполне достаточно и разбирать POST надо в контроллере или вспомогательном классе.
>>423147
Настраивать ничего не надо. Покажи код и какую ошибку выдает. правильно, если что, писать так:
<?= $x ?>
>>423154
О, шифр Бэкона? Интересная штука, искатели тайн средневековые книги в свое время перерыли в поисках шифрованных сообщений.
> $word=wordwrap($word,5," ",true);
Можно разбить на группы по 5 по-другому. Сначала заменяем буквы на A/B, хаком с preg_split разбиваем текст на массив букв, затем с помощью array_chunk разбиваем массив букв на группы по 5 букв (которые потом можно склеить в строку с помощью implode).
Что за хак я упоминаю? Он есть в моем учебнике.
Для разбиения на буквы можно использовать
$letters = preg_split("//u", $text, null, PREG_SPLIT_NO_EMPTY);
Это работает за счет того, что пустая регулярка соответствует промежуткам между буквами и разбивает по ним строку на буквы. Флаг в конце нужен чтобы удалить 2 пустых элемента в начале и конце массива.
Обрати внимание на флаг u. Он говорит что текст в utf-8 и заставляет разбивать строку именно на буквы по границам utf-8 символов, а не на куски по 1 байту.
Также, есть функция http://php.net/manual/ru/function.str-split.php но учти что она работает только с латинницей (подробнее мой мини-урок про то, какие функции работают с utf8 а какие нет и почему: https://gist.github.com/codedokode/ff99e357e9860ea169b8 )
Ошибка у тебя из-за оставшейся в конце буквы B. Не надо ее добавлять наверно.
> Первых штук 16.
Это на сам яваскрипт? Вообще, многовато, конечно, я потом переделаю, чтобы их было меньше. Я там не так давно еще задачи на DOM сократил и добавил jQuery и jQuery UI, так что если ты хочешь их освоить, задачи есть.
Там раньше было штук 10 задач на DOM, но это конечно перебор, они по времени занимают больше чем я думал, да и сейчас почти везде используют jQUery, так что в дальнейшем я наверно их еще упрощу или сокращу.
> Тогда уж в контроллере надо сделать массив нужных значений, а разгребать их в объект уже в модели.
Ну вот, ты опять пытаешься перенести разбор данных из запроса в модель. Ты можешь сделать так, если хочешь, но мне кажется что имеющегося setAttributes вполне достаточно и разбирать POST надо в контроллере или вспомогательном классе.
>>423147
Настраивать ничего не надо. Покажи код и какую ошибку выдает. правильно, если что, писать так:
<?= $x ?>
>>423154
О, шифр Бэкона? Интересная штука, искатели тайн средневековые книги в свое время перерыли в поисках шифрованных сообщений.
> $word=wordwrap($word,5," ",true);
Можно разбить на группы по 5 по-другому. Сначала заменяем буквы на A/B, хаком с preg_split разбиваем текст на массив букв, затем с помощью array_chunk разбиваем массив букв на группы по 5 букв (которые потом можно склеить в строку с помощью implode).
Что за хак я упоминаю? Он есть в моем учебнике.
Для разбиения на буквы можно использовать
$letters = preg_split("//u", $text, null, PREG_SPLIT_NO_EMPTY);
Это работает за счет того, что пустая регулярка соответствует промежуткам между буквами и разбивает по ним строку на буквы. Флаг в конце нужен чтобы удалить 2 пустых элемента в начале и конце массива.
Обрати внимание на флаг u. Он говорит что текст в utf-8 и заставляет разбивать строку именно на буквы по границам utf-8 символов, а не на куски по 1 байту.
Также, есть функция http://php.net/manual/ru/function.str-split.php но учти что она работает только с латинницей (подробнее мой мини-урок про то, какие функции работают с utf8 а какие нет и почему: https://gist.github.com/codedokode/ff99e357e9860ea169b8 )
Ошибка у тебя из-за оставшейся в конце буквы B. Не надо ее добавлять наверно.
Вообще, конечно, обычно в константы запихивают не объект, а просто число или строку. мне кажется, правильнее было бы сделать константы числом или строкой, а информацию о стоимости/калорийности хранить в отдельном словаре.
> if (gam.filling.name == fill.name) {
Вообще можно сравнивать и сами объекты. Ты знаешь как работает сравнение объектов в JS? Вот тут например что будет?
var a = { x: 1};
var b = { x: 1};
var c = { x:1, y: 2};
console.log(a == b); // ?
console.log(a === b); // ?
console.log(a == c); // ?
> for (var i = 0; i < this.filling.length; i++) {
> if (this.filling.name == fill.name) {
Этот цикл у тебя повторяется в 2 местах. Вынеси-ка его в функцию, которая ищет в массиве добавку и возвращает либо ее индекс либо -1
В общем, не знаю, так-то программа работает, и сделана неплохо, но вот это хранение данных в константах мне не очень нравится. Вообще, если хочешь, можешь так оставить и переходить к следующей задаче.
Не, я глянул код, createTestFromPost надо перенести из модели в другой класс. Модель ни при каких обстоятельствах не должна лезть в ПОСТ, тем более еще и через эти глобальные ссылки типа Yii->request.
Вот еще замечания:
> $test = Test::getTestFromPost( );
Лучше не создавать тест из ПОСТ а набивать данные в существующий тест из ПОСТ. Тогда такой код будет работать и для создания и для редактирования.
Вот это
> $this->render('createTest.twig',
У тебя аж 3 раза повторяется. Одного недостаточно? Сделай лучше так:
тест = загружаем/создаем тест;
если (форма запощена) {
набиваем данные в тест;
если (все верно) {
....
}
}
выводим форму;
Это общепринятый алгоритм для любых форм.
Ну и при редактировании хорошо бы сохранять id вопросов/ответов. Для этого достаточно добавить скрытый инпут с id. Интуиция подсказывает мне что это поможет например не потерять ссылки на них в других таблицах если такие появятся. Ну и вообще, редактирование != удаление + создание заново.
В функции валидации стоит предусмотреть не только return false/true но и сохранять текст ошибки и элемент к которому она относится. Для этого можно использовать либо встроенные возмжности Юи если таковые есть, либо сделать свой класс ErrorMessages и может быть хелперы для отображения сообщений в форме.
> if ($a->number == $b->number) {
> return 0;
Есть еще такой интересный хак (использовать его разумеется не обязательно):
return $a->number - $b->number;
Не, я глянул код, createTestFromPost надо перенести из модели в другой класс. Модель ни при каких обстоятельствах не должна лезть в ПОСТ, тем более еще и через эти глобальные ссылки типа Yii->request.
Вот еще замечания:
> $test = Test::getTestFromPost( );
Лучше не создавать тест из ПОСТ а набивать данные в существующий тест из ПОСТ. Тогда такой код будет работать и для создания и для редактирования.
Вот это
> $this->render('createTest.twig',
У тебя аж 3 раза повторяется. Одного недостаточно? Сделай лучше так:
тест = загружаем/создаем тест;
если (форма запощена) {
набиваем данные в тест;
если (все верно) {
....
}
}
выводим форму;
Это общепринятый алгоритм для любых форм.
Ну и при редактировании хорошо бы сохранять id вопросов/ответов. Для этого достаточно добавить скрытый инпут с id. Интуиция подсказывает мне что это поможет например не потерять ссылки на них в других таблицах если такие появятся. Ну и вообще, редактирование != удаление + создание заново.
В функции валидации стоит предусмотреть не только return false/true но и сохранять текст ошибки и элемент к которому она относится. Для этого можно использовать либо встроенные возмжности Юи если таковые есть, либо сделать свой класс ErrorMessages и может быть хелперы для отображения сообщений в форме.
> if ($a->number == $b->number) {
> return 0;
Есть еще такой интересный хак (использовать его разумеется не обязательно):
return $a->number - $b->number;
Ох, я сейчас на тебя кучу замечаний высыплю. Но это все ради твоей же пользы.
Насчет кук, надо добавить секретный код в куки вместо email. То есть при регистрации мы ставим куку с id и куку с секретным кодом, который генерируется случайно для каждого студента и сохраняется в БД. Соответственно потом этот код проверяется при попытке редактирования. Злоумышленник не знает кода и не может отредактировать чужие данные.
А email может меняться, что создает дополнительные проблемы.
Также, важная вещь: ты должен использовать htmlspecialchars при выводе данных в шаблоне. Иначе у тебя получается XSS уязвимость: злоумышленник может вписать в имя любые HTML теги и они выведутся. Подробнее: https://gist.github.com/anonymous/52adda0113428b274c64
> https://github.com/MindiMakridi/Students/blob/master/index.php#L68
Это надо вынести в шаблон, например footer.html
> ?>
Не надо ставить это если этот маркер в самом конце файла
> https://github.com/MindiMakridi/Students/blob/master/lib/DataMapper.php#L22
тут конечно можно было и без регулярок обойтись, просто сделать массив и проверять через in_array. Ну да ладно, можно и регуляркой, почему нет.
> die ("Не верный запрос к базе данных");
В мире Ооп используют исключения:
https://gist.github.com/codedokode/65d43ca5ac95c762bc1a
http://php.net/manual/ru/language.exceptions.php
замени die на throw
else там не нужен так как после die или throw выполнение функции завершается.
Алсо, у тебя в файле https://github.com/MindiMakridi/Students/blob/master/lib/DataMapper.php форматирование поплыло, пропусти код через phpformatter
> "/lib/profileclass.php";
Имена классов пишутся с большой буквы и должны совадать с именем файла то есть должно быть Profile.php
Класс StudentMapper должен быть в StudentMapper.php
> public function addStudent($profile){
Тут нужен тайп хинт: http://php.net/manual/ru/language.oop5.typehinting.php
Это делает код надежнее и понятнее.
> $STH->bindparam(":name", $name);
> $name = $profile->showName( );
Можно использовать bindValue и обойтись без промежуточной переменной:
$STH->bindValue(':name', $profile->getName( ));
Также, можно передавать массив значений в execute.
> https://github.com/MindiMakridi/Students/blob/master/lib/DataMapper.php#L85
> WHERE email=:prevMail
Индентифицировать студента удобнее не по email, а по id так как он не меняется никогда.
> https://github.com/MindiMakridi/Students/blob/master/lib/DataMapper.php#L109
В файле с классом не должно быть постороннего кода
> https://github.com/MindiMakridi/Students/blob/master/lib/profileclass.php#L8
этот html код надо перенести куда-нибудь в шаблон
> https://github.com/MindiMakridi/Students/blob/master/lib/profileclass.php#L29
Модель ничего не должна выводить. У тебя вообще весь html должен быть в шаблонах, а не в коде. Вынеси все HTML теги из модели в другое место.
> if ($this->checkField($data['name'], $regExp)) {
> $this->name = $this->checkField($data['name'], $regExp);
Во второй строчке по моему checkField лишний
> https://github.com/MindiMakridi/Students/blob/master/lib/profileclass.php#L82
hello@003.ru не пройдет.
Вот интересные статьи на тему проверки email:
http://habrahabr.ru/post/55820/
http://habrahabr.ru/post/175375/
(у нас пропускать наркоманские адреса вроде "hello world"@[ff01::0] конечно не требуется)
> public function showName()
Везде обычно такие методы назваются getName
Насчет register.php и profile.php, там много похожего кода, надо бы объединить их в один файл. Примерно так:
-------------
если (идет редактирование) {
загружаем студента из БД;
} иначе {
создаем пустого студента;
}
если (форма запощена) {
записываем данные из ПОСТ в студента;
проверяем все ли верно;
если (все верно) {
сохраняем студента (вставкой или редактированием);
если надо ставим куки;
редиректим;
}
}
выводим форму;
----------------
> <<?php echo $tag ?>
А зачем менять вид тега при регистрации/редактировании? Я не понимаю. Нельзя и там и там инпут использовать?
Чтобы в инпуте уже было сохранено введенное значение достаточно подставить его в value:
<input name="..." value="<?= htmlspecialchars($name) ?>">
А в твоем варианте, как я понимаю, в форме регистрации данные теряются при ошибке.
Также надо чтобы в форме выводился выбранные ранее пол. Для этого у option есть атрибут selected: http://htmlbook.ru/html/option
Я вижу, ты не очень знаешь HTML формы. Почитай-ка самоучитель по ним:
http://htmlbook.ru/samhtml5/formy
http://htmlbook.ru/html/type/form
Если что-то там непонятно, задавай вопросы.
> order=name&direction
В HTML & это спецсимвол и чтобы вставить знак & надо писать
&
подробнее: https://ru.wikipedia.org/wiki/%D0%9C%D0%BD%D0%B5%D0%BC%D0%BE%D0%BD%D0%B8%D0%BA%D0%B8_%D0%B2_HTML
http://htmlbook.ru/samhtml/tekst/spetssimvoly
> <?php foreach ($table as $student) {
В шаблонах применяется версия с двоеточием: http://php.net/manual/ru/control-structures.alternative-syntax.php
> echo "<tr><td>{$student->showName()}
Это делается так:
<td><?= htmlspecialchars($student->showName()) ?></td>
Мануал: http://php.net/manual/ru/language.basic-syntax.phpmode.php
Ну и код выровняй еще, где он съехал. Нормальные редакторы обычно сохраняют отступ при переходе на новую строку, ты случайно не в блокноте его пишешь?
Ох, я сейчас на тебя кучу замечаний высыплю. Но это все ради твоей же пользы.
Насчет кук, надо добавить секретный код в куки вместо email. То есть при регистрации мы ставим куку с id и куку с секретным кодом, который генерируется случайно для каждого студента и сохраняется в БД. Соответственно потом этот код проверяется при попытке редактирования. Злоумышленник не знает кода и не может отредактировать чужие данные.
А email может меняться, что создает дополнительные проблемы.
Также, важная вещь: ты должен использовать htmlspecialchars при выводе данных в шаблоне. Иначе у тебя получается XSS уязвимость: злоумышленник может вписать в имя любые HTML теги и они выведутся. Подробнее: https://gist.github.com/anonymous/52adda0113428b274c64
> https://github.com/MindiMakridi/Students/blob/master/index.php#L68
Это надо вынести в шаблон, например footer.html
> ?>
Не надо ставить это если этот маркер в самом конце файла
> https://github.com/MindiMakridi/Students/blob/master/lib/DataMapper.php#L22
тут конечно можно было и без регулярок обойтись, просто сделать массив и проверять через in_array. Ну да ладно, можно и регуляркой, почему нет.
> die ("Не верный запрос к базе данных");
В мире Ооп используют исключения:
https://gist.github.com/codedokode/65d43ca5ac95c762bc1a
http://php.net/manual/ru/language.exceptions.php
замени die на throw
else там не нужен так как после die или throw выполнение функции завершается.
Алсо, у тебя в файле https://github.com/MindiMakridi/Students/blob/master/lib/DataMapper.php форматирование поплыло, пропусти код через phpformatter
> "/lib/profileclass.php";
Имена классов пишутся с большой буквы и должны совадать с именем файла то есть должно быть Profile.php
Класс StudentMapper должен быть в StudentMapper.php
> public function addStudent($profile){
Тут нужен тайп хинт: http://php.net/manual/ru/language.oop5.typehinting.php
Это делает код надежнее и понятнее.
> $STH->bindparam(":name", $name);
> $name = $profile->showName( );
Можно использовать bindValue и обойтись без промежуточной переменной:
$STH->bindValue(':name', $profile->getName( ));
Также, можно передавать массив значений в execute.
> https://github.com/MindiMakridi/Students/blob/master/lib/DataMapper.php#L85
> WHERE email=:prevMail
Индентифицировать студента удобнее не по email, а по id так как он не меняется никогда.
> https://github.com/MindiMakridi/Students/blob/master/lib/DataMapper.php#L109
В файле с классом не должно быть постороннего кода
> https://github.com/MindiMakridi/Students/blob/master/lib/profileclass.php#L8
этот html код надо перенести куда-нибудь в шаблон
> https://github.com/MindiMakridi/Students/blob/master/lib/profileclass.php#L29
Модель ничего не должна выводить. У тебя вообще весь html должен быть в шаблонах, а не в коде. Вынеси все HTML теги из модели в другое место.
> if ($this->checkField($data['name'], $regExp)) {
> $this->name = $this->checkField($data['name'], $regExp);
Во второй строчке по моему checkField лишний
> https://github.com/MindiMakridi/Students/blob/master/lib/profileclass.php#L82
hello@003.ru не пройдет.
Вот интересные статьи на тему проверки email:
http://habrahabr.ru/post/55820/
http://habrahabr.ru/post/175375/
(у нас пропускать наркоманские адреса вроде "hello world"@[ff01::0] конечно не требуется)
> public function showName()
Везде обычно такие методы назваются getName
Насчет register.php и profile.php, там много похожего кода, надо бы объединить их в один файл. Примерно так:
-------------
если (идет редактирование) {
загружаем студента из БД;
} иначе {
создаем пустого студента;
}
если (форма запощена) {
записываем данные из ПОСТ в студента;
проверяем все ли верно;
если (все верно) {
сохраняем студента (вставкой или редактированием);
если надо ставим куки;
редиректим;
}
}
выводим форму;
----------------
> <<?php echo $tag ?>
А зачем менять вид тега при регистрации/редактировании? Я не понимаю. Нельзя и там и там инпут использовать?
Чтобы в инпуте уже было сохранено введенное значение достаточно подставить его в value:
<input name="..." value="<?= htmlspecialchars($name) ?>">
А в твоем варианте, как я понимаю, в форме регистрации данные теряются при ошибке.
Также надо чтобы в форме выводился выбранные ранее пол. Для этого у option есть атрибут selected: http://htmlbook.ru/html/option
Я вижу, ты не очень знаешь HTML формы. Почитай-ка самоучитель по ним:
http://htmlbook.ru/samhtml5/formy
http://htmlbook.ru/html/type/form
Если что-то там непонятно, задавай вопросы.
> order=name&direction
В HTML & это спецсимвол и чтобы вставить знак & надо писать
&
подробнее: https://ru.wikipedia.org/wiki/%D0%9C%D0%BD%D0%B5%D0%BC%D0%BE%D0%BD%D0%B8%D0%BA%D0%B8_%D0%B2_HTML
http://htmlbook.ru/samhtml/tekst/spetssimvoly
> <?php foreach ($table as $student) {
В шаблонах применяется версия с двоеточием: http://php.net/manual/ru/control-structures.alternative-syntax.php
> echo "<tr><td>{$student->showName()}
Это делается так:
<td><?= htmlspecialchars($student->showName()) ?></td>
Мануал: http://php.net/manual/ru/language.basic-syntax.phpmode.php
Ну и код выровняй еще, где он съехал. Нормальные редакторы обычно сохраняют отступ при переходе на новую строку, ты случайно не в блокноте его пишешь?
Оба сложные.
>>423167
гугли ЧПУ. Вообще, при использовании фреймворков вроде Slm, Yii2, Symfony 2 проблема уже решена в них, а если ты пишешь на чистом php то ты можешь с помощью htaccess перенаправить все обращения на index.php а уже в нем писать:
$uri = $_SERVER['REQUEST_URI'];
if (preg_match("!^/some/url!", $uri)) {
....
}
Ну или подключить роутер от той же симфони и задавать шаблоны URL через конфиг, но это может быть непросто.
>>423171
Да. Суть DataMApper в том что это класс, который умеет сохранять и загружать объекты сущности из Бд (и никто другой этим не занимается). На одну таблицу обычно делается один маппер и вся работа с таблицей делается только в этом маппере. Таким образом мы добиваемся порядка в коде, когда все запросы к таблице собраны в одном месте, а не размазаны по всему коду.
Судя по коду, ты в общем идею понял правильно. Так и должно быть, как у тебя.
Если что вот еще инфа от автора (Мартина Фаулера) придумавшего этот паттерн:
http://design-pattern.ru/patterns/data-mapper.html
Вот по коду:
> $name = strip_tags(trim($name));
Ой-ой, код из старых непраивльных учебников? Почитай про правильную защиту от XSS: https://gist.github.com/anonymous/52adda0113428b274c64
> $this->properties = array('name'=>$name, 'age'=>$age, 'email'=>$email);
Это нехорошо. Зачем ты используешь классы если в итоге хранишь все в массиве? Надо сделать 3 свойства name, age, email и хранить все в них.
> \tfunction getInfo(){
надо сделать 3 функции getName/Age/Email
> (Student &$student){
Не надо писать & . Объекты и так передаются (почти) как по ссылке: http://php.net/manual/ru/language.oop5.references.php
> \t$stmt->bindParam(':name', $this->db->quote($info['name']));
не надо делать quote, bindParam делает quote сам. Также, лучше использовать bindValue, bindParam предназначен для двухсторонней связи.
В функции insert обычно еще делают чтобы после вставки в базу проставлялся сгенерированный базой id в объект студента.
Оба сложные.
>>423167
гугли ЧПУ. Вообще, при использовании фреймворков вроде Slm, Yii2, Symfony 2 проблема уже решена в них, а если ты пишешь на чистом php то ты можешь с помощью htaccess перенаправить все обращения на index.php а уже в нем писать:
$uri = $_SERVER['REQUEST_URI'];
if (preg_match("!^/some/url!", $uri)) {
....
}
Ну или подключить роутер от той же симфони и задавать шаблоны URL через конфиг, но это может быть непросто.
>>423171
Да. Суть DataMApper в том что это класс, который умеет сохранять и загружать объекты сущности из Бд (и никто другой этим не занимается). На одну таблицу обычно делается один маппер и вся работа с таблицей делается только в этом маппере. Таким образом мы добиваемся порядка в коде, когда все запросы к таблице собраны в одном месте, а не размазаны по всему коду.
Судя по коду, ты в общем идею понял правильно. Так и должно быть, как у тебя.
Если что вот еще инфа от автора (Мартина Фаулера) придумавшего этот паттерн:
http://design-pattern.ru/patterns/data-mapper.html
Вот по коду:
> $name = strip_tags(trim($name));
Ой-ой, код из старых непраивльных учебников? Почитай про правильную защиту от XSS: https://gist.github.com/anonymous/52adda0113428b274c64
> $this->properties = array('name'=>$name, 'age'=>$age, 'email'=>$email);
Это нехорошо. Зачем ты используешь классы если в итоге хранишь все в массиве? Надо сделать 3 свойства name, age, email и хранить все в них.
> \tfunction getInfo(){
надо сделать 3 функции getName/Age/Email
> (Student &$student){
Не надо писать & . Объекты и так передаются (почти) как по ссылке: http://php.net/manual/ru/language.oop5.references.php
> \t$stmt->bindParam(':name', $this->db->quote($info['name']));
не надо делать quote, bindParam делает quote сам. Также, лучше использовать bindValue, bindParam предназначен для двухсторонней связи.
В функции insert обычно еще делают чтобы после вставки в базу проставлялся сгенерированный базой id в объект студента.
А нельзя проверку сделать проще?
Если пользователь изначально выбрал правильный ответ if ($option == $truth) то при смене ответа он очевидно проигрывает.
Если пользователь изначально выбрал неправильный ответ с козой (а ведущий открывает вторую козу), то при смене ответа он гарантирванно выигрывает.
Получается, можно сделать так:
if (пользователь изначально выбрал правильный ответ) {
при смене он проиграет;
} иначе {
при смене он выиграет;
}
Или я где-то ошибся?
>if ($option == $truth)
Говнокод ! Сравнение нужно делать с помощью точного сравнения "===" с учитыванием типов.
>Не, я глянул код, createTestFromPost надо перенести из модели в другой класс.
Я просто не хочу набивать массив вопросов в контроллере.
>Лучше не создавать тест из ПОСТ а набивать данные в существующий тест из ПОСТ.
Если метод будет не в модели - то оно и понятно.
>Вот это $this->render('createTest.twig',
Два раза. Один раз там - заглушка, пока я не уверен в валидации.
>Это общепринятый алгоритм для любых форм.
Я его изменил, потому что часть "форма запощена" получалась большей частью контроллера. Но теперь, когда я раскидал все по функциям, я вернусь к нему, да.
>Ну и при редактировании хорошо бы сохранять id вопросов/ответов.
Айди пока нет. Они будут после сохранения. То я айди обозвал при создании / редактировании, а по сути это лишь номер в $_POST['questons']. А так да, при редактировании теста будет скрытый инпут с id.
>Есть еще такой интересный хак (использовать его разумеется не обязательно):
Знаю и лучше оставлю как есть.
>В функции валидации стоит предусмотреть не только return false/true но и сохранять текст ошибки и элемент к которому она относится.
Та часть, которая делается с validate() сама создают такой текст в элементе. А остальное я да, добавлю. Ошибки вроде "ни одного верного ответа", "ни одного вопроса в тесте", etc. Надо, наверное, поле в модели предусмотреть для этого, как сам Yii и делает.
> Айди пока нет. Они будут после сохранения. То я айди обозвал при создании / редактировании, а по сути это лишь номер в $_POST['questons']. А так да, при редактировании теста будет скрытый инпут с id.
Ну и нормально. Если пришел id — значит мы редактируем вопрос из БД, если не пришел или такого вопроса нет — создаем новый.
Ну и еще, хорошо бы после страницы создания и прохождения теста перейти к автоматизированному тестированию. тема эта интересная, но мы в треде раньше такого не делали, так что может ты будешь первым кто будет писать тесты к своему коду в нашем треде.
>Ну и еще, хорошо бы после страницы создания и прохождения теста перейти к автоматизированному тестированию.
Так ведь план такой и был изначально.
Я там поигрался с валидацией немного и унес из модели парсинг теста из запроса.
Ты IDE настроил? Там тоже надо настройки прописать. Какие именно написано в документации по IDE, вот пример для phpstorm: https://www.jetbrains.com/phpstorm/help/php-debugging-session.html
Также вопрос, где ты пытаешься отлаживать код? На своем компьюетере? На удаленном сервере? Если на сервере то настройки явно неправильные.
Насчет опции connect_back. Она значит что xdebug на сервере пытается соединиться с тем IP с которого пришел запрос. Но если ты находишься за Nat (то есть если у тебя нет выделенного внешнего белого адреса, и сервер не в локальной сети) то соединиться не получится.
Единственный вариант если тебя и сервер разделяет NAT это соединиться по SSH c сервером, сделать проброс портов через SSH и настроить в отладчике соединение с лоакалхостом. Но в этом случае стоило бы протестировать сначала рабоатет ли этот проброс вообще.
>>423265
Вот спасибо, как с души камень. Да за NAT и не одним. Зато проброс с того же vps точно работает, проверял на mysql workbench. Но правильный ли будет проброс вида
ssh -L 9000:localhost:9000? Там есть еще параметр -R и если читать маны по диагонали, то они похожи.
>>423263
Вот хз. Костыли для браузеров вообще настроек не имеют, но также не работают.
Спасибо, сделал как ты сказал, теперь код компактнее http://ideone.com/xEvlXG Правда на 11 строчке возникла ошибка, кажется из-за того что неизвестная переменная, не подскажешь случайно если не сложно как избавиться от этой ошибки, она довольно часто у меня возникает, хоть и не влияет не скрипт но всёравно это же плохо что она возникает?
Мне почему то показалось что так он будет просто подсчитывать количество угаданных раз из трёх вариантов, то есть всегда будет вероятность 1\3 что правильно назвал с самого начала и 2\3 что неправильно назвал, почему то и сейчас так кажется, я наверное где-то что-то не уловил.
>Задачки на js порешал бы. У нас там для первых 4 даже автоматическая проверялка есть.
>Я делал их. Первых штук 16.
Это где их найти?
>Вообще можно сравнивать и сами объекты.
Сделал
>Ты знаешь как работает сравнение объектов в JS? Вот тут например что будет?
Везде false, как я понял потому что при сравнении объектов они сравниваются на идентичность а не на равенство, то есть являются ли операнды одной сущностью или разными.
Инфа отсюда: http://bonsaiden.github.io/JavaScript-Garden/ru/#types.equality
>Этот цикл у тебя повторяется в 2 местах. Вынеси-ка его в функцию, которая ищет в массиве добавку и возвращает либо ее индекс либо -1
Запилил: http://jsbin.com/musafimuli/3/edit?js,console
Про объект в константе понял, но не вижу преимуществ, может позже сделаю.
Спасибо.
Мне кажется ты не совсем понимаешь как substr работает. Алсо, для чего там цикл, если ты на каждой итерации одно и тоже значение проверяешь, не используя $i? И я бы советовал результат выводить не внутри условия, а в самом конце, чтобы он выводился в любом случае. А внутри условия просто менять его, например на "не палиндром".
>>423173
Вот короче простенький вывод сделал.
http://rghost.ru/60205213
С JS буду разбираться в скором времени, опасаюсь, что как начну в Css html JS уходить так забуду половину в php
В этом варианте там куча багов конечно, переделал немного сессию, чтобы при повторной отправке данных из index.html чтобы начиналась новая сессия с новым ником, но как предотвратить выполнение скрипта путем нажатия f5?
Точнее, если без захода на index.html сразу запустить страницу php-скрипта, как сделать редирект на index.html если через $_POST не были отправлены данные в сессию? на isset($_SESSION['name']) проверять бесполезно, всегда возвращает true, есть ещё варианты?
Премного благодарен, сработало
Так ты сначала вставь что-нибудь, а потом айди бери.
Два чаю, никак не могу допереть до решения.
Понятно, что нужно делать с условием несовпадения и типа как только буква не совпадёт - прервать цикл и заменить результ на "не палиндром". Но как именно?
>прервать цикл и заменить результ на "не палиндром". Но как именно?
А что не понятно?
Если(переменная А не равна переменной Б){
результат = "не палиндром"
}
в конце выводим результат.
Да до этого я допёр, но у меня почему то, если делать (длина слова-i) последним символом пустой выводит символ, а первым букву "а". А если просто с отрицательного i начинать, то выводит, естественно, сначала первую "а", а потом уже последнюю, что логично, ибо (-0) = 0. Я вот с этим присваиванием букв запутался.
>последним символом пустой выводит символ, а первым букву "а"
В смысле при проверке с конца слова сначала идёт какой-то пустой символ, а потом "а". Естественно "" != "а" и выводится, что не палиндром.
http://ideone.com/zgVyHK
и
http://ideone.com/MSH1nx
Вывел символы просто для примера, ибо понимаю как там надо завершать цикл.
Ну да, у тебя 0 будет на первом шаге цикла во второй переменной, на втором шаге -1, то есть отставание по буквам от первой переменной. Не вижу ничего сложного в том, чтобы это исправить, тут простая арифметика. Что касается второго скрипта, то ты зачем-то отнимаешь $i от длинны слова. Если длинна слова 4 буквы, то позиция 4ой буквы в mb_substr будет под номером 3, т.к они начинаются с нуля, как в массиве. Соответственно на первом шаге у тебя substr обращается к несуществующему индексу.
Точно, чувствую себя теперь дураком. Я и до этого догадывался, но после того, как сообщение твоё прочитал всё прямо очевидно стало, лол.
Выполнил, спасибо. :з
У SSH есть 2 режима проброса:
- когда порт открывается на локальном компьютере и при соединении с ним (локально) ssh-сервер открывает соединение с сервера на указанный адрес и пробрасывает данные.
- когда порт открывается на удаленном хосте и пробрасывается локально на ssh-клиент
-L это первый режим
-R это второй
Почитай внимательно описание в мануале например тут http://www.opennet.ru:8101/man.shtml?topic=ssh&category=1&russian=0
Тебе надо чтобы php на сервере мог соединиться с IDE на локалхосте. Значит тебе надо открыть порт на сервере, пробросить его на свой комп и в настройках xdebug указать localhost и открытый порт.
Видимо тебе нужно
ssh -R 9000:localhost:9000
то есть открываем удаленно порт 9000 (к которому подсоединится xdebug) и при соединении с ним ssh будет коннектиться к 9000 на локальном компьютере где ждет соединения IDE.
Если у тебя линукс то ты можешь поставить утилиту nc (netcat, https://ru.wikipedia.org/wiki/Netcat ) и тестировать соединение ей. На лоакльном компьютере пишешь
nc -vv -l -p 9000 # слушать порт 9000
На удаленном сервере пишешь
echo hello | nc -vv localhost 9000 # подсоединиться и переслать строку
После этого если все проброшено правильно ты локально у себя увидишь hello. Если ты не знаком с утилитой nc то советую познакомится, она незаменима для тестирования таких вещей. Она умеет как соединяться с указанным портом так и принимать соединения.
> Вот хз. Костыли для браузеров вообще настроек не имеют, но также не работают.
Они в них наверно просто жестко заданы и не меняются. Но порты-то пробрасывать нужно в любом случае.
Ну и по моему конечно удобнее отлаживать что тебе надо локально, а не мучаться с пробросами. И уж тем более не стоит запускать наверно отладчик на продакшен сервере.
У SSH есть 2 режима проброса:
- когда порт открывается на локальном компьютере и при соединении с ним (локально) ssh-сервер открывает соединение с сервера на указанный адрес и пробрасывает данные.
- когда порт открывается на удаленном хосте и пробрасывается локально на ssh-клиент
-L это первый режим
-R это второй
Почитай внимательно описание в мануале например тут http://www.opennet.ru:8101/man.shtml?topic=ssh&category=1&russian=0
Тебе надо чтобы php на сервере мог соединиться с IDE на локалхосте. Значит тебе надо открыть порт на сервере, пробросить его на свой комп и в настройках xdebug указать localhost и открытый порт.
Видимо тебе нужно
ssh -R 9000:localhost:9000
то есть открываем удаленно порт 9000 (к которому подсоединится xdebug) и при соединении с ним ssh будет коннектиться к 9000 на локальном компьютере где ждет соединения IDE.
Если у тебя линукс то ты можешь поставить утилиту nc (netcat, https://ru.wikipedia.org/wiki/Netcat ) и тестировать соединение ей. На лоакльном компьютере пишешь
nc -vv -l -p 9000 # слушать порт 9000
На удаленном сервере пишешь
echo hello | nc -vv localhost 9000 # подсоединиться и переслать строку
После этого если все проброшено правильно ты локально у себя увидишь hello. Если ты не знаком с утилитой nc то советую познакомится, она незаменима для тестирования таких вещей. Она умеет как соединяться с указанным портом так и принимать соединения.
> Вот хз. Костыли для браузеров вообще настроек не имеют, но также не работают.
Они в них наверно просто жестко заданы и не меняются. Но порты-то пробрасывать нужно в любом случае.
Ну и по моему конечно удобнее отлаживать что тебе надо локально, а не мучаться с пробросами. И уж тем более не стоит запускать наверно отладчик на продакшен сервере.
connect back точно надо отключить так как с сервера напрямую к тебе не соединиться.
>>423274
Там же есть поиск и категории, посмотри сам
>>423276
> всёравно это же плохо что она возникает?
Да, плохо. Ошибок вообще не должно быть никаких.
Чтобы ошибки не было, надо до цикла присвоить переменной letters какое-то значение, например, пустую строку.
> for($i=0; $i<count($word); $i++) {
Для перебора массива удобнее использовать foreach :
foreach ($words as $word)
Ну и наверно склеивать 5-буквенные слова в одну строку уже не надо. Если у тебя есть массив 5-буквенных слов то ты можешь пройтись циклом по нему и заменить их на расшифрованные буквы.
заодно стоит добавить проверку, если встретилась комбинация для которой нет шифра например BBBBB то вставлять вместо нее знак вопроса.
Автоматическая проверялка для первых 7 (ого, а было только 4): http://dkab.github.io/jasmine-tests/
Разумеется даже если проверялка пишет что все ок, стоит все равно запостить ссылку на свой код в тред. Если ты проверил код проверялкой, упомяни это.
Я ничего не удалял. Поста про udacity не видел.
>>423297
> Везде false, как я понял потому что при сравнении объектов они сравниваются на идентичность а не на равенство, то есть являются ли операнды одной сущностью или разными.
Да, все верно. Хорошо, что ты это знаешь.
> if (this.findFilling(fill) != -1) {
> this.filling.splice(fillIndex, 1);
Опечатка же. переменная не существует такая
> Про объект в константе понял, но не вижу преимуществ, может позже сделаю.
Ладно, тогда можешь не делать. Я лучше потом подумаю, может можно как-то условия задачи поменять чтобы это не работало :)
Анон правильно пишет. lastInsertId как следует из названия, возвращает число после выполнения INSERT.
Что-то я сомневаюсь в этом.
Неа, не лучше.
Блядь, угораздило. Сейчас функция удаления постов пришлась бы очень кстати.
>Опечатка же. переменная не существует такая
Да, точно, упустил, поправил: http://jsbin.com/hunuxugaru/1/edit?js,console
В общем приступаю к 13 задаче
(preg_match('~^([0-9a-zA-Z_\.-]+@[0-9a-zA-Z_\.-]+\.[0-9a-zA-Z_\.-]+)$~', $string)
Любишь велосипеды?
Советую освоить git и github чтобы постить туда код. Книга на русском по гиту: http://git-scm.com/book/ru/v1/
github это бесплатный хостинг git репозиториев. Ты можешь с помощью git загружать туда свой код.
session_start в index.html не нужен так как сессия там все равно не используется.
> if (!isset($_SESSION['name']))
>\t$_SESSION['name']= $_POST['name1'];
Тут стоило бы проверять есть ли вообще в POST такое поле и не пустое ли оно, если нету то редиректить на index
Смесь html и php в одном файле смотрится не очень — лучше вынести html код в шаблоны в папочке templates и подключать черехз require.
Классы по идее тоже стоит вынести в отдельный файлы lib/Desk.php и lib/Player.php
> <META HTTP-EQUIV='Refresh' CONTENT='5; URL=http://localhost/php/chess/index.html'>
Лучше использовать header("Location ...") для редиректа.
> if (isset($_POST['reset1']))
Кнопка reset не отправляет форму а только очищает поля в ней.
Также, хорошо бы убрать копипасту шапки страницы и вынести ее в отдельный шаблон.
Введенный ник нигде не отображается.
Также, раз уж ты сделал HTML ты бы мог сделать отображение более наглядным. Например сделать таблицу table для игрового поля, а игроков отображать кружочками разных цветов или картинками. Разумеется для этого надо убрать все echo из классов и выводить поле по-другому.
В общем, тут есть что развивать.
Советую освоить git и github чтобы постить туда код. Книга на русском по гиту: http://git-scm.com/book/ru/v1/
github это бесплатный хостинг git репозиториев. Ты можешь с помощью git загружать туда свой код.
session_start в index.html не нужен так как сессия там все равно не используется.
> if (!isset($_SESSION['name']))
>\t$_SESSION['name']= $_POST['name1'];
Тут стоило бы проверять есть ли вообще в POST такое поле и не пустое ли оно, если нету то редиректить на index
Смесь html и php в одном файле смотрится не очень — лучше вынести html код в шаблоны в папочке templates и подключать черехз require.
Классы по идее тоже стоит вынести в отдельный файлы lib/Desk.php и lib/Player.php
> <META HTTP-EQUIV='Refresh' CONTENT='5; URL=http://localhost/php/chess/index.html'>
Лучше использовать header("Location ...") для редиректа.
> if (isset($_POST['reset1']))
Кнопка reset не отправляет форму а только очищает поля в ней.
Также, хорошо бы убрать копипасту шапки страницы и вынести ее в отдельный шаблон.
Введенный ник нигде не отображается.
Также, раз уж ты сделал HTML ты бы мог сделать отображение более наглядным. Например сделать таблицу table для игрового поля, а игроков отображать кружочками разных цветов или картинками. Разумеется для этого надо убрать все echo из классов и выводить поле по-другому.
В общем, тут есть что развивать.
А так, вообще, выглядит интересно, хотя в некоторых местах буквы попадают на светлый фон и плохо читаются. Надо наверно добавить темный полупрозрачный фон.
Задания по HTML/CSS советую прорешать и запостить тут решения.
>>423486
Ок, хорошо, приступай.
>>423567
http://habrahabr.ru/post/55820/
http://habrahabr.ru/post/175375/
Читал?
>
>Читал?
>Если же вы все равно не можете успокоиться, пока не проверите адрес на корректность, просто проверьте на наличие в нем символа @. А если чувствуете, что способны на большее — добавьте проверку на точку:
>/.+@.+\..+/i
Охуеть просто, такой была первая версия того выражения что выше 1 в 1, лал. А потом полезли тараканы: вот, мол, на почтовых сервисах юзаются ограниченный набор символов, значит будем подстраиваться.
Ну тогда верну как было и прицеплю экранирование к sql-запросу.
все понял, $ не нужна при обращении к полю объекта, а еще скобочки забыл прои создании экземпляра класса
может там return нужен у функции, чтобы сумму эту возвращал?
Где ты её вызываешь, там она и выводится
Я не понимаю где можно применять пхп, объясните аутисту.
i4b:в тред для ньюфагов.
Очень сухо описано в http://git-scm.com/book/ru/v1/ плохо воспринимается, есть ли более краткое и более содержательное объяснение сути git и инструкций по пользованию? Видеогайд какой-нибудь годный может
Почему когда я пытаюсь связать локальный рипозиторий и github у меня логин вводится нормально, а в строке где просит ввести пароль у меня ничего не набирается на любой раскладке?
Только с этим и разобрался, ничего не ясно с git, я один начинаю беситься когда ничего не ясно и не ясно даже с чего начать?
Т.е. я создал новый объект этого класса, запустил для него метод, пишет что переменная (я использовал поле свойства объекта класса, тот который как паблик объявлен) не определена.
Можно как-то вывести из функции больше одного значения?
>Поясните, вот создал я паблик переменные в классе, а еще в этом классе есть метод, так как мне с помощью метода этого менять поля объекта этого класса?
Имел в виду не поля у класса менять, а у ЭКЗЕМПЛЯРА класса.
$this->$clientDebt = $creditSumm;
$creditSumm - аргумент метода,
$clientDebt - поле объекта класса
пишет Cannot redeclare
$this->clientDebt = $this->clientDebt + $a+$b
А так приемлимо писать? Как-то не очень красиво получается. С другой стороны, чтоб не юзать this постоянно прийдется продублировать каждое поле класса отдельной переменной в методе.
И я не понял, поля меняться будут у объекта класса или у класса? Что если вызвать метод сам по себе без привязки к классу?
>И я не понял, поля меняться будут у объекта класса или у класса?
У объекта конечно. Класс это просто описание. Вызвать метод без привязки к классу? Ты наверное имел ввиду без привязки к объекту? Вроде бы можно, только я не понимаю зачем это нужно.
>Ты наверное имел ввиду без привязки к объекту? Вроде бы можно, только я не понимаю зачем это нужно.
Ну как же , просто передаем аргументы, получаем возвращаемое значение - профит.
>делается обычной функцией.
Мне надо в результате работы функции получить более чем 1 значение. Так я могу сохранить их в поле класса и получить к ним доступ.
Чорт, я знал что что-то забыл.
Пытаюсь повторить пример из урока, а оно мне пишет то, что на пикрелейтед.
ЧЯДНТ?
>то есть есть панели
вот тут в 13 задаче: https://gist.github.com/codedokode/ce30e7a036f18f416ae0
Там дохуя опечаток, но мы же тебе не гуманитарии.
з.ы. Конкретно в этом случае опечатки нет, аффтар так и хотел сказать:
"... то есть есть панели, которые генерируют 1 мегаватт, (а) есть (панели) которые (генерируют) 2".
Будь я граммар-наци, я бы лучше приебался к отсутствию запятой перед "которые".
<?php не забыл написать? PHP выполняет код только после того маркера иначе он просто его выводит.
>>423774
Имеется в виду «то есть существуют панели»
>>423777
Сейчас прочел и ужаснулся. Корявый стиль изложения, конечно, как будет время, попробую написать аккуратнее. Я так-то знаю, как ставить запятые, но когда спешу, то могу пропустить. Также, раньше я читал книжки, а сейчас читаю интернет и когда целый день видишь примеры неграмотного написания, сам начинаешь так же писать.
Хорошо, спасибо. Вопрос: у меня есть папка с проектом, как мне её добавить в репозиторий локальный и как потом перенести её на мой аккаунт в github
> <?php не забыл написать?
Оу, вот оно че, михалыч!
чсх, сначала написал шорт опен тег, не проканало. а с полным тегом <?php работает, да.
К слову, раз уж затронули короткие теги, шо вы можете сказать по этому поводу, сэнсэй? Их наверное лучше вообще не использовать, да?
Вот в юнит-тестировании с ним проблемка оказалась, вдруг еще где-нибудь всплывет.
Удвою этого лентяя.
Пожалуйста, не посылайте нас штудировать этот талмуд http://git-scm.com/book/ru/v1, там слишком много буков!
Нам бы кратенько пару основных команд.
>как мне её добавить в репозиторий локальный
git init
git add .
git commit -m "твой комментарий"
>как потом перенести её на мой аккаунт в github
Прости, еще не выучил наизусть это
Ну в моем понимании если ты ньюфаг, то и переменную от массива не отличишь, куда уж тут до алгоритмов
<? никогда не использовать
<?php использовать
<?= использовать для вывода в шаблонах
>>423811
Гит не управляет папками. Он управляет файлами. Чтобы добавить пустую папку, создай в ней пустой файл .placeholder и добавь его через
git add .
git commit -m "...."
git init писать не надо, это только для создания нового репозитория.
Что, это? Чтобы отличить переменную от массива, учебника ОПа хватит с головой.
> Можно как-то вывести из функции больше одного значения?
массив
return array(
'a' => 1,
'b' => 2
);
или
return array(1, 2, 3);
Хуйню, в том и соль
У тебя нет ретурна и не совсем по условиям задачи. Для третьего банка, например, надо начислять 7777 после того, как проценты насчитаешь, если я правильно понял условия задачки.
И ещё над условием завершения цикла. Ты подумай, ведь за последний месяц тоже нужно внести ежемесячный платеж.
Вот моё решение:http://ideone.com/Ya9GnQ
Знаю, что называю переменные как мразь.
Вроде норм, посмотрим потом еще.
>>423647
Это хорошая книга. Если что-то непонятно, напиши какое именно предложение непонятно, разъясним. Видеогайд не поможет так как надо не нажимать кнопочки а понимать как git работает.
>>423663
> так как мне с помощью метода этого менять поля объекта этого класса?
Через $this ($this это псевдопеременная представляющая собой текущий объект, на котором и вызвана функция).
....
public $x = 0;
public function doSmth()
{
$this->x = 1; // меняем поле x
}
.....
>>423678
Можно писать через +=
> поля меняться будут у объекта класса или у класса?
У объекта. Объектов может быть много и у них свои значения полей у каждого, а класс один.
> Что если вызвать метод сам по себе без привязки к классу?
Нельзя вызвать. Ошибка будет.
>>423679
Нельзя же.
>>423688
Массив можно использовать.
>>423774
Переформулировал предложение, спасибо за внимательность. Действительно, 2 слова «есть» подряд сбивают с толку.
>>423777
Но ведь слово «панели» пропущено, точно ли нужна запятая?
>>423806
Я мог тебе неправильно ответить. Я выше написал как добавить пустую папку в репозиторий.
Насчет папки с проектом есть 2 варианта. В любом случае сначала надо создать пустой репозиторий на гитхабе.
- создать новый репозиторий через git init и закоммитить файлы проекта. После чего добавить remote origin указывающий на гитхаб. Описано тут https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/
- склонировать пустой репозиторий с гитхаба через git clone в пустую папку и в эту папку добавить свои файлы, закоммитить.
То есть всего есть 2 варианта создания репозитория:
- создать в любой папке через git init (фактически это только создаст папку .git с пустым репозиторием)
- склонировать другой репозиторий через git clone (при этом связь с исходным сохраняется). При этом файлы из репозитория будут автоматически выгружены в папку. Так стоит делать только в пустой папке.
Вроде норм, посмотрим потом еще.
>>423647
Это хорошая книга. Если что-то непонятно, напиши какое именно предложение непонятно, разъясним. Видеогайд не поможет так как надо не нажимать кнопочки а понимать как git работает.
>>423663
> так как мне с помощью метода этого менять поля объекта этого класса?
Через $this ($this это псевдопеременная представляющая собой текущий объект, на котором и вызвана функция).
....
public $x = 0;
public function doSmth()
{
$this->x = 1; // меняем поле x
}
.....
>>423678
Можно писать через +=
> поля меняться будут у объекта класса или у класса?
У объекта. Объектов может быть много и у них свои значения полей у каждого, а класс один.
> Что если вызвать метод сам по себе без привязки к классу?
Нельзя вызвать. Ошибка будет.
>>423679
Нельзя же.
>>423688
Массив можно использовать.
>>423774
Переформулировал предложение, спасибо за внимательность. Действительно, 2 слова «есть» подряд сбивают с толку.
>>423777
Но ведь слово «панели» пропущено, точно ли нужна запятая?
>>423806
Я мог тебе неправильно ответить. Я выше написал как добавить пустую папку в репозиторий.
Насчет папки с проектом есть 2 варианта. В любом случае сначала надо создать пустой репозиторий на гитхабе.
- создать новый репозиторий через git init и закоммитить файлы проекта. После чего добавить remote origin указывающий на гитхаб. Описано тут https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/
- склонировать пустой репозиторий с гитхаба через git clone в пустую папку и в эту папку добавить свои файлы, закоммитить.
То есть всего есть 2 варианта создания репозитория:
- создать в любой папке через git init (фактически это только создаст папку .git с пустым репозиторием)
- склонировать другой репозиторий через git clone (при этом связь с исходным сохраняется). При этом файлы из репозитория будут автоматически выгружены в папку. Так стоит делать только в пустой папке.
Прочитать все равно стоит. Если не понимаешь как устроен гит, работать с ним тяжело.
>>423815
Добавить удаленный репозиторий через git remote add ... и сделать pull / push
>>423818
В общем для развития да, но в веб программировании они не очень нужны тем более начинающему.
>>423822
> var objectType = Object.prototype.toString.call(variable).split(" ")[1].substr(0, Object.prototype.toString.call(variable).split(" ")[1].length - 1);
Это нечитаемо, вынеси в переменную. И substr стоит заменить наверно на регулярки. Или вообще проверять через
case '[object Date]':
> case "Function":
>\t\t\t\t\t\t\treturn "Function";
Функцию можно определять через typeof
> if (variable.length >= 0 && variable.splice(
У псевдомассивов нет методов массива вроде splice, потому они и псевдомассивы. Также, проверяющая функция не должна что-то менять в массиве (а splice меняет).
А так, идея решения правильная.
Прочитать все равно стоит. Если не понимаешь как устроен гит, работать с ним тяжело.
>>423815
Добавить удаленный репозиторий через git remote add ... и сделать pull / push
>>423818
В общем для развития да, но в веб программировании они не очень нужны тем более начинающему.
>>423822
> var objectType = Object.prototype.toString.call(variable).split(" ")[1].substr(0, Object.prototype.toString.call(variable).split(" ")[1].length - 1);
Это нечитаемо, вынеси в переменную. И substr стоит заменить наверно на регулярки. Или вообще проверять через
case '[object Date]':
> case "Function":
>\t\t\t\t\t\t\treturn "Function";
Функцию можно определять через typeof
> if (variable.length >= 0 && variable.splice(
У псевдомассивов нет методов массива вроде splice, потому они и псевдомассивы. Также, проверяющая функция не должна что-то менять в массиве (а splice меняет).
А так, идея решения правильная.
У нас кроме учебника есть задачи (мозголомные) на HTMl/CSS, JS, MySQL. А также продвинутые задания вроде сделать страничку или сайт. Может их лучше решать?
>>423830
Эксель тоже очень полезная программа. По моему электронные таблицы (и редактор текстов конечно) вообще революционная вещь, так как до них заставить компьютер что-то считать можно было лишь написав программу.
>>423597
Код лучше на ideone постить
Учтите, что она пока в тестовом режиме и может ошибаться. И разумеется, даже если она пишет что все верно, лучше все равно запостить ссылку на решение в тред.
Да, тут все прям пару задачек порешали и го бабло закалачивать. Сейчас накидают ответов, погоди немного.
Вот наконец-то решился сделать кошек-мышек, https://github.com/Si0n/CatNmouse/blob/master/catnmouse.php пока что наброски, есть ли какие-нибудь замечания?
Оп, буду очень благодарен, если поможешь провести расследование.
В общем нарыл я галерею( http://tympanus.net/Development/GammaGallery/ исходники тут можно найти http://tympanus.net/codrops/2012/11/06/gamma-gallery-a-responsive-image-gallery-experiment/ ) , которая подходит мне для проекта. Перепидарил многое под себя, даже исправил пару косяков в коде. И тут заметил одну раздражающую меня вещь: при клике на стрелочку смены фотографии на следующую ширина изображения на пару пикселей меняется(справа) прежде чем переключиться. И получается, что изображение немного дергается. Причем в мозиле такого нет, а в хроме и опере случается. Ума не приложу что за хуйня такая. Когда при смене картинки смотришь в инструменты разработчика - параметры ширины там не меняются. Ума не приложу что это за такое.
Зачем всё в паблике? Зачем можно создать экземпляр класса Animal? В __construct Desk'а заполнение доски выноси в приватный метод. Циклы в getAnimalsOnBoard выноси в приватный метод. В getClosiestEnemy тоже плохо понятно что происходит внутри цикла, дроби на мелкие методы. Не знаю как в php это делается, но возможно стоит хранить максимальный number в Animal в виде переменной класса и обновлять при создании экземпляра, чтоб не заморачиваться с присвоением номера очередному животному.
Область видимости перепишу, а номера я ввел для того чтобы быстрее проверить - правильно ли ищет ближайшего врага, номера наверное уберу потом когда отпадет надобность в такого рода визуальной проверке.
У тебя детектор сарказма неисправен.
>подскажи пожалуйста милый друг,знаком ли ты вот с этими курсами? http://rutracker.org/forum/viewtopic.php?t=4620353 .Стоит ли учиться по ним?
MySQL устарели, а MySQLi продвигается как новое решение. Хотя PDO обычно удобнее.
MySQL это СУБД, а mysqli и pdo - расширения похапе для работы с mysql. Сравниваешь теплое с мягким
Неплохие курсы, но не для новичков.
Вот я по ним учился, было очень-очень сложно.
И там голая теория, практически нет примеров, а если есть то ненаглядные и непонятные.
Курсы специально растянуты на много часов, чтобы оправдать те деньги, которые люди за них платят, много воды, паузы (это запись вебинаров).
С другой стороны, послушать Борисова не помешает, уважаемый опытный человек.
Короче, если ты полный новичок, то качни оттуда только первые два курса из четырех. Остальные два (а там есть реально ценная инфа) посмотришь после прохождения уроков ОПа.
Ты имеешь ввиду с каждым символом по отдельности?
Почему бы и нет.
$str = 'hello world';
for($i=0; $i<mb_strlen($str); $i++){
echo $str{$i}.'<br>';
}
Можно и разбить строку на символы через str_split.
<?php
function getBalanceInFuture($deposit, $percent, $years) {
\tfor ($i = 0\t, $i < $years; $i++;)
\t{
\t\t$deposit = $deposit $percent;
\t}
\t
\treturn $deposit;
}
$balance = getBalanceInFuture(10000, 1.05, 7);
echo "Через 7 лет у нас будет {$balance} рублей на счету\n";
По итогу все равно выводит 10 000 рублей.
В чем ошибка?
Всё, понял, неправильно оформил тело цикла.
Подскажите как сделать такое:
у меня три больших дива на странице. При большом разрешении они умещаются на экране в ряд.
При маленьком наезжают друг на друга.
Как сделать, чтобы вместо того, чтобы наезжать друг на друга -- они в столбик.
просто не знаю как загуглить такое
становились в столбик.
После первых двух уровней будешь делать свои сайтики как бох. За третий и четвертый лучше не браться пока не доведешь до совершенства процедурное программирование, которое и излагается в первых двух полностью.
медиазапросы гугли
Анон, начал мутить уроки, расположенные по этйо ссылке. Сделал первый, покритикуй, все правильно сделал, или нет.
Нет. Кавычки нужны одинарные.
>Ты имеешь ввиду с каждым символом по отдельности?
Да именно это я и имел ввиду. Мне кажется где-то натыкался и не раз что это крайний метод, лучше так не поступать, я правда не знаю почему, может это медленнее?
Это же отличные курсы как мне кажется, они+учебник ОПа+мануал это как раз то что надо, спасибо что поделился ссылкой, буду качать. Там есть очень ценная вещь, пошаговое создание интернет-магазина и т.д
Сделай плавающими, например:
\t\tdiv {
\t\t\twidth: 300px;
\t\t\theight: 300px;
\t\t\tbackground: #ccc;
\t\t\tborder: 1px solid #000;
\t\t\tfloat: left;
\t\t}
Что-то не могу догнать, почему не проходит подготовленный запрос. Если подставить параметры ручками, все прекрасно фетчится.
А подставляю плейсхолдеры, возвращается пустой массив.
Вот это фетчится
$query = 'SELECT name, surname, group, mark FROM info ORDER BY mark LIMIT 0, 10';
А это нет
$query = 'SELECT name, surname, group, mark FROM info ORDER BY mark LIMIT :offset, 10';
https://gist.github.com/krbn/dd3040adc8cd6f813647
Для начала, включи отображение ошибок приходязих от БД если оно еще не включено:
http://php.net/manual/ru/pdo.error-handling.php
Тебе нужен режим PDO::ERRMODE_EXCEPTION
Заметь что по умолчанию там стоит SILENT то есть молча игнорировать все ошибки (я не понимаю чем думали разработчики PDO, если честно).
исправь $stmt->bindParam(':offset', $offset);
на $stmt->bindParam(':offset', $offset, PDO::PARAM_INT);
Далее, ты передаешь вот тут значение аргумента
$stmt->bindParam(':field', $order);
который не используется в запросе. Это хорошо? Я думаю, нет.
Если тебе надо вставлять в запрос имя поля, то, к сожалению, плейсхолдеры не помогут, так как они вставляют только данные (число или строку в кавычках).
Потому имена полей придется вставлять напрямую в запрос. Разумеется, перед этим ты должен проверить, что имя соответствует одному из разрешенных вариантов (белому списку), например через in_array, а если не соответствует, то выкинуть исключение.
Вместо bindParam может быть удобнее использовать bindValue, так как ей можно передать не только переменную, но и выражение. bindParam вообще предназаначен в первую очередь для двухсторонней привязки, например при вызове процедур.
Ну и напоследок. Проверь, что у тебя отображаются сообщения об ошибках вообще. Может там есть предупреждение, а ты его не видишь.
В PHP по умолчанию выключено отображение ошибок в браузере, так как обычному пользователю сайта эта информация ни к чему. Но тебе, как программисту, надо видеть эти ошибки. Вот, как можно их просмотреть:
- ошибки сохраняются в лог ошибок. Можно открыть его и почитать. Если ты запускаешь код на локалхосте, у себя, то лог хранится в папке Апача (обычно она называется logs) и имеет название вроде error.log (в линуксе в папку /var/log/apache2 ). Если на хостинге — там либо есть файл error.log либо раздел в панели управления, где лог можно посмотреть
- также, ты можешь включить отображение ошибок. Открой файл php.ini, поставь там display_errors = On и error_reporting = E_ALL и перезапусти сервер. Теперь ошибки должны выводиться на экран.
Проверить, работает ли вывод ошибок, можно запустив скрипт содержающий обращение к несуществующей переменной вроде echo $sdgasdad; и проверив, выведется ошибка или нет. Если все верно, то должна вывестись.
Да, может быть у него число в кавычки заключается по умолчанию. Но при этом должна выводиться ошибка MySQL.
Спасибо.
Вот она, ошибка.
SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''0', 10' at line 1
>>424342
Да, дело было в типе передаваемой переменной. Он ожидал число, а пришла строка (или наоборот, что-то я путаюсь).
>>424343
Ох, чувак, ты быстрее пишешь, чем я читаю.
Да, у тебя в запросе получилось
LIMIT '0', 10
Так как по умолчанию bindParam вставляет параметр как строку.
>ты передаешь вот тут значение аргумента, который не используется в запросе
Используется, я просто на время закомментировал ту строчку, пока искал ошибку, и прямо подставил название колонки таблицы, по которой будет сортировка.
>проверить на белый список
Я в курсе, собирался сделать следующим шагом эту проверку.
>bindValue вместо bindParam
Первый раз слышу, сейчас буду разбираться с ней, ок.
Насчет логов понял, ага.
Хорошо, благодарствую за помощь! Так всего час психовал, без вас мучился бы еще два.
Кстати, сначала подозревал, что в этом ошибка. Но в другом методе моего класса точь в точь такой же запрос, и там все работает (потому что тип совпал, теперь понимаю).
Сейчас допиливаю этот квест. https://gist.github.com/codedokode/d7e7f11449fc3bcb24b4
Если не споткнусь еще на чем-то, то завтра надеюсь закончить.
Вот кусок кода с основными классами. Может посмотрите, вдруг еще какие-нибудь замечания, чтоб не пришлось еще раз переделывать (а таки наверняка придется).
https://gist.github.com/krbn/1b1681e85ccca3b0d96f
И еще вопрос по MVC. Я правильно понял, что смысл ее в том, чтобы распихать код по файлам контроллеры - файлы моделей - шаблоны с хтмл?
На пике прикрепляю грубую схему сайта с регистрацией абитуриентов (там еще куча мелких контроллеров на самом деле).
Основную идею я правильно понял?
Что?
Массив можно сериализовать многими способами, через функции json, например. Пока непонятно, что ты хочешь.
Кидай свой код на gist.github.com или ideone.com, потом сюда ссылку, разберемся.
Мануалы все-равно курить придется, и не три дня, а три месяца.
Завтра тебе скажут передать данные обратно из js в php, ты опять сюда придешь за готовым решением?
>тут это есть
Это я написал решение твоей задачи. Пост анонимный кстати, не знаю, сколько они хранятся на гитхабе. Так что скопируй, пока не удалили.
Простой сайтик.
https://github.com/tokotun/matriculant/blob/master/app/functions.php#L55
Вот тут в GET-запрос попадает только 'name'. Остальное почему то не записывается :(
Ебать я ленивый. Заставить себя что либо делать удаётся только раз в неделю, а то и реже.
Наверно боги те, кто может управлять собой.
>js в php
Это я уже умею. POST/GET
Я просто решил пока сосредоточиться на одном языке. Жаваскрипте. Когда я натяну его до должного уровня, то крепко займусь пхп. Так я решил. Возможно, для кого-то это покажется глупым и неправильным, но я по такой методе овладел уже двумя различными сложными для меня навыками на нужном мне уровне. А это английский и рисование.
>Так что скопируй, пока не удалили.
Я оттуда взял всего пару строчек. Да и их я запомнил уже. Спасибо на том.
>>424178
>>424044
Со строчками нельзя вести себя как с массивами, если используется мультибайтовая кодировка как utf-8, так как каждый символ весит разное количество байт, а для использования [] нужно, чтобы символы весили равное количество байт.
Попробуй mb_substr($str,$pos,1,'UTF-8');
Вот паста ОПа про работу со строками. https://gist.github.com/codedokode/ff99e357e9860ea169b8
Чтобы пользователь дважды не отправил пост/рег.данные при обновлении f5.
Видел такой заголовок, но не совсем понял, в каком месте его лепить.
header('Location: '.$_SERVER['REQUEST_URI']);
Вот у меня после отправки формы через шаблонизатор подгружается содержимое if($_SERVER['REQUEST_METHOD'] == 'POST'){ первая вьюха } else { вторая вьюха }.
Если я допишу хедер локейшн то меня же перекинет методом гет, и прорисуется совсем другой контент. Как быть?
Один из вариантов — сделать переход через скрипт подсчета на своем сайте например
http://example.com/goto/site.com/page.html
>>423976
> чем отличается mb_substr от mb_strcut
http://php.net/manual/ru/function.mb-strcut.php
> mb_strcut() вычленияет подстроку из строки также, как mb_substr(), но оперирует байтами вместо символов.
Тебе она скорее всего никогда не понадобится.
> Нужен ли EREG или сейчас все PCRE используют?
pcre. ereg вроде даже удалять собирались.
>>423997
Как советует анон, давай на этой задаче освоим что такое доступ private/protected. Сделай все свойства private/protected, а не public, чтобы они быди доступны только из своего класса. Также, все методы которые не должны вызываться снаружи, пометь закрытыми.
Мануал: http://php.net/manual/ru/language.oop5.visibility.php
В Desk лучше не передавать массивы кошек/мышек, а сделать методы для добавления и удаления животных, так будет удобнее.
Ширину/высоту доски лучше не задавать жестко, а обозначить переменными.
Свойство this->board лучше заменить на переменную, так как его не требуетс хранить, оно временное.
Методы поиска врагов и выбор хода должны быть в кошке/мышке, а не в карте.
Один из вариантов — сделать переход через скрипт подсчета на своем сайте например
http://example.com/goto/site.com/page.html
>>423976
> чем отличается mb_substr от mb_strcut
http://php.net/manual/ru/function.mb-strcut.php
> mb_strcut() вычленияет подстроку из строки также, как mb_substr(), но оперирует байтами вместо символов.
Тебе она скорее всего никогда не понадобится.
> Нужен ли EREG или сейчас все PCRE используют?
pcre. ereg вроде даже удалять собирались.
>>423997
Как советует анон, давай на этой задаче освоим что такое доступ private/protected. Сделай все свойства private/protected, а не public, чтобы они быди доступны только из своего класса. Также, все методы которые не должны вызываться снаружи, пометь закрытыми.
Мануал: http://php.net/manual/ru/language.oop5.visibility.php
В Desk лучше не передавать массивы кошек/мышек, а сделать методы для добавления и удаления животных, так будет удобнее.
Ширину/высоту доски лучше не задавать жестко, а обозначить переменными.
Свойство this->board лучше заменить на переменную, так как его не требуетс хранить, оно временное.
Методы поиска врагов и выбор хода должны быть в кошке/мышке, а не в карте.
Лучше залить это куда-то, так как вряд ли кто-то будет заморачиваться со скачиванием, установкой, настройкой этой библиотеки. А так, можно было бы отладчиком глянуть.
>>424158
Сам по себе mysqli позиционируется как замена mysql функциям и не устарел. Проблема в том, что преподаватели вместо того чтобы написать новые уроки, берут старые уроки по mysql c ошибками и уязвимостями и приписывают там буковку i. Это разумеется плохо.
Потому лучше изучать PDO чтобы не наткнуться на такие уроки: http://habrahabr.ru/post/137664/
Вот статья по mysqli: http://habrahabr.ru/post/141127/
Я советую не использовать процедурные методы, а ООП-вариант mysqli. Ну и PDO удобнее хотя бы тем что умеет кидать исключения (хотя есть места где он проигрывает mysqli).
То есть если вы видите в уроке mysqli_query(), mysqli_fetch_..., не используются плейсхолдеры то 99% что это старый неграмотный урок в котором приписана буква i к быдлокоду из mysql-функций.
Он имел в виду php-расширение mysql предоставляющее функции клиента MySQL.
>>424044
Не стоит, так как в PHP строка это не набор символов, а набор байт. И ты получишь в итоге разорванные на куски буквы (в utf-8 буква занимает несколько байт). Если тебе хочется то лучше разбить строку на массив букв и с ним работать:
Для разбиения на буквы можно использовать
$letters = preg_split("//u", $text, null, PREG_SPLIT_NO_EMPTY);
Это работает за счет того, что пустая регулярка соответствует промежуткам между буквами и разбивает по ним строку на буквы. Флаг в конце нужен чтобы удалить 2 пустых элемента в начале и конце массива.
Обрати внимание на флаг u. Он говорит что текст в utf-8 и заставляет разбивать строку именно на буквы по границам utf-8 символов, а не на куски по 1 байту.
В след раз пости ссылку на ideone а не сам код.
>>424191
Разметка
>>424214
У тебя изначаьно сверстано неправильно скорее всего, не видя кода трудно дать совет. Если хочешь могу дать задачи на HTML/CSS, полезные.
>>424218
bootstrap не заменяет необходимость знать CSS
>>424251
Гляну но наверно завтра, пока что некогда
>>424270
Не стоит давать такие советы если человек не знает флоатов так как он все равно не поймет что к чему и почему текст ниже уехал вверх. Лучше прорешать задачки на HTML/CSS.
>>424351
> И еще вопрос по MVC. Я правильно понял, что смысл ее в том, чтобы распихать код по файлам контроллеры - файлы моделей - шаблоны с хтмл?
Да, мы разбиваем приложение на компоненты, каждая из которых отвечает за что-то одно и таким образом уменьшаем его сложность и спутанность.
> На пике прикрепляю грубую схему сайта с регистрацией абитуриентов (там еще куча мелких контроллеров на самом деле).
> Основную идею я правильно понял?
Боюсь то не совсем. require для классов не надо ставить в if а надо ставить в самое начало файла.
По коду:
Синглтоны не очень хорошая штука, лучше вообще без них делать тем более в учебной задаче (если интересно почему почитай мой урок про внедрение зависимостей и связи между объектами: https://gist.github.com/codedokode/e1d31a31b37d5f635057 Учти что уровень урока довольно сложный).
Если одному классу нужен экземпляр другого напрмер объект PDO то лучше всего передавать его через конструктор.
> \tfunction insertIntoDB(Student &$student){
& не нужен: http://php.net/manual/ru/language.oop5.references.php (кстати я уже второй раз пишу это замечание, не тебе ли в прошлый раз писал?)
try/catch писать не надо, вот мой урок про исключения: https://gist.github.com/codedokode/65d43ca5ac95c762bc1a
Даже если твой код пока не работает, лучше все равно его показывать, так как в этом случае меньше исправлять потом придется.
В след раз пости ссылку на ideone а не сам код.
>>424191
Разметка
>>424214
У тебя изначаьно сверстано неправильно скорее всего, не видя кода трудно дать совет. Если хочешь могу дать задачи на HTML/CSS, полезные.
>>424218
bootstrap не заменяет необходимость знать CSS
>>424251
Гляну но наверно завтра, пока что некогда
>>424270
Не стоит давать такие советы если человек не знает флоатов так как он все равно не поймет что к чему и почему текст ниже уехал вверх. Лучше прорешать задачки на HTML/CSS.
>>424351
> И еще вопрос по MVC. Я правильно понял, что смысл ее в том, чтобы распихать код по файлам контроллеры - файлы моделей - шаблоны с хтмл?
Да, мы разбиваем приложение на компоненты, каждая из которых отвечает за что-то одно и таким образом уменьшаем его сложность и спутанность.
> На пике прикрепляю грубую схему сайта с регистрацией абитуриентов (там еще куча мелких контроллеров на самом деле).
> Основную идею я правильно понял?
Боюсь то не совсем. require для классов не надо ставить в if а надо ставить в самое начало файла.
По коду:
Синглтоны не очень хорошая штука, лучше вообще без них делать тем более в учебной задаче (если интересно почему почитай мой урок про внедрение зависимостей и связи между объектами: https://gist.github.com/codedokode/e1d31a31b37d5f635057 Учти что уровень урока довольно сложный).
Если одному классу нужен экземпляр другого напрмер объект PDO то лучше всего передавать его через конструктор.
> \tfunction insertIntoDB(Student &$student){
& не нужен: http://php.net/manual/ru/language.oop5.references.php (кстати я уже второй раз пишу это замечание, не тебе ли в прошлый раз писал?)
try/catch писать не надо, вот мой урок про исключения: https://gist.github.com/codedokode/65d43ca5ac95c762bc1a
Даже если твой код пока не работает, лучше все равно его показывать, так как в этом случае меньше исправлять потом придется.
Насчет мотивации, мы этому не учим и никого не мотивируем, но у разных людей разные способы. Кому-то надо думать о цели и выгоде, чтобы замотивироваться, кому-то просто железной рукой взять себя и заставить что-то делать, кому-то нужен надсмотрщик.
> Вот тут в GET-запрос попадает только 'name'
Попробуй через var_dump вывести все переменные, а заодно и _GET и _SERVER.
Код гляну, но позже.
>>424405
У меня если что есть задачки на яваскрипт, а один анон даже запилил проверялку для первых 7: http://dkab.github.io/jasmine-tests/
>>424432
После location надо делать die так как при редиректе выводить ничего не требуется, хватит заголовка.
Речь идет об уроках "Регулярные выражения"(http://archive-ipq-co.narod.ru/l1/regexp.html).
Вот то, что я наговнокодил на данный момент: http://ideone.com/p3nTVR.
Со ссылкой на урок обосрался, но вы поняли, я думаю.
http://archive-ipq-co.narod.ru/l1/regexp.html
Не обращай внимания. Я ему посоветовал учить теорию и не использовать готовые решения, а он обиделся и начал нести ахинею про саморазвитие.
Видно, я грубовато выражаюсь, привык ведь к мамоебству на бе.
Надо будет тщательнее подбирать слова, чтобы не травмировать мнительных омег.
>& не нужен: http://php.net/manual/ru/language.oop5.references.php (кстати я уже второй раз пишу это замечание, не тебе ли в прошлый раз писал?)
nyet. Просто в задачнике стоит ссылка на хабру http://habrahabr.ru/post/198450/, там в примере стоит эта козявка public function saveFoo(Foo &$foo), вот все и копипастят.
>require для классов не надо ставить в if а надо ставить в самое начало файла
Дак это же у меня не классы, а модели.
Если одно условие, то подключить одну модель и соответственный шаблон, если другое условие, то другая модель.
Ну ладно, сейчас я уже до конца допилю, потом сверимся, каким должен быть правильный порядок файлов.
Вот оно как ... прямо хоть предупреждение рядом пиши. Надо же не бездумно переписывать код, а почитать и написать своими словами.
>>424574
> травмировать мнительных омег.
Не разжигай тут. Все аноны, котоые у нас учатся, уж точно не «омеги», а люди, идущие к своей цели. Алсо, какой-то чудак придумал делить людей по буквам греческого
алфавита, а вы ему верите.
>>424558
> а как сделать так, чтоб выводилось предложение, в котором ошибка?
Это не так просто. Один из вариантов — разбить строку на массив предложений, обходить их циклом и тогда мы можем при нахождении ошибки вывести текущее предложение.
Но вообще можно и просто вывести место с ошибкой.
Алсо
> PHP Notice: Use of undefined constant PREG_SPLIN_NO_EMPTY - assumed 'PREG_SPLIN_NO_EMPTY' in /home/yiEQbo/prog.php on line 10
Не сплин, а сплит.
Не уверен что тут подойдет preg_match так как он находит только первое совпадение с шаблоном. Чтобы найти все совпадния, нужен preg_match_all
Ну и в регулярке не уверен что все верно:
> [.]\\s
Что плохого в пробеле после точки?
> [жы]
Это ищет не послежовательность «жы» а любую из букв то есть «ж» или «ы». Квадратные скобки значат «один из указанных символов».
Вот оно как ... прямо хоть предупреждение рядом пиши. Надо же не бездумно переписывать код, а почитать и написать своими словами.
>>424574
> травмировать мнительных омег.
Не разжигай тут. Все аноны, котоые у нас учатся, уж точно не «омеги», а люди, идущие к своей цели. Алсо, какой-то чудак придумал делить людей по буквам греческого
алфавита, а вы ему верите.
>>424558
> а как сделать так, чтоб выводилось предложение, в котором ошибка?
Это не так просто. Один из вариантов — разбить строку на массив предложений, обходить их циклом и тогда мы можем при нахождении ошибки вывести текущее предложение.
Но вообще можно и просто вывести место с ошибкой.
Алсо
> PHP Notice: Use of undefined constant PREG_SPLIN_NO_EMPTY - assumed 'PREG_SPLIN_NO_EMPTY' in /home/yiEQbo/prog.php on line 10
Не сплин, а сплит.
Не уверен что тут подойдет preg_match так как он находит только первое совпадение с шаблоном. Чтобы найти все совпадния, нужен preg_match_all
Ну и в регулярке не уверен что все верно:
> [.]\\s
Что плохого в пробеле после точки?
> [жы]
Это ищет не послежовательность «жы» а любую из букв то есть «ж» или «ы». Квадратные скобки значат «один из указанных символов».
>>424587
Хорошо, ждем.
>Даже если твой код пока не работает, лучше все равно его показывать
пока так
https://github.com/krbn/students
не сделал еще: обработку заполнения полей в js, страницу редактирования профиля
не работает почему-то сортировка по колонке (хотя сейчас уже ночь, и я ничего не соображаю, скорее всего какая-то глупая ошибка)
раскомментируйте строку, где подключается модель, инсёртящая в бд, а то я отключил, чтоб не париться каждый раз
500 постов, тред не утонет?
>Дак это же у меня не классы, а модели.
Нет такого в php. Для классов, которые могут вызваться, а могут не вызваться используется __autoload(). При этом каждый класс кладется в отдельный файл и обзывается таким же именем. В результате избавляемся от лишних веток с условиями.
у меня содержимое элемента не умещается и я использую overflow: auto; всё бы хорошо, но он размещается не в ту сторону, в которую я бы хотел. т. е скроллить можно в низ, а я хочу, чтобы вправо. как быть? спасибки заранее
Ты бы хоть почитал про работу с массивами и параметры in_array(), а потом приходил.
Непонятно, как у тебя контент отпозиционирован.
Я так понял, что у тебя куча дивов (типа галерея с картинками), которые должны прокручиваться горизонтально.
Сделай эти дивы плавающими (float: left), засунь их себе в другой див, типа контейнер, у которого захардкодь высоту и ширину. Потом эту матрешку суешь в еще один див, у которого указываешь свойство overflow-x: scroll.
Что-то типа такого: https://gist.github.com/anonymous/2a61745087023226ebe4
А вообще учи матчасть.
Сейчас вернется оп треда, даст мне пизды за то что я вам раздаю вредные советы, а тебе вручит коллекцию уроков по хатемелю и css.
оп, не смотри это говно, я уже понял, что обосрался.
Сейчас переделаю (пятый раз, пристрелите меня кто-нибудь!)
Поздно, лол. Он сначала смотрит смотрит пост и проверяет всё, что в нем, а потом только читает следующие.
Суп, пхпшеры. Замыслил я одно дело. Раскритикуйте и отговорите. В пхп я очень не очень, но основы понимаю. Решил для себя написать удобную управлялку для личинки от анона из набигача. Кратко опишу принцип работы этой личинки. Запускается батник у жертвы, затем батник по таймеру проверяет текстовый документик на управляющем сайте строго прописаном в настройках. Список команд весьма большой, от информации о машине, до записи с вебки. Каждой личинке дается уникальное имя. Личинка может отвечать на команды 4 типами: фтп, смтп, бэйс64 в гет запросе, или просто гет запрос. Вот тут и врывается пхп. Мой план таков: на интерфейсе кнопуля: "проверить онлайн" действия которой будут -
а) поменять командный файлик в котором теперь будет запрашиваться команда "hey". Ответить по специальному адресу.
б) Начать ждать гет запросы по специальному адресу.
в) Отсчитать минуту молчания это чтобы все личинки успели ответь и сообщить результат.
И это кнопка "проверить онлайн". Все ничего, но у меня в голове сразу увиделись недостатки:
а) В нынешней версии личинки, которой пользуюсь я не работают просто ГЕТ запросы. Работает только зашифрованный в бейс64. От чего одна личинка шлет ~5 ответов в base64 на команду hey.
б) Если одна личинка шлет по 5 ответов с разными интервалами, то как мне ловить ответы от 5 таких личинок? Они же все в куче будут.
в) Долго. У всех личинок разный таймер в зависимости от ситуации. Они не видят командный файлик сразу же как он изменен.
Таки что не так в моем наивно-ньюфажном плане? И как мне решить проблемы выше?
Сравнение юникодных строк (collation на английском) — сложная тема. Проблема не в том, что там много букв из разных алфавитов, а в том что одни и те же буквы имеют разный порядок в разных языках. Например, буквы с точечками и черточками: http://en.wikipedia.org/wiki/Alphabetical_order#Language-specific_conventions
В некоторых языках буквы вроде å идут после z, в некоторых после a. В некорых (английский) они имеют одинаковый вес с «a». То есть сортировка зависит от языка.
В немецком, ß равносильно ss по моему.
В японском есть 2 алфавита (хирагана/катакана), обозначающих одни и те же слоги.
Лигатуры вроде Œ могут быть равносильны комбинации oe, а могут и не быть.
Также, одна буква (упомянутая выше å) может храниться в строке как один символ либо как комбинация 2 символов: кружочек + a (чтобы избежать проблем из-за этого, строки перед сравнением можно нормализовать, приведя к еждиному виду).
Как ты надеюсь, догадался, сравнение строк очень нетривиальная вещь. Потому для этого есть специальные библиотеки, самая известная из них это открытая ICU. В PHP ты можешь воспользоваться ее возможностями с помощью расширения Intl (которое умеет не только сравнение строк, но и многое другое): http://php.net/manual/ru/book.intl.php
В этом расширении есть класс Collator для сравнения строк по правилам указанного языка: http://php.net/manual/ru/class.collator.php
Он умеет сравнивать строки и сортировать массивы, в том числе применяя нормализацию, по правилам в выбранной локали.
Если локаль не указана, то по моему применяются общие правила. подробно это все описано в стандарте UNICODE COLLATION ALGORITHM: http://www.unicode.org/reports/tr10/ (англ). Там в начале есть примеры всех этих сложностей со сравнением, интересно почитать.
Без него (расширения Intl), например в выражении if ($x > $y), php сравнивает строки побайтово, по кодам символов. То есть у кого код больше тот и ниже в списке. Вот получающийся порядок символов, например, для кириллицы: http://unicode-table.com/ru/#cyrillic
Видно что буква Ё там идет раньше чему буква А (а маленькая ё наоборот ниже чем я).
> Только через установку локалей с преобразованиями кодировки?
Локали лучше вообще не использовать так как они общие на весь процесс, а php может выполняться в многопточной среде. C utf8 строками локали по моему вообще не работают, по крайней мере в php. Ну и вообще, есть решение для этой задачи, не надо изобретать костыли.
Кстати вопрос про сравнение строк хорошо задавать на собеседовании, мне кажется, чтобы посмотреть ход мыслей кандидата.
Сравнение юникодных строк (collation на английском) — сложная тема. Проблема не в том, что там много букв из разных алфавитов, а в том что одни и те же буквы имеют разный порядок в разных языках. Например, буквы с точечками и черточками: http://en.wikipedia.org/wiki/Alphabetical_order#Language-specific_conventions
В некоторых языках буквы вроде å идут после z, в некоторых после a. В некорых (английский) они имеют одинаковый вес с «a». То есть сортировка зависит от языка.
В немецком, ß равносильно ss по моему.
В японском есть 2 алфавита (хирагана/катакана), обозначающих одни и те же слоги.
Лигатуры вроде Œ могут быть равносильны комбинации oe, а могут и не быть.
Также, одна буква (упомянутая выше å) может храниться в строке как один символ либо как комбинация 2 символов: кружочек + a (чтобы избежать проблем из-за этого, строки перед сравнением можно нормализовать, приведя к еждиному виду).
Как ты надеюсь, догадался, сравнение строк очень нетривиальная вещь. Потому для этого есть специальные библиотеки, самая известная из них это открытая ICU. В PHP ты можешь воспользоваться ее возможностями с помощью расширения Intl (которое умеет не только сравнение строк, но и многое другое): http://php.net/manual/ru/book.intl.php
В этом расширении есть класс Collator для сравнения строк по правилам указанного языка: http://php.net/manual/ru/class.collator.php
Он умеет сравнивать строки и сортировать массивы, в том числе применяя нормализацию, по правилам в выбранной локали.
Если локаль не указана, то по моему применяются общие правила. подробно это все описано в стандарте UNICODE COLLATION ALGORITHM: http://www.unicode.org/reports/tr10/ (англ). Там в начале есть примеры всех этих сложностей со сравнением, интересно почитать.
Без него (расширения Intl), например в выражении if ($x > $y), php сравнивает строки побайтово, по кодам символов. То есть у кого код больше тот и ниже в списке. Вот получающийся порядок символов, например, для кириллицы: http://unicode-table.com/ru/#cyrillic
Видно что буква Ё там идет раньше чему буква А (а маленькая ё наоборот ниже чем я).
> Только через установку локалей с преобразованиями кодировки?
Локали лучше вообще не использовать так как они общие на весь процесс, а php может выполняться в многопточной среде. C utf8 строками локали по моему вообще не работают, по крайней мере в php. Ну и вообще, есть решение для этой задачи, не надо изобретать костыли.
Кстати вопрос про сравнение строк хорошо задавать на собеседовании, мне кажется, чтобы посмотреть ход мыслей кандидата.
Сделал из поста мини-урок про сравнение строк: https://gist.github.com/codedokode/ea09d0224a4df0c4442f
Ну и конечно воспользуюсь возможностью послать лучи поноса разработчикам популярных ОС которые не хотят сделать их надежными и безопасными вроде той же iOS от Эппл. Если вы даете возможность пользователю кликом запустить троян по ссылке или из письма (а не ставить только подписанные приложения из магазина), то найдется дурак который его запустит. Если вы не помещаете приложения в контейнеры (вроде приложений на iOS или процессов вкладок в Google Chrome) и используете языки без проверки границ строк, то через них взломают всю систему.
Вот советы и замечания по улучшению кода.
Насчет кук, ты не задаешь на путь к кукам, ни время жизни. Это значит что будет поставлена временная кука, которая при закрытии браузера удалится. Почитай мануал http://php.net/manual/ru/function.setcookie.php В качестве path лучше указать '/' чтобы куки были доступны на всем сайте. Также на всякий случай стоит поставить httponly = true, чтобы куку нельзя было украсть при XSS узявимости яваскриптом.
> $id = 'Регистрация';
Выглядит странно. Наверно, лучше завести булеву переменную $isRegistered или как-то так.
> if(isset($_POST['exit'])){
> setcookie('studentscookie[email]', "", time()-3600);
Разлогинивание (удаление кук) логично сделать отдельной функцией, то есть
if (isset($_POST['exit'])) {
logout( );
}
> ?>
Не надо ставить этот маркер в конце файла
> https://github.com/MindiMakridi/Students/blob/master/lib/functions.php#L26
> $mapper=new StudentMapper($DBH);
Почему этот код в файле functions? Логично что в файле functions должны быть только функции. Вынеси код оттуда.
> https://github.com/MindiMakridi/Students/blob/master/lib/DataMapper.php#L39
> throw new Exception("Íå âåðíûé çàïðîñ ê áàçå äàííûõ");
Сохраняй файлы в utf-8 без BOM
> profile
Имена классов должны писаться с большой буквы.
> $salt1 = "pineapple";
> $secretcode = md5($salt1 . $email . $salt2);
Это лучше всего вынести в отдельную функцию, то есть сделать функцию которая на вход принимает email и выдает код. А безопаснее вообще генерировать код случайно, так как в твоем случае при похищении всего двух секретных слов злоумышленник сможет получить любой код любого пользователя.
Сами секретные слова хорошо бы вынести из кода в конфиг чтобы их было легко менять.
> https://github.com/MindiMakridi/Students/blob/master/lib/DataMapper.php#L80
такие длинные строки надо переносить (в PHP и в SQL запросах можно делать переносы внутри строки).
> public function getLastId()
> public function getCode()
Лучше не делать 2 дополнительных функции, а просто при сохранении студента в addStudent прописывать id и код в переданный объект profile.
> if ($mapper->fetchMail($email) && $email != $_COOKIE['studentscookie']['email']) {
Что это? Запрет менять email? Почему так?
> https://github.com/MindiMakridi/Students/blob/master/profile.php#L56
Это лучше вынести в функцию updateStudentCookie(Profile $profile);
> https://github.com/MindiMakridi/Students/blob/master/lib/Profile.php#L40
HTML теги должны быть в шаблоне, а не тут.
Насчет секретного кода, тут https://github.com/MindiMakridi/Students/blob/master/profile.php#L14 надо сделать проверку что если профиль не выбрался, то вывести ошибку вроде «редактирование данных невозможно из-за технической ошибки».
Вот тут https://github.com/MindiMakridi/Students/blob/master/profile.php#L9 в обоих ветках условия находится почти одинаковый код обработки формы. Подумай, как объединить его в один общий код.
> header("Location: $redirect");
После редиректа надо делать die так как выведенную страницу все равно никто не увидит. Также, откуда берется переменная redirect? Что-то не очевидно. Может надо вверху страницы подключить конфиг? Или сделать функцию вроде getConfig('redirect')? Ну и переменную хорошо бы назвать вроде configRedirect чтобы было очевидно откуда она.
> <?php echo $student->showName()." ".$student->showSname() ?>
В шаблоне короче писать <?= вместо <?php echo
Также, тут у тебяможет быть XSS-уязвимость, ведь ты не экранируешь спецсимволы через htmlspecialchars.
Также, когда ты используешь htmlspecialchars надо всегда ставить вторым параметром флаг ENT_QUOTES иначе одиночная кавычка не экранируется и если ты ее используешь в HTML то появляется шанс на обход защиты.
> https://github.com/MindiMakridi/Students/blob/master/templates/main.html#L3
Для поиска принято использовать не POST а GET так как поиск не изменяет никакие данные на сервере + появляется возможность получить ссылку на результаты поиска.
> https://github.com/MindiMakridi/Students/blob/master/templates/main.html#L15
В шаблоне надо использовать версию foreach с двоеточием: http://php.net/manual/ru/control-structures.alternative-syntax.php
Вот советы и замечания по улучшению кода.
Насчет кук, ты не задаешь на путь к кукам, ни время жизни. Это значит что будет поставлена временная кука, которая при закрытии браузера удалится. Почитай мануал http://php.net/manual/ru/function.setcookie.php В качестве path лучше указать '/' чтобы куки были доступны на всем сайте. Также на всякий случай стоит поставить httponly = true, чтобы куку нельзя было украсть при XSS узявимости яваскриптом.
> $id = 'Регистрация';
Выглядит странно. Наверно, лучше завести булеву переменную $isRegistered или как-то так.
> if(isset($_POST['exit'])){
> setcookie('studentscookie[email]', "", time()-3600);
Разлогинивание (удаление кук) логично сделать отдельной функцией, то есть
if (isset($_POST['exit'])) {
logout( );
}
> ?>
Не надо ставить этот маркер в конце файла
> https://github.com/MindiMakridi/Students/blob/master/lib/functions.php#L26
> $mapper=new StudentMapper($DBH);
Почему этот код в файле functions? Логично что в файле functions должны быть только функции. Вынеси код оттуда.
> https://github.com/MindiMakridi/Students/blob/master/lib/DataMapper.php#L39
> throw new Exception("Íå âåðíûé çàïðîñ ê áàçå äàííûõ");
Сохраняй файлы в utf-8 без BOM
> profile
Имена классов должны писаться с большой буквы.
> $salt1 = "pineapple";
> $secretcode = md5($salt1 . $email . $salt2);
Это лучше всего вынести в отдельную функцию, то есть сделать функцию которая на вход принимает email и выдает код. А безопаснее вообще генерировать код случайно, так как в твоем случае при похищении всего двух секретных слов злоумышленник сможет получить любой код любого пользователя.
Сами секретные слова хорошо бы вынести из кода в конфиг чтобы их было легко менять.
> https://github.com/MindiMakridi/Students/blob/master/lib/DataMapper.php#L80
такие длинные строки надо переносить (в PHP и в SQL запросах можно делать переносы внутри строки).
> public function getLastId()
> public function getCode()
Лучше не делать 2 дополнительных функции, а просто при сохранении студента в addStudent прописывать id и код в переданный объект profile.
> if ($mapper->fetchMail($email) && $email != $_COOKIE['studentscookie']['email']) {
Что это? Запрет менять email? Почему так?
> https://github.com/MindiMakridi/Students/blob/master/profile.php#L56
Это лучше вынести в функцию updateStudentCookie(Profile $profile);
> https://github.com/MindiMakridi/Students/blob/master/lib/Profile.php#L40
HTML теги должны быть в шаблоне, а не тут.
Насчет секретного кода, тут https://github.com/MindiMakridi/Students/blob/master/profile.php#L14 надо сделать проверку что если профиль не выбрался, то вывести ошибку вроде «редактирование данных невозможно из-за технической ошибки».
Вот тут https://github.com/MindiMakridi/Students/blob/master/profile.php#L9 в обоих ветках условия находится почти одинаковый код обработки формы. Подумай, как объединить его в один общий код.
> header("Location: $redirect");
После редиректа надо делать die так как выведенную страницу все равно никто не увидит. Также, откуда берется переменная redirect? Что-то не очевидно. Может надо вверху страницы подключить конфиг? Или сделать функцию вроде getConfig('redirect')? Ну и переменную хорошо бы назвать вроде configRedirect чтобы было очевидно откуда она.
> <?php echo $student->showName()." ".$student->showSname() ?>
В шаблоне короче писать <?= вместо <?php echo
Также, тут у тебяможет быть XSS-уязвимость, ведь ты не экранируешь спецсимволы через htmlspecialchars.
Также, когда ты используешь htmlspecialchars надо всегда ставить вторым параметром флаг ENT_QUOTES иначе одиночная кавычка не экранируется и если ты ее используешь в HTML то появляется шанс на обход защиты.
> https://github.com/MindiMakridi/Students/blob/master/templates/main.html#L3
Для поиска принято использовать не POST а GET так как поиск не изменяет никакие данные на сервере + появляется возможность получить ссылку на результаты поиска.
> https://github.com/MindiMakridi/Students/blob/master/templates/main.html#L15
В шаблоне надо использовать версию foreach с двоеточием: http://php.net/manual/ru/control-structures.alternative-syntax.php
Забыл сказать, в классе Collator есть метод asort для сортировки массива строк. Если тебе нужна более хитрая сортировка (например объектов-студентов по имени) то можно использовать usort c использованием пользовательской функции сравнения.
Замечаний тут можно написать много. Но давай я сначала лучше расскажу про то, что такое MVC и как его делать правильно.
Вообще, все эти MVC, ООП и прочие вещи появились не от хорошей жизни. Они нужны для организации кода, чтобы по мере роста объема кода он не становился запутанным (от чего с ним трудно работать и легко сделать ошибку). Организация кода заключается в том, что мы разбиваем его на слабо связанные части и каждая часть занимается только своим делом. В случае с процедурным подходом мы разбиваем код на набор функций + глобальных переменных, в случае ООП на классы, в случае MVC мы выделяем части, отвечающие за логику и за вывода, отдельно.
В случае MVC модель (M) (обычно это один или несколько классов) отвечает за хранение данных (например в базе), обработку этих данных. Представление (или вид, V) отвечает за отображение данных. А контроллер (C) обрабатывает пользовательские запросы и дает команды модели и представлению сделать какое-то действие и что-то отобразить.
Вот например как может выглядеть реализация MVC для сайта, выводящего постранично список студентов из базы:
Контроллер, обычный php файл index.php:
-------------
// Создаем объект модели для работы со студентами
$mapper = new StudentMapper( );
// Получаем студентов
$students = $mapper->findStudents( );
// Выводим список
require 'templates/index.phtml';
Модель, StudentMapper.php
-------------
class StudentMapper
{
....
}
Модель, Student.php
-------------
class Student
{
public $name;
}
Представление templates/index.phtml
-------------
<?php require 'header.phtml' ?>
<h1>Наши студенты</h1>
<ul>
<?php foreach ($students as $student) ?>
<li><?= html($student->name) ?></li>
<?php endforeach ?>
</ul>
<?php require 'footer.phtml' ?>
Как видишь, у нас каждый занимается своим делом: StudentMapper загружает список объектов-студенов из БД, Student представляет одного студента, представление index.phtml их отображает.
У тебя, к сожалению, все как-то смешано и явно понять что делает один файл, а что другой, трудно. Ну и названия плохие: model1.php и model2.php ничего не говорят читателю.
Вот статья про другой вариант реализации MVC на PHP: http://habrahabr.ru/post/150267/ но в нем довольно много сомнительных мест. Не копируй код оттуда, а думай своей головой.
Вот мой урок про работу с БД и мапперы: https://gist.github.com/codedokode/c4cbc4d7dc8e45ea074a
Если что-то непонятно или есть вопросы, задавай.
Замечаний тут можно написать много. Но давай я сначала лучше расскажу про то, что такое MVC и как его делать правильно.
Вообще, все эти MVC, ООП и прочие вещи появились не от хорошей жизни. Они нужны для организации кода, чтобы по мере роста объема кода он не становился запутанным (от чего с ним трудно работать и легко сделать ошибку). Организация кода заключается в том, что мы разбиваем его на слабо связанные части и каждая часть занимается только своим делом. В случае с процедурным подходом мы разбиваем код на набор функций + глобальных переменных, в случае ООП на классы, в случае MVC мы выделяем части, отвечающие за логику и за вывода, отдельно.
В случае MVC модель (M) (обычно это один или несколько классов) отвечает за хранение данных (например в базе), обработку этих данных. Представление (или вид, V) отвечает за отображение данных. А контроллер (C) обрабатывает пользовательские запросы и дает команды модели и представлению сделать какое-то действие и что-то отобразить.
Вот например как может выглядеть реализация MVC для сайта, выводящего постранично список студентов из базы:
Контроллер, обычный php файл index.php:
-------------
// Создаем объект модели для работы со студентами
$mapper = new StudentMapper( );
// Получаем студентов
$students = $mapper->findStudents( );
// Выводим список
require 'templates/index.phtml';
Модель, StudentMapper.php
-------------
class StudentMapper
{
....
}
Модель, Student.php
-------------
class Student
{
public $name;
}
Представление templates/index.phtml
-------------
<?php require 'header.phtml' ?>
<h1>Наши студенты</h1>
<ul>
<?php foreach ($students as $student) ?>
<li><?= html($student->name) ?></li>
<?php endforeach ?>
</ul>
<?php require 'footer.phtml' ?>
Как видишь, у нас каждый занимается своим делом: StudentMapper загружает список объектов-студенов из БД, Student представляет одного студента, представление index.phtml их отображает.
У тебя, к сожалению, все как-то смешано и явно понять что делает один файл, а что другой, трудно. Ну и названия плохие: model1.php и model2.php ничего не говорят читателю.
Вот статья про другой вариант реализации MVC на PHP: http://habrahabr.ru/post/150267/ но в нем довольно много сомнительных мест. Не копируй код оттуда, а думай своей головой.
Вот мой урок про работу с БД и мапперы: https://gist.github.com/codedokode/c4cbc4d7dc8e45ea074a
Если что-то непонятно или есть вопросы, задавай.
Не, ты молодец что как-то помогаешь анонам. Но тому анону, конечно, надо подучить HTML/CSS.
Чтобы не вычислять ширину руками, можно попробовать использовать display table на враппере и display table cell на картинке.Тогда все картинки выстроятся в одну длинную линию и это должно работать даже с разными размерами картинок. Плюс, мы получаем возможность выравнивать их вертикально.
Минус — display table не работает в IE6/7.
Не хочешь проверить этот вариант?
>>424821
Логично что переносятся. По умолчанию инлайновые элементы выстраиваются в стакан шириной равной ширине родителя-блока.
>>424846
ну почитай мой совет, надеюсь поможет
>>424847
Это да, чтобы никого не пропустить.
Еще один вариант который может быть сработает везде — использовать для картинок display inline block + white-space nowrap на враппере чтобы картинки не переносились а шли одной строкой. Опять же, инлайн блоки можно выравнивать вертикально. Но тут надо проверять, заработает ли.
На тему выравнивания блоков у меня есть задача 4 отсюда: https://gist.github.com/codedokode/58ebc90bd006baf4b35c#%D0%97%D0%B0%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5-4
Не беда. Со временем у тебя будет получаться все лучше и лучше, особенно если ты будешь показывать код и следовать моим советам. Наш тред для этого и предназначен.
сорьки, уже нашел.
Возьми за основу ICQ|jabber, чтобы твои скрипты показывали кто из прокаженных онлайн. Разбери основательно принципы работы и алгоритм, чтобы реализовать это на php, который заведется хоть на шареде. Че велосипеды то лепить, ну.
>> if ($mapper->fetchMail($email) && $email != $_COOKIE['studentscookie']['email']) {
Что это? Запрет менять email? Почему так?
Запрещает ставить уже существующий в бд почтовый адрес. А вторая проверка, чтобы не выдавало ошибку, когда наш эмаил не изменяется.
>В шаблоне надо использовать версию foreach с двоеточием:
У меня там в комментарии написано: версия с двоеточием почему-то вызывает ошибку, тогда как обычная прекрасно работает. Так же и с <?= вместо <?php echo. Такая конструкция у меня не работает и все что внутри <?= ?> отображается как хтмл код, вместе с самим тегом.
> ерсия с двоеточием почему-то вызывает ошибку, тогда как обычная прекрасно работает.
Значит надо разобраться почему. Покажи код и текст ошибки
> Запрещает ставить уже существующий в бд почтовый адрес
Ясно. А почему она не вместе с другими проверками в check что-то там? И есть ли такая проверка при регистрации?
>И есть ли такая проверка при регистрации?
Да
https://github.com/MindiMakridi/Students/blob/master/profile.php#L46
Она не вместе с другими check, потому-что тут в отличие от остальных нужно делать запрос к бд.
file_get_contents('https://plus.google.com/' . $id . '/about');
То на выходе вижу, что спарсился профиль на немецком. Гугл как-то определил, что я якобы немец. Как мне ему показать, что я из России?
header("Content-Type:text/plain; charset=utf-8");
$html = file_get_contents('https://plus.google.com/' . $id . '/about');
Что еще дописать можно?
наверное, придется мне в jquery вычислять ширину
Дальше второй строчки не осилил?
Хохол в треде!
mysql+php
$pole = 'как@блядь@это@сделать'; (на самом деле это находится в базе данных - в одном текстовом поле)
$m = preg_split("/@/i", $pole);
for($i = 0; $i < 4; ++$i) {
echo '<br><input type="text" name="lol" value="' . $m[$i] . '" /><br>';
}
Юзер заполняет эти четыре поля так:
1) очень
2) легко
3) это
4) сделать
Как соединить эти инпуты и UPDATE базу данных? Так чтобы в базе данных (в поле) стало: 'очень@легко@это@сделать'.
Если ты подключаешь файл через include/require то он выполняется. То есть если в нем написан код, то он выполняется, если в нем описаны функции/классы, то они создаются.
Потому я не очень понимаю твой вопрос. В твоем коде должны сначала сработать print из одключенного файла, потом из основного.
Все так. А у меня почему то пехапа не исполняет прикрепленный файл. Ну то есть я его в браузере прям открываю, а там чистый лист без ошибок. Гмм.
И тут он на пустом месте заработал. Хотя вру. Первое что пришло в голову - сделать его исполняемым, но заработал он лишь через минуту. А еще что-то мне подсказывает, что php пофигу на флаг execute.
Спасибо, брат.
Кому интересно:
$pole = 'как@блядь@это@сделать';
$m = explode("@", $pole);
for($i = 0; $i < 4; ++$i) {
echo '<br><input type="text" name="lol[]" value="' . $m[$i] . '" /><br>';
}
обработка:
$in = implode("@", $_POST['form_nsc']);
то есть $in = implode("@", $_POST['lol']);
Вообще, неплохо. Я вижу что в сравнении с первыми версиями код стал намного аккуратнее. Правда, к нему по прежнему есть некоторые замечания. Я думаю, что после их исправления останется сделать еще одну большую проверку (и исправить ее замечания) и все будет готово. Не знаю, какие у тебя планы, но я бы советовал дальше делать задачку на файлообменник с шаблонизатором Twig, и может быть параллельно потихоньку решать задачки на SQL/JS/HTML/CSS чтобы подтянуть знания по ним. А дальше браться за фреймворки Yii2 и Symfony 2.
Советы и замечания.
Что-то у тебя с индексами перебор:
> PRIMARY KEY (`id`),
> UNIQUE KEY `id` (`id`),
Уникальный индекс не нужен так как PRIMARY KEY и так является уникальным индексом. Первичный ключ — это колонка которая однозначно идентифицирует запись и значения первичного ключа не могут повторяться.
> `code` int(16) NOT NULL,
Число в скобках для int это не максимальное число цифр в колонке. Это сколько места оставлять под число при выводе таблицы. int позволяет хранить число от -2 млрд до +2 млрд., а это не более 12 цифр. Чтобы было 16, тебе нужен bigint. Прочти в мануале, какие типы чисел существуют: http://phpclub.ru/mysql/doc/column-types.html
> ENGINE=MyISAM
Скидывал ли я ссылку на отличия MyISAM и InnoDB? Если кратко, MyISAM не поддерживает внешние ключи и транзакции, а они скорее всего понадобятся когда у тебя больше одной таблицы.
> generate_page_links
HTML-код все же лучше генерировать в шаблоне. Иначе получается каша. А в этой функции можно генерировать просто массив вида:
array(
подпись к кнопке => ссылка,
подпись к кнопке => ссылка,
....
);
Также, постраничную навигацию удобно делать через отдельный класс, примерно так (делать не обязательно, не хочешь, не делай, просто хочу показать, как это можно решить красивее с помощью ООП):
// Передаем общий шаблон ссылки, и дополнительно ссылку для первой станицы если она отличается по виду
$pager = new Pager('/students/page/{page}', '/students');
// передаем номер страницы и сколько всего страниц
$pager->setPage(3, 34);
// Передаем объект $pager в шаблон
....
// В шаблоне выводим пагинацию
<?php foreach ($pager->getLinks() as $text => $link): ?>
<a href="<?= html($link) ?>"><?= html($text) ?></a>
<?php endforeach ?>
> https://github.com/tokotun/matriculant/blob/master/app/functions.php#L27
В HTML коде вместо & надо писать & amp; так как & это спецсимвол для кодирования HTML-сущностей.
> https://github.com/tokotun/matriculant/blob/master/app/functions.php#L17
Чтобы вставить знак < надо писать & lt;
Я вижу, у тебя пробелы в знании HTML. Прочти-ка эти статьи:
http://htmlbook.ru/samhtml/tekst/spetssimvoly
http://ru.wikipedia.org/wiki/%D0%9C%D0%BD%D0%B5%D0%BC%D0%BE%D0%BD%D0%B8%D0%BA%D0%B8_%D0%B2_HTML
Чтобы вставить в HTML код символы < > & (эти 3 символа и их мнемоники надо выучить наизусть) надо использовать мнемоники. Также, можно использовать мнемоники если тебе надо вставить кавычку внутрь аттрибута: <a title="test " test" ...
> generate_sort_link
Эту функцию лучше переделать чтобы она генерировала только URL ссылки, а не тег A целиком. А заголовок таблицы со ссылками выводить в шаблоне например на основе массива с названиями колонок. Главная мысль, что надо стараться держать HTML код в шаблоне. Оттуда же можно и вызывать эти функции.
> https://github.com/tokotun/matriculant/blob/master/app/autoloader.php#L3
правильнее писать автолоадер так:
опредеяем путь к файлу
если (файл существует) то подключаем иначе ничего не делаем
Так как автолоадеров может быть несколько (например у библиотек бывают свои автолоадеры) и не должно возникать ошибки вроде «файл не найден».
Я вижу, у тебя есть повторяющийся в index.php и loin.php код, который подключает файлы, создает PDO и т.д. Удобно вынести этот код в отдельный файл, например app/boostrap.php и подключать только его (через require_once чтобы 2 раза не подключить).
> https://github.com/tokotun/matriculant/blob/master/index.php#L17
> $pdo = null;
А это зачем?
> https://github.com/tokotun/matriculant/blob/master/login.php#L55
> $name = htmlspecialchars($matriculant->name);
Это надо делать в шаблоне при выводе. Иначе трудно проверить, все ли ты заэкранировал или нет. Вообще, экранировать данные надо в том же месте где они применяются.
Также, не надо передавать 10 переменных. Передавай в шаблон только объект matriculant.
Также, надо в htmlspecialchars указывать флаг ENT_QUOTES иначе одиночная кавычка не экранируется и появляется риск XSS, можешь посмотреть в мануале.
> https://github.com/tokotun/matriculant/blob/master/app/Matriculant.php#L24
Модель не должна работать с POST данными. Надо переделать функцию чтобы она брала данные не из POST а из переданного массива (и переименовать ее). И разумеется, прежде чем брать $_POST['name'] надо проверить что этот элемент существует иначе получим ошибку.
> public function getName($name)
Это надо назвать setName а не getName
Еще. У тебя не очень удачно смешаны заполнение объекта данными из POST и проверка правильности данных (валидация). Лучше сделать 2 отдельных функции: одна загружает данные из массива в поля объекта, другая их проверяет и заполняет массив ошибок. Это делает функцию проверки более универсальной.
> public function notUniqueEmail()
Имя функции начинается с глагола: setNotUniqueEmailError
> https://github.com/tokotun/matriculant/blob/master/app/MatriculantMapper.php#L14
> if (isset($matriculant->id)) $statment->bindParam(':id', $matriculant->id);
Это не очень надежно, такие проверки делать. лучше передавать в функцию bindField дополнительный параметр, который говорит надо ли передавать id/code или нет. Кстати, кроме bindParam есть еще bindValue который позволяет передавать любые выражения.
Также, функция bindField явно не должна вызываться снаружи. Значит, она должна быть private/protected. Если ты не знаешь что такое private, прочти тут: http://php.net/manual/ru/language.oop5.visibility.php Вообще, старайся все что можно делать закрытым. Чем меньше public свойств и методов тем лучше код.
> https://github.com/tokotun/matriculant/blob/master/app/MatriculantMapper.php#L32
> $matriculant->code = mt_rand ( 0 , 2097151 );
Давай защиту сделаем понадежнее, сделаем чтобы там хотя бы цифр 15-16 было. Можно сгенерировать три 5-значных числа и склеить их в строку. Разумеется, генерация кода должна быть в отдельной функции.
> https://github.com/tokotun/matriculant/blob/master/app/MatriculantMapper.php#L95
> $total = $statment->rowCount( );
Вот это очень неправильно. Ты выбираешь очень много данных из базы, передаешь их в PHP, и ради чего? ТОлько чтобы посчитать их количество и выбросить. Не надо так. Используй функцию COUNT в MySQL которая умеет считать число строчек.
Если ты плохо знаешь MySQL могу посоветовать почитать мануалы по ссылкам и решить задачки отсюда: https://gist.github.com/codedokode/10539213 Там есть ссылка на учебник Пирамидина, он вполне неплохо объясняет разные виды запросов. Советую параллельно потихоньку читать его и решать задачки.
> https://github.com/tokotun/matriculant/blob/master/login.php#L27
> if (!$matriculantMapper->uniqueEmail($matriculant->email)){
При редактировании надо проверять email на уникальность исключая собственный email.
При редактировании надо сначала загрузить объект из базы, а потом перезаписывать его свойства на основе POST данных. Так надежнее, иначе какие-то данные могут потеряться. То есть алгоритм должен быть примерно такой:
-------------
при редактировании {
загрузить объект из БД
} иначе {
создать пустой объект
}
если форма отправлена {
обновить объект данными из POST
проверить на правильность;
если (ошибок нет) {
сохранить данные в БД;
сделать редирект и умереть;
}
}
вывести форму;
---------------
Соответвенно, я тебе советую сделать одну функцию проверки, например в M.Mapper, которой передается объект Matriculant и которая возвращает результат в виде true/false.
> https://github.com/tokotun/matriculant/blob/master/templates/profile.php#L17
Тут у тебя почему-то мужской пол всегда checked
> https://github.com/tokotun/matriculant/blob/master/templates/profile.php#L52
Закрывающие теги body/html лучше вынести в footer.php
А, там еще узявимоcть XSRF есть. Злоумышленник может создать страницу, поместить на нее невидимую заполненную форму, у которой action указывает на твой сайт, и сделать яваскрипт который при заходе отправляет форму. Заманив абитуриента на свою страницу злоумышленник может отредактировать его данные, например занизить ему результат ЕГЭ. Для борьбы с XSRF форму надо защитить каким-то кодом или токенов неизвестным злоумышленнику. Если не догадаешься сам как это сделать, попроси подсказку.
XSRF довольно серьезная уязвимость. С помощью нее можно отправлять любые формы от имени пользователя, например рассылать спам или делать переводы денег в платежной системе.
Вообще, неплохо. Я вижу что в сравнении с первыми версиями код стал намного аккуратнее. Правда, к нему по прежнему есть некоторые замечания. Я думаю, что после их исправления останется сделать еще одну большую проверку (и исправить ее замечания) и все будет готово. Не знаю, какие у тебя планы, но я бы советовал дальше делать задачку на файлообменник с шаблонизатором Twig, и может быть параллельно потихоньку решать задачки на SQL/JS/HTML/CSS чтобы подтянуть знания по ним. А дальше браться за фреймворки Yii2 и Symfony 2.
Советы и замечания.
Что-то у тебя с индексами перебор:
> PRIMARY KEY (`id`),
> UNIQUE KEY `id` (`id`),
Уникальный индекс не нужен так как PRIMARY KEY и так является уникальным индексом. Первичный ключ — это колонка которая однозначно идентифицирует запись и значения первичного ключа не могут повторяться.
> `code` int(16) NOT NULL,
Число в скобках для int это не максимальное число цифр в колонке. Это сколько места оставлять под число при выводе таблицы. int позволяет хранить число от -2 млрд до +2 млрд., а это не более 12 цифр. Чтобы было 16, тебе нужен bigint. Прочти в мануале, какие типы чисел существуют: http://phpclub.ru/mysql/doc/column-types.html
> ENGINE=MyISAM
Скидывал ли я ссылку на отличия MyISAM и InnoDB? Если кратко, MyISAM не поддерживает внешние ключи и транзакции, а они скорее всего понадобятся когда у тебя больше одной таблицы.
> generate_page_links
HTML-код все же лучше генерировать в шаблоне. Иначе получается каша. А в этой функции можно генерировать просто массив вида:
array(
подпись к кнопке => ссылка,
подпись к кнопке => ссылка,
....
);
Также, постраничную навигацию удобно делать через отдельный класс, примерно так (делать не обязательно, не хочешь, не делай, просто хочу показать, как это можно решить красивее с помощью ООП):
// Передаем общий шаблон ссылки, и дополнительно ссылку для первой станицы если она отличается по виду
$pager = new Pager('/students/page/{page}', '/students');
// передаем номер страницы и сколько всего страниц
$pager->setPage(3, 34);
// Передаем объект $pager в шаблон
....
// В шаблоне выводим пагинацию
<?php foreach ($pager->getLinks() as $text => $link): ?>
<a href="<?= html($link) ?>"><?= html($text) ?></a>
<?php endforeach ?>
> https://github.com/tokotun/matriculant/blob/master/app/functions.php#L27
В HTML коде вместо & надо писать & amp; так как & это спецсимвол для кодирования HTML-сущностей.
> https://github.com/tokotun/matriculant/blob/master/app/functions.php#L17
Чтобы вставить знак < надо писать & lt;
Я вижу, у тебя пробелы в знании HTML. Прочти-ка эти статьи:
http://htmlbook.ru/samhtml/tekst/spetssimvoly
http://ru.wikipedia.org/wiki/%D0%9C%D0%BD%D0%B5%D0%BC%D0%BE%D0%BD%D0%B8%D0%BA%D0%B8_%D0%B2_HTML
Чтобы вставить в HTML код символы < > & (эти 3 символа и их мнемоники надо выучить наизусть) надо использовать мнемоники. Также, можно использовать мнемоники если тебе надо вставить кавычку внутрь аттрибута: <a title="test " test" ...
> generate_sort_link
Эту функцию лучше переделать чтобы она генерировала только URL ссылки, а не тег A целиком. А заголовок таблицы со ссылками выводить в шаблоне например на основе массива с названиями колонок. Главная мысль, что надо стараться держать HTML код в шаблоне. Оттуда же можно и вызывать эти функции.
> https://github.com/tokotun/matriculant/blob/master/app/autoloader.php#L3
правильнее писать автолоадер так:
опредеяем путь к файлу
если (файл существует) то подключаем иначе ничего не делаем
Так как автолоадеров может быть несколько (например у библиотек бывают свои автолоадеры) и не должно возникать ошибки вроде «файл не найден».
Я вижу, у тебя есть повторяющийся в index.php и loin.php код, который подключает файлы, создает PDO и т.д. Удобно вынести этот код в отдельный файл, например app/boostrap.php и подключать только его (через require_once чтобы 2 раза не подключить).
> https://github.com/tokotun/matriculant/blob/master/index.php#L17
> $pdo = null;
А это зачем?
> https://github.com/tokotun/matriculant/blob/master/login.php#L55
> $name = htmlspecialchars($matriculant->name);
Это надо делать в шаблоне при выводе. Иначе трудно проверить, все ли ты заэкранировал или нет. Вообще, экранировать данные надо в том же месте где они применяются.
Также, не надо передавать 10 переменных. Передавай в шаблон только объект matriculant.
Также, надо в htmlspecialchars указывать флаг ENT_QUOTES иначе одиночная кавычка не экранируется и появляется риск XSS, можешь посмотреть в мануале.
> https://github.com/tokotun/matriculant/blob/master/app/Matriculant.php#L24
Модель не должна работать с POST данными. Надо переделать функцию чтобы она брала данные не из POST а из переданного массива (и переименовать ее). И разумеется, прежде чем брать $_POST['name'] надо проверить что этот элемент существует иначе получим ошибку.
> public function getName($name)
Это надо назвать setName а не getName
Еще. У тебя не очень удачно смешаны заполнение объекта данными из POST и проверка правильности данных (валидация). Лучше сделать 2 отдельных функции: одна загружает данные из массива в поля объекта, другая их проверяет и заполняет массив ошибок. Это делает функцию проверки более универсальной.
> public function notUniqueEmail()
Имя функции начинается с глагола: setNotUniqueEmailError
> https://github.com/tokotun/matriculant/blob/master/app/MatriculantMapper.php#L14
> if (isset($matriculant->id)) $statment->bindParam(':id', $matriculant->id);
Это не очень надежно, такие проверки делать. лучше передавать в функцию bindField дополнительный параметр, который говорит надо ли передавать id/code или нет. Кстати, кроме bindParam есть еще bindValue который позволяет передавать любые выражения.
Также, функция bindField явно не должна вызываться снаружи. Значит, она должна быть private/protected. Если ты не знаешь что такое private, прочти тут: http://php.net/manual/ru/language.oop5.visibility.php Вообще, старайся все что можно делать закрытым. Чем меньше public свойств и методов тем лучше код.
> https://github.com/tokotun/matriculant/blob/master/app/MatriculantMapper.php#L32
> $matriculant->code = mt_rand ( 0 , 2097151 );
Давай защиту сделаем понадежнее, сделаем чтобы там хотя бы цифр 15-16 было. Можно сгенерировать три 5-значных числа и склеить их в строку. Разумеется, генерация кода должна быть в отдельной функции.
> https://github.com/tokotun/matriculant/blob/master/app/MatriculantMapper.php#L95
> $total = $statment->rowCount( );
Вот это очень неправильно. Ты выбираешь очень много данных из базы, передаешь их в PHP, и ради чего? ТОлько чтобы посчитать их количество и выбросить. Не надо так. Используй функцию COUNT в MySQL которая умеет считать число строчек.
Если ты плохо знаешь MySQL могу посоветовать почитать мануалы по ссылкам и решить задачки отсюда: https://gist.github.com/codedokode/10539213 Там есть ссылка на учебник Пирамидина, он вполне неплохо объясняет разные виды запросов. Советую параллельно потихоньку читать его и решать задачки.
> https://github.com/tokotun/matriculant/blob/master/login.php#L27
> if (!$matriculantMapper->uniqueEmail($matriculant->email)){
При редактировании надо проверять email на уникальность исключая собственный email.
При редактировании надо сначала загрузить объект из базы, а потом перезаписывать его свойства на основе POST данных. Так надежнее, иначе какие-то данные могут потеряться. То есть алгоритм должен быть примерно такой:
-------------
при редактировании {
загрузить объект из БД
} иначе {
создать пустой объект
}
если форма отправлена {
обновить объект данными из POST
проверить на правильность;
если (ошибок нет) {
сохранить данные в БД;
сделать редирект и умереть;
}
}
вывести форму;
---------------
Соответвенно, я тебе советую сделать одну функцию проверки, например в M.Mapper, которой передается объект Matriculant и которая возвращает результат в виде true/false.
> https://github.com/tokotun/matriculant/blob/master/templates/profile.php#L17
Тут у тебя почему-то мужской пол всегда checked
> https://github.com/tokotun/matriculant/blob/master/templates/profile.php#L52
Закрывающие теги body/html лучше вынести в footer.php
А, там еще узявимоcть XSRF есть. Злоумышленник может создать страницу, поместить на нее невидимую заполненную форму, у которой action указывает на твой сайт, и сделать яваскрипт который при заходе отправляет форму. Заманив абитуриента на свою страницу злоумышленник может отредактировать его данные, например занизить ему результат ЕГЭ. Для борьбы с XSRF форму надо защитить каким-то кодом или токенов неизвестным злоумышленнику. Если не догадаешься сам как это сделать, попроси подсказку.
XSRF довольно серьезная уязвимость. С помощью нее можно отправлять любые формы от имени пользователя, например рассылать спам или делать переводы денег в платежной системе.
У тебя поля называются одинаково и перезапишут друг дуга. Используй поля-массивы с именем вроде lol[]
мануал
http://php.net/manual/ru/faq.html.php#faq.html.arrays
http://php.net/manual/ru/language.variables.external.php
PHP пофигу на флаг. Ошибка была в чем-то другом. Кстати, у тебя случайно не выключен вывод ошибок? Может там была ошибка а ты просто ее не видел?
В PHP по умолчанию выключено отображение ошибок в браузере, так как обычному пользователю сайта эта информация ни к чему. Но тебе, как программисту, надо видеть эти ошибки. Вот, как можно их просмотреть:
- ошибки сохраняются в лог ошибок. Можно открыть его и почитать. Если ты запускаешь код на локалхосте, у себя, то лог хранится в папке Апача (обычно она называется logs) и имеет название вроде error.log (в линуксе в папку /var/log/apache2 ). Если на хостинге — там либо есть файл error.log либо раздел в панели управления, где лог можно посмотреть
- также, ты можешь включить отображение ошибок. Открой файл php.ini, поставь там display_errors = On и error_reporting = E_ALL и перезапусти сервер. Теперь ошибки должны выводиться на экран.
Проверить, работает ли вывод ошибок, можно запустив скрипт содержающий обращение к несуществующей переменной вроде echo $sdgasdad; и проверив, выведется ошибка или нет. Если все верно, то должна вывестись.
Может быть по IP сервера в Германии с которого ты делал запрос? Тогда остается только делать азпрос залогиненным.
>Кстати, у тебя случайно не выключен вывод ошибок?
Работает да так, чтобы на нотисы ругаться. Прописано в /etc/apach2/sites-available/default.conf что-то типа такого
ErrorLog /var/www/log/error.log
CustomLog /var/www/log/access.log combined
# Custom php settings
php_flag log_errors on
php_flag display_errors on
php_value error_reporting 6143
И сейчас вот нарочно убрал ; и получил ошибку, а тогда был просто белый экран. Мистика, в общем. Ну да фиг с ней. Может хостер баловался чем-то.
Кстати, насчет полностью случайно сгенерированного кода:
Я сначала пытался сделать вот так:
$cypher = "abcdefghiklmnopqrstuvwxyz";
$length = count($cypher);
$string = mb_substr($cypher, mt_rand(0, $length-1), mt_rand(0, $length-1));
И хешировал эту строку вместо введенного эмейла. Но код одинаковый получался. Почему так?
Дату создания естественно нужно сохранять в бд. Текущее время возвращает time().
да, time() возвращает временную метку в секундах прошедших с 70го года. Дату создания тоже храни в этом формате. Вычитаешь из первого второе, 7 дней переводишь в секунды и сравниваешь, вроде так.
Добавь пару var_dump и увидишь сам: http://ideone.com/sHVftz
Алсо, мануал: https://php.net/manual/ru/function.count.php
> count — Подсчитывает количество элементов массива или что-то в объекте
> Возвращает количество элементов в array_or_countable. Если параметр не является массивом или объектом, реализующим интерфейс Countable, будет возвращена 1. За одним исключением: если array_or_countable - NULL, то будет возвращён 0
А ты передаешь строку вместо массива.
Урок о работе с датой/временем: https://gist.github.com/codedokode/10539805
>>425302
По 1С я бы советовал для начала посмотреть на официальном сайте. Вообще, насколько я знаю, у них книги и курсы то ли платные то ли даются при покупке их продуктов, не уверен.
Для тех кто не знает, поясню что 1С это что-то вроде фреймворка, объединенного с файловой базой данных, графическим интерфейсом и средой разработки (IDE). Язык 1С напоминает русифицированный Visual Basic. Также, есть русифицированный аналог SQL для работы с их встроенной базой данных. Чистым 1С никто не пользуется, а обычно покупают написанную под нее программу (которая наызвается конфигуация). Все вещи, для которых есть общепринятые названия, в 1С называются по-своему. Например, та же «конфигурация», которая на самом деле является программой. Есть стандатные конфигуации типа программы учета товаров на складе или программы учета товаров в магазине, есть нестандатные котоые делают сторонние разработчики, есть перепиленные стандартные.
Надо понимать что в 1С есть разные уровни обучения:
- обучение работе с 1С и/или стандартными конфигуациями как пользователь , изучение всяких бухгалтерских терминов
- обучение работе как разработчик, начиная с доиливания стандатных конфигуаций и заканчивая написанием каких-то
своих модеулей.
Потому насчет
> думаю там не особо сложно будет?
я не знаю.
Дату создания надо хранить в DATETIME/TIMESTAMP так как они специально для того придуманы, а не интом. Не надо помойку в базе создавать.
Алсо, мне кажется, у вас тред тонет.
Поздравьте меня, я снова запрострировал. Прострация начинается с того как у меня начинается ступор в очевидных вещах. Ты не будешь против, если я буду спрашивать в треде о них? Вот например:
Здесь >>420607>>420831, я не смог придумать проверку на тип. В итоге, через месяц, я решил просто отказаться от этой проверки в методе формы и добавил проверку в файле с отправкой формы.
https://github.com/someApprentice/ThumbnailService/blob/master/Classes/Form.php
https://github.com/someApprentice/ThumbnailService/blob/master/upload.php#L30-L32
> Ты не будешь против, если я буду спрашивать в треде о них?
Этот тред специально для этого и создан. Задавай тут любые вопросы.
> я не смог придумать проверку на тип. В итоге, через месяц, я решил просто отказаться от этой проверки в методе формы и добавил проверку в файле с отправкой формы.
Это действительно непросто догадаться самому. Проверки стоит сделать 2:
- проверка по расширению, что расширение (без учета регистра букв) находится в списке разрешенных. Для JPEG может быть 2 расширения, .jpeg или .jpg
- проверка по содержимому, что файл является картинкой в одном из разрешенных форматов. Для этого удобно использовать http://php.net/manual/ru/function.getimagesize.php — она умеет определять настоящий формат картинки (ну и размеры заодно) по содержимому.
И еще один совет:
> https://github.com/someApprentice/ThumbnailService/blob/master/upload.php#L48
В имени файла могут быть спецсимволы, потому лучше обработать его функцией urlencode которая заменит их процентным кодированием (которое используется в параметрах в URL): https://ru.wikipedia.org/wiki/URL#.D0.9A.D0.BE.D0.B4.D0.B8.D1.80.D0.BE.D0.B2.D0.B0.D0.BD.D0.B8.D0.B5_URL
Рейт ми. Насиловал мозг час или два, решение оказалось проще раза в три, чем я думал.
Думаю, что ждет, если будешь стараться. Насчет перспектив, лучше всего открыть сайты вроде hh.ru или http://brainstorage.me/ или odesk и посмотреть самому.
ОП работает, но сколько получает никому не расскажет.
По коду программы: лучше постить не картинкой, а ссылкой на ideone. Ты сделал проверку на случай ничьи?
Ох, как у тебя все в голове смешалось.
> хочется красивых рестфул–ссылочек,
Ты не путаешь REST и ЧПУ? «рестфул»-ссылочки обычно в АПИ используются.
> Хочу писать на фреймворке, который будет выполнять роль рестфул–клиента — фреймворк в данном случае не оверкил?
Опять же, ты не путаешь? Клиент это тот кто делает запрос, а тот кто отдает страницу это сервер.
Если тебе база не нужна, не проще ли просто сверстать страницы статически и вынести отдельно повторяющиеся части вроде шапки/подвала?
> фреймворк в данном случае не оверкил?
Смотря какой. Скорее всего нет.
Не сделал, сейчас сделал. А вот допустим овладею я на нормальном таком уровне РНР, что дальше? У меня мечта детская - роботов делать, радиотехникой занимаюсь, вот решил еще и погроммированием. Не подскажешь на этот счет ничего?
Считает верно, хотя в начале у тебя по моему кусок от старого решения остался.
Также, вместо 2 переменных $earningsTotal и $depositBalance можно использовать одну.
Роботов не на PHP программируют. Там обычно микроконтроллер и Си/Си++. PHP все же больше для сайтов и веб-приложений.
С другой стороны, после изучения PHP тебе другие языки включая Си учить будет куда как легче.
Я немного знаю Си и Си++ так что если захочешь что-то спросить или овеить решение задачи, можешь заходить в наш тред.
Насчет роботов, я думаю это вещь очень перспективная и в будущем они будут так же распростанены как сейчас комьютеры или смартфоны. Но чтобы сделать хорошего робота, надо много в чем разбираться, начиная с микроконтроллеов и заканчивая алгоитмами ориентации в пространстве.
[code]
$data1 = x;
foreach ($array1 as $data2 => $data3) {
if ($data3 > data1) {
$array2 = array($data3 > $data1);
}
}[/code]
Вижу, чего не хватает, но как оформить по-нормальному?
Да, я после попытки самоизнасилования через перезапись двух переменных по очереди просто все стер и взял решение предыдущей задачи, а потом модифицировал под новые нужды. Или это неправильно?
Ассемблер используют только на самых простых микроконтроллерах, где очень мало памяти (и где ничего серьезного не сделаешь). А на контроллерах помощнее на Си писать удобнее будет (+ ты получаешь доступ к множеству готовых библиотек). Плюс, есть тот же распберри в котором по моему то ли 128 то ли 256 Мб, запускается Линукс и можно хоть на Питоне писать и куча аналогичных китайских нонейм плат.
Если что, я под микроконтроллеры только в универе код писал, опыта у меня с ними особого нет.
>>425531
Можно не не как у тебя. Сначала создаешь пустой массив
$a = array( );
Затем добавляешь данные либо через
$a[$x] = $y;
либо через
$a[] = $y;
Тогда индексы автоматически начиная с нуля проставятся.
Также есть много функций для работы с массивами.
Ну и рекомендую мой урок в учебнике по массивам почитать если не читал. И мануал php по массивам.
А у тебя куча ошибок
> $data1 = x;
Непонятно что такое x
> $array2 = array($data3 > $data1);
Ты наверно хотел написать => а не >
Ассемблер используют только на самых простых микроконтроллерах, где очень мало памяти (и где ничего серьезного не сделаешь). А на контроллерах помощнее на Си писать удобнее будет (+ ты получаешь доступ к множеству готовых библиотек). Плюс, есть тот же распберри в котором по моему то ли 128 то ли 256 Мб, запускается Линукс и можно хоть на Питоне писать и куча аналогичных китайских нонейм плат.
Если что, я под микроконтроллеры только в универе код писал, опыта у меня с ними особого нет.
>>425531
Можно не не как у тебя. Сначала создаешь пустой массив
$a = array( );
Затем добавляешь данные либо через
$a[$x] = $y;
либо через
$a[] = $y;
Тогда индексы автоматически начиная с нуля проставятся.
Также есть много функций для работы с массивами.
Ну и рекомендую мой урок в учебнике по массивам почитать если не читал. И мануал php по массивам.
А у тебя куча ошибок
> $data1 = x;
Непонятно что такое x
> $array2 = array($data3 > $data1);
Ты наверно хотел написать => а не >
Это не то чтобы непраивльно, просто можно написать лучше и короче с одной переменной.
Так например:
$money = $money * $percent;
Спасибо. Нет, не путаю, я криво выразился просто — хотел сказать, что на сайте будут данные, забираемые из апи, поэтому я потом и назвал его рестфул–клиентом.
>Если тебе база не нужна, не проще ли просто сверстать страницы статически и вынести отдельно повторяющиеся части вроде шапки/подвала?
См. выше.
>Смотря какой. Скорее всего нет.
Думал о Ларавеле.
Тогда феймворк не помешает
> Думал о Ларавеле.
Не разбиаюсь в нем потому ничего не могу сказать.
ОП, зачем ты это делаешь? Мне правда интересно. Такое-то волонтерство. Ты сослан в сибирь, или просто агентуру вербуешь?
Доброчановцы они такие, самоутверждаются за счет помощи другим. "Я совершил хороший поступок, я хороший человек" — такова их мантра.
Они получают позитивные эмоции, когда слышат благодарность, достигают душевного равновесия из альтруизма.
А чем еще им жить? Любви к себе у них особой нет, они не могут жить эгоизмом, прославляя имя свое.
Да и просто скучно, наверное.
Мне как питурду они враждебны, потому что я не признаю деления людей на плохих и хороших, поэтому автоматически попадаю в отряд плохих.
Но определенный респект все-таки чувствую.
Во всяком случае, поиметь с них профит можно и нужно.
Хз, я так называю всех, кто размахивает моралью и "добром" как флагом.
Это не привязка к конкретной борде, а alignment.
Тред утонул кстати, он тебя не слышит. Перекатывайся в новый.
http://codepad.viper-7.com/E5NrKq
Это копия, сохраненная 6 февраля 2015 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.