Сохранен F 523
https://2ch.hk/pr/res/333445.html
Изменился адрес Архивача в сети Tor — arhivachqqqvwqcotafhk4ks2he56seuwcshpayrm5myeq45vlff44yd.onion. Установите Tor Browser для беспрепятственного доступа!

Клуб любителей изучать PHP #13

 !xnn2uE3AU. Срд 06 Ноя 2013 23:20:52  #1 №333445 

Добрый день. В этом треде мы изучаем основы языка PHP (и немного HTML) и решаем простые задачки. Зачем? Кому-то интересно, что такое программирование, или как делают сайты, или просто хочется отвлечься от безделья и поработать мозгами. Полезно же.

Для удобства читателей архивы уроков по PHP выложены по адресу http://archive-ipq-co.narod.ru Если ты ньюфаг, просто решай задачки оттуда, они там реально простые, и пости сюда ссылки на решения, мы посмотрим и скажем, правильно или нет. Если не совсем ньюфаг, напиши, что ты знаешь, что нет, я дам тебе какую-нибудь задачку посложнее.

Требуемые знания: умение включить компьютер и пользоваться браузером. Если ты читаешь этот текст, оно у тебя скорее всего есть. Устанавливать и скачивать пока что ничего не требуется, разве что редактор кода вроде Notepad++ или Sublime (необязательно).

Правила: ведем себя воспитанно, помогаем новичкам, постим ссылки на решения задачек.

Предыдущий тред: >>327422

ОП, как всегда, помогает и дает советы, отвечает на самые нубские и простые вопросы. У ОПа есть почта, так что даже если он не появляется в треде уже неделю, вы всегда можете написать ему что-то хорошее.

Оформляй код правильно!!! например пропусти через phpformatter.com

Сайт опять упал!!!!! Не паникуй, а открой http://rghost.net/45000175

Тред не открывается!!! Можешь спросить совет или проверить решение, написав письмо ОПу (адрес на сайте)

Где архивы старых тредов? Известно, где, на mediafire: http://www.mediafire.com/?vz0z5134irhn2zl (треды 1-10, 160 Мб) http://www.mediafire.com/?3zxb19z9j2q5gf2 (11-19, 74 Мб) и на дропбоксе: https://www.dropbox.com/sh/4sb69jrx9qwrpcw/-nY5ia__VC (ок, он иногда не работает)

Не понимаешь, как дальше решать задачу? Запости свой код и напиши, где затык, что непонятно.

Решил сложную задачу? Покажи решение, может оно не такое уж и правильное.

Куда постить код Удобнее всего на ideone. Пости ссылку на ideone, код копипастить не надо. Еще, говорят, модно постить на instacode. HTML, CSS и JS постят на jsbin.com

Как привести код в аккуратный вид? Закачай его на phpformatter.com, робот его выровняет как надо.

Решил задачу, но ничего не понял? Попроси еще пару для закрепления знаний.

А HTML, CSS у вас изучают Ну, у нас есть несколько простых задач на верстку. На сайте в разделе «Учим сами».

В общем, хватит разговоров, давайте начинать уже!

Loading...
!xnn2uE3AU. Срд 06 Ноя 2013 23:25:53  #2 №333446 

... Но прежде чем начинать! Код надо писать не как попало, а аккуратно и красиво. Почему? Потому, что на неакуратно написанный код не хочется даже смотреть.

Если тебе лень выравнивать код руками, закачай его на http://beta.phpformatter.com/ и нажми «format». Робот исправит выравнивание и отступы в мгновение ока (да, прогресс не стоит на месте).

Самый распространенный стандарт оформления — это Zend Coding Guides (http://framework.zend.com/manual/1.12/en/coding-standard.html — на англ. яз.), вот его суть:

- переменные и функции пишутся с маленькой буквы, _ не используется, используется 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 ставятся так:


if (...) {
// ...
} else {
// ...
}

for (...) {
// .....
}


- у определений функций и классов так:


function makeMeFeelGood(...)
{
// ...
}


В общем, пиши как на картинке, и проблем не будет.
!xnn2uE3AU. Срд 06 Ноя 2013 23:38:53  #3 №333452 

Как установить PHP под Windows? Картинка слева.

Как установить Апач самому? Паста → https://gist.github.com/anonymous/946f4f1830be3955fe17
Как начать пользоваться командной строкой? Паста → https://gist.github.com/anonymous/2dfa134fe20d9cf91bbe

!xnn2uE3AU. Срд 06 Ноя 2013 23:41:52  #4 №333454 

Как установить PHP, продолжение.

Аноним Чтв 07 Ноя 2013 00:01:05  #5 №333463 

>>333454
Ох уж эта убогая cmd.exe.

Аноним Чтв 07 Ноя 2013 03:27:35  #6 №333488 

Проясните за валидацию форм. Учусь по видеокурсам на ютубе, там автор абсолютно любой запрос, любую форму проверяет очень громоздкими конструкциями как на пикрелейтед. Причем неважно что некоторые значения устанавливаются автоматически, например в скрытых полях и никаким путем вписать туда пустое значение нельзя. Это правильно или чел просто копипастит шаблон, а я перенимаю хуевые привычки?

Аноним Чтв 07 Ноя 2013 03:35:54  #7 №333490 

>>333488
>в скрытых полях и никаким путем вписать туда пустое значение нельзя.
Тебе так кажется.

!xnn2uE3AU. Чтв 07 Ноя 2013 10:03:56  #8 №333513 

>>333488

> Причем неважно что некоторые значения устанавливаются автоматически, например в скрытых полях и никаким путем вписать туда пустое значение нельзя

Проверять все равно надо. Ведь злоумышленник может отправить POST-запрос не браузером, а скриптом, или же подменить значения полей в браузере и подставить вообще любые значения.

> Это правильно
Писать нечитаемую лапшу, конечно, неправильно. Лучше сделать проверку отдельной функуией:


$age = isset($_POST['age']) ? intval($_POST['age']) : 0;
$name = isset($_POST['name']) ? $_POST['name'] : '';

$data = array(
'age' => $age,
'name' => $name
);

$result = validateForm($data);

function validateForm(array $data)
{
if ($data['age'] < 18) {
return "Вам должно быть больше 18 лет";
}

if ($data['age'] > 70) {
return "Вам должно быть не так много лет";
}

return true; // все ок
}


Если полей много, то вместо копипасты можно использовать например цикл. Ну а вообще, в фремйворках есть специальные способы для описания форм, чтобы не надо было такие проверки писать руками.
!xnn2uE3AU. Чтв 07 Ноя 2013 10:13:35  #9 №333515 

>>333513

Ну как переделать мой код, чтобы он возвращал все ошибки, а не останавливался на первой, я думаю, ты догадаешься сам.

Если полей оч много (например 20), можно сделать описание формы массивом (до ООП ты вряд ли дошел, так что пока по-простому) и сделать универсальную функцию-проверяльщик, которая проверяет поля на основе правил из массива:


$fields = array(
'age' => array(
'type' => 'integer', // делает intval(), чтобы прошли только числа
'nonempty' => true, // обязательно должен быть заполнен
'between' => '18-70', // должен быть от 18 до 70
),

'name' => array(
'type' => 'string', // имя — строка от 3 до 30 символов, обязательно
'nonempty' => true,
'maxlength' => 30,
'minlength' => 3
),

....

);



Или можно записать правила еще короче, но тогда надо будет написать код, который их сможет понять и разобрать:


$rules = array(
'age' => 'integer, between 18-70, nonempty',
'name'=> 'string, minlength 3, maxlength 30, nonempty',
.....
);


Такой подход полезен при работе с большими формами, а то замучаешься копипастить if и легко допустить ошибку.

Как написать функцию, которая будет на основании этого набора правил получать и проверять поля формы, я думаю, ты можешь догадаться и сам.
Аноним Чтв 07 Ноя 2013 10:24:57  #10 №333517 

>>333515
в ООП принципиально новый подход будет к проверке разве?

!xnn2uE3AU. Чтв 07 Ноя 2013 11:17:01  #11 №333522 

>>333517

Ну в Zend_Framework например форма сделана объектом, валидаторы для полей тоже отдельными объектами. Не то что принципиально новый подход, но немного по-другому. В фреймворках обычно не надо писать код проверки руками, а ты просто описываешь правила для полей (а код проверки уже встроен в фреймворк). И не только проверки, но и например, код для вывода формы тоже уже есть, он создает HTML-код формы по описанным тобой полям.

Аноним Чтв 07 Ноя 2013 12:04:50  #12 №333526 

>>333517
Нет, в ООП и в фреймворках всё будет значительно проще и быстрее. Поскольку бОльшая часть валидирующего кода там уже написана и тебе остаётся только задать критерии валидации.

Аноним Чтв 07 Ноя 2013 12:19:41  #13 №333528 

ОП, помоги пожалуйста с задачкой. Я даже алгоритма не смог придумать который сможет реализовать все это, а сделать нужно. Суть такова: есть текстовый файлик, куда написаны теги html. Скрипт должен прочесть этот файлик ивывести OK если порядок тегов правильный и нет ошибок в них, если же где-то есть ошибка, то вывести номер строки в которой она допущена. Не нужно проверять названия тегов и прочее, нужно лишь проверить является ли это тегом (открывающий и закрывающий уголок, возможно какие-то атрибуты), и если является проверить, имеется ли закрывающий тег. Открывающий тег может быть на одной строке, а закрывающий на другой. Условие таково, что ошибка будет только в том случае, если тег разделен построчно или после <body> идет сразу </html>, без закрытия <body>. Пикрелейтед задание в целом. Как его сделать вообще не понимаю. Подскажи пожалуйста.

Аноним Чтв 07 Ноя 2013 12:23:33  #14 №333532 

>>333513>>333515
Меня интересует скорее логика таких проверок(на isset и empty), для тех форм которые заведомо "не опасные", что ли.
Например, есть форма редактирования статьи в админке, которая появляется при клике на кнопку edit. В этой форме можно поправить текст и заголовок, а остальные данные - id, автор, время написания - передаются в скрытых полях. Текст и заголовок не могут быть пустыми, ок, но зачем кому-то с разрешенным доступом в админку пытаться вписать в базу пустые значения id, автора и времени? Угробить базу из админки можно и проще же. Другой пример - есть форма фильтрации товаров, например, машин. На ней три селекта - новая/подержанная, иномарка/отечественная и красная/синяя. Пустые значения там никак не выберешь, в базу ничего не пишется, по идее достаточно mysql_real_escape_string от инъекции и все. Тем не менее лектор видеокурсов проверяет абсолютно все на свете на isset и empty.
Насчет нечитаемой лапши он оговаривается что это для экономии времени, в отдельном уроке показывает как правильно делать, примерно как у тебя.

Аноним Чтв 07 Ноя 2013 12:51:05  #15 №333536 

>>333148

>Вообще, у тебя хорошо получается решать задачки. К тому же ты проверяешь свой код перед тем, как его показывать. Это плюс.

Спасибо, доброе слово и макаке приятно :3
Хотя особо радоваться нечему - я уже достаточно долго говнокодингом занимаюсь, правда, пугающе нерегулярно. Будь на моём месте кто-нибудь более целеустремленный, давно бы уже к успеху пришел.

Я даже поработать с месяцок успел, где как раз и выдрессировали хотя бы в первом приближении тестирование проводить.

Сейчас опять хочу где-то через месяц устраиваться, но в этот прийти на работу более-менее подготовленным и избежать того панического состояния, когда вообще не понимаешь что и как делать, а сроки колом стоят.



Код поправил, замечания принял к сведению.
Хитрый трюк с транспозицией (так вроде называется?) матрицы через array_map() очень крут.

Кстати. Встретил очень занимательно написанную серию статей про функциональные возможности PHP, может кому интересно будет: http://www.recessframework.org/page/functional-php-anonymous-functions-lambdas-closures
Еще спросить хотел, есть ли какие-нибудь реальные применения ф-ции array_reduce для рядового уеб-кодерка?

!xnn2uE3AU. Чтв 07 Ноя 2013 12:51:54  #16 №333538 

>>333532

> Меня интересует скорее логика таких проверок(на isset и empty), для тех форм которые заведомо "не опасные", что ли.
Если это админка, которой пользуешься только ты, это другое дело, ты можешь вообще ничего не проверять. Но ведь кроме злонамеренных изменений, есть еще баги, например из-за бага в форму в невидимое поле подставляется кривое или пустое значение. Если не делать проверок, то ты сам того не заметив, поломаешь данные в базе.

> Тем не менее лектор видеокурсов проверяет абсолютно все на свете на isset и empty.
Это чтобы варнинги не сыпались если параметр не передан.

Аноним Чтв 07 Ноя 2013 12:52:45  #17 №333539 

>>333528

!xnn2uE3AU. Чтв 07 Ноя 2013 12:53:40  #18 №333540 

>>333528

Используй стек (гугли, гугли). Когда ты встречаешь открывающий тег, кладешь в стек наверх его имя. Когда встречаешь закрывающий, снимаешь со стека верхний элемент и сравниваешь, совпадают они или нет.

!xnn2uE3AU. Чтв 07 Ноя 2013 12:58:02  #19 №333544 

>>333539

Ты вопрос ОПа прочел? Где там слово регулярки? Алсо, автор ответа не прав, я не раз парсил (X)HTML регулярками и все работало, и проблем не было. Алсо, автор ответа похож на рубиребенка. Как я это угадал? По последней строчке:

> Have you tried XML parser instead

Аноним Чтв 07 Ноя 2013 12:59:34  #20 №333547 

>>333538
>Это чтобы варнинги не сыпались если параметр не передан.
А вот эта конструкция как тебе? Дурной тон или ок?

Всякое упоминание подавления ошибок которое я встречал было в контексте того, что это зло и бэд прэктис (ну кроме разве что парсинга html, да и то с оговорками), но вот в этом случае вроде как достаточно красиво получается.

$name = @$_POST['name'] or $name = 'имярек';

Аноним Чтв 07 Ноя 2013 13:07:16  #21 №333550 

>>333544
Хэй-хэй, это слегка рилейтед шуточка же. Смешная как по мне.

Как я понимаю, регэксами html парсить имеет смысл когда точно знаешь, что твой html валидный и знаешь, какое подмножество языка тебе встретится.

Алсо, в чем проблема использовать XML парсер в PHP? Тот же DOMDocument.

!xnn2uE3AU. Чтв 07 Ноя 2013 13:19:52  #22 №333557 

>>333536

> есть ли какие-нибудь реальные применения ф-ции array_reduce

По идее функции вроде filter/map/reduce (которая еще называется в других языках fold) придуманы для сокращения количества кода, чтобы не надо было писать циклы. Но в PHP они довольно-таки криво сделаны, и сам синтаксис PHP к краткости не располагает, так что я таких применений не могу припомнить. Я обычно использую только:

$a = array_filter($b); // убрать пустые элементы из $b
$x = array_map('trim', $y); // очевидно зачем

Вывод массива в строку вида «a=12, b=13, c=15»:

$data = array('a' => 12, 'b' => 13, ....)
echo implode(', ', array_map(function($value, $key) { return "$key=$value"; }, $data));

Все это можно сделать и циклом (и работать будет быстрее), но цикл займет больше места, его дольше писать и дольше читать.

В других языках эти функции имеют гораздо больше применений (я надеюсь, проходящие мимо питонщики, хаскеллисты и рубисты подкажут пару примеров). Вот, например, генерация квадратов чисел от 1 до 10 в Руби:

(1..10).map { |n| n * n }

Аналог на PHP выглядит так:

array_map(function ($n) { return $n * $n; }, range(1, 10));

Чуть больше лишнего текста выходит. Но это все равно короче, чем писать цикл.

В хаскелле все эти штуки сделаны еще круче. Вот, например, подсчет суммы списка с помощью fold (аналог array_reduce): fold (+) [1,2,3,4,5] . Здесь (+) — это функция, которая равносильна такой: function ($a, $b) { return $a + $b; }, а все вместо равносильно такой строчке кода: array_reduce(array(1, 2, 3, 4, 5), function ($a, $b) { return $a + $b; }, 0);

Еще замыкания удобно применять с preg_replace_callback, это очень мощная функция.

В общем, иногда эти штуки позволяют сократить объем кода и улучшить читабельность. Думаю, стоит уметь ими пользоваться, тем более что они есть и в яваскрипте (через библиотеки вроде underscore/lodash) и в других языках.

!xnn2uE3AU. Чтв 07 Ноя 2013 13:25:07  #23 №333559 

>>333550

> Алсо, в чем проблема использовать XML парсер

1) HTML != валидный XML, потому просто XML парсер не катит. Нужен именно HTML парсер.
2) В HTML закрывающие теги могут быть пропущены иногда, валидный пример кода: <ul><li>1<li>2<li>3</ul>
3) При этом, никто не обещал что HTML будет валидным
4) Но при этом, DOMDocument::loadHtml обычно работает корректно

Также, DOM дольше работает, когда тебе надо обрабатывать большие (>= 1 Мб) или много документов потоком, и при этом брать из них только пару значений, проще и быстрее использовать регулярку. Хотя, DOM, если прикрутить к нему поиск по CSS3-селекторм или хотя бы XPAth, тоже неплохая вещь. Огромные XML лучше обрабатывать не DOM (который съест всю память), а потоковым XMLReader-ом.

В общем, надо смотреть по ситуации.

!xnn2uE3AU. Чтв 07 Ноя 2013 13:26:46  #24 №333560 

>>333547

Дурной. @ = быдлокод

Если тебе лень писать каждый раз isset, в чем проблема поместить isset в функцию и использовать ее? Например: $name = ge('name');



Аноним Чтв 07 Ноя 2013 13:46:34  #25 №333565 

>>333560
>в чем проблема поместить isset в функцию и использовать ее?

Гм, логично.

>@ = быдлокод
Можешь развернуть? Почему конкретно в этом примере это плохо, кроме того, что @ - плохо и не модно само по себе? Я просто не понимаю, какие тут подводные камни и встречал эту конструкцию на stack overflow, там вроде никто не плевался.

!xnn2uE3AU. Чтв 07 Ноя 2013 13:52:35  #26 №333567 

>>333536

Вот еще интересная вещь: итераторы в PHP. Вот пример, какие штуки можно вытворять с рекурсивным массивом: http://ideone.com/hk9bfN

Еще советую посмотреть RecursiveDirectoryIterator, им можно рекурсивно обходить файлы на диске в несколько строк.

!xnn2uE3AU. Чтв 07 Ноя 2013 13:57:42  #27 №333569 

>>333565

Оно подавляет любые ошибки, в том числе и те, которые ты не хотел бы подавлять. Особенно опасно, когда @ стоит перед вызовом функции, которая вызывает еще 20 функций и во всех них тоже появляются ошибки. Ошибки должны фиксироваться, и потому проще в принципе говорить что @ плохая и запрещать ее везде, чем делить на случаи. Плюс, разрешив @ в проекте, ты в итоге придешь к тому, что ее будут лепить где попало. Потому проще сделать функцию ge(), чем переходить к друным практикам написания кода.

Пример: $x = @$array['x']; предполагается что @ нужна для обхода случаев когда в массиве нет элемента. Но (внезапно) она скроет и ошибку, когда $array не существует или не является массивом. Используя @ мы делаем код хуже.У нее столько подводных камней, что проще от нее отказаться.

!xnn2uE3AU. Чтв 07 Ноя 2013 14:10:07  #28 №333572 

>>333532

Только сейчас заметил:
> достаточно mysql_real_escape_string от инъекции и все.

Расширение mysql и функции mysql_* давно устарели, сейчас модно использовать либо ООП-расширение PDO, либо (если ты никак не можешь отвыкнуть от mysql_query) mysqli, но лучше бы PDO.

Так что если не хочешь выглядеть например на собеседовании как пришелец из прошлого, изучи потом PDO. Ну и ознакомься с http://www.phptherightway.com/ (русский? http://getjump.github.io/ru-php-the-right-way/ )

Аноним Чтв 07 Ноя 2013 14:17:36  #29 №333574 

>>333572
>PDO

!xnn2uE3AU. Чтв 07 Ноя 2013 14:24:44  #30 №333577 

Анон как-то спрашивал, как прибавлять даты в PHP. Нашел новый способ, с использованием класса DateTime: http://getjump.github.io/ru-php-the-right-way/#Дата_и_Время

Аноним Чтв 07 Ноя 2013 16:26:11  #31 №333615 

>>332256

Ох, что то тяжко идёт освоение Yii. Читаю и выполняю "Создание блога с использованием Yii". http://yiiframework.ru/doc/blog/ru/start.overview
Но плохо понимаю, то что я делаю. Такое ощущение, что учу как-то неправильно.
Сколько времени уходит на то чтоб научиться делать в yii что-нибудь простое, но самостоятельно?

Аноним Чтв 07 Ноя 2013 16:33:11  #32 №333618 

>>333615
Гыйи нужен для того, чтобы не увели заказ на сторону.
Переусложнённость, как правило никому не нужная - от этого.

Web, что поделать.

Аноним Чтв 07 Ноя 2013 19:21:48  #33 №333621 

