Это копия, сохраненная 24 октября 2014 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
Это тред для начинающих. Не написал за свою жизнь ни одной программы? Ты наш человек.
Требуемые знания: умение читать. Устанавливать пока что ничего не требуется, разве что редактор кода вроде Sublime Text 3, Notepad++, Netbeans PHP или PhpStorm (необязательно).
Предыдущий тред был тут: >>382412
У нас есть уроки по основам PHP, они собраны и выложены по адресу http://archive-ipq-co.narod.ru Если ты ньюфаг, просто решай задачки оттуда, они там реально простые, и пости сюда ссылки на решения, мы посмотрим и скажем, правильно или нет и дадим совет, если можно что-то улучшить. Если не совсем ньюфаг, напиши, что ты знаешь, что нет, что хочешь изучить, я дам тебе какую-нибудь задачку посложнее. После прохождения учебника напиши, ОП даст тебе более сложные задания.
Есть задачки по основам JS и DOM, хорошие, многие их с ходу решить не могут, попроси, дадим ссылку. Есть задачка на MySQL.
Правила: ведем себя воспитанно, помогаем новичкам, постим ссылки на решения задачек, ОП их проверяет и дает советы и замечания.
ОП, как всегда, помогает и дает советы, отвечает на самые нубские и простые вопросы. У ОПа есть почта, так что даже если он не появляется в треде уже неделю, вы всегда можете написать ему что-то хорошее. ОП обычно занят, но где-то раз в сутки в треде появляется.
Оформляй код аккуратно!!! например пропусти через phpformatter.com . Также, если ты пользуешься IDE вроде PhpStorm, Netbeans, Eclipse, то в них эта опция встроена, подробнее: https://gist.github.com/codedokode/8759492
Что почитать?
Мануал по PHP — http://www.php.net/manual/ru/langref.php
Начинающим: Никсон Р. - Создаем динамические веб-сайты с помощью PHP (аноны говорят, она не очень хорошая и устаревает)
Сайт phptherightway
По PHP: Профессиональное программирование на PHP Джордж Шлосснейгл
По PHP: Мэтт Зандстра — PHP: Объекты, шаблоны, методики программирования
JS: learn.javascript.ru
Позиционирование в CSS: http://softwaremaniacs.org/blog/category/primer/ (снизу вверх).
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 жизнь может быть намного проще (еще в них есть автодополнение, автоматическая проверка кода и подсветка ошибок, навигация по файлам и функциям и много чего еще).
Основные правила
Если ты вдруг решил выровнять код вручную, запомни эти правила:
- переменные и функции пишутся с маленькой буквы, подчеркивание не используется, используется camelCase, пример: $x, $numberOfPeople, printResults()
- название функции начинается с глагола, в стиле «сделайЧтоТо»
- не знаешь английский (неужели такое бывает?) Не беда, в 21 веке есть решение этой проблемы. Не пиши транслитом, открой лучше Гугл Транслейт или slovari.yandex.ru и найди название для переменной там
- в именах классов используется CamelCase, первая буква большая, «_» может использоваться
- мы предпочитаем подстановку переменных вместо конкатенации строк: "I am $age years old" — хорошо, 'I am ' . $age . ' years old' — плохо
- мы используем для отступов 4 пробела, а не табы (нужно настроить редактор, чтобы при нажатии Tab он вставлял 4 пробела)
скобки в for и if/else ставятся так (египетские скобки):
[code]
if (...) {
// ...
} else {
// ...
}
for (...) {
// .....
}
[/code]
у определений функций и классов так:
[code]
function bakeCookies(...)
{
// ...
}
[/code]
Официальные ссылки
В PHP есть система стандартов с названием PSR. Вот стандарты, относящиеся к оформлению кода:
http://www.php-fig.org/psr/psr-1/
http://www.php-fig.org/psr/psr-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 жизнь может быть намного проще (еще в них есть автодополнение, автоматическая проверка кода и подсветка ошибок, навигация по файлам и функциям и много чего еще).
Основные правила
Если ты вдруг решил выровнять код вручную, запомни эти правила:
- переменные и функции пишутся с маленькой буквы, подчеркивание не используется, используется camelCase, пример: $x, $numberOfPeople, printResults()
- название функции начинается с глагола, в стиле «сделайЧтоТо»
- не знаешь английский (неужели такое бывает?) Не беда, в 21 веке есть решение этой проблемы. Не пиши транслитом, открой лучше Гугл Транслейт или slovari.yandex.ru и найди название для переменной там
- в именах классов используется CamelCase, первая буква большая, «_» может использоваться
- мы предпочитаем подстановку переменных вместо конкатенации строк: "I am $age years old" — хорошо, 'I am ' . $age . ' years old' — плохо
- мы используем для отступов 4 пробела, а не табы (нужно настроить редактор, чтобы при нажатии Tab он вставлял 4 пробела)
скобки в for и if/else ставятся так (египетские скобки):
[code]
if (...) {
// ...
} else {
// ...
}
for (...) {
// .....
}
[/code]
у определений функций и классов так:
[code]
function bakeCookies(...)
{
// ...
}
[/code]
Официальные ссылки
В PHP есть система стандартов с названием PSR. Вот стандарты, относящиеся к оформлению кода:
http://www.php-fig.org/psr/psr-1/
http://www.php-fig.org/psr/psr-2/
Мало подробной информации по этому evaluate. Но я нагуглил, оказывается он возвращает объект XPathResult, у которого есть множество свойств и методов. Вот этот код заработал:
var xpath = "//div[contains(concat(' ', @class, ' '), ' tovtable ')]";
var elements = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
var test = elements.singleNodeValue;
Объясни зачем concat здесь?
Например чтобы показывала айпи, с которых она просматривается. Мне видится только через мозгоебкой с базой данных.
>>386619
Какая нахуй мозгоебка с базой данных для временных ин мемори данных? Используй memcached.
Единственная сложность тут - определение, что юзер покинул сайт, с http это не совсем просто. На каждый открытый юзером пейдж увеличиваем его счетчик открытых страниц в мемкеше. На закрытие странички (onunload) на js вешаем реквест аджаксом, который будет понижать счетчик конкретного юзера. Трабл в том, что onunload не всегда будет успевать срабатывать, в таком случае нужно постоянно гонять ping-pong аджаксом, сохраняя последнее время запроса в мемкеше, и по какому то ивенту на сервере обходить всех чуваков из мемкеша у которых значение >0, на предмет того, когда последний раз от них приходил реквест и если больше скажем 3 минут, то считаем что юзер покинул сайт.
Итак, все что тебе нужно - мемкеш. В качестве ключа идет хэш на основе его ip или сам ip, в качестве значения массив с параметрами, счетчик открытых страниц, время последнего реквеста, ну и что ты ещё себе там хочешь.
Теперь сама страничка с кол-вом и ip активных юзеров на сайте - сущий пустяк, делаешь из мемкеша выборку юзеров со счетчиком открытых пейджев > 0.
прохожу lynda.com php beyond the basics (essential training прошел)
я понимаю что он пишет, как он это делает и прочее, с пониманием проблем особо нет. я понимаю что я только что списал, но я нихуя не понимаю как до такого допереть самостоятельно - то есть я сам до этого не дошел бы. мне пиздец и не дано, или с опытом придет? вообще, как накачать именно мышление для php?
ДЕЛАЛ ПЕРЕСЧЕТ АЙДИ ПОСТОВ ПРИ УДАЛЕНИИ, ЧТОБ ПРОБЕЛОВ НЕ БЫЛО, РАБОТАЛО, ПРОШЛО ВРЕМЯ Я ЗАБЫЛ ОБ ЭТОМ, УДАЛИЛ ПАРУ ПОСТОВ И ВСЕ НАХУЙ ПО ПИЗДЕ СУКА ПОШЛО НАХУЙ БЛЯТЬ Я ЕБАЛ СУКА ПРОБЕЛЫ В ПОРЯДКЕ НОМЕРОВ, ДОБОВЛЕНИЕ ПОСТОВ В НЕАДЕКВАТНОМ ПОРЯДКЕ ОООООЯЯЕБУУУУУУУУУ Я НЕ МОГУ СОВЛАДАТЬ С ЭТИМ
> $this->db->query("SET @count = 0; UPDATE `$table` SET `$table`.`id` = @count:= @count + 1;");
ДОКОЛЕ
Аноны, я не совсем ньюфаг, но всетаки ньюфаг. Вот вопрос, какую литературу можно юзать, если я не могу разобраться, точнее, я прошел тесты и выполнил все задачки, но все равно мне тяжело разобраться например КАК запилить файлообменник, мне трудно разобраться с YII.
Короче, запрашиваю годной литры, чтобы была уровня Никсона, но не Никсон, ибо же говорят бидлокод и вообще устаревшее дерьмо.
Я очень хочу стать веб девелоупером
Проектируем ресурс типа блога, с миллионом записей в день и 10 миллионами посетителей.
Разрабатываем БД, особенности записи могут расширяться в дальнейшем - там тип записи, цена, ещё что нибудь.
Собственно вопрос был про оптимизацию. Я сказал про индексы. Ок. Вопрос по структуре - делать одной таблицей или выносить "справочники" со связью?
Я помню что куча индексов в 1 таблице не даёт прироста производительности. Как влияет на производительность разбиение по таблицам и добавление индексов туда? Это же ещё и джойнить придётся...
> зачем concat
Мы ищем в строке имя класса, окруженное пробелами. Если в исходной строке оно идет с краю: 'tovtable a b' то оно не найдется, потому к строке class мы тоже добавляем 2 пробела.
>>386616
При заходе кладешь на 1 минуту в кеш IP (+ можно аяксом раз в минуту слать запрос для продления)
>>386630
Ненадежно с onunload. Есть вариант с открытием вебсокет-соединения, но там тоже свои заморочки, лучше просто по таймауту считать посещение.
>>386632
Надо решать задачки самому, а не переписывать код с экрана. У нас кстати есть задачки на разные темы. если скажешь какие темы уже изучил — дадим подходящую задачку.
Для поиска подойдут интеграционные тесты, то есть делаем тестовую базу и ищем по ней. Например, проверяем что по слову «php» находятся записи 1 и 4. Если речь о MySQL то удобно тестовую базу создавать с типом MEMORY, быстрее будет работать.
Также, если у тебя есть что-то вроде разбора запроса пользователя, это можно проверить юнит-тестами.
Для тестирования в PHP используют phpunit. Еще есть codeception, но он больше подходит для тестов API и интерфейсов.
>>386669
В ОП-посте есть 2 неплохих книги, Мэтт Зандстра и Шлосснейгл, может там нужная тема есть (а может конечно и нет).
> но все равно мне тяжело разобраться например КАК запилить файлообменник, мне трудно разобраться с YII.
По идее основной источник информации - официальные мануалы к этим фреймворкам, но если что-то непонятно, можешь в треде вопросы задавать.
> Вопрос по структуре - делать одной таблицей или выносить "справочники" со связью?
Выносить.
> Как влияет на производительность разбиение по таблицам
Не очень хорошо, но по-другому никак. Отказ от нормализации превратит твою базу в помойку и сделает ее обновление и поддержание в актуальном состоянии сложным.
> Это же ещё и джойнить придётся...
Сами по себе джойны не фатальны. Тормозить начинает когда MySQL приходится большое количество лишних данных доставать, например читать 1000 строк чтобы взять только одну нужную.
Для блога наверно можно использовать кеширование. Кешировать можно уже собранные вместе данные. Основной подвох тут - появляется необходимость своевременно обновлять данные в кеше, это отдельная проблема.
Насчет оптимизации, там еще саму MySQL можно покрутить, памяти ей побольше дать, это сильно влияет на скорость работы. Железо получше поставить.
>>386680
> Какие подводные камни? Какие самые дурацкие ошибки я могу допустить на начальном этапе?
Да никаких особо. Язык несложный. Показывай нам примеры своего кода и мы с радостью укажем тебе все твои ошибки.
Анон, реально трудно, нихера не понять, там сразу про MVC в доках пишут и о всяких таких приблудах, очень сложно разобраться. Ладно, буду пробовать разобраться во всем этом, даже сам оп мне ссыкнул если, значит я еще то чмо.
Класс ЭлектрическаяСеть
св-ва: список Электростанций, список Панелей, список Домов, список ЛинийЭлектропередач.
методы: считатьРазницу, считатьСтоимость, добавить Электростанцию, добавить Панель, добавить Дом, добавить ЛиниюЭлектропередач
Класс Электростанция
св-ва: вырабатываемая электроэнергия.
Класс СолнечнаяПанель
св-ва: вырабатываемая днем электроэнергия.
Класс Дома
св-ва: потребление днем, потребление ночью, количество человек.
методы: посчиать затрачиваемую энергию днем, почитать затрачиваемую энергию ночью.
Класс ЛинииЭлектропередач
св-ва: пропускная способность, цена за мегаватт.
Там имеет смысл применить наследование и сделать базовый класс ЭлементСети, от которого наследовать потребителей/генераторов энергии. Соответственно, в Электросети можно сделать просто один общий массив ее участников.
>>386806
Может тебе поискать доки попроще для начала, если сложно разобраться?
>>386827
> title.parentNode.
> title
наверно из-за этого
http://ideone.com/qhzJNK
Сумма прописью. Тут мой быдлокод внезапно оброс раковыми опухолями как только я занялся склонением слов.
http://ideone.com/8aocgi
Пиши верно. Пердолинг с кодировкой и фейл(((
http://ideone.com/fInUFz
Йоду сделал, но и там хуита случилась после переноса. Кодировка изначально была АНСИ, я поменял, на утф, но нормально так и не стала работать. В результате большие буквы большими так и не становятся.
http://ideone.com/X5k49W
Наверно, стоило бы переписать с нуля в нормальной кодировке... meh. Жи нет.
> $text[0]
Так нельзя. Используй mb_substr так как $text[0] возвращает первый байт, а не первую букву (в utf-8 русская буква содержит 2 байта). Потому нельзя обращаться к строке как к массиву — ничего хорошего из этого не выйдет.
Нахуя Томку шкваришь о свое пхп, макака тупорылая?
lynda-кун на связи. по идее в меня уже попытались впихнуть и я ДОЛЖЕН (но знаю ли?) знать: ооп, sessions, cookies, работа с файлами, mysql через mysqli. вот. если дашь мне задачку с тем что я не изучал - с радостью приму, но ты пожалуйста укажи чего я не знаю, но должен для нее знать, я самостоятельно покопаюсь. знаю основы js без jq пока, знаю что jq таки надо начать учить. такое. html/css само собой знаю, но без фреймворков.
http://ideone.com/LlT1Oy
Оп, ну помоги. Ничего не выходит. Я не знаю как ту отлаживать код, ведь пошагово его не пройдешь. Console.log() молчит, и только потому что где-то ошибка. Посмотри на код. Меня беспокоит код на 22-36 строках, без него все работает. Но сам evaluate работает и поддерживается, я же проверял.
Документацию всю прочитал уже тут http://help.dottoro.com/ljagksjc.php Перебор элементов возможен только через метод iterateNext() как я понял.
CCNA Official Cert Guide
>>386443
>>386444
Решаю задачки, читаю статейки. Ощущение, будто чему то новому научился. Но уже знаю, что мне раз двадцать нужно прорешать на практике, что б теория не вылетела из головы.
ОП, принимай.
кошка http://jsbin.com/pupezepekevu/1/edit
1 это задание ты вроде уже одобрил.
2 http://jsbin.com/yowelejayalo/3/edit теперь вложил css от этой задачи.
3 http://jsbin.com/rurodafeyoga/1/edit ну тут просто решил избавится от пробелов.
4 http://jsbin.com/viqoloxipayu/1/edit
5 http://jsbin.com/bazukeyukulu/1/edit вот над этим заданием я почему-то залип надолго. хоть и не раз перечитывал теорию.
6 http://jsbin.com/hoguzekajojo/1/edit
7 http://jsbin.com/vacaraqibiqo/1/edit
А в чем проявляется ошибка? В консоли должно по идее писаться сообщение если что-то не так. Или он что-то не делает из того, что должен? Поясни.
> Я не знаю как ту отлаживать код, ведь пошагово его не пройдешь.
Ты можешь открыть консоль и вставить туда код, чтобы запустить. Или поместить код в функцию и из консоли ее вызвать.
калькулятор
Форматирование куда-то уехало. Надо бы пропустить код через phpformatter.com
Функции вроде strlen и substr не работают с многобайтовыми кодировками вроде utf-8. Здесь, конечно, не используются русские буквы, и потому все сработало, но вообще это ненадежно.
> preg_match('/^[1-9]/',...
Не найдет число, содержащее 0
Если добавить пробелы, все ломается: http://ideone.com/qJC97Y
Сама логика крайне запутанная. Надо бы все это упростить. Я думаю, можно регуляркой разбить исходную строку на массив элементов вида array('123', '+', '456', ...) а затем с этим массивом уже работать. Так мы разом избавимся от кучи запутанных строковых конструкций.
Сумма прописью
То же самое, пропусти код через phpformatter. тяжело его читать. Проблемы там конечно есть почти в каждой строчке, но они исправимы.
> else
> echo $spelling[$number]." ";
Надо всегда ставить скобки { }, даже если там одно действие, так как иначе появляется риск сделать ошибку. А со скобками весь блок виден гораздо лучше.
> $GLOBALS['isFemale']
Не используй глобальные переменные. Все, что нужно функции, надо передавать через аргументы в скобках.
> if ($number[strlen($number)-4]==1)//проверяет последние цифры
Для работы с числами используй только математику. Я дам тебе готовые формулы:
Вот 2 волшебных команды:
// получить последние 3 цифры числа:
echo 1234567 % 1000; // выведет 567
// получить число миллионов
echo floor(1234678 / 1000000); // выведет 12
Комбинируя их, можно получить что угодно. Надо все места, где ты работаешь с числом как со строкой, переделать.
То, что идет в строках 57-89 и 127-139 (склонение слов) — копипаста, а копипаста зло. Надо вынести это в функцию, которая сможет склонять любое слово (точнее выбирать 1 из 3 вариантов написания).
> $A
C большой буквы пишутся только константы и имена классов. Также, переменным надо давать осмысленные названия, плохо знаешь английский, не беда, slovari.yandex.ru и translate.google.com помогут.
> (($A[1].$A[2])
Обращение к строке как к массиву не работает с utf-8 (например с русскими буквами). Потому лучше всего вообще его не исопльзовать, а исплоьзовать mb_substr. Но в данном случае надо использовать математику, а не строковые функции.
echo надо вынести из функций. Нам нужна функция, которой мы даем число и которая возвращает строку, с которой мы делаем что хотим. Она не должна ничего печатать, так как в таком случае мы не можем например записать эту строку в файл или базу данных. Функция не должна ничего печатать, она получает что-то на вход и что-то возвращает.
калькулятор
Форматирование куда-то уехало. Надо бы пропустить код через phpformatter.com
Функции вроде strlen и substr не работают с многобайтовыми кодировками вроде utf-8. Здесь, конечно, не используются русские буквы, и потому все сработало, но вообще это ненадежно.
> preg_match('/^[1-9]/',...
Не найдет число, содержащее 0
Если добавить пробелы, все ломается: http://ideone.com/qJC97Y
Сама логика крайне запутанная. Надо бы все это упростить. Я думаю, можно регуляркой разбить исходную строку на массив элементов вида array('123', '+', '456', ...) а затем с этим массивом уже работать. Так мы разом избавимся от кучи запутанных строковых конструкций.
Сумма прописью
То же самое, пропусти код через phpformatter. тяжело его читать. Проблемы там конечно есть почти в каждой строчке, но они исправимы.
> else
> echo $spelling[$number]." ";
Надо всегда ставить скобки { }, даже если там одно действие, так как иначе появляется риск сделать ошибку. А со скобками весь блок виден гораздо лучше.
> $GLOBALS['isFemale']
Не используй глобальные переменные. Все, что нужно функции, надо передавать через аргументы в скобках.
> if ($number[strlen($number)-4]==1)//проверяет последние цифры
Для работы с числами используй только математику. Я дам тебе готовые формулы:
Вот 2 волшебных команды:
// получить последние 3 цифры числа:
echo 1234567 % 1000; // выведет 567
// получить число миллионов
echo floor(1234678 / 1000000); // выведет 12
Комбинируя их, можно получить что угодно. Надо все места, где ты работаешь с числом как со строкой, переделать.
То, что идет в строках 57-89 и 127-139 (склонение слов) — копипаста, а копипаста зло. Надо вынести это в функцию, которая сможет склонять любое слово (точнее выбирать 1 из 3 вариантов написания).
> $A
C большой буквы пишутся только константы и имена классов. Также, переменным надо давать осмысленные названия, плохо знаешь английский, не беда, slovari.yandex.ru и translate.google.com помогут.
> (($A[1].$A[2])
Обращение к строке как к массиву не работает с utf-8 (например с русскими буквами). Потому лучше всего вообще его не исопльзовать, а исплоьзовать mb_substr. Но в данном случае надо использовать математику, а не строковые функции.
echo надо вынести из функций. Нам нужна функция, которой мы даем число и которая возвращает строку, с которой мы делаем что хотим. Она не должна ничего печатать, так как в таком случае мы не можем например записать эту строку в файл или базу данных. Функция не должна ничего печатать, она получает что-то на вход и что-то возвращает.
Только не основы, как записать и как считать данные из кеша, а, так сказать, стратегию кеширования.
Допустим у меня есть класс, который тянет данные из БД, переваривает их и отдает результат. Если я правильно понял, то для ускорения работы методов класса мне надо закешировать результат работы метода, достающего из БД данные и переваривающего их.
От тут и вопросы:
1)кеш нужно сбрасывать. А значит идентификатор, сгененированный в читающем методе нужно где-то запомнить. А потом в других методах, пишущих в БД, очистить закешированные данные, помеченные указанным идентификатором.
Как этот идентификатор обычно именуют? $cacheId=__CLASS__ .'::'. __METHOD__ ."($searchParam)"; ?? Что-то типа такого? Хранить его в приватном приватном свойстве, а потом в пишушем методе очишать данные с этим ID ?? Как такое вообще обычно делают?
2) Если есть пять читающих методов и 5 пишущих, то там будет целая хитрая система, когда пишушие методы должны очищать кеши читающих методов. Блин, это сложно, очень легко запутаться! Есть какие-то простые варианты, как уследить за всеми кешами класса, чтоб не путаться?
3) Зачем вообще нужно кеширование с таймаутом? Если я правильно понял - то кеширование с таймаутом - для сложных случаем, когда читающий метод тянет инфу из множества источников, соответственно нереально везде в методах, которые данные в этих источниках меняют, вспомнить о том, что надо кеш какого-то там метода в каком-то классе сбросить? Эдакий примитивный вариант для сложных случаем, когда меняющихся источников инфы слишком много и за всеми не уследить?
Короче просветите, как в больших проектах решают проблемы, когда есть огромная куча методов, результаты которых надо закешировать и потом в других методах надо не забыть эти кеши сбросить. И как идентиикаторы передавать между классами, когда один класс читает и кеширует, а другой меняет данные и должен кеш сбросить.
Надеюсь ясно выразился.
Пиши верно
> substr_replace($value,$firstChar,0,1);
Некоторые функции PHP (strlen, substr, а также обращение к строке как к массиву: $str[0]) не работают с многобайтовыми кодировками (вроде utf-8). В utf-8 1 символ закодирован с помощью от 1 до 6 байтов, а эти функции думают, что 1 буква вегда кодируется одним байтом. По этой причине они ломают символы, в результате получаются битые символы и ничего не работает. Потому вместо них надо использовать mb_ функции например mb_strlen, mb_substr. Вместо доступа к строке как к массиву надо использовать mb_substr.
Давай разберем пример. Допустим, у нас есть строка из русской буквы «щ» в кодирове utf-8. Попытаемся взять первую букву с помощью неправильной функции:
// Внимание! это неправильный код, не пиши так!
$s = "щ";
$x = substr($s, 0, 1);
Буква «щ» кодируется в utf-8 как 2 байта: 209 137 (я взял информацию тут: http://www.utf8-chartable.de/unicode-utf8-table.pl?start=1024&utf8=dec ). substr отрезает от строки не первую букву, а первый байт. Это значит, что в $x он положит 1 байт с кодом 209. В utf-8 это неверная последовательность, она не соответвует никакому символу (так как после 209 обязательно должно идти второе число). Ideone может вообще отказаться что-то отображать, встретив такой код.
То же самое, когда ты обращаешься к строке как к массиву: $s[0]. Эта команда берет не первую букву, а только первый байт строки. Естественно, такая программа не будет работать.
Функция strlen считает число байт (не букв) в строке. То есть в данном случае strlen($s) вернет нам 2.
Латинница и цифры кодируются в utf-8 одним байтом, с ними это работает, но все равно, не надо использовать эти функции — это слишком ненадежно и легко сделать ошибку.
Вывод: используй mb_ функции. Не исплоьзуй доступ к строке как к массиву. В регулярных выражениях используй флаг u (он говорит что исплоьзуется utf-8 а не однобайтовая кодировка).
Некоторые строковые функции без префикса mb тем не менее корректно работают с utf-8 и их можно использовать. Вот они: strtr (если передавать массив), str_replace, str_repeat, explode, addslashes, trim.
> $firstChar=mb_substr($value,0,1,'utf-8');
utf-8 не надо писать если ты сделал в начале mb_internal_encoding
Пиши верно
> substr_replace($value,$firstChar,0,1);
Некоторые функции PHP (strlen, substr, а также обращение к строке как к массиву: $str[0]) не работают с многобайтовыми кодировками (вроде utf-8). В utf-8 1 символ закодирован с помощью от 1 до 6 байтов, а эти функции думают, что 1 буква вегда кодируется одним байтом. По этой причине они ломают символы, в результате получаются битые символы и ничего не работает. Потому вместо них надо использовать mb_ функции например mb_strlen, mb_substr. Вместо доступа к строке как к массиву надо использовать mb_substr.
Давай разберем пример. Допустим, у нас есть строка из русской буквы «щ» в кодирове utf-8. Попытаемся взять первую букву с помощью неправильной функции:
// Внимание! это неправильный код, не пиши так!
$s = "щ";
$x = substr($s, 0, 1);
Буква «щ» кодируется в utf-8 как 2 байта: 209 137 (я взял информацию тут: http://www.utf8-chartable.de/unicode-utf8-table.pl?start=1024&utf8=dec ). substr отрезает от строки не первую букву, а первый байт. Это значит, что в $x он положит 1 байт с кодом 209. В utf-8 это неверная последовательность, она не соответвует никакому символу (так как после 209 обязательно должно идти второе число). Ideone может вообще отказаться что-то отображать, встретив такой код.
То же самое, когда ты обращаешься к строке как к массиву: $s[0]. Эта команда берет не первую букву, а только первый байт строки. Естественно, такая программа не будет работать.
Функция strlen считает число байт (не букв) в строке. То есть в данном случае strlen($s) вернет нам 2.
Латинница и цифры кодируются в utf-8 одним байтом, с ними это работает, но все равно, не надо использовать эти функции — это слишком ненадежно и легко сделать ошибку.
Вывод: используй mb_ функции. Не исплоьзуй доступ к строке как к массиву. В регулярных выражениях используй флаг u (он говорит что исплоьзуется utf-8 а не однобайтовая кодировка).
Некоторые строковые функции без префикса mb тем не менее корректно работают с utf-8 и их можно использовать. Вот они: strtr (если передавать массив), str_replace, str_repeat, explode, addslashes, trim.
> $firstChar=mb_substr($value,0,1,'utf-8');
utf-8 не надо писать если ты сделал в начале mb_internal_encoding
Йода
Не используй substr_replace и strtolower.
> '/\. |\! |\? /'
Ненадежно, тут расчет что будет ровно 1 пробел. Лучше писать \s чтобы было любое число пробелов.
>>386861\t
Не работает с utf-8. Плохо ты знаешь PHP, видимо мои уроки не читал.
>>386875\t
На яваскрипт (просто яваскрипт и DOM) у нас тоже есть задачки, можешь глянуть: https://gist.github.com/codedokode/ce30e7a036f18f416ae0 — может оказаться что есть что подучить.
> mysql через mysqli
Это вообще плохо. Это обычно значит, что авторы взяли урок 10-летней давности и заменили там mysql_query (которая устарела) на mysqli_query. Лучше бы PDO осваивать: http://habrahabr.ru/post/137664/
Ты говоришь, что знаешь базы данных? Как насчет простой задачки отсюда: https://gist.github.com/codedokode/10539213#%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%BA%D0%B0-%D0%BF%D1%80%D0%BE-%D0%BB%D0%B0%D0%B9%D0%BA%D0%B8 Код можно постить на sqlfiddle.
Далее, не хочешь решить задачку на знание ООП? Если ты его хорошо знаешь и понимаешь, ты решение за 10 минут напишешь. Вот она: http://archive-ipq-co.narod.ru/l1/pasta.html (прокрути до заголовка «Задача про компанию «Вектор»):
> В большой международной перспективной компании «Вектор» есть 4 департамента: департамент закупок, продаж, рекламы и логистики...
Ну и после того, как ты проверишь себя на знание ООП и БД, я думаю, ты будешь вполне готов перейти к задаче про файлообменник, которую мы даем всем желающим: https://gist.github.com/codedokode/9424217 Там тебе и куки, и файлы, и базы данных пригодятся.
Если вдруг она покажется тебе слишком сложной (что вряд ли), то можешь начать с задания попроще: сделай сайт регистрации абитуриентов. Он состоит из 2 страниц: форма ввода/редактирования информации (главная страница) и список зарегистрированных абитуриентов.
Форма содержит поля: имя, фамилия, пол, номер группы (4 или 5 цифр), e-mail (должен быть уникален), суммарное число баллов на ЕГЭ (проверять на адекватность), год рождения, местный или иногородний. Данные надо сохранять в БД, все поля обязательны, при ошибке ввода отображать форму с сообщением об ошибке и выделенным красным цветом полем, при успешном заполнении — спасибо, данные сохранены, вы можете их отредактировать если хотите или просмотреть список абитуриентов.
Список абитуриентов — выводит имя, фамилию, номер группы, число баллов. Выводятся по 50 человек на страницу, сортировка по любому полю (по умолчанию по числу баллов вниз). Есть поле поиска, которое ищет сразу по всем строкам таблицы, регистронезависимо (то есть туда можно ввести номер группы либо часть имени/фамилии).
HTML-шаблоны должны быть отдельно от PHP кода. Редактировать можно только свои данные (проверяется через куки например). Надо использовать ООП.
Йода
Не используй substr_replace и strtolower.
> '/\. |\! |\? /'
Ненадежно, тут расчет что будет ровно 1 пробел. Лучше писать \s чтобы было любое число пробелов.
>>386861\t
Не работает с utf-8. Плохо ты знаешь PHP, видимо мои уроки не читал.
>>386875\t
На яваскрипт (просто яваскрипт и DOM) у нас тоже есть задачки, можешь глянуть: https://gist.github.com/codedokode/ce30e7a036f18f416ae0 — может оказаться что есть что подучить.
> mysql через mysqli
Это вообще плохо. Это обычно значит, что авторы взяли урок 10-летней давности и заменили там mysql_query (которая устарела) на mysqli_query. Лучше бы PDO осваивать: http://habrahabr.ru/post/137664/
Ты говоришь, что знаешь базы данных? Как насчет простой задачки отсюда: https://gist.github.com/codedokode/10539213#%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%BA%D0%B0-%D0%BF%D1%80%D0%BE-%D0%BB%D0%B0%D0%B9%D0%BA%D0%B8 Код можно постить на sqlfiddle.
Далее, не хочешь решить задачку на знание ООП? Если ты его хорошо знаешь и понимаешь, ты решение за 10 минут напишешь. Вот она: http://archive-ipq-co.narod.ru/l1/pasta.html (прокрути до заголовка «Задача про компанию «Вектор»):
> В большой международной перспективной компании «Вектор» есть 4 департамента: департамент закупок, продаж, рекламы и логистики...
Ну и после того, как ты проверишь себя на знание ООП и БД, я думаю, ты будешь вполне готов перейти к задаче про файлообменник, которую мы даем всем желающим: https://gist.github.com/codedokode/9424217 Там тебе и куки, и файлы, и базы данных пригодятся.
Если вдруг она покажется тебе слишком сложной (что вряд ли), то можешь начать с задания попроще: сделай сайт регистрации абитуриентов. Он состоит из 2 страниц: форма ввода/редактирования информации (главная страница) и список зарегистрированных абитуриентов.
Форма содержит поля: имя, фамилия, пол, номер группы (4 или 5 цифр), e-mail (должен быть уникален), суммарное число баллов на ЕГЭ (проверять на адекватность), год рождения, местный или иногородний. Данные надо сохранять в БД, все поля обязательны, при ошибке ввода отображать форму с сообщением об ошибке и выделенным красным цветом полем, при успешном заполнении — спасибо, данные сохранены, вы можете их отредактировать если хотите или просмотреть список абитуриентов.
Список абитуриентов — выводит имя, фамилию, номер группы, число баллов. Выводятся по 50 человек на страницу, сортировка по любому полю (по умолчанию по числу баллов вниз). Есть поле поиска, которое ищет сразу по всем строкам таблицы, регистронезависимо (то есть туда можно ввести номер группы либо часть имени/фамилии).
HTML-шаблоны должны быть отдельно от PHP кода. Редактировать можно только свои данные (проверяется через куки например). Надо использовать ООП.
Простую задачу про абитуриентов оформил и залил на гитхаб: https://gist.github.com/codedokode/d7e7f11449fc3bcb24b4
>>386879
Не знаю, учебник какой-нибудь для вузов может быть, потолще и поновее.
>>386909
Если этих задач будет мало, можешь попросить дополнительные на какую-то тему, не проблема.
кошка попробуй поменять ширину страницы: http://jsbin.com/wavomirofupa/1/edit - цифры наезжают на текст. Вот из-за этого:
> right: 430px;
У тебя позиция цифры привязана к правому краю страницы. А логичнее к левому, либо исплользовать привязку к 100% ширины.
2 line-height слишком тесный, по умолчанию стоит ставить 1.3-1.4 для этого шрифта и этой ширины текста. Попробуй, сразу просторнее станет. Шрифт должен быть нежирный. Тег p можно убрать либо обнулить ему маргины, а то отступ от верха у тебя не равен 10px —он больше.
И кстати, умеешь ли ты пользоваться инспектором (Ctrl + Shift + I) или фаербагом? Это обязательно для верстки. Если нет, то почитай: http://habrahabr.ru/post/143767/ — пригодится не раз.
3
> width: 100%
Зачем? По умолчанию и так ведь будет работать
В остальном, верно.
Простую задачу про абитуриентов оформил и залил на гитхаб: https://gist.github.com/codedokode/d7e7f11449fc3bcb24b4
>>386879
Не знаю, учебник какой-нибудь для вузов может быть, потолще и поновее.
>>386909
Если этих задач будет мало, можешь попросить дополнительные на какую-то тему, не проблема.
кошка попробуй поменять ширину страницы: http://jsbin.com/wavomirofupa/1/edit - цифры наезжают на текст. Вот из-за этого:
> right: 430px;
У тебя позиция цифры привязана к правому краю страницы. А логичнее к левому, либо исплользовать привязку к 100% ширины.
2 line-height слишком тесный, по умолчанию стоит ставить 1.3-1.4 для этого шрифта и этой ширины текста. Попробуй, сразу просторнее станет. Шрифт должен быть нежирный. Тег p можно убрать либо обнулить ему маргины, а то отступ от верха у тебя не равен 10px —он больше.
И кстати, умеешь ли ты пользоваться инспектором (Ctrl + Shift + I) или фаербагом? Это обязательно для верстки. Если нет, то почитай: http://habrahabr.ru/post/143767/ — пригодится не раз.
3
> width: 100%
Зачем? По умолчанию и так ведь будет работать
В остальном, верно.
4 — все верно
5
> h1 id= ...
Обычно h1 один на странице и id не требуется. Также, старайся реже использовать id в верстке так как они не могут повторяться и ты не сможешь их повторно использовать.
> #menu ul li{
>\tpadding-bottom: 0.5em;
А почему паддинг-то? Для отступов между блоками маргин больше подходит, паддинг — это поля.
Что касается отступов от края страницы. Ты используешь паддинг на заголовке и меню. Но лучше поставить паддинг на body — иначе тебе придется к каждому элементу его приписывать.
> #main p{
>\tmargin: 0px; padding: 10px;
Это неправильно. Попробуй вставить внутрь main текст без тега p или картинку — и к ней паддинг не применится. Поля надо задавать 1 раз на родителе. на p должен быть только отступ (маргин) по ветикали.
Непраивльно: ставит паддинг/маргин на всех детях.
Правильно: поставить паддинг 1 раз на родителе.
6
> box-sizing: border-box;
В моем фаерфоксе 24 не работает, там надо писать -moz-box-sizing. Прочти про вендорные префиксы http://htmlbook.ru/css/box-sizing либо сделай без этого свойства.
7
> #note{
Нельзя добавить 2 примечания. Смотри, надо сделать нормальную верстку, чтобы мы ей могли заверстать и какой-то другой текст, в котором больше абзацев и примечаний.
> p {
>\tcolor: #0011aa;
Не надо ставить цвет на каждый абзац, ставь на родителе. А то например к списку он не применится. То же относится к маргину. Посмотри сам: http://jsbin.com/hiwezodeqetu/1/edit
> p class="paragraph"
Масло масляное. Не думаю, что тут нужен класс. Я думаю, тут для p вообще никаких стилей писать не надо — те, что встроены в браузер, подойдут.
4 — все верно
5
> h1 id= ...
Обычно h1 один на странице и id не требуется. Также, старайся реже использовать id в верстке так как они не могут повторяться и ты не сможешь их повторно использовать.
> #menu ul li{
>\tpadding-bottom: 0.5em;
А почему паддинг-то? Для отступов между блоками маргин больше подходит, паддинг — это поля.
Что касается отступов от края страницы. Ты используешь паддинг на заголовке и меню. Но лучше поставить паддинг на body — иначе тебе придется к каждому элементу его приписывать.
> #main p{
>\tmargin: 0px; padding: 10px;
Это неправильно. Попробуй вставить внутрь main текст без тега p или картинку — и к ней паддинг не применится. Поля надо задавать 1 раз на родителе. на p должен быть только отступ (маргин) по ветикали.
Непраивльно: ставит паддинг/маргин на всех детях.
Правильно: поставить паддинг 1 раз на родителе.
6
> box-sizing: border-box;
В моем фаерфоксе 24 не работает, там надо писать -moz-box-sizing. Прочти про вендорные префиксы http://htmlbook.ru/css/box-sizing либо сделай без этого свойства.
7
> #note{
Нельзя добавить 2 примечания. Смотри, надо сделать нормальную верстку, чтобы мы ей могли заверстать и какой-то другой текст, в котором больше абзацев и примечаний.
> p {
>\tcolor: #0011aa;
Не надо ставить цвет на каждый абзац, ставь на родителе. А то например к списку он не применится. То же относится к маргину. Посмотри сам: http://jsbin.com/hiwezodeqetu/1/edit
> p class="paragraph"
Масло масляное. Не думаю, что тут нужен класс. Я думаю, тут для p вообще никаких стилей писать не надо — те, что встроены в браузер, подойдут.
Главная проблема кеширования — информация в нем может стать неактуальной. Пользователь поменял ник, а на части страниц выводится старый. Решения:
- кешировать меньше
- кешировать более атомарно (не выборку, а отдельные строки например)
- меньшее время жизни
- удалять затронутые ключи кеша при изменении данных
Анализировать эффективность кеша можно соотношением hit/miss
> Если я правильно понял, то для ускорения работы методов класса мне надо закешировать результат работы метода, достающего из БД данные и переваривающего их.
Прежде чем это делать надо посмотреть сколько времени уходит на выборку и на обработку. Если выбирается медленно то может проще оптимизировать запрос? Кеш не замена плохому коду.
> Как этот идентификатор обычно именуют?
userInfo:1234 (id юзера)
lastVisit:1234
friends:12345:byDate:1 (список друзей отсортированный по дате, первая страница)
cities:russia (города России)
> Что-то типа такого? Хранить его в приватном приватном свойстве,
Сделать метод, вроде User::getInfoCacheKey($id) или константу User::INFO_CACHE_KEY. Метод лучше так как туда можно впилить проверку правильности аргументов.
> Как такое вообще обычно делают?
при обновлении профиля сбрасывают кеш по id и другие кеши где он может быть. Чем больше ключей, тем сложнее поддерживать актуальность. Но если они все завязаны на id то сбросить их не так и сложно. Можно ставить маленькое время жизни, но тогда будет низкая эффективность. Потому всегда есть возможность лучше не кешировать данные.
> Есть какие-то простые варианты, как уследить за всеми кешами класса, чтоб не путаться?
Использовать меньше ключей кеша. есть такая штука как «теги для кеша», то есть мы помечаем все ключи, где есть пользователь 123 тегом user_123 и потом можем их разом удалить по тегу, но это не бесплатно и напоминает оверинжиниринг. Лучше меньше ключей делать.
Посмотри, если какие-то данные дергаются на каждый запрос (инфа о юзере), ее стоит кешировать. Если редко, то проще вообще не кешировать. Каждую функцию кешировать глупо.
Можно еще сделать метод типа dropUserСache($id) который знает какие ключи надо сбросить при обновлении пользователя.
> Зачем вообще нужно кеширование с таймаутом?
Да, для обновления информации.
Главная проблема кеширования — информация в нем может стать неактуальной. Пользователь поменял ник, а на части страниц выводится старый. Решения:
- кешировать меньше
- кешировать более атомарно (не выборку, а отдельные строки например)
- меньшее время жизни
- удалять затронутые ключи кеша при изменении данных
Анализировать эффективность кеша можно соотношением hit/miss
> Если я правильно понял, то для ускорения работы методов класса мне надо закешировать результат работы метода, достающего из БД данные и переваривающего их.
Прежде чем это делать надо посмотреть сколько времени уходит на выборку и на обработку. Если выбирается медленно то может проще оптимизировать запрос? Кеш не замена плохому коду.
> Как этот идентификатор обычно именуют?
userInfo:1234 (id юзера)
lastVisit:1234
friends:12345:byDate:1 (список друзей отсортированный по дате, первая страница)
cities:russia (города России)
> Что-то типа такого? Хранить его в приватном приватном свойстве,
Сделать метод, вроде User::getInfoCacheKey($id) или константу User::INFO_CACHE_KEY. Метод лучше так как туда можно впилить проверку правильности аргументов.
> Как такое вообще обычно делают?
при обновлении профиля сбрасывают кеш по id и другие кеши где он может быть. Чем больше ключей, тем сложнее поддерживать актуальность. Но если они все завязаны на id то сбросить их не так и сложно. Можно ставить маленькое время жизни, но тогда будет низкая эффективность. Потому всегда есть возможность лучше не кешировать данные.
> Есть какие-то простые варианты, как уследить за всеми кешами класса, чтоб не путаться?
Использовать меньше ключей кеша. есть такая штука как «теги для кеша», то есть мы помечаем все ключи, где есть пользователь 123 тегом user_123 и потом можем их разом удалить по тегу, но это не бесплатно и напоминает оверинжиниринг. Лучше меньше ключей делать.
Посмотри, если какие-то данные дергаются на каждый запрос (инфа о юзере), ее стоит кешировать. Если редко, то проще вообще не кешировать. Каждую функцию кешировать глупо.
Можно еще сделать метод типа dropUserСache($id) который знает какие ключи надо сбросить при обновлении пользователя.
> Зачем вообще нужно кеширование с таймаутом?
Да, для обновления информации.
Почитай еще
http://lib.custis.ru/images/6/6d/WebAppCache.pdf
http://vimeo.com/66739605
http://www.insight-it.ru/highload/ — про архитектуру
Посты начинают добовляться-абы как, не в самый конец, иногда. И некрасиво же.
Спасибо.
>Также, если у тебя есть что-то вроде разбора запроса пользователя
Есть такое, да. С пхпюнит я уже познакомился, выглядит норм.
это исходники. Ищи windows binaries: http://windows.php.net/downloads/pecl/releases/
Убедись что используешь версию соответсвтующую твоему php и Апачу (скорее всего ts и vc11 или vc9)
Спасибо, ОП, ты как всегда охуенен.
А как узнать какая у меня?
И когда я качал, вообще рандомно выбирал помнится, чем они хоть отличаются?
Нашел в phpinfo()
Но теперь не могу поставить. Кинул в ext, включил в php.ini - не работают функции и в phpinfo() не появилось.
А, так сначала надо поставить сам мемкеш, во дела. А в гуглах везде ссылки битые на виндовс версию. Как так.
Забавно, что даже в одном несколько-летнем видео на сайте видно версии 1.4. для виндовс, а сейчас на это сайте только версия времен палеолита. Что происходит? Мир сошел с ума! Это же такая расхожая вещь, почему я нигде не могу её найти.
Будет так?
Класс ЭлектрическаяСеть
св-ва: список ЭлементовСети.
методы: считатьРазницу, считатьСтоимость, добавить ЭлементСети.
Класс ЭлементСети:
св-ва: выработаннаяЭнергия, затраченнаяЭнергия.
методы: посчитатьСколькоВырабатано, посчитатьСколькоЗатрачено.
Класс Электростанция
св-ва: вырабатываемая электроэнергия.
Класс СолнечнаяПанель
св-ва: вырабатываемая днем электроэнергия.
Класс Дома
св-ва: потребление днем, потребление ночью, количество человек.
методы: посчиать затрачиваемую энергию днем, почитать затрачиваемую энергию ночью.
Класс ЛинииЭлектропередач
св-ва: пропускная способность, цена за мегаватт.
хтмл:
<tag attribute="value">content</tag>
ксс:
elements {
prorepty: value;
}
Могу поздравить! Теперь ты знаешь хтмл и ксс. Можешь приступать к php. Видео-формат на codeschool обычно.
$php_var = 'Hello world'; еще и пых знает
Он не установлен на хостингде, очевидно. Или скажите мне ололо-бессплатный хостинг хороший, где бы стоял он.
что за старье у тебя на хостинге? он вроде стандарт в комплекте с пятой версии
Ни разу он не включен в стандарт.
одно другому не мешает, мне, например, так усваивать легче информацию.
>>386976
>логичнее к левому.
Хоть убей не понимаю как. У меня получается что цифры выравнены в право, да и если строка станет длиннее, то символы начинают заезжать за текст.
кошка1 http://jsbin.com/viqowepoliho/1/edit
>либо использовать привязку к 100% ширины.
А так я вообще не представляю как сделать, не вмешиваясь в HTML-код. Символы не желают залазить за край родительского блока.
кошка2 http://jsbin.com/casahonadari/1/edit
>И кстати, умеешь ли ты пользоваться инспектором (Ctrl + Shift + I) или фаербагом.
Спасибо. Так намного удобней.
5 задача http://jsbin.com/wuwifakuxeya/1/edit Как то так.
>Я думаю, тут для p вообще никаких стилей писать не надо. Это как? Я для FLOAT умею только маргинами верстать.
7 задача http://jsbin.com/tamuzakiwaro/1/edit
>>387061
Ты про задачу про айфон? С ней все мучаются. Покажи свой код и напиши в чем именно затык.
Также, можешь попробовать решить для начала задачу которая идет дальше, она более простая:
> W5.2 Некто кладет в банк 10000 р. Банк начисляет 10% годовых (то есть, каждый год на счету становится на 10% больше, чем в прошлом году). Напиши программу, считающую, через сколько лет в банке будет миллион? Сколько лет будет этому некто? Доживет ли некто до этого дня, если сегодня ему 16 лет?
>>387063
ts — c поддержкой многопоточности, nts (non threadsafe) — без. Апач использует многопоточность под виндой, потому надо ts
vc9, vc11 — каким компилятором собрана
x86 — 32 битная, x64 — 64 битная, это ты должен и сам знать, какая у тебя ОС и Апач.
>>387074
Апач перезапустил?
>>387098
Функции и информация в PHP.ini должны появляться и без этого. Раширение которое ты ставишь — это лишь клиент который позволяет подключиться к мемкеш-серверу (memcached).
>>387107
Автор распространяет исходники, а скомпилировать их — твоя задача, ты же программист . Версия 1.4 (точнее 1.4.20) вполне современна, судя по оф сайту: http://memcached.org/
Раньше вообще винда не поддерживалась так как livejournal делали мемкеш для себя (линукс и мак), а не для тебя.
Бинарники под винду надо либо компилировать, либо скачать кем-то скомпилированный (возможно с троянами внутри, обязательно проверяй антивирусом).
>>387123
А где тут наследование? Мне кажется должно быть так:
ЭлементСети (базовый абстрактный класс), метод: получитьВкладВОбщийБаланс()
От него наследуются дома и прочее.
А у тебя лишние свойства получаются:
> выработаннаяЭнергия, затраченнаяЭнергия.
Хватит одного свойства, просто писать туда положительные или отрицательные числа. Или вообще без них обойтись — есть же метод.
>>387136
Если хостинг не предоставляет мемкеш или что-то аналогичное, то никак. Разве что на файлах, но будет тормозить. Ищи нормальный (платный) хостинг, а лучше свой VPS.
>>387141
Что за бред? Memcached — сторонний демон, который не поставляется вместе с php
>>387061
Ты про задачу про айфон? С ней все мучаются. Покажи свой код и напиши в чем именно затык.
Также, можешь попробовать решить для начала задачу которая идет дальше, она более простая:
> W5.2 Некто кладет в банк 10000 р. Банк начисляет 10% годовых (то есть, каждый год на счету становится на 10% больше, чем в прошлом году). Напиши программу, считающую, через сколько лет в банке будет миллион? Сколько лет будет этому некто? Доживет ли некто до этого дня, если сегодня ему 16 лет?
>>387063
ts — c поддержкой многопоточности, nts (non threadsafe) — без. Апач использует многопоточность под виндой, потому надо ts
vc9, vc11 — каким компилятором собрана
x86 — 32 битная, x64 — 64 битная, это ты должен и сам знать, какая у тебя ОС и Апач.
>>387074
Апач перезапустил?
>>387098
Функции и информация в PHP.ini должны появляться и без этого. Раширение которое ты ставишь — это лишь клиент который позволяет подключиться к мемкеш-серверу (memcached).
>>387107
Автор распространяет исходники, а скомпилировать их — твоя задача, ты же программист . Версия 1.4 (точнее 1.4.20) вполне современна, судя по оф сайту: http://memcached.org/
Раньше вообще винда не поддерживалась так как livejournal делали мемкеш для себя (линукс и мак), а не для тебя.
Бинарники под винду надо либо компилировать, либо скачать кем-то скомпилированный (возможно с троянами внутри, обязательно проверяй антивирусом).
>>387123
А где тут наследование? Мне кажется должно быть так:
ЭлементСети (базовый абстрактный класс), метод: получитьВкладВОбщийБаланс()
От него наследуются дома и прочее.
А у тебя лишние свойства получаются:
> выработаннаяЭнергия, затраченнаяЭнергия.
Хватит одного свойства, просто писать туда положительные или отрицательные числа. Или вообще без них обойтись — есть же метод.
>>387136
Если хостинг не предоставляет мемкеш или что-то аналогичное, то никак. Разве что на файлах, но будет тормозить. Ищи нормальный (платный) хостинг, а лучше свой VPS.
>>387141
Что за бред? Memcached — сторонний демон, который не поставляется вместе с php
> меня получается что цифры выравнены в право, да и если строка станет длиннее, то символы начинают заезжать за текст.
Все просто. Блок с цифрами прижат к левому краю страницы - значит используем left а не right. Чтобы цифры были выровнены как надо, задаем блоку ширину и делаем text-align right
Либо пробуем заюзать float left вместо position absolute, а остальное так же.
Кстати, надпись is in the picture можно подвинуть вправо на 1-2 пикселя для лучшего выравнивания относительно заголовка, точнее большой буквы A.
5 задача — теперь верно
7 задача примечание сдвинь чуть ниже и увеличь в нем line-height а то тесно.
> p{
>\tmargin: 10px;
>\tmargin-left: 120px;
Смотри, я добавляю в текст список и что я вижу? http://jsbin.com/fuwecugasori/1/edit
Ты замучаешься margin добавлять ко всем видам тегов. И это неправильно.
Для создания полей задавай padding на родительском элементе (например body), а не margin на детях. margin не для этого, он для того, чтобы задать внешний отступ между 2 элементами, а не поля.
На p вообще не надо никаких стилей вешать.
Наконец то я родил эти задачи, ну по крайней мере мне так кажется. Вот почему я не смог это решить с первого раза и без подсказок? Вроде про все эти свойства уже не раз прочитал.
кошка http://jsbin.com/firowuyipise/1/edit
задача 7 http://jsbin.com/niyumogomupi/1/edit
Эти статьи читал кстати? Если нет то почитай, там хорошо все объясняется: http://softwaremaniacs.org/blog/category/primer/ (снизу вверх). В том числе флоаты.
> html{
>\tmargin-left: 120px;
Тут логичнее использовать padding так как он задает поля. А margin это отступ между элементами.
> float:left;
> margin-right: -100px;
> right: 110px;
Это костыли, так не пойдет. Ты должен прижимать флоат не к левому краю текста, а выносить левее текста, например с помощью отрицательного margin-left.
Вот я написал мини-урок про флоаты и маргины (надеюсь все понятно): https://gist.github.com/codedokode/3f6063edf0a2227eb313
задача 7
Обойдись без posiion relative, достаточно использовать отрицательный маргин
Спасибо тебе милый человек.
>Это костыли, так не пойдет.
Как отличить костыль от некостыля?
Кошка http://jsbin.com/firowuyipise/2/edit
Задача 7 http://jsbin.com/niyumogomupi/2/edit
Интерпретатор позволяет запускать программу у себя на компьютере (а не через сервисы типа ideone). Соответственно, ты можешь запускать программы без ограничений, которые есть на ideone и эти программы могут читать/сохранять файлы на диск, работать с сетью и т.д (что в ideone недоступно).
Как установить: https://gist.github.com/codedokode/7054af4a03865c4cc863 (с картинками)
Не костыль — это когда ты делаешь логичным способом. Например, выносишь блок с помощью float left и отрицательного margin. Либо position absolute. Костыль — когда ты не догадался до логичного способа и начинаешь усложнять все без надобности или придумывать обходные пути: смещать блок к левому краю текста, компенсировать его ширину отрицательным маргином и прикручивать относительное позиционирование.
Еще есть такая вещь, как «меняем свойства наугад пока не заработает». Я в учебных задачах такое не пропускаю, каждое свойство должно иметь причину по которой оно там стоит.
> Кошка
Тут конечно можно спросить тебя зачем на флоате отрицательный margin-right, но ладно, хватит тебя мучать, задача решена.
> Задача 7
> right: 120px;
Зачем? Забыл удалить?
В примечании я бы на пару пикселей увеличил margin-top и увеличил line-height до 1.3-1.4 (а то тесно). И тогда, думаю, все будет решено. Заметь, насколько проще и логичнее в итоге стал код.
Парсер делаю, сори.
Делаю задание с кубиком. Нужно перенести текст на новую строчку, но текст все равно пишется слитно.
<?php
header('Content-Type: text/html; charset=utf-8');
error_reporting(-1);
echo "Бросаем кубик...";
$random = mt_rand(1, 6);
echo "Выпало $random";
?>
как сделать с новой строчки текст?
>Вопрос!
Делаю задание с кубиком. Нужно перенести текст на новую строчку, но текст все равно пишется слитно.
<?php
header('Content-Type: text/html; charset=utf-8');
error_reporting(-1);
echo "Бросаем кубик...";
$random = mt_rand(1, 6);
echo "Выпало $random";
?>
как сделать с новой строчки текст?
Забыл написать, \n; \r\n; \n\r- все перепробовал.
Чтобы переносы строк нормально работали и в браузере и в ideone (и в консоли), можно использовать для этого \n, а в начале программы поставить
header("Content-Type: text/plain; charset=utf-8");
Это заставит браузер воспринимать то, что выводит твоя программа, как обычный текст, а не HTML, и уважать переносы строк в нем (так как в языке HTML перенос строки равносилен пробелу).
Иначе перенос строки будет в исходном коде страницы (его можно увидеть нажав Ctrl + U), но на самой странице его не будет.
>>387264
Не в PHP, а в plain text, то есть обычном тексте.
Браузер по умолчанию воспринимает то что выводит программа как HTML а в этом языке перенос строки воспринимается по умолчанию как обычный пробел.
То есть какая структура, что происходит при открытии ссылки вида site.ru/?r=... - по каким файлам прыгаем, как и что грузим?
Как реализованы "компоненты" типа проверки корректности аргументов запроса, авторизация, капча, итп?
Какие вообще сущности есть в Yii, как я понял модуль view не полноценный, а кусок контроллера?
Вообщем по офф руководству у меня структура фреймворка вообще в голове не выстраивается.
Плюс стопорнулся на мануалу по созданию тестового блога на этапе добавления проверок аргументов, фильтры или как там - смутил этот формат указания правил как элементы массива с кучей зарегестрированных слов вперемешку с именами полей. Ну ок, есть проверка ключевым словом "email". А если у меня в таблице есть поле "email"? Не пойдет оно все по?
Вообщем хочется какую-то картинку в голове прежде чем идти дальше то есть есть вот ядро, оно лежит тут, делает то-то, есть компоненты, они лежат тут, итп.
>>387401
Как то глупо поступает твой анон. Сначала платит, и только потом смотрит сколько ещё осталось заплатить. Вот и переплачивает.
if ($creditBalance < 0)
Было бы логичней если б он как все нормальные люди сначала смотрел сколько осталось заплатить,а потом бы думал сколько ему нужно заплатить.
Не знаю, не пишу на говне :3
Если серьезно, ты правда не понимаешь? В таком случае я даже не представляю на что ты рассчитываешь в области погромирования. С таким уровнем знаний\интеллекта тебе даже пол в офисе мыть не доверят.
http://codepad.org/ffm208GG
ОП критикуй. Что из наляпаного допустимо, а что нет.
Задача 8 http://jsbin.com/sinelekafujo/1/edit
Я даже не уверен, что правильно понял условие.
Нужен. Кто-то же должен хранить список всех элементов сети и вычислять общее потребление.
>>387299\t
Задача про айфон сложная, на ней все спотыкаются.
Вернуться к предыдущему шагу цикла никак нельзя и не нужно. Вместо этого надо менять логику и не переплачивать больше чем требуется.
Надо смотреть чему равен остаток долга и обрабатывать ситуацию, когда она маленький, а не выплачивать сразу же 5000 вот в этом месте: ... + $servicePayment - $monthlyPayment;
Попробуй переписать код внутри цикла примерно так:
- прибавляем проценты и комиссию к остатку долга
- если остаток маленький, выплачиваем сколько осталось и уходим
- иначе платим 5000
Читал официальный гайд? Вот этот http://www.yiiframework.com/doc/guide/1.1/ru/index ?
> То есть какая структура,
Вот тут вроде описана страктура папок http://habrahabr.ru/sandbox/57183/
> что происходит при открытии ссылки вида site.ru/?r=... - по каким файлам прыгаем, как и что грузим?
Это читал?
http://www.yiiframework.com/doc/guide/1.1/ru/basics.mvc
http://www.yiiframework.com/doc/guide/1.1/ru/basics.entry
ну и то что там далее
> Как реализованы "компоненты" типа проверки корректности аргументов запроса, авторизация, капча, итп?
Это надо смотреть описание конкретных компонентов.
> Какие вообще сущности есть в Yii, как я понял модуль view не полноценный, а кусок контроллера?
Не очень понял этот вопрос — там есть контроллеры, модели, вью, фильтры, виджеты, расширения и разные вспомогательные классы.
> Плюс стопорнулся на мануалу по созданию тестового блога на этапе добавления проверок аргументов, фильтры или как там - смутил этот формат указания правил как элементы массива с кучей зарегестрированных слов вперемешку с именами полей. Ну ок, есть проверка ключевым словом "email". А если у меня в таблице есть поле "email"? Не пойдет оно все по?
Ты про формы? А гайд по формам прочел? http://www.yiiframework.com/doc/guide/1.1/ru/form.overview
Ошибки не будет так как тип ты пишешь тип поля в элементе type:
array(
'x' => array('type' => 'email'),
.....
)
> Вообщем хочется какую-то картинку в голове
Прочитай руководство по ссылкам. Если еще что-то непонятно, задавай вопросы.
Читал официальный гайд? Вот этот http://www.yiiframework.com/doc/guide/1.1/ru/index ?
> То есть какая структура,
Вот тут вроде описана страктура папок http://habrahabr.ru/sandbox/57183/
> что происходит при открытии ссылки вида site.ru/?r=... - по каким файлам прыгаем, как и что грузим?
Это читал?
http://www.yiiframework.com/doc/guide/1.1/ru/basics.mvc
http://www.yiiframework.com/doc/guide/1.1/ru/basics.entry
ну и то что там далее
> Как реализованы "компоненты" типа проверки корректности аргументов запроса, авторизация, капча, итп?
Это надо смотреть описание конкретных компонентов.
> Какие вообще сущности есть в Yii, как я понял модуль view не полноценный, а кусок контроллера?
Не очень понял этот вопрос — там есть контроллеры, модели, вью, фильтры, виджеты, расширения и разные вспомогательные классы.
> Плюс стопорнулся на мануалу по созданию тестового блога на этапе добавления проверок аргументов, фильтры или как там - смутил этот формат указания правил как элементы массива с кучей зарегестрированных слов вперемешку с именами полей. Ну ок, есть проверка ключевым словом "email". А если у меня в таблице есть поле "email"? Не пойдет оно все по?
Ты про формы? А гайд по формам прочел? http://www.yiiframework.com/doc/guide/1.1/ru/form.overview
Ошибки не будет так как тип ты пишешь тип поля в элементе type:
array(
'x' => array('type' => 'email'),
.....
)
> Вообщем хочется какую-то картинку в голове
Прочитай руководство по ссылкам. Если еще что-то непонятно, задавай вопросы.
Запости код и напиши конкретно на каком месте остановился. А то я не знаю, какая именно тебе подсказка нужна.
Задача сложная, на ней все спотыкаются.
>>387372\t
В PHP есть неоьязательные аргументы функций: http://php.net/manual/ru/functions.arguments.php#functions.arguments.default
Но в твоем случае, можно не передавать босса в конструктор, а сделать метод «назначитьБосса». В конструктор обычно передают то, что обязательно, например, название, а босс (и сотрудники) как мне кажется необязательны — департамент можно создать пустым и постепенно заполнять.
>>387373\t
Нет, нельзя
>>387401\t
Нечитаемая лапша с однобуквенными переменными. Такой код в нашем треде не принимается.
>>387489
Пришел самоутверждаться в тред для начинающих? Я уверен что и для тебя можно найти то, что ты не сможешь сделать, например сыграть несколько нот на скрипке или кота нарисовать или мяч в корзину забросить.
Алсо, пошел вон.
Запости код и напиши конкретно на каком месте остановился. А то я не знаю, какая именно тебе подсказка нужна.
Задача сложная, на ней все спотыкаются.
>>387372\t
В PHP есть неоьязательные аргументы функций: http://php.net/manual/ru/functions.arguments.php#functions.arguments.default
Но в твоем случае, можно не передавать босса в конструктор, а сделать метод «назначитьБосса». В конструктор обычно передают то, что обязательно, например, название, а босс (и сотрудники) как мне кажется необязательны — департамент можно создать пустым и постепенно заполнять.
>>387373\t
Нет, нельзя
>>387401\t
Нечитаемая лапша с однобуквенными переменными. Такой код в нашем треде не принимается.
>>387489
Пришел самоутверждаться в тред для начинающих? Я уверен что и для тебя можно найти то, что ты не сможешь сделать, например сыграть несколько нот на скрипке или кота нарисовать или мяч в корзину забросить.
Алсо, пошел вон.
Ответ праивльный, но логику надо допилить.
Надо смотреть чему равен остаток долга и обрабатывать ситуацию, когда она маленький, а не выплачивать сразу же 5000 вот в этом месте: ... + $servicePayment - $monthlyPayment;
Попробуй переписать код внутри цикла примерно так:
- прибавляем проценты и комиссию к остатку долга
- если остаток маленький, выплачиваем сколько осталось и уходим
- иначе платим 5000
А то ты в минус уходишь, неправильно.
>>387506
Желтый квадрат (который float) не должен вываливаться вниз из серого блока (сделай окно пошире если не видишь).
> <div class="container1">
> <div class="container2">
Тут должен быть один и тот же класс, так как может быть я хочу 20 таких серых блоков поставить друг за другом
> body div{
Это вообще не имеет смысла, так как любой div находится внутри body
> div
Неправильно, так как ты применяешь стили ко всем дивам на странице. То есть если добавить твою верстку на сайт, то он сломается. Применяй стили только к своим дивам, например так:
.container { ... }
> div div
Используй классы тут
> p{
> margin-left: 160px;
А если я захочу добавить внутрь серого блока список или картинку? Они не получат отступ. Поля делаются паддингом на родителе, а не маргином на детях. И кажется я в предыдущих задачах тебе (или не тебе?) это говорил. Смотри сам: http://jsbin.com/nunotalefafe/2/edit
> .container1{
> min-height: 170px;
А если я поменяю высоту желтого блока? http://jsbin.com/nunotalefafe/3/edit Я думаю, min-height тут не нужен
> .container2 div{
> margin-bottom: -162px;
то же самое, это тут не нужно. Это какие-то костыли, которые развалятся при любом изменении верстки.
И вообще, это задача на флоаты, клеар и клеарфикс. Читай:
http://softwaremaniacs.org/blog/2005/12/01/css-layout-float/
http://habrahabr.ru/post/136622/
http://habrahabr.ru/post/142486/
http://nicolasgallagher.com/micro-clearfix-hack/ (вот это тут пригодится)
http://private-face.ru/habrahabr.ru/blogs/css/48391/
Заметь, что есть 2 способа заставить блок охватывать свое содержимое: clearfix и overflow hidden. Так как второй — это костыль и обладает недостатками, его в решении использовать нельзя.
Ответ праивльный, но логику надо допилить.
Надо смотреть чему равен остаток долга и обрабатывать ситуацию, когда она маленький, а не выплачивать сразу же 5000 вот в этом месте: ... + $servicePayment - $monthlyPayment;
Попробуй переписать код внутри цикла примерно так:
- прибавляем проценты и комиссию к остатку долга
- если остаток маленький, выплачиваем сколько осталось и уходим
- иначе платим 5000
А то ты в минус уходишь, неправильно.
>>387506
Желтый квадрат (который float) не должен вываливаться вниз из серого блока (сделай окно пошире если не видишь).
> <div class="container1">
> <div class="container2">
Тут должен быть один и тот же класс, так как может быть я хочу 20 таких серых блоков поставить друг за другом
> body div{
Это вообще не имеет смысла, так как любой div находится внутри body
> div
Неправильно, так как ты применяешь стили ко всем дивам на странице. То есть если добавить твою верстку на сайт, то он сломается. Применяй стили только к своим дивам, например так:
.container { ... }
> div div
Используй классы тут
> p{
> margin-left: 160px;
А если я захочу добавить внутрь серого блока список или картинку? Они не получат отступ. Поля делаются паддингом на родителе, а не маргином на детях. И кажется я в предыдущих задачах тебе (или не тебе?) это говорил. Смотри сам: http://jsbin.com/nunotalefafe/2/edit
> .container1{
> min-height: 170px;
А если я поменяю высоту желтого блока? http://jsbin.com/nunotalefafe/3/edit Я думаю, min-height тут не нужен
> .container2 div{
> margin-bottom: -162px;
то же самое, это тут не нужно. Это какие-то костыли, которые развалятся при любом изменении верстки.
И вообще, это задача на флоаты, клеар и клеарфикс. Читай:
http://softwaremaniacs.org/blog/2005/12/01/css-layout-float/
http://habrahabr.ru/post/136622/
http://habrahabr.ru/post/142486/
http://nicolasgallagher.com/micro-clearfix-hack/ (вот это тут пригодится)
http://private-face.ru/habrahabr.ru/blogs/css/48391/
Заметь, что есть 2 способа заставить блок охватывать свое содержимое: clearfix и overflow hidden. Так как второй — это костыль и обладает недостатками, его в решении использовать нельзя.
Условие задачи примерно такое:
Надо сделать верстку для размещения на странице произвольного числа серых блоков. Серые блоки занимают всю ширину страницы и располагаются вертикально. У них слева располагается желтый блок фиксированной ширины и неизвестной высоты. Справа располагается произвольный текстовый контент (возможно со списками, заголовками, таблицами, картинками и т д). Например, это может быть верстка форума, где слева идет аватарка, а справа содержание поста.
Содержание по высоте может быть выше желтого блока, а может быть ниже — но серый блок должен охватывать их полностью.
Верстка не должна ломать другие элементы страницы (если мы заходтим их добавить), потому стили должны применяться не к дивам, а к конкретным классам. В верстке надо избежать использования лишних элементов и мне кажется, тут хватит 2 дивов на 1 пост: один для серого блока, один для желтого.
Мне кажется это специально было сделано, типа - не дрочился как мы - то вообще иди в пизду.
Просто баттхерт вызывает то, что можно написать в двух словах, просто дополнив доки и тогда новичку даже не понадобятся книги по Пыхе, но нет сука, давай деньги, давай свой баттхерт.
Напр 3,10,4,7,1 и тд.
возможно некорректно задал вопрос, еще сплю видимо.
Выборка такая есть, но она возвращается как 1,3,4,7,10
Как отсортировать чтобы вернулось как в запросе?
а, я тебя не понял, вроде по нормальному никак нельзя в sql, проще в уже полученном результате отсортировать как тебе нужно
http://stackoverflow.com/a/8322898
http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_field
Алсо можно сортировать на стороне PHP. Алсо скорее всего ты что-то делаешь неправильно раз такое тебе понадобилось.
я знаю, просто нужно же было чето ляпнуть в помощь )
В PHP по моему (и не только по моему) лучший мануал в сравнении с другими языками. Есть и русский перевод, и куча примеров, и комментарии, и все объяснено что можно.
Не забывай что это мануал для профессионалов и IT-специалистов, а не пособие для блондинок из инстаграма.
Привыкай, читай его чаще и со временем он станет тебе как родной.
Если что-то непонятно, задай вопрос в треде. Может ты просто какую-то важную тему не изучил, и за сложное берешься.
выборка с я.метрики популярных урлов. Потом с этих урлов достаю айди и выбираю новости. Раньше показывал их так как приходят, а сейчас захотелось вывести в том порядке в котором показывает их метрика. За час бестолкового гугления нарыл только order by field.
Его и заюзал, вроде норм.
Ну если еще чего аноны посоветуют буду рад.
Алсо спасибо за помощь :3
И не забывай, что это документация, а не учебник. Она предназаначена для ответа на вопрос «как работает та или иная функция или опция, как работает PHP» и предполагает определенный набор базовых знаний (принципы работы веб-серверов, HTTP, HTML, основы линукса). В идеале, хорошо если ты знаешь один или несколько других языков и являешься IT-специалистом.
Это не учебник для начинающих с нуля. Не верь тем, кто говорит что по документации можно хорошо изучить язык — это вряд ли.
К базе данных ты можешь подключиться и в обход Джумлы, но сначала стоит поискать какое-нибудь АПИ. Лезть напрямую — очень опасно так как ты можешь забыть изменить какое-то поле и все сломается или будет глючить и уйдет куча времени на отладку. Официальное АПИ всегда лучше.
Во-первых, можно сделать компонент, и из него дергать нужные вызовы. Вот описание: http://docs.joomla.org/Absolute_Basics_of_How_a_Component_Functions
Как я понимаю, компонент ты запускаешь обращением через браузер к сайту, указав нужный URL.
Также, можно попробовать вариант написать внешний скрипт (это может быть CLI скрипт или скрипт работающий через веб-сервер и браузер) для взаимодействия с Джумлой.
Общая схема работы обычно такая: твой скрипт загружает ядро CMS (бутстрапит ее), а затем вызвыает какие-то функции или методы, которые тебе нужны. В Друпале например есть функция bootsrap() для этого, наверно и в Джумле что-то должно быть. Вот пример чего-то подобного:
http://stackoverflow.com/questions/24030499/bootstrapping-joomla-2-5-from-an-external-script
http://kurund.com/blog/2012/08/20/how-to-bootstrap-or-initialize-joomla-environment-in-external-script/
Также у некоторых CMS есть АПИ для удаленного доступа на основе XMLRPC (например у Вордпресса). То есть в этом случае ты подключаешь библиотеку, поддерживающую XMLRPC и ей из своего скрипта шлешь запросы. Но у Джумлы вроде нет такого API.
Так что остаются варианты 1 и 2. После того как ты получишь доступ к ядру Джумлы, ты можешь вызывать любые нужные функции. Как найти функцию, отвечающую за создание меню? 1) нагуглить 2) открыть исходники нужного модуля и посмотреть как там сделано.
Вот пример добавления статьи: http://stackoverflow.com/a/12644433
Вот меню (код там непонятный, я бы на всякий случай почитал документацию): http://stackoverflow.com/questions/12651075/programatically-create-menu-item-in-joomla
> Для php реально создать gui,
Обычно делают веб-интерфейс то есть gui в виде страницы в браузере с кнопками.
К базе данных ты можешь подключиться и в обход Джумлы, но сначала стоит поискать какое-нибудь АПИ. Лезть напрямую — очень опасно так как ты можешь забыть изменить какое-то поле и все сломается или будет глючить и уйдет куча времени на отладку. Официальное АПИ всегда лучше.
Во-первых, можно сделать компонент, и из него дергать нужные вызовы. Вот описание: http://docs.joomla.org/Absolute_Basics_of_How_a_Component_Functions
Как я понимаю, компонент ты запускаешь обращением через браузер к сайту, указав нужный URL.
Также, можно попробовать вариант написать внешний скрипт (это может быть CLI скрипт или скрипт работающий через веб-сервер и браузер) для взаимодействия с Джумлой.
Общая схема работы обычно такая: твой скрипт загружает ядро CMS (бутстрапит ее), а затем вызвыает какие-то функции или методы, которые тебе нужны. В Друпале например есть функция bootsrap() для этого, наверно и в Джумле что-то должно быть. Вот пример чего-то подобного:
http://stackoverflow.com/questions/24030499/bootstrapping-joomla-2-5-from-an-external-script
http://kurund.com/blog/2012/08/20/how-to-bootstrap-or-initialize-joomla-environment-in-external-script/
Также у некоторых CMS есть АПИ для удаленного доступа на основе XMLRPC (например у Вордпресса). То есть в этом случае ты подключаешь библиотеку, поддерживающую XMLRPC и ей из своего скрипта шлешь запросы. Но у Джумлы вроде нет такого API.
Так что остаются варианты 1 и 2. После того как ты получишь доступ к ядру Джумлы, ты можешь вызывать любые нужные функции. Как найти функцию, отвечающую за создание меню? 1) нагуглить 2) открыть исходники нужного модуля и посмотреть как там сделано.
Вот пример добавления статьи: http://stackoverflow.com/a/12644433
Вот меню (код там непонятный, я бы на всякий случай почитал документацию): http://stackoverflow.com/questions/12651075/programatically-create-menu-item-in-joomla
> Для php реально создать gui,
Обычно делают веб-интерфейс то есть gui в виде страницы в браузере с кнопками.
Верно, не стоит замыкаться в себе и мучаться. Стоит зайти в тред, покзать код написать в каком месте затык и получить подсказку.
и живительных пиздюлей
Сейчас попробовал напрямую рандомный контент добавить к таблице - все равно вопросительные знаки. При том, то что я добавляю к базе через сайт показывается нормально. ЧОМУТАК.
http://jsbin.com/hecahuzenuwi/1/edit - посмотри, мб что-то сможешь уже сказать. Я вообще не понимаю зачем здесь наследование и в чем его польза. А если и надо, то что оно должно делать?
http://ideone.com/t0J0I2
Я вот так сделал. Проследил как сама джумла добавляет материал и заюзал уже у нее имеющиеся возможности.
http://ideone.com/7U2zjv
А тот js-ный скрипт допилил, когда время прижало на работе.
Я бы хотел расширить sublimetext. Вот я редактирую код, потом нажимаю сочетание клавиш, и на фтпшник заливается этот файл с кодом, далее запускается этот скрипт и в джумле появляется статья. Или забить на это дело. Не знаю.
Поиск по тегам на js не доделал, но я уже сделанный код потерял. Он где то в предыдущих тредах.
Оп, хочу задание на php какое-нибудь, чтобы расширило понимание CMS, самой сути работы CMS. Джумлы например, т.к. я в ней теперь хотя бы не теряюсь.
И что там с Yii2 ?? Стоит его учить?
http://savecode.ru/codes/68
http://php.net/manual/ru/pdo.lastinsertid.php
Ну а вообще в зависимости от того, как именно ты в PDO запрос делаешь можно и по другому узнать
>Оп, почему после slim`а и yii ты рекомендуешь учить именно Symphony2 ??
Потому что это самый грамотный фреймворк на сегодняшний день. В нем все сделано умно и так, что почти не доебешься. Все остальные нервно посасывают пиписю
Вообще задавайте вопросы лол, может я тут поселюсь
переписываю odesk.com на симфони2-кун
Что в нем монструозного? Мегабайты на диске экономишь? Один из самых самых модульных фреймворков эва. Все, что хочешь можешь заменить, убрать, перетрясти этот конструктор как хочешь, а не то что один класс к другому гвоздями прибит.
В общем, влюот чтоб без кукареку, называешь "монструозную" часть и лучше сделанную альтернативу. А то перднут в лужу и думают, что под умного закосили.
Я не говорю, что он идеален, но для среднебольших проектов альтернатив такого уровня нет
Блоять, пик забыл.
Передавать в конструктор тип вывода, в методах возвращать ->output($data) где приводить данные к нужному типу? Не по объектному это как-то...
Проверяй, что все верно настроено: utf-8 в таблицах, utf-8 как кодировка соединения (ну или что ты там используешь).
Изучай
http://phpfaq.ru/charset
http://www.tmanager.ru/russian/charset.html
http://fstrange.ru/coder/mysql/kodirovka-krakozyably.html
http://gahcep.github.io/blog/2013/01/05/mysql-utf8/
>>387656
> Я вообще не понимаю зачем здесь наследование и в чем его польза. А если и надо, то что оно должно делать?
Наследование служит 2 целям:
1) показать (другим людям которые будут читать код) что классы связаны, они имеют что-то общее. В данном случае общее — что это классы объектов, которые можно подключать к электросети. То есть и Дом и Электростанцию можно подключить к электросети (а другие классы, не наследующиеся от базового — нельзя) — в этом они похожи, но при этом это разные классы с разными свойствами.
Ты можешь даже поставить проверку в ElectricNetwork.prototype.addNewElement:
if (!(element instanceof SomeClass)) {
throw new Error("You can only add objects inheriting SomeClass");
}
2) вынести общий код их классов-наследников и избавиться от копипасты. Очень странно если ты наследуешь классы, но общего кода у них нет. Это значит что ты скорее всего что-то сделал неверно. В данном случае общий для всех метод — посчитатьВкладВбаланс()
Это классический пример когда надо применить наследование — когда мы имеем однотипные сущности.
> ElementsNetwork.prototype.getContribution = function(power) {
> this.contribution.push(power);
Это какой-то странный метод - называется getSomething но ничего не возвращает, а вместо этого что-то делает с массивом.
> Powerhouse.prototype = Object.create(ElementsNetwork.prototype);
Тут еще стоит проставлять свойство constuctor. Так как раньше Powerhouse.prototype.constructor указывал на Powerhouse а сейчас ты переписал это свойство. Не то чтобы его кто-то использует, но лучше сохранять его значение.
Определения классов не стоит перемешивать. Должно быть так:
function Powerhouse(generatedPower) {...
Powerhouse.prototype = .....
function SolarPanel(generatedPower) {
SolarPanel.prototype = ...
В конструкторе класса-наследника надо вызвать конструктор предка (сам он не вызовется). Даже если конструктор пустой, вызвать надо так как может позже мы захотим туда что-то вписать.
Ну и что касается функций подсчета потребления/выработки энергии. Так как у нас есть 2 периода — ночь и день — то очевидно надо передавать туда параметр, показывающий какой период нас интересует.
Проверяй, что все верно настроено: utf-8 в таблицах, utf-8 как кодировка соединения (ну или что ты там используешь).
Изучай
http://phpfaq.ru/charset
http://www.tmanager.ru/russian/charset.html
http://fstrange.ru/coder/mysql/kodirovka-krakozyably.html
http://gahcep.github.io/blog/2013/01/05/mysql-utf8/
>>387656
> Я вообще не понимаю зачем здесь наследование и в чем его польза. А если и надо, то что оно должно делать?
Наследование служит 2 целям:
1) показать (другим людям которые будут читать код) что классы связаны, они имеют что-то общее. В данном случае общее — что это классы объектов, которые можно подключать к электросети. То есть и Дом и Электростанцию можно подключить к электросети (а другие классы, не наследующиеся от базового — нельзя) — в этом они похожи, но при этом это разные классы с разными свойствами.
Ты можешь даже поставить проверку в ElectricNetwork.prototype.addNewElement:
if (!(element instanceof SomeClass)) {
throw new Error("You can only add objects inheriting SomeClass");
}
2) вынести общий код их классов-наследников и избавиться от копипасты. Очень странно если ты наследуешь классы, но общего кода у них нет. Это значит что ты скорее всего что-то сделал неверно. В данном случае общий для всех метод — посчитатьВкладВбаланс()
Это классический пример когда надо применить наследование — когда мы имеем однотипные сущности.
> ElementsNetwork.prototype.getContribution = function(power) {
> this.contribution.push(power);
Это какой-то странный метод - называется getSomething но ничего не возвращает, а вместо этого что-то делает с массивом.
> Powerhouse.prototype = Object.create(ElementsNetwork.prototype);
Тут еще стоит проставлять свойство constuctor. Так как раньше Powerhouse.prototype.constructor указывал на Powerhouse а сейчас ты переписал это свойство. Не то чтобы его кто-то использует, но лучше сохранять его значение.
Определения классов не стоит перемешивать. Должно быть так:
function Powerhouse(generatedPower) {...
Powerhouse.prototype = .....
function SolarPanel(generatedPower) {
SolarPanel.prototype = ...
В конструкторе класса-наследника надо вызвать конструктор предка (сам он не вызовется). Даже если конструктор пустой, вызвать надо так как может позже мы захотим туда что-то вписать.
Ну и что касается функций подсчета потребления/выработки энергии. Так как у нас есть 2 периода — ночь и день — то очевидно надо передавать туда параметр, показывающий какой период нас интересует.
> 'catid' => 3, //newsarticles
Учти что это не очень надежно, вписывать id так как на другом сайте/инсталляции могут быть другие id и надо за ними следить. Может лучше как-то по названию искать было?
> Я бы хотел расширить sublimetext. Вот я редактирую код, потом нажимаю сочетание клавиш, и на фтпшник заливается этот файл с кодом, далее запускается этот скрипт и в джумле появляется статья. Или забить на это дело. Не знаю.
Тут есть 2 варианта:
1) Sublime позволяет писать плагины на Питоне. Надо знать хотя бы основы Питона (он простой, но все же).
2) Sublime может по нажатию клавиши вызывать внешний скрипт. Это может быть cmd-скрипт (под Windows), или bash-скрипт (под Линукс либо под Windows c установленным Cygwin). Так как я знаю bash то я бы выбрал этот путь. заливал бы скрипт по SFTP и запускал через SSH.
А еще это может быть PHP-скрипт для командной строки.
Вот способ: http://stackoverflow.com/a/10466565
> и на фтпшник заливается этот файл с кодом, далее запускается этот скрипт и в джумле появляется статья.
Вообще, ты бы мог написать скрипт на PHP для CLI, который зальет файл и что-то там запустит. Чтобы работать с FTP из PHP есть разные ftp-клиенты ( http://www.google.ru/search?sourceid=chrome&ie=UTF-8&q=ftp+class+client+php ) а также расширение ftp http://php.net/manual/ru/book.ftp.php
Но что касается создания статей, этот подход годится только если статей много и они создаются как-то автоматически — иначе ты больше времени на написание и отладку скрипта потратишь.
> сделанный код потерял
Надо было на гитхаб заливать или хотя бы аккаунт на сайтах вроде jsbin заводить — там наверно код сохраняется.
> 'catid' => 3, //newsarticles
Учти что это не очень надежно, вписывать id так как на другом сайте/инсталляции могут быть другие id и надо за ними следить. Может лучше как-то по названию искать было?
> Я бы хотел расширить sublimetext. Вот я редактирую код, потом нажимаю сочетание клавиш, и на фтпшник заливается этот файл с кодом, далее запускается этот скрипт и в джумле появляется статья. Или забить на это дело. Не знаю.
Тут есть 2 варианта:
1) Sublime позволяет писать плагины на Питоне. Надо знать хотя бы основы Питона (он простой, но все же).
2) Sublime может по нажатию клавиши вызывать внешний скрипт. Это может быть cmd-скрипт (под Windows), или bash-скрипт (под Линукс либо под Windows c установленным Cygwin). Так как я знаю bash то я бы выбрал этот путь. заливал бы скрипт по SFTP и запускал через SSH.
А еще это может быть PHP-скрипт для командной строки.
Вот способ: http://stackoverflow.com/a/10466565
> и на фтпшник заливается этот файл с кодом, далее запускается этот скрипт и в джумле появляется статья.
Вообще, ты бы мог написать скрипт на PHP для CLI, который зальет файл и что-то там запустит. Чтобы работать с FTP из PHP есть разные ftp-клиенты ( http://www.google.ru/search?sourceid=chrome&ie=UTF-8&q=ftp+class+client+php ) а также расширение ftp http://php.net/manual/ru/book.ftp.php
Но что касается создания статей, этот подход годится только если статей много и они создаются как-то автоматически — иначе ты больше времени на написание и отладку скрипта потратишь.
> сделанный код потерял
Надо было на гитхаб заливать или хотя бы аккаунт на сайтах вроде jsbin заводить — там наверно код сохраняется.
> Оп, хочу задание на php какое-нибудь, чтобы расширило понимание CMS, самой сути работы CMS. Джумлы например, т.к. я в ней теперь хотя бы не теряюсь.
Суть работы CMS — возможность создавать сайт через админку, с помощью кнопочек а не написания кода. Для этого обычно CMS предоставляет админку для редактирования базы данных и обеспечивает вывод контента из этой базы на сайте.
С заданием такая штука. Задание я придумать, конечно, могу, но не уверен, что это то, но что стоит тратить время. CMS, а в особенности Джумла, красивой архитектурой не блещут, они состоят из велоспедов, костылей и странных решений, пишут их тоже весьма странные в плане уровня знания программирования люди, и полезному они вряд ли научат (полезному учат фремйворки и продвинутые ООП-библиотеки). Ну и если уж брать CMS то стоило бы брать что-нибудь поизвестнее и попрямее вроде Вордпресса или Друпала.
Задач на CMS может быть 2 вида: сделать шаблон (тему оформления) или плагин (расширение, компонент). Темы делать наверно не очень интересно, потому если ты так хочешь, то сделай например такую вещь: расширение «карта». После его установки в админке редактирования статьи появляется поле «адрес». Если туда ввести какой-то адрес, то при просмотре статьи под ней будет выведена Яндекс-карта с отмеченным адресом. Например, таким образом можно отметить на карте где расположен магазин.
А оп растет на глазах!
Еще полгода назад все фреймворки были говном и хорошими были его самописные велосипеды, а теперь вот как стало, респект таким парням
Тут такие причины:
— он может многому научить в плане архитектуры, паттернов и ООП. Тут и DI, и ORM (доктрина), и разбиение на бандлы, и роутер нормальный есть, и YML, и Twig — много полезного. И он на голову выше в этом плане чем тот же Yii.
— к нему есть документация и хороший гайд (создание сайта за 24 урока)
— он популярен. Если в 1-х версиях ZF1 был популярнее Symfony1 то во второй версии, наоборот, Симфони оказался впереди. Многие проекты его используют.
— на компонентах Симфони строят другие фреймворки, например микрофреймворк Silex
Насчет остальных:
> Zend?
ZF1 был популярным, но он все же понемного устаревает. А с ZF2 я не очень знаком, он неплохой, но вроде усложненный и не так популярен как Симфони
> Laravel
Из того что я вижу (в доках), там решили пойти каким-то своим странным путем и напридумывали велосипедов. Ну и использование статических методов меня огорчает. И шаблонизатор не нравится. Подчеркивания в именах (которые не совместимы со стандартом PSR) — тоже, их скорее всего используют только из-за предпочтений авторов.
В общем, не очень с точки зрения архитектуры (я много лет назад похожие велосипеды на статических методах писал). Но я знаю, кто-то его использует.
> Codeignitier
Старье же. Как я понимаю, он напоминает Yii, только старше и меньше возможностей.
> Yii2
По идее он лучше Yii тем что там сделали совместимость с композером, сделали локализацию на основе стандартного PHP расширения, а не велосипеда, еще что-то подправили, но он пока не так популярен какпеврый Юи, потому я советую начинать с первого. Если ты знаешь Yii 1, то тебе достаточно будет посмотреть список отличий наверно, радикально там вроде ничего не менялось.
Тут такие причины:
— он может многому научить в плане архитектуры, паттернов и ООП. Тут и DI, и ORM (доктрина), и разбиение на бандлы, и роутер нормальный есть, и YML, и Twig — много полезного. И он на голову выше в этом плане чем тот же Yii.
— к нему есть документация и хороший гайд (создание сайта за 24 урока)
— он популярен. Если в 1-х версиях ZF1 был популярнее Symfony1 то во второй версии, наоборот, Симфони оказался впереди. Многие проекты его используют.
— на компонентах Симфони строят другие фреймворки, например микрофреймворк Silex
Насчет остальных:
> Zend?
ZF1 был популярным, но он все же понемного устаревает. А с ZF2 я не очень знаком, он неплохой, но вроде усложненный и не так популярен как Симфони
> Laravel
Из того что я вижу (в доках), там решили пойти каким-то своим странным путем и напридумывали велосипедов. Ну и использование статических методов меня огорчает. И шаблонизатор не нравится. Подчеркивания в именах (которые не совместимы со стандартом PSR) — тоже, их скорее всего используют только из-за предпочтений авторов.
В общем, не очень с точки зрения архитектуры (я много лет назад похожие велосипеды на статических методах писал). Но я знаю, кто-то его использует.
> Codeignitier
Старье же. Как я понимаю, он напоминает Yii, только старше и меньше возможностей.
> Yii2
По идее он лучше Yii тем что там сделали совместимость с композером, сделали локализацию на основе стандартного PHP расширения, а не велосипеда, еще что-то подправили, но он пока не так популярен какпеврый Юи, потому я советую начинать с первого. Если ты знаешь Yii 1, то тебе достаточно будет посмотреть список отличий наверно, радикально там вроде ничего не менялось.
> protected function add($add_fields)
массивы? Может стоит класс-сущность Band запилить?
Если использовать паттерн DataMapper ( http://design-pattern.ru/patterns/data-mapper.html ), то можно сделать 2 класса:
Band — объект, соответствующий 1 группе
BandMapper — объект, умеющий сохранять/загружать группы в БД
Ну и конечно ты бы мог не изобретать велосипед а использовать какой-нибудь фреймворк. В ZF есть TableGateway, в Symfony есть ORM, в Yii есть что-то напоминающее ActiveRecord для работы с БД.
> $error_array = $this->db->errorInfo();
> if($this->db->errorCode() != 0000)
Не надо обрабатывать ошибки. Поставь для PDO ERRMODE_EXCEPTION http://php.net/manual/ru/pdo.error-handling.php и забудь про эти if
>>387744
> переписываю odesk.com
Ты или твои семпаи сеньоры Джоэла не читали? http://habrahabr.ru/post/219651/ (оригинал http://www.joelonsoftware.com/articles/fog0000000069.html )
>создание сайта за 24 урока
нету такого
>Юи
БЛЯТЬ СУКА МЕНЯ АЖ ТРИСЕТ
Yii произносится как [ii:], то бишь ИИ
Где вы, обезьяны, Ю там находите?
Некая громоздкость конечно есть, если бы PHP не перезапускался на каждый запрос, проблем бы особых не было, а так приходится там какие-то кеши изобретать и т д.
Ну и ORM тоже отдельная песня. Очень противоречивая штука. С одной стороны, красивый концепт, что ты можешь просто работать с объектным графом, а хитрая библиотека сама оптимальным образом подгрузит нужные данные, с другой стороны там столько ограничений и недостатков. Сериализовать так просто нельзя, наследовать так просто нельзя, частично подгружать данные нельзя, запросы неидеальные, подгрузить часть связанных данных (первые 3 коммента к посту) нельзя. Если ты попробуешь обрабатывать тысячи сущностей, потребление памяти пробьет небеса и тебе придется переписывать на странный цикл с ручным освобождением сущностей. Тут конечно виноваты и особенности PHP, но все равно как-то не очень иделально получается.
> но для среднебольших проектов альтернатив такого уровня нет
Велосипеды, либо использовать только часть фреймворка, а остальное писать самим. С ростом нагрузки некоторые так делают.
>>387814
Читать стоит. Раз пишут что можно значит можно, если все разработчики понимают русский и планов их менять нет, то почему бы и нет. Мнение местных клоунов (особенно из других тредов) можно вообще смело игнорировать.
Ну так от тебя же пердолиться с кешем не требуется, он сам себе клеится и тебя не трогает. Производительность ядра на уровне с остальными, более 'легкими' фреймворками, если в режиме prod
>наследование
Орм привязана к таблице. Как ты себе представляешь наследование таблиц в MySQL?
>неидеальные запросы
ОРМ не создана для того, чтобы 'идеальные' запросы делать. Она добавляет слой абстракции, что заметно упрощает жизнь, но немного связывает руки. Глядя на код 99% пиэйчпи программистов, доктрина пишет запросы лучше и работают они быстрее.
Чаще всего щебетание про громоздкость слышу от тех, кто di не понимает, compilerpath-ы эти, вот это все. Как следствие, не понимают, как работают чужие бандлы и вообще фреймворк и говорят о монструозности фреймворка, вместо того, чтобы признать миниатюрность своего мозга
Ты меня с кем-то путаешь.
>>387893
> создание сайта за 24 урока
http://symfony.in.ua/symfony2-jobeet-tutorial.html
http://symfony.in.ua/creating-blog-symfony2-symblog-tutorial.html
Их там не ровно 24, 24 урока было в оригинальном туториале для Симфони 1: http://symfony.com/legacy/doc/jobeet/1_4/ru/01?orm=Doctrine но какая разница?
> Юи
Мне так больше нравится из-за пикрелейтед
>Ты меня с кем-то путаешь.
Да ладно тебе, дурачка не включай
Когда тред был по счету 17 или что-то около того, ты говорил, что фреймворки говно и писать надо исключительно свои велосипеды, тебя еще за это многократно головой в парашу окунали, видимо сработало, глядишь через пару месяцев и юнит-тесты говном ненужным быть перестанут. Они же все еще ненужны, да?
> Как ты себе представляешь наследование таблиц
Так же как Фаулер:
http://design-pattern.ru/patterns/single-table-inheritance.html
http://design-pattern.ru/patterns/class-table-inheritance.html
http://design-pattern.ru/patterns/concrete-table-inheritance.html
Ну и Ява тоже это умеет: http://blog.xebia.com/2009/06/21/jpa-implementation-patterns-mapping-inheritance-hierarchies/
Если уж на то пошло, может быть несколько похожих (но не одинаковых) сущностей в разных таблицах. Тут наследование помогло бы.
Ну и что касается ORM, абстракции это хорошо но если у тебя где-то больше нескольких десятков-сотен сущностей, то скорее всего от абстракций придется отказываться.
> Чаще всего щебетание про громоздкость слышу от тех, кто di не понимает, compilerpath-ы эти, вот это все.
Я понимаю, но мне все равно многое не нравится. И DI у них не такой и идеальный, надо вручную прописывать аргументы для конструктора в то время, как ZF2 умеет сам их по тайп хинтам находить например (может конечно и в Симфони такое есть, а я не знал).
А насчет громоздкости — это тоже есть, когда приодится всякие длинные конструкции писать:
> return $this->render('EnsJobeetBundle:Job:show.html.twig', array(
(кстати, эта особенность — возвращать response из контроллера — мне не нравится, в ZF ничего возвращать не надо, там по умолчанию шаблон соответствует имени экшена).
Все же convention over configuration имхо лучше - меньше копипасты надо делать.
> compilerpath-ы эти, вот это все.
CompilerPass? Мне название кажется странным и неудачным.
> Как ты себе представляешь наследование таблиц
Так же как Фаулер:
http://design-pattern.ru/patterns/single-table-inheritance.html
http://design-pattern.ru/patterns/class-table-inheritance.html
http://design-pattern.ru/patterns/concrete-table-inheritance.html
Ну и Ява тоже это умеет: http://blog.xebia.com/2009/06/21/jpa-implementation-patterns-mapping-inheritance-hierarchies/
Если уж на то пошло, может быть несколько похожих (но не одинаковых) сущностей в разных таблицах. Тут наследование помогло бы.
Ну и что касается ORM, абстракции это хорошо но если у тебя где-то больше нескольких десятков-сотен сущностей, то скорее всего от абстракций придется отказываться.
> Чаще всего щебетание про громоздкость слышу от тех, кто di не понимает, compilerpath-ы эти, вот это все.
Я понимаю, но мне все равно многое не нравится. И DI у них не такой и идеальный, надо вручную прописывать аргументы для конструктора в то время, как ZF2 умеет сам их по тайп хинтам находить например (может конечно и в Симфони такое есть, а я не знал).
А насчет громоздкости — это тоже есть, когда приодится всякие длинные конструкции писать:
> return $this->render('EnsJobeetBundle:Job:show.html.twig', array(
(кстати, эта особенность — возвращать response из контроллера — мне не нравится, в ZF ничего возвращать не надо, там по умолчанию шаблон соответствует имени экшена).
Все же convention over configuration имхо лучше - меньше копипасты надо делать.
> compilerpath-ы эти, вот это все.
CompilerPass? Мне название кажется странным и неудачным.
Не было такого или ты не так понял. Уж я бы точно не стал такое советовать другим.
А насчет юнит-тестов — я уже писал, что мне в них не нравится
— попробуй оценить объем тестов для среднего проекта, если делать их не как попало, а тщательно, по всем правилам, то они будут код по объему превышать в несколько раз, так как одну функцию можно вызвать с кучей разных параметров. Если функция получает на вход объект с 20 полями, все становится еще сложнее. И помножь это на число функций. Те, кто говорят что это не проблема, скорее всего их делают не тщательно, а кое-как. Мы получаем замедление разработки.
— многие классы трудно тестировать. Как тестировать контроллеры, где логики мало и она шаблонная, а взаимодействия с другими классами много? надо писать кучу моков. Как тестировать HTML+JS-интерфейсы?
— многие вещи тестировать сложно. Есть функция сохранения поста в БД, как ее тестировать? Проверить, что она вызовет метод execute у мока соединения с БД? А где гарантия что она передала правильный запрос с правильными аргументами?
— тесты надо переписывать при изменениях в коде. Никто не любит удваивать-утраивать объем работы, и в итоге люди начинают вместо изменений пристраивать обертки на обертке.
При этом я не говорю, что тесты не нужны. Конечно нужны, но не юнит-тесты, а функциональные, интерфейсыные — то есть то, что позволяет заменить живых тестировщиков. А юнит-тесты нужны только там где есть хитрая логика — всякие оптимизаторы, парсеры текста (напр. парсер телефонных номеров в тексте), и т.д, то есть там где затраты на написание невысоки, а объем проверяемой логики высок. Тестировать однотипные контроллеры/модели/вью смысла нет.
В общем, тут надо подходить с точки зрения бизнеса, сопоставить затраты и выгоду. А не с точки зрения аутиста «каждая строка должна быть покрыта тестами».
>Если уж на то пошло, может быть несколько похожих (но не одинаковых) сущностей в разных таблицах. Тут наследование помогло бы.
https://github.com/doctrine/doctrine2 - вперед
>И DI у них не такой и идеальный, надо вручную прописывать аргументы для конструктора в то время, как ZF2 умеет сам их по тайп хинтам находить например (может конечно и в Симфони такое есть, а я не знал).
>возвращать response из контроллера — мне не нравится
> имхо лучше - меньше
> Мне название кажется странным и неудачным.
https://github.com/symfony/symfony - покажи класс
Языком пиздеть, это не мешки ворочать
Возвращать вьюху из контроллера - это для уменьшения связности. Ты можешь не возвращать вьюху, а возврашать например число, и запрашивать его через API, или сабреквестом встраивать в текущую страницу. Если бы оно "само" определяло вьюху и рисовало ее, пришлось бы изъябываться.
Передавать вручную параметры в DI тоже неплохо, так как может быть 2 разных сервиса одного типа например (логер ошибок и логер пользовательских действий например)
В общем, пока тебе еще надо растишку кушать, но прогресс есть, одобряю
>Как тестировать HTML+JS-интерфейсы?
ты же пошутил, правда?
вот прямо эту строку забивай в гугл - многое узнаешь
>многие классы трудно тестировать.
потому что плохой код трудно тестировать, хороший легко.
Если у тебя в основном плохой, кто ж виноват?
>многие вещи тестировать сложно. Есть функция сохранения поста в БД, как ее тестировать? Проверить, что она вызовет метод execute у мока соединения с БД? А где гарантия что она передала правильный запрос с правильными аргументами?
Лол, transaction->begin + transaction->rollback и можно без моков
>— тесты надо переписывать при изменениях в коде. Никто не любит удваивать-утраивать объем работы, и в итоге люди начинают вместо изменений пристраивать обертки на обертке.
Это плохой код и тесты, если их надо прямо часто переписывать
>Как тестировать контроллеры, где логики мало и она шаблонная, а взаимодействия с другими классами много?
Не писать контроллеры, где много взаимодейтсвия с другими классами, нэ?
Ну и контроллеры обычно функциональными тестами покрываются в том же phpunit, у всех фреймвокрков есть методы а-ля $this->dispatch(<url>), и можно даже ничего не мокать там
Ты блять код нормальный покажи, а не твои какие-то фантазии.
Создай пулл-реквест к симфони, где сделаешь как надо контроллеры и наследование в доктрине, а посоны будут пользоваться хорошим кодом, а не неидельным симфони
Я серьезно, ты можешь не полотна словоблудия выдавать, а альтернативные, лучшие как ты считаешь, реализации ORM и компонентов фреймворка?
> Если у тебя в основном плохой, кто ж виноват?
Ты не видел, а говоришь что плохой. В любом случае, тесты должны подстраиваться под код, а не код под тесты.
Ну и тот факт что ты так защищаешь эти юнит тесты намекает на то что ты либо их не пишешь либо пишешь кое-как и думаешь что это правильно.
> Лол, transaction->begin + transaction->rollback и можно без моков
Почитай определение юнит-теста. Юнит-тесты не взаимодействуют с настоящей БД, на то они и юнит тесты. Если говорить простым языком, юнит-тест — это тест компонента, например датчика температуры в топливном баке, без использования самого бака и топлива.
И смысла писать тест для такой простой функции нет. Она прекрасно покрывается тестом создания поста через интерфейс.
> Это плохой код и тесты, если их надо прямо часто переписывать
Это плохие тесты. Код не должен подстраиваться и писаться под тесты, код должен писаться для решения задачи. Если для решения задачи надо отрефакторить несколько классов, значит надо.
> Не писать контроллеры, где много взаимодейтсвия с другими классами, нэ?
Может вообще код не писать?
> у всех фреймвокрков есть методы а-ля $this->dispatch(<url>), и можно даже ничего не мокать там
Это бесполезные тесты скорее всего так как контроллер сам ничего не делает, и логики в нем минимум - он лишь управляет процессом
> ты можешь не полотна словоблудия выдавать, а альтернативные, лучшие как ты считаешь, реализации ORM и компонентов фреймворка?
Конечно могу, но не хочу. Написать реализацию ORM — это дело не на 5 минут, с чего бы я стал тратить время на это? Мне от этого профита никакого.
>Мне от этого профита никакого.
А от пиздежа от твоего какой профит?
>Ты не видел, а говоришь что плохой
Так ты ж не показываешь. Посоны ждут наследования таблиц в доктрине. Или просто хотя бы наследования таблиц
> В любом случае, тесты должны подстраиваться под код, а не код под тесты.
Никто ни под кого подстраиваться не должен. Код должен в первую очередь по SOLIDу писаться, тогда и с тестированием его проблем не будет.
>Ну и тот факт что ты так защищаешь эти юнит тесты намекает на то что ты либо их не пишешь либо пишешь кое-как и думаешь что это правильно.
Я не защищаю юнит-тесты, я против самодурства.
Полгода назад оно в твоих тредах было, а именно "Пишите велосипеды, в жопу тесты".
>И смысла писать тест для такой простой функции нет. Она прекрасно покрывается тестом создания поста через интерфейс.
Только вот беда, если тестировать не код, а интерфейс (именно он в этом случае тестируется), на это нужно в разы больше случаев, и выполняются эти тесты по пол-дня на нормальных проектах. А рефакторить и программировать нужно постоянно, а не раз в 4 часа.
>Это плохие тесты.
Я ж не спорю. Плохими могут быть и тесты и код одновременно, даже скорее всего если код плохой, то и тесты плохие, где противоречие?
>Код не должен подстраиваться и писаться под тесты, код должен писаться для решения задачи. Если для решения задачи надо отрефакторить несколько классов, значит надо.
Так тесты чем мешают? Тесты как раз помогут отрефакторить и убедиться, что все по прежнему работает.
>Это бесполезные тесты скорее всего так как контроллер сам ничего не делает, и логики в нем минимум - он лишь управляет процессом
Так а чем твое тестирование интерфейса отличается от диспатча контроллера? Тем, что работает в браузере и медленно?
Ну и да
>Юнит-тесты не взаимодействуют с настоящей БД, на то они и юнит тесты.
Тогда ответ на вопрос
>Проверить, что она вызовет метод execute у мока соединения с БД? А где гарантия что она передала правильный запрос с правильными аргументами?
Да. Проверить можно не только вызов метода, но и входные параметры тоже кстати.
>Может вообще код не писать?
Так а ты его пишешь вообще?
>Мне от этого профита никакого.
А от пиздежа от твоего какой профит?
>Ты не видел, а говоришь что плохой
Так ты ж не показываешь. Посоны ждут наследования таблиц в доктрине. Или просто хотя бы наследования таблиц
> В любом случае, тесты должны подстраиваться под код, а не код под тесты.
Никто ни под кого подстраиваться не должен. Код должен в первую очередь по SOLIDу писаться, тогда и с тестированием его проблем не будет.
>Ну и тот факт что ты так защищаешь эти юнит тесты намекает на то что ты либо их не пишешь либо пишешь кое-как и думаешь что это правильно.
Я не защищаю юнит-тесты, я против самодурства.
Полгода назад оно в твоих тредах было, а именно "Пишите велосипеды, в жопу тесты".
>И смысла писать тест для такой простой функции нет. Она прекрасно покрывается тестом создания поста через интерфейс.
Только вот беда, если тестировать не код, а интерфейс (именно он в этом случае тестируется), на это нужно в разы больше случаев, и выполняются эти тесты по пол-дня на нормальных проектах. А рефакторить и программировать нужно постоянно, а не раз в 4 часа.
>Это плохие тесты.
Я ж не спорю. Плохими могут быть и тесты и код одновременно, даже скорее всего если код плохой, то и тесты плохие, где противоречие?
>Код не должен подстраиваться и писаться под тесты, код должен писаться для решения задачи. Если для решения задачи надо отрефакторить несколько классов, значит надо.
Так тесты чем мешают? Тесты как раз помогут отрефакторить и убедиться, что все по прежнему работает.
>Это бесполезные тесты скорее всего так как контроллер сам ничего не делает, и логики в нем минимум - он лишь управляет процессом
Так а чем твое тестирование интерфейса отличается от диспатча контроллера? Тем, что работает в браузере и медленно?
Ну и да
>Юнит-тесты не взаимодействуют с настоящей БД, на то они и юнит тесты.
Тогда ответ на вопрос
>Проверить, что она вызовет метод execute у мока соединения с БД? А где гарантия что она передала правильный запрос с правильными аргументами?
Да. Проверить можно не только вызов метода, но и входные параметры тоже кстати.
>Может вообще код не писать?
Так а ты его пишешь вообще?
Ну и да, ты кокой-то непоследовательный
То тебе прямой рендер контроллера хуже, чем магия в бэкграунде, и каноничная реализация DI хуже convention over configuration, то ты выступаешь борцуном за чистоту юнит-тестов, чтоб все зависимости были пустышками.
Ты уж определись, ты за качественный код, выкатывая который ты уверен, что ничего не отломалось, или я уже даже не знаю
>А от пиздежа от твоего какой профит?
Можно отвлечься от работы, поговорить с благодарными читателями.
> Посоны ждут наследования таблиц в доктрине. Или просто хотя бы наследования таблиц
Я вроде дал ссылки на 3 способа его организовать. Что еще надо?
> Только вот беда, если тестировать не код, а интерфейс (именно он в этом случае тестируется), на это нужно в разы больше случаев,
Тестируют обычно тестировщики, а не разработчики (а вот юнит-тесты надо писать самим). Так что наоборот.
Ну и что касается числа опций, обычно в GUI форма соответствует какому-то классу, сколько в ней инпутов, столько в нем полей, так что число комбинаций одинаковое. Ну и яндекс вовсю на Хабре пишет про интерфейсные тесты, а про юнит не особо (при них правда Баду пишет, у них их десятки тысяч по моему).
> Тесты как раз помогут отрефакторить и убедиться, что все по прежнему работает.
Если тесты тестируют отдельные функции, и эти функции меняются (тип аргументов, возвращаемое значение) или вообще удаляются, тесты тоже надо актуализировать. Опять же интуиция подсказывает что ты с этим мог и не сталкиваться.
> Так а чем твое тестирование интерфейса отличается от диспатча контроллера? Тем, что работает в браузере и медленно?
Гм, можно и не через браузер, разницы нет, но яваскрипт не будет поддерживаться. Насчет медленно — можно что-то придумывать с порядком тестов, например тестировать в первую очередь то что затронуто коммитом, те модули сайта.
> Проверить можно не только вызов метода, но и входные параметры тоже кстати.
Ну и бред. Ты полноценный парсер SQL писать собрался ради теста? В этой функции логики нет, потому ее проверять отдельно и не надо.
> Так а ты его пишешь вообще?
Есть такая проблема, маловато пишу, надо бы больше. Но организм сопротивляется.
Основная мысль была что функции без хитрой логики незачем тестировать, по крайней мере юнит-тестами. И что то, что ты привел в примере это не юнит-тесты.
Качественный код, это конечно хорошо, удобнее смотреть на результаты тестов чем самому проверять, но я пока еще таких (которые могут все сами проверить) тестов не видел. Больше как-то вижу код который никто уже не помнит, зачем написан, и который непонятно как работает, но если его удалить, обязательно что-то отвалится.
>Я вроде дал ссылки на 3 способа его организовать. Что еще надо?
Внатуре, пойду Фабьену скажу, что наконец решена проблема тысячилетия, нашлись священные 3 ссылки. Сча заживем посоны
>Если тесты тестируют отдельные функции, и эти функции меняются (тип аргументов, возвращаемое значение) или вообще удаляются, тесты тоже надо актуализировать. Опять же интуиция подсказывает что ты с этим мог и не сталкиваться.
А ты видно не сталкивался с проектами, которые нельзя ломать. Так вот в них рефакторинг по возможности делается так, чтобы основной интерфейс не сломать, в этом юнит-тесты и помогают
>Гм, можно и не через браузер, разницы нет, но яваскрипт не будет поддерживаться. Насчет медленно — можно что-то придумывать с порядком тестов, например тестировать в первую очередь то что затронуто коммитом, те модули сайта.
Так чем это от прямого диспатча контроллера отличается, кроме большей еботни с написанием?
>Ну и бред. Ты полноценный парсер SQL писать собрался ради теста?
Охуеть, ты данные для теста каждый раз рандомно генеришь? Если они зашиты в тест-кейсе ты ожидаешь вполне конкретный запрос, но понимаешь чо, и его проверять не надо. Если ты не пещерный человек, то используешь как-минимум query-builder примитивный, и весь запрос чекать не надо - это прочекано в самом квери-билдере. В этом-то и суть, если используешь готовые протестированные компоненты, каждый чих тестирвать не надо
Ну а если как ты, "под себя" подстраивать, тем более нетестируемым кодом, то действительно с тестами зашьешься
>>387940
Ты вот ответил на этот пост. А почитал вообще что там написано?
Ладно, хочу учиться на фреймворке. ты меня убедил. С чего начать? Только напиши подробно, с заданием каким-нибудь начального уровня. Я твои задачи в учебнике прошел.
Для чего нужны конкретно и их функции
PDO::prepare
PDO::exec
PDO::query
Ну, мне помогли эти туториалы https://www.youtube.com/watch?v=QtCdk459NFg Всё просто, отталкиваясь от них можно пилить уже что-то сложнее
>PDO
бЛЯ, ПАРСОНЫ, я конечно может неосилятор, mysqli же удобнее же, не?
В плане общего понимания и работы с базой данных.
Есть инфа, ЧТО используется PDO или MYSQLI в таких движках как WP и Drupal?
ОП, а если сделать наследование от основного класса и в зависимости от нужного формата делать экземпляр нужного класса, например SomeClassXML? Который реализует все публичные методы основного класса в виде
public function getSome($data) {
$ret = parent::getSome($data);
/ преобразуем данные как хотим/
return $xmlData;
}
из минусов вижу необходимость следить за расширением основного класса в дочерних и реализовывать новые методы.
Просто делать единый конвертор, конвертирующий данные без учета какой метод их вернул... А если мне нужно что бы вывод конкретного метода был специально переформатирован?
Вот ты говоришь в оп посте, мол, читай книги Мэтта Зандстра, а что скажешь за его книгу пикрелейт?
Она же для совсем ньюфагов, почему бы её не включить в список. Или она совсем старая?
Я хз крч.
кукаретик, объясни почему с PDO не могу получить всю таблицу?
пример http://ideone.com/5XAjy0
Тому чо ты не читал ман по ссылке
$query = $db->query('select from newsmf');
$query->setFetchMode(PDO::FETCH_ASSOC);
if ($rows = $query->fetchAll()) {
$retArray = $rows;
}
Мне кажется ты усложняешь
Я бы сделал класс для самих данных (ну то бишь обертку) и возвращал бы ее. в ней бы определил метод __toString() и еще типа xml(), json() и так далее. Ну и по канону нужно еще сделал интерфейс XMLable, JSONable, HuiPizdable и так далее, в каждом шоб был метод convertTo<formatName>
Сча кароче в ideone накидаю лучче
Идея опа с всякими утил-классами тухлая, потому что для каждого типа данных нужно будет свой метод добавлять в эти классы, получается что эти утилы явно завязаны на другие объекты данных (т.е. без этих объектов они бессмысленны). Это было модно в 2006 примерно, но сейчас так лучше не делать
Нет, та вторая книга говно
Нет, "это только для фото".
Там 4 класса - сама модель, аутентификация, форматтер вывода и роутер.
Сначала вызываем роутер, проверяем аутентификацию, определяемся по параметрам что вызвать из модели и выводим результат в заданном формате.
Анончик, а при помощи mysqli
$query = "SELECT FROM my_table";
$result = mysql_query($query);
echo $result;
я бы смог таким образом получить таблицу?
то есть использования всяких fetch? Подскажи, позязя, для дебила.
для исключений лучше свои классы, и их обрабатывать тоже выборочно, а не catch(Exception)
костыль addSlashes() не нужен совершенно
Ну и вообще грязь какая-то, я посмотрел 5 минут на твой код и голова заболела
Рекомендую тебе "Чистый код" почитать и Рефакторинги фаулера
Класс роутов - это пиздец, что апи, что реализация
Посмотри в любом фреймворке, как роутинг сделан, в той же Kohana например, или в Silex
https://github.com/silexphp/Silex/blob/master/src/Silex/Route.php
А в чем смысл этого? Это какая-то "задачка" или из живого проекта код?
идея в том, что я вызываю из модели конкретные методы, которые возвращают конкретные наборы данных. То есть selectUsers возвращает один набор данных, которые следовало бы обрабатывать в XML не так, как например результат addUser.
Пока в голову не приходит ничего умнее фабрики типа:
http://ideone.com/guwME6
Фантазии на заданную тему, разумеется.
Так в чем проблема с моим способом? Он как раз и расчитан на то, что в разных данных разный экспорт можно делать
Так ты то же самое сделал, что я сказал, только хуже.
Делай с интерфейсами и с базовой логикой, как в эту обертку засовывать данные
Спасибо, теперь условие понял. ОП глянь, что я нашлёпал.
Задача 8 http://jsbin.com/pimumevocuxa/1/edit
Задача 9 http://jsbin.com/rehewajiyuwi/1/edit
Задачу 10 решал-решал, гуглил-гуглил, но так и не осилил. То ли торможу, то ли знаний не хватает, хоть и мануалы почитываю в полглаза.
Как прижать float блок к низу родителя?
Задача 10 http://jsbin.com/surixalerino/1/edit
>>388169
>>388036
Спасибо.
Для себя долбоёба, нарыл по PDO
http://www.youtube.com/watch?v=mH1nMwEhGwM
https://ideone.com/oWltna
Я пока делаю так: если какая-то часть сайта, которую можно выделить в сущность (гостевуха там, или админка), требует несколько страниц, то помещаю её в новый контроллер, иначе кидаю в общий. Это нормально?
> Проверяй, что все верно настроено: utf-8 в таблицах, utf-8 как кодировка соединения (ну или что ты там используешь).
> Изучай
Оказалось надо было просто добавить [CODE]SET NAMES "utf8"[/CODE] после соединения с новым сервером, ибо у него серверная кодировка latin1. Спасибо, опа.
http://ideone.com/5dC96C
Оп, смотри теперь поиск по названию категории. Надо наверное форму вывести с полями: "Заголовок", "Категория", "Текст", "Доступ". И вбивать туда все статьи, а скрипт уже разделит по тегу h1 и закинет в базу.
=(
C чего открываешь? С десктопного браузера не перекидывает. Алсо, может у тебя какое вредоносное расширение в браузере стоит или троян? Может на вирусы провериться стоит?
Если с мобильной версии перекиыдвает то это юкоз виноват.
Копия сайта выложена доброаноном на http:// webmacaque . tk / архив есть тут http://rghost.net/45000175
>Головой вообще не думаешь?
Иди нахуй.
https://ru.wikipedia.org/wiki/Пассивно-агрессивное_поведение
>Я пока делаю так: если какая-то часть сайта, которую можно выделить в сущность (гостевуха там, или админка), требует несколько страниц, то помещаю её в новый контроллер, иначе кидаю в общий. Это нормально?
Ты немного не въехал в то, что такое контроллер
Контроллер - это не класс, с кучей методов для каждой страницы. Контроллер - это 1 метод, соответвтующий 1 странице/ресурсу/etc. Хуй знает откуда пошла мода называть контроллером класс, содержащий контроллеры
Апач там, еще что скачать нужно?
У меня мегафон модем (и только он), значит в этом дело. Просто раньше нормально отображалось, а лишь недавно стало перекидывать.
Спасибо, вроде без проблем открыл.
Няш, подкинь пару задачек для мидла, в твоем понимании. Проверить скилз, так сказать. Ну или понять куда мне еще расти. А то в понедельник на собеседование, а в интернете что-то только для джунов.
Подскажите в чем проблема? Выдает ошибку:
Unknown column 'field' in 'where clause'
Но поле с таким значением есть на самом деле.
Вообще, неплохо, но есть кое-какие замечания.
> $this->data = $data;
> $this->name = $data['name'];
Не надо сваливать в одну кучу (=массив) работников и название департамента. Используй 2 отдельных аргумента в конструкторе. Более того, удобнее когда можно добавлять работников постепенно, потому лучше добавить метод addEmployees(array $employees) который позволит это делать.
Босса наверно стоит хранить не в общем массиве, а в отдельном свойстве — так его будет проще поменять. И если понадобится узнать «кто босс?» — это тоже будет проще сделать.
> function workers()
Обычно принято писать public явно, то есть public function ...
> $this->data = $data;
> $this->name = $data['name'];
Эти свойства надо объявить в начале класса. А то неудобно, смотришь на класс и непонятно какие у него есть свойства. Конструктор тоже принято писать в начале, после свойств, так как с него начинается создание объекта.
> function cofee()
Названия функций начинаются с глагола: сделайЧтоТо, например getCoffeeConsumption()
> function setHead()
> $this->salary = $this->salary 1.50;
Вот тут тоже неправильно сделано. От того, что работник становится руководителем, его базовая ставка не меняется — он просто получает в 1.5 раза больше. Соответственно, правильно сделать свойство «является ли руководителем» (isHead) и учитывать его при расчете зарплаты. Плюс, в твоем случае, когда ты изменяешь значения свойств, ты не сможешь понизить работника назад в обычного служащего. А с отдельным свойством — можешь.
> $department1 = createEmployee('Manager', 1, 9, $department1);
> $department1 = createEmployee('Manager', 2, 3, $department1);
Лучше сделать возможность добавлять работников за несколько заходов, тогда не придется всюду передавать этот массив.
> while (mb_strlen($name) < $col) {
> $name .= " ";
Используй str_repeat
> $data
Вот эта переменная очень плохая, от нее надо избавиться. Почему? Потому что в ней в кучу свалено все, что можно и это никак не подходит для красивого ООП-дизайна. Вот примерно как должно быть:
департаментПродаж = новый Департамент('продаж');
департаментПродаж->добавитьРаботников(создатьРаботников(Инженер x 5));
департаментПродаж->добавитьРаботников(создатьРаботников(Маркетолог x 7));
босс = новый Инженер(3 ранга);
департаментПродаж->назначитьБосса(босс);
Также, в функции createEmployee надо сделать защиту, чтобы нельзя было передавть неправильный тип работника (например по ошибке).
Функция createDepartment($data) должна заниматься тем, что написано в названии, и не пытаться заодно что-то выводить на экран.
Размеры колонок надо поместить в переменные или массив чтобы не менять их в 2 или более местах одновременно.
Также везде, где это возможно, надо проставить тайп хинты ( http://php.net/manual/ru/language.oop5.typehinting.php ). Тайп хинты позволяют указать, что аргумент функции является массивом или объектом определенного класса. Их использование делает твой код надежнее, солиднее, понятнее, потому использовать их надо при любой возможности.
Ну и насчет публичных свойств. В этом задании их использовать можно, но в следующем надо будет перейти на private/protected свойства, которые доступны только через методы. Это тоже делает код солиднее и надежнее.
В таблице надо вывести сумму и среднее.
Вообще, неплохо, но есть кое-какие замечания.
> $this->data = $data;
> $this->name = $data['name'];
Не надо сваливать в одну кучу (=массив) работников и название департамента. Используй 2 отдельных аргумента в конструкторе. Более того, удобнее когда можно добавлять работников постепенно, потому лучше добавить метод addEmployees(array $employees) который позволит это делать.
Босса наверно стоит хранить не в общем массиве, а в отдельном свойстве — так его будет проще поменять. И если понадобится узнать «кто босс?» — это тоже будет проще сделать.
> function workers()
Обычно принято писать public явно, то есть public function ...
> $this->data = $data;
> $this->name = $data['name'];
Эти свойства надо объявить в начале класса. А то неудобно, смотришь на класс и непонятно какие у него есть свойства. Конструктор тоже принято писать в начале, после свойств, так как с него начинается создание объекта.
> function cofee()
Названия функций начинаются с глагола: сделайЧтоТо, например getCoffeeConsumption()
> function setHead()
> $this->salary = $this->salary 1.50;
Вот тут тоже неправильно сделано. От того, что работник становится руководителем, его базовая ставка не меняется — он просто получает в 1.5 раза больше. Соответственно, правильно сделать свойство «является ли руководителем» (isHead) и учитывать его при расчете зарплаты. Плюс, в твоем случае, когда ты изменяешь значения свойств, ты не сможешь понизить работника назад в обычного служащего. А с отдельным свойством — можешь.
> $department1 = createEmployee('Manager', 1, 9, $department1);
> $department1 = createEmployee('Manager', 2, 3, $department1);
Лучше сделать возможность добавлять работников за несколько заходов, тогда не придется всюду передавать этот массив.
> while (mb_strlen($name) < $col) {
> $name .= " ";
Используй str_repeat
> $data
Вот эта переменная очень плохая, от нее надо избавиться. Почему? Потому что в ней в кучу свалено все, что можно и это никак не подходит для красивого ООП-дизайна. Вот примерно как должно быть:
департаментПродаж = новый Департамент('продаж');
департаментПродаж->добавитьРаботников(создатьРаботников(Инженер x 5));
департаментПродаж->добавитьРаботников(создатьРаботников(Маркетолог x 7));
босс = новый Инженер(3 ранга);
департаментПродаж->назначитьБосса(босс);
Также, в функции createEmployee надо сделать защиту, чтобы нельзя было передавть неправильный тип работника (например по ошибке).
Функция createDepartment($data) должна заниматься тем, что написано в названии, и не пытаться заодно что-то выводить на экран.
Размеры колонок надо поместить в переменные или массив чтобы не менять их в 2 или более местах одновременно.
Также везде, где это возможно, надо проставить тайп хинты ( http://php.net/manual/ru/language.oop5.typehinting.php ). Тайп хинты позволяют указать, что аргумент функции является массивом или объектом определенного класса. Их использование делает твой код надежнее, солиднее, понятнее, потому использовать их надо при любой возможности.
Ну и насчет публичных свойств. В этом задании их использовать можно, но в следующем надо будет перейти на private/protected свойства, которые доступны только через методы. Это тоже делает код солиднее и надежнее.
В таблице надо вывести сумму и среднее.
Жаваскрипт? Можно на любое событие назначить чек у чекбокса. Чекбокс скрыть, и сделать что-то другое, чекбоксозаменитель.
Чтобы показать код — гитхаб, чтобы показать приложение — хостинг/VPS. В принципе, можно взять даже платный хостинг если там есть пробный период — на то, чтобы показать, хватит. Я вроде один раз так и сделал. Ну или бесплатный, но там может быть реклама и падения.
Или можно на том же селектеле взять облачный сервер в минимальной конфигурации и на него все поставить — он стоит в районе 140 р в месяц, причем платишь поминутно, то есть на несколько дней поднять совсем недорого.
Ну и отсутствие проекта — не такая большая проблема, часть работодатель готов дать (или ты можешь предложить сделать) тестовое задание.
>>387991
Раз прошел, то ты готов к задаче, которую мы всем даем после учебника: https://gist.github.com/codedokode/9424217 — сделай файлообменник на микрофреймворке Slim. Она заставит тебя изучить много полезных вещей, ну и главное — ты с нуля сделаешь вполне полноценный (пусть и крошечный) сайт.
Для внешнего вида можно подключить CSS-фреймворк Twitter Bootstrap.
>>388027
Вообще, эти функции описаны в мануале по php. Вбей их в гугл и попадешь туда.
> PDO::prepare
Создать запрос (после чего надо привязать к нему данные и можно выполнять)
> PDO::exec
Создать и сразу выполнить запрос без параметров, не возвращающий результаты
> PDO::query
Создать и сразу выполнить запрос без параметров, возвращающий результаты
Ошибку исправил. Всегда эти странные кавычки путают меня.
Проблема в другом теперь - ничего не заменяет. Цикл работает, проходит по всем столбцам. И проверки-то не знаю как налепить. С базами данных совсем недавно начал работать, но синтаксис больно уж простой, хотя я похоже где-то и допустил ошибку.
Посмотри, Оп, это мне для завтра надо.
>>388563
Конечно можно, для новых браузеров достаточно CSS3:
http://habrahabr.ru/post/144104/
http://habrahabr.ru/post/154719/
Для более полной поддержки надо написать яваскрипт который будет менять класс при щелчке.
>>388095
Чем удобнее? В PDO есть возможность выкидывать исключения и удобно привязывать параметры. mysqli используют те, кто взял старый 10-летний мануал по mysql и приписал там букву i.
Естественно, для использования PDO нужен ООП. Но без ООП ты все равно никуда не уедешь.
> Есть инфа, ЧТО используется PDO или MYSQLI в таких движках как WP и Drupal?
Свои велосипеды, так как они давно написаны.
>>388174
> а если сделать наследовани
Слишком усложненно. По идее ты должен возвращать рещультат в каком-то универсальном формате, из которого легко получить любой другой. Должны же быть какие-то правила преобразования. Ну или, если у тебя есть модельки, можно у них сделать метод toJson, toXml и т.д.
> А если мне нужно что бы вывод конкретного метода был специально переформатирован?
Может тебе это не так уж и нужно? Если у тебя данные не в виде тупого массива, а в виде моделек, то как я сказал, можно у них сделать метод toXml и в нем что угодно писать. Если нет, то нельзя конечно, тогда надо в getData добавлять параметр format.
>>388197
Не читал, выглядит старой и название отпугивает.
>>388563
Конечно можно, для новых браузеров достаточно CSS3:
http://habrahabr.ru/post/144104/
http://habrahabr.ru/post/154719/
Для более полной поддержки надо написать яваскрипт который будет менять класс при щелчке.
>>388095
Чем удобнее? В PDO есть возможность выкидывать исключения и удобно привязывать параметры. mysqli используют те, кто взял старый 10-летний мануал по mysql и приписал там букву i.
Естественно, для использования PDO нужен ООП. Но без ООП ты все равно никуда не уедешь.
> Есть инфа, ЧТО используется PDO или MYSQLI в таких движках как WP и Drupal?
Свои велосипеды, так как они давно написаны.
>>388174
> а если сделать наследовани
Слишком усложненно. По идее ты должен возвращать рещультат в каком-то универсальном формате, из которого легко получить любой другой. Должны же быть какие-то правила преобразования. Ну или, если у тебя есть модельки, можно у них сделать метод toJson, toXml и т.д.
> А если мне нужно что бы вывод конкретного метода был специально переформатирован?
Может тебе это не так уж и нужно? Если у тебя данные не в виде тупого массива, а в виде моделек, то как я сказал, можно у них сделать метод toXml и в нем что угодно писать. Если нет, то нельзя конечно, тогда надо в getData добавлять параметр format.
>>388197
Не читал, выглядит старой и название отпугивает.
>>388211
> Идея опа с всякими утил-классами тухлая, потому что для каждого типа данных нужно будет свой метод добавлять в эти классы, получается что эти утилы явно завязаны на другие объекты данных
Я подумал, может у анона нет моделей, а данные в виде тупого массива — тогда вариант универсальной функции (возможно с опциями) вполне работоcпособно выглядит. Не переделывать же ему весь код ради экспорта в XML.
>>388218
Вполне нормальный подход, если надо преобразование прикручивать сверху к существующей системе.
>>388206
if зачем? просто $data = $q->fetchAll(); — он всегда вернет массив (а на случай ошибки надо поставить опцию чтобы выбрасывал исключение)
Вот нашел вроде что-то сам. https://getjump.github.io/ru-php-the-right-way/
http://toster.ru/q/70082
Плохо, что ты для работы с БД изобрел велосипед, да еще и с кривыми колесами. У тебя в одном классе свалено в кучу несколько разных вещей. Вот представь, например, ты добавишь в БД вторую таблицу и захочешь с ней работать — тебе придется делать второй класс методом копипасты. Ты изобретаешь свой кривой велосипед для экранирования данных вместо использования стандартного. Запросы ты собираешь какими-то костылями, вместо того чтобы сделать например отдельный Query Builder. Проверку на уникальность ты делаешь в той же функции что и сборку запроса. Всюду массивы на массивах. Не умеешь разбивать код на функции, все пишешь одной длинной портянкой.
Для сборки запросов по частям придуман паттерн Query Builder.
Сам код — жуткий велосипед (то есть до тебя аналогичное придумывало наверно несколько сотен тысяч человек). Советую сначала посмотреть как это сделано в том же Yii или ZF (класс Zend_Db_Table) — чтобы сразу перенять полезные вещи. Особенно внимательно изучи Zend: http://framework.zend.com/manual/1.12/ru/zend.db.html (прочти весь раздел, а особенно Zend_Db_Select/Zend_Db_Table −— поверь, много нового узнаешь. Там используются паттерны Query Builder и Table Data Gateway). В Yii используется своя вариация Active Record (описания всех этих паттернов можешь нагуглить на design-pattern.ru).
> private $dbStruct = array ( 'table' => 'users',
> 'columns' => array ('id' => 'key',
Зачем сваливать все в массив, когда можно хранить просто в свойствах объекта? У тебя массиво-ориентированное программирование.
> self::$DBH
Использованием статических св-в/методов ты убиваешь все преимущества ООП так как ты не можешь например создать 2 независимых объекта. Не используй их где не надо (а где надо? для реализации паттерна UtilityClass, для реализации Singleton и может еще в паре редких случаев).
> } catch(Exception $e) {
> throw new Exception
Зачем ловить исключение чтобы сразу же его выкинуть? Изучи получше как работают ичключения и убери try/catch
> $val = addslashes($val);
Во-первых, функция addslashes не предназначена для экранирования параметров в SQL-запросах, для этого есть $pdo->quote(), во-вторых, изучи плейсхолдеры в PDO ( http://habrahabr.ru/post/137664/ ) и используй bindValue либо массив в execute. Я вижу, ниже ты их используешь — использовал бы и тут.
> public function addUser(array $data)
Лучше вместо глупого массива сделать класс-модель User соответствующую 1 пользователю и передавать везде ее.
> экранируем - необходимо, т.к. запрос сборный и мы не сможем использовать paramValue PDO
Можем. В один массив кладем сгенерированные идентификаторы (вида :value3), в другой — значения.
> throw new Exception ( "[" . __CLASS__ . "]
XDebug при исключении пишет полный стектрейс места где оно произошло и название класса писать не придется
> if (strpos($val, '') !== false) { // найдены условия, нужен LIKE
А если я хочу найти запись со звездочкой?
> $sqlStr = "DELETE FROM " . $this->dbStruct['table'] .
Тут можно плейсхолдеры использовать. Или лучше напиши Query Builder наподобие Zend_Db_Select
> Получает структуру таблицы для дальнейшей обработки \ построения запроса
> возвращает массив данных
А лучше бы возвращал объект
> $OBJ;
Большими буквами пишут только константы
> } catch(Exception $e) {
> $this->makeError( $e->getMessage() );
Надо сделать отдельный класс исключения, например APIException
> FormatUtil::{'to' . $this->format}($data);
Так нельзя писать. Надо сделать константы и вызывать метод типа FormatUtil::convertTo('xml'). Алсо, класс с названием FormatUtil не должен ничего выводить.
В общем, по хорошему, тут переписать надо практически все.
Плохо, что ты для работы с БД изобрел велосипед, да еще и с кривыми колесами. У тебя в одном классе свалено в кучу несколько разных вещей. Вот представь, например, ты добавишь в БД вторую таблицу и захочешь с ней работать — тебе придется делать второй класс методом копипасты. Ты изобретаешь свой кривой велосипед для экранирования данных вместо использования стандартного. Запросы ты собираешь какими-то костылями, вместо того чтобы сделать например отдельный Query Builder. Проверку на уникальность ты делаешь в той же функции что и сборку запроса. Всюду массивы на массивах. Не умеешь разбивать код на функции, все пишешь одной длинной портянкой.
Для сборки запросов по частям придуман паттерн Query Builder.
Сам код — жуткий велосипед (то есть до тебя аналогичное придумывало наверно несколько сотен тысяч человек). Советую сначала посмотреть как это сделано в том же Yii или ZF (класс Zend_Db_Table) — чтобы сразу перенять полезные вещи. Особенно внимательно изучи Zend: http://framework.zend.com/manual/1.12/ru/zend.db.html (прочти весь раздел, а особенно Zend_Db_Select/Zend_Db_Table −— поверь, много нового узнаешь. Там используются паттерны Query Builder и Table Data Gateway). В Yii используется своя вариация Active Record (описания всех этих паттернов можешь нагуглить на design-pattern.ru).
> private $dbStruct = array ( 'table' => 'users',
> 'columns' => array ('id' => 'key',
Зачем сваливать все в массив, когда можно хранить просто в свойствах объекта? У тебя массиво-ориентированное программирование.
> self::$DBH
Использованием статических св-в/методов ты убиваешь все преимущества ООП так как ты не можешь например создать 2 независимых объекта. Не используй их где не надо (а где надо? для реализации паттерна UtilityClass, для реализации Singleton и может еще в паре редких случаев).
> } catch(Exception $e) {
> throw new Exception
Зачем ловить исключение чтобы сразу же его выкинуть? Изучи получше как работают ичключения и убери try/catch
> $val = addslashes($val);
Во-первых, функция addslashes не предназначена для экранирования параметров в SQL-запросах, для этого есть $pdo->quote(), во-вторых, изучи плейсхолдеры в PDO ( http://habrahabr.ru/post/137664/ ) и используй bindValue либо массив в execute. Я вижу, ниже ты их используешь — использовал бы и тут.
> public function addUser(array $data)
Лучше вместо глупого массива сделать класс-модель User соответствующую 1 пользователю и передавать везде ее.
> экранируем - необходимо, т.к. запрос сборный и мы не сможем использовать paramValue PDO
Можем. В один массив кладем сгенерированные идентификаторы (вида :value3), в другой — значения.
> throw new Exception ( "[" . __CLASS__ . "]
XDebug при исключении пишет полный стектрейс места где оно произошло и название класса писать не придется
> if (strpos($val, '') !== false) { // найдены условия, нужен LIKE
А если я хочу найти запись со звездочкой?
> $sqlStr = "DELETE FROM " . $this->dbStruct['table'] .
Тут можно плейсхолдеры использовать. Или лучше напиши Query Builder наподобие Zend_Db_Select
> Получает структуру таблицы для дальнейшей обработки \ построения запроса
> возвращает массив данных
А лучше бы возвращал объект
> $OBJ;
Большими буквами пишут только константы
> } catch(Exception $e) {
> $this->makeError( $e->getMessage() );
Надо сделать отдельный класс исключения, например APIException
> FormatUtil::{'to' . $this->format}($data);
Так нельзя писать. Надо сделать константы и вызывать метод типа FormatUtil::convertTo('xml'). Алсо, класс с названием FormatUtil не должен ничего выводить.
В общем, по хорошему, тут переписать надо практически все.
Почему бы не открыть http://php.net/manual/ru/book.mysqli.php и не почитать?
>>388242
Ты даешь плохие советы. Начинающий не поймет Фаулера, так как книги про архитектуру рассчитаны на миддлов и сеньоров, т.е. тех кто определенное число строк прочитал и написал.
>>388243
Как раз роутер там самая нормальная часть. Незачем ради 5 функций городить полноценный сложный роутер наподобие симфони с генерацией PHP-кода по конфигу и сложной системой условий.
>>388420
Обычно функции в контроллер группируют по сущности или по разделу: раздел новостей, раздел статей и т.д.
>>388460
Тем не менее все популярные фреймворки позволяют группировать действия в один класс и называть его контроллер. Вроде, формально Контроллер определенв MVC как компонент, который управляет обработкой запросов.
http://ideone.com/eX6Xyh
Пофиксил. Почему-то меняется только последний столбец таблицы.
$db->loadObjectList(); возвращает массив объектов.
Значит все остальные пропускаются, как такое может быть?
Апач уже входит в XAmpp зачем его качать?
>>388550
Ты до понедельника ведь не сделаешь задачу для миддла. Если подумать, можно предложить что-то такое:
- спроектировать схему БД для чего-нибудь, с внешними ключами. Например, сайт Хабрахабр или Википедия.
- знаешь ли ты способы хранения в БД древовидных данных?
- придумать способ хранения большого числа отмеченных на карте объектов
- написать, а потом оптимизировать сложный запрос
- есть сайт вроде Хабрахабр с 100 000 постов, надо организовать на нем поиск. Как?
- есть сайт вроде хабрахабр, у каждого пользователя есть карма, пользователей сто тысяч, надо в профиле выводить на каком он месте в топе находится. Как?
- поговорить про стратегии кеширования и поддержания актуальности кеша на том или ином сайте. Например, что бы ты кешировал на хабре?
- спроектируй форму выбора города/села/деревни с проверкой правильности и автодополнением
- у тебя на сайте подключено 20 CSS- и 20 JS файлов, из-за этого он долго грузится и прыгает верстка, что делать?
- есть какой-то сайт на русском, надо его локализовать — сделать англоязычную версию. Расскажи, что делать будешь
- что лучше и прогрессивнее, SQL или NoSQL?
- расскажи про деплой
- расскажи про тестирование
- зачем писать на PHP если есть прекрасный ruby on rails?
- нужны ли ORM?
>>388567
> WHERE ' . $db->quoteName($title) . ' = ' . $title)
Должно быть что-то вроде WHERE title = (quote...). Условие пишется в виде WHERE имяполя = знаечние
Ну и сдмапь готовый запрос, скинь сюда.
Апач уже входит в XAmpp зачем его качать?
>>388550
Ты до понедельника ведь не сделаешь задачу для миддла. Если подумать, можно предложить что-то такое:
- спроектировать схему БД для чего-нибудь, с внешними ключами. Например, сайт Хабрахабр или Википедия.
- знаешь ли ты способы хранения в БД древовидных данных?
- придумать способ хранения большого числа отмеченных на карте объектов
- написать, а потом оптимизировать сложный запрос
- есть сайт вроде Хабрахабр с 100 000 постов, надо организовать на нем поиск. Как?
- есть сайт вроде хабрахабр, у каждого пользователя есть карма, пользователей сто тысяч, надо в профиле выводить на каком он месте в топе находится. Как?
- поговорить про стратегии кеширования и поддержания актуальности кеша на том или ином сайте. Например, что бы ты кешировал на хабре?
- спроектируй форму выбора города/села/деревни с проверкой правильности и автодополнением
- у тебя на сайте подключено 20 CSS- и 20 JS файлов, из-за этого он долго грузится и прыгает верстка, что делать?
- есть какой-то сайт на русском, надо его локализовать — сделать англоязычную версию. Расскажи, что делать будешь
- что лучше и прогрессивнее, SQL или NoSQL?
- расскажи про деплой
- расскажи про тестирование
- зачем писать на PHP если есть прекрасный ruby on rails?
- нужны ли ORM?
>>388567
> WHERE ' . $db->quoteName($title) . ' = ' . $title)
Должно быть что-то вроде WHERE title = (quote...). Условие пишется в виде WHERE имяполя = знаечние
Ну и сдмапь готовый запрос, скинь сюда.
как делать задачу кошки-мышки? есть какие-то хинты? я уже на этапе конструктора хз что делать. у меня в голове такие мысли: классы: кот, мышь, собака и поле; поле будет представлять из себя N строк длиной N точек. все строки будут содержатся в массиве. далее надо как-то расположить наших персонажей. рандомами. допустим я их как-то расположил по строкам, вставив их обозначением вместо точки соотв. строки. дальше веселее. движение эти гадов надо прописать в соотв. классах (кот, мышь). а потом анимаци движения как при вызове поля? гет/пост? куки? оп, чего ты от меня ожидаешь при выполнении этой задачи? я долбоеб, я застрял.
Зачем ты пишешь replace? Ты на стороне PHP заменить не можешь?
UPDATE some_table SET some_field = ?, some_other_field = ? WHERE id = ?
Тебе надо примерно такой запрос, зачем там REPLACE?
Напиши для начала без анимации. То, что у тебя описано, примерно так и должно быть.
Логику (то есть классы кошки мышки и поля) лучше отделить от кода, отвечающего за вывод (работающего с DOM и анимацией).
>>388580
Заменяй на стороне PHP а не через REPLACE и для надежности выводи куда-нибудь чтобы проверить можно было что заменилось.
> Там вокруг еще полно текста.
В PHP загрузи текст целиком в переменную, сделай замену, запиши обратно в базу целиком.
У меня есть набор статей и я хочу к ним рейтинг прикрутить, чтобы любой мог зайти и поставить статье оценку от 0 до 10.
Таблицу сделал так: http://pastebin.com/57YqU9Wc
В rating - сумма оценок, а в quantity - количество проголосовавших. Оценку получаю деля rating на quantity.
Может есть хитрый способ сделать проще, чтобы в таблице хранить только оценку (например, 7,43) или ещё как-нибудь упростить?
Но тот, попутно, всплыл другой интересный вопрос. А именно:
Вот есть у нас с десяток подключенных к чату юзеров. Один из них отправляет пост в чат. PHP скрипт принимает пост, и тут он должен каким-то образом уведомить остальных 9 клиентов о том, что появился новый пост и надо его аяксом подгрузить.
Когда читал learn.javascript.ru, видел там разделы про всякие server-driven events и WebSockets.
И от тут встал вопрос: а в ПХП вообще как-то возможно эти вебсокеты использовать? Ведь скрипты то в ПХП выполняются по запросу клиента и закрываются после обработки запроса. Нет никакой возможности открыть постоянное TCP соединение с клиентом, чтоб, когда нужно, отправить ему уведомление.
Вот и хочу спросить: на ПХП какое нибудь некостыльное решение такой задачи существует? Или тут нужно совсем другое серверное решение. NodeJS?? Ещё что-то??
Да, и по певому вопросу (по регистрации на сайте через стронние сервисы) не дашь советов годных? Как обычно делают? 2 таблицы - одна с данными про локально зарегистрированных пользователей (включая хешированные пароли), а другая с инфой про зарегистрированных через внешние сервисы? Где только айди юзера и токен для извлечения инфы о нем с соотв. сайта?? Или как это делают??
http://ideone.com/fIlgR0
Сделал. Намучался с кодировкой. Все перепробовал. Пришлось сохранять с метатегами, а потом вычищать регулярками.
[CODE]
$qr_result = $db->setQuery('SELECT FROM ' . $db->quoteName('#__content') . ' WHERE 1');
[/CODE]
проверка на инъекции идет?
> $res = preg_replace('~<(?:!DOCTYPE|/?(?:html|head|meta|body))[^>]>\s~i', '', $res);
Ты можешь сохранить код только части документа если в saveHtml() передаешь нужную ноду, почитай мануал.
Стоит ли их задрачивать?
http://rutracker.org/forum/viewtopic.php?t=4620353
Лаура Томсон и Люк Веллинг "Разработка WEB-
приложений на PHP и MySQL"
http://rutracker.org/forum/viewtopic.php?t=3731475
Самоучитель PHP 5
Авторы: Максим Кузнецов, Игорь Симдянов
PHP и MySQL. Разработка Web-приложений
Автор: Денис Колисниченко
Обязательно.
Оп, делаю свой велосипед трехколесным. но возникла проблема - имена таблиц у меня тоже могут подставляться через плейсхолдеры, а функция quote берет в кавычки, при передаче query добавляются еще одни - SELECT FROM ''users''. Как быть?
http://ideone.com/WHVPcT
Воспользовался simple_html_dom, т.к. проблема с кодировками мне надоела. Решить никак не смог. Сегодня все поломал на работе. Пришлось дописывать код.
он имел ввиду - ты экранируешь значение $db->quoteName('#__content') где-то в глубине db?
Потому что если твоя переменная будет содержать "table ' AND ..." произвольный SQL запрос, который будет выполнен. Например, DROP TABLE
Хотя нет, я соврал, просто MeSQL не переваривает имя таблицы в кавычках =\ Печаль. Как быть? Ведь имя таблицы я тоже через ЗР могу подставлять.
Ну joomla же, там защита явно есть от инъекций. Как раз в quoteName уже происходит проверка.
ОП, меня пропустил.
>>388760
Сделать спец плейсхолдер для иденификаторов как тут например (библиотека старье, не используй ее только посмотри описание): http://dklab.ru/lib/DbSimple/
>>388771
И где ты там видишь пришедшую от пользователя переменную? Алсо, название quoteName как бы намекает что все в порядке.
У тебя наверно в базе не utf-8 хранится? Или как? С utf-8 по идее все норм должно работать через DOM. Если не utf-8 то да, могут быть проблемы.
> setlocale(L
Это вообще почти ни на что не влияет (кроме функций типа strtoupper)
http://infinitecats.github.io/
https://github.com/infinitecats/infinitecats.github.io
Еще несколько вопросов:
1.\tКак определить Line-height, когда всего одна строка?(и не указано в фотошопе)
2.\tКак сделать так, чтобы надпись The Cool The Minimal не уезжала?
3.\tКак сделать чтобы плюсик реагировал на наведение, если он у меня псевдоэлементом?
4.\tА как сделать псевдоэлементами иконки в топ-меню, если у меня там спрайт?
5.\tВ левом верхнем углу, ссылкой должно быть лого или название? Или и то и другое?
7.\tСодержимым тега h1 может быть, например, название страницы?
Тебе нужно просто сделать и возвращать объект с методами toJson/toXml:
http://ideone.com/3UGrnM
(пишет что это спам)
>>388344
8
> margin: 10px -170px 10px -160px;
А зачем margin right отрицательный? А так, в остальном все верно.
9
> <a href="like1"
Давай тег ссылки заменим на тег button, так как обычно кнопка «нравится» на другую страницу не ведет. И тот же вопрос про отрицательный margin-right у флоатов. А так, все остальное верно.
10
> Как прижать float блок к низу родителя?
Никак не прижать. Можешь прижать к верху, как сейчас сделано.
div container достаточно сделать один, а не 2. В остальном все верно.
Я напомню, там еще есть задача 11 про кота, а также дополнительные задачи на CSS:
12. Сверстай форму как на картинке. Форма расположена по центру страницы.
Ширина диалога 400px на широкой странице, на узкой — сколько есть места, такая и ширина. Можно использовать bootstrap.css, но только если это не приведет к каше в коде и куче костылей.
13. Задание на CSS: сделать кастомные чекбоксы и радиокнопки. Кастомные — значит нестандартно выглядящие, чекбоксы и радиокнопки — это элементы форм (посмотреть на них можно тут: http://jsfiddle.net/bv6fB/1/ ). Надо сделать чтобы радиокнопки выглядели так: http://jsfiddle.net/viralpatel/p499h/embedded/result/
А чекбоксы — так: http://jsfiddle.net/Ft73h/embedded/result/
Естественно, кнопок может быть и не 3, а 2, 4, 6, 10, 20 и так далее.
Не подглядывай в исходный код. Бонусное задание: сделай табы (вкладки) на CSS3, как тут: http://inferusvv.ru/demo/tabs/index.html
Подсказка: используются невидимые радиокнопки и селектор ~
Материал для вдохновения: http://habrahabr.ru/post/154719/ http://habrahabr.ru/post/105267/ http://habrahabr.ru/post/138020/
После 13-й задачи я обычно даю простой макет для верстки (вот такой если любопытно: http://rghost.ru/58151961 )
Такие вот у нас задачки.
Тебе нужно просто сделать и возвращать объект с методами toJson/toXml:
http://ideone.com/3UGrnM
(пишет что это спам)
>>388344
8
> margin: 10px -170px 10px -160px;
А зачем margin right отрицательный? А так, в остальном все верно.
9
> <a href="like1"
Давай тег ссылки заменим на тег button, так как обычно кнопка «нравится» на другую страницу не ведет. И тот же вопрос про отрицательный margin-right у флоатов. А так, все остальное верно.
10
> Как прижать float блок к низу родителя?
Никак не прижать. Можешь прижать к верху, как сейчас сделано.
div container достаточно сделать один, а не 2. В остальном все верно.
Я напомню, там еще есть задача 11 про кота, а также дополнительные задачи на CSS:
12. Сверстай форму как на картинке. Форма расположена по центру страницы.
Ширина диалога 400px на широкой странице, на узкой — сколько есть места, такая и ширина. Можно использовать bootstrap.css, но только если это не приведет к каше в коде и куче костылей.
13. Задание на CSS: сделать кастомные чекбоксы и радиокнопки. Кастомные — значит нестандартно выглядящие, чекбоксы и радиокнопки — это элементы форм (посмотреть на них можно тут: http://jsfiddle.net/bv6fB/1/ ). Надо сделать чтобы радиокнопки выглядели так: http://jsfiddle.net/viralpatel/p499h/embedded/result/
А чекбоксы — так: http://jsfiddle.net/Ft73h/embedded/result/
Естественно, кнопок может быть и не 3, а 2, 4, 6, 10, 20 и так далее.
Не подглядывай в исходный код. Бонусное задание: сделай табы (вкладки) на CSS3, как тут: http://inferusvv.ru/demo/tabs/index.html
Подсказка: используются невидимые радиокнопки и селектор ~
Материал для вдохновения: http://habrahabr.ru/post/154719/ http://habrahabr.ru/post/105267/ http://habrahabr.ru/post/138020/
После 13-й задачи я обычно даю простой макет для верстки (вот такой если любопытно: http://rghost.ru/58151961 )
Такие вот у нас задачки.
Стараюсь в контроллерах все азбивать на много-много маленьких функций, это правильно? Алсо, это CodeIgniter.
В базе utf-8. Это такая популярная проблема, в гугле столько вопросов по поводу этого.
Вот такую еще вещь нашел: https://bugs.php.net/bug.php?id=32547
А еще вот: https://bugs.php.net/bug.php?id=47875&thanks=6
Ничего не помогло. Интернет полон "левых" решений.
loadHTML или saveHTML методы (не знаю какой именно)) конвертируют не-ASCII символы в html сущности. Страница по прежнему остается в UTF-8, но вместо кириллицы появляются сущности, заменяющие ее.
Проблемы DOM: оборачивает в ненужные теги и перекодирует зачем-то сам.
Но я нашел выход буквально только что!
http://ideone.com/zjLiVV
Вот он фикс, который я встретил поздно: https://gist.github.com/Xeoncross/9401853
А именно:
$doc = new DOMDocument('1.0', 'UTF-8');
$doc->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));
print $doc->saveHTML($doc->documentElement) . PHP_EOL . PHP_EOL;
При загрузке сразу же конвертируем все сущности в символы UTF-8, а дальше сохраняем дочерний элемент, который и является документом. С просто saveHTML() не срабатывает почему-то.
Другая проблема: убирать лишние теги регулярками ненадежно как я понимаю. Оп, не знаешь решение?
В базе utf-8. Это такая популярная проблема, в гугле столько вопросов по поводу этого.
Вот такую еще вещь нашел: https://bugs.php.net/bug.php?id=32547
А еще вот: https://bugs.php.net/bug.php?id=47875&thanks=6
Ничего не помогло. Интернет полон "левых" решений.
loadHTML или saveHTML методы (не знаю какой именно)) конвертируют не-ASCII символы в html сущности. Страница по прежнему остается в UTF-8, но вместо кириллицы появляются сущности, заменяющие ее.
Проблемы DOM: оборачивает в ненужные теги и перекодирует зачем-то сам.
Но я нашел выход буквально только что!
http://ideone.com/zjLiVV
Вот он фикс, который я встретил поздно: https://gist.github.com/Xeoncross/9401853
А именно:
$doc = new DOMDocument('1.0', 'UTF-8');
$doc->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));
print $doc->saveHTML($doc->documentElement) . PHP_EOL . PHP_EOL;
При загрузке сразу же конвертируем все сущности в символы UTF-8, а дальше сохраняем дочерний элемент, который и является документом. С просто saveHTML() не срабатывает почему-то.
Другая проблема: убирать лишние теги регулярками ненадежно как я понимаю. Оп, не знаешь решение?
картинка к 12 задаче.
>>388379
Потому что большинство str-функций рассчитано на старые однобайтовые кодировки и не работает с utf-8.
Некоторые функции PHP (strlen, substr, а также обращение к строке как к массиву: $str[0]) не работают с многобайтовыми кодировками (вроде utf-8). В utf-8 1 символ закодирован с помощью от 1 до 6 байтов, а эти функции думают, что 1 буква вегда кодируется одним байтом. По этой причине они ломают символы, в результате получаются битые символы и ничего не работает. Потому вместо них надо использовать mb_ функции например mb_strlen, mb_substr. Вместо доступа к строке как к массиву надо использовать mb_substr.
Вывод: используй mb_ функции. Не исплоьзуй доступ к строке как к массиву. В регулярных выражениях используй флаг u (он говорит что исплоьзуется utf-8 а не однобайтовая кодировка).
Некоторые строковые функции без префикса mb тем не менее корректно работают с utf-8 и их можно использовать. Вот они: strtr (если передавать массив), str_replace, str_repeat, explode, addslashes, trim.
Не работают с utf-8: strrev, strlen, substr, strpos, ucfirst, wordwrap и большинство других строковых функций.
>>388410
> echo $yoba = md5("$yoba");
Не надо объединять присваивание (=) и echo, сделай 2 отдельных строчки
> md5("$yoba")
Можно без кавычек — будет то же самое
А так, верно.
картинка к 12 задаче.
>>388379
Потому что большинство str-функций рассчитано на старые однобайтовые кодировки и не работает с utf-8.
Некоторые функции PHP (strlen, substr, а также обращение к строке как к массиву: $str[0]) не работают с многобайтовыми кодировками (вроде utf-8). В utf-8 1 символ закодирован с помощью от 1 до 6 байтов, а эти функции думают, что 1 буква вегда кодируется одним байтом. По этой причине они ломают символы, в результате получаются битые символы и ничего не работает. Потому вместо них надо использовать mb_ функции например mb_strlen, mb_substr. Вместо доступа к строке как к массиву надо использовать mb_substr.
Вывод: используй mb_ функции. Не исплоьзуй доступ к строке как к массиву. В регулярных выражениях используй флаг u (он говорит что исплоьзуется utf-8 а не однобайтовая кодировка).
Некоторые строковые функции без префикса mb тем не менее корректно работают с utf-8 и их можно использовать. Вот они: strtr (если передавать массив), str_replace, str_repeat, explode, addslashes, trim.
Не работают с utf-8: strrev, strlen, substr, strpos, ucfirst, wordwrap и большинство других строковых функций.
>>388410
> echo $yoba = md5("$yoba");
Не надо объединять присваивание (=) и echo, сделай 2 отдельных строчки
> md5("$yoba")
Можно без кавычек — будет то же самое
А так, верно.
Ох, какое в Джумле все древнее. Вот эта штука называется Query Builder:
$query->select ... ->from ... (кстати по моему стрелочку лучше оставлять в конце строки, как математические знаки)
но в джумле он реализован криво. Смотри, ты подставляешь данные через вызов quote:
" WHERE x = {$db->quote($xValue)} AND y = 1";
Это правильно, данные надо экранировать, но это плохой подход так как код превращается в нечитаемую лапшу. Когда будет время, ознакомься с концепцией плейсхолдеров на примере PDO: http://habrahabr.ru/post/137664/ — с их помощью и данные экранируются, и запрос остается читабельным.
Насчет имен полей, их можно экранировать вручную с помощью косых кавычек: WHERE `x` = ... — должно работать — если только quoteName не делает какие-то преобразования.
Так вот, говоря про правильные примеры, глянь например как в ZF сделан Zend_db_Select ( http://framework.zend.com/manual/1.12/ru/zend.db.select.html#zend.db.select.building.where ): там используются плейсхолдеры и код гораздо читабельнее:
$select->from('table')->where('x > ?', $x); // не надо писать quote
Я специально рассказываю про PDO и ZF чтобы ты знал как такие вещи (построение запроса и подстановка параметров) делать правильно.
Вообще, запросы писать удобнее без query builder, напрямую в виде SQL c плейсхолдерами. QB используют когда запрос надо модифицировать в зависимости от разных условий и собирать его по кусочкам.
> Надо наверное форму вывести с полями: "Заголовок", "Категория", "Текст", "Доступ". И вбивать туда все статьи, а скрипт уже разделит по тегу h1 и закинет в базу.
Ты так дойдешь до написания копии админки.
>>388448
> Создаем электростанция, потом добавляем элементы.
Правильно
> Cчитаем вклад каждого элемента.
Неправильно. Ты придумываешь что-то усложненное. Считать должна Электросеть. Мы лишь вызваем метод
дневное = сеть.рассчитатьБаланс(днем);
ночное = сеть.рассчитатьБаланс(ночь);
А она сама рассчитывает этот баланс (складывает потребление/генерацию всех элементов). Соответственно она возвращает положительное/отрицательнео число.
> Считаем сколько надо продать/докупить; считаем выручку/затраты
Ну вот посчитав баланс мы легко можем определить продаем мы (если он положительный) или покупаем и сколько. Стоимость можно посчитать на основе списка ЛЭП (сначала покупаем самую дешевую, потом с тех что подороже). Опять же, для расчета всего этого должны быть методы у электросети.
У элемента сети мне кажется достаточно сделать один метод: получитьВкладВБаланс (положительный если он генерирует и отрицательный если потребляет энергию). Плюс у ЛЭП еще можно сделать метод посчитатьСтоимость.
>>388569
Я не очень хорошо отношусь к кодеакадеми, так как уровень там очень и очень базовый. Плюс, задания проверяет робот (который не увидит многих ошибок). На мой взгляд, мои задачки по CSS куда как лучше.
Насчет сайтов — я про такие не слышал, увы.
php the right way — отличный сайт, но он не особо учит начинающих, а просто рассказывает как делать правильно.
Ох, какое в Джумле все древнее. Вот эта штука называется Query Builder:
$query->select ... ->from ... (кстати по моему стрелочку лучше оставлять в конце строки, как математические знаки)
но в джумле он реализован криво. Смотри, ты подставляешь данные через вызов quote:
" WHERE x = {$db->quote($xValue)} AND y = 1";
Это правильно, данные надо экранировать, но это плохой подход так как код превращается в нечитаемую лапшу. Когда будет время, ознакомься с концепцией плейсхолдеров на примере PDO: http://habrahabr.ru/post/137664/ — с их помощью и данные экранируются, и запрос остается читабельным.
Насчет имен полей, их можно экранировать вручную с помощью косых кавычек: WHERE `x` = ... — должно работать — если только quoteName не делает какие-то преобразования.
Так вот, говоря про правильные примеры, глянь например как в ZF сделан Zend_db_Select ( http://framework.zend.com/manual/1.12/ru/zend.db.select.html#zend.db.select.building.where ): там используются плейсхолдеры и код гораздо читабельнее:
$select->from('table')->where('x > ?', $x); // не надо писать quote
Я специально рассказываю про PDO и ZF чтобы ты знал как такие вещи (построение запроса и подстановка параметров) делать правильно.
Вообще, запросы писать удобнее без query builder, напрямую в виде SQL c плейсхолдерами. QB используют когда запрос надо модифицировать в зависимости от разных условий и собирать его по кусочкам.
> Надо наверное форму вывести с полями: "Заголовок", "Категория", "Текст", "Доступ". И вбивать туда все статьи, а скрипт уже разделит по тегу h1 и закинет в базу.
Ты так дойдешь до написания копии админки.
>>388448
> Создаем электростанция, потом добавляем элементы.
Правильно
> Cчитаем вклад каждого элемента.
Неправильно. Ты придумываешь что-то усложненное. Считать должна Электросеть. Мы лишь вызваем метод
дневное = сеть.рассчитатьБаланс(днем);
ночное = сеть.рассчитатьБаланс(ночь);
А она сама рассчитывает этот баланс (складывает потребление/генерацию всех элементов). Соответственно она возвращает положительное/отрицательнео число.
> Считаем сколько надо продать/докупить; считаем выручку/затраты
Ну вот посчитав баланс мы легко можем определить продаем мы (если он положительный) или покупаем и сколько. Стоимость можно посчитать на основе списка ЛЭП (сначала покупаем самую дешевую, потом с тех что подороже). Опять же, для расчета всего этого должны быть методы у электросети.
У элемента сети мне кажется достаточно сделать один метод: получитьВкладВБаланс (положительный если он генерирует и отрицательный если потребляет энергию). Плюс у ЛЭП еще можно сделать метод посчитатьСтоимость.
>>388569
Я не очень хорошо отношусь к кодеакадеми, так как уровень там очень и очень базовый. Плюс, задания проверяет робот (который не увидит многих ошибок). На мой взгляд, мои задачки по CSS куда как лучше.
Насчет сайтов — я про такие не слышал, увы.
php the right way — отличный сайт, но он не особо учит начинающих, а просто рассказывает как делать правильно.
>>388582
Классы: кошка, мышка (наследуются от общего предка абстрактного класса Животное), Карта, Игра.
Не используй в этой задаче public свйоства, только private/protected.
> допустим я их как-то расположил по строкам, вставив их обозначением вместо точки соотв. строки.
Храни лучше массив объектов. Это гораздо удобнее.
> а потом анимаци движения как при вызове поля? гет/пост? куки?
Ты можешь просто сделать без анимации, выводить для каждого хода картинку игрового поля, сверху вниз. Но если с анимацией то конечно лучше.
> чего ты от меня ожидаешь при выполнении этой задачи?
Посмотреть как ты сделашеь классы, как раззложишь по ним код и как свяжешь их друг с другом. Проверить понимание ООП. Как ты будешь это все отображать, второстепенно.
>>388596
> У меня есть набор статей и я хочу к ним рейтинг прикрутить,
Обычно делают таблицу из 3 колонок, «кто», «за что», «как» проголосовал. Чтобы например предотвратить повторное голосование. А для статьи можно хранить сумму балоов и число голосов, да.
> Может есть хитрый способ сделать проще, чтобы в таблице хранить только оценку (например, 7,43) или ещё как-нибудь упростить?
Тогда ты не сможешь например защититься от накручивания голосов одним пользователем или не сможешь удалить часть голосов и пересчитать результат.
>>388600
> И от тут встал вопрос: а в ПХП вообще как-то возможно эти вебсокеты использовать?
Можно написать эту часть (демон передающий сообщения, он же comet server) на node.js или взять готовый: http://dklab.ru/lib/dklab_realplexor/ http://habrahabr.ru/post/104945/ http://javascript.ru/ajax/comet/server-patterns#otkrytye-comet-servera
> Нет никакой возможности открыть постоянное TCP соединение с клиентом, чтоб, когда нужно, отправить ему уведомление.
Вообще есть, ты можешь запустить скрипт из командной строки (не через Апач), он открывает порт и принимает соединения от клиентов и пересылает данные между ними. Но тут нужно знать сокеты и использовать обработку событий на скоетах с помощью libevent (она позволяет поддерживать огромное число соединений, а без нее будет тормозить).
> 2 таблицы - одна с данными про локально зарегистрированных пользователей (включая хешированные пароли), а другая с инфой про зарегистрированных через внешние сервисы?
Нет. Первая таблица — локальные пользователи (и местные, и внешние). Вторая таблица — связь «внешний аккаунт -> локальный аккаунт». При первом входе через внешний сервис аккаунт создается автоматом. Тогда можно к 1 пользователю привязать несколько внешних аккаунтов + иметь пароль для входа локально.
Вторая таблица может иметь вид:
service | external_id | local_id | userinfo
facebook | 10234834848 | 123 | {"username": "xxx", "surname": "yuyy", ...}
>>388582
Классы: кошка, мышка (наследуются от общего предка абстрактного класса Животное), Карта, Игра.
Не используй в этой задаче public свйоства, только private/protected.
> допустим я их как-то расположил по строкам, вставив их обозначением вместо точки соотв. строки.
Храни лучше массив объектов. Это гораздо удобнее.
> а потом анимаци движения как при вызове поля? гет/пост? куки?
Ты можешь просто сделать без анимации, выводить для каждого хода картинку игрового поля, сверху вниз. Но если с анимацией то конечно лучше.
> чего ты от меня ожидаешь при выполнении этой задачи?
Посмотреть как ты сделашеь классы, как раззложишь по ним код и как свяжешь их друг с другом. Проверить понимание ООП. Как ты будешь это все отображать, второстепенно.
>>388596
> У меня есть набор статей и я хочу к ним рейтинг прикрутить,
Обычно делают таблицу из 3 колонок, «кто», «за что», «как» проголосовал. Чтобы например предотвратить повторное голосование. А для статьи можно хранить сумму балоов и число голосов, да.
> Может есть хитрый способ сделать проще, чтобы в таблице хранить только оценку (например, 7,43) или ещё как-нибудь упростить?
Тогда ты не сможешь например защититься от накручивания голосов одним пользователем или не сможешь удалить часть голосов и пересчитать результат.
>>388600
> И от тут встал вопрос: а в ПХП вообще как-то возможно эти вебсокеты использовать?
Можно написать эту часть (демон передающий сообщения, он же comet server) на node.js или взять готовый: http://dklab.ru/lib/dklab_realplexor/ http://habrahabr.ru/post/104945/ http://javascript.ru/ajax/comet/server-patterns#otkrytye-comet-servera
> Нет никакой возможности открыть постоянное TCP соединение с клиентом, чтоб, когда нужно, отправить ему уведомление.
Вообще есть, ты можешь запустить скрипт из командной строки (не через Апач), он открывает порт и принимает соединения от клиентов и пересылает данные между ними. Но тут нужно знать сокеты и использовать обработку событий на скоетах с помощью libevent (она позволяет поддерживать огромное число соединений, а без нее будет тормозить).
> 2 таблицы - одна с данными про локально зарегистрированных пользователей (включая хешированные пароли), а другая с инфой про зарегистрированных через внешние сервисы?
Нет. Первая таблица — локальные пользователи (и местные, и внешние). Вторая таблица — связь «внешний аккаунт -> локальный аккаунт». При первом входе через внешний сервис аккаунт создается автоматом. Тогда можно к 1 пользователю привязать несколько внешних аккаунтов + иметь пароль для входа локально.
Вторая таблица может иметь вид:
service | external_id | local_id | userinfo
facebook | 10234834848 | 123 | {"username": "xxx", "surname": "yuyy", ...}
>>388613
> new DOMDocument('4.0','UTF-8');
Тут указывается версия XML, а не HTML, то есть 1.0 (так как первоначально DOM делался для XML). Кодировку наверно надо было указать ту же что и данные в БД (либо преобразовать данные из БД в utf-8 через iconv).
> $nodeMeta->setAttribute ("content","ISO-8859-1");
Это вообще непонятно зачем
> $res = preg_replace('~<(?:!DOCTYPE|/
saveHtml умеет сохранять не весь документ а только одну ноду
> ' WHERE ' . $db->quoteName('title')
Надежнее обновлять не по названию а по id
>>388712
Ну попробуй, хотя мне их курс не особо нравится. Если будут вопросы, приходи в наш тред. Если захочешь порешать нормальные задачки, приходи в наш тред.
Насчет книг, эти я не читал, пара хороших книг (Зандстра и Шлоснейгл) есть в ОП-посте.
>>388760
Идентификаторы (имена полей и таблиц) пишутся в косых кавычках или без них. Если ид-р содержит косую кавычку, она пишется 2 раза: http://dev.mysql.com/doc/refman/5.0/en/identifiers.html (англ) http://phpclub.ru/mysql/doc/legal-names.html (рус)
Для них нужен отдльный вид плейсхолдеров работающий по эжтим правилам.
>>388765
> $img->alt = $title;
По моему для аттрибутов там используются скобки: $img['alt'] = ....; Ты хоть тестировал этот код?
>>388828
> Как определить Line-height, когда всего одна строка?(и не указано в фотошопе)
Ставь по умолчанию, 1.3 или 1.4. Для крупных заголовков можно 1.2 или 1.0
> Как сделать так, чтобы надпись The Cool The Minimal не уезжала?
Выбрать правльный способ позиционирования. А где она? Ее вообще не вижу на макете.
> Как сделать чтобы плюсик реагировал на наведение, если он у меня псевдоэлементом?
Реагировать может только элемент, а не псевдоэлемент. Надо наверно его отдельным элементом делать.
> А как сделать псевдоэлементами иконки в топ-меню, если у меня там спрайт?
А как одно мешает другому? position: absolute, width, height, background-image. Опиши подробнее, в чем сложность.
> В левом верхнем углу, ссылкой должно быть лого или название? Или и то и другое?
И то и другое
> Содержимым тега h1 может быть, например, название страницы?
да, иногда им даже логотип делают, но обычно это главный заголовок. Тут заголовка нет, так что можешь им логотип со словом THEYALOW сделать.
> Страница разваливается уже на 1200пикселях - это плохо
Это потому что ты жестко задаешь высоту блоков. Например внизу сервый блок - надо не прописывать высоту в пикслях а сделать чтобы она определялась содержимым. Вообще, старайся как можно чаще использовать автоматическое определение размеров, а не явное задание. В некоторых местах придется поставить overflow. И при уменьшении до определенной ширины надо с помощью правил @media перестраивать дизайн на узкий.
Верхнее меню About is | services не должно уменьшаться, а должно определяться размером текста в нем.
В блоке Better design | Customize надо наладить выравнивание текста чтобы он центрировался, а не уезжал влево.
В блоке с твиттером надо сделать overflow чтобы текст не вываливался
В черном блоке внизу надо сделать чтобы высота определядась содердимым.
Если есть еще вопросы, задавай.
> Как исправлять я не знаю, где-то тупо перестает вмещаться текст и все слетает.
Это значит ты изначально неправильно его сверстал. Если текст выводится по центру надо использовать text align center а не ставить жестко рассчитанный отступ слева в пикселах.
Ты ведь не решал мои задачки по CSS? Впрочем, их и не обязательно решать, давай на этом макете тогда учиться правильно верстать.
>>388613
> new DOMDocument('4.0','UTF-8');
Тут указывается версия XML, а не HTML, то есть 1.0 (так как первоначально DOM делался для XML). Кодировку наверно надо было указать ту же что и данные в БД (либо преобразовать данные из БД в utf-8 через iconv).
> $nodeMeta->setAttribute ("content","ISO-8859-1");
Это вообще непонятно зачем
> $res = preg_replace('~<(?:!DOCTYPE|/
saveHtml умеет сохранять не весь документ а только одну ноду
> ' WHERE ' . $db->quoteName('title')
Надежнее обновлять не по названию а по id
>>388712
Ну попробуй, хотя мне их курс не особо нравится. Если будут вопросы, приходи в наш тред. Если захочешь порешать нормальные задачки, приходи в наш тред.
Насчет книг, эти я не читал, пара хороших книг (Зандстра и Шлоснейгл) есть в ОП-посте.
>>388760
Идентификаторы (имена полей и таблиц) пишутся в косых кавычках или без них. Если ид-р содержит косую кавычку, она пишется 2 раза: http://dev.mysql.com/doc/refman/5.0/en/identifiers.html (англ) http://phpclub.ru/mysql/doc/legal-names.html (рус)
Для них нужен отдльный вид плейсхолдеров работающий по эжтим правилам.
>>388765
> $img->alt = $title;
По моему для аттрибутов там используются скобки: $img['alt'] = ....; Ты хоть тестировал этот код?
>>388828
> Как определить Line-height, когда всего одна строка?(и не указано в фотошопе)
Ставь по умолчанию, 1.3 или 1.4. Для крупных заголовков можно 1.2 или 1.0
> Как сделать так, чтобы надпись The Cool The Minimal не уезжала?
Выбрать правльный способ позиционирования. А где она? Ее вообще не вижу на макете.
> Как сделать чтобы плюсик реагировал на наведение, если он у меня псевдоэлементом?
Реагировать может только элемент, а не псевдоэлемент. Надо наверно его отдельным элементом делать.
> А как сделать псевдоэлементами иконки в топ-меню, если у меня там спрайт?
А как одно мешает другому? position: absolute, width, height, background-image. Опиши подробнее, в чем сложность.
> В левом верхнем углу, ссылкой должно быть лого или название? Или и то и другое?
И то и другое
> Содержимым тега h1 может быть, например, название страницы?
да, иногда им даже логотип делают, но обычно это главный заголовок. Тут заголовка нет, так что можешь им логотип со словом THEYALOW сделать.
> Страница разваливается уже на 1200пикселях - это плохо
Это потому что ты жестко задаешь высоту блоков. Например внизу сервый блок - надо не прописывать высоту в пикслях а сделать чтобы она определялась содержимым. Вообще, старайся как можно чаще использовать автоматическое определение размеров, а не явное задание. В некоторых местах придется поставить overflow. И при уменьшении до определенной ширины надо с помощью правил @media перестраивать дизайн на узкий.
Верхнее меню About is | services не должно уменьшаться, а должно определяться размером текста в нем.
В блоке Better design | Customize надо наладить выравнивание текста чтобы он центрировался, а не уезжал влево.
В блоке с твиттером надо сделать overflow чтобы текст не вываливался
В черном блоке внизу надо сделать чтобы высота определядась содердимым.
Если есть еще вопросы, задавай.
> Как исправлять я не знаю, где-то тупо перестает вмещаться текст и все слетает.
Это значит ты изначально неправильно его сверстал. Если текст выводится по центру надо использовать text align center а не ставить жестко рассчитанный отступ слева в пикселах.
Ты ведь не решал мои задачки по CSS? Впрочем, их и не обязательно решать, давай на этом макете тогда учиться правильно верстать.
> По моему для аттрибутов там используются скобки: $img['alt'] = ....; Ты хоть тестировал этот код?
Более того он и помог мне сегодня, все сработало просто отлично, но подключение библиотеки пошатнуло уверенность в собственных силах исправить данную проблему. Ниже ты увидишь, что я нашел выход все-таки.
Ага, вижу. Надо либо приписывать тег <?xml в самое начало, либо преобразовывать все в html-сущности. да уж, печалька. Наверно xml-тег приписывать проще выйдет?
> При загрузке сразу же конвертируем все сущности в символы UTF-8, а дальше сохраняем дочерний элемент, который и является документом. С просто saveHTML() не срабатывает почему-то.
Наоборот, мы русские буквы превращаем в сущности вида & # 12345 ; Стоило бы конечно это в отдельную функцию вынести. Жаль конечно что там такие проблемы есть.
> Проблемы DOM: оборачивает в ненужные теги
Если ты про автоматическое добавление html/body то по спецификации HTML они сами дописываются если их нет в документе. Но ты можешь делать saveHtml не для всего документа а только для одного узла.
> Другая проблема: убирать лишние теги регулярками ненадежно как я понимаю. Оп, не знаешь решение?
Сохранять не весь документ, а только один узел (например только body) через saveHtml($node). Алсо, есть такое: http://stackoverflow.com/a/2087136
>>388899
Трудно по такому кусочку что-то сказать.
> Стараюсь в контроллерах все азбивать на много-много маленьких функций, это правильно? Алсо, это CodeIgniter.
ну в контроллерах принято вообще не писать много кода. Они должны вызвыать методы других классов. Алсо, CI — старый.
Ага, вижу. Надо либо приписывать тег <?xml в самое начало, либо преобразовывать все в html-сущности. да уж, печалька. Наверно xml-тег приписывать проще выйдет?
> При загрузке сразу же конвертируем все сущности в символы UTF-8, а дальше сохраняем дочерний элемент, который и является документом. С просто saveHTML() не срабатывает почему-то.
Наоборот, мы русские буквы превращаем в сущности вида & # 12345 ; Стоило бы конечно это в отдельную функцию вынести. Жаль конечно что там такие проблемы есть.
> Проблемы DOM: оборачивает в ненужные теги
Если ты про автоматическое добавление html/body то по спецификации HTML они сами дописываются если их нет в документе. Но ты можешь делать saveHtml не для всего документа а только для одного узла.
> Другая проблема: убирать лишние теги регулярками ненадежно как я понимаю. Оп, не знаешь решение?
Сохранять не весь документ, а только один узел (например только body) через saveHtml($node). Алсо, есть такое: http://stackoverflow.com/a/2087136
>>388899
Трудно по такому кусочку что-то сказать.
> Стараюсь в контроллерах все азбивать на много-много маленьких функций, это правильно? Алсо, это CodeIgniter.
ну в контроллерах принято вообще не писать много кода. Они должны вызвыать методы других классов. Алсо, CI — старый.
>Вообще есть, ты можешь запустить скрипт из командной строки (не через Апач), он открывает порт и принимает соединения от клиентов и пересылает данные между ними.
Понтяно, что так можно. Но это похоже на какой то жуткий костыль. Неужели кто то так делает на практике?
>Нет. Первая таблица — локальные пользователи (и местные, и внешние). Вторая таблица — связь «внешний аккаунт -> локальный аккаунт». При первом входе через внешний сервис аккаунт создается автоматом.
Такс, а чем заполнять поля user_login,user_password,user_email, user_display_name в основной таблице при первом входе через внешний сервис? Или, типа, оставить поле пароля пустым, и это будет признаком того, что данный конкретный пользователь не может залогиниться, используя локальный пароль, а только через внешние сервисы??
Хочу сделать ссылку с пост запросом, тут же есть какой-нибудь хелпер для этого? Не хочется самому через js делать.
$url = array('controller/action');
CHtml::link(
'label',
$url,
array(
'submit' => $url,
'params' => array('param1' => $data['id1'], 'param2' => $data['id2']),
)
);
Создается невидимая форма с методом post и видимая кнопка отправки к ней
Это в первом. Наверняка и во втором работает
Спасибо.
Погуглил немного, в Yii2 достаточно к ссылке добавить параметр data-method="post"
<a href="#" data-method="post" data-confirm="Точно перейти?">Ссылка</a>
Html::a(
'Ссылка',
['#'],
['data-confirm' => 'Точно перейти?', 'data-method' => 'post']
);
> Но это похоже на какой то жуткий костыль. Неужели кто то так делает на практике?
Разработчики под node.js, Питон и другие языки так делают например. Что костыльного? Сервер нужен для обработки http-запросов, а comet это другая вещь и работать с ним надо по другому.
> Такс, а чем заполнять поля user_login,user_password,user_email, user_display_name в основной таблице при первом входе через внешний сервис?
email некоторые соцсети отдают, некоторые нет. login можно генерировать из ника например, можно не генерировать, можно генерировать по шаблону facebook03737327327. display_name делается из имени в соцсети.
И кстати, зачем тебе login если у тебя есть email? Я бы это поле вообще удалил.
> Или, типа, оставить поле пароля пустым, и это будет признаком того,
Лучше бы отдельное поле для этого (что нельзя залогиниться) завести.
>>389046\t
В Руби он рельс/ноде аналогичного полно. Это не наше изобретение. Не заводить же нам отдельный тип данных LinkTarget ради этого?
>>389031
Это абсолютно неприавльно. Ссылка не может отправлять POST-запросы и у нее должен быть указан href. А это какой-то кривой костыль. Для отправки любых запросов существуют кнопки.
Алсо, то что у него стоит href=# ты не видишь, а к какому-то несчастному массиву придираешься. Бревна не видишь.
Калькулятор:
http://ideone.com/HczV4K
Исправление пробелов/букв:
http://ideone.com/dQWVf2
Йода:
http://ideone.com/0L0A63
Старое, которое надо было еще доделать раньше:
http://ideone.com/mbPdsr
http://ideone.com/xEms8a
"Пиши верно" так и не переделал потому что слишком муторно и вообще..., такие дела.
Фаулер - это вообще для детей. Там разжёвано как для школьников.
Роутер как минимум не должен роуты в себе захардкоженные содержать. Про симфони никто и не говорит, в кохане например простой роутер, но написан грамотно.
да, вместо того что бы себя пересилить я просто взял и пришел сюда попиздеть.
Есть одна mysql-таблица: ID, Товар, Название магазина (а их много, а товары повторяются), цена в этом магазине, ссылка на магазинную страничку.
Значит задача такая: по вот такому реквесту:
[code]
<a href="http://priceserv.com/ifeed/link/samsung/1" target="_blank" rel="nofollow"><img src="http://priceserv.com/ifeed/img/samsung/1" /></a>
<a href="http://priceserv.com/ifeed/link/samsung/2" target="_blank" rel="nofollow"><img src="http://priceserv.com/ifeed/img/samsung/2" /></a>
<a href="http://priceserv.com/ifeed/link/samsung/3" target="_blank" rel="nofollow"><img src="http://priceserv.com/ifeed/img//samsung/3" /></a>
[/code]
Получить картинки с названиями, ценой и ссылками на энти магазины в интернете. А код этого реквеста вообще будет висеть на другом сайте.
Вопрос такой:
Чем лучше обмазаться для доступа к БД - pdo, ORM или че там? Не хочу писать mysql-команды - боюсь хакиров. И фреймворки тоже не очень хочется - слишком тяжеловесно будет. Нужна простая библиотека для чайника, чтобы я написал: ищем "samsung" по базе и он мне вернул значения - где он самсунги на шел по таким-то ценам. А я потом их уже конвертирую в графику и возвращаю.
Алсо, если здесь есть аноны, у которых много свободного времени сегодня вечером и кому не чужды $50 через Paypal, и которые могут мне написать такую йобу - кидайте контакты.
Алсо Doctrine2 - хорошая штука? Может сразу за нее взяться, чтобы не ковыряться с велосипедами...
Ну вот посмотри, я сделал метод у ЭлектрическойСети - http://jsbin.com/hecahuzenuwi/3/edit . Извини за тупость, но я не понимаю, что должен делать метод ЭлементаСети, если уже все у меня получается уже посчитано.
>Ставь по умолчанию, 1.3 или 1.4. Для крупных заголовков можно 1.2 или 1.0
Это в em'ах?
>Выбрать правльный способ позиционирования. А где она? Ее вообще не вижу на макете.
Я просто строчку в html-файле закомментировал.
>А как одно мешает другому? position: absolute, width, height, background-image. Опиши подробнее, в чем сложность.
Ну смотри, когда делаем что-то с помощью спрайта, вешаем фон на блок, а его детям делаем background-position. С псевдоэлементами у меня что-то так не получалось. Или если я задам основному блоку фон, а потом буду иконкис помощью псевдоэлементов делать background-position будет работать?
>Верхнее меню About is | services не должно уменьшаться, а должно определяться размером текста в нем.
Ну а текст же всегда одного размера. Ка это понимать?
>В черном блоке внизу надо сделать чтобы высота определядась содердимым.
В подвале или который перед ним? Или всем блокам height: auto проставить?
А смотри, я скачал перфект пиксель начал верстать по нему, и где-то, например, надписи не ровно по центру, а слева отступ чуть больше, чем справа. При адаптивной верстке стоит на глаз определять? А при обычной стоит все таки высчитывать отступы?
Лол, пришел сегодня на работу, и меня обрадовали новостью, что мой скрипт почистил содержимое тегов в базе оказывается. А я плохо проверил, лол. Там просто большая часть сайта - картинки, поэтому не заметил. Адреналин в кровь хлынул, и тут я вспомнил, что экспортировал таблицу перед редактированием. Восстановил и уже отредактировал нормальным скриптом с замещением сущностей.
А мораль такова, всегда иметь при себе исходник на всякий случай.
Сегодня-завтра начну файлообменник пилить.
У меня есть столбец с типом text, я нагуглил, что он вмещает 65535 байт, а сколько это будет символов для utf-8?
Или вот varchar(1000). Если я поставлю кодировку таблицы utf-8, я смогу хранить 1000 символов или 1000 байт?
Скачал здесь: http://www.apachelounge.com/download/
httpd-2.4.10-win32-VC11.zip
Распаковал в c:\Apache24
Как устанавливать. И нет никакой папки conf
utf-8 так называется, потому что для каждого символа используется 8 байт.
Лол. Боюсь подумать, как мир пользуется UTF-16.
>>389282
Количество используемых UTF-8 байт зависит от code-point (символа). Максимальная длина закодированного в UTF-8 code-point - 6 байт. Но обычный текст будет занимать меньше места. Латиница - 1 байт, русские буквы - 2 байта.
Что касается VARCHAR, длину можно задавать в байтах или в символах. Если единица не указана, то считается, что она в символах. Т.е., в твой VARCHAR(1000) влезет 1000 символов.
Если ниосилишь, то накати денвер.
> И нет никакой папки conf
Ищи лучше или смирись с тем, что тебе еще рано программировать если не можешь даже в подпапку заглянуть.
Что там устанавливать-то? Распаковал, запустил httpd.exe, полюбовался на it works, поправил конфиг, перезапустил. Это тебе не лайти под винду компилять.
>У меня есть столбец с типом text, я нагуглил, что он вмещает 65535 байт, а сколько это будет символов для utf-8?
http://dev.mysql.com/doc/refman/5.6/en/string-type-overview.html
> MySQL interprets length specifications in character column definitions in character units.
1000 значит 1000 символов.
> VARCHAR(M)
> A variable-length string. M represents the maximum column length in characters. The range of M is 0 to 65,535. The effective maximum length of a VARCHAR is subject to the maximum row size (65,535 bytes, which is shared among all columns) and the character set used. For example, utf8 characters can require up to three bytes per character, so a VARCHAR column that uses the utf8 character set can be declared to be a maximum of 21,844 characters.
Указать VARCHAR можно до 65535, но в одной строке таблицы может быть не более 65535 байт, потому для utf8 там будет лишь максимум 21844 символа. Обрати внимание, этот лимит не распространяется на TEXT/BLOB так как они хранятся отдельно.
> A TEXT column with a maximum length of 65,535 (216 – 1) characters.
В колонке TEXT хранится до 65535 символов.
> MEDIUMTEXT
> A TEXT column with a maximum length of 16,777,215 (224 – 1) characters.
А тут до 16 млн. символов
> LONGTEXT
> A TEXT column with a maximum length of 4,294,967,295 or 4GB (232 – 1) characters.
Тут до 4 Гб, то есть около полтора миллиардов utf8-символов.
>У меня есть столбец с типом text, я нагуглил, что он вмещает 65535 байт, а сколько это будет символов для utf-8?
http://dev.mysql.com/doc/refman/5.6/en/string-type-overview.html
> MySQL interprets length specifications in character column definitions in character units.
1000 значит 1000 символов.
> VARCHAR(M)
> A variable-length string. M represents the maximum column length in characters. The range of M is 0 to 65,535. The effective maximum length of a VARCHAR is subject to the maximum row size (65,535 bytes, which is shared among all columns) and the character set used. For example, utf8 characters can require up to three bytes per character, so a VARCHAR column that uses the utf8 character set can be declared to be a maximum of 21,844 characters.
Указать VARCHAR можно до 65535, но в одной строке таблицы может быть не более 65535 байт, потому для utf8 там будет лишь максимум 21844 символа. Обрати внимание, этот лимит не распространяется на TEXT/BLOB так как они хранятся отдельно.
> A TEXT column with a maximum length of 65,535 (216 – 1) characters.
В колонке TEXT хранится до 65535 символов.
> MEDIUMTEXT
> A TEXT column with a maximum length of 16,777,215 (224 – 1) characters.
А тут до 16 млн. символов
> LONGTEXT
> A TEXT column with a maximum length of 4,294,967,295 or 4GB (232 – 1) characters.
Тут до 4 Гб, то есть около полтора миллиардов utf8-символов.
С Доктриной разбираться и настраивать гораздо дольше чем написать пару SQL запросов. Если использовать PDO и плейсхолдеры, хакеры не страшны.
> Нужна простая библиотека для чайника, чтобы я написал: ищем "samsung"
Это называется программист
>> 389202
У псевдоэлементов свой фон, независимый от элемента-владельца.
>>389224
Базу и (репозитории с кодом) надо бекапить. Иначе можно поиметь много проблем.
>>389285
Неверно, от 1 до 6 байт
>>389283
Скачал сейчас архив с сайта по ссылке http://www.apachelounge.com/download/VC11/binaries/httpd-2.4.10-win32-VC11.zip
Распаковал. Вижу папки:
bin\
cgi-bin\
conf\
error\
htdocs\
icons\
include\
logs\
manual\
lib\
modules\
Ты точно уверен что conf нету? У меня почему-то есть.
С Доктриной разбираться и настраивать гораздо дольше чем написать пару SQL запросов. Если использовать PDO и плейсхолдеры, хакеры не страшны.
> Нужна простая библиотека для чайника, чтобы я написал: ищем "samsung"
Это называется программист
>> 389202
У псевдоэлементов свой фон, независимый от элемента-владельца.
>>389224
Базу и (репозитории с кодом) надо бекапить. Иначе можно поиметь много проблем.
>>389285
Неверно, от 1 до 6 байт
>>389283
Скачал сейчас архив с сайта по ссылке http://www.apachelounge.com/download/VC11/binaries/httpd-2.4.10-win32-VC11.zip
Распаковал. Вижу папки:
bin\
cgi-bin\
conf\
error\
htdocs\
icons\
include\
logs\
manual\
lib\
modules\
Ты точно уверен что conf нету? У меня почему-то есть.
ищу совета опытных PHP программистов
есть один запрос
$fp = fsockopen('2ch.hk', 80, $errno, $errstr, 0.1);
$out = "GET /pr HTTP/1.1\r\n";
$out.= "HEADERHUEADER: ZNACHENIE\r\n";
$out.= "Host: 2ch.hk\r\n";
$out.= "Connection: Close\r\n\r\n";
fwrite($fp, $out);
fclose($fp);
я хочу на страницу послать заголовок с именем HEADERHUEADER и значением ZNACHENIE
но заголовок не отправляется.
в чём ошибка?
Если ты реально отправляешь запрос на 2ch.hk, то по пути наверняка стоит нормализатор трафика, который отбрасывает невалидные HTTP-заголовки. Безопасность, десу.
нет, не туда
у меня есть приёмник, я пойму когда пришлю верный заголовок.
может ты подскажешь как дебажить это?
например увидеть что именно приходит
ну допустим скрипт в локалхост\1.пхп
а я посылаю в локалхост\2.пхп
Можешь попробовать каким-нибудь сниффером типа Wireshark хукнуть исходящий трафик. Но учитывая, что это трафик на локалхост, он может просто не отправляться в стек, а маршрутизироваться средствами ОС. Если так, то только шаманить.
я сильно сомневаюсь что мне что-то даст именно список заголовков
потому что он просто не посылается
дело в синтаксисе или чем-то ещё
кто-нибудь ебашил заголовки так или через фопен?
Wireshark не перехватывает трафик с локалхоста на локалхост.
Для таких целей обычно втыкают прокси и шлют данные через него (гуглить по http debug proxy). Если надо отлаживать https то начинается боль и унижение с генерацией и добавлением сертификатов.
>>389469
Все отправляется, ты просто что-то не так делаешь. Алсо, увидеть полученные PHP заголовки можно через var_dump($_SERVER)
Алсо, надо проверять все ошибки при вызове функций. там часто бывает полезная информация, а у тебя отображение ошибок скорее всего отключено. Включи сначала, а потом только запускай.
один файл 1.пхп
<?php
$urlToSend='2.php';
$domen='localhost';
$fp = fsockopen($domen, 80, $errno, $errstr, 0.1);
$out = "GET $urlToSend HTTP/1.1\r\n";
$out.= "Host: ".$domen."\r\n";
$out.= "Connection: Close\r\n\r\n";
fwrite($fp, $out);
fclose($fp);
2.php
file_put_contents('sdfsdf',json_encode($_SERVER).PHP_EOL);
при запуске первого второй не вызывается
где я ошибся?
http://ideone.com/fork/bfvRC6
и чем ты лучше пхп-макак?
что за недоумки кругом?
ему же ткнули блять в ошибку носом
что эта сука делает?
и не говорите что все начинают с такого.
если этот объебос не может из документации скопировать пример цикла то может ему лучше очком торговать идти?
Пиздос, такой то обосрамс вышел, нашел ошибку и исправил.
document root must be a directory
В httpd.conf прописал:
<VirtualHost :80>
DocumentRoot с:/test/slim.local
ServerName slim.local
</VirtualHost>
В hosts тоже прописал, что нужно. Папка test создана. В чем проблема?
>slim.local
>must be a directory
я себя чувствую таким умным
теперь буду итт каждый день сидеть
алсо тебя, долбоёба, спосло бы гугление фразы
>document root must be a directory
но ты же долбоёб и не способен на это, верно?
Пиши верно:
http://ideone.com/FCJxD3
Йода:
http://ideone.com/AklCtm
Котики:
http://wpapers.ru/wallpapers/animals/Cats/
Гугуление же было уже. Оно все не то выводит. А я делал по инструкциям ОПа.
Оформление у тебя в коде поплыло, пропускай в следующий раз код через phpformatter.com
Калькулятор
> $array[0]
Это слишком часто повторяется, надо вынести в отдельную переменную а не копипастить.
Чтобы не писать вот это некрасивое $key + 1, можно было поступить лучше:
$tokens = $array[0];
$firstNumber = array_shift($tokens); // Забирает первый элемент из массива
foreach ($tokens as $key => $token) {
Также, у тебя сейчас нет никакой проверки на лишние символы — по идее их не должно быть, но ведь все возможно. Лучше писать регулярку так: /([0-9]+)|(\+|\-|\|\/|\=)|\S/ — тогда мы поймаем лишние символы и сможем вывести сообщение об ошибке. Ну и числа хорошо бы проверять через is_numeric на всякий случай. А то смотри что может выйти: http://ideone.com/LkHCCW
else можно убрать, без него все будет работать так же.
Исправление пробелов/букв:
> $array
> $array2
> $value
Надо давать нормальные имена переменным, твой код ведь читают люди, а не роботы. Тут прекрасно подойдут названия $sentences и $words
> "UTF-8");
Если ты указал в начале программы кодировку, это можно не писать
Так, все верно работает.
Йода:
> makeFirstletterUppercase($text)
Тут можно сделать проще: взять первую букву, перевести в верхний регистр (mb_strtoupper) и присоединить остаток строки — должно короче получиться.
> (\.\s)
Это не очень надежно. Лучше писать \s, тогда программа не сломается от отсутвия пробела (но сломается от многоточия).
То же замечание, не называй переменные $array и $value, есть $sentence и $word.
> /\.|\!|\?|\,|\;|\:/
Это можно записать в квадратных скобках и без бекслешей (в квадратных скобках экранируются только 5 символов [ ] \ - ^ ).
Номера
> (\s)
Скобки не нужны тут
> |-|\(|
Это лучше писать в квадратных скобках — короче будет.
> [0-9]$
Не сработает же если за последней цифрой еще пробел идет. Или если перед плюсом пробел. Впрочем, в данных номерах их и нету
> Элемент 0 неверен
Надо не индекс, а номер телефона выводить в таких случаях.
А так, регулярка почти (кроме случая пробелов с краев) верная. Молодец, что догадался preg_grep прикрутить.
Номера с заменой
Тут те же замечания к регулярке (пробелы с краев) и тут лучше простую регулярку прямо в preg_replace вписывать, без вот таких лишних переменных: $regular = '/\+7/';
> слишком муторно
Ну и зря. может у тебя сложности с разбиением больших программ на части? Тогда лучше было бы научиться, а не уходить от проблемы.
Оформление у тебя в коде поплыло, пропускай в следующий раз код через phpformatter.com
Калькулятор
> $array[0]
Это слишком часто повторяется, надо вынести в отдельную переменную а не копипастить.
Чтобы не писать вот это некрасивое $key + 1, можно было поступить лучше:
$tokens = $array[0];
$firstNumber = array_shift($tokens); // Забирает первый элемент из массива
foreach ($tokens as $key => $token) {
Также, у тебя сейчас нет никакой проверки на лишние символы — по идее их не должно быть, но ведь все возможно. Лучше писать регулярку так: /([0-9]+)|(\+|\-|\|\/|\=)|\S/ — тогда мы поймаем лишние символы и сможем вывести сообщение об ошибке. Ну и числа хорошо бы проверять через is_numeric на всякий случай. А то смотри что может выйти: http://ideone.com/LkHCCW
else можно убрать, без него все будет работать так же.
Исправление пробелов/букв:
> $array
> $array2
> $value
Надо давать нормальные имена переменным, твой код ведь читают люди, а не роботы. Тут прекрасно подойдут названия $sentences и $words
> "UTF-8");
Если ты указал в начале программы кодировку, это можно не писать
Так, все верно работает.
Йода:
> makeFirstletterUppercase($text)
Тут можно сделать проще: взять первую букву, перевести в верхний регистр (mb_strtoupper) и присоединить остаток строки — должно короче получиться.
> (\.\s)
Это не очень надежно. Лучше писать \s, тогда программа не сломается от отсутвия пробела (но сломается от многоточия).
То же замечание, не называй переменные $array и $value, есть $sentence и $word.
> /\.|\!|\?|\,|\;|\:/
Это можно записать в квадратных скобках и без бекслешей (в квадратных скобках экранируются только 5 символов [ ] \ - ^ ).
Номера
> (\s)
Скобки не нужны тут
> |-|\(|
Это лучше писать в квадратных скобках — короче будет.
> [0-9]$
Не сработает же если за последней цифрой еще пробел идет. Или если перед плюсом пробел. Впрочем, в данных номерах их и нету
> Элемент 0 неверен
Надо не индекс, а номер телефона выводить в таких случаях.
А так, регулярка почти (кроме случая пробелов с краев) верная. Молодец, что догадался preg_grep прикрутить.
Номера с заменой
Тут те же замечания к регулярке (пробелы с краев) и тут лучше простую регулярку прямо в preg_replace вписывать, без вот таких лишних переменных: $regular = '/\+7/';
> слишком муторно
Ну и зря. может у тебя сложности с разбиением больших программ на части? Тогда лучше было бы научиться, а не уходить от проблемы.
> Роутер как минимум не должен роуты в себе захардкоженные содержать.
Не должны. Точнее, не всегда должны. Если мы хотим написать библиотеку для повторного использования, то да, нужен конфиг. Но если у тебя 5 роутов, которые не будут часто меняться, то их можно и в код встроить. Не городить же анону ради простого приложения загрузку конфигов в разных форматах, компиляцию роутера в PHP-файл и все остальное, что есть в симфониевском роутере например.
>>389103
Если не можешь понять, покажи код и напиши что именно непонятно. Регулярки — сложная, но важная тема, они везде используютяс, и лучше попросить подсказку и разобраться, чем забить на это дело и потом все время с ними мучаться.
>>389131
Потому, что $element — это не элемент в массиве, а его копия. И меняя ее, ты меняешь лишь копию а не сам массив. Чтобы менять массив надо либо использовать доступ через индекс:
foreach ($array as $key => $element) {
$array[$key] = ....;
}
Либо использовать (но лучше не использовать так как тут есть побочные эффекты) специальный знак & который сделает переменную не копией, а ссылкой на исходный элемент:
foreach ($array as &$element) {
$element = ...;
}
Чтобы понять как работают ссылки, надо прочесть весь рездел мануала: http://php.net/manual/ru/language.references.php Поверь, проще использовать первый способ.
>>389188
Хорошая, но сложная и для твоей задачи как пушка для воробья.
>>389191
> listElements [ j ].power.timeOfDay
Не надо лезть внутрь другого объекта — лучше делать это через вызов метода — так гибче получается.
> power.timeOfday
Это равносильно power['timeOfDay'] то есть не то что ты задумал
> var constructor = this.constructor;
> Powerhouse.prototype = Object.create(ElementsNetwork.prototype);
> Powerhouse.prototype.constructor = constructor;
Я тебя наверно запутал. Этот код должен быть не внутри функции-конструктора, а сразу после него (так как он должен выполниться один раз, а не при каждом создании объекта).
> "afternoon"
А вот это нехорошо — это магическая строка, которая взялась непонятно откуда. Надо либо использовать константы (которые мы использовали в задаче про гамбургер), либо в данной задаче можно обойтись true/false.
> Извини за тупость, но я не понимаю, что должен делать метод ЭлементаСети, если уже все у меня получается уже посчитано.
Если у тебя уже все посчитано, покажи код, посмотрим. Этот пока ничего не считает.
> что должен делать метод ЭлементаСети
Метод нужен чтобы не лезть внутрь объекта в свойство power. С методом получается гибче (мы можем возвращать разные числа в зависимости от условий) и надежнее (когда один объект лезет в потроха другого, это не очень хорошо и делает код запутаннее).
> Роутер как минимум не должен роуты в себе захардкоженные содержать.
Не должны. Точнее, не всегда должны. Если мы хотим написать библиотеку для повторного использования, то да, нужен конфиг. Но если у тебя 5 роутов, которые не будут часто меняться, то их можно и в код встроить. Не городить же анону ради простого приложения загрузку конфигов в разных форматах, компиляцию роутера в PHP-файл и все остальное, что есть в симфониевском роутере например.
>>389103
Если не можешь понять, покажи код и напиши что именно непонятно. Регулярки — сложная, но важная тема, они везде используютяс, и лучше попросить подсказку и разобраться, чем забить на это дело и потом все время с ними мучаться.
>>389131
Потому, что $element — это не элемент в массиве, а его копия. И меняя ее, ты меняешь лишь копию а не сам массив. Чтобы менять массив надо либо использовать доступ через индекс:
foreach ($array as $key => $element) {
$array[$key] = ....;
}
Либо использовать (но лучше не использовать так как тут есть побочные эффекты) специальный знак & который сделает переменную не копией, а ссылкой на исходный элемент:
foreach ($array as &$element) {
$element = ...;
}
Чтобы понять как работают ссылки, надо прочесть весь рездел мануала: http://php.net/manual/ru/language.references.php Поверь, проще использовать первый способ.
>>389188
Хорошая, но сложная и для твоей задачи как пушка для воробья.
>>389191
> listElements [ j ].power.timeOfDay
Не надо лезть внутрь другого объекта — лучше делать это через вызов метода — так гибче получается.
> power.timeOfday
Это равносильно power['timeOfDay'] то есть не то что ты задумал
> var constructor = this.constructor;
> Powerhouse.prototype = Object.create(ElementsNetwork.prototype);
> Powerhouse.prototype.constructor = constructor;
Я тебя наверно запутал. Этот код должен быть не внутри функции-конструктора, а сразу после него (так как он должен выполниться один раз, а не при каждом создании объекта).
> "afternoon"
А вот это нехорошо — это магическая строка, которая взялась непонятно откуда. Надо либо использовать константы (которые мы использовали в задаче про гамбургер), либо в данной задаче можно обойтись true/false.
> Извини за тупость, но я не понимаю, что должен делать метод ЭлементаСети, если уже все у меня получается уже посчитано.
Если у тебя уже все посчитано, покажи код, посмотрим. Этот пока ничего не считает.
> что должен делать метод ЭлементаСети
Метод нужен чтобы не лезть внутрь объекта в свойство power. С методом получается гибче (мы можем возвращать разные числа в зависимости от условий) и надежнее (когда один объект лезет в потроха другого, это не очень хорошо и делает код запутаннее).
>>389202
> Это в em'ах?
Это относительно размера шрифта. Для line-height можно писать просто числа: http://htmlbook.ru/css/line-height
> Я просто строчку в html-файле закомментировал.
Ну когда раскомментируешь, тогда и посмотрим на нее.
> Или если я задам основному блоку фон, а потом буду иконкис помощью псевдоэлементов делать background-position будет работать?
У псевдоэлемента свой фон, независимый от родителя. И размеры свои.
>> Верхнее меню About is | services не должно уменьшаться, а должно определяться размером текста в нем.
> Ну а текст же всегда одного размера. Ка это понимать?
Смотри, если подумать головой, от чего зависит ширина пункта меню «About us»? Если подумать, то она равна ширине текста + какие-то небольшие поля с краев (включая иконку). Логично? Логично. А как ее задал ты?
> .top-menu .about {
> width: 37.74%;
Ты задаешь ее через ширину окна. Хотя с уменьшением ширины окна буквы меньше не становятся, и из-за этого они перестают помещаться в плашку.
Когда ты задаешь размер элемента, ты должен подумать чем он определяется (внутренним текстом? родителем? фиксирован?) и выбирать соответствующий способ.
>> В черном блоке внизу надо сделать чтобы высота определядась содердимым.
> В подвале или который перед ним? Или всем блокам height: auto проставить?
Надо для каждого блока подумать чем определяются его размеры и использовать соответствующие CSS правила. Если есть сомнения - пиши, обсудим. Для каких-то блоков должно быть auto, для каких-то жестко задано.
> А смотри, я скачал перфект пиксель начал верстать по нему, и где-то, например, надписи не ровно по центру, а слева отступ чуть больше, чем справа.
Тут надо смотреть по логике. Дизайнер мог отцентрировать текст на глаз и он из-за этого не точно по центру. В таком случае он не совпадет идеально с макетом, ничего не поделать. Или он мог блок расположить на 1-2 пикселя вбок от направляющей — в таком случае надо увидеть эту воображаемую линию и расположить блок правильно. То есть надо понимать логику, как что расположено.
> При адаптивной верстке стоит на глаз определять? А при обычной стоит все таки высчитывать отступы?
Не важно, адаптивная верстка или нет — правила одинаковые. Если текст отцентрирован, то надо писать text-align center, а не подбирать отступ слева.
>>389221
Почему такое плохое оформление? Учись писать код аккуратно или хотя бы научись его автоматически форматировать. В любой IDE это делается нажатием пары кнопок.
Сама сортировка не совсем верно написана. Алгоритм выглдяит так:
Повторять .... пока есть непраивльно расположенные элементы.
А твой алгоритм это не проверяет и делает лишние действия, может там все уже отсортировалось давно.
Функции в PHP пишутся кемелкейсом (doSomething), а не через подчеркивания. Ты спросишь, а как же str_repeat и другие? Я отвеу, они придуманы 15 лет назад, стандарты поменялись.
Ну и мог бы что-нибудь поинтереснее взять, например сортировку вставкой или quicksort. Смотри, сколько алгоритмов: https://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%81%D0%BE%D1%80%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B8#.D0.A1.D0.BF.D0.B8.D1.81.D0.BE.D0.BA_.D0.B0.D0.BB.D0.B3.D0.BE.D1.80.D0.B8.D1.82.D0.BC.D0.BE.D0.B2_.D1.81.D0.BE.D1.80.D1.82.D0.B8.D1.80.D0.BE.D0.B2.D0.BA.D0.B8
>>389202
> Это в em'ах?
Это относительно размера шрифта. Для line-height можно писать просто числа: http://htmlbook.ru/css/line-height
> Я просто строчку в html-файле закомментировал.
Ну когда раскомментируешь, тогда и посмотрим на нее.
> Или если я задам основному блоку фон, а потом буду иконкис помощью псевдоэлементов делать background-position будет работать?
У псевдоэлемента свой фон, независимый от родителя. И размеры свои.
>> Верхнее меню About is | services не должно уменьшаться, а должно определяться размером текста в нем.
> Ну а текст же всегда одного размера. Ка это понимать?
Смотри, если подумать головой, от чего зависит ширина пункта меню «About us»? Если подумать, то она равна ширине текста + какие-то небольшие поля с краев (включая иконку). Логично? Логично. А как ее задал ты?
> .top-menu .about {
> width: 37.74%;
Ты задаешь ее через ширину окна. Хотя с уменьшением ширины окна буквы меньше не становятся, и из-за этого они перестают помещаться в плашку.
Когда ты задаешь размер элемента, ты должен подумать чем он определяется (внутренним текстом? родителем? фиксирован?) и выбирать соответствующий способ.
>> В черном блоке внизу надо сделать чтобы высота определядась содердимым.
> В подвале или который перед ним? Или всем блокам height: auto проставить?
Надо для каждого блока подумать чем определяются его размеры и использовать соответствующие CSS правила. Если есть сомнения - пиши, обсудим. Для каких-то блоков должно быть auto, для каких-то жестко задано.
> А смотри, я скачал перфект пиксель начал верстать по нему, и где-то, например, надписи не ровно по центру, а слева отступ чуть больше, чем справа.
Тут надо смотреть по логике. Дизайнер мог отцентрировать текст на глаз и он из-за этого не точно по центру. В таком случае он не совпадет идеально с макетом, ничего не поделать. Или он мог блок расположить на 1-2 пикселя вбок от направляющей — в таком случае надо увидеть эту воображаемую линию и расположить блок правильно. То есть надо понимать логику, как что расположено.
> При адаптивной верстке стоит на глаз определять? А при обычной стоит все таки высчитывать отступы?
Не важно, адаптивная верстка или нет — правила одинаковые. Если текст отцентрирован, то надо писать text-align center, а не подбирать отступ слева.
>>389221
Почему такое плохое оформление? Учись писать код аккуратно или хотя бы научись его автоматически форматировать. В любой IDE это делается нажатием пары кнопок.
Сама сортировка не совсем верно написана. Алгоритм выглдяит так:
Повторять .... пока есть непраивльно расположенные элементы.
А твой алгоритм это не проверяет и делает лишние действия, может там все уже отсортировалось давно.
Функции в PHP пишутся кемелкейсом (doSomething), а не через подчеркивания. Ты спросишь, а как же str_repeat и другие? Я отвеу, они придуманы 15 лет назад, стандарты поменялись.
Ну и мог бы что-нибудь поинтереснее взять, например сортировку вставкой или quicksort. Смотри, сколько алгоритмов: https://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%81%D0%BE%D1%80%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B8#.D0.A1.D0.BF.D0.B8.D1.81.D0.BE.D0.BA_.D0.B0.D0.BB.D0.B3.D0.BE.D1.80.D0.B8.D1.82.D0.BC.D0.BE.D0.B2_.D1.81.D0.BE.D1.80.D1.82.D0.B8.D1.80.D0.BE.D0.B2.D0.BA.D0.B8
Посмотрим. Тут все такое неудобное, в частности ответ на пост, что я теперь пишу текст ответа в Саблайме.
>>389271
Рад за тебя
>>389299
> Что касается VARCHAR, длину можно задавать в байтах или в символах. Если единица не указана, то считается, что она в символах.
Как это в байтах? Вроде в мануале MySQL написано что только в символах.
>>389358
Мануал предоставишь? Только не такой какие в интернете есть, а нормальный, на уровне моих уроков, где все объясняется с нуля.
>>389544
Если у тебя есть Linux или Cygwin то можно сделать проще. Можно открыть порт через
nc -vv -l -p 1234
И к нему коннектиться. nc выведет все что передано, в консоль. Но это надо уметь пользоваться комнадной строкой и линуксом и установить netcat (потому я всем советую при возможности научиться - пригодится не раз). Может есть аналогичные программы и под Windows. Вот например ncat для командной строки: http://nmap.org/ncat/guide/ncat-usage.html
Также, ты можешь (а может и нет конечно) перехватить трафик Wireshark если будешь коннектиться к себе не через локальный интефрейс (localhost/127.0.0.1), а через IP своей сетевой карты (10.0.x.x или 192.168.x.x, посмотреть можно в настройках сетевых подключений).
Алсо, почему у тебя таймаут 0.1 секунды. Ты уверен, что он успевает приконнектиться?
Посмотрим. Тут все такое неудобное, в частности ответ на пост, что я теперь пишу текст ответа в Саблайме.
>>389271
Рад за тебя
>>389299
> Что касается VARCHAR, длину можно задавать в байтах или в символах. Если единица не указана, то считается, что она в символах.
Как это в байтах? Вроде в мануале MySQL написано что только в символах.
>>389358
Мануал предоставишь? Только не такой какие в интернете есть, а нормальный, на уровне моих уроков, где все объясняется с нуля.
>>389544
Если у тебя есть Linux или Cygwin то можно сделать проще. Можно открыть порт через
nc -vv -l -p 1234
И к нему коннектиться. nc выведет все что передано, в консоль. Но это надо уметь пользоваться комнадной строкой и линуксом и установить netcat (потому я всем советую при возможности научиться - пригодится не раз). Может есть аналогичные программы и под Windows. Вот например ncat для командной строки: http://nmap.org/ncat/guide/ncat-usage.html
Также, ты можешь (а может и нет конечно) перехватить трафик Wireshark если будешь коннектиться к себе не через локальный интефрейс (localhost/127.0.0.1), а через IP своей сетевой карты (10.0.x.x или 192.168.x.x, посмотреть можно в настройках сетевых подключений).
Алсо, почему у тебя таймаут 0.1 секунды. Ты уверен, что он успевает приконнектиться?
>>389626
> при запуске первого второй не вызывается
> где я ошибся?
Ты сразу же закрываешь соединение. Это может привести к завершению скрипта. Надо ждать ответа. Почитай про HTTP
>>389656
Ты переписывал невнимательно, там $i а не $1. Переменная вообще с буквы должна начинаться, а не с цифры.
>>389677
Посмотри пример Hello World http://docs.slimframework.com/#Hello-World и добейся чтобы он заработал, а потом что-нибудь поменяй.
> Наверное нужно прошерстить весь код, чтобы понять, да?
Не надо, достаточно документацию почитать по диагонали. ЧТо именно тебе непонятно?
Так как Slim — микрофреймворк, то в нем совсем немного компонентов. Главное — это роутер (часть которая разбирает URL запроса и вызвает нужную функцию), ну и немного кода для организации обработки ошибок, вывода данных, получения данных из GET/POST/COOKIE. Главное преимущество — минимализм. Вдохновлен (читай скопирован) с рубиевского Синатры.
Написание кода под Slim сводится к тому, что ты пишешь несколько блоков кода $slim->get/$slim->post для каждой страницы сайта прямо в index.php. А все остальные файлы пишешь сам, без особых обращений к слиму.
Вот еще есть презентация, но она не очень понятная: http://www.slideshare.net/jeremykendall/keeping-it-small-slim-php
>>389750
Семен, выйди вон
>>389788
Папку slim.local создал внутри test?
>>389790
Проваливай, клоун
>>389626
> при запуске первого второй не вызывается
> где я ошибся?
Ты сразу же закрываешь соединение. Это может привести к завершению скрипта. Надо ждать ответа. Почитай про HTTP
>>389656
Ты переписывал невнимательно, там $i а не $1. Переменная вообще с буквы должна начинаться, а не с цифры.
>>389677
Посмотри пример Hello World http://docs.slimframework.com/#Hello-World и добейся чтобы он заработал, а потом что-нибудь поменяй.
> Наверное нужно прошерстить весь код, чтобы понять, да?
Не надо, достаточно документацию почитать по диагонали. ЧТо именно тебе непонятно?
Так как Slim — микрофреймворк, то в нем совсем немного компонентов. Главное — это роутер (часть которая разбирает URL запроса и вызвает нужную функцию), ну и немного кода для организации обработки ошибок, вывода данных, получения данных из GET/POST/COOKIE. Главное преимущество — минимализм. Вдохновлен (читай скопирован) с рубиевского Синатры.
Написание кода под Slim сводится к тому, что ты пишешь несколько блоков кода $slim->get/$slim->post для каждой страницы сайта прямо в index.php. А все остальные файлы пишешь сам, без особых обращений к слиму.
Вот еще есть презентация, но она не очень понятная: http://www.slideshare.net/jeremykendall/keeping-it-small-slim-php
>>389750
Семен, выйди вон
>>389788
Папку slim.local создал внутри test?
>>389790
Проваливай, клоун
пиши верно
Насчет сохранения знаков, есть такая идея. Если в preg_split регулярку заключить в круглые скобки (один раз) и добавить флаг PREG_SPLIT_DELIM_CAPTURE то она сохранит эти знаки-разделители:
....preg_split($regexp, $text, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE)...
Соответственно не надо будет сохранять их в отдельный массив. Подробности в мануале если что.
Второй вариант — разбивать текст разделителем, который не поглощает символы, а именно, утверждениями ( https://php.net/manual/ru/regexp.reference.assertions.php ). Тогда знаки препинания останутся в конце предложения.
Лучше когда функция не выводит текст, а возвращает через return — тогда у нас больше вариантов ее использования — мы можем например этот текст в файл сохранить или еще что-то с ним сделать. Потому замени в фукнции echo на return
> if (preg_match_all($regexp, $text, $signes)) {
If используют обычно с preg_match, а тут он не нужен. Более того, если в строке нет знаков препинания. т твоя программа падает с ошибкой: http://ideone.com/07V6N0 — это надо исправить.
> $lines as $key => $line
$key не используется потому ее можно не писать тут
В остальном верно.
Йода:
Что-то многовато кода для такой простой задачи.
Насчет знаков, то же самое - проще наверно использовать PREG_SPLIT_DELIM_CAPTURE либо утверждения.
> $signsInt_rev
Не стоит смешивать камелкей и подчеркивание
Если в предложении одно слово, то программа ломается: http://ideone.com/Go685c
> Котики
А я подумал, это решение какой-то задачи
пиши верно
Насчет сохранения знаков, есть такая идея. Если в preg_split регулярку заключить в круглые скобки (один раз) и добавить флаг PREG_SPLIT_DELIM_CAPTURE то она сохранит эти знаки-разделители:
....preg_split($regexp, $text, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE)...
Соответственно не надо будет сохранять их в отдельный массив. Подробности в мануале если что.
Второй вариант — разбивать текст разделителем, который не поглощает символы, а именно, утверждениями ( https://php.net/manual/ru/regexp.reference.assertions.php ). Тогда знаки препинания останутся в конце предложения.
Лучше когда функция не выводит текст, а возвращает через return — тогда у нас больше вариантов ее использования — мы можем например этот текст в файл сохранить или еще что-то с ним сделать. Потому замени в фукнции echo на return
> if (preg_match_all($regexp, $text, $signes)) {
If используют обычно с preg_match, а тут он не нужен. Более того, если в строке нет знаков препинания. т твоя программа падает с ошибкой: http://ideone.com/07V6N0 — это надо исправить.
> $lines as $key => $line
$key не используется потому ее можно не писать тут
В остальном верно.
Йода:
Что-то многовато кода для такой простой задачи.
Насчет знаков, то же самое - проще наверно использовать PREG_SPLIT_DELIM_CAPTURE либо утверждения.
> $signsInt_rev
Не стоит смешивать камелкей и подчеркивание
Если в предложении одно слово, то программа ломается: http://ideone.com/Go685c
> Котики
А я подумал, это решение какой-то задачи
Может у тебя другой DocumentRoot (не тот что внтри VirtualHost, а тот что в другом месте конфига) не туда указывает?
Там выше ещё есть один documentRoot, указывающий на папку htdocs. Там я тоже менял на test. Та же фигня.
>ocument root must be a directory
Он не пишет на какой строке конфига ошибка? Апач можно вызвать из командной строки с флагом -t для проверки конфига:
c:\xyz\bin\httpd.exe -t
Также, можно вывести список всех удачно прочитанных вирт. хостов:
c:\xyz\bin\httpd.exe -t -D DUMP_VHOSTS
У Апача все доступные ему папки должны быть описаны в блоках <Directory> — к тем, которые там не описаны, у него по умолчанию нет доступа.
Ну и посмотри внимательно, может там где еще DocumentRoot есть
> Как это в байтах? Вроде в мануале MySQL написано что только в символах.
Ты прав. С оракловским VARCHAR2 перепутал.
Да там есть еще один DocumentRoot, который имеет путь: DocumentRoot "c:/Apache24/htdocs"
Его я пробовал комментировать, но это не помогает.
Пробовал дописывать вот это:
<Directory "c:/test/slim.local">
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>
Не помогает.
Вот конфиг, посмотри, Оп. http://rghost.ru/private/58193089/9e7cdbd4417c6a7309f92eb0b21b35ea
У тебя там подключены другие файлы:
# Virtual hosts
Include conf/extra/httpd-vhosts.conf
Может в них что не так?
(кстати по идее именно в vhosts и стоит прописывать виртуальные хосты)
Может стоит с:/test/slim.local взять в кавчки?
И попробуй команду проверки конфига из консоли выполнить.
>Мануал предоставишь? Только не такой какие в интернете есть, а нормальный, на уровне моих уроков, где все объясняется с нуля.
https://www.youtube.com/playlist?list=PLvAOICvbvsbml8kNKgXcUFG4Ujhn6j7lW
Это мануал-реклама платного сервиса Digital Ocean (если уж брать платные сервисы, имхо у нас актуальнее селектел). Плюс, это не мануал, в видеоурок в стиле «делай то же что на экране».
Для начинающего удобнее поставить линукс в тот же виртуалбокс бесплатно.
Объяснение на английском, причем устном, а не письменном (что сложнее). Никаких рисунков и схем конечно нету.
Он подписан как outdated
Не объясняется как работает Putty, не объясняется работа в командной строке, не объясняется синтаксис bash сотоварищи, не объясняется копценпция cli программ. Какой смысл запускать программу. не понимая, как она работает? То же самое и с настройками — автор правит конфиги ничего не поясняя.
Автор видео не умеет настраивать utf8 в Putty.
Зато много внимания удаляется объяснению интерфейса DO. Это конечно самая важная часть тут.
Ну и сама установка там тоже сделана странно. Вместо того чтобы как нормальный пацан использовать apt-get, он использует псевдо-гуи (которое у него разъехалось от неправильной кодировки).
Если уж использовать GUI инсталляторы, так не проще ли использовать номальные Windows-версии программ? А ты предлагаешь вместо этого смотреть видео про кривые разъезжающиеся текстовые псевдоинтерфейсы? В чем смысл менять хорошее на плохое? У тебя какой-то нездоровый фанатизм к линуксу и видео где говорят по-английски, что ты его уровень оценить не способен.
Имхо, это и есть «типичный мануал из интернета», который толком ничему не учит и ничуть не лучше пиратcких видеокурсов по php. Не рекомендую никому его смотреть.
Судя по тому, что у автора в других видео идет реклама других сервисов (типа CloudFlare который 99% пользователей не нужен) он тупо снимает эти видео ради каких-то реферальных выплат от рекламируемых сервисов. Отсюда и такой уровень.
Постарался переделать оформление и еще перепилил отдельно алгоритм сортировки, по моей логике все должно хорошо работать, но почему-то по факту не хочет. В чем косяк?
http://ideone.com/r0sYed
> if ($flag = 0) {
= и == перепутал
Алсо, насчет оформления, для начала пропусти код через phpformatter.com — и руками скорее всего переделывать ничего не придется.
Объясни, почему ты считаешь, что Cloudflare не нужен кроме появившихся проблем с забаненными в России серверами (назойливая DDoS-protection тоже не аргумент, она отключается)? Настраивается за десять минут, работает с любым копеечным хостингом, экономит трафик за счет раздачи статики (весьма актуально, если на сайте есть какая-нибудь фото-галерея, например).
Имхо, потому что лишний слой на пути к сайту. Увеличивает время доступа, шанс возникновения каких-то проблем. Может в любое время начать какую-нибудь монетизацию или встраивать тебе на страницу какие-нибудь скрипты.
Если у тебя копеечный хостинг то вряд ли там столько трафика чтобы что-то сэкономить.
Спасибо большое, теперь работает. http://ideone.com/LNW1LD
Дело в том что я уже пробовал
>phpformatter.com
но он выдал ошибку на строчке $a = [];
поэтому к нему у меня сразу упало все доверие.
Проблемы возникают только с правками статики на сайте (но кто же на продакшне правит?), приходится кэш чистить. Насчет времени доступа не уверен, это ведь CDN, должно быть наоборот. С трафиком на хостингах за $3 бывает так, что на тебя куда-нибудь вбросили ссылку, и ты получил %сервиснейм%-эффект, съеденный за полсуток месячный трафик и нерабочий сайт (или даже все сайты, если их несколько на аккаунте). Клаудфлара от этого отлично спасает.
Но спасибо за мнение. Добра.
> Include conf/extra/httpd-vhosts.conf
Это я пробовал прописать в vhosts.
В кавычки тоже брал. Проверку делал, пишет
document root must be a directory
Строку указывает как раз там, где DocumentRoot с:/test/slim.local.
Оп, в чем проблема? Что мне делать?
Точку в конце убери, уебок. Еще можешь слеш попробовать добавить в конец.
А вообще апач не нужен.
Точка - это конец предложения. В конфиге ее нет. Слеш тоже не помогает. Я уже все пробовал.
Slim Extras
Twig 1.1
Paris and Idiorm
?
Я их установил компосером, но не знаю для чего они.
Нормально, что сам slim лежит в папке vendor?
В общем вот:
https://github.com/fxsloker/rgclone.ru
> phpformatter
Действительно, видимо он синтаксис 5.4 пока не поддерживает. Тогда есть пост >>386603 где описаны кратко правила форматирования и клавиши для этого в разных IDE.
В функциях обычно скобки ставят так:
function x()
{
....
}
Имена функций обычно начинаются с глагола, в стиле «делайЧтоТо», то есть не arrayGen а generateArray.
Ты используешь табы и из-за этого все разъехалось на ideone. Лучше в редакторе включить опцию «заменять таб на 4 пробела» — при этом кнопка Tab будет работать так же, но проблем с разъехжающимся текстом не будет. Если ты пишешь на самом ideone, это сделать не получится, только в редакторе кода.
> $array[$i] = mt_rand(10,99);
$i тут можно не писать — будет чуть короче
> while ($sorted == FALSE) {
В условиях
вместо $x == true или $x != 0 можно просто писать if ($x)
вместо $x == false или $x == 0 можно писать if (!$x)
Тут не обязательно делать такую замену, но скорее всего в чужом коде ты можешь с такой конструкцией столкнуться.
Из 2 переменных $flag и $sorted можно оставить только $sorted
Если ты тестируешь скорость работы функции, ее обычно вызывают не 1 раз, а например 100 или 1000 — чтобы разница была заметнее и не влияли всякие случайности.
А так, норм сделано.
>>389977
Пока особо некогда. Позже может быть, у меня вообще была мысль сделать урок про освоение линукса (с нуля).
>>390007
ООП достаточно должно быть, ну еще иметь представление о HTTP, куках, HTTP-заголовках, как работает веб-сервер и браузер когда открывает страницу на сайте.
> phpformatter
Действительно, видимо он синтаксис 5.4 пока не поддерживает. Тогда есть пост >>386603 где описаны кратко правила форматирования и клавиши для этого в разных IDE.
В функциях обычно скобки ставят так:
function x()
{
....
}
Имена функций обычно начинаются с глагола, в стиле «делайЧтоТо», то есть не arrayGen а generateArray.
Ты используешь табы и из-за этого все разъехалось на ideone. Лучше в редакторе включить опцию «заменять таб на 4 пробела» — при этом кнопка Tab будет работать так же, но проблем с разъехжающимся текстом не будет. Если ты пишешь на самом ideone, это сделать не получится, только в редакторе кода.
> $array[$i] = mt_rand(10,99);
$i тут можно не писать — будет чуть короче
> while ($sorted == FALSE) {
В условиях
вместо $x == true или $x != 0 можно просто писать if ($x)
вместо $x == false или $x == 0 можно писать if (!$x)
Тут не обязательно делать такую замену, но скорее всего в чужом коде ты можешь с такой конструкцией столкнуться.
Из 2 переменных $flag и $sorted можно оставить только $sorted
Если ты тестируешь скорость работы функции, ее обычно вызывают не 1 раз, а например 100 или 1000 — чтобы разница была заметнее и не влияли всякие случайности.
А так, норм сделано.
>>389977
Пока особо некогда. Позже может быть, у меня вообще была мысль сделать урок про освоение линукса (с нуля).
>>390007
ООП достаточно должно быть, ну еще иметь представление о HTTP, куках, HTTP-заголовках, как работает веб-сервер и браузер когда открывает страницу на сайте.
На сайте Slim Extras написано: https://github.com/codeguy/Slim-Extras
Deperecated (устарело)
Точно не нужно.
Насчет Twig — это шаблонизатор, неплохой, ты можешь использовать его если хочешь, если нет то можешь использовать стандартные php-шаблоны (а лучше всего сделай сначала пару обычных шаблонов а потом мигрируй на твиг чтобы изучить и то и другое).
> Paris and Idiorm
Нет конечно. Зачем? Удаляй.
> но не знаю для чего они.
Если не знаешь то не устанавливай
> Нормально, что сам slim лежит в папке vendor?
Да. Композер скачивает все библиотеки в эту папку и туда же кладет сгенерированный автозагрузчик (изучи в мануале php что такое автозагрузка классов если не знаешь). Не забудь добавить vendor в gitignore чтобы не замусоривать репозиторий.
Так как ты уже его добавил, то сначала удали все из vendor, закоммить, а только потом добавь ее в gitignore.
Ну и давай уже хотя бы Hello World сделай.
Еще посмотри раздел в доументации про Middleware. Этот концепт взят с других микрофреймворков и суть в том, что ты можешь обернуть весь цикл обработки запроса в свою функцию. То есть она вызывается до начала обработки запроса, что-то делает если хочет, вызвает остальные слои (в т.ч сам Слим), получает результат (сгенерированную страницу), и что-то с ней делает если хочет и выводит результат.
Например, с помощью middleware легко сделать такую штуку: сделать чтобы на любой странице при добавлении параметра ?translit=yes русский текст заменялся на транслит (хард моде: сохранять флаг транслита в куки чтобы при переходе со страницы по ссылке режим транслита оставался включенным и отключался только ссылкой ?translit=no). Можешь потом это задание сделать если хочешь разобраться в middleware.
C помощью middleware например в Слиме реализована поддержка сессий на куках ( https://github.com/codeguy/Slim/blob/master/Slim/Middleware/SessionCookie.php ).
Понемногу разбираюсь в yii2 и js, хочется что-нибудь такое, чтобы закрепить знания, в особенности js.
Наши простые с виду но с подвохом внутри задания на JS решал? https://gist.github.com/codedokode/ce30e7a036f18f416ae0
Что скажешь?
По поводу Yii — есть такое задание, но оно очень сложное и длительное по времени: https://gomockingbird.com/mockingbird/#l0bk13j/3S7gC7 (это вайрфрейм, самого дизайна нет и неизвестно когда будет), можно придумать что-нибудь попроще. Например, сделать доску объявлений с категориями и поиском.
Спасибо, ещё не решал, займусь этим, а потом тогда то приложение с тестами по ссылке.
https://github.com/fxsloker/rgclone.ru
Пока все просто, нашел как это делается. Скопировал и вставил.
А как вот это делается не знаю:
$app->get('/hello/:name', function ($name) {
echo "Hello, $name";
});
А еще, хорошо, что slim лежит так далеко? \vendor\slim\slim\Slim\
Это нормально?
Если честно, то я не особо понимаю, что делают POST, GET запросы. Пойду читать.
В общем, у меня есть такая строчка в скрипте:
[code]exec("sudo -u user amixer sset ".escapeshellarg(escapeshellcmd($key))." unmute ".intval($value)."%", $out);[/code]
amixer - это линуксовая утилита, позволяющая контролировать громкость.
В sudoers, соответственно, есть строчка:
[code]www-data ALL=(ALL) NOPASSWD: /usr/bin/amixer[/code]
Раньше всё прекрасно работало, скрипт отлично ставил громкость. Пока я не обновил бубунту на этой машине.
Теперь выполнение скрипта с такой же строкой из консоли sudo -u www-data php test.php меняет громкость и возвращает вывод amixer, а вот запросив то же самое из браузера, я вижу пустой массив $out и неизменную громкость.
В общем, подскажи, анон, куда копать?
Сейчас вариантов два:
либо это что-то связанное с тем, что обновив Apache c 2.2 до 2.4 пришлось переписать в conf-available/security.conf строчку Require all granted вместо Allow from all И как это связано?
либо оно связано с фиксами уязвимости bash, которые вышли буквально вчера.
`Ах, коварный Абу меня меня в faq обманул.`
Хорошо, с форматированием кода я попытаюсь разобраться, раньше просто совсем не уделял этому внимания
А вот про это я немного не понял.
>Из 2 переменных $flag и $sorted можно оставить только $sorted
сделать так что если за время прохода внутреннего цикла for переменная не менялась, то прекращать внешний через брейк?
еще проблема такая возникает, если я ставлю скажем сортировать массив размером в 1000 элементов, то вместо логичного увеличения времени он выдает отрицательные результаты.
http://ideone.com/0c7Lnd
Мне не понятно, как работает функция get.
Вот она вызывает метод mapRoute($args), а аргументы в моем случае:
'/' и function() use ($app) {
\techo "<h1>Hello Slim World</h1>";
}
$pattern = '/';
$callable = function() use ($app) ...;
Это пока понятно. Далее создается экземпляр класса Route с параметрами ($pattern, $callable, $this->settings['routes.case_sensitive'])
Далее вот это непонятно: $this->router->map($route);
По alt+click sublime меня отправляет на функцию router. Но тут-то без (), значит это свойство класса, но его там нет.
Далее вызывается метод map(тут объект класса Router);
Метод map вообще делает что-то непонятное:
return $this->mapRoute($args); Он снова вызывает mapRoute, зачем? mapRoute оперирует с массивом, а у нас объект в $args.
Дальше уже смысла не было читать, т.к. я это не понял.
Оп, можешь построчно объяснить как работает метод get в Slim.php вместе с вызывающимися в ней методами?
Мне не понятно, как работает функция get.
Вот она вызывает метод mapRoute($args), а аргументы в моем случае:
'/' и function() use ($app) {
\techo "<h1>Hello Slim World</h1>";
}
$pattern = '/';
$callable = function() use ($app) ...;
Это пока понятно. Далее создается экземпляр класса Route с параметрами ($pattern, $callable, $this->settings['routes.case_sensitive'])
Далее вот это непонятно: $this->router->map($route);
По alt+click sublime меня отправляет на функцию router. Но тут-то без (), значит это свойство класса, но его там нет.
Далее вызывается метод map(тут объект класса Router);
Метод map вообще делает что-то непонятное:
return $this->mapRoute($args); Он снова вызывает mapRoute, зачем? mapRoute оперирует с массивом, а у нас объект в $args.
Дальше уже смысла не было читать, т.к. я это не понял.
Оп, можешь построчно объяснить как работает метод get в Slim.php вместе с вызывающимися в ней методами?
get задает обработчик для GET-запроса с указанным URL то есть если придет GET запрос c URL вида /hello/:name то будет вызвана указанная функция.
>>390179
Да, если ты используешь плейсхолдеры и не вставляешь переменные прямо в тело запроса.
>>390177
http://ideone.com/tFzBCZ
> Метод map вообще делает что-то непонятное:
> return $this->mapRoute($args);
Не вижу в методе map того, что ты написал: https://github.com/codeguy/Slim/blob/master/Slim/Router.php#L126 — вот тот map который вызывается в $this->router->map(...);
А вот строчка, добавляющая маршрут в список маршрутов:
https://github.com/codeguy/Slim/blob/master/Slim/Router.php#L131
$this->routes[] = $route;
Имей в виду что Sumlime Text при клике по слову просто ищет функцию или класс с таким именем. Он никак не анализирует код, а просто ищет по имени.
> А еще, хорошо, что slim лежит так далеко? \vendor\slim\slim\Slim\
Путь лежит. Тебе же руками это писать в любом случае нигде не надо и лезть туда не требуется. Композер делает это чтобы не было конфликтов между библиотеками с похожим названием.
>>390164\t
Во-первых проверь лог ошибок Апача — потом ошибок от вызываемых программ идет туда (скорее всего). Во-вторых, sudo при ошибке пишет сообщения куда-то в /var/log может в /var/log/messages может в /var/log/security.log или еще куда-нибудь, посмотри.
Если там нету то ты можешь дописать в конец команды 2>&1 чтобы перенаправить поток ошибок на стандартный вывод.
Может Апач теперь не из-под www-data запускается?
> либо оно связано с фиксами уязвимости bash, которые вышли буквально вчера.
Тогда бы при ручном запуске тоже не работало.
>>390171\t
> А вот про это я немного не понял.
>>Из 2 переменных $flag и $sorted можно оставить только $sorted
Вместо того чтобы писать flag ++ ты можешь писать sorted = true и выкинуть переменную flag вообще. Либо выкинуть sorted и в условии проверять flag.
Алсо,
> Сортировка пузырьком выполненна за -0.433958.
У тебя явно что-то неправильно считается.
> А еще, хорошо, что slim лежит так далеко? \vendor\slim\slim\Slim\
Путь лежит. Тебе же руками это писать в любом случае нигде не надо и лезть туда не требуется. Композер делает это чтобы не было конфликтов между библиотеками с похожим названием.
>>390164\t
Во-первых проверь лог ошибок Апача — потом ошибок от вызываемых программ идет туда (скорее всего). Во-вторых, sudo при ошибке пишет сообщения куда-то в /var/log может в /var/log/messages может в /var/log/security.log или еще куда-нибудь, посмотри.
Если там нету то ты можешь дописать в конец команды 2>&1 чтобы перенаправить поток ошибок на стандартный вывод.
Может Апач теперь не из-под www-data запускается?
> либо оно связано с фиксами уязвимости bash, которые вышли буквально вчера.
Тогда бы при ручном запуске тоже не работало.
>>390171\t
> А вот про это я немного не понял.
>>Из 2 переменных $flag и $sorted можно оставить только $sorted
Вместо того чтобы писать flag ++ ты можешь писать sorted = true и выкинуть переменную flag вообще. Либо выкинуть sorted и в условии проверять flag.
Алсо,
> Сортировка пузырьком выполненна за -0.433958.
У тебя явно что-то неправильно считается.
Ой, я неприавльно написал. Ты защищен от SQL инъекций. XSS — совсем другая вещь и PDO на нее никак не влияет.
про XSS и меры борьбы можно почитать мой мини-урок: https://gist.github.com/anonymous/52adda0113428b274c64
>38−10=28
Почиму, когда пересчитаешь, то выходит так:
1. 38
2. 37
3. 36
4. 35
5. 34
6. 33
7. 32
8. 31
9. 30
10. 29
11. 28
Шо ета за хуйня?
Спасибо!
Да пиздос. Почему так выходит?
1. 38−1=37
2. 37−1=36
3. 36−1=35
4. 35−1=34
5. 34−1=33
6. 33−1=32
7. 32−1=31
8. 31−1=30
9. 30−1=29
10. 30−1=28
Я делю задачи на блоки, а на деле выходит, что 10 блоков — это не десять операций, а 11. Ёбаный нуль. У меня возникает логическая ошибка.
>Вместо того чтобы писать flag ++ ты можешь писать sorted = true и выкинуть переменную flag вообще. Либо выкинуть sorted и в условии проверять flag.
Не могу, ибо логика всей этой конструкции с двумя переменными такова: сначала мы допускаем что поданный в функцию массив неотсортирован и ставим $sorted = false, далее запускается цикл while который будет работать до тех пор пока массив не отсортирован.
>Повторять .... пока есть непраивльно расположенные элементы.
внутри запускается цикл обхода массива for, который меняет элементы местами если левый больше правого и заодно отмечает в переменную $flag что была произведена какая-то сортировка. Если сюда вставить $sorted = true, то внешний цикл прервется после первой же итерации, а этого в 99% случаев будет недостаточно для полной сортировки. Как раз вся идея в том, что после нужного числа обходов, у нас уже не осталось ниодного неправильностоящего элемента, и переменная $flag после полного прохода внутреннего цикла for так и осталась = 0, это и означает что теперь массив отсортирован и цикл можно завершать.
Можно в начале цикла ставить $sorted = true а при перестановке элементов делать $sorted = false.
Просто есть еще метод map в Slim.php
Большое спасибо, а я и недопер до такого крутого упрощения, целую лишнюю переменную выкинуть можно и if в придачу.
вот вроде прилизал http://ideone.com/5QP1rI
какие еще есть косяки? Ща буду пробовать реализовать еще пару алгоритмов сортировки, а время я пока выкинул, потом отдельную функцию сделаю с ним.
Взял на заметку, еще одно крутое упрощение кода, хотя как я понял это скорее трюк нежели напрямую предназначенная для этого штука, ибо у неё в описании много всяких мутных оговорок, которые не доконца ясны.
Впилил еще 1 способ который как мне поначалу казалось не взлетит, а в итоге вроде всё работает нормально.
http://ideone.com/ESaLyN
Пользователь точно www-data, ибо exec("whoami") возвращал его.
В логах ничего интересного не нашёл плохо искал, да.
В поток ошибок посылалась строка: sudo: PERM_ROOT: setresuid(0, -1, -1): Operation not permitted
Быстрогугление подсказало, что это лечится отключением модуля mpm_itk апача. Так и сделал.
Спасибо, анон.
Файл с командой "exec" тоже лежит в папке "/folder"
>>390302
Я кажется понял. Программа написана для винды или dos (http://chicago.sourceforge.net/xlhtml/binarys.html) и её просто невозможно запустить на линуксе. Эта программа берёт XLS и конвертирует его в CSV, попробую найти решение на PHP (я уже искал, но проблема в огромных размерах принимаемых XLS файлов).
Я бы из этого сделал вывод: не надо замалчивать ошибки. Если ты запускаешь внешнюю программу, надо фиксировать и поток ошибок, и stdout и код возврата — тогда поиск причины проблемы занял бы не больше минуты. Собственно, я всегда вместо exec применяю велосипед который все это умеет, так как хочу на 100% контролировать все что происходит. Жаль, что стандартной функции для этого нет.
Оп, не могу понять зачем namespace нужен?
Например: namespace Slim\Helper;
А еще вот это непонятно:
class Set implements \ArrayAccess, \Countable, \IteratorAggregate
Зачем тут '\' ?
Спустя немного времени я осознал что писать алгоритм сортировки массивов используя min($array) должно быть зашкварно, ведь по сути внутри этой казалось бы простой функции уже должен быть встроенный цикл обхода массива для поиска минимального элемента. И чем использовать такие вот функции лучше не шквариться а сразу юзать sort($array); А тут меня даже никто не ткнул носом в говно, ну и ладно, решил попробовать реализовать хитровыебанную выборку по моей логике должна быть быстрее пузырька таким образом:
-встаем на 1й элемент внешним циклом
-внутренним циклом ищем минимальный элемент среди [1;n]
-меняем 1й элемент с найденным минимальным
-встаем на второй элемент внешним циклом
-внутренним ищем минимальный элемент среди [2;n]
-меняем 2й элемент с выявленным минимальным
...
массив отсортирован
причем в теории меньше чем за n^2 дейсвий, ведь внутренний цикл становится короче с каждой итерацией внешнего.
Но что-то не работает, может кто подскажет в чем проблема.
Нет, на дату посмотри.
http://php.net/manual/ru/language.namespaces.php
Проблема которую они решают — это наличие функций или классов с одинаковыми названиями в разных библиотеках. В этом случае, как ты понимаешь, одновременно их подключить нельзя.
до неймспейсов эту проблему решали, дописывая префиксы, вроде DeveloperName_LibraryName_Class но это приводит к длинным некрасивым именам классов. В других языках (ява, Питон) эта проблема решается пространствами имен, вот и в php решили их добавить.
Преимущество в том, что они решают проблему конфликтов. Недостаток в том что теперь ты обязан писать везде namespace и use (хорошие IDE вроде PhpStorm кажется умеют подставлять их автоматически — но я не уверен).
http://ideone.com/k6w0cL
Тут два параметра получает метод singleton. Пока понятно.
http://ideone.com/JJDAyp
Дальше вызывается метод set с двумя параметрами. Начиная с use я уже в ступоре. Мне надо разжевать эту вещь. Я все таки решил понять и разобрать как Slim работает, чтобы знать с чем имею дело.
Разве нельзя реализовать так: http://ideone.com/QFs7Xn
А задача писалась всего-то год или два назад. Экономика — штука хитрая.
>>390333
Не надо для связующей таблицы делать класс.
>>390336
>лучше не шквариться а сразу юзать sort($array);
Я думал, ты знаешь про эту функцию и принципиально решил ее не использовать, потому и не сказал ничего.
Насчет алгоритма, посмотри список в википедии — там указана сложность — а твой алгоритм наверняка уже кем-то придуман и имеет название.
>>390351
В классах-наследниках наверно перекрыто или планируют в будущем что-то вписать.
>>390364
Инструкция c картинками: https://gist.github.com/codedokode/7054af4a03865c4cc863
> Разве нельзя реализовать так:
Так тут надо руками класс сделать и написать всю эту лапшу. И чтобы получить доступ к объекту, надо писать Test::getInstance() (ого, сколько букв)
А в случае Слима ты пишешь
$slim->container->singleton... не создавая ни одного нового класса.
И заметь, что ты получаешь доступ через $app->xyz, не указывая конкретно как надо получать этот объект.
Это просто другой способ реализации.
> Начиная с use я уже в ступоре.
Изучи замыкания в PHP (в JS ты же с ними сталкивался? они и в PHP есть): http://us3.php.net/manual/ru/functions.anonymous.php
http://habrahabr.ru/post/147620/
Разница в том что в PHP ты явно указываешь какие переменные попадут в замыкание и как их передать — как копию или по ссылке (с возможностью изменять оригинал).
> static $object;
Это статическая переменная http://php.net/manual/ru/language.variables.scope.php#language.variables.scope.static
Если непонятно, давай по строчкам разберем.
Сделай функцию-шаблонизатор:
$template = "{{name}} говорит «{{phrase}}»";
$data = [
'name' => 'Иван',
'phrase' => 'надо уходить'
];
echo render($template, $data); // Иван говорит «надо уходить»
$template = "{{name}} и {{count|numeral:еще %d пользователь:еще %d пользователя:еще %d пользователей}} советуют вам не выходить в интернет";
$data = [
'name' => 'Иван',
'count' => 16
];
echo render($template, $data); // Иван и еще 16 пользователей советуют вам не выходить в интернет
В PHP для такого форматирования сообщений (b других задач связанных с локализацией) кстати не так давно появилось встроенное расширение intl ( http://php.net/manual/ru/book.intl.php )
Напиши функцию создания генератора sequence(start, step). Она при вызове возвращает другую функцию-генератор, которая при каждом вызове дает число на 1 больше, и так до бесконечности. Начальное число, с которого начинать отсчет, и шаг, задается при создании генератора. Шаг можно не указывать, тогда он будет равен одному. Начальное значение по умолчанию равно 0.
var generator = sequence(10, 3);
console.log(generator()); // 10
console.log(generator()); // 13
console.log(generator()); // 16
console.log(generator()); // 19
(код на яваскрипте, переделай его на PHP сам)
Курс доллара — все верно решено
Кубик — правильно
Игра в кубики
В if надо всегда ставить фигурные скобки {}, даже если там всего 1 действие:
> if($anonSum > $compSum)
>\techo "Победил анон!\n";
Отсутствие скобок повышает вероятность сделать ошибку при правке кода, потому проще всегда их ставить чем тратить потом время на поиск ошибки.
А в остальном верно.
Рулетка — хорошо, все правильно сделал
> Но что-то не работает, может кто подскажет в чем проблема.
Посмотри, что произойдет если минимальный элемент не будет найден? minKey тогда возьмется с предыдущего шага цикла.
ОПчик, у меня в классе User есть метод
public static function findIdentity($id)
{
return static::findOne($id);
}
Это чтобы если мы расширили этот класс классом MyUser, и вызвали у класса MyUser метод findIdentity, то внутри findIdentity вызвался бы findOne реализованнный в MyUser, а не в User? А при использовании self вызвался бы тот, что в User, да?
> причем в теории меньше чем за n^2 дейсвий, ведь внутренний цикл становится короче с каждой итерацией внешнего.
Если ты в школе изучал арифметические прогрессии, то можешь посчитать точно число действий. Там будет что-то около
n^2 / 2 или n(n - 1)
То есть по сути примерно то же что и n^2 в пузырьковой сортировке (в плане сложности O(n ^ 2) и O(n ^ 2 / 2) это одинаковая сложность так как обе растут одинаково с увеличением n — если увеличить n в 10 раз, сложность увеличивается в 100 раз).
> $sorted = FALSE;
>\twhile ($sorted == FALSE) {
Это костыль. Тут надо использовать цикл с постусловием:
do { lalala; } while (....)
Он гарантированно выполняется в первый раз.
Да, верно.
Я замечу что использовать статические методы тут плохая идея так как это лишает нас преимуществ ООП: мы не можем создать 2 экземпляра класса и например задать им разные настройки.
Также, в том месте где мы используем класс мы вынуждены писать его имя явно:
User::findIndentity()
И это лишает нас второго преимущества ООП: возможность вместо объекта одного класса подсунуть его наследника, не меняя сам код вызова.
Также это делает код более связанным.
То есть используя статические методы, ты многое теряешь. Потому в такой ситуации их использовать не стоит.
http://ideone.com/AEjywM
2) И снова о задаче про айфон:
>>387540
>- прибавляем проценты и комиссию к остатку долга
>- если остаток маленький, выплачиваем сколько осталось и уходим
>- иначе платим 5000
А как записать условие с маленьким остатком? Не до конца понимаю, как это должно выглядеть: http://ideone.com/pO4BZW
Какие есть способы кэширования запросов базе? Скажем на главной странице некий список который получается из базы. Как сделать, чтобы он не каждый посетитель не заставлял сервер делать запрос к базе данных?
меня унижают на работе за то что я ебашу классы там где не надо и сваливаю всё в один класс там где надо разделить.
я понимаю что такое класс и прочитал пару книг по основам ооп, но мне поясняют что понимаю я как-то через жопу.
логично методы делающие что-то одно вынести в класс. но тогда нахуй вообще нужны контроллеры? я бы с удовольствием ебашил классы, так же удобнее чем класс контроллера на 2000 строк.
вопрос конкретнее: плодить классы плохо? класс для 4х методов плохо? сколько должно быть методов чтобы было хорошим решением вынести его в класс
посоветуйте книгу или так поясните, лучше так, хоть поговорю с аноном
Просто я уже запилил костыль с генерацией готовых html страничек. Хотел узнать насколько это плохо.
http://ideone.com/d60q8z
Я не понял твое задание наверное.
Второе задание:
http://ideone.com/d60q8z
Или так:
http://ideone.com/d60q8z
Лол одно и тоже написал.
Фикс:
Первое: http://ideone.com/OLQEy2
Второе: http://ideone.com/kietI5
Или: http://ideone.com/d60q8z
Давай по строчкам разберем, начиная с
http://ideone.com/9bPgVe
С учетом того, что мы уже знаем, что container - это класс \Slim\Helper\Set()
Можно, но зачем? Код то страшноватый получается. Чем функция лучше чем просто глобальная переменная-массив в этом случае? И вообще, я сторонник ООП.
>>390429
> А можно ли как-нибудь записать, чтобы еще и считало его возраст после каждого шага?
Конечно, можно. Заведи переменную, в которой хранится возраст анона в момент создания вклада, после чего ты легко сможешь найти сколько ему сейчас лет (сложить начальный возраст и число прошедших лет).
Сама задача сделана не совсем так. У тебя заложен расчет на 50 лет, а почему именно 50? Мне кажется, надо заложить побольше лет и добавить проверку: если накопилась нужная сумма, выйти из цикла и написать сообщение, сколько анону лет и сколько он накопил.
> Задача про айфон
А где общая сумма выплат? Она должна в итоге написать сколько всего анону пришлось заплатить, я этого не вижу.
Кеширование — интересная тема и тут есть много вопросов.
Стоит ли вообще кешировать? Кеширование усложняет код и создает проблемы, потому если можно не кешировать, то лучше не кешировать.
Не стоит забывать, что испльзовать кеш как костыль для ускорения неэффективного кода — не лучшая идея, лучше исправить код.
Что именно кешировать? Список id сущностей, отдельные сущности целиком (список постов) или их html-представление? Кеширование html эффективнее в плане производительности (так как отдать кусок html быстрее чем взять из кеша данные и сгенерировать по ним html), но на практике оно не всегда применимо, так как эти данные получаются неизменными.
Например ты можешь закешировать html-код списка постов на главной, но при добавлении комментария тебе придется сбрасывать кеш чтобы вывести актуальное значение. А если кешировать только id постов то число комментариев, заголовок поста, имя автора будет браться из базы и будет актуальным (но такой кеш менее эффективен).
Когда создавать ключи кеша? При первом обращении либо же крон скриптом? Во втором случае нужно отдельно писать эти скрипты, зато генерация кеша может быть быстрее и может делаться ночью в период минимальной нагрузки.
Как обновить кеш при изменении данных в базе? Например, при добавлении комемнтария к посту надо сбросить или обновить кеш числа комментариев. Если ключ кеша содержит id поста то это не очень сложно, главное не забыть. Еще можно делать маленькое время жизни или систему тегов.
В общем, посмотри вот эту презентацию — она как раз на эту тему:
http://lib.custis.ru/images/6/6d/WebAppCache.pdf
http://vimeo.com/66739605
И почитай http://www.insight-it.ru/highload/ — про архитектуру
Что касается твоего вопроса. Если у тебя не сотни-тысячи посещений в секунду, а тормозит, то скорее всего у тебя плохой код или настройки базы данных. Оптимизируй запросы и исправь код — это гораздо лучше чем делать кеш.
Не все можно легко нагуглить. Да и в интернете много неграмотных советов.
>>390472
> логично методы делающие что-то одно вынести в класс. но тогда нахуй вообще нужны контроллеры? я бы с удовольствием ебашил классы, так же удобнее чем класс контроллера на 2000 строк.
2000 строк — слишком много. При 700 строках пора задумываться о разделении на части, при 1000 — разделять (в исключительных случаях можно не разделять, но это вряд ли твой случай).
Контроллер нужен для того, чтобы управлять процессом. Давай попробуем написать контроллер, выводящий список постов в блоге:
public function indexAction($request)
{
$page = $request->getIntParam('page', 1); // если передан номер страницы, то берем его
$this->view->posts = $this->postMapper->findFrontpagePosts($page); // ищем посты в базе и возвращаем массив объектов-постов
}
А вот пример неправильного кода, типичная лапша когда все пишут в контроллере:
public function indexAction()
{
$url = $this->url;
if (preg_match("!/page/(\d+)!", $url, $m)) {
$page = intval($m[1]);
} else {
$page = 1;
}
$query = $this->db->prepare("SELECT post., COUNT() AS commentCount,
FROM posts
WHERE post.visible = 1
ORDER BY date DESC
LIMIT :limit OFFSET :offset
");
$postsArray = $query->execute(array(
'limit' => $this->postsPerPage,
'offset' => ($page - 1) $this->postsPerPage
));
foreach ($postsArray as $post) {
....
}
...
}
В общем, дальше мне лень писать, но надеюсь суть принципа «тонкие контроллеры» ты понял. Первый пример — хороший, второй — плохой. При втором подходе ты будешь писать либо копипастить один и тот же код в каждый метод, а при первом подходе ты работаешь на более высоком уровне.
> вопрос конкретнее: плодить классы плохо?
Зависит от ситуации
> класс для 4х методов плохо?
Зависит от ситуации
> сколько должно быть методов чтобы было хорошим решением вынести его в класс
Сколько угодно. Если ты используешь MVC фреймворк то там есть определенные компоненты (контроллеры, модели, сервисы, формы, валидаторы, behaviour, виджеты) и надо делать как принято в этом фремйворке.
Если ты не работал с MVC фреймворками, посмотри например как все сделано в Симфони 2: http://symfony.in.ua/symfony2-jobeet-tutorial.html
> посоветуйте книгу
Советую изучить Симфони 2, ну или соответсвенно прочесть книгу про него.
Не все можно легко нагуглить. Да и в интернете много неграмотных советов.
>>390472
> логично методы делающие что-то одно вынести в класс. но тогда нахуй вообще нужны контроллеры? я бы с удовольствием ебашил классы, так же удобнее чем класс контроллера на 2000 строк.
2000 строк — слишком много. При 700 строках пора задумываться о разделении на части, при 1000 — разделять (в исключительных случаях можно не разделять, но это вряд ли твой случай).
Контроллер нужен для того, чтобы управлять процессом. Давай попробуем написать контроллер, выводящий список постов в блоге:
public function indexAction($request)
{
$page = $request->getIntParam('page', 1); // если передан номер страницы, то берем его
$this->view->posts = $this->postMapper->findFrontpagePosts($page); // ищем посты в базе и возвращаем массив объектов-постов
}
А вот пример неправильного кода, типичная лапша когда все пишут в контроллере:
public function indexAction()
{
$url = $this->url;
if (preg_match("!/page/(\d+)!", $url, $m)) {
$page = intval($m[1]);
} else {
$page = 1;
}
$query = $this->db->prepare("SELECT post., COUNT() AS commentCount,
FROM posts
WHERE post.visible = 1
ORDER BY date DESC
LIMIT :limit OFFSET :offset
");
$postsArray = $query->execute(array(
'limit' => $this->postsPerPage,
'offset' => ($page - 1) $this->postsPerPage
));
foreach ($postsArray as $post) {
....
}
...
}
В общем, дальше мне лень писать, но надеюсь суть принципа «тонкие контроллеры» ты понял. Первый пример — хороший, второй — плохой. При втором подходе ты будешь писать либо копипастить один и тот же код в каждый метод, а при первом подходе ты работаешь на более высоком уровне.
> вопрос конкретнее: плодить классы плохо?
Зависит от ситуации
> класс для 4х методов плохо?
Зависит от ситуации
> сколько должно быть методов чтобы было хорошим решением вынести его в класс
Сколько угодно. Если ты используешь MVC фреймворк то там есть определенные компоненты (контроллеры, модели, сервисы, формы, валидаторы, behaviour, виджеты) и надо делать как принято в этом фремйворке.
Если ты не работал с MVC фреймворками, посмотри например как все сделано в Симфони 2: http://symfony.in.ua/symfony2-jobeet-tutorial.html
> посоветуйте книгу
Советую изучить Симфони 2, ну или соответсвенно прочесть книгу про него.
Оп, я не могу в Slim разобраться. Я ничего не понимаю.
$app->get('/', function() use ($app) {
\techo "<h1>Hello Slim World</h1>";
});
Зачем я это пишу?
Я могу так написать: echo "<h1>Hello Slim World</h1>";
Что такое роутер не могу понять также. Я к этому не готов похоже.
>Зависит от ситуации
вот тут мне нужно разобраться
коллега на работе поучает меня, но мне кажется он просто навязывает свою точку зрения, и мне нужна другая точка зрения, например твоя.
допустим есть контроллер работы с клиентами, там оче много всего, профиль, сбросы паролей и т.д.
и есть регистрация (её 3 типа, для разных пользователей), для неё я создал 4 класса - один родительский - то есть общий код, само обращение в модели и т.д.
и 3 по типам регистрации, они наследуют родительский, переопределяя пару методов и добавляя каждый своё.
он утверждает что это лишнее пложение классов, что нужно тупо закинуть всё в контроллер. алсо, похоже он считает себя максимум умным, а я в своих способностях не уверен. поясни где эта грань между кучей классов по 20 строк и контроллером в 1000
У тебя, если ты все настроил, все обращения перенаправляются в index.php. То есть какой бы ты Url не набрал в адресно строке (http://localhost/lalala/lololo), вызван будет index.php
Роутер нужен чтобы проанализировать URL и вызвать соотвутствующую ему функцию.
> Я могу так написать: echo "<h1>Hello Slim World</h1>";
Тогда эта надпись будет выводиться всегда на всех страницах независимо от URL. А с роутером ты можешь сделать так:
$app->get('/page1', function () {
echo "It is page 1";
});
$app->get('/page2', function () {
echo "Time is " . date('r');
});
$app->get('/page3', function () {
echo "lalala";
});
Тогда в зависимости от URL будут вызваться разные функции.
Конечно, ты можешь вместо использования Слим навелосипедить свой роутер на if и регулярных выражениях:
if ($_SERVER['REQUEST_URI'] == '/page1') {
...
}
но так выйдет больше кода и он будет уродливым.
У тебя, если ты все настроил, все обращения перенаправляются в index.php. То есть какой бы ты Url не набрал в адресно строке (http://localhost/lalala/lololo), вызван будет index.php
Роутер нужен чтобы проанализировать URL и вызвать соотвутствующую ему функцию.
> Я могу так написать: echo "<h1>Hello Slim World</h1>";
Тогда эта надпись будет выводиться всегда на всех страницах независимо от URL. А с роутером ты можешь сделать так:
$app->get('/page1', function () {
echo "It is page 1";
});
$app->get('/page2', function () {
echo "Time is " . date('r');
});
$app->get('/page3', function () {
echo "lalala";
});
Тогда в зависимости от URL будут вызваться разные функции.
Конечно, ты можешь вместо использования Слим навелосипедить свой роутер на if и регулярных выражениях:
if ($_SERVER['REQUEST_URI'] == '/page1') {
...
}
но так выйдет больше кода и он будет уродливым.
Понятно, а что view делает?
Как мне уже начать что-то писать?
Для rgclone нужно 3 такие страницы создать?
$app->get('/page1', function () {
echo "It is page 1";
});
А дальше как?
> static $start;
В задании написано:
> Она при вызове возвращает другую функцию-генератор, которая при каждом вызове дает число на 1 больше, и так до бесконечности.
Должна быть функция которая создает и возвращает новую функцию. У тебя тут этого нет. Более того, у тебя используется по сути глобальная переменная $start и нельзя создать 2 независимых счетчика.
Поэтому вот это
> echo generator(2, 2);
Вообще не то.
Теперь разберем другую программу.
> if (func_num_args() == 1) {
Это не будет работать: http://ideone.com/DXWK60 — выдает ошибку, так как в PHP нельзя передать меньше аргументов чем указано (больше — можно). Надо использовать аргументы по умолчанию (заодно могу посоветовать иногда перечитывать мануал): http://php.net/manual/ru/functions.arguments.php#functions.arguments.default
> return $start += $step;
Это лучше записть в 2 строки, одна строка увеличение, другая return
Но в общем, примерно так и надо было сделать, на замыканиях.
> Шаблонизатор
http://ideone.com/EH4ehf - тут слово {{phrase}} не должно заменяться.
Замену надо сделать не циклом, а одним вызовом preg_replace_callback. Либо подготовить массив замен и вызвать strtr. Но чтобы сделать вторую часть задания (склонение слов) тебе точно понадобится preg_replace_callback
> static $start;
В задании написано:
> Она при вызове возвращает другую функцию-генератор, которая при каждом вызове дает число на 1 больше, и так до бесконечности.
Должна быть функция которая создает и возвращает новую функцию. У тебя тут этого нет. Более того, у тебя используется по сути глобальная переменная $start и нельзя создать 2 независимых счетчика.
Поэтому вот это
> echo generator(2, 2);
Вообще не то.
Теперь разберем другую программу.
> if (func_num_args() == 1) {
Это не будет работать: http://ideone.com/DXWK60 — выдает ошибку, так как в PHP нельзя передать меньше аргументов чем указано (больше — можно). Надо использовать аргументы по умолчанию (заодно могу посоветовать иногда перечитывать мануал): http://php.net/manual/ru/functions.arguments.php#functions.arguments.default
> return $start += $step;
Это лучше записть в 2 строки, одна строка увеличение, другая return
Но в общем, примерно так и надо было сделать, на замыканиях.
> Шаблонизатор
http://ideone.com/EH4ehf - тут слово {{phrase}} не должно заменяться.
Замену надо сделать не циклом, а одним вызовом preg_replace_callback. Либо подготовить массив замен и вызвать strtr. Но чтобы сделать вторую часть задания (склонение слов) тебе точно понадобится preg_replace_callback
view — это компонент который может отрендерить и вывести шаблон. По умолчанию используется встроенный в php шаблонизатор (то есть view->render() фактически в итоге просто инклудит файл шаблона). Если ты подключишь какие-то расширения, например twig for slim то view будет использовать twig. Ну или ты можешь (но не надо) вообще написать свой view.
Ты это посмотрел? http://docs.slimframework.com/#View-Overview
> Как мне уже начать что-то писать?
Сделать главную страницу с формой загрузки файла. Сделать базу данных. Сделать страницу, которая будет принимать запрос от формы, сохранять файл на диск и добавлять запись в таблицу, а затем редиректить на страницу скачивания. Сделать страницу скачивания.
> Давай по строчкам разберем, начиная с
ну, тут всего-то 3 строчки. Открываем документацию по Slim, раздел DI: http://docs.slimframework.com/#DI-Overview
И видим там что метод singleton создает синглтон. То есть при обращении
$app->response
в первый раз будет вызвана наша функция (которая создаст и вернет new \Slim\Http\Response();) а во второй и далее разы Слим вернет тот же самый ранее созданный объект.
Проще говоря $app->response — это объект класса \Slim\Http\Response который создается при первом обращении к этому свойству.
Ну теперь можно разобрать сам код, когда мы знаем что он делает.
Откроем класс Helper\Set. Мы видим по названиям методов, что это класс-коллекция (то есть в него можно класть элементы и искать их по имени, напоминает массив).
Для начала посмотрим в шапку и увидим
implements \ArrayAccess, \Countable, \IteratorAggregate
Это стандартные интерфейсы, которые входят в SPL (библиотеку встроенных классов). Они описаны в мануале PHP, найди их там сам.
Если класс реализует ArrayAccess то к нему (точнее, объектам этого класса) можно обращаться как к массиву через скобки: $object[$x]. Это делается за счет объявления в классе методов offset... (то есть когда ты пишешь $object[$x], PHP автоматически вызовет метод $object->offsetGet($x)). Мы видим, что в классе Helper\Set все 4 требуемых метода есть.
Интерфейс Countable позволяет определить что вернет вызов count() на объекте. Для его поддержки в классе сделана функция count.
Интерфейс IteratorAggregate позволяет использовать объект в foreach.
Еще мы видим что в классе реализованы магические методы _ _ get сотоварищи. То есть, наш класс-коллекция неплохо сделан: к нему можно обращаться как к массиву, можно обращаться к свойствам по имени, можно считать число элементов в нем, перебирать через foreach.
Также, мы видим методы get/set/all/has/keys/replace для работы с коллекцией.
В общем, ясно что класс Set — это класс, в который можно добавлять и хранить какие-то элементы.
Также, посмотрев метод get мы видим особенность: если в коллекцию положить объект с методом _ _ invoke, то он ее вернет результат ее вызова.
Что это за метод (ты еще не открыл мануал? открой)? Это магический метод, который позволяет вызывать объект как функцию. То есть когда ты пишешь $object() то вызывается этот магический метод.
Важно, что замыкания и анонимные функции в PHP реализованы как объекты класса Closure у которого разумеется этот метод определен (опять же открой мануал по Closure). То есть если мы сохраним в класс Set анонимную функцию, то при вызове get() он ее вызовет и вернет то что она вернула.
Также, мы видим еще 2 метода — singleton и protect. Первый позволяет добавить в коллекцию синглтон, второй позволяет добавить функцию, которая не будет автоматически вызываться, а возвращаться как есть.
Ок, мы увидели что $app->container это Helper\Set и знаем какие у него есть методы. Осталось еще одно звено — что происходит когда мы пишем $app->something?
Откроем класс Slim и найдем там магический метод _ _ get (мануал по которому ты надеюсь прочел): https://github.com/codeguy/Slim/blob/master/Slim/Slim.php#L232
При обращении к несуществующем свойству объекта $app вызовется этот _ _ get. А он, как мы видим, просто берет элемент с указанным именем из контейнера. То есть
$x = $app->something ;
равносильно в итоге вызову
$x = $app->container->get('someting');
Таким образом понятно зачем нужен этот $app->container — он позволяет хранить разные объекты (переданные напрямую или созданные с помощью singleton) и обращаться к ним с помощью короткой записи $app->something.
> Давай по строчкам разберем, начиная с
ну, тут всего-то 3 строчки. Открываем документацию по Slim, раздел DI: http://docs.slimframework.com/#DI-Overview
И видим там что метод singleton создает синглтон. То есть при обращении
$app->response
в первый раз будет вызвана наша функция (которая создаст и вернет new \Slim\Http\Response();) а во второй и далее разы Слим вернет тот же самый ранее созданный объект.
Проще говоря $app->response — это объект класса \Slim\Http\Response который создается при первом обращении к этому свойству.
Ну теперь можно разобрать сам код, когда мы знаем что он делает.
Откроем класс Helper\Set. Мы видим по названиям методов, что это класс-коллекция (то есть в него можно класть элементы и искать их по имени, напоминает массив).
Для начала посмотрим в шапку и увидим
implements \ArrayAccess, \Countable, \IteratorAggregate
Это стандартные интерфейсы, которые входят в SPL (библиотеку встроенных классов). Они описаны в мануале PHP, найди их там сам.
Если класс реализует ArrayAccess то к нему (точнее, объектам этого класса) можно обращаться как к массиву через скобки: $object[$x]. Это делается за счет объявления в классе методов offset... (то есть когда ты пишешь $object[$x], PHP автоматически вызовет метод $object->offsetGet($x)). Мы видим, что в классе Helper\Set все 4 требуемых метода есть.
Интерфейс Countable позволяет определить что вернет вызов count() на объекте. Для его поддержки в классе сделана функция count.
Интерфейс IteratorAggregate позволяет использовать объект в foreach.
Еще мы видим что в классе реализованы магические методы _ _ get сотоварищи. То есть, наш класс-коллекция неплохо сделан: к нему можно обращаться как к массиву, можно обращаться к свойствам по имени, можно считать число элементов в нем, перебирать через foreach.
Также, мы видим методы get/set/all/has/keys/replace для работы с коллекцией.
В общем, ясно что класс Set — это класс, в который можно добавлять и хранить какие-то элементы.
Также, посмотрев метод get мы видим особенность: если в коллекцию положить объект с методом _ _ invoke, то он ее вернет результат ее вызова.
Что это за метод (ты еще не открыл мануал? открой)? Это магический метод, который позволяет вызывать объект как функцию. То есть когда ты пишешь $object() то вызывается этот магический метод.
Важно, что замыкания и анонимные функции в PHP реализованы как объекты класса Closure у которого разумеется этот метод определен (опять же открой мануал по Closure). То есть если мы сохраним в класс Set анонимную функцию, то при вызове get() он ее вызовет и вернет то что она вернула.
Также, мы видим еще 2 метода — singleton и protect. Первый позволяет добавить в коллекцию синглтон, второй позволяет добавить функцию, которая не будет автоматически вызываться, а возвращаться как есть.
Ок, мы увидели что $app->container это Helper\Set и знаем какие у него есть методы. Осталось еще одно звено — что происходит когда мы пишем $app->something?
Откроем класс Slim и найдем там магический метод _ _ get (мануал по которому ты надеюсь прочел): https://github.com/codeguy/Slim/blob/master/Slim/Slim.php#L232
При обращении к несуществующем свойству объекта $app вызовется этот _ _ get. А он, как мы видим, просто берет элемент с указанным именем из контейнера. То есть
$x = $app->something ;
равносильно в итоге вызову
$x = $app->container->get('someting');
Таким образом понятно зачем нужен этот $app->container — он позволяет хранить разные объекты (переданные напрямую или созданные с помощью singleton) и обращаться к ним с помощью короткой записи $app->something.
Оп, а как делается, если я к примеру я ввожу rgclone.ru и выводится моя индексная страница? То есть не нужно писать rgclone/index.php
> То есть не нужно писать rgclone/index.php
Не понял. В чем тут проблема? Если ты обращаешься по URL вида site.com/ то веб-сервер по умолчанию ищет и вызывает файл index.php (или index.html).
Соответсвтенно, чтобы при обращении по адресу rglone.ru вызывался index.php — делать ничего не надо, это и так уже сделано.
На своем локальном сервере если я пишу http://slim.local/rgclone.ru, то я получаю список файлов внутри:
Parent Directory
.git/
.gitignore
composer.json
composer.lock
index.php
templates/
vendor/
А мне надо, чтобы запускался index.php сразу.
Короче надо намутить интерфейс позволяющий создавать таблицы в mysql а затем искать их там же, фишка в следующем допустим у меня уже есть несколько таблиц с префиксом P_ и мне надо найти все такие таблицы, есть какие нибудь идеи как такое намутить? Также интересует вопрос создания таких таблиц, допустим юзер зашел на страничку и решил намутить таблицу Nurses которая в последствии станет P_Nurses и допустим он хочет чтобы там было n строк, в таком случае мне надо будет намутить здоровенную форму в которой будут циклом создаваться вводы как например:
'<input type="text" name="ColumnName'.$i'" value=""/>'
'<input type="text" name="ColumnType'.$i'" value=""/>'
Как думаете котаны, норм идея?
Заметь также, что при использовании Слима ты должен настроить веб-сервер так, чтобы при запросе любого URL (не соответствующего файлу на диске) вызвался index.php. Для Апача это делается с помощью файла .htaccess в котором прописываются соответствующие правила (которые ты, я надеюсь, прописал).
Что именно надо написать в этом файле, упомянуто здесь: http://docs.slimframework.com/#Route-URL-Rewriting
Заметь что .htaccess работает только с Апачем. Если бы ты использовал например nginx то тебе пришлось бы править его конфиг.
Это ты так странно настроил сервер. Какие файлы используются по умолчанию, определяется директивой DirectoryIndex
Проверь чему она у тебя равно и пропиши там
DirectoryIndex index.php idnex.html
(Апач будет перебирать файлы именно в указанном порядке так что не перепутай).
Заметь что этого недостаточно, там еще надо через htaccess зарулить все запросы на index.php
Во-первых, зачем приписывать число к имени поля если можно использовать индексы вида <input name="SomeColumn[1]" которые PHP c радостью соберет в массив. Подробности в мануале который советую читать почаще:
http://php.net/manual/ru/faq.html.php#faq.html.arrays
http://php.net/manual/ru/language.variables.external.php
Также, не надо писать вот этоn слеш / в конце input если ты верстаешь на HTML5 или HTML4 - он там не используется. Он используется только в XML и умершем XHTML.
> Как думаете котаны, норм идея?
думаю, для этого написано уже что-нибудь готовое а ты делаешь велосипед. Например, есть такие вещи как phpMyAdmin и adminer.
Ах да, советую тебе еще писать нормальные (краткие но емкие) описания коммитов. А то смотришь на эту страницу: https://github.com/fxsloker/rgclone.ru/commits/master и понять что-то трудно.
Спасибо, согласен в принципе на счет велосипеда но задумка дать юзеру некоторый контроль над дб так как в моем случае не известно какие группы будут регистрироваться и какие у них будут атрибуты например для одних надо записывать возраст для других адрес и чтобы не делать тысячу разных таблиц я думаю сделать так чтобы юзер с этим парился.
Вот поучись у них (и заодно обрати внимание, как удобно использовать github, можно просмотреть изменения отдельно по каждому коммиту, а также коммит может быть привязан к багу из issues, а также можно все комментировать):
https://github.com/codeguy/Slim/commits/master
https://github.com/jquery/jquery/commits/master
Алсо, это не совсем в тему, но если ты еще не читал сайт phptherightway, то почитай.
Делать много таблиц для разных пользователей не лучшая идея. Лучше одну таблицу с большим числом полей либо использовать какой-нибудь EAV ( http://habrahabr.ru/post/45935/ ) для дополнительных свйств.
ОП, и другие, что посоветуете почитать/посмотреть о безопасности: от инъекций до чего-нибудь вообще обывателю не приходящего в голову. в общем все по безопасности - как создать веб-приложение так, чтоб после запуска через сутки денюжка или данные не улетели к человеку с айкью выше моего в два раза.
Написал нормальный коммит.
Гляди, теперь upload.php он почему-то найти не может, а index.php, который в папке templates видит.
action="/templates/upload.php" тоже писал. Не работает. Почему-то он ищет его в корне всегда.
Там есть разные виды уязвимостей, можно гуглить их по названиям: include vulnerability или RFI ( http://www.abc-it.lv/index.php/id/609 ) , sql инъекции ( http://habrahabr.ru/post/148701/ ), XSS (моя паста на тему: https://gist.github.com/anonymous/52adda0113428b274c64 ), CSRF http://habrahabr.ru/post/126409/
Это список основных уязвимостей. Не знаю, есть ли вся эта информация в какой-то одной книге.
Способы борьбы: писать код правильно, а не как попало. Если конкретнее, то для борьбы с
- include vuln — не инклюдить что попало
- SQL инъекцией — использовать плейсхолдеры и PDO вместо подстановки переменных в запрос
- XSS — использовать экранирование в шаблонах либо шаблонизатор делающий это автомтически (twig например)
- CSRF — проверять CSRF токен при обработке форм
Ну и не доверять никаким данным, пришедшим от пользователя — там может быть подсунуто что угодно.
Вот еще моя паста про защиту паролей: https://gist.github.com/codedokode/9576319
Проверить свой сайт можно программами-сканерами (они умеют автоматически искать уязвимости), но они не гарантируют нахождение 100% всех уязвимостей — чтобы сайт был защищен, надо писать его с соблюдением определенных правил. Вот пример программы поиска SQL инъекций (не забудь что применять ее можно только против своих сайтов): https://www.netsparker.com/communityedition/
Если ты исплоьзуешь сторонние CMS, плагины, библиотеки, своевременно обновляй и проверяй, нет ли в них уязвимостей. Можно даже подписаться на какой-нибудь сайт с новостями об уязвимостях.
> if(is_uploaded_file($_FILES["filename"]["tmp_name"])) {
> \t\tmove_uploaded_file($_FILES["filename"]["tmp_name"], "/uploads/".$_FILES["filename"]["name"]);
Шаблон должен использоваться только для генерации HTML-страницы, никакой обработки файлов там не должно быть, переноси это в index.php.
> <form action="upload.php"
Ты отправляешь форму на URL /upload.php а в index.php у тебя нет обработчика для такого URL (есть только для / и /upload без .php). Надо что-то поменять. Я думаю, адрес в форме. Ну и
> method="post"
> $app->get('/upload',
Тут у тебя post, а там у тебя get — не будет работать.
Что он из себя представляет? Цмс? Фреймворк? Он проприетарный, но он же вроде на php, там есть какие-то компилированные / защищенные модули?
Тк от 1С, я так понимаю там есть какое-то api для работы с 1С предприятие, это можно выдрать в свой проект?
Вообще, что есть сказать про битрикс?
Нет, к счастью. Битрикс изначально разработан не 1С, а какой-то другой компанией, а потом они его переименовали, подозреваю, ради узнаваемости названия.
Код зашифрован, так что остается только читать документацию — вроде на оф. сайте ее много.
>Тк от 1С, я так понимаю там есть какое-то api для работы с 1С предприятие, это можно выдрать в свой проект?
Код зашифрован (или нет?), так что вряд ли. Но можно попробовать нагуглить что-то готовое или почитать описание протокола обмена у 1С и навелосипедить свое что-то.
Файлы шаблонов я назвал, как .tpl, но наверно без разницы? Можно и .php, и .html?
Я хочу сделать один главный шаблон main.tpl, в котором и доктайп, и теги обертки, и главный контент. Плюс еще 2 файла с необходимым содержимым. Далее в блоке контента прописать условия, в зависимости от которых появляется то или иное содержимое. А может html код хранить в базе данных, как в джумле? Или как это делается правильно? Где можно почитать что-нибудь толковое про шаблоны?
Кстати потом считывать вот такие блоки, например как {{$title}}, с помощью file_get_contents. Но это я уже нагуглил. Это правильно?
Почему сессия не назначается?
[CODE]if (!empty($isPassed)) {
\t\t$_SESSION["loginStatus"] = "logged";
\t\t$_SESSION["username"] = $isPassed[0]["username"];
\t\theader("Location: http://{$_SERVER['SERVER_NAME']}/chatbox/index.php?g=5");
\t} else {
\t\t$_SESSION["loginStatus"] = "failed";
\t\theader("Location: http://{$_SERVER['SERVER_NAME']}/chatbox/index.php?g=6");
\t}[/CODE]
Полюбому я долблюсь в глаза и где-то опечатался, но нихрена не вижу.
бамп
А, стоп! Сессия работает только на одной странице? Не на всем сайте? Вот дела.
А, стоп-стоп! Я просто забыл начать сессию, дурачина.
> Можно и .php, и .html?
В Zend Framework используется phtml — типа php + html.
> Я хочу сделать один главный шаблон main.tpl, в котором и доктайп, и теги обертки, и главный контент. Плюс еще 2 файла с необходимым содержимым.
Можно просто сделать шапку и футер и инклудить их. Ну можно и как ты задумал. Лишь бы копипасты не было.
> А может html код хранить в базе данных, как в джумле?
Я же вроде писал ранее — Джумла это не пример хорошей архитектуры, а антипример. Как ты свои шаблоны в базе в git будешь помещать? Это наоборот, крайне дурная идея.
> Или как это делается правильно?
Хранить в файлах
> Где можно почитать что-нибудь толковое про шаблоны?
https://php.net/manual/ru/language.basic-syntax.phpmode.php
http://www.phpinfo.su/articles/practice/shablony_v_php.html
http://habrahabr.ru/post/230737/ (пункт 6 прочти в первую очередь)
> Кстати потом считывать вот такие блоки, например как {{$title}}, с помощью file_get_contents. Но это я уже нагуглил. Это правильно?
Прочти сначала пункт 6 из статьи выше
То, что ты хочешь — это наркоманство и не нужно тебе.
А так, ты можешь посмотреть на ссылки http://php.net/manual/ru/language.references.php но лучше переписать код нормально.
Сделать капчу в смысле? в гугле смотрел? http://www.google.ru/search?sourceid=chrome&ie=UTF-8&q=%D0%B4%D0%B5%D0%BB%D0%B0%D0%B5%D0%BC+%D0%BA%D0%B0%D0%BF%D1%87%D1%83+%D0%BD%D0%B0+php
Да нет, именно как POST запрос сделать. Но уже вроде как получилось через cUrl, хотя я плохо понял как, но работает.
Это значит что в PHP уже встроен шаблонизатор:
<li>Имя: <?= htmlspecialchars($name) ?>
<li>Дата рождения: <?= date('r', $birthday) ?>
Вот этот кусок кода на PHP является шаблоном, для которого не нужны никакие внешние библиотеки.
> допустим есть контроллер работы с клиентами, там оче много всего, профиль, сбросы паролей и т.д.
Это уже не очень хорошо
> и есть регистрация (её 3 типа, для разных пользователей),
Это тоже. Какой смысл делать 3 страницы регистрации? вы наркоманы?
> для неё я создал 4 класса - один родительский - то есть общий код, само обращение в модели и т.д.
> и 3 по типам регистрации, они наследуют родительский, переопределяя пару методов и добавляя каждый своё.
Тут это может быть излишне. Если разница в регистрациях только в том что в одной на 2 поля больше, а в другой надо в базу записать единичку вместо нолика, то может быть проще сделать одной функцией с парой дополнительных if. Если же есть разница в логике работы форм, то может быть лучше сделать через наследование.
Не видя кода трудно точно сказать.
> он утверждает что это лишнее пложение классов, что нужно тупо закинуть всё в контроллер.
Он может исходить из такой логики: «если он сейчас начнет писать свою систему классов, это неизвестно сколько займет времени, а если набыдлокодить то получится быстро — а потом хоть трава не расти». То есть не всегда нужен правильный код. иногда нужен быстрый код.
Стоит заметить, что такой подход годится когда не надо подерживать код, то есть написали по-быстрому, сдали и забыли. Если же вы годами пилите приложение то с хорошим кодом быстрее и удобнее работать.
> поясни где эта грань между кучей классов по 20 строк и контроллером в 1000
Контроллер в 1000 это нездоровая вещь. Но опять же, тут может быть такая логика: нам нужно написать код как можно быстрее. Пользователь же в исходный код не заглянет, ему все равно как написано.
Он может быть прав, он может быть не прав — я не знаю.
Также, что касается форм, в фреймворках (вроде Симфони 2) обычно форму и логику ее валидации делают отдельным классом, а не пишут код в контроллере.
>Это тоже. Какой смысл делать 3 страницы регистрации? вы наркоманы?
ну давай без неадекватности
3 типа пользователей, с тремя разными регистрациям, ну там физическое лицо, юридическое лицо, разные подтверждения на почту, и т.д.
> иногда нужен быстрый код
всё с точностью наоборот
я за быстрый код с последующим рефакторингом в слабых местах
он за долгое время разработки, но чтобы было всё прям роксолид и заебись по архитектуре
>нам нужно написать код как можно быстрее
нет, здесь речи об этом не идёт
он настаивает именно на архитектуре и задаёт вопрос - если я выношу всё в классы то зачем нужны контроллеры?
вот лично мне удобно иметь например 20 папок - и в них классы рассортированы, и там логика, а контроллеры вызывают эти классы через автолоадеры. это плохо?
>Он может быть прав, он может быть не прав
ну охуеть теперь
> если я выношу всё в классы то зачем нужны контроллеры?
Почитай, а потом дай ему почитать про «тонкие контроллеры». Код в контроллере нельзя повторно использовать (например если ты получаешь список последних новостей прямо в контроллере то ты не можешь где-то в другом месте вызвать этот код), потому его надо писать как можно меньше и выносить в другие классы (то есть сделать отдельный метод getLatestNews() в нашем примере который можно вызвать откуда угодно).
Вот даже в вики написано что толстые контроллеры это плохо: https://ru.wikipedia.org/wiki/Model-View-Controller#.D0.9D.D0.B0.D0.B8.D0.B1.D0.BE.D0.BB.D0.B5.D0.B5_.D1.87.D0.B0.D1.81.D1.82.D1.8B.D0.B5_.D0.BE.D1.88.D0.B8.D0.B1.D0.BA.D0.B8
> 3 типа пользователей, с тремя разными регистрациям, ну там физическое лицо, юридическое лицо, разные подтверждения на почту, и т.д.
Ну не знаю, не знаю. Если разница большая то да, наверно лучше наследование.
> а контроллеры вызывают эти классы через автолоадеры. это плохо?
Нет конечно.
>Код в контроллере нельзя повторно использовать
что мешает вызывать один метод контроллера в двух других методах этого контроллера?
>тонкие контроллеры
ну блин ты не о том же
ну речь не о тонких контроллерах
специально для тебя перепишу всё про модели:
я вынес всю логику в модели, контроллеры теперь очень тонкие.
но теперь модель 1000 строк.
при этом чётко видны группы методов - например один публичный использует 4 приватных метода (разделил один длинный метод на несколько)
я хочу вынести это в класс. он говорит - нехуй, оставляй всё в куче.
конкретный вопрос: какие правила создания классов? в каком случае стоит создать класс, в каком - нет?
>что мешает вызывать один метод контроллера в двух других методах этого контроллера?
А мне надо из любого места кода, а не из того же контроллера
> конкретный вопрос: какие правила создания классов? в каком случае стоит создать класс, в каком - нет?
Когда есть какая-то отдельная сущность или отдельная вещь которую этот класс делает. Ну например, если у тебя в модели есть несколько функций для разбора телефонных номеров на части, проверки, выделения кода страны и города, а все остальные функции взаимодействуют с базой данных, то вполне можно это вынести в отдельный класс работы с телефонными номерами. Тем более что если его правильно написать то его можно будет повторно использовать в других проектах.
В случае с моделями как классом взаимодействия с БД обычно делают так, одна таблица/сущность в БД = 1 класс модели.
Противоположный пример: если у тебя в модели есть функция удаления записи, функция увеличения рейтинга записи и функция изменения автора записи, то их нет особого смысла разносить в разные классы так как они по сути делают одну вещь — изменение в таблице записей.
>А мне надо из любого места кода, а не из того же контроллера
ебашишь компонент или пишешь в кейкпхп есть апп-контроллер, например
тогда ударимся в крайность -
вот проект большой.
в итоге получится 30 классов с допустим 4 методами в каждом
по сути эти классы могут быть как моделями (делают то что должна делать модель) или контроллерами
это ок или не ок?
Ну и если модель стала слишком толстая, то можно попробовать выносить из нее функционал: например делать 2 класса, один для разных проверок и валидаций, другой только для взаимодействия с БД.
Последний вопрос на ночь глядя. Как динамически подгружать содержимое контента? Например страница /upload, там одно содержимое, а страница /files - другое. У меня только есть вариант проверять через $_SERVER["REQUEST_URI"], но опять может быть просто rgclone.ru и rgclone/index.php. Кстати хорошо бы, чтобы автоматически редиректилось на rgclone.ru, даже если в ручную прописал index.php
>> А мне надо из любого места кода, а не из того же контроллера
> ебашишь компонент или пишешь в кейкпхп есть апп-контроллер, например
В апп-контроллер писать получение новостей — быдлокод, выносить в компонент = придерживаться принципа тонких контроллеров, в итоге непонятно с чем ты споришь, так как я об этом и писал.
> вот проект большой.
> в итоге получится 30 классов с допустим 4 методами в каждом
Это не большой проект, а средний, ну да ладно.
В случае если у тебя 30 таблиц в базе то 30 моделей (точнее классов работы с БД) по 1 на таблицу это ок. В случае если у тебя 5 таблиц то не ок.
> по сути эти классы могут быть как моделями (делают то что должна делать модель) или контроллерами
контроллеры делаются обычно по принципу 1 раздел = 1 контроллер. Например: контроллер раздела новостей, контроллер объявлений, контроллер пользовательского профиля, контроллер регистрации и восстановления паролей, контроллер админки пользователей. Модели (точнее классы взаимодействия БД) делаются по числу сущностей таблиц: PostsModel, UsersModel, NewsModel.
Не зная сколько у тебя разделов и сущностей, я не могу сказать хорошо это или плохо, 30 классов. Но я бы нес казал что 30 классов это много.
> Как динамически подгружать содержимое контента? Например страница /upload, там одно содержимое, а страница /files - другое.
У тебя в этих случаях вызываются разные функции. Соответственно в них ты можешь написать что угодно, например присвоить какое-то значение переменной:
$app->get('/files', function () {
$x = 1;
....
$this->render('files.tpl', ...);
});
$app->get('/upload', function () {
$x = 2;
....
$this->render('upload.tpl', ...);
});
> У меня только есть вариант проверять через $_SERVER["REQUEST_URI"],
Нет. У тебя в Слиме есть роутер, и ты не должен лезть в REQUEST_URI
> Кстати хорошо бы, чтобы автоматически редиректилось на rgclone.ru, даже если в ручную прописал index.php
Нет, нехорошо. С чего это пользователь станет что-то руками допиcывать в строку адреса, тем более непонятную ему команду index.php? Ты заходя на двач тоже index.php руками приписываешь?
>В случае если у тебя 30 таблиц в базе то 30 моделей (точнее классов работы с БД) по 1 на таблицу это ок. В случае если у тебя 5 таблиц то не ок.
я то думаю что ты несёшь, а ты не понял ничего
я не про контроллеры\методы
просто рандомная папка и там классы
Ну ты сам начал сначала про контроллеры, а потом про модели — я рассказываю по каким принципам они делаются.
Если у тебя рандомная папка с 30 классами, неизвестно что это за проект, что это за классы и что они делают, то я ничего не могу сказать.
Вот смотри например Sfiftmailer — библиотека для оправки почты — https://github.com/swiftmailer/swiftmailer/tree/master/lib/classes/Swift — посчитай сколько там классов.
С другой стороны, много классов может быть признаком того, что ты начал придумывать свой странный велосипед вместо использования общепринятых паттернов.
Хотя повторю, 30 классов имхо немного. Если бы их было хотя бы 100-200 тут уже можно было бы спрашивать, а нафига так много классов для такого простого сайта.
>я рассказываю по каким принципам они делаются
в этом проблема. я не просил рассказывать как делаются модели. я задал конкретный вопрос - ок ли выносить из контроллеров и моделей куски кода просто в классы.
>Sfiftmailer
да, вижу что там классы по 20 строк и автор не стесняется этого
только вопрос в том насколько это правильно. то что так сделано в свифтмайлер не значит что это ок.
а если архитектура мвц? допустимо также просто создать кучу классов и ссылаться на них из моделей и контроллеров?
я понял что допустимо.
а вот такое пложение классов по 20 строк как в свифт майлер. меня имеют право унижать за это или это приемлемо?
> а вот такое пложение классов по 20 строк как в свифт майлер. меня имеют право унижать за это или это приемлемо?
Приемлемо, если они осмысленно плодятся в соотсветствие с общепринятыми паттернами проектирования.
>осмысленно плодятся в соотсветствие с общепринятыми паттернами проектирования
как определить эту осмысленность?
пусть я тебе сейчас пачку кода дам, но мне нужно самому разобраться
какие критерии по которым можно сказать - это можно вынести в класс - это нельзя
я имею ввиду что-нибудь официальное, ну там стандарт или какой-нибудь авторитетный человек
чтобы я мог предъявить это
>какие критерии по которым можно сказать - это можно вынести в класс - это нельзя
Не знаю, где взять эти критерии. Если ты делаешь игру сапер, то ты можешь сделать каждую клеточку отдельным объектом, а можешь сделать один объект Поле. И то, и другое будет правильно. Главное, что каждый класс представляет отдельную сущность, а не просто от балды функции по классам раскиданы.
Попробуй код Swiftmailer или Symfony 2 предъявить что ли.
По поводу теории — есть книга Фаулера про рефакторинг, вот что там написано про вынесение кода в отдельный класс:
http://www.refactoring.com/catalog/extractClass.html (как я понимаю, в книге это подробнее должно быть описано).
http://codingcraft.ru/resources/REFACTORING/ExtractClass.htm
То есть если видно что часть методов занимается отдельной задачей, то их можно вынести в отдельный класс.
начинал читать эту книгу, но не закончил
можно ли применять всё что в ней описано к мвц?
не накладывает ли мвц каких-то ограничений на работу с классами?
вот смотри - в мвц есть контроллеры и модели
когда я создаю класс - он же перестаёт быть контроллером. можно условно сказать что этот класс должен вести себя как контроллер, но по сути это отдельный класс и из него я могу делать что хочу. так или не так?
например обращение к бд. я всё равно не могу обратится к бд напрямую. или могу? такой класс - это отдельная сущность или на него распространяется всё что распространяется на контроллер\модель, откуда он был вынесен?
мне в отпочковавшихся классах нужно работать с бд, работать с компонентами и т.д.
я передаю туда $this, то есть экземпляр контроллера (это так называется?)
это нормальная практика? то есть у меня все отпочковавшиеся классы всё равно связаны с контроллерами
>мы предпочитаем подстановку переменных вместо конкатенации строк: "I am $age years old" — хорошо, 'I am ' . $age . ' years old' — плохо
Учу сейчас пых и где-то читал, что кот в двойных кавычках исполняется дольше, и лучше использовать одинарные там, где возможно. Хотя двойные универсальнее и удобнее.
Проясни ситуацию, программач, а то так дураком и помру.
http://ideone.com/GAJYfs
Как я понимаю, в заголовки они передаются. Тогда совсем непонятно. Другие куки назначаются.
вся суть пхппрограмистов
пошёл бы в своё время на курсы явы - ссал бы тебе в рот в этом итт треде
но сейчас ты мой братишка, поэтому придётся помогать
у тебя на одной странице есть куки, а на другой нет? а если переходишь туда-сюда тоже самое? на одной всегда есть а на другой всегда нет?
Да. Как я понял, нужно четвертым параметром указать домен. Указал "/", как сказал гугл и все нахуй сломалось. Указал url, не помогло, не видно на главной.
>метром указать домен. Указал "/", как сказал гугл и все нахуй сло
setcookie("TestCookie", $value, time()+3600, "/~rasmus/", "example.com", 1);
пятым домен
попробуй по документации, а лучше вообще без домена
http://php.net/manual/ru/function.setcookie.php
Оп, я знаю, что ерунду написал. Но я не знаю как же мне загрузить файл на сервер.
Самое интересное у меня открывается rgclone.ru/index.php, в котором пишет, что страница не найдена. А если я обновлю страницу, то все на своих местах. Почему так?
Отказался от динамического контента. Вернее сделал по-другому. Ну ты сам видишь. Как я хотел не получилось.
Исходники Slim'а ты и так можешь найти. Думаешь я Slim переписываю? Я не настолько умный. Оп сказал так правильно.
какой-то новый уровень долбоебизма
ты экномишь гитхабу 1мб?
>Не забудь добавить vendor в gitignore чтобы не замусоривать репозиторий.
это хуйня полное говно
это - часть твоего проекта
оно должно быть в репозитории чтобы любой хуй мог склонировать его и у него был проект целиком
не знаю откуда оп набрался этого говна, но это бред
это хуёвый подход
оп не будда с истинным знанием
ТЫ мне объясни - зачем убирать папку с частью проекта?
давай пример приведу
пишешь на симфони - изменил один файл чтобы хелловолрд выводил, и загружаешь на гитхаб
ты выгрузишь один файл, а остальное нужно самому разворачивать, так как
>Исходники симфониты и так можешь найти
?
ты серьёзно?
что за ебанутый квест "собери проект по кускам"?
вообще впервые о таком слышу.
потом ты подключишь пхпмайлер, ещё дохуя всего
и что? мне бегать по сайтам разворачивать в твой проект всё это?
> и что? мне бегать по сайтам разворачивать в твой проект всё это?
Нет, тебе нужно запустить компосер, который сам все развернет. composer.json я же не убрал.
ясно
Ты дурак? Прочитай что такое менеджеры пакетов. В репозитории есть composer.json который достаточен для описания зависимостей. если надо привязать версии (нам это не надо), можно туда же добавить conposer.lock.
Ты наверно и гитом не пользуешься, а до сих пор исходники в rar-архив запаковываешь и в папочку складываешь?
>>390818
Если ты пишешь на Симфони то Симфони в проект тащить незачем. Хотя бы чтобы не замусоривать коммит лог при обновлении.
Алсо,
> что за ебанутый квест "собери проект по кускам"?
> вообще впервые о таком слышу.
Попробуй скачай любой open source продукт в исходниках, например PHP, открой файл INSTALL и внезапно увидишь те самые инструкции сбора проекта по кускам.
У тебя знаний и опыта ноль, а столько самоуверенности.
В репозитории должен быть только твой код, код библиотек должен храниться в их репозиториях.
Если продолжать твою логику, то анон должен в репозиторий положить и настроенные PHP c Апачем?
Посмотри на свои посты. Если бы не на начал тут всех учить, а просто нормально спросил, почему так, то никто бы ничего не сказал. Веди себя адекватнее.
> никто бы ничего не сказал
а кто что-то сказал?
ты аутист какой-то
>просто нормально спросил
>зачем загружать в гит пол проекта?
Ну нет, ты не нормально спросил, а написал пост в стиле «ты все делаешь неправильно», да еще и в крайне невежливой форме, обругал тут всех, потому я принял тебя за местного тролля и решил прогнать чтобы ты не путал людей.
>зачем загружать в гит пол проекта?
ответ здорового программиста
>я использую композер
ответ курильщика
>Исходники Slim'а ты и так можешь найти. Думаешь я Slim переписываю? Я не настолько умный. Оп сказал так правильно.
2 в одном. Хорошая новость.
ответ здорового программиста
>Макака с мемсами не знает про менеджеры зависимостей и что-то там кукарекает :3
но теперь я знаю про менеджер зависимостей и теперь я не макака
Так не работает, если не указывать. Попробовал "../" тоже не пашет. Надо чтоб они работали на одну папку вверх. Попробовал явно указать домен четвертым аргументом - не пашет.
Давай еще раз посмотрим на код.
> action="index.php"
Твоя форма при отправке отправляет POST запрос на URL /index.php относительно корня сайта.
Все запросы к сайту ловятся и обрабатываются файлом index.php, а точнее Слимовским роутером который там вызывается.
У тебя не задано обработчика для URL /index.php потому Слим выводит страницу ошибки. Логично, так и должно быть. Как иначе?
B зачем ты отправляешь именно на index.php? Что за странный URL? Что тебе мешает отправлять форму на /hello/world или /123456 если для любых URL в итоге вызывается index.php?
> А если я обновлю страницу, то все на своих местах.
Если ты по-настоящему обновляешь страницу то отправляется повторный POST запрос с тем же результатом.
> Но я не знаю как же мне загрузить файл на сервер.
Настрой нормально URL на который отправляется форма и его обработку в index.php
Алсо, читани мануал http://php.net/manual/ru/features.file-upload.post-method.php если не читал.
В данном случае файлы еще надо будет как-то по папкам раскладывать и в базу данных информацию о них записывать.
Ну и после загрузки тогда можно редиректить на страницу скачивания.
> <input type="file" size="50"
Зачем size?
Алсо, если у тебя htaccess не в корневой папке то может быть надо добавить RewriteBase (а может и нет, не знаю). Почитай-ка
http://habrahabr.ru/company/sprinthost/blog/129560/
http://httpd.apache.org/docs/current/mod/mod_rewrite.html
> $app->render('header.tpl');
Это абсолютно неправильно. А если ты захочешь JSON отдать или что-то еще? Это надо удалить.
Если ты хочешь выводить шапку и подвал при выводе шаблона, то надо либо
- сделать функцию которая будет это делать (вывести шапку, вывести основной шаблон, вывести подвал)
- либо что лучше сделать шаблон который будет это делать
Давай еще раз посмотрим на код.
> action="index.php"
Твоя форма при отправке отправляет POST запрос на URL /index.php относительно корня сайта.
Все запросы к сайту ловятся и обрабатываются файлом index.php, а точнее Слимовским роутером который там вызывается.
У тебя не задано обработчика для URL /index.php потому Слим выводит страницу ошибки. Логично, так и должно быть. Как иначе?
B зачем ты отправляешь именно на index.php? Что за странный URL? Что тебе мешает отправлять форму на /hello/world или /123456 если для любых URL в итоге вызывается index.php?
> А если я обновлю страницу, то все на своих местах.
Если ты по-настоящему обновляешь страницу то отправляется повторный POST запрос с тем же результатом.
> Но я не знаю как же мне загрузить файл на сервер.
Настрой нормально URL на который отправляется форма и его обработку в index.php
Алсо, читани мануал http://php.net/manual/ru/features.file-upload.post-method.php если не читал.
В данном случае файлы еще надо будет как-то по папкам раскладывать и в базу данных информацию о них записывать.
Ну и после загрузки тогда можно редиректить на страницу скачивания.
> <input type="file" size="50"
Зачем size?
Алсо, если у тебя htaccess не в корневой папке то может быть надо добавить RewriteBase (а может и нет, не знаю). Почитай-ка
http://habrahabr.ru/company/sprinthost/blog/129560/
http://httpd.apache.org/docs/current/mod/mod_rewrite.html
> $app->render('header.tpl');
Это абсолютно неправильно. А если ты захочешь JSON отдать или что-то еще? Это надо удалить.
Если ты хочешь выводить шапку и подвал при выводе шаблона, то надо либо
- сделать функцию которая будет это делать (вывести шапку, вывести основной шаблон, вывести подвал)
- либо что лучше сделать шаблон который будет это делать
домен нужно указывать пятым аргументом
>Надо чтоб они работали на одну папку вверх
хуйня какая-то
дай код, в куске выше всего три параметра
Пятым я имел ввиду, считать разучился. В гугле везде пишет, что надо просто "/" указать четвертым параметром. Но тогда сайт виснет, браузер пишет, что сервер делает бесконечный запрос вероятно из-за того, что не принимает куки. И надо чистить их, чтобы зайти снова.
Кука может быть ограничена по пути (например отдаваться только для адресов начинающихся с x.com/lalala/lololo) и по поддомену (напрмиер сайт x.com может выставить куку доступную только на abc.x.com)
Если домен не указан, берется текущий. Если путь не указан, берется путь к странице которая ставит куку.
Заметь что сайт не может выставлять или получать куки от чужого домена — только свой домен и его поддомены.
Очевидно, ты что-то накосячил с этими опциями потому что не почитал теорию и мануалы, а вместо них посмотрел какой-то плохой урок где это не обхясняется.
Давай исправлять и начнем с теории про куки:
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
http://wiki.dieg.info/cookie
http://curl.haxx.se/rfc/cookie_spec.html (англ)
http://tools.ietf.org/html/rfc6265 (стандарт на англ, много букв)
Затем, разобравшись с аттрибутами ты открываешь инспектор в браузере (Ctrl +Shift + I), в нем вкладку Network, заходишь на страницу которая ставит куку и смотришь заголовок Set-Cookie на вкладке Network. По нему ты определяешь, правильные ли ты параметры задал для куки и если нет то исправляешь.
Кстати, выставленные для сайта куки тоже видны в инстпекторе Хрома на вкладке Resources.
А, вижу ты уже инспектором посмотрел заголовки. Видно, что ни domain ни path не выставлены — а раз так, берутся их значения по умолчанию. Из-за которых видимо кука отдается не для всех страниц.
> дай код, в куске выше всего три параметра
Все просто, смотри, если в коде ниже убрать переадресацию и вывести куки, то он показывает их. Их и те что в родительской директории. Если же включить переадресацию, или просто самому перейти к ../index.php, то там только куки которые назначались оттуда, т.е. в родительской директории нет кук дочерней директории.
выглядит это так:
/chatbox/index.php
/chatbox/includes/user_login.php
http://ideone.com/TpLJDJ
> Заметь что сайт не может выставлять или получать куки от чужого домена — только свой домен и его поддомены
>>390883
> А, вижу ты уже инспектором посмотрел заголовки. Видно, что ни domain ни path не выставлены — а раз так, берутся их значения по умолчанию. Из-за которых видимо кука отдается не для всех страниц.
Это все понятно. Как мне сделать чтобы куки назначались не от директории файла, а от родительской? "../" - не помогает, "/" - вешает все нахуй.
Ты дебил? Ты не можешь написать в чем проблема. так как не знаешь, но пытаешься тут самоутверждаться. Проваливай отсюда, уродец.
>>390792
> указать домен.
> Указал "/",
Ты знаешь, что такое доменное имя? Это вот эта штука: http:// --> google.com <-- /lalala/lololo
Алсо, читай теорию про куки. Надо разобраться в предмете а не пробовать менять код наугад.
> В гугле везде пишет, что надо просто "/" указать четвертым параметром.
Ну такой уровень гугла.
> setcookie("username", $isPassed[0]["username"], time() + 60 60 60 24, "../", "pozor.site40.net");
Почитай стандарты. http://tools.ietf.org/html/rfc6265#section-5.2.4
> If the attribute-value is empty or if the first character of the attribute-value is not %x2F ("/"):
> Let cookie-path be the default-path.
Если путь не начинается с / то он игнорируется и используется путь по умолчанию
То есть ты должен указывать путь начинающийся с / подсказка для умненьких: чтобы работало на всем сайте очевидно надо указать просто /
Алсо, домен можно не указывать - по умолчанию там берется домен страницы.
> "/" - вешает все нахуй.
Ну так исправляй свой кривой код чтобы не вешал. Опять же, разберись что приходит в _COOKIE что в какой переменной и почему так происходит.
> Ты знаешь, что такое доменное имя?
Догадываюсь. Я думал это типо, относительного имени корня данного домена. Сейчас я уже понял , наверное, в чем проблема. Куки просто назначаются в директорию /chatbox/includes, а надо /chatbox. Как?
И вообще, тут (в лучшем мануале по PHP) все написано темным по серому: http://php.net/manual/ru/function.setcookie.php
> path
> Путь к директории на сервере, из которой будут доступны cookie. Если задать '/', cookie будут доступны во всем домене domain. Если задать '/foo/', cookie будут доступны только из директории /foo/ и всех ее поддиректорий (например, /foo/bar/) домена domain. По умолчанию значением является текущая директория, в которой cookie устанавливается.
По моему понятнее написать нельзя.
тебе нужны куки на весь сайт или на 1 страницу?
В index.php
http://ideone.com/63iFjC
В upload.tpl
http://ideone.com/dn4ggx
Но не выводит ничего.
Кстати файлы загружает сейчас нормально:
Я писал $_FILES['userfile'], а в name у меня file.
Запоминание логина. И потом на главной, проверяю куки, и если чекаво то ставлю сессию мол залогинен. А я, ебанутый, после назначений сессии сделал редирект, при чем на эту же страницу. Вчера ночью это было, тупизм увеличился призмой сонливости.
index.php
Но ведь файлы загружаются. И я не хочу, чтобы со всех левых страниц редиректилось на index.php, а наоборот на страницу 404.
Ну и как ты сказал только после загрузки был редирект на страницу скачки файла.
так нихуя не пойдёт
почитай книг, основы всякие
ты будешь с каждым говном днями ебаться
ты для развлечения кодишь?
Кстати htaccess у меня в корне лежит.
Нет. Хочу суметь научиться хотя-бы до уровня гавнокодера ущербной шаражки, физическая работа - это пиздец. Какие книги? Что за основу? Не понимаю что точно мне читать. К тому же просто читать быстро забрасывается, и вообще не откладывается в голове. К тому же такое гавно вроде и вылазит на практике в начале пути, не? В книге тебе не напишут, что ты тупое существо, сделало редирект на эту же страницу, хз что вообще меня надоумило на это вчера. Совсем мозги размылились.
> был редирект на страницу скачки файла.
Я не вижу в коде редиректа так что ты наверно просто ты что-то другое называешь этим словом. Редирект — это код 3XX и заголовок Location которые направляют браузер на другую страницу.
> index.php
> Но ведь файлы загружаются.
Не знаю, что там и как загружается. Но если ты отправляешь форму на адрес index.php то обработчик
$app->post('/')
вызван не будет. Чтобы он был вызван, надо отправлять форму на URL /
> Кстати htaccess у меня в корне лежит.
То есть у тебя сайт находится в корне виртуального хоста, куда указывает DocumentRoot, а не в подпапке?
> Я не вижу в коде редиректа так что ты наверно просто ты что-то другое называешь
Я бы хотел, чтобы он был. Да, его нет.
Приходи в наш тред, проси задачки (или приходи со своими), мы тебе и ссылки что почитать дадим, и скажем где у тебя код неправильно написан. Но у нас ООП и придирки к каждой строчке кода, имей в виду.
Короче: в action должен быть указан тот же URL что и в обработчике $app->post. Иначе работать не будет, очеивидно.
Может ты путаешь, видишь что идет отправка запроса браузером и думаешь что это и есть «загрузка файла»?
Ну да. Так что если хочешь получить советы и замечания по коду, можешь его выложить куда-нибудь (ideone/github) и показать нам.
>придирки к каждой строчке кода
ты не думаешь что это лишнее?
я не предлагаю учить говнокодить, но кажется это излишний перфекционизм.
> куда указывает DocumentRoot
Сайт в DocumentRoot лежит. Не создавал я виртуальный хост. У меня не получилось, ты же помнишь. Я просто поменял значение DocumentRoot, который указывал на htdocs.
>>390915
Нет я вижу скаченные файлы в папке uploads. Я на гит еще не выложил новые изменения. Сейчас глянь:
https://github.com/fxsloker/rgclone.ru
Revert у меня все поменял в файлах.
https://github.com/fxsloker/rgclone.ru
Вот сейчас правильный вариант.
Тяжело в учении. Если человек пишет не как попало, а с пониманием, то у него этого не будет, а если не понимает то надо направить на правильный путь. Так как мелкая ошибка может быть признаком того что человек что-то не знает.
>>390921
Вохможно, Слим по каким-то соображениям вырезает index.php из URL так как он совпадает с именем скрипта. Это не очень хорошо, конечно. В любом случае в action формы надо прописать не index.php а / тогда.
http://ideone.com/fASJZs
Оп, так почему flash не работает? И редирект не работает тоже пишет upload не найден, хотя я его прописал выше.
Это такая доска, что из одной формы она ставит подпись, а из высплывающего окна нет. Попробуй сам.
>>390929
> И редирект не работает тоже пишет upload не найден, хотя я его прописал выше.
Кто пишет? Слим? Апач? Что в адресной строке браузера?
> так почему flash не работает?
flash кладет что-то в сессию и берет из нее при следующем запросе. Попробуй сдампить _SESSION и посмотреть что там.
> Что в адресной строке браузера?
http://rgclone.ru/upload
Not Found
The requested URL /upload was not found on this server.
Но /upload прописан выше.
я вижу уже 30+ тред, ты долго этим занимаешься.
тебе удобно в одной тредопортянке отвечать куче народа?
что ты думаешь на счёт запиливания какой-либо площадке, например форуме, где у каждого анона будет своя ветка, где можно будет стереть неадекватов
?
Если это ошибка Апача, которая выглядит так:
http://perishablepress.com/wp/wp-content/images/2009/pimp-your-404/404-01.gif
http://www.elated.com/res/Image/articles/management/apache/making-a-custom-error-page/apache_404_default.gif
— то значит что управление не доходит до PHP и что ты написал в index.php не имеет значения.
Почему это возможно? Потому, что ты где-то накосячил с htaccess. Например, в конфиге веб-сервера не разрешил использование htaccess (опция http://httpd.apache.org/docs/current/mod/core.html#allowoverride )
Или еще какая-то причина, например неправильный код в htaccess (тот что в гите выглядит праивльным)
Нет, у меня сейчас не так как в гите, а как здесь:
http://ideone.com/fASJZs
Оп, и вроде это не апачевская ошибка, судя по картинкам. Index.php же видит. Он думает, что редиректится на неизвестную страницу. Почему-то
$app->get('/upload', function() use ($app) {
$app->render('upload.tpl');
})->name("upload");
Не имеет силу.
Мы можем попробовать запилить ОПу что-нибудь типа форума и за одним попрактиковаться.
>попрактиковаться
вот этого пожалуйста не надо
берём хостинг, бесплатный форумный движок, и соединяем это
Установить, настроить, допиливать под свои требования, модерировать.
>>390939
Скриншот сделай.
> Index.php же видит.
Потому что тут в URL явно указано имя файла. По умолчанию Апач отдает/выполняет тот файл который указан в URL.
> Не имеет силу.
Интуиция подсказывает мне что это ошибка Апача. Ты можешь проверить лог ошибок и увидеть там эту 404 (логи хранется скорее всего в папке Апача/logs)
>>390938
Если кратко:
> мне в отпочковавшихся классах нужно работать с бд, работать с компонентами и т.д.
> я передаю туда $this, то есть экземпляр контроллера (это так называется?)
Это плохо так как ты с таким же успехом можешь это прямо в тело контроллера вписать. Это фактически часть контроллера и у тебя фактически толстые контроллеры. Этот код нельзя вызвать без контроллера потому он не повторно используемый.
Надо передавать только конкретные зависимости. Вообще это отдельная тема передачи зависимостей под названием DI (dependency injection) и там свои паттерны и антипаттерны. Вот статья классика на английском: http://www.martinfowler.com/articles/injection.
Переводы (неизвестного качества): http://www.google.ru/search?sourceid=chrome&ie=UTF-8&q=%D1%84%D0%B0%D1%83%D0%BB%D0%B5%D1%80+dependency+injection
Если ты хочешь быть хорошим разработчиком ты должен
это все прочесть и понять что хорошо а что плохо и почему передавать контроллер плохо.
> это нормальная практика? то есть у меня все отпочковавшиеся классы всё равно связаны с контроллерами
Это значит у тебя толстые контроллеры и код можно смело вписать назад в них. Твой коллега тут был прав.
> можно ли применять всё что в ней описано к мвц?
> не накладывает ли мвц каких-то ограничений на работу с классами?
MVC — концепция разделения кода на M, V и С и ничего более. И это не значит что любой класс можно отнести к M, V или С. Может быть и просто дополнительный класс-утилита например.
> когда я создаю класс - он же перестаёт быть контроллером. можно условно сказать что этот класс должен вести себя как контроллер, но по сути это отдельный класс и из него я могу делать что хочу. так или не так?
В твоем CakePHP контроллер — это то, что унаследовано от Controller. Так что новый класс формально перестает быть контроллером. Но если ты пытаешься его использовать как контроллер и писать там код как в контроллере то это плохо.
> например обращение к бд. я всё равно не могу обратится к бд напрямую. или могу? такой класс - это отдельная сущность или на него распространяется всё что распространяется на контроллер\модель, откуда он был вынесен?
Ты можешь но будет бардак. Чтобы бардака не было, вся работа с Бд должна быть изолирована в 1 или нескольких классах, например в твоем CakePHP это модели. Каждый должен заниматься своим делом.
Установить, настроить, допиливать под свои требования, модерировать.
>>390939
Скриншот сделай.
> Index.php же видит.
Потому что тут в URL явно указано имя файла. По умолчанию Апач отдает/выполняет тот файл который указан в URL.
> Не имеет силу.
Интуиция подсказывает мне что это ошибка Апача. Ты можешь проверить лог ошибок и увидеть там эту 404 (логи хранется скорее всего в папке Апача/logs)
>>390938
Если кратко:
> мне в отпочковавшихся классах нужно работать с бд, работать с компонентами и т.д.
> я передаю туда $this, то есть экземпляр контроллера (это так называется?)
Это плохо так как ты с таким же успехом можешь это прямо в тело контроллера вписать. Это фактически часть контроллера и у тебя фактически толстые контроллеры. Этот код нельзя вызвать без контроллера потому он не повторно используемый.
Надо передавать только конкретные зависимости. Вообще это отдельная тема передачи зависимостей под названием DI (dependency injection) и там свои паттерны и антипаттерны. Вот статья классика на английском: http://www.martinfowler.com/articles/injection.
Переводы (неизвестного качества): http://www.google.ru/search?sourceid=chrome&ie=UTF-8&q=%D1%84%D0%B0%D1%83%D0%BB%D0%B5%D1%80+dependency+injection
Если ты хочешь быть хорошим разработчиком ты должен
это все прочесть и понять что хорошо а что плохо и почему передавать контроллер плохо.
> это нормальная практика? то есть у меня все отпочковавшиеся классы всё равно связаны с контроллерами
Это значит у тебя толстые контроллеры и код можно смело вписать назад в них. Твой коллега тут был прав.
> можно ли применять всё что в ней описано к мвц?
> не накладывает ли мвц каких-то ограничений на работу с классами?
MVC — концепция разделения кода на M, V и С и ничего более. И это не значит что любой класс можно отнести к M, V или С. Может быть и просто дополнительный класс-утилита например.
> когда я создаю класс - он же перестаёт быть контроллером. можно условно сказать что этот класс должен вести себя как контроллер, но по сути это отдельный класс и из него я могу делать что хочу. так или не так?
В твоем CakePHP контроллер — это то, что унаследовано от Controller. Так что новый класс формально перестает быть контроллером. Но если ты пытаешься его использовать как контроллер и писать там код как в контроллере то это плохо.
> например обращение к бд. я всё равно не могу обратится к бд напрямую. или могу? такой класс - это отдельная сущность или на него распространяется всё что распространяется на контроллер\модель, откуда он был вынесен?
Ты можешь но будет бардак. Чтобы бардака не было, вся работа с Бд должна быть изолирована в 1 или нескольких классах, например в твоем CakePHP это модели. Каждый должен заниматься своим делом.
Я же требовательный, вы замучаетесь допиливать. Хотя идея попробовать сделать не учебный, а полезный кому-то проект мне нравится. Но чтобы до этого дойти, надо какие-то знания сначала накопить.
Если у кого-то есть идеи простых, но востребованных проектов — пишите, может действительно соберемся, делаем что-нибудь и на гитхаб выложим для всех. Вот, кто-то например говорил про мониторинг доменов (чтобы не забыть продлить). Это небольшое, но полезное приложение.
Алсо, если хочешь запилить простую борду то у нас есть верстка: https://github.com/codedokode/board-markup
В error.log Апача я специально все стер и заново попробовал. Там ничего не пишет.
>но полезное приложение
которых существует тысячи
алсо сейчас истекает домен, который я не буду продлевать так меня за 2 месяца просто доебали спамом. даже смс прислали, откуда у них мой номер вообще? из вхуис взяли?
>>390946
опять начинается путаница.
>Это значит у тебя толстые контроллеры и код можно смело вписать назад в них
а если модели, можно?
>вся работа с Бд должна быть изолирована в 1 или нескольких классах
имеешь ввиду find\findall ?
да, работа с бд идёт через них, и из моделей я получаю данные через них. через find\findall приемлемо работать с бд из таких классов вынесенных из моделей куда я передал this
алсо, я не могу в класс передать всё что нужно. мне нужно куча всего, в том числе наследования метода в контроллере от которого я выделил этот класс. как решить эту проблему? оставить всё в модели? тогда получатся модели на 3000 строк с четырмя десятками методов. это ок?
Поставь в начале index.php
http://ideone.com/31O4Yx
чтобы увидеть что он выполняется. Если нет — значит дело в Апаче.
> а если модели, можно?
Нет. Если ты делаешь новый класс, в который передаешь только ссылку на старый, то весь код из этого класса логичнее вписать прямо в старый.
> через find\findall приемлемо работать с бд из таких классов вынесенных из моделей куда я передал this
Работать приемлемо а вот передавать this не особо приемлемо.
> алсо, я не могу в класс передать всё что нужно. мне нужно куча всего,
Тебе нужен рефакторинг (чтобы не было столько зависимостей). И чтение статьи про DI. В фремворках типа CakePHP как я понимаю вместо решения проблемы тупо передают в класс $app (что в общем с тз архитектуры скорее антипаттерн так как вместо того чтобы явно обозначить зависимость класса ты передаешь туда все сразу в куче. Такой класс не получится использовать без фреймворка и других классов).
> оставить всё в модели? тогда получатся модели на 3000 строк с четырмя десятками методов. это ок?
3000 / 40 ~ 90 строк на функцию. Что так много? Или это наполовину документация? Тогда может быть ок. Если нет то скорее всего ты все свалил в одну функцию вместо того чтобы сделать декомпозицию на отдельные подзадачи и вынести их в другие классы.
Код выглядит верный. При открытии страницы /upload должна по идее вызываться соотв. функция и выводиться страница из шаблона upload.tpl.
http://rghost.ru/private/58252267/765f69b654a1ca27040555e1f93738e9
Посмотри еще раз мой httpd.conf
>Что так много?
это цифры на вскидку так как половина логики в классах.
если я засуну всё в модель - получится дохуя кода
>вынести их в другие классы
это невозможно
например мне нужен модуль поиска, он должен активно работать с бд, работать с компонентами, тянуть методы из апп_контроллера, использовать методы в модели, из которой он отделён.
сейчас я передаю this и не заморачиваюсь. ты предлагаешь на создание каждого класса передавать ему дохуя параметров в виде бд, методов и прочего? это будет такой же говнокод
Не забывай что при любом изменении в конфиге Апач надо перезапускать.
> AllowOverride none
Ты читал ссылку что я давал про htaccess? По идее это отключает чтение htaccess файлов Апачем.
http://httpd.apache.org/docs/current/mod/core.html#allowoverride
http://httpd.apache.org/docs/current/howto/htaccess.html
Обрати внимание что когда Апач игнорирует записи из htaccess он пишет уведомление в лог ошибок об этом.
> например мне нужен модуль поиска, он должен активно работать с бд, работать с компонентами, тянуть методы из апп_контроллера, использовать методы в модели, из которой он отделён.
Это сейчас тебе все это нужно. А если отрефакторить то может будет и не нужно. Скорее всего ты просто пишешь код по принципу «простыни», то есть все одной такой длинной функцией, вместо того чтобы разбить на отдельные части.
Ну например в поиске может быть такие части:
— разбор и парсинг поискового запроса на части
— поиск в самой БД через MATCH AGAINST как я понимаю
— добавление дополнительных данных к результатам поиска
Опять же, я кода не вижу, но уверен что это можно сделать компактнее. Или хотя бы вынести в класс-сервис Search.
> сейчас я передаю this и не заморачиваюсь.
Это некачественный код.
> ты предлагаешь на создание каждого класса передавать ему дохуя параметров в виде бд, методов и прочего?
То есть статью читать, изучать DI и просвещаться ты не хочешь.
http://ideone.com/FHEgzf
Заменил на All. Ему понравилось по-моему, что даже главную теперь не открывает.
Там страница 404, он ничего не пишет кроме нее. Это я в смысле того, что пробовал.
> Invalid command 'RewriteEngine', perhaps misspelled or defined by a module not included in the server configuration
Погугли эту ошибку. Раньше ее не было так как ты отключил исполнение htaccess и перенаправление всех запросов на index.php не работало.
А ты die() поставил? Slim перехватывает вывод и если не ставить die() то можно не увидеть ничего.
Если все равно 404 это значит что index.php не вызввается в этом случае и проблема в Апаче.
Заработало! Нагуглил, что модуль выключен.
Надо подробно изучить htaccess, а то я даже не понимаю, что там пишу.
я хочу понять вначале что именно делаю не так и на что мне обращать внимание перед чтением.
ок, прочту
https://github.com/revuls/SlimMVC?files=1
Оп, как прокомментируешь эту структуру. Стоит использовать?
Сомнительный код, да еще и на статических методах. Что там можно взять? Там авторского кода 100 строчек максимум.
Автор забывает что Слим — микрофреймворк, то есть предполагается что в нем будет немного маршрутов и выносить их в такие файлы https://github.com/revuls/SlimMVC/tree/master/routers не требуется
Если у тебя немного маршрутов, ты их пишешь в index.php. Если много — берешь полноценный фреймворк.
Класс Core непонятно зачем нужен. Класс Config зачем-то на статических методах написан.
Плюс, он дублирует то что уже есть в Слиме (конфиг например).
Оп, помнишь ты говорил, что так можно и админку написать для джумлы? В общем я решил написать. Мне надоела ее тормознутость. Просто я столько времени на работе теряю.
Ты проконтролируешь мою писанину? Я думаю сделать ее универсальной, то есть можно к любой версии джумлы подключать.
Из функций:
- массово закидывать статьи, то есть я нажимаю кнопку добавить пишу что-то типа:
<h1>title</h1>
<p>text</p>
Далее нажимаю еще одну кнопку добавить и т.д. Без перезагрузки страницы.
То, что в h1 нужно закидывать и в базу как title, user автоматически ставится как и на всех остальных материалах.
В джумле 3 еще нужно добавлять данные в таблицу assets, а то все полетит к чертям, что усложняет дело.
- выбор создавать ли для этого материала меню или нет (флаг), соответственно меню для этого материала создается автоматически, что исправляет кривую ссылку материала (это делается только для этого)
- keywords, title, description создаются автоматически, если не были указаны. Тут сложность: сначала ищется название в самом материале, если нет, то в титле главной страницы и ее тексте, если там нет, то во всех материалах. Преимущественно конечно должно быть то, что написано в тегах h1. То есть собирается некая статистика. Выбирается город, который чаще встречается в тексте сайта. 90%, что это будет верны город.
А также можно самому в начале формы проставить какой город юзать в дискрипшинах, титлах и кейвордсах, а также в титлах и альтах картинок (т.к. они должны совпадать с титлом страницы).
Алгоритм составления титла: то, что в теге h1 + мой шаблон (опционально) + город (если в теге сам город не указан)
Алгоритм составления кейвордса: все, что в титле через запятую, и исключать повторяющиеся слова.
Алгоритм составления дискрипшина: все, что в титле + мой шаблон
Шаблон я задаю в самом начале.
- следующая функция: массовый поиск по уже имеющимся материалам необходимых строк и замена их на нужный текст
А реально сделать, когда к примеру копируешь некую статью из ворда, и если было правильное форматирование, то выставлялись автоматически теги p, ul, li, h1, h2? Ворд их как-то помечает, а потом когда вставляешь текст в dreamweaver, то все эти теги проставляются. Как это делает dreamweaver?
Ну пока все, но хотелось бы еще, чтобы админка была расширяема, то есть можно было без труда добавлять новые возможности.
Оп, подскажи, может мысли какие есть? Или скажи, что это все бредовая идея, и не стоит свое время на это тратить, а лучше заниматься рутиной.
Может это сделать как api?
Оп, помнишь ты говорил, что так можно и админку написать для джумлы? В общем я решил написать. Мне надоела ее тормознутость. Просто я столько времени на работе теряю.
Ты проконтролируешь мою писанину? Я думаю сделать ее универсальной, то есть можно к любой версии джумлы подключать.
Из функций:
- массово закидывать статьи, то есть я нажимаю кнопку добавить пишу что-то типа:
<h1>title</h1>
<p>text</p>
Далее нажимаю еще одну кнопку добавить и т.д. Без перезагрузки страницы.
То, что в h1 нужно закидывать и в базу как title, user автоматически ставится как и на всех остальных материалах.
В джумле 3 еще нужно добавлять данные в таблицу assets, а то все полетит к чертям, что усложняет дело.
- выбор создавать ли для этого материала меню или нет (флаг), соответственно меню для этого материала создается автоматически, что исправляет кривую ссылку материала (это делается только для этого)
- keywords, title, description создаются автоматически, если не были указаны. Тут сложность: сначала ищется название в самом материале, если нет, то в титле главной страницы и ее тексте, если там нет, то во всех материалах. Преимущественно конечно должно быть то, что написано в тегах h1. То есть собирается некая статистика. Выбирается город, который чаще встречается в тексте сайта. 90%, что это будет верны город.
А также можно самому в начале формы проставить какой город юзать в дискрипшинах, титлах и кейвордсах, а также в титлах и альтах картинок (т.к. они должны совпадать с титлом страницы).
Алгоритм составления титла: то, что в теге h1 + мой шаблон (опционально) + город (если в теге сам город не указан)
Алгоритм составления кейвордса: все, что в титле через запятую, и исключать повторяющиеся слова.
Алгоритм составления дискрипшина: все, что в титле + мой шаблон
Шаблон я задаю в самом начале.
- следующая функция: массовый поиск по уже имеющимся материалам необходимых строк и замена их на нужный текст
А реально сделать, когда к примеру копируешь некую статью из ворда, и если было правильное форматирование, то выставлялись автоматически теги p, ul, li, h1, h2? Ворд их как-то помечает, а потом когда вставляешь текст в dreamweaver, то все эти теги проставляются. Как это делает dreamweaver?
Ну пока все, но хотелось бы еще, чтобы админка была расширяема, то есть можно было без труда добавлять новые возможности.
Оп, подскажи, может мысли какие есть? Или скажи, что это все бредовая идея, и не стоит свое время на это тратить, а лучше заниматься рутиной.
Может это сделать как api?
только я не понял как мне из класса вызвать метод контроллера
я передам дб, ок, а для того чтобы вызвать метод мне нужно передать this, иначе никак же
Конечно, ты же программист, все что автоматизируется, надо автоматизировать.
Но я бы такие вещи делал скорее как скрипт. То есть сделал библиотеку простых функций (типа добавления статьи), и когда надо добавить 100 статей или отредактировать или метатеги проставить, накатал быстро скриптик, запустил в консоли и готово.
А ты опять хочешь сделать GUI в который надо что-то вводить, нажимать, в общем, ручной труд. Стоит ли тратить на него (GUI) время, которого может уйти немало? Я не уверен.
Для замены тебе придется изобретать свой язык шаблонов, это все надолго может затянуться. по моему код написать выйдет быстрее.
Но конечно я не знаю, какие там перед тобой задачи, может действительно удобнее форму с кнопками сделать. Но мне больше консольные скрипты нравятся.
И если ты говоришь что админка Джумлы тормозит, может просто сервер плохо настроен? Дать побольше памяти под MySQL, включить кеширование опкодов, еще что-нибудь может и не будет тогда тормозить? Ты не пробовал гуглить на эту тему?
> А реально сделать, когда к примеру копируешь некую статью из ворда, и если было правильное форматирование, то выставлялись автоматически теги p, ul, li, h1, h2? Ворд их как-то помечает, а потом когда вставляешь текст в dreamweaver, то все эти теги проставляются. Как это делает dreamweaver?
Ворд вставляет в HTML очень много мусора. Попробуй вставить текст из ворда в WYSIWYG-редактор и посомтреть получившийся HTML. Соответственно надо написать какую-то штуку (возможно это удобно делать с помощью DOM или SimpleXML) которая пройдется и исправит текст. Если у тебя заголовки в ворде сделаны просто увеличением шрифта, то придется как-то хитро анализировать это.
Алсо, я бы погуглил, нет ли готовых решений. Наша цель ведь как можно быстрее решить задачу.
>>391251
> только я не понял как мне из класса вызвать метод контроллера
Код в контроллере нельзя повторно использовать. Ты не можешь из стороннего класса вызывать методы контроллера. Ты должен отрефакторить код чтобы вынести этот метод из контроллера в модель или класс-сервис где его можно будет вызвать.
Именно по этой причине я раза 3 повторил фразу «тонкие контроллеры» ранее.
> а для того чтобы вызвать метод мне нужно передать this, иначе никак же
У тебя просто неправильно написан код. Надо его исправить, чтобы this не требовался, а не передавать this.
Имей в виду, что если речь о существующем проекте то переписывать его не стоит. Почему — объясняет Джоэл (он очень умный):
http://habrahabr.ru/post/219651/ (перевод)
http://www.joelonsoftware.com/articles/fog0000000069.html (оригинал)
Если у тебя уже есть сколько-нибудь большой проект, то оставь его как есть и быдлокодь дальше, а правильную архитектуру строй на следующем или для нового добавленного кода.
Видишь ли в рунете ничего дельного нет, а на английском не знаю какие у них там выражения в ходу. Отсеивать сложно.
Подобное находит не то, что надо:
joomla adding many articles programmatically
script for joomla creating articles programmatically
creating articles in joomla with php
http://www.joelonsoftware.com/articles/fog0000000043.html (англ)
http://russian.joelonsoftware.com/Articles/TheJoelTest.html (перевод)
который позволяет оценить уровень разработки в вашей компании ответив на 12 вопросов да/нет. Можете себя проверить.
Я попробовал оценить организацию обучения в нашем треде с помощью этих вопросов:
+ Do you use source control?
- Can you make a build in one step? (но у нас и билдить-то особо нечего пока)
+ Do you make daily builds? (у нас не надо делать сборку потому я поставил +)
- Do you have a bug database? (багтрекер мы не используем — я просто пишу замечания в посте)
- Do you fix bugs before writing new code? (увы)
- Do you have an up-to-date schedule?
- Do you have a spec? (описание у задач на спеку не тянет)
+ Do programmers have quiet working conditions? (я поставил + так как аноны у нас работают в удобной им обстановке)
- Do you use the best tools money can buy? (нет, мы ничего не купим для вас)
- Do you have testers?
+ Do new candidates write code during their interview? (я поставил + так как код я заставляю писать всех)
- Do you do hallway usability testing? (а что это?)
Получается 4/12. Нам есть куда расти.
Это называется «joomla bulk add articles»: http://www.google.ru/search?aq=f&sourceid=chrome&ie=UTF-8&q=joomla+bulk+add+articles
Bulk — значит массово. Также можно искать по словам «automated adding», «script to add articles» или «add via api».
Что касается добавления статей, может тебе как-то удобно из html-файлов добавлять их было бы? Тогда можно консольный скрипт написать который их импортирует (а если очень напрячься то еще и с возможностью обновления).
Ну да неплохо бы, тем более начало уже было положено.
http://ideone.com/jtyPRn
Остается считать все html файлы в директории, положить в массив и циклом добавлять по одной. Опять же нужно понять как работает таблица assets. Пишут, если про нее забыть у сайта могут возникнуть серьезные проблемы. Добавляешь статью, добавь и туда запись.
Там выставляются какие-то права доступа, система иерархии какая-то, как я понял. Что-то вроде дерева, раз указываются поля left, right, parent и т.д. И за меня их никто не пропишет.
Да, left/right/parent — это явный признак использования Nested Sets для хранения дерева:
http://www.getinfo.ru/article610.html
Про assets что-то гуглится тут: http://stackoverflow.com/questions/12877216/joomla-assets-table-purpose и далее по ссылкам.
Связь между таблицами можно увидеть по наличию FOREIGN KEY (его можно увидев сделав например в консоли MySQL команду SHOW CREATE TABLE table\G или GUI программой).
В коде Джумлы по идее должны быть какие-то функции для работы с этим деревом. Напрямую в него лезть не стоит.
http://jsbin.com/mucujuyovoqe/1/edit - пока без линий электропередач. Не знаю для них нужен отдельный массив или скидывать в один массив вместе с другими элементами? Если в 1 массив, тогда в makeBalance придется еще дописывать.
Пробовал array_fill(0, n, new Test), но создаётся массив ссылок на один и тот же объект. Получается, только циклом можно?
>Код в контроллере нельзя повторно использовать
поясни
вызов метода контроллера из двух мест - это нельзя?
а вызов того же метода из класса - это тоже нельзя? а в чём разница? разве методы в контроллере пишутся не для того чтобы вызывать их?
>переписывать его не стоит
где та тонкая грань между переписать и отрефакторить?
иногда во время рефакторинга я пишу заново и старые куски просто удаляю. это считается за переписать?
>из контроллера в модель
вот смотри класс:
class strepsils{
}
ты пишешь:
>в модель ... где его можно будет вызвать.
как возможно вызвать из такого пустого класса модель? он же никак не связан с фреймворком. а для связи я и использую this
Если ширина задается в зависимости от внутреннего текста, то как задавать? Если же задаешь что-то в процентах, то берется ширина родителя.
>Смотри, если подумать головой, от чего зависит ширина пункта меню «About us»? Если подумать, то она равна ширине текста + какие-то небольшие поля с краев (включая иконку). Логично? Логично. А как ее задал ты?
Там же text-align: center; нужен? Я пробую, но у меня получается, что сильно отклоняется от макета и залезает на иконки.
>У псевдоэлемента свой фон, независимый от родителя. И размеры свои.
Получается, что смысла использовать спрайт нету? Ведь мне придется для каждого псевдоэлемента загружать фон.
Я бы еще все поместил в <div id="wrapper"> и задал бы ему прозрачный фон как у #fon, a <div id="fon"> соответственно убрал бы. Не люблю пустые и ненужные теги. Ну или в крайнем случае можно к body применить эти же стили.
.bannera можно убрать opacity:1;. Да и он там 2 раза встречается.
У .text я бы проценты поменял бы на пиксели.
Как же хорошо комментировать чужую работу. Завидую ОПу.
Я кстати не ОП.
> this.balance = 0;
Ты нигде больше в других функциях это значение не используешь, зачем его тогда сохранять? Используй простую переменную.
Да и вообще, если подумать баланс это не совсем свойство электросети хотя бы потому что он зависит от времени суток, а у тебя свойство одно. Значит, оно изначально неправильно спроектировано.
Да и зачем сохранять balance в свойство, если мы можем в любой момент его вычислить? Я думаю, незачем.
То есть вместо метода задающего this.balance стоит сделать метод который считает баланс, возвращает и никуда не сохраняет. Кому надо, тот сам куда-нибудь его сохранит.
> function Powerhouse(generatedPower) {
Когда ты делаешь наследование, надо вызывать конструктор предка (ElementsNetwork). Он у тебя пустой, но вызывать все равно стоит на случай если туда кто-то что-то впишет.
> constructor = this.constructor;
var забыл
Если поставить в начало кода "use strict"; (почему не поставил?) то вывалятся среди прочего такие варнинги на jsbin:
> Line 64: var constructor = this.constructor; --- Possible strict violation.
> Line 77: constructor = this.constructor; --- Possible strict violation.
> Line 94: constructor = this.constructor; --- Possible strict violation.
> Line 115: var constructor = this.constructor; --- Possible strict violation.
Это ошибки и их надо исправить.
Сама логика вполне верная.
> Не знаю для них нужен отдельный массив или скидывать в один массив вместе с другими элементами? Если в 1 массив, тогда в makeBalance придется еще дописывать.
По моему в 1 массив проще выходит. Но можешь сделать и на двух.
Линии надо выбирать по цене: если покупаем то покупаем начиная с дешевой, если продаем то с дорогой.
> this.balance = 0;
Ты нигде больше в других функциях это значение не используешь, зачем его тогда сохранять? Используй простую переменную.
Да и вообще, если подумать баланс это не совсем свойство электросети хотя бы потому что он зависит от времени суток, а у тебя свойство одно. Значит, оно изначально неправильно спроектировано.
Да и зачем сохранять balance в свойство, если мы можем в любой момент его вычислить? Я думаю, незачем.
То есть вместо метода задающего this.balance стоит сделать метод который считает баланс, возвращает и никуда не сохраняет. Кому надо, тот сам куда-нибудь его сохранит.
> function Powerhouse(generatedPower) {
Когда ты делаешь наследование, надо вызывать конструктор предка (ElementsNetwork). Он у тебя пустой, но вызывать все равно стоит на случай если туда кто-то что-то впишет.
> constructor = this.constructor;
var забыл
Если поставить в начало кода "use strict"; (почему не поставил?) то вывалятся среди прочего такие варнинги на jsbin:
> Line 64: var constructor = this.constructor; --- Possible strict violation.
> Line 77: constructor = this.constructor; --- Possible strict violation.
> Line 94: constructor = this.constructor; --- Possible strict violation.
> Line 115: var constructor = this.constructor; --- Possible strict violation.
Это ошибки и их надо исправить.
Сама логика вполне верная.
> Не знаю для них нужен отдельный массив или скидывать в один массив вместе с другими элементами? Если в 1 массив, тогда в makeBalance придется еще дописывать.
По моему в 1 массив проще выходит. Но можешь сделать и на двух.
Линии надо выбирать по цене: если покупаем то покупаем начиная с дешевой, если продаем то с дорогой.
>>391454
Каждый объект надо создавать через new (либо копировать через clone). Такой готовой функции нету. Используй цикл либо array_map.
>>391501
Спам фильтр не пропускает: http://ideone.com/IxO2qu
> Если ширина задается в зависимости от внутреннего текста, то как задавать?
Имеется в виду ширина блока равна ширине текста.
А ты делал наши задачки на CSS? там это изучеатся.
Для некоторых элементво можно указать width: auto и тогда длина определится по содержимому (алгоритм shrink-to-fit).
Например, для float, inline-block, positin absolute это работает.
> Получается, что смысла использовать спрайт нету? Ведь мне придется для каждого псевдоэлемента загружать фон.
Не понимаю. по моему мы о каких-то разных вещам говорим. Спрайты позволяют лишь уменьшить число запросов и ускорить загрузку тем самым. Спрайты можно исплоьзовать с псевдоэлементами.
> Я пробую, но у меня получается, что сильно отклоняется от макета и залезает на иконки.
Ты инспектором умеешь пользоваться? (Ctrl + Shift + I в браузере). пробовал им смотреть почему отклоняется?
> font-family: Arial;
> font-size: 14px;
> line-height
Почему не объединишь в одну строку font:....?
> <p class="top">
Это называется заголовок и для этого есть сециальные теги
> <button c
Надо писать type=buttin иначе он вроде бы сабмитит форму (или нет?)
Кнопку которая выглядит как ссылка обычно называют псевдоссылка и делают css-класс для таких случаев.
> button class="enter"
А если надо будет еще пару кнопок похожих, ты еще 2 класса сделаешь? Надо старатьяс делать классы которые можно повторно использовать — не только на данной кнопке но и на любой.
> opacity: 1;
Не надо это писать
> max-height: 202px;
Что за волшебная цифра? Зачем?
Ты позиционируешь попап через fixed. Это имеет тот недостаток, что если попап будет выше экрана, его невозможно проскороллить. Также, fixed работает (работал раньше?) иногда странно на мобильных устройствах с их логикой масштабирования картинки.
> p.top{
p тут излишне.
> p.log{
> padding: 10px 10px 0px 15px;
Поля с краев попапа логичнее задать 1 раз на самом попапе а не у каждого дочернего элемента.
Мышь должна менять вид при наведении на крестик. Зону клика для крестика надо сделать больше, а то трудно попасть.
Для кнопок надо прописать реакцию на наведение.
Правый край полей ввода не выровнен с кнопкой и слишком близко к края попапа.
fon -> overlay
> font-family: Arial;
> font-size: 14px;
> line-height
Почему не объединишь в одну строку font:....?
> <p class="top">
Это называется заголовок и для этого есть сециальные теги
> <button c
Надо писать type=buttin иначе он вроде бы сабмитит форму (или нет?)
Кнопку которая выглядит как ссылка обычно называют псевдоссылка и делают css-класс для таких случаев.
> button class="enter"
А если надо будет еще пару кнопок похожих, ты еще 2 класса сделаешь? Надо старатьяс делать классы которые можно повторно использовать — не только на данной кнопке но и на любой.
> opacity: 1;
Не надо это писать
> max-height: 202px;
Что за волшебная цифра? Зачем?
Ты позиционируешь попап через fixed. Это имеет тот недостаток, что если попап будет выше экрана, его невозможно проскороллить. Также, fixed работает (работал раньше?) иногда странно на мобильных устройствах с их логикой масштабирования картинки.
> p.top{
p тут излишне.
> p.log{
> padding: 10px 10px 0px 15px;
Поля с краев попапа логичнее задать 1 раз на самом попапе а не у каждого дочернего элемента.
Мышь должна менять вид при наведении на крестик. Зону клика для крестика надо сделать больше, а то трудно попасть.
Для кнопок надо прописать реакцию на наведение.
Правый край полей ввода не выровнен с кнопкой и слишком близко к края попапа.
fon -> overlay
Почему?
при скролле страницы с fixed оверлееем приходится перерисовать все окно.
при скролле страницы с absolute оверлеем только небольшую полоску внизу.
>>391612
> бы еще все поместил в <div id="wrapper">
Не уверен, что стоит. Это может усложнить верстку так как мы вынуждены будеv опираться на блок с position fixed.
Да и попап не является частью оверлея.
> У .text я бы проценты поменял бы на пиксели.
Эти стили я не проверяю так как это вспомогательная штука.
> Завидую ОПу.
А ты присоединяйся к обсуждению решений. Только будь ответственнен, взвешен и рассудителен.
>>391642
Если на другую то да, ссылка
Почему?
при скролле страницы с fixed оверлееем приходится перерисовать все окно.
при скролле страницы с absolute оверлеем только небольшую полоску внизу.
>>391612
> бы еще все поместил в <div id="wrapper">
Не уверен, что стоит. Это может усложнить верстку так как мы вынуждены будеv опираться на блок с position fixed.
Да и попап не является частью оверлея.
> У .text я бы проценты поменял бы на пиксели.
Эти стили я не проверяю так как это вспомогательная штука.
> Завидую ОПу.
А ты присоединяйся к обсуждению решений. Только будь ответственнен, взвешен и рассудителен.
>>391642
Если на другую то да, ссылка
1) Кто уже перешел на Yii 2, какие впечатления? (уже ведь вышла рабочая версия)
2) Скажем у меня сайт, на котором постят объявления. Как мне интернационализировать эти объявления? сразу создать такую же таблицу объявлений в базе данных, рассчитанную на другой язык и предлагать пользователям, если хотят, переводить свои же объявления? (живу в стране, где говорят на 2-х языках, так что требуется постоянно)
В таком случае, как мне организовать это в Yii, усли сайт уже готов и все модели для всех таблиц уже построены? (чтоб было ясно, я не спрашиваю, как менять язык и переводить статичные сообщения, я это знаю. как сделать так, чтобы для каждого объявления можно было достать эквивалентное на другом языке)
>>391658
>>391659
Спасибо за советы.
Чуток подредактировал.
http://jsbin.com/fomazikalizu/1/edit
Если php установлен как cgi, при каждом обращении запускается процесс php.
Если как модуль апача — хуй знает.
Допустим ты запустил Хром и открыл в нем какую-то страницу. Что произойдет, если ты не закрывая Хром, запустишь Фаерфокс?
Да ничего особенного, современные ОС многозадачные и в них может параллеьно выполняться несколько программ.
Аналогично делает Апач: он запускает несколько (10-20) процессов-работников и раздает им приходящие запросы. Процесс-работник получает запрос и начинает выполнять соответствующий php-скрипт. Если все они будут заняты, он запускает дополнительные процессы-работники. Таким образом, большое число запросов может обрабатываться параллельно — лишь бы памяти хватало.
Ты можешь спросить, а где здесь PHP? Под Апачом PHP работает как плагин к нему, то есть входит в состав процесса-работника.
Если пользователей очень много (сотни), и все процессы заняты обработкой запросов, только тогда приходящие запросы ставятся в очередь на ожидание.
В случае с 2 пользователями проблем не будет.
Число изначально запущенных проессов и максимальное число процессов настраивается.
Стоит только помнить, что сессии в PHP могут блокировать параллеьный процесс, обращающийся к той же сессии: http://habrahabr.ru/company/bitrix/blog/179803/
Заметь что с точки зрения твоего скрипта эти параллельные процессы изолированы: один скрипт никак не видит и не взаимодействует с параллельно выполняющимися скриптами и никак на них не влияет.
Апач запускает несколько процессор-работников. Под Windows они обычно запускаются как потоки в рамках одного или нескольких процессов (как я понимаю, так памяти меньше расходуется), под linux как независимые процессы.
Справка:
http://httpd.apache.org/docs/2.2/mpm.html
http://www.stableit.ru/2008/01/apache2-prefork-vs-worker.html
Какие еще бывают серверы кроме апача? И почему именно он? Почему часто встречаются советы по использовании связки Nginx и Apache? Что значит "Nginx в качестве проксирующего сервера Apache"?
Смотри, ты написал «грамотный кодер / команда». Но по идее проектирование начинается не с программистов: кто-то придумывает идею продукта, бизнес-модель. Потом дизайнер рисует наброски и макеты интерфейсов, а аналитик расписывает требования. И только потом все это дается программистам на реализацию (а потом тестерам для тестирования и поиска багов). Но тебя, как я понимаю, интересует именно та часть, которой занимаются программисты.
В разных компаниях разный подход. Вот подход небольших и средних компаний:
Проектирование в 99% случаев не подразумевает изобретения чего-то нового, а использование существующих подходов и компонент. Например, делая какое-то веб-приложение, мы можем решить использовать в основе библиотеки A, B и С и фреймворк D.
Соответственно, если у разработчиков есть опыт, то они вспоминают, с чем работать было удобно, с чем нет и делают на основе этого выбор.
Неопытные разработчики выбирают по принципу «читал на Хабре» или «модно среди хипстеров» и разумеется потом заслуженно страдают.
Что касается архитектуры, как я уже написал, ничего нового изобретать не надо, делаем как принято в используемом фреймворке, используем MVC, а если надо что-то сверх того то паттерны проектирования описаны Фаулером.
В более серьезных компаниях, а также в аутсорсерах может быть специальный человек-аналитик, который при проектировании составляет огромное ТЗ, где расписана каждая кнопочка и ее поведение. Программистам фактически остается только переложить это описание на язык программирования. В аутсорсерах этот подход используется когда например проектированием занимается инстранный заказчик, а реализацией — наши местные кодеры. Подробное ТЗ нужно чтобы кодеры не схалтурили.
Также есть разные подходы с точки зрения этапов разработки. Например, очень медленный waterfall ( https://ru.wikipedia.org/wiki/%D0%9A%D0%B0%D1%81%D0%BA%D0%B0%D0%B4%D0%BD%D0%B0%D1%8F_%D0%BC%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C ) когда все далется по порядку и итеративные подходы, когда дизайнер может рисовать новые страницы параллельно с тем, как программисты пишут код. Можешь почитать в том же вики:
https://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%BE%D1%86%D0%B5%D1%81%D1%81_%D1%80%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B8_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%BE%D0%B1%D0%B5%D1%81%D0%BF%D0%B5%D1%87%D0%B5%D0%BD%D0%B8%D1%8F
Из книг про архитектуру можно почитать «Идеальный код» и «Паттерны проектирования для корпоративных приложений», но имей в виду, чтобы их понять, надо иметь определенный опыт.
Смотри, ты написал «грамотный кодер / команда». Но по идее проектирование начинается не с программистов: кто-то придумывает идею продукта, бизнес-модель. Потом дизайнер рисует наброски и макеты интерфейсов, а аналитик расписывает требования. И только потом все это дается программистам на реализацию (а потом тестерам для тестирования и поиска багов). Но тебя, как я понимаю, интересует именно та часть, которой занимаются программисты.
В разных компаниях разный подход. Вот подход небольших и средних компаний:
Проектирование в 99% случаев не подразумевает изобретения чего-то нового, а использование существующих подходов и компонент. Например, делая какое-то веб-приложение, мы можем решить использовать в основе библиотеки A, B и С и фреймворк D.
Соответственно, если у разработчиков есть опыт, то они вспоминают, с чем работать было удобно, с чем нет и делают на основе этого выбор.
Неопытные разработчики выбирают по принципу «читал на Хабре» или «модно среди хипстеров» и разумеется потом заслуженно страдают.
Что касается архитектуры, как я уже написал, ничего нового изобретать не надо, делаем как принято в используемом фреймворке, используем MVC, а если надо что-то сверх того то паттерны проектирования описаны Фаулером.
В более серьезных компаниях, а также в аутсорсерах может быть специальный человек-аналитик, который при проектировании составляет огромное ТЗ, где расписана каждая кнопочка и ее поведение. Программистам фактически остается только переложить это описание на язык программирования. В аутсорсерах этот подход используется когда например проектированием занимается инстранный заказчик, а реализацией — наши местные кодеры. Подробное ТЗ нужно чтобы кодеры не схалтурили.
Также есть разные подходы с точки зрения этапов разработки. Например, очень медленный waterfall ( https://ru.wikipedia.org/wiki/%D0%9A%D0%B0%D1%81%D0%BA%D0%B0%D0%B4%D0%BD%D0%B0%D1%8F_%D0%BC%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C ) когда все далется по порядку и итеративные подходы, когда дизайнер может рисовать новые страницы параллельно с тем, как программисты пишут код. Можешь почитать в том же вики:
https://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%BE%D1%86%D0%B5%D1%81%D1%81_%D1%80%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B8_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE_%D0%BE%D0%B1%D0%B5%D1%81%D0%BF%D0%B5%D1%87%D0%B5%D0%BD%D0%B8%D1%8F
Из книг про архитектуру можно почитать «Идеальный код» и «Паттерны проектирования для корпоративных приложений», но имей в виду, чтобы их понять, надо иметь определенный опыт.
Я наверно написал не очень понятный ответ, так что если есть какие-то уточняющие вопросы то пиши.
>>391731
> Как мне интернационализировать эти объявления?
Если языка только 2 и расширения не планируется то можно просто удвоить число колонок в таблице. Это само простое решение.
Если языков больше, то можно добавлять поле «язык» и создавать для объявления несколько строк, можно хранить языковые колонки в отдельной таблице и джойнить как-то.
Готового ответа нет, есть только разные варианты, из которых ты выбираешь какой-то один.
> В таком случае, как мне организовать это в Yii, усли сайт уже готов и все модели для всех таблиц уже построены?
Берешь и меняешь. Автоматического решения, чтобы нажать кнопку и все само заработало, нет.
Из-за box-sizing сломалась высота полей: они стали ниже и пропорции формы нарушились. Как можно не заметить?
Кстати до появления этого свойства проблему 100% ширина решали дополнительным дивом вокруг инпута.
> input.log
> p.log
Не надо одним классом обозначать разные вещи (кстати делать классы из 3 букв тоже не стоит). То, что находится в теге p — это пояснение или описание, потому можно для него написать
.form-comment { ... }
То что касается input, можно написать
.form-input { ... }
или же
.login-form input[type="text"] { ... }
Заметь, что я не пишу названия тегов там, где они избыточны — одного класса достаточно.
> font: 14px Arial ;
> line-height: 1.5;
Это можно объединить в 1 строчку
Также, когда задаешь шрифт, в конце списка шрифтов должен идти один из стандартных. Почитай: http://htmlbook.ru/css/font-family
> max-height: 160px;
Зачем это? В учебных задачах ты должен понимать почему стоит каждое правило, наугад писать нельзя. Почему именно 160? И почему max-height а не height?
> line-height: 35px;
Я думаю, лучше тут поставить паддинг или маргин для отступов сверху и снизу, так как если вдруг придется переносить текст на новую строчку, будут огромные промежутки. line-height все же не для этого сделан.
> white-space: nowrap;
Это неправильно, так как в форме может быть описание не в одну, а в несколько строк (например решили текст поменять). Опять же, используй маргин для создания отступа.
Правильнее конечно было бы использовать вместо exit -> close, banner -> popup (баннер — это рекламная картинка, а всплывающее окно это попап).
В общем, пока главная проблема - то что пропорции нарушились и стали не как на картинке. Ну и небольшие замечания к Css коду.
Из-за box-sizing сломалась высота полей: они стали ниже и пропорции формы нарушились. Как можно не заметить?
Кстати до появления этого свойства проблему 100% ширина решали дополнительным дивом вокруг инпута.
> input.log
> p.log
Не надо одним классом обозначать разные вещи (кстати делать классы из 3 букв тоже не стоит). То, что находится в теге p — это пояснение или описание, потому можно для него написать
.form-comment { ... }
То что касается input, можно написать
.form-input { ... }
или же
.login-form input[type="text"] { ... }
Заметь, что я не пишу названия тегов там, где они избыточны — одного класса достаточно.
> font: 14px Arial ;
> line-height: 1.5;
Это можно объединить в 1 строчку
Также, когда задаешь шрифт, в конце списка шрифтов должен идти один из стандартных. Почитай: http://htmlbook.ru/css/font-family
> max-height: 160px;
Зачем это? В учебных задачах ты должен понимать почему стоит каждое правило, наугад писать нельзя. Почему именно 160? И почему max-height а не height?
> line-height: 35px;
Я думаю, лучше тут поставить паддинг или маргин для отступов сверху и снизу, так как если вдруг придется переносить текст на новую строчку, будут огромные промежутки. line-height все же не для этого сделан.
> white-space: nowrap;
Это неправильно, так как в форме может быть описание не в одну, а в несколько строк (например решили текст поменять). Опять же, используй маргин для создания отступа.
Правильнее конечно было бы использовать вместо exit -> close, banner -> popup (баннер — это рекламная картинка, а всплывающее окно это попап).
В общем, пока главная проблема - то что пропорции нарушились и стали не как на картинке. Ну и небольшие замечания к Css коду.
Есть еще из известных есть IIS (от Майкрософта, работает на Windows-серверах,я с ним не сталкивался).
Исторически, Апач был довольно мощным и к нему была написана куча расширений. Нгинкс появился не так и давно, я помню времена когда его еще не было (точнее когда он был не известен и использовался только его автором, работавшим тогда в Рамблере если я не путаю). Он разработан русским (Игорь Сысоев) и потому исторически более популярен в России (но это не значит что он чем-то хуже западных разработок — просто менее известен). На западе есть похожий на него по архитектуре Lighttpd ( https://ru.wikipedia.org/wiki/Lighttpd ).
Архитектура у них разные. Апач и IIS используют многопоточную модель: они запускают несколько процессов-работников (или потоков-работников внутри 1 процесса) и затем главный процесс раздает им приходящие запросы. Если кто-то из работников тормозит или зависает, остальные работают независимо от него.
Однако каждый процесс (или поток) требует ресурсы, память и процессорное время на запуск и инциализацию. Ты не можешь запустить 10 000 процессов просто так, там число порядка десятков-сотен, если запустить больше то будут слишком большие накладные расходы. Одно только переключение между этими процессами будет занимать значительное время. Это значит что ты не можешь параллельно поддерживать десятки тысяч соединений с пользователями. В вебе это не очень и нужно, так как при использовании HTTP клиент (=браузер) получив нужные файлы, закрывает соединение.
Нгинкс и лайти работают по другой модели — асинхронной. Они используют всего 1 поток, но при этом используют неблокирующие операции. Ну к примеру, вот как работает Апач, получив от браузера запрос на получение файла file.css:
- прочитать часть файла с диска в память (процесс блокируется пока не поступят нужные данные, диск работает не мгновенно)
- передать эти данные в сетевое соединение клиенту (процесс блокируется и ждет пока эти данные уйдут в сеть)
- если мы передали не весь файл, то перейти к пункту 1
- закрыть соединение с клиентом и ждать следующего запроса
Заметь, что большую часть времени процесс ждет — либо пока данные прочитаются с жесткого диска либо пока они уйдут по сети. Если у клиента медленный интернет то ждать придется долго, и все это время процесс не может обрабатывать другие запросы.
Одновременно можно обрабатывать столько запросов, сколько есть процессов-работников, то есть сотни, не больше.
Нгинкс работает по другому. Он работает с использованием неблокирующих вызовов. То есть когда ему надо прочитать данные с диска, он просит систему начать чтение данных, а когда все будет готово, дать ему сигнал, а сам продолжает обрабатывать другие запросы. Когда файл будет прочитан и поступит сигнал, он попросит систему отправить их по сети, а сам снова возвращается к обработке запросов.
Таким образом, 1 процесс может обрабатывать запросы от большого числа клиентов параллельно. Заметь что так как процесс один, то ему ничего не стоит поддерживать большое число клиентов.
Если ты знаком с JS то знаешь что там используется аналогичная асинхронная модель при отправке аякс-запросов: ты указываешь, какую функцию вызвать при поступлении ответа, отправляешь запрос и продолжаешь что-то делать, не блокируясь на то время, пока он будет отправляться и пока будет получаться ответ.
Когда нгинкс появился, он позиционировался не как замена Апачу, а как прокси, который ставился перед Апачем. Идея была в том, что если есть клиент с медленным каналом, то нгинкс перенаправляет его запрос Апачу, тот его обрабатывает и быстро отдает нгиксу, переходя к следующему запросу, а потом нгинкс не спеша скармливает ответ клиенту. Без нгинкс Апач (и PHP в нем) вынуждены ждать пока клиент не примет ответ и все это время занимают память, соединения с базой и другие ценные ресурсы.
Позже в нгинкс добавили возможность работать без Апача: ты можешь запустить несколько процессов PHP (c помощью php-fpm), а нгинкс будет передавать им запросы от клиентов для выполнения по протоколу FastCGI.
Ну и еще нгинкс умеет решать другие задачи: например, добавлять или проверять какие-то заголовки.
> Что значит "Nginx в качестве проксирующего сервера Apache"?
То что он стоит перед Апачем и работает по выше описанной схеме: позволяет Апачу не ждать медленного клиента, а мгновенно отдать ответ нгинксу и перейти к обработке следующего запроса.
Это был обзор вариантов организации сервера для PHP. На других языках веб-сервер часто встроен в само приложение. То есть в случае с Руби: ты запускаешь свое приложение без всяких Апачей, оно открывает 80-й порт и само принимает запросы от бразуеров, вызывая твои функции когда это требуется. Аналогично в Питоне, Node.JS и других языках. Они обычно тоже используют nginx для ускорения обработки запросов.
Есть еще из известных есть IIS (от Майкрософта, работает на Windows-серверах,я с ним не сталкивался).
Исторически, Апач был довольно мощным и к нему была написана куча расширений. Нгинкс появился не так и давно, я помню времена когда его еще не было (точнее когда он был не известен и использовался только его автором, работавшим тогда в Рамблере если я не путаю). Он разработан русским (Игорь Сысоев) и потому исторически более популярен в России (но это не значит что он чем-то хуже западных разработок — просто менее известен). На западе есть похожий на него по архитектуре Lighttpd ( https://ru.wikipedia.org/wiki/Lighttpd ).
Архитектура у них разные. Апач и IIS используют многопоточную модель: они запускают несколько процессов-работников (или потоков-работников внутри 1 процесса) и затем главный процесс раздает им приходящие запросы. Если кто-то из работников тормозит или зависает, остальные работают независимо от него.
Однако каждый процесс (или поток) требует ресурсы, память и процессорное время на запуск и инциализацию. Ты не можешь запустить 10 000 процессов просто так, там число порядка десятков-сотен, если запустить больше то будут слишком большие накладные расходы. Одно только переключение между этими процессами будет занимать значительное время. Это значит что ты не можешь параллельно поддерживать десятки тысяч соединений с пользователями. В вебе это не очень и нужно, так как при использовании HTTP клиент (=браузер) получив нужные файлы, закрывает соединение.
Нгинкс и лайти работают по другой модели — асинхронной. Они используют всего 1 поток, но при этом используют неблокирующие операции. Ну к примеру, вот как работает Апач, получив от браузера запрос на получение файла file.css:
- прочитать часть файла с диска в память (процесс блокируется пока не поступят нужные данные, диск работает не мгновенно)
- передать эти данные в сетевое соединение клиенту (процесс блокируется и ждет пока эти данные уйдут в сеть)
- если мы передали не весь файл, то перейти к пункту 1
- закрыть соединение с клиентом и ждать следующего запроса
Заметь, что большую часть времени процесс ждет — либо пока данные прочитаются с жесткого диска либо пока они уйдут по сети. Если у клиента медленный интернет то ждать придется долго, и все это время процесс не может обрабатывать другие запросы.
Одновременно можно обрабатывать столько запросов, сколько есть процессов-работников, то есть сотни, не больше.
Нгинкс работает по другому. Он работает с использованием неблокирующих вызовов. То есть когда ему надо прочитать данные с диска, он просит систему начать чтение данных, а когда все будет готово, дать ему сигнал, а сам продолжает обрабатывать другие запросы. Когда файл будет прочитан и поступит сигнал, он попросит систему отправить их по сети, а сам снова возвращается к обработке запросов.
Таким образом, 1 процесс может обрабатывать запросы от большого числа клиентов параллельно. Заметь что так как процесс один, то ему ничего не стоит поддерживать большое число клиентов.
Если ты знаком с JS то знаешь что там используется аналогичная асинхронная модель при отправке аякс-запросов: ты указываешь, какую функцию вызвать при поступлении ответа, отправляешь запрос и продолжаешь что-то делать, не блокируясь на то время, пока он будет отправляться и пока будет получаться ответ.
Когда нгинкс появился, он позиционировался не как замена Апачу, а как прокси, который ставился перед Апачем. Идея была в том, что если есть клиент с медленным каналом, то нгинкс перенаправляет его запрос Апачу, тот его обрабатывает и быстро отдает нгиксу, переходя к следующему запросу, а потом нгинкс не спеша скармливает ответ клиенту. Без нгинкс Апач (и PHP в нем) вынуждены ждать пока клиент не примет ответ и все это время занимают память, соединения с базой и другие ценные ресурсы.
Позже в нгинкс добавили возможность работать без Апача: ты можешь запустить несколько процессов PHP (c помощью php-fpm), а нгинкс будет передавать им запросы от клиентов для выполнения по протоколу FastCGI.
Ну и еще нгинкс умеет решать другие задачи: например, добавлять или проверять какие-то заголовки.
> Что значит "Nginx в качестве проксирующего сервера Apache"?
То что он стоит перед Апачем и работает по выше описанной схеме: позволяет Апачу не ждать медленного клиента, а мгновенно отдать ответ нгинксу и перейти к обработке следующего запроса.
Это был обзор вариантов организации сервера для PHP. На других языках веб-сервер часто встроен в само приложение. То есть в случае с Руби: ты запускаешь свое приложение без всяких Апачей, оно открывает 80-й порт и само принимает запросы от бразуеров, вызывая твои функции когда это требуется. Аналогично в Питоне, Node.JS и других языках. Они обычно тоже используют nginx для ускорения обработки запросов.
А, еще нгинкс очень хорошо отдает статику (то есть файлы c диска: CSS, JS, картинки, для отдачи которых не требуется запускать PHP). Нгинкс может легко загрузить гигабитный канал на отдачу, потребляя совсем немного памяти и процессора, в то время как Апач для обработки большого числа соединений должен запустить много процессов-работников и операционная система начинает тратить время на переключения между ними (она же должна останавливать процесс в начале блокирующей операции и возобновлять выполнение позже).
Спасибо, оп. Все предельно понятно и просто. Так надо отказаться от апача? Или все таки использовать в связке? Как я могу экспериментально визуально ощутить разницу в них? Что ты советуешь?
Где отказаться? на локальном компьютере или на сервере? Если на локальном то нет смысла, разве что с целью лучше изучить nginx и php-fpm. Если на сервере — то есть, но надо обязательно прочесть документацию по nginx а не какую-нибудь неграмотную статью с готовыми инструкциями.
Если брать не статику, а PHP-скрипты то особой разницы в плане производительности между
nginx + php-fpm
и
nginx + apache + mod_php
нету.
\t\t$postRestriction = $_POST["lowestPostId"] - 500;
\t} else {
\t\t$postRestriction = 0;
\t}
Не пойму почему $postRestriction возращает NULL, когда $_POST["lowestPostId"] дает число в виде строки
var_dump($_POST["lowestPostId"]);
\tvar_dump($postRestriction); - возращает:
string(4) "3099" NULL
Это копия, сохраненная 24 октября 2014 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.