Это копия, сохраненная 22 февраля 2015 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
Это тред для начинающих. Не написал за свою жизнь ни одной программы? Ты наш человек.
Требуемые знания: умение читать. Устанавливать пока что ничего не требуется, разве что редактор кода вроде Sublime Text 3, Notepad++, Netbeans PHP или PhpStorm (необязательно).
Предыдущий тред был тут: >>419972
У нас есть уроки по основам 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 пробела)
Не тратим время и силы на выяснения и заоминания где надо что ставить. Не имеем проблем с отображением кода нигде. В общем, пишем код., а не занимаемся аутизмом.
Приглашаю всех ее опробовать. Она может иногда ошибаться, потому пишите в тред или мне на почту — мы ее исправим. Ну и постите ссылки на решения тоже.
Да я снова просто каким-то дебилизмом занимаюсь. После часа ебли с абсолютно, как оказалось, не нужными мне массивами я решил задачу в две строки.
http://ideone.com/G8Zrss
С чего начать? О_о
> так что хотелось бы спросить помощи тут по поводу того, что именно задрочить и по каким материалам для лучшей отдачи.
В идеале лучше все. У нас есть задачи на HTML, CSS, JS, SQL, PHP но те что на PHP с фреймворками довольно трудоемкие, не знаю, хватит ли у тебя времени их делать.
> Думал о том, что надо освоить верстку до самого пиздеца, а именно всякую адаптивную хуйню и что там дальше еще, если есть, где почитать про нее?
Вся адативность сводится к использованию не фиксированной ширины и media queries, так что просто погугли эти темы. Если что, у нас есть неплохие задачки на HTML/CSS где тоже часто надо использовать гибкую верстку: https://gist.github.com/codedokode/58ebc90bd006baf4b35c - если тебе интересны эти задачи, можешь порешать
> Как я понимаю нынче жквери нахер не нужен и все используют какую-то хипстерскую поеботу вроде ноды, ангулара, еще хуй знает чего.
Нет, ты все путаешь. jQuery используется как и раньше, как DOM библиотека, Node JS это платформа для написания серверного кода, Angular для разработки Single Page Apps.
> Где про них почитать
Я читал официальную документацию. Нормально написано, правда на английском. А так, я не знаю, есть ли учебники на ту тему на русском. Наверно нету.
Если что у нас есть задания на JS /jQuery, хотя не знаю. будут ли они тебе интересны: https://gist.github.com/codedokode/ce30e7a036f18f416ae0
Для первых 8 есть проверялка: http://dkab.github.io/jasmine-tests/
> какие фреймворки/цмски сейчас дохуя востребованы
Yii2, Symfony 2
Из CMS Wordpress наверно,в России еще Битикс часто используют.
>В идеале лучше все.
Ну это да. Ванила жс и жквери не особо нужны тогда, там все просто. Замыкания, колбеки не особо сложны. ооп ебнутый разве что, но думаю тоже справлюсь, если потребуется.
>на PHP с фреймворками
А где у вас эти задачи можно носом ткнуть? Посмотрим.
>Вся адативность сводится
Погуглю. Задачи посмотрю дома.
>Нет, ты все путаешь.
Ок. В таком случае остается вопрос, в целом ноду и ангулар маст хев учить?
>Yii2, Symfony 2
Спасибо.
>Из CMS Wordpress наверно
Часто слышал, что еще джумла популярна, так ли это?
А тебе удобно на ideone c смартфона будет решать задания? Если удобно то ничего устанавливать не надо. Бери и начинай решать.
Скорее всего надо будет установить клавиатуру с расширенным набором символов.
Если нет (на ideone удобно писать только маленькие программки) то вроде под Андроид есть приложеня в которых можно писать и запускать код на PHP.
Вот есть PHP for Android: http://phpforandroid.net/doku.php (там придется повозиться с установкой). Она позволяет запускать скрипты на PHP в консоли без сервера и ее хватит чтобы пройти наш учебник (для дальнейших заданий понадобится сервер).
Есть прогаммы вроде такой https://play.google.com/store/apps/details?id=ru.kslabs.ksweb&hl=ru но она платная.
Есть такая https://play.google.com/store/apps/details?id=org.kidinov.awd тоже частично платная.
Есть бесплатные вроде такой: https://play.google.com/store/apps/details?id=com.esminis.server.php или https://play.google.com/store/apps/details?id=com.phpmobile
В общем, работать с php вполне реально, придется только повозиться с подбором приложений.
Так как я этими приложениями не пользовался, то могу посоветовать ввести php в маркете и изучить самому, если есть какие-то сомнения спрашивай.
> А где у вас эти задачи можно носом ткнуть? Посмотрим.
Ну вот например задачка на файлообменник на микрофреймворке Slim: https://gist.github.com/codedokode/9424217
Вот сложная длинная задача на сайт для тестирования TestHub на Yii: https://gist.github.com/codedokode/8733007
> в целом ноду и ангулар маст хев учить?
Ну не знаю, если хочешь на ноде северную часть делать то да, если нет то нет. Ангулар стоит посмотреть.
> джумла популярна
Джумла то болото. Насчет популярности точно не знаю, но по моему давно уже не поулярна.
Почитал задачки. Не вижу ничего невыполнимого, хоть и не шибко быстро оно. Может сделаю в качестве ознакомления с slim и yii, лучше всего ведь на практике учиться всегда.
У меня появляются в каждой задаче какие-то смутные очертания, выглядящие вполне логично и правильно, которые на деле оказываются абсолютно нерабочей сранью, после чего загорается лампочка над головой и приходит решение легче в тысячу раз, это нормально?
Кстати, еще вопрос. Рекомендуется использовать шаблонизатор twig. Я с ним не знаком нихуя, у меня на работе используется смарти. Твиг лучше?
https://github.com/Si0n/CatNmouse
Кроме документации, может есть хорошие статьи для новичков на хабре, например?
(На гугол не посылайте, там слишком долго нужно ковыряться в шлаке, пока найдешь то что ищешь; я сюда пишу в надежде, что кто-то недавно натыкался на годноту и поднесет на блюдечке.)
Кстати, насколько сильно отличается первый от второго? Может, тогда сразу учить второй, на первый даже не смотреть, что скажете?
Вполне.
same shit.
Так и должно быть, когда учишься.
Лично мне очень понравилось учиться веб-разработке, пхп в частности.
Убивает только отсутствие четкой и легкодоступной для умственно отсталых программы обучения.
Информации в интернете море, не спорю, но ясность изложения иногда хромает. Большинство уроков и статей написаны либо гиками для гиков, где они обсасывают какую-то незначительную (с нубской точки зрения) мелочь, либо людьми непрофессиональными. Яркий пример — видео на ютубе: "ну вот короче, это, нажимаем сюда, эээ... тут прописываем вот такую строчку, эээ... а сюда копируем вот эти файлы, хз зачем, но так надо... Так, теперь попробуем запустить... Хелло ворлд работает! Всем спасибо, подписывайтесь на мой канал, ставьте лайки :)".
Приходится перечитывать десятки статей, психовать, если непонятно, пробовать повторить, снова искать новый материал.
Это очень сильно заморачивает, честолюбцев доводит до припадков бешенства, неуверенных в себе вообще демотивирует заниматься дальше.
Из всего материала по пхп в рунете (в англицком не силен) скажу, что имхо годными можно признать только курсы Борисова из "Специалиста" (но там голая теория, огромное количество материала в сжатом виде, усвоить все сразу сложно, хотя объясняет недурно), а также уроки господина опа данного треда (тут в основном акцент на задачах, которые нужно решать самостоятельно, плюс только в том, что оп охотно помогает каждому лично).
Я бы счел идеальным курс, программа которого была бы разбита по схеме MVC ТПЗ: теория, примеры (из реальной практики, а не сферические кони!), и наконец хитрые задачи для самостоятельного решения.
Первое есть в избытке и у специалиста. У опа есть прекрасный задачник.
А вот демо-примеров лично мне не хватает.
Ну вот не могу я послушав трехчасовой бубнежь лекции или прочитав до покраснения глаз 20-страничную статью сразу сесть и написать готовое приложение. Да, вроде все понятно, когда слушаешь или читаешь. Потом садишься делать, и впадаешь в ступор: а чё, с чего начинать-то, что писать? У меня голова забита всякими кудрявыми формулировками и терминами, а примера кода я в глаза не видел.
Хотеть уроки в стиле "show me!".
inb4: "бугурт макаки)))00", но ей богу, так жить нельзя
same shit.
Так и должно быть, когда учишься.
Лично мне очень понравилось учиться веб-разработке, пхп в частности.
Убивает только отсутствие четкой и легкодоступной для умственно отсталых программы обучения.
Информации в интернете море, не спорю, но ясность изложения иногда хромает. Большинство уроков и статей написаны либо гиками для гиков, где они обсасывают какую-то незначительную (с нубской точки зрения) мелочь, либо людьми непрофессиональными. Яркий пример — видео на ютубе: "ну вот короче, это, нажимаем сюда, эээ... тут прописываем вот такую строчку, эээ... а сюда копируем вот эти файлы, хз зачем, но так надо... Так, теперь попробуем запустить... Хелло ворлд работает! Всем спасибо, подписывайтесь на мой канал, ставьте лайки :)".
Приходится перечитывать десятки статей, психовать, если непонятно, пробовать повторить, снова искать новый материал.
Это очень сильно заморачивает, честолюбцев доводит до припадков бешенства, неуверенных в себе вообще демотивирует заниматься дальше.
Из всего материала по пхп в рунете (в англицком не силен) скажу, что имхо годными можно признать только курсы Борисова из "Специалиста" (но там голая теория, огромное количество материала в сжатом виде, усвоить все сразу сложно, хотя объясняет недурно), а также уроки господина опа данного треда (тут в основном акцент на задачах, которые нужно решать самостоятельно, плюс только в том, что оп охотно помогает каждому лично).
Я бы счел идеальным курс, программа которого была бы разбита по схеме MVC ТПЗ: теория, примеры (из реальной практики, а не сферические кони!), и наконец хитрые задачи для самостоятельного решения.
Первое есть в избытке и у специалиста. У опа есть прекрасный задачник.
А вот демо-примеров лично мне не хватает.
Ну вот не могу я послушав трехчасовой бубнежь лекции или прочитав до покраснения глаз 20-страничную статью сразу сесть и написать готовое приложение. Да, вроде все понятно, когда слушаешь или читаешь. Потом садишься делать, и впадаешь в ступор: а чё, с чего начинать-то, что писать? У меня голова забита всякими кудрявыми формулировками и терминами, а примера кода я в глаза не видел.
Хотеть уроки в стиле "show me!".
inb4: "бугурт макаки)))00", но ей богу, так жить нельзя
>Так и должно быть, когда учишься.
Так даже когда уже работаешь во всю бывает. Ситуации разные, иногда сидишь, тупишь и высераешь эталонный говнокод, чтобы потом его переписать в что-то нормальное.
Насчет видеуроков не соглашусь. Как там по поводу пхп не знаю, а вот другие языки (кресты, шарп, джава) не обделены годными уроками. По сути можно их посмотреть нюфагу, самое главное выучат, чтоб потом спокойно мелочи у любого языка обсасывать. Наверняка и по пхп что-то такое тоже есть.
спасибо, друг, вот тебе поней
Хороший обзор получился.
Насчет примеров из практики, в моем учебнике мы изучаем самые основы языка, и на таком уровне смотреть «практический» код довольно сложно, так как там будет много непонятных конструкций. Также, на этом этапе мы еще не изучили как работает веб-сервер, браузер и потому сложно давать примеры которрые их используют.
Потому, увы, в учебнике сделать такое вряд ли получится. Там задачки на закрепление понимания того, как работают циклы или массивы.
А вот после учебника у нас идут гораздо более практические задачи: сделать сайт для регистрации абитуиентов или файлообменник. К ним, правда, не прилагается уроков и теории так как я их еще не написал (но вот в них уже примеры из практики давать было бы можно).
Но я готов ответить на какой-то конкетный вопрос и может быть найти ссылочку с информацией.
> Яркий пример — видео на ютубе: "ну вот короче, это, нажимаем сюда, эээ... тут прописываем вот такую строчку,
мне кажется такое видео годится только для того чтобы посмотреть как работает прогаммист, знания ты из него вряд ли получишь.
> "Специалиста"
я смотрел мельком пару видео на ютубе, не знаю, те или не те, мне показалось что там просто пересказывают официальный мануал.
> Ну вот не могу я послушав трехчасовой бубнежь лекции или прочитав до покраснения глаз 20-страничную статью сразу сесть и написать готовое приложение.
Ну а ты попробуй взяться за задачку по абитуриентов, помучаешься и в итоге разбеешься.
Говорят что похапе хорош для веб, но этот миф мы сейчас развенчаем.
Итак, задачи из веб можно разделить на 4 категории.
1. Маленькие и средние сайты/сервисы:
Тут однозначно лучший язык руби и веб-фреймворк всех времён и народов - руби он рейлз. Никакие его пхп копии не дают даже 30% возможностей оригинала. В рельсах 95% вашего фронтенда и бекенда может быть сгенерена автоматически, нужно свернуть лишь пару контроллеров. Единственный php фреймворк который претендует на нечто похожее - это Symfony, но он менее удобен, за счёт общей невыразительности php как языка. Там где в рельсах всё будет сгенерено за счёт рубяшного метапрограммирования, в Symfony вместо кода вы будете писать конфиги, при чём в тех же объёмах. Во-вторых в рельсах сразу всё заточено под REST архитектуру, полное и правильное использование HTTP протокола, сотни удобных гемов, любой проект можно собрать как конструктор лего, множество гайдлайнов, адекватное комьюнити, а не освоившие за 24 часа курс Попова дауны. Короче, RoR однозначно лучший выбор для этого пункта.
2. Небольшие web-realtime серверы, аля вебсокет-чятик на 50 человек, небольшие бекенды браузерных игр и т.д. Тут однозначно node.js. Работа руками сводится к минимуму за счёт множества библиотек, ставишь сокет.ио, экспресс, ещё пару либ и останется только отмапать ивенты по колбекам. В пхп это всё в лучшем случае закончилось бы взятием кривого и тормозного phpDaemon с кучей ручного допила, либо полным лоу-левел велосипедированием. Эта область однозначно за популярным нынче ноджс.
3. Большие веб-энтерпрайз проекты. Очевидная Java. Язык и платформа создавались для автоматизации процессов корпораций, банков и за 20 лет имеют кучу наработок. Мощные стандарты, всякие промышленные паттерны, Spring, шустрая JVM с тысячами библиотек на все случаи жизни. Если есть вкус, не хочется жрать AbstractProxySingltonFactoryMemoryBeanGovno - то есть достойная замена - Scala с современным Play Framework 2, программируя на которой можно раскрыть весь свой потенциал, так как язык очень выразителен. На языках с динамической типизацией вести крупные тырпрайз проекты - самоубийство, так что никакой пыхи тут в помине быть не может.
4. Хайлод. Очевидный Erlang или C++, в зависимости от задач. Пусть вас не смущают кукареки, вооон фейсбук такой то хайлод, а на пхп написан. Во-первых там уже давно не совсем пхп, а нечто своё, во-вторых оно транслируется в цпп-код, в третих пхп - только морда, за кулисами там работают C++ с Erlang. Насчёт цпп всё ясно, нулевой оверхед, производительный нативный код, множество либ и фреймворков. Насчёт Erlang тоже - линейное масштабирование на любое кол-во узлов, искоробочная распределённость, концепция отказоустойчивости, конкурентные примитивы.
5. В общем остаётся ещё одна веб область:
Поддержка ржавых уёбищных веб магазинов, визиток, сервисов, порталов, написанных в 90е в веб 1.0 стиле кривыми руками бывших перлистов, допиливание CMS-based сайтов всяких быдлокомпаний. Тут похапе однозначная звезда. Но оно вам надо?
Говорят что похапе хорош для веб, но этот миф мы сейчас развенчаем.
Итак, задачи из веб можно разделить на 4 категории.
1. Маленькие и средние сайты/сервисы:
Тут однозначно лучший язык руби и веб-фреймворк всех времён и народов - руби он рейлз. Никакие его пхп копии не дают даже 30% возможностей оригинала. В рельсах 95% вашего фронтенда и бекенда может быть сгенерена автоматически, нужно свернуть лишь пару контроллеров. Единственный php фреймворк который претендует на нечто похожее - это Symfony, но он менее удобен, за счёт общей невыразительности php как языка. Там где в рельсах всё будет сгенерено за счёт рубяшного метапрограммирования, в Symfony вместо кода вы будете писать конфиги, при чём в тех же объёмах. Во-вторых в рельсах сразу всё заточено под REST архитектуру, полное и правильное использование HTTP протокола, сотни удобных гемов, любой проект можно собрать как конструктор лего, множество гайдлайнов, адекватное комьюнити, а не освоившие за 24 часа курс Попова дауны. Короче, RoR однозначно лучший выбор для этого пункта.
2. Небольшие web-realtime серверы, аля вебсокет-чятик на 50 человек, небольшие бекенды браузерных игр и т.д. Тут однозначно node.js. Работа руками сводится к минимуму за счёт множества библиотек, ставишь сокет.ио, экспресс, ещё пару либ и останется только отмапать ивенты по колбекам. В пхп это всё в лучшем случае закончилось бы взятием кривого и тормозного phpDaemon с кучей ручного допила, либо полным лоу-левел велосипедированием. Эта область однозначно за популярным нынче ноджс.
3. Большие веб-энтерпрайз проекты. Очевидная Java. Язык и платформа создавались для автоматизации процессов корпораций, банков и за 20 лет имеют кучу наработок. Мощные стандарты, всякие промышленные паттерны, Spring, шустрая JVM с тысячами библиотек на все случаи жизни. Если есть вкус, не хочется жрать AbstractProxySingltonFactoryMemoryBeanGovno - то есть достойная замена - Scala с современным Play Framework 2, программируя на которой можно раскрыть весь свой потенциал, так как язык очень выразителен. На языках с динамической типизацией вести крупные тырпрайз проекты - самоубийство, так что никакой пыхи тут в помине быть не может.
4. Хайлод. Очевидный Erlang или C++, в зависимости от задач. Пусть вас не смущают кукареки, вооон фейсбук такой то хайлод, а на пхп написан. Во-первых там уже давно не совсем пхп, а нечто своё, во-вторых оно транслируется в цпп-код, в третих пхп - только морда, за кулисами там работают C++ с Erlang. Насчёт цпп всё ясно, нулевой оверхед, производительный нативный код, множество либ и фреймворков. Насчёт Erlang тоже - линейное масштабирование на любое кол-во узлов, искоробочная распределённость, концепция отказоустойчивости, конкурентные примитивы.
5. В общем остаётся ещё одна веб область:
Поддержка ржавых уёбищных веб магазинов, визиток, сервисов, порталов, написанных в 90е в веб 1.0 стиле кривыми руками бывших перлистов, допиливание CMS-based сайтов всяких быдлокомпаний. Тут похапе однозначная звезда. Но оно вам надо?
Да, руби и правда хорош. Собираюсь его выучить после того, как овладею в должной степени пхп.
Что сказать-то хотел, лалка?
В этом треде одни нубы, им на подобные нюансы насрать.
Из профессионалов только оп и еще пара зануд, но они не будут участвовать в холиваре, а если и отзовутся на вброс, то крайне невкусно, неэмоционально.
В общем, шел бы ты отсюда с этой пастой из нашей песочницы.
>Что сказать-то хотел, лалка?
Ну как бы предупредить пацанов)) Мож одумается кто и сразу начнёт с норм языка.
>Собираюсь его выучить после того, как овладею в должной степени пхп.
Нахуя, если можно сразу учить руби?
Проверял несколько раз. Лол, спасибо.
Можно с таким же успехом и даже с такой же точно зарплатой устроиться Symfony девелопером.
Когда то кажется в этом треде всплывала книга где очень много уделяется внимание практике и подробно прогоняются различные практические решения (вроде авторизации, написания блога, интрент-магазина и т.д.), кажется там целая серия таких книг от определённого издательства по разным языкам программирования, может кто то подсказать название?
Пока писал понял как сделать, но все же дождусь твоего комментария.
Есть множество готовых CMS для интернет магазинов. Можно посмотеть как в них сделано. Но зачем писать свою корзину когда можно взять ту готовую CMS?
Вот список CMS: OpenCart, PrestaShop или Magento SimplaCMS, osCommerce, PrestaShop, Joomla! Virtuemart Webasyst Shop-script
И еще не могу понять, как вообще работает php на сервере? Что он делает? Ведь в генерируемых страницах, которые отдаются браузеру- нет ни строчки кода php.
Простите за нубский вопрос, просто нигде не могу найти внятого объяснения.
Вопрос не нубский, а очень хороший. Тред как раз создан для таких вопросов.
Насчет отдачи сервером HTML кода, есть 2 вида сайтов: статические (на чистом HTML) и динамические (где HTML генерируется размещенной на сервере программой).
В статическом сайте вебмастер вручную или в редакторе создает HTML файлы и загружает их на сервер (по FTP, SFTP или какими-то своими скриптами). Соответственно при заходе пользователя сервер просто отдает ему в браузер файлы с диска. Например при заходе на страницу http://example.com/1.html отдается файл 1.html
Изменить информацию на статическом сайте может только сам вебмастер, отредактировав HTML файлы и выгузив их на сервер.
В случае с динамическими сайтами HTML файлов нет. HTML код динамически генерируется программой при обращении к сайту из браузера. Программа может быть написана на разных языках, например на PHP (или Питоне, Руби, Java, Node.JS, C#, Go и так далее).
В разных языках используются разные механизмы передачи данных из программы в браузер. В PHP все просто: все что выведет программа будет передано в браузер. То есть если ты сделаешь и загрузишь на сервер файл 1.php c таким кодом:
<?php
echo "<h1>Hello!</h1>\n";
То при обращении по адресу http://example.com/1.php этот скрипт запустится и выведенный им код будет отдан в браузер где отобразится в виде написанного большими буквами слова «Hello!»
(я надеюсь ты знаком хотя бы с основами HTML, если нет то h1 в угловых скобочках обозначает что это заголовок первого уровня, который выводится большими буквами).
Выводить HTMl код можно и без echo за счет того что PHP выводит без изменений все, что написано не внутри тегов <?php ... ?>. Вот пример другого файла 2.php выводящего чему равно 2 + 2:
2 + 2 = <?php echo 2 + 2 ?>!
PHP сначала выведет «2 + 2 =», затем выполнит код внутри маркеров <?php ... ?> (то есть цифру 4) и затем выведет воскл. знак.
Подробнее в мануале: http://php.net/manual/ru/language.basic-syntax.phpmode.php
http://php.net/manual/ru/tutorial.php
Разумеется, это самые простые примеры. В более сложных ситуациях код лежит не в одном файле, а в нескольких, отдельно логика, отдельно html код.
То есть принцип такой:
- пользователь вводит адрес сайта или переходит по ссылке
- браузер отправляет запрос к серверу чтобы получить html код страницы
- на сервере запускается твой php скрипт
- то что он выводит отправляется назад в браузер и тот воспринимает это как HTML код который надо отобразить на странице
Отвечая на твои вопросы
> каким образом генерируются html и скармливается браузеру.
Выполняется php скрипт и то, что он выводит, отправляется в браузер.
> как вообще работает php на сервере?
Так же как и в любом другом варианте: он выполняет записанные в скрипте команды. Скрипт пишет и загружает на сервер программист, то есть ты.
> Ведь в генерируемых страницах, которые отдаются браузеру- нет ни строчки кода php.
Так и должно быть. Браузер все равно не понимает язык PHP, он понимает только HTML.
Сам PHP файл не отдается в браузер. Он выполняется на сервере, а то что он выводит через echo или другим способом, отдается в браузер.
> Простите за нубский вопрос
Это хороший вопрос и хорошо что ты пытаешься разобраться в том как все работает. Если у тебя есть еще какие-то вопросы или что-то непонятно, задавай, объясним.
Вопрос не нубский, а очень хороший. Тред как раз создан для таких вопросов.
Насчет отдачи сервером HTML кода, есть 2 вида сайтов: статические (на чистом HTML) и динамические (где HTML генерируется размещенной на сервере программой).
В статическом сайте вебмастер вручную или в редакторе создает HTML файлы и загружает их на сервер (по FTP, SFTP или какими-то своими скриптами). Соответственно при заходе пользователя сервер просто отдает ему в браузер файлы с диска. Например при заходе на страницу http://example.com/1.html отдается файл 1.html
Изменить информацию на статическом сайте может только сам вебмастер, отредактировав HTML файлы и выгузив их на сервер.
В случае с динамическими сайтами HTML файлов нет. HTML код динамически генерируется программой при обращении к сайту из браузера. Программа может быть написана на разных языках, например на PHP (или Питоне, Руби, Java, Node.JS, C#, Go и так далее).
В разных языках используются разные механизмы передачи данных из программы в браузер. В PHP все просто: все что выведет программа будет передано в браузер. То есть если ты сделаешь и загрузишь на сервер файл 1.php c таким кодом:
<?php
echo "<h1>Hello!</h1>\n";
То при обращении по адресу http://example.com/1.php этот скрипт запустится и выведенный им код будет отдан в браузер где отобразится в виде написанного большими буквами слова «Hello!»
(я надеюсь ты знаком хотя бы с основами HTML, если нет то h1 в угловых скобочках обозначает что это заголовок первого уровня, который выводится большими буквами).
Выводить HTMl код можно и без echo за счет того что PHP выводит без изменений все, что написано не внутри тегов <?php ... ?>. Вот пример другого файла 2.php выводящего чему равно 2 + 2:
2 + 2 = <?php echo 2 + 2 ?>!
PHP сначала выведет «2 + 2 =», затем выполнит код внутри маркеров <?php ... ?> (то есть цифру 4) и затем выведет воскл. знак.
Подробнее в мануале: http://php.net/manual/ru/language.basic-syntax.phpmode.php
http://php.net/manual/ru/tutorial.php
Разумеется, это самые простые примеры. В более сложных ситуациях код лежит не в одном файле, а в нескольких, отдельно логика, отдельно html код.
То есть принцип такой:
- пользователь вводит адрес сайта или переходит по ссылке
- браузер отправляет запрос к серверу чтобы получить html код страницы
- на сервере запускается твой php скрипт
- то что он выводит отправляется назад в браузер и тот воспринимает это как HTML код который надо отобразить на странице
Отвечая на твои вопросы
> каким образом генерируются html и скармливается браузеру.
Выполняется php скрипт и то, что он выводит, отправляется в браузер.
> как вообще работает php на сервере?
Так же как и в любом другом варианте: он выполняет записанные в скрипте команды. Скрипт пишет и загружает на сервер программист, то есть ты.
> Ведь в генерируемых страницах, которые отдаются браузеру- нет ни строчки кода php.
Так и должно быть. Браузер все равно не понимает язык PHP, он понимает только HTML.
Сам PHP файл не отдается в браузер. Он выполняется на сервере, а то что он выводит через echo или другим способом, отдается в браузер.
> Простите за нубский вопрос
Это хороший вопрос и хорошо что ты пытаешься разобраться в том как все работает. Если у тебя есть еще какие-то вопросы или что-то непонятно, задавай, объясним.
Пока работаешь pнpшником, получать хоть какие-то деньги и опыт работы, а потом уйти в рубисты и чувствовать себя охуенным.
Сейчас тебя затралят и ты проебёшь тут ещё два часа.
http://vasyan.root.com/script.php
А мне хочется вернуть в нем root.com
Зачем, если можно вместо того, чтоб тратить время на похапе, потратить его на руби и сразу уйти в рубисты и чувствовать себя охуенным?
>Или вообще проверять через
Так и сделал
>Функцию можно определять через typeof
Сделал
>У псевдомассивов нет методов массива вроде splice, потому они и псевдомассивы. Также, проверяющая функция не должна что-то менять в массиве (а splice меняет).
Действительно, надо быть внимательней. В общем, вот новый вариант:
http://jsfiddle.net/3utu7xyu/
\t$requestedServerName = $_SERVER['SERVER_NAME']; // = dev.mysite.com
\t$thisSite = explode('.', $requestedServerName); // site name now an array
\tarray_shift($thisSite); //chop off the first array entry eg 'dev'
\t$thisSite = join('.', $thisSite); //join it back together with dots ;)
\techo $thisSite;
На benchmarksgame по производительности проигрывает только C/C++. Самый быстрый VM-based язык ЯП, и уж точно в 100500 раз производительней всякой скриптоты. Да отжирает много памяти и уёбищно фризится на сборке мусора, особенно если код писали долбоёбы, но по чистой производительности претензий нет.
>>426157
>Java не тормозит!
Спиздани уже что-нибудь, что бы я удивился.
>но по чистой производительности претензий нет.
Аналогично можно сказать в отношении любого скрипто-языка, лол.
>>426192
Исправленная версия задачи №15 по JavaScript:
http://jsbin.com/fuwicacila/1/edit?js,console
Спасибо, я просто думал, что моя задачка утонула в треде.
Вот смотри. Есть у меня, к примеру, класс. У класса есть метод. Метод принимает два массива. Этот метод, из первого массива выкидывает все элементы, которые есть во втором массиве. Короче вычитает массивы.
Мне надо, чтобы этот метод вернул сразу несколько наборов данных:
1) Измененный первый массив, из которого выкинуты элементы, которые есть во втором.
2) Новый массив - разница двух массивов. Тобишь те элементы которые были выкинуты из первого.
3) Ну и ошибки, к примеру, которые могут возникнуть в процессе.
Но я же return`ом могу только что то одно вернуть?
Как правильнее всего реализовать это? Понятно, что можно, к примеру, передать в метод пару дополнительных переменных по ссылке, куда запишется результат вычитания и ошибки. Или запоминать в классе результат вычитания и ошибки и добавить в класс пару дополнительных методов для их возврата.
Как это сделать - понятно, вопрос в том, как правильнее всего.
> Но я же return`ом могу только что то одно вернуть?
Возвращать массив
return array('deleted' => ..., 'added' => ...);
Учишь Symfony, параллельно делаешь всякие тестовые задания. Некоторые работодатели прям в описании вакансии прикладывают. Сделал ТЗ? Заебись, ты годен. Идешь на собеседование, продаешь себя как джун за 35К и все, успех.
ФУх, вроде ничего не забыл. Алсо, какова вероятность, что по такому вот алгоритму
https://github.com/MindiMakridi/Students/blob/master/lib/Profile.php#L37
у двух разных юзеров сгенерится одинаковый код?
>$string = "abcdefghijklmnopqrstuvwxyz1234567890";
>$length = mb_strlen($string);
>$string = mb_substr($string, mt_rand(0,$length-1), mt_rand(1,$length-1));
код у тебя зависит от результатов mt_rand(0,$length-1) и mt_rand(1,$length-1).
у mt_rand(0,$length-1) есть 36 вариантов
у mt_rand(1,$length-1) 35.
итого всего вариантов кодов будет 36*35=1260
отсюда вероятность что код повторится 1 к 1260
Занимательно. Зря я в школе не учил комбинаторику.
Ого. Вот это развернутый ответ на мой вопрос. Спасибо тебе огромное, анон!
И еще вот есть непонятный момент относительно Post и Get запросов. Каким образом они обрабатываются сервером? (например, когда в поисковой системе пишешь поисковой запрос, то в адресной строке можно увидеть что-то в стиле google.com/?bla%bla%bla)
Не могу понять именно алгоритм обработки сервером запроса с браузера.
Спасибо тебе огромное еще раз, анончик. Очень многое прояснил. Пусть в твоей жизни будет очень много добра.
Когда видно параметры запроса - это гет. Когда не видно - пост. В редких случаях что-то другое.вроде бы так
Обрабатывает такой логикой. Своим запросом браузер как бы сообщает серверу, а если точнее конкретному скрипту на нем, как и обычночто ему нужно. Скрипт смотрит, переваривает и отвечает на запрос все той же хтмл страницей. Отличается от простого обращения к скрипту тем, что скрипт должен быть готов работать с переданной из браузера клиента информацией, а не просто сам по себе.
Параметры запроса передаются в виде url.com/?param1=1¶m2=2¶mn=n
Есть 2 метода отправки формы: GET и POST. Для POST также есть 2 варианта кодирования данных (описаны тут http://htmlbook.ru/html/form/enctype ). Разница между 2 вариантами в том, что с помощью multipart/form-data можно передавать файлы, а с помощью application/x-www-form-urlencoded нельзя. C помощью GET файлы передавать тоже нельзя. Длина данных при GET запросе после кодирования должна не более 2000 байт.
Данные формы отправляются на адрес, указанный в атрибуте action. Это может быть любой URL в том числе указывающий на любой сайт.
По стандарту отправлять через GET можно только «безопасные» формы, не меняющие состояние сервера — например, форму поиска. Формы добавления, редактирования, удаления информации надо отправлять методом POST. Если форма отправлена методом GET то все данные из нее есть в строке URL и ты можешь поделиться ссылкой на результаты. С POST формами так сделать нельзя.
Если у формы стоит метод GET то при отправке данные из нее кодируются процентным кодированием ( подробнее 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 ) и добавляются к URL в виде строки запроса (после знака вопроса):
/index.php?a=1&b=2
Если у формы стоит метод POST то данные тоже кодируются (в зависимости от выбранного enctype) и передаются в теле запроса. В адресной строке при этом их нет.
Дополнительно перед телом запроса при исплоьзовании POST браузер передает заголовки Content-Type (в нем хранится способ кодирования данных) и Content-Length (содержит длину тела запроса).
В википедии описано как именно кодируются данные при enctype = Multipart/form-data
https://ru.wikipedia.org/wiki/Multipart/form-data
При использовании enctype = application/x-www-form-urlencoded данные кодируются так же как и при GET. то есть в виде a=1&b=2 но передаются в теле запроса, а не в URL.
PHP, перед тем как запустить твою программу, анализирует URL и все, что идет после знака вопроса (query string) разбирает и помещает в массив $_GET. Далее, он смотрит на метод которым отправлен запрос и если это POST, то PHP анализирует заголовки Content-Type и тело запроса и данные из него посещает в массив $_POST. Если с формой были переданы файлы, то они сохраняются во временную папку, а информация о них помещается в массив $_FILES.
Эти и другие массивы подробно описаны в мануале: http://php.net/manual/ru/language.variables.superglobals.php (там еще есть другие, о которых я не написал).
http://php.net/manual/ru/language.variables.external.php
То есть PHP обрабатывает все эти данные автоматически, и твоя программа получает их уже в разобранном виде в массивах вроде $_POST. Также на разбор данных влияют некоторые настройки в php.ini.
Вообще, тебе стоило бы почитать еще про протокол HTTP. Ведь именно с его помощью браузер отправляет запрос на сервер и получает ответ.
Почитать можно для начала хотя бы в википедии: https://ru.wikipedia.org/wiki/HTTP
Есть 2 метода отправки формы: GET и POST. Для POST также есть 2 варианта кодирования данных (описаны тут http://htmlbook.ru/html/form/enctype ). Разница между 2 вариантами в том, что с помощью multipart/form-data можно передавать файлы, а с помощью application/x-www-form-urlencoded нельзя. C помощью GET файлы передавать тоже нельзя. Длина данных при GET запросе после кодирования должна не более 2000 байт.
Данные формы отправляются на адрес, указанный в атрибуте action. Это может быть любой URL в том числе указывающий на любой сайт.
По стандарту отправлять через GET можно только «безопасные» формы, не меняющие состояние сервера — например, форму поиска. Формы добавления, редактирования, удаления информации надо отправлять методом POST. Если форма отправлена методом GET то все данные из нее есть в строке URL и ты можешь поделиться ссылкой на результаты. С POST формами так сделать нельзя.
Если у формы стоит метод GET то при отправке данные из нее кодируются процентным кодированием ( подробнее 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 ) и добавляются к URL в виде строки запроса (после знака вопроса):
/index.php?a=1&b=2
Если у формы стоит метод POST то данные тоже кодируются (в зависимости от выбранного enctype) и передаются в теле запроса. В адресной строке при этом их нет.
Дополнительно перед телом запроса при исплоьзовании POST браузер передает заголовки Content-Type (в нем хранится способ кодирования данных) и Content-Length (содержит длину тела запроса).
В википедии описано как именно кодируются данные при enctype = Multipart/form-data
https://ru.wikipedia.org/wiki/Multipart/form-data
При использовании enctype = application/x-www-form-urlencoded данные кодируются так же как и при GET. то есть в виде a=1&b=2 но передаются в теле запроса, а не в URL.
PHP, перед тем как запустить твою программу, анализирует URL и все, что идет после знака вопроса (query string) разбирает и помещает в массив $_GET. Далее, он смотрит на метод которым отправлен запрос и если это POST, то PHP анализирует заголовки Content-Type и тело запроса и данные из него посещает в массив $_POST. Если с формой были переданы файлы, то они сохраняются во временную папку, а информация о них помещается в массив $_FILES.
Эти и другие массивы подробно описаны в мануале: http://php.net/manual/ru/language.variables.superglobals.php (там еще есть другие, о которых я не написал).
http://php.net/manual/ru/language.variables.external.php
То есть PHP обрабатывает все эти данные автоматически, и твоя программа получает их уже в разобранном виде в массивах вроде $_POST. Также на разбор данных влияют некоторые настройки в php.ini.
Вообще, тебе стоило бы почитать еще про протокол HTTP. Ведь именно с его помощью браузер отправляет запрос на сервер и получает ответ.
Почитать можно для начала хотя бы в википедии: https://ru.wikipedia.org/wiki/HTTP
провел небольшие правки.
https://github.com/tokotun/matriculant
И пара вопросов.
>экранировать данные надо в том же месте где они применяются.
Данные полученные из белых списков тоже нужно экранировать?
>При редактировании надо сначала загрузить объект из базы, а потом перезаписывать его свойства на основе POST данных. Так надежнее, иначе какие-то данные могут потеряться.
Плохо понимаю для чего это. Это нужно для того что б при некоторых потерянных данных всё равно сделать обновление?
>Для борьбы с XSRF форму надо защитить каким-то кодом или токенов неизвестным злоумышленнику.
Нашел пару способов в интернете.
Первый способ - заставлять пользователя жать подтверждение на каждое действие? это вроде представляю
Второй способ с генерацией секретного посылаемого среди запросов, что то там ещё и динамической генерацией страниц. Про него вообще не понял.
Заранее спасибо.
Наконец-то я нашел время все проверить.
Вот советы и замечания. Там пока что код слабо соответствует идее ООП так как у тебя все свалено в один класс Desk.
Выбор хода у тебя почему-то сделан в классе Desk. Гораздо логичнее его перенести в класс животного. Пусть кошка или мышка сама выбирает себе ход. Иначе получится что все, что относится к разным объектам, свалено в кучу в один класс Desk.
Далее, свойства создаются для хранения какой-то информации об объекте. Но у тебя много свойств используются как временные переменные:
> public $toEnemyX;
> public $toEnemyY;
> public $enemyRoad;
> public $wayX;
> public $wayY;
Их стоит заменить на переменные.
> $x = mt_rand(0, 9);
> $y = mt_rand(0, 9);
координаты лучше выставлять снаружи, а не в конструкторе, а то у тебя жестко задано что кошки/мышки имеют координаты от 0 до 9 и нет никакой проверки что эта клетка занята.
> public function __construct($cats, $mice)
Удобнее не передавать кошек/мышек в конструктор, а сделать возможность добавлять и снимать животных с карты по мере игры.
Поле board в классе Desk используется как временная переменная. раз так, надо заменить его на переменную.
Вместо того чтобы постоянно во всех местах проверять, мертвая ли мышка, лучше просто при съедении снимать ее с карты.
В функции https://github.com/Si0n/CatNmouse/blob/master/catnmouse.php#L93 2 больших похожих куска кода. Надо избавиться от копипасты, например, вынеся это в отдельную функцию.
Та же проблема в функции getNextStep https://github.com/Si0n/CatNmouse/blob/master/catnmouse.php#L144
Размеры поля надо задать переменной, чтобы ее можно было легко поменять, а не прописывать жестко в коде.
> foreach ($this->mice as &$mouse) {
& не нужен так как объект и так можно менять: http://php.net/manual/ru/language.oop5.references.php
А, и еще. Давай сделаем все свойства объектов private или protected, чтобы доступ к ним был только через методы. Вот мануал: http://php.net/manual/ru/language.oop5.visibility.php
Наконец-то я нашел время все проверить.
Вот советы и замечания. Там пока что код слабо соответствует идее ООП так как у тебя все свалено в один класс Desk.
Выбор хода у тебя почему-то сделан в классе Desk. Гораздо логичнее его перенести в класс животного. Пусть кошка или мышка сама выбирает себе ход. Иначе получится что все, что относится к разным объектам, свалено в кучу в один класс Desk.
Далее, свойства создаются для хранения какой-то информации об объекте. Но у тебя много свойств используются как временные переменные:
> public $toEnemyX;
> public $toEnemyY;
> public $enemyRoad;
> public $wayX;
> public $wayY;
Их стоит заменить на переменные.
> $x = mt_rand(0, 9);
> $y = mt_rand(0, 9);
координаты лучше выставлять снаружи, а не в конструкторе, а то у тебя жестко задано что кошки/мышки имеют координаты от 0 до 9 и нет никакой проверки что эта клетка занята.
> public function __construct($cats, $mice)
Удобнее не передавать кошек/мышек в конструктор, а сделать возможность добавлять и снимать животных с карты по мере игры.
Поле board в классе Desk используется как временная переменная. раз так, надо заменить его на переменную.
Вместо того чтобы постоянно во всех местах проверять, мертвая ли мышка, лучше просто при съедении снимать ее с карты.
В функции https://github.com/Si0n/CatNmouse/blob/master/catnmouse.php#L93 2 больших похожих куска кода. Надо избавиться от копипасты, например, вынеся это в отдельную функцию.
Та же проблема в функции getNextStep https://github.com/Si0n/CatNmouse/blob/master/catnmouse.php#L144
Размеры поля надо задать переменной, чтобы ее можно было легко поменять, а не прописывать жестко в коде.
> foreach ($this->mice as &$mouse) {
& не нужен так как объект и так можно менять: http://php.net/manual/ru/language.oop5.references.php
А, и еще. Давай сделаем все свойства объектов private или protected, чтобы доступ к ним был только через методы. Вот мануал: http://php.net/manual/ru/language.oop5.visibility.php
Yii Второй новее и лучше, но пока не так распространен как первый.
>>425844
> if ($i == 10) {
Плохо прописывать число. Ведь если мы поменяем массив полей нам придется вручную его менять. Надо чтобы само менялось.
Прогамма не видит что бобавлены лишние поля: http://ideone.com/8hE7iV
Также, эта задача гораздо проще решается черех функции типа array_diff/intersect
>>425907
Yii 2 и Symfony 2. Но начать можно с микрофреймворка Slim, он проще и у нас на него есть задача: https://gist.github.com/codedokode/9424217
Глупо выбирать язык исходя из того что в почете у кучки поехавших социопатов с двача. Гораздо умнее открыть сайты с вакансиями и фрилансом и проанализировать вакансии и заказы. Ну или хотя бы выбирать по принципу что нравится самому.
Ну и мы никого не заставляем всю жизнь на Php писать. Если кто-то хочет потом другой язык изучить, после нашего курса делать это будет гораздо проще.
Ну и с php все проще чем с рельсами. Не надо никаких консолей, линуксов и приложений — ставишь на свою винду Апач, создаешь станичку и открываешь в браузере. Куда как проще чем с консолью мучаться.
Ебать, да вы тут клуб копрофилов собрали? Охуеть просто. Ссут всем на голову ИТТ.
На одеске с нулевым опытом ловить нечего.
>>426059
если тебе надо на рабочий стол то проще в графическом редакторе обрезать.
Если программно то считаешь отношение новой высоты к старой, то же для ширины и берешь наибольшее. Получишь во сколько раз надо уменьшить картинку. Потом считашь сколько надо отрезать. В общем, тут математика нехитрая.
>>426131
На бекбоне бессмысленно решать абстрактные задачи. Он предназначен для написания SPA (одностраничных приложений на JS). Соответственно чтобы научиться надо сделать какое-то приложение.
Далее, представление (view) что идет в поставке бекбона, совсем никакое, потому стоит взять что-нибудь получше, например knockout — то хороший шаблонизатор с поддержкой дата байндинга (то есть переменная привязываетя к элементу DOM и при ее изменении меняется текст или свойства этого элемента).
Что бы нам сделать? Давай например сделаем аналог вот этой задачи: https://gist.github.com/codedokode/d7e7f11449fc3bcb24b4 только с помощью SPA
Итак, надо сделать приложение для регистации абитуриентов. Ну например сотрудники приемной комиссии могут открыть это приложение на ланшете и с его мпомощью вводить, редактировать и просматривать список абитуриентов.
По умолчанию приложение показывает список абитуриентов. В списке есть кнопки удаления и редактирования. Также, есть кнопка добавления нового абитуриента. Есть постраничный просмотр списка, сортировка, а также поиск как описано в задании.
Все это должно работать без перезагузки страницы. Изменения должны периодически отправляться на сервер и с сервера же скачиваться изменения сделанные другими сотрудниками. При отстутсвии связи изменения должны сохраняться локально и при появлении связи сбрасываться на сервер (это все же планшет, связь может пропадать). Изменения должны сохраняться в надежное хранилище, чтобы даже при закрытии браузера они не терялись.
У страниц должны быть свои URL чтобы можно например было сохранить в закладки ссылку на страницу редактирования конкретного абитуриента.
Как ты наверно успел заметить, тут требуется серверная часть. Если ты знаешь какой-то серверный язык (php, node.js, и тд), то сделай эту часть, если не знаешь то можно пока хранить все локально, без сервера.
Код можно постить на гитхаб.
Что скажешь?
Насчет underscore , можешь сразу изучать lodash — это улучшенная версия.
На одеске с нулевым опытом ловить нечего.
>>426059
если тебе надо на рабочий стол то проще в графическом редакторе обрезать.
Если программно то считаешь отношение новой высоты к старой, то же для ширины и берешь наибольшее. Получишь во сколько раз надо уменьшить картинку. Потом считашь сколько надо отрезать. В общем, тут математика нехитрая.
>>426131
На бекбоне бессмысленно решать абстрактные задачи. Он предназначен для написания SPA (одностраничных приложений на JS). Соответственно чтобы научиться надо сделать какое-то приложение.
Далее, представление (view) что идет в поставке бекбона, совсем никакое, потому стоит взять что-нибудь получше, например knockout — то хороший шаблонизатор с поддержкой дата байндинга (то есть переменная привязываетя к элементу DOM и при ее изменении меняется текст или свойства этого элемента).
Что бы нам сделать? Давай например сделаем аналог вот этой задачи: https://gist.github.com/codedokode/d7e7f11449fc3bcb24b4 только с помощью SPA
Итак, надо сделать приложение для регистации абитуриентов. Ну например сотрудники приемной комиссии могут открыть это приложение на ланшете и с его мпомощью вводить, редактировать и просматривать список абитуриентов.
По умолчанию приложение показывает список абитуриентов. В списке есть кнопки удаления и редактирования. Также, есть кнопка добавления нового абитуриента. Есть постраничный просмотр списка, сортировка, а также поиск как описано в задании.
Все это должно работать без перезагузки страницы. Изменения должны периодически отправляться на сервер и с сервера же скачиваться изменения сделанные другими сотрудниками. При отстутсвии связи изменения должны сохраняться локально и при появлении связи сбрасываться на сервер (это все же планшет, связь может пропадать). Изменения должны сохраняться в надежное хранилище, чтобы даже при закрытии браузера они не терялись.
У страниц должны быть свои URL чтобы можно например было сохранить в закладки ссылку на страницу редактирования конкретного абитуриента.
Как ты наверно успел заметить, тут требуется серверная часть. Если ты знаешь какой-то серверный язык (php, node.js, и тд), то сделай эту часть, если не знаешь то можно пока хранить все локально, без сервера.
Код можно постить на гитхаб.
Что скажешь?
Насчет underscore , можешь сразу изучать lodash — это улучшенная версия.
Подскажите по поводу задачи про Конату Изуми, где надо найти места на которые надо сесть. Там можно обойтись без рекурсии?
Что-то у тебя код разъехался. Табы вместо пробелов используешь?
> var checkVarType = function(variable) {
По моему лучше и логичнее писать function checkVarType(...) { ...}
> for (var i = 0; i < variable.length; i++) {
> j++;
> if (variable.length == (j-1)) {
непонятно в чем смысл этого цикла. Если ты хочешь просто N раз увеличить j на 1, не проще ли написать сразу j = N?
>>426189
>>426196
Ок, почти верно, только не называй переменные с большой буквы — с большой пишутся только классы (точнее функции-конструкторы) и константы.
Насчет даты, как-то ненадежно выглядит копирование через преобразование в строку, лучше мне кажется сделать как здесь в первом варианте http://stackoverflow.com/a/1090817
>Данные полученные из белых списков тоже нужно экранировать?
Если ты в этой же функции проверил что данные соответствуют белому списку то можно не экранировать (если например это имя поля которое вставляется в запрос). Главное проверять в той же самой функции (а не в другом месте кода), чтобы с первого взгляда было видно что все надежно.
> Это нужно для того что б при некоторых потерянных данных всё равно сделать обновление?
Завтра ты добавишь какое-нибудь свойство которое есть в объекте, но которого нет в форме, и оно начнет теряться при редактировании. Надежнее именно перезаписывать существующий объект.
Про XSRF — надо добавлять в форму токен, то есть какой-то код который уникален для разных пользователей и который не знает злоумышленник. Наличие этого токена в POST данных подтверждает что форма отправлена пользователем явно.
Обычно для этого генерируют случайный код и добавляют его и в куки и в форму, а при отправке формы сверяют (иногда токен генерируется на основе IP адреса но это не очень надежно так как IP адрес в мобильном устройстве может меняться при обрыве связи). В твоем случае код генерировать не надо, у тебя уже есть токен для проверки доступа, можно его использовать. Просто добавь его коме кук еще в форму и сверяй при отправке формы.
да. Просто сделай массив, сделай переменную-счетчик, обходи массив циклом и удаляй каждый N-й по счету элемент.
>Что-то у тебя код разъехался. Табы вместо пробелов используешь?
Yep, но у меня по ссылке ничего никуда не разъехалось.
>По моему лучше и логичнее писать function checkVarType(...) { ...}
Да ну, не принципиально. Ну ок.
>непонятно в чем смысл этого цикла. Если ты хочешь просто N раз увеличить j на 1, не проще ли написать сразу j = N?
Кажется идея была в том, чтобы проверять доступ по вот этому условию из задачи:
>элементы с 0 до length - 1
но сейчас я уже не уверен в этом решении. Может проверки наличия length будет достаточно?
http://jsfiddle.net/3utu7xyu/1/
>Ок, почти верно, только не называй переменные с большой буквы — с большой пишутся только классы (точнее функции-конструкторы) и константы.
>Насчет даты, как-то ненадежно выглядит копирование через преобразование в строку, лучше мне кажется сделать как здесь в первом варианте
Пофиксил:
http://jsbin.com/timedisapo/1/edit?js,console
Не, у тебя ненадежная генерация кода, там всего 1000 вариантов и их можно подобрать. надо генерировать примерно так:
Пусть L = желаемая длина (20-40 символов)
Повторять L раз:
- выбрать случайную букву
- добавить ее к строке
>>426222
Аноны, вас к сожалению сегодня не успеваю проверить, давайте завтра проверю. делайте пока задачу дальше, если там еще что-то осталось.
>>426334
> Кажется идея была в том, чтобы проверять доступ по вот этому условию из задачи:
Так а где проверка наличия в псевдомассиве элемента с индексом j? Ее нету же.
> Может проверки наличия length будет достаточно?
Это слишком просто для 15-й (или какая она там) задачи.
Проверялка работает в тестовом режиме и может проверять неверно. Пишите мне, вправим ей мозги. Ну и решения стоит в любом случае в тред вбрасывать для более тщательной проверки.
>>426339
Все правильно считает.
Я пытался так сделать, но возникли проблемы, например в цикле я удаляю каждый 5 элемент, как потом мне вновь в цикле (уже изменившемся) удалить каждые пятый элемент? Не делать же каждый раз новый массив.
>Так а где проверка наличия в псевдомассиве элемента с индексом j? Ее нету же.
Именно это я и забыл. Вот:
http://jsfiddle.net/3utu7xyu/2/
>Это слишком просто для 15-й (или какая она там) задачи.
Это значит неработает/ненадежно или стоит сделать лучше чтобы больше узнать/изучить?
Есть, я даже недопрошел обучение, и уже взяли, но сам ушел через неделю, так как ездить надо было 2 часа в 1 сторону, ща хуи сосу и жалею что ушел, уже бы экспы море загреб.
>2 часа в 1 сторону
>зря ушел
Дурак чтоль? Столько времени тратить на дорогу - идиотизм. Не проще ли было найти работу поближе?
Не было тестового, я пилил стори 2-3 треда назад. Поищи что и как если интересно. У других стремящихся даже бомбануло. На тот момент я выполнил всё вплоть до http://archive-ipq-co.narod.ru/l1/finals.html
ну и уже мог 1 табличку в mysql сделать и с помощью пхп с ним работать.
Ну и простейшие html штуки знал. Ну например делал простейшую хрень типа гостевухи пикрилейтед. Как-то так. Устроился по случайности.
Ну как бы здравый смысл одно, а реальность другое. И сейчас я понимаю, что лучше бы я там поработал 2 месяца, и стал бы куда лучше разбираться в специальности, а по выходным пилил бы тестовые для других контор, которые рядом, и ушел вот сейчас оттуда. В итоге я ушел, попилил тестовое неделю, просрал сроки и завис на нем, сидел все каникулы двачевал тупо. Даже для себя не доделал толком.
А там у меня мозги работали прям. Не то что дома. Вот почему жалею. Да и на рынке труда перед новым годом и сразу после как я понимаю было все глухо. У меня в городе 1 вакансия пхп джуна сейчас. И то проебано собеседование уже с ними.
О, я гостевую книгу делал ещё до того как познакомился с учебником ОПа, но надо сказать некоторые задания из учебника ОПа поставили меня в тупик. Я понял некоторую двойственность ПХП, на него можно смотреть только как на оружие для веба, и также как на обычный язык программирования именно на это делает упор ОП как я понял. Может я неправильно сформулировал, извиняюсь.
Извини что спрашиваю, просто интересно оценить, ты можешь допустим написать блог, где будет сортировка по категориям, постраничный вывод, возможность добавлять, комментировать (с использованием капчи и прикрепления картинок), редактировать и удалять записи?
Да смогу конечно, если буду усиленно гуглить и читать, за несколько недель думаю что да.
Понятно, удачи тебе в поисках, если раз уже взяли значит ещё раз возьмут.
Напиши автоматическиую логинилку на двач.
и сразу НЁХ для меня какой-то.
http://ideone.com/M3yZ5p
Это типа обращаешься к значению переменной как к имени? В принципе вроде осознал, но применение пока не вижу.
У него там в 31 вопросе не ошибка случайно???
Он задает кодировку по умолчанию для хранения данных в таблице. Если для колонки не указана своя кодировка (в MySQL у каждой колонки может быть своя кодировка) то она берется из таблицы. Если не указана кодировка таблицы то она берется из базы данных. Если не указана у базы данных то берется из настроек в my.ini
Заметь что это именно кодировка хранения, то есть в какой кодировке данные сохраняются на диске. Она не влияет на то, в какой кодировке данные постуают или выходят из MySQL так как она делает преобразование из/в кодировку соединения при их передаче.
Всегда стоит использовать utf8 так как однобайтовые кодировки не позволят хранить более 256 символов.
Подробнее
http://fstrange.ru/coder/mysql/kodirovka-krakozyably.html
http://gahcep.github.io/blog/2013/01/05/mysql-utf8/
http://phpfaq.ru/charset
Заметь что кроме кодировки есть еще collation — правила сравнения строк (collation определяет учитывать ли регистр и сравнении, как выстраивать слова по алфавиту ит тд)
А, по твоему воросу: слово DEFAULT не обаязательно. Оно скорее всего добавлено для совместимости с другой базой данных где оно обязательно.
Такая возможность есть, но это крайне плохая вещь так как усложняет понимание кода. Не могу представить ни одной ситуации, где это было бы нужно, потому никогда так не делай. Надеюсь, в будущих версиях Php это выпилят.
Это рабоатет ненадежно. Проверять наличие свойства length недостаточно, так как есть такой пример:
var box = { width: 100, length: 300 };
Это явно не псевдомассив так как у него нет свойств 0, 1, 2 ... 99
>Это рабоатет ненадежно. Проверять наличие свойства length недостаточно, так как есть такой пример:
var box = { width: 100, length: 300 };
Но ведь этот пример остановится на case "[object Object]"
>>426471
Алсо надо проверять что length содержит число.
http://jsbin.com/fohelihaze/1/edit?js,console
Бандл может быть как приложением так и библиотекой. Ну например можно сайт сделать в одном бандле, а форум в другом, чтобы этот форум был независим и его можно было одключить к любому другому сайту.
Бандлы могут иметь зависимости, то есть бандлу A нужны B, C и D.
> Но ведь этот пример остановится на case "[object Object]"
Действительно, как я не заметил. Молодец, ты нашел баг в своем же коде:
http://jsbin.com/jupirirevi/1/edit?js,console
В 2 последних случаях передан псевдомассив.
Молодец, вижу что ты в экономике немного разбираешься, только что-то ты совсем уж пессимистично оценил уровень инфляции.
>>426343
Так надо делать по-другому:
Повторяем пока в массиве много лементов:
- Перебираем массив, для каждого элемента:
-- увеличиваем счетчик
-- если счетчик дошел до N удаляем текущий элемент
Примерно так. Ну и код показывай, если уже что-то написал.
Хорошая идея. Я немного разбираюсь в Симфони так что одскажу, если что не так. Ну и надеюсь, ты будешь использовать Симфони по полной, то есть Twig, Doctrine2 и может быть даже даже что-нибудь от Friends of Symfony?
>Аналогично можно сказать в отношении любого скрипто-языка, лол.
Ага, потому то твиттер выкинул руби, а фейсбук с вконтактами пишут трансляторы из пхп в цпп.
>Спиздани уже что-нибудь, что бы я удивился.
Я ему факт, он мне кукареку. Пошёл нахуй тогда, хуисас. Сам зайди на benchmarksgame и меряй. Если не веришь им, опубликуй свой бенч. Хотя, блять, что ты там можешь сделать, ты же школьник кода в жизни не писавший.
Он прав, JVM очень быстрая и оптимизированная. Не такая быстрая как Си++, но на сложных приложениях я подозреваю разница будет не принципиальная, а вот работать с явой удобнее.
С другой стороны, пример v8 показывает что JIT может и с динамическими языками творить чудеса. Ну и фейсбуковский HipHop использует именно JIT. Динамические языки во время компиляции оптимизировать трудно, только в рантайме можно.
Я вообще заметил, всякие руби и нододети любят рассуждать о языках программирования при том что в жизни ничего сложнее гостевухи с 1 пользователем не писали.
Вот когда будешь твиттером или фейсбуком - там и выкинешь Руби и начнёшь на плюсах потеть.
А пока ты манясайт или пусть даже стартап с хорошей посещаемостью, но без денег на год потных плюсовых программистов - делаешь всё на интепретируемых медленных фреймворках, зато за три месяца и в одно рыло.
Не надо ездить на внедорожнике по городу, не надо ездить на смарте в лес. Это неэффективно.
Но ты же понимаешь что средний пыхер из пункта 5 получает под 100к, что выше среднего даже в ДС
У нас на игровом серваке на ноде socket.io просто доебал - всё очень сыро. И нода через год разработки читается новоприбывшими очень некомфортно (при всех попытках быть аккуратными).
В следующий раз возьму Ruby.
На php делаются (в том числе и) нормальные сайты. А руби- и нододети это клоуны которым плевать на все, лишь бы применить библиотеку или технологию о которой они прочли в твиттере. Как правило сделанные ими сайты дергаются и трясутся в любом браузере (кроме браузера под мак которым пользуются рубидети, а часто и в нем тоже). Что хорошего с ними работать? Лучше уж в компании опытных адекватных php разработчиков.
Алсо меня бесит твиттер бутстрап и материал дизайн.
>Зато за три месяца и в одно рыло.
Норм, если это прототип, который чуть позже будет выкинут.
И на джаве разработка будет вполне быстра, так как библиотек, фреймворков, серверов и прочих наработок на этой платформе больше, чем на какой либо.
Алсо руби он рейлс это кривая поделка с кучей уязвимостей, непредсказуемым поведением и повсеместным использованием статических методов. Как ей вообще можно пользоваться? Вы, тролли, хотя бы нормальные примеры противопоставляли.
Oh boy here we go. Кто-то вбросил идею про прототип который можно будет выкинуть (и переписать сайт на PHP), а вы ее повторяете. Ни один заказчик не захочет оплачивать разработку продукта только чтобы его потом выкинуть.
Я и не спорю что для чатиков и вебсокет демонов нода подходит хорошо. А вот сайты на ней делать это уже фанатизм, там даже нормальное ООП не завезли еще.
А что скажешь на таких чуваков?
http://www.hemju.com/index.php/2014/06/why-lingohub-is-switching-from-ruby-on-rails-to-java-spring-mvc/
> However, the biggest problem that I see with Gems is their quality and code activity. Don’t get me wrong, I really appreciate all the hard work that is done by the individuals that create these Gems, but the problem is that many projects are (actively) maintained by one guy.
>How compares Rails to other frameworks like Spring if just need REST? Not good. Development with Rails isn’t faster anymore. Frontend developers and designers are glad to use pure HTML/CSS/JS (with some GruntJS love) and the backend developers are glad that there are defined interfaces between controller and view (one of the weaknesses in Rails).
Но ты ведь не из тех, кто НА МОЁМ ЛЮБИМОМ ЯЗЫЧКЕ МОЖНО СДЕЛАТЬ ВСЁ КУ-КА-РЕ-КУ.
Программист, как любой грамотный инженер, должен понимать, что есть различные задачи и различные инструменты, и некоторые инструменты подходят под определённые задачи больше, чем остальные. И иногда так получается, что есть два и более инструментов под одну и ту же задачу, но не обязательно, что все они одинаково хороши и следует выбрать лучший. За PHP я не вижу ниши где это был бы top1 инструмент, кроме
>Поддержка ржавых уёбищных веб магазинов, визиток, сервисов, порталов, написанных в 90е в веб 1.0 стиле кривыми руками бывших перлистов, допиливание CMS-based сайтов всяких быдлокомпаний.
То есть единственное преимущество владения таким языком - возможность по-быстрому найти работу. Потом все эти сегодняшние ньюфаги из этого треда, через год будут ныть в зк/ о том, что их окружает говно и развал и они хотят в няшный стартап на руби, но нет времени.
Преимущество php в том что под него есть много готовых библиотек и много разработчиков разного уровня. Вполне разумным представляется выбрать именно его для разработки какого-то нового проекта.
На физическом уровне модель данных состоит из следующих таблиц:
Learners(id_learner, name, birthday, address, email, mobile), Tasks(id_task, name), Steps(id_step,name), Components(id_cks,name), TaskStructure(id_task, id_step, id_cks), Solving(id_learner, id_task, id_step, id_cks, num_try, p, t).
Какой-нибудь учебник по сетевым технологиям.
Я в свое время читал «Компьютерные сети. Принципы, технологии, протоколы. Учебник для вузов.» но может там что-то устарело уже?
> В этом ИТТ треде мы изучаем PHP (а также MySQL, JS, CSS, HTML),
Первая пикча это как было, вторая пикча это я добавил <p></p> и всё стало скакать. Как я понял это из за отступов (пикча 3). Как починить и не сталкиваться больше с этим?
Это протекание и схлопывание границ (margin collapsing). Оно описано например тут http://softwaremaniacs.org/blog/2005/09/05/css-layout-flow-margins/
Надо не столько бороться, а учитывать его когда ты делаешь макет.
Таненбаум "Компьютерные сети"
По-сути, есть набор предметов, на каждый предмет прописана аудитория, также на каждый предмет прописано количество часов в неделе на одну группу, затем это все формируется в одну таблицу. По началу, я пытался учесть такие вещи, как нечетное количество часов, когда на деле пара идет 2 часа, да-да, ИРЛ такое бывает и вводятся пары по числителю/знаменателю, несколько групп, быстрый перенос пары без сильного колбашения расписания, один преподаватель прикреплен к нескольким предметам и не может быть одновременно на двух, типы аудиторий и пары соответствующие им. И еще много других нюансов легко реализуемых на бумаге. Но в результате я оставил только основные условия: "кабинет не пересекается, часов используется ровно столько сколько надо и группа всего одна". Не смог. Куда копать-то? Примеров вразумительных с открытым кодом мне найти не удалось. Что делать?
Приходишь, собеседуешься, рассказываешь что готов работать за еду первый месяц, главное возьмите. Решаешь какой-нибудь тест например, далее тебе все равно дают тестовое задание и ты отправляешься домой. Начинаешь его ковырять, выполняешь какие-нибудь основы, но далее понимаешь что не успеешь всё равно, работа затухает, сидишь сосешь хуй как раньше, вот и всё. Второй раз к этим ребятам нет смысла соваться энивей, пока не сделаешь их тестовое.
Что за тестовое? Какой инструментарий требуют? Что там было сложно и ты не осилил?
>Вовсе не обязательно.
Не обязательно, но вполне реально. Знаю чувака который уже будучи крутым авиационным инженегром под 30 перекатился в пых и к 32 получает 130к. перекатился потому что жена пилила что мало денег, лол
Ты хочешь мне помочь разобраться? Или ты для себя интересуешься? Ну тестовое например запилить админку в виде веб-интерефейса, в которую можно логиниться и удалять, редактировать юзеров. Или блог сделать с возможностью редактировать, комментировать, поиском и пр плюшками.
Инструменты: php, mysql, html, css.
Советы и замечания по коду.
Вообще, я вижу что решение почти готово. Тут в основном замечания по оформлению, ну и код надо генерировать понадежнее.
> https://github.com/MindiMakridi/Students/blob/master/students.sql#L32
> `sex` enum('М','Ж')
Для ENUM обычно используют латинские обозначения, например male/female
> if(isset($_POST['exit'])){
> logOut( );
После успешной обработки POST-формы надо делать редирект (иначе при обновлении страницы отправится повторный запрос)
> https://github.com/MindiMakridi/Students/blob/master/index.php
Тут все разъехалось — надо исправить оформление руками или на phpformatter.com. Например, скобки около else ставятся так:
} else {
То же самое в файле profile.php
> https://github.com/MindiMakridi/Students/blob/master/profile.php#L15
> $profile = $mapper->fetchProfile($code);
> $id = $profile->showID( );
Здесь нет проверки на случай если fetchprofile вернет null или false. Надо обрабатывать эту ситуацию.
> https://github.com/MindiMakridi/Students/blob/master/profile.php#L36
Эту функцию лучше назвать не fetchEMail, а isEmailUsed (исппользуется ли email)
> https://github.com/MindiMakridi/Students/blob/master/profile.php#L54
> header("Location: $Configredirect");
После редиректа не надо выводить страницу. Надо завершать скрипт.
> https://github.com/MindiMakridi/Students/blob/master/lib/DataMapper.php#L2
> require_once "/lib/PDO.php";
Переменная $DBH никак не исплоьзуется тут, и значит подключать файл здесь не надо. Подключать его надо там где она используется. Ну и не надо называть переменные с большой буквы, с большой буквы пишутся классы и константы
> https://github.com/MindiMakridi/Students/blob/master/lib/DataMapper.php#L83
> $STH->bindparam(":name", $name);
> $name = $profile->showName( );
Гораздо удобнее тут исплоьзовать bindValue и обойтись без промежуточной переменной. Вообще, bindParam нужен в первую очередь для двухсторонней привязки, то есть практически никогда.
> https://github.com/MindiMakridi/Students/blob/master/lib/DataMapper.php#L127
> public function getLastId()
Эта функция написана неправильно. Ведь между выполнением INSERT и вызовом getLastId другой процесс может вставить еще одну запись и ты прочитаешь не тот id. Надо использовать специально сделанную функцию getLastInsertId в PDO которая возващает именно последний сгенерированный в этом сеансе связи id.
Если же эта функция нигде не используется, надо ее удалить.
> https://github.com/MindiMakridi/Students/blob/master/lib/Profile.php#L5
> class profile
Имена классов пишутся с большой буквы
> https://github.com/MindiMakridi/Students/blob/master/lib/Profile.php#L37
> public function generateCode(){
Тут слишком мало вариантов кода получается. Надо сделать нормально, чтобы каждая буква выбиралась случайно.
> https://github.com/MindiMakridi/Students/blob/master/lib/Profile.php#L64
> public function setFields($data)
У тебя объединены в одну функцию простановка значений из массива и их проверка. Лучше сделать 2 отдельные функции для этого, а то у тебя например нельзя проверить поля объекта на правильность.
> https://github.com/MindiMakridi/Students/blob/master/lib/Profile.php#L84
> "<font color=\"red\
В модели не должно быть HTML тегов
> class StudentMapper
> DataMapper.php
Имя файла должно совпадать с именем класса в нем
> https://github.com/MindiMakridi/Students/blob/master/lib/DataMapper.php#L9
> public function __construct($DBH)
Тут стоит поставить тайп хинт что DBH относится к классу PDO
> https://github.com/MindiMakridi/Students/blob/master/templates/header.html#L11
> <?php echo $isRegistered
Тут лучше использовать htmlspecialchars
> <form method="post">
> <input type='hidden' name="exit">
У тебя не указан атрибут action. Потому на странице profile.php эта кнопка выхода не будет работать
> Управляющая конструкция с двоеточими и endif вызывает ошибку unexpected string T_ENDIF,
> а <?=?> вместе с содержимым выводится как хтмл код
Покажи мне пример кода который не работает, я гляну и скажу в чем ошибка. Надо разобраться, а не бросать это
Также, я вижу ты не очень хорошо знаешь HTML/CSS? Не хочешь потом как-нибудь порешать хорошие задачки на эту тему? https://gist.github.com/codedokode/58ebc90bd006baf4b35c
Советы и замечания по коду.
Вообще, я вижу что решение почти готово. Тут в основном замечания по оформлению, ну и код надо генерировать понадежнее.
> https://github.com/MindiMakridi/Students/blob/master/students.sql#L32
> `sex` enum('М','Ж')
Для ENUM обычно используют латинские обозначения, например male/female
> if(isset($_POST['exit'])){
> logOut( );
После успешной обработки POST-формы надо делать редирект (иначе при обновлении страницы отправится повторный запрос)
> https://github.com/MindiMakridi/Students/blob/master/index.php
Тут все разъехалось — надо исправить оформление руками или на phpformatter.com. Например, скобки около else ставятся так:
} else {
То же самое в файле profile.php
> https://github.com/MindiMakridi/Students/blob/master/profile.php#L15
> $profile = $mapper->fetchProfile($code);
> $id = $profile->showID( );
Здесь нет проверки на случай если fetchprofile вернет null или false. Надо обрабатывать эту ситуацию.
> https://github.com/MindiMakridi/Students/blob/master/profile.php#L36
Эту функцию лучше назвать не fetchEMail, а isEmailUsed (исппользуется ли email)
> https://github.com/MindiMakridi/Students/blob/master/profile.php#L54
> header("Location: $Configredirect");
После редиректа не надо выводить страницу. Надо завершать скрипт.
> https://github.com/MindiMakridi/Students/blob/master/lib/DataMapper.php#L2
> require_once "/lib/PDO.php";
Переменная $DBH никак не исплоьзуется тут, и значит подключать файл здесь не надо. Подключать его надо там где она используется. Ну и не надо называть переменные с большой буквы, с большой буквы пишутся классы и константы
> https://github.com/MindiMakridi/Students/blob/master/lib/DataMapper.php#L83
> $STH->bindparam(":name", $name);
> $name = $profile->showName( );
Гораздо удобнее тут исплоьзовать bindValue и обойтись без промежуточной переменной. Вообще, bindParam нужен в первую очередь для двухсторонней привязки, то есть практически никогда.
> https://github.com/MindiMakridi/Students/blob/master/lib/DataMapper.php#L127
> public function getLastId()
Эта функция написана неправильно. Ведь между выполнением INSERT и вызовом getLastId другой процесс может вставить еще одну запись и ты прочитаешь не тот id. Надо использовать специально сделанную функцию getLastInsertId в PDO которая возващает именно последний сгенерированный в этом сеансе связи id.
Если же эта функция нигде не используется, надо ее удалить.
> https://github.com/MindiMakridi/Students/blob/master/lib/Profile.php#L5
> class profile
Имена классов пишутся с большой буквы
> https://github.com/MindiMakridi/Students/blob/master/lib/Profile.php#L37
> public function generateCode(){
Тут слишком мало вариантов кода получается. Надо сделать нормально, чтобы каждая буква выбиралась случайно.
> https://github.com/MindiMakridi/Students/blob/master/lib/Profile.php#L64
> public function setFields($data)
У тебя объединены в одну функцию простановка значений из массива и их проверка. Лучше сделать 2 отдельные функции для этого, а то у тебя например нельзя проверить поля объекта на правильность.
> https://github.com/MindiMakridi/Students/blob/master/lib/Profile.php#L84
> "<font color=\"red\
В модели не должно быть HTML тегов
> class StudentMapper
> DataMapper.php
Имя файла должно совпадать с именем класса в нем
> https://github.com/MindiMakridi/Students/blob/master/lib/DataMapper.php#L9
> public function __construct($DBH)
Тут стоит поставить тайп хинт что DBH относится к классу PDO
> https://github.com/MindiMakridi/Students/blob/master/templates/header.html#L11
> <?php echo $isRegistered
Тут лучше использовать htmlspecialchars
> <form method="post">
> <input type='hidden' name="exit">
У тебя не указан атрибут action. Потому на странице profile.php эта кнопка выхода не будет работать
> Управляющая конструкция с двоеточими и endif вызывает ошибку unexpected string T_ENDIF,
> а <?=?> вместе с содержимым выводится как хтмл код
Покажи мне пример кода который не работает, я гляну и скажу в чем ошибка. Надо разобраться, а не бросать это
Также, я вижу ты не очень хорошо знаешь HTML/CSS? Не хочешь потом как-нибудь порешать хорошие задачки на эту тему? https://gist.github.com/codedokode/58ebc90bd006baf4b35c
Тебя я сегодня не успел проверить, только в общем посмотрел, что все неплохо сделано. Вот только тут мне в глаза бросилось:
> <h1><?php if (isset($_COOKIE['id'])):?>Редактирование данных об абитуриенте
Шаблон не должен обращаться к POST, COOKIE и подобным переменным, то не его задача, а задача контроллера. Все, что нужно шаблону, передается явно через переменные.
По поводу
> с десятью уровнями внутри
ты изучал ООП? С помощью объектов можно сделать все эти связи проще и удобнее.
Насчет алгоритма, есть отдельный предмет (методы оптимизации или как-то так) в котором изучаются способы решения таких задач. Задача составления расписания довольно сложная и в идеальном решении требуется сделать огромное число вычислений (так как очень много вариантов расстановки). Но если не стоит задача составить самое идеальное расписание, то она решаема.
Например, может быть сработает «жадный» алгоритм, когда мы просто берем по очереди группы, занятия и подбираем лучшее место в сетке для них из тех что свободны.
Может быть потребуется что-то более сложное. Я советую для начала погуглить:
http://www.google.ru/search?sourceid=chrome&ie=UTF-8&q=%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC+%D1%81%D0%BE%D1%81%D1%82%D0%B0%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F+%D1%80%D0%B0%D1%81%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D1%8F
http://www.google.ru/search?sourceid=chrome&ie=UTF-8&q=%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B0+%D1%81%D0%BE%D1%81%D1%82%D0%B0%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F+%D1%80%D0%B0%D1%81%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D1%8F
Там конечно много ерунды но можно найти и полезные статьи.
Если тебе та тема интересна, давай решим эту задачу. Начать можно с максимально упрощенного варианта, и постеенно его усложнять.
Кстати ты знаешь что у нас крроме учебника есть доолнительные задачи на SQL, HTML, CSS, JS, а также сделать простой сайт или страничку? На учебнике все не заканчивается.
Надумал попердолить простой кодинг, с++ кажется монструозным, жава сложноватой, да и неябу как их для себя применить и что на них писать в свое удовольствие чтоб был интерес. Пхп же выглядит полезным, т.к. сайты всем нужны и важны. А если повезет то можно даже поработать макакой. Говорят работа в офисах всегда есть, а на высокие зп мне срать.
Одно время админил сайт индуса на которого работал, но там был уже адаптированный интерфейс для написания новостей и прочего говна. Не помню как назывался движок, но было интересно, хотя я нихрена не понимал как модифицировать модули, как прикручивать другие ну и прочее, сам процесс доставлял.Еще помню делал свою страничку в фронт пейдже вроде, заливал на народ, все дела. Можно было заходить и качать мои карты для квейка.
Вижу в этом итт (и в интернетах) хаят пхп, неужто все так плохо? Неужто будущее вебкодинга за жавой или руби и пхп доживает свое? Я в небольшом смятении. Все же на мой взгляд осваивать ту же джаву будет посложнее, да и результаты труда не будут видны непосредственно, как в случае с пхп.
Что скажете? Опыта кодинга у меня ноль целых хуй десятых.
Проверялка может ошибаться, пишите, я исправлю.
>>426600
Да
PHP бессмертен, легок для старта и за него относительно неплохо платят, да и работу найти не проблема. Хаят его в основном потому что он дружелюбек к новичкам что дает нам большое количество ньюфагов, пилящих небезопасный, нечитаемый, трудоподдерживаемый код. Но как и в любом другом ремесле, тут можно много добиться, если ты стараешься и готов постоянно учиться. Если коротко: если ты уебок и пишешь хуйню, ты будешь писать хуйню на любом языке.
Нет, на PHP написать хуйню проще, чем на Ruby. А на C++ до 11-го стандарта только хуйня и получалась. См. http://eev.ee/blog/2012/04/09/php-a-fractal-of-bad-design/ .
Ох, что то медленно двигается. То какую-то лажу напишу что все в итоге возвращаю обратно. То по полчаса не замечаю очевидную ошибку, и залипаю ни на чем.
Одно радует, что мотивация из ниоткуда пришла уже не раз в неделю возвращаюсь к задачке. Надеюсь она подержится подольше.
Аноны, можете пожалуйста подсказать. Есть такая проблема, сбоку есть категории, у некоторых их них есть подкатегории (но не у всех), надо сделать так что бы при нажатии на категории выводился либо список товаров на странице, либо список подкатегорий (если они есть конечно). К тому же есть две таблицы в базе данных, одна посвящена категориям и имеет один числовой параметр от которого зависит есть ли подкатегории у этой таблицы или нет. Если параметр равен -1 то подкатегорий нет, если не -1 то число которое он содержит в этом поле, говорит о том подкатегорией какой категории он является (этот параметр равен id этой категории, подкатегории и категории в одной таблице).
Есть ещё таблица со страницами, у каждой странице есть принадлежность к той или иной категории, при помощи определённого параметра который равен id категории в первой таблице. Теперь вопрос (может я слишком непонятно описал, мне кажется сам вопрос частично самодостаточен, в плане того что может обойтись и без написанного выше).
Как мне сделать так что бы при нажатие на категорию которая имеет подкатегорию, подкатегории выскакивали именно под ней, а не в конце списка?
Я делаю ттак, записываю в каждую категории в ГЕТ запрос её параметр ай-ди, по которому при нажатии можно выявить подкатегорию (если она есть), но в этом случае у меня подкатегории выскакивают в конце списка, как иначе сделать не знаю.
Использую сборку open server самую расширеную, при попытке вывода даты на кириллице, выводится в виде кракозябр, как исправить? Гугл говорит, что нужно с локалью что-то делать, как решить проблему? Заранее благодарю
Браузер не знает в какой кодировке страница и не может ее корректно отобразить. Поставь тег meta charset utf-8 (и убедись что исходник сохранен в utf8).
Не стоит тернарный оператор ?: применять там, где должен быть if. Тернарный оператор применяется в таких ституациях:
echo "Автор: " . ($name ? $name : 'Аноним');
То есть как часть выражения.
В твоем случае должен быть if.
Ну а за null можно и вовсе в угол поставить.
>>426674
>После редиректа не надо выводить страницу. Надо завершать скрипт.
Не понял.
>Гораздо удобнее тут исплоьзовать bindValue и обойтись без промежуточной переменной.
Сейчас посмотрел, тут так же объявляются переменные, как и с bindparam, прежде чем вносить их в функцию. В чем разница?
>та функция написана неправильно. Ведь между выполнением INSERT и вызовом getLastId другой процесс может вставить еще одну запись и ты прочитаешь не тот id
Нет, это функция возвращает количество всех записей в таблице, а не последний вставленный.
>Тут слишком мало вариантов кода получается. Надо сделать нормально, чтобы каждая буква выбиралась случайно.
Проще было тогда уж сделать поле пароля.
>Не хочешь потом как-нибудь порешать хорошие задачки на эту тему? https://gist.github.com/codedokode/58ebc90bd006baf4b35c
Хотел, кстати, порешать хтмл или ЖС, но в оп-посте не нашел эти ссылки, как и на ту задачу, которую я сейчас решаю. Почему их там нет?
> Сейчас посмотрел, тут так же объявляются переменные, как и с bindparam
Нет. С bindValue можно писать
$sth->bindValue(':x', $a->getX());
> Нет, это функция возвращает количество всех записей в таблице, а не последний вставленный.
Тогда почему она называется getLastId а не getCount? Это меня и сбило с толку.
Также, в функции еще 2 ошибки. Во-первых ты почему то берешь не последний id, а все что есть в таблице, все эти огромные массивы данных выбираются, пересылаются из mysql в php, и все ради того чтобы взять один элемент и выкинуть все остальные. Это неправильно, в таких ситуациях надо использовать LIMIT
Также, чтобы получить число записей в таблице неправильно брать id. Ведь записи могли быть удалены по какой-то причине. Чтобы найти число записей в MySQL есть функция COUNT: http://www.mysql.ru/docs/man/Counting_rows.html
Вообще, многие начинающие делают такие ошибки, ты не первый. Если ты не очень хорошо знаешь MySQL, я бы советовал параллеьно читать гайды и решать задачки вот отсюда: https://gist.github.com/codedokode/10539213
> Хотел, кстати, порешать хтмл или ЖС, но в оп-посте не нашел эти ссылки, как и на ту задачу, которую я сейчас решаю. Почему их там нет?
ОП пост и так большой. Посмотрим, может можно будет что-то выкинуть ради полезных ссылок. Действительно, они бы там не помешали.
Вот сами ссылки:
JS задачи: https://gist.github.com/codedokode/ce30e7a036f18f416ae0
JS проверялка: http://dkab.github.io/jasmine-tests/
HTML/CSS: https://gist.github.com/codedokode/58ebc90bd006baf4b35c
SQL: https://gist.github.com/codedokode/10539213
> Есть правда проблема: я не знаю как сделать, чтобы при сортировке, когда нажимаешь на вторую страницу, остальные Get переменные не пропадали.
Надо их передавать в ссылку, чтобы ссылка на вторую страницу содержала order и что там требуется:
index.php?order=name&dir=DESC&page=2
Также, у тебя там зачем-то куча переменных сделана:
> $directionName="ASC";
> $directionGroup="ASC";
> $directionPoints="ASC";
Зачем? Хватит 2 переменных, имя поля для сортировки и направление сортировки.
Кстати вместо 2 переменных (order и direction) можно в адресной строке использовать одну с именем поля и ставить знак минус для обратной сортировки:
order=-name
Ну то не требуется, твой вариант тоже годится.
У тебя еще ошибка: число 50 почему-то раскидано по 2 местам в коде:
> $pages = ceil($mapper->getLastId()/50);
> "SELECT name, sname, groupindex, points FROM students ORDER BY $sort $order LIMIT $num,50
Это конечно не годится. Это число надо поместить в переменную, чтобы оно задавалось только в одном месте.
> Есть правда проблема: я не знаю как сделать, чтобы при сортировке, когда нажимаешь на вторую страницу, остальные Get переменные не пропадали.
Надо их передавать в ссылку, чтобы ссылка на вторую страницу содержала order и что там требуется:
index.php?order=name&dir=DESC&page=2
Также, у тебя там зачем-то куча переменных сделана:
> $directionName="ASC";
> $directionGroup="ASC";
> $directionPoints="ASC";
Зачем? Хватит 2 переменных, имя поля для сортировки и направление сортировки.
Кстати вместо 2 переменных (order и direction) можно в адресной строке использовать одну с именем поля и ставить знак минус для обратной сортировки:
order=-name
Ну то не требуется, твой вариант тоже годится.
У тебя еще ошибка: число 50 почему-то раскидано по 2 местам в коде:
> $pages = ceil($mapper->getLastId()/50);
> "SELECT name, sname, groupindex, points FROM students ORDER BY $sort $order LIMIT $num,50
Это конечно не годится. Это число надо поместить в переменную, чтобы оно задавалось только в одном месте.
>>После редиректа не надо выводить страницу. Надо завершать скрипт.
> Не понял.
Ну вот ты там делаешь
> header("Location: $Configredirect");
А после этого программа продолжает работать и зачем-то выводит форму (которую никто не увидит так как браузер не отобразит ее, а сделает редирект). Надо после редиректа делать die.
А что за обучалка?
git book читал? http://git-scm.com/book/ru/v1/
Там в первой же главе написано зачем.
Гит (точнее любая система контроля версий) помогает делать 2 вещи:
- хранить историю изменений в коде, так что можно просмотреть ее и вернуться к любой старой версии
- делать ветки, то есть сделать какие-то изменения, но не вливать их в основной код
- при командной работе она позволяет объединять изменения вносимые участниками. Как без системы управления версиями работать над одним кодом несколькими людям? Нескольким десяткам людей? на флешке что ли измененные файлы носить друг другу? Это быстро надоедает.
Кстати, забыл описать еще одну проблему. При первом открытии сайта, после регистрации меня перекидывает не на зарегистрированный профиль, а на какой-то другой, вроде бы на предыдущий. Уже потом, если выйти и зарегистрироваться еще раз все работает нормально. А вот при первом открытии почему-то такой вот баг. Вроде бы все куки удаляются при выходе, с чего бы вдруг такая проблема возникает?
Без гита неопытные программисты часто вынуждены использовать римитивные способы, чтобы вести историю изменений. Например они делают кучу копий папки с проектом вида
project_23_марта_2014
project_с_работающим_удалением_пользователей
В общем, костыли какие-то, как будто это не программисты, а блондинки-секретарши которые компьютером пользоваться не умеют.
Попробуй поставить в начале файла var_dump($_COOKIE) чтобы увидеть что пришло в куках от браузера. На стороне браузера, если это Хром то куки можно просмотреть нажав Ctrl + Shift + I на вкладке Resources или Network.
В фаерфоксе куки есть в информации о странице.
>историю изменений
Но ведь в работе за час спокойно можно пару сотен раз изменения внести. Или эти системы позволяют вносить изменения по выбору, когда сделала что-то, а не постоянно топить?
Все участники проекта имеют свою, так сказать, копию проекта над которой работают и изменения из которой потом вливают в ту, которая в репозитории?и забирают оттуда текущую, когда захотят?
Я просто не могу представить как это происходит все на самом деле. Ебаная каша в голове.
Почитай "про гит", там все ответы на твои вопросы
У тебя нет баша потому что у тебя венда. Хватит уже стрелять себе в ноги, поставь хотя бы wubi и будет тебе и баш и все что хочешь. И никаких денверов.
Ты явно коммитишь изменения. Но вообще проблем никаких нет даже если там будут десятки тысяч коммитов.
> и изменения из которой потом вливают в ту, которая в репозитории?и забирают оттуда текущую, когда захотят?
Да. Были еще раньше централизованные системы вроде SVN где репозиторий был один, но у них недостаток что есть нет связи с ним то неельзя смотреть историю, коммитить, в общем когда у каждого свой репозиторий на практике удобнее, а что касается занимаемого места то с нынешними жесткими дисками это не проблема — большие репозитории по моему опыту занимают несколько сотен мегабайт, это терпимо. Плюс при желании там можно как-то совсем старые коммиты удалять.
> Я просто не могу представить как это происходит все на самом деле
C утра скачиваешь изменения других участников к себе. Потом пишешь код, коммитишь, пушишь на сервер. И так да бесконечности.
Если у тебя еще какие-то вопросы будут, обязательно задавй (но сначала почитай книгу git book).
На винде надо писать это в командной строке (пуск -> cmd). Вот мой гайд для начинающих по команжной строке: https://gist.github.com/codedokode/10539568
>>426820
Фигню же написал. Не всем же мак покупать, особенно с нынешним курсом доллара, можно и под виндой кодить.
И кто после этого фигню написал? Я про мак ни слова не сказал. Под той же бубунтой все это в разы удобнее, стоит попробовать.
> нужно в Bash ввести mysql -h localhost -u root -p
Не в bash а в командной строке в твоем случае. Эта команда всего лишь откроет командную строку управления mysql в которой можно писать запросы. Вот гайд для начинабщих по ней
http://jtest.ru/bazyi-dannyix/sql-dlya-nachinayushhix.html
http://jtest.ru/bazyi-dannyix/sql-dlya-nachinayushhix-chast-2.html
http://jtest.ru/bazyi-dannyix/sql-dlya-nachinayushhix-chast-3.html
Его стоит прочесть целиком
Насчет ошибки, покажи код или запрос которым ты пытался создать базу данных и что вывелось, текст ошибки. Тогда я скажу точную причину и что делать.
В чем смысл использовать недоделанную ОС для любителей ковыряться в исходниках вместо выпускаемой, тестируемой, развиваемой нормальной компанией?
Алсо можно подумать в убунте SQL запросы будут другие. Ты предлагаешь потратить кучу времени на то что никак не поможет решению проблемы.
Алсо лину удобнее всего ставить в виртуалбокс в режиме командной строки не подвергая риску основную систему.
Не знаю, я не предлагаю использовать недоделанную ОС
>Насчет ошибки, покажи код или запрос которым ты пытался создать базу данных и что вывелось, текст ошибки. Тогда я скажу точную причину и что делать.
Ты наверно зашел под анонимным пользователем у которого нет прав создавать базу. Тебе надо либо зайти из под администратора (root) либо создать (опять же из под администратора) пользователя с нужными праваим и заходить им.
Так что да, надо набирать
mysql -uroot -p
чтобы зайти в mysql под администратором.
Если что, справку по параметрам mysql (что значат -u, -p, -h) можно увидеть набрав в командной строке
mysql --help
Или подробно на англ. языке на оф сайте: http://dev.mysql.com/doc/refman/5.6/en/mysql.html
Как реализовать данныю шляпу? Мне подсказали <? include $_GET["view"] . 'chainsaw.php'; ?>, но я чет тугой и не разобрался как это прописать.
Помохите нубу.
Оче хуевая идея так делать. Лучше слегка разберись в теме, или накати что-то популярное.
ЛОЛ если уж и делать, то:
<? include $path_to_articles . '/chainsaw/' . $_GET["id"] . '/about.php'; ?>
Или возьми готовый движок, тот же Bitrix, там карточки товаров (инфоблоки) давно уже зделоли.
Проверил твое задание. Вот советы и замечания.
> https://github.com/tokotun/matriculant/blob/master/index.php#L2
> include 'config.php';
Логично все эти инклуды тоже перенести в bootstrap.php чтобы вначале достаточно было написать require_once('app/boostrap.php'); и все.
Алсо, загугли разницу между include и require.
Неиспользуемые файлы надо удалить. Что делает этот файл? https://github.com/tokotun/matriculant/blob/master/dataMapper.php
> https://github.com/tokotun/matriculant/blob/master/app/getLoginData.php
Что это за код написанный прямо в файле? Надо сделать функцию.
Насчет класса Pager, он получился не универсальным, а привязанным именно к этому приложению. Смотри сам:
> '?sort=' . $this->sort .
> '&order=' . $this->order .
> '&page=' . $i;
Ты не можешь использовать его где-то в другом месте из-за этого. Правильнее было бы передавать шаблон URL снаружи:
$pager = new Pager('index.php?sort=a&page=%d');
Тогда класс можно было бы использовать с любыми ссылками. Впрочем, у тебя в него еще и сортировка засунута, так что можно так оставить.
Насчет проверки токена: неправильно проверять XSRF токен в модели так как токен нужен для защиты от подделки отправки формы. Взаимодействием с формами и внешним миром занимается не модель, а контроллер и представление. Потому проверку надо вынести из модели, например в отдельную функцию, которая будет вызываться из login.php. Так будет правильнее.
При несовпадении токена не надо писать непонятные пользователю вещи вроде «Тоукен невалиден». Ну что по твоему в такой ситуации должен делать пользователь? Лучше написать «Произошла ошибка. Пожалуйста, попробуйте отправить форму еще раз.»
Алсо, почему тоукен? token же.
Кстати, для сортировки можно в URL использовать всего один параметр, имя поля, и добавлять знак минус для обратной сортировки: order=-name. Ну можно и так, как у тебя, конечно.
Теперь по поводу интерфейса. Вот советы и замечания:
Не очень, понятно, зачем ты пометил все ячейки классом success. Мне кажется, он предназначен для выделения одной или нескольких строк, а не всей таблицы и белая таблица смотрелась лучше. Ну да ладно, можно и так.
Для пагинации в бутстрапе есть стандартные классы: http://getbootstrap.com/2.3.2/components.html#pagination Используй их.
Ссылка «Войти/редактировать данные» должна содержать более правильный текст. «Зарегистрироваться» для нового пользователя и «Редактировать информацию о себе» для зарегистрировавшегося. Такие вещи тоже важны так как они путают пользователей.
Не хватает поиска — что такое? Я думал, ты уже все сделал, а оказывается поиска нет. Кстати, для формы поиска в бутстрапе тоже есть стандартное решение.
Далее, у тебя получилось двойное экранирование параметров (2 раза вызвана htmlspecialchars) в ссылке пагинации:
> <a href="/tokotun/index.php?sort=name&amp;order=ASC
надо из пейджера возвращать неэкранированную ссылку, а в шаблоне при выводе экранировать. Из-за этого параметры теряются при переходе на другую страницу.
При попытке зарегистрироваться мне пишет что «Тоукен невалиден». Что это значит? Ты тестировал свою программу без кук (например из приватного режима в браузере)?
Данные в форме все теряются. Я ввожу «Иван» в поле имени, и при попытке отправить форму выводятся ошибки, а поле очищается. Это неправильно. Даже если всю форму заполнить, из-за ошибки токена не удается зарегистрироваться.
label не связаны с input. Я кликаю по слову «Имя студента», а курсор в поле не ставится. ЧТобы все работало, надо чтобы атрибут for у label указывал на input.
Сортировка работает, только вот ширина колонок таблицы скачет при сортировке.
Сообщения об ошибках наверно лучше разместить справа от поля. А то все как-то вперемешку получается.
Если поле не заполнено, то лучше писать «Необходимо заполнить это поле», а не «Неверно введен номер группы».
Не забудь при получении данных из POST делать trim для всех полей, чтобы убрать лишние пробелы.
На странице регистрации стоит поставить ссылку «вернуться к списку» если вдруг человек передумает регистрироваться.
В общем, давай, исправляй баги и будем проверять дальше. Там немного осталось.
Проверил твое задание. Вот советы и замечания.
> https://github.com/tokotun/matriculant/blob/master/index.php#L2
> include 'config.php';
Логично все эти инклуды тоже перенести в bootstrap.php чтобы вначале достаточно было написать require_once('app/boostrap.php'); и все.
Алсо, загугли разницу между include и require.
Неиспользуемые файлы надо удалить. Что делает этот файл? https://github.com/tokotun/matriculant/blob/master/dataMapper.php
> https://github.com/tokotun/matriculant/blob/master/app/getLoginData.php
Что это за код написанный прямо в файле? Надо сделать функцию.
Насчет класса Pager, он получился не универсальным, а привязанным именно к этому приложению. Смотри сам:
> '?sort=' . $this->sort .
> '&order=' . $this->order .
> '&page=' . $i;
Ты не можешь использовать его где-то в другом месте из-за этого. Правильнее было бы передавать шаблон URL снаружи:
$pager = new Pager('index.php?sort=a&page=%d');
Тогда класс можно было бы использовать с любыми ссылками. Впрочем, у тебя в него еще и сортировка засунута, так что можно так оставить.
Насчет проверки токена: неправильно проверять XSRF токен в модели так как токен нужен для защиты от подделки отправки формы. Взаимодействием с формами и внешним миром занимается не модель, а контроллер и представление. Потому проверку надо вынести из модели, например в отдельную функцию, которая будет вызываться из login.php. Так будет правильнее.
При несовпадении токена не надо писать непонятные пользователю вещи вроде «Тоукен невалиден». Ну что по твоему в такой ситуации должен делать пользователь? Лучше написать «Произошла ошибка. Пожалуйста, попробуйте отправить форму еще раз.»
Алсо, почему тоукен? token же.
Кстати, для сортировки можно в URL использовать всего один параметр, имя поля, и добавлять знак минус для обратной сортировки: order=-name. Ну можно и так, как у тебя, конечно.
Теперь по поводу интерфейса. Вот советы и замечания:
Не очень, понятно, зачем ты пометил все ячейки классом success. Мне кажется, он предназначен для выделения одной или нескольких строк, а не всей таблицы и белая таблица смотрелась лучше. Ну да ладно, можно и так.
Для пагинации в бутстрапе есть стандартные классы: http://getbootstrap.com/2.3.2/components.html#pagination Используй их.
Ссылка «Войти/редактировать данные» должна содержать более правильный текст. «Зарегистрироваться» для нового пользователя и «Редактировать информацию о себе» для зарегистрировавшегося. Такие вещи тоже важны так как они путают пользователей.
Не хватает поиска — что такое? Я думал, ты уже все сделал, а оказывается поиска нет. Кстати, для формы поиска в бутстрапе тоже есть стандартное решение.
Далее, у тебя получилось двойное экранирование параметров (2 раза вызвана htmlspecialchars) в ссылке пагинации:
> <a href="/tokotun/index.php?sort=name&amp;order=ASC
надо из пейджера возвращать неэкранированную ссылку, а в шаблоне при выводе экранировать. Из-за этого параметры теряются при переходе на другую страницу.
При попытке зарегистрироваться мне пишет что «Тоукен невалиден». Что это значит? Ты тестировал свою программу без кук (например из приватного режима в браузере)?
Данные в форме все теряются. Я ввожу «Иван» в поле имени, и при попытке отправить форму выводятся ошибки, а поле очищается. Это неправильно. Даже если всю форму заполнить, из-за ошибки токена не удается зарегистрироваться.
label не связаны с input. Я кликаю по слову «Имя студента», а курсор в поле не ставится. ЧТобы все работало, надо чтобы атрибут for у label указывал на input.
Сортировка работает, только вот ширина колонок таблицы скачет при сортировке.
Сообщения об ошибках наверно лучше разместить справа от поля. А то все как-то вперемешку получается.
Если поле не заполнено, то лучше писать «Необходимо заполнить это поле», а не «Неверно введен номер группы».
Не забудь при получении данных из POST делать trim для всех полей, чтобы убрать лишние пробелы.
На странице регистрации стоит поставить ссылку «вернуться к списку» если вдруг человек передумает регистрироваться.
В общем, давай, исправляй баги и будем проверять дальше. Там немного осталось.
Еще если можешь хорошо бы подсвечиват ошибочные поля красным. В бутстрапе для этого есть класс
http://getbootstrap.com/2.3.2/base-css.html#forms
Промотай до раздела Validation states
Там кстати есть пример как текст ошибки выводить справа от поля.
Кнопочку лучше сделать синей и побольше чтобы она была заметнее: http://getbootstrap.com/2.3.2/base-css.html#buttons
Интернет магазин лучше делать на стандартной CMS а не на своем велосипеде.
Копипаста зло. Ты не должен копипастить 100 файлов, а должен сделать таблицу и хранить данные о бензопилах в ней.
>>426856
>>426880
Пацаны, я все понимаю, цмс напорядок упрощает создание больших сайтов-магазинов, работает луцше и вообще через жопу, так как я, никто не делает лет так много.
Но всеже хотелось бы увидь хотяб пример такой реализации через инклюд. Гуглил примеры, но ничего немогу найти того, что мне нужно, а именно живой пример, а не описание функции.
Судя по твоему вопросу, ты плохо знаешь PHP. Тебе нужно изучить этот язык прежде чем браться за написание сайтов. Без этого ты ничего не напишешь.
Либо, как тебе выше советовали, взять и допилить какую-нибудь CMS. Это и быстрее и проще.
Google:
php include example
php include sample code
php get parameters from url
и т.д.
У меня есть даже домашняя сраничка с тем, что тебе нужно, вот только... там создаётся объект $article и в нём уже вызывается include() и это слишком сложно для начинающего будет. ПРОСТО читай параметры из get-запроса и подключай страницы по "id", пусть это будет артикул товара.
Я прикрутил к сайту 2 слайдера, стилизовал их не зная ни jq ни js. Это не к тому, что я такой охуенный, просто сейчас делаю сайт знакомому, у меня нет пары недель на поверхностное изучение языка, темболее что есть основная работа и времени свободного немного.
Я пилю потиху сайт, гуглю что непонятно, если не могу нагуглить- спрашиваю у анона.
В данном случае я не могу найти именно пример кода, подходящего для моей ситуации. Как именно должна выглядеть ссылка на странице, чтобы при ее нажатии открывалась этаже страница но с содержимым, указанным в ссылке. Именно точный синтаксис. Принцип работы инклюда я знаю, у меня на всех страницах типа контакты, о компании и тд. футер, хедер и новости через инклюд.пхп. Но тут все понятно.
На том же http://www.w3schools.com/ я конкретно это ненахожу, а интерпретировать и переделать что-то похожее я не понимаю как, просто не знаю как правильно писать.
И да, я естественно не требую от анона помогать мне, но было бы неплохо.
Ставил, и там и там, прописывал Lang в html и body, ничего, но когда ставишь кодировку 1251, отображается коряво все, кроме даты, парадокс
А, видимо php не умеет дату в utf8 выводить. Найди или напиши свою функцию для вывода русских дат тогда. Это лучше чем полагаться на локали которых на сервере может не быть. По крайней мере под линуксом и виндой они по разному называются и я не уверен есть ли в винде utf8.
Тебе кажется уже писали об этом. Определяй через гет-параметр. При клике на товар добавляй к ссылке параметр. То есть ссылка вида parasha.php?N=2, у тебя в скрипте в массиве $_GET будет лежать N => 2, берешь и делаешь запрос в базу, получаешь на выходе всякую хуйню и подставляешь в шаблон. Говорят что это хуевый метод, но для начала сойдет. Кстати, олдфаги, как правильно будет?
Какой запрос в базу? Есть куча 1.php, 2.php, 3.php, в них лежит инфа по 1,2,3 позициям. Я спрашивал про синтаксис, как правильно пишется код вплоть то точки с запятой ибо точного примера не, соответствующего моему примеру не нашел. Я не знаю как код написать чтоб он работал.
В базу заноси всю инфу. То, как ты сейчас делаешь даже пхп не требует.
>Какой запрос в базу? Есть куча 1.php, 2.php, 3.php, в них лежит инфа по 1,2,3 позициям.
Так не делается. Если у тебя 3 позиции товара, и для каждого товара страничка одинаковая, не считая там например фото товара, цены и характеристик, то делать 3 скрипта не нужно. Нужно хранить свойства товара в базе и доставать по уникальному id товара. Иначе у тебя разница между 1.php 2.php и 3.php минимальная, зачем по 10 раз писать одно и тоже?
>Я не знаю как код написать чтоб он работал.
Справочник по синтаксису похапе читается за вечер, максимум два: http://php.net/manual/ru/langref.php
А что если через регулярные, возможно ли?
То есть там где стоит голый и простой if не нужен он? Его стоит впихивать туда, где по идее стоит if + else ?
Нет. Смоти, if — это когда тебе надо выполнить какую-то команду при определенном условии:
if (условие) {
команда;
}
if ($a == 1) {
$b++;
}
Тернарный оператор — это когда тебе надо получить какое-то значение в зависимости от условия:
$x = условие ? значение1 : значение2;
echo условие ? строка1 : строка2;
То есть тернарный операто используется как часть выражения. В нем не должны стоять команды изменяющие значения переменных вроде $a = 1 или $b++. Такие команды всегда должны быть отдельной строкой, а не спятаны внутри выражения.
Правила php конечно позволяют использовать тернарный оператор (а также логические операторы && и ||) как замену if, но это усложняет понимание кода. Вряд ли тому кто читает код охота разгадывать подобные ребусы, хочется чтобы он был написан как можно проще и очевиднее.
Уже раз десять. Да и ни причем параметр. Говорю же то через минуту вылазит ошибка, то пишу пост на двачик минут 5, после чего возвращаюсь в консоль и запрос выполняется сразу.
Ну я бы посоветовал тебе поставить линух, но меня тут уже один раз захуесосили на эту тему, так что подождем богов веб-разработки под вендой.
Не старадай хуйней, освой работу в консоли.
1. Создаешь репозиторий на гитхабе.
2. Тянешь его на комп дома.
3. Работаешь
4. коммит=>пуш
5. на работ повторяешь шаги 2-4
6. делаешь пулл дома когда пушил на работе и наоборот
Остальное освоешь по ходу дела
Какая версия MySQL? Похоже на баг.
Я тоже сталкивался с таймаутом (если ты например полчаса ничего не вводишь) но второй раз запрос вводить не надо, он сам пересоединятся и выполняется.
Если у тебя есть фаерволл/антивирус, можно попробовать его временно отключить чтобы понять не в нем ли проблема.
Какая версия MySQL (запрос SELECT VERSION( ); )?
Что выводит SHOW VARIABLES LIKE '%timeout%';
Нет. Надо почитать git book: http://git-scm.com/book/ru/v1/
Без понимания как работает гит ничего не выйдет
Спасибо, но тут наткнулся на тему товарища на форуме опенсервера с такой же проблемой. Оказывается есть еще interactive_timeout, поставил его на 10 минут. Вроде как полет нормальный.
На первой картинке видно, что последний айди 73, а зашел я на сайт под 72ым. Такого быть не может, я выходил будучи в 73 профиле, а зашел обратно на 72ом. Далее при выходе и последующей регистрации в первый раз перебрасывает не на новый профиль, а опять же на страницу регистрации, и куки не сохранились, как видно на картинказ 2 и 3. Последующие регистрации работают нормально и в куки сохраняется то, что должно, но вот при первом входе на сайт происходят такие странные вещи.
Ставь не 10 минут а например 30 000 секунд лучше.
>>427287
Открой отладчик в браузере (Ctrl + Sift + I), в нем вкладку Network. Сделай какое-нибудь действие, ставящее куки, например регистрацию. В отладчике появится запрос, посмотри в нем заголовки. Если сервер ставит куки то там будет заголовок Set-cookie с параметрами куки. Его формат описан например тут:
https://ru.wikipedia.org/wiki/HTTP_cookie#.D0.90.D1.82.D1.80.D0.B8.D0.B1.D1.83.D1.82.D1.8B_.D0.BA.D1.83.D0.BA.D0.B8
Проверь правильные ли они. Также, запости их сюда, я тоже посмотрю.
>Ставь не 10 минут а например 30 000 секунд лучше.
Чего так много? И вообще должен же быть какой то смысл у того что этот параметр по умолчанию имел 30 секунд? Я понимаю что если поставлю 30 000 то уж точно не столкнусь с проблемой отваливания коннекта, но все же интересно зачем этот параметр вообще нужен и почему бы он такой мелкий был.
>>427299
Вот картинка.
https://gist.github.com/krbn/52f5ffc42bc893994991
Остальное тут, если что. https://github.com/krbn/news
Это мое тестовое задание, кстати. Надо до понедельника сделать, и меня возьмут на стажировку.
параметр описан в мануале http://dev.mysql.com/doc/refman/5.0/en/server-system-variables.html#sysvar_interactive_timeout
По умолчанию он равен 28800
В твоем случае авторы openserver (или это ты поставил?) зачем-то его понизили: https://github.com/stden/openserver/blob/master/userdata/config/MySQL-5.5.25_my.ini.txt#L41 . Зачем — не знаю, лучше наверно ставить mysql самому а не использовать сборки.
В set-cookie code и email какие значения выставляются? Для нового зарегистистрированного пользователя или нет?
После регистрации var_dump показывает те же значения кук что были в Set Cookie?
Если не для нового то ошибка в твоем коде, ты не те куки ставишь.
В headers показывает те значения, которые я выставлял. В var_dump неправильные, от предыдущего профиля.
Используй шаблоны чтобы не смешивать html и php: http://www.phpinfo.su/articles/practice/shablony_v_php.html
Ну и тестовое задание должно проверять твои знания а не мои.
Значит сервер шлет заголовок Set Cookie но браузер почему-то не принимает его и не заменяет значения кук. Проверь еще вкладку Resources в отладчике, в ней в разделе Cookies выводятся сохраненные в браузере куки и посмотри там их параметры.
И еще, посмотри что шлется из браузера на сервер (на вкладке Network при открытии страницы) в заголовке Cookie.
Ну что поделать, поищи. Я потом конечно еще твой код проверю, но попробуй сам найти.
Также, если ты менял какие-то параметры кук то может то как-то связано.
Также, для чистоты эксперимента стоит почистить куки (удалить на вкладке resources или удалить глобально через Ctrl + Shift + Del или через приватный режим тестировать).
Получается проблема выглядит так:
- при очистке кук в браузере и первой регистрации мы попадаем в чужой профиль
- если выйти через функцию выхода и зарегистрироваться то все ок?
Все верно?
Если зайти на сайт в первый раз то возможны два варианта:
1.При выходе из текущего профиля и последующей регистрации нас выбрасывает на пустую страницу регистрации, куки тоже пустые
2. При выходе из текущего профиля и последующей регистрации нас кидает в другой профиль, как на скринах выше.
А потом уже все ок.
> Если зайти на сайт в первый раз
Надо в самом начале очищать куки в браузере или использовать приватный режим. Иначе непонятно, может у тебя там до сих пор неделю назад установленная кука жива.
Я сейчас попробовал зарегистрироваться — в первый раз регистрация сработала, куки выставились и я вижу свою страницу.
Я нажал выход. Он попытался очистить куки заголовком
Set-Cookie:studentscookie[email]=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT
studentscookie[name]=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT
studentscookie[code]=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT
Но они не очистились и после редиректа я по-прежнему залогинен.
(почему куки не очистились? потому что для них не задан path а так как твой сайт у меня в папке /mm/ то он выставил для удаляемых кук path = /mm и эти куки не смогли затереть те что имели path=/ )
Я добавил path в функцию logOut и после этого куки стали удаляться. И я теперь снова могу регистрироваться и все ок.
В общем, почитай очень внимательно как определяется path для кук и зачем он нужен: http://citforum.ru/internet/html/cookie.shtml
Я думаю что причина проблем в том, что у тебя не был явно задан path при удалении кук и в итоге удаленные куки действовали не на всем сайте, а только на части. А на остальной части сайта действовали куки с path = /
То есть у тебя было 2 набора кук: один с path = / и другой с path = /profile.php например и это создавало разные нехорошие эфффекты.
Очисти куки в браузере, исправь код, проставив path для каждого setcookie и протестируй заново. И не забудь почитать как работает path.
> Если зайти на сайт в первый раз
Надо в самом начале очищать куки в браузере или использовать приватный режим. Иначе непонятно, может у тебя там до сих пор неделю назад установленная кука жива.
Я сейчас попробовал зарегистрироваться — в первый раз регистрация сработала, куки выставились и я вижу свою страницу.
Я нажал выход. Он попытался очистить куки заголовком
Set-Cookie:studentscookie[email]=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT
studentscookie[name]=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT
studentscookie[code]=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT
Но они не очистились и после редиректа я по-прежнему залогинен.
(почему куки не очистились? потому что для них не задан path а так как твой сайт у меня в папке /mm/ то он выставил для удаляемых кук path = /mm и эти куки не смогли затереть те что имели path=/ )
Я добавил path в функцию logOut и после этого куки стали удаляться. И я теперь снова могу регистрироваться и все ок.
В общем, почитай очень внимательно как определяется path для кук и зачем он нужен: http://citforum.ru/internet/html/cookie.shtml
Я думаю что причина проблем в том, что у тебя не был явно задан path при удалении кук и в итоге удаленные куки действовали не на всем сайте, а только на части. А на остальной части сайта действовали куки с path = /
То есть у тебя было 2 набора кук: один с path = / и другой с path = /profile.php например и это создавало разные нехорошие эфффекты.
Очисти куки в браузере, исправь код, проставив path для каждого setcookie и протестируй заново. И не забудь почитать как работает path.
Исправил функцию logOut:
setcookie('studentscookie[email]', "", time()-3600, '/');
setcookie('studentscookie[name]', "", time()-3600, '/');
setcookie('studentscookie[code]', "", time()-3600, '/');
Теперь не перебрасывает на чужой профиль. НО. Осталась еще одна проблема >>427287
Теперь при первой регистрации меня перебрасывает снова на регистрацию, а не в профиль и куки пустые. Стоит мне закрыть сайт и снова открыть его, и у меня уже куки те, что я только что зарегистрировал. Далее, если зарегистрироваться еще раз то все нормально, но если выйти и зайти на сайт, то на сайт зайдет под предыдущем зарегистрированным профилем а не текущем.
А хотя нет, вот сейчас снова перебросило, когда я зарегистрировался, меня кинуло на предыдущий профиль. Путь выставил, в чем проблема?
Ты очистил все куки в браузере (Ctrl + Sift + del) перед тестированием? Если нет то у тебя могут быть старые куки.
И ты всегда открываешь сайт на одном и том же домене, то есть www.students.ru а не students.ru?
Ну так students.ru и www.students.ru это разные домены. И куки установленные на одном могут быть недоступны на другом. И у тебя может опять быть 2 набора кук которые пересекаются.
Прочитай еще и про домен у кук:
http://stackoverflow.com/a/1063760 (англ)
http://citforum.ru/internet/html/cookie.shtml
Как я понимаю кука выставленная для students.ru доступна и на поддомене www, а вот обратное неверно.
Правильное рещение использовать только один домен, а не 2. А с неправильного домена редиректить на правильный.
Да. Причем куки со students.ru по умолчанию доступны и на www, а обратное неверно.
Это описано в RFC и честно говоря все эти правила про path и domain довольно сложны, я сам наизусть их не помню: http://tools.ietf.org/html/rfc6265#section-5.2.3 (англ)
Чтобы не иметь проблем надо использовать один домен, а также всегда стаивть path = /
Если кука ставится с поддомена то можно указать домен = students.ru явно но в твоем случае проще использовать только главный домен всегда.
В общем я надеюсь ты из всего этого извлек умение пользоваться отладчиком и понимание как передаются и хранятся куки.
Bindvalue так и не поставил, лень переписывать, но это ведь не критично, верно?
После пары лет работы над проектом в режиме
>лень переписывать, но это ведь не критично, верно?
уже решительно невозможно что-то разобрать или исправить. Проще переписать с нуля. Такие дела.
мимо-переписывал-бомбануло
Но аромат борща твоей мамки еще хуже.
Да ладно тебе.
Я уже сам разобрался. Запендюрил смарти по самые гланды.
Может хоть глянешь, скажешь правильно или нет? (Я волшебное слово знаю, пожалуйста блджад! Ну что ты ломаешься как девочка.)
https://github.com/krbn/news/blob/master/index.php
https://github.com/krbn/news/blob/master/templates/index.tpl
В общем я год работал версталой и jQuery программистом и теперь решил перекатываться в настоящий фронтенд. Но оказывается, что js это нихуя не jQuery, а без знания этого самого js никуда двигаться не получается.
Что эффективнее всего читать/смотреть/делать для обучения js на?
Алсо, мои нынешние знания vanilla.js по этой нерабочей параше, которую я пинал 3 часа http://jsfiddle.net/6540egqe/
Если не сложно - обоссыте
html,body,div,span,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,abbr,address,cite,code,del,dfn,em,img,ins,kbd,q,samp,small,strong,sub,sup,var,b,i,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,figcaption,figure,footer,header,menu,nav,section,summary,time,mark,audio,video{margin:0;padding:0;border:0;outline:0;font-size:100%;vertical-align:baseline;background:transparent;}body{line-height:1;}article,aside,details,figcaption,figure,footer,header,menu,nav,section{display:block;}nav ul{list-style:none;}blockquote,q{quotes:none;}blockquote::before,blockquote::after,q::before,q::after{content:'';content:none;}a{margin:0;padding:0;font-size:100%;vertical-align:baseline;background:transparent;}ins{background-color:#ff9;color:#000;text-decoration:none;}mark{background-color:#ff9;color:#000;font-style:italic;font-weight:bold;}del{text-decoration:line-through;}abbr[title],dfn[title]{border-bottom:1px dotted;cursor:help;}table{border-collapse:collapse;border-spacing:0;}hr{display:block;height:1px;border:0;border-top:1px solid #cccccc;margin:1em 0;padding:0;}input,select{vertical-align:middle;}
Это чо? Ты откуда-то это говно скопипастил или как так получилось?
Алсо в файрфоксе не работает. Потому jQuery и используют.
Знать стандартные методы полезно, конечно, но их знание != понимание js. Почитай теорию (была где-то целая серия постов с переводами на хабре) и начинай практиковаться. Сейчас во фронтенде используют SPA-фреймворки, парочку из них можешь попердолить ради интереса, в процессе и понимание придет. Я дико угорел по Reactjs, особенно после ангуляра, теперь форсю его везде.
Влад?
Ах да, еще:
1) По JS можешь сделать задачи ОПа: https://gist.github.com/codedokode/ce30e7a036f18f416ae0
2) Выглядит твоя хуйня неплохо в результате. Код критиковать не буду, сам не б-г JS, да и лень сильно вникать.
>30-40к
Нормально ты устроился с одним годом опыта. Это какой-то один заказчик или уже успел поработать с несколькими за два месяца? На какой бирже работаешь? Сколько часов в день примерно? Что именно делаешь?
Ну я еще в офисе фриланс начал осваивать по вечерам/выходным, так что получается около 7 месяцев.
Заказчиков много, как постоянных, так и разовых.
В день 8-12 часов, как повезет. Работаю на всех более менее крупных биржах.
Заказы только на верстку + немного jquery и php.
За год надрочился очень быстро верстать, поэтому и выходит иногда по 2, а то и 3 проекта в день. Хотя после нового года заказчиков стало поменьше
Но от этих лендингов, бмщиков и прочего скама уже блевать тянет. Поэтому и хочу освоить тот же ангулар, как белый человек.
Для офиса может и средне, но во фрилансе это неплохие деньги для такого опыта. За что платят? Верстка йоба-лендингов по готовому макету?
>В день 8-12 часов
Ну тогда нормально, а то я ж охуел слегка. 8-12 часов это суровое въебование.
>Верстка йоба-лендингов по готовому макету
~70% заказов
10% правки чужого говна.
Остальное интернет-магазины, порталы и вот это всё.
Да, ты правильно думаешь, надо начать с изучения JS, а потом можно и за Backbone/Knockout/Angular и подобные инструменты браться.
Задания на JS https://gist.github.com/codedokode/ce30e7a036f18f416ae0
проверялка для первых 10: http://dkab.github.io/jasmine-tests/
> Что эффективнее всего читать/смотреть/делать для обучения js на?
learn.javascript.ru неплохой учебник. Фленаган, которого советуют, тоже неплохой. Javascript the Good parts Крокфорда тоже известная книга.
> мои нынешние знания vanilla.js по этой нерабочей параше,
Код конечно страшноват, так как состоит из тяжелочитаемой и повторяющейся колбасы вроде
> body.querySelector('.innder_image_filed').style.marginTop = -(body.querySelector('.innder_image_filed img').offsetHeight)/2 + 'px';
\t\tsetTimeout(next, 10)
Строки конечно должны быть короче.
> close = function() {
Можно же писать function close() {}, зачем усложнять все?
>>427547
reset это очень плохая вещь, придуманная не осилившими CSS индусами (и популярная так как таких много). Не используйте ее.
Почему? Потому что никто потом не возвращает сброшенные стили и списки, текст начинают выглядеть как сплошная стена без отступов и абзацев. В браузере выставлены неплохие стили по умолчанию, надо уметь их использовать а не сбрасывать все в ноль. У меня reset css синоним слова быдлокод.
Да, ты правильно думаешь, надо начать с изучения JS, а потом можно и за Backbone/Knockout/Angular и подобные инструменты браться.
Задания на JS https://gist.github.com/codedokode/ce30e7a036f18f416ae0
проверялка для первых 10: http://dkab.github.io/jasmine-tests/
> Что эффективнее всего читать/смотреть/делать для обучения js на?
learn.javascript.ru неплохой учебник. Фленаган, которого советуют, тоже неплохой. Javascript the Good parts Крокфорда тоже известная книга.
> мои нынешние знания vanilla.js по этой нерабочей параше,
Код конечно страшноват, так как состоит из тяжелочитаемой и повторяющейся колбасы вроде
> body.querySelector('.innder_image_filed').style.marginTop = -(body.querySelector('.innder_image_filed img').offsetHeight)/2 + 'px';
\t\tsetTimeout(next, 10)
Строки конечно должны быть короче.
> close = function() {
Можно же писать function close() {}, зачем усложнять все?
>>427547
reset это очень плохая вещь, придуманная не осилившими CSS индусами (и популярная так как таких много). Не используйте ее.
Почему? Потому что никто потом не возвращает сброшенные стили и списки, текст начинают выглядеть как сплошная стена без отступов и абзацев. В браузере выставлены неплохие стили по умолчанию, надо уметь их использовать а не сбрасывать все в ноль. У меня reset css синоним слова быдлокод.
Ты странные вещи пишешь. Знать JS надо чтобы изучать библиотеки на нем.
> Я дико угорел по Reactjs, особенно после ангуляра, теперь форсю его везде.
В большинстве случаев ни тот ни другой не нужны (так как решают специфические задачи: написание SPA приложения). Инструмент надо выбирать исходя из задачи, а не из того о чем прочел вчера на Хабре.
И мне ангулар не нравится. Шаблонизатор в нем неплох, но все остальное, включая свои странные велосипеды для создания классов, фабрики абстрактных файбрик, ужасно.
Ну а реакт где предлагается писать HTML код прямо внутри JS это вообще шаг назад. Это напонимает код начинающего php программиста котоый посмотрел курсы специалиста и html c php в один файл складывает.
> Знать JS надо чтобы изучать библиотеки на нем.
Ой, я фигню выше написал, я подумал, что ты хотел сказать, что изучать vanilla JS не нужно вообще.
> Знать JS надо чтобы изучать библиотеки на нем
Чтобы быстро понимать чужой код. По большей части это касается библиотек, да, потому что это твои основные инструменты.
>В большинстве случаев ни тот ни другой не нужны (так как решают специфические задачи: написание SPA приложения)
В случае если на фронтенде логики вообще нет или ее очень мало – тогда не нужны. Но с каждым годом ее там становится все больше, а поддерживать и развивать jQuery-лапшу чаще всего просто неудобно. С jQuery не получится создать понятный, структурированный код и единственная причина по которой jQuery так широко используется – недостаточная сформированность и молодость MVC фреймворков. Уже в ближайшие пару лет весь фронтенд код будет построен на MV* даже в мелких проектах, просто потому что это в 100 раз удобнее.
>реакт где предлагается писать HTML код прямо внутри JS это вообще шаг назад
Так никто и не пишет внутри JS, все используют jsx.
>недостаточная сформированность и молодость
В том смысле что api в 90% этих фреймворков в ближайшем будущем изменится и многие погромисты этого опасаются, но тот же react уже достаточно давно production-ready и используется в куче проектов уровня airbnb и codeacademy.
как сделать, чтобы, например, POST данные передавались между страницами? Почему-то суперглобальные переменные(пост, сешн, куки) обнуляются при переходе по ссылкам пагинации.
Это плохо, потому что я не могу сохранить значения фильтров при переходе на страницы, там 10ю например. Всё сбивается
Когда ты переходишь на новую страницу на сервере запускается новый скрипт с нуля. Никакие переменные не сохраняются.
Чтобы сохранять сортировку/фильтры надо в ссылки пагинации добавлять парамеры сортировки и фильтрации например
index.php?page=2&order=name&category=5
Конечно данные можно сохранять в куках/сессии, но в данном случае это не годится, так как тогда во всех вкладках будет одинаковая сортировка + нельзя скопирвать ссылку с нужной сортировкой.
Смысла выводить 100 номеров страниц нет.
Форму фильтра лучше сделать через GET а не POST чтобы можно было скопировать ссылку на результаты.
окей, я тоже об этом думал, но как сделать так, чтобы get запросы не перетирали друг друга в юрл. и как сделать, чтобы страничка правильно парсила эти гет запросы, ведь их будет несколько, если выставить различные параметры фильтров
Почему не хочет работать? Коннекта к mysql нет? Использую пакет Denwer.
Читай что в ошибке написано. Параметр переданный в mysql_num_fields() булевый (тру или фолс), так быть не должно.
Я понимаю, что так быть не должно, я не понимаю почему так есть. Начал разбираться с SQL пару дней назад.
ты просто выполняешь запрос, но никак не преобразовываешь его в данные, с которыми можно работать. Используй mysql_fetch_array, или mysql_fetch_object. Функции преобразуют запрос в массив\объект. Например:
$q = mysql_fetch_array(mysql_query("SELECT * FROM pet"));
извиняюсь, не читай. не до конца твой код прочел
<b>Warning</b>: mysql_fetch_array() expects parameter 1 to be resource, boolean given in <b>K:\home\localhost\www\php\SQL.php</b> on line <b>22</b><br />
После mysql_query воткни echo mysql_error. А ругается оно, потому что mysql_query false возвращает из-за ошибки. А ошибка в том, что второй аргумент mysql_connect - имя юзера, а база выбирается mysql_select_db.
пофиксил строчку коннекта $link = mysql_connect($host);
добавил строчку выбора бд:
mysql_select_db($database) or die("Не могу подключиться к базе.");
В итоге выполняется второе условие (die). Когда захожу через cmd в mysql пароль не ввожу, набираю только mysql -u root; как узнать под кем заходить через mysql_connect()?
И еще в die выводи mysql_error, чего гадаешь-то?
И еще посмотри, что у тебя в базе с привилегиями:
SHOW GRANTS; через консольку
У него mysql query вернул false почему-то
>>427694
Поставь вот этот код
> echo "ERROR " . mysql_errno() . " " . mysql_error() . "\n";
После строчки SELECT FROM pet - он должен вывести причину ошибки
Ну и еще. Расширение MySQL давно устарело. Сейчас используют PDO: http://habrahabr.ru/post/137664/ Найди время почитать мануал по ссылке.
Также, у тебя может быть выключено отображение всех ошибок или их часть.
В PHP по умолчанию выключено отображение ошибок в браузере, так как обычному пользователю сайта эта информация ни к чему. Но тебе, как программисту, надо видеть эти ошибки. Вот, как можно их просмотреть:
- ошибки сохраняются в лог ошибок. Можно открыть его и почитать. Если ты запускаешь код на локалхосте, у себя, то лог хранится в папке Апача (обычно она называется logs) и имеет название вроде error.log (в линуксе в папку /var/log/apache2 ). Если на хостинге — там либо есть файл error.log либо раздел в панели управления, где лог можно посмотреть
- также, ты можешь включить отображение ошибок. Открой файл php.ini, поставь там display_errors = On и error_reporting = E_ALL и перезапусти сервер. Теперь ошибки должны выводиться на экран.
Проверить, работает ли вывод ошибок, можно запустив скрипт содержающий обращение к несуществующей переменной вроде echo $sdgasdad; и проверив, выведется ошибка или нет. Если все верно, то должна вывестись.
Страничка ничего не парсит. GET параметры не будут перетирать друг друга если у них разные имена.
>>427705
Под тем же аккаунтом. Пользователь 'root', пароль '' (пустая строка)
>>427711
Тебе надо разобраться с отображением ошибок. При ошибке соединения MySQL выдает Warning: Cannot connect to MySQL ... и если у тебя этого сообщения не было то у тебя что-то отключено в настройках и это плохо.
> , чтобы get запросы не перетирали друг друга в юрл
Ты по моему не очень понял как работает _GET. Этот массив с нуля заполняет PHP на основе данных из URL.
И эти GET параметры никуда не сохраняются. Если сейчас ты открываешь
index.php?a=1
ТО $_GET['a] содержит 1, но если ты после этого откроешь
index.php
То _GET будет пустой, то есть он каждый раз пересоздается с нуля и ничего от старого скрипта в нем не сохраняется.
Это так называемый REST, когда содержимое странички зависит только от параметров в URL и ничего нигде скрытно не сохраняется, все на виду.
но я всё же не понимаю как получить сразу два параметра, например index.php?a=1?b=2
> Уже в ближайшие пару лет весь фронтенд код будет построен на MV* даже в мелких проектах, просто потому что это в 100 раз удобнее.
Нет. дело не в удобстве, а в том что разные инструменты для разных целей.
Есть сайты (где например нажатие на кнопку раскрывает форму комментирования) и есть веб-приложения. Конечно для SPA нам нужны модели на клиенте (и на сервере скорее всего тоже, причем как я понимаю никаких стандартных методов для этого нет. Я когда-то давно делал такое через трансляцию php классов в JS), шаблонизация на клиенте, дата байндинг.
Но для сайтов-страниц вроде блога это все оверкил. Чтобы при нажатии кнопки раскрыть форму, отправить коммент аяксом и добавить его в список, лучше всего подходит jQuery иначе ты будешь заниматься бесполезной работой по дублированию функционала какого-нибудь вордпресса на клиенте. Чтобы оживить корзину интернет магазина, хватит формы и кучки скриптов на jQuery.
Конечно, очень много фронтендщиков неопытны и имеют низкий уровень знаний, они этого могут не понимать, и они могут захотеть сделать блог целиком на клиентсайде. Это даже может стать модным и популяным среди их неграмотных коллег. Что поделать.
Вообще, мне кажется каждый инструмент лучше подходит для своих целей. И стремление все сделать на яваскрипте на клиенте так же нездорово как принципиальный отказ от яваскрипта. Ну и одно дело делать todo app на 10 записей и восхищаться и другое дело реальный большой сложный сайт с большим объемом данных, разделов, шаблонов — тут много подвохов.
> недостаточная сформированность и молодость MVC фреймворков.
У нас на серверсайде все нормально с этим.
>>реакт где предлагается писать HTML код прямо внутри JS это вообще шаг назад
> Так никто и не пишет внутри JS, все используют jsx.
Даже название JSX намекает что это то же самое.
Тебе стоит для начала почитать вики тогда: https://ru.wikipedia.org/wiki/URL#.D0.A1.D1.82.D1.80.D1.83.D0.BA.D1.82.D1.83.D1.80.D0.B0_URL
Я поправляю небольшой сайт на Джумле и сейчас не понимаю как изменить определенный шаблон , надеюсь анон подскажет.
Я сделал портфолио заказчика в виде:
http://galeriaufa.ru/portfolio-otzyvy.html
(Pic 1)
На сайте есть раздел Новости: http://galeriaufa.ru/novosti.html , pic2 ,
Я хотел просто применить существующий шаблон , но общей страницы новостей нет в материалах. Есть материал каждой новости в отдельности , их изменение затрагивает нужную мне страницу , но получается что вроде pic 3 , хотя в css прописал для этого класса display:inline-block.
Ткните мне пальцем пожалуйста- где изменять этот шаблом или на худой конец как мне правильно разместить их оперируя разными материалами.
Я прокомментирую по второму скриншоту что справа от картинки должен быть отступ 10-15 px чтобы отбить ее от текста. Ну как на это можно спокойно смотреть?
> хотя в css прописал для этого класса display:inline-block.
Не гадай а проверь инспектором (Ctrl Shift I) какие там стили применены.
Насчет шаблонов, они там могут храниться не на диске, а в базе и редактировать их тогда надо через админку. Также там может быть вместо правильного решения сделано все как-то через костыли.
Изучи например мануал по натягиванию верстки на Джумлу для начала. Такая документация обычно называется «docs for template designers/docs for developers» и обычно есть на официальном сайте. Но я сегодня решил даже нагуглить за тебя русский перевод этой документации:
http://joomla.ru/docs/administrator/joomla3-start/1749-dizajn-maket-tsveta65
http://joomla-book.ru/development/creating-templates
session_destroy
Алсо что значит «с куки»? Сессии хранятся на сервере, в куке только id сессии.
http://codepad.viper-7.com/E5NrKq
точно, спасибо
http://codepad.viper-7.com/F2UqVu
Два вопроса:
1. Почему не переносит строку? Или это из-за эмулятора?
2. Почему выводит неправильный ответ? В чем опять я ошибся?
>1. Почему не переносит строку? Или это из-за эмулятора?
Вероятно. Почему ты используешь эту херню? ОП рекомендует ideone.
>2. Почему выводит неправильный ответ? В чем опять я ошибся?
Запускай на идеоне: http://ideone.com/f4UOju
нашел ошибку, было anonDice1 два раза
Строчку не переносит потому что в HTML перенос строки это <br />, в пхп есть даже функция n12br, которая заменяет все \n в коде на br
Неправильно потому что у тебя на самом деле другие числа.
>У анона выпало {$anonDice1} и {$anonDice1}
Чтобы переносы строк нормально работали и в браузере и и в консоли, можно использовать для этого \n, а в начале программы поставить
header("Content-Type: text/plain; charset=utf-8");
Это заставит браузер воспринимать то, что выводит твоя программа, как обычный текст, а не HTML, и уважать переносы строк в нем (так как в языке HTML перенос строки равносилен пробелу).
Иначе перенос строки будет в исходном коде страницы (его можно увидеть нажав Ctrl + U), но на самой странице его не будет.
Она имеет в виду что пхп лучше не использовать для визуального оформления сайта? Или что-то иное и я не правильно ее понял?
Что скажете, лорды? К слову в книге говорится что в интернете всего 20% сайтов сделанных на пхп, что так же расходится с цифрой 90% которую я встречал ранее.
>GUI-приложений
>Она имеет в виду что пхп лучше не использовать для визуального оформления сайта?
пиздец
GUI приложения это не сайт а программа с графическим интерфесом то есть окошками, кнопками и т д. Например, Блокнот Windows, Excel и подобное. Не стоит их писать на PHP.
>>428226
Задания на MySQL: https://gist.github.com/codedokode/10539213
Учебник дает лишь основы PHP. Чтобы научится делать на нем сайты и приложения, надо заниматься еще. С уроками на ти темы у нас не очень, но задания есть. В ходе их решения ты изучишь как на PHP выдавать страницы в браузер, работу с таблицами в БД, работу с формами, MVC, может еще что-то.
Задание на PHP:
- попроще https://gist.github.com/codedokode/d7e7f11449fc3bcb24b4
- сложнее https://gist.github.com/codedokode/9424217
Чтобы делть эти задания, тебе надо установить Апач + PHP (можно заодно сразу и MySQL) на компьютер. Вот полезные инструкции:
https://gist.github.com/codedokode/10774100
https://gist.github.com/codedokode/7054af4a03865c4cc863
Может тебе понадобится пользоваться командной строкой, вот гайд https://gist.github.com/codedokode/10539568
Вот небольшой туториал по тому как начать использовать PHP с сервером и браузером: https://php.net/manual/ru/tutorial.php
Увы, уроков плавно подводящих к тому, как сделать задачи выше, пока нет, так что если что задавай вопросы.
Решения задач лучше показать мне, особенно на ООП,так как сам ты вряд ли увидишь все ошибки.
Книга по гиту: http://git-scm.com/book/ru/v1
Если что задавай вопросы. Это как раз тред для начинающих. Показывай код по хожду решения — чем раньше найдем ошибку тем меньше переделывать.
GUI приложения это не сайт а программа с графическим интерфесом то есть окошками, кнопками и т д. Например, Блокнот Windows, Excel и подобное. Не стоит их писать на PHP.
>>428226
Задания на MySQL: https://gist.github.com/codedokode/10539213
Учебник дает лишь основы PHP. Чтобы научится делать на нем сайты и приложения, надо заниматься еще. С уроками на ти темы у нас не очень, но задания есть. В ходе их решения ты изучишь как на PHP выдавать страницы в браузер, работу с таблицами в БД, работу с формами, MVC, может еще что-то.
Задание на PHP:
- попроще https://gist.github.com/codedokode/d7e7f11449fc3bcb24b4
- сложнее https://gist.github.com/codedokode/9424217
Чтобы делть эти задания, тебе надо установить Апач + PHP (можно заодно сразу и MySQL) на компьютер. Вот полезные инструкции:
https://gist.github.com/codedokode/10774100
https://gist.github.com/codedokode/7054af4a03865c4cc863
Может тебе понадобится пользоваться командной строкой, вот гайд https://gist.github.com/codedokode/10539568
Вот небольшой туториал по тому как начать использовать PHP с сервером и браузером: https://php.net/manual/ru/tutorial.php
Увы, уроков плавно подводящих к тому, как сделать задачи выше, пока нет, так что если что задавай вопросы.
Решения задач лучше показать мне, особенно на ООП,так как сам ты вряд ли увидишь все ошибки.
Книга по гиту: http://git-scm.com/book/ru/v1
Если что задавай вопросы. Это как раз тред для начинающих. Показывай код по хожду решения — чем раньше найдем ошибку тем меньше переделывать.
Да, и в этом треде где-то выше кидал один из вариантов кошек-мышек, я исправил некоторые замечания ОПа, но потерял интерес к задачке.
Кстати, для оформления сайта используется HTML/CSS, а не PHP. PHP используется только чтобы сформировать и отдать в браузер HTML код.
Спасибо, попробую сделать https://gist.github.com/codedokode/10539213
,а по Mysql я твою статью и читал, там где в начале ссылка на мануал, и 2 задачки. С гитом я вроде немного разобрался, я тот анон у которого фрустрация была после первого знакомства с гит.
>русский автор
Ну а тут что не так? Вон оп тоже русский. Тем паче у нас неплохие программисты частенько выходят.
>GUI приложения это не сайт а программа с графическим интерфесом то есть окошками, кнопками и т д. Например, Блокнот Windows, Excel и подобное. Не стоит их писать на PHP.
Спасибо, так яснее.
Первое что в голову пришло http://robokassa.ru/ru/
Вообще их много, погугли, посмотри какой лучше.
Ну а если собираешься прикручивать конкретную систему типо яд, то думаю логичнее всего у них же на сайте и поискать документацию по прикручиванию.
Давно когда-то смотрел робокассу, мне не понравилось что там очень много шагов и много данных спрашивается. Это и оплате через СМС, там был очень плохой и неудобный интефейс (крупные сайты потому делают свое окошко оплаты без ухода с сайта — оно лучше работает). Но это было давно.
Это снижает процент конверсии. Ну и люс двойная комиссия в сравнении с прямым подключением.
>>428246
В случае яндекса там надо официаольно от оганизации обращаться: https://money.yandex.ru/joinups
Доки: https://money.yandex.ru/merchants/
https://money.yandex.ru/doc.xml?id=526382
После согласования яндекс высылает документацию по интеграции (которая и так есть в откытом доступе) и данные для боевого и тестового сервера. На тестовом сервере можно создать тестовый кошелек и с него оплачивать, правда тестовый сервер может глючить, по моему опыту.
Вот вроде бы доки по подключению: https://money.yandex.ru/doc.xml?id=526537
Это только о яндексу.Если надо много способов оплаты то наверно проще через агрегатора, но процесс оплаты будет менее удобен и меньше человек заплатит.
У меня на работе как один из вариантов оплаты стоит робокасса. Как показывает практика клиент предпочитает платить именно с ее помощью. Такие дела.
> Это только о яндексу.Если надо много способов оплаты то наверно проще через агрегатора, но процесс оплаты будет менее удобен и меньше человек заплатит.
Действительно, это так удобно для пользователя когда пара вариантов оплаты, вместо пары десятков где он может выбрать наиболее удобный для себя.
А по поводу робокассы - ни разу не пользовался, просто дал человеку понять что существуют сервисы что за процент решат проблему оплаты через кучу платежных систем.
Не понятно. Они у тебя в мускуле или что? Или тебя абстрактный алгоритм интересует?
Их еще нет у меня, но будут и мне придется что то с ними делать. Вот что именно делать - я и хочу понять.
Ты довольно абстрактно описал. Я так понял у тебя будет таблица со столбцами: Название, Год выпуска, страна выпуска, продолжительность, етц.
Так? Если ты будешь их руками вносить в мускуль, зачем вносить дубли? Или можешь внести все, добавив AUTO_INCREMENTкаждой следующей запили будет добавляться порядковый номер, больший на 1 от предыдущего, что делает каждую строку уникальной и потом разгрести средствами мускуля. Там тончо есть такие фичи, но конкретно не подскажу.
Нет, все прозаичней) Я буду парсить сайт (торрент), мне нужны названия фильмов без дубликатов. Названия я получу строкой.
Немного теорий на ночь.
> можешь внести все, добавив AUTO_INCREMENTкаждой следующей запили будет добавляться порядковый номер, больший на 1 от предыдущего, что делает каждую строку уникальной и потом разгрести средствами мускуля. Там тончо есть такие фичи, но конкретно не подскажу.
шта
Сначала зарегестрируйся
Вот такая ошибка, думаю где то в этом коде.
$sql = "SELECT * FROM matriculant WHERE name LIKE ? ORDER BY $orderBy $order LIMIT :skipResult, :resultPerPage";
$statment = $this->db->prepare($sql);
$statment->bindValue(':skipResult', $skipResult);
$statment->bindValue(':resultPerPage', $resultPerPage);
$statment->execute(array("%$userSearch%"));
Это еще почему?
И почему из класса можно обращаться к методам экземпляра, а из экземпляра к статическим методам?
Есть мнение что это бесполезное подключение еще одной внешней зависимости, из который далеко не факт что все понадобиться. Я например в последнем проекте не использовал reset.css, а по итогам верстки собрал свой css-файл из тех мест где надо было сбросить стили. Получилось меньше чем reset.css.
Котанские поясните если не сложно такой момент. В одном файле описаны все функции, они подключаются ко всем файлам интернет-магазина. В этом файле описана функция которая добавляет пришедший id и количество товара в сессии:
function addToBasket($id,$q) {
$_SESSION[$id]=$q;
}
Эта функция вызывается в файле который обрабатывает добавление в корзину, в случае нажатия на ссылку "ВКОРЗИНУ" в каталоге товаров. Но в сессию сохраняется только последнее значение, и никак не получается сохранить ряд заказанных товаров. Я видимо не понимаю как работают сессии но это же суперглобальный массив и он должен сохранять всё подряд лишь-бы названия разные были? В данном случае без вспомогательного массива в котором можно хранить данные просто не обойтись?
list($width, $height) = getimagesize('14215306748581.jpg');
$newWidth = 1280;
$newHeight = 1024;
$cropRatioX = $newWidth / $width;
$cropRatioY = $newHeight / $height;
$cropRatio = max(array($cropRatioX, $cropRatioY));
$newCropWidth = round($width $cropRatio);
$newCropHeight = round($height $cropRatio);
$cropX = ($newCropWidth - $newWidth) / 2;
$cropY = ($newCropHeight - $newHeight) / 2;
$cropX = ($newCropWidth > $newCropHeight) ? $cropX : 0;
$cropY = ($newCropHeight > $newCropWidth) ? $cropY : 0;
$image_p = imagecreatetruecolor($newWidth, $newHeight);
$image = imagecreatefromjpeg('14215306748581.jpg');
imagecopyresampled($image_p, $image, 0, 0, $cropX, $cropY, $newCropWidth, $newCropHeight, $width, $height);
imagejpeg($image_p, __DIR__ . '/name.jpg');
Разобрался. Добавил пару строк:
$x = ($newCropWidth > $newCropHeight) ? $x : 0;
$y = ($newCropHeight > $newCropWidth) ? $y : 0;
И поменял строку
imagecopyresampled($image_p, $image, $x, $y, $cropX, $cropY, $newCropWidth, $newCropHeight, $width, $height);
>$x = ($maxWidth > $maxHeight) ? ($cropX / 2) (-1) : 0;
>$y = ($maxHeight > $maxWidth) ? ($cropY / 2) (-1) : 0;
fix
Алсо, мне осталось допилить только проверку на количество файлов в директории. Я уже нагуглил как это делается и, думаю, сегодня вечером или завтра сделаю. Пока добавлю здесь черновичок чтобы потом не чего не забыть и не запутаться. Если есть есть какая-то критика, то буду рад услышать.
http://pastebin.com/ZQcHES2e
Я же уже писал. Он
> сбрасывает все стили текста, списков, таблиц и прочее
При этом 99% верстальщиков никогда не выставляют эти стили назад. А те кто выставляют занимаются довольно бесполезной работой: сбрасывают стили чтобы затем их прописать снова.
Так как никто не возвращает стили назад то на сайтах с CSS reset как правило текст выглядит как сплошная стена без отступов и абзацев, списки без точек и паддинга, таблицы с вжатыми друг в друга без промежутков ячейками. Если ты на каком-то сайте видишь такое — тут скорее всего поработал ресет.
Более того, стили по умолчанию прописаны в браузерах не для того, чтобы вредить верстальщику, а наоборот, чтобы текст по умолчанию выглядел более менее читаемо. Глупо с ними бороться.
Сам собой напрашивается вопрос: зачем подключать этот ресет если с ним получается хуже?
Некоторые малограмотные (таких кстати большинство) верстальщики думают что подключение css reset как-то волшебным образом сделает их верстку кроссбраузерной. Но в итоге у них получается не кроссбраузерная верстка, а слипшийся текст и списки без точек. Правильное решение не сбрасывать стили, а уметь пользоваться инспектором, верстать по стандатам, хорошо знать CSS, тестировать верстку в разных браузерах.
Популярный css фреймворк Twitter Bootstarp и html 5 boilerplate не использует Css reset (это я пишу на случай если тебе нужно более авторитетное, а не более правильное мнение).
Не надо вот этого.
Статьи по работе с чем-то, что там может применятся, вот это нужно примерно.
То я и сам нашел, но там слишком "сухой" язык документации, мне бы примеры использования посмотреть, где это человеческим языком пояснятся для дебилов-неосиляторов.
http://php.net/manual/ru/curl.examples-basic.php
Просто берешь и читаешь в тех же доках что значит каждый параметр в примере. Или например подумай о том что бы ты хотел сделать курлом и гугли.
>>427386
Я сейчас посмотрел твой код. А ты исправил все замечания, которые я давал ранее, вот тут >>426674 ? А то мне приходится некоторые из них писать по второму разу. Почему не хочешь исправлять?
> https://github.com/MindiMakridi/Students/blob/master/students.sql#L32
> `sex` enum('М','Ж')
Для ENUM обычно используют латинские обозначения, например male/female
> if(isset($_POST['exit'])){
> logOut( );
> header("Location: $currentPage");
После редиректа надо делать die, а то у тебя скрипт продолжает зачем-то дальше работать
> https://github.com/MindiMakridi/Students/blob/master/profile.php
Здесь в строках 39-65 надо поправить отступы, а то код трудно читать
> https://github.com/MindiMakridi/Students/blob/master/profile.php#L64
> die("Регистрация завершена");
Ты по моему не понял, как работает HTTP редирект. Когда браузер получает заголовок Location то он переходит по нему, а не отображает содержимое страницы с заголовком Location. Потому твой текст никто не увидит. Хотя с другой стороны, от того что ты вывел текст, ничего плохого не случится.
> https://github.com/MindiMakridi/Students/blob/master/lib/DataMapper.php#L131
> $result = $STH->fetch( );
> $id = $result[0];
Чтобы получить значение только первой колонки, удобнее использовать не fetch (получить массив значений), а http://php.net/manual/ru/pdostatement.fetchcolumn.php
Я вижу ты переписал генерацию кода. По моим прикидкам, там сейчас получается 1000 ^ 6 = 10 в 18 степени вариантов, что приемлемо, но ты зря пытаешься изобрести свои способы генерации. Вот посмотри, например вот это вот:
> mb_substr($string, mt_rand(0, $length-1), mt_rand(1, $length-1));
плохой способ генерации так как он генерирует предсказуемые куски строки, где буквы идут по порядку, вроде «abcdef». Более того, с высокой вероятностью третий аргумент (длина подстроки) будет таким, что символов не хватит, и мы получим одинаковые результаты. Ну например, если второй аргумент ( mt_rand(0, $length-1) ) указывает на последний символ, цифру 0, то каким бы не был третий аргумент, мы получим подстроку из одного символа «0». Это делает такую подстроку гораздо более вероятной и сами случайные последовательности более предсказуемые. Ты наверно думал, чем больше символов, тем лучше, но в реальности если ты получаешь подстроку из идущих подряд букв, это почти не добавляет защищенности, так как эта подстрока определена ровно 2 числами: начальной позицией и длиной и это дает меньше вариантов, чем 2 случайно взятые буквы.
То есть не надо изобретать странные способы генерации строки, надо просто брать N случайных символов, между которыми нет никакой связи.
> Управляющая конструкция с двоеточими и endif вызывает ошибку unexpected string T_ENDIF, а <?=?> вместе с содержимым выводится как хтмл код
С этой проблемой надо разобраться. Покажи мне код который не работает, я сам проверю. Если все работает, то перепиши foreach на синтаксис с двоеточием, а <?php echo меняй на <?=
Также, я вижу ты используешь br в верстке. Тебе явно стоит потом пройти мои задачки на HTML/CSS.
Чтобы не писать везде длинную функцию htmlspecialchars(..., ENT_QUOTES) можно сделать свою функцию с названием h или html и использовать ее.
Постраничная навигация выглядит очень плохо: цифры мелкие и идут без промежутков: __12345__ , как их читать? Добавь хотя бы пробелы. Текущую страницу надо как-то выделить, чтобы было видно на какой мы находимся.
Опция $recordsPerPage = 10; в конфиге не учиытвается: когда я ее меняю, в пагинации все равно стоит ссылка на 2-ю страницу вида index.php?num=50. Надо это исправить.
Когда пользователь делает сортировку, надо возвращать его на первую страницу. Если я например жму на колонку с баллами, то я хочу увидеть самых лучших или худших учеников, а не середину списка. Да и так как записи теперь отсортированы по-новому, сохранять номер страницы нет смысла.
При сортировке надо рядом с заголовком колонки выводить стрелочку, чтобы было видно что по ней идет сортировка, и в каком направлении.
При применении поиска надо выводить сообщение и ссылку для сброса поиска, вроде такого:
> Показываются только студенты, найденные по словам «иван». __Показать всех__
Также, в поле поиска надо оставить введенную туда строку.
При заполнении формы не надо очищать неправильно заполненные поля, надо показывать введенное туда значение. Может я случайно лишнюю букву или знак ввел, и хочу их удалить.
Фамилию вроде «Тянь-Шанский» ввести не получается. Иностранные фамилии почему-то тоже.
Явно неправильный email «ололо me@mail.ru ололо» проходит проверку.
Около поля «Пол» не выводится сообщения об ошибке если его не выбрать.
После регистрации/изменения данных хорошо бы выводить вверху зеленьким цветом: «Вы успешно зарегистрировались»/«Изменения сохранены» чтобы было видно что все работает.
var_dump COOKIE ты забыл убрать.
При чтении данных из формы надо делать trim. У тебя если в поле «номер группы» ввести «1234 » (добавить пробел в конце), вываливается ошибка, но ведь этот пробел можно случайно нажать и не заметить и долго искать причину, почему форма не отправляется. Надо делать trim и отрезать лишние пробелы.
Сообщения об ошибках можно оставить такими, но вообще, лучше делать их более информативными. Например: «Пожалуйста, укажите ваш номер группы. Он должен состоять из 4 или 5 цифр» или «В имени нельзя использовать символ '@'». Так как угадать что имеется в виду под «Неверный формат данных» очень трудно. Надо помогать людям заполнять форму, а не говорить им «ты криворукий, не можешь даже имя правильно ввести, попробуй теперь догадайся что не так».
В остальном, хорошо, я вижу что простейший сайт c формами и таблицами на PHP ты сделать можешь. Но не стоит на этом останавливаться, я советую дальше делать задание на файлообменник, изучать фреймворк Slim и шаблонизатор Twig.
А да, чем ты редактируешь код? Каким редактором?
>>427386
Я сейчас посмотрел твой код. А ты исправил все замечания, которые я давал ранее, вот тут >>426674 ? А то мне приходится некоторые из них писать по второму разу. Почему не хочешь исправлять?
> https://github.com/MindiMakridi/Students/blob/master/students.sql#L32
> `sex` enum('М','Ж')
Для ENUM обычно используют латинские обозначения, например male/female
> if(isset($_POST['exit'])){
> logOut( );
> header("Location: $currentPage");
После редиректа надо делать die, а то у тебя скрипт продолжает зачем-то дальше работать
> https://github.com/MindiMakridi/Students/blob/master/profile.php
Здесь в строках 39-65 надо поправить отступы, а то код трудно читать
> https://github.com/MindiMakridi/Students/blob/master/profile.php#L64
> die("Регистрация завершена");
Ты по моему не понял, как работает HTTP редирект. Когда браузер получает заголовок Location то он переходит по нему, а не отображает содержимое страницы с заголовком Location. Потому твой текст никто не увидит. Хотя с другой стороны, от того что ты вывел текст, ничего плохого не случится.
> https://github.com/MindiMakridi/Students/blob/master/lib/DataMapper.php#L131
> $result = $STH->fetch( );
> $id = $result[0];
Чтобы получить значение только первой колонки, удобнее использовать не fetch (получить массив значений), а http://php.net/manual/ru/pdostatement.fetchcolumn.php
Я вижу ты переписал генерацию кода. По моим прикидкам, там сейчас получается 1000 ^ 6 = 10 в 18 степени вариантов, что приемлемо, но ты зря пытаешься изобрести свои способы генерации. Вот посмотри, например вот это вот:
> mb_substr($string, mt_rand(0, $length-1), mt_rand(1, $length-1));
плохой способ генерации так как он генерирует предсказуемые куски строки, где буквы идут по порядку, вроде «abcdef». Более того, с высокой вероятностью третий аргумент (длина подстроки) будет таким, что символов не хватит, и мы получим одинаковые результаты. Ну например, если второй аргумент ( mt_rand(0, $length-1) ) указывает на последний символ, цифру 0, то каким бы не был третий аргумент, мы получим подстроку из одного символа «0». Это делает такую подстроку гораздо более вероятной и сами случайные последовательности более предсказуемые. Ты наверно думал, чем больше символов, тем лучше, но в реальности если ты получаешь подстроку из идущих подряд букв, это почти не добавляет защищенности, так как эта подстрока определена ровно 2 числами: начальной позицией и длиной и это дает меньше вариантов, чем 2 случайно взятые буквы.
То есть не надо изобретать странные способы генерации строки, надо просто брать N случайных символов, между которыми нет никакой связи.
> Управляющая конструкция с двоеточими и endif вызывает ошибку unexpected string T_ENDIF, а <?=?> вместе с содержимым выводится как хтмл код
С этой проблемой надо разобраться. Покажи мне код который не работает, я сам проверю. Если все работает, то перепиши foreach на синтаксис с двоеточием, а <?php echo меняй на <?=
Также, я вижу ты используешь br в верстке. Тебе явно стоит потом пройти мои задачки на HTML/CSS.
Чтобы не писать везде длинную функцию htmlspecialchars(..., ENT_QUOTES) можно сделать свою функцию с названием h или html и использовать ее.
Постраничная навигация выглядит очень плохо: цифры мелкие и идут без промежутков: __12345__ , как их читать? Добавь хотя бы пробелы. Текущую страницу надо как-то выделить, чтобы было видно на какой мы находимся.
Опция $recordsPerPage = 10; в конфиге не учиытвается: когда я ее меняю, в пагинации все равно стоит ссылка на 2-ю страницу вида index.php?num=50. Надо это исправить.
Когда пользователь делает сортировку, надо возвращать его на первую страницу. Если я например жму на колонку с баллами, то я хочу увидеть самых лучших или худших учеников, а не середину списка. Да и так как записи теперь отсортированы по-новому, сохранять номер страницы нет смысла.
При сортировке надо рядом с заголовком колонки выводить стрелочку, чтобы было видно что по ней идет сортировка, и в каком направлении.
При применении поиска надо выводить сообщение и ссылку для сброса поиска, вроде такого:
> Показываются только студенты, найденные по словам «иван». __Показать всех__
Также, в поле поиска надо оставить введенную туда строку.
При заполнении формы не надо очищать неправильно заполненные поля, надо показывать введенное туда значение. Может я случайно лишнюю букву или знак ввел, и хочу их удалить.
Фамилию вроде «Тянь-Шанский» ввести не получается. Иностранные фамилии почему-то тоже.
Явно неправильный email «ололо me@mail.ru ололо» проходит проверку.
Около поля «Пол» не выводится сообщения об ошибке если его не выбрать.
После регистрации/изменения данных хорошо бы выводить вверху зеленьким цветом: «Вы успешно зарегистрировались»/«Изменения сохранены» чтобы было видно что все работает.
var_dump COOKIE ты забыл убрать.
При чтении данных из формы надо делать trim. У тебя если в поле «номер группы» ввести «1234 » (добавить пробел в конце), вываливается ошибка, но ведь этот пробел можно случайно нажать и не заметить и долго искать причину, почему форма не отправляется. Надо делать trim и отрезать лишние пробелы.
Сообщения об ошибках можно оставить такими, но вообще, лучше делать их более информативными. Например: «Пожалуйста, укажите ваш номер группы. Он должен состоять из 4 или 5 цифр» или «В имени нельзя использовать символ '@'». Так как угадать что имеется в виду под «Неверный формат данных» очень трудно. Надо помогать людям заполнять форму, а не говорить им «ты криворукий, не можешь даже имя правильно ввести, попробуй теперь догадайся что не так».
В остальном, хорошо, я вижу что простейший сайт c формами и таблицами на PHP ты сделать можешь. Но не стоит на этом останавливаться, я советую дальше делать задание на файлообменник, изучать фреймворк Slim и шаблонизатор Twig.
А да, чем ты редактируешь код? Каким редактором?
Не бред так как учат MVC и правильной разработке. Плюс, бложек не такая простая вещь: там рано или поздно захочется теги, древовидные комменты, плюсование, медиавложения и тд.
Я не знаю книг про то, как написать блог на php (по идее они и не нужны — достаточно знать сам php, как работать с формами, с БД и так далее), но у фреймворков в туториале в качестве примера как раз часто делают блог.
А без знания фреймворков, как правило люди пишут лапшу из смеси php, html и sql запросов в одном файле. Не думаю, что такое произведет впечатление в качестве портфолио.
Sublime плох тем что в нем нет умного автодополнения и автоматического переформатирования кода. Может быть, стоило бы попробовать попользоваться IDE вроде PhpStorm/Netbeans PHP/Eclipse PDT? Да и отладчика в саблайме нет. Ну хотя если ты можешь в саблайме качественно код писать, можно и в нем.
А ты протокол HTTP знаешь? Может для начала стоит про него хотя бы в вики почитать? curl это ведь HTTP клиент.
Если у тебя есть конкретные вопросы (например «как выставить заголовок в запросе»), можешь писать тут, я потом отвечу.
>>428558
Когда пишешь скобки и точку с запятой, надо писать
( звездочка пробел звездочка );
Например: hello( );
И спам лист отступит.
> Проблема в том, то что видимо класс караванграббера не видит получаемый объект
Это как? Если написать в конструкторе караванграббера var_dump($caravan); что выводится?
По моему так все должно работать. Поясни что именно не так.
> допилить только проверку на количество файлов в директории
Там можно проще поступить, можно класть файл в папку с именами из первых символов, например:
Файл превьюшки имеет имя kitten.jpg
Кладем его в папку /k/i/kitten.jpg
При таком подходе, есди предположить что имена файлов случайно распределены, то у нас будет 26 × 26 = 676 комбинаций из 2 букв что дает 676 папок. Если в каждую положить по 500 файлов, то получается мы можем хранить где-то 338000 файлов (это исходя из предположения что они распределены равномерно по папкам).
Если использовать не две, а три буквы то получается 17576 вариантов комбинаций, и более 8 млн. файлов.
Разумеется если имена файлов начинаются одинаково, они попадут в одну папку и подход не сработает.
Другой вариант — использовать в названии папки дату загрузки файла (так делает вордпресс), например /2014/10/kittemn.jpg. У нас это не работает так как у нас нет такого понятия как дата загрузки. Но если бы она была, то это был бы простой и хороший вариант, не требующий базы данных.
Еще вариант — считать число-хеш от имени файла и помещать файл в папку с таким именем. Ну например допустим что хеш от имени kitten.jpg равен 124 значит мы сохраняем файл в папку
/124/kitten.jpg
Хеш-функция это функция которая получеает на вход любую строку и выдает число в заданном диапазоне.
Разумеется, надо правильно подобрать хеш-функцию. Например стандартная функция crc32() дает значения от -2 млрд до +2 млрд, если убрать знак минус и поделить результат на 1 млн. то получим число от 0 до 2000. Это число можно исплоьзовать в качестве имени папки. Если у нас 2000 папок и файлы распределяются по ним равномерно то мы можем хранить 1 млн файлов (из расчет 500 файлов в одной папке). Если сделать число от 0 до 20 000 то уже 10 млн. преимущество этого подода в том что папка вычисляется по имени файла и не требуется БД, так же мы можем регулировать число папок.
Ну и можно конечно реализовать все это через БД. Тогда мы можем класть имя файла в базу, брать его id и поделив на 500 получим номер папки. Например файл с id = 3400 помещается в папку 3400 / 500 ~ номер 6.
Варианты без базы данных по моему удобнее. ну ладно, покажешь код, посмотрим.
Заметь что многие подходы, которые я предложил, неточные: они не гарантируют что в папке будет меньше 500 файлов в некоторых случаях. Но в реальности они вполне работают и решабют проблему «у меня миллион превьюшек в одной папке».
> допилить только проверку на количество файлов в директории
Там можно проще поступить, можно класть файл в папку с именами из первых символов, например:
Файл превьюшки имеет имя kitten.jpg
Кладем его в папку /k/i/kitten.jpg
При таком подходе, есди предположить что имена файлов случайно распределены, то у нас будет 26 × 26 = 676 комбинаций из 2 букв что дает 676 папок. Если в каждую положить по 500 файлов, то получается мы можем хранить где-то 338000 файлов (это исходя из предположения что они распределены равномерно по папкам).
Если использовать не две, а три буквы то получается 17576 вариантов комбинаций, и более 8 млн. файлов.
Разумеется если имена файлов начинаются одинаково, они попадут в одну папку и подход не сработает.
Другой вариант — использовать в названии папки дату загрузки файла (так делает вордпресс), например /2014/10/kittemn.jpg. У нас это не работает так как у нас нет такого понятия как дата загрузки. Но если бы она была, то это был бы простой и хороший вариант, не требующий базы данных.
Еще вариант — считать число-хеш от имени файла и помещать файл в папку с таким именем. Ну например допустим что хеш от имени kitten.jpg равен 124 значит мы сохраняем файл в папку
/124/kitten.jpg
Хеш-функция это функция которая получеает на вход любую строку и выдает число в заданном диапазоне.
Разумеется, надо правильно подобрать хеш-функцию. Например стандартная функция crc32() дает значения от -2 млрд до +2 млрд, если убрать знак минус и поделить результат на 1 млн. то получим число от 0 до 2000. Это число можно исплоьзовать в качестве имени папки. Если у нас 2000 папок и файлы распределяются по ним равномерно то мы можем хранить 1 млн файлов (из расчет 500 файлов в одной папке). Если сделать число от 0 до 20 000 то уже 10 млн. преимущество этого подода в том что папка вычисляется по имени файла и не требуется БД, так же мы можем регулировать число папок.
Ну и можно конечно реализовать все это через БД. Тогда мы можем класть имя файла в базу, брать его id и поделив на 500 получим номер папки. Например файл с id = 3400 помещается в папку 3400 / 500 ~ номер 6.
Варианты без базы данных по моему удобнее. ну ладно, покажешь код, посмотрим.
Заметь что многие подходы, которые я предложил, неточные: они не гарантируют что в папке будет меньше 500 файлов в некоторых случаях. Но в реальности они вполне работают и решабют проблему «у меня миллион превьюшек в одной папке».
> из экземпляра к статическим методам?
Это можно. К статическим методам (с учетом private/public разумеется) можно обращаться откуда угодно, так как им не нужен экземпляр объекта. То есть писать
A::someStaticMethod()
можно везде. В этом плане статический метод очень охож на обычную функцию.
> почему из класса можно обращаться к методам экземпляра
Это можно делать только в нескольких случаях:
parent::x() — обращение к методу родительского класса. При этом значение this сохраняется. Обычно это используется когда мы переопределяем метод в наследнике. например:
http://ideone.com/gS52jz
Это полезная и нужная вещь. Как ты иначе в примере вызовешь getName из родительского класса?
self::x(), static::x() — странная конструкция, которую я не советую использовать так, как приведено в примере номер 3. Видимо это рабоатет, но в других языках так не делают и тут делать не стоит.
> Объясните пожалуйста примеры 3 и 4
Лучше задавать конретно что именно непонятно. А то я не знаю, что именно объяснять.
Пример 3:
Этот пример писали наркоманы. Никогда не стоит писать такой код. Я сам толком не понимаю почему он работает, он очень запутан. Если бы меня по нему поспрашивали, я мог бы и ошибиться.
Лучше всего загрузить его на ideone и подправить: http://ideone.com/ccuhFF чтобы было понятнее.
Сначала мы создаем объект класса B и вызываем в нем метод test. В нем мы вызываем foo и вызывается тот foo который в классе A и содержит echo. Так и должно быть. Пока все нормально. Затем мы используем вызов static::foo. Вот тут начинаются чудеса. Так как мы вызывали test через
$b->test()
То у нас static по идее указывает на класс B. И static::foo по идее должен пытаться вызвать тот foo что объявлен в классе B, которого там нет, и падать с ошибкой. Казалось бы. Но по какой-то неведомой причине в этой ситуации вызывается A#foo, я сам не понял почему, видимо какая то хитрая особенность PHP. В любом случае, через static вызывать нестатические методы не стоит.
Поясню фразу «которого там нет». Приватный метод по определению принадлежит только классу A и в других классах его нету. Потому то, что static::foo срабатывает, это очень странно.
Затем при вызове через класс С static::foo интерпретируется как C::foo и происходит ошибка доступа к приватному методу.
Сам пример в общем ненормальный: в других языках через self/static можно вызывать только статические методы и подобных проблем с пониманием кода не возникает.
> из экземпляра к статическим методам?
Это можно. К статическим методам (с учетом private/public разумеется) можно обращаться откуда угодно, так как им не нужен экземпляр объекта. То есть писать
A::someStaticMethod()
можно везде. В этом плане статический метод очень охож на обычную функцию.
> почему из класса можно обращаться к методам экземпляра
Это можно делать только в нескольких случаях:
parent::x() — обращение к методу родительского класса. При этом значение this сохраняется. Обычно это используется когда мы переопределяем метод в наследнике. например:
http://ideone.com/gS52jz
Это полезная и нужная вещь. Как ты иначе в примере вызовешь getName из родительского класса?
self::x(), static::x() — странная конструкция, которую я не советую использовать так, как приведено в примере номер 3. Видимо это рабоатет, но в других языках так не делают и тут делать не стоит.
> Объясните пожалуйста примеры 3 и 4
Лучше задавать конретно что именно непонятно. А то я не знаю, что именно объяснять.
Пример 3:
Этот пример писали наркоманы. Никогда не стоит писать такой код. Я сам толком не понимаю почему он работает, он очень запутан. Если бы меня по нему поспрашивали, я мог бы и ошибиться.
Лучше всего загрузить его на ideone и подправить: http://ideone.com/ccuhFF чтобы было понятнее.
Сначала мы создаем объект класса B и вызываем в нем метод test. В нем мы вызываем foo и вызывается тот foo который в классе A и содержит echo. Так и должно быть. Пока все нормально. Затем мы используем вызов static::foo. Вот тут начинаются чудеса. Так как мы вызывали test через
$b->test()
То у нас static по идее указывает на класс B. И static::foo по идее должен пытаться вызвать тот foo что объявлен в классе B, которого там нет, и падать с ошибкой. Казалось бы. Но по какой-то неведомой причине в этой ситуации вызывается A#foo, я сам не понял почему, видимо какая то хитрая особенность PHP. В любом случае, через static вызывать нестатические методы не стоит.
Поясню фразу «которого там нет». Приватный метод по определению принадлежит только классу A и в других классах его нету. Потому то, что static::foo срабатывает, это очень странно.
Затем при вызове через класс С static::foo интерпретируется как C::foo и происходит ошибка доступа к приватному методу.
Сам пример в общем ненормальный: в других языках через self/static можно вызывать только статические методы и подобных проблем с пониманием кода не возникает.
Пример 4
Тоже очень наркоманский код, лучше бы запретили такие вещи, чем заставляли угадывать что выведется. Если мне не показать результат, я в жизни не догадался бы что он выведет.
A::foo выводит A так как мы явно тут вызвали метод foo у класса A и static равен A.
Почему parent::foo() выводит С я не понял. По логике, parent для класса B это A и должно вывестись A.
self указывает на тот класс, внути которого он наисан. То есть на класс B. Почему тут выводится С, я тоже не очень понял.
Видимо «текущий класс» не меняется при вызове через parent или self и продолжает указывать на С (ведь в самом начале стоит C::test). А когда мы пищем A::foo то «текущий класс» меняется на A.
Вообще, ты должен использовать только parent из нестатических методов, и self. И стараться поменьше исплоьзовать статические методы. И тогда проблем не будет.
Это сложная задача. Попробуй написать функцию приведения названия к каноническому виду (в нижнем регистре, без лишних символов, ровно с одним пробелом между словами, с исправлением ошибок и разных наисаний одного слова) и сравнивай эти канонические названия. Ну например
[EvilWolf] Возвращение кролика [720p, BDRip] -> "возвращение кролика"
[Releasers] Возвращение кролика (Return of the Rabbit), 2007, Drama -> "возвращение кролика"
[RuDub] Вернувшийся заяц -> "вернувшийся заяц" // тут совпадение не будет найдено
Если ты можешь написать функцию приведения к каноническому виду, то сможешь решить задачу точно. Если нет то только ручное разгребание.
Для поиска похожих названий можно разбивать имя на массив слов, удалять цифры, лишние слова и символы и сравнивать число совпадений слов.
Вообще это сложно, если учесть что бывают фильмы с одинаковым названием, но снятые в разные годы.
Алсо советую бросать эту затею. Если ты будешь все время заниматься такой ерундой как парсинг пиратских сайтов с торрентами, ты не будешь развиваться. Парсинг это вообще самое дно в веб-разработке. Хотя конечно компании вроде яндекса умудряются делать его на высоком уровне автоматизации, а не вручную составляя регулярки.
>>428368
Робокасса лучше чем одна система, но хуже чем прямая интеграция с несколькими системами — вот что я хотел сказать. Вконтакте и крупные сайты делают свои страницы оплаты, а не исользуют агрегаторы.
>>427386
> Bindvalue так и не поставил, лень переписывать, но это ведь не критично,
Вообще, там исправлять-то 10 минут если ты хорошо умеешь пользоваться редактором, почему не исправить?
С виду нормально, но я бы еще экранирование в шаблоне добавил, а то может быть у тебя там XSS: https://gist.github.com/anonymous/52adda0113428b274c64
>Вообще, там исправлять-то 10 минут если ты хорошо умеешь пользоваться редактором, почему не исправить?
Я могу исправлять через find replace однотипные вещи, типа там функцию переименовать, а тут полностью переписывать нужно.
Содержимое папки cache надо добавлять в gitignore, а не коммитить в репозиторий, так как это никому не нужные временные файлы.
Я бы конечно советовал вместо смарти осваивать twig. Он более новый, у него более адекватный синтаксис и есть интересные фичи вроде наследования шаблонов и экранирования данных. А в смарти из-за старости все довольно беспорядочно, мне не нравится.
GET запросы не должны изменять данные на сервее. Для удаления, изменения, добавления данных надо исплоьзовать POST.
> $mapper->selectCategories( );
...
> $mapper->getResult()
Это плохая идея. Непонятно зачем делать 2 отдельных функции и все усложнять если можно вернуть результат сразу же?
Да ладно? 2ной клик на bindparam + несколько раз Ctrl D чтобы выделить остальные слова, заменить на bindValue, перенести мышкой вызовы типа showName в bindValue — это же недолго. Да и что там переписывать, там 2 функции на 20 строк, их с нуля можно за 5 минут написать.
В общем уселся за sql, выполняю в консольке и конспектирую в нотепад++ уроки по ссылке опа http://jtest.ru/bazyi-dannyix/sql-dlya-nachinayushhix-chast-2.html
Дык вот, есть у меня таблица со штатами. Там их названия, год присоединения и популяция.
Никак не могу допедрить каким запросом получить строку штата у которого MAX или MIN population.
>Вконтакте и крупные сайты делают свои страницы оплаты, а не исользуют агрегаторы.
>Посоны, спрашивал в веб, но спрошу и тут. Поясните за организацию онлайн-оплаты для магазина. Я нюфаг, до этого делал только странички с обратной связью.
Сравнил так сравнил.
Прошу прощенья, надо было страницу до конца дочитать, ниже был ответ на интересующий меня вопрос.
сделал некоторые исправления.
https://github.com/tokotun/matriculant
>Сортировка работает, только вот ширина колонок таблицы скачет при сортировке.
это из за добавления стрелок ▼ ▲ длина строки становится больше. И колонки становятся шире. Не придумал пока элегантного способа зафиксировать ширину. Разве что в css прописать ширину у всех колонок по 25%
http://jsfiddle.net/0v82tucp/
Откомментите плиз, что не так, что можно было сделать лучше и т.д.
Я прямо жду твоего варианта в 15 строк на любом языке.
Ничего отвратительней я еще не видел. Переписывай всё на хуй. А лучше зайди в JS тред, там тебе пояснят за прототипы хотя бы.
Ты это, прекращай там. Еще один быдлокодер js-у не нужен.
Оп, я почти закончил свои дела с сессией и начинаю понемногу вспоминать про учебу.
https://github.com/sqghub/TestHub
Пока там по мелочи, но дальше планирую сделать страницу прохождения теста а вообще с неё стоило начать, как мне кажется. Сразу спрошу: хранить данные о вопросах и тесте в сессии хорошая идея или не очень?
Там еще в главной директории должна быть папка 'thumbnails', но она почему-то не загрузилась наверно, потому что пустая
Если нет никаких замечаний, то я возьмусь за задачу про кошек-мышек :3
>хранить данные о вопросах и тесте в сессии хорошая идея или не очень?
Это вообще зачем?
Как ты собрался организовывать хранение данных в сессии?
в массиве $_SESSION нельзя использовать числовые индексы - $_SESSION[1], $_SESSION['10'] - cессии работать не будут.
http://code.tutsplus.com/tutorials/rapid-application-prototyping-in-php-using-a-micro-framework--net-21638
Ожидал что будет пошаговая инструкция, но что то пошло не так.
Встрял на месте где потребовалось установить и настроить вот эти компоненты: Slim 1.5.02 (Stable Release), Slim Extras, Twig 1.1, Paris and Idiorm.
Я скачал и затолкал всё в одну папку, в результате получилась структура не как на картинке. В итоге это дело конечно же не работает.
Видимо гайд рассчитан на тех кто уже с этим сталкивался и умеет настраивать.
Вопрос с чего начинать что б всё это настроить?
> но она почему-то не загрузилась
Гит управляет файлами, а не папками. Чтобы добавить в репозитоий папку, создай в ней пустой файл .placeholder и добавь его.
Не надо писать просто «не работает», ты же не блондинка. Пиши что именно не так, какой текст ошибки выводится, и т.д. А то понять в чем причина невозможно.
Ну и пример кода с ошибкой тоже стоит показать.
А в чем сложность перенести папки чтобы было как на картинке?
Вообще, там нет каких-то требований к структуре папок. Ты просто в этом случае должен пути при подключении файлов в своем коде поменять соответственно. То есть писать например не
> require 'Slim/Slim.php';
А
> require 'myfolders/Slim1.0/Slim/Slim.php';
Алсо, в задании надо будет их через композер устанавливать, но это будет позже.
Все эти библиотеки используют автозагрузку классов ( http://php.net/manual/ru/language.oop5.autoload.php ). Когда ты делаешь require 'Slim/Slim.php'; то подкючается файл в котором создается и настаивается автозагузчик для Слима (который подключит остальные файлы).
Также, я не уверен что это хороший гайд для начинающего так как там упоминается ORM, c которым ты скорее всего не сталкивался. ORM это штука, которая позволяет загружать и сохранять объекты в базу данных вместо того, чтобы писать SQL запросы вручную. Про ORM написано в этом моем гайде: https://gist.github.com/codedokode/c4cbc4d7dc8e45ea074a
За ORM конечно стоит браться только после того как освоишь обычные SQL запросы.
Также там упоминается Twig. Это в общем полезная вещь для изучения, можно его и в задаче на файлообменник использовать.
В общем, не знаю, подойдет ли тебе этот гайд. Там объяснений по моему не очень много.
В любом случае, раз ты знаешь английский, я бы советовал почитать официальную документацию по Слиму. Она по моему неплохая и не очень большая по объему: http://docs.slimframework.com/
Не надо писать просто «не работает», ты же не блондинка. Пиши что именно не так, какой текст ошибки выводится, и т.д. А то понять в чем причина невозможно.
Ну и пример кода с ошибкой тоже стоит показать.
А в чем сложность перенести папки чтобы было как на картинке?
Вообще, там нет каких-то требований к структуре папок. Ты просто в этом случае должен пути при подключении файлов в своем коде поменять соответственно. То есть писать например не
> require 'Slim/Slim.php';
А
> require 'myfolders/Slim1.0/Slim/Slim.php';
Алсо, в задании надо будет их через композер устанавливать, но это будет позже.
Все эти библиотеки используют автозагрузку классов ( http://php.net/manual/ru/language.oop5.autoload.php ). Когда ты делаешь require 'Slim/Slim.php'; то подкючается файл в котором создается и настаивается автозагузчик для Слима (который подключит остальные файлы).
Также, я не уверен что это хороший гайд для начинающего так как там упоминается ORM, c которым ты скорее всего не сталкивался. ORM это штука, которая позволяет загружать и сохранять объекты в базу данных вместо того, чтобы писать SQL запросы вручную. Про ORM написано в этом моем гайде: https://gist.github.com/codedokode/c4cbc4d7dc8e45ea074a
За ORM конечно стоит браться только после того как освоишь обычные SQL запросы.
Также там упоминается Twig. Это в общем полезная вещь для изучения, можно его и в задаче на файлообменник использовать.
В общем, не знаю, подойдет ли тебе этот гайд. Там объяснений по моему не очень много.
В любом случае, раз ты знаешь английский, я бы советовал почитать официальную документацию по Слиму. Она по моему неплохая и не очень большая по объему: http://docs.slimframework.com/
> Сразу спрошу: хранить данные о вопросах и тесте в сессии хорошая идея или не очень?
А зачем их хранить в сессии если они есть в базе данных?
https://github.com/MindiMakridi
>Для ENUM обычно используют латинские обозначения, например male/female
Вот это не исправил, придется значения во всей таблице менять, чтоб корректно сайт работал.
>Также, я вижу ты используешь br в верстке.
А чем плох <br>? Я хтмл плохо знаю, учил по http://htmlbook.ru/samhtml пробежавшись по всем статьям за пару часов. Css еще хуже.
Алсо, пикрелейтед ошибки альтернативного синтаксиса.
> в массиве $_SESSION нельзя использовать числовые индексы - $_SESSION[1], $_SESSION['10'] - cессии работать не будут.
Действительно, нельзя. Но это не проблема, можно хранить в $_SESSION['data'][10]
> Как ты собрался организовывать хранение данных в сессии?
Это как раз просто, если используется ООП:
$test = new Test( );
$_SESSION['test'] = $test;
> Вот это не исправил, придется значения во всей таблице менять, чтоб корректно сайт работал.
Делаешь ALTEr TABLE чтобы добавить в ENUM кроме русских латинские обозначения, делаешь 2 UPDATE чтобы поменять русские значения на латинницу, делаешь ALTER TABLE убирающий русские значения из ENUM. Заодно в SQL потренируешься.
Если есть сложности с этим, напиши что именно непонятно, дам подсказку.
Не забудь положить в репозиторий обновленный дамп или файл с SQL командами для обновления (такое обновление называют миграцией базы данных) чтобы я мог у себя обновить базу тоже.
> А чем плох <br>
Он предназначен для вставки разрыва строки, например в стихах, в коде или почтовом адресе. А не как замена margin. Верстать с его помощью нельзя.
> Я хтмл плохо знаю
Если есть время и желание, решай мои задачки на HTML/CSS, прокачаешь знания до нормалного уровня. Я всегда готов помочь подсказкой или ссылкой.
Вот так пойдет:
ALTER TABLE students MODIFY sex ENUM(Male/Female);
UPDATE students SET sex='Male' WHERE sex='М';
UPDATE students SET sex='Female' WHERE sex='Ж';
?
> ошибки альтернативного синтаксиса.
> <?php foreach ...
> <?php endif ?>
Ты тут не видишь ничего подозрительного? Может там не endif, а endforeach нужен? Почитай-ка мануал: http://php.net/manual/ru/control-structures.alternative-syntax.php
По поводу бага с <?= у тебя какая версия php? И чему равна настройка short_open_tag в php.ini?
Чтобы увидеть версию php и настройки надо создать в папке сервера файл с кодом
<?php phpinfo( );
И открыть файл через браузер (http://localhost/1.php)
Не совсем так. Сначала надо разрешить 4 значения в ENUM то есть
MODIFY sex ENUM('М', 'Ж', 'Male', 'Female') NOT NULL
Не забудь добавить NOT NULL так как иначе для колонки включится NULL то есть можно хранить в ней NULL.
4 значения надо чтобы не потерять существующие данные. А после UPDATE можно убрать русские буквы из ENUM.
Версия 5.3.10 short_open_tag отключен. Я как раз спрашивал тут нужно ли включать что-то в настройках, чтобы такой синтаксис работал, мне ответили что нет.
В старом PHP (а 5.3 реально старый, надо хотя бы 5.4 или выше ставить уже, а то ты на версии двухлетней давности сидишь) опция short_tags отключает и <? и <?= потому тебе надо ее включить.
В новом PHP <?= (а также длинный маркер <?php ) включены всегда, и эта опция влияет только на <?.
Потому тебе надо эту опцию включить либо обновить PHP.
Ну и разумеется используй только <?php и <?=, и не используй <? так как он может быть отключен.
А, если ты справшивал «хорошо ли хранить ответы на вопросы в сессии», то я не уверен. Ведь ответы можно сохранять и в базу. С другой стороны, можно копить их в сессии, почему нет, а при завершении теста сохранять в БД.
ладно, перехоу к http://docs.slimframework.com
Вот такое дело стараюсь выполнять пошагово, точно по инструкции.Старался роутер настроить.
Но почему то пишет ошибку 404, при вводе такого пути
http://localhost/slim/hello/world
но может выводить "Hello, world!" если указать путь на прямую к Slim. Вот так.
http://localhost/slim/vendor/slim/slim/hello/world
Что я делаю не так? Или должно быть?
Такое ощущение что там опущены некоторые нюансы которые для авторов казались очевидными. Я не понимаю как это всё работает.
Сами по себе хитрые адреса вроде http://localhost/slim/hello/world работать не будут. Ведь по умолчанию веб-сервер (Апач) пытается просто открыть указанный в URL файл или папку. Так как на сервере нет папки hello/world то ничего не откроется и появляется 404.
Потому сначала мы должны перенастроить сервер так, чтобы обращение к любому несуществующему файлу или папке вызывало запуск файла index.php. Делается это в разных серверах по-разному. Для Апача настройки задаются либо в конфиге либо, что проще, в файле .htaccess.
Для этого надо в корень сайта положить файл .htaccess c специальными инструкциями, как описано тут: http://docs.slimframework.com/#Route-URL-Rewriting (там должно быть 3 строчки, начинающихся с Rewrite)
После этого при обращении к /hello/world будет вызываться index.php, а он уже подключит Slim и может быть что-нибудь выведет.
В твоем случае правда ничего не выведется, так как у тебя пустой index.php. Поставь там хотя бы echo "Yes" для начала.
Можно обойтись и без htaccess но тогда адрес должен выглядеть как
http://localhost/index.php/hello/world
Что не очень красиво. Это работает за счет того, что веб-сервер, найдя файл /index.php вызывает его, а остаток URL (/hello/world) передает ему как $_SERVER[PATH_INFO]
Также, потом удали содержимое папки vendor из репозитория и добавь ее в .gitinore
C композером не надо выгужать код сторонних в библиотек в репозиторий, только свой код.
Задания на PHP для начала:
- попроще https://gist.github.com/codedokode/d7e7f11449fc3bcb24b4
- сложнее https://gist.github.com/codedokode/9424217
Чтобы делать эти задания, тебе надо установить Апач + PHP (можно заодно сразу и MySQL) на компьютер. Вот полезные инструкции:
https://gist.github.com/codedokode/10774100
https://gist.github.com/codedokode/7054af4a03865c4cc863
Может тебе понадобится пользоваться командной строкой, вот гайд https://gist.github.com/codedokode/10539568
Вот небольшой туториал по тому как начать использовать PHP с сервером и браузером: https://php.net/manual/ru/tutorial.php
Увы, уроков плавно подводящих к тому, как сделать задачи выше, пока нет, так что если что задавай вопросы.
Решения задач лучше показать мне, особенно на ООП,так как сам ты вряд ли увидишь все ошибки. Пости свой код на гитхаб и вкидывай ссылку в тред по мере решения. Я прокомментирую и укажу на ошибки.
Книга по гиту: http://git-scm.com/book/ru/v1
Если что задавай вопросы. Это как раз тред для начинающих. Показывай код по хожду решения — чем раньше найдем ошибку тем меньше переделывать.
После этих задач можно переходить к феймворкам посерьезнее, например Yii 2 или Symfony 2.
Параллельно проходи задания и тутоиалы по MySQL: https://gist.github.com/codedokode/10539213
Если плохо знаешь HTML, CSS, JS у нас есть неплохие задания по ним.
Задания на PHP для начала:
- попроще https://gist.github.com/codedokode/d7e7f11449fc3bcb24b4
- сложнее https://gist.github.com/codedokode/9424217
Чтобы делать эти задания, тебе надо установить Апач + PHP (можно заодно сразу и MySQL) на компьютер. Вот полезные инструкции:
https://gist.github.com/codedokode/10774100
https://gist.github.com/codedokode/7054af4a03865c4cc863
Может тебе понадобится пользоваться командной строкой, вот гайд https://gist.github.com/codedokode/10539568
Вот небольшой туториал по тому как начать использовать PHP с сервером и браузером: https://php.net/manual/ru/tutorial.php
Увы, уроков плавно подводящих к тому, как сделать задачи выше, пока нет, так что если что задавай вопросы.
Решения задач лучше показать мне, особенно на ООП,так как сам ты вряд ли увидишь все ошибки. Пости свой код на гитхаб и вкидывай ссылку в тред по мере решения. Я прокомментирую и укажу на ошибки.
Книга по гиту: http://git-scm.com/book/ru/v1
Если что задавай вопросы. Это как раз тред для начинающих. Показывай код по хожду решения — чем раньше найдем ошибку тем меньше переделывать.
После этих задач можно переходить к феймворкам посерьезнее, например Yii 2 или Symfony 2.
Параллельно проходи задания и тутоиалы по MySQL: https://gist.github.com/codedokode/10539213
Если плохо знаешь HTML, CSS, JS у нас есть неплохие задания по ним.
Кстати, ты ООП знаешь? Если нет то сначала надо по ООП урок пройти: http://archive-ipq-co.narod.ru/l1/pasta.html
Хотел бы немного развить тему, заданную этим вопросом.
Допустим, мне понравился сериал "True Detective" с Макконахи и Вуди Харрельсоном, и я хочу узнать, где они еще снимались вместе. Каким образом я могу решить эту задачу? Очевидно, сделав соответствующий запрос в какую-либо онлайновую базу данных фильмов, например imdb, у которого вроде бы как есть api, с помощью которого можно получать оттуда разную информацию.
Тогда можно сделать простейший сайт, на котором будут два поля ввода, актёр_1 и актер_2. Получив на свой сервер эти значения, я перенаправляю запрос на imdb и в ответ получаю два списка фильмов по каждому из них, а потом делаю что-то вроде foreach film-name in film-list1: if film-name in film-list2, return film-name и вывожу получившийся список на экран, естественно, с гиперссылками на соответствующую страничку на imdb. Будет ли работоспособна данная задумка в реале?
Теперь к практической части. Для того, чтобы мой сайт работал, мне нужен постоянно работающий компьютер с подключением к интернету, доступный из внешней сети. Что для этого нужно? Оплатить ДНС? Купить домен? Еще что-то?
И из чего состоит сам сайт? Вот конкретно, какие файлы будут лежать на компьютере? index.html с основной разметкой сайта и script.php, который будет обновлять изменяемые блоки страницы?
К чему я все это пишу. Вот прошел htmlacademy и задачки из учебника, но как начать строить свой сайт, хотя бы вот такой простой, с нуля? Не загрузить все готовое через редактор на бесплатный хостинг, а чтобы все по-настоящему, от установки сервера на свой компьютер до полноценного запуска.
Буду благодарен если кто-то разжует или подскажет, где это все разжевано.
ООП знаю по C++ и Java. Тут вроде тоже самое.
Сайты обычно размещают на хостинге. На хостинге используется хорошее оборудование, есть система резевного питания, хорошие надежные каналы — все это ты вряд ли можешь организовть дома. Да и даже если мог бы, счет за электичество потребленное компьютером скорее всего окажется выше чем плата за хостинг.
Хостингов много, и есть сайты сравнения цен:
http://hosting101.ru/
http://hosting-ninja.ru/rating/
http://www.hosting-obzor.ru/
http://hostdb.ru/
Хостинг бывает разный. Где-то ты арендуешь условно говоря папку на сервере в которую можешь закачивать файлы по FTP/SFTP (shared hosting), где-то арендуешь виртуальный (или реальный) сервер (VPS) на который можешь ставить любой софт (но для этого надо уметь администрировать линукс или нанимать того кто умеет).
Хостинг бывает в разных странах, западные можно оплатить только картой или пейпалом, наши принимают также всякие яндекс-деньги.
Хостинг бывает бесплатный, с ограничениями и рекламой.
Кроме хостинга тебе нужен домен, то есть имя для сайта вроде http://example.com . Домены можно купить в куче мест (погугли), российские ru например стоят от 99 рублей на первый год (но помни что для российского домена нужны паспортные данные, также в нашей стране неясная ситуация с регулированием интернета). Домен указывает на какой-то IP адрес, соответственно тебе надо будет прописать туда IP адрес хостинга, чтобы домен указывал на твой сайт.
В целом твоя задумка осуществима, только есть шанс что подобные выборки может делать сам, через апи.
>И из чего состоит сам сайт?
Из файлов
>Вот конкретно, какие файлы будут лежать на компьютере? index.html с основной разметкой сайта и script.php, который будет обновлять изменяемые блоки страницы?
Как правило чистый html нынче редкость, потому что его можно запихнуть в php-файл и туда же добавить логику. Но на базовом уровне ты прав.
>Для того, чтобы мой сайт работал, мне нужен постоянно работающий компьютер с подключением к интернету, доступный из внешней сети. Что для этого нужно? Оплатить ДНС? Купить домен? Еще что-то?
Покупаешь хостинг, есть и бесплатные, грузишь туда файлы и все. Насколько я понимаю отличие хостинга от облака, на хостинге тебе дают закуток с админкой и предварительно запиленным пхп/бд/етц, а в облаке тебе дают голую пеку(или кусок пеки) на который ты коннектишь и делаешь что хочешь.
> Вот конкретно, какие файлы будут лежать на компьютере? index.html с основной разметкой сайта и script.php, который будет обновлять изменяемые блоки страницы?
Сайты бывают статические и динамические. В статических сайтах HTML лежит в HTML файлах. В динамических HTML-код генерируется и выдается скриптом, например на PHP.
Вот почитай тут примеры кода хотя бы: https://php.net/manual/ru/tutorial.php
Ну и прежде чем загружать сайт на хостинг, тебе захочется проверить работает ли код вообще. Для этого ты устанавливаешь себе на компьютер веб-сервер (Апач + PHP + MySQL если надо) и можешь сразу же одновременно с редактированием кода просматривать сайт в браузере.
У меня есть кое-какая инфа по установке Апача, PHP, на компьютер:
https://gist.github.com/codedokode/7054af4a03865c4cc863
https://gist.github.com/codedokode/10774100
Вот гайд по командной стрроке если она тебе понадобится: https://gist.github.com/codedokode/10539568
После того как ты убедился что все рабоатет, ты можешь загружать сайт на хостинг. Если ты используешь шаред хостинг то выгрузка делается любым FTP- или SFTP-менеджером. Из бесплатных там есть WinSCP для SFTP и FTP, FileZilla для FTP, ну и куча других программ, я тут не особо разбираюсь.
>>429050
>>429051
Спасибо, очень информативно. В общем, насколько я понял, большую часть технических вопросов за меня решит уже настроенный хостинг, куда я просто закину готовые файлы, привяжу к нему свой домен (кстати, как это делается в общих чертах?), и мой сайт будет доступен интернету. Значит, моя часть заключается в том, чтобы разобраться, как правильно вводить-выводить информацию с АРІ, ну и как сделать динамически обновляющуюся страничку.
Прежде чем покупать что-то добейся чтобы сайт работал на твоем компьютере под Апачем.
Как привязать домен, попробуй погуглить в интернете. По идее сам по себе домен надо где-то размещать (это называется DNS хостинг), но с этим проблем не будет так как многие регистраторы при покупке домена бесплатно его размещают, плюс домен бесплатно можно хостить на яндексе. И сама привязка домена к сайту обычно заключается в том что ты в формочку вводишь IP адрес сайта и жмешь Сохранить.
Вот информация про яндекс хостинг доменов: http://help.yandex.ru/pdd/hosting.xml
Вот информация про то как работает DNS, что такое A-запись и тд: https://ru.wikipedia.org/wiki/DNS
Благодарю за инфу, добра тебе.
Приклеилась.
Не могу долго смотреть в монитор с кодом на РНР, глаза болят.
Начинаю смотреть на любой другой код - отлично.
Монитор годный, ипс и все дела.
Но как только пробую читать код на рнр, сразу глаза слеятся и болят. Сталкивался ли кто с такой проблемой?
Народные методы не помогли, платная медицина тоже.
По работе приходится читать много чужого кода на код ревью. С другими языками такого нет, но вот рнр это ужасно.
такой вопрос:
один тимлид запилил внутренний проект полностью на статических классах.
другой - на динамических.
суть продуктов - это наши внутренние cms, которая используется всей командой в двух крупных продуктах.
встал вопрос оставить один продукт.
функционал одинаков, влпдение кодом тоже у всех хорошее.
я пока склоняюсь к тому, что динамика лучше, потому как тесты писать удобнее, да и читабельность получше, когда объекты динамические. но есть внутри команды и те, кто говорит - норм, статические классы это удобно.
аргументы у обоих сторон - ни о чем.
поясните нубу почему цмс на статических классах - это плохо?
Нет больше сил думать, я сдаюсь: как переносить остаток счетчика после окончания счета на новый цикл, чтобы не получить 1, 2, 3, 4 в ответе?
Код: http://ideone.com/jAXlzB
Ты каждый раз дойдя до 5, начинаешь считать заново с номера 1. А надо продолжать считать с того места где остановился. Можешь использовать указатели в этой задаче,
http://www.softtime.ru/bookphp/gl4_5.php
Make sure that you fix the issues listed below and run this script again:
The openssl extension is missing, which means that secure HTTPS transfers are impossible.
If possible you should enable it or recompile php with with-openssl»
гугл посоветовал раскомментировать строку
extension=php_openssl.dll в php.ini, сделано, но результат тот же. Хотел скачать и установить
php_openssl.dll вручную, но первая страница гугла выдает какие-то обменники с которых закачка не идет, как пофиксить?
[PHP Modules]
bcmath
calendar
com_dotnet
Core
ctype
curl
date
dom
ereg
filter
ftp
gd
hash
iconv
json
libxml
mbstring
mcrypt
mhash
mysql
mysqli
mysqlnd
odbc
pcre
PDO
pdo_mysql
pdo_sqlite
Phar
Reflection
session
SimpleXML
soap
SPL
sqlite3
standard
tokenizer
wddx
xml
xmlreader
xmlwriter
xsl
zip
zlib
[Zend Modules]
[PHP Modules]
bcmath
calendar
com_dotnet
Core
ctype
curl
date
dom
ereg
filter
ftp
gd
hash
iconv
json
libxml
mbstring
mcrypt
mhash
mysql
mysqli
mysqlnd
odbc
pcre
PDO
pdo_mysql
pdo_sqlite
Phar
Reflection
session
SimpleXML
soap
SPL
sqlite3
standard
tokenizer
wddx
xml
xmlreader
xmlwriter
xsl
zip
zlib
[Zend Modules]
http://windows.php.net/download качни отсюда нужную версию, где-то в архиве должен быть php_openssl.dll
Мне нужно поменять местами, сохранив при этом ключи.
Спрошу по другому
$array = Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 )
foreach ($array as $key => value) {
if ($value == 1 ) {
$value == 2;
}
}
print_r($array); // Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 )
не работает. Почему?
Не знаю, попробуй.
Потому что значение присваивается внутренней переменной. Тебе надо передать его по ссылке или присвоить по ключу $array[$key] = 2.
Свапнуть можно так
list($arr[$m], $arr[$n]) = [$arr[$n], $arr[$m]];
Потому что статические методы это то же самое что функции. Это не ООП, а процедурный стиль.
Соответственно ты не можешь пользоваться всеми преимуществами ООП при работе с таким кодом. Например, ты не можешь создать 2 объекта с разными настройками, так как статические поля существуют только в одном экземпляре. Ну к примеру, у тебя есть класс Db, работающий с базой. Ты не можешь создать второе соединение к другой базе данных.
Так же, код получается спутанным. Например если есть класс A и он обращается к классу B:
class PostMapper {
static function addPost() {
Db::insert('posts', ...);
...
}
То мы не можем в таком коде заменить Db на что-то другое, классы намертво связаны. Например мы не можем сделать чтобы класс использовал отдельное соединение к базе данных. Или специальный класс LoggedDb вместо Db. А при тестировании мы не можем подсунуть заглушку вместо базы данных.
У меня то еще тут упомянуто: https://gist.github.com/codedokode/e1d31a31b37d5f635057
В общем, код на статических методах это фактически процедурный код и мы не можем с ним пользоваться многими преимуществами ООП.
Куда можно податься для прокачки скиллов до более-менее адекватного уровня?
Куда-нибудь в некоммерческий проект чисто ради опыта или за еду на полдня? Мне почему то кажется, что даже конфочка в скайпе с такими же раздолбаями дала бы мне хоть что то.
Не используйте внутренний указатель массива. Так как он никак не виден снаружи, код с его использованием трудно читать и отлаживать.
Тут нужен обычный цикл:
Повторять пока девочек больше чем требуется: {
Для каждой по очереди: {
- увеличиваем счетчик
- если счетчик дошел до максимума, убираем текущий элемент из массива и сбрасываем счетчик
}
}
>гугл посоветовал раскомментировать строку
> extension=php_openssl.dll в php.ini, сделано, но результат тот же.
Скорее всего ты не в том файле раскомментировал. Сделай файл 1.php c текстом
<?php phpinfo( );
Запусти его и посмотри что там выведется в поле used config fille или как-то так. Этот файл и надо править.
Как альтернатива можно в командной строке набрать php -i чтобы увидеть ту же информацию что и phpinfo().
Но помни что у PHP могут быть разные конфигурации в командной строке и под Апачом, особенно если ты используешь сборки а не ставишь Апач + PHP сам. В этом случае в командной строке можно явно указать какой конфиг использовать:
php -i -c "d:/files/php.ini"
> Хотел скачать и установить
> php_openssl.dll вручную,
Сначала стоит посмотреть нет ли ее в папке с PHP. И качать надо с http://windows.php.net/download или http://windows.php.net/downloads/pecl/releases/ а не с левых сайтов.
> Задачки из интернетов решать не интересно,
Но почему? У нас есть вполне приближенные к реальности задачи вроде сделать сайт-файлообменник. На них ты получаешь вполне конкретные навыки. Тем более что в качестве тестового задания тебя скорее всего попросят сделать сайт или страничку.
> на работу вряд ли возьмут из-за скудных навыков
Компания компании рознь.
> Куда-нибудь в некоммерческий проект чисто ради опыта
зачем ты там нужен если не умеешь ничего делать?
> Мне почему то кажется, что даже конфочка в скайпе с такими же раздолбаями дала бы мне хоть что то.
Вряд ли.
Я для вас сочинил хайку:
Нужно выбрать проект.
Найду-ка я эксперта на двачах.
Вся суть манагерства.
>>Но почему? У нас есть вполне приближенные к реальности задачи вроде сделать сайт-файлообменник.
Я не вглядываясь прокрутил, мне они показались слишком "учебными" что ли. А вот файлообменник - это интересно.
>>Компания компании рознь.
Еще я студент и не могу уделять работе целый день, как принято. Вряд ли такой кому нужен.
>>зачем ты там нужен если не умеешь ничего делать?
Мне кажется, там были бы какие то реальные задачи, решением которых мне было бы интересно заниматься. В том и беда - не знаю куда податься, что бы мои косяки не так в глаза бросались.
>>Вряд ли.
У меня совершенно нет идей, на чем можно попрактиковаться. И самому их генерировать не получается.
Решил всё же обновить php до 5.6.5 и тут стала вылезать ошибка что отсутствует msvcr110.dll , установил visual c++ 11, не помогло, установил visual c++ 2013 итог тот же, взял более раннюю версию php 5.5.21 - всё то же самое.
> Еще я студент и не могу уделять работе целый день, как принято.
Я работал студентом на полставки. Все зависит от компании и от того кто им нужен.
>>429337
> тут стала вылезать ошибка что отсутствует msvcr110.dll , установил visual c++ 11, не помогло, установил visual c++ 2013 итог тот же,
надо ставить не студию, а Visual C++ Redistributable которая легко гуглится на сайте майкрософта:
> MSVCR110.dll is the Microsoft Visual C++ Redistributable dll that is needed for projects built with Visual Studio 2011. The dll letters spell this out.
> MS = Microsoft, V = Visual, C = C++, R = Redistributable
Там есть разные версии, 110 скоее всего значит VS 11.0
Качать надо с официального сайта а не с левых сайтов.
Тут наисано: http://support.microsoft.com/kb/2019667/en-us
> Visual Studio 2012 (VC++ 11.0)
Значит нам надо Microsoft Visual C++ Redistributable 2012: http://www.microsoft.com/ru-ru/download/details.aspx?id=30679
Также помни что вместе с PHP надо обновить и расширения.
И как в «нормальной» ОС установить 2 версии PHP? Как установить самую новую (а не версию 2 годичной давности как в дебиане)? Как установить PHP не в общесистемную папку?
Если захочешь порешать вот ссылки на задачи. В ходе их решения ты изучишь как на PHP выдавать страницы в браузер, работу с таблицами в БД, работу с формами, MVC, может еще что-то.
Задания на PHP для начала:
- попроще https://gist.github.com/codedokode/d7e7f11449fc3bcb24b4
- сложнее https://gist.github.com/codedokode/9424217
Чтобы делать эти задания, тебе надо установить Апач + PHP (можно заодно сразу и MySQL) на компьютер. Вот полезные инструкции:
https://gist.github.com/codedokode/10774100
https://gist.github.com/codedokode/7054af4a03865c4cc863
Может тебе понадобится пользоваться командной строкой, вот гайд https://gist.github.com/codedokode/10539568
Вот небольшой туториал по тому как начать использовать PHP с сервером и браузером: https://php.net/manual/ru/tutorial.php
Увы, уроков плавно подводящих к тому, как сделать задачи выше, пока нет, так что если что задавай вопросы.
Решения задач лучше показать мне, особенно на ООП,так как сам ты вряд ли увидишь все ошибки. Пости свой код на гитхаб и вкидывай ссылку в тред по мере решения. Я прокомментирую и укажу на ошибки.
Книга по гиту: http://git-scm.com/book/ru/v1
Если что задавай вопросы. Это как раз тред для начинающих. Показывай код по хожду решения чем раньше найдем ошибку тем меньше переделывать.
После этих задач можно переходить к феймворкам посерьезнее, например Yii 2 или Symfony 2.
Параллельно проходи задания и тутоиалы по MySQL: https://gist.github.com/codedokode/10539213
Если плохо знаешь HTML, CSS, JS у нас есть неплохие задания по ним.
Если захочешь порешать вот ссылки на задачи. В ходе их решения ты изучишь как на PHP выдавать страницы в браузер, работу с таблицами в БД, работу с формами, MVC, может еще что-то.
Задания на PHP для начала:
- попроще https://gist.github.com/codedokode/d7e7f11449fc3bcb24b4
- сложнее https://gist.github.com/codedokode/9424217
Чтобы делать эти задания, тебе надо установить Апач + PHP (можно заодно сразу и MySQL) на компьютер. Вот полезные инструкции:
https://gist.github.com/codedokode/10774100
https://gist.github.com/codedokode/7054af4a03865c4cc863
Может тебе понадобится пользоваться командной строкой, вот гайд https://gist.github.com/codedokode/10539568
Вот небольшой туториал по тому как начать использовать PHP с сервером и браузером: https://php.net/manual/ru/tutorial.php
Увы, уроков плавно подводящих к тому, как сделать задачи выше, пока нет, так что если что задавай вопросы.
Решения задач лучше показать мне, особенно на ООП,так как сам ты вряд ли увидишь все ошибки. Пости свой код на гитхаб и вкидывай ссылку в тред по мере решения. Я прокомментирую и укажу на ошибки.
Книга по гиту: http://git-scm.com/book/ru/v1
Если что задавай вопросы. Это как раз тред для начинающих. Показывай код по хожду решения чем раньше найдем ошибку тем меньше переделывать.
После этих задач можно переходить к феймворкам посерьезнее, например Yii 2 или Symfony 2.
Параллельно проходи задания и тутоиалы по MySQL: https://gist.github.com/codedokode/10539213
Если плохо знаешь HTML, CSS, JS у нас есть неплохие задания по ним.
Легко.
>установить 2 версии PHP
команда_установки php-{версия}
>как в дебиане
А зачем дебиан на десктопе? В моём школоарче порой новые версии появляются резвее, чем виндовые билды на php.net, или откуда вы там их руками качаете.
>не в общесистемную папку
Зачем? Даже если это зачем-то кому-то нужно, есть chroot, либо распаковка собранных кем-нибудь/самостоятельно бинарных версий.
а зачем платить больше, если можно вообще не платить?
>>- попроще https://gist.github.com/codedokode/d7e7f11449fc3bcb24b4
Интересная, ябрешил :3
Спасибо, анон)
>>- сложнее https://gist.github.com/codedokode/9424217
А вот эта для меня больно сложна, вот так сразу не осилю.
>>Может тебе понадобится пользоваться командной строкой, вот гайд https://gist.github.com/codedokode/10539568
Я у мамы красноглазик)
Спасибо анон, добра тебе)
Школьник и айфон 5.1:
http://ideone.com/WH7Slq
Хардкорный депозит 5.2:
http://ideone.com/acQUYL
Карланы не нужны 5.4:
http://ideone.com/a6JkYa
Палиндром:
http://ideone.com/9kdHa5
Как в этой задаче нужно было правильно удалять пробелы?
gen = add
Ты вызываешь add передавая ей a = [5, 7] и b = undefined (так как ты не указал второй аргумент). при сложении массив приводится к строке и получается "5, 7" к которой прибавляется строка "undefined"
Можешь поставить console.log внутрь add и проверить чему равны a и b.
Ну задрвствуй. Давай посмотрим что ты написал.
> Школьник и айфон 5.1:
Тут все верно
> Хардкорный депозит 5.2:
Тут тоже верно решено.
> Карланы не нужны 5.4:
Правильно решено.
> Палиндром:
Тут тоже программа работает верно, но удаление пробелов лучше сделать через str_replace.
> Как в этой задаче нужно было правильно удалять пробелы?
Есть функции замены одной последовательности символов на другую: str_replace и strtr. Лучше использовать их, а решение с массивом это обходной путь, тут достаточно str_replace.
Вообще, у тебя хорошо получается, давай решай дальше.
>list($arr[$m], $arr[$n]) = [$arr[$n], $arr[$m]];
Оп милый, это ты?
Я сейчас думаю над задачей с кошками мышками и поле планирую сделать двумерным массивом, допустим поле 4х4 будет выглядеть так:
$field = array(
[0] => array ([0] => '.', [1] => '.', [2] => '.', [3] => '.'),
[1] => array ([0] => '.', [1] => '.', [2] => '.', [3] => '.'),
...
);
// точки - точки координат, как у тебя в задаче
Естественно, он будет создаваться функцией. Далее, допустим, что кошка (К) появляется в точке 2х2, соответственно её координата будет = $field[2][2].
Я в общем мыслю в правильном направлении?
пиздец што это
Скорее так:
я создаю в бд запись о выполнении кем-то теста, а айди этой записи запихиваю в сессию выполнителю. У меня нет больше идей, как сопоставить пользователя и тест, если мы делаем каждый вопрос в новом окне. либо пилить что-то на аяксе, о котором я знаю лишь то, что он существует
Упс, что-то я про тебя подзабыл. Исправляюсь.
Посмотрел я твой код, впечатление двоякое. С одной стороны, все работает, с другой, к коду много замечаний. Вот они:
> https://github.com/tokotun/matriculant/blob/master/app/MatriculantMapper.php#L101
> public function checkUser(Matriculant $matriculant)
Для того чтобы проверить есть ли такой абитуриент в базе, не надо выбирать его (тем более все поля) и пересылать в PHP. Лучше писать запрос в виде SELECT COUNT ... WHERE так будет гораздо очевиднее что ты хочешь проверить.
> https://github.com/tokotun/matriculant/blob/master/templates/main.php#L6
> if ($matriculantMapper->checkUser($matriculant))
Явных обращений к БД в шаблоне не должно быть. Если бы там было $loginService->isUserLogged(), это еще ладно, но логику определения залогиненности в шаблон тащить не надо.
> https://github.com/tokotun/matriculant/blob/master/templates/main.php#L24
> Поиск по запросу "<?= $userSearch ?>"
Это же XSS прямо как в примере: https://gist.github.com/anonymous/52adda0113428b274c64
Попробуй сам открыть ссылку вида http://example.com/index.php?userSearch=<script>alert(/xss/)</script> (Хром правда достаточно умный чтобы увидеть тут уязвимость и заблокировать ее, но это наверняка обходится).
> стрелка расширяет колонку
Стрелки все же скрывать не стоит. Насчет проблемы ширины колонок, правильно было бы зафиксирвать ширину колонок (только не по 25% а с учетом того что например колонки с номером группы и баллами могут быть меньше, процентов по 5). Но вообще, это не принипциально в этом задании, пусть ширина меняется.
Около надписи «Поиск по запросу X» надо добавить ссылку чтобы показать всех абитуриентов. А то как иначе выйти из режима поиска?
Если доступна всего 1 страница, пагинацию можно не показывать.
> https://github.com/tokotun/matriculant/blob/master/templates/main.php#L53
> <li class="disabled"><a href="">Prev</a></li>
Не очень понятно зачем выводить ссылку на саму себя (href="" ссылается на ту же самую страницу). Наверно тут лучше вообще убрать тег <a>?
> https://github.com/tokotun/matriculant/blob/master/index.php#L25
> $matriculant->setData($sentData);
Вот это неаккуратно сделано. Ведь у нас тут нет POST данных. Сделай лучше функцию типа isLoggedIn или как-то так, которая просто проверяет code и id из кук на правильность.
> $matriculant->rewriteMatriculant($sentData);
> $matriculant->setData($sentData);
Непонятно почему надо тут делать 2 функции для одной и той же цели. По моему в обоих случаях подойдет setData.
> https://github.com/tokotun/matriculant/blob/master/login.php#L28
> if ($matriculant->errors['error'] == false){
Правильнее делать так: if (!$matriculant->hasErrors()). В этом случае логика проверки есть ли ошибка помещена в класс Matriculant, а в твоем варианте она размазана по login.php
Вообще, я вижу что у тебя тут часто идет обращение к полям класса извне. Это плохо, лучше делать поля по возможности private/protected и обращаться к ним через методы. Так код получается более надежный и понятный, так как поле можно поменять только изнутри класса.
> https://github.com/tokotun/matriculant/blob/master/login.php#L11
> //считываем данные об абитуринте из базы
> //заносим эти данные в обьект
Давай лучше сделаем чтобы MatriclantMapper сразу возвращал объект. Зачем нам вообще эти массивы? С объектами работать ведь удобнее.
Код login.php выглядит каким-то запутанным, например readMatriculant в нем аж 2 раза встречается. Более того, ты
не делаешь редирект после обработки запроса что неправильно. Надо его упростить. Давай сделаем так:
---------------------------
Если (id/code указаны) {
matriculant = загружаем из БД;
если (не загрузилось) {
создаем новый объект;
}
} иначе {
matriculant = новый объект;
}
Если (форма запощена) {
Записываем в matriculant данные из POST;
делаем валидацию;
Если (email не уникален) {
добавляем ошибку;
}
Если (токен неправильный) {
Добавляем ошибку;
}
Если (ошибок нет) {
вставляем или обновляем запись в БД;
ставим куки;
делаем редирект;
умираем;
}
}
---------------------------
> https://github.com/tokotun/matriculant/blob/master/templates/profile.php#L2
> <div class="navbar">
Это скопипащено в main и в profile.php. Избавься от копипасты.
> https://github.com/tokotun/matriculant/blob/master/templates/profile.php#L18
> if (isset($_COOKIE['id']))
Шаблон не должен лезть в куки. Нужные значения передаются в него снаружи в виде переменных.
> https://github.com/tokotun/matriculant/blob/master/app/Matriculant.php#L184
> $this->{$key} = ...
Тут должна быть хотя бы проверка что такое поле в объекте существует а то он надобавляет лишних полей.
В качестве email проходит строчка «lol me@mail.ru lol»
После успешной регистрации/редактирования надо бы вверху формы выводить зелененькую надпись «Вы успешно зарегистрировались и добавлены в таблицу»/«Изменения сохранены». А то у тебя выводится та же форма и непонятно, что произошло и не ошибка ли это. В бутстрапе есть класс чтобы сделать зелененький прямоугольник с текстом, alert или как-то так.
Упс, что-то я про тебя подзабыл. Исправляюсь.
Посмотрел я твой код, впечатление двоякое. С одной стороны, все работает, с другой, к коду много замечаний. Вот они:
> https://github.com/tokotun/matriculant/blob/master/app/MatriculantMapper.php#L101
> public function checkUser(Matriculant $matriculant)
Для того чтобы проверить есть ли такой абитуриент в базе, не надо выбирать его (тем более все поля) и пересылать в PHP. Лучше писать запрос в виде SELECT COUNT ... WHERE так будет гораздо очевиднее что ты хочешь проверить.
> https://github.com/tokotun/matriculant/blob/master/templates/main.php#L6
> if ($matriculantMapper->checkUser($matriculant))
Явных обращений к БД в шаблоне не должно быть. Если бы там было $loginService->isUserLogged(), это еще ладно, но логику определения залогиненности в шаблон тащить не надо.
> https://github.com/tokotun/matriculant/blob/master/templates/main.php#L24
> Поиск по запросу "<?= $userSearch ?>"
Это же XSS прямо как в примере: https://gist.github.com/anonymous/52adda0113428b274c64
Попробуй сам открыть ссылку вида http://example.com/index.php?userSearch=<script>alert(/xss/)</script> (Хром правда достаточно умный чтобы увидеть тут уязвимость и заблокировать ее, но это наверняка обходится).
> стрелка расширяет колонку
Стрелки все же скрывать не стоит. Насчет проблемы ширины колонок, правильно было бы зафиксирвать ширину колонок (только не по 25% а с учетом того что например колонки с номером группы и баллами могут быть меньше, процентов по 5). Но вообще, это не принипциально в этом задании, пусть ширина меняется.
Около надписи «Поиск по запросу X» надо добавить ссылку чтобы показать всех абитуриентов. А то как иначе выйти из режима поиска?
Если доступна всего 1 страница, пагинацию можно не показывать.
> https://github.com/tokotun/matriculant/blob/master/templates/main.php#L53
> <li class="disabled"><a href="">Prev</a></li>
Не очень понятно зачем выводить ссылку на саму себя (href="" ссылается на ту же самую страницу). Наверно тут лучше вообще убрать тег <a>?
> https://github.com/tokotun/matriculant/blob/master/index.php#L25
> $matriculant->setData($sentData);
Вот это неаккуратно сделано. Ведь у нас тут нет POST данных. Сделай лучше функцию типа isLoggedIn или как-то так, которая просто проверяет code и id из кук на правильность.
> $matriculant->rewriteMatriculant($sentData);
> $matriculant->setData($sentData);
Непонятно почему надо тут делать 2 функции для одной и той же цели. По моему в обоих случаях подойдет setData.
> https://github.com/tokotun/matriculant/blob/master/login.php#L28
> if ($matriculant->errors['error'] == false){
Правильнее делать так: if (!$matriculant->hasErrors()). В этом случае логика проверки есть ли ошибка помещена в класс Matriculant, а в твоем варианте она размазана по login.php
Вообще, я вижу что у тебя тут часто идет обращение к полям класса извне. Это плохо, лучше делать поля по возможности private/protected и обращаться к ним через методы. Так код получается более надежный и понятный, так как поле можно поменять только изнутри класса.
> https://github.com/tokotun/matriculant/blob/master/login.php#L11
> //считываем данные об абитуринте из базы
> //заносим эти данные в обьект
Давай лучше сделаем чтобы MatriclantMapper сразу возвращал объект. Зачем нам вообще эти массивы? С объектами работать ведь удобнее.
Код login.php выглядит каким-то запутанным, например readMatriculant в нем аж 2 раза встречается. Более того, ты
не делаешь редирект после обработки запроса что неправильно. Надо его упростить. Давай сделаем так:
---------------------------
Если (id/code указаны) {
matriculant = загружаем из БД;
если (не загрузилось) {
создаем новый объект;
}
} иначе {
matriculant = новый объект;
}
Если (форма запощена) {
Записываем в matriculant данные из POST;
делаем валидацию;
Если (email не уникален) {
добавляем ошибку;
}
Если (токен неправильный) {
Добавляем ошибку;
}
Если (ошибок нет) {
вставляем или обновляем запись в БД;
ставим куки;
делаем редирект;
умираем;
}
}
---------------------------
> https://github.com/tokotun/matriculant/blob/master/templates/profile.php#L2
> <div class="navbar">
Это скопипащено в main и в profile.php. Избавься от копипасты.
> https://github.com/tokotun/matriculant/blob/master/templates/profile.php#L18
> if (isset($_COOKIE['id']))
Шаблон не должен лезть в куки. Нужные значения передаются в него снаружи в виде переменных.
> https://github.com/tokotun/matriculant/blob/master/app/Matriculant.php#L184
> $this->{$key} = ...
Тут должна быть хотя бы проверка что такое поле в объекте существует а то он надобавляет лишних полей.
В качестве email проходит строчка «lol me@mail.ru lol»
После успешной регистрации/редактирования надо бы вверху формы выводить зелененькую надпись «Вы успешно зарегистрировались и добавлены в таблицу»/«Изменения сохранены». А то у тебя выводится та же форма и непонятно, что произошло и не ошибка ли это. В бутстрапе есть класс чтобы сделать зелененький прямоугольник с текстом, alert или как-то так.
> . У меня нет больше идей, как сопоставить пользователя и тест, если мы делаем каждый вопрос в новом окне
Можно еще в скрытом поле передавать или в ппараметре в URL: /test/123456789/
С сессией есть подвохи:
- сессия использует куки для идентификации, куки общие, значит мы не можем в 2 вкладках проходить 2 разных теста. Вообще, ты должен всегда помнить что сессия и куки общие для всех окон и вкладок и это может быть проблемой.
- сессия умирает через 25-30 минут неактивности (при настройках по умолчанию). Сессия это временное, не постоянное хранилище.
Потому если можно хранить id сеанса не в сессии, и это не сложно то лучше хранить не в сессии. как я сказал, можно передавать его в скрытом поле формы или добавить в URL. Например после нажатия «начать тест» создается сеанс в БД и его id вставляется в URL.
C другой стороны, тебе надо еще где-то хранить ответы на вопросы.. сессия как временное хранилище тут конечно подошла бы.
>C другой стороны, тебе надо еще где-то хранить ответы на вопросы.. сессия как временное хранилище тут конечно подошла бы.
Я планировал еще две таблицы запилить.
Что-то вроде result и questions_result. В первой информация общая: время начало, время конца, туда-сюда, а во втором просто вопрос-ответ. А в сессии я планировал хранить именно айди текущего теста. Но про два теста во вкладках я не подумал, да. В общем недельку я подумаю, пока закрываю сессию, и начну писать код.
Первую таблицу наверно правильнее назвать «test_sessions» или «test_attempts», а вторую «answers» или как-то так.
Так, да, схема вроде выглядит верной.
>>429487
Так, в общем, неплохо. Вот некоторые замечания:
Небольшой баг: если мы открываем главную страницу, то там стоит стрелочка вверх около поля «Баллы». И если щелкнуть по надиси Баллы, чтобы поменять сортировку, то первый раз ничего не меняется. И только на второй раз направление меняется. Нехорошо как-то.
Далее, если мы делаем поиск, то там выводится текст
> Показываются только студенты, найденные по словам кев
Но надо еще тут же выводить ссылку «Показать всех студентов», иначе как выйти из режима поиска?
Также, при поиске неверно показывается число страниц и вообще, не работает постраничная навигация. Надо как минимум скрывать ее. А в идеале сделать чтобы результаты поиска корректно отображались постранично.
В качестве почты можно указать «lol me@mail.ru lol» хотя это явно неправильно.
После успешной регистации надо писать «Вы усешно зарегистрировались и добавлены в список», а после редактирования «Изменения сохранены». А то нету никакой обратной связи, непонятно сохранилось что-то или нет.
При вводе пустой строки в поле поиска и отавки формы режим поиска включать не надо.
> $nameArrow = "";
> $groupArrow = "";
> $pointsArrow = "";
> $directionName = "ASC";
> $directionGroup = "ASC";
> $directionPoints = "ASC";
Нехорошо как-то. Когда будет 8 колонок ты сделаешь 8 переменных? Надо либо использовать тут массив либо, что лучше, обойтись двумя переменными, например название поля и направление.
> https://github.com/MindiMakridi/Students/blob/master/lib/DataMapper.php#L43
> LIMIT $num, $recordsPerPage");
Эти значения можно передать через bindValue добавив там параметр PARAM_INT или как-то так. Не надо вставлять их прямо в запрос.
> https://github.com/MindiMakridi/Students/blob/master/lib/Profile.php#L73
> "/^[а-яa-z-]+$/ui";
Букву ё надо указывать отдельно, так как она в юникоде не находится внутри диапазона а-я. Посмотри сам: http://unicode-table.com/ru/#cyrillic - буква Ё стоит отдельно.
> https://github.com/MindiMakridi/Students/blob/master/templates/header.html#L13
Не туда action поставил
> https://github.com/MindiMakridi/Students/blob/master/templates/main.html#L9
Тут нужен if с двоеточием
>>429487
Так, в общем, неплохо. Вот некоторые замечания:
Небольшой баг: если мы открываем главную страницу, то там стоит стрелочка вверх около поля «Баллы». И если щелкнуть по надиси Баллы, чтобы поменять сортировку, то первый раз ничего не меняется. И только на второй раз направление меняется. Нехорошо как-то.
Далее, если мы делаем поиск, то там выводится текст
> Показываются только студенты, найденные по словам кев
Но надо еще тут же выводить ссылку «Показать всех студентов», иначе как выйти из режима поиска?
Также, при поиске неверно показывается число страниц и вообще, не работает постраничная навигация. Надо как минимум скрывать ее. А в идеале сделать чтобы результаты поиска корректно отображались постранично.
В качестве почты можно указать «lol me@mail.ru lol» хотя это явно неправильно.
После успешной регистации надо писать «Вы усешно зарегистрировались и добавлены в список», а после редактирования «Изменения сохранены». А то нету никакой обратной связи, непонятно сохранилось что-то или нет.
При вводе пустой строки в поле поиска и отавки формы режим поиска включать не надо.
> $nameArrow = "";
> $groupArrow = "";
> $pointsArrow = "";
> $directionName = "ASC";
> $directionGroup = "ASC";
> $directionPoints = "ASC";
Нехорошо как-то. Когда будет 8 колонок ты сделаешь 8 переменных? Надо либо использовать тут массив либо, что лучше, обойтись двумя переменными, например название поля и направление.
> https://github.com/MindiMakridi/Students/blob/master/lib/DataMapper.php#L43
> LIMIT $num, $recordsPerPage");
Эти значения можно передать через bindValue добавив там параметр PARAM_INT или как-то так. Не надо вставлять их прямо в запрос.
> https://github.com/MindiMakridi/Students/blob/master/lib/Profile.php#L73
> "/^[а-яa-z-]+$/ui";
Букву ё надо указывать отдельно, так как она в юникоде не находится внутри диапазона а-я. Посмотри сам: http://unicode-table.com/ru/#cyrillic - буква Ё стоит отдельно.
> https://github.com/MindiMakridi/Students/blob/master/templates/header.html#L13
Не туда action поставил
> https://github.com/MindiMakridi/Students/blob/master/templates/main.html#L9
Тут нужен if с двоеточием
>Но надо еще тут же выводить ссылку «Показать всех студентов», иначе как выйти из режима поиска?
Вот же она https://github.com/MindiMakridi/Students/blob/master/templates/main.html#L11
>Не туда action поставил
Почему не туда? На текущую страницу.
>Если вызвано из функции, выражение return немедленно прекращает выполнение текущей функции и возвращает свой аргумент как значение данной функции
http://php.net/manual/ru/function.return.php
var sequence = function(start, step) {
\tif (start) {
\t\tvar currentValue = start;
\t} else
\t{
\t\tvar currentValue = 0;
\t}
\tif(!step) {
\t\tstep = 1;
\t}
\treturn function() {
\t\tcurrentValue = currentValue + step ;
\t\treturn currentValue;
\t}
}
var generator = sequence(2, 4);
console.log(generator()); ------- 6
Как бы мне тогда выводить стартовое значение счетчика в первой задаче по js?
Ну вот, теперь вообще ничего не работает. Во первых выводится таблица теперь без какой-либо сортировки, просто первые 50 записей. То есть из 4 параметров, 3 он игнорирует и только :records работает. Теперь при переходе на другую страницу или клике на поле таблицы показывают просто пустую таблицу. Если же задать в адресной строке явным образом гет параметры без num, то он на них никак не реагирует, а если с num, то таблица вообще пустая.
Сообщения об ошибках выводятся? Должны так как там ошибка.
Алсо прочти это http://php.net/manual/ru/pdo.error-handling.php и включи режим ERRMODE_EXCEPTION. Тогда ты должен увидеть ошибку.
Также, вот это очень странно:
> ORDER BY :sort :order
Вставить в запрос с помощью параметров можно только числа и строки но не имена полей или таблиц. Так как у тебя получается неправильный запрос ORDER BY "name" вместо ORDER BY name который работать не будет.
Имена полей придется вставлять в запрос напрямую.
Насчет полей понял, уже поменял, но вот такой код
ORDER BY $sort $order LIMIT :num, :records все равно не работает, зато вот такой:
ORDER BY $sort $order LIMIT $num, :records без параметра :num работает. Почему вторую переменную после LIMIT можно передать параметром, а первую нет?
Тогда в чем у меня ошибка?
Что означает строка в гайде:
"После установки Composer устанавливать Yii можно запустив следующую команду в папке доступной через веб:"
- Открываешь командную строку
- Вводишь команду из мануала, жмешь Enter
- Если все ок то юи установится
Гайд по командной строке: https://gist.github.com/codedokode/10539568
Что такое и как пользоваться композером: http://habrahabr.ru/post/145946/
Там на хабре большая статья, но главная идея композера в том что с ним не надо руками скачивать никакие библиотеки, ты просто вписываешь их названия и версии в composer.json (или набираешь команду которая это сделает ) и композер сам их скачает и установит в нужную папку.
Если еще что-то непонятно, спрашивай.
Папка доступная через веб это корневая папка сайта. Та которая открывается когда ты через браузер открываешь http://site.local/
Так в чем тут ошибку, не пойму? Почему неправильный синтаксис sql? Я же нормально параметр вставил.
я посмотрел, статья на хабре про композер конечно довольно сложная.
Главное что надо запомнить что ты можешь вписать названия и версии библиотку в composer.json после чего доступны 2 команды:
php composer.phar install - установить те библтотеки которые добавлены в composer.json но еще не установлены
php composer.phar update обновить все установленные библиотеки до новых версий
Композер сам скачает и установит библиотеки в папку vendor и создаст файл с автозагузчиком классов vendor/autoload.php который надо подключить в своем коде чтобы подключить библиотеки.
Библиотеки доступные через композер хранятся на packagist.org там можно посмотреть точное название и версии которые вписываются в composer.json
После LIMIT должны идти числа а не строки в кавычках.
Потому надо добавить в bindValue PARAM_INT чтобы параметры вставлялись как числа без кавычек
А, может дело в том что 0 у тебя в функию передается как строка а не число? Странно, надо проверить у себя.
попробуй оставить bindValue(..., intval($num), PDO::PARAM_INT)
Похоже там строки автоматически не преобразуются в число даже при использовании PARAM_INT потому надо явно сделать преобраование через intval. Это конечно недоработка разработчиков PDO.
А вообще, если ты устанавливал его установщиком то через установку/удаление программ в панели управления наверно.
При установке он просит указать путь к php.exe, я указал путь на 5.3 php, в open-server. Он установился. Потом прочитав что нужен 5.4+ я попытался установить на 5.4 но инсталлер указал на то, что компосер уже привязан к другой версии и нужно сперва его удалить.
Теперь при установке на php 5.4 выдает ошибку:
The openssl extension is missing, which means that secure HTTPS transfers are impossible.
If possible you should enable it or recompile php with --with-openssl.
Но ты все равно можешь запускать композер, только более неудобным способом вроде такого:
php "c:/composer/composer.phar" install
То есть напрямую указывая путь к композеру. Это на тот случай если ты не сможешь установить.
Это работает за счет того, что composer.phar это архив с php файлами и php может запустить его если ему указать путь к файлу.
Я сам ставлю композер без установщика, просто скачиваю composer.phar и кладу в папку, потому с этим не сталкивался.
Сделай в комнадной строке команды
php -v (показать версию)
php -i (показать информацию о настройках)
И в настройках поищи какой указан путь к php.ini. Соответственно, дальге там надо будет раскомментировать строку с extension=openssl
Команда php -i выводит много информации, найти нужную можно отфильтровав ее командой find, например
php -i | find "php.ini"
выведет то что надо.
5.3.29 (как изменить чтобы запускалась 5.4?, в настройках open server php driver выбрал 5.4)
php.ini загружает из папки с 5.3 .
Проверить что openssl доступен можно выведя список расширений php командой
php -m
Или чтобы оставить только одну строчку
php -m | find "ssl"
Ты можешь спросить откуда я узнал эти команды и оции вроде -m? Они оисаны тут: http://php.net/manual/ru/features.commandline.options.php
Или можно просто набрать php -h
> (как изменить чтобы запускалась 5.4?, в настройках open server php driver выбрал 5.4
Настройки open server влияют только на него, а не на всю систему. Чтобы php в командной строке был нужной версии, надо открывать командную строку через openserver, там где-то есть пункт такой. При этом он выставит значение PATH так, чтобы php искался в нужной папке.
Зря ты ставишь openserver конечно. Начинабщему лучше самому ставить Апач, PHP, MySQL.
У меня до вчера была сборка Денвера, но последняя сборка поддерживала только php 5.3.29 версию.
А в списке php -m есть строчка openssl ? Если исопльзуется именно этот php.ini то должна быть.
Проверить какой php.ini исользуется можно через команду которую я писал выше.
Ну и старье этот твой денвер. Нафига его вообще ставить? К тому же там еще и регистацию требуют.
Значит в этой командной строке в этой версии php с этим файлом php.ini он есть и композер не должен жаловаться.
Я по сути ничего не менял нигде, но теперь сделав всё то же что и раньше с гайда на гите у меня началась загрузка фреймворка, очень всё это странно.
После установки приложение будет доступно по следующему URL:
http://localhost/basic/web/index.php
Warning: require(D:\Webserver\OpenServer\domains\localhost\basic\web/../vendor/autoload.php): failed to open stream: No such file or directory in D:\Webserver\OpenServer\domains\localhost\basic\web\index.php on line 7
Fatal error: require(): Failed opening required 'D:\Webserver\OpenServer\domains\localhost\basic\web/../vendor/autoload.php' (include_path='.;d:/webserver/openserver/modules/php/PHP-5.4;d:/webserver/openserver/modules/php/PHP-5.4/PEAR/pear') in D:\Webserver\OpenServer\domains\localhost\basic\web\index.php on line 7
Открой index.php и исправь путь к vendor/autoload.php, скорее всего надо добавить пару ../.. (.. значит подняться на папку выше).
Похоже что-то в туториале неправильно было написано.
я раньше немного работал с системой сеток бутстрапа, но не понимаю как её тут применить .
может кто разъяснить или подсказать шаблон который можно взять и доработать руками.
А КАКАЯ РЕАЛЬНО РАЗНИЦА??
У меня нет ни папки vendor ни папки yii в папке Basic куда Yii должна была установиться.
Ладно, спустя полдня ебли с мануалами вдруг оказалось, что open-server последних версий уже содержит в себе установленный composer и все проблемы из-за того, что я запускал стандартную консоль, а надо было запускать консоль open-server'a. Может кому-то пригодится.
Код здесь https://ideone.com/myD9CN
отклеилась
Да
С intvalом заработало. Ну и зачем тогда PDO::PARAM_INT нужен? Бесполезный параметр.
https://github.com/MindiMakridi/Students
Ох и не завидую я тебе, ОП. Об шаблона главной страницы можно повредиться рассудком.
Аноны, поясните пожалуйста, если писать корзину для интернет-магазина, то лучше всего данные сохранять в куки или Сессии? А то у меня с куками получается а с сессиями не очень.
>>429779
Я проверил твой код. Тут настало время рефакторинга надо правильно разнести методы по классам и по мелочам кое-что подправить.
У тебя конечно все печально с архитектурой. Классы есть, но чем занимается каждый, не очень ясно. Например класс Thumbnail кроме создания уменьшенной копии картинки, зачем-то лезет в базу, класс Upload зачем то одновременно с загрузкой картинки делает превьюшку. Тут надо все разложить по полочкам, может даже схему нарисовать кто кого вызывает, и решить какой класс чем занимается. Каждый должен заниматься своим делом.
В твоем случае логично сделать:
- класс работающий с БД
- класс умеющий уменьшать/обрезать картинки, и ничего более
- возможно, стоит сделать класс объект которого хранит информацию о картинке, чтобы избавиться от функций с 6 аргументами
- класс который всем этим дирижирует
Классы не должны быть спутаны друг с другом. Например, функция генерации уменьшенной картинки должна генерировать уменьшенную картинку и не зависеть от наличия базы данных.
То есть к примеру, делаем класс ImageManager, и у него метод для сохранения картинки, а также метод получения превьюшки. А уже он вызывает другие классы.
Так как это все может быть сложно держать в голове, сначала стоит описать какие классы будут, чем каждый занимается, и примерно прикинуть, какие у них должны быть методы, что они будут принимать и возвращать.
Ну в твоем случае, начнем с высокоуровневых функций. Нужны функции сохранения файла, получения превьюшки, получения всех превьюшек к файлу, удаления файла и превьюшек, в общем ты лучше меня наверно это представляешь. А уже эти функции будут для своей работы вызывать более низкоуровневые методы других классов.
Ты можешь список классов и функций запостить, и я проверю и дам советы.
При этом не требуется выкидывать уже написанный код, надо просто навести порядок и возможно перенести какие-то методы в другой класс и чуть подправить.
Также, по поводу базы данных, я не вижу связи между таблицами. как они связаны? Где внешние ключи? Почему некоторые колонки повторяются в обеих таблицах? Почитай-ка про нормализацию:
http://club.shelek.ru/viewart.php?id=311
http://habrahabr.ru/post/129195/
Также, почитай про внешние ключи для связи таблиц:
http://denis.in.ua/foreign-keys-in-mysql.htm
Тебе явно надо их использовать.
Также, небольшие замечания по остальному коду:
> https://github.com/someApprentice/ThumbnailService/blob/master/upload.php#L27
> if($errors) exit;
Как-то странно при ошибке молча завершить скрипт. Логичнее показывать форму с введенными в нее значениями и сообщением об ошибке. Чтобы это сделать, надо переделать алгоритм обработки данных их формы (
это универсальный алгоритм для любых форм):
------------
$values = значения по умолчанию (пустые);
$errors = пустой массив;
Если (форма отправлена через POST) {
Читаем значения полей в $values;
Проверяем все ли верно;
Кладем ошибки в $errors;
Если (все заполнено верно) {
Делаем требуемое действие (например вставляем запись в БД);
Редиректим куда-нибудь;
Завераем скрипт;
}
}
Выводим форму($values, $errors);
-------------
Также, не очень понятно, почему часть проверок в validateForm, а часть нет, например эта: «
if (!$extension = $upload->getExtension($fileName)) {...»
> https://github.com/someApprentice/ThumbnailService/blob/master/upload.php#L13
Конструкцию вида
if () {
много строк
} else {
одна строка
}
Надо перевернуть чтобы таких больших блоков не было, например, так:
if () {
одна строка;
exit;
}
много строк;
> https://github.com/someApprentice/ThumbnailService/blob/master/Classes/Database.php#L7
> public function newName($originalname) {
Не очень понятно зачем в класс Database класть функцию генерации имени, которая никак не обращается к базе данных. Может ее в Upload поместить?
> https://github.com/someApprentice/ThumbnailService/blob/master/Classes/Database.php#L8
> $extension = array(end($originalname));
Это тяжело читать. Получение расширения из имени надо сделать отдельной функцией. Можно статическим методом в каком-нибудь классе вроде Util.
> https://github.com/someApprentice/ThumbnailService/blob/master/Classes/Database.php#L15
> $ru = "А а Б б В в Г г Д д Е е Ё ё Ж ж
Это неудачное решение так как трудно понять какая русская буква соответствует какой латинской.
> $value = '/' . $value . '/u';
Чтобы заменить одну букву на другую не нужны регулярки, есть же функиця strtr (которую мы использовали в задаче про шифрование).
> https://github.com/someApprentice/ThumbnailService/blob/master/Classes/Database.php#L32
> Connect::getPdo( );
Статический метод и явно прописанное имя класса Connect плохо. Надо передавать объект pdo в конструктор Database. Почему подробно разъяснено в этом уроке, хотя он может быть сложным для начинающего: https://gist.github.com/codedokode/e1d31a31b37d5f635057
> https://github.com/someApprentice/ThumbnailService/blob/master/Classes/Database.php#L77
> $name = isset($_GET['name'])
Ты смешиваешь все в кучу. Класс работы с базой данных не должен лезть в GET, имя можно передать обычным аргументом в функцию.
> https://github.com/someApprentice/ThumbnailService/blob/master/Classes/Thumbnail.php#L60
> Database::addThumbnail($name, $thumbnailName, $hash, $newWidth_p, $newHeight_p, $thumbnailDirectory);
Не надо использовать статический метод тут (статические методы используются в редких случаях, вроде вспомогательных функций). addThumbnail нужен объект PDO, а он у тебя будет храниться в поле объекта, доступа к которому из статического метода нет.
Также, не пиши if без фигурных скобок в одну строчку. Пиши нормально, с фигурными скобками и в 3 строки.
>>429779
Я проверил твой код. Тут настало время рефакторинга надо правильно разнести методы по классам и по мелочам кое-что подправить.
У тебя конечно все печально с архитектурой. Классы есть, но чем занимается каждый, не очень ясно. Например класс Thumbnail кроме создания уменьшенной копии картинки, зачем-то лезет в базу, класс Upload зачем то одновременно с загрузкой картинки делает превьюшку. Тут надо все разложить по полочкам, может даже схему нарисовать кто кого вызывает, и решить какой класс чем занимается. Каждый должен заниматься своим делом.
В твоем случае логично сделать:
- класс работающий с БД
- класс умеющий уменьшать/обрезать картинки, и ничего более
- возможно, стоит сделать класс объект которого хранит информацию о картинке, чтобы избавиться от функций с 6 аргументами
- класс который всем этим дирижирует
Классы не должны быть спутаны друг с другом. Например, функция генерации уменьшенной картинки должна генерировать уменьшенную картинку и не зависеть от наличия базы данных.
То есть к примеру, делаем класс ImageManager, и у него метод для сохранения картинки, а также метод получения превьюшки. А уже он вызывает другие классы.
Так как это все может быть сложно держать в голове, сначала стоит описать какие классы будут, чем каждый занимается, и примерно прикинуть, какие у них должны быть методы, что они будут принимать и возвращать.
Ну в твоем случае, начнем с высокоуровневых функций. Нужны функции сохранения файла, получения превьюшки, получения всех превьюшек к файлу, удаления файла и превьюшек, в общем ты лучше меня наверно это представляешь. А уже эти функции будут для своей работы вызывать более низкоуровневые методы других классов.
Ты можешь список классов и функций запостить, и я проверю и дам советы.
При этом не требуется выкидывать уже написанный код, надо просто навести порядок и возможно перенести какие-то методы в другой класс и чуть подправить.
Также, по поводу базы данных, я не вижу связи между таблицами. как они связаны? Где внешние ключи? Почему некоторые колонки повторяются в обеих таблицах? Почитай-ка про нормализацию:
http://club.shelek.ru/viewart.php?id=311
http://habrahabr.ru/post/129195/
Также, почитай про внешние ключи для связи таблиц:
http://denis.in.ua/foreign-keys-in-mysql.htm
Тебе явно надо их использовать.
Также, небольшие замечания по остальному коду:
> https://github.com/someApprentice/ThumbnailService/blob/master/upload.php#L27
> if($errors) exit;
Как-то странно при ошибке молча завершить скрипт. Логичнее показывать форму с введенными в нее значениями и сообщением об ошибке. Чтобы это сделать, надо переделать алгоритм обработки данных их формы (
это универсальный алгоритм для любых форм):
------------
$values = значения по умолчанию (пустые);
$errors = пустой массив;
Если (форма отправлена через POST) {
Читаем значения полей в $values;
Проверяем все ли верно;
Кладем ошибки в $errors;
Если (все заполнено верно) {
Делаем требуемое действие (например вставляем запись в БД);
Редиректим куда-нибудь;
Завераем скрипт;
}
}
Выводим форму($values, $errors);
-------------
Также, не очень понятно, почему часть проверок в validateForm, а часть нет, например эта: «
if (!$extension = $upload->getExtension($fileName)) {...»
> https://github.com/someApprentice/ThumbnailService/blob/master/upload.php#L13
Конструкцию вида
if () {
много строк
} else {
одна строка
}
Надо перевернуть чтобы таких больших блоков не было, например, так:
if () {
одна строка;
exit;
}
много строк;
> https://github.com/someApprentice/ThumbnailService/blob/master/Classes/Database.php#L7
> public function newName($originalname) {
Не очень понятно зачем в класс Database класть функцию генерации имени, которая никак не обращается к базе данных. Может ее в Upload поместить?
> https://github.com/someApprentice/ThumbnailService/blob/master/Classes/Database.php#L8
> $extension = array(end($originalname));
Это тяжело читать. Получение расширения из имени надо сделать отдельной функцией. Можно статическим методом в каком-нибудь классе вроде Util.
> https://github.com/someApprentice/ThumbnailService/blob/master/Classes/Database.php#L15
> $ru = "А а Б б В в Г г Д д Е е Ё ё Ж ж
Это неудачное решение так как трудно понять какая русская буква соответствует какой латинской.
> $value = '/' . $value . '/u';
Чтобы заменить одну букву на другую не нужны регулярки, есть же функиця strtr (которую мы использовали в задаче про шифрование).
> https://github.com/someApprentice/ThumbnailService/blob/master/Classes/Database.php#L32
> Connect::getPdo( );
Статический метод и явно прописанное имя класса Connect плохо. Надо передавать объект pdo в конструктор Database. Почему подробно разъяснено в этом уроке, хотя он может быть сложным для начинающего: https://gist.github.com/codedokode/e1d31a31b37d5f635057
> https://github.com/someApprentice/ThumbnailService/blob/master/Classes/Database.php#L77
> $name = isset($_GET['name'])
Ты смешиваешь все в кучу. Класс работы с базой данных не должен лезть в GET, имя можно передать обычным аргументом в функцию.
> https://github.com/someApprentice/ThumbnailService/blob/master/Classes/Thumbnail.php#L60
> Database::addThumbnail($name, $thumbnailName, $hash, $newWidth_p, $newHeight_p, $thumbnailDirectory);
Не надо использовать статический метод тут (статические методы используются в редких случаях, вроде вспомогательных функций). addThumbnail нужен объект PDO, а он у тебя будет храниться в поле объекта, доступа к которому из статического метода нет.
Также, не пиши if без фигурных скобок в одну строчку. Пиши нормально, с фигурными скобками и в 3 строки.
Я ничего не понял =_____________=
Вот например начнем по порядку:
>В твоем случае логично сделать:
>
>- класс работающий с БД
>- класс умеющий уменьшать/обрезать картинки, и ничего более
>- возможно, стоит сделать класс объект которого хранит информацию о картинке, чтобы избавиться от функций с 6 аргументами
>- класс который всем этим дирижирует
Вот допустим у нас появляется класс который всем дирижирует - Core.php
При загрузке изображения вызывается скрипт upload.php, в котором:
$core->upload($name, $size, $type, $temp);
А в самом классе Core.php происходит следующее:
public function upload(...) {
$upload = new Upload;
$database = new Database;
$thumbnail = new Thumbnail;
Вызов необходимых методов для загрузки;
}
Это правильно?
>Классы не должны быть спутаны друг с другом. Например, функция генерации уменьшенной картинки должна генерировать уменьшенную картинку и не зависеть от наличия базы данных.
А как тогда без БД узнать какую картинку надо уменьшать/есть ли уже такая картинка?
>То есть к примеру, делаем класс ImageManager, и у него метод для сохранения картинки, а также метод получения превьюшки. А уже он вызывает другие классы.
Т.е. класс ImageManager тоже самое что мой Core?
Я ничего не понял =_____________=
Вот например начнем по порядку:
>В твоем случае логично сделать:
>
>- класс работающий с БД
>- класс умеющий уменьшать/обрезать картинки, и ничего более
>- возможно, стоит сделать класс объект которого хранит информацию о картинке, чтобы избавиться от функций с 6 аргументами
>- класс который всем этим дирижирует
Вот допустим у нас появляется класс который всем дирижирует - Core.php
При загрузке изображения вызывается скрипт upload.php, в котором:
$core->upload($name, $size, $type, $temp);
А в самом классе Core.php происходит следующее:
public function upload(...) {
$upload = new Upload;
$database = new Database;
$thumbnail = new Thumbnail;
Вызов необходимых методов для загрузки;
}
Это правильно?
>Классы не должны быть спутаны друг с другом. Например, функция генерации уменьшенной картинки должна генерировать уменьшенную картинку и не зависеть от наличия базы данных.
А как тогда без БД узнать какую картинку надо уменьшать/есть ли уже такая картинка?
>То есть к примеру, делаем класс ImageManager, и у него метод для сохранения картинки, а также метод получения превьюшки. А уже он вызывает другие классы.
Т.е. класс ImageManager тоже самое что мой Core?
>Так как это все может быть сложно держать в голове, сначала стоит описать какие классы будут, чем каждый занимается, и примерно прикинуть, какие у них должны быть методы, что они будут принимать и возвращать.
>Ну в твоем случае, начнем с высокоуровневых функций. Нужны функции сохранения файла, получения превьюшки, получения всех превьюшек к файлу, удаления файла и превьюшек, в общем ты лучше меня наверно это представляешь. А уже эти функции будут для своей работы вызывать более низкоуровневые методы других классов.
>Ты можешь список классов и функций запостить, и я проверю и дам советы.
Вообще ничего не понял =___________________________________=
Ну все же попробую шевельнуть извилиной и написать список классов и функций:
Core.php
public function form(...) {
проверка значений формы;
}
============================================
public function upload(...) {
if (файл уже существует) {
if (заданы пропорции превью) {
self::thumbnail;
}
выход;
}
$hash = $upload->generateHash(...);
if ($database->validateImageHash($hash)) {
выход и вывод ошибки;
}
$directory = $upload->createDirectory(...);
$upload->uploadFile(...);
if (!$database->addImage(...)) {
удаление файла и вывод ошибки;
}
if (заданы пропорции превью) {
self::thumbnail;
}
return true
}
============================================
public function thumbnail(...) {
if (такой размер уже существует) {
выходим;
}
$thumbnailName = $thumbnail->createThumbnail(...); //возвращает имя созданной превьюшки
$upload->createDirectory($thumbnailName);
$hash = upload->generateHash($thumbnailName);
$database->addThumbnail(...); //надо ли здесь делать проверку и в случае неудачи удалять превью?
return true;
}
============================================
public function delete(...) {
вызов фукнций на удаление изображения и превью с жесткого диска и бд.
}
=============================================
>Так как это все может быть сложно держать в голове, сначала стоит описать какие классы будут, чем каждый занимается, и примерно прикинуть, какие у них должны быть методы, что они будут принимать и возвращать.
>Ну в твоем случае, начнем с высокоуровневых функций. Нужны функции сохранения файла, получения превьюшки, получения всех превьюшек к файлу, удаления файла и превьюшек, в общем ты лучше меня наверно это представляешь. А уже эти функции будут для своей работы вызывать более низкоуровневые методы других классов.
>Ты можешь список классов и функций запостить, и я проверю и дам советы.
Вообще ничего не понял =___________________________________=
Ну все же попробую шевельнуть извилиной и написать список классов и функций:
Core.php
public function form(...) {
проверка значений формы;
}
============================================
public function upload(...) {
if (файл уже существует) {
if (заданы пропорции превью) {
self::thumbnail;
}
выход;
}
$hash = $upload->generateHash(...);
if ($database->validateImageHash($hash)) {
выход и вывод ошибки;
}
$directory = $upload->createDirectory(...);
$upload->uploadFile(...);
if (!$database->addImage(...)) {
удаление файла и вывод ошибки;
}
if (заданы пропорции превью) {
self::thumbnail;
}
return true
}
============================================
public function thumbnail(...) {
if (такой размер уже существует) {
выходим;
}
$thumbnailName = $thumbnail->createThumbnail(...); //возвращает имя созданной превьюшки
$upload->createDirectory($thumbnailName);
$hash = upload->generateHash($thumbnailName);
$database->addThumbnail(...); //надо ли здесь делать проверку и в случае неудачи удалять превью?
return true;
}
============================================
public function delete(...) {
вызов фукнций на удаление изображения и превью с жесткого диска и бд.
}
=============================================
>Также, по поводу базы данных, я не вижу связи между таблицами. как они связаны? Где внешние ключи? Почему некоторые колонки повторяются в обеих таблицах? Почитай-ка про нормализацию:
>
>
>Также, почитай про внешние ключи для связи таблиц:
>
>
>Тебе явно надо их использовать.
Хорошо, я это прочту как разберусь с кодом. И еще остальные полезные статьи ты кидал. Я со всеми этими полезностями планировал ознакомиться перед написанием хостинга. У тебя вроде есть такая задачка же?
С остальным позже, как переварю и переделаю то что выше. Ниже вроде бы не очень сложно сделать.
$wall = array(
\tarray('.', '.', '.', '.'),
\tarray('.', '@', '.', '.'),
\tarray('.', '.', '.', '.'),
\tarray('.', '.', '.', '.')
);
foreach($wall as $keyY => $valueY) {
\tforeach($valueY as $keyX => $valueX) {
\t\tif($valueX == '@') {
\t\t\tfor ($i = -1; $i < 2; $i++) {
\t\t\t\tfor ($j = -1; $j < 2; $j++) {
\t\t\t\t\tif ((($i != 0) xor ($j != 0)) or (($i != 0) and ($j != 0))) {
\t\t\t\t\t\tif(isset($wall[$keyY + $i][$keyX + $j])) $opportunity[] = array($keyY + $i, $keyX + $j);
\t\t\t\t\t}\t
\t\t\t\t}
\t\t\t}
\t\t\t
\t\t\t//Тут выполняется дальнейшие действия с перемещением
\t\t}
\t}
}
Как насчет айдеона? Сделай хотя бы для начала чтобы на поле было одно животное и пару его ходов, хотя бы рандомных.
> Вот допустим у нас появляется класс который всем дирижирует - Core.php
Название плохое так как ничего не значит. Лучше что-то говорящее о том что это класс работы с изображенияим и превьюшками: ImageManager, ImageService.
> При загрузке изображения вызывается скрипт upload.php, в котором:
> А в самом классе Core.php происходит следующее:
> Это правильно?
В общем, да, но не совсем так. Во-первых, ты не написал что возвращает upload(), во-вторых, неясно занимается ли она проверкой размера, типа файла или нет. Далее, не уверен что надо передавать type так как это переданный браузером тип и там может быть в принципе что угодно. Нет никаких гарантий что он соответствует настоящему типу файла.
Ну и вместо того чтобы создавать объекты Database внутри Core, лучше их передавать через конструктор. Это описано тут под названием «внедрение зависимостей»: https://gist.github.com/codedokode/e1d31a31b37d5f635057
Это конечно сложная тема для начинающего, но когда мы передаем Database через конструктор, мы получаем более гибкий и менее спутанный код.
>>Классы не должны быть спутаны друг с другом. Например, функция генерации уменьшенной картинки должна генерировать уменьшенную картинку и не зависеть от наличия базы данных.
> А как тогда без БД узнать какую картинку надо уменьшать/есть ли уже такая картинка?
А это не задача Thumbnail, проверять. Это должен делать вышестоящий класс, например, Core. А задача Thumbnail только уменьшать картинку. Его кстати стоило бы переименовать в ImageResizer или как-то так. Ибо название Thumbnail намекает на то что это объект представляющий собой превьюшку, и это не соответствует действительности.
> Т.е. класс ImageManager тоже самое что мой Core?
Да. Только название лучше отражает его деятельность.
У тебя в твоем наброске есть проблемы:
Непонятно что делают методы, наеример thumbnail. Создает превьюшку? Возвращает ранее созданную? Удаляет? Из названия это неочевидно, а пояснения нет. Что он получает на вход? Что должен вернуть? Это (аргументы и возвращаемый результат) горадо важнее чем его содержимое. Мы сначала должны решить что делает метод, что получает, что возвращает, а потом писать код.
> Ну все же попробую шевельнуть извилиной и написать список классов и функций:
> public function upload(...) {
> if (заданы пропорции превью) {
> self::thumbnail;
Не очень понятно почему метод upload (загрузка файла на сервер) заодно делает превьюшку. Не логичнее ли сделать 2 отдельных метода: один для проверки и сохранения картинки, второй для получения превьюшки из любой, в том числе ранее загруженной, картинки?
Попробуй исправить. Сейчас важно не само содержимое методов, а четкое определение, что они делают, что получают и что возвращают. Как именно они это будут делать, не так принципиально.
Зачем ты хранишь данные в массиве строчек? зачем вообще нужен этот массив? Это же задача на ООП.
Когда ты решаешь задачу на ООП, ты должен ответить на вопросы:
какие есть сущности, для которых мы сделаем классы? (Кошки, Мышки, Карта о которой они ходят. Может быть еще класс Игра который всем этим управляет)
какие у них есть свойства (координаты например, размер карты).
что мы хотим от них получить, что они должны уметь делать (какие у них должны быть методы). Например, от карты мы можем хотеть получить список всех кошек на ней или список кошек в определенном радиусе от мышки. От мышки мы хотим чтобы она умела выбирать и делать ход.
как сущности связаны между собой? Очевидно, Мышки и Кошки ходят по Карте, их можно добавлять и убирать с нее.
Советую начать с краткого описания: какие классы ты создаешь, какие у них свойства и методы, как они связаны. Конкретные алгоритмы, что находится внутри методов, писать не надо. Можешь написать сюда, а я проверю, дам советы и предупрежу про подвохи.
Форматирование сбилось. Вот список вопросов:
какие у нас есть сущности, для которых мы сделаем классы?
какие у них есть свойства?
что мы хотим от них получить, что они должны уметь делать?
как сущности связаны между собой?
Ну так исправляйся. Я всегда при проверке решений стараюсь обращать на такое внимание.
Кстати, я не знал что wrap клонирует элементы. Но я им и не пользуюсь, а вот многие плагины пользуются и из-за этого даже баги бывают на сложной верстке.
Ну и прокомментирую:
> Эффективность этого подхода особенно заметна, если тело цикла занимает одну-две страницы.
Вообще циклы на две страницы и огромные простыни кода тоже плохая идея (то есть в контексте статьи, хорошая идея для того чтобы читающий код мог в нем запутаться).
> При выборе имени старайтесь применить максимально абстрактное слово, например obj, data, value, item, elem
Еще key, string, str хорошо подходят
Спасибо за ссылку, кстати. Буду при случае давать ее анончикам.
Теперь более конкретный вопрос.
Я написал http://pastebin.com/JEreHfJU , оно привязано к стандартным стилям бутстрапа , получился пикрелейтед .
Объясните пожалуйста как форму с инпутами переместить в правый верхних угол , а слева поставить лого. В нему не применяется align
Тебе сначала надо изучить CSS. Какой еще align? Это было в HTML3 15 лет назад. Без знания CSS верстать невозможно.
В данном случае форму можно поместить за счет абсолютного позиционирования или float right. Эти способы разные и выбирать надо исходя из того что ты хочешь получить.
Я советую почитать этот учебник, там рассказывается про позиционирование в CSS. Я даю тебе ссылку, так как вижу из твоего вопроса, что в CSS ты совсем не разбираешься, а без этого верстать невозможно: http://softwaremaniacs.org/blog/category/primer/
Там вроде объясняется как сделать раскладку сайта из 2 колонок.
Если ты хочешь изучить HTML/CSS на хорошем уровне и у тебя есть время и желание, у меня есть неплохие задания: https://gist.github.com/codedokode/58ebc90bd006baf4b35c
Я могу проверить решения задач, дать советы и замечания.
Система сеток тут не причем. Верстка на картинке простая, но чтобы ее сделать, надо разбираться в CSS, в позиционировании элементов, знать какие есть способы влиять на их расположение (это свойства display, float, clear, position).
Бампану на всякий случай. Алсо, ОП, не мешало бы добавить во второй или хотя-бы в третий пост задачки на ЖС, хтмл и прочие ссылки, которых в оп-посте нет. А то как-то неудобно персонально каждому выдавать их.
> Я со всеми этими полезностями планировал ознакомиться перед написанием хостинга. У тебя вроде есть такая задачка же?
Файлообменника? Да, есть https://gist.github.com/codedokode/9424217
Но перед ее решением я советую добить задачи про картинки и кошек-мышек. Лучше сразу научиться нормально использовать классы, чем привыкнуть неправильно и потом все переделывать.
Могу ошибаться но алерт будет выскакивать после выполнения функции, а к этому моменту list.value = 4
Нет, alert нормально работает, выводит последовательно все значения от 1ого до 4ех (но не рекомендую тестировать это у себя в браузере, дальше поймешь почему), однако на 4 он зацикливается и alert продолжает выводить 4ку до бесконечности.
Тебе надо изучать рекурсию. Я вижу что ты не понимаешь как работают рекурсивные вызовы функций и что в каждом вызове у нас свой набор переменных.
Если тебе будет понятнее, посмотри по шагам что происходит:
var list = { value: 3, next: непустое значение };
showList(list);
------------
# ывыводим цифру 3
alert(list.value);
# Пока list.next не пусто (так и есть)
while(list.next != null) {
# вызываем функцию showList (она выведет 4 и завершится)
showList(list.next);
# После чего повторяем цикл (бесконечное число раз)
}
Бред какой-то, если честно. Ты пишешь зачем-то в коде бесконечный цикл, значит ты хочешь чтобы код работал бесконечно, так? Если нет то зачем бесконечный цикл? Я не могу понять.
Начни для начала с того, что определи что ты хочешь сделать. затем напиши алгоритм словами. А только потом пиши код.
Ну и я бы советовал тебе попросить у меня задачку-другую на рекурсию.
Также ты и в первом и во втором варианте кода не учиытваешь важную вещь. Переменная list внутри функции не изменяется. Раз так то условия вроде
> if(list.next==null) {
> while(list.next != null) {
Всегда дают один и тот же результат. Цикл либо не выполнится ни разу либо выполнится бесконечное число раз.
Ну и заменяй alert на console.log, никто сейчас alert не использует.
Он не бесконечный, он прерывается, когда нет следующего подмассива.
http://learn.javascript.ru/array-methods Тут почти такое же решение, только без рекурсии.
> Он не бесконечный, он прерывается
Он бесконечный. Замени showList(list.next); на console.log(list.next) и посмотри на код внимательно.
> Тут почти такое же решение, только без рекурсии.
Ну так это совсем другое.
>>430395
Тут нормально. Хотя я не понимаю, зачем тут вообще рекурсия если можно сделать только циклом. Зачем делать сложно когда можно написать проще? Наркоманство какое-то.
Я думал рекурсией проще. Справедливости ради, там следующая задача все равно на рекурсию. А у меня уже готовый код, который нужно было только немного изменить.
>>Не туда action поставил
> Почему не туда? На текущую страницу.
Атрибут action надо ставить на тег form, а не input
>>429945
Я конечно надеялся, что мы уже доделаем это задание, но замечания по-прежнему есть. В основном к оформлению и стилю написания кода.
> https://github.com/MindiMakridi/Students/blob/master/index.php#L95
> $search = $_GET['search'];
Тут надо делать trim иначе один лишний невидимый пробел приведет к тому что ничего не найдется
После успешной регистации надо писать «Вы успешно зарегистрировались и добавлены в список», а после редактирования «Изменения сохранены». А то нету никакой обратной связи, непонятно сохранилось что-то или нет. Это можно сделать если после сохранения редиректить на адрес вроде profile.php?msg=saved
> $nameArrow = "";
> $groupArrow = "";
> $pointsArrow = "";
> $directionName = "ASC";
> $directionGroup = "ASC";
> $directionPoints = "ASC";
Нехорошо как-то. Когда будет 8 колонок ты сделаешь 8 переменных? Нельзя ли уменьшить число переменных до 2-3? Заодно наверно и кода в index.php меньше станет.
> https://github.com/MindiMakridi/Students/blob/master/templates/header.html#L13
Не туда action поставил. Оно к form относится.
> https://github.com/MindiMakridi/Students/blob/master/templates/main.html#L10
> <?=$searchText?>
А это не XSS случайно? Пройдись так же по всем шаблонам и проверь, нет ли еще таких ошибок.
> https://github.com/MindiMakridi/Students/blob/master/templates/main.html#L4
> value=<?= htmlspecialchars($search, ENT_QUOTES) ?>>
Значение атрибута value надо брать в кавычки, иначе в лучшем случае оно может обрезаться (если в нем есть пробел), в худшем появится возможность для какой-нибудь уязвимости. Пройдись так же по всем шаблонам и проверь, нет ли еще таких ошибок.
> https://github.com/MindiMakridi/Students/blob/master/templates/main.html#L13
> href=<?= htmlspecialchars($currentPage)?>?num=<?= $i*$recordsPerPage?>.....
Это очень длинная строка. Смотри, как лучше делать такие ссылки. Делаем в файле index.php шаблон ссылки, например
$pagerUrl = 'index.php?sort=name&desc=ASC&search=xyz&num=';
И в шаблоне делаем из него полную ссылку:
<a href="<?= html( $pagerUrl . $i ) ?>">
Аналогично надо переделать адские длинные ссылки в заголовках колонок для сортировки.
> https://github.com/MindiMakridi/Students/blob/master/templates/main.html#L21
> if(isset($_GET['search'])):
Шаблон не должен обращаться к GET. Вместо этого ему надо передавать переменную, например $isSearchMode
> https://github.com/MindiMakridi/Students/blob/master/templates/main.html#L35
Тут очень длинно. Перенеси на несколько строк. Аналогично, пройдись по другим шаблонам и все строки длинее 80-100 символов перенеси, чтобы на гитхабе ни одна строка не уходила за правый край области с кодом.
> https://github.com/MindiMakridi/Students/blob/master/profile.php#L21
> if (!$mapper->fetchProfile($code)) {
> $profile = $mapper->fetchProfile($code);
Надо убрать повторный запрос в базу. Вызывай fetchProfile только один раз.
> https://github.com/MindiMakridi/Students/blob/master/profile.php#L27
> }
> ....
> else {
Почему тут перед else так много пустых строк? Запутывает же.
> https://github.com/MindiMakridi/Students/blob/master/lib/DataMapper.php#L37
> $regExp2 = "/^(ASC|DESC)$/ui";
Ужасное название переменной. Лучше написать что-то вроде $orderRegExp. Почитай-ка статью: http://learn.javascript.ru/write-unmain-code#будьте-абстрактны-при-выборе-имени - она как раз про это.
В profile.php куда-то потерялась защита от XSRF. Была же раньше!
> https://github.com/MindiMakridi/Students/blob/master/lib/PDO.php#L8
> catch (PDOException $e) {
Не надо ставить try/catch тут. Ибо ты зачем-то пользователю выводишь технические подробности которые ему не понятны (а взломщику наоборот даешь ценную информацию). Более того, в твоем варианте сообщение об ошибке не попадет ни в какие логи и ты о нем не узнаешь.
Если же не писать try/catch, то наоборот, сообщение попадет в логи, пользователь его скорее всего не увидит (если отключен display_errors), а ты у себя увидишь (если включен display_errors). Ты по моему не очень понимаешь, как работают исключения. Почитай-ка мой урок, может он окажется полезен: https://gist.github.com/codedokode/65d43ca5ac95c762bc1a
>>Не туда action поставил
> Почему не туда? На текущую страницу.
Атрибут action надо ставить на тег form, а не input
>>429945
Я конечно надеялся, что мы уже доделаем это задание, но замечания по-прежнему есть. В основном к оформлению и стилю написания кода.
> https://github.com/MindiMakridi/Students/blob/master/index.php#L95
> $search = $_GET['search'];
Тут надо делать trim иначе один лишний невидимый пробел приведет к тому что ничего не найдется
После успешной регистации надо писать «Вы успешно зарегистрировались и добавлены в список», а после редактирования «Изменения сохранены». А то нету никакой обратной связи, непонятно сохранилось что-то или нет. Это можно сделать если после сохранения редиректить на адрес вроде profile.php?msg=saved
> $nameArrow = "";
> $groupArrow = "";
> $pointsArrow = "";
> $directionName = "ASC";
> $directionGroup = "ASC";
> $directionPoints = "ASC";
Нехорошо как-то. Когда будет 8 колонок ты сделаешь 8 переменных? Нельзя ли уменьшить число переменных до 2-3? Заодно наверно и кода в index.php меньше станет.
> https://github.com/MindiMakridi/Students/blob/master/templates/header.html#L13
Не туда action поставил. Оно к form относится.
> https://github.com/MindiMakridi/Students/blob/master/templates/main.html#L10
> <?=$searchText?>
А это не XSS случайно? Пройдись так же по всем шаблонам и проверь, нет ли еще таких ошибок.
> https://github.com/MindiMakridi/Students/blob/master/templates/main.html#L4
> value=<?= htmlspecialchars($search, ENT_QUOTES) ?>>
Значение атрибута value надо брать в кавычки, иначе в лучшем случае оно может обрезаться (если в нем есть пробел), в худшем появится возможность для какой-нибудь уязвимости. Пройдись так же по всем шаблонам и проверь, нет ли еще таких ошибок.
> https://github.com/MindiMakridi/Students/blob/master/templates/main.html#L13
> href=<?= htmlspecialchars($currentPage)?>?num=<?= $i*$recordsPerPage?>.....
Это очень длинная строка. Смотри, как лучше делать такие ссылки. Делаем в файле index.php шаблон ссылки, например
$pagerUrl = 'index.php?sort=name&desc=ASC&search=xyz&num=';
И в шаблоне делаем из него полную ссылку:
<a href="<?= html( $pagerUrl . $i ) ?>">
Аналогично надо переделать адские длинные ссылки в заголовках колонок для сортировки.
> https://github.com/MindiMakridi/Students/blob/master/templates/main.html#L21
> if(isset($_GET['search'])):
Шаблон не должен обращаться к GET. Вместо этого ему надо передавать переменную, например $isSearchMode
> https://github.com/MindiMakridi/Students/blob/master/templates/main.html#L35
Тут очень длинно. Перенеси на несколько строк. Аналогично, пройдись по другим шаблонам и все строки длинее 80-100 символов перенеси, чтобы на гитхабе ни одна строка не уходила за правый край области с кодом.
> https://github.com/MindiMakridi/Students/blob/master/profile.php#L21
> if (!$mapper->fetchProfile($code)) {
> $profile = $mapper->fetchProfile($code);
Надо убрать повторный запрос в базу. Вызывай fetchProfile только один раз.
> https://github.com/MindiMakridi/Students/blob/master/profile.php#L27
> }
> ....
> else {
Почему тут перед else так много пустых строк? Запутывает же.
> https://github.com/MindiMakridi/Students/blob/master/lib/DataMapper.php#L37
> $regExp2 = "/^(ASC|DESC)$/ui";
Ужасное название переменной. Лучше написать что-то вроде $orderRegExp. Почитай-ка статью: http://learn.javascript.ru/write-unmain-code#будьте-абстрактны-при-выборе-имени - она как раз про это.
В profile.php куда-то потерялась защита от XSRF. Была же раньше!
> https://github.com/MindiMakridi/Students/blob/master/lib/PDO.php#L8
> catch (PDOException $e) {
Не надо ставить try/catch тут. Ибо ты зачем-то пользователю выводишь технические подробности которые ему не понятны (а взломщику наоборот даешь ценную информацию). Более того, в твоем варианте сообщение об ошибке не попадет ни в какие логи и ты о нем не узнаешь.
Если же не писать try/catch, то наоборот, сообщение попадет в логи, пользователь его скорее всего не увидит (если отключен display_errors), а ты у себя увидишь (если включен display_errors). Ты по моему не очень понимаешь, как работают исключения. Почитай-ка мой урок, может он окажется полезен: https://gist.github.com/codedokode/65d43ca5ac95c762bc1a
Э... Я не очень понял что надо сделать, а по ссылке страница 404.
>>429892
Советую также пройти мой путь HTML/CSS:https://gist.github.com/codedokode/58ebc90bd006baf4b35c
>>429864
У тебя значки в отдельных ячейках таблицы. Наверно надо поместить значки в одну ячейку и расположить вертикально. Если ты не знаешь HTML/CSS, то, к сожалению, ничего не получится.
> Я сейчас думаю над задачей с кошками мышками и поле планирую сделать двумерным массивом, допустим поле 4х4 будет выглядеть так:
Не, это что-то странное. Это задача на ООП и там должны быть объекты-кошки и объекты-мышки которые ходят по объекту-карте.
Ну не знаю, не пользовался им. Может ты просто какой-нибудь кеш не включил?
>>429347
> А зачем дебиан на десктопе?
А у меня он в виртуалке и на серверах тоже бывает. На десктопе виндоуз конечно же.
> Даже если это зачем-то кому-то нужно, есть chroot, либо распаковка собранных кем-нибудь/самостоятельно бинарных версий.
Вот-вот, а в виндоуз просто распаковываешь в любую папку и все. Вообще это сваливаение всех файлов в одну общую кучу устаревший подход, я думаю в будущем в линуксе тоже будут каждое приложение в своей папке хранить потому что так удобнее. Так уже делают в макоси и на мобильных платформах.
>>429249
Я не уверен есть ли туториалы как написать блог на чистом PHP, но вот нагуглить туториал по написанию блога фреймворке несложно.
>Почитай-ка статью: http://learn.javascript.ru/write-unmain-code
Лол, я как раз её и скинул в тред. Если б я еще прочитал её до того, как начал делать эту задачу.
Делаю задачку на поиск пути. Дошел до момента когда нужно в функцию добавить рекурсию и не пойму как это должно выглядеть, теорию только, что прочитал про рекурсивные функции но как это должно выглядеть в этой задачке не понял.
В задаче на поиск пути может быть лучше использовать не тот алгоритм, который дан в подсказке, а что-нибудь из википедии: http://ru.wikipedia.org/wiki/%D0%9F%D0%BE%D0%B8%D1%81%D0%BA_%D0%BF%D1%83%D1%82%D0%B8
Аноны, например, с помощью Дейкстры эту задачу решали. Посмотри, он наверно проще будет.
Или если ты хочешь решать рекурсией, то надо написать makeOneStep примерно таким образом:
Пусть текущая точка называется A.
Если цель соседняя с A точка, добавляем ее в текущий путь и возвращаем как результат.
Если цель не соседняя точка, то перебираем все соседние c A точки и для каждой такой точки X:
- добавлем точку X к пути
- вызываем makeOneStep чтобы попробовать найти путь к цели через точку X. Если путь нашелся, добавляем его в масив путей.
После того как мы перебрали все сосединие точки, мы получаем массив возможных путей к цели. Надо взять из него самый короткий путь и вернуть его как результат. Если массив пуст то добраться до цели из текущей точки невозможно.
В общем, если ты хочешь решать рекурсией то ты должен полностью понимать как работает алгоритм. Суть в том, что за каждый вызов мы приближаемся к цели на одну точку (после чего вызываем функцию рекурсивно чтобы приблизиться еще).
> По PHP: Профессиональное программирование на PHP Джордж Шлосснейгл
На каком трекере можно купить?
Оп проверь.
https://github.com/tokotun/matriculant
> делаем редирект;
> умираем;
Что значит умереть и редирект? Тут редирект значит скинуть на другую страницу?
> В качестве email проходит строчка «lol me@mail.ru lol»
http://habrahabr.ru/post/175375/ Но в этой статье сказали, что регулярки на проверку имейл сложнее этой, "/.+@.+\..+/i", излишни.
А ещё у меня от чего-то вёрстка съехала. Первый DIV стал ниже на сантиметр. Ошибку сам не нашел.
>Что значит умереть и редирект? Тут редирект значит скинуть на другую страницу?
Я думаю редирект - это заголовок, а умереть - die()
public function thumbnail(...) {
if (такой размер уже существует) {
выходим;
}
$thumbnailName = $thumbnail->createThumbnail(...); //возвращает имя созданной превьюшки
$upload->createDirectory($thumbnailName);
$hash = upload->generateHash($thumbnailName);
$database->addThumbnail(...); //надо ли здесь делать проверку и в случае неудачи удалять превью?
return true;
}
Так как проверка на существование у меня выполняется в самом классе Thumbnail (https://github.com/someApprentice/ThumbnailService/blob/master/Classes/Thumbnail.php#L44), у меня возникает проблема в передаче параметров вне класса. Я конечно мог бы разбить на несколько методов этот класс и сделать так, чтобы новый метод calculateSize(...) возвращал массив с новыми размерами, но не уверен правильно ли будет так поступить.
> у меня возникает проблема в передаче параметров вне класса.
Не очень понял, а в чем именно проблема? Какие пааметры откуда куда ты не можешь передать?
>>430859
Ок, проверю сегодня.
> Что значит умереть и редирект? Тут редирект значит скинуть на другую страницу?
Редирект это когда ты выдаешь вместо страницы заголовок location: http://example.com/ Он говорит браузеру о том, что надо сделать новый запрос по указанному адресу.
Соответственно если ты делаешь редирект то после него надо завершать скрипт.А ты почему-то по непонятным причинам не завершаешь, а продолжаешь работать и выводишь страницу котрую никто не увидит. Зачем?
> Но в этой статье сказали, что регулярки на проверку имейл сложнее этой, "/.+@.+\..+/i", излишни.
Я бы конечно заменил точки на «не пробел», так как не представляю что кто-то будет вводить адреса вроде "Ivan Ivanov"@example.com. Ну да ладно.
> А ещё у меня от чего-то вёрстка съехала. Первый DIV стал ниже на сантиметр. Ошибку сам не нашел.
Ок, я гляну, а тебе напомню что у нас есть задания на CSS/HTML.
>Не очень понял, а в чем именно проблема? Какие пааметры откуда куда ты не можешь передать?
Я не уверен что параметры передавать массивом будет правильно. Просто хотел услышать одобрение или не одобрение с твоей стороны этого.
Сейчас допишу код и покажу тебе.
Не выходит отсеять варианты через $time, только через количество промежуточных станций.
http://ideone.com/DOtu6C , ошибку с $lowerTime видел но не пойму почему вылезает.
Чет не очень совсем. Но я и не оп.
Школьник и IPad:
http://ideone.com/Y3h9YO
Сумма прописью:
http://ideone.com/gyxb0I
Там можно было еще функцию ввести и слегка уменьшить код, но меня уже переполняла ненависть и я не осилил.
Можно мне ближе к сайтостроительству задание? А то мотивация пропадает от таких задач.
Когда ОП, подкинул мне идейку, eval'ить пользовательский код прямо в браузере, я конечно подумал, что это XSS в чистом виде. Но вот я так и не придумал, как можно это абузить тут. Может ты мне расскажешь, как ты можешь навредить через XSS в данном конкретном случае? Ну или покажи сразу на примере, мне правда интересно.
XSS тут был бы если бы код можно было передавать извне например
/jasmine-tests/?code=... тут злой код ...
Так как авторизации на ресурсе нет, то этот злой код может максимум отправлять от имени пользователя запросы на другие сайты, майнить биткойны и пакостить по мелочи до тех пор, пока пользователь не закроет станицу.
Так как код извне передавать нельзя то уязвимости нет - «взломать» можно только свой собственный браузер.
>А ты почему-то по непонятным причинам не завершаешь, а продолжаешь работать и выводишь страницу котрую никто не увидит
Вот тут по подробней. Я же вижу страницу которую вывожу.
Я делаю всё в одной странице. И принимаю данные и записываю и вывожу. И тут же показываю эту страницу. Всё связано инклюдами. Все далается за 1 проход.
Ты предлагаешь это разделить.
Должна быть страничка, которая отправляет данные отдельно стоящей PHP-программе.
Потом эта программа отравляет на страницу для вывода.
Поправь меня, если я не правильно понял.
>Должна быть страничка, которая отправляет данные отдельно стоящей PHP-программе.
Программа данные обрабатывает.
Далее идёт редирект на страничку для вывода.
строчка у меня пропала
Нет, мы по моему совсем друг друга не понимаем.
> Я делаю всё в одной странице. И принимаю данные и записываю и вывожу. И тут же показываю эту страницу
Так делать неправильно потому что зарос отправляется через метод POST, соответственно при обновлении такой страницы у нас запрос (например на регистрацию) отправляется повторно. Потому всегда после успешной обработки POST запроса делается редирект, то есть браузеру дается инструкция перейти на указанную страницу и загрузить ее методом GET.
Если по шагам расписать то должно быть так:
# пользователь открывает страницу регистрации
Браузер скачивает страницу регистациим методом GET и отображает форму
# Пользователь заполняет форму и жмет «отправить»
Браузер отправляет POST запрос с данными формы
Сервер обрабатывает и если все верно, выдает заголовок Location
Браузер получает этот ответ и загужает указанную в заголовке страницу методом GET. Даже если пользователь обновит страницу, повторно POST запрос не отправится.
По моему, ты не понимаешь либо как работает браузер и протокол HTTP либо не понимаешь, о чем я говорю.
Если у тебя есть такой код:
header("Location: ....");
// Не завершаем скрипт, а продолжаем работу
....
echo "Hello";
То он неправильный так как слово Hello никто не увидит.
Нет, мы по моему совсем друг друга не понимаем.
> Я делаю всё в одной странице. И принимаю данные и записываю и вывожу. И тут же показываю эту страницу
Так делать неправильно потому что зарос отправляется через метод POST, соответственно при обновлении такой страницы у нас запрос (например на регистрацию) отправляется повторно. Потому всегда после успешной обработки POST запроса делается редирект, то есть браузеру дается инструкция перейти на указанную страницу и загрузить ее методом GET.
Если по шагам расписать то должно быть так:
# пользователь открывает страницу регистрации
Браузер скачивает страницу регистациим методом GET и отображает форму
# Пользователь заполняет форму и жмет «отправить»
Браузер отправляет POST запрос с данными формы
Сервер обрабатывает и если все верно, выдает заголовок Location
Браузер получает этот ответ и загужает указанную в заголовке страницу методом GET. Даже если пользователь обновит страницу, повторно POST запрос не отправится.
По моему, ты не понимаешь либо как работает браузер и протокол HTTP либо не понимаешь, о чем я говорю.
Если у тебя есть такой код:
header("Location: ....");
// Не завершаем скрипт, а продолжаем работу
....
echo "Hello";
То он неправильный так как слово Hello никто не увидит.
> И принимаю данные и записываю и вывожу. И тут же показываю эту страницу.
Это неправильно, после POST надо делать редирект иначе если обновить страницу POST-запрос отправится повторно.
Как передавать переменные в шаблон редиректом?
Пока у меня на уме какие-то бредовые варианты. Ещё немного погуглю может найду.
> А ещё у меня от чего-то вёрстка съехала. Первый DIV стал ниже на сантиметр. Ошибку сам не нашел.
Действительно, проблему увидеть сложно. Но если открыть исходник страницы в Фаефоксе (Ctrl + U) то видно что надпись DOCTYPE выделена красным цветом (то есть там рядом ошибка), а если открыть инспектор в Хроме то видно что head пустой, а title и link находятся внутри body.
Чтобы увидеть источник проблем, обычный текстовый редактор не годится, нужен hex-редактор ( что это: http://ru.wikipedia.org/wiki/Hex-%D1%80%D0%B5%D0%B4%D0%B0%D0%BA%D1%82%D0%BE%D1%80 )
Скачай какой-нибудь Hex редактор (например этот https://en.wikipedia.org/wiki/HxD ) и открой файл templates/header.php. В начале файла ты увидишь 3 странных байта. Это BOM ( http://ru.wikipedia.org/wiki/%D0%9C%D0%B0%D1%80%D0%BA%D0%B5%D1%80_%D0%BF%D0%BE%D1%81%D0%BB%D0%B5%D0%B4%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%BE%D1%81%D1%82%D0%B8_%D0%B1%D0%B0%D0%B9%D1%82%D0%BE%D0%B2 ). Некоторые редакторы вставляют его в начало файла при сохранении. Например, блокнот Windows.
BOM не отображается на печати и потому увидеть его в браузере или текстовом редакторе нельзя. Но страницу он ломает. Дело в том, что доктайп должен идти в самом начале HTML документа. Но из-за BOM он идет не в самом начале, а после BOM и не воспринимается как доктайп. Из-за отстутвия доктайпа браузер переходит в режим совместимости с древними (написанными до 2000 года) сайтов и начинает отображать страницу не по стандартам (это называется режим Quirks Mode). Также, Хром, увидев в начале документа непонятные символы, подставляет перед ними пропущенный по его мнению тег body (так как текст страницы должен быть внутри body) что тоже может ломать верстку.
Такая вот история.
Пересохрани файл без BOM и hex редактором проверь что в других файлах его тоже нет.
Переменные в шаблон нельзя передавать редиректом. Редирект это такой вид ответа (код 3xx + заголовок Location) который говорит браузеру перейти по указанному адресу. Шаблон тут вообще не при чем.
Напиши подробнее что ты хочешь сделать.
>Сервер обрабатывает и если все верно, выдает заголовок Location
Браузер получает этот ответ и загужает указанную в заголовке страницу методом GET. Даже если пользователь обновит страницу, повторно POST запрос не отправится.
Покажи кусок кода, и напиши что надо сделать, я код посмотрю. А то на словах мы не поймем ничего.
Напомнил сам о себе.
Я проверил твой код.
Что-то у тебя регистрация сломалась.
Баг, у тебя в меню всегда написано «Редактировать профиль» даже если я не зарегистрирован (легко проверить открыв сайт в приватном режиме).
При попытке регистрации на любой адрес пишет «Неверный формат email адреса» и «Произошла ошибка. Пожалуйста, попробуйте отправить форму еще раз.».
Надо тестировать хотя бы в общих чертах что все работает (а в идеале писать и запускать автоматические тесты).
Вообще, по коду вроде как замечаний стало поменьше.
> https://github.com/tokotun/matriculant/blob/master/.gitignore
> # ингорировать файлы в папке boostrap
Зачем?
> https://github.com/tokotun/matriculant/blob/master/app/MatriculantMapper.php#L109
> $total = $statment->fetch( );
Тут удобнее использовать fetchColumn
> https://github.com/tokotun/matriculant/blob/master/templates/main.php#L5
> if ($matriculantMapper->loggedIn)
Это абсолютно неправильный код. MatriculantMapper это класс, который загужает и сохраняет объекты Matriculant в БД. Откуда у него поле loggedIn? Это свойство маппера? Оно тут ни к селу, ни к городу. Каждый класс должен заниматься только своим делом. Не добавляй поля в первый попавшийся класс. Функция isLoggedIn так же неуместна там.
> https://github.com/tokotun/matriculant/blob/master/index.php#L19
> if ($countPage == 0) $countPage =1;
If надо всегда писать с фигурными скобками и в 3 строчки, для единообазия и чтобы меньше был шанс сделать ошибку. В стандарте оформления кода PSR-2 написано:
> Тело каждой управляющей структуры НЕОБХОДИМО заключать в фигурные скобки. Это стандартизирует вид управляющих структур и уменьшает вероятность возникновения ошибок при добавлении новых строк в тело.
Там же есть пример оформления if.
> https://github.com/tokotun/matriculant/blob/master/templates/profile.php#L3
> https://github.com/tokotun/matriculant/blob/master/templates/main.php
> <li><a href="index.php">На главную</a></li>
Неудачное решение. У тебя половина меню находится в header.php, а вторая половина продублирована в 2 файлах. Ну как с этим работать? Как там посчитать все ли дивы закрыты или нет если они по разным файлам раскиданы? Перенеси меню в header.php целиком.
> https://github.com/tokotun/matriculant/blob/master/app/boostrap.php#L2
> require_once 'config.php';
Конфиг надежнее подкючать через просто require. А то вдруг его где-то раньше уже подключали внутри функции например.
> https://github.com/tokotun/matriculant/blob/master/app/boostrap.php#L13
> (isset($_COOKIE['id'])) ? $id = $_COOKIE['id'] : $id = '';
Здесь надо либо писать $id = ... либо использовать if/else, а в твоем варианте читаемость ухудшена. Тернарный оператор должен быть часть выражения, строка не должна с него начинаться.
> https://github.com/tokotun/matriculant/blob/master/login.php#L29
> if (!validateToken()) {
> $matriculant->errors['token'] = TRUE;
Ты не выставляешь errors['errors'] в true и эта ошибка проверки токена останется незамеченной. Чтобы избежать такой проблемы, надо не лезть напрямую в массив errors, а надо сделать метод setError($field, $message) который выставит все как надо. Старайся работать с объектами черех методы, а не менять поля, тем более сложные массивы, напрямую.
> https://github.com/tokotun/matriculant/blob/master/templates/profile.php#L20
> <?php if ($matriculantMapper->recorded) : ?>
Неудачное решение. Почему у тебя Mapper который предназначен работать с базой данных, занимается отобажением уведомлений? Это не его задача.
Также, само поле recorded неудачно сделано. Функция должна возвращать результаты через return, а не записывать их в общее поле, где их может перезаписать следующий вызов функции и где в итоге глядя на код неясно что хранится.
Хороший, понятный код:
$result = $obj->doSomething( );
Плохой, непонятный код:
$obj->doSomething( );
$x = $obj->result; // Это результат работы doSomething или какой-то другой функции? Непонятно.
> https://github.com/tokotun/matriculant/blob/master/app/Matriculant.php#L133
> $regexp = '/^[a-z]{1,50}@[a-z]{1,50}
Тебе уже наверно надоело это выражение для проверки email, но ведь наша цель это знания и просвещение, верно? Потому давай его еще помучаем. Это новые выражение не пропускает например точки и минусы в имени, и такие адреса не пройдут:
ivan.ivanov@example.com
toko-kun@example.com
Потому твое предыдущее выражение было конечно лучше. Но оно пропускает явно неправильные конструкции вроде lol ivan@example.com (а люди могут вводить в поле email что угодно: я видел как в поле «эл. почта» пытались ввести почтовый адрес). Потому на мой взгляд, было бы разумно взять то простое выражение, но заменить точку («любой символ») на «не-пробел» так как я ни разу не встречал email с пробелами, он не пройдет ни на одном сайте и явно свидетельствует об ошибке при вводе.
Потому правильно сделать один из вариантов:
- взять простое выражение и запретить в нем пробелы
- взять старое выражение, оставить как есть и привести аргументы почему оно вполне тут подходит
> header("Location: loginForm.php");
> <?php include 'templates/profile.php'; ?>
Э не, это так не работает. Когда ты делаешь header location, браузер отправляет на указанный адрес новый запрос и запускается новая копия скрипта которая ничего не знает о предыдущей. Соответственно, никакие переменные не передаются, и тд. В твоем случае правильнее редиректить на тот же самый login.php
Чтобы передать информацию о том что надо показать уведомление, можно использовать query string параметры: /login.php?msg=registered
Вообще, каждый запрос из браузера обрабатывает отдельная копия скрипта и никакие переменные между ними не передаются и не сохраняются.
Ну и коммиты лучше конечно нормально называть, а то история печально выглядит: https://github.com/tokotun/matriculant/commits/master
Я проверил твой код.
Что-то у тебя регистрация сломалась.
Баг, у тебя в меню всегда написано «Редактировать профиль» даже если я не зарегистрирован (легко проверить открыв сайт в приватном режиме).
При попытке регистрации на любой адрес пишет «Неверный формат email адреса» и «Произошла ошибка. Пожалуйста, попробуйте отправить форму еще раз.».
Надо тестировать хотя бы в общих чертах что все работает (а в идеале писать и запускать автоматические тесты).
Вообще, по коду вроде как замечаний стало поменьше.
> https://github.com/tokotun/matriculant/blob/master/.gitignore
> # ингорировать файлы в папке boostrap
Зачем?
> https://github.com/tokotun/matriculant/blob/master/app/MatriculantMapper.php#L109
> $total = $statment->fetch( );
Тут удобнее использовать fetchColumn
> https://github.com/tokotun/matriculant/blob/master/templates/main.php#L5
> if ($matriculantMapper->loggedIn)
Это абсолютно неправильный код. MatriculantMapper это класс, который загужает и сохраняет объекты Matriculant в БД. Откуда у него поле loggedIn? Это свойство маппера? Оно тут ни к селу, ни к городу. Каждый класс должен заниматься только своим делом. Не добавляй поля в первый попавшийся класс. Функция isLoggedIn так же неуместна там.
> https://github.com/tokotun/matriculant/blob/master/index.php#L19
> if ($countPage == 0) $countPage =1;
If надо всегда писать с фигурными скобками и в 3 строчки, для единообазия и чтобы меньше был шанс сделать ошибку. В стандарте оформления кода PSR-2 написано:
> Тело каждой управляющей структуры НЕОБХОДИМО заключать в фигурные скобки. Это стандартизирует вид управляющих структур и уменьшает вероятность возникновения ошибок при добавлении новых строк в тело.
Там же есть пример оформления if.
> https://github.com/tokotun/matriculant/blob/master/templates/profile.php#L3
> https://github.com/tokotun/matriculant/blob/master/templates/main.php
> <li><a href="index.php">На главную</a></li>
Неудачное решение. У тебя половина меню находится в header.php, а вторая половина продублирована в 2 файлах. Ну как с этим работать? Как там посчитать все ли дивы закрыты или нет если они по разным файлам раскиданы? Перенеси меню в header.php целиком.
> https://github.com/tokotun/matriculant/blob/master/app/boostrap.php#L2
> require_once 'config.php';
Конфиг надежнее подкючать через просто require. А то вдруг его где-то раньше уже подключали внутри функции например.
> https://github.com/tokotun/matriculant/blob/master/app/boostrap.php#L13
> (isset($_COOKIE['id'])) ? $id = $_COOKIE['id'] : $id = '';
Здесь надо либо писать $id = ... либо использовать if/else, а в твоем варианте читаемость ухудшена. Тернарный оператор должен быть часть выражения, строка не должна с него начинаться.
> https://github.com/tokotun/matriculant/blob/master/login.php#L29
> if (!validateToken()) {
> $matriculant->errors['token'] = TRUE;
Ты не выставляешь errors['errors'] в true и эта ошибка проверки токена останется незамеченной. Чтобы избежать такой проблемы, надо не лезть напрямую в массив errors, а надо сделать метод setError($field, $message) который выставит все как надо. Старайся работать с объектами черех методы, а не менять поля, тем более сложные массивы, напрямую.
> https://github.com/tokotun/matriculant/blob/master/templates/profile.php#L20
> <?php if ($matriculantMapper->recorded) : ?>
Неудачное решение. Почему у тебя Mapper который предназначен работать с базой данных, занимается отобажением уведомлений? Это не его задача.
Также, само поле recorded неудачно сделано. Функция должна возвращать результаты через return, а не записывать их в общее поле, где их может перезаписать следующий вызов функции и где в итоге глядя на код неясно что хранится.
Хороший, понятный код:
$result = $obj->doSomething( );
Плохой, непонятный код:
$obj->doSomething( );
$x = $obj->result; // Это результат работы doSomething или какой-то другой функции? Непонятно.
> https://github.com/tokotun/matriculant/blob/master/app/Matriculant.php#L133
> $regexp = '/^[a-z]{1,50}@[a-z]{1,50}
Тебе уже наверно надоело это выражение для проверки email, но ведь наша цель это знания и просвещение, верно? Потому давай его еще помучаем. Это новые выражение не пропускает например точки и минусы в имени, и такие адреса не пройдут:
ivan.ivanov@example.com
toko-kun@example.com
Потому твое предыдущее выражение было конечно лучше. Но оно пропускает явно неправильные конструкции вроде lol ivan@example.com (а люди могут вводить в поле email что угодно: я видел как в поле «эл. почта» пытались ввести почтовый адрес). Потому на мой взгляд, было бы разумно взять то простое выражение, но заменить точку («любой символ») на «не-пробел» так как я ни разу не встречал email с пробелами, он не пройдет ни на одном сайте и явно свидетельствует об ошибке при вводе.
Потому правильно сделать один из вариантов:
- взять простое выражение и запретить в нем пробелы
- взять старое выражение, оставить как есть и привести аргументы почему оно вполне тут подходит
> header("Location: loginForm.php");
> <?php include 'templates/profile.php'; ?>
Э не, это так не работает. Когда ты делаешь header location, браузер отправляет на указанный адрес новый запрос и запускается новая копия скрипта которая ничего не знает о предыдущей. Соответственно, никакие переменные не передаются, и тд. В твоем случае правильнее редиректить на тот же самый login.php
Чтобы передать информацию о том что надо показать уведомление, можно использовать query string параметры: /login.php?msg=registered
Вообще, каждый запрос из браузера обрабатывает отдельная копия скрипта и никакие переменные между ними не передаются и не сохраняются.
Ну и коммиты лучше конечно нормально называть, а то история печально выглядит: https://github.com/tokotun/matriculant/commits/master
Спасибо за анализ. Завтра переделаю.
> о в этой статье сказали, что регулярки на проверку имейл сложнее этой, "/.+@.+\..+/i", излишни.
правильно сказали, но я все же запретил бы пробелы в email так как в 99.999% случаев это ошибка, например люди их ставят иногда вместо собачки или вместо точки:
ivan@mail ru
>>431037
Ну сделай пока массивом, потом код посмотрим и проверим.
>>431043
Давай.
>>431056
> ошибку с $lowerTime видел но не пойму почему вылезает.
Найди в программе все места где присваивается значение этой переменной. Там только одно такое место: строка 174 внутри if и foreach. Но если до этой строчки управление не дойдет, то переменная не создастся. Это очень плохо, когда у тебя переменная может существовать. а может и нет. Это ненадежный код. Исправь, чтобы такого не было.
Также, не пиши вот так:
> if (!isset($lowerTime)
Надо чтобы было однозначно ясно, есть переменная или нет, а в твоем случае видно что даже ты, автор кода, не понимаешь, сущетсвует она в этом месте или нет. Так быть не должно.
В твоем случае надо явно создать переменную перед циклом, чтобы она всегда существовала.
> о в этой статье сказали, что регулярки на проверку имейл сложнее этой, "/.+@.+\..+/i", излишни.
правильно сказали, но я все же запретил бы пробелы в email так как в 99.999% случаев это ошибка, например люди их ставят иногда вместо собачки или вместо точки:
ivan@mail ru
>>431037
Ну сделай пока массивом, потом код посмотрим и проверим.
>>431043
Давай.
>>431056
> ошибку с $lowerTime видел но не пойму почему вылезает.
Найди в программе все места где присваивается значение этой переменной. Там только одно такое место: строка 174 внутри if и foreach. Но если до этой строчки управление не дойдет, то переменная не создастся. Это очень плохо, когда у тебя переменная может существовать. а может и нет. Это ненадежный код. Исправь, чтобы такого не было.
Также, не пиши вот так:
> if (!isset($lowerTime)
Надо чтобы было однозначно ясно, есть переменная или нет, а в твоем случае видно что даже ты, автор кода, не понимаешь, сущетсвует она в этом месте или нет. Так быть не должно.
В твоем случае надо явно создать переменную перед циклом, чтобы она всегда существовала.
> &$time,
Зачем ты исплоьзуешь ссылки? Это сложная тема и там легко сделать ошибку. Более того, ты усложняешь понимание кода. Ведь работать с функциями, которые возвращают результат только через return, гораздо проще, чем с такими которые еще и меняют (а может быть и не меняют) свои аргументы.
В твоем случае функция вызывается много раз, вызывая себя рекурсивно. Ты вообще уверен, что в time будет только время текущего маршрута, а не сумма времени всех проверенных ранее маршрутов?
Если ты сам не знаешь ответа на этот вопрос то упрощай код, чтобы он был понятен и не использовал ссылки.
> $newPath = makeOneStep($paths, $k, $endPoint, $time, $pathDone);
> if ($newPath) {
А в каком случае newPath может быть пустой? Я не вижу такого места, где бы возвращался пустой массив. Он всегда непустой.
Ну и непонятно, какого формата массив возвращает функция makeOneStep. В одном месте путь возвращается в элементе с индексом 0:
> $result[] = $pathDone;
> $result['time'] = $time;
В другом, в самом массиве:
> $result = $shortest;
> $result['time'] = $lowerTime;
Ну и выбиать оптимальный путь надо по времени. И выбор оптимаьного пути лучше наверно сделать отдельным циклом, так будет проще.
Для if всегда надо ставить фигурные скобки и писать его в 3 строки. Иначе трудно понять что относится к if а что нет. В твоем случае например $shortest = $newPath; выполняется всегда.
> &$time,
Зачем ты исплоьзуешь ссылки? Это сложная тема и там легко сделать ошибку. Более того, ты усложняешь понимание кода. Ведь работать с функциями, которые возвращают результат только через return, гораздо проще, чем с такими которые еще и меняют (а может быть и не меняют) свои аргументы.
В твоем случае функция вызывается много раз, вызывая себя рекурсивно. Ты вообще уверен, что в time будет только время текущего маршрута, а не сумма времени всех проверенных ранее маршрутов?
Если ты сам не знаешь ответа на этот вопрос то упрощай код, чтобы он был понятен и не использовал ссылки.
> $newPath = makeOneStep($paths, $k, $endPoint, $time, $pathDone);
> if ($newPath) {
А в каком случае newPath может быть пустой? Я не вижу такого места, где бы возвращался пустой массив. Он всегда непустой.
Ну и непонятно, какого формата массив возвращает функция makeOneStep. В одном месте путь возвращается в элементе с индексом 0:
> $result[] = $pathDone;
> $result['time'] = $time;
В другом, в самом массиве:
> $result = $shortest;
> $result['time'] = $lowerTime;
Ну и выбиать оптимальный путь надо по времени. И выбор оптимаьного пути лучше наверно сделать отдельным циклом, так будет проще.
Для if всегда надо ставить фигурные скобки и писать его в 3 строки. Иначе трудно понять что относится к if а что нет. В твоем случае например $shortest = $newPath; выполняется всегда.
Очень странный код. Например, непонятно что представляет собой объект класса Thumbnail, одну картинку? Одну уменьшенную картинку? Зачем у него так много свойств?
$width, $maxWidth, $newWidth, $cropX, $newWidth_p
5 значений ширины у одной картинки? и все публичные? Я не понимаю, что это вообще значит.
Объект должен хранить информацию о свойствах чего-то. Например, объект картинки может иметь свойства «ширина», «высота», «имя файла», и методы «сгенерировать уменьшенную картинку», но 5 значений ширины у него быть не может.
Не очень понятно что делает calculateImage и зачем он нужен.
Метод createThumbnailеще хуже. Чтобы он работал корректно, надо сначала задать значения полей $this->newWidth_p, $this->newHeight_p, $this->x, $this->y, $this->cropX, $this->cropY, $this->newWidth, $this->newHeight но как программист об этом догадается? Это не метод, а мина замедленного действия которая рано или поздно сломает код.
Чтобы гарантировать что эти свойства будут заданы, ты должен выставлять их в конструкторе (так как он гарантированно вызывается при создани и объекта), и может быть сделать все их непубличными, чтобы их нельзя было стереть снаружи. Тогда код будет надежным.
if надо писать в 3 строчки с фигуными скобками, иначе могут быть ошибки и читать тяжело.
> Школьник и IPad:
Тут можно избавиться от if (и повторяющихся по 2 раза строчек вроде $creditSum -= $monthlyPayment;) с помощью функций min/max. Подумай, как.
А так, считает верно.
> Сумма прописью:
Тут над кодом надо поработать.
> $spellingRubles = array(
> 0 => 'рублей', 6 => 'рублей',
> 1 => 'рубль', 7 => 'рублей',
В русском языке всего 3 формы склонения слова. Незачем передавать массив из 10 элементов, достаточно значений для цифр 1, 2 и 5.
Также, сумма в 0 рублей не обрабатывается корректно: http://ideone.com/Lr2yOZ - проще всего для нее сделать отдельное условие.
> <br/>
Чтобы переносы строк нормально работали и в браузере и в ideone (и в консоли), можно использовать для этого \n, а в начале программы поставить
header("Content-Type: text/plain; charset=utf-8");
Это заставит браузер воспринимать то, что выводит твоя программа, как обычный текст, а не HTML, и уважать переносы строк в нем (так как в языке HTML перенос строки равносилен пробелу).
Иначе перенос строки будет в исходном коде страницы (его можно увидеть нажав Ctrl + U), но на самой странице его не будет.
> Можно мне ближе к сайтостроительству задание?
А ты ООП выучил? У нас все, что с сайтостроительством, использует ООП.
Пока ты не выучил ООП, ты можешь прокачивать знания HTML/CSS/JS/SQL с помощью наих задачек.
Так-то я не против, вот ссылки:
- Простая, но полезная задача сделать список студентов: https://gist.github.com/codedokode/d7e7f11449fc3bcb24b4
- Более сложная задача сделать файлообменник на микрофреймворке Slim: https://gist.github.com/codedokode/9424217
- HTML/CSS: https://gist.github.com/codedokode/58ebc90bd006baf4b35c
- JS: https://gist.github.com/codedokode/ce30e7a036f18f416ae0
- Проверялка решений на JS: http://dkab.github.io/jasmine-tests/
- MySQL: https://gist.github.com/codedokode/10539213
> Школьник и IPad:
Тут можно избавиться от if (и повторяющихся по 2 раза строчек вроде $creditSum -= $monthlyPayment;) с помощью функций min/max. Подумай, как.
А так, считает верно.
> Сумма прописью:
Тут над кодом надо поработать.
> $spellingRubles = array(
> 0 => 'рублей', 6 => 'рублей',
> 1 => 'рубль', 7 => 'рублей',
В русском языке всего 3 формы склонения слова. Незачем передавать массив из 10 элементов, достаточно значений для цифр 1, 2 и 5.
Также, сумма в 0 рублей не обрабатывается корректно: http://ideone.com/Lr2yOZ - проще всего для нее сделать отдельное условие.
> <br/>
Чтобы переносы строк нормально работали и в браузере и в ideone (и в консоли), можно использовать для этого \n, а в начале программы поставить
header("Content-Type: text/plain; charset=utf-8");
Это заставит браузер воспринимать то, что выводит твоя программа, как обычный текст, а не HTML, и уважать переносы строк в нем (так как в языке HTML перенос строки равносилен пробелу).
Иначе перенос строки будет в исходном коде страницы (его можно увидеть нажав Ctrl + U), но на самой странице его не будет.
> Можно мне ближе к сайтостроительству задание?
А ты ООП выучил? У нас все, что с сайтостроительством, использует ООП.
Пока ты не выучил ООП, ты можешь прокачивать знания HTML/CSS/JS/SQL с помощью наих задачек.
Так-то я не против, вот ссылки:
- Простая, но полезная задача сделать список студентов: https://gist.github.com/codedokode/d7e7f11449fc3bcb24b4
- Более сложная задача сделать файлообменник на микрофреймворке Slim: https://gist.github.com/codedokode/9424217
- HTML/CSS: https://gist.github.com/codedokode/58ebc90bd006baf4b35c
- JS: https://gist.github.com/codedokode/ce30e7a036f18f416ae0
- Проверялка решений на JS: http://dkab.github.io/jasmine-tests/
- MySQL: https://gist.github.com/codedokode/10539213
https://gist.github.com/codedokode/7005985
Насчет статеек, попробуй для начала погуглить «как написать калькулятор», «калькулятор для вычисления выражений».
Если кратко, надо сначала разбить строку с выажением на массив токенов (лексем) вроде '16', '+', '23'
Затем пармером пройтись по списку и сосдавить дерево выражения (AST) как тут: https://ru.wikipedia.org/wiki/%D0%90%D0%B1%D1%81%D1%82%D1%80%D0%B0%D0%BA%D1%82%D0%BD%D0%BE%D0%B5_%D1%81%D0%B8%D0%BD%D1%82%D0%B0%D0%BA%D1%81%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B5_%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE
Ну если ты это сделаешь, то вычислить результат легко. Если будут какие-то затруднения, пиши вопросы.
Yes sir, thank you sir.
http://lord-n.narod.ru/download/books/walla/programming/Spr_po_C/24/24.htm
Тут код правда на Си.
http://programmersforum.ru/showthread.php?t=61703
Тут тоже рассматривается метод рекурсивного спуска для Си.
Идея рекурсивного спуска в том, что мы пишем функции, каждая из которых разбирает какую-то одну конструкцию, а для разбора остальных вызывает другие функции. То есть у нас будут функции вроде
разобратьВыражение
разобратьСумму
разобратьПроизведение
разобратьЧислоИлиСкобки
разобратьЧисло
разобратьВыражениеВСкобках
Эти функции принимают на вход набор токенов и текущую позицию, а возвращают узел дерева AST.
Вот пример функции разобратьСумму:
функция {
первыйОперанд = разбатьПроизведение; // вернет узел AST
операнды[] = первый операнд;
пока (следующий токен == плюс или минус) {
проглотить токен плюс или минус;
операнд = разобратьПроизвдение;
операнды[] = операнд;
}
// прочти все, что можно теперь надо создать узел
создать и вернуть УзелСуммы(операнды);
}
Заметь что операнды мы разбираем функцией разобратьПроизвденеи. Оерандом для суммы может быть:
- число
- поизвденеие или деление вида a / b × c (так как их приоритет выше суммы)
- любое выражение в скобках
А для функции разобратьПроизведение операндами могут быть только
- число
- выражение в скобках
Надеюсь, что ты уяснил идею как работает разбор выражений методом рекурсивного спуска.
http://programmersforum.ru/showthread.php?t=61703
Тут тоже рассматривается метод рекурсивного спуска для Си.
Идея рекурсивного спуска в том, что мы пишем функции, каждая из которых разбирает какую-то одну конструкцию, а для разбора остальных вызывает другие функции. То есть у нас будут функции вроде
разобратьВыражение
разобратьСумму
разобратьПроизведение
разобратьЧислоИлиСкобки
разобратьЧисло
разобратьВыражениеВСкобках
Эти функции принимают на вход набор токенов и текущую позицию, а возвращают узел дерева AST.
Вот пример функции разобратьСумму:
функция {
первыйОперанд = разбатьПроизведение; // вернет узел AST
операнды[] = первый операнд;
пока (следующий токен == плюс или минус) {
проглотить токен плюс или минус;
операнд = разобратьПроизвдение;
операнды[] = операнд;
}
// прочти все, что можно теперь надо создать узел
создать и вернуть УзелСуммы(операнды);
}
Заметь что операнды мы разбираем функцией разобратьПроизвденеи. Оерандом для суммы может быть:
- число
- поизвденеие или деление вида a / b × c (так как их приоритет выше суммы)
- любое выражение в скобках
А для функции разобратьПроизведение операндами могут быть только
- число
- выражение в скобках
Надеюсь, что ты уяснил идею как работает разбор выражений методом рекурсивного спуска.
>>431165
http://ideone.com/hOhYnF
Вот. На свежую голову с утра стало более понятно, что мне нужно было от функции .
Лал, у меня просто этот скрипт подключен к двум документам.
у = х
у = 20
Это как возможно? Ведь у = 10 и не может быть ровно 20. (это на курсах СПЕЦИАЛИСТ)
>х = 10
Положил в коробку с названием Х 10 яблок
>у = х
Положил в коробку Y столько же яблок сколько в коробке X
>у = 20
Вынул из коробки Y то что в ней лежало раньше и положил 20 яблок
Было 10, стало 20, что непонятного?
> Вынул из коробки Y то что в ней лежало раньше и положил 20 яблок
Но я не вынимал яблоки. Мамка купила 10 яблок, я заглянул и там действительно 10 яблок. А потом батя говорит "мамка купила 20 яблок", но какие 20 если мамка купила 10.
Поехавший, я комментирую только то, что ты написал. Откуда мне знать, сколько там было в игреке и что ты хочешь сказать записью "y = 20".
> Как работать с тегом <iframe>?
Так же как и с другими элементами. Что именно надо сделать?
>>431365
Я не очень понял откуда это, но в программировании знак «=» значит не то же самое, что в математике. В математике = обозначает равенство:
x = y # x и y содержат одинаковые числа
x = 5 # x равно пяти
В программировании знак «=» обычно обозначает «положить в переменную значение», причем позже значение переменной можно поменять:
$x = 5; // с этого момента в $x хранится число 5
$y = $x; // помещаем в $y значение хранящееся в $x то есть пять
$x = 10; // помещаем в переменную $x значение 10, старое значение удаляется
В математике x = y это равенство: то есть определенное правило, говоящее что x всегда равен y. В программиовании $x = $y это команда поместить в переменную определенное знаечние.
Ты от куда это вырыл?
Я твою маму ебал. Я тебе говорю как это работает, похуй что ты по этому поводу думаешь.
Программа по моему нашла явно не оптимальный путь. Там можно быстрее проехать.
Код тоже сложноват:
> function makeOneStep($paths, $startPoint, $endPoint, $time, $lowerTime, $crossingTime, $pathDone)
Зачем передавать аж 3 переменных времени? Хватило бы одного — время накопленное в pathDone. Более того, его всегда можно вычисляить по pathDone и вообще не передавать.
Выбор наилучшего маршрута сделан неверно, например:
> $time += $paths[$startPoint][$stationName]['time'];
Тут ты постоянно суммируешь все подряд в time, так что первый выбранный путь получает наименьшее время, а последний наибольшее.
Что хранится в time, в принципе непонятно.
В общем, выбор наилучшего маршрута надо переделать. Лишние переменные убрать.
Если что-то непонятно, задавай вопросы.
>>431432
Ругаться в другой тред.
То есть, хорошо, что твоя программа что-то считает и выводит, но ее надо улучшить, пока что как решение она не годится.
Аноны, у вас были такие моменты в изучении, когда учить синтаксис уже смысла практически нет, но выполнять многие задания не получается? Что вы делаете в таком случае?
Пишешь, пишешь и пишешь. Что угодно. Все что взбредет в голову. Что не знаешь - гуглишь. Проходишь туториалы, коих миллионы. Задаешь вопросы, в этом смысле этот тред идеальное место. ОП не даст прямого ответа, а будет тебя только подталкивать к нему. И вот в таком режиме первые года два, по крайней мере если ты самоучка с нуля
Считая их массами имеющихся в наличии предметов, определить, можно ли все эти предметы положить на
весы так, чтобы весы находились в равновесии. Вывести вариант расположения.
Определить, можно ли из них отобрать какое-то количество предметов с суммарным весом 100
(вывести yes или no, в зависимости от результата).
Говорил еще что ее можно решить с помощью генераторов. Тогда нифига не понял, но сейчас вернувшись к ней начал немного больеш понимать. Правда все равно один момент не ясный - для использования генератора надо шарить в итераторах. А их дохуя и трошки. Какие именно итераторы надо разобрать для решения этой задачи?
>Зачем передавать аж 3 переменных времени?
Мне хотелось в конце отображать время требуемое для перемещения между станциями. Тот вариант который у меня был в самом начале без $time вообще - прокладывал путь по минимальному количеству вершин, как привязать к времени у меня других идей пока-что нет, меньше промежуточных пунктов - не всегда же меньшее время.
>Говорил еще что ее можно решить с помощью генераторов.
Можно и без них.
>Правда все равно один момент не ясный - для использования генератора надо шарить в итераторах
Нет, не надо.
http://habrahabr.ru/post/189796/
https://github.com/MindiMakridi/Students Исправил вроде, кроме переменных. От
> $directionName = "ASC";
> $directionGroup = "ASC";
> $directionPoints = "ASC";
Я не могу избавиться, каждая отвечает за своё поле сортировки, а одна переменная будет влиять на все поля.
И еще, что-то мне подсказывает, что пропускать шаблон через phpformatter было не самой лучшей идеей.
И еще заодно вопрос по phpstorm 8. В семерке при запуске дебага на автомате открывалось окно с первой пикчи, с инфой о всех переменных и т.д. В восьмой же версии при каждом дебаге перескакивает на окно консоли, на пикче 2, где нет ну никакой полезной информации. Когда еще дебаг работал нормально заколебался перещелкивать с консоли на дебаггер, но опций позволяющих сделать как было в 7 не нашел.
http://ideone.com/NLl72h
Генераторы это не метод решения. Генераторы это способ снизить потребление памяти. Вот решение без генератора:
большой массив = сгенерироватьКучуВариантов()
результат = найти лучший из вариантов в большом массиве
Генератор просто позволяет избавиться тут от промежуточного большого массива и снизить расход памяти:
генеатор = создатьГенераторВариантов()
результат = найти лучший из тех что выдает генератор
И в генераторах ничего сложного нет. Итераторы тут вообще не при чем, итератор это объект который можно перебирать с помощью foreach, только и всего. Генератор это функция которая через yield выдает значения, и которую можно многократно вызывать через foreach.
Пример генератора:
$gen = function () {
yield 1;
yield 2;
yield 3;
}
// используем
foreach ($gen as $value) {
echo $value;
echo "\n";
}
Пример выведет числа 1, 2, 3. Что тут сложного?
Ты наверно какую-то неправильную статью прочел.
Генераторы это не метод решения. Генераторы это способ снизить потребление памяти. Вот решение без генератора:
большой массив = сгенерироватьКучуВариантов()
результат = найти лучший из вариантов в большом массиве
Генератор просто позволяет избавиться тут от промежуточного большого массива и снизить расход памяти:
генеатор = создатьГенераторВариантов()
результат = найти лучший из тех что выдает генератор
И в генераторах ничего сложного нет. Итераторы тут вообще не при чем, итератор это объект который можно перебирать с помощью foreach, только и всего. Генератор это функция которая через yield выдает значения, и которую можно многократно вызывать через foreach.
Пример генератора:
$gen = function () {
yield 1;
yield 2;
yield 3;
}
// используем
foreach ($gen as $value) {
echo $value;
echo "\n";
}
Пример выведет числа 1, 2, 3. Что тут сложного?
Ты наверно какую-то неправильную статью прочел.
Да, стоит. Там ты ближе к базе данных.
>>431522
> Мне хотелось в конце отображать время требуемое для перемещения между станциями.
Это время есть в массиве paths, его незачем хранить.
> Тот вариант который у меня был в самом начале без $time вообще - прокладывал путь по минимальному количеству вершин, как привязать к времени у меня других идей пока-что нет, меньше промежуточных пунктов - не всегда же меньшее время.
Идея простая: считаешь для каждого варианта сколько времени он занимает и выбираешь наименьший. Но тебе рано это делать, тебе надо сначала ошибки в коде исправить.
> Я не могу избавиться, каждая отвечает за своё поле сортировки, а одна переменная будет влиять на все поля.
Сделай хотя бы массив вместо однотипных переменных. И по моему, избавиться легко:
Если (по текущему полю идет сортировка ASC) {
выводим в ссылке DESC;
} иначе {
выводим в ссылке ASC;
}
> И еще, что-то мне подсказывает, что пропускать шаблон через phpformatter было не самой лучшей идеей.
Да, выглядит ужасно и нечитаемо. Видимо, он с шаблонами не умеет работать. Но не беда, у тебя же есть гит, ты можешь взять предыдущую версию файла из истории.
Весь код я наверно попозже гляну.
>>431802
Скоро-скоро переедем.
Проверь настройки и меню. Если останов не работает то скорее всего отвалилась связь между php и отладчиком. Например, IDE слушает не тот порт или не дает команду PHP перейти в режим отладки. Проверь по документации какие настройки надо выставить и проверь что они все как надо стоят.
PHP создает свойства в такой ситуации.Но делать так не стоит. Почему?
Потому что в ООП у нас должно быть известно какие поля есть у объекта, они должны быть описаны в классе, их легко увидеть. Если же ты создаешь и добавляешь произвольные поля, то это скорее массив получается чем класс. Читабельность и понятность кода сильно снижается.
Можно предположить что функция будет вызываться только из одного скрипта, и хранить данные в переменных.
Куки и сессии никак не помогли бы, так как они индивидуальные для каждого пользователя.
http://ideone.com/cs4u1I
Второе задание:
http://ideone.com/p8ECxj
Во втором задании я так понял надо всё привести к определённым типам? Немного не понял как это сделать, может кто подсказать?
>>431908
> Первое задание:
Названия переменных ничего не говорят и только затрудняют понимание кода. Почитай как-нибудь эту статью: http://learn.javascript.ru/write-unmain-code
Также, не дописывай array в имена. В большинстве случаев то что там массив и так очевидно.
> array_flip($resultArray);
Чтобы получить массив ключей есть функция array_keys.
Так, логика решения правильная, но код оформлен плохо.
> Второе задание:
Не, неправильно.Смотри сам:
http://ideone.com/46aF0x - слово World куда-то потерялось.
http://ideone.com/gxZZrF - выдает ошибки
Также, названия переменных ужасные.
Этот код бессмысленный:
> if (is_float($mess1[1])) {
> $mess1[1] = (double) $mess1[1];
Если переменная имеет тип float то преобразуем ее к типу float? И в чем смысл?
>>431908
> Первое задание:
Названия переменных ничего не говорят и только затрудняют понимание кода. Почитай как-нибудь эту статью: http://learn.javascript.ru/write-unmain-code
Также, не дописывай array в имена. В большинстве случаев то что там массив и так очевидно.
> array_flip($resultArray);
Чтобы получить массив ключей есть функция array_keys.
Так, логика решения правильная, но код оформлен плохо.
> Второе задание:
Не, неправильно.Смотри сам:
http://ideone.com/46aF0x - слово World куда-то потерялось.
http://ideone.com/gxZZrF - выдает ошибки
Также, названия переменных ужасные.
Этот код бессмысленный:
> if (is_float($mess1[1])) {
> $mess1[1] = (double) $mess1[1];
Если переменная имеет тип float то преобразуем ее к типу float? И в чем смысл?
А как тогда лучше во втором задании раскидать части строки в элементы массива? Через регулярные выражения?
А например по запятой можно разделить одним explode, а уже дальше работать посимвольно с каждым элементом полученного массива? И кстати, как лучше работать посимвольный, то есть если если символ не цифра и не буква то считаем его разделителем и записываем в массив?
> А например по запятой можно разделить одним explode, а уже дальше работать посимвольно с каждым элементом полученного массива?
Можно попробовать, но непонятно зачем делить по запятой если можно сразу все разбить на символы.
> И кстати, как лучше работать посимвольный, то есть если если символ не цифра и не буква то считаем его разделителем и записываем в массив?
там более сложная логика, в зависимости от того, внутри кавычек мы или нет, какие символы мы уже видели, что мы разбираем — имя свойства или его значение.
>5 значений ширины у одной картинки? и все публичные? Я не понимаю, что это вообще значит.
$width - исходная ширина
$maxWidth - максимальная ширина, заданная пользователем
$newWidth - Новая ширина, вычисляемая для "вырезания" изображения из оригинала и вставки его в новое изображение
$cropX - Количество пикселей которые надо обрезать
$newWidth_p - Новая ширина, для нового изображения, в которое будет вставлен обрезанный оригинал.
>Метод createThumbnailеще хуже. Чтобы он работал корректно, надо сначала задать значения полей $this->newWidth_p, $this->newHeight_p, $this->x, $this->y, $this->cropX, $this->cropY, $this->newWidth, $this->newHeight но как программист об этом догадается? Это не метод, а мина замедленного действия которая рано или поздно сломает код.
>Надо сначала задать значения полей
Они задаются сначала, функцией calculateImage.
>но как программист об этом догадается?
А как я догадаюсь, о чем догадается программист?
>Чтобы гарантировать что эти свойства будут заданы, ты должен выставлять их в конструкторе (так как он гарантированно вызывается при создани и объекта), и может быть сделать все их непубличными, чтобы их нельзя было стереть снаружи. Тогда код будет надежным.
Я сейчас еще больше запутался... Эти свойства вычисляются методом, зачем кому-то принудительно вызывать метод создания превью без метода вычисления его свойств? Хорошо, допустим кому-то взбредет это в голову. Тогда мне нужно будет в этом методе сделать проверку на эти свойства или же в конструкторе вызвать метод вычисления свойств превью, а уже в нем делать проверку на свойства.
=========================================
В целом, я, кажется, начинаю понимать, что код должен быть понятным для другого программиста. Т.е. задавать названия переменных и функций чтобы из названия было понятно зачем они нужны. Но непонятно такой момент:
>Это не метод, а мина замедленного действия которая рано или поздно сломает код.
Как она сломает код рано или поздно? Что от количества генераций превью будет метятся код?
Код сломать может только программист, и вот собственно вопрос - Как я узнаю каким образом он будет ломать код?
Может есть какие-то стандарты в написании кода? От чего можно оттолкнутся.
Мне всегда казалось что код должен быть максимально простым, т.е. решение должно быть очевидным и максимально коротким, а так же, безопасным (чтобы пользователь не смог сломать все или воспользоваться как-нибудь багами системы).
Я признаю что мой код никуда не годиться, но я писал его с кашей в голове, и даже не знаю как эту кашу переворить. Даже не знаю от чего отталкиваться теперь и к чем придти.
Как в общем узнать к чему стремиться?
>5 значений ширины у одной картинки? и все публичные? Я не понимаю, что это вообще значит.
$width - исходная ширина
$maxWidth - максимальная ширина, заданная пользователем
$newWidth - Новая ширина, вычисляемая для "вырезания" изображения из оригинала и вставки его в новое изображение
$cropX - Количество пикселей которые надо обрезать
$newWidth_p - Новая ширина, для нового изображения, в которое будет вставлен обрезанный оригинал.
>Метод createThumbnailеще хуже. Чтобы он работал корректно, надо сначала задать значения полей $this->newWidth_p, $this->newHeight_p, $this->x, $this->y, $this->cropX, $this->cropY, $this->newWidth, $this->newHeight но как программист об этом догадается? Это не метод, а мина замедленного действия которая рано или поздно сломает код.
>Надо сначала задать значения полей
Они задаются сначала, функцией calculateImage.
>но как программист об этом догадается?
А как я догадаюсь, о чем догадается программист?
>Чтобы гарантировать что эти свойства будут заданы, ты должен выставлять их в конструкторе (так как он гарантированно вызывается при создани и объекта), и может быть сделать все их непубличными, чтобы их нельзя было стереть снаружи. Тогда код будет надежным.
Я сейчас еще больше запутался... Эти свойства вычисляются методом, зачем кому-то принудительно вызывать метод создания превью без метода вычисления его свойств? Хорошо, допустим кому-то взбредет это в голову. Тогда мне нужно будет в этом методе сделать проверку на эти свойства или же в конструкторе вызвать метод вычисления свойств превью, а уже в нем делать проверку на свойства.
=========================================
В целом, я, кажется, начинаю понимать, что код должен быть понятным для другого программиста. Т.е. задавать названия переменных и функций чтобы из названия было понятно зачем они нужны. Но непонятно такой момент:
>Это не метод, а мина замедленного действия которая рано или поздно сломает код.
Как она сломает код рано или поздно? Что от количества генераций превью будет метятся код?
Код сломать может только программист, и вот собственно вопрос - Как я узнаю каким образом он будет ломать код?
Может есть какие-то стандарты в написании кода? От чего можно оттолкнутся.
Мне всегда казалось что код должен быть максимально простым, т.е. решение должно быть очевидным и максимально коротким, а так же, безопасным (чтобы пользователь не смог сломать все или воспользоваться как-нибудь багами системы).
Я признаю что мой код никуда не годиться, но я писал его с кашей в голове, и даже не знаю как эту кашу переворить. Даже не знаю от чего отталкиваться теперь и к чем придти.
Как в общем узнать к чему стремиться?
https://github.com/someApprentice/ThumbnailService
Решил перенести некоторые методы из Upload в новый класс Functions (не знаю как правильно назвать чтобы понятно было, но там будут писаться полезные функции такие как например, генерация хэша изображения или создание директории). Все методы вызываются статически т.к, мне показалось что $functions = new Functions; как-то не совсем понятно. В общем хотелось бы услышать твои замечания по этому поводу.
Про остальные замечания, которые ты писал выше, я не забыл, и сделаю их, как разберусь с архитектурой, и вообще с моим пониманием ООП надо что-то делать.
Это копия, сохраненная 22 февраля 2015 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.