Аноны. Не могу додуматься. Маны перечитал пару раз и все что понял это вот:
" /^8[-|(]([0-9]{3})[)|-|(][0-9]{3}[)|-|(][0-9]{4}/ " рег.выражение, которое проверяет правильность введеного номера. [)|-|(] - значит что в этом месте может стоять как ), так и -, такт и ( или же все три сразу, верно?
Задание с archive-ipq-co.narod.ru.

Аноним Птн 08 Ноя 2013 15:58:29  #34 №333631 

Есть необходимость хранить в базе HTML-код статьи, то есть текст вместе с тегами, например
<h1>Заголовок статьи</h1>
<p>Текст абзаца<a href='#'>Ссылка</a></p>
Проблема заключается вот в чем - когда делаю сокращенный вывод, скажем, первые 100 символов и ссылку "... read more" может получиться так, что substr($text,0,100) разорвет какой-то тег, например <a href='' class=''> где-нибудь посреди атрибутов и тогда вообще весь остальной текст страницы окажется текстом этой ссылки.
Должна же быть изящная функция для этого без лишней ебатни?

Аноним Птн 08 Ноя 2013 16:30:55  #35 №333640 

>>333615
Узнаю себя в твоём посте. Когда читал - думал ебанусь со всего этого. Ну никак не мог вкурить что там и как. Проблема в том, что документация написана в таком ключе, что типо "вот то то мы делаем так и так (но можно и так, и вот так тоже можно)" но оно не даёт СИСТЕМНОГО ПОНИМАНИЯ. Моя тебе рекомендация - запили какой нибудь проектик на нём. Попутно пользуй гугл и класс референс. Я например сейчас просто кончаю радугой с ЙИИ и думаю все свои простенькие быдло-проэктики на него перетащить. Причина проста - разработка тех самых проектов с нуля на фреймворке займёт на много меньше времени, чем их поддержание в текущем их состоянии.
> Сколько времени уходит на то чтоб научиться делать в yii что-нибудь простое, но самостоятельно?
Прошло примерно 20 рабочих часов, пока на меня снизошло тотальное понимание. Сайчас чувствую себя богом веб-разработки.

Алсо, Аноны, стоит ли упарывать симфони или зенд? И какие профиты можно с них получить по сравнении с ЙИИ?

Аноним Птн 08 Ноя 2013 17:27:57  #36 №333649 

>>333631
Вопрос не актуальный, в моем случае приемлемо substr(strip_tags($text),0,100) но вообще, погуглив удивлен тем что задача легкой обрезки html-кода далеко не тривиальная.

!xnn2uE3AU. Птн 08 Ноя 2013 20:09:38  #37 №333697 

Антоны, тред что-то иногда висит и выдает vocaroo, так что я даже написать ничего не могу. Пишите мне на почту (адрес внизу сайта) если у вас есть вопросы или хотите проверить решение.

>>333618

Ты пишешь бред.

>>333615

Не знаю, от нескольких дней до недельки-двух. Ты попробуй хотя бы для начала сделать главную страницу с формой загрузки файла, хотя бы без оформления, и выложи куда-нибудь,а я подскажу куда дальше двигаться.

!xnn2uE3AU. Птн 08 Ноя 2013 20:14:59  #38 №333700 

>>333621

Нет, не так. | внутри квадратных скобок значит не «или», а просто «вертикальная палка». Потому

[)|-|(] значит что в этом месте может быть один из символов ) | - или ( но не все 3 сразу
[)|-|(]+ — значит что тут может быть от 1 до бесконечности любых из этих символов в любом порядке
[)|-|(]{3} — значит что тут должно быть любые 3 символа из указанных в любом порядке

Алсо, внутри квадратных скобок большинство символов не имеет специального значения. | ? * ( ) { } — все эти символы просто обозначают сами себя. Но вот минус внутри квадратных скобок значит «от и до», например 0-9 — от 0 до 9, a-z от a до z. И если ты хочешь написать просто минус, то ставишь его либо в конец [0-9./+-] либо добавляешь бекслеши [0-9\\-./+]

!xnn2uE3AU. Птн 08 Ноя 2013 20:22:15  #39 №333701 

>>333640

> Алсо, Аноны, стоит ли упарывать симфони или зенд?
Если ты их поймешь, то почуствуешь себя богом архитектуры в сравнении с теми, кто использует примитивные фреймворки вроде Yii. Учти, что там есть ZF1 и ZF2 и Symfony 1 / 2 и они сильно различаются. 2-е версии конечно круче.

> но оно не даёт СИСТЕМНОГО ПОНИМАНИЯ
Да, есть такое. Люди, которые привыкли писать кривые скриптики, где все в кучу, не сразу понимают преимущества правильной архитектуры и разделения кода на MVC, виджеты, валидаторы и что там еще есть.

>>333631

> Должна же быть изящная функция для этого
О, можно будет сделать из этого задачку и давать анонам.

Аноним Птн 08 Ноя 2013 20:55:04  #40 №333705 

Привет братве, привет доброкунчик. Такой вопрос: мне нужно чтобы некоторый скрипт постоянно висел в памяти, и раз в N минут делал кое-какие проверки. Я могу это просто набылокодить в своем коде, но дело в том, что задача для приложения, в котором участвую неск-ко человек. Разработка на Yii. Поэтому все должно быть максимально прилично. Там еще куча всяких условий, но мне как это принципиально делается, в концепции MVC и Yii. Может у кого есть опыт?

!xnn2uE3AU. Птн 08 Ноя 2013 21:01:00  #41 №333711 

>>333705

Если раз в N минут, используй крон, который будет вызывать твой cli-скрипт (cli = для командной строки) раз в N минут. Это традиционный способ.

Для создания cli-скриптов в Yii есть готовые средства: http://www.yiiframework.com/doc/guide/1.1/en/topics.console

Чем плох вариант «постоянно висеть в памяти»? Как минимум тем, что тебе надо писать/искать и настраивать супервизор, который будет его перезапускать в случае падения и оформить все это как службу, чтобы оно запускалось при перезагрузке сервера. Думаешь, проще перезапустить руками? ну попробуй, раз на двадцатый ты поменяешь свое мнение.

Аноним Птн 08 Ноя 2013 21:02:03  #42 №333712 

>>333697
>научиться делать в yii что-то простое → от нескольких дней до недельки-двух.
>Ты попробуй хотя бы для начала сделать главную страницу с формой загрузки файла

Я так понял, для начала сделать это без Yii? Потому что на данном этапе я пока пытаюсь понять что к чему там.

Аноним Птн 08 Ноя 2013 21:14:44  #43 №333716 

>>333711
Мне нужно чтобы этот скрипт запускался только если определенный тип пользователей зашел в систему. Пользователи разделены по ролям. Если заходит нужный пользователь, то этот скрипт запускается, и запускает крон. Как-то так. Ладно, спасибо вобщем за ссылку. Кстати, я в прошлом треде спрашивал про грид и отдельную форму поиска для него - с большим трудом я это сделал!

!xnn2uE3AU. Птн 08 Ноя 2013 21:15:58  #44 №333720 

>>333712

> Потому что на данном этапе я пока пытаюсь понять что к чему там.
Если ты будешь много читать теорию и мало уделять практике, трудно будет что-то понять.

Для начала, если ты не читал, почитай мануалы. Слишком не увлекайся, просто ознакомься. Например, такие:

http://www.yiiframework.com/doc/guide/1.1/ru/basics.mvc
http://borisnote.wordpress.com/2011/07/29/yii-create/

Там есть урок «создание первого приложения». В нем создается пример приложения, ты можешь его взять и просто поменять главную страницу для начала.

В том уроке правда нужно пользоваться командной строкой. У меня есть паста на эту тему: http://gist.github.com/anonymous/2dfa134fe20d9cf91bbe

В общем, попробуй освоить просто создание приложения как там описано. Если что-то непонятно или не работает — пиши, будем разбираться. Если проблемы с командной строкой — сразу прикладывай скриншоты или копипасть текст ошибки.

Аноним Птн 08 Ноя 2013 21:16:38  #45 №333722 

>>333716
Кстати
>>только если определенный тип пользователей зашел в систему
это как раз не сложно. Я что-то не додумал

!xnn2uE3AU. Птн 08 Ноя 2013 21:26:58  #46 №333728 

>>333716

> то этот скрипт запускается, и запускает крон
Не, ты не можешь запустить крон.

> Мне нужно чтобы этот скрипт запускался только если определенный тип пользователей зашел в систему.
Ну смотри. Если скрипт короткий и быстро работает, можно вставить его в то место, где происходит авторизация. Это просто.

А вот если скрипт длинный, то его нельзя просто так вставить, так как страница будет долго загружаться, зля пользователя, или что хуже, отвалится по таймауту и твой скрипт сдохнет на полпути, попутно поломав базу (чтобы не поломал, можно завернуть все в транзакцию, которая отменится при падении скрипта). Некоторые решают это костылем: скрипт запускают в фоне аякс-запросом со страницы. Это конечно сомнительное, ненадежное и велосипедное решение. Никто не гарантирует, что пользователь не перейдет на другую странцу или закроет вкладку.

Можно запускать скрипт отдельным фоновым процессом из PHP, через команду вроде exec('nohup php myscript.php & ') — минус такого подхода, что ты никак не контролируешь что происходит дальше и не получаешь обратной связи. Ну зато это несложно. Может тебе подойдет такой вариант.

Еще это реализуют через очередь задач: когда нам надо что-то сделать, мы добавляем задание в очередь. Специальный демон или крон-скрипт постоянно проверяет очередь, берет из нее задачи и запускает воркеров для выполнения, следит за ними, пишет логи. Это можно даже делать в несколько потоков, такие системы уже есть готовые, например http://gearman.org/

В общем, не знаю, очередь задач ради такой простой вещи наверно слишком круто, но знай, что такие штуки есть. Например, очередь задач можно использовать для конвертации видео, загружаемого пользователем на местный клон ютуба.

Аноним Птн 08 Ноя 2013 22:59:33  #47 №333757 

>>333567
>итераторы в PHP
А yield и генераторы ещё пока в php не завезли?

!xnn2uE3AU. Птн 08 Ноя 2013 23:18:49  #48 №333763 

>>333757

Завезли, в 5.5: http://php.net/manual/ru/language.generators.overview.php

Аноним Птн 08 Ноя 2013 23:20:30  #49 №333764 

Как мне в RegularExpression искать слова от 4 букв на любых языках без цифр?

!!8VDVWZyN Птн 08 Ноя 2013 23:30:36  #50 №333769 

http://dumpz.org/722942/

Оп, не слишком ли это быдлокодно?
У меня весь код в таком стиле.

Всё ещё тот кун, который не доделал обменник на Slim Framework.

Аноним Птн 08 Ноя 2013 23:31:56  #51 №333771 

>>333764
\w{4}\w*

Аноним Птн 08 Ноя 2013 23:41:20  #52 №333773 

>>333728
расскажи как обернуть код в транзакции?

!xnn2uE3AU. Птн 08 Ноя 2013 23:50:40  #53 №333775 

>>333769

Ну круто конечно, но по ссылке только поле для ввода пароля. Если ты не хочешь никому показывать код, то можешь скинуть мне на почту, но было бы конечно лучше, если бы и другие аноны могли его посмотреть, и может быть что-то для себя уяснить.

>>333771

А с русскими буквами в utf-8 будет работать? В мануале написано, что \w зависит от локали, и как я понимаю, вся это чудо хрень принципиально не может в utf-8. Зато есть вот такая штука: http://www.php.net/manual/ru/regexp.reference.unicode.php

Чтобы написать «буква на любом языке (как и просил анон)» можно использовать \p{L}

>>>>333773

Транзакция, имеется в виду транзакция в базе данных. Это штука, которая позволяет сделать пачку запросов так, что они либо все 100% выполнятся и сохранятся, либо все отменятся.

Ну типичный пример — банк: когда Вася переводт деньги Пете, мы должны убавить баланс Васи (запрос #1) и прибавить баланс Пети (запрос #2). Ну и скорее всего сделать еще несколько запросов для сохранения логов, статистики и подобных вещей. Если вдруг посередине операции произойдет что-то вроде перезагрузки сервера, ошибки в PHP скрипте или потери соединения, то мы окажемся в неприятной ситуации: деньги у Васи сняли, а Пете не зачислили. Чтобы этого не было, всю последовательность операций заворачивают в транзакцию. Она либо полностью выполнится, либо не выполнится ни одного запроса.

Плюс, транзакции могут еще изолировать изменения. Например, скрипт добавляет запись в таблицу, и он эту запись видит, а другие скрипты видят исходную таблицу, они увидят добавленные данные только когда транзакция будет завершена.

В MySQL есть такие команды: BEGIN (TRANSACTION) - начинает транзакцию, COMMIT — завершает транзакцию и атомарно вносит изменения, ROLLBACK — откатывает транзакцию.

В общем, читай http://ru.wikipedia.org/wiki/%D0%A2%D1%80%D0%B0%D0%BD%D0%B7%D0%B0%D0%BA%D1%86%D0%B8%D1%8F_(%D0%B8%D0%BD%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B0)

http://www.mysql.ru/docs/man/ANSI_diff_Transactions.html

Аноним Птн 08 Ноя 2013 23:51:58  #54 №333776 

>>333775
2ch же.

!xnn2uE3AU. Птн 08 Ноя 2013 23:56:42  #55 №333778 

>>333773

Теория про уровни изоляции транзакций: http://habrahabr.ru/post/135217/

Еще, кстати, транзакции в некоторых случаях ускоряют вставку записей в MySQL. Например, вставить 10 записей одной транзакцией обычно быстрее, чем 10 отдельными запросами (по сути в этом случае каждый запрос идет как одна транзакция). Почему? Потому, что при записи транзакции MySQL сбрасывает данные на диск и ждет ответа от ОС, что все сбросилось, чтобы убедиться что данные надежно сохранены (а это не очень быстро), и ждать один раз быстрее, чем сбросить данные 10 раз подряд и 10 раз ждать.

Аноним Птн 08 Ноя 2013 23:59:11  #56 №333779 

>>333775
Пароль: 2ch

!xnn2uE3AU. Суб 09 Ноя 2013 00:08:55  #57 №333782 

>>333769

Цель задачи была — научиться использовать ООП и фреймворки, ну и наверно научиться MVC. Ну, фреймворк я тут конечно вижу, но вот с MVC, ООП как бы не очень.

> static $db = null;
В Slim можно использовать Resource Locator: http://docs.slimframework.com/#DI-Overview

Пишешь $app->container->singleton('db', function () { ...устанавливаем соединение ... }) и при обращении к $app->db он будет возвращать объект pdo.

> function render
В Slim и для этого есть решение: http://docs.slimframework.com/#View-Overview — зачем писать свой велосипед?

Если мало возможностей Slim, ты можешь определить свой View, унаследовав его от \Slim\View

> $search = isset($_GET['search']) ? htmlspecialchars($_GET['search']) : null;
Зачем htmlspeciachars?

> $search_results->execute
Нет. Код работы с Бд должен быть в отдельных классах. Сделай например класс FilesTable и в нем делай метод searchFiles($like).

Ну и конечно результаты поиска лучше бы сделать не глупым массивом, а объектом-моделькой File. Тогда ты можешь например вызывать разные методы вроде if ($file->isPicture()) { ... } и твой код будет лучше.

Также, у меня есть подозрение, что ты свалил весь код в один файл, если так то тоже плохо.

В общем, есть что улучшать.

!xnn2uE3AU. Суб 09 Ноя 2013 00:14:52  #58 №333784 

>>333769

> $search_results_
Вот это особенно плохо. Мне пришлось вглядываться в экран, чтобы увидеть что это не у меня глюки, а действительно 2 разных переменных. Не делай так. А переименуй:

$search_results → $search_statement или $search_stmt
$search_results_ → $search_results или $files




!xnn2uE3AU. Суб 09 Ноя 2013 00:16:31  #59 №333785 

>>333769

> while($a = $search_results->fetch()){
Открой для себя fetchAll: http://www.php.net/manual/ru/pdostatement.fetchall.php

Аноним Суб 09 Ноя 2013 00:20:56  #60 №333788 

>>333775 >>333778
спасибо, знал что такое транзакции и для чего но не делал их на php Mysql никогда

Аноним Суб 09 Ноя 2013 00:27:21  #61 №333790 

>>333778
хммм а кто-нибудь знает подводные камни? почему не панацея в использование?

!xnn2uE3AU. Суб 09 Ноя 2013 00:43:03  #62 №333794 

>>333790

Я не такой большой специалист по БД, так что о подводных камнях не знаю. Транзакции как раз и придуманы, чтобы снять с разработчика головную боль по обеспечению целостности данных.

Аноним Суб 09 Ноя 2013 01:06:09  #63 №333800 

ОП-кун, вот очередная задачка, на поиск пути. Жду комментов.
Вместо того, чтобы городить велосипеды реализовал алгоритм Дейкстры. Единственный косяк, если не считать потенциально неэффективных кусков кода, - то, что не обработан случай, когда из А в Б в принципе нельзя добраться.

Итераторы оно круто, конечно, на заметку возьму, но пока плотно изучать не буду.

Давно уже пора к ООП переходить, а я что-то просрал уже несколько дней вообще впустую, да и с задачками как-то долго уже вожусь.

!xnn2uE3AU. Суб 09 Ноя 2013 01:24:20  #64 №333805 

>>333800

Задачку-то не приложил.

Аноним Суб 09 Ноя 2013 09:23:16  #65 №333862 

>>333805
http://viper-7.com/6vHrF4

Аноним Суб 09 Ноя 2013 11:32:49  #66 №333887 

а можете сказать как правильно вставлять данные из php в html страницу, шаблоны не самая оптимальная по производительности штука, использовать регулярные выражения для замены, тоже не оптимально

Аноним Суб 09 Ноя 2013 12:18:26  #67 №333893 

>>333887
<?php echo htmlspecialchars($yoba); ?>

Аноним Суб 09 Ноя 2013 14:04:05  #68 №333913 

>>333887
<?=$yoba;?>
>>333893
обрабатывать данные в бекенде нужно.

Аноним Суб 09 Ноя 2013 14:10:42  #69 №333916 

>>333913
согласен
а так нормально
что есть echo в самом html коде?

!xnn2uE3AU. Суб 09 Ноя 2013 18:16:58  #70 №333939 

>>333913

> обрабатывать данные в бекенде нужно.
Это как? По моему, либо я тебя не понял, либо ты ошибаешься. htmlspecialchars — это не обработка данных, а перевод просто текста в HTML.

Правильно писать именно <?= htmlspecialchars($yoba); ?> чтобы любые символы, в том числе < > и & в $yoba выводились корректно и в соответствие с правилами HTML.

Плюс, как ты «обработаешь в бекенде» обращение к методам модели, например: <?= htmlspecialchars($project->getTitle()) ?>

Кстати, умные шаблонизаторы, (например Google Closure Templates или XSLT) делают htmlspecialchars сами.

Аноним Суб 09 Ноя 2013 18:20:29  #71 №333940 

Есть index.php, в который путем include подключаются остальные странички. Есть javascript-функция которая, например, запрещает ввод любых символов кроме цифр в строку, т.е. обычная вспомогательная функция. Используется она, допустим, на двух-трех из двадцати подключаемых страницах. И таких функций очень много. Как правильнее - вставить их все один раз в index.php или копировать по тем страницам где они реально нужны? В первом случае засираем индексный файл кодом, который может и не понадобится, во втором дублируем одни и те же куски по нескольким страницам.

!xnn2uE3AU. Суб 09 Ноя 2013 18:27:57  #72 №333943 

>>333940

Копипастить — плохо.

Можно к каждой странице подключать 2 JS-файла: global.js — функции, которые нужны везде или почти везде, page-x.js — только на странице x. Эта твоя функция пойдет в global, а вызываться будет только там, где нужна.

Аноним Суб 09 Ноя 2013 18:36:49  #73 №333948 

Макаканы, помогите построить базу, с которой можно пилить сайты с нуля?
Для html и css - это boilerplate. Обнуление стилей классная штука, чтобы все элементы на странице выглядели во всех браузерах максимально похожи. Алсо там есть шаблонный .htaccess для Апача.
Далее: для JS нам пригодится html-shiv, чтобы IE не тупил с новыми HTML5-тэгами и jQuery.
Для mysql ничего не нужно.
А теперь самое главное: на чем строить php-скрипты? Около месяца разбирался с Zend 2. Это просто охренеть, какая монструозная и комплексная штука. Согласен, там есть модули на все случаи жизни, но сама повседневная разработка очень уж утомляет. Если я на чистом PHP за 15 минут склепаю форму и ее валидацию на стороне сервера, то для такой тривиальной задачи в Zend'e мне придется поебаться в 2 раза дольше. Там и злоебучая маршрутизация и сущности базы данных с гидратацией, это слишком для простого новостного сайта, скажем.
Но если писать на голом PHP, то я становлюсь неуверен в безопасноти. Постоянно опасаюсь SQL-инъекций. А в Zende все сделает за тебя класс взаимодействия с БД.

Как же быть, анон?

!xnn2uE3AU. Суб 09 Ноя 2013 18:40:33  #74 №333950 

>>333862

Вообще, хорошо сделано, все работает.

Алгоритм Дийкстры, конечно, далеко не самый оптимальный способ поиска пути, но для этой задачи вполне подходит, так как тут очень мало точек. Когда точек очень много (например, поиск маршрута с учетом всех улиц или поиск пути в играх), используют другие алгоритмы. Дийкстра — универсальный алгоритм, и он ищет путь, распространяясь во все стороны, а другие алгоритмы оптимизируют поиск тем, что учиытвают координаты точек и в первую очередь проверяют те точки, которые находятся в направлении к цели.

Но для этой задачи он подходит. Небольшие замечания:

> extract($pathArray);
Ой, лучше явно брать значения вроде

$prevNodes = $result['prevNodes'];
$totalTime = $result['totalTime'];

а то с extract абсолютно непонятно сколько там будет переменных и каких.

> & laquo ;
Так тоже можно, но можно вставить (скопировать или ввести с клавиатуры, если у тебя типографская раскладка) сами символы «». Чем лучше? Тем, что « выглядит лучше и понятнее чем & laquo ; Чем хуже? Если кто-то откроет твой исходный код не в utf-8 символ покорежится.

Реализация алгоритма, конечно, выглядит как-то усложненно.

Заполнить массив можно не только циклом но и с помощью array_fill_keys (получается короче):

$pathTimes = array_fill_keys(array_keys($paths), NULL); или
$pathTimes = array_fill_keys($points, NULL); если названия точек вынести в массив

> $i = 0;
> while($i < $numNodes) {
> $i++;
Это ты пытаешься заново изобрести цикл for.

!xnn2uE3AU. Суб 09 Ноя 2013 18:52:00  #75 №333955 

>>333948

> Обнуление стилей классная штука, чтобы все элементы на странице выглядели во всех браузерах максимально похожи.
Что еще расскажешь? А ты не забываешь после обнуления выставить назад все стили для всех элементов, которые ты сбросил или же как у 99% верстальщиков текст с тегами на твоей странице выглядит как сплошная серая полоса без отступов?

reset давно устарел, это даже на западе наконец-то поняли, и в том же bootstrap используют не reset, а normalize.css (ну а мне было очевидно с самого начала, что reset — это типичный быдлоскрипт для индусов, которым плевать на качество). Не советую его использовать, советую изучать CSS и знать особенности браузеров.

Бесит, когда на сайте например списки отображаются без отступов и точечек, или таблицы скособочены, или заголовки неправильно выровнены после применения reset.css

> Если я на чистом PHP за 15 минут склепаю форму и ее валидацию на стороне сервера
C подстановкой сообщений около нужных полей, сохранением значений, CSRF токеном и прочими плюшками? Да ну, сомневаюсь.

> помогите построить базу, с которой можно пилить сайты с нуля?
Фреймворки же, Yii например или ZF (но он сложнее) + расширения и плагины к ним + что-нибудь готовое для админки. Zend 2, конечно, не самая простая штука.

!xnn2uE3AU. Суб 09 Ноя 2013 18:53:25  #76 №333956 

>>333948

> Обнуление стилей классная штука, чтобы все элементы на странице выглядели во всех браузерах максимально похожи.
Что еще расскажешь? А ты не забываешь после обнуления выставить назад все стили для всех элементов, которые ты сбросил или же как у 99% верстальщиков текст с тегами на твоей странице выглядит как сплошная серая полоса без отступов?

reset давно устарел, это даже на западе наконец-то поняли, и в том же bootstrap используют не reset, а normalize.css (ну а мне было очевидно с самого начала, что reset — это типичный быдлоскрипт для индусов, которым плевать на качество). Не советую его использовать, советую изучать CSS и знать особенности браузеров.

Бесит, когда на сайте например списки отображаются без отступов и точечек, или таблицы скособочены, или заголовки неправильно выровнены после применения reset.css

> Если я на чистом PHP за 15 минут склепаю форму и ее валидацию на стороне сервера
C подстановкой сообщений около нужных полей, сохранением значений, CSRF токеном и прочими плюшками? Да ну, сомневаюсь.

> помогите построить базу, с которой можно пилить сайты с нуля?
Фреймворки же, Yii например или ZF (но он сложнее) + расширения и плагины к ним + что-нибудь готовое для админки. Zend 2, конечно, не самая простая штука.

Алсо, советую лучше заниматься чем-то одним, например, бекендом на PHP, а верстку свалить на кого-нибудь другого, зачем тебе сидеть пиксели выравнивать, лепить костыли для ИЕ и скрипты отлаживать, когда ты можешь заниматься более высокоуровневыми вещами?

Аноним Суб 09 Ноя 2013 18:58:29  #77 №333963 

>>333955
А чем годен Yii? Самое основное, что мне нужно, это класс для работы с БД, зародыш админки и зародыш системы залогинивания.

!xnn2uE3AU. Суб 09 Ноя 2013 19:05:42  #78 №333965 

>>333963

Там есть класс для работы с Бд, система залогинивания + куча расширений в сети разной степени годности.

Аноним Суб 09 Ноя 2013 19:11:42  #79 №333970 

>>333965
Пока читаю take a tour на офф. сайте спрошу такую вещь: планирую впервые в жизни пилить сайт, через который идут интернет платежи. Насколько сложно прикрутить к нему всякие Киви, Вебмани, Яндексы, PayPal'ы?

Аноним Суб 09 Ноя 2013 19:19:49  #80 №333976 

Скриптаны, хочу запилить свой сайт, чтобы приносил доход хотя бы 100$ в месяц. В какую тематику идти?
Алсо пилите ссылки на свои сайты, я хоть вдохновение буду черпать.

!xnn2uE3AU. Суб 09 Ноя 2013 19:29:13  #81 №333977 

>>333970

Есть простое решение — подключить какую-нибудь универсальную систему типа робокассы, оно простое в плане времени, но с точки зрения удобства пользования ниже плинтуса, так как для оплаты там надо пройти 100500 экранов, на которых половина юзеров потеряет всякое желание платить. Если тебя интересует сделать как можно удобнее, то придется тщательно продумать процесс оплаты и интерфейсы и самому подключать все системы (нужно юрлицо и договор). Вдохновиться можно, походив и посмотрев системы оплаты на купонных сайтах, вконтактике, вкиви и подобных сайтах.

С точки зрения программирования все системы похожи: ты делаешь форму, подставляешь в нее всякие идетификаторы и сумму платежа. Когда пользователь оплачивает заказ, система отправляет на твой сайт POST-запрос с данными, ты либо принимаешь его либо отказываешься и если все ок, получаешь второй запрос, с уведомлением об оплате, после чего пользователя назад перекидывает. Можешь почитать тут например: https://money.yandex.ru/doc.xml?id=526025 - это у яндекса.

!xnn2uE3AU. Суб 09 Ноя 2013 19:30:36  #82 №333978 

>>333976

> В какую тематику идти?
В /web. Здесь мы изучаем PHP.

Аноним Суб 09 Ноя 2013 19:50:17  #83 №333986 

>>333965
>система залогинивания
О, а проясните за авторизацию. Сейчас сделано так - в индексном файле проверка:
if ($_SESSION['logged_in']==true) {
//показываем саму страничку
} else {
//показываем форму логина
}
Форма, соответственно, при верно введенных данных записывает true в $_SESSION['logged_in'].
Все остальные файлы имеют проверку:
if ($_SESSION['logged_in']==true) {
//показываем саму страничку
} else {
//редирект на index.php
}
Понимаю что это полный примитив, но вроде норм работает.

Аноним Суб 09 Ноя 2013 19:51:06  #84 №333989 

>>333939
>Плюс, как ты «обработаешь в бекенде» обращение к методам модели
мы просто php учим или учим и придерживаемся принципов mvc?
Ок, может я неверно понял про htmlspecialchars, я к тому чтобы работать с фреймворками и отдавать переменные шаблонизаторам, да если и без них в контроллере готовить переменные а потом отдавать готовые во вьюху.

!xnn2uE3AU. Суб 09 Ноя 2013 20:03:01  #85 №333995 

>>333986

Лучше бы вынести это в отдельный класс и писать if ($auth->isLoggedIn()), тогда если где-то ты меняешь правила или систему авторизации, ты делаешь это в одном месте, а не переписываешь весь код.

Ну а вместо

> редирект на index.php
лучше редиректить на форму логина с надписью «вам нужно залогиниться или зарегистрироваться для просмотра этой страницы», сохраняя адрес исходной страницы, чтобы после логина/регистрации перебрасывало назад.

>>333989

Мы учим MVC, и ты наверно что-то не так понимаешь. В контроллер выносить htmlspecialchars неудобно так как:

- контроллер перестает быть тонким и оказывается завален мусорным однотипным кодом
- мы не можем передать во вью модельку, так как должны вместо этого в контроллере писать:

$title = htmlspecialchars($project->getTitle())
$author = htmlspecialchars($project->getAuthor())
....

и еще строчек 10 такой лапши вместо того чтобы передать во вью единственную переменную $project.

- использование хелперов во вью никак не противоречит MVC, наоборот способствует порядку в коде. К хелперам относится не только htmlspecialchars, но и функции форматирования чисел, валют, дат, перевода строк, обрезки длинных строк, склонения числительных, имен и городов — все это удобнее вызывать в шаблоне.
- и наконец, как я сказал, некоторые шаблонизаторы сами автоматически делают htmlspecialchars

Заметь, что противоречия MVC тут никакого нет. Мы лишь используем во вью хелперы для оформления данных, мы не выносим туда никакой логики, не пишем там запросы к базе данных, не проверяем правильность заполнения формы и подобные вещи.

Аноним Суб 09 Ноя 2013 22:00:55  #86 №334051 

А есть здесь люди, которые разбирали исходники php?

!!8VDVWZyN Суб 09 Ноя 2013 22:31:00  #87 №334064 

Сначала я забил на свой обменник на Slim Framework, потом захотел попробовать Yii. В итоге я перенёс обменник на Yii (причем очень быстро). Теперь быдлокода меньше в 100 раз.
Но есть одна проблема:
У меня есть layouts/main.php (это основной шаблон, где подключаются js скрипты, стили)
И есть там шапка. Раньше реализовано было так:
http://dumpz.org/723747/
И всё работало. Не могу придумать, как сделать сейчас.

Аноним Суб 09 Ноя 2013 22:36:09  #88 №334066 

Макаканы, сотоит ли избегать нотисов по поводу существования переменной, либо ключа массива? Эти дополнительные isset убивают меня.

Аноним Суб 09 Ноя 2013 23:00:00  #89 №334075 

>>333253
> https://github.com/Somepony/php-wakabamark
> Ну а статей бы русских по использованию этого всего? Есть такое?

Подключаешь markUp.php (require "markUp.php"), а перед вводом (или выводом) в БД оборачиваешь переменную с текстом в функцию MarkPost(), например, MarkPost($message) или MarkPost($_post['message']).

!xnn2uE3AU. Вск 10 Ноя 2013 01:19:47  #90 №334091 

>>334064

В Yii можно получить имя контроллера и action и в зависимости от них, выделять пункт меню. Например, как тут: http://shanideveloper.blogspot.ru/2012/01/yii-how-to-get-current-controller-name.html

Поместить этот код можно куда-нибудь в beforeAction() базового контроллера, от которого наследуются остальные (чтобы он выполянлся везде).


!xnn2uE3AU. Вск 10 Ноя 2013 01:21:56  #91 №334092 

>>334066

Если тебе приходится isset всюду ставить, то скорее всего ты просто неправильно организовал хранение данных в программе и валишь все в сложный запутанный массив, в котором часть элементво может отсутствовать. Это крайне дурной подход. Надо его распутать.

Если же речь о GET/POST, то просто сделай функцию вроде getQuery('name') которая внутри будет делать isset.

!xnn2uE3AU. Вск 10 Ноя 2013 01:23:54  #92 №334094 

>>334075

Лучше делать это в момент сохранения поста, и завести 2 колонки в таблице: post_source (исходынй пост) и post_html (обработанный). А то может быть дорого каждый раз при вызове делать все эти преобразования.

Аноним Вск 10 Ноя 2013 01:46:02  #93 №334100 

Анончики, выручайте (вы уже не раз мне помогали, я верю в вас). Есть софт-парсер, который шлет POSTом картинки скрипту (с помощью Curl), а тот сохраняет их на сервер. Нужно, чтобы скриптец также на лету также обрезал (crop) картинки. А он никак не хочет, зараза; GВ-library установлен, конечно:


// 1. GET IMAGES VIA POST
$imgpath = $_POST['img_url'];
$dirname = $_POST['img_folder'];
$imgid = $_POST['imgid'];
$ch = curl_init($imgpath);
$fn = ($imgid.substr($imgpath,strrpos($imgpath,'/')+1,strlen($imgpath)));
$fn = str_replace('?', '_', $fn);
$fn = str_replace('=', '_', $fn);
if (is_dir($dirname)==FALSE) mkdir($dirname);
$fp = fopen($dirname.'/'.$fn, 'wb');
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_exec($ch);
curl_close($ch);
// 2. CROP IMAGE
$in_filename = $imgpath;
list($width, $height) = getimagesize($in_filename);
$offset_x = 0;
$offset_y = 0;
$new_height = $height - 40;
$new_width = $width;
$out_filename = $in_filename . '_crop';
$image = imagecreatefromjpeg($in_filename);
$new_image = imagecreatetruecolor($new_width, $new_height);
imagecopy($new_image, $image, 0, 0, $offset_x, $offset_y, $width, $height);
header('Content-Type: image/jpeg');
imagejpeg($new_image, $out_filename);
imagedestroy($new_image);
echo($dirname.'/'.$fn);`



Причем, если просто запускать скрипт с кропом для единичного файла, то всё работает:


$in_filename = '1111.jpg';
list($width, $height) = getimagesize($in_filename);
$offset_x = 0;
$offset_y = 0;
$new_height = $height - 40;
$new_width = $width;
$image = imagecreatefromjpeg($in_filename);
$new_image = imagecreatetruecolor($new_width, $new_height);
imagecopy($new_image, $image, 0, 0, $offset_x, $offset_y, $width, $height);
header('Content-Type: image/jpeg');
imagejpeg($new_image, 'crop.jpg');
imagedestroy($new_image);

Аноним Пнд 11 Ноя 2013 16:47:05  #94 №334149 

ОП поясни про mvc, я правильно понимаю что контроллер только получает инфу с вьюхи, проверяет на существование необходимых данных а дальше все отправляется в модель, где проходит уже валидация, бизнес-логика и т.д.

Аноним Пнд 11 Ноя 2013 16:57:58  #95 №334152 

>>334149

Вообще, контроллер — это как директор, который сам почти ничего не делает, а только заставляет других делать. Если ему нужно что-то из базы достать или положить, он обращается к модели, надо что-то вывести, он использует вьюшку.

Это еще называется «тонкие контроллеры» — старайся писать как можно меньше кода в контроллере. Почему? Потому, что код в модели, если он правильно написан, можно использовать повторно, например вызвав этот код из другого места, а код в контроллере — нельзя.

В больших сложных приложениях часто еще бывает слой сервисов, который находится выше моделей и вызывает их методы. Ну например, регистрация пользователя подразумевает несколько действий — добавление пользователя в таблицу users, отправку письма, обновления всяких статистик — все это может делать сервис.

Аноним Пнд 11 Ноя 2013 17:07:59  #96 №334156 

>>334149

Так что по видимому ты все правильно понял.

Аноним Пнд 11 Ноя 2013 17:34:05  #97 №334162 

>>334149
Может даже не проверять. Просто получил данные, передал, получил результат валидации - отдал вюхе. Сам контролер данные не валидирует.

Аноним Пнд 11 Ноя 2013 17:44:46  #98 №334165 

>>334152
>>334162
Благодарю аноны, хорошо пояснили.

!xnn2uE3AU. Пнд 11 Ноя 2013 19:20:31  #99 №334181 

Антоны, смотрите какая офигенная идея: платные комментарии — http://tjournal.ru/paper/pay-per-comment

Я бы тоже так хотел. Если уж хейтеры и хаскеллисты хотят рассказать нам про фракталы неправильного дизайна, пусть хотя бы заплатят.

Аноним Пнд 11 Ноя 2013 20:31:55  #100 №334205 

>>333950
Ок, всё понял, приму к сведению. While там остался от прошлой реализации, как-то забыл на foreach переделать, замотался уже под конец.

Изначально сам пытался сделать через array_keys, но что-то там не получилось, уж и не помню.

У меня вопрос по задачке про молодую динамично развивающуюся компанию. Как лучше высчитывать статистику по департаменту? Я как-то с кондачка сделал так, что при каждом устройстве/увольнении сотрудника изменяются соответствующие поля в объекте департамента (кофе, общая зарплата и т.д.).

Плюс в том, что если вообразить риаллайф использование скрипта, то увольнять/брать на работу будут, кмк, намного реже, чем запрашивать данные о департаменте.

Минус же в том, что если, к примеру, изменять ставку или количество выпитого кофе прямо в классе сотрудников, то надо отдельно вручную делать пересчет - как минимум, запустить соотв. метод в департаменте. А если делать сеттер этих полей в классе сотрудников, то надо его как-то связывать с соответствующим департаментом. Что плохая идея, насколько я понимаю.

Альтернатива - высчитывать этих величины при вызове методов getCoffee и т.п., но стоит убедиться, что действительно так лучше будет, перед тем как переделывать.

Что посоветуешь, ОП?

Аноним Пнд 11 Ноя 2013 20:43:13  #101 №334207 

http://ideone.com/k8r7GE
массивы 2я задачка,что я делаю не так?

Аноним Пнд 11 Ноя 2013 20:46:29  #102 №334209 

>>334207
Перечитай про for, он работает совсем не так, как ты от него ожидаешь.

!xnn2uE3AU. Пнд 11 Ноя 2013 22:01:14  #103 №334227 

>>334205

> Как лучше высчитывать статистику по департаменту? Я как-то с кондачка сделал так, что при каждом устройстве/увольнении сотрудника изменяются соответствующие поля в объекте департамента (кофе, общая зарплата и т.д.).

Ты увлекаешься преждевременной оптимизацией. Считать можно по-простому, сделав каждого сотрудника объектом, и просуммировав кофе/зарплату сотрудников департамента обычным циклом.

> Плюс в том, что если вообразить риаллайф использование скрипта, то увольнять/брать на работу будут, кмк, намного реже, чем запрашивать данные о департаменте.

Это и есть преждевременная оптимизация. Может, будут, а может и не будут. Может в компании никогда не будет больше 20 сотрудников. Может, нужен не идеальный код, а как можно быстрее написанный. Может тут такая текучка кадров, что люди больше полдня отработать не успевают. Лучше сначала сделать по-простому, аккуратно, но оставить возможность для оптимизации в будущем. В чем профит простого подхода? В том, что он быстрее пишется и с ним труднее сделать ошибку.

Это задача в первую очередь на понимание ООП, правильно определить объекты в задаче, их свойства и методы. А потом уже оптимизировать.

Ну если у тебя все уже оптимизировано и правильно считает, а код соответствует ООП-подходу, оставь так. Не разоптимизировать же обратно.

!xnn2uE3AU. Пнд 11 Ноя 2013 22:12:57  #104 №334228 

>>334207

Тут надо решать по другому. заводишь переменную с названием $числоОдноклассниковВышеАнона (по-английски естественно), присваиваешь ей 0. Затем циклом foreach проходишь по массиву, и если встречаешь одноклассника выше анона, увеличиваешь переменную на единицу.

Насчет for, ты все напутал. Смотри, в for пишется 3 выражения:

1) выражение, которое выполняется перед началом цикла. Обычно там присваивается начальное значение переменной (например, $x = 0).

У тебя там $number; Это выражение ничего не делает, оно берет значение переменной $number и ничего с ним не делает. Это то же самое, что написать

2+2;

PHP трудолюбиво сложит числа, но результат никуда не сохранит.

2) выражение, которое проверяется перед каждым шагом цикла и говорит, продолжать ли цикл (если оно истинно) или закончить

У тебя там $height > $anonHeight — продолжать выполнять цикл пока одна переменная больше другой. По видимому, это условие выполняется всегда и цикл тожде выполняется вечно.

3) выражение, которое выполняется после шага цикла. У тебя там $number ++ — увеличивается переменная $number.

В общем, да, цикл for ты понял как-то неправильно.Почитай тут например: http://www.php.su/learnphp/cs/?cycles#for

В общем, я тебе советую прочесть теорию, и для закрепления, решить дополнительную задачу. Задача такая: напиши программу, которая выводит таблицу умножения всех чисел от 1 до 9. Вывести можно в любом виде, можно красивой табличкой, если сложно то можно по простому, в 9 строчек:

1 × 1 = 1, 1 × 2 = 2, .... 1 × 9 = 9
2 × 1 = 2, 2 × 2 = 4, .... 2 × 9 = 18
...
9 × 1 = 9 .... 9× 9 = 81

Знак умножения (да, это не буква x, а знак умножения ×) можешь просто скопировать из этого поста.

Аноним Втр 12 Ноя 2013 01:39:09  #105 №334266 

http://ideone.com/LaM1Pp поправил
с доп заданием ничего лучше http://ideone.com/OgwiVD
не получилось;

!xnn2uE3AU. Втр 12 Ноя 2013 10:23:38  #106 №334308 

>>334266

Задача про рост анона — все верно.

Задача про таблицу умножения:

- тут не нужен массив и foreach, используй цикл for который увеличивает переменную от 1 до 9
- чтобы сделать полную таблицу, надо использовать 2 вложенных друг в друга цикла, первый меняет допустим переменную $a от 1 до 9, второй для каждого значеия $a меняет $b от 1 до 9:


for ($a = 1; ....) {
for ($b = 1; ...) {
// пишем строчку $a * $b
}

}

!xnn2uE3AU. Втр 12 Ноя 2013 10:26:35  #107 №334309 

>>334266

Алсо, сделай чтобы таблица умножения выводилась строчками по 9 значений (для этого надо правильно поставить echo "\n"; который выводит перевод строки)

Аноним Втр 12 Ноя 2013 19:52:00  #108 №334536 

Доброкунчик, подкинь материала годного по вот этой теме http://www.php.su/functions/?cat=pcntl , а так же по управление процессами в Unix для пхп-макак. Я здесь >>333705 спрашивал про крон. Теперь мне нужно писать демон. Все классы есть, все работает, но если я смотрю на исходный абстрактный класс демона - мне становиться грустно. Помоги развеять тоску-печаль.

!xnn2uE3AU. Втр 12 Ноя 2013 20:15:01  #109 №334540 

>>334536

Ну для начала стоит проверить, понимаешь ли ты вообще как работают процессы в posix/linux, что такое сигналы, что такое fork и exec. Если не очень понимаешь, то для начала стоит почитать общую теорию:

http://www.k-max.name/linux/processy-v-linux/
http://www.opennet.ru/docs/RUS/lnx_process/
http://ru.wikipedia.org/wiki/Сигналы_(UNIX)

(если там что-то непонятно объяснено, можешь погуглить или задать тут вопрос).

Понимать общую теорию важно, так как функции pcntl ничего нового не представляют, а просто вызывают соответствующие функции ядра linux. Ну то есть pcntl_fork вызывает системный вызов fork(), pcntl_wait — вызывает wait() и так далее.

Ну и естественно, команды, которые упомянуты в статьях, надо вызывать из командной строки. Надеюсь, ей ты тоже умеешь пользоваться. Твой демон при отладке надо будет запускать из командной строки, так что без этого никак.

Плюс, если твой демон должен принимать соединения от других PHP-процессов, то тебе придется еще учиться работать с сокетами и придумывать протокол. Ну это отдельная интересная и обширная тема.

Ну и насчет кода — старайся все делать как можно проще, а не усложнять вещи. В частности, в демоне важны такие вещи:

- возможность блокировки, чтобы нельзя было запустить один и тот же демон 2 раза. Можно использовать блокирование с помощью создания файла с PID процесса (чтобы предыдущую копию можно было убить принудительно).
- возможно, стоит отслеживать сколько времени и памяти потребил скрипт. Ведь демон обычно обрабатывает большие массивы данных, и там легко отъесть много ресурсов и не заметить.
- стоит убедиться, что логгирование работает и любые варнинги и нотисы сохраняются в логи. Иначе демон может сидеть себе и тихонько портить базу неправильными значениями
- в некоторых случаях полезен еще флаг для тестирования, чтобы можно было запустить демон, но он ничего не писал в базу.

Еще возможно, надо будет научиться отцепляться от консоли (через posix_setsid() отсюда: http://www.php.net/manual/ru/ref.posix.php ) и наверно стоит написать init-скрипт, чтобы твой демон был полноценной службой и его например можно было бы запускать/останавливать/перезапускать стандартной командой и поставить на сервере в автозапуск, а не запускать ручками при каждой перезагрузке (поверь, это быстро надоест).

Ну ты вроде под Yii пишешь, так что делай как там принято, там есть класс для консольных команд.

!xnn2uE3AU. Втр 12 Ноя 2013 20:17:47  #110 №334544 

vocaroo

Аноним Втр 12 Ноя 2013 20:56:51  #111 №334557 

аноны незнаю куда обратиться

пытаюсь разгадать одну херню

вот оригинал строчки:
Then HMAC-SHA512 is used to hash STRING1 with STRING2 giving us a 128 character hex string.

вот значения стрингов:
STRING1 = "3501:46fc85ae6e87cac1:3501"
STRING2 = "3501:c4d536307d28fc15:3501"

собственно вопросы:

для hmac sha512 я так понял обязательно нужен ключ для шифрования, так? и если хэш генерировать просто sha512 то получиться другое совершенно, так?

и я так понял что мы объединяем эти 2 строчки, так?

!xnn2uE3AU. Втр 12 Ноя 2013 21:47:39  #112 №334574 

>>334557

Может быть одна из строк и есть ключ? Написано же

> hash STRING1 with STRING2
захешировать строку1 строкой2

Аноним Срд 13 Ноя 2013 04:31:41  #113 №334648 

>>334309
http://ideone.com/1yqSg1
пойду скушаю пирожок

Аноним Срд 13 Ноя 2013 10:18:51  #114 №334660 

Гуру PHP, ай нид хэлп, суть такова: внезапно, не помню после чего, перестали работать все регексы в проекте (возвращают false и отдают пустые массивы групп). Кодировка разбираемых текстов windows-1251, IDE – Eclipse.
Перед этим игрался с сессиями (но, в итоге, выпилил их использование) и написал пару методов, пишущих массивы в XML, но они никак не связаны с регулярками и контентом.

!xnn2uE3AU. Срд 13 Ноя 2013 11:24:16  #115 №334663 

>>334648

Хорошо, только вместо этого if

> if ($b==9){

можно было поставить echo после цикла, то есть


for ($a = 1...) {
for ($b = 1; ....) {
...
}

echo "\n";
}


ну да ладно. Главное, что с циклами разобрался.

>>334660

Может ты в другой кодировке что-нибудь сохранил? Так вообще, непонятно.
Аноним Срд 13 Ноя 2013 12:55:39  #116 №334681 

> echo "\n";
Рекомендую анонам в место этого использовать echo PHP_EOL;

!xnn2uE3AU. Срд 13 Ноя 2013 12:57:12  #117 №334684 

>>334681

Чем оно лучше? \n работает везде, и пишется короче. То же самое и с DIRETORY_SEPARATOR: / работает везде и пишется короче.

Аноним Срд 13 Ноя 2013 13:05:36  #118 №334688 

>>334684
На маках другая последовательность символов. Да и просто, если язык даёт средства для автоматизации, то имхо предпочтительнее их использовать. Меня самого иногда ломает писать все эти длинные названия. По этому:
define(EOL, PHP_EOL);
define(DS, DIRETORY_SEPARATOR);

Аноним Срд 13 Ноя 2013 13:31:57  #119 №334700 

>>334688
Я конечно же хотел сказать.
> define('EOL', PHP_EOL);
> define('DS', DIRETORY_SEPARATOR);

!xnn2uE3AU. Срд 13 Ноя 2013 13:56:36  #120 №334708 

>>334688

> На маках другая последовательность символов.
На маках используется \n для новой строки (как и в Линуксе), / как разделитель каталогов (как и в линуксе). В Windows используется \r\n но \n переводит строку в консоли, и виндовые функции понимают / как разделитель каталогов.

Вопрос, зачем тогда уродовать код этими константами?

Да, когда-то в маках были свои причуды, но с выходом Mac OS X там все стало как в линуксе, а вышла Mac OS X лет 10 назад.

Или ты знаешь какой-то реальный пример, когда / или \n не работабт на современных осях?

Аноним Срд 13 Ноя 2013 15:34:22  #121 №334737 

>>334708
Анончик, я таки считаю, что код уродуется отсутствием констант. И да, используя константы эти , я не вникаю в тонкости функционирования разных ОС, но я получаю гарантию, что код будет работать так как нужно и обеспечивается обратная совместимость. Так почему бы эти константы не использовать?

!xnn2uE3AU. Срд 13 Ноя 2013 15:40:52  #122 №334744 

>>334737

Потому, что читать такой код тяжело. А если кто-то в будущем сделает свою ОС с нестандартными разделителями каталогов, то пусть заслуженно страдает.

Аноним Срд 13 Ноя 2013 15:54:33  #123 №334754 

>>334744
Анончик, я опять таки считаю, что сложнее читать
echo "\r\n";
чем
echo EOL;
Да и писать дольше.
По поводу новых разработок, твоя аргументация железная, лол. А если не разработает а модифицирует уже существующее популярное решение? Ты уверен, что в следующей версии макоси или винды не изменяться их стандарты?
Короче забей, Анон. Пиши как пишется, я никому ничего не навязываю.

Аноним Срд 13 Ноя 2013 17:07:58  #124 №334776 

>>334700
Я думаю, ты всё-таки хотел сказать
> define('EOL', PHP_EOL);
> define('DS', DIRECTORY_SEPARATOR);

Аноним Срд 13 Ноя 2013 18:07:36  #125 №334785 

Сдаю домашку.
http://viper-7.com/xdJKY9

Что-то переработал мальца, ну да ладно. ОП, особенно интересно было бы что-нибудь про эксепшны услышать. Я их там покидал немного, но не уверен, что в подходящих местах.

Еще - может что посоветуешь почитать про объектно-ориентированное проектирование? Так чтобы совсем энтри-левел, а то тема как я понимаю необъемная.

!xnn2uE3AU. Срд 13 Ноя 2013 18:10:26  #126 №334786 

>>334754

\r не нужен же, я же написал, достаточно \n:

echo "Start\nWorking\nEnd\n"; — если строку разбить EOL и точками, то будет каша.

А пути как ты будешь писать?

$path = APP_DIR . "/data/files/file.txt";

Но я тут подумал и придумал решение. Можно сделать функцию, которая заменяет / на DS, а \n на EOL и писать нормально:

echo newlines("Start\nWork\nEnd\n");
$path = path(APP_DIR . "/data/file.txt");

!xnn2uE3AU. Срд 13 Ноя 2013 18:21:03  #127 №334788 

>>334785

> может что посоветуешь почитать про объектно-ориентированное проектирование?

Ну конечно же Мэтт Зандстра — PHP. Объекты, шаблоны и методики программирования

Ну еще наверно можно почитать Thinking in Java (философия Java) но это книга про Яву, она огромная, так что если ты ее начнешь читать, мы тебя точно потеряем. Еще есть книга Мартин Фаулер «Patterns of Enterprise Application Architecture» — но она для тех, у кого есть опыт работы с реальными проектами, начинающий там половину не поймет. Но можешь посмотреть из любопытства. Именно в этой книге описываются разные паттерны, фабрики и прочие вещи.

Задачку сейчас тоже проверю.

!xnn2uE3AU. Срд 13 Ноя 2013 19:01:46  #128 №334793 

>>334785

Табличка милая. Но, увы, старомодная. Таблицы в наше время выглядят так (меньше ненужных линий, промежутки между соседними ячейками и так достаточно большие):

http://viper-7.com/YZ5Pec

Не стоит выравнивать данные по центру ячеек. Надписи лучше выровнять влево, а числа −— вправо, чтобы их было легче сравнивать (я поленился это сделать). Задавать для таблицы высоту (height) нет смысла, так как высота определяется содержимым, а не тем, что ты задал. Ширину, наверно, лучше тоже не указывать, пусть определяется автоматиечски. Стоит указывать padding для ячеек, чтобы в любом случае оставались промежутки. Удобно в HTML-коде использовать теги thead, tbody, tfoot для выделения частей таблицы, чтобы можно было применить отдельные стили для подвала например.

А вот с ООП ты, конечно, напутал.

Company::__construct — да ну, зачем так сложно? Можно создавать пустую компанию, а добавлять департаменты просто через addDepartment(). Такой подход имеет смысл только если класс очень часто используется (и то, мне не нравятся такие функции, которые принимают на вход что угодно). Вряд ли у тебя будет создаваться компания в 30 разных местах в программе.

> is_a($d, 'Department')
Лучше использовать специальный оператор instanceof: $d instanceof Department
В мануале ( http://us1.php.net/is_a ) написано:

> Эта функция была помечена устаревшей в пользу оператора instanceof. Вызов данной функции вызовет предупреждение уровня E_STRICT
Читай мануал, это полезно.

!xnn2uE3AU. Срд 13 Ноя 2013 19:03:29  #129 №334794 

>>334785
> throw new RuntimeException();
надо указывать причину: throw new RuntimeException("Element of array with key=$key, passed to ".METHOD." is not instance of class Department");

Желательно делать такие сообщения об ошибке, чтобы сразу было видно в чем проблема.

> public function addDepartment(Department $dep){
> if (is_a($dep, 'Department')) {

Это не нужно. У тебя стоит type hint в заголовке функции, PHP тебе не позволит передать что-то другое.

> try {
> ...
> throw new RuntimeException();
> }
> catch(Exception $e) {
> die("Компания должна состоять из департаментов!<br>".$e);
> }

Тогда проще сразу написать if (..) { die(); }. Исключения обычно выбрасывают и ловят в разных местах программы.
Плюс, die не нужен — PHP и так по умолчанию умирает при непойманном исключении.
Плюс, если ты ловишь исключения, то лови не все подряд, а только свои исключения: catch (RuntimeException $e)

!xnn2uE3AU. Срд 13 Ноя 2013 19:06:09  #130 №334796 

>>334785


> $deps = array_filter($deps, function($d) { return is_a($d, 'Department'); });
Эта функция молча отбросит неправильные объекты, ничего не написав. А другие — выкидывают исключение. Неправильно. Лучше через foreach проверить.

> public function removeDepartment($dep) {
Не имеет никакого смысла передавать туда int (номер в массиве), так как непонятно, где этот номер взять? Ни одна функция его не возвращает. Передавай туда Department.

> public function getDepartment($id = 0) {
То же самое. Плюс, непонятно, почему 0-й депарамент такой особенный что возвращается по умолчанию.

> private function getterHelper($field) {
Нехорошо. Передавать половину названия метода нехорошо (например, ты не сможешь тогда поиском найти все места где вызывается getSomething, так как в коде написано просто 'Something'). Лучше сделай метод sumDepartmentsBy($callback), который вызывает переданную извне функцию на каждом департаменте:

$pay = $company->sumDepartmentsBy(function ($dep) { return $dep->getPay(); });

Чуть длиннее, но зато аккуратнее.

> $salaryMod = self::RANK_1;
Лучше массив вида (ранг => прибавка), не надо в константах хранить данные.

> public function hire($employee) {
> try {
> if (!is_a($employee, 'Employee')) throw new RuntimeException();

Короче так: public function hire(Employee $employee) {

> if ($isBoss && !$this->isBoss) {
Вот это особый кошмар. Это вообще понять невозможно, надо заменить на что-нибудь другое. Наример, так:

if ($this->isBoss) { .... }

> public function getPayPerPage() {
> return $this->payPerPage;
> }

Если написать return $this->getPay() / $this->getPages() то мы избавимся от неунжного поля payPerPage и сделаем код функции в 3 раза понятнее и очевиднее. Это нездоровая оптимизация, которая больше вреда приносит читабельности, чем пользы. Поделить 2 числа недолго, даже в PHP.

Для исключений лучше бы завести свой класс, а не юзать RuntimeException, так как в этом случае мы можем ловить только твои исключения.

В общем, исправь пока это, а потом проверим еще раз.

Аноним Срд 13 Ноя 2013 19:06:45  #131 №334797 

Вечер в хату, phpach.

Расскажи мне, пожалуйста, как на php эффективно работать с изображениями?

В чем суть: есть чб изображение, на изображении две метки(черные области 40х40px), Необходимо повернуть изображение так, что бы одна метка была над другой. Затем найти среднее значение цвета в некоторых заданых областях.

С первой задачей вообще не имею понятия как справится.
Со второй справляюсь простым проходом по всем пикселям и нахождением среднего арифметического, но это очень медленно.
Юзаю imagemagic

!xnn2uE3AU. Срд 13 Ноя 2013 19:18:33  #132 №334804 

>>334785

Про исключения. История тут очень простая. До ООП ошибки обратаывались примерно так:


function bigFunction(&$error = '' /* для возврата текста ошибки */) {

$x = doSmth();

if ($x === false) {
$error = 'doSmth() failed';
return false;
}

$y = doSmth2();
if ($y === false) {
$error = 'doSmth2() failed';
return false;
}

return $x + $y;
}


Поскольку любая более-менее сложная функция, работающая с файлами/базой может получить ошибку от нижележащих функций, везде надо было ставить эти if и проверять результат вызова. Ну или можно сразу умирать при ошибке, но тогда ошибку нельзя перехватить и обработать (например при проблеме с сетью — повторить попытку). Ну или, как настоящий быдлокодер, не проверять результат вызова, кого волнуют какие-то там ошибки.

Потому придумали исключения. Если что-то пошло не так, ты выкидываешь исключение, и оно либо ловится ближайшим блоком catch, либо роняет программу.

Вот как выглядит bigFunction с использованием исключений:


function bigFunction() {
return doDomth() + doSmth2();
}


Если в doDmth/doSmth2 произойдет ошибка, выброшенное исключение пролетит сквозь функию bigFunction наверх, и нам не надо его ловить или обрабатывать. Этот пример можно показывать особо упоротным фанатам, которые кричат что ООП тяжелый, усложненный и не нужен.

Про таблицы. Вдохновляться видом таблиц можно тут: http://dribbble.com/search?page=1&q=data+table Можно еще поискать в картинках в Google, но там половина — адский треш.

!xnn2uE3AU. Срд 13 Ноя 2013 19:20:15  #133 №334805 

>>334797

Найти как-то эти метки, найти угол линии, проведенной между ними и повернуть на этот угол.

Аноним Срд 13 Ноя 2013 19:22:01  #134 №334807 

>>334786
Ого сколько всего! Спасибо. Буду править.

>>334793
>в мануале там написано

Ну да, а дальше написано:
>This function is no longer deprecated, and will therefore no longer throw E_STRICT warnings.

Но не суть, я быстро-быстро его проглядывал, до этих моментов даже не дошел. Впредь буду instanceof использовать.

Вообще, мануал не только читаю, но и задрачиваю. С помощью anki заучиваю основные функции с их параметрами, всякие моменты неочевидные вроде поведения self:: и static::.

Замечания по поводу вёрстки передам тян, она верстала :3

Аноним Срд 13 Ноя 2013 19:23:16  #135 №334808 

>>334805
До этого то я дошел.
Проход по всей линии в поиках черного пикселя-ну ооочень долго.

Да и как найти угол?

!xnn2uE3AU. Срд 13 Ноя 2013 19:51:37  #136 №334813 

>>334807

> Вообще, мануал не только читаю, но и задрачиваю.
Не, наизусть учить не надо. Просто когда встречаешь новую функцию, просмотри страничку про нее, чтобы знать ее особенности. Постепенно все часто используемые функции будешь знать.

Единственный случай, когда стоит перечитать мануал — когда идешь на собеседование, например. Там любят спршивать дурацкие вопросы про то, чем отличается ++$x от $x++, про разницу операторов and и && или сработает ли if (array()) { ... } и if ("10" > "9") { ... }

Аноним Срд 13 Ноя 2013 20:19:08  #137 №334815 

>>334813
Ну, у меня хреновая память, так что мне это здорово помогает, плюс структурирует знания. Да и приятно не лазить каждый раз в мануал, когда строку надо обрезать или там регуляркой разделить. И времени не так уж много занимает.

Кстати, ответы на вопросы кажется знаю.
1. Преинкремент/постинкремент - сначала увеличивает, потом возвращает значение/сначала возвращает значение, потом увеличивает. Интересней было бы, если бы спросили что выдаст и как рассчитывается $a = 2; $a = $a += $a++;
2. Уровень приоритетности (главная разница - у 'and' он ниже чем у '=')
3. Вот тут не знаю, вроде да, т.к. массив хоть и пустой, но в списке falsy значений я его не припоминаю. Да и кажется пердолился как-то с тем, что выборка из БД была пустым массивом, а проверку if($res){} она проходила. Но не уверен.
4. Не сработает, сравнение строк идет по первому знаку (если не natcase)

Лол, меня возьмут жуниором?

Но я вообще чего спросить пришел. Нормально вообще выбрасывать исключение и не ловить его? Вроде где-то читал, что да, но при этом меня как-то коробит повторяющаяся дважды информация о нём при срабатывании.

И еще. Может кто-нибудь посоветовать халявный хостинг с php5.3+ ?

!xnn2uE3AU. Срд 13 Ноя 2013 20:41:24  #138 №334820 

>>334815

Про пустой массив (он falsy) написано тут: http://www.php.net/manual/ru/language.types.boolean.php#language.types.boolean.casting

> Нормально вообще выбрасывать исключение и не ловить его?
Нормально. Если например тебе пытаются в функцию передать что-то левое, то зачем ловить такое исключение? Надо просто исправить код.

То же и с фатальными ошибками типа файл должен быть на диске, а его нет. Ну нет файла — извините, программа не работает.

Если речь идет о сайте, то конечно, придется поставить обработчик ошибок, чтобы при ошибке пользователи видели не белую страницу, а красивое сообщение о том, что скоро все исправится.

> коробит повторяющаяся дважды информация о нём при срабатывании.
Это странная особенность PHP, не обращай внимания (непойманное исключение вызывает фатальную ошибку и она выводит текст исключения второй раз, вроде так). В продакшене все равно ошибки пишутся только в логи, а на экран не выводятся.

> И еще. Может кто-нибудь посоветовать халявный хостинг с php5.3+ ?
Вроде один анон appFrog использовал. Еще есть host1free, но он легко может пару дней лежать.

!xnn2uE3AU. Срд 13 Ноя 2013 20:42:50  #139 №334821 

>>334815

Алсо, для вопросов с собеседований, тут есть список правил преобразований: http://www.php.net/manual/ru/language.types.type-juggling.php в конце

И умопомрачающая таблица сравнения типов: http://www.php.net/manual/ru/types.comparisons.php (на тот случай если спросят как сравниваются массивы с помощью == и ===)

Аноним Срд 13 Ноя 2013 21:03:45  #140 №334828 

>>334820
А, понял, почему про массив напутал. Там то он был не пустой, а с другими массивами внутри, которые пустые.
Остальное принял к сведению.


>Передавать половину названия метода нехорошо (например, ты не сможешь тогда поиском найти все места где вызывается getSomething, так как в коде написано просто 'Something').

Вот про это не совсем понял, это же хелпер, он нужен только для внутренней структуры объекта. Там то там $vector->getSmth везде. Завтра перечитаю, сейчас уже голова мутная.

Остальное вроде поправил.

http://viper-7.com/TqJGRH

sageАноним Срд 13 Ноя 2013 21:47:47  #141 №334834 

Аноны, поясните что тут делать? Как мне в субклассе изменить метод? Допустим родитель имеет метод: echo "Text";. Что писать, дабы субкласс изменял метод родителя на echo "text 2"? Я по-моему что-то упустил. Маны перелопатил и не нашел примера :( Только не серчайте на ньюфажину.

!xnn2uE3AU. Срд 13 Ноя 2013 22:17:58  #142 №334842 

>>334828

Вот эта оптимизация опасна:

> $this->pay -= $employee->getSalary();
А что если между приемом на работу и увольнением у сотрудника изменился ранк или оклад? надо делать дополнительные проверки (ок, в учебной задаче нельзя менять ранг у сотрудника. Но в более реалистичной задаче наверняка понадобится. И тогда код всех тих проверок может стать запутанным и глючным).

> public function removeDepartment($name) {
Почему бы не передавать туда сам объект $department?

> Вот про это не совсем понял, это же хелпер, он нужен только для внутренней структуры объекта. Там то там $vector->getSmth везде. Завтра перечитаю, сейчас уже голова мутная.
Ну представь мы решили переименовать у класса Employee getPay в getSalary и делаем поиск по getPay (чтобы поменять название везде). 'Pay' мы не найдем и не переименуем.

>>334834

Определи в сабклассе новый метод с таким же именем.

!xnn2uE3AU. Чтв 14 Ноя 2013 01:29:45  #143 №334874 

>>334828

> $this->pay -= $employee->getSalary();
Я вспомнил еще одну потенциальную проблему: округление. В PHP дробные числа хранятся с ограниченной точностью. Если у работников дробная зарплата и ты добавишь человек 100, а потом всех уволишь, в итоге может остаться не 0, а например 0.0000001.

> Call to ". METHOD ." failed
Это было в моем примере, но я тут подумал, писать это не нужно. Если у тебя есть xdebug, то там и так выводится полный стек вызовов функций с именами и номерами строк, и в сообщениях об ошибке тоже есть номер строки.

> foreach($this->departments as $key → $dep) {
наверно => а не ->

> if ($dep->getName() == $dep->getName()) {
Это что?

> return $this->getterHelper('Pay');
Сделай хотя бы 'getPay', а то имя не будет вываливаться при поиске. Алсо getterHelper можно бы переименовать в sumBy

> if (!is_int($rank)) return false;
В конструкторе это не имеет никакого эффекта, как я понимаю, вернется все равно новый объект. Надо бросать эксепшен, так как false все равно не вернется. И даже если бы конструктор мог вернуть false, ты же все равно не проверяешь это.

public function __destruct() {
self::$employeesNumber--;
}

Неверно. Так может получиться 2 работника с одинаковыми номерами (если мы уничтожим не последнего, а какого-то другого). Также, объект можно клонировать (оператор clone) и копии уничтожить, тогда будет уничтожено 2 объекта и employeesNumber уменьшится на 2.

По этой причине, деструктор лучше вообще не использовать - он таит в себе столько подвохов, что легко наделать ошибок. деструктор используют обычно для освобождения выделяемых в конструкторе ресурсов, и то в 99% случаев он не нужен в PHP.

> protected $employeesCount = 0;
Это поле не нужно. Вызов count($this->employees) работает очень быстро, за O(1) так как в PHP в массиве хранится его длина. Эта твоя микрооптимизация то же самое, что заменять двойные кавыки на одинарные ради якобы ускорения программы.

Заметь, что удалив поле мы избавляемся и от ненужных более строк по его увеличению/уменьшению.

Если так хочется оптимизировать код, попробуй выоптимизировать цикл из fire() — там можно обойтись без перебора всего массива.

Аноним Чтв 14 Ноя 2013 14:44:22  #144 №334939 

>>334842
>А что если между приемом на работу и увольнением у сотрудника изменился ранк или оклад? надо делать дополнительные проверки (ок, в учебной задаче нельзя менять ранг у сотрудника. Но в более реалистичной задаче наверняка понадобится. И тогда код всех тих проверок может стать запутанным и глючным).

Вот собственно примерно про это изначально и спрашивал, мне тоже показалось, что это порочный путь - слишком много подводных камней. Т.е. если надо изменить у какого-то сотрудника его параметры (повысить ранг например), или, например, в принципе модификаторы ранга поменять, то надо каждый раз всё пересчитывать заново. А ведь я читал у Макконелла про то, что микрооптимизации в ущерб очевидности кода надо оставить на потом, если производительности хватать не будет. Но одно дело прочитать, а совсем другое - напороться на это самому. Урок усвоен. :3

>Почему бы не передавать туда сам объект $department?
Вот не знаю, мне как-то это нелогично кажется. Это принятая практика? Тут проблема в том, что я не могу представить, как в риаллайф-приложении что-то подобное работает.

>Ну представь мы решили переименовать у класса Employee getPay в getSalary и делаем поиск по getPay (чтобы поменять название везде). 'Pay' мы не найдем и не переименуем.
Окей, ты наверное прав - при поддержке, когда уже не помнишь, что там и зачем автоматическому рефакторингу помешает. Буду иметь в виду на будущее.

>Я вспомнил еще одну потенциальную проблему: округление. В PHP дробные числа хранятся с ограниченной точностью. Если у работников дробная зарплата и ты добавишь человек 100, а потом всех уволишь, в итоге может остаться не 0, а например 0.0000001.
Ага, помнил про это пока писал, вроде там специальный класс есть для работы с валютой. Опять же, буду иметь в виду, но в учебном задании, да еще и на работу с ООП прежде всего, слегка overkill по-моему.

>Это было в моем примере, но я тут подумал, писать это не нужно. Если у тебя есть xdebug, то там и так выводится полный стек вызовов функций с именами и номерами строк, и в сообщениях об ошибке тоже есть номер строки.
Ага, тоже это заметил. Ну зато знаю теперь про магические константы в ООП, профит.

> if ($dep->getName() == $dep->getName()) {
> foreach($this->departments as $key → $dep) {
Ох лол. Невнимательность и суетливость - уже устал под вечер, хотелось поскорее расправиться. Гнилая отмаза, да.
Вообще мне кажется, что уже даже на таком маленьком "приложении" можно поиметь профиты от автоматического тестирования. Тесты бы такие косячки не пропустили. А второй (вроде должен с ошибкой синтаксиса вываливаться) я так и вовсе у себя исправил, а на вайпера залить забыл.

>По этой причине, деструктор лучше вообще не использовать - он таит в себе столько подвохов, что легко наделать ошибок. деструктор используют обычно для освобождения выделяемых в конструкторе ресурсов, и то в 99% случаев он не нужен в PHP.

Принял к сведению. Как тогда лучше айдишники генерировать? Мне приходит в голову только с помощью mt_rand и проверять при создании нового, что такого еще нет. Но это наверное не совсем верная мысль.
Кстати, в каких случаях стоит использовать деструктор для освобождения ресурсов? Например, насчет circular references не особо понятно - вроде есть специальный гарбаж коллектор, а вроде он и не всегда включен бывает.

>Если так хочется оптимизировать код, попробуй выоптимизировать цикл из fire() — там можно обойтись без перебора всего массива.
Если передавать объект Employee и использовать array_keys или array_search? Но в этом же случае емнип массив всё равно будет перебираться, просто за кадром.

Аноним Чтв 14 Ноя 2013 14:47:14  #145 №334941 

Вообще, ОП, огромное тебе спасибо. Многие косяки из тех, что ты подмечаешь, только видя код со стороны и обладая значительным опытом можно заметить, очень рад, что есть кому попинать и не давать расслабляться.

!xnn2uE3AU. Чтв 14 Ноя 2013 15:31:26  #146 №334962 

>>334939

>> Почему бы не передавать туда сам объект $department?
> Вот не знаю, мне как-то это нелогично кажется. Это принятая практика? Тут проблема в том, что я не могу представить, как в риаллайф-приложении что-то подобное работает.

Ну возьмем риаллайф-приложение: DOM в браузере. DOM — это дерево всех узлов (соответствующим HTML-тегам) на странице. DOM есть и в PHP в виде расширения. Там для удаления дочернего узла используется такой код:

$parentNode->removeChild($childNode); // http://php.net/manual/ru/domnode.removechild.php

То есть родителю передается объект-ребенок, которого надо удалить. Хотя, в такой ситуации можно конечно было бы сразу сделать метод remove у ребенка:

$childNode->remove();

Но почему-то так не сделали (так сделали в jQuery, которая является оберткой над DOM).

В общем, первый вариант - передавать объект или сделать метод remove у самого объекта. Второй вариат — передавать в removeDepartment id департамента, если они уникальные. Но для получения id тебе скорее всего надо сначала как-то найти сам департамент, и вызывать у него getId() — так что, передавать сразу объект выходит короче. Передача id обычно используется во всяких удаленных интерфейсах, например, в каком-нибудь сетевом API, чтобы не гонять объект туда-сюда.

> Как тогда лучше айдишники генерировать?
Так как у тебя, но никогда не убавлять self::$employeeNumber, только увеличивать. Тогда повторов не будет. По такому принципу работает AUTO_INCREMENT в MySQL.

> вроде там специальный класс есть для работы с валютой
При работе с валютой обычно используют числа фиксированной точности, с заранее заданным числом знаков после запятой (в MySQL это тип DECIMAL например). Также, есть расширение BCMath для работы с числами произвольной точности.

> Кстати, в каких случаях стоит использовать деструктор для освобождения ресурсов? Например, насчет circular references не особо понятно - вроде есть специальный гарбаж коллектор, а вроде он и не всегда включен бывает.

Ненужные объекты PHP (на которые больше нет живых ссылок) должны по идее всегда собираться и удаляться сами. Если кто-то отключил GC — он делает это на свой страх и риск и это его проблема, если что-то не очистится. Специально учитывать это в коде не надо, если что-то не освобождается по вине PHP — пиши им баг-репорт, пусть исправляют.

Ресурсы - имеются в виду внешние относительно PHP ресурсы. Например, если мы создали в конструкторе временный файл, то можно в деструкторе его удалять. И то, это какой-то сомнительный код, конечно получается, так как PHP вполне может упасть так, что деструкторы вызваны не будут. В линуксе обычно делают по-другому, создают и открывают временный файл и сразу же делают ему unlink: в этом случае файл автоматически удалится операционной системой, как только его закроют (в том числе при падении программы). Но под виндой это уже не работает, там файл удаляется сразу.

Я в реальных проектах особо применения деструкторов не видел. Открытые файлы закрываются сами, соединения тоже, незакомиченные транзакции в базе откатываются при разрыве соединения, практически всегда все это происходит автоматически. Единственный раз, когда я видел использование деструктора, он удалял временные файлы, причем из-за этого по моему как раз возникал какой-то баг.

>> Если так хочется оптимизировать код, попробуй выоптимизировать цикл из fire() — там можно обойтись без перебора всего массива.
> Если передавать объект Employee и использовать array_keys или array_search?

Нет. Это все равно будет O(N). Чтобы было O(1), надо в массиве employees использовать id в качестве ключа и удалять работника тогда можно через unset($employees[$id]).

> Вообще мне кажется, что уже даже на таком маленьком "приложении" можно поиметь профиты от автоматического тестирования.
Верно, это приложение, которое вещь в себе не лезет никуда наружу, и оно хорошо тестируется. Реальный код, увы, не всегда является «вещью в себе». Если хочешь заморочиться с тестированием, то хорошо бы установить например phpUnit и писать тесты на нем, так как это уже готовый тестовый фреймворк.

>>334941

Для этого мы и решаем задачки. Косяки, да, подмечаю, так как ООП не самая простая вещь и многие в нем путаются, а знать его надо обязательно (и есть книги/курсы, где его не изучают, что печально).

Аноним Чтв 14 Ноя 2013 16:16:26  #147 №334971 

Как грамотнее устанавливать JS-события на множество однотипных элементов, которые формируются на php?
1. HTML внутри php-цикла:
<?php foreach($row as $value) {
//формируем большущую табличку с кнопками, например такими:
?>
<span class='delete' onclick='deleteRow()'></span> <!--элемент интерфейса, удаляющий ряд в таблице-->
<?php
}
?>
2. На чистом JS, как-то так:
<script>
var spans=document.getElementByClassName('delete');
var total=spans.length;
for (var i=0;i<total;i++) {
spans.onclick=deleteRow;
}
</script>
3. На jQuery, как-то так
$(function() {
$('.delete').click(function() {
deleteRow();
})
})
tags: Производительность, говнокод.

!xnn2uE3AU. Чтв 14 Ноя 2013 16:24:53  #148 №334973 

>>334971

Вариант с onclick="..." — ОК (так любит делать например вконтакте)

Вариант 2 и 3 с $('.delete').click — отстой, так как ты сначала ищешь кучу элменетов и ставишь кучу обработчиков. А если бы автор кода вместо изучения jQuery изучил яваскрипт и DOM ( в чудесном учебнике http://learn.javascript.ru/event-delegation ) то узнал бы, что события всплывают и можно один поставить обработчик на родительский элемент (и да, в этом случае динамиечски добавляемые элементы тоже будут работать).

Так что либо прописывай onclick="" либо ставь один обработчик на родителя. И еще, я бы советовал использовать для кнопки button: он гораздо удобнее, чем span, плюс он выделяется табом, не разрешает выделять на нем текст и вообще ведет себя как настоящая кнопка.

!xnn2uE3AU. Чтв 14 Ноя 2013 16:28:05  #149 №334974 

>>334971

Насчет jQuery, если используешь его, то и обработчик удобно ставить с помощью него: $('#table').on('click', '.delete-row', function (e) {
...
}); — по моему в новом jQ это делается так. Строчка '.delete-row' пропускает только события, возникшие на кнопке, а не в любом месте таблицы.

Аноним Чтв 14 Ноя 2013 17:32:51  #150 №334980 

>>334973
Спасибо, пожалуй, c onclick='' проще всего сделать. А если несколько функций надо повесить, решение со вспомогательной функцией покатит?
onclick='temp()' где
function temp() {
deleteRow();
recount();
ajax();
}
А то onclick='deleteRow(); recount(); ajax();' как-то вырвиглазно выглядит, хотя работает. Про addEventListener, attachEvent читал, там ад с кроссбраузерностью, передачей this и аргументов, не хотеть.
И вдогонку: есть ли смысл дополнительно прописывать id для инпута чтобы брать его в JS с помощью getElementById(), если его можно взять getElementsByName()[0]. По айди вроде как быстрее, но в данном случае имя на форме уникально и всего одно.

!xnn2uE3AU. Чтв 14 Ноя 2013 17:48:48  #151 №334984 

>>334980

> Про addEventListener, attachEvent читал, там ад с кроссбраузерностью, передачей this и аргументов, не хотеть.
jQuery кое-что в этом плане исправляет и приводит события к единообразному виду. Алсо если без jQuery, ада нет, есть код для w3с и для IE, всего 2 варианта:

function myCallback(e) {
var ev = e || window.event;
var target = ev.target || ev.srcElement;

...
}

Этот код уже решает половину проблемы.

> решение со вспомогательной функцией покатит?
Да только название сделай нормальное, желательно со своим префиксом чтобы не пересеклось с другой функцией.

> И вдогонку: есть ли смысл дополнительно прописывать id для инпута чтобы брать его в JS с помощью getElementById(), если его можно взять getElementsByName()[0]
Есть, наверно. В jQuery тогда тоже можно писать $('#abc') что и быстрее и короче. Чтобы не было проблем с дублирующимися id (например, 2 формы на странице), используй префиксы: #register-email, #login-email

Аноним Чтв 14 Ноя 2013 20:37:15  #152 №335025 

Объясните мне пожалуйста, зачем нужны абстрактные классы? http://www.php.net/manual/ru/language.oop5.abstract.php <-- здесь вообще не говорится зачем они нужны (а нахуя?) а вот здесь первый ответ вроде 27 человек оценили, но я ничего не понял. Читал ответы на stackoverflow и на askdev но всё равно не пойму зачем их использовать. Может кто-то попытается объяснить на пальцах? Помогите анончики, вы последняя надежда.

Cупер дабл Аноним Чтв 14 Ноя 2013 20:51:26  #153 №335033 

У анона выпало 6 и 6
У компьютера 6 и 6
Сума в анона 12
Сума у компьютера 12
2 дабла!

Аноним Чтв 14 Ноя 2013 21:02:24  #154 №335038 

>>335025
ОНА НАСТОЯЩАЯ!!!

!xnn2uE3AU. Чтв 14 Ноя 2013 21:28:08  #155 №335039 

>>335033

Да, это редко бывает.

>>335025

Абстрактный класс — это класс, объект которого нельзя (или нет смысла) создать. Обычно а.к. используется в качестве базового класса, от которого наследуются уже не-абстрактные (=конкретные) классы.

Если ты программист, и ты хочешь запретить создавать объекты класса (или ты в общем-то не против, но смысла создавать их нету), ставь ему abstract. Плюс, ты можешь натыкать абстрактных методов, и классы-наследники будут обязаны их реализовать.

Пример — программа про ООО Вектор: http://viper-7.com/TqJGRH — здесь класс Employee просто обязан быть абстрактным (но это почему-то не сделано), так как надо создавать один из его наследников.

>>335038

Да, и судя по виду местности, из нашей страны.

Аноним Птн 15 Ноя 2013 01:13:31  #156 №335082 

https://github.com/Somepony/pdd.yandex-mail-register

Аноним Птн 15 Ноя 2013 03:38:09  #157 №335106 

>>335025
Большая часть всех этих непонятных штук в программировании имеет отношение к повторному использованию кода.
И абстрактные классы - не исключение.

Причин делать класс именно абстрактным может быть несколько.
Например - требование ко всем наследникам реализовать определённый (полиморфный) метод, который невозможно реализовать в данном классе, но который используется другими методами, уже реализованными в данном классе (это может быть достаточно хитро для начинающего).
Тогда абстрактный класс включает только заголовок такого метода (методов), т.е. только интерфейс, но не реализацию.

Или, класс может быть просто абстрактным по определению, т.е. создание его объектов не имеет смысла. Но, при этом он реализует кучу функционала, необходимого наследникам. Например, Creature в какой-нибудь игре. Тогда его делают абстрактным просто чтобы гарантировать невозможность создания его экземпляров.

Сохранение в html. Сайт о шарах Аноним Птн 15 Ноя 2013 08:42:26  #158 №335120 

Аноны, а двач ведь схороняет страницы в html, чтобы грузить быстрее и независимо от базы, так? У двача все просто, можно разложить треды по доскам (в папках) и радоваться жизни. А если сайт, например, о шарах. Шары бывают большие, средние и маленькие, а ещё красные, чёрные, синие и коричневые. Под цвет и размер есть две разные менюшки, сделать размер или цвет главным параметром (чтобы вложить в него другие) нельзя, так как надо в любой момент иметь возможность вывести все красные шары или все маленькие или все большие коричневые. Как разложить их? Дублировать две вложенные структуры? Это наверное быдлокод и может усложнить жизнь раскручивающему. Может какие-то номера дать отдельным шарам (образно, страниц с описанием товара шар, статьям о шарах, контактных данных шаров) и сохранять их по номерам, а в структуре хранить только основные страницы каталога?

!xnn2uE3AU. Птн 15 Ноя 2013 10:53:54  #159 №335140 

>>335120

Не изобретай велосипедов, а возьми готовую CMS, например, Друпал, Вордпресс, и вбей свои шары в нее. Выйдет гораздо быстрее, кода писать почти не надо, только верстку.

Параметры шара в WP можно сделать тегами, тогда одной статье можно назначить 2 тега — «красные шары» и «большие шары». Или же, если рчь о Друпале, можно сделать у шара 2 категории через CCK — «цвет» и «размер». Ну и менюшки после этого можно прикрутить любые.

Заметь, что используя CMS ты получаешь уже готовый код и админку, из которой в любой момент можно добавлять, удалять. редактировать описания шаров. И это все не написав ни строчки кода. А сам ты угробишь на это неделю-две и получишь кучу быдлокода без админки.

> чтобы грузить быстрее и независимо от базы, так?
База есть на любом хостинге за 50 рублей в месяц. Плюс, такой подход, как я понимаю, создает огромную нагрузку на диск при активном постинге.

!xnn2uE3AU. Птн 15 Ноя 2013 10:55:33  #160 №335141 

>>335120

А, если ты эти шары собрался продавать, то бери готовый движок интернет-магазина.

Аноним Птн 15 Ноя 2013 11:17:41  #161 №335143 

>>335038
Среднетян из хохлостана.
http://lisavasya.deviantart.com/

!xnn2uE3AU. Птн 15 Ноя 2013 12:18:50  #162 №335148 

>>335143

Да, няшная.

Аноним Птн 15 Ноя 2013 15:41:58  #163 №335166 

>>335120
>грузить быстрее и независимо от базы
Либо отправить запрос в базу и узнать имя html документа, где эти данные лежат в файловой системе, а затем отправить клиенту 302-й редирект (не 301-й, т.к. это не жёсткий редирект, а простое сообщение о том, что данные физически лежат в другом месте), чтобы клиент их забрал -

- либо никак.

!xnn2uE3AU. Птн 15 Ноя 2013 15:45:41  #164 №335169 

>>335166

Что за наркоманство ты пишешь? Чтобы ускорить сайт на тяжелой CMS или вордпрессе, не нужны никакие самописные кривые системы на файлах.

Ставишь нгинкс, на нкинкс ставишь кеширование в мемкеш (к примеру), дописываешь костыль чтобы при постинге коммента/правке в админке кеш чистился, и твой сайт легко будет такой хайлоад держать, который самоделкиным с файлами и не снился.

Аноним Птн 15 Ноя 2013 16:07:36  #165 №335172 

>>335169
Дорого. У меня хостинг в "Зеноне", они сами зеркалируют сколько угодно файлов на какое-то количество зеркал, и отдают файлы с них. А чтобы поставить nginx и memcahce, надо... надо... иметь хоть какой-то доход от сайта, наверное! А у меня его нету.

!xnn2uE3AU. Птн 15 Ноя 2013 16:12:30  #166 №335174 

>>335172

И твое время на написание кривых неуправляемых велосипедов стоит меньше, чем нормальный хостинг? Ну ок, это хорошо для тебя, но я хочу предупредить, что для 99% анонов совет писать велосипеды только вреден и им с точки зрения затрат проще поставить готовую CMS и мемкеш.

Если тебе нужен статический сайт на файлах без БД, не надо писать код, ты можешь сделать так:

- найти и заюзать программу-генератор статических сайтов (вроде бы фронтпейдж так умеет, рисуешь в нем сайт а он генерирует HTML)

- сделать на локалхосте сайт на любой CMS, какой-нибудь программой типа супер-пупер-сайт-даунлоадер скачать его в папку в виде кучи HTML файлов и их выложить на хостинг. При обновлении повторить.

!xnn2uE3AU. Птн 15 Ноя 2013 16:14:28  #167 №335175 

>>335172

Насчет генераторов сайтов: тут их много: http://habrahabr.ru/post/93499/

Аноним Птн 15 Ноя 2013 16:19:40  #168 №335177 

>>335174
>> фронтпейдж

Аноним Птн 15 Ноя 2013 18:57:54  #169 №335216 

>>335120
>>335140
Анон, а если я хочу велосипед? База есть, просто я предпочитаю нагрузку на диск нагрузке на базу. Скорость постинга в тысячу раз реже скорости чтения.

Аноним Птн 15 Ноя 2013 19:02:43  #170 №335218 

>>335216
Аноны предпочитают нагрузку на память нагрузке на диск (даже те, кто предпочитает нагрузку на диск нагрузке на базу), такие дела.

Аноним Птн 15 Ноя 2013 19:24:30  #171 №335222 

Что можешь посоветовать в обучение в дальнейшим ?
Имеется основная база(без ООП) со знаниемя mysql, etc.

!xnn2uE3AU. Птн 15 Ноя 2013 19:38:23  #172 №335225 

>>335222

ООП и фреймворки, они везде нужны.

Также, научиться HTML/CSS/JS, не на уровне крутого фронтендщика, а на базовом, уметь что-то поправить.

!xnn2uE3AU. Птн 15 Ноя 2013 19:40:12  #173 №335226 

>>335216

Тогда используй генератор статических сайтов или разверни сайт на локалхосте и сохрани его в HTML. И эти файлы копируй на хостинг — нагрузка будет только на диск, хостить можно хоть на юкозе, PHP не нужен.

Аноним Птн 15 Ноя 2013 21:34:54  #174 №335257 

Если @ - это плохо, то как можно изящно заменить
<input type='text' value="<[email protected]$_POST['foo']>">
в форме, так чтобы если валидация не пройдена значения там сохранялись?
Или в готовом варианте просто выключить эти нотисы?

!xnn2uE3AU. Птн 15 Ноя 2013 21:38:25  #175 №335260 

>>335257

Использовать @ — плохо
Выключать нотисы — дважды плохо

Правильное решение: сделай функцию post('foo', 'defaultValue') или сразу post('foo')

Алсо не забудь про экранирование:

<?= htmlspecialchars(post('foo')) ?>

Паста про экранирование и XSS: https://gist.github.com/anonymous/52adda0113428b274c64

Аноним Птн 15 Ноя 2013 22:16:37  #176 №335275 

>>335225
Какие фреймворки можешь посоветовать ?

!xnn2uE3AU. Птн 15 Ноя 2013 22:31:11  #177 №335279 

>>335275

Yii, Symfony 2

Аноним Суб 16 Ноя 2013 07:53:23  #178 №335318 

На словах ты Лев Толстой
не могу понять как решать эту задачку,halp

Аноним Суб 16 Ноя 2013 11:10:59  #179 №335327 

Задачка про школьника и айфон. Скажем, я выполнил задание, но решил пойти дальше и подсчитать сколько школьнику пришлось переплатить. Т.е. надо посчитать разницу между $totalPayment и суммой заёма = 40000. Я не смог придумать ничего умнее, чем создать новую переменную $loan и присвоить ей значение 40000 (4-ая строчка). А как можно это сделать не засоряя пространство имен лишней переменной? В каждой итерации цикла мы увеличиваем $currentBalance, а как можно обратиться к первоначальному значению, не создавая новую переменную?

http://codepad.org/1oi7ksFd

Аноним Суб 16 Ноя 2013 11:19:27  #180 №335329 

Задачка про школьника и айфон. Скажем, я выполнил задание, но решил пойти дальше и подсчитать сколько школьнику пришлось переплатить. Т.е. надо посчитать разницу между $totalPayment и суммой заёма = 40000. Я не смог придумать ничего умнее, чем создать новую переменную $loan и присвоить ей значение 40000 (4-ая строчка). А как можно это сделать не засоряя пространство имен лишней переменной? В каждой итерации цикла мы увеличиваем $creditBalance, а как можно обратиться к первоначальному значению, не создавая новую переменную?

http://codepad.org/1oi7ksFd

Аноним Суб 16 Ноя 2013 11:47:55  #181 №335331 

http://codepad.org/5rIZvMMa

Правильно ли я использую префиксный декремент? Или он тут не нужен? Ведь сначала увеличивается сумма на счету, а потом выполняется инкрементирование $i++. В следующий раз условие цикла не выполняется, но $i то уже увеличилось на единицу.

Аноним Суб 16 Ноя 2013 13:37:44  #182 №335336 

Анон, а научи меня в mysql! Всегда пользовался двумя типами полей, никогда не заморачивался с индексами, транзакциями, связями таблиц, что там еще есть страшного, вообще не знаю, зачем нужна половина настроек phpmyadmin - тем более не представляю, логические поля делаю целочисленными с длиной 1, с перечислениями вообще не разбирался, с типами таблиц тем более. Какая есть годнота на русском языке по этой теме? Чтобы от и до желательно, как, где, почему, а главное, что это даст (желательно иметь подробную книгу с разбором принципов, может даже реляционной модели вообще, но при этом чтобы был также упор на объяснение, зачем это все нужно и что это нам даст. Это - каждый конкретный случай).
>>335327
какая няшка, я бы проткнул ее своей пикой. Только современная заколка и низ штанов в ноль портит впечатление. Косплеит кого-то? И еще вопрос: меч пластмассовый? Если нет, то как она его держит так легко своей хлипкой ручкой, если он весит не меньше грамм 900, а балансом ему, по всей видимости, выступает гарда?

!xnn2uE3AU. Суб 16 Ноя 2013 15:48:48  #183 №335349 

>>335318

Берешь первый массив слов. C помощью mt_rand генерируешь число от 0 до (число элементов - 1). Потом берешь элемент с индексом, равным этому числу и таким образом получаешь случайное слово из массива.

Так же делаешь и с остальными массивами.

Потом из слов собираешь строчки.

Аноним Суб 16 Ноя 2013 16:00:22  #184 №335351 

>>335336
> Косплеит кого-то?
Ути какой ньюфажик

!xnn2uE3AU. Суб 16 Ноя 2013 16:04:08  #185 №335352 

>>335327

> А как можно это сделать не засоряя пространство имен лишней переменной?
Одна переменная ничего не решает. Так что засоряй, и не заморачивайся. Вместо того, чтобы думать как убрать одну переменную, лучше думать, как убрать десяток лишних строчек из программы.

Тем более, у тебя программа на 40 строчек. «Засорение пространства имен» опасно в огромных программах, так как можно случайно сделать новую переменную, которая совпадет с какой-то уже существующей и перезаписать ее значение, а у тебя такой проблемы нет.

Код как-то выглядит усложненно. Я проверил, программа считает все верно, но код лучше упростить:

switch ... case из 2 вариатов можно заменить if или, что еще короче, тернарным оператором ( http://php.net/manual/ru/language.operators.comparison.php ):

echo ($years != 1) ? "$years лет" : "$years год";

switch используют когда вариантов не 2, а много.

Замечу, что для числа 21 твой код напишет «21 лет», а по-русски будет «21 год».

> if ( floor($month/12) >= 1) {
Можно написать if ($years >= 1) зачем копипастить?

> $last = (($creditBalance * $percent + $servicePayment) < $monthlyPayment);
> $lastPayment = $creditBalance * $percent + $servicePayment;
> $creditBalance = ( $creditBalance * $percent ) + $servicePayment - $monthlyPayment;

Это копипаста, копипаста — зло. Лучше бы ты один раз посчитал и положил в переменную, а не копипастил формулы.

Но вообще, неплохо сделано, программа считает, да еще и числа пытается склонять.

!xnn2uE3AU. Суб 16 Ноя 2013 16:11:10  #186 №335355 

>>335331

Нехорошо, так как приходиится тупить и вспоминать, в ккаком порядке это считается. Надо писать так, чтобы порядок был очевиден:

$i--;
$age += $i;

Код должен быть читабельным и понятным в первую очередь, чтобы кто-то мог взглянуть и за секунду понять как он работает, а не расшифровывать его.

> В следующий раз условие цикла не выполняется, но $i то уже увеличилось на единицу.
Можно просто поставить $age++ внутрь цикла — тогда возраст будет расти только пока работает цикл.

Алсо, выравнивание у тебя как-то разъехалось, все криво. Попробуй писать код в редакторе типа Sublime или Notepad++ или ideone.com, там при переходе на новую строку пробелы не теряются. Или пропускай код через phpformatter.com, вот что получается:


<?php
/*W5.2 Некто кладет в банк 10000 р. Банк начисляет 10% годовых (то есть, каждый год на счету
становится на 10% больше, чем в прошлом году). Напиши программу, считающую, через сколько лет
в банке будет миллион? Сколько лет будет этому некто? Доживет ли некто до этого дня, если сегодня
ему 16 лет? */

$dep = 10000;
$rate = 1.1;
$age = 16;

for ($i = 1; $dep < 1000000; $i++) {
$dep *= $rate;
}
$age += --$i;
echo "$i years passed. \n";
if ($age <= 100) {
echo "The man will be $age - He'll probably be still alive.";
} else {
echo "The man would be $age - Most likely he won't make it...";
}
?>


!xnn2uE3AU. Суб 16 Ноя 2013 16:22:03  #187 №335356 

>>335336

На русском мало что есть. Есть вот это:

http://www.mysql.ru/docs/
http://www.mysql.ru/docs/mysql-man-4.0-ru/

— но там все не очень новое. Но транзакции и индексы там есть.

Индексы нужны ради повышения производительности. Поиск записи по индексы — быстрый, без индекса MySQL перебирает всю таблицу. Джойнить таблицы без индексов — вообще кошмар.

Про оптимизацию и производительность можно почитать тут: https://www.google.ru/search?client=opera&rls=en-GB&q=mysql+exmplain+%D0%B8%D0%BD%D0%B4%D0%B5%D0%BA%D1%81%D1%8B&sourceid=opera&ie=utf-8&oe=utf-8&channel=suggest

Транзакции нужны ради обеспечения целостности. Пример — банк, Вася переводит деньги Пете, банк вычел деньги с Васиного счета, и в этот момент отключилось питание. Чтобы деньги не исчезли, нужно было использовать транзакцию. Подробнее:

http://ru.wikipedia.org/wiki/Транзакция_(информатика)
http://habrahabr.ru/post/135217/
http://www.mysql.ru/docs/man/ANSI_diff_Transactions.html

!xnn2uE3AU. Суб 16 Ноя 2013 16:36:08  #188 №335363 

>>335336

Насчет типов полей и вещей, которые стоит знать:

ENUM — позволяет задать значением поля только один из нескольких вариантов. Профит: защищает от ошибок (если случайно попытаться вставить неправиьное значение), плюс сразу видно какие значения могут быть. Пример использования: статус заказа в мазазине:

status ENUM('new', 'paid', 'cancelled', 'sent', 'completed') NOT NULL

DECIMAL — тип с фиксированной точностью. В отличие от FLOAT/DOUBLE, которые приближенные и могут терять знаки после запятой, DECIMAL хранит заданное число знаков. Используется например, для хранения суммы денег.

DATE, TIME, DATETIME, TIMESTAMP — хранят дату/время.

NULL — в БД NULL значит «неизвестно». Например, возраст пользователя неизвестен. Соответственно, все операции с NULL это учитывают: NULL + 5 тоже дает в итоге NULL (5 + неизвестное число дает неизвестное число), сравнение (NULL == NULL) возвращает ложь, чтобы проеврить равно ли поле NULL надо использовать ISNULL(x). http://ru.wikipedia.org/wiki/NULL_(SQL)

> логические поля делаю целочисленными с длиной 1
В MySQL по моему есть BOOL, но он равносилен TINYINT

VARCHAR(N), TEXT, MEDIUMTEXT, LONGTEXT — разница в том, что в VARCHAR органичение на N симовов и он хранится в ряду с другими данными,а у TEXT — 65535 символов и он хранится отдельно. MEDIUMTEXT и LONGTEXT позволяют хранить больше 65535 символов.

Связи таблиц — полезная вещь. Не позволяют, например, удалить запись на которую ссылкаются другие записи (или же позволяют удалить, но при этом удалить и все ссылающиеся записи). Неплохо защищают от ошибок.

В общем, попробуй прочесть мануал и посмотри, что из перечисленного можно использовать.


Про реляционные отношения, надо в первую очередь разобраться с нормализацией ( http://club.shelek.ru/viewart.php?id=311 ) и денормализацией, отношениями один-к-одному, один-ко-многим, многие-ко-многим. Нормализация нужна для устранения избыточности, денормализация — прием, применяемый ради повышения производительности.

Ну и наконец, есть еще такая тема, как хранение иерархических данных в БД (например, категории товаров или древовидные комментарии). По ней у меня есть паста: https://gist.github.com/anonymous/005304b65600a3889ee4

!xnn2uE3AU. Суб 16 Ноя 2013 16:38:43  #189 №335364 

>>335336

А, и еще есть такая вещь как UNIQUE INDEX. С помощью уникального индекса можно запретить вставлять в таблицу одинаковые значения (например, 2 пользователей с одинаковым логином).

sageАноним Суб 16 Ноя 2013 19:08:28  #190 №335388 

Аноны. Вопрос. Как сделать так - Echo запрос ввода данных, пауза, пока данные не введут и не нажмут Enter, запрос других данных, снова пауза пока не введут и не нажмут Enter. Так около 4х раз, И УЖЕ ПОСЛЕ - выполнение скрипта дальше. Помогите?
Это все реализовываю в виде консольного скрипта.
Можно сделать с формами, но мне так не нужно.

Аноним Суб 16 Ноя 2013 19:33:32  #191 №335398 

доброанон, помоги
Почему может не проходить запрос вида
UPDATE table SET param1='$param1', time=$time WHERE param2='$param2' AND param3='$param3'
пробовал играться со скобками у AND, пробовал ставить-убирать кавычки - толку никакого, запрос просто не проходит, при этом ошибки не выдается никакой. Названия таблицы, полей правильные.
Попытка спросить о причинах ошибки у mysql_error($result) ничем не заканчивается, он говорит, что ему передано логическое значение, когда он хотел получить ресурс. Попытка распечатать $result дает нихера. Перед этим с той же базой и почти теми же параметрами SELECT проходит спокойно и без ошибок. Практически такой же код с UPDATE раньше с другой базой тоже работал прекрасно.

!xnn2uE3AU. Суб 16 Ноя 2013 19:38:14  #192 №335400 

>>335388

Очень просто.

1) Открываем поток стандартного ввода (stdin, то есть поток данных с клавиатуры) на чтение и сохраняем полученный дескриптор потока в $fd:

$fd = fopen('php://stdin', 'r');

Мануал: http://php.net/manual/en/function.fopen.php
http://www.php.net/manual/ru/wrappers.php.php
http://php.net/manual/ru/features.commandline.php

2) читаем из открытого потока одну строку (любые символы + Enter):

$line = fgets($fd);

В $line будет введенная строка + символ \n который можно отрезать с помощью rtrim().

3) Наверняка тебе захочется проверять то, что ввел пользователь, и просить ввести повторно при ошибке. Ок, используй цикл do ... while(). Код думаю ты и сам можешь написать.

4) Наверняка, тебе захочется улучшить возможности ввода. Например, сделать автодополнение по нажатию Tab, чтобы работали стрелки и редактирование или историю с доставанием ранее введенных данных стрелками ↑↓ и оиском по Ctrl + R как в настоящей командой строке. Ну что, любители windows тут, увы, проходят мимо, а любители linux или mac могут использовать расширение Readline: http://www.php.net/manual/ru/ref.readline.php

!xnn2uE3AU. Суб 16 Ноя 2013 19:45:26  #193 №335402 

>>335400

Наконец, расскажу еще про одну штуку, которая есть в линуксе. Допустим, тебе попалась консольная программа, которая не поддерживает редактирование командной строки и историю команд. Печалька. Не беда, можно запустить ее через команду rlwrap, которая добавит эти возможности.

> Почему может не проходить запрос вида
Включи display_errors, если это не боевой сервер, если боевой, ищи сообщение об ошибке в логах.

> mysql_error($result) ничем не заканчивается
Туда надо передавать не $result, а соединение $conn, которое возвращает mysql_conneect:

$conn = mysql_connect(....)

Или, можно вообще ничего не передавать, тогда она сама возьмет текущее соединение.


Алсо, дам тебе еще 2 совета:

1) Функции mysql_* устарели много лет назад. Не знаю, где ты их умудрился откопать и выучить, сейчас все работают с базой через PDO

2) Нельзя подставлять переменные прямо в запрос, это веет к инъекциям. Правильно — использовать плейсхолдеры в PDO или библиотеке для рбаоты с БД:

$title = 'PHP%';
$author = 'Bobi%';
// query
$sql = "SELECT * FROM books WHERE title like :title AND author like :author ";
$q = $conn->prepare($sql);
$q->execute(array(':author'=>$author,
':title'=>$title));

Аноним Суб 16 Ноя 2013 19:47:27  #194 №335403 

>>335363
не пугайте народ

Enum внутри все равно преобразуется либо к tinyint либо к int.
Даты настолько разные, что ОБЯзательно читать мануал по каждой, т.к. скорость поиска разница в сотни раз.
И ОБЯзательно помнить, что поле NULL занимает дополнительный байт и при обработке полей с нулами применяются дополнительные просчеты.
varchar запомните что это ДИНАМИЧЕское поле, которое хранит вначале байт длинны, это очень сильно отразится на больших обьемах поиском в этих полях, поля постоянной длины намного быстрей работают.

Лучше все запомните пару важный правил
1) стремиться делать выборки только по индексу и только по числу (инт, бигинт)
2) избегайте Null-ов и динамических полей насколько возможно

sageАноним Суб 16 Ноя 2013 19:51:37  #195 №335406 

>>335400
Огромное тебе спасибо ОПушка. Добра :3

!xnn2uE3AU. Суб 16 Ноя 2013 20:06:05  #196 №335415 

>>335398

Ты даешь дурные и неграмотные советы. Не слушайте этого анона.

> Enum внутри все равно преобразуется либо к tinyint либо к int.
Ну и круто, хранится он компактно числом, а в таблице мы видим понятные вещи вроде new|paid|cancelled, плюс MySQL не позволяет вставлять левые значения. Надо быть дурачком, чтобы вместо ENUM лепить какие-то свои кривые велосипеды.

> Даты настолько разные, что ОБЯзательно читать мануал по каждой, т.к. скорость поиска разница в сотни раз.
Это бред, насчет сотен раз. Даты стоит хранить как DATETIME хотя бы потому, что в этом случае они выводятся в нормальном виде и можно писать NOW() + INTERVAL 7 DAYS.

Насчет того, в каком виде хранится, написано тут: http://dev.mysql.com/doc/internals/en/date-and-time-data-type-representation.html

> TIMESTAMP
> 4 bytes, little endian

> DATETIME
> 8 bytes, little endian

Вполне норм. Какой смысл вместо стандартного способа хранения дат/времени придумывать свои кривые велосипеды? Так делают только школьники, которым в видеокурсе не рассказали про эти типы.

> это очень сильно отразится на больших обьемах поиском в этих полях, поля постоянной длины намного быстрей работают.
Для поиска нужен индекс, а индексу пофиг varchar у тебя или char, верно? Плюс, использование char увеличивает объем таблицы, так как если у тебя поле 200 символов, то эти 200 * (размер символа) байт хранятся в любом случае, таблица становится огромной, надо больше памяти, дисковых операций, и в итоге все может наоборот работать медленнее. Потому твой совет неграмотный. В одних ситуациях лучше одно, в других — другое.

Алсо, я еще видел, некоторые используют хеши для ускорения поиска по строке.

> И ОБЯзательно помнить, что поле NULL занимает дополнительный байт и при обработке полей с нулами применяются дополнительные просчеты.
И пофиг. Это ничего не меняет. База тормозит не из-за «дополнительных просчетов», а из-за дисковых операций.

> Лучше все запомните пару важный правил
> 1) стремиться делать выборки только по индексу и только по числу (инт, бигинт)
> 2) избегайте Null-ов и динамических полей насколько возможно

Лучше изучить, как работают индексы и научиться пользоваться командой EXPLAIN, а не применять такие советы бездумно. Научиться смотреть статистику использования разных буферов и делать выводы.

Аноним Суб 16 Ноя 2013 20:31:11  #197 №335417 

>>335415
ооо вижу ты совсем не знаком с приличными проектами на мускуле,
где ты увидел что предлагают использовать свои форматы енума?
чет я вижу только предложения использовать tinyint как вариант и не более...
С датами сразу вижу ты не работал, когда наберешь хотябы 5-10 миллиончиков, узнаешь насколько DATETIME медленней TIMESTAMP-а,
и опять же ГДЕ вы ВИДИТЕ изобретателя велосипеда?
было только предложено прочитать какая именно дата подойдет именно в вашем случае.

Для начинающих нулы может и пофиг, потом когда вы наберете только истории хотябы на 400гб, узнаете что такое нулы которые вам не нужны вообще. Если вам нужен нулл то спорить нечего, но когда пишут
time int defaul 0
то подумайте зачем вам нул который тут не нужен и будет только мешаться.

И еще открою тебе тайну, раз не знаешь, индексы по строке индексируют только 1 символ, а представь когда будет 5млн записей по 1символу, вот тут научитесь пользоваться unsignet int not null и хеши по b-tree ...

и для выводов по запросу, как раз нужно вспоминать про эти 2 важных правила...

Аноним Суб 16 Ноя 2013 21:52:15  #198 №335425 

Привет, парни. Я анон, делавший борду в прошлых двух тредах, решил прикрутить к ней систему пользователей. Типа как у людей: админы, модераторы, абу, все дела.
Идея, я ёё нашел где-то на стэковерфлоу, следующая:
пользователь заходит в систему, его имя и, возможно, ещё какие-то данные пишутся в сессию. Если он при входе отметил пункт "запомнить меня", то дополнительно пишутся куки с именем и случайно сгенерированным при регистрации токеном. В следующий раз проверяется наличие кук. если имя и токен совпадают с указаными в таблице происходит авторизация.
ПХП-анон, можешь посмотреть мой код? Там все по-сути происходит с в трех файлах - Application/Model/User.php,
Application/Controller/User.php и Application/Core/ Auth.php

Аноним Суб 16 Ноя 2013 21:53:49  #199 №335426 

>>335425
Ах да, ссылку забыл:
https://github.com/melanchthon/board

sageАноним Суб 16 Ноя 2013 22:17:17  #200 №335437 

>>335400
>дескриптор потока
Пожалуйста объясни в двух словах или дай ссылочку где почитать, что это? Погуглил и не много не понял, а может и не то нагуглил. Спасибо :3

Все-тот-же-анон

!xnn2uE3AU. Суб 16 Ноя 2013 22:46:48  #201 №335444 

>>335437

Поток — в данном случае значит «открытый файл». Дескриптор значит «идентификатор».

Когда ты открываешь файл с помощью fopen, ты получаешь (если все ок) дескриптор потока — специальное значение типа resource, которое нужно сохранить в переменную:

$fd = fopen('php://stdin', 'r');

Этот дескриптор передается в функции работы с файлами, например, fread, fgets, fwrite, чтобы указать им, с каким потоком работать. без дескриптора нельзя, так как непонятно откуда именно ты хочешь читать данные. Ведь кроме стандартого ввода (то есть клавиатуры), данные можно читать из файла, из сетевого сокета, откуда угодно.
Для начала почитай мануал:

http://www.php.net/manual/ru/function.fopen.php

Кроме fopen() есть еще fclose(), которая закрывает файл, когда он тебе больше не нужен, но для чтения с клавиатуры он не нужен.

Ты можешь спросить, я же хочу вводить данные с клавиатуры, при чем тут файлы и файловые дескрипторы? Отвечаю, в linux такая концепция, что данные с клавиатуры можно читать теми же функциями, что и данные из файла или сетевого соединения.

Вот например, как можно прочитать строку из файла:

$fd = fopen('file.txt', 'r');
$line = fgets($fd);

Как видишь, код точно такой же, только первый параметр у fopen поменялся. Линуксу (и PHP который во многом взялего идеологию) без разницы откуда читать/писать данные, это делается одной и той же командой.

Кстати, в PHP этот функционал расширили еще дальше. С помощью stream wrappers ты можешь через fopen не только открыть файл, но и читать данные из TCP-, HTTP-соединения, gzip-архива и много чего еще.

!xnn2uE3AU. Вск 17 Ноя 2013 00:27:44  #202 №335456 

>>335425

О, пользователи — это хорошо. Но тут немало подводных камней.

Начнем с сессий. У сессий в PHP есть подвохи:

- время жизни (кстати, хороший вопрос для заваливания новичков и даже опытных программистов на собеседовании). Знаешь ли ты, как и когда удаляются сессии? Вообще, это зависит от ОС и настроек php.ini. В дебиане, например, сессии удаляет крон, котрый запускается, по моему раз в 15 минут и удаляет все файлы сессий, в которые не велась запись в течение 24 минут. Это значит, что если ты откроешь форму добавления поста, потом полчасика позанимаешься чем-нибудь другим, потом все-такие напишешь пост, ты можешь оказаться разлогиненным.

- блокировка. По умолчанию, сессия блокируется при открытии, и если второй процесс пытается открыть ту же сессию, он ждет пока первый не закроет ее. Это может быть актуально там, где например активно используются AJAX-запросы — они будут блокировать друг друга:

http://habrahabr.ru/company/bitrix/blog/179803/
http://habrahabr.ru/post/62412/
http://habrahabr.ru/post/182352/

Конечно, можно похимичить с настройками PHP, но лучше, по моему, особо не полагаться на сессии. Например, в случае авторизации, можно выставлять куки в любом случае — только если не выбрано «запомнить меня» ставить сессионные куки (куки, у которых не вставлено время жизни и которые удаляются при закрытии окна браузера).

Теперь про куки. У кук есть полезный флаг — httpOnly. Куки, отмеченные этим флагом, недоступны яваскриптам на странице и их нельзя угнать с помощью уязвимости XSS. Думаю, стоит этот флаг использовать: http://www.php.net/manual/ru/function.setcookie.php

Теперь про удобство пользования твоей регистрацией. Оно, по моему, ниже нуля:

- при ошибке в форме логина/регистрации поля сбрасываются, надо вводить данные второй раз. Зачем?
- после регистрации, надо же, я могу войти на сайт с помощью формы логина, то есть по второму разу ввести логин и пароль. Внимание, вопрос: почему я должен это делать?

Посмотри, как сделана регистрация в фейсбуке, твитторе. Там ничего подобного нет, после регистрации ты сразу же оказывешься залогиненным.

- какие-то дурацкие требования к паролю. Минимум 8 символов, да еще и должны быть цифры. То есть giYhdi — плохой пароль, а 12345678 — хороший? Причем ведь об этом еще никто не предупреждает заранее, ввел gYuhdy — фиг тебе, вводи все заново.
- нельзя войти через фейсбук, твиттор, одной кнопкой, надо регистрироваться.

Также, хорошо бы как-то отличать посты зарегистрированных пользователей от анонимов. Можно, например, запретить анонимам вводить имя в форме постинга или же выделять цветом имена залогиненных юзеров. Ну и вообще, тем, кто прошел регистрацию, надо давать какие-то няшки и преимущества, иначе зачем это делать? Тем, кто входит через соцсети, надо давать няшки вдвойне, так как от таких пользователей мы получаем максимум ценных данных.

Теперь про безопасность. Плохо:

Токен пользователя один и никогда не меняется. Спер токен из кук, например, трояном, и заходи когда угодно из любой страны
Нет привязки кук к IP. Здесь есть как недостатки, так и положительные стороны. Привязка хороша тем, что стыренным токеном не воспользоваться с другого компьютера с другим IP. Недостатки:

- если юзер с айпадом выходит из дома (переключаясь с WiFi на 3G), он разлогинивается
- у мобильных операторов и операторов с динамическим IP адрес может меняться (но при этом он обычно из той же подсети, первые 2-3 числа в IP совпадают)

Потому, привязывать, или нет — сложный вопрос. Соцсети вроде вконтакте и платежные системы обычно при входе с другого IP начинают просить либо перезалогиниться, либо ввести последние цифры номера телефона.

Защита от подбора паролей

У тебя ее нет. Можно хоть в 100 потоков перебирать пароли. Обычно делают по другому: если с одного IP больше нескольких ошибок входа за последние N минут, показываем капчу.

!xnn2uE3AU. Вск 17 Ноя 2013 01:06:15  #203 №335464 

>>335425

Теперь про CSRF.

У тебя можно легко принудительно разлогинить юзера: заманиваем на свою страницу (например, постим ссылку с подписью «смотрите какие няши! http:// t . co / 12345678»), а оттуда редиректим их на /user/logout .

А можно на этой же странице разместить невидимую форму постинга, которая заполнена и автоматически сабмитится при заходе на страницу, и юзер от своего имени публикует пост (вроде я ньюфаг на 30% проверь насколько ты ньюфаг). Причем в пост можно поместить ссылку, по которой будут переходить другие.

Это и называется уязвимость CSRF: http://intsystem.org/768/learn-about-csrf-intro/

Как защититься от CSRF? Просто: генерируем уникальный токен, зависящий например от IP адреса (ну или лучше, от адреса подсети). Добавляем его в формы невидимым полем и в ссылки вроде logout. И проверяем его наличие. Злоумышленник не может угадать значение токена и не может подставить его в свою форму.

Не стоит полагаться на проверку Referer: в стандарте написано, что браузер не обязан его отправлять, антивирусы, фаерволлы, расширения могут его вырезать или менять, он может быть отключен в браузере, и есть способы отправки запросов с обнулением referer.

Теперь по коду

> $hash = md5($salt.$pass);
О, это хорошо, что ты используешь соль. Потому что для md5 без соли существуют готовые радужные таблицы: https://www.freerainbowtables.com/en/tables2/ — обрати внимание, например таблица md5_mixalpha-numeric#1-9 расшифровывает пароли из букв и цифр до 9 символов при весе в терабайт. И с ростом мощностей компьютеров их будет расшифровать еще проще.

Обрати внимание, в PHP5.5 появились стандартные функции шифрования паролей: http://habrahabr.ru/post/194972/ — со временем стоит отказаться от велосипедов с md5 и переходить на них.

> ADD CONSTRAINT comment_ibfk_1 FOREIGN KEY (post_id) REFERENCES post (id);
Зачем удалил из дампа?

> $user->name = $_POST["name"];
Лучше бы сделать через isset($_POST["name"]) ? $_POST["name"] : '' или через функцию, а то кто-нибудь будет слать пустые пост-запросы и забивать логи варнингами о несуществующем значении массива. То же самое и с $name = $_COOKIE['name']; — куки может и не быть.

> $STH->bindValue(":name",$user->name);
> $STH->bindValue(":pass",$user->pass);

Можно передавать массив в execute:

$STH->execute(array(
':name' => $user->name,
....
));

> userExists
Лучше назвать getUserIfExists(), названия функций надо начинать с глагола.

> checkPass($pass,$realHash,$salt)
Эту функцию, кстати, можно перенести и в класс Core_User, оставив только параметр $pass

> if (strlen($user->name)<5)
Надо использовать mb_strlen

> <span>Добро пожаловать, <?=$auth->getName()?>! </span>
htmlspecialchars бы не помешал.

У тебя в коде есть поиск пользователя по name, а индекса на первые N символов name нет, нехорошо, MySQL'у придется всю таблицу обходить чтобы найти пользователя. Нет проверки уникальности логина, можно зарегистрировать несколько пользователей с одинаковым или отличающимся только регистром букв логином. Нет ограничения и проверки на максимальную длину логина. Нет проверки на разрешенные в логине символы, хотя может это и хорошо. Нет защиты от регистрации под логином «администратор сайта» или «модератор».

У данных, ввденных в форму, надо делать trim() так как пользователь может нечаянно впечатать пробел в начале или конце и не заметить.

Аноним Вск 17 Ноя 2013 11:37:03  #204 №335507 

про палиндромы решил вот

http://ideone.com/QrVm4z

Аноним Вск 17 Ноя 2013 13:56:45  #205 №335523 

спасибо за задачки, Опушка

!xnn2uE3AU. Вск 17 Ноя 2013 16:16:27  #206 №335540 

>>335507

Молодец, программа работает правильно. Едиснтвенное, вместо этого:

($lower == $reversed) ? $result = "Это палиндром" : $result = "Не палиндром";

Лучше нормально использовать if/else (ради читабельности). Тернарный оператор обычно используют как выражение, а не как отдельную команду. Ну или можно переписать это в виде:

$result = ($lower == $reversed) ? "Это палиндром" : "Не палиндром";

Так сразу видно, что это команда присваивающая переменной result какое-то значение.

Аноним Вск 17 Ноя 2013 19:16:28  #207 №335580 

Присоединяюсь к вашему клубу. Вот мое решение задачи про айфон в кредит
http://codepad.org/fxTTiwWS

Аноним Вск 17 Ноя 2013 19:24:46  #208 №335582 

>>335580
Мое решение задачи про банк в догонку http://ideone.com/rvMBeo

!xnn2uE3AU. Вск 17 Ноя 2013 20:26:56  #209 №335592 

>>335580

Ну здравствуй. Айфон в кредит — все решено верно, хорошо, у анонов обычно эта задача проблемы вызывает. Задача про банк — считает верно, но не пишет сколько же лет анону будет в заветный день.

Аноним Вск 17 Ноя 2013 20:50:55  #210 №335597 

Проясните за die/exit, почему-то вижу их буквально в каждом коде во всех местах, хотя не понимаю что такого полезного в этих операторах, кроме сообщения про ошибки. Где надо использовать?

!xnn2uE3AU. Вск 17 Ноя 2013 21:44:08  #211 №335599 

>>335597

В консольном скрипте, например, при ошибке. Или чтобы завершить выполнение скрипта, не доходя до конца. Если не видишь ничего полезного — можешь не использовать.

Аноним Пнд 18 Ноя 2013 10:27:49  #212 №335682 

>>335597
>рождённый, чтобы умирать

!xnn2uE3AU. Пнд 18 Ноя 2013 10:45:09  #213 №335685 

>>335682

Это же отлично:

- если на дохлосайт полдня никто не заходит, приложение не запущено и не ест память сервера. Это позволяет хостить тысячи малопосещаемых сайтов на одном сервере. А теперь попробуй-ка захостить 1000 ява- или питон-приложений.

- поскольку скрипт умирает, то не надо тратить время на отладку, например, утечек памяти (например, когда приложение добавляет данные в кеш без ограничений и в итоге падает). Это позволяет использовать более дешевых и менее квалифицированных специалистов.

Аноним Пнд 18 Ноя 2013 12:13:34  #214 №335690 

>>335349
http://ideone.com/pNXsox как оно?

!xnn2uE3AU. Пнд 18 Ноя 2013 12:20:32  #215 №335693 

>>335690

Все верно, только вот strtr($word1,$st1); — это ты наверно забыл убрать, от этой команды ошибки идут из-за неопределенных переменных.

Аноним Пнд 18 Ноя 2013 12:37:24  #216 №335704 

>>335693
ага.
>(число элементов - 1)
а зачем -1.
хард моде: переделай под стиль Маяковского
у этого ведь нет програмного решения?

!xnn2uE3AU. Пнд 18 Ноя 2013 13:27:57  #217 №335724 

>>335704

> а зачем -1.
Сделай массив из 5 элементов, например, сделай var_dump($array) и посмотри какие индексы у элементов. В массиве из 5 элементов нет элемента с индексом 5, они нумеруются с 0 до 4.

> у этого ведь нет програмного решения?
Нет, наверно. Надо поменять исходные слова на более подходящие (жесткие и решительные) и схему предложения, у Маяковского обычно стихи всякими столбиками и треугольниками идут.

Аноним Пнд 18 Ноя 2013 16:20:40  #218 №335761 

Оп, я правильно понял суть первой задачи на регулярные выражения или тут надо было просто проверить строку на соответствие одному шаблону? (Я подумал, что шаблон, соответствующий требованиям задачи получился бы довольно громоздким. Или нет?).

http://ideone.com/ixAx6y


!xnn2uE3AU. Пнд 18 Ноя 2013 16:48:14  #219 №335764 

>>335761

Ну вообще не такой и громоздкий, если подумать. Это можно сделать одним preg_match. Но как у тебя, тоже работает.

Если ты хочешь удалить символы, то вместо preg_split + implode проще использовать preg_replace (или ее ты пока не изучил?) или strtr.

Аноним Пнд 18 Ноя 2013 16:59:11  #220 №335768 

>>335764
Ох, спасибо, совсем забыл про strtr. Я сегодня прочитал, что вообще предпочтительно пользоваться строковыми функциями вместо регулярных выражений там, где это возможно, т.к. они быстрей.

Аноним Пнд 18 Ноя 2013 19:30:24  #221 №335827 

Как лучше хранить много картинок, например, обложек книг для каталога?
1. Все в одной папке, с рандомными именами типа be677264d0_poster.png, be677264d0_thumb.png + отдельное поле в базе с именем.
2. Каждую в отдельной папке вида /books/.$title/ со стандартными именами типа poster.png, thumb.png. Поле в базе при этом не нужно, проверки существования и генерации имен тоже.
Второй вариант выглядит намного изящнее, но нет ли каких-то подводных камней с производительностью из-за множества папок?

!xnn2uE3AU. Пнд 18 Ноя 2013 19:36:45  #222 №335830 

>>335827

> нет ли каких-то подводных камней с производительностью из-за множества папок?
Подводные камни есть когда в каталоге много файлов и ты пытаешься его открыть каким-нибудь файловым менеджером — тормозит.

Так что возможно лучше сделать каталог двухуровневым, с использованием id в имени, напрмиер:

/books/162/162354.png
/books/102/102500.png

Если не надо лезть в базу, это плюс.

Аноним Пнд 18 Ноя 2013 19:36:46  #223 №335831 

Есть переменная. В ней html текст.
В тексте абзацы, бр теги и картинки. Другое исключено (strip_tags же)

Мне надо сделать:
1. так, чтобы каждая картинка была выкачана в папку /images
2. Заменен путь этой картинки на локальный адрес

Я не прошу написать вместо меня, я прошу помочь и дать наводку на то, что именно гуглить и какие техгнологии надо использовать.

Пишу свой RSS ридер, обучаюсь.

!xnn2uE3AU. Пнд 18 Ноя 2013 19:38:35  #224 №335833 

>>335831

1) можно регулярками (preg_match_all, preg_replace) найти URL картинок и регулярками же заменить
2) можно загрузить HTML в DOM дерево (DomDocument::loadHtml) и в дереве искать все элементы IMG, после чего поменять им аттрибут src и преобразовать назад в HTML.


Аноним Пнд 18 Ноя 2013 19:39:36  #225 №335834 

>>335833

И еще, надо чтобы текст был гарантированно в utf-8, кодировка на входе может быть ЛЮБАЯ. Как сделать?

!xnn2uE3AU. Пнд 18 Ноя 2013 19:40:30  #226 №335835 

Питоняши и рубисты ! В ваших языках есть простой способ рекурсивного обхода дерева, с использованием какой-нибудь стандартной функции? Например, есть дерево каких-нибудь объектов, надо его обойти и с каждым что-нибудь сделать. Или посчитать сумму чего-нибудь.

Просто интересно, проще это чем в PHP или сложнее.

!xnn2uE3AU. Пнд 18 Ноя 2013 19:41:31  #227 №335837 

>>335834

Определяешь кодировку на входе (по заголовку Content-Type, тегу meta charset и другим правилам описанным в стандарте HTML) и преобразуешь в utf-8 через iconv()

Аноним Пнд 18 Ноя 2013 19:41:35  #228 №335838 

>>335833

а выкачать картинки как?

Т.е. мне надо гуглить регулярные и их учить, а по DOM что гуглить?

Аноним Пнд 18 Ноя 2013 19:44:29  #229 №335842 

>>335837

на входе xml же с RSS

!xnn2uE3AU. Пнд 18 Ноя 2013 19:56:18  #230 №335845 

>>335842

В XML указана кодировка в первой строчке иначе это utf-8:

<?xml charset=.... ?> (или как-то так, погугли)

>>335838

любым из способов:

1) курл + самописный велосипед
2) file_get_contents('http://...')
3) Zend_Http
4) http://requests.ryanmccue.info/
5) Guzzle

> Т.е. мне надо гуглить регулярные и их учить, а по DOM что гуглить?

У меня есть урок по регуляркам: http://archive-ipq-co.narod.ru/l1/regexp.html
По DOM гугли «php работа с dom»

Я написал может не очень понятно, так что напиши если что-то не понял.

!xnn2uE3AU. Пнд 18 Ноя 2013 19:59:32  #231 №335847 

>>335842

Плюс, как я понимаю, если ты используешь DOM:

$dom = new DOMDocument('1.0', 'utf-8');
$dom->loadXml('....');

то он сам решает проблемы с кодировками. Мануал по DOM (большой): http://www.php.net/manual/ru/class.domdocument.php



Аноним Пнд 18 Ноя 2013 21:42:43  #232 №335909 

Оп запости решение второй задачи на регэкспы. часов пять пытаюсь решить нихуя не получается, уже вырубаюсь. Приду завтра с работы гляну.

Аноним Пнд 18 Ноя 2013 21:46:24  #233 №335910 

>>335845

Смотри, дружище.
xml имеет кодировку utf-8
Файл с php кодом тоже.
Беру из файла и пишу в бд. В бд - пикрелейтед.

utf8_encode() не помогает.
как решить эту проблему?

!xnn2uE3AU. Пнд 18 Ноя 2013 21:52:20  #234 №335912 

>>335910

Ну так может у тебя в БД через одно место кодировка выставлена? Ты запрос SET NANES utf8 при соединении с БД делаешь или надеешься на авось, что все само правильно выставится?

Также хочу спросить, что за криворукий инвалид сделал так, что при обновлении капчи вся страница блокируется??

Аноним Пнд 18 Ноя 2013 22:03:26  #235 №335919 

>>335912

Делаю

> $link = mysql_connect('localhost',$user, $pass) or die ('пиздец нахуй!'.mysql_error());
>mysql_query('SET NAMES UTF-8');

!xnn2uE3AU. Пнд 18 Ноя 2013 22:08:36  #236 №335923 

>>335919

Вроде бы SET NAMES utf8 без знака минус.

Аноним Пнд 18 Ноя 2013 22:22:10  #237 №335930 

ОП, помоги пожалуйста установить Apache+PHP+MySQL. Какие только дистрибутивы не попробовал, как только не делал, второй день уже не могу установить. Апач ставится, вбиваю в адр.строку локалхост, все хорошо. Все работает, включается, выключается. Устанавливаю PHP, тут и начинается весь геморрой. Ставится вроде все хорошо, но после перезапуска Апача он больше не включается. Пишет либо "Невозможно запустить, специфическая ошибка 1", либо выскакивает отчет об ошибке Майкрософта, что приложение завершило свою работу. Из конфига Апача убираю когда последние строки о подключении модуля php, то все норм становится, Апач запускается. Сколько искал, так не смог найти ответы. Подкинь пожалуйста проверенно рабочий софт, который не конфликтует между собой. Вроде все делаю по гайдам, но ничего не получается. Вот что попробовал последнее:
httpd-2.2.18-win32-x86-no_ssl-r2.msi
php-5.2.16-Win32-VC6-x86.msi
mysql-5.5.34-win32.msi
Шиндоус ХР, сервис пак 3.
До установки MySQL так и не добрался пока.

Аноним Пнд 18 Ноя 2013 22:28:08  #238 №335933 

>>335464
Про привязку к IP в-целом понятно. Но вот как привязать к подсети непонятно нихуя.
Смотри, насколько я понимаю IP-адрес состоит из двух частей: адрес подсети/адрес узла, аналогия - название улицы/номер дома. Адрес подсети можно высчитать из IP зная маску подсети - она для каждой подсети своя, я всё правильно понял?
Ну и собственно вопрос, я могу узнать айпи из $_SERVER['REMOTE_ADDR']? но как мне узнать из него собственно адрес самой подсети, не зная маски? Ткни носом, пожалйста, не могу разобраться.

Аноним Пнд 18 Ноя 2013 23:03:05  #239 №335960 

Спасибо большое ОП за уроки. Пару месяцов назад сделал почти все уроки кроме регулярок, но мне очень жаль, что нет уроков по mysql. Теперь начну с более практических уроков. Хочу написать сначала гостевою, а потом и форум...

Аноним Пнд 18 Ноя 2013 23:19:15  #240 №335976 

>>335930
Гугли wamp.

Аноним Пнд 18 Ноя 2013 23:28:32  #241 №335980 

>>335976
Нет, это что-то на уровне Денвера. Я сейчас смотрю специалиста, дошел до момента работы с базами данных, там идет работа из под командной строки. Денверский же MySQL настроен как-то по другому, или я пока не могу разобраться во всем этом из-за недостаточного уровня знаний. Уж лучше установить все как и у преподавателя, дабы не путаться и не ломать голову. Застопорился даже на моменте подключения к самой БД MySQL, решил установить все по отдельности, но уже два дня вместо занятий ломаю голову над установкой.

!xnn2uE3AU. Пнд 18 Ноя 2013 23:33:12  #242 №335984 

>>335933

Диапазоны IP адресов распределяет вроде бы IANA, она раздает большие блоки региональным реестрам, они выдают из них кусочки поменьше, и так далее. Наверно, эти реестры можно собрать, но это долго.

> она для каждой подсети своя, я всё правильно понял?
Верно. Маску можно конечно узнать через хуиз: http://whois7.ru/?q=8.8.8.8

NetRange: 8.8.8.0 - 8.8.8.255
CIDR: 8.8.8.0/24


Но во-первых, ты замучаешься это писать, во-вторых, whois-сервера забанят тебя за постоянные запросы. Тут надо иметь локальную базу, и искать по ней.

Ну или можно поступить проще: считать, подсетью первые 2 или 3 цифры IP адреса. Это будет неточно, но в большинстве случаев работать как нам надо.

!xnn2uE3AU. Пнд 18 Ноя 2013 23:47:48  #243 №335990 

>>335930

Версия Php совместима ли с апачем? Все ли пути и библиотеки прописаны, все ли в правильные папки разложено? Апач лучше брать с apachelounge.

Вот например: апач http://www.apachelounge.com/download/

Обрати внимание, Minimum system required: Windows 7 SP1, Windows 8 / 8.1, Windows Vista SP2, Windows Server 2008 R2 SP1, Windows Server 2012 / R2

XP не поддерживается, если у тебя XP бери чтонибудь постарее, например VC10 или VC9: http://www.apachelounge.com/download/win32/

Поскольку Апач собран с VC10, наверняка надо к нему с сайта майкрософт будет скачать Visual C redistributable 10 (ссылка на странице скачивания есть). Проверь, что версия x86/64 соответствует битности компа и ОС.

Потом идем качать PHP: http://windows.php.net/download/

Бери VC10 (лучше такой же как у апача!) или Vc9, thread safe (обязательно для апача под виндой), x64 или x86 в зависимости от битности компа.

Обрати внимание, Php 5.5 тоже требует минимум Windows 7. Раз у тебя XP, бери 5.4.

!xnn2uE3AU. Пнд 18 Ноя 2013 23:49:56  #244 №335993 

>>335930

Еще советы: если при запуске Апача с Php пишется «не найдена какая то библиотека попробуйте переустановить прилоежние» то это скорее всего у тебя какая-то папка важная не добалена в PATH. Добавь, не спеша перезагрузись и продолжай эксперименты.

Вот еще пасты, может помогут:

http://gist.github.com/anonymous/2dfa134fe20d9cf91bbe Как научиться пользоваться командной строкой
http://gist.github.com/anonymous/946f4f1830be3955fe17 Как установить Апач (старая)

!xnn2uE3AU. Пнд 18 Ноя 2013 23:57:44  #245 №335999 

>>335960

А что писать гостевую? У нас есть задачка «запрограммировать имиджборду», причем верстка уже готовая есть, смотри какая: https://github.com/codedokode/board-markup

Не хочешь попробовать?

Уровень: нужно знать PHP и SQL хотя бы немного
Цель: научиться писать приложения, а не простые скрипты, познакомиться с MVC, повысить практические навыки.

Данные хранятся в базе данных, например, MySQL. Схему БД (то есть список таблиц и полей) предлагаю придумать самостоятельно, считай это частью задания. Позже (если твой код заработает) мы будем тестировать твой код, насколько он хорошо справляется с нагрузкой, и возможно, менять схему БД, если будут проблемы.

Нужно использовать ООП.

Аноним Втр 19 Ноя 2013 00:01:05  #246 №336002 

>>335990
Да, версия совместима с Апачем. Библиотека для Апач2.2 имеется, PHP автоматически прописывает к ней путь, когда при установке указываю расположение httpd.conf. Я пробовал качать Апач с apachelounge, но так и не понял что они мне предлагают, так как вместо инсталятора скачались какие-то папки и пару файликов. Что с ними делать так и не понял.
Да, про поддержку старых и новых версий уже читал. На официальном сайте Апача говорят лучше качать Апач2.2, чтобы запустить его с VC6. Как же все запутано. Очень жаль, что на уроках в Специалисте не показали так сказать наглядную установку, а показали лишь на картиночках. А про не найденную библиотеку не писал, писал только про "Специфическую ошибку 1". Сколько гуглил - ответы были что мол был невнимателен, вместо одной папки в пути прописал другую, исправил и все заработало. 300 раз перепроверил, какие статьи только не попробовал, так и не получилось. Ладно, спасибо, ОП. Буду сносить ХР, поставлю семерку и буду пробовать на ней с более новыми сборками.

!xnn2uE3AU. Втр 19 Ноя 2013 00:10:39  #247 №336004 

>>336002

> так как вместо инсталятора скачались какие-то папки и пару файликов. Что с ними делать так и не понял.

Это и есть сборка апача. Там есть файл readme, в нем описано как устанавливать. Берешь и ручками ставишь, а как ты хотел, это софт для настоящих бородатых программистов, а не блондинок с айпадом. Кряки к играм небось ставить умеешь, а апач не можешь. Вот что написано в ридми:

|Install
|-------

|- Unzip the Apache24 folder to c:/Apache24 (that is the ServerRoot in the config).
распакуй и скопируй содержимое папки Apache24 например в c:\Apache24 или куда-нибудь еше.
| Default folder for your your webpages is DocumentRoot "c:/Apache24/htdocs"

| When you unzip to an other location, change ServerRoot in the httpd.conf,
| and change in httpd.conf e.g. the Documenroot, Directories, ScriptAlias,
| also when you use the extra folder config files change to your location there.
Можно распаковать в другую папку, но тогда надо будет поменять указанные настрйки в httpd.conf

| Start apache in a DOS box:
Запуск Апача из командной строки

|httpd.exe


| Install as a service:
Установить в систему как службу
|httpd.exe -k install

| ApacheMonitor:

| Double click ApacheMonitor.exe, or put it in your Startup folder.
Можешь создать ярлык на ApacheMonitor на рабочем столе или в меню пуск для удобства.

| Буду сносить ХР, поставлю семерку и буду пробовать на ней с более новыми сборками.
только не думай, что это избавит от необходимости разбираться.

Аноним Втр 19 Ноя 2013 00:20:37  #248 №336006 

>>336004
Как все запутанно. С каждым днем чувствую себя все более и более криворукой макакой, тяжело усваиваю материал. А тут еще и с установкой софта такой фейл, не понимаю, как люди по книжкам это читают и делают.
Спасибо за перевод, так будет гораздо проще.
А про игры нет, в них я совсем не играю, разве что майнкрафт иногда. Большинство времени провожу тупо скроля интернеты, бессмысленно тратя время, поэтому собственно решил осваивать данный язык. Паскаль в быдловузике совсем не вдохновляет, но вроде как дал неплохую почву для какого-никакого понимания других языков.

Аноним Втр 19 Ноя 2013 01:23:34  #249 №336036 

Доброанон, посоветуй. Есть сайт. Сайт наполняется статьями. Мне сказали, причем весьма уверенно, что для поисковой оптимизации очень хорошо в адресной строке иметь написанное транслитом название каждой статьи. То есть вместо page.php?id=12345 нужно делать page.php?name="kak zavyazivat galstuk" и потом делать это красиво через mod_rewrite. Здесь id и name - соответственно номер и название статьи. Дак вот, правда ли это, что так делать лучше (все популярные сайты и правда так делают) и как это реализовывать? Вводить специально транслитную версию отдельным полем в БД или использовать русское имя, но какими-то функциями перегонять его в транслит для адресной строки? Еще вопрос, если в БД куча статей, запрос, содержащий where name='kak zavyazivat galstuk' ведь должен сильно тормозить? Это же поиск по тексту почти. Вообщем, как делать правильно, расскажи, посоветуй.

Аноним Втр 19 Ноя 2013 04:23:50  #250 №336065 

>>336006
Запутанно когда ставишь по советом двачей..прочитай хорошую книжецу про unix и все распутается у тебя

Аноним Втр 19 Ноя 2013 09:51:48  #251 №336080 

>>335540
Почему когда вводим другую фразу-не палиндром,все равно пишет что это палиндром,где-то косяк,помоги найти :3

Аноним Втр 19 Ноя 2013 10:14:05  #252 №336082 

>>336080
самофикс,точка лишняя стояла

Аноним Втр 19 Ноя 2013 10:22:34  #253 №336086 

>>336082
Все равно не работает :(

!xnn2uE3AU. Втр 19 Ноя 2013 10:26:01  #254 №336087 

>>336086

Что-то я проглядел это.

$reversed .= mb_substr($lower, $i, 1);

Ты прибавляешь буквы в конец строки. Попробуй добавлять в начало:

$reversed = mb_substr() . $reversed;

Или же переделай цикл, чтобы он шел не с первой до последней буквы. а с последней до первой.

Аноним Втр 19 Ноя 2013 11:39:22  #255 №336110 

>>336087
Спасибо,доброкун

Аноним Втр 19 Ноя 2013 11:56:07  #256 №336114 

>>336036
>>336087
доброанон, выручи.

!xnn2uE3AU. Втр 19 Ноя 2013 12:04:30  #257 №336115 

>>336036

SEO обсуждается в разделе /web. Я могу прокомментировать с личной точки зрения и с т.з. технической реализации.

> page.php?id=12345
Я слышал, поисковики считают то, что идет после впроса дополнительным параметром, и воспринимают все это как одну страницу page.php. Хотя, с другой стороны, такие страницы и индексируются и ищутся. Смотрится отстойно.

Мое личное мнение, автосгенерированные адреса транслитом выглядят как кошмар: http://example.com/pitanie/zyri-i-vitaminy-dlya-zdoro-16312.html

Но если ты оптимизируешь под роботов, может им это и нравится.

Хорошо могут выглядеть заданные вручную URL: http://exanple.com/nutrition/vitamins. Пример — URL новостей на lenta.ru.

Что касается технической реализации, то конечно надо хранить URL в базе. Для поиска можно поставить индекс по полю, например на первые 8-16 символов.

!xnn2uE3AU. Втр 19 Ноя 2013 12:07:16  #258 №336117 

>>336036

У меня есть еще паста про URL (с точки зрения человека, а не робота): https://gist.github.com/codedokode/772a4ccc03e41d6b7cba

Аноним Втр 19 Ноя 2013 12:10:14  #259 №336118 

>>336117
>>336115
спасибо, бро. Я именно про это и хотел спросить. То есть все обычно ставят индекс по первым символам особого текстового поля и хранят эти транслитные адреса в нем, так?

!xnn2uE3AU. Втр 19 Ноя 2013 12:11:09  #260 №336119 

>>336118

Да.

!xnn2uE3AU. Втр 19 Ноя 2013 13:18:43  #261 №336138 

Аноны, я знаю, среди вас есть те, кто немного изучил HTML/CSS и берется за яваскрипт. Вот вам ссылочки для вдохновения:

Учебник JS на русском: learn.javascript.ru
Серия постов на Хабре про маленькие программки на яваскрипт:

http://habrahabr.ru/post/202556/ Гоночка на JavaScript (30 строк кода)
http://habrahabr.ru/post/202530/ Крошечный арканоид на JavaScript (30 строк кода)
http://habrahabr.ru/post/202304/ Крошечный Excel на чистом JavaScript (30 строк кода)
habrahabr.ru/post/202476/ Крошечная змейка на JavaScript (30 строк кода)
habrahabr.ru/post/202628/ Tetris на javascript (в 30+ строк)
http://habrahabr.ru/post/202684/ Roguelike/RPG на JavaScript (30 строк кода)

Изучайте.

Аноним Втр 19 Ноя 2013 14:20:35  #262 №336152 

чего-то никак палиндром не получается,что я делаю не так
http://ideone.com/NGgItv

!xnn2uE3AU. Втр 19 Ноя 2013 14:47:32  #263 №336155 

>>336152

$half2=strrev($half1);

Ты читал что там в учебнике написано про strrev? После задачи, там еще картинка есть с 2 чуваками на крыше.

Аноним Втр 19 Ноя 2013 20:41:46  #264 №336242 

Ебался-ебался я со второй задачей на регулярки, и вот только сейчас доделал: http://ideone.com/ZGLiNh
.
А всё потому, что никто блджад в этом сраном мануале не потрудился сообщить о том, что функция preg_match_all, если ей передать флаг PREG_OFFSET_CAPTURE будет выдавать смещение в БАЙТАХ а на в символах...
Я очень долго пытался вкурить почему же всё работает не так, как надо.

Аноним Втр 19 Ноя 2013 20:48:26  #265 №336246 

>>336242
вот прогнал через http://beta.phpformatter.com/ если что.
http://ideone.com/QpWj9l

Аноним Втр 19 Ноя 2013 20:54:00  #266 №336250 

ОП, это кун который вчера спрашивал тебя про не работающий Апач когда к нему подключаю php. По твоему совету скачал Apache 2.4.6 Win64 с http://www.apachelounge.com/download/. Ставил на Win8.1 64x. Все установилось, как служба поставился, из под командной строки все запускается. Но проблема опять та же самая. Как только привязываю к Апачу php - "Специфическая ошибка службы 1". PHP брал с http://windows.php.net/download/, попробовал версии PHP 5.5 VC11 x64 Thread Safe, и на всякий случай PHP 5.4 VC9 x86 Thread Safe (x64 не нашел). Visual C++ и Visual Studio 2012 устанавливал. Что только не делал. Даже Аллаху молился, все равно "Специфическая ошибка службы 1". PHP вроде подключаю правильно, не понимаю почему не работает. Помоги пожалуйста. По ссылке конфиг Апача (Подключение PHP в последних строчках):
http://pastebin.com/Ja3yCBkF

Аноним Втр 19 Ноя 2013 21:00:47  #267 №336253 

ОП, это кун который вчера спрашивал тебя про не работающий Апач когда к нему подключаю php. По твоему совету скачал Apache 2.4.6 Win64 с http://www.apachelounge.com/download/. Ставил на Win8.1 64x. Все установилось, как служба поставился, из под командной строки все запускается. Но проблема опять та же самая. Как только привязываю к Апачу php - "Специфическая ошибка службы 1". PHP брал с http://windows.php.net/download/, попробовал версии PHP 5.5 VC11 x64 Thread Safe, и на всякий случай PHP 5.4 VC9 x86 Thread Safe (x64 не нашел). Visual C++ и Visual Studio 2012 устанавливал. Что только не делал. Даже Аллаху молился, все равно "Специфическая ошибка службы 1". PHP вроде подключаю правильно, не понимаю почему не работает. Помоги пожалуйста. По ссылке конфиг Апача (Подключение PHP в последних строчках):
http://pastebin.com/Ja3yCBkF

!xnn2uE3AU. Втр 19 Ноя 2013 22:34:29  #268 №336278 

>>336250

Сейчас разберемся. Сначала убедимся, что На apachelounge написано:

1) Be sure that you have installed Visual C++ Redistributable for Visual Studio 2012 : VC11 (vcredist_x64/86.exe) — установил библиотеку по ссылке (это не Visual Studio а Visual Studio Redistributable)?

2) Точно ли существует файл С:/PHP/php5apache2_4.dll который прописан в конфиге в конце? Проверить можно например командой

attrib С:\PHP\php5apache2_4.dll

Если файл не найден, то будет так и написано.

3) Проверь содержимое логов (в папке апача есть папка logs, а в ней скорее всего error.log и покажи нам)

!xnn2uE3AU. Втр 19 Ноя 2013 22:39:02  #269 №336279 

>>336253

Трюки вроде установки на 64-битную систему 64-битного Апача и 32-битного PHP точно не сработают. Все должно быть одинаковой битности (включая библиотеку redistributable от майкрософт).

Аноним Втр 19 Ноя 2013 22:42:57  #270 №336280 

Привет, Анон.
Сперва скажу спасибо, благодаря тебе я устроился джуниором на пхп.
Но у меня проблема, которая заключается в следующем. Есть форма - вводишь данные, нажимаешь сохранить, и программа запихивает все в базу данных. Проблема в том, что после этого, если что-то поменять в инпутах и снова нажать Сохранить, то программа должна обновлять только что созданную запись. Как это лучше сделать?
Я думаю использовать такой вариант: после того, как данные в БД записаны, с помощью LAST_INSERT_ID получить id и сделать редирект на новую вьюшку, передав id. Потом уже извлекать данные, вставлять их в точно такую же форму, но при сабмите обновлять данные. Как думаешь, такое решение пойдет?

!xnn2uE3AU. Втр 19 Ноя 2013 22:58:56  #271 №336287 

>>336246

> никто блджад в этом сраном мануале не потрудился сообщить о том, что функция preg_match_all, если ей передать флаг PREG_OFFSET_CAPTURE будет выдавать смещение в БАЙТАХ а на в символах...

Бывает. Ведь PHP-ники не сами писали обработку регулярок, а подключили библиотеку pcre, видимо на этот момент не обратили внимания.

Для преобразования байты → символы можно применить хак (мы отрезаем кусочек строки в байтах и считаем его длину в символах):

$offsetChars = mb_strlen(substr($string, 0, $offsetBytes));

Вообще, сделано неплохо. Выводится причина ошибки, это хорошо. Жаль, нелегко понять где именно, так как ошибочное место не выделено ни стрелочками, ни скобками, напрмер так:


...жывотное ...


или так:

...→жы←вотное ...
...[жы]вотное ...
..._жы_вотное ...



Баги: http://ideone.com/1XpcDf — глючит когда одна ошибка несколько раз, не видит «этажы» в конце текста, не видит ошибки в «нас 100 а он 1».

Если ты хочешь написать например «цифра или конец текста», можно написать (\\d|\\Z)

\\Z значит конец строки, \\A — начало: http://www.php.net/manual/ru/regexp.reference.escape.php

Советы:

У тебя повторяются куски регулярки: в массиве possibleErrors и в regExp. Это плохо, так как когда правишь, можно забыть поправить в другом месте или сделать это неправильно. Лучше бы автоматом собирать regExp из кусочков, например так:

$reg = '...' . implode(')|(', array_keys($errors)) . '...';

Копипаста — источник ошибок в программах.

> [а-яё]{1}
Можно просто [a-яё]

> $position = (mb_strpos($coolStory, $value) < 20) ? 0 : mb_strpos($coolStory, $value) - 20;

Можно писать max(0, mb_strpos(....) - 20); — функция max не даст взять значение меньше 0

> echo "Ошибка" . $errNo . ":\"...";
Лучше без точек: echo "Ошибка {$errNo}:\"...";

Внутри квадратных скобок обяательно экранировать надо только минус и квадратные скобки, а ? и . можно писать без бекслещей (ну можно и с ними).
!xnn2uE3AU. Втр 19 Ноя 2013 23:02:31  #272 №336288 

>>336280

Да, сделай в форме скрытое поле id. Изначально оно пусто, а после создания записи делай редирект на адрес в котором есть id:

- открываем страницу scrip.php, форма пуста
- отправляем форму через POST, запись вставляется в базу и редиректит на scrip.php?id=12345
- при открытии этой ссылки в форму подставляется id из параметров и пишется текст «Редактирование записи 12345»
- когда ты отправляешь форму, скрипт по наличию id понимает что надо редактировать запись.

Обрати внимание на редикерт после POST. Это нужно чтобы при нажатии F5 не вставилась еще одна запись.

Аноним Втр 19 Ноя 2013 23:16:42  #273 №336290 


>>336288
>Обрати внимание на редикерт после POST. Это нужно чтобы при нажатии F5 не вставилась еще одна запись.
Можно насчет этого поподробней. И еще одно забыл. У меня же есть еще одна кнопка: сохранить и создать новое. Я так понимаю, различить какую кнопку нажал юзер можно только с помощью js, но вот как сабмитить форму при этом я совсем не въезжаю.

!xnn2uE3AU. Втр 19 Ноя 2013 23:20:36  #274 №336292 

>>336290

Если у кнопки есть имя (name =), то вместе с данными формы отправляется параметр с именем нажатой кнопки (попробуй сделать var_dump($_POST) чтобы увидеть).

Но если ты хочешь извратиться делать через JS (например чтобы поддержать ИЕ6 который отправлял все кнопки button а не только нажатую), то тоже нет проблем. При клике на кнопку пишешь в скрытое поле что это за кнопка и делаешь form.submit(), где form — это DOM-нода формы (ее можно получить например getElemetnById()): http://learn.javascript.ru/forms-methods

Аноним Втр 19 Ноя 2013 23:28:08  #275 №336293 

>>336292
Понятно. Спасибо.

Аноним Срд 20 Ноя 2013 00:05:04  #276 №336303 

>>336278
Ура! У меня все заработало, ОП, но я так и не понял в чем была ошибка. Нагуглил туториал вот этот:
http://www.youtube.com/playlist?list=PLV19T7yKWLmZkZl2Ti8fa3g4Sdyd3ZrBp
Поставил в точности такие же версии какие ставит и он, прописал все под диктовку и слава всем богам - завелось. Может я поставил не весь нужный софт, который требовался для новых версий (хотя и со старыми у меня ничего вчера не получалось), может еще что-нибудь. Но скорее всего из-за того что не настраивал файл php.ini, а лишь оставлял его как есть. Это может быть из-за этого? Даже не знал, что что-то нужно прописывать и там.

!xnn2uE3AU. Срд 20 Ноя 2013 00:06:42  #277 №336304 

>>336303

Скорее всего ты опечатался когда прописывал путь к php в конфиге апача.

Аноним Срд 20 Ноя 2013 00:12:20  #278 №336306 

>>336304
Нет, ошибка точно была не в этом. Забыл дописать, что в пути перепроверял много раз и данная библиотека там точно присутствовала. Спасибо за разъяснения, на будущее буду уже знать про разрядность и прилагающий софт для корректной работы. Не думал что возникнет столько трудностей. Даже когда LAMP ставил на Убунту все было гораздо проще.

Аноним Срд 20 Ноя 2013 11:01:56  #279 №336366 

Похожие посты. Анон, как оно реализуется? Часто на сайтах при чтении статей есть раздел ПохожиеСтатьи. Какая статья похожа на какую - прописывается только вручную или есть какие-то механизмы, основанные на тегах, например? Зачем, кстати, нужны теги, куда их прописывать и что вообще с ними делать?

!xnn2uE3AU. Срд 20 Ноя 2013 13:39:37  #280 №336397 

>>336366

Обычно берутся статьи с максимально близкими тегами. Или статьи из той же категории. Или же берется заголовок, удаляются стоп-слова и ищутся похожие. В общем, каждый придумывает свой велосипед.

> Зачем, кстати, нужны теги, куда их прописывать и что вообще с ними делать?
Если ты не знаешь, зачем они нужны, значит тебе они не нужны. Но вообще теги — это пришло из блогов, это что-то вроде тем, которые затрагивает пост, например:

«Работаем с Yandex Maps API», теги: JS, Yandex maps
«Никому нельзя верить», теги: отношения, печалька, когда это кончится

Потом можно найти все посты с тегом «JS» например. Посмотри например теги под статьями на хабре или в ЖЖ.

Аноним Срд 20 Ноя 2013 16:05:43  #281 №336427 

>>336155
http://ideone.com/cYEFd4
а теперь второй цикл отказывается работать

Аноним Срд 20 Ноя 2013 16:29:21  #282 №336432 

>>336427
http://ideone.com/kFbw80
быстрофикс,вроде работает

Аноним Срд 20 Ноя 2013 16:53:57  #283 №336436 

>>336306
Чому линукс в виртуалку не поставишь? Рабочий LAMP ставится одной командой, и все равно потом это будет работать на линуксе.

Аноним Срд 20 Ноя 2013 17:52:03  #284 №336445 

>>336397
тогда можешь рассказать, как они реализуются? В каком виде хранятся в базе, как происходит поиск по ним (допустим, количество статей, как на хабре или постов, как у жж, у каждого по 3-10 тегов). До черта же информации, поиск должен быть долгим

!xnn2uE3AU. Срд 20 Ноя 2013 18:48:23  #285 №336477 

>>336432

Молодец, правильно работает.

!xnn2uE3AU. Срд 20 Ноя 2013 18:51:50  #286 №336480 

>>336445

Реализуются самым простым образом: таблица tags, где хранятся теги и таблица связи многие-ко-многим tags_to_posts. Для оптимизации (чтобы не джойниться при выводе постов) можно в таблицу постов в отдельном поле засунуть список тегов через запятую, но надо не забывать его обновлять при редактировании.

Поиск идет с помощью SQL-запроса SELECT наверно.

> До черта же информации, поиск должен быть долгим
Используй индексы и правильные запросы. Базы данных специально сделаны чтобы работать с большими объемами информации. Тем более что информации в тегах куда как меньше чем в статье или комментариях.

Зачем, кстати, ты пишешь свой велосипед, а не берешь вордпресс где уже все написано, есть теги и куча плагинов?

Аноним Срд 20 Ноя 2013 20:30:20  #287 №336509 

>>335764
>Ну вообще не такой и громоздкий, если подумать.

Я подумал и таки получилось. И правда несложно:
"/^[8\\+7]{1,2}[\\s(-]\\d{3}[\\s)(-](\\d[-)(\\s]?){7}$/"

Это третья задачка на регулярки.

http://ideone.com/ZGLiNh

Аноним Срд 20 Ноя 2013 20:32:10  #288 №336511 

>>336509
блджад не та ссылка http://ideone.com/eHNoCl

!xnn2uE3AU. Срд 20 Ноя 2013 20:36:41  #289 №336513 

>>336509

Пропускает неверный номер: http://ideone.com/CXEkrb
Не пропускает верный: http://ideone.com/oIy5X6

Думаю лучше не задавать жестко 3 цифры в коде города, а разрешить любые 10 цифр + разделители.


Аноним Срд 20 Ноя 2013 20:44:05  #290 №336515 

>>336513
ох ты ж какой молодец, все дыры увидишь, спасибо.

Аноним Срд 20 Ноя 2013 21:17:38  #291 №336521 

>>336513
Пофиксил! Ну теперь-то не придраться, ОПушка.
http://ideone.com/jZZcAZ

!xnn2uE3AU. Срд 20 Ноя 2013 21:49:55  #292 №336527 

>>336521

Теперь все верно.

Аноним Срд 20 Ноя 2013 22:51:15  #293 №336551 

>>336480
Можешь подробнее рассказать и, если не лень, пояснить примером? Как завести такое классное поле в базе данных, чтобы без связей и прочих жутких операций решить проблему? Тэгов много, у каждого поста их может быть с десяток, они часто в разном порядке стоят (или сортировать надо), постов может быть 10 000 и больше. Поиск по ним будет делом не очень быстрым, наверное.


!xnn2uE3AU. Срд 20 Ноя 2013 23:13:10  #294 №336555 

>>336551

> Как завести такое классное поле в базе данных, чтобы без связей и прочих жутких операций решить проблему?
Ничего жуткого в связях нет.

Я-то могу рассказать, но у меня подозрение, что ты не знаешь ни понятия «многие ко многим», ни как работают индексы. В этом случае, тебе лучше почитать и изучить теорию сначала.

Для начала, почитай «Руководство по проектированию реляционных баз данных»: http://habrahabr.ru/post/193380/ желательно целиком.

Там описаны как раз способы связи таблиц, в том числе «многие ко многим».

Чтобы разобраться с тем, как сделать быстрым поиск по жалкому миллиону тегов, почитай:

http://xpoint.ru/know-how/MySQL/Optimizatsiya/Indeksyi
http://habrahabr.ru/post/31129/
http://habrahabr.ru/post/70640/

Если в этих статьях что-то непонятно написано, пиши, разберемся.

Аноним Чтв 21 Ноя 2013 06:18:55  #295 №336606 

Сап, Антуаны, заебался искать примеры того, как на ПХП сжимать пачку файлов в файл.tar.bz2
Если не сложно, можно пример чтоб легко понять, что к чему. Файлы будут выбираться из папки по шаблону, я без понятия, как оно работает на ПХП с модулями сжатия, можно ли туда пихнуть массив имён файлов или надо по одному циклом добавлять. И нужно сделать так, что если всё прошло успешно, файлы потереть с папки. Всё что находил было про Phar и ни разу ни одного примера про tar.bz2, я не совсем знаком с вызовом команд из библиотек с "классами"(или как их там).

!xnn2uE3AU. Чтв 21 Ноя 2013 15:52:43  #296 №336712 

>>336606

Тут есть примеры кода: http://www.binarytides.com/how-to-create-tar-archives-in-php/ с Phar. Пример простой.

> я не совсем знаком с вызовом команд из библиотек с "классами"(или как их там).
Ну так изучи ООП. У меня есть первый урок по ООП тут: http://archive-ipq-co.narod.ru/l1/pasta.html

Аноним Чтв 21 Ноя 2013 21:22:54  #297 №336823 

$query = 'SELECT topic_text_hash FROM spc_topic WHERE 1';
$result = mysql_query($query) or die ('циклу хэша облом!'.mysql_error());
$result = mysql_fetch_array($result,MYSQL_NUM);

echo $result[0].'<br/>';
echo $result[1].'<br/>';
echo $result[2].'<br/>';

//Почему в каждом элементе массива первый хэш из БД?

http://pastebin.com/VSrUJJqL

Тот же запрос в phpmyadmin работает и выдает все верно (пикрелейтед)

Аноним Чтв 21 Ноя 2013 22:19:24  #298 №336835 

>>336823

Почитай мануал.
http://us3.php.net/manual/ru/function.mysql-fetch-array.php

fetch_array возвращает 1 ряд за раз, а не весь результат.

Аноним Чтв 21 Ноя 2013 22:54:09  #299 №336841 

>>336835
А что надо, чтобы вернул весь результат?

!xnn2uE3AU. Чтв 21 Ноя 2013 22:55:35  #300 №336842 

>>336841

Использовать цикл while: посмотри на примеры кода в мануале http://php.net/manual/ru/function.mysql-fetch-array.php

Аноним Птн 22 Ноя 2013 14:57:31  #301 №336965 

>>335260
ОП, ты, безусловно, няша, но откуда столько фанатизма по отношению к подавлению ошибок? Это не register_globals, которые плохо, потому что это пиздец. Если кодер понимает, что и зачем делает, то эта возможность полезна и не является признаком говнокода.

Вот, к примеру, Slim PHP, о котором ты хорошо отзывался. Не думаю, что его говнокодер писал.
В ту же степь - анализ html xml парсерами, которые вполне справляются с разбором, но выкидывают варнинги на невалидный html.

Аноним Птн 22 Ноя 2013 15:12:29  #302 №336966 

>>336965
@ тормозит же.
http://ideone.com/zhuX30 — без @
http://ideone.com/BmyVLu — c @

!xnn2uE3AU. Птн 22 Ноя 2013 15:40:12  #303 №336970 

>>336965

> откуда столько фанатизма по отношению к подавлению ошибок
Потому что эта штука обычно используется юными быдлокодерами как костыль, чтобы кривой код побыстрее заработал.

> Вот, к примеру, Slim PHP, о котором ты хорошо отзывался. Не думаю, что его говнокодер писал.
Мне не нравится то, что у них написано. Я бы по другому сделал, пусть на несколько строчек больше, но зато никакие сообщения об ошибках не теряются. Там @ нафиг не нужен.

Напрмиер, вот это: @fopen('stderr', 'w') — какая ошибка может возникнуть при попытке открыть поток ошибок? Он обычно уже открыт и ошибок быть не должно, а если они есть то значит все совсем плохо и скрывать сообщения о них точно не нужно, наоборот, нужно их зафиксировать.

> Если кодер понимает, что и зачем делает, то эта возможность полезна и не является признаком говнокода.
Да ни фига. У каждого кодера свои представления о красивом коде. Если их не ограничивать жесткими рамками стандартов, то проект будет содержать все существующие стили именования функций, расстановки скобок, виды костылей и функции вроде mysql_query. Ну и до кучи найдется эстет, который будет лепить хакерские выражения вроде $sum += ++$sum << 1;

> В ту же степь - анализ html xml парсерами, которые вполне справляются с разбором, но выкидывают варнинги на невалидный html.
HTML надо парсить HTML-парсером а не XML. Ну тут ты прав, в PHP функция DOMDocument::loadHtml сделана кривовато:

> While malformed HTML should load successfully, this function may generate E_WARNING errors when it encounters bad markup. libxml's error handling functions may be used to handle these errors.

Заметь, что там есть ссылка, можно переключить эту функцию, чтобы ошибки не генерировались, а складывались в отдельный буфер, откуда их можно взять. Вроде в PHP есть еще пара функций, которые генерируют неотключаемые варнинги даже когда не нужно, но опять же, прежде чем ставить @ стоит посмотреть — может, эту проблему уже поправили?

Аноним Птн 22 Ноя 2013 18:02:38  #304 №336999 

Ололо я теперь гуру регулярных выражений, благодаря Опу.
http://ideone.com/is6Evl
http://ideone.com/bC4xUI
http://ideone.com/kMENMk



!xnn2uE3AU. Птн 22 Ноя 2013 18:39:40  #305 №337004 

>>336999

О, неплохо. Но и тут есть баги.

Первая задача: http://ideone.com/1wFk6A — большие буквы заменяются на маленькие, и вместо $2 написано S2.

Вторая задача: все хорошо сделано.

Третья: все верно, работает.

Аноним Птн 22 Ноя 2013 21:36:13  #306 №337042 

>>337004
ОП-先生! я тебе еще покушать принёс! Отличная задачка, заставила подумать.
http://ideone.com/SZAvQY

!xnn2uE3AU. Птн 22 Ноя 2013 22:39:20  #307 №337059 

>>337042

Боюсь, надо подумать еще. http://ideone.com/u8dvOx — этот текст что-то толком не обрабатывается, пробелы не исправляются.

Аноним Птн 22 Ноя 2013 23:15:39  #308 №337072 

Пагни,а если я выберу вебкодинг, полученный опыт поможет если я захочу кардинально поменять направление - геймдев, например при условии, что недостающие знания разберу?

Аноним Суб 23 Ноя 2013 00:28:49  #309 №337092 

ОПушка, помоги пожалуйста. У меня ТРУБЫ ГОРЯТ написать электронный дневник, который в последствии будет моей курсовой, а при полнейшей доработке дипломной работой. PHP изучая смотря Специалиста и попутно пописывая этот самый электронный дневник. Худо-бедно понял озы, дошел до MySQL, но чтобы в данном курсе понять как делать сложные запросы, нужно посмотреть весь второй курс, а на это времени совсем нет. Хочется пока просто понять как сделать нужную на данный момент мне вещь и писать нужные мне функции уже на php, которая будет выполнять требуемые запросы. Так вот, суть вопроса собственно пикрелейтед. У меня есть таблица users и months. В поле users поле id - ключевое, автоинткрементарное. В таблице months поле id тоже ключевое, автоинкрементальное. Суть в том, что мне нужно получить третью таблицу, которая также изображена на пикрелейтед и названа таблица info. Как мне сделать такую таблицу? Как мне в данной таблице поле id.Users сделать ссылкой на id в таблице users? Как поле id.Months сделать ссылкой на поле id в таблице users? Пожалуйста, объясни кратко как это реализовывается, а то повсюду написанно заумными словами и терминологией языка. Я же пока хуй простой, просто хочется поскорее начать доделывать, попутно также смотря Специалиста и постигать новые вершины. Можно ли ее как-то реализовать, чтобы я мог спокойно написать:

USE database;
SELECT * FROM info WHERE (id.Users = 5, id.Months = 11);


В итоге мне выводится таблица примерно такого вида:

id.Users id.Moths vsego_propuskov propuskov_po_neuv_pr
5 11 15 6

И при все этом в поле id.Users и id.Moths будут значения взятые из таблицы users и months?
Если не трудно - напиши пожалуйста подабающий запрос, на создание таблицы info. С меня твердое обещание разобраться как это делается и в будущем самому делать подобные вещи как раз плюнуть.

!xnn2uE3AU. Суб 23 Ноя 2013 00:33:21  #310 №337094 

>>337092

Гугли JOIN, он объединяет таблицы вместе. Алсо поля надо называть нормально, например user_id или id_user, а не через точку. И конечно хорошо бы не транслитом.

!xnn2uE3AU. Суб 23 Ноя 2013 00:35:49  #311 №337095 

>>337092

давно бы выгуглил:

http://www.anton-pribora.ru/articles/mysql/mysql-join
http://www.anton-pribora.ru/articles/mysql/mysql-join

!xnn2uE3AU. Суб 23 Ноя 2013 00:36:51  #312 №337096 

>>337092

Вторая ссылка: http://www.mysql.ru/docs/man/JOIN.html

>>337072

Поможет, тем более что половина геймдева сейчас онлайн-игры делает.

Аноним Суб 23 Ноя 2013 00:39:40  #313 №337099 

Анон, ты советовал мне
>>333180
в ответ на этот пост вот эту либу
>>333191
До сих пор разбираюсь. Всё хорошо, все круто, но есть три больших подводных камня, точнее, два маленьких и один огромный.
1) Все круто, интерфейс хорош, но все это жутко избыточно, мне это все не надо, автоматы это очень здорово, гораздо круче регулярок, но мне нужно всего 5-10 тэгов, а для отключения всего остального надо сильно править исходники.
2) Хреново создаются стили css, все кидается в один класс и разбивается по типам, лучше бы делал отдельные классы с префиксами, а лучше, если бы я сам решал, где класс нужен, а где нет. Но это опять активно править исходники.
3) Третий и главный камень - для решения первых двух первых проблем мне не только не хватит опыта, но мне это делать не позволит лицензия, так как измененный код я опубликовать не могу, проект закрытый. Поэтому вопрос: есть ли что-то подобное, тоже на автоматах, но под MIT, например? Или решающее первые две проблемы. Сам написание вряд ли осилю.

Аноним Суб 23 Ноя 2013 00:49:22  #314 №337102 

>>337096
Окей, бегло окинув статьи понял что JOIN при при использовании селекта образует какую-то третью таблицу, где хранятся данные в которых объединены заданные поля. Я правильно понимаю? Но ведь мне не совсем это нужно. Мне нужно чтобы ввел я в форму допустим логин нового студента, его пароль, выбрал нужный мне месяц, ввел значения прогулов, отправил запрос. В итоге у меня данные в таблицк users добавляется новая строка, где id прописался автоматически, логин записался с отправленных данных, также пароль. В этот же момент, когда внесены в таблицу users необходимые данные, мы в таблицу info колонку users.id добавляем нового студента считанное с таблицы users, в колонке mouths добавляем значение переданное с формы, в колонки пропусков по ув и н/у причине добавляем также значение переданное с формы. Вот и все, добавили в таблицу users нового пользователя, расширили таблицу users и info, прибавив ей нужные значения.
Или я не так что-то понимаю?

Аноним Суб 23 Ноя 2013 01:03:47  #315 №337106 

>>337102
id.Users и id.Months - внешние ключи, но это только позволит контролировать целостность таблиц. Можно обойтись без них.
Добавлять строку в info придется отдельным запросом.

Аноним Суб 23 Ноя 2013 01:24:42  #316 №337114 

>>337106
>id.Users и id.Months - внешние ключи
То есть внешние - значит никак не относящиеся к таблице info? Значит в таблице info нельзя использовать какую-то ссылку на значение определенной строки из другой таблицы? Как же все запутанно.

>но это только позволит контролировать целостность таблиц
Вот это не совсем понял, пока не особо понимаю что подразумевается под целостностью таблиц.

>Добавлять строку в info придется отдельным запросом.
То есть у меня есть форма, куда я ввел информацию о студенте. Ввел его логин, пароль, месяца в который хочу вписать пропуски, все это записалось в какие-то переменные, переменные хранятся в сессии. Далее выполняется первый запрос, а именно запрос на занесение данных в таблицу users. Берем из сессии логин, пароль, добавляем их в таблицу. В итоге у меня в users появился новый пользователь. Далее пошел второй запрос. Второй запрос выбирает id этого последнего пользователя, запоминает в переменную. Пошел третий запрос. В третьем запросе идет вставка уже наконец-то в таблицу info, где поле id вставляется из переменной последнего созданного пользователя, поле id.mouths вставляется тоже из переменной в сессии, поле пропусков тоже из сессии. В итоге чисто теоретически получилась новая запись в таблице info, содержащая параметры которые мне были нужны. А уже селектом я могу использовать этот самый JOIN, объеденяя их и выводя нужную информацию. Это так должно работать? Это и есть связи, или это велосипед говнокодовый? И сам запутался, и вас наверное запутал.

Аноним Суб 23 Ноя 2013 01:42:37  #317 №337120 

аноны, такой вопрос: на локальном сервере установлен apache+mysql+php, создаю папку тестовую папку с данными сайта, помещаю туда index.php, все работает нормально. создаю вторую папку с сайтом, помещаю туда тот же файл-пишет нет прав доступа (в настройках апача и хостов все прописано верно), перемещаю данные второго сайта в папку первого - все работает, значит, если настройки одинаковы для обоих сайтов одинаковы, то дело в настройках апача, может кто-нибудь знает какие конкретно настройки отвечают за количество серверных имен, запускаемых с одной машины?

!xnn2uE3AU. Суб 23 Ноя 2013 01:52:11  #318 №337123 

>>337114


Так. Смотри сюда.

- таблица info сама не создастся. Ты конечно должен создать ее руками (как и первые 2 таблицы).
- после этого, ты можешь использовать JOIN. JOIN объединяет в одном запросе несколько таблиц, примеры есть по ссылкам.

Насчет внешних ключей. Ты можешь (но не обязан)(но лучше это сделать) сказать MySQL что одна таблица ссылается на другую через ALTER TABLE (имена полей и таблиц подставь свои):

ALTER TABLE info ADD FOREIGN KEY id_user REFERENCES users(id) ON DELETE CASCADE ON UPDATE CASCADE

Это дает такие плюсы:
+ MySQL будет сама удалять связанные записи при удалении родительской
+ MySQL будет следить за целостностью связи и не позволит например случайно поменять id у связанных записей
+ программы типа adminer будут отображать связанные поля ссылочкой, по которой можно перейти на связанную запись
+ Это правильный классический подход

Теория на русском понятными словами: http://denis-in-ua.livejournal.com/7672.html

В общем, сплошные плюсы. Кстати, в старых учебниках пишут что FOREIGN KEY ничего не делает. Сейчас это не так, все работает. Так что научись использовать эту хрень.

> Вот это не совсем понял, пока не особо понимаю что подразумевается под целостностью таблиц.
Целостность — это когда какая-то запись A ссылается на запись B и та существует. Нарушение целостности - когда запись ссылается на несущестующую (например, запись B удалена или у нее криворукий админ поменял id, а ссылку в A не поменял). Если использовать FOREIGN KEY, MySQL будет следить за целостностью и блокировать недопустимые операции. Если не использовать — база в любой момент может превратиться в кашу одним неловким запросом.

> То есть внешние - значит никак не относящиеся к таблице info?
Внешний ключ — значит это поле содержит в себе id записи из внешней таблицы и таким образом ссылается на нее. Например, поле user_id таблицы info является внеш. кл. и ссылается на поле id таблицы user. Согласен, название дурацкое.

!xnn2uE3AU. Суб 23 Ноя 2013 01:57:21  #319 №337125 

>>337114

> Далее пошел второй запрос. Второй запрос выбирает id этого последнего пользователя, запоминает в переменную.
Погугли насчет функции lastInsertId (например http://php.net/manual/ru/pdo.lastinsertid.php если ты как правильный паца