Вы видите копию треда, сохраненную 27 марта 2015 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
Это тред для начинающих. Не написал за свою жизнь ни одной программы? Ты наш человек.
Устанавливать пока что ничего не требуется, разве что редактор кода вроде Sublime Text 3, Notepad++, Netbeans PHP или PhpStorm (необязательно).
Предыдущий тред был тут: >>438085
Правила: ведем себя воспитанно, помогаем новичкам, постим ссылки на решения задачек, ОП их проверяет и дает советы и замечания. ОП отвечает даже на самые нубские вопросы. ОП заходит где-то раз в день, не жди его, решай задачки дальше.
У нас есть уроки по основам PHP, они собраны и выложены по адресу http://archive-ipq-co.narod.ru/ Это учебник для изучающих с нуля, то есть если ты вообще ничего не знаешь, то надо начать с него. Он простой и понятный (по крайней мере в начале). Там есть задачи, их надо решать обязательно (чтобы стать программистом, надо писать код — иначе никак). Пости ссылки на решения в тред, мы их проверим, напишем замечания и дадим советы по улучшению.
Если не знаешь как решать, запости код, напиши в каком месте остановился и попроси подсказку.
Учебник дает основы языка PHP, но чтобы делать сайты, этого недостаточно. Если ты его прошел, то надо переходить в более серьезным задачкам, которые научат тебя как выдавать страницы в браузер, работе с таблицами в БД, работе с формами, MVC.
- Простая, но полезная задача сделать список студентов: https://gist.github.com/codedokode/d7e7f11449fc3bcb24b4
- Более сложная задача сделать файлообменник на микрофреймворке Slim: https://gist.github.com/codedokode/9424217
- Еще более сложная и долгая задача на Yii/Yii2: https://gist.github.com/codedokode/8733007
- Если ты все их решил, переходи к Symfony 2/Doctrine 2
Чтобы делать эти задания, тебе надо установить Апач + PHP (можно заодно сразу и MySQL) на компьютер. Вот полезные инструкции:
https://gist.github.com/codedokode/10774100
https://gist.github.com/codedokode/7054af4a03865c4cc863
Может тебе понадобится пользоваться командной строкой, вот гайд https://gist.github.com/codedokode/10539568
Вот небольшой туториал по тому как начать использовать PHP на сервере для отдачи странички в браузер: https://php.net/manual/ru/tutorial.php Увы, уроков плавно подводящих к тому, как сделать задачи выше, пока нет, так что если что, задавай вопросы.
Решения задач лучше показать мне, особенно на ООП,так как сам ты вряд ли увидишь все ошибки. Пости свой код на гитхаб и вкидывай ссылку в тред по мере решения. Я прокомментирую и укажу на ошибки.
Также, у нас есть задачи которые позволят тебе изучить или подтянуть до нормального уровня знания JS/HTML/CSS/SQL. Решай их параллельно с задачами выше.
- HTML/CSS: https://gist.github.com/codedokode/58ebc90bd006baf4b35c
- JS: https://gist.github.com/codedokode/ce30e7a036f18f416ae0
- Проверялка решений на JS: http://dkab.github.io/jasmine-tests/
- MySQL: https://gist.github.com/codedokode/10539213
Что почитать
- Мануал по PHP — http://www.php.net/manual/ru/langref.php
- Сайт phptherightway (перевод на русский: http://getjump.github.io/ru-php-the-right-way/ )
- По PHP: Профессиональное программирование на PHP Джордж Шлосснейгл
- По PHP: Мэтт Зандстра — PHP: Объекты, шаблоны, методики программирования
- JS: learn.javascript.ru
- Про Git:
Нужен ли ООП, фреймворки, MVC? — Да, однозначно. Посмотри любую вакансию.
Сайт опять упал!!!!! — Не паникуй, а открой http://rghost.net/45000175
Оформляй код аккуратно!!! — например пропусти через phpformatter.com . Также, если ты пользуешься IDE вроде PhpStorm, Netbeans, Eclipse, то в них эта опция встроена, подробнее: https://gist.github.com/codedokode/8759492
ОП, сделай за меня мою работу или домашнее задание? — Это конечно, хорошая идея, но нет.
Где искать работу и заказы — hh.ru, geekjob.ru, brainstorage.me, fl.ru, odesk.com. Имей в виду, что кроме фриланса есть еще постоянная удаленная работа (remote job) когда тебе не надо тратить время на поиск заказов и переговоры с неадекватными заказчиками.
Если тебе лень выравнивать код руками, закачай его на http://beta.phpformatter.com/ и нажми «format». Робот исправит выравнивание и отступы в мгновение ока (да, прогресс не стоит на месте). Если ты используешь мощную IDE вроде PhpStorm, там тоже есть функция форматирования кода.
Горячие клавиши для форматирования кода в разных IDE: https://gist.github.com/codedokode/8759492
Вообще, в PHP долгое время не было единого стандарта оформления кода, все писали как попало и было много бардака, но сейчас дело лучше — есть стандарты PSR-1 и 2. Вот как надо оформлять код:
- переменные и функции пишутся с маленькой буквы, подчеркивание не используется, используется camelCase, пример: $x, $numberOfPeople, printResults()
- Название функции начинается с глагола, в стиле «сделайЧтоТо»
- не знаешь английский? Не беда, в 21 веке есть решение этой проблемы. Не пиши транслитом, открой лучше Гугл Транслейт или slovari.yandex.ru и найди название для переменной там
- в именах классов используется CamelCase, первая буква большая, «_» может использоваться
- мы предпочитаем подстановку переменных вместо конкатенации строк: "I am $age years old" — хорошо, 'I am ' . $age . ' years old' — плохо из-за обилия точек и кавычек
- мы используем для отступов 4 пробела (можно настроить редактор, чтобы при нажатии Tab он вставлял 4 пробела)
Вот ссылка на стандарты, где все это описано подробнее и даны примеры оформления:
PSR-1: https://github.com/php-fig/fig-standards/blob/master/accepted/ru/PSR-1-basic-coding-standard.md
PSR-2: https://github.com/php-fig/fig-standards/blob/master/accepted/ru/PSR-2-coding-style-guide.md
>Сократить в каждом департаменте 40% (округляя в большую сторону) инженеров, преимущественно самого низкого ранга. Если инженер является боссом, вместо него надо уволить другого инженера, не босса.
Здесь в класс Депортамента я добавлю метод подсчета количества сотрудников определенного типа. Далее, я создам класс Кризис в котором буду находить сотрудников которых необходимо уволить, и с помощью нового метода в Депортаменте увольнять их.
Единственное что я не могу понять это как проверить всех сотрудников в каждом департаменте? Есть идея создать класс который будет хранить в массиве каждого сотрудника и вызываться каждый раз при создании нового сотрудника, но я сомниваюсь в её правильности.
>>442509
>Все зависит от компании. Куда-то возьмут с первой, куда-то потребуют минимум 3 решить.
Т.е. если я довольно быстро решил два задания, можно попробовать походить по собеседованиям, а что им говорить/писать? показывать гитхаб и говорить что я быстро учусь?
Аноны, что я делаю не так, почему не хочет компилировать задачку? Я нихуя не пони.
http://ideone.com/qIka80
Скинь решение. А тут уже увидим решил ты или не решил.
нахуй иди дибил бля)
Не за что. Обращайся!
foreach ($subject as $key => $value) {
\t $brother = explode(" ", $value);
\t$sister = array_reverse($brother);
\t$father = implode(" ", $sister);
}
foreach создаёт копию массива. Чтобы $value менялось, его нужно передавать по ссылке
foreach ($subject as $key => &$value) {
тогда в конце каждой итерации можно делать
$value = $father;
Но за передачу по ссылке, как известно, можно получить по тупому ебалу ручкам, если нет серьёзных на то оснований (например ограничения памяти).
Поэтому правильно создать новый массив на основании старого
$newSubject = array();
foreach ($subject as $key => $value) {
$brother = explode(" ", $value);
$sister = array_reverse($brother);
$newSubject[] = implode(" ", $sister);
}
Или как ФП-бог:
$formatSubjects = function($value) {
$brother = explode(" ", $value);
$sister = array_reverse($brother);
return implode(" ", $sister);
}
$newSubjects = array_map($formatSubjects, $subject);
foreach создаёт копию массива. Чтобы $value менялось, его нужно передавать по ссылке
foreach ($subject as $key => &$value) {
тогда в конце каждой итерации можно делать
$value = $father;
Но за передачу по ссылке, как известно, можно получить по тупому ебалу ручкам, если нет серьёзных на то оснований (например ограничения памяти).
Поэтому правильно создать новый массив на основании старого
$newSubject = array();
foreach ($subject as $key => $value) {
$brother = explode(" ", $value);
$sister = array_reverse($brother);
$newSubject[] = implode(" ", $sister);
}
Или как ФП-бог:
$formatSubjects = function($value) {
$brother = explode(" ", $value);
$sister = array_reverse($brother);
return implode(" ", $sister);
}
$newSubjects = array_map($formatSubjects, $subject);
Спасибо.
if (in_array('2qwerty', array(1, 2)))
{
echo 'ПЫХ ГОВНО';
}
Хорошо еще код не ушел в продакшен.
Теперь планирую менять язык.
https://github.com/NotBadCode/Students
https://github.com/NotBadCode/Upload
if (in_array('2qwerty', array(1, 2), true))
{
echo 'ПЫХ ГОВНО';
}
else {
\techo 'Пых заебись';
\t}
Регистрация reguser.php:
Пользователь заносится в БД и ему выставляются соответствующие cookie. Если у пользователя уже есть cookie, доступ к этой странице ему запрещён.
Авторизация login.php:
Пользователь вводит id и пароль. Если в базе под таким id имеется именно такой пароль какой он ввёл, ему ставятся специальные куки. Теперь он имеет доступ к закрытым страницам сайта. Если у пользователя уже есть cookie, доступ к этой странице ему запрещён.
Проверка авторизации:
В каждую закрытую скрипт сайта вставляется require_once "gate.php";, который проверяет куки пользователя.
Если в куках правильные данные, то страница загружается.
Если данные неправильные, gate.php перенаправляет пользователя на страницу входа.
Остаётся только вопрос, как зашифровать cookie, чтобы пользователь не мог найти в них закономерность и не стал подделывать их, пытаясь зайти под именем другого пользователя. Слышал это можно сделать через встроенные функции md5.
Какие подводные камни во всём описанном?
Циклом.
Это надо будет создать множество переменных, или как? Мне для задачи про Вектор надо.
Но если у каждого объекта конструктор с разными входными параметрами, например, нам нужно чтобы каждый объект был пронумерован, почему бы не сделать
class object {
...
private $id;
...
function __construct($id) {
$this->id = $id;
}
...
}
$array = []; // Множество объектов
for (i<N) {
$array = new object(i);
}
$array->doSomethingEvil;
fix
Синтаксис неправильный у меня, простите.
Но суть, наверное, нормальная.
Храни в куках какую-нибудь ебанутую хуйню, но которая связана с юзером.
Например зашифруй его логин через md5, потом отрежь первые 8 символов этого шифра, посоли и опять зашифруй это говно. Такое практически нереально сломать, если не спиздить твой код. Далее в базу добавь поле, в которое, при удачном логине тоже будет записываться какое-нибудь зашифрованное говнецо, и делай как имя куки, а то как пароль, и сверяй при переходе на другие странички.
Мимодиванный
Проблемс? Укажи мне на то, как это говно можно обойти? Просто так куку не дешифровать, спиздив чужую тоже незалогиниться, ибо кусочек в базе не будет соответствовать, разве что надо при логауте в базе смешивать код с говном. Главное кароче что бы по куке хаккер не мог имя юзера вычислить, а пароль никого неебет тащем-то
Сукпзц, ты школьник что ли? Я тебя попросил ткнуть меня носом в недостаток, а ты какую-то клоунаду разводишь.
Да ты доебал меня уже, блядь. Не можешь свою анальную илитарность отбросить, и разговаривать с человеком не сквозь призму своих ебаных ярлыков, навешанных в первую секунду. Кроч, ты меня понял.
Быстро ты тему скатил на мою личность, вместо конструктива. Я бы задумался, кто тут настоящее двачебыдло, перед тем как кидаться словами.
Сириусли, доебал. Ты тот даун который просил помощь с регулярками, или ты местный?
Сириусли? Хорошо что ты мне сказал, а то я и не понял. Думал я тут поведение школьников изучаю, которые пытаются гринтекстом писать.
С тобой ведь бесполезно разговаривать? Каждая твоя фраза будет состоять из визгливых попыток меня задеть?
Я просто не опускаюсь до твоего уровня, я бы мог отвечать тебе в твоем же стиле, но это как-то... примитивно что ли. Картинка_про_баттхерт.жпг
Оставляю последнее слово за тобой, посмотрим что ты там кукарекнешь напоследок.
Бомбануло у псевдоэлитки!
Как правильно обращаться к сумме часов каждого сотрудника для их дальнейшего сложения(чтобы вывести в "Всего")?
21, да.
Ну, я уже заебался его приближать.
ухаживаешь такой за тянкой месяцами, а её какой-то ерохин на вписке за 1 вечер выебал, всё как в жизни. Гордись дальше, хули.
ну ты чего такой тупорогий? Али ты тралить пришел сюда?
попробуй для начала
if (47) {
echo "true"
}
а потом бы и не пришлось тут хуйни нести, да?
да я шучу, на самом деле я знал что так будет.
Я поблагодарил без сарказма, полчаса мудился с этой простейшей хуитой.
Я думал по возможности обойти md5, о котором я мало чего знаю. У меня были мысли такие, например, для каждого id, которое должно храниться в куках, сделать битовый сдвиг влево, например на 20 значений. То есть, айди пользователя, к примеру, "5". Предположим что php хранят такие небольшие значения в двух байтах. Тогда значение 5 в двоичной системе выглядит: 0000000000000101. Делаем (циклический!) сдвиг, например, 20 раз влево. Получим 0000000001010000. Оно уже в куках будет храниться как "80". Добавим к этому инверсию. Будет 1111111110101111, такое значение в куках будет выглядеть как "65455". Но что если каким-то образом значения для разных пользователей могут случайно повторяться? Все эти выкрутасы, это конечно хорошо, но нам нужен такой алгоритм, который гарантирует невозможность восстановления и невозможность случайного повторения. И тут приходит он, MD5, который я лично не знаю, но слышал что это один из таких алгоритмов, который гарантированно превращает значение в набор уникальных недешифруемых символов.
Мораль сей басни такова. Нехуй выёбываться, ребята, используйте стандартные функции и будьте счастливы.
http://ideone.com/UAwBcA
В чем ошибка, или мб я что-то делаю не так?
> я добавлю метод подсчета количества сотрудников определенного типа.
наверно лучше не метод подсчета, а метод поиска (отобратьСотрудников) который найдет и вернет массив сотрудников (с которыми потом можно что-нибудь сделать
> я создам класс Кризис в котором буду находить сотрудников которых необходимо уволить, и с помощью нового метода в Депортаменте увольнять их
Логичнее назвать класс АнтикризисноеУправление или просто Руководсвто, но ты можешь сделать это и в функции если хочешь.
> это как проверить всех сотрудников в каждом департаменте?
у тебя же есть в департаменте массив сотрудников. Берешь из него только сотрудников нужного типа, сортируешь их по нужному критерию и берешь первых N. И возвращаешь этот массив.
> Есть идея создать класс который будет хранить в массиве каждого сотрудника
Этот класс уже есть — Департамент
>>444144
Можно походить. Сказать что нет опыта но быстро учишься и готов показать гитхаб и сделать тестовое задание.
>>444147
Циклом
>>444168
Молодец, решение правильное.
> почему не хочет компилировать задачку?
Если ты используешь кнопку indeone it, то ошибки не выводятся. Перезагрузи страницу чтобы их увидеть (я им отписал о баге, они потом его исправят).
>>444220
$subject[$key] = ....;
писать
$value = ...
бесполезно так как value содержит только копию значения и при его изменении массив не изменится.
Ну или ты можешь писать &$value но тут куча подвохов ии ты должен сначала прочесть и понять весь раздел про ссылки: http://php.net/manual/ru/language.references.php
Также прочитай предупреждения тут http://php.net/manual/ru/control-structures.foreach.php
Я бы не советовал лишний раз использовать ссылки.
> я добавлю метод подсчета количества сотрудников определенного типа.
наверно лучше не метод подсчета, а метод поиска (отобратьСотрудников) который найдет и вернет массив сотрудников (с которыми потом можно что-нибудь сделать
> я создам класс Кризис в котором буду находить сотрудников которых необходимо уволить, и с помощью нового метода в Депортаменте увольнять их
Логичнее назвать класс АнтикризисноеУправление или просто Руководсвто, но ты можешь сделать это и в функции если хочешь.
> это как проверить всех сотрудников в каждом департаменте?
у тебя же есть в департаменте массив сотрудников. Берешь из него только сотрудников нужного типа, сортируешь их по нужному критерию и берешь первых N. И возвращаешь этот массив.
> Есть идея создать класс который будет хранить в массиве каждого сотрудника
Этот класс уже есть — Департамент
>>444144
Можно походить. Сказать что нет опыта но быстро учишься и готов показать гитхаб и сделать тестовое задание.
>>444147
Циклом
>>444168
Молодец, решение правильное.
> почему не хочет компилировать задачку?
Если ты используешь кнопку indeone it, то ошибки не выводятся. Перезагрузи страницу чтобы их увидеть (я им отписал о баге, они потом его исправят).
>>444220
$subject[$key] = ....;
писать
$value = ...
бесполезно так как value содержит только копию значения и при его изменении массив не изменится.
Ну или ты можешь писать &$value но тут куча подвохов ии ты должен сначала прочесть и понять весь раздел про ссылки: http://php.net/manual/ru/language.references.php
Также прочитай предупреждения тут http://php.net/manual/ru/control-structures.foreach.php
Я бы не советовал лишний раз использовать ссылки.
& имеет много подвохов, пример:
foreach ($a as &$value) {
echo "$value\n";
}
foreach ($b as &$value) {
echo "$value\n";
}
Видишь ли ты ошибку в этом коде? Для начинающего ее трудно увидеть. Если нет то тебе (и всем остальным анонам) лучше прочесть мануал про ссылки и не использовать их пока не разберешься.
>>444326
Ты еще с яваскриптом не работал наверно.
Ну и я надеюсь что ты меняешь язык на язык с типизацией вроде Явы или C#? Потому что в тех же Руби или Питоне все еще хуже, там даже тайп хинтов нет, а в Питоне еще и private. Я не представляю как там вообще программы больше чем на 500 строк писать можно.
Ну и справедливости ради, зачем ты сравниваешь строку с числом? Ты же сам создаешь себе проблему. Пиши in_array(..., array('1', '2')) и проблема внезапно исчезнет.
>>444336
Если ты сравниваешь значения разных типов то идет преобразование. Не сравнивая значения разных типов либо же используй строгое сравнение.
>>444362
Это надо массив. Циклом создаешь объекты и кладешь в массив. Ты предыдущие задачи решал?
& имеет много подвохов, пример:
foreach ($a as &$value) {
echo "$value\n";
}
foreach ($b as &$value) {
echo "$value\n";
}
Видишь ли ты ошибку в этом коде? Для начинающего ее трудно увидеть. Если нет то тебе (и всем остальным анонам) лучше прочесть мануал про ссылки и не использовать их пока не разберешься.
>>444326
Ты еще с яваскриптом не работал наверно.
Ну и я надеюсь что ты меняешь язык на язык с типизацией вроде Явы или C#? Потому что в тех же Руби или Питоне все еще хуже, там даже тайп хинтов нет, а в Питоне еще и private. Я не представляю как там вообще программы больше чем на 500 строк писать можно.
Ну и справедливости ради, зачем ты сравниваешь строку с числом? Ты же сам создаешь себе проблему. Пиши in_array(..., array('1', '2')) и проблема внезапно исчезнет.
>>444336
Если ты сравниваешь значения разных типов то идет преобразование. Не сравнивая значения разных типов либо же используй строгое сравнение.
>>444362
Это надо массив. Циклом создаешь объекты и кладешь в массив. Ты предыдущие задачи решал?
>Потому что в тех же Руби или Питоне все еще хуже
Ну тащем-то проблема тут не в динамической типизации, а в слабой типизации, преобразованиях по умолчанию между совершенно разными типами. В руби с питоном такой хуйни нет.
И да, хотел вам еще неплохих задачек подкинуть чтобы размять мозги: http://download.yandex.ru/company/shad/exam.pdf
Ну примерно такие задачки дают на собеседовании на джуниора по языку Хаскелл, причем там время ограничено. Плюс могут специально создавать стрессовую ситуацию чтобы проверить как ты способен с ней справиться.
Если ты не можешь догадаться, я могу подсказать путь решения по первой или второй задачке и немного по четвертой
Ну вот по четвертой мне кажется 1. Дисперсия судя по определению это отклонение от мат.ожидания. Если мат ожидание будет выпадать на границу, то максимальная дисперсия будет на другой границе.
Я решил пятую кстати, она не сложная.
В википедии есть определение: https://ru.wikipedia.org/wiki/%D0%94%D0%B8%D1%81%D0%BF%D0%B5%D1%80%D1%81%D0%B8%D1%8F_%D1%81%D0%BB%D1%83%D1%87%D0%B0%D0%B9%D0%BD%D0%BE%D0%B9_%D0%B2%D0%B5%D0%BB%D0%B8%D1%87%D0%B8%D0%BD%D1%8B
Дисперсия это среднее значение ((x - среднее(x)) ^ 2)
Среднее от случайной величины это 0.5
Разница (x - 0.5) принимает значения от -0.5 до 0.5 (равномерно), а ее квадрат от 0 до 0.25. Но этот квадрат распределен неравномерно, какие-то значения встречаются чаще, какие-то реже. Потому как найти мат. ожидание от этого квадрата, не очень понятно. тут явно нужна какая-то формула, может надо площадь на графике найти и на что-то поделить.
Ну а если требуется найти площадь то очевидно придется брать интеграл, от x в квадрате индеграл это x в третьей степени умножить на что-то.
Ну еще 0,5 может быть при нормальном распределении, один хуй.
То есть мы можем взять распределение, при которм 0 или 1 выпадают с вероятностью 0,999..., а все остальные значения - с бесконечно малой вероятностью. Тогда дисперсия стремится к 1.
Хотя с математикой у меня хуево, могу что-то важное тут упускать.
Да, я ошибся с тем что распределение должно быть нормальным.
Но вот насчет 1 я не уверен. Смотри, если у нас выпадают только значения 0 и 1 равномерно то среднее будет 0.5, квадрат разницы будет 0.25 и его среднее тоже будет 0.25. Единица не получается.
Если у нас все время выпадает 0 и очень редко 1 то среднее будет около 0.0001 и среднее отклонение тоже будет очень маленьким.
То есть насчет 1 я не уверен. Чтобы было отклонение = 1 надо чтобы среднее было например 0, а средний квадрат разницы = 1, не представляю как такого добиться.
Дисперсия как я понимаю, это среднее от квадрата отклонения (а не максимальное отклонение). Если у нас среднее значение 0 (то есть большиснтво значений около нуля), то вряд ли получится средняя дисперсия 1 .
>>444637
Вы правы, я забыл определение дисперсии.
Тогда ответ - 0.25, тут хорошее и простое объяснение: http://math.stackexchange.com/questions/769923/maximum-possible-variance
Эта?
> Еще более сложная и долгая задача на Yii/Yii2
Там много таблиц будет. для тестов, для вопросов, ответов и т.д.
А ты про отношения между таблицами знаешь? Вот это читал? http://jtest.ru/bazyi-dannyix/sql-dlya-nachinayushhix-chast-3.html
задачи отсюда решал? https://gist.github.com/codedokode/10539213
Ну и ты можешь показать схему БД а я скажу все ли верно и где подвохи.
И ты вторую задачу решил, про файлообменник? Комментарии к файлам сделал древовидные? Может стоит с них начать тогда, а не браться за сложное?
http://jsfiddle.net/u0pjLzcz/1/ ничего не изменилось с этим хаком. Вообще не могу врубиться в его смысл.
>float всегда ставит display = block
Зачем тогда тут http://nicolasgallagher.com/micro-clearfix-hack/demo/
указан inline?
>Не, так не пойдет. Надо чтобы работало с картинками неизвестного размера (например они могут браться из базы данных и заранее размер неизвестен).
У меня такое ощущение, что ты ставишь свойства наугад, в надежде что заработает. Это неправильно. надо понимать эффект от разных свойств и ставить те, которые нужны.
Например, у нас задача чтобы блок с картинкой (figure) с одной стороны зависел от размеров картинки, с другой стороны не превышал ширины родителя.
Давай подумаем, а в каких случаях ширина элемента зависит от содержимого? Ровно в трех: display: table/table-cell, display: inline-block/inline, float.
Я что-то вообще не понял, каким образом мне тут поможет inline-block для figure. Он и так нужной нам ширины. На figcaption вообще я не вижу смысла ставить дисплей. У него контент это текст внутри, а не картинка, он от неё никак не зависит, что бы я там не ставил:
http://jsfiddle.net/wbvgwdph/1/
> Зачем тогда тут http://nicolasgallagher.com/micro-clearfix-hack/demo/ указан inline?
По ошибке. Либо по старой памяти - во времена IE6 display inline исправлял баг с отображением флоатов (не влияя на другие браузеры): http://www.positioniseverything.net/explorer/doubled-margin.html (я этот хак наизусть помнил)
Поэтому ты не должен бездумно копировать код. Ты должен понимать каждую строчку. А если не понимаешь, можно спросить у меня.
> ничего не изменилось с этим хаком.
Ты ошибку сделал при его копировании. Вместо graybox написал content.
Давай разберемся в чем суть хака. Для начала тебе надо почитать где-нибудь про псевдоэлемнты :before и :after. Иди, почитай.
Так вот, эти псевдоэлементы можно через CSS добавить в начало и конец любого элемента. На них конечно накладываются определенные ограничения, но для наших целей они подходят. Суть хака в том что мы добавляем конец блока невидимый (так как он содержит пробел и ему можно выставить высоту в 1px) псевдоэлемент со свойством clear:both. это свойство заставляет его опуститься ниже края всех флоатов, и растягивает серый блок до нужной высоты.
Ты можешь спросить зачем там display: table и зачем псевдоэлемент before? Хак будет работать и без них. Там дано объяснение в комментарии:
> The use of `table` rather than `block` is only necessary if using
> `:before` to contain the top-margins of child elements.
Добавление элемента с display:table видимо предотвращает эффект вываливания границ нижнего и верхнего элемента за родительский блок (margin collapsing). Этот эффект описан тут: http://softwaremaniacs.org/blog/2005/09/05/css-layout-flow-margins/
Почему именно table его предотвращает, я точно не знаю. Но ты можешь попробовать поискать ответ в стандарте CSS3 где детально описаны условия возникновения этого эффекта: http://www.w3.org/TR/css3-box/#collapsing-margins (англ, очень много букв)
Надеюсь, я тебя не запутал. Чтобы увидеть псевдоэлементы, замени content: " "; на content: "hello"; и посмотри сам.
> Зачем тогда тут http://nicolasgallagher.com/micro-clearfix-hack/demo/ указан inline?
По ошибке. Либо по старой памяти - во времена IE6 display inline исправлял баг с отображением флоатов (не влияя на другие браузеры): http://www.positioniseverything.net/explorer/doubled-margin.html (я этот хак наизусть помнил)
Поэтому ты не должен бездумно копировать код. Ты должен понимать каждую строчку. А если не понимаешь, можно спросить у меня.
> ничего не изменилось с этим хаком.
Ты ошибку сделал при его копировании. Вместо graybox написал content.
Давай разберемся в чем суть хака. Для начала тебе надо почитать где-нибудь про псевдоэлемнты :before и :after. Иди, почитай.
Так вот, эти псевдоэлементы можно через CSS добавить в начало и конец любого элемента. На них конечно накладываются определенные ограничения, но для наших целей они подходят. Суть хака в том что мы добавляем конец блока невидимый (так как он содержит пробел и ему можно выставить высоту в 1px) псевдоэлемент со свойством clear:both. это свойство заставляет его опуститься ниже края всех флоатов, и растягивает серый блок до нужной высоты.
Ты можешь спросить зачем там display: table и зачем псевдоэлемент before? Хак будет работать и без них. Там дано объяснение в комментарии:
> The use of `table` rather than `block` is only necessary if using
> `:before` to contain the top-margins of child elements.
Добавление элемента с display:table видимо предотвращает эффект вываливания границ нижнего и верхнего элемента за родительский блок (margin collapsing). Этот эффект описан тут: http://softwaremaniacs.org/blog/2005/09/05/css-layout-flow-margins/
Почему именно table его предотвращает, я точно не знаю. Но ты можешь попробовать поискать ответ в стандарте CSS3 где детально описаны условия возникновения этого эффекта: http://www.w3.org/TR/css3-box/#collapsing-margins (англ, очень много букв)
Надеюсь, я тебя не запутал. Чтобы увидеть псевдоэлементы, замени content: " "; на content: "hello"; и посмотри сам.
Все же position absolute на figure тут не годится. Если за fogure будет идти текст то он окажется под картинкой так как она не занимает места в потоке.
Ну и картинка не сужается. Я подозреваю, это из-за того что ты не задал left/right. Если их задать то max-width начнет действовать.
> Я что-то вообще не понял, каким образом мне тут поможет inline-block для figure.
Он тебе поможет тем, что inline-block умеет подстраивать ширину под содержимое.
> На figcaption вообще я не вижу смысла ставить дисплей
Не ставь
Без position absolute на figure у figcaption родитель становится body, и я не смогу задать ему ширину относительно картинки. Если только совсем убрать position у всех элементов. Но как тогда разместить figcaption внутри картинки?
Можно задать position: relative. Он в большиснтве случаев для этого и используется. Тут описано: http://softwaremaniacs.org/blog/2005/08/03/css-layout-positioning/
> Но самое интересное, что этот позиционированный бокс сам внутри себя создает такой же стакан, и все его дети (боксы, находящиеся у него внутри) позиционируются уже относительно него, а не относительно окна. И внутри него происходит то же самое: любой позиционированный (не static) бокс создает внутри себя такой стакан.
«позиционированный» значит имеющий значение свлойства position отличное от static, например absolute, relative, fixed (и sticky который в будущем появится).
Не, это не хорошая идея, ставить на каждый тег класс. Есть более простое решение, вместо того чтобы ставить отступ через margin на каждом элементе, можно поставить padding на родителе. Это же кстати написано в подсказках к заданию.
> С тегом ol Все равно криво выглядит, почему-то цифры в нумерованном списке не считаются за контент и лезут в зафлоаченный блок.
Так всегда и было. Но это можно исправить: http://jsfiddle.net/vxkL3uj1/1/
Вот это свойство: http://htmlbook.ru/css/list-style-position
В стандарте 2.1 написано: http://www.w3.org/TR/CSS21/generate.html#propdef-list-style-position
> outside
> The marker box is outside the principal block box. The position of the list-item marker adjacent to floats is undefined in CSS 2.1.
Ок, хорошо, только я бы после font-samily еще добавил serif и указал line-height везде где есть font size. А так, все верно.
Попадет. Но ты можешь задвинуть его влево например отрицательным маргином. У меня даже картинка есть: https://gist.github.com/codedokode/3f6063edf0a2227eb313
Все равно, через паддинг делать поля гораздо проще и надежнее чем маргины на каждый элемент ставить и что-то пропустить.
>echo '<script>window.location.href = "page.php";</script>';
это нормально или можно сделать лучше?
Вот вроде бы написал функцию которая делает 1 шаг, это было легко, но что дальше то делать, чет догнатьь не могу, помогите анончики, был перерыв в решении задачек, и мозг зачерствел что-то.
Ну если ты на пхп пишешь, то можно php функцией header(); переносить, например:
header('Location: /index.php');
Это ненормально. Есть же заголовок location
>>444773
Вроде смотрится правильно, но я бы сделал note флоатом. А то если рядом 2 примечания поставить, они накладываются: http://jsfiddle.net/wu0cyh8d/2/
>>444774
Надо дописать примерно так:
....
А если за один шаг до цели не добраться, то перебираем все соседние точки, которых нет в пройденном пути. Для каждой точки вызываем ту же функцию для прокладки пути. Из полученных путей выбираем кратчайший и возвращаем.
Ну или ты можешь посмотреть готовые алгоритмы: https://ru.wikipedia.org/wiki/%D0%9F%D0%BE%D0%B8%D1%81%D0%BA_%D0%BF%D1%83%D1%82%D0%B8
Дейкстра например несложный.
Если его сделать флоатом он попадет под padding и будет вместе с остальными элементами страницы.
>Надо дописать примерно так:
Это выглядит большим и сложным, ведь это и есть сразу написать решение, с похоже что парой циклов и несколькими условиями. А можно выделить какой-нибудь такой же простой шаг промежуточный?
Сделай чтобы просто перебирались соседние вершины, которые не входят в путь, и функция вызывала сама себя для них. И чтобы в начале функция печатала название текущей точки (чтобы видеть как она работает).
Не выходит запретить скачивание swf файла (uppod плеера). Все файлы нормально блокируются, а uppod.swf нормально грузиться. В htaccess прописывал по всякому, даже так:
RewriteEngine on
RewriteRule uppod\.swf - [NC,F,L]
Ему похуй.
В идеале хочу проверку на рефера сделать и не отдавать для левых сайтов плеер.
Может там в админке хостинга покопаться надо?
Бросайте Руби! Переходите на PHP! мы этим уже переболели.
class Base {
//базовый класс
//тут в конструкторе создаётся объект производного класса Config
}
class Config extends Base {
//производный класс Config
private $props = array(
'a' => 'A', //это свойство должно быть доступно только из класса TestA
'b' => 'B', //это свойство должно быть доступно из любого класса
'c' => 'C' //это свойство должно быть доступно из любого класса
);
public function __get($name)
{
//получаем приватное свойство из $props
}
}
class TestA extends Base {
print $this->config->get('a');
}
class TestB extends Base {
print $this->config->get('a');
}
Как сделать так, чтобы в TestA метод get вернул A, а в TestB метод не вернул ничего?
class Base {
//базовый класс
//тут в конструкторе создаётся объект производного класса Config
}
class Config extends Base {
//производный класс Config
private $props = array(
'a' => 'A', //это свойство должно быть доступно только из класса TestA
'b' => 'B', //это свойство должно быть доступно из любого класса
'c' => 'C' //это свойство должно быть доступно из любого класса
);
public function __get($name)
{
//получаем приватное свойство из $props
}
}
class TestA extends Base {
print $this->config->get('a');
}
class TestB extends Base {
print $this->config->get('a');
}
Как сделать так, чтобы в TestA метод get вернул A, а в TestB метод не вернул ничего?
Сделал сам, коряво, но хоть как-то. Есть примеры годного решения?
чет я тебя не понял, ну через иф например
if ($_GET['huy'] == 1) {
str_replace("huy", "<b>huy</b>");
}
например как вариант.
Но опять же неясно что у тебя там за гет и что вообще на странице, пиши подробнее в след раз.
Конкретизируй. Тебе один фрагмент надо жирным выделять или несколько? Они хранятся в переменных или их надо искать в тексте?
Понял как. Что-то я забыл что можно так сделать. Завтра жди отчета, сегодня, к сожалению, я поздно прочел твой пост.
лолблять, я эникею в госконторе, а пхп это от скуки и для учебы. Устроился просто - пришел, сказал, хочу эникеить, взяли, платят 500 баксов по новому курсу.
Для древовидных комментов это правильное решение?
Или нужно больше вложенности и с новым уровнем новую таблицу создавать?
На мой нубский взгляд можно просто сделать еще одно поле в таблице, где будет указан id родительского коммента.
Ребята, почему вы решили изучать ПХП? Почему не выбрали другой язык а-ля питон или руби? Я не траль, просто интересно. В двух словах поясните плиз.
Я начинал с руби, работу без опыта на нём не найдешь
Относительно просто, относительно много обучающего материала, полно работы, неплохо платят.
А поясни за связи между таблицами, все вот эти онапдейтс, ондилит, а то я нубас, но скоро мне все это пригодится.
>как проверить всех сотрудников в каждом департаменте?
>у тебя же есть в департаменте массив сотрудников. Берешь из него только сотрудников нужного типа, сортируешь их по нужному критерию и берешь первых N. И возвращаешь этот массив.
У тебя в задаче дано:
>антикризисный код вроде «уволить 30% сотрудников» не должен быть в классе Департамент (так как бороться с кризисом задача руководства компании, а не департамента), но ты можешь написать в департаменте универсальные методы вроде «уволить указанных сотрудников» или «выбрать N% сотрудников определенного типа».
Исходя из этого, мне следует увольнять 30% сотрудников где-то снаружи/в дргугом классе. Но как мне обратится снаружи ко всем созданным классам?
Ведь в коде они у меня создаются таким образом:
>$procurement = new Department('Procurement');
>$sales = new Department('Sales');
Как пройтись по всем созданным объектам класса Department?
>В тех департаментах, где руководитель не является аналитиком, заменить его на аналитика самого высшего ранга из этого департамента (а бывшего руководителя вернуть к обычной работе)
А что делать если в департаменте нету ни одного аналитика? Оставлять все как есть?
>>445008
Да
>>445007
Положить их в массив и сделать цикл. Либо сделать класс Компания и в нем массив департаментов и опять же цикл.
> margin-left: -130px;
> \tmargin: 10px;
Ты же сам переопределил маргин ниже.
Кстати, а ты пользуешься инспектором в браузере (Ctrl + shift + I, в ИЕ жать F12)? Он в том числе показывает какие свойства применены к элементу, какие у него размеры и отсиупы и кучу полезной информации. Верстальщик должен уметь им пользоваться так что если не умеешь то почитай про него:
http://habrahabr.ru/post/143767/
https://developer.chrome.com/devtools (англ, более новая)
Если бы ты им пользовался то причину ошибки бы увидел сам.
>>444893
Как хранить в БД древовидные структуры: https://gist.github.com/codedokode/10539720
> Или нужно больше вложенности и с новым уровнем новую таблицу создавать?
Ты так таблиц не напасешься. Хватит одной таблицы, прочитай урок выше. Кстати, вопрос про деревья в базе любят задавать на собеседованиях, так что это может пригодиться.
То, что у тебя, какой-то велосипед с одним уровнем вложенности. Не надо изобретать велосипеды, надо изучить существующие паттерны.
>>444897
Ты тоже почитай урок выше, если интересно. Есть другие методы.
>>444866
Ты его переопределил ниже.
>>444960
Это называется внешние ключи: http://denis.in.ua/foreign-keys-in-mysql.htm
Используй их всегда.
>Положить их в массив и сделать цикл. Либо сделать класс Компания и в нем массив департаментов и опять же цикл.
А как их складывать в массив? Допустим я создам массив $департаменты, как мне в него передать все возможные объекты класса Департамент, вместе со всеми сотрудниками?
Попробую перефразировать вопрос.
Как получить в массив все объекты класса Департамент?
Это снова я, из прошлого треда, прилепил к своему скрипту калькулятора побед - заглавную страницу и страницу вывода.
Так вот, как лучше - все это запихать в один index.php и с ним уже работать через GET и другие параметры или сделать для каждого отдельную страничку - отдельно для добавления записи, отдельно для всего списка, отдельно для записи и комментов к ней? Я прост не понимаю, как надо правильно.
Чую жопой, мой планируемый перекат-это же смена шила на мыло, да? Вразуми, анон.
Что-то я не могу понять, каким образом она с помощью бордеров различные фигуры делает?
Если снизу и слева бордеры имеют разный цвет, то стык получается треугольной формы. Попробуй сделать бордер большой ширины и разных цветов и увидишь. Если теперь один из бордеров сделать прозрачным, а высоту и ширину дива равной нулю, получится треугольник. Это старый трюк: http://htmlbook.ru/blog/treugolniki-cherez-css
Причем современные браузеры ради этого трюка сглаживают уголки (антиалиасинг). Раньше вроде этого не было и уголки получались лесенкой (или это было в ИЕ? не помню).
Если ты хочешь хорошо знать CSS, изучи этот трюк.
А тут описано как сделать треугольник с тенью: http://habrahabr.ru/post/142534/
>>445042
> Задавали какие-то теоретические вещи, которые не нужны на практике.
Может быть как раз нужны.
>>445035
Правильно было бы использовать фреймворк с контроллерами и решать это его средствами. А если ты делаешь велосипед то разницы нет.
Ну и GET можно использовать только для запросов не меняющих ничего на сервере. Править и удалять надо через POST.
>>445019
Это какие-то кривые костыли. Использовать статические свойства (ты хотя бы мануал почитал по ним надеюсь?) плохая идея так как они общие для всех экземпляров класса. Например, если ты захочешь сделать клон компании то у тебя будет в этом массиве не 4 а 8 департаментов и все запутается.
Храни департаменты либо в обычном массиве либо сделай класс Компания и храни в ней.
>фреймворк с контроллерами
По сути, это то же самое, что делаю я, когда конфигурирую свой проект, связывая все вместе, только запиленное умными людьми и с кучей свистоперделок, правильно понимаю?
Алсо, как правильно вставлять HTML-код в php-файлы? Тупо через echo набивать все что мне нужно?
Еще поясните за конфигурацию подключения к базе. У меня есть два файлика db.php и config.php. В конфиге лежат пароль, логин и путь до базы и прочая лабуда, а в db - код подключения к базе (с include до конфига). Если мне надо работать с базой, я вызываю через include db.php и работаю. Немного коряво объяснил, но надеюсь, понятно. Так вот, с точки зрения безопасности, удобства и прочего - это вообще нормально или я опять делаю не то?
Анон, подскажи простую вещь, как просто вызвать функцию?
Суть такова, у меня есть например строка, например "hui", я хочу чтобы запустилась функция hui(). Аналогично с другими строками. Вроде бы просто, но никак не могу понять как такую фигню запилить. Пока решил генерированием файлика с вызовом функции и последующим его инклудом
Внезапно. Вот так вот работает:
$_GET['method']($arg);
В $_GET['method'] просто строка с названием функции
Ты открываешь дорогу хакерам таким кодом. Они же могут любую функцию из тысяч имеющихся вызвать.
используй if/elseif или switch
>>445063
Если ты такие «решения» придумываешь то значит ты плохо знаешь PHP и тебе надо его изучить как следует, а не браться делать сайты.
>>445061
> Алсо, как правильно вставлять HTML-код в php-файлы?
делать шаблоны: http://www.phpinfo.su/articles/practice/shablony_v_php.html
У нас в треде есть полезные задания (в шапке), решая которые ты бы научился все это делать правильно. Сам ты сделаешь скорее всего что-то кривое, глючное и с уязвимостями. Надо сначала научиться, а потом за сайты браться.
> Так вот, с точки зрения безопасности, удобства и прочего - это вообще нормально или я опять делаю не то?
Именно в этом ничего опасного нет
>делать шаблоны
О, спасибо, посмотрю сейчас.
> Сам ты сделаешь скорее всего что-то кривое, глючное и с уязвимостями. Надо сначала научиться, а потом за сайты браться.
Стараюсь делать параллельно и то и то, так уж получилось.
>Храни департаменты либо в обычном массиве либо сделай класс Компания и храни в ней.
Ну а как передать тогда департаменты в него???
$company->addDepartment($dep);
или
$company->addDepartments([
$dep1,
$dep2
]);
Честно говоря не понял, что именно тут сложного.
У меня все ограничено одним лишь классом. То есть:
$foobar = new FooBarClass();
$foobar->$_GET['method']($arg);
Так я в меньшей опасности? Приложение просто не станет работать если я вызову что-то не из этого класса. Вообще изначально был switch, но я хочу нечто универсальное.
>ты плохо знаешь PHP
Я вообще мало чего знаю
>а не браться делать сайты
Да вот как-то на работе мне не дают что-то спокойно изучать. Есть задача - ебись как хочешь. И нужно чтобы было сделано еще вчера.
>Я вообще мало чего знаю
Это он мне отвечал, не парься. Я действительно еблан и не шарю, а пхпой занимаюсь чисто от скуки и потому что по учебе надо.
Почему? Я знаю о руби и о другой функциональщине. Мне очень нравится, но пока не было проектов на руби/других лиспах и вряд ли появятся
https://www.youtube.com/watch?v=xCUt4Z1W3Ps&list=PLov7vC9M_skKZj_R1MnVwqJTMi7HZjUrE&index=17
Нормальный источник?
Я думал нужно не в ручную это сделать. Мы же отличники и победители олимпиад :3
Сейчас сделаю все.
Не учил уии, сразу начал писать. Причем потом появился уии2, быстро перекатился на него, испытал бугурт от изменений и все
ну засунь тогда пустую ссылку в ячейку и назначь ей display:block или inline-block
Не понял тебя.
А какой тогда фреймворк лучше учить? Я хотел для устройства на работу выучить какой-нибудь один популярный фреймворк что бы вписать его в резюме, как плюс к трудоустройству YII показался самым понятным, его и реши выучить, много где в вакансиях для джуниоров видел требование YII
Там какой-то омежный заикающийся колхозный школьник, выдающий перлы типа "автоинструмент", "фреймовик" и т.д.
Читай лучше документацию на офф.сайте. Или покопайся в коде демо-приложения.
$a = 10;
$b = '+';
$c = 5;
$abc = $a . $b . $c;
var_dump($abc) выдает не желаемое int(15), а строку string(4) "10+5". Видимо проблема в том что $b - строка, и складывать он не хочет. Что с этим делать, кто подскажет?
Не ОП.
Почитай PSRы. Ты все, что можно нарушил, это как минимум. И как по твоему коду строить антикризисные модели, что упоминались в предыдущем треде?
В том дело, что (.) - это оператор склеивания СТРОК, стало быть у тебя при её использовании числовые переменные автоматически перегоняются в строчные.
Нет конечно, тебе нужен eval: http://php.net/manual/ru/function.eval.php
Ну или switch по арифметическому оператору.
Суть. Установил Денвер на комп. Но при этом глоб.переменная Get не раьотает (когда открываю через тест ру)
Какие могут быть ошибки?
Пикрандом
Спасибо.
http://ideone.com/wflQGe
Добавление антикризисных решений заняло 145 строк кода. Весь класс CrisisModel этому посвящен. В принципе, вышло бы меньше, если бы я не использовал класс-хелпер для вывода в виде таблицы, класс-хелпер для парсинга коротких строк вида "9×ме1" в нужные в моей реализации ассоциативные массивы. У меня все строится на диспетчеризации. Тестировочные функции, показывают, чего стоит: добавление нового класса рабочего, изменение условий (пример: з/п) (я почему-то решил делать это через статические свойства и методы).
Сегодня увидел расширение задачи про принятие антикризисных мер и накатал еще кода. Я изначально понимал, что ООП нужно для создания универсального кода, с максимально простым расширением функционала. Читал про паттерны, здесь применил некое подобие "Фабрики".
И еще парочка нюансов, которые я узнал про работу PHP. Я пришел из мира Python, поэтому кое-что буду сравнивать с ним.
1. В голове нужно всегда держать возможности из коробки, такие вещи как array_merge(), array_combine(), array_map() с анонимными функциями func(), usort() и т.д.
2. Внимательно следить за определением и использованием $this и self. (Верно $this->property, self::$property).
3. При клонировании, если хотите обнулить существующие свойства необходимо в методе __clone() сделать это явно.
А методы для работы с этими свойствами придется применять извне как я понял, но могу ошибаться.
4. Вот не рабочий код на PHP: http://ideone.com/GrsEJ1. Аналогичное в python работает: http://ideone.com/fM1m3v. Знающие, подскажите как реализовывать такое.
Читай про замыкания и анонимные функции.
function f1(){
$first = 10;
function () use ($first){
return $first + 5;
}
}
Что за антикризисная модель? Я вроде бы через ПХП форматер пропускал код.
Поставил себе убунту на виртуальную машину, сижу смотрю на нее.
Знаю как сменить права, создать файл, папку етс. Что еще может пригодиться?
В некоторых вакансиях просят "уметь поднять сервер". Нет ли короткого гайда?
А то я тут скачал курс по системному администрированию, сижу слушаю про какие-то шины, драйвера и прочие увлекательные вещи.
>В некоторых вакансиях просят "уметь поднять сервер". Нет ли короткого гайда?
Это очень просто на убунте, например. Там все из коробки, и пхп и апач и скуль.
По началу, процесс проходил стандартно. Каловая масса вываливалась из меня словно шоколадный град но потом я почуял не ладное. Это была она, мерзкая подлива. Тонкой струйкой она вытекла из моего напряженного ануса. Словно горный ручей, каловый поток извергался из меня струясь в глубины унитаза и смешиваясь с тамошними водами. Я уже и не ждал у моря погоды как снова обратно выбуривая из пучин прямой кишки выходили коричневые гномики словно они долго плыли по фикальным ручьям из черной бездны. Раздирая анальные врата они рвались на свободу, в новые, прозрачные воды унитазариума. Вены в моей голове начали пульсировать, а задние врата потрескивать от наплыва коричневых беженцев. Пришлось под напрячься еще сильнее и тут анальные врата пуще прежнего заскрипели и, не выдержав дикого напора, анальные петли треснули и под натиском фикаломассы полились багровые реки. Анальный портал кровоточил, меня обуял страх, а фикалоиды все не кончались. Боль пронзила мое тело, анус был в огне. Треск жопы разразился громом на соседние окрестности продолжившийся кровавой молнией и анальными реками.
Потом я очень долго заживлял мой анальный храм, многое пришлось пережить. Но теперь я научен печальным опытом, больше не буду питаться в макдональдс!
Задание: напиши программу для учета расходов и результатов работы всего дружного коддектива компании «Вектор».
Пока ты решал задачу по выводу отчета о сотрудниках и департаментах, разразился мировой экономический кризис. Доходы компании начали снижаться, и совет директоров поставил перед руководством задачу принять меры. Менеджеры 3-го ранга, блестящие выпускники топовых экономических вузов столицы, быстро смогли разработать три альтернативных антикризисных решения:
1. Сократить в каждом департаменте 40% (округляя в большую сторону) инженеров, преимущественно самого низкого ранга. Если инженер является боссом, вместо него надо уволить другого инженера, не босса.
2. Увеличить в целях стимуляции умственной деятельности базовую ставку аналитика с 800 до 1100 тугриков, а количество выпиваемого им кофе с 50 до 75 литров. В тех департаментах, где руководитель не является аналитиком, заменить его на аналитика самого высшего ранга из этого департамента (а бывшего руководителя вернуть к обычной работе)
3. В каждом департаменте повысить 50% (округляя в большую сторону) менеджеров 1-го и 2-го ранга на один ранг с целью расширить их полномочия.
Совет директоров в затруднении: какой путь выбрать? Помоги им с этим, распечатав прогноз по потреблению и расходам (аналогичный тому что требуется в задаче) после принятия каждой из мер.
Классы надо обзывать в CamelCase, область видимости методов указывать явно, т.е. не просто function money(), а public/private/protected function money(). У тебя методы - существительные, а надо, чтобы были глаголами, не money(), а calculateMoney() например.
Ну его и учи. Они все простые, просто у них функционал богатый. ПРобуй запилить простенькие бложики на каждом из фреймворков что найдешь, Симфони, уии, Зенд, ну ты понел.
Функционал весь в доках описан, с этим проблем у тебя возникнуть не должно.
Алсо, советую наработки выкладывать на гитхаб, чтобы приходишь на собеседование и даешь тимлиду ссылочку на свой говнокод.
Я так на нынешнюю работу устроился
Пример кода покажи лучше. Телепатов тут нет
Накидал вроде бы что бы функция путешествовала по графу вызывая сама себя: http://ideone.com/jmT6x2
Как дальше оптимизировать её?
А на русском что-нибудь есть? Только не надо эти мантры начинать про пидорах и обязательном знании английского.
Алсо, еще такой же вопрос о заливе/отображении картинок на сайте.
Понятно, что я могу в гугл все это забить и поискать самостоятельно, только не факт, что найду не устаревшую/попросту вредную инфу.
это антикризисные модели? Что-то не видать увеличения количества менеджеров на 50%, сокращения инженеров. И лучше наверное замутить итоговую инфу. Ты специально искажаешь слова (solary, coffe, procent, Депортамент)?
Держи ссылку на документацию, лол.
https://php.net/manual/ru/function.setcookie.php
Там же узнаешь про сессии, куки.
Не читал его уроки. Если не знаешь че делать - запили сайтик с регистрацией(запись в бд mysql/sqlite), после залогинивание/разлогинивание.
Чего непонятно - спрашивай. Могу даже скайп дать, если слишком много непонятно
Есть библиотека ExtJS. Есть фреймворк Zend2.
Структура MVC приложения на ExtJS выглядит следующим образом:
-app
--controller
--model
--store
--view
+extjs
app.js
index.html
Далее. Структура Zend2 выглядит следующим образом примерно:
+config
+data
+module
+vendor
-public
--css
--fonts
--img
--js
--index.php
...
...
Так вот у меня вопрос. Скажите как мне совместить эти две структуры? Где должна находится библиотека extjs в структуре Zend и где вся папка app приложения на extjs.
Есть библиотека ExtJS. Есть фреймворк Zend2.
Структура MVC приложения на ExtJS выглядит следующим образом:
-app
--controller
--model
--store
--view
+extjs
app.js
index.html
Далее. Структура Zend2 выглядит следующим образом примерно:
+config
+data
+module
+vendor
-public
--css
--fonts
--img
--js
--index.php
...
...
Так вот у меня вопрос. Скажите как мне совместить эти две структуры? Где должна находится библиотека extjs в структуре Zend и где вся папка app приложения на extjs.
>Если не знаешь че делать - запили сайтик с регистрацией(запись в бд mysql/sqlite), после залогинивание/разлогинивание.
Я именно это и хочу сделать, точнее, в том числе и это. Пока не дошел еще, на будущее ищу инфу, чтобы потом не искать. Попозже тогда отпишу, надо домой идти.
Почему ты такой тупой? Там же есть кнопочка Edit code, которая кидает тебя на http://cssdeck.com/labs/css-responsive-tabs
И там только html и css присутствуют, никакого js.
Если ты реально пытаешься разобраться, то сиди ковыряйся, или же ты просто бояль спрашиваешь хуйню, что бы что-то спросить?
Каким образом? Догадываюсь, что через :cheked, но как связать div где-то в другой части хтмл документа с инпутом через ксс?
Всё, нашел
http://htmlbook.ru/css/selector/sibling
Только такой способ не работает, если инпут внутри тега <label>
Получается, лучше всегда использовать конструкцию <input><label for>
Есть две таблицы в базе данных, одна с заказами, другая с покупателями. Таблица с заказами (ORDERS) содержит:
Имя товара, его айди, цену и номер заказа(orderid). Таблица с покупателями (users) содержит имя покупателям, и номер заказа (orderid). Можно записать такой запрос:
$sql="SELECT u.name, o.price, o.orderid
FROM users u
INNER JOIN orders o ON u.orderid = o.orderid";
После этого можно получит массив в котором будет содержаться имя покупателя с таблицы (users) цена товара (с таблицы orders), номер заказа. Причём во многих элементах массива номер заказа может быть одинаковый, как вывести эту информацию на страницу, так что бы это выглядело
НОМЕР заказа
-все заказы по этому номеру в виде имени покупателя и цены заказа-
НОМЕР заказа
-все заказы по этому номеру в виде имени покупателя и цены заказа-
До этого делал таким образом брал данные с одной таблицы, по том по номеру заказа доставал все данные с другой таблицы и потом уже формировал многомерный массив для вывода, где номер заказа был ключём. Как это делается с помощью INNER JOIN. Задача кажется часто используемая, можете пояснить если не сложно или поделиться сылочкой где это разбирается, хочу запомнить раз и навсегда как это правильно делается.
Я бы не говорил. Как то мутно звучит. "Жизненная ситуация, нужно идти работать, доучусь на заочном" чутка получше.
Работодателя чаще волнует, что бы тебя внезапно в армейку не забрали на самом деле.
Всем похуй. У меня знакомый к Теме устроился, дропнув инст, мы еще над ним смеялись, типа куда ты поперся в ДС, в метро ночевать будешь, дошираки кушать. В итоге его одногруппники закончили сраный инст, получив никому не нужный диплом, а он ебет тяночек, занимается любимой работой и катается по всему миру в отпусках.
> армейку не забрали на самом деле.
скажу что не годен, это на 98% так
но военник ещё не дали
прокатит?
Лол, тут некоторые вообще за еду работают. А те кто нет, не работают вообще.
Почему нет? Там можно работать тупо за условия труда, которые он запилил, лол.
и н а м и ч е с к и е с т р а н и ч к и н а р н р ) ) ) ) д
н а м и ч е с к и е с т р а н и ч к и н а р н р ) ) ) ) д и
а м и ч е с к и е с т р а н и ч к и н а р н р ) ) ) ) д и н
м и ч е с к и е с т р а н и ч к и н а р н р ) ) ) ) д и н а
и ч е с к и е с т р а н и ч к и н а р н р ) ) ) ) д и н а м
ч е с к и е с т р а н и ч к и н а р н р ) ) ) ) д и н а м и
е с к и е с т р а н и ч к и н а р н р ) ) ) ) д и н а м и ч
с к и е с т р а н и ч к и н а р н р ) ) ) ) д и н а м и ч е
к и е с т р а н и ч к и н а р н р ) ) ) ) д и н а м и ч е с
и е с т р а н и ч к и н а р н р ) ) ) ) д и н а м и ч е с к
е с т р а н и ч к и н а р н р ) ) ) ) д и н а м и ч е с к и
с т р а н и ч к и н а р н р ) ) ) ) д и н а м и ч е с к и е
с т р а н и ч к и н а р н р ) ) ) ) д и н а м и ч е с к и е
т р а н и ч к и н а р н р ) ) ) ) д и н а м и ч е с к и е с
р а н и ч к и н а р н р ) ) ) ) д и н а м и ч е с к и е с т
а н и ч к и н а р н р ) ) ) ) д и н а м и ч е с к и е с т р
н и ч к и н а р н р ) ) ) ) д и н а м и ч е с к и е с т р а
и ч к и н а р н р ) ) ) ) д и н а м и ч е с к и е с т р а н
ч к и н а р н р ) ) ) ) д и н а м и ч е с к и е с т р а н и
к и н а р н р ) ) ) ) д и н а м и ч е с к и е с т р а н и ч
и н а р н р ) ) ) ) д и н а м и ч е с к и е с т р а н и ч к
н а р н р ) ) ) ) д и н а м и ч е с к и е с т р а н и ч к и
н а р н р ) ) ) ) д и н а м и ч е с к и е с т р а н и ч к и
а р н р ) ) ) ) д и н а м и ч е с к и е с т р а н и ч к и н
р н р ) ) ) ) д и н а м и ч е с к и е с т р а н и ч к и н а
р н р ) ) ) ) д и н а м и ч е с к и е с т р а н и ч к и н а
н р ) ) ) ) д и н а м и ч е с к и е с т р а н и ч к и н а р
р ) ) ) ) д и н а м и ч е с к и е с т р а н и ч к и н а р н
) ) ) ) д и н а м и ч е с к и е с т р а н и ч к и н а р н р
) ) ) д и н а м и ч е с к и е с т р а н и ч к и н а р н р )
) ) д и н а м и ч е с к и е с т р а н и ч к и н а р н р ) )
) д и н а м и ч е с к и е с т р а н и ч к и н а р н р ) ) )
и н а м и ч е с к и е с т р а н и ч к и н а р н р ) ) ) ) д
н а м и ч е с к и е с т р а н и ч к и н а р н р ) ) ) ) д и
а м и ч е с к и е с т р а н и ч к и н а р н р ) ) ) ) д и н
м и ч е с к и е с т р а н и ч к и н а р н р ) ) ) ) д и н а
и ч е с к и е с т р а н и ч к и н а р н р ) ) ) ) д и н а м
ч е с к и е с т р а н и ч к и н а р н р ) ) ) ) д и н а м и
е с к и е с т р а н и ч к и н а р н р ) ) ) ) д и н а м и ч
с к и е с т р а н и ч к и н а р н р ) ) ) ) д и н а м и ч е
к и е с т р а н и ч к и н а р н р ) ) ) ) д и н а м и ч е с
и е с т р а н и ч к и н а р н р ) ) ) ) д и н а м и ч е с к
е с т р а н и ч к и н а р н р ) ) ) ) д и н а м и ч е с к и
с т р а н и ч к и н а р н р ) ) ) ) д и н а м и ч е с к и е
с т р а н и ч к и н а р н р ) ) ) ) д и н а м и ч е с к и е
т р а н и ч к и н а р н р ) ) ) ) д и н а м и ч е с к и е с
р а н и ч к и н а р н р ) ) ) ) д и н а м и ч е с к и е с т
а н и ч к и н а р н р ) ) ) ) д и н а м и ч е с к и е с т р
н и ч к и н а р н р ) ) ) ) д и н а м и ч е с к и е с т р а
и ч к и н а р н р ) ) ) ) д и н а м и ч е с к и е с т р а н
ч к и н а р н р ) ) ) ) д и н а м и ч е с к и е с т р а н и
к и н а р н р ) ) ) ) д и н а м и ч е с к и е с т р а н и ч
и н а р н р ) ) ) ) д и н а м и ч е с к и е с т р а н и ч к
н а р н р ) ) ) ) д и н а м и ч е с к и е с т р а н и ч к и
н а р н р ) ) ) ) д и н а м и ч е с к и е с т р а н и ч к и
а р н р ) ) ) ) д и н а м и ч е с к и е с т р а н и ч к и н
р н р ) ) ) ) д и н а м и ч е с к и е с т р а н и ч к и н а
р н р ) ) ) ) д и н а м и ч е с к и е с т р а н и ч к и н а
н р ) ) ) ) д и н а м и ч е с к и е с т р а н и ч к и н а р
р ) ) ) ) д и н а м и ч е с к и е с т р а н и ч к и н а р н
) ) ) ) д и н а м и ч е с к и е с т р а н и ч к и н а р н р
) ) ) д и н а м и ч е с к и е с т р а н и ч к и н а р н р )
) ) д и н а м и ч е с к и е с т р а н и ч к и н а р н р ) )
) д и н а м и ч е с к и е с т р а н и ч к и н а р н р ) ) )
Я неоднократно от разных людейслышал что там платят ниже рынка, потому что ТЁМА
Я видел код чуваков оттуда, весьма посредственно. А какие там условия труда?
http://ideone.com/ZbyzIY
Во-первых:
array_push($this->a, clone $b);
Во-вторых, какой нахуй пуш, если можно просто
$this->a[] = clone $b;
Нет, я поганый троечник. Сейчас исправлю все.
Там в задаче надо не увеличить количество менеджеров, а повысить их ранг.
>3. В каждом департаменте повысить 50% (округляя в большую сторону) менеджеров 1-го и 2-го ранга на один ранг с целью расширить их полномочия.
Теперь все сломалось. Почему?
\tpublic function calculateDepartmentTotalSalary() {
\t\t$totalSalary = 0;
\t\tforeach ($this->employees as $key => $Employee) {
\t\t\t$totalSalary += $Employee->salary; //Department.php line 30
\t\t}
\t\treturn $totalSalary;
\t}
================
class Employee {
\tpublic $name;
\tpublic $rang;
\tpublic $salary;
\tpublic $coffee;
\tpublic $document;
\tpublic $leader;
\tpublic function __construct($name, $salary, $coffee, $document, $rang = 1, $leader = false) {
\t\t$this->name = $name;
\t\t$this->salary = $salary;
\t\t$this->coffee = $coffee;
\t\t$this->document = $document;
\t\t$this->rang = $rang;
\t\t$this->leader = $leader;
\t\t$this->salary = $this->calculateSalary();
\t\t$this->coffee = $this->calculateCoffee();
\t\t$this->document = $this->calculateDocument();
\t}
Теперь все сломалось. Почему?
\tpublic function calculateDepartmentTotalSalary() {
\t\t$totalSalary = 0;
\t\tforeach ($this->employees as $key => $Employee) {
\t\t\t$totalSalary += $Employee->salary; //Department.php line 30
\t\t}
\t\treturn $totalSalary;
\t}
================
class Employee {
\tpublic $name;
\tpublic $rang;
\tpublic $salary;
\tpublic $coffee;
\tpublic $document;
\tpublic $leader;
\tpublic function __construct($name, $salary, $coffee, $document, $rang = 1, $leader = false) {
\t\t$this->name = $name;
\t\t$this->salary = $salary;
\t\t$this->coffee = $coffee;
\t\t$this->document = $document;
\t\t$this->rang = $rang;
\t\t$this->leader = $leader;
\t\t$this->salary = $this->calculateSalary();
\t\t$this->coffee = $this->calculateCoffee();
\t\t$this->document = $this->calculateDocument();
\t}
>1. Сократить в каждом департаменте 40% (округляя в большую сторону) инженеров, преимущественно самого низкого ранга. Если инженер является боссом, вместо него надо уволить другого инженера, не босса.
>2. Увеличить в целях стимуляции умственной деятельности базовую ставку аналитика с 800 до 1100 тугриков, а количество выпиваемого им кофе с 50 до 75 литров. В тех департаментах, где руководитель не является аналитиком, заменить его на аналитика самого высшего ранга из этого департамента (а бывшего руководителя вернуть к обычной работе)
>3. В каждом департаменте повысить 50% (округляя в большую сторону) менеджеров 1-го и 2-го ранга на один ранг с целью расширить их полномочия.
Есть один сайт с видео. Нужно как-то получать самые просматриваемые за последний час, и это должно работать быстро. В наличии мускль и редис. Как это лучше сделать?
> грамматикой.
Запомните, грамар-наци хуевы, грамматика - это когда говоришь. когда пишешь - орфография и пунктуация.
Да, самое очевидное - с помощью Implode сделать из массива строку с запятыми и подсунуть это строку в IN. Но сомневаюсь в верности такого решения, поэтому спрашиваю.
Хэлп, аноны. Я конечно понимаю, что должен бы сам с этим справиться, если хочу быть хорошим программером, но я уже запарился спотыкаться на чем-то и из-за этого забивать на изучение в течении недель.
$request = "SELECT Id FROM table";
$result = mysql_query($request);
$i = 0;
while ($row = mysql_fetch_array($result)) {
\t$IdArray[$i] = $row['Id'];
\t$i = $i++;
}
Бро, я не понял что ты делаешь? Я сириусли не понял? Распиши подробнее?
Я видимо тебя не дождался
Наконец-то я нашел время все проверить.
Советы и замечания по https://github.com/NotBadCode/Students
> https://github.com/NotBadCode/Students/blob/master/list.php#L11
> $students = $mapper->getAllStudents( );
Ну не, давай лучше сделаем тут нормально, то есть выбираем только часть студентов, которые есть на текущей странице. Должны же мы научиться правильно делать постраничную навигацию. Для этого стоит добавить к функции параметры $offset и $limit. Незачем выбирать 100 студентов, чтобы вывести первых 20.
Список студентов надо вывести в виду таблицы, а не вертикально по строчкам. Сортировку надо сделать щелчком по заголовку, при этом колонка по которой идет сортировка должна быть помечена треугольничком или стрелочкой (указывающей направление сортировки). Включение сортировки сбрасывает номер страницы на первый.
Вот тут описаны HTML теги которыми можно сделать таблицу: http://htmlbook.ru/samhtml/tablitsy
Результаты поиска тоже должны просматриваться постранично и с сортировкой. Введенное в поиск слово должно выводиться в поле поиска. При выводе результатов поиска должен быть поясняющий текст вроде «Выводятся результаты поиска по слову «студент». Показать всех студентов.».
> `groupnum` int(5) NOT NULL,
Номера групп (как и номера телефонов, паспортов, домов) надо делать не числом, а строкой. Как ты будешь хранить номер вроде 00100? Также, потом могут появиться номера вроде 115M.
Числовой тип должен использоваться для обозначения количества чего-то или значения какой-то величины.
> https://github.com/NotBadCode/Students/blob/master/lib/pdo.php#L8
Не ставь ?> в конце файла. За ним можно забыть пробелы, они выведутся и сломают все функции работающие с заголовками (header, setcookie, session_start). Также, стандарт оформления кода (которого мы придерживаемся) PSR-2 недвусмысленно говорит:
http://www.php-fig.org/psr/psr-2/ru/
> Закрывающий тэг ?> НЕОБХОДИМО удалять из файлов, содержащих только PHP.
> https://github.com/NotBadCode/Students/blob/master/lib/pdo.php#L3
> require_once "/lib/config.php";
Конфиг правильнее подключать через require так как иначе если он уже подключался где-то, то тут он не подключится.
> class DataMapper
> lib/Datamapper.php
Название файла должно содержать буквы в том же регистре, что и имя класса. На linux регистр букв имеет значение, и когда ты захочешь подключить автозагрузик, он не найдет файл. На Windows регистр букв не имеет значения и если просто переименовать файл может быть git не увидит разницы. Есть 2 варианта решения проблемы:
1) http://stackoverflow.com/a/20907647
2) http://stackoverflow.com/a/17688308
Я бы советовал выставить эту настройку в false, после переименовать файл через git mv.
Аналогично надо сделать с profile.php. Заодно получишь опыта смены регистра имени файла на Windows.
Название DataMapper неудачное, надо было назвать ProfileMapper.
> https://github.com/NotBadCode/Students/blob/master/index.php#L44
После успешного обновления данных в профиле тоже надо делать редирект чтобы страница была загружена методом GET, иначе браузер при обновлении страницы или нажатии кнопки назад будет спрашивать про повторную отправку формы.
> https://github.com/NotBadCode/Students/blob/master/templates/list.html#L33
> $students[$j×$_GET['num']]
Во-первых ты никогда не должен из шаблона обращаться к GET, POST, COOKIE и т.д. Шаблон должен использовать только переданные ему переменные, иначе он занимается не своим делом (его дело лишь выводить переданные ему значения).
Также, тут ошибка. Если num = 3, а в массиве 30 студентов, и цикл идет от 0 до 30 то мы выводим студентов с такими индексами: 0, 3, 6, 9, в общем явно не то что требуется.
> https://github.com/NotBadCode/Students/blob/master/templates/list.html#L25
> <?
Нельзя исплоьзовать короткий тег PHP (это написано в PSR-2). Можно только либо <?php либо <?=
> <br />
Слеш не ставится в конце HTML-тегов (так было в XHTML много лет назад).
> https://github.com/NotBadCode/Students/blob/master/templates/profile.html#L5
> ?if($error=="name"):?> style="border:2px solid red;"<?endif?>>
Не надо прописывать стили в атрибуте style. Надо добавлять CSS-класс и прописывать стили в нем (http://htmlbook.ru/samcss/klassy )
Вообще, я вижу ты HTML/CSS совсем плохо знаешь. Не хочешь порешать мои полезные задачки на эти темы? Ссылка стоит в ОП-посте.
Насчет выбора пола и места проживания, если у тебя всего 2 пункта, лучше использовать радиокнопки (они требуют меньше кликов для выбора). Выпадающий список используют когда пунктов много, чтобы сэкономить место. Для 2-4 пунктов делать выпадающий список нет смысла. Это не обязательно исправлять, это просто чтобы ты понимал, когда что лучше использовать.
> https://github.com/NotBadCode/Students/blob/master/templates/profile.html#L35
> ($student->getPlace()=='local')
Чтобы было совсем правильно, лучше значения пола и места жительства (а также любые случаи когда есть выбор из нескольких вариантов) сделать константами:
$student->getPlace() == Profile::PLACE_LOCAL
Это делает код понятнее (понятно какие в общем есть варианты) и надежнее (защищает от опечаток). Профессиональные программисты использовали бы тут константу.
> https://github.com/NotBadCode/Students/blob/master/lib/Datamapper.php#L18
> return "error request";
Это неправильно. Во-первых, ты при вызове функции не проверяешь что она вернула (зачем тогда вообще возвращать эту строку?). Во-вторых, с функцией которая возвращает либо строку либо массив, неудобно работать: ты должен каждый раз после ее вызова ставить if. В таких случаях в ООП принято исплоьзовать исключения:
https://gist.github.com/codedokode/65d43ca5ac95c762bc1a
http://php.net/manual/ru/language.exceptions.php
Также, как альтернатива, можно в случае передачи неправильного значения просто ставить вместо него правильное.
> https://github.com/NotBadCode/Students/blob/master/lib/Datamapper.php#L34
> public function isemailUsed($email, $code)
Чтобы проверить не занят ли email, не надо возвращать объект. Достаточно сделать запрос вида SELECT COUNT(...) и проверить что результат больше нуля.
> public function iscodeUsed($code)
То же самое
> bindValue
Вообще bindValue предназначен для двухсторонней привязки переменной (когда база может поменять значение в ней). Исправлять не надо, просто в будущем используй bindParam который делает одностороннюю привязку и в который можно передавать выражение или число, а не только переменную.
> $STH->setFetchMode(PDO::FETCH_CLASS, 'profile');
Вместо того чтобы глобально менять режим выбора, надо передавать эти параметры в fetch(). Не используй setFetchMode, это плохая идея.
> https://github.com/NotBadCode/Students/blob/master/lib/Datamapper.php#L87
> return $this->DBH->lastInsertId( );
Обычно маппер проставляет id в объект, то есть делает
$student->setId(...);
Это логично: после сохранения в базу у объекта появляется id.
Наконец-то я нашел время все проверить.
Советы и замечания по https://github.com/NotBadCode/Students
> https://github.com/NotBadCode/Students/blob/master/list.php#L11
> $students = $mapper->getAllStudents( );
Ну не, давай лучше сделаем тут нормально, то есть выбираем только часть студентов, которые есть на текущей странице. Должны же мы научиться правильно делать постраничную навигацию. Для этого стоит добавить к функции параметры $offset и $limit. Незачем выбирать 100 студентов, чтобы вывести первых 20.
Список студентов надо вывести в виду таблицы, а не вертикально по строчкам. Сортировку надо сделать щелчком по заголовку, при этом колонка по которой идет сортировка должна быть помечена треугольничком или стрелочкой (указывающей направление сортировки). Включение сортировки сбрасывает номер страницы на первый.
Вот тут описаны HTML теги которыми можно сделать таблицу: http://htmlbook.ru/samhtml/tablitsy
Результаты поиска тоже должны просматриваться постранично и с сортировкой. Введенное в поиск слово должно выводиться в поле поиска. При выводе результатов поиска должен быть поясняющий текст вроде «Выводятся результаты поиска по слову «студент». Показать всех студентов.».
> `groupnum` int(5) NOT NULL,
Номера групп (как и номера телефонов, паспортов, домов) надо делать не числом, а строкой. Как ты будешь хранить номер вроде 00100? Также, потом могут появиться номера вроде 115M.
Числовой тип должен использоваться для обозначения количества чего-то или значения какой-то величины.
> https://github.com/NotBadCode/Students/blob/master/lib/pdo.php#L8
Не ставь ?> в конце файла. За ним можно забыть пробелы, они выведутся и сломают все функции работающие с заголовками (header, setcookie, session_start). Также, стандарт оформления кода (которого мы придерживаемся) PSR-2 недвусмысленно говорит:
http://www.php-fig.org/psr/psr-2/ru/
> Закрывающий тэг ?> НЕОБХОДИМО удалять из файлов, содержащих только PHP.
> https://github.com/NotBadCode/Students/blob/master/lib/pdo.php#L3
> require_once "/lib/config.php";
Конфиг правильнее подключать через require так как иначе если он уже подключался где-то, то тут он не подключится.
> class DataMapper
> lib/Datamapper.php
Название файла должно содержать буквы в том же регистре, что и имя класса. На linux регистр букв имеет значение, и когда ты захочешь подключить автозагрузик, он не найдет файл. На Windows регистр букв не имеет значения и если просто переименовать файл может быть git не увидит разницы. Есть 2 варианта решения проблемы:
1) http://stackoverflow.com/a/20907647
2) http://stackoverflow.com/a/17688308
Я бы советовал выставить эту настройку в false, после переименовать файл через git mv.
Аналогично надо сделать с profile.php. Заодно получишь опыта смены регистра имени файла на Windows.
Название DataMapper неудачное, надо было назвать ProfileMapper.
> https://github.com/NotBadCode/Students/blob/master/index.php#L44
После успешного обновления данных в профиле тоже надо делать редирект чтобы страница была загружена методом GET, иначе браузер при обновлении страницы или нажатии кнопки назад будет спрашивать про повторную отправку формы.
> https://github.com/NotBadCode/Students/blob/master/templates/list.html#L33
> $students[$j×$_GET['num']]
Во-первых ты никогда не должен из шаблона обращаться к GET, POST, COOKIE и т.д. Шаблон должен использовать только переданные ему переменные, иначе он занимается не своим делом (его дело лишь выводить переданные ему значения).
Также, тут ошибка. Если num = 3, а в массиве 30 студентов, и цикл идет от 0 до 30 то мы выводим студентов с такими индексами: 0, 3, 6, 9, в общем явно не то что требуется.
> https://github.com/NotBadCode/Students/blob/master/templates/list.html#L25
> <?
Нельзя исплоьзовать короткий тег PHP (это написано в PSR-2). Можно только либо <?php либо <?=
> <br />
Слеш не ставится в конце HTML-тегов (так было в XHTML много лет назад).
> https://github.com/NotBadCode/Students/blob/master/templates/profile.html#L5
> ?if($error=="name"):?> style="border:2px solid red;"<?endif?>>
Не надо прописывать стили в атрибуте style. Надо добавлять CSS-класс и прописывать стили в нем (http://htmlbook.ru/samcss/klassy )
Вообще, я вижу ты HTML/CSS совсем плохо знаешь. Не хочешь порешать мои полезные задачки на эти темы? Ссылка стоит в ОП-посте.
Насчет выбора пола и места проживания, если у тебя всего 2 пункта, лучше использовать радиокнопки (они требуют меньше кликов для выбора). Выпадающий список используют когда пунктов много, чтобы сэкономить место. Для 2-4 пунктов делать выпадающий список нет смысла. Это не обязательно исправлять, это просто чтобы ты понимал, когда что лучше использовать.
> https://github.com/NotBadCode/Students/blob/master/templates/profile.html#L35
> ($student->getPlace()=='local')
Чтобы было совсем правильно, лучше значения пола и места жительства (а также любые случаи когда есть выбор из нескольких вариантов) сделать константами:
$student->getPlace() == Profile::PLACE_LOCAL
Это делает код понятнее (понятно какие в общем есть варианты) и надежнее (защищает от опечаток). Профессиональные программисты использовали бы тут константу.
> https://github.com/NotBadCode/Students/blob/master/lib/Datamapper.php#L18
> return "error request";
Это неправильно. Во-первых, ты при вызове функции не проверяешь что она вернула (зачем тогда вообще возвращать эту строку?). Во-вторых, с функцией которая возвращает либо строку либо массив, неудобно работать: ты должен каждый раз после ее вызова ставить if. В таких случаях в ООП принято исплоьзовать исключения:
https://gist.github.com/codedokode/65d43ca5ac95c762bc1a
http://php.net/manual/ru/language.exceptions.php
Также, как альтернатива, можно в случае передачи неправильного значения просто ставить вместо него правильное.
> https://github.com/NotBadCode/Students/blob/master/lib/Datamapper.php#L34
> public function isemailUsed($email, $code)
Чтобы проверить не занят ли email, не надо возвращать объект. Достаточно сделать запрос вида SELECT COUNT(...) и проверить что результат больше нуля.
> public function iscodeUsed($code)
То же самое
> bindValue
Вообще bindValue предназначен для двухсторонней привязки переменной (когда база может поменять значение в ней). Исправлять не надо, просто в будущем используй bindParam который делает одностороннюю привязку и в который можно передавать выражение или число, а не только переменную.
> $STH->setFetchMode(PDO::FETCH_CLASS, 'profile');
Вместо того чтобы глобально менять режим выбора, надо передавать эти параметры в fetch(). Не используй setFetchMode, это плохая идея.
> https://github.com/NotBadCode/Students/blob/master/lib/Datamapper.php#L87
> return $this->DBH->lastInsertId( );
Обычно маппер проставляет id в объект, то есть делает
$student->setId(...);
Это логично: после сохранения в базу у объекта появляется id.
Советы и замечания по https://github.com/NotBadCode/Upload
Насчет проблемы с X-sendfile. Раз ты его установил, давай начнем с проверки, работает ли он вообще. Для этого положи картинку, например, picture.jpg и рядом файл например download.php и сделай чтобы он выдавал header для загрузки картинки, и проверь будет ли что загружаться. Если нет, то отладчиком (Ctrl + Shift + I в браузере) посмотри заголовки ответа на вкладке Network и напиши в тред.
Ну и установить модуль к Апачу мало, надо еще в httpd.conf его включить и перезапустить сервер. Включается модуль директивой LoadModule.
composer.phar и composer.lock не надо класть в репозиторий. Перемести их куда-нибудь, закоммить, добавь в gitignore, закоммить и потом верни назад — git должен их проигнорировать.
По базе данных.
> `path` text NOT NULL,
Вот это плохая идея. Дело в том, что мы не можем на колонку типа text добавить индекс, а значит MySQL не сможет использовать индекс для выборки отсортированных комментариев — вместо этого она будет вынуждена сначала выбрать комментарии в память, а потом отсортировать.
А так, индекс (fileid, path) позволил бы выбрать все комментарии для файла в уже отсортированном порядке. Ты конечно скорее всего не знаешь про это, но почитай чтобы хотя бы в общих чертах представлять когда и зачем нужны индексы:
http://ruhighload.com/post/%D0%A0%D0%B0%D0%B1%D0%BE%D1%82%D0%B0+%D1%81+%D0%B8%D0%BD%D0%B4%D0%B5%D0%BA%D1%81%D0%B0%D0%BC%D0%B8+%D0%B2+MySQL (очень полезная статья для начинающего)
Тут нужно использовать VARCHAR ограниченной длины (или CHAR как вариант).
Для связей между таблицами надо прописать внешние ключи: http://denis.in.ua/foreign-keys-in-mysql.htm
Для comments я бы советовал добавить поле parent_id. Оно избыточно, но в случае если ты где-то накосячишь с path, с его помощью ты сможешь восстановить порядок записей. Без него он будет потерян. Тут лучше подстраховаться.
Для работы с комментариями надо сделать отдельный маппер. Обычно делают на каждую таблицу свой маппер. Иначе класс начинает становиться слишком сложным.
> https://github.com/NotBadCode/Upload/blob/master/index.php#L5
> \Slim\Slim::registerAutoloader( );
При использовании композера это писать не надо, композер сам организует автозагрузку всех библиотек.
> https://github.com/NotBadCode/Upload/blob/master/index.php#L28
> $file = new File( );
Непонятно, зачем ты заранее создаешь пустой файл. Создавай там, где он понадобится.
> newFilesMapper'
Очень неудачное название. Почему new? Пиши просто fileMapper.
PDO тоже наверно стоит сделать отдельным синглтоном. А то где ты будешь брать PDO для CommentMapper?
> $numfiles = count($mapper->getAllFiles( )); //oi kak ne effektivnoooo!
Правильное замечание! Так писать нельзя. Если тебе нужно число файлов, стоит сделать отдельный метод в маппере. Но тут оно вообще не нужно, можно просто сделать не больше 10 попыток генерации кода например (если у тебя код 32 символьный, то там вероятность повтора практически нулевая).
> echo "Ошибка загрузки";
> die( );
Это плохая идея, так обрабатывать ошибки. Ведь сообщение увидит пользователь, а ты о проблеме даже не узнаешь. Надо выкидывать исключение — тогда оно будет зафиксировано в логе ошибок, а пользователь увидит слимовскую страницу ошибки (которую можно переопределить).
> https://github.com/NotBadCode/Upload/blob/master/index.php#L79
> "files/$code.$name");
Определение места хранения надо сделать методом, чтобы можно было всегда вызвать его и получить путь к файлу
Также, нет ли тут ошибки? Ты используешь переданное имя файла для сохранения, а что если пользователь попробует загрузить файл 1.php и потом его вызвать? Он ведь выполнится. Вот твой сайт и взломан.
Также, при загрузке файлов надо бы проверять значение поля error, оно описано тут: https://php.net/manual/ru/features.file-upload.errors.php Не надо обрабатывать все коды ошибок, надо просто проверять есть ошибка или нет.
> upload.html
Шаблоны twig принято называть upload.twig или upload.html.twig (и кстати есть расширение для Sublime, если ты его используешь, которое дает подсветку таких файлов и сокращения).
> https://github.com/NotBadCode/Upload/blob/master/index.php#L94
> $list = $mapper->getAllFiles( );
Функцию надо переименовать. Она же не все файлы вернет.
> if (preg_match($RegExp, $file->getType())) {
Было бы удобнее сделать метод file->isImage()
> https://github.com/NotBadCode/Upload/blob/master/index.php#L127
> filename=\"" . basename($filename) . "\";"
Это не работает для русских букв, так как разные браузеры исплоьзуют разные кодировки для этого параметра. Единственный кроссбраузерный способ это ставить имя файла в конец URL, например download/100/задания.doc
> https://github.com/NotBadCode/Upload/blob/master/index.php#L175
> $app->render('/file.html', array(
После успешной обработки POST-формы не надо ничего выводить, надо делать редирект.
> https://github.com/NotBadCode/Upload/blob/master/lib/FileMapper.php#L23
> ORDER BY -id
Принято писать ORDER BY id DESC. Я подозреваю в случае -id это считается выражением и MySQL не сможет использовать индекс для выборки в отсортированном порядке.
Плохо что ты принимаешь и используешь path от пользователя. Ведь он может вписать тебе что угодно и замусорить базу. Я думаю, надо передавать id коммента, на который дается ответ.
Когда ты составляешь путь, ты должен дополнять число нулями. Иначе сортировка получается неправильной:
1.1
10.1
2.1.1
3.1
А надо так:
00001.00001
00010.00001
...
Это ограничивает число комментариев в ветке, но зато дает правильную сортировку. Процесс создания пути (и всю работу с ними) надо вынести в отдельные методы, чтобы легче было читать и править код.
> https://github.com/NotBadCode/Upload/blob/master/templates/file.html#L15
> style="width: 250px;"
Это нехорошо, во-первых маленькие картинки будут растягиваться, во-вторых, пользователь при просмотре страницы качает огромную картинку. Лучше бы при сохранении файла или при первом обращении создавать маленькую превьюшку. Разумеется, для этого должен быть отдельный класс.
> https://github.com/NotBadCode/Upload/blob/master/templates/file.html#L26
Тут конечно немного печально получается, жаль что ты JS не знаешь, тут надо через JS бы сделать кнопку «ответить», чтобы при нажатии добавлялась форма ответа.
> '/>
В HTML не ставится слеш в конце тега
> comment.getPath()|length
Это же костыль, считать длину строки, надо сделать метод getDepth() у комментария
> https://github.com/NotBadCode/Upload/blob/master/templates/file.html#L45
> <input type='text' name='text' size='100' maxlength="200" />
Для текста комментария надо использовать textarea, а не input
В общем, я бы советовал тебе параллельно начинать изучать HTML/CSS, так как с версткой у тебя все плохо, а от php программистов обычно базовые знания верстки требуют. У меня в ОП-посте есть ссылка на хорошие задания по теме. Это изучать не так и долго, а тебе пригодится.
Было бы хорошо разобраться с этим языком и сделать нормальное оформление.
Ну и еще, у меня есть задания на SQL (в ОП посте), я бы тоже советовал их сделать, чтобы лучше понимать базы данных.
Ну и если тебе интересен JS, у меня и на него есть задания.
Без этих знаний задачу на тестирование (3-я большая задача) вряд ли получится сделать.
Советы и замечания по https://github.com/NotBadCode/Upload
Насчет проблемы с X-sendfile. Раз ты его установил, давай начнем с проверки, работает ли он вообще. Для этого положи картинку, например, picture.jpg и рядом файл например download.php и сделай чтобы он выдавал header для загрузки картинки, и проверь будет ли что загружаться. Если нет, то отладчиком (Ctrl + Shift + I в браузере) посмотри заголовки ответа на вкладке Network и напиши в тред.
Ну и установить модуль к Апачу мало, надо еще в httpd.conf его включить и перезапустить сервер. Включается модуль директивой LoadModule.
composer.phar и composer.lock не надо класть в репозиторий. Перемести их куда-нибудь, закоммить, добавь в gitignore, закоммить и потом верни назад — git должен их проигнорировать.
По базе данных.
> `path` text NOT NULL,
Вот это плохая идея. Дело в том, что мы не можем на колонку типа text добавить индекс, а значит MySQL не сможет использовать индекс для выборки отсортированных комментариев — вместо этого она будет вынуждена сначала выбрать комментарии в память, а потом отсортировать.
А так, индекс (fileid, path) позволил бы выбрать все комментарии для файла в уже отсортированном порядке. Ты конечно скорее всего не знаешь про это, но почитай чтобы хотя бы в общих чертах представлять когда и зачем нужны индексы:
http://ruhighload.com/post/%D0%A0%D0%B0%D0%B1%D0%BE%D1%82%D0%B0+%D1%81+%D0%B8%D0%BD%D0%B4%D0%B5%D0%BA%D1%81%D0%B0%D0%BC%D0%B8+%D0%B2+MySQL (очень полезная статья для начинающего)
Тут нужно использовать VARCHAR ограниченной длины (или CHAR как вариант).
Для связей между таблицами надо прописать внешние ключи: http://denis.in.ua/foreign-keys-in-mysql.htm
Для comments я бы советовал добавить поле parent_id. Оно избыточно, но в случае если ты где-то накосячишь с path, с его помощью ты сможешь восстановить порядок записей. Без него он будет потерян. Тут лучше подстраховаться.
Для работы с комментариями надо сделать отдельный маппер. Обычно делают на каждую таблицу свой маппер. Иначе класс начинает становиться слишком сложным.
> https://github.com/NotBadCode/Upload/blob/master/index.php#L5
> \Slim\Slim::registerAutoloader( );
При использовании композера это писать не надо, композер сам организует автозагрузку всех библиотек.
> https://github.com/NotBadCode/Upload/blob/master/index.php#L28
> $file = new File( );
Непонятно, зачем ты заранее создаешь пустой файл. Создавай там, где он понадобится.
> newFilesMapper'
Очень неудачное название. Почему new? Пиши просто fileMapper.
PDO тоже наверно стоит сделать отдельным синглтоном. А то где ты будешь брать PDO для CommentMapper?
> $numfiles = count($mapper->getAllFiles( )); //oi kak ne effektivnoooo!
Правильное замечание! Так писать нельзя. Если тебе нужно число файлов, стоит сделать отдельный метод в маппере. Но тут оно вообще не нужно, можно просто сделать не больше 10 попыток генерации кода например (если у тебя код 32 символьный, то там вероятность повтора практически нулевая).
> echo "Ошибка загрузки";
> die( );
Это плохая идея, так обрабатывать ошибки. Ведь сообщение увидит пользователь, а ты о проблеме даже не узнаешь. Надо выкидывать исключение — тогда оно будет зафиксировано в логе ошибок, а пользователь увидит слимовскую страницу ошибки (которую можно переопределить).
> https://github.com/NotBadCode/Upload/blob/master/index.php#L79
> "files/$code.$name");
Определение места хранения надо сделать методом, чтобы можно было всегда вызвать его и получить путь к файлу
Также, нет ли тут ошибки? Ты используешь переданное имя файла для сохранения, а что если пользователь попробует загрузить файл 1.php и потом его вызвать? Он ведь выполнится. Вот твой сайт и взломан.
Также, при загрузке файлов надо бы проверять значение поля error, оно описано тут: https://php.net/manual/ru/features.file-upload.errors.php Не надо обрабатывать все коды ошибок, надо просто проверять есть ошибка или нет.
> upload.html
Шаблоны twig принято называть upload.twig или upload.html.twig (и кстати есть расширение для Sublime, если ты его используешь, которое дает подсветку таких файлов и сокращения).
> https://github.com/NotBadCode/Upload/blob/master/index.php#L94
> $list = $mapper->getAllFiles( );
Функцию надо переименовать. Она же не все файлы вернет.
> if (preg_match($RegExp, $file->getType())) {
Было бы удобнее сделать метод file->isImage()
> https://github.com/NotBadCode/Upload/blob/master/index.php#L127
> filename=\"" . basename($filename) . "\";"
Это не работает для русских букв, так как разные браузеры исплоьзуют разные кодировки для этого параметра. Единственный кроссбраузерный способ это ставить имя файла в конец URL, например download/100/задания.doc
> https://github.com/NotBadCode/Upload/blob/master/index.php#L175
> $app->render('/file.html', array(
После успешной обработки POST-формы не надо ничего выводить, надо делать редирект.
> https://github.com/NotBadCode/Upload/blob/master/lib/FileMapper.php#L23
> ORDER BY -id
Принято писать ORDER BY id DESC. Я подозреваю в случае -id это считается выражением и MySQL не сможет использовать индекс для выборки в отсортированном порядке.
Плохо что ты принимаешь и используешь path от пользователя. Ведь он может вписать тебе что угодно и замусорить базу. Я думаю, надо передавать id коммента, на который дается ответ.
Когда ты составляешь путь, ты должен дополнять число нулями. Иначе сортировка получается неправильной:
1.1
10.1
2.1.1
3.1
А надо так:
00001.00001
00010.00001
...
Это ограничивает число комментариев в ветке, но зато дает правильную сортировку. Процесс создания пути (и всю работу с ними) надо вынести в отдельные методы, чтобы легче было читать и править код.
> https://github.com/NotBadCode/Upload/blob/master/templates/file.html#L15
> style="width: 250px;"
Это нехорошо, во-первых маленькие картинки будут растягиваться, во-вторых, пользователь при просмотре страницы качает огромную картинку. Лучше бы при сохранении файла или при первом обращении создавать маленькую превьюшку. Разумеется, для этого должен быть отдельный класс.
> https://github.com/NotBadCode/Upload/blob/master/templates/file.html#L26
Тут конечно немного печально получается, жаль что ты JS не знаешь, тут надо через JS бы сделать кнопку «ответить», чтобы при нажатии добавлялась форма ответа.
> '/>
В HTML не ставится слеш в конце тега
> comment.getPath()|length
Это же костыль, считать длину строки, надо сделать метод getDepth() у комментария
> https://github.com/NotBadCode/Upload/blob/master/templates/file.html#L45
> <input type='text' name='text' size='100' maxlength="200" />
Для текста комментария надо использовать textarea, а не input
В общем, я бы советовал тебе параллельно начинать изучать HTML/CSS, так как с версткой у тебя все плохо, а от php программистов обычно базовые знания верстки требуют. У меня в ОП-посте есть ссылка на хорошие задания по теме. Это изучать не так и долго, а тебе пригодится.
Было бы хорошо разобраться с этим языком и сделать нормальное оформление.
Ну и еще, у меня есть задания на SQL (в ОП посте), я бы тоже советовал их сделать, чтобы лучше понимать базы данных.
Ну и если тебе интересен JS, у меня и на него есть задания.
Без этих знаний задачу на тестирование (3-я большая задача) вряд ли получится сделать.
> HTML/CSS, так как с версткой у тебя все плохо,
Нет, я понимаю всё верста-костыли, просто было лень заморачиваться с ней.
Для простоты сделал так как есть.
JS я то же немного знаю, но похуже.
>Список студентов надо вывести в виду таблицы, а не вертикально по строчкам. Сортировку надо сделать щелчком по заголовку, при этом колонка по которой идет сортировка должна быть помечена треугольничком или стрелочкой (указывающей направление сортировки). Включение сортировки сбрасывает номер страницы на первый.
Не проще тогда таблицу сортировать на клиенте в bootsrtram вроде есть нужные плагины?
Что стоит положить в ридми на гитхаб, описания тобой задач?
> Если у пользователя уже есть cookie, доступ к этой странице ему запрещён.
лучше не запрещать а редиректить например на свою домашнюю страницу
Ну и судя по твоему описанию ты какой-то велосипед делаешь, зря, на фремйворках удобнее и лучше получится.
>Остаётся только вопрос, как зашифровать cookie, чтобы пользователь не мог найти в них закономерность и не стал подделывать их, пытаясь зайти под именем другого пользователя. Слышал это можно сделать через встроенные функции md5.
md5 это не функция шифрования, а получения необратимого хеша.
Обычно в куки кладут id + уникальный токен (у каждого свой, хранится в базе) либо id + хеш от пароля либо id + хеш от (пароль + сложный секретный код).
Можно хранить в куке хеш от (id + секретный код), преимущество в том что проверять авторизацию можно без обращения к БД, минус в том что украв код можно зайти под любым пользователем. Небезопасно в общем.
>>444359
Циклом
>>444363
Можно так, почему бы и нет.
>>444378
> потом отрежь первые 8 символов этого шифра,
И ты сразу же во много раз снизил сложность подбора, с 2 ^ 128 (для 32 символов) до 2 ^ 32 (для 8 символов). Не надо изобретать криптографические алгоритмы, тем более если не видишь таких очевидных вещей.
>>444384
Хакер может нарегистрировать аккаунтов с известными паролями и проанализировать коды. Также, не стоит полагаться на то, что никто никогда не увидит твой код. Например, однажды из-за ошибки конфигурации веб-сервера главная фейсбука отдавала код файла index.php.
Также, насчет того что воспользоваться украденными куками нельзя, ты ошибаешься. Впрочем, если использовать httpOnly куки то украсть их через XSS не получится.
>>444407
В бан вас обоих отправить бы на недельку чтобы тред не засоряли.
> Если у пользователя уже есть cookie, доступ к этой странице ему запрещён.
лучше не запрещать а редиректить например на свою домашнюю страницу
Ну и судя по твоему описанию ты какой-то велосипед делаешь, зря, на фремйворках удобнее и лучше получится.
>Остаётся только вопрос, как зашифровать cookie, чтобы пользователь не мог найти в них закономерность и не стал подделывать их, пытаясь зайти под именем другого пользователя. Слышал это можно сделать через встроенные функции md5.
md5 это не функция шифрования, а получения необратимого хеша.
Обычно в куки кладут id + уникальный токен (у каждого свой, хранится в базе) либо id + хеш от пароля либо id + хеш от (пароль + сложный секретный код).
Можно хранить в куке хеш от (id + секретный код), преимущество в том что проверять авторизацию можно без обращения к БД, минус в том что украв код можно зайти под любым пользователем. Небезопасно в общем.
>>444359
Циклом
>>444363
Можно так, почему бы и нет.
>>444378
> потом отрежь первые 8 символов этого шифра,
И ты сразу же во много раз снизил сложность подбора, с 2 ^ 128 (для 32 символов) до 2 ^ 32 (для 8 символов). Не надо изобретать криптографические алгоритмы, тем более если не видишь таких очевидных вещей.
>>444384
Хакер может нарегистрировать аккаунтов с известными паролями и проанализировать коды. Также, не стоит полагаться на то, что никто никогда не увидит твой код. Например, однажды из-за ошибки конфигурации веб-сервера главная фейсбука отдавала код файла index.php.
Также, насчет того что воспользоваться украденными куками нельзя, ты ошибаешься. Впрочем, если использовать httpOnly куки то украсть их через XSS не получится.
>>444407
В бан вас обоих отправить бы на недельку чтобы тред не засоряли.
> Как правильно обращаться к сумме часов каждого сотрудника для их дальнейшего сложения
заводишь переменную, в нее добавляешь часы и складываешь.
>>444451
надо выбирать тян более тщательно
>>444454
> $number == 45||47)
так писать нельзя (точнее это работает не так как ты думаешь). PHP не понимает человеческого языка, а действует по своей, компьютерной логике. Твое условие php поймет как:
«Выполнить код если number равен 45 ИЛИ любому значению»
Это потому,что в if все операции приводятся к булевым значениям (ложь/истина = false/true). Если в итоге получается true, if выполнится, если false то нет.
$number == 45 вернет true если равенство выполяется и false в противном случае.
47 при преобразовании в булев тип даст true так как оно не равно нулю.
|| вернет true если справа или слева есть хотя бы одно true . В данном случае справа всегда стоит true
Таким образом if срабоатет в любом случае.
Аналогично если ты напишешь
if ($x)
То if сработает при непустом значении в $x (то есть не 0, не пустая строка, не null, false или пустой массив).
Мануал: http://php.net/manual/ru/language.types.boolean.php
http://php.net/manual/ru/language.operators.logical.php
http://php.net/manual/ru/language.operators.comparison.php
если тебе что-то непонятно, напиши, я попробую объяснить.
Главное что PHP все то, что написано в if понимает как выражение которое должно дать в итоге либо true либо false, а не условие на человеческом языке. Потому «если x равен 1 или 2 » надо писать в виде «если x равен 1 ИЛИ х равен 2».
> Как правильно обращаться к сумме часов каждого сотрудника для их дальнейшего сложения
заводишь переменную, в нее добавляешь часы и складываешь.
>>444451
надо выбирать тян более тщательно
>>444454
> $number == 45||47)
так писать нельзя (точнее это работает не так как ты думаешь). PHP не понимает человеческого языка, а действует по своей, компьютерной логике. Твое условие php поймет как:
«Выполнить код если number равен 45 ИЛИ любому значению»
Это потому,что в if все операции приводятся к булевым значениям (ложь/истина = false/true). Если в итоге получается true, if выполнится, если false то нет.
$number == 45 вернет true если равенство выполяется и false в противном случае.
47 при преобразовании в булев тип даст true так как оно не равно нулю.
|| вернет true если справа или слева есть хотя бы одно true . В данном случае справа всегда стоит true
Таким образом if срабоатет в любом случае.
Аналогично если ты напишешь
if ($x)
То if сработает при непустом значении в $x (то есть не 0, не пустая строка, не null, false или пустой массив).
Мануал: http://php.net/manual/ru/language.types.boolean.php
http://php.net/manual/ru/language.operators.logical.php
http://php.net/manual/ru/language.operators.comparison.php
если тебе что-то непонятно, напиши, я попробую объяснить.
Главное что PHP все то, что написано в if понимает как выражение которое должно дать в итоге либо true либо false, а не условие на человеческом языке. Потому «если x равен 1 или 2 » надо писать в виде «если x равен 1 ИЛИ х равен 2».
Ругаться иди в другой тред. Анон задал правильный и хороший вопрос.
>>444506
> Предположим что php хранят такие небольшие значения в двух байтах
В 4 (=32 бита) на 32-битных системах и в 8 на 64-битных.
>Но что если каким-то образом значения для разных пользователей могут случайно повторяться?
Не будут так как преобразования преобразуют разные числа в разные.
Но это нетрудно подобрать. злоумышленник может зарегистрировать много аккаунтов и сопоставить id и код. Ну и плюс, код может по разным причинам утечь. Фейсбук однажды отдавал код index.php вместо главной.
> используйте стандартные функции и будьте счастливы.
Здравая мысль. Жаль только в твоем посте нет конкретного алгоритма (я описал его выше).
>>444696
> div.graybox{
лучше писать .graybox — div тут явно лишний.
> \tfont-size: 14px;
Когда задаешь font задавай рядом line-height.
> .graybox div{
Во-первых, это плохая идея использовать тут div вместо класса. Что, если в тексте справа окажется див? К нему этот стиль тоже применится.
Во-вторых, тут не нужен лишний див. Просто поставь на graybox паддинг слева и все.
Желтый квадрат должен быть в 10px от левого края. А у тебя в 20px, видно же что расстояние больше чем надо.
Ругаться иди в другой тред. Анон задал правильный и хороший вопрос.
>>444506
> Предположим что php хранят такие небольшие значения в двух байтах
В 4 (=32 бита) на 32-битных системах и в 8 на 64-битных.
>Но что если каким-то образом значения для разных пользователей могут случайно повторяться?
Не будут так как преобразования преобразуют разные числа в разные.
Но это нетрудно подобрать. злоумышленник может зарегистрировать много аккаунтов и сопоставить id и код. Ну и плюс, код может по разным причинам утечь. Фейсбук однажды отдавал код index.php вместо главной.
> используйте стандартные функции и будьте счастливы.
Здравая мысль. Жаль только в твоем посте нет конкретного алгоритма (я описал его выше).
>>444696
> div.graybox{
лучше писать .graybox — div тут явно лишний.
> \tfont-size: 14px;
Когда задаешь font задавай рядом line-height.
> .graybox div{
Во-первых, это плохая идея использовать тут div вместо класса. Что, если в тексте справа окажется див? К нему этот стиль тоже применится.
Во-вторых, тут не нужен лишний див. Просто поставь на graybox паддинг слева и все.
Желтый квадрат должен быть в 10px от левого края. А у тебя в 20px, видно же что расстояние больше чем надо.
>> bindValue
Вообще bindValue предназначен для двухсторонней привязки переменной (когда база может поменять значение в ней). Исправлять не надо, просто в будущем используй bindParam который делает одностороннюю привязку и в который можно передавать выражение или число, а не только переменную.
> $STH->bindparam(":name", $name);
> $name=$profile->showName( );
Зачем ты испльзуешь bindParam? Он предназачен для двухсторонней привязки (с получением данных из базы) и почти никогда не нужен. Используй bindValue, в который данные можно передать без промежуточной переменной, и сделай функцию в 2 раза короче.
>> $STH->setFetchMode(PDO::FETCH_CLASS, 'profile');
Вместо того чтобы глобально менять режим выбора, надо передавать эти параметры в fetch(). Не используй setFetchMode, это плохая идея.
У меня почему то не получается через fetch(), как это правильно сделать?
Не знаю, может ты имя папки забыл дописать? Почитай на всякий случай http://habrahabr.ru/company/sprinthost/blog/129560/
Там есть способ отлачки, можно какаую-то опцию (rewriteLoglevel?) включить и он будет в лог писать какие правила применялись.
>>444831
Это против логики и здравого смысла. Методу get не важно откуда он вызван.
Если тебе надо сделать 2 класса с разными настройками то правильным будет либо передать им разные конфиги:
$configForB = ...
$b = new TestB($configForB);
Либо в конструкторе TextB заменить config на другой объект.
Самое правильное вообще не передавать config в TestA/TestB, а например получать значение через метод который определен и в TestA и в TestB:
print $this->getSomeValue( );
>>444845
Через if
>>444881
Тут наверно проще через if или тернарный оператор добавить CSS класс:
<th <?= ($sortField == 'name') ? 'class="active" ' : '' ?> >Имя</th>
Не надо использовать HTML теги для выделения, лучше использовать CSS классы.
>>444886
Можно взять алгоритм Дейкстры. Он проще.
Если ты хочешь получше разобраться в рекурсии, из-за которой ты тут застрял, можешь решить такую задачку:
Найти N-е число Фибоначчи. Числа Фибоначчи определяются так:
- первое число равно 0
- второе равно 1
- третье и далее равно сумме 2 предыдущих чисел.
Вот ряд чисел Фибоначчи: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144....
Это задача легко решается с помощью рекурсии (то есть вызова функцией самой себя). После ее решения я дам задачу на рекурсию посложнее.
Не знаю, может ты имя папки забыл дописать? Почитай на всякий случай http://habrahabr.ru/company/sprinthost/blog/129560/
Там есть способ отлачки, можно какаую-то опцию (rewriteLoglevel?) включить и он будет в лог писать какие правила применялись.
>>444831
Это против логики и здравого смысла. Методу get не важно откуда он вызван.
Если тебе надо сделать 2 класса с разными настройками то правильным будет либо передать им разные конфиги:
$configForB = ...
$b = new TestB($configForB);
Либо в конструкторе TextB заменить config на другой объект.
Самое правильное вообще не передавать config в TestA/TestB, а например получать значение через метод который определен и в TestA и в TestB:
print $this->getSomeValue( );
>>444845
Через if
>>444881
Тут наверно проще через if или тернарный оператор добавить CSS класс:
<th <?= ($sortField == 'name') ? 'class="active" ' : '' ?> >Имя</th>
Не надо использовать HTML теги для выделения, лучше использовать CSS классы.
>>444886
Можно взять алгоритм Дейкстры. Он проще.
Если ты хочешь получше разобраться в рекурсии, из-за которой ты тут застрял, можешь решить такую задачку:
Найти N-е число Фибоначчи. Числа Фибоначчи определяются так:
- первое число равно 0
- второе равно 1
- третье и далее равно сумме 2 предыдущих чисел.
Вот ряд чисел Фибоначчи: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144....
Это задача легко решается с помощью рекурсии (то есть вызова функцией самой себя). После ее решения я дам задачу на рекурсию посложнее.
Советы
> <? session_start() ?>
используй либо <?php либо <?= и не используй <? так как он может быть отключен и не по стандарту
> <meta http-equiv="content-type" content="text/html; charset=utf-8" />
Слеш в конце тега в html не ставят, это было в XHTML
> <div id="form" align="left">
Тут надо исплоьзовать CSS. Не хочешь мои задачки на HTML/CSS из оп-поста порешать? Было бы полезно, там как раз позиционированию учат. Я вижу по использованию br, что ты CSS не знаешь.
> https://github.com/Si0n/winCalculator/blob/master/index2.php#L18
редирект надо делать через header("Location: ...") и die(), а не такие костыли. Почитай примеры тут: http://php.net/manual/ru/function.header.php
Также, ты зря смешиваешь php c html в этом файле. Это приводит к очень плохому и запутанному коду: https://github.com/Si0n/winCalculator/blob/master/index2.php#L18
Почитай про шаблоны тут: http://www.phpinfo.su/articles/practice/shablony_v_php.html
Классы надо класть в отдельные файлы, причем имя файла должно совпадать с именем класса, и ничего кроме класса там не должно быть.
При ошибке заполнения формы лучше не сбрасывать все значения полей, а подставлять их в форму. Чтобы это сделать, надо обрабатывать форму по такому универсальному алгоритму:
------------
$values = значения по умолчанию (пустые);
$errors = пустой массив;
Если (форма отправлена через POST) {
Переносим значения полей из POST в $values;
Если (все заполнено верно) {
Делаем требуемое действие (например рассчет боя);
Редиректим куда-нибудь или выводим результат;
Выходим;
}
Кладем ошибки в $errors;
}
Выводим форму($values, $errors);
-------------
Сессия не нужна если ты сразу же выводишь результат после расчета. Если редиректишь, то нужна. В ней тогда можно сохранять введенные значения.
Советы
> <? session_start() ?>
используй либо <?php либо <?= и не используй <? так как он может быть отключен и не по стандарту
> <meta http-equiv="content-type" content="text/html; charset=utf-8" />
Слеш в конце тега в html не ставят, это было в XHTML
> <div id="form" align="left">
Тут надо исплоьзовать CSS. Не хочешь мои задачки на HTML/CSS из оп-поста порешать? Было бы полезно, там как раз позиционированию учат. Я вижу по использованию br, что ты CSS не знаешь.
> https://github.com/Si0n/winCalculator/blob/master/index2.php#L18
редирект надо делать через header("Location: ...") и die(), а не такие костыли. Почитай примеры тут: http://php.net/manual/ru/function.header.php
Также, ты зря смешиваешь php c html в этом файле. Это приводит к очень плохому и запутанному коду: https://github.com/Si0n/winCalculator/blob/master/index2.php#L18
Почитай про шаблоны тут: http://www.phpinfo.su/articles/practice/shablony_v_php.html
Классы надо класть в отдельные файлы, причем имя файла должно совпадать с именем класса, и ничего кроме класса там не должно быть.
При ошибке заполнения формы лучше не сбрасывать все значения полей, а подставлять их в форму. Чтобы это сделать, надо обрабатывать форму по такому универсальному алгоритму:
------------
$values = значения по умолчанию (пустые);
$errors = пустой массив;
Если (форма отправлена через POST) {
Переносим значения полей из POST в $values;
Если (все заполнено верно) {
Делаем требуемое действие (например рассчет боя);
Редиректим куда-нибудь или выводим результат;
Выходим;
}
Кладем ошибки в $errors;
}
Выводим форму($values, $errors);
-------------
Сессия не нужна если ты сразу же выводишь результат после расчета. Если редиректишь, то нужна. В ней тогда можно сохранять введенные значения.
Без дива внутри серого бокса как-то неаккуратно получается. Приходится подбирать отрицательный маржин для желтого из-за паддинга
http://jsfiddle.net/u0pjLzcz/5/
Я похоже делал, но в цикле while просто закидывал все данные из row в массив, выглядело то примерно так:
while($row=mysql_fetch_array($result)) {
$newRow[] = $row;
}
После чего можно было возвращать через return значение $newRow, если это делалось в функции. Но потом мне посоветовали обратить внимание на безопасность, в том случае когда в запросах есть какие либо переменные приходящие из вне (до этого я всегда писал специальные функции очистки возможных передаваемых данных, что бы не было инфекций) и посоветовали mysqli или PDO, потом я вообще прочитал что чистый mysql скоро не будет обрабатываться и решил перейти на mysqli причём в ООП стиле, это не так и сложно, вот хорошая ссылка:
http://hashcode.ru/research/302429/php-mysqli-примеры-работы-для-начинающих
Получается значительно безопаснее и быстрее.
тут https://github.com/Si0n/winCalculator/blob/master/css/style.css#L2 что-то дофига стилей в одном блоке.
>>445081
Ок, теперь все верно, но не забывай ставить line-height рядом с font-size.
>>445093
input:cheked + label
Это применит стиль к label который идет за активной кнопкой.
надо писать label input:checked
То есть именно так писать не надо. Если ты хочешь применить стиль ко всем радиокнопкам везде, то надо писать
input[type=radio]:checked
А если только в конкретном месте то
.some-class input:checked
>>445102
Лучше сделать if/else или switch или хотя бы проверку через массив разрешенных значений.
И не надо GET пихать прямо в вызов, помести значение в переменную и обращайся через нее
$obj->$method()
> Так я в меньшей опасности?
Все равно ненадежно. завтра ты добавишь метод в класс и забудешь что его можно вызвать снаружи. Ну и ты зря изобретаешь велосипеды, есть фреймворки и CMS.
>>445193
У нас есть задание на фреймворк Yii (в Оп-посте), но оно сложное.
>>445108
Не беда, я дам подсказки.
> как сделать разные границы для кнопок, не используя при этом id
Есть такие варианты:
http://htmlbook.ru/css/first-child
http://htmlbook.ru/css/last-child (заметь что этот поддерживается меньшим числом браузеров чем first-child так как добавлен позже)
Изучи какие вообще есть псевдоклассы:
http://vremenno.net/html-css/css-pseudo-classes/
http://htmlbook.ru/css/cat/pseudoclass
И псевдоэлементы:
http://htmlbook.ru/css/cat/pseudoelement
Также, почитай интересную статью:
http://habrahabr.ru/company/paysto/blog/251933/
> Тень какая-то не такая, сколько я с ней не шаманил.
Это действительно непросто, новичку на глаз определить параметры тени. Но я подскажу, как это делать. Для начала, почитай описание box-shadow и убедись что запомнил все параметры тени. Теперь давай посмотрим на картинку.
Для начала определяем цвет и прозрачность тени. Цвет, очевидно серый или черный, и тень очень бледная, то есть скорее всего у нее стоит прозрачность около 0.05 - 0.15 (черный цвет при такой прозрачности становится бледно-серым).
Далее, попробуем определить смещение тени. Мы видим что больше всего тени сверху, немного еле-еле видно с боков и нет снизу. Значит, тень смещена вниз. Если бы она была смещена вбок, то с одного боку было бы больше тени чем с другого. Если бы не была смещена, то тени было бы поровну со всех сторон. А тут тень смещена вниз настолько, что нижний кусок тени полностью не виден (ну то есть источник света сверху над кнопкой).
Сравнив размер тени слева и сверху, мы определим на сколько она смещена. На глаз — где-то 5-6 пикселей.
Далее, остались последние параметры тени — радиус размытия + растяжение. Их можно определить как расстояние от плотной части тени до того места, где она исчезает. Так как тень не смещена вбок то это расстояние от левого края кнопки до места исчезновения тени. на глаз, пикселей 5-8. Растяжение тут по моему либо нулевое либо 1-2 пикселя, так как тень размывается, а не тянется равномерной плотностью.
Ну и если тебе придется верстать с фотошопного макета, там все проще — параметры тени можно посмотреть в эффектах слоя. Но фотошопная тень отличается от браузерной по плотности, так что скорее всего придется все равно на глаз подгонять.
> И почему-то кнопки не отжимаются, хотя я указал атрибут name у всех.
так надо одинаковый name дать.
При наведении мыши надо бы сделать чтобы курсор менял форму на руку с пальцем.
Линии надо сделать более мягким цветом, не черными.
Шрифт, который используется — Arial.
> input{
>\tdisplay: none;
это плохой селектор. Ведь если это добавить на страницу, на ней исчезнут все поля ввода. Сделай, чтобы стили влияли только на переключалку.
тут https://github.com/Si0n/winCalculator/blob/master/css/style.css#L2 что-то дофига стилей в одном блоке.
>>445081
Ок, теперь все верно, но не забывай ставить line-height рядом с font-size.
>>445093
input:cheked + label
Это применит стиль к label который идет за активной кнопкой.
надо писать label input:checked
То есть именно так писать не надо. Если ты хочешь применить стиль ко всем радиокнопкам везде, то надо писать
input[type=radio]:checked
А если только в конкретном месте то
.some-class input:checked
>>445102
Лучше сделать if/else или switch или хотя бы проверку через массив разрешенных значений.
И не надо GET пихать прямо в вызов, помести значение в переменную и обращайся через нее
$obj->$method()
> Так я в меньшей опасности?
Все равно ненадежно. завтра ты добавишь метод в класс и забудешь что его можно вызвать снаружи. Ну и ты зря изобретаешь велосипеды, есть фреймворки и CMS.
>>445193
У нас есть задание на фреймворк Yii (в Оп-посте), но оно сложное.
>>445108
Не беда, я дам подсказки.
> как сделать разные границы для кнопок, не используя при этом id
Есть такие варианты:
http://htmlbook.ru/css/first-child
http://htmlbook.ru/css/last-child (заметь что этот поддерживается меньшим числом браузеров чем first-child так как добавлен позже)
Изучи какие вообще есть псевдоклассы:
http://vremenno.net/html-css/css-pseudo-classes/
http://htmlbook.ru/css/cat/pseudoclass
И псевдоэлементы:
http://htmlbook.ru/css/cat/pseudoelement
Также, почитай интересную статью:
http://habrahabr.ru/company/paysto/blog/251933/
> Тень какая-то не такая, сколько я с ней не шаманил.
Это действительно непросто, новичку на глаз определить параметры тени. Но я подскажу, как это делать. Для начала, почитай описание box-shadow и убедись что запомнил все параметры тени. Теперь давай посмотрим на картинку.
Для начала определяем цвет и прозрачность тени. Цвет, очевидно серый или черный, и тень очень бледная, то есть скорее всего у нее стоит прозрачность около 0.05 - 0.15 (черный цвет при такой прозрачности становится бледно-серым).
Далее, попробуем определить смещение тени. Мы видим что больше всего тени сверху, немного еле-еле видно с боков и нет снизу. Значит, тень смещена вниз. Если бы она была смещена вбок, то с одного боку было бы больше тени чем с другого. Если бы не была смещена, то тени было бы поровну со всех сторон. А тут тень смещена вниз настолько, что нижний кусок тени полностью не виден (ну то есть источник света сверху над кнопкой).
Сравнив размер тени слева и сверху, мы определим на сколько она смещена. На глаз — где-то 5-6 пикселей.
Далее, остались последние параметры тени — радиус размытия + растяжение. Их можно определить как расстояние от плотной части тени до того места, где она исчезает. Так как тень не смещена вбок то это расстояние от левого края кнопки до места исчезновения тени. на глаз, пикселей 5-8. Растяжение тут по моему либо нулевое либо 1-2 пикселя, так как тень размывается, а не тянется равномерной плотностью.
Ну и если тебе придется верстать с фотошопного макета, там все проще — параметры тени можно посмотреть в эффектах слоя. Но фотошопная тень отличается от браузерной по плотности, так что скорее всего придется все равно на глаз подгонять.
> И почему-то кнопки не отжимаются, хотя я указал атрибут name у всех.
так надо одинаковый name дать.
При наведении мыши надо бы сделать чтобы курсор менял форму на руку с пальцем.
Линии надо сделать более мягким цветом, не черными.
Шрифт, который используется — Arial.
> input{
>\tdisplay: none;
это плохой селектор. Ведь если это добавить на страницу, на ней исчезнут все поля ввода. Сделай, чтобы стили влияли только на переключалку.
Я не большой специалист, только учусь, смею посоветовать попробовать такой запрос:
$keys=array_keys($checkbox);
$key=implode(",",$keys);
$q=mysql_query("SELECT id FROM catalog WHERE value IN($key)");
Где в переменной $key содержаться ключи полученные из массива $checkbox и записанные в строку, а столбец value это там где содержится значение. Ну я просто предполагаю, может я не понял немного проблемы, я так выводил данные записанные в куках для корзины интернет-магазина.
А, еще кроме last-child/first-child можно использовать селектор +:
label + label { ...не применяется к первому label ... }
В CSS3 также есть first-of-type или как-то так.
>>445111
4 департамента в массив можно и ручками добавить. Тем более ведь ты пишешь универсальный код, который работает с любым числом департаментов любых видов, а значит код не должен сам их создавать.
>>445117
Можно поместить содержимое ячейки в тег a и дать ему display block и нужные стили.
Извиняюсь catalog это название таблицы в моём коде, я скопировал и не изменил, ну ты понял наверное.
> class WORKER
Классы пишутся так: Worker. Все слово из больших букв используется для констант.
> function money()
Функция должна начинаться с глагола, сделайЧтоТо(), например, getSalary()
> else
> return $money;
не забывай фигурные скобкочки
> $page = 0;
> return $page;
не лучше ли написать return 0? зачем тут переменную создавать?
Класс Worker надо сделать абстрактным, чтобы запретить создавать объекты такого класса и чтобы было понятно что это базовый класс. Мануал http://php.net/manual/ru/language.oop5.abstract.php
> $sumMoney="";
Надо записывать 0, а не пустую строку сюда. ты же числа складываешь.
Так, неплохо. А что таблицу не сделал?
>>445167
Нельзя так. Внутри tr можно только td и th помещать.
>>445176
Лучше display: block а то она не растянется на всю ширину ячейки сама.
>>445193
Yii, Symfony 2
>>445217
Точка только склеивает строки, но не выполняет код в них. То есть для php '+' это строка из символа + которая ничего для него не значит.
> Что с этим делать, кто подскажет?
Через if/else писать
>>445240
Может надо $_GET писать? мануал http://php.net/manual/ru/reserved.variables.get.php
> class WORKER
Классы пишутся так: Worker. Все слово из больших букв используется для констант.
> function money()
Функция должна начинаться с глагола, сделайЧтоТо(), например, getSalary()
> else
> return $money;
не забывай фигурные скобкочки
> $page = 0;
> return $page;
не лучше ли написать return 0? зачем тут переменную создавать?
Класс Worker надо сделать абстрактным, чтобы запретить создавать объекты такого класса и чтобы было понятно что это базовый класс. Мануал http://php.net/manual/ru/language.oop5.abstract.php
> $sumMoney="";
Надо записывать 0, а не пустую строку сюда. ты же числа складываешь.
Так, неплохо. А что таблицу не сделал?
>>445167
Нельзя так. Внутри tr можно только td и th помещать.
>>445176
Лучше display: block а то она не растянется на всю ширину ячейки сама.
>>445193
Yii, Symfony 2
>>445217
Точка только склеивает строки, но не выполняет код в них. То есть для php '+' это строка из символа + которая ничего для него не значит.
> Что с этим делать, кто подскажет?
Через if/else писать
>>445240
Может надо $_GET писать? мануал http://php.net/manual/ru/reserved.variables.get.php
О, спасибо. У меня в процедурном стиле есть простой интернет магазин, блог и простенький файлообменник, также много разных заданий из учебника ОПа и не только, некоторые на ООП сделаны. если я сделаю обычный блог с типичным функционалом например на YII это будет большим плюсом при трудоустройстве? Задания давали на собеседовании?
$sql = 'SELECT * FROM `table` WHERE `id` = ';
foreach ($array as $key => $value) {
$sql = $sql.'"'.$value.'" OR ';
}
$sql = substr($sql, 0, -3);
Не проверял проходит ли запрос, но я думаю ты мысль понял
JS 1
http://pastebin.com/JSDwrwZH
JS 2
http://pastebin.com/rUd3zheq
JS 3
http://pastebin.com/BYa5bAcE
Четвертое задание не понимаю как передать произвольное количество аргументов.
JS 4
http://pastebin.com/84fs3EDm
Удобнее сделать с помощью foreach. Он переберет все значения массива что ты ему дашь.
foreach ($array as $key => $value) {
$secondArr[$i] = $value;
$i++;
}
Алсо, у тебя $i = $i++ - это не имеет смысла, функция инкримента пишется так как выше я написал
Не, так как ты писал, я уже сделал, но мне надо фильтровать по нескольким значениям, то есть запрос может быть и WHERE value IN($key) и WHERE value IN($key) AND value1 IN($key1) и WHERE value3 IN($key3) AND value5 IN($key5) AND ... и вообще без WHERE (если ни один чекбокс не выбран). Проблема именно в составлении этого запроса.
Ну так ты же можешь сделать название чекбокса как массив, и допустим получить его таким образом из формы.
$checkbox=$_POST["checkbox"];
Потом получить строку значений из этого массива, допустим строка будет "1463" всё это будут номера выбранных чекбоксов, а при помощи IN ты их всех выведешь AND тебе здесь кажется не нужны.
> класс-хелпер для парсинга коротких строк вида "9×ме1" в нужные в моей реализации ассоциативные массивы.
Зачем вводить лишнюю сущность — массив, когда у тебя есть классы? Логичнее наверно создавать сразу объекты. А так ты в массиво-ориентированное программирование скатываешься.
Также, мне кажется поля в массиве лучше было назвать по-английски, а не по-русски. А вместо «аналитик» хранить имя класса.
> if(!is_string($single)) {
>\t\t\t throw new WrongDataException("string");
Это удобнее делать через assert:
assert(is_string($single));
Если у тебя включено преобразование ошибок в исключения то провалившийся ассерт завершит всю программу.
Названия переменных конечно плохие. Незачем писать arr, можно просто использовать множественное число. То есть $strings, $descriptions, $employees, как-то так.
Класс InitDataParser спроектирован неудачно. Во-первых, тут используется статическое поле, это значит мы не можем создать 2 парсера с разными настройками, фактически у тебя настройки это что-то вроде глобальной переменной. Во-вторых, странно что строки передаются прямо в конструктор, ведь мы не можем задать настройки парсера до передачи строк. Обычно используется такой паттерн:
$factory = new EmployyeeFactory( );
$factory->addWorkerTypes(...);
$workers = $factory->createWorkers('2ме3');
$moreWorkers = $factory->createWorkers('2ме3');
$boss = $factory->createBoss('ме2');
Здесь как ты видишь мы можем использовать один парсер несколько раз и можем задать настройки до парсинга.
Поля private $depInit, private $depBoss это вообще что-то лишнее по моему.
> if(!in_array(self::$typesDispatcher[$workType], array_keys($this->depInit))) {
Проверить наличие ключа можно более простым isset($array[$key]) или боле правильным array_key_exists (isset воспримет null как отсутствие элемента).
> We should somehow get over array_key duplications.\t
если честно, очень странный код, еще и с рандомом (это чтобы отладку усложнить?). Если ты хотел для одинаковых типов складывать количество, то можно просто писать
$this->depInit[$jobTitle]['количество'] += $count;
В общем, на мой взгляд реализация класса InitParser переусложненная без какой-либо выгоды.
> return $this->salary + $this->salary ($this->rank / 100);
Формула ведь не соответствует задаче:
> Сотрудник второго ранга получает на 25% больше, чем первого, а сотрудник 3-го ранга - на 50% больше, чем первого.
В классе Worker лучше ранг и подобные вещи ставить через конструктор. А то у тебя можно создать рабочего с пустыми полями и он будет непонятно что возвращать. А если в конструктор прописать поля, то нельзя будет создать объект, не передав значения.
> if(is_numeric($num)) {
>\t\t\t$this->workDone = (int)$num;
>\t\t} else {
>\t\t\tthrow new WrongDataException("int");
>\t\t}
Это лучше писать как
if (!is_numeric(..)) {
...
}
$this->workDone = ...;
Тогда явно виден основной код и дополнительная ветка для проверки. А у тебя проверка типа смешана с логикой функции. Но короче по моему assert использовать.
> public function getBossSalary()
Странный метод. Получается у каждого сотрудника есть 2 метода, getSalary b getBossSalary и мы должны угадать какой надо вызвать?
Если ты хотел вынести бизнес-логику расчета зарплаты с учетом статуса босса и ранга из класса рабочего, было логично сделать объект, допустим, класса WorkerConsumptionAndProductionStrategy (согласен, длинно, можно короче написать как SalaryAndCoffeeCalculator) с методами вроде
calculateSalary($baseSalary, $rank, $isBoss)
calculateCoffeeConsumption(..)
По моему, это паттерн «стратегия». Он выносит логику расчета из класса сотрудника и позволяет например менять глобально надбавки в зависимости от инфляции, курса доллара и прочих внешних факторов.
> class WorkersCreator
Очень странный и непонятный класс. Судя по названию, он создает сотрудников, но кода в нем подозрительно много для этой цели.
> if(!is_array($inDepInit)) {
Для array есть тайп-хинт: http://php.net/manual/ru/language.oop5.typehinting.php
> $tempRank = array_values($depInit)[$i]["ранг"];
Что за странные конструкции? Зачем тут array_values?
Ты явно все переусложнил. Хватило бы класса, получающего строчку и возвращающего массив сотрудников, а ты наделал промежуточных массивов каких-то, хранишь все в каких-то двух или трехмерных массивах .в которых без полного анализа кода не понять, что хранится. Этот код очень тяжело читать и тяжело поддерживать.
Это все можно сделать намного проще и понятнее.
> class Department extends WorkersCreator
Это по моему неправильно. Наследник это улучшенная или измененная версия родителя. Например, Самолет может наследоваться от Транспорта. Но с какой статти Департамент наследуется от СоздателяРабочих? департамент не создает рабочих, он их нанимает.
> public function fillTotals()
Нет никакого смысла хранить totalSalary. Ее всегда можно посчитать заново, и нам не надо писать сложный код для пересчета totalSalary если мы например уволиил или наняли работника, понизили ранг, и тд (у тебя он впрочем и не написан).
> $this->statData["Департамент"] = self::$depName;
Это опять массиво-ориентированное программирование. Также, тут есть довольно неудачный антипаттерн, когда задача разбивается на несколько функций. Ты делаешь так:
$dep->fillTotals( );
$dep->initStatData( );
$data = $dep->getStatData( );
А можно сделать
$data = $dep->getStatData( *);
В твоем случае надо как-то догадаться и запомнить порядок, в котором вызываются функции. Вот я смотрю на код и мне это не очевидно, и никому не будет очевидно. Не надо так делать.
Также, на мой взгляд эти statData не нужны, это ненужное усложнение. Достаточно методов вроде getTotalSalary().
> public static function addNewWorkerType($newWorker)
тут тоже логики не вижу. Почему мы добавляем новые профессии через Департамент? И почему тут передается массив непонятного формата из 4 полей с ничего не говорящими названиями 0, 1, 2 и 3?
> public static function changeWorkerCond($newConds)
Какой-то странный метод который непонятно чем занимется. Если он вызывает
parent::changeSalary($victim, $newVal); то не проще ли сразу ее и вызвыать?
> class Department extends WorkersCreator
> function __construct($inDepInit, $inBoss, $depName)
Это тоже какое-то усложнение. Если подумать, то как связаны Департамент и Сотрудники? В Департамент можно добавлять Сотрудников и можно их увольнять. Но у тебя в Департамент передаются какие-то строки вместо объектов-сотрудников. зачем? И почему Департамент занимается не своим делом - создает сотрудников? Он их по идее только нанимает.
Мне кажется, должны быть методы вроде добавитьСотрудника(сотрудник)/уволитьСотрудника(сотрудник) где сотрудник это объект. Так будет и проще и понятнее, и максимально универсально: ты можешь сам создать какого хочешь сотрудника и добавить в Департамент.
> $crisis = ["аналитик", "зарплата", 700];
> Department::changeWorkerCond($crisis);
Опять ты все запутываешь. Почему не Department::changeWorkerCond("аналитик", "зарплата", 700)? А еще лучше, сделать нормально примерно так:
аналитики = департамент->найтиВсех(аналитиков);
(для каждого аналитика) {
аналитик->задатьБазовуюЗарплату(N);
}
Ну посмотри, насколько проще и универсальнее получается. Без непонятных массивов, статических методов и прочих антипаттернов. И мы можем отбирать аналитиков по любым условиям, например пропустить тех у кого фамилия на «А» начинается, с помощью одного if.
> У меня все строится на диспетчеризации.
Я честно говоря не слышал про такой паттерн.
В общем, по моему код переусложнен, и требует серьезного рефакторинга. Предлагаю упростить схему на картинке. Сделать, чтобы Department занимался только своим делом, а именно, хранением, приемом, увольнением, отбором сотрудников и расчетом общих показателей. Чтобы у сотрудника была одна функция расчет зарплаты, а не 2. Убрать все лишние многомерные массивы. Мне кажется, так будет гораздо проще и код будет меньше по объему.
тут конечно много чего еще рефакторить, потому давай сначала уберем из департамента функцию создания рабочих, а потом посмотрим куда двигаться дальше. Я всегда готов дать подсказку.
> Я изначально понимал, что ООП нужно для создания универсального кода, с максимально простым расширением функционала.
Боюсь, пока что это не очень ООП, а просто код в котором встречаются классы.
> я почему-то решил делать это через статические свойства и методы
Это неправильно. С ними ты не можешь например в одном департаменте повысить зарплату, а в другом нет.
И еще, у тебя почему то в последних 3 таблицах все департаменты одинаково называются.
Сами таблички получились аккуратные, норм.
> класс-хелпер для парсинга коротких строк вида "9×ме1" в нужные в моей реализации ассоциативные массивы.
Зачем вводить лишнюю сущность — массив, когда у тебя есть классы? Логичнее наверно создавать сразу объекты. А так ты в массиво-ориентированное программирование скатываешься.
Также, мне кажется поля в массиве лучше было назвать по-английски, а не по-русски. А вместо «аналитик» хранить имя класса.
> if(!is_string($single)) {
>\t\t\t throw new WrongDataException("string");
Это удобнее делать через assert:
assert(is_string($single));
Если у тебя включено преобразование ошибок в исключения то провалившийся ассерт завершит всю программу.
Названия переменных конечно плохие. Незачем писать arr, можно просто использовать множественное число. То есть $strings, $descriptions, $employees, как-то так.
Класс InitDataParser спроектирован неудачно. Во-первых, тут используется статическое поле, это значит мы не можем создать 2 парсера с разными настройками, фактически у тебя настройки это что-то вроде глобальной переменной. Во-вторых, странно что строки передаются прямо в конструктор, ведь мы не можем задать настройки парсера до передачи строк. Обычно используется такой паттерн:
$factory = new EmployyeeFactory( );
$factory->addWorkerTypes(...);
$workers = $factory->createWorkers('2ме3');
$moreWorkers = $factory->createWorkers('2ме3');
$boss = $factory->createBoss('ме2');
Здесь как ты видишь мы можем использовать один парсер несколько раз и можем задать настройки до парсинга.
Поля private $depInit, private $depBoss это вообще что-то лишнее по моему.
> if(!in_array(self::$typesDispatcher[$workType], array_keys($this->depInit))) {
Проверить наличие ключа можно более простым isset($array[$key]) или боле правильным array_key_exists (isset воспримет null как отсутствие элемента).
> We should somehow get over array_key duplications.\t
если честно, очень странный код, еще и с рандомом (это чтобы отладку усложнить?). Если ты хотел для одинаковых типов складывать количество, то можно просто писать
$this->depInit[$jobTitle]['количество'] += $count;
В общем, на мой взгляд реализация класса InitParser переусложненная без какой-либо выгоды.
> return $this->salary + $this->salary ($this->rank / 100);
Формула ведь не соответствует задаче:
> Сотрудник второго ранга получает на 25% больше, чем первого, а сотрудник 3-го ранга - на 50% больше, чем первого.
В классе Worker лучше ранг и подобные вещи ставить через конструктор. А то у тебя можно создать рабочего с пустыми полями и он будет непонятно что возвращать. А если в конструктор прописать поля, то нельзя будет создать объект, не передав значения.
> if(is_numeric($num)) {
>\t\t\t$this->workDone = (int)$num;
>\t\t} else {
>\t\t\tthrow new WrongDataException("int");
>\t\t}
Это лучше писать как
if (!is_numeric(..)) {
...
}
$this->workDone = ...;
Тогда явно виден основной код и дополнительная ветка для проверки. А у тебя проверка типа смешана с логикой функции. Но короче по моему assert использовать.
> public function getBossSalary()
Странный метод. Получается у каждого сотрудника есть 2 метода, getSalary b getBossSalary и мы должны угадать какой надо вызвать?
Если ты хотел вынести бизнес-логику расчета зарплаты с учетом статуса босса и ранга из класса рабочего, было логично сделать объект, допустим, класса WorkerConsumptionAndProductionStrategy (согласен, длинно, можно короче написать как SalaryAndCoffeeCalculator) с методами вроде
calculateSalary($baseSalary, $rank, $isBoss)
calculateCoffeeConsumption(..)
По моему, это паттерн «стратегия». Он выносит логику расчета из класса сотрудника и позволяет например менять глобально надбавки в зависимости от инфляции, курса доллара и прочих внешних факторов.
> class WorkersCreator
Очень странный и непонятный класс. Судя по названию, он создает сотрудников, но кода в нем подозрительно много для этой цели.
> if(!is_array($inDepInit)) {
Для array есть тайп-хинт: http://php.net/manual/ru/language.oop5.typehinting.php
> $tempRank = array_values($depInit)[$i]["ранг"];
Что за странные конструкции? Зачем тут array_values?
Ты явно все переусложнил. Хватило бы класса, получающего строчку и возвращающего массив сотрудников, а ты наделал промежуточных массивов каких-то, хранишь все в каких-то двух или трехмерных массивах .в которых без полного анализа кода не понять, что хранится. Этот код очень тяжело читать и тяжело поддерживать.
Это все можно сделать намного проще и понятнее.
> class Department extends WorkersCreator
Это по моему неправильно. Наследник это улучшенная или измененная версия родителя. Например, Самолет может наследоваться от Транспорта. Но с какой статти Департамент наследуется от СоздателяРабочих? департамент не создает рабочих, он их нанимает.
> public function fillTotals()
Нет никакого смысла хранить totalSalary. Ее всегда можно посчитать заново, и нам не надо писать сложный код для пересчета totalSalary если мы например уволиил или наняли работника, понизили ранг, и тд (у тебя он впрочем и не написан).
> $this->statData["Департамент"] = self::$depName;
Это опять массиво-ориентированное программирование. Также, тут есть довольно неудачный антипаттерн, когда задача разбивается на несколько функций. Ты делаешь так:
$dep->fillTotals( );
$dep->initStatData( );
$data = $dep->getStatData( );
А можно сделать
$data = $dep->getStatData( *);
В твоем случае надо как-то догадаться и запомнить порядок, в котором вызываются функции. Вот я смотрю на код и мне это не очевидно, и никому не будет очевидно. Не надо так делать.
Также, на мой взгляд эти statData не нужны, это ненужное усложнение. Достаточно методов вроде getTotalSalary().
> public static function addNewWorkerType($newWorker)
тут тоже логики не вижу. Почему мы добавляем новые профессии через Департамент? И почему тут передается массив непонятного формата из 4 полей с ничего не говорящими названиями 0, 1, 2 и 3?
> public static function changeWorkerCond($newConds)
Какой-то странный метод который непонятно чем занимется. Если он вызывает
parent::changeSalary($victim, $newVal); то не проще ли сразу ее и вызвыать?
> class Department extends WorkersCreator
> function __construct($inDepInit, $inBoss, $depName)
Это тоже какое-то усложнение. Если подумать, то как связаны Департамент и Сотрудники? В Департамент можно добавлять Сотрудников и можно их увольнять. Но у тебя в Департамент передаются какие-то строки вместо объектов-сотрудников. зачем? И почему Департамент занимается не своим делом - создает сотрудников? Он их по идее только нанимает.
Мне кажется, должны быть методы вроде добавитьСотрудника(сотрудник)/уволитьСотрудника(сотрудник) где сотрудник это объект. Так будет и проще и понятнее, и максимально универсально: ты можешь сам создать какого хочешь сотрудника и добавить в Департамент.
> $crisis = ["аналитик", "зарплата", 700];
> Department::changeWorkerCond($crisis);
Опять ты все запутываешь. Почему не Department::changeWorkerCond("аналитик", "зарплата", 700)? А еще лучше, сделать нормально примерно так:
аналитики = департамент->найтиВсех(аналитиков);
(для каждого аналитика) {
аналитик->задатьБазовуюЗарплату(N);
}
Ну посмотри, насколько проще и универсальнее получается. Без непонятных массивов, статических методов и прочих антипаттернов. И мы можем отбирать аналитиков по любым условиям, например пропустить тех у кого фамилия на «А» начинается, с помощью одного if.
> У меня все строится на диспетчеризации.
Я честно говоря не слышал про такой паттерн.
В общем, по моему код переусложнен, и требует серьезного рефакторинга. Предлагаю упростить схему на картинке. Сделать, чтобы Department занимался только своим делом, а именно, хранением, приемом, увольнением, отбором сотрудников и расчетом общих показателей. Чтобы у сотрудника была одна функция расчет зарплаты, а не 2. Убрать все лишние многомерные массивы. Мне кажется, так будет гораздо проще и код будет меньше по объему.
тут конечно много чего еще рефакторить, потому давай сначала уберем из департамента функцию создания рабочих, а потом посмотрим куда двигаться дальше. Я всегда готов дать подсказку.
> Я изначально понимал, что ООП нужно для создания универсального кода, с максимально простым расширением функционала.
Боюсь, пока что это не очень ООП, а просто код в котором встречаются классы.
> я почему-то решил делать это через статические свойства и методы
Это неправильно. С ними ты не можешь например в одном департаменте повысить зарплату, а в другом нет.
И еще, у тебя почему то в последних 3 таблицах все департаменты одинаково называются.
Сами таблички получились аккуратные, норм.
>Ну так ты же можешь сделать название чекбокса как массив, и допустим получить его таким образом из формы.
Я уже так и делаю, только у меня несколько таких массивов.
> В голове нужно всегда держать возможности из коробки, такие вещи как array_merge(), array_combine(), array_map() с анонимными функциями func(), usort() и т.д.
Ну так да. В питоне тоже надо сначала коллекции изучить прежде чем пользоваться.
> Внимательно следить за определением и использованием $this и self. (Верно $this->property, self::$property).
$this-> соответствует обращению к обычным методам, self:: к статическим, отсюда и разница. Исключение только parent::
> При клонировании, если хотите обнулить существующие свойства необходимо в методе __clone() сделать это явно.
Логично, клонирование создает копию объекта с такими же значениями свойств. Если тебе нужен пустой объект, используй new.
> Знающие, подскажите как реализовывать такое.
Надо использовать анонимные функции. Обычные функции нельзя определять внутри так как имена функций глобальные и ты получишь ошибку «повторное определение функции». Ну и вообще, как-то быдлокодисто выглядит создание неанонимных функций внутри фукнции, если честно.
Не понял вопрос, приведи кусочек кода или поясни, что ты имеешь в виду под словами «ловить вложенность родителя».
>>445327
bash + популярные команды (cat, grep, sed, tail, stat, tar, du, touch, chmod, head, less, sort, uniq и подобные). Чтобы решить задачу вроде «дан лог сервера, посчитать сколько раз там встречается имя каждого домена» или «найти все файлы где встречается слово eval». Написать простейший скрипт выгрузки измененных файлов на удаленный сервер.
Управление сервисами: запуск, останов, перезапуск, reload. Как прописать и убрать сервис из автозапуска.
Настройка Апач/PHP: где лежат конфиги, как применить изменения
Файловая система: основные стандартные директории, система прав
Пользователи: концепции, добавление/удаление/изменение пользователей и групп, sudo, su, как дать себе sudo-права.
ssh, scp, использование ключей.
Пакетный менеджер: как искать, устанавливать пакеты
> "уметь поднять сервер"
Установить и настроить Апач, PHP, mysql.
> А то я тут скачал курс по системному администрированию, сижу слушаю про какие-то шины, драйвера и прочие увлекательные вещи.
Это по моему что-то не то.
Тут есть список полезных команд: http://ss64.com/bash/ — хотя для начинающего может он великоват, но было бы неплохо хотя знать про их наличие. Я большинство знаю например.
Не понял вопрос, приведи кусочек кода или поясни, что ты имеешь в виду под словами «ловить вложенность родителя».
>>445327
bash + популярные команды (cat, grep, sed, tail, stat, tar, du, touch, chmod, head, less, sort, uniq и подобные). Чтобы решить задачу вроде «дан лог сервера, посчитать сколько раз там встречается имя каждого домена» или «найти все файлы где встречается слово eval». Написать простейший скрипт выгрузки измененных файлов на удаленный сервер.
Управление сервисами: запуск, останов, перезапуск, reload. Как прописать и убрать сервис из автозапуска.
Настройка Апач/PHP: где лежат конфиги, как применить изменения
Файловая система: основные стандартные директории, система прав
Пользователи: концепции, добавление/удаление/изменение пользователей и групп, sudo, su, как дать себе sudo-права.
ssh, scp, использование ключей.
Пакетный менеджер: как искать, устанавливать пакеты
> "уметь поднять сервер"
Установить и настроить Апач, PHP, mysql.
> А то я тут скачал курс по системному администрированию, сижу слушаю про какие-то шины, драйвера и прочие увлекательные вещи.
Это по моему что-то не то.
Тут есть список полезных команд: http://ss64.com/bash/ — хотя для начинающего может он великоват, но было бы неплохо хотя знать про их наличие. Я большинство знаю например.
if (empty($_SESSION))
{
header("Location: http://localhost/php2/lessons/index.html");
exit;
}
Почему подобная конструкция в хедере не хочет работать? Редиректит даже при условии что $_SESSION не пустая.
Про куки есть:
https://ru.wikipedia.org/wiki/HTTP_cookie
http://citforum.ru/internet/html/cookie.shtml
Авторизация:
- если ненадолго то создаешь сессию, и если пароль/логин правильный, записываешь в нее loggedUser = id пользователя. Сессия после 20 минут неактивности умирает. Проверяешь залогиненность наличием сессии с переменной loggedUser.
- если надо надолго то дополнительно ставишь куки с логином/хешем (пароль + соль) и когда сессия умирает, пересоздаешь ее из кук.
>>445449
О, да это же неплохой код. Почти решает задачу. Но нужно его еще улучшить.
Во-первых, надо решить, а что будет возвращать через return наша функция? Мне кажется, она должна возвращать найденный путь (например массивом), или null если его найти не удалось.
Исходя из этого давай допилим функцию. Вот тут вот:
> if ($point == $target) {
>\techo "путь пройден за $time\n";
Очевидно надо выходить из функции чтобы после достижения цели мы не перебирали никакие точки, так как мы уже пришли в конечную точку.
Сделай чтобы в случае достижения цели функция возвращала пройденный путь.
Далее, вот тут:
> foreach($paths[$point] as $name => $value) {
мы пытаемся пройти к цели через все возможные точки. Но этого мало. Мы должны сохранить куда-то полученные пути, которые нам возвращает makeStep (в массив например), а потом их всех полученных путей найти наикратчайший и вернуть.
Сделаешь? Если что-то непонятно, напиши что, я могу еще подсказок дать.
Про куки есть:
https://ru.wikipedia.org/wiki/HTTP_cookie
http://citforum.ru/internet/html/cookie.shtml
Авторизация:
- если ненадолго то создаешь сессию, и если пароль/логин правильный, записываешь в нее loggedUser = id пользователя. Сессия после 20 минут неактивности умирает. Проверяешь залогиненность наличием сессии с переменной loggedUser.
- если надо надолго то дополнительно ставишь куки с логином/хешем (пароль + соль) и когда сессия умирает, пересоздаешь ее из кук.
>>445449
О, да это же неплохой код. Почти решает задачу. Но нужно его еще улучшить.
Во-первых, надо решить, а что будет возвращать через return наша функция? Мне кажется, она должна возвращать найденный путь (например массивом), или null если его найти не удалось.
Исходя из этого давай допилим функцию. Вот тут вот:
> if ($point == $target) {
>\techo "путь пройден за $time\n";
Очевидно надо выходить из функции чтобы после достижения цели мы не перебирали никакие точки, так как мы уже пришли в конечную точку.
Сделай чтобы в случае достижения цели функция возвращала пройденный путь.
Далее, вот тут:
> foreach($paths[$point] as $name => $value) {
мы пытаемся пройти к цели через все возможные точки. Но этого мало. Мы должны сохранить куда-то полученные пути, которые нам возвращает makeStep (в массив например), а потом их всех полученных путей найти наикратчайший и вернуть.
Сделаешь? Если что-то непонятно, напиши что, я могу еще подсказок дать.
Проверку сделай через session_id() - есть айди оставайся, пустая строка - улетай. А вообще, у тебя ошибка в коде :
if(empty($_SESSIONЗдесь ничего не хочешь поставить?)
А всё, разобрался.
> Не регулярками же парсить?
Конечно нет.
Парсить удобно либо XML-парсером (DOMDocument, SimpleXMLDom) либо аналогичными библиотеками (вроде phpQuery). В случае XML парсера надо еще знание языка для поиска узлов в дереве XPAth:
https://ru.wikipedia.org/wiki/XPath
http://zvon.org/xxl/XPathTutorial/General_rus/examples.html
В случае с яваскриптом лол, опечтался и написал язваскрипт можно либо попробовать раскодировать содержимое onmouseover либо использовать эмулятор браузера наподобие phantomJS, либо расширение php v8.
>>445511
> Скажите как мне совместить эти две структуры? Где должна находится библиотека extjs в структуре Zend и где вся папка app приложения на extjs.
Я думаю JS код должен быть внутри JS-папки, например public/js
>>445545
Через CSS, есть минимум 2 способа:
- с исплоьзованием якорей и псевдоселектора :target (профит: выбранный таб есть в адресной строке и не теряется при перезагрузке страницы)
- с помощью скрытого input type=radio (профит: адресная строка не загрязняется, можно переключать табы стрелками если выделить)
Советую изучить оба способа. Чтение:
http://habrahabr.ru/post/223583/
http://habrahabr.ru/post/174029/
http://habrahabr.ru/sandbox/40690/
http://habrahabr.ru/post/167151/
>>445551
Почему он тупой? Он начинающий и задал нормальный вопрос. Сам ты тупой.
> Там же есть кнопочка Edit code
Это все равно что списать решение. знаний не дает.
>>445600
Перегруппировать полученный массив кодом на php в массив нужного тебе вида. Делается с помощью циклов и if.
>>445719
А что плохого? Там как я понимаю, талантливый творческий коллектив и можно много чему научиться. Ну и строчка в резюме весомая получается.
>>445744
Может быть платят ниже рынка за возможность научиться, работать с именитыми заказчиками и получить строчку в резюме?
> Я видел код чуваков оттуда, весьма посредственно.
Там в первую очередь интересно дизайнерам, программисты там обслуживающий персонал.
>>445751
Они добавляются же:
> ["a"]=>
> array(3) {
> [0]=>
> object(Test)#3 (1) {
>>445791
Это не я. Я обычно к написанию не придираюсь если вижу что человек на «вы» с английским. Но конечно лучше бы слова в google translate хотя бы смотреть.
> Не регулярками же парсить?
Конечно нет.
Парсить удобно либо XML-парсером (DOMDocument, SimpleXMLDom) либо аналогичными библиотеками (вроде phpQuery). В случае XML парсера надо еще знание языка для поиска узлов в дереве XPAth:
https://ru.wikipedia.org/wiki/XPath
http://zvon.org/xxl/XPathTutorial/General_rus/examples.html
В случае с яваскриптом лол, опечтался и написал язваскрипт можно либо попробовать раскодировать содержимое onmouseover либо использовать эмулятор браузера наподобие phantomJS, либо расширение php v8.
>>445511
> Скажите как мне совместить эти две структуры? Где должна находится библиотека extjs в структуре Zend и где вся папка app приложения на extjs.
Я думаю JS код должен быть внутри JS-папки, например public/js
>>445545
Через CSS, есть минимум 2 способа:
- с исплоьзованием якорей и псевдоселектора :target (профит: выбранный таб есть в адресной строке и не теряется при перезагрузке страницы)
- с помощью скрытого input type=radio (профит: адресная строка не загрязняется, можно переключать табы стрелками если выделить)
Советую изучить оба способа. Чтение:
http://habrahabr.ru/post/223583/
http://habrahabr.ru/post/174029/
http://habrahabr.ru/sandbox/40690/
http://habrahabr.ru/post/167151/
>>445551
Почему он тупой? Он начинающий и задал нормальный вопрос. Сам ты тупой.
> Там же есть кнопочка Edit code
Это все равно что списать решение. знаний не дает.
>>445600
Перегруппировать полученный массив кодом на php в массив нужного тебе вида. Делается с помощью циклов и if.
>>445719
А что плохого? Там как я понимаю, талантливый творческий коллектив и можно много чему научиться. Ну и строчка в резюме весомая получается.
>>445744
Может быть платят ниже рынка за возможность научиться, работать с именитыми заказчиками и получить строчку в резюме?
> Я видел код чуваков оттуда, весьма посредственно.
Там в первую очередь интересно дизайнерам, программисты там обслуживающий персонал.
>>445751
Они добавляются же:
> ["a"]=>
> array(3) {
> [0]=>
> object(Test)#3 (1) {
>>445791
Это не я. Я обычно к написанию не придираюсь если вижу что человек на «вы» с английским. Но конечно лучше бы слова в google translate хотя бы смотреть.
В чем проблема была?
Короче, я разобрался, нашел вот это http://myrusakov.ru/php-filter-search.html и понял, куда надо рыть.
Еще неплохо бы знать основы работы в vim, меня как-то спрашивали на собеседовании, лол. Но к счастью я имел дело с ним.
А я знаю что это не ты был. Просто все равно лучше написать правильно. Так красивее.
Кстати, там атмосфера очень рабочая, как я понимаю, люди чуть ли не живут на работе, а не так что в 19 или 20 встал и ушел.
Ну а зарабатывает там конечно только один человек. Остальные не ради денег приходят.
>>445796
Редисом наверно. Там есть sorted lists, они не годятся? Наверняка годятся.
>>445804
Нет. Грамматика это склонения, спряжения, структура предложений и подобные вещи.
>>445816
WHERE id IN (?, ?, ?)
>>445818
надо числа перед implode обработать через intval а то будет sql инъекция
>>445821
Не паникуй. Я просто весь день проспал и потому не ответил сразу.
>>445825
Расширение mysql давно устарело. Используй PDO (рекомендуется) или mysqli. Ну и тебе не надо читать весь массив, там обычно есть функции типа fetch_column которые берут только одно значение, а не массив.
> $IdArray[$i]
надо писать $ids[] = ... ты php-то изучал? Тут $i не нужен.
>>445860
Только на HTML кофейниках.
>>445872
> Не проще тогда таблицу сортировать на клиенте в bootsrtram вроде есть нужные плагины?
Эти плагины либо выгружают всю таблицу на страницу (что плохо) либо шлют аякс-запросы и придется все равно писать выборку по условию. А в чем проблема сделать? Лучше сделать нормально, а то ты ничему толком не научишься.
> Что стоит положить в ридми на гитхаб, описания тобой задач?
Можно описание задачи и как скачать/развернуть.
>>445894
Лол. Ок, я запутался сам. Тебе нужен http://php.net/manual/ru/pdostatement.bindvalue.php разумеется.
>>445895
Ты похоже прав, в комментах тоже используется этот setFetchStyle: http://php.net/manual/ru/pdostatement.fetch.php#78794
Тут есть такая функция: http://php.net/manual/ru/pdostatement.fetchobject.php но у нее тоже свои «странности»: она выставляет свойства до вызова конструктора, вопреки здравому смыслу (так как конструктор всегда вызывается до любых дейтсвий с объектом).
Видимо это еще один архитектурный недостаток PDO. Увы, в некоторых местах PHP c ООП не все гладко, видимо некоторые разработчики его сами не очеь понимают.
Раз так, пусть остается setFetchStyle, только не забывай это ставить перед любым fetch.
>>445910
Так нормально. Только я не советую писать такие селекторы:
> div.graybox{
div тут избыточен, значит не стоит его писать. Ведь мы вряд ли будем использовать graybox c чем-то кроме div.
>>445925
Этот конструктор называется Query Builder. Вот пример из ZF: http://framework.zend.com/manual/1.12/ru/zend.db.select.html
Он позволяет конструировать запрос по частям не боясь сломать SQL код или пропустить SQL инъекуцию. Ты можешь взять готовую библиотеку или написать свой велосипед (плохая идея).
Query Builder есть и в Doctrine Dbal: http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/query-builder.html
>>445932
Keys надо пропустить через array_map('intval', ...) чтобы защититься от инъекции.
>>445941
Блог лучше чем его отстуствие.
>>445946
Нет защиты от SQL инъекуий, и лучше не возиться со строчками, а использовать Query Builder.
Кстати, там атмосфера очень рабочая, как я понимаю, люди чуть ли не живут на работе, а не так что в 19 или 20 встал и ушел.
Ну а зарабатывает там конечно только один человек. Остальные не ради денег приходят.
>>445796
Редисом наверно. Там есть sorted lists, они не годятся? Наверняка годятся.
>>445804
Нет. Грамматика это склонения, спряжения, структура предложений и подобные вещи.
>>445816
WHERE id IN (?, ?, ?)
>>445818
надо числа перед implode обработать через intval а то будет sql инъекция
>>445821
Не паникуй. Я просто весь день проспал и потому не ответил сразу.
>>445825
Расширение mysql давно устарело. Используй PDO (рекомендуется) или mysqli. Ну и тебе не надо читать весь массив, там обычно есть функции типа fetch_column которые берут только одно значение, а не массив.
> $IdArray[$i]
надо писать $ids[] = ... ты php-то изучал? Тут $i не нужен.
>>445860
Только на HTML кофейниках.
>>445872
> Не проще тогда таблицу сортировать на клиенте в bootsrtram вроде есть нужные плагины?
Эти плагины либо выгружают всю таблицу на страницу (что плохо) либо шлют аякс-запросы и придется все равно писать выборку по условию. А в чем проблема сделать? Лучше сделать нормально, а то ты ничему толком не научишься.
> Что стоит положить в ридми на гитхаб, описания тобой задач?
Можно описание задачи и как скачать/развернуть.
>>445894
Лол. Ок, я запутался сам. Тебе нужен http://php.net/manual/ru/pdostatement.bindvalue.php разумеется.
>>445895
Ты похоже прав, в комментах тоже используется этот setFetchStyle: http://php.net/manual/ru/pdostatement.fetch.php#78794
Тут есть такая функция: http://php.net/manual/ru/pdostatement.fetchobject.php но у нее тоже свои «странности»: она выставляет свойства до вызова конструктора, вопреки здравому смыслу (так как конструктор всегда вызывается до любых дейтсвий с объектом).
Видимо это еще один архитектурный недостаток PDO. Увы, в некоторых местах PHP c ООП не все гладко, видимо некоторые разработчики его сами не очеь понимают.
Раз так, пусть остается setFetchStyle, только не забывай это ставить перед любым fetch.
>>445910
Так нормально. Только я не советую писать такие селекторы:
> div.graybox{
div тут избыточен, значит не стоит его писать. Ведь мы вряд ли будем использовать graybox c чем-то кроме div.
>>445925
Этот конструктор называется Query Builder. Вот пример из ZF: http://framework.zend.com/manual/1.12/ru/zend.db.select.html
Он позволяет конструировать запрос по частям не боясь сломать SQL код или пропустить SQL инъекуцию. Ты можешь взять готовую библиотеку или написать свой велосипед (плохая идея).
Query Builder есть и в Doctrine Dbal: http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/query-builder.html
>>445932
Keys надо пропустить через array_map('intval', ...) чтобы защититься от инъекции.
>>445941
Блог лучше чем его отстуствие.
>>445946
Нет защиты от SQL инъекуий, и лучше не возиться со строчками, а использовать Query Builder.
> не понимаю как передать произвольное количество аргументов.
Получить через arguments:
http://learn.javascript.ru/arguments-pseudoarray
http://javascript.ru/arguments
Передать через apply:
http://javascript.ru/Function/apply
http://learn.javascript.ru/this#явное-указание-this-apply-и-call
> fn = fn|| function fn() {};
> array = array|| [];
Это не требуется, так как нет никакого смысла вызывать функцию без аргументов.
> var newArray = []
Точку с запятой забыл. Лучше не забывать так как иначе JS их сам расставит и не факт что правильно.
> newArray = fn(array);
Лучше push
А первые 2 задачи решены верно.
Выводим форму($values, $errors);
В каком виде? Стартовую страницу вывести с заполненными данными но с пустыми строками там где ошибка? Можно ли где-то об этом почитать? Я сам не нашел как можно вернуть стартовую форму с заполненными данными.
Тащемта, :q! если ты про выход без сохранения :-)
Иногда используя vim простые манипуляции над файлом быстрее получается делать чем через гуи, хотя дело привычки, конечно.
> https://github.com/someApprentice/Vector-Com/blob/master/Classes/Direction.php#L125
> $Employee->rang = 3
Опечатка
> https://github.com/someApprentice/Vector-Com/blob/master/index.php#L24
> https://github.com/someApprentice/Vector-Com/blob/master/index.php#L31
Копипаста
> https://github.com/someApprentice/Vector-Com/blob/master/Classes/Direction.php#L8
> $Department
Переменные пишутся с маленькой буквы
> PHP_ROUND_HALF_UP);
Есть более короткие функции floor и ceil
> $Department->unsetEmployee($employeekey);
это нелогично, передавать в функцию unsetEmployee какой-то $key который непонятно как получить. Логично передавать объект-работника.
Плюс, ты занимаешься опасным делом: ты перебираешь массив одновременно с удалением элементов из него.Лучше было бы отобрать кандидатов на увольнение в массив, а затем уволить.
> https://github.com/someApprentice/Vector-Com/blob/master/Classes/Direction.php#L26
Тут логика немного неправильная. Надо в каждом департаменте уволить по 40% человек. А ты можешь в первом департаменте вообще всех уволить с таким подходом, а в последнем никого.
Ну и 3 цикла различаются только одной цифрой — это копипаста.
> https://github.com/someApprentice/Vector-Com/blob/master/Classes/Direction.php#L81
> \t\t\t\t\t$Employee->salary = $newSalary;
>\t\t\t\t\t$Employee->salary = $Employee->calculateSalary( );
Это сильно запутывает. У тебя в одной строчке salary обозначает базовую зарплату, а во второй уже итоговую. Такой код — верный путь к ошибкам.
Я советую сделать так чтобы salary обозначало базовую ставку, а итоговая зарплата нигде не хранилась, а рассчитывалась с помощью метода. И тогда достаточно будет одной строчки для замены зарплаты.
Или у тебя есть какие-то аругменты в пользу твоего подхода? Давай их выслушаем тогда.
Ну и еще неочевидно, что после того как меняешь salary надо вызвать calculateSalary. Как я например об этом догадаюсь, если захочу использовать твой класс? Я советую тебе не делать таких трюков, а просто сделать метод getSalary который посчитает текущую зарплату работника. Или сделать изменение базовой ставки через метод, а не публично доступное свойство.
В этом методе
> https://github.com/someApprentice/Vector-Com/blob/master/Classes/Direction.php#L105
> public function setToLeader($type) {
Ошибка в логике. Сначала ты снимаешь всех боссов. Затем пытаешься найти замену. А если замены нет? Департамент останется без босса.
Ну и вторая ошибка. Тут логичнее сделать у Департамента метод поменятьБосса(новыйБосс). Так как если мне (или какому-то воображаемому программисту) захочется поменять босса, то ему не придется писать руками это, а он сможет использовать готовый метод. Также, если закрыть доступ к массиву employees снаружи, код станет надежнее. А твой подход, когда ты снаружи ковыряешься в работниках, делает код менее надежным. Потому в правильном ООП коде вообще нет public свойств, а все действия с объектом делаются через методы.
Также, тут https://github.com/someApprentice/Vector-Com/blob/master/Classes/Direction.php#L117 копипаста.
Я думаю, надо сделать метод вроде отобратьРаботников(департамент, профессия, процент, порядокСортировки). Кстати, отобрать их можно без этих адских циклов. Отсеять подходящих по профессии можно через array_filter, отсортировать по рангам через usort, взять первые N через array_slice. Так код будет читабельнее и аккуратнее, ну и ты лучше научишься работать с массивами.
Насчет «побыстрее закончить» — я в принципе не против, ты можешь параллельно делать следующее задание. Но это надо бы сделать нормально, а не как побыстрее. Потому что главная цель научиться писать хороший ООП-код.
> https://github.com/someApprentice/Vector-Com/blob/master/Classes/Direction.php#L125
> $Employee->rang = 3
Опечатка
> https://github.com/someApprentice/Vector-Com/blob/master/index.php#L24
> https://github.com/someApprentice/Vector-Com/blob/master/index.php#L31
Копипаста
> https://github.com/someApprentice/Vector-Com/blob/master/Classes/Direction.php#L8
> $Department
Переменные пишутся с маленькой буквы
> PHP_ROUND_HALF_UP);
Есть более короткие функции floor и ceil
> $Department->unsetEmployee($employeekey);
это нелогично, передавать в функцию unsetEmployee какой-то $key который непонятно как получить. Логично передавать объект-работника.
Плюс, ты занимаешься опасным делом: ты перебираешь массив одновременно с удалением элементов из него.Лучше было бы отобрать кандидатов на увольнение в массив, а затем уволить.
> https://github.com/someApprentice/Vector-Com/blob/master/Classes/Direction.php#L26
Тут логика немного неправильная. Надо в каждом департаменте уволить по 40% человек. А ты можешь в первом департаменте вообще всех уволить с таким подходом, а в последнем никого.
Ну и 3 цикла различаются только одной цифрой — это копипаста.
> https://github.com/someApprentice/Vector-Com/blob/master/Classes/Direction.php#L81
> \t\t\t\t\t$Employee->salary = $newSalary;
>\t\t\t\t\t$Employee->salary = $Employee->calculateSalary( );
Это сильно запутывает. У тебя в одной строчке salary обозначает базовую зарплату, а во второй уже итоговую. Такой код — верный путь к ошибкам.
Я советую сделать так чтобы salary обозначало базовую ставку, а итоговая зарплата нигде не хранилась, а рассчитывалась с помощью метода. И тогда достаточно будет одной строчки для замены зарплаты.
Или у тебя есть какие-то аругменты в пользу твоего подхода? Давай их выслушаем тогда.
Ну и еще неочевидно, что после того как меняешь salary надо вызвать calculateSalary. Как я например об этом догадаюсь, если захочу использовать твой класс? Я советую тебе не делать таких трюков, а просто сделать метод getSalary который посчитает текущую зарплату работника. Или сделать изменение базовой ставки через метод, а не публично доступное свойство.
В этом методе
> https://github.com/someApprentice/Vector-Com/blob/master/Classes/Direction.php#L105
> public function setToLeader($type) {
Ошибка в логике. Сначала ты снимаешь всех боссов. Затем пытаешься найти замену. А если замены нет? Департамент останется без босса.
Ну и вторая ошибка. Тут логичнее сделать у Департамента метод поменятьБосса(новыйБосс). Так как если мне (или какому-то воображаемому программисту) захочется поменять босса, то ему не придется писать руками это, а он сможет использовать готовый метод. Также, если закрыть доступ к массиву employees снаружи, код станет надежнее. А твой подход, когда ты снаружи ковыряешься в работниках, делает код менее надежным. Потому в правильном ООП коде вообще нет public свойств, а все действия с объектом делаются через методы.
Также, тут https://github.com/someApprentice/Vector-Com/blob/master/Classes/Direction.php#L117 копипаста.
Я думаю, надо сделать метод вроде отобратьРаботников(департамент, профессия, процент, порядокСортировки). Кстати, отобрать их можно без этих адских циклов. Отсеять подходящих по профессии можно через array_filter, отсортировать по рангам через usort, взять первые N через array_slice. Так код будет читабельнее и аккуратнее, ну и ты лучше научишься работать с массивами.
Насчет «побыстрее закончить» — я в принципе не против, ты можешь параллельно делать следующее задание. Но это надо бы сделать нормально, а не как побыстрее. Потому что главная цель научиться писать хороший ООП-код.
Вполне. Скажи, что в процессе получения военника. Его не всегда моментально выдают. Мне год давали. Диагноз. На следующий призыв подтверждение и только через 5-6 месяцев сам военник в руки.
> Стартовую страницу вывести с заполненными данными
Да
> но с пустыми строками там где ошибка?
лучше оставить ошибочные данные чтобы их можно было отредактировать.
> Можно ли где-то об этом почитать?
Не знаю.
> Я сам не нашел как можно вернуть стартовую форму с заполненными данными.
// допустим это пришло нам из _GET
$armor = 400;
require 'form.php';
// Файл form.php
Броня:
<input value="<?= $armor ?>">
Прочел. Появились несколько вопросов, но я задам их завтра на свежую голову. Сейчас уже поздно.
Добра.
Твоя задача спроектировать все нужные таблицы. Если для решения задачи требуется хранить кто кому что поставил, то надо хранить.
Взаимный лайк это если пользователь A поставил лайк пользователю B, и пользователь B — пользователю A. Невзаимный это если A поставил лайк B, а B нет.
я не понимаю как я должен сделать ретерн из функции которая сама себя много раз вызывает параллельно. Очевидно из того что она эхает, что она путь находит десятком способов в процессе, и как мне сделать что бы она вернула всё это?
Вот я таким же вопросом задавался, когда решал. В итоге забил и взял другой алгоритм (Дейкстра).
Сравнивать варианты: брать первый путь найденный до точки назначения и сравнивать со следующим - если он быстрее по времени - перезаписывать, если нет - ничего не делать. В конце вернуть путь из этой переменной.
Есть две таблицы, на одной пики в одной у меня есть столбец со списком слов, а во второй таблице тоже столбец со списком слов и столбец числового значения к этому столбцу. Никак не могу сформулировать запрос, чтобы объединил эти таблицы в одну, как видно на пикче. Раньше всегда объединял джоином по id, но сейчас айдишники разные. Помогите, плз.
Окей, давай я постараюсь тебе помочь, хоть я тут и самый рак в принципе. У тебя эти таблицы связаны через FOREIGN KEY по полю word?
Вот у меня на пикрилейтеде создание двух таблиц, и вторая, которая posts, связана с users, через user_id. Думаю что можно через ALTER TABLE сделать, если это при создании упущено.
Далее селект у тебя должен быть примерно такой:
SELECT table1.id1, table1.word, table2.number
FROM table1 JOIN table2 ON table1.word = table2.word;
Хм, а ведь точно получилось! Не думал, что текстовые значения тоже можно сравнивать.
>>446194
Сорь, я не знаю, что такое FOREIGN KEY. Знаю только, что во второй таблице у меня есть некоторые слова, которые есть и в первой, поэтому есть возможность вытянуть некоторые значения number.
Благодарю обоих, вышло так:
SELECT * FROM table1
LEFT JOIN table2 ON table1.word = table2.word
WHERE table1.id = 553
Блядь, написал большой ответ и все пошло по пизде из-за невалидной капчи.
В кратце: проверил твой запрос, он работает, но отфильтровывает результаты, где нет числа number. Поэтому нужен именно левый джоин.
я пока не разбираюсь в типах джойнов, но если просто поменять в моем запросе JOIN на LEFT JOIN, то всё сработает?
> $Department->unsetEmployee($employeekey);
это нелогично, передавать в функцию unsetEmployee какой-то $key который непонятно как получить. Логично передавать объект-работника.
>Плюс, ты занимаешься опасным делом: ты перебираешь массив одновременно с удалением элементов из него.Лучше было бы отобрать кандидатов на увольнение в массив, а затем уволить.
А как из массива удалить целый объект?
>Я советую сделать так чтобы salary обозначало базовую ставку, а итоговая зарплата нигде не хранилась, а рассчитывалась с помощью метода. И тогда достаточно будет одной строчки для замены зарплаты.
>Или у тебя есть какие-то аругменты в пользу твоего подхода? Давай их выслушаем тогда.
Ну, если честно, мне пришла в голову мысль, что так не бывает на самом деле. То есть сотрудник должен знать свою зарплату без обращения к функции, поэтому она должна где-то храниться. Но думаю, что вопрос того уже что мы требуется от задачи.
>Ну и еще неочевидно, что после того как меняешь salary надо вызвать calculateSalary. Как я например об этом догадаюсь, если захочу использовать твой класс? Я советую тебе не делать таких трюков, а просто сделать метод getSalary который посчитает текущую зарплату работника. Или сделать изменение базовой ставки через метод, а не публично доступное свойство.
Я, если честно, сам обратил на это внимание только когда выводил зарплату. Теперь я вижу что лучше выводить зарплату через метод, хоть и считаю что конечная зарплата все равно должна где-то храниться.
>Ошибка в логике. Сначала ты снимаешь всех боссов. Затем пытаешься найти замену. А если замены нет? Департамент останется без босса.
Не понял. А зачем тогда вызывать эту функцию если мы не собираемся назначать нового лидера?
>array_filter
А как пользоваться callback-функциями? Я не понимаю что значит >return($var & 1);. Конкретно что делает здесь оператор &.
Это из мануала: http://php.net/manual/ru/function.array-filter.php
>Но это надо бы сделать нормально, а не как побыстрее.
Я хочу побыстрее сделать правильно =^_^=
> $Department->unsetEmployee($employeekey);
это нелогично, передавать в функцию unsetEmployee какой-то $key который непонятно как получить. Логично передавать объект-работника.
>Плюс, ты занимаешься опасным делом: ты перебираешь массив одновременно с удалением элементов из него.Лучше было бы отобрать кандидатов на увольнение в массив, а затем уволить.
А как из массива удалить целый объект?
>Я советую сделать так чтобы salary обозначало базовую ставку, а итоговая зарплата нигде не хранилась, а рассчитывалась с помощью метода. И тогда достаточно будет одной строчки для замены зарплаты.
>Или у тебя есть какие-то аругменты в пользу твоего подхода? Давай их выслушаем тогда.
Ну, если честно, мне пришла в голову мысль, что так не бывает на самом деле. То есть сотрудник должен знать свою зарплату без обращения к функции, поэтому она должна где-то храниться. Но думаю, что вопрос того уже что мы требуется от задачи.
>Ну и еще неочевидно, что после того как меняешь salary надо вызвать calculateSalary. Как я например об этом догадаюсь, если захочу использовать твой класс? Я советую тебе не делать таких трюков, а просто сделать метод getSalary который посчитает текущую зарплату работника. Или сделать изменение базовой ставки через метод, а не публично доступное свойство.
Я, если честно, сам обратил на это внимание только когда выводил зарплату. Теперь я вижу что лучше выводить зарплату через метод, хоть и считаю что конечная зарплата все равно должна где-то храниться.
>Ошибка в логике. Сначала ты снимаешь всех боссов. Затем пытаешься найти замену. А если замены нет? Департамент останется без босса.
Не понял. А зачем тогда вызывать эту функцию если мы не собираемся назначать нового лидера?
>array_filter
А как пользоваться callback-функциями? Я не понимаю что значит >return($var & 1);. Конкретно что делает здесь оператор &.
Это из мануала: http://php.net/manual/ru/function.array-filter.php
>Но это надо бы сделать нормально, а не как побыстрее.
Я хочу побыстрее сделать правильно =^_^=
И в новый тред его я репостну
Возьму фап-пак, запощу няшных тней
Анончику, спалившему годноту
У меня есть таблица организаций, организация может быть дочерней по отношению к другой. Определяю это полем parent_id, если 0 - организация сама по себе, если дочерняя - там id головной организации из этой же таблицы.
Как через ORM вытащить список головных организаций, у которых в одном поле будет список id дочерних?
> А как из массива удалить целый объект?
Есть разные способы: найти ключ с помощью array_search и удалить, удалить через array_diff (если надо удалить много человек сразу). Мне кажется, проще всего через array_search + unset. Не забудь сначала прочесть мануал ( https://php.net/manual/ru/function.array-search.php ), и не забудь поставить флаг $strict = true иначе сравнение будет нестрогое и array_search найдет не тот же самый объект, а первый попавшийся объект с теми же значениями полей (то есть не то, что нам надо).
Также не забудь, что нужного объекта может и не найтись.
Поиск через array_search перебирает все элементы массива и имеет сложность O(N), то есть когда тебе надо удалить много тысяч сотрудников из большого массива, этот метод неэффективен. Если ты будешь работать с большими коллекциями объектов, лучше вместо массива использовать SplObjectStorage ( http://php.net/manual/ru/class.splobjectstorage.php ). Этот класс умеет сохранять коллекцию объектов (это что-то вроде массива, где ключами служат объекты, в обычных массивах ключи могут быть только числом или строкой), быстро добавлять и удалять объекты из нее, перебирать их через foreach. Если у тебя есть желание разобраться, можешь попробовать его использовать.
> Ну, если честно, мне пришла в голову мысль, что так не бывает на самом деле. То есть сотрудник должен знать свою зарплату без обращения к функции, поэтому она должна где-то храниться. Но думаю, что вопрос того уже что мы требуется от задачи.
У тебя одно и то же поле (salary) обозначает и базовую ставку, и итоговую зарплату. Этого не должно быть в любом случае, так как это приводит к путанице. Как работать с объектом если непонятно что у него хранится в поле? Должно быть либо 2 разных поля, либо одно поле с базовой ставкой.
Теперь насчет хранения итоговой зарплаты. Хранить ее нет смысла, так как ее в любой момент можно вычислить. Но если тебе так хочется ее хранить, ты должен как-то гарантировать ее актуальность. То есть при смене базовой ставки, ранга, статуса босса она должна пересчитываться автоматически.
Вот это пример плохого кода:
$employee->baseSalary = 10; // меняем базовую ставку
$employee->recalculateSalary( ); // пересчитываем зарплату
echo $employee->salary;
Он плохой, так как неочевидно, почему я должен вызывать recalculateSalary? Как я об этом догадаюсь? Если у меня допустим среднего размера приложение состоит из 1000 классов, я для каждого класса должен наизучть помнить, что я должен вызвать при изменении того или иного поля? ООП не для этого придумывался. ООП придумывался для того, чтобы помнить было ничего не надо.
Вот как можно сделать это:
$employee->baseSalary = 10; // меняем базовую ставку
echo $employee->getSalary( ); // выводим результат
Или, что еще лучше, убрать поля из публичного доступа и делать все через методы. Так код становится еще надежнее, так как метод setBaseSalary может например запретить ставить отрицательное число в качестве зарплаты:
$employee->setBaseSalary(10);
echo $employee->getSalary( );
Видишь, в 2 последних примерах нам не надо ничего знать о классе. Мы просто смотрим какие у него есть публичные поля или методы и обращаемся к ним, и все работает.
> То есть сотрудник должен знать свою зарплату без обращения к функции
Что плохого в обращении к функции? Разница между вызовом метода и обращением к полю всего лишь 2 скобки, и в хорошем ООП-коде ты все равно снаружи не можешь обращаться к полям объектов.
> Теперь я вижу что лучше выводить зарплату через метод, хоть и считаю что конечная зарплата все равно должна где-то храниться.
Ты можешь ее хранить, но в отдельном поле и надо обеспечить ее автоматический пересчет.
> А зачем тогда вызывать эту функцию если мы не собираемся назначать нового лидера?
Мы назначем нового лидера если есть достойный кандидат. Если его нет, надо оставлять старого.
> А как пользоваться callback-функциями?
Для начала изучи раздел про анонимные функции.Это функции, ссылка на которые хранится в переменной: https://php.net/manual/ru/functions.anonymous.php
array_filter обходит массив и вызывает для каждого элемента твою функцию. Она должна решить оставляем мы элемент в массиве, или нет, и вернуть true/false. Вот пример, который выведет нечетные числа:
$numbers = array_filter(range(1, 50), function ($n) {
return ($n % 2) != 0;
});
echo implode(', ', $numbers);
Если ты не понял, как он работает, то вспомни что оператор != возвращает true если числа не равны, и false в противном случае. Оператор % берет остаток от деления $n на 2.
> return(!($var & 1));
Это хитрый трюк, и зря конечно они его используют в мануале. & это оператор, который делает побитовое «И» над двумя числами в двоичном виде (вики: https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 ). Нечетные числа в двоичном виде всегда оканиваются на 1, а четные на 0. $var & 1 откусывает от числа этот последний бит и возвращает 0 или 1. !0 == true, а !1 == false.
Если ты захочешь разобраться в двоиной арифметике, задавай вопросы, и я могу ссылку какую-нибудь найти.
Но мне кажется, это неудачный пример для мануала, так как требует знание двоичных чисел и битовых операций.
Проверять на нечетность лучше взятием остатка от деления на 2. Нечетные числа дают в остатке 1, а четные 0.
> А как из массива удалить целый объект?
Есть разные способы: найти ключ с помощью array_search и удалить, удалить через array_diff (если надо удалить много человек сразу). Мне кажется, проще всего через array_search + unset. Не забудь сначала прочесть мануал ( https://php.net/manual/ru/function.array-search.php ), и не забудь поставить флаг $strict = true иначе сравнение будет нестрогое и array_search найдет не тот же самый объект, а первый попавшийся объект с теми же значениями полей (то есть не то, что нам надо).
Также не забудь, что нужного объекта может и не найтись.
Поиск через array_search перебирает все элементы массива и имеет сложность O(N), то есть когда тебе надо удалить много тысяч сотрудников из большого массива, этот метод неэффективен. Если ты будешь работать с большими коллекциями объектов, лучше вместо массива использовать SplObjectStorage ( http://php.net/manual/ru/class.splobjectstorage.php ). Этот класс умеет сохранять коллекцию объектов (это что-то вроде массива, где ключами служат объекты, в обычных массивах ключи могут быть только числом или строкой), быстро добавлять и удалять объекты из нее, перебирать их через foreach. Если у тебя есть желание разобраться, можешь попробовать его использовать.
> Ну, если честно, мне пришла в голову мысль, что так не бывает на самом деле. То есть сотрудник должен знать свою зарплату без обращения к функции, поэтому она должна где-то храниться. Но думаю, что вопрос того уже что мы требуется от задачи.
У тебя одно и то же поле (salary) обозначает и базовую ставку, и итоговую зарплату. Этого не должно быть в любом случае, так как это приводит к путанице. Как работать с объектом если непонятно что у него хранится в поле? Должно быть либо 2 разных поля, либо одно поле с базовой ставкой.
Теперь насчет хранения итоговой зарплаты. Хранить ее нет смысла, так как ее в любой момент можно вычислить. Но если тебе так хочется ее хранить, ты должен как-то гарантировать ее актуальность. То есть при смене базовой ставки, ранга, статуса босса она должна пересчитываться автоматически.
Вот это пример плохого кода:
$employee->baseSalary = 10; // меняем базовую ставку
$employee->recalculateSalary( ); // пересчитываем зарплату
echo $employee->salary;
Он плохой, так как неочевидно, почему я должен вызывать recalculateSalary? Как я об этом догадаюсь? Если у меня допустим среднего размера приложение состоит из 1000 классов, я для каждого класса должен наизучть помнить, что я должен вызвать при изменении того или иного поля? ООП не для этого придумывался. ООП придумывался для того, чтобы помнить было ничего не надо.
Вот как можно сделать это:
$employee->baseSalary = 10; // меняем базовую ставку
echo $employee->getSalary( ); // выводим результат
Или, что еще лучше, убрать поля из публичного доступа и делать все через методы. Так код становится еще надежнее, так как метод setBaseSalary может например запретить ставить отрицательное число в качестве зарплаты:
$employee->setBaseSalary(10);
echo $employee->getSalary( );
Видишь, в 2 последних примерах нам не надо ничего знать о классе. Мы просто смотрим какие у него есть публичные поля или методы и обращаемся к ним, и все работает.
> То есть сотрудник должен знать свою зарплату без обращения к функции
Что плохого в обращении к функции? Разница между вызовом метода и обращением к полю всего лишь 2 скобки, и в хорошем ООП-коде ты все равно снаружи не можешь обращаться к полям объектов.
> Теперь я вижу что лучше выводить зарплату через метод, хоть и считаю что конечная зарплата все равно должна где-то храниться.
Ты можешь ее хранить, но в отдельном поле и надо обеспечить ее автоматический пересчет.
> А зачем тогда вызывать эту функцию если мы не собираемся назначать нового лидера?
Мы назначем нового лидера если есть достойный кандидат. Если его нет, надо оставлять старого.
> А как пользоваться callback-функциями?
Для начала изучи раздел про анонимные функции.Это функции, ссылка на которые хранится в переменной: https://php.net/manual/ru/functions.anonymous.php
array_filter обходит массив и вызывает для каждого элемента твою функцию. Она должна решить оставляем мы элемент в массиве, или нет, и вернуть true/false. Вот пример, который выведет нечетные числа:
$numbers = array_filter(range(1, 50), function ($n) {
return ($n % 2) != 0;
});
echo implode(', ', $numbers);
Если ты не понял, как он работает, то вспомни что оператор != возвращает true если числа не равны, и false в противном случае. Оператор % берет остаток от деления $n на 2.
> return(!($var & 1));
Это хитрый трюк, и зря конечно они его используют в мануале. & это оператор, который делает побитовое «И» над двумя числами в двоичном виде (вики: https://ru.wikipedia.org/wiki/%D0%91%D0%B8%D1%82%D0%BE%D0%B2%D1%8B%D0%B5_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8 ). Нечетные числа в двоичном виде всегда оканиваются на 1, а четные на 0. $var & 1 откусывает от числа этот последний бит и возвращает 0 или 1. !0 == true, а !1 == false.
Если ты захочешь разобраться в двоиной арифметике, задавай вопросы, и я могу ссылку какую-нибудь найти.
Но мне кажется, это неудачный пример для мануала, так как требует знание двоичных чисел и битовых операций.
Проверять на нечетность лучше взятием остатка от деления на 2. Нечетные числа дают в остатке 1, а четные 0.
Я не могу посоветовать сторонний курс, но ты не хочешь порешать мои задачки? У меня есть простые задачки на основы ООП, и более сложные где например надо сделать файлообменник на микрофреймворке Slim, разумеется с примененем ООП, используя паттерн DataMapper для работы с базой.
Вот ссылка на урок и простые задания по ООП: http://archive-ipq-co.narod.ru/l1/pasta.html
>>446308
Ты можешь скопировать библиотеки себе на сервер, зачем что-то грузить из интернета?
>>446201
> я не знаю, что такое FOREIGN KEY
Тогда тебе надо сначала изучать теорию, а не писать код: http://denis.in.ua/foreign-keys-in-mysql.htm
>>446174
Это потому что ты return не поставил.
>>446157
Так же как и из любой другой: return ....;
Может ты задачку на Фибоначчи решишь (и потом еще одну-две) для начала, чтобы лучше разобраться в рекурсии?
http://ideone.com/jmT6x2
Ну вот, я поставил же, причем я в функциях вроде бы разбираюсь, и понимаю как её делать, что бы возвращала.
Давай решу твои задачи на рекурсию.
тривиально- забрать данные авторизации из форм html и подтвердить запретить логин. Спасибо
>>446326
Это читал?
http://php.net/manual/ru/tutorial.php
https://php.net/manual/ru/tutorial.forms.php
http://php.net/manual/ru/language.variables.external.php
Также тебе нужно иметь знание HTML и HTML форм. Нужно немного знать HTTP и понимать что такое методы GET или POST.
> Ну вот, я поставил же
Ну так у тебя функция возвращает что-то только если мы дошли до конца с первого раза. А если нет то она переходит ниже и там нет никакого return и в этом случае она вернет null.
> makeStep($paths, $pathDone, $time, $point, $target);
Вот здесь ты рекурсивно вызываешь саму себя и никуда не сохраняешь результат например. Он теряется.
> Давай решу твои задачи на рекурсию.
1) Сделай функцию, которая находит N-е число Фибоначчи. Числа Фибоначчи определяются так:
- первое число равно 0
- второе равно 1
- третье и далее равно сумме 2 предыдущих чисел.
Вот ряд чисел Фибоначчи: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144....
2) Дана маска и имя файла. Напиши функцию, определяющую, соответствует ли имя файла маске? В маске можно использовать символы вопроса ? который соответствует ровно одному любому символу, и звездочки, которая соответствует 0 или больше любых символов. Пустая маска соответствует только пустому имени файла. Пpимеры:
match("f???.txt", "file.txt") -> true
match("f×", "file.txt") -> true
match("f????×txt", "file.txt") -> false
match("×", "") -> true
× здесь обозначает звездочку
3) Есть синие, красные и зеленые шары. Синий стоит 1 тугрик и весит 5 килограмм. Красный стоит 3 тугрика и весит 3 килограмма. Зеленый стоит 5 тугриков и весит 2 кг. Помоги гному определить, какие шары надо купить, чтобы получить максимальное их количество. Гном может унести не более 50 кг и у него с собой только 50 тугриков.
Реши задачу таким образом, чтобы число шаров легко можно было поменять, например добавить оранжевые и желтые шары.
Если что, это задача о ранце (к ней же относится и задача про банкомат с любыми банкнотами). Она имеет нерекурсивное, оптимальное решение, но оно сложное и наша цель изучить рекурсию, так что реши ее рекурсивно.
>>446326
Это читал?
http://php.net/manual/ru/tutorial.php
https://php.net/manual/ru/tutorial.forms.php
http://php.net/manual/ru/language.variables.external.php
Также тебе нужно иметь знание HTML и HTML форм. Нужно немного знать HTTP и понимать что такое методы GET или POST.
> Ну вот, я поставил же
Ну так у тебя функция возвращает что-то только если мы дошли до конца с первого раза. А если нет то она переходит ниже и там нет никакого return и в этом случае она вернет null.
> makeStep($paths, $pathDone, $time, $point, $target);
Вот здесь ты рекурсивно вызываешь саму себя и никуда не сохраняешь результат например. Он теряется.
> Давай решу твои задачи на рекурсию.
1) Сделай функцию, которая находит N-е число Фибоначчи. Числа Фибоначчи определяются так:
- первое число равно 0
- второе равно 1
- третье и далее равно сумме 2 предыдущих чисел.
Вот ряд чисел Фибоначчи: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144....
2) Дана маска и имя файла. Напиши функцию, определяющую, соответствует ли имя файла маске? В маске можно использовать символы вопроса ? который соответствует ровно одному любому символу, и звездочки, которая соответствует 0 или больше любых символов. Пустая маска соответствует только пустому имени файла. Пpимеры:
match("f???.txt", "file.txt") -> true
match("f×", "file.txt") -> true
match("f????×txt", "file.txt") -> false
match("×", "") -> true
× здесь обозначает звездочку
3) Есть синие, красные и зеленые шары. Синий стоит 1 тугрик и весит 5 килограмм. Красный стоит 3 тугрика и весит 3 килограмма. Зеленый стоит 5 тугриков и весит 2 кг. Помоги гному определить, какие шары надо купить, чтобы получить максимальное их количество. Гном может унести не более 50 кг и у него с собой только 50 тугриков.
Реши задачу таким образом, чтобы число шаров легко можно было поменять, например добавить оранжевые и желтые шары.
Если что, это задача о ранце (к ней же относится и задача про банкомат с любыми банкнотами). Она имеет нерекурсивное, оптимальное решение, но оно сложное и наша цель изучить рекурсию, так что реши ее рекурсивно.
Простые давно еще порешал, задача про файлообменник чем-то не нравится, не хочу лезть во фреймворки раньше чем задрочу ООП до автоматизма. Я хочу понять как именно большие проекты разбивать на классы и как им грамотно назначать свойства и методы. Например модуль логина/разлогина. Достаточно ли класса Пользователь, или надо дробить его дальше, скажем, до классов Пароль/Хэш. Не знаю как внятнее объяснить.
Итак, есть форма поиска по базе (сам писал, тот еще костыль). Есть страница, которая выводит все записи в таблице в удобном виде - с разбивкой на странички, с возможностью сортировки по столбцам и т.д. Как результат поиска засунуть в страничку с этим самым удобным выводом результатов? Ну, чтобы была и сортировка и разбивка на страницы, но только для тех записей, что нашлись по результатам поиска. На первый раз можно через require вызывать, передавая массив с найденными айди, но вот сортировка по столбцам у меня по гиперссылке, я же не могу в GET засунуть массив с айдишниками. Как быть?
Реши задачку про список абитуриентов, она без фреймворков.
Да и Slim это очень простой микрофреймворк, ничего сложного в нем нет.
Ну и что касается простых задач, ты показывал решения? Может ты там не все понял.
> Я хочу понять как именно большие проекты разбивать на классы
Это на практике проще понять. Есть такой подход как MVC, есть паттерны для работы с базой данных (тот же Data Mapper). Их бы ты изучил пока делал задания.
Вообще, разбивать надо по принципу. что каждый класс занимается своей задачей. В твоем случае можно сделать проще или сложнее в зависимости от того, что требуется.
Например, можно сделать классы User (представляет информацию о пользователе), UserMapper (сохраняет и ищет пользователей в БД) и AuthService (проверяет логин/пароль, проверяет залогиненность, выставляет куки, реализует функционал «запомнить меня»). А можно сделать сложнее, например в Symfony 2 система авторизации устроена намного сложнее:
http://habrahabr.ru/post/128159/
http://symfony.com/doc/current/book/security.html
> или надо дробить его дальше, скажем, до классов Пароль/Хэш.
Не надо, так как нет особого смысла.
Тоже так думал, но тогда получается, при любой сортировке столбца будет выполнятся запрос в базу, не слишком затратно?
База для того и предназначена, чтобы выполнять запросы. Если там индексы для сортировки поставить, то будет не так тяжело, да и на практике пользователь вряд ли дальше 4-5 страницы полезет.
На больших сайтах обычно делают поиск с помощью отдельного поискового движка вроде sphinx или elasticSearch, они умеют искать быстрее за счет хитрых индексов. У нас маленький проект, потому можно не заморачиваться.
Ну хорошо, только у меня ведь не поиск онли по строке, там еще и фильтры стоят (по дате, по автору и т.д.). Их-то уж точно не передашь в GET (например, массив из пяти чекбоксов в форме). Может, записывать найденные айдишники в специальную таблицу и брать их уже оттуда для запроса вывода всего в красивом виде?
Это бессмысленное увеличение нагрузки. создание и запись данных в таблицу создает куда большую нагрузку, чем поиск. Если у тебя сложный поиск. используй внешний поисковый движок, а не изобретай велосипеды.
Хотя, если подумать, то все можно мне в GET передать, только адресная строка будет ублюдочно выглядеть. Только вот хотелось бы, чтобы все галочки, текст в поле поиска и прочие параметры при обновлении странички оставались такими же, чтобы юзер не забывал, что искать. Если с текстом это легко сделать >>446083, то с чекбоксами/списками как быть*
Ну и создание таблицы увеличивает нагрузку, а не уменьшает. Допустим у нас миллион записей, и фильтры отбирают из них 100 000, и мы выводим 50 записей на страницу.
В случае с поиском при наличиии индекса для сортировки MySQL найдет 50 записей и остановится.
В твоем случае она просмотрит всю таблицу, выберет 100 000 записей, создаст новую таблицу на диске, отстортирует ее, выберет 50 записей. Это будет намного дольше.
Если ты хочешь заниматься оптимизацией, ты должен сначала изучить как работает MySQL, хотя бы документацию прочесть. А не придумывать бессмысленные велосипеды.
>не изобретай велосипеды.
Чего я тогда вообще тут забыл, лучше использовать внешнего погромиста, который мне все напишет, а не изобретать лисапед. ну ты понел.
>В твоем случае она просмотрит всю таблицу, выберет 100 000 записей, создаст новую таблицу на диске, отстортирует ее, выберет 50 записей. Это будет намного дольше.
Нет, он запишет туда одну запись - те айдишники (в виде строки, например), которые удовлетворяют условиям поиска.
http://lib.custis.ru/%D0%9A%D1%8D%D1%88%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%B2_%D0%B2%D0%B5%D0%B1-%D0%BF%D1%80%D0%B8%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F%D1%85_-_%D1%87%D1%82%D0%BE,_%D0%B3%D0%B4%D0%B5,_%D0%BA%D0%BE%D0%B3%D0%B4%D0%B0
Не знаю, где видео с этого доклада.
Но чтобы заниматься оптимизацией, надо понимать как работает БД, когда что выгоднее использовать, искать узкие места, и т.д. А ты ничего этого не знаешь и занимаешься самодеятельностью только потому что тебе кажется что это будет медленно работать. Так дела не делаются.
В твоем случае правильно будет:
1) проверить может быть скорость работы хорошая безо всяких оптимизаций
2) если нет то может в БД неправильно стоят индексы
3) если нет то надо использовать внешний поисковый движок
http://ideone.com/MLt487
Делай сайт со студентами.
спасибо.
Я так понимаю в этих классах должен быть метод getCurrentPositon() и у кота и у мыши. И если "Кот" оказывается в поле зрения "Мыши", то она применит метод runFromCat() (т.е. изменит поведение на обратное, эвристическая фунцкия будет это позволять) Каким образом классы Мышь и Кот должны делить этот функционал? Надо написать общий класс, допустим Pathfinder, в котором будет этот функционал, а классы "Мышь" и "Кот" будут его наследовать?
Алгоритм тут вряд ли подойдет. Он находит оптимальный путь из точки A в точку B за несколько шагов. Но у нас нет точки A и точки B. И мышки, и кошки каждый ход движутся.
Ну и учитывая что препятствий на поле нет, если и понадобится рассчитать путь, то тут никакие хитрые алгоритмы не нужны.
Тут нужен алгоритм, который исходя из текущей ситуации выбирает и делает 1 ход.
Один из вариантов решения — использовать алгоритм оценки позиций, аналогичный тому, который используется в играх вроде шашек или шахмат. Он выглядит примерно так:
— составить список всех возможных ходов, включая «стоять на месте»
— оценить выгоду от каждого хода в баллах
— выбрать наиболее выгодный
Причем у разных животных разные критерии оценки. Для кота выгоден тот ход, после которого он окажется как можно ближе к мышке. Для мышки выгоден тот ход, после которого рядом не будет котов.
Также, стоит оценивать число выходов с клетки: ход на угловую клетку, где мышку легко зажать в угол, должен оцениваться ниже чем ход на центральную.
> Каким образом классы Мышь и Кот должны делить этот функционал? Надо написать общий класс, допустим Pathfinder, в котором будет этот функционал, а классы "Мышь" и "Кот" будут его наследовать?
Неправильно наследовать. Разве Кот это улучшенная версия Проводника? Конечно нет. Значит и наследоваться он от него не может.
Наследование используется для создания улучшенной или модифицированной версии класса.
Кот и Мышь могут наследоваться от базового класса Животное.
Если ты хочешь вынести поиск пути в отдельный класс (я сомневаюсь, что это нужно), то нужно просто сделать отдельный класс и ничего от него не наследовать.
Ну и я бы советовал с Вектором разобраться. Если задачи на полпути бросать, ничему не научишься.
Алгоритм тут вряд ли подойдет. Он находит оптимальный путь из точки A в точку B за несколько шагов. Но у нас нет точки A и точки B. И мышки, и кошки каждый ход движутся.
Ну и учитывая что препятствий на поле нет, если и понадобится рассчитать путь, то тут никакие хитрые алгоритмы не нужны.
Тут нужен алгоритм, который исходя из текущей ситуации выбирает и делает 1 ход.
Один из вариантов решения — использовать алгоритм оценки позиций, аналогичный тому, который используется в играх вроде шашек или шахмат. Он выглядит примерно так:
— составить список всех возможных ходов, включая «стоять на месте»
— оценить выгоду от каждого хода в баллах
— выбрать наиболее выгодный
Причем у разных животных разные критерии оценки. Для кота выгоден тот ход, после которого он окажется как можно ближе к мышке. Для мышки выгоден тот ход, после которого рядом не будет котов.
Также, стоит оценивать число выходов с клетки: ход на угловую клетку, где мышку легко зажать в угол, должен оцениваться ниже чем ход на центральную.
> Каким образом классы Мышь и Кот должны делить этот функционал? Надо написать общий класс, допустим Pathfinder, в котором будет этот функционал, а классы "Мышь" и "Кот" будут его наследовать?
Неправильно наследовать. Разве Кот это улучшенная версия Проводника? Конечно нет. Значит и наследоваться он от него не может.
Наследование используется для создания улучшенной или модифицированной версии класса.
Кот и Мышь могут наследоваться от базового класса Животное.
Если ты хочешь вынести поиск пути в отдельный класс (я сомневаюсь, что это нужно), то нужно просто сделать отдельный класс и ничего от него не наследовать.
Ну и я бы советовал с Вектором разобраться. Если задачи на полпути бросать, ничему не научишься.
Ну и мне кажется неправильно хранить массив мышей внутри кота. Что, Кот это хранилище для мышей? Только если для съеденных.
Животных логично хранить на Карте, по которой они ходят.
MVC + стандартные паттерны вроде Data Mapper для работы с БД.
Ну то есть там будет Роутер, Контроллеры, сущности, мапперы, может быть классы-сервисы. Это все уже давно придумано до нас.
Советую порешать задачки из ОП-поста про регистрацию студентов, файлообменник. В ходе их решения тебе как раз с этим придется разобраться.
>>446413
> Где-то пошло не так, и текст получился выведенный одним столбом
Потому что ты разбиваешь строку на буквы и вставляешь между ними \n. разумеется, это делает перевод строки, и сделав его уже верх вернуться нельзя.
Алогритм надо поменять на такой:
вывести первые буквы всех строк по очереди
вывести вторые буквы всех строк
....
вывести последние буквы всех строк
>>446390
Не вижу проблем. Ты про атрибут checked слышал? Если нет то тебе надо начать с изучения HTML: http://htmlbook.ru/html/input
Ну и хорошо, кстати, что ты рисуешь диаграммы классов. Очень наглядно получается и сразу видно что неправильно.
>Не вижу проблем. Ты про атрибут checked слышал? Если нет то тебе надо начать с изучения HTML: http://htmlbook.ru/html/input
>>446530
Да это понятно, но получается очень громоздко. Ладно, что-нибудь придумаю, ты мне лучше ответь, сохранять текст запроса в строку, хранить ее где-нибудь и вытаскивать для составления запроса - это норм или не очень? Пока не получается у меня корректно составить урл с гет-параметрами для той странички, которая обеспечивает постраничный вывод с сортировкой результатов по разным столбцам.
ОП, у меня ничего не получается.
С array_search не могу понять как искать в многомерном массиве: http://ideone.com/0xJ4WE
С SplObjectStorage тоже не могу разобраться как пользоваться: http://ideone.com/kqI49b
Он выводит массивы о которых я ничего не знаю. Можно от них как-нибудь избавиться для удобства? Так бы не пришлось делать много foreach.
>[storage:SplObjectStorage:private] => Array
>[0000000029a68279000000006f869372] => Array
И еще, я решил объединить все что связанно с увольнением инженеров в одну функцию (http://ideone.com/O1OFxC) потом, если потребуются разделю. Так просто удобней., но ничего не получилось. Если вызывать эту функцию с передачей $type = 'engineer', то он выдает ошибку о том что в 9 строке неизвестная переменная $type. А если заменить её на просто 'engineer', то просто ничего не происходит.
Но все же, я считаю, что это удобно - хранить в классе "Департамент" инфу о сотрудниках и их з/п, кофе, страницах, но для каждого параметра выделять отдельный массив. Я вроде переделал эту часть. Убрал полностью парсер, свои исключения, WorkersCreator. Теперь все выглядит так:
http://ideone.com/iVkQB7
Поле типа TEXT нельзя индексировать. Ну сам представь, какого размера будет индекс, больше чем сама таблица.
Если у тебя там хранятся небольшие строки, замени его на VARCHAR. Если большие то откажись от индекса. Это все равно довольно бессмысленная идея.
>>446555
> сохранять текст запроса в строку, хранить ее где-нибудь и вытаскивать для составления запроса - это норм или не очень?
Зачем ее где-то хранить? Храни ее в URL: search.php?q=big+cats — он для этого и предназначен.
> Пока не получается у меня корректно составить урл с гет-параметрами для той странички, которая обеспечивает постраничный вывод с сортировкой результатов по разным столбцам.
list.php?q=big+cats&page=2&sort=name
Не вижу никаких сложностей. Все данные присутствуют в URL.
Ну и надеюсь ты знаешь про urlencode и http_build_query.
>>446685
Есть CMS вроде Wordpress, есть фреймворки (Slim, Yii, Symfony 2). Если ты хочешь сразу делать сайт, то делай на том который больше нравится.
Если хочешь изучать все это, у меня в ОП-посте есть задания, например на список абитуриентов и на файлообменник, но там придется много чего изучить, включая ООП.
>Поле типа TEXT нельзя индексировать
Ну как нельзя, вот у меня даже пруф на такую базу в sqlite. А вообще я погуглил и вижу, что там тоже говорят о невозможности. Хз, конкретно эту табличку я импортнул из другого места, я не эти индексы лично создавал. Но факт остается фактом.
> С array_search не могу понять как искать в многомерном массиве:
У тебя одномерный массив. Одномерный массив объектов. И искать в нем можно только объекты:
$key = array_search($second, $array, true);
http://ideone.com/f3skd4
Объект это не массив. Ты не должен относиться к нему как к массиву, и искать что-то в нем через array-search
Array_search возвращает первый ключ под которым в массиве хранится указанное значение. Он не подойдет для задачи «отобрать всех сотрудников определенного типа».
Решал ли ты мои задачи на массивы из учебника? Что-то у тебя пробелы в знаниях функций работы с массивами.
Почитай мануал по этим функциям и почитай хотя бы примерно что они делают: array_chunk, array_column, array_combine, array_count_values , array_diff, array_fill_keys , array_fill, array_filter, array_flip, array_intersect, array_keys , array_map, array_merge, array_pop, array_push, array_rand, array_reverse, array_search , array_shift, array_slice, array_splice, array_sum, array_unique, array_unshift, array_values, range, usort
Все они описаны тут http://php.net/manual/ru/ref.array.php
Рано или поздно они тебе пригодятся.
Чтобы отобрать элементы массива по критерию, есть функция array_filter. Ей можно например отобрать работников определенной профессии.
> С SplObjectStorage тоже не могу разобраться как пользоваться
Добавляешь объекты через attach, удаляешь через detach, проверяешь наличие через contains, считаешь объем через count, перебираешь через foreach.
> Он выводит массивы о которых я ничего не знаю.
Он выводит внутреннюю структуру хранилища. Тебя это волновать не должно, что там внутри, ты работаешь с хранилищем через методы.
> Так бы не пришлось делать много foreach.
Тебе и так не придется. Пишешь
foreach ($storage as $key => $worker)
и все работает, так как объект SplObjectStorage поддерживает Traversable (мануал http://php.net/manual/ru/class.traversable.php ) и при попытке пройтись по нему через foreach возвращает тебе положенные в него объекты по одному.
Кстати, SplObjectStorage еще поддерживает интерфейс Countable ( http://php.net/manual/ru/class.countable.php ) и число элементов в нем можно считать через count($storage)
> С array_search не могу понять как искать в многомерном массиве:
У тебя одномерный массив. Одномерный массив объектов. И искать в нем можно только объекты:
$key = array_search($second, $array, true);
http://ideone.com/f3skd4
Объект это не массив. Ты не должен относиться к нему как к массиву, и искать что-то в нем через array-search
Array_search возвращает первый ключ под которым в массиве хранится указанное значение. Он не подойдет для задачи «отобрать всех сотрудников определенного типа».
Решал ли ты мои задачи на массивы из учебника? Что-то у тебя пробелы в знаниях функций работы с массивами.
Почитай мануал по этим функциям и почитай хотя бы примерно что они делают: array_chunk, array_column, array_combine, array_count_values , array_diff, array_fill_keys , array_fill, array_filter, array_flip, array_intersect, array_keys , array_map, array_merge, array_pop, array_push, array_rand, array_reverse, array_search , array_shift, array_slice, array_splice, array_sum, array_unique, array_unshift, array_values, range, usort
Все они описаны тут http://php.net/manual/ru/ref.array.php
Рано или поздно они тебе пригодятся.
Чтобы отобрать элементы массива по критерию, есть функция array_filter. Ей можно например отобрать работников определенной профессии.
> С SplObjectStorage тоже не могу разобраться как пользоваться
Добавляешь объекты через attach, удаляешь через detach, проверяешь наличие через contains, считаешь объем через count, перебираешь через foreach.
> Он выводит массивы о которых я ничего не знаю.
Он выводит внутреннюю структуру хранилища. Тебя это волновать не должно, что там внутри, ты работаешь с хранилищем через методы.
> Так бы не пришлось делать много foreach.
Тебе и так не придется. Пишешь
foreach ($storage as $key => $worker)
и все работает, так как объект SplObjectStorage поддерживает Traversable (мануал http://php.net/manual/ru/class.traversable.php ) и при попытке пройтись по нему через foreach возвращает тебе положенные в него объекты по одному.
Кстати, SplObjectStorage еще поддерживает интерфейс Countable ( http://php.net/manual/ru/class.countable.php ) и число элементов в нем можно считать через count($storage)
> Если вызывать эту функцию с передачей $type = 'engineer', то он выдает ошибку о том что в 9 строке неизвестная переменная $type.
Функция не видит внешние переменные, а снаружи не видны созданные в функции (локальные) переменные. Но в случае с анонимными функциями ты можешь пробросить переменную снаружи с помощью use, смотри пример 3 тут: https://php.net/manual/ru/functions.anonymous.php
Заметь что пробросить можно 2 способами:
use ($a) — передает копию переменной. Меняя копию, ты не влияешь на исходную переменную
use (&$a) — передает саму переменную по ссылке. Меняя ее, ты меняешь переменную $a снаружи
> for ($i = 0; $i < $percent; $i++) {
Используй array_slice
Так, код в общем выглядит верно.
Ну и сделать надо будет немного по-другому. Давай-ка, чтобы ты лучше научился понимать суть ООП и инкапсуляции, ты закроешь все свойства объектов. То есть поменяешь public на private или protected. И будешь работать с ними только через методы.
Это конечно чуть больше писанины, но такой код получается надежнее. Ведь когда у тебя есть public свойство, в него можно записать что угодно. Ты никак не можешь это запретить. А когда запись делается через метод, ты можешь в нем сделать какие-то проверки, например, проверить что salary является числом от 1 до 10:
function setSalary($salary) {
if (!is_numeric($salary) || $salary < 0 || $salary > 100) {
throw new Exception("Invalid salary: $salary");
}
$this->salary = $salary;
}
Тебе проверки делать не обязательно, но свойства закрой.
> Если вызывать эту функцию с передачей $type = 'engineer', то он выдает ошибку о том что в 9 строке неизвестная переменная $type.
Функция не видит внешние переменные, а снаружи не видны созданные в функции (локальные) переменные. Но в случае с анонимными функциями ты можешь пробросить переменную снаружи с помощью use, смотри пример 3 тут: https://php.net/manual/ru/functions.anonymous.php
Заметь что пробросить можно 2 способами:
use ($a) — передает копию переменной. Меняя копию, ты не влияешь на исходную переменную
use (&$a) — передает саму переменную по ссылке. Меняя ее, ты меняешь переменную $a снаружи
> for ($i = 0; $i < $percent; $i++) {
Используй array_slice
Так, код в общем выглядит верно.
Ну и сделать надо будет немного по-другому. Давай-ка, чтобы ты лучше научился понимать суть ООП и инкапсуляции, ты закроешь все свойства объектов. То есть поменяешь public на private или protected. И будешь работать с ними только через методы.
Это конечно чуть больше писанины, но такой код получается надежнее. Ведь когда у тебя есть public свойство, в него можно записать что угодно. Ты никак не можешь это запретить. А когда запись делается через метод, ты можешь в нем сделать какие-то проверки, например, проверить что salary является числом от 1 до 10:
function setSalary($salary) {
if (!is_numeric($salary) || $salary < 0 || $salary > 100) {
throw new Exception("Invalid salary: $salary");
}
$this->salary = $salary;
}
Тебе проверки делать не обязательно, но свойства закрой.
> Изнчально, я хотел упростить процесс создания объекта конкретного рабочего, то есть не писать 50 раз new Employee, но все слишком усложнил, и я это понял.
Так проблемы нет, ты можешь сделать функцию которая по строке вида '3ме2' создает массив работников. Но эта функция не должна быть в Департаменте, а отдельно. Пусть кто хочет создает работников через эту функцию, кто не хочет, через new. А ты не даешь никакого выбора.
Департамент должен позволять добавлять в себя объект-работника, неважно каким методом он создан. Это самое универсальное решение.
А ты сделал в прошлый раз неуниверсально: у тебя работников можно передавать только в виде какого-то непонятного массива строк и только через конструктор. То есть максимально неудобно. Если я создал работника через new Manager то я никак не могу добавить его в департамент. Разве это правильно?
> Но все же, я считаю, что это удобно - хранить в классе "Департамент" инфу о сотрудниках и их з/п, кофе, страницах, но для каждого параметра выделять отдельный массив
Зачем? У тебя есть массив сотрудников. В них и так хранится сколько они кофе пьют и сколько денег проедают. Зачем дублировать эту информацию второй раз в каком-то массиве и мучаться с поддержкой ее актуальности? Мы пишем ООП-код, а ты опять хочешь массиво-ориентированным программированием заняться.
По новому коду:
> public function IncreaseRank($emp)
А почему ты эту функцию в департаменте сделал? По моему логичнее ее сделать в самом же сотруднике:
$employee->increaseRank( );
заодно сделать проверку чтобы выше 3-го ранга нельзя было поставить.
Ну и эти функции получились неуниверсальные:
> public function addEmployee($cls, $rank, $amt, $boss=false)
Лучше addEmployee(Employee $employee). Создание работников не задача Департамента, сделай это в другом месте.
> (($key = array_search($emp, $this->employees))
Надо добавить 3-й параметр к array_search иначе он найдет другого работника. Прочитай про строгое и нестрогое сравнение: http://php.net/manual/ru/language.oop5.object-comparison.php
> public function changeBoss($cls, $rank)
Опять же логичнее передавать объекта-босса. Дополнительно можно сделать проверку что босс местный, а не кто-то посторонний. также надо предусмотреть ситуацию когда босса пытаются поменять на самого себя.
> public function changeBaseSalary($cls, $salary)
Это метод работника, а не Департамента
> array_push($this->totalSalary, $employee->getSalary());
Можно сразу складывать в переменную: $total += ....
> return number_format(array_sum($this->totalSalary) /
>\t\t array_sum($this->totalWorkDone), 3);
Форматирование должно делаться при выводе, а возвращать надо точные данные.
> private $totalCoffeeAmount = [];
Где это свойство используется? Если не используется, зачем оно?
> Изнчально, я хотел упростить процесс создания объекта конкретного рабочего, то есть не писать 50 раз new Employee, но все слишком усложнил, и я это понял.
Так проблемы нет, ты можешь сделать функцию которая по строке вида '3ме2' создает массив работников. Но эта функция не должна быть в Департаменте, а отдельно. Пусть кто хочет создает работников через эту функцию, кто не хочет, через new. А ты не даешь никакого выбора.
Департамент должен позволять добавлять в себя объект-работника, неважно каким методом он создан. Это самое универсальное решение.
А ты сделал в прошлый раз неуниверсально: у тебя работников можно передавать только в виде какого-то непонятного массива строк и только через конструктор. То есть максимально неудобно. Если я создал работника через new Manager то я никак не могу добавить его в департамент. Разве это правильно?
> Но все же, я считаю, что это удобно - хранить в классе "Департамент" инфу о сотрудниках и их з/п, кофе, страницах, но для каждого параметра выделять отдельный массив
Зачем? У тебя есть массив сотрудников. В них и так хранится сколько они кофе пьют и сколько денег проедают. Зачем дублировать эту информацию второй раз в каком-то массиве и мучаться с поддержкой ее актуальности? Мы пишем ООП-код, а ты опять хочешь массиво-ориентированным программированием заняться.
По новому коду:
> public function IncreaseRank($emp)
А почему ты эту функцию в департаменте сделал? По моему логичнее ее сделать в самом же сотруднике:
$employee->increaseRank( );
заодно сделать проверку чтобы выше 3-го ранга нельзя было поставить.
Ну и эти функции получились неуниверсальные:
> public function addEmployee($cls, $rank, $amt, $boss=false)
Лучше addEmployee(Employee $employee). Создание работников не задача Департамента, сделай это в другом месте.
> (($key = array_search($emp, $this->employees))
Надо добавить 3-й параметр к array_search иначе он найдет другого работника. Прочитай про строгое и нестрогое сравнение: http://php.net/manual/ru/language.oop5.object-comparison.php
> public function changeBoss($cls, $rank)
Опять же логичнее передавать объекта-босса. Дополнительно можно сделать проверку что босс местный, а не кто-то посторонний. также надо предусмотреть ситуацию когда босса пытаются поменять на самого себя.
> public function changeBaseSalary($cls, $salary)
Это метод работника, а не Департамента
> array_push($this->totalSalary, $employee->getSalary());
Можно сразу складывать в переменную: $total += ....
> return number_format(array_sum($this->totalSalary) /
>\t\t array_sum($this->totalWorkDone), 3);
Форматирование должно делаться при выводе, а возвращать надо точные данные.
> private $totalCoffeeAmount = [];
Где это свойство используется? Если не используется, зачем оно?
Это же бред. Поле TEXT может содержать до 65535 символов, а в индексе все записи равны наибольшему возможному значению.Индекс в котором записи размером 65535 неэффективен. Потому он и запрещен в MySQL.
Ну я при импорте просто забил на эти два индекса хуй, и все пошло нормально. Правда открывать в веб 200мб базу долго и нудно... Я уже заебался
Ну и по моему просматривать информацию о таблице гораздо удобнее через SHOW CREATE TABLE x; (не знаю есть ли это в SQlite) чем через все эти окошки с кучей бессмысленных вкладок. Или может это я просто такой ориентированный на командную строку.
Что значит «открывать в веб»? sqlite вообще для веб плохо подходит. Mysql хорошо. Если у тебя что-то медленно работает и ты хочешь ускорить, изучи индексы и EXPLAIN для начала, тут ссылки:
https://gist.github.com/codedokode/10539213#%D0%98%D0%BD%D0%B4%D0%B5%D0%BA%D1%81%D1%8B
Хотя дело конечно может быть не только в индексах.
Если это таблица для хранения переводов строк, то это конечно очень странное решение.
>Что значит «открывать в веб»
Моя база sqlite находилась в одном файле, мне же нужно было вытянуть всю информацию с этой базы сначала на локальный сервер (да, там mysql), а потом уже, когда закончу с программированием, в онлайн. Поэтому я переводил всю таблицу в наборы запросов, которые теперь исполняю.
Благодарю, покурю в ближайшее время его.
>Ну так у тебя функция возвращает что-то только если мы дошли до конца с первого раза. А если нет то она переходит ниже и там нет никакого return и в этом случае она вернет null.
Если функция вызывает сама себя, то в вызванной функции есть ретерн же.
>Вот здесь ты рекурсивно вызываешь саму себя и никуда не сохраняешь результат например. Он теряется.
Я ведь вызываю функцию еще раз, передавая ей в том числе и $pathDone, но уже обновленный. По моей логике всё должно быть ок, видимо я что-то не понимаю пока о рекурсии или особенностях языка. Ведь когда у меня функция выполняется первый раз, она условно говоря делает шаг, и $pathDone содержит уже две точки, далее функция вызывается сама в себе, и в новый вызов передается этот же самый $pathDone, но уже с двумя точками в себе. и так далее. Когда доходим до нужной точки, в десятой - пятнадцатой по глубине вызово функции лежит большой $pathDone из 10-15 элементов, и при выполнении условия пытаюсь его ретернить. Что тут не так? Как я должен его сохранить куда-то? Или я кажется начинаю понимать. Я должен внутри первой функции завести переменную, и что бы вторая фунция ретернила в эту переменную что-то, и так далее по списку? Окей, я понял похоже кое что.
Вот первая задача на Фибоначчи http://ideone.com/0ZToC5
Но похоже что она решена не так как нужно? Надо хитрым способом её решать?
>По моей логике всё должно быть ок, видимо я что-то не понимаю пока о рекурсии
Вообще-то рекурсия нужна для очень небольшого круга задач вроде обхода дерева (в том числе и дерева каталогов) или быстрой сортировки... А вот здесь:
>Я ведь вызываю функцию еще раз, передавая ей в том числе и $pathDone, но уже обновленный
Наверняка можно было бы нопейсать и по-другому!
http://ideone.com/3uKlRy
Делаю задачку по регуляркам (граммар наци).
После выполнения цикла заглавными становятся все буквы в предложении, хотя глаза мои ошибки не видят.
Что не так?
Ссылка: http://ideone.com/tMxAXk
$temp[0] = mb_strtoupper($temp[0]);
Ну типа ты все буквы в предложении и делаешь заглавными. Если хочешь сделать тольо первую букву заглавной, то тебе надо разбить предложение например на две строки: в первой - первая буква, во второй - все остальное предложение. Далее через mb_strtoupper() прогоняешь первую строку, и далее склеиваешь их.
http://ideone.com/JFtjFn
Потому что теперь у тебя в $temp[0] лежит одна буква, а не целая строка? Как я вообще должен отвечать на вопрос: "почему все работает?" ???
Пикрилейтед:
сначала ты делаешь:
\tvar_dump($a);
и это дает результат:
array(1) {
[0]=>
string(138) "ну что. не смотрел еще black mesa. я собирался скачать, но все как-то некогда было."
}
это значит что $a - это массив из 1 элемента, который в свобю очередь является строкой, бла бла бла.
дале ты делаешь:
\t$a[0] = mb_strtoupper($a[0]);
что в свою очередь переводит все буквы той строчки в верхний регистр.
дампишь опять:
array(1) {
[0]=>
string(138) "НУ ЧТО. НЕ СМОТРЕЛ ЕЩЕ BLACK MESA. Я СОБИРАЛСЯ СКАЧАТЬ, НО ВСЕ КАК-ТО НЕКОГДА БЫЛО."
}
Получаешь то что и должно быть, вроде бы всё логично. Не знаю как еще объяснить.
Пикрилейтед:
сначала ты делаешь:
\tvar_dump($a);
и это дает результат:
array(1) {
[0]=>
string(138) "ну что. не смотрел еще black mesa. я собирался скачать, но все как-то некогда было."
}
это значит что $a - это массив из 1 элемента, который в свобю очередь является строкой, бла бла бла.
дале ты делаешь:
\t$a[0] = mb_strtoupper($a[0]);
что в свою очередь переводит все буквы той строчки в верхний регистр.
дампишь опять:
array(1) {
[0]=>
string(138) "НУ ЧТО. НЕ СМОТРЕЛ ЕЩЕ BLACK MESA. Я СОБИРАЛСЯ СКАЧАТЬ, НО ВСЕ КАК-ТО НЕКОГДА БЫЛО."
}
Получаешь то что и должно быть, вроде бы всё логично. Не знаю как еще объяснить.
$sql = "SELECT блаблабла";
$result = mysql_query($sql);
$row = mysql_fetch_assoc($result);
echo $row['table.col'];
> Вот первая задача на Фибоначчи
Хорошо, добавим ограничение: циклы и массивы использовать нельзя. Используй рекурсию. Ведь если N-е число равно сумме 2 предыдущих, мы можем прямо так в коде и написать.
Вообще, конечно, на практике надо помнить что рекурсия работает довольно неэфективно и глубже 100-200 вызовов рекурсию делать не стоит. Но так как наша цель ее изучить, то не будем об этом задумываться.
> Когда доходим до нужной точки, в десятой - пятнадцатой по глубине вызово функции лежит большой $pathDone из 10-15 элементов, и при выполнении условия пытаюсь его ретернить. Что тут не так?
Допустим у нас 15-й шаг — последний. На 15-м шаге ты находишь ответ и возвращаешь его через return.
Но на 14-м шаге у тебя стоит такой вызов:
function makePath(...) {
if (..) {// сработает на 15-м шаге
return ..;
}
// сработает на 1-14 шагах
....
makePath(....);
....
}
Ты никуда не сохраняешь то, что вернул 15-й шаг, и 14-й вызов возвращает null. А за ним и 13-й, и 12-й ... и так до самого первого.
> Я должен внутри первой функции завести переменную, и что бы вторая фунция ретернила в эту переменную что-то
да
>Ведь если N-е число равно сумме 2 предыдущих, мы можем прямо так в коде и написать.
Ты предстовляеш себе скоко памети ЭТО сожрёт?..
> но у меня такое обращение не возвращает ничего:
Потому что mysql называет это поле в ответе просто col.Сделай var_dump($row); и увидишь.
> как пхп реагирует на одинаковые название столбцов после select'а
php никак не реагирует, а вообще для такой ситуации есть алиасы.
Ну и ты учишься по какому-то старью. Расширение mysql устарело давно, переходи на pdo: http://habrahabr.ru/post/137664/
Вообще ты прав в том, что рекурсия работает довольно неэффективно. Но если у нас немного данных (например мы считаем числа Фибоначчи не дальше 100-го) то это приемлемо. А если много, то рекурсию надо заменять на работу с массивом или стеком.
Я в preg_split указал значение limit -1. После этого всё заработало.
Почему не работало до этого? Разве preg_split не должен по дефолту делить строку на максимальное количество частей? В таком случае, тогда какое значение у limit стоит по умолчанию?
В PHP кстати дерево можно обходить рекурсивным итератором. Ну например если тебе надо обойти все файлы в каталоге и его подкаталогах, это довольно удобно можно сделать 1 циклом.
>>446782
Если непонятно, как работает программа, попробуй ставить команды вроде var_dump($x); чтобы увидеть что хранится в той или иной переменной.
>>446778
Посмотри внизу страницы на ideone ошибки:
> PHP Notice: Undefined variable: totalEmp in /home/eUKC16/prog.php on line 171
> PHP Notice: Undefined variable: totalInc in /home/eUKC16/prog.php on line 172
Их надо все исправить.
> public function addEmployees($quantity, $employee)
Это неудачное решение. Департамент не должен клонировать работников (но ты можешь сделать это отдельной функцией). Департамент
может принимать готовых работников либо по одному, либо массивом.
> public function addLeader($employee){
тут нужно добавить тайп-хинт.
Тайп хинты позволяют указать, что аргумент функции должен быть определенного типа (например быть объектом определенного класса или его наследника). Тайп хинт делает код понятнее (так как видно какого типа переменная) и надежнее (так как PHP не позволит передать что-то неразрешенное и ты сразу увидишь ошибку). Используй их везде.
Мануал: http://php.net/manual/ru/language.oop5.typehinting.php
> public function getTotalEmployees()
Используй функцию count
> return floor($total);
Не стоит округлять здесь. Пусть функция возвращает точные данные, а округление лучше делать при выводе.
> public function setRank()
Название функции надо поменять так как оно не говорит что делает функция. «задать ранг»? Так он вообще-то в конструкторе задается. Функция занимается рассчетом зарплаты.
Сама функция неудачно сделана. Что будет, если ее вызвать несколько раз подряд? Если не вызвать ни разу? Тогда объект начнет возвращать недостоверные данные. Если каждый класс в программе будет так работать, то ошибки в ней будут сыпаться как из рога изобилия.
Также, у тебя одно свойство (income) хранит 2 разных величины: базовую ставку и зарплату с учетом надбавок. Это тоже усложняет программу, как работать с классом если непонятно что в данный момент хранится в этом свойстве?
Такого быть не должно.
Я советую хранить в income только базовую ставку, а итоговую зарплату нигде не хранить, а сделать метод для ее вычисления.
> public function makeLeader(){
> $this->papers = 0;
А что ты будешь делать при разжаловании из начальника в обычные сотрудники? Как восстановишь значение papers? Я советую не менять никакие свойства.
В PHP кстати дерево можно обходить рекурсивным итератором. Ну например если тебе надо обойти все файлы в каталоге и его подкаталогах, это довольно удобно можно сделать 1 циклом.
>>446782
Если непонятно, как работает программа, попробуй ставить команды вроде var_dump($x); чтобы увидеть что хранится в той или иной переменной.
>>446778
Посмотри внизу страницы на ideone ошибки:
> PHP Notice: Undefined variable: totalEmp in /home/eUKC16/prog.php on line 171
> PHP Notice: Undefined variable: totalInc in /home/eUKC16/prog.php on line 172
Их надо все исправить.
> public function addEmployees($quantity, $employee)
Это неудачное решение. Департамент не должен клонировать работников (но ты можешь сделать это отдельной функцией). Департамент
может принимать готовых работников либо по одному, либо массивом.
> public function addLeader($employee){
тут нужно добавить тайп-хинт.
Тайп хинты позволяют указать, что аргумент функции должен быть определенного типа (например быть объектом определенного класса или его наследника). Тайп хинт делает код понятнее (так как видно какого типа переменная) и надежнее (так как PHP не позволит передать что-то неразрешенное и ты сразу увидишь ошибку). Используй их везде.
Мануал: http://php.net/manual/ru/language.oop5.typehinting.php
> public function getTotalEmployees()
Используй функцию count
> return floor($total);
Не стоит округлять здесь. Пусть функция возвращает точные данные, а округление лучше делать при выводе.
> public function setRank()
Название функции надо поменять так как оно не говорит что делает функция. «задать ранг»? Так он вообще-то в конструкторе задается. Функция занимается рассчетом зарплаты.
Сама функция неудачно сделана. Что будет, если ее вызвать несколько раз подряд? Если не вызвать ни разу? Тогда объект начнет возвращать недостоверные данные. Если каждый класс в программе будет так работать, то ошибки в ней будут сыпаться как из рога изобилия.
Также, у тебя одно свойство (income) хранит 2 разных величины: базовую ставку и зарплату с учетом надбавок. Это тоже усложняет программу, как работать с классом если непонятно что в данный момент хранится в этом свойстве?
Такого быть не должно.
Я советую хранить в income только базовую ставку, а итоговую зарплату нигде не хранить, а сделать метод для ее вычисления.
> public function makeLeader(){
> $this->papers = 0;
А что ты будешь делать при разжаловании из начальника в обычные сотрудники? Как восстановишь значение papers? Я советую не менять никакие свойства.
>По умолчанию там null что значит «нет ограничений».
Поставил null -- всё ок. Убрал null -- пихает всё в один элемент массива.
Шутник однако.
Лару юзай.
Вот простейший пример. Допустим, у меня есть в базе таблицы со статьями (article) и категориями (category).
Как вывести только статьи разобрался (CListView). Нужно теперь:
а) вывести в виде меню список категорий из другой таблицы;
б) в описании статьи использовать не category_id (int), а ее название, которое берется из таблицы.
В общем, не понимаю саму архитектуру приложения. Для одной таблицы создается только одна модель? А для одной модели один котроллер?
Как тогда через один экшн (article/index) вывести содержимое двух табличек?
з.ы. Я щас стену головой пробью.
Ну так ты константу PREG_SPLIT_NOT_EMPTY передал вместо $limit. А эта константа содержит какое-то число которое и вопринимается как $limit. Нельзя пропускать аргументы функции.
>>446837
Есть у меня, частично выложен тут:
http://www.mediafire.com/download/gza5360wdzqd743/threads-archive-pr-1..17.zip (первые треды из pr)
http://www.mediafire.com/?3zxb19z9j2q5gf2 (древние 11-19 треды, 74 Мб)
и на дропбоксе: https://www.dropbox.com/sh/4sb69jrx9qwrpcw/-nY5ia__VC (периодически дежит)
Если нужен какой-то конкретный тред, я могу найти.
Но вообще, в архиве тредов ничего особо ценного нет, больше флуда всякого.
Если ты сгенерировал код автоматически, то значит надо его править. Разумеется для этого надо понимать сам фреймворк.
> Как тогда через один экшн (article/index) вывести содержимое двух табличек?
Из контроллера можно обращаться к любым моделям.
> вывести в виде меню список категорий из другой таблицы;
Получаешь их и выводишь. Может, средствами Юи это как-то автоматически можно сделать, не знаю.
> в описании статьи использовать не category_id (int), а ее название, которое берется из таблицы.
Правь нужные контроллеры и шаблоны.
> Для одной таблицы создается только одна модель?
да
> А для одной модели один котроллер?
Нет. Контроллер соответствует разделу сайта, а не моделям.
>Ну так ты константу PREG_SPLIT_NOT_EMPTY передал вместо $limit. А эта константа содержит какое-то число которое и вопринимается как $limit. Нельзя пропускать аргументы функции.
Благодарю.
Ну теперь-то надеюсь мне не придется каждому это все каждый раз объяснять!
Я знаю пхп на средненьком уровне, сейчас насилую yii. Туговато идет.
В общем, кто хочет, сюда: ashwwwww@mail.ru , потом вк, если надо.
Будем подсказывать друг другу, делиться новыми знаниями.
Лучше помоги ОПу написать гайд по плавному перекату в ООП, чтобы даже аутист понял.
http://www.yiiframework.com/doc/guide/1.1/ru/database.arr
>>446908
Основы ООП неплохо излагаются у "Специалиста" (уровень 3, первые 2 модуля) http://rutracker.org/forum/viewtopic.php?t=4620353
а также у "Школы программирования" http://rutracker.org/forum/viewtopic.php?t=4917138
>в описании статьи использовать не category_id (int), а ее название, которое берется из таблицы.
Гугли связывание в юи
Вот то что тебе надо, пришлось сократить двач не пропускает оригинальную ссылку по причине наличия слов из спам-листа:
http://su0.ru/WY3b
>Ну и ты учишься по какому-то старью. Расширение mysql устарело давно, переходи на pdo: http://habrahabr.ru/post/137664/
Я копирую просто напрямую с этой статьи, подставляя свои значения столбцов, и в результате получаю ошибку в строке запроса:
"Catchable fatal error: Object of class PDOStatement could not be converted to string in D:\OpenServer\domains\localhost\test.php on line 47"
Охуительный способ решения задач с БД, который не работает.
Забыл дописать, что тут очевидная проблема, что PDO не может вытянуть информацию как обычный текст, ей видимо объекты подавай.
> Это неудачное решение. Департамент не должен клонировать работников (но ты можешь сделать это отдельной функцией). Департамент
> может принимать готовых работников либо по одному, либо массивом.
Добавить функцию вне класса?
>
Сама функция неудачно сделана. Что будет, если ее вызвать несколько раз подряд? Если не вызвать ни разу? Тогда объект начнет возвращать недостоверные данные. Если каждый класс в программе будет так работать, то ошибки в ней будут сыпаться как из рога изобилия.
Вот это не понял.
>Я советую хранить в income только базовую ставку, а итоговую зарплату нигде не хранить, а сделать метод для ее вычисления.
А как тогда сотрудников добавлять? Один объект - один сотрудник.
>Я советую не менять никакие свойства.
Вот это тоже не понял.
Данкую, оно самое.
Очень не хватает вот таких простых примеров для иллюстрации мозговыносящей теории.
Щас вот разберусь с фреймворком и сам запилю по нему простой гайд с игровыми автоматами и блудницами.
Вообще, я уже написал то, что хотел на джаве (формочка, которая считывает информацию с БД, особым образом ее обрабатывает, и записывает назад), но вот в пхп я без понятия, как приступить к решению проблемы. ХЕЛП
Есть два файла с простой формой. Почему не срабатывает формочка при использовании шаблона с передачей переменной?
index.php: http://pastebin.com/Q1AjCVaW
main.html: http://pastebin.com/ptWiM17C
Спасибо.
>число элементов в нем можно считать через count($storage)
А есть какой-нибудь аналог array_filter чтобы можно было с SplObjectStorage работать?
>PHP Catchable fatal error: Object of class Foo could not be converted to string in /home/Cb9m7d/prog.php on line 20
Есть какой-нибудь способ подружить эту функцию с объектами в массиве?
Подскажите с regexp. Как исключить строку с символами?
Первая попытка искать Фибоначчи с помощью рекурсии. Пока что не могу понять, почему у меня не эхается каждый раз число??
http://ideone.com/3DelYM
array_udiff
Укажи, что строка должна начинаться и заканчиваться на цифру.
хочешь интенсив типа пройти?
>Слишком просто? Ок, давай усложним задачу. Добавим в банкомат банкноты номиналом 200 и 2000 р. После чего выставляем такое число банкнот: 1 по 5000, 4 по 2000, 1 по 500, 3 по 200 и пытаемся выдать 6600 р.
Ребятки. Эту задачу (именно в таком, усложнённом виде) без рекурсии решить можно? Уже час голову ломаю. Простой вариант решён.
Зашквар только в твоей голове
можно и задачу о сортировке массива решить с помощью 1 лишь shuffle($array), а ты всего-то рекурсию исключаешь из списка вариантов. Думаю да. ты же когда выдаешь сдачу, не делаешь многоступенчатую рекурсию?
Ты читал эту версию задачи, с подробными пояснениями и советами?
https://github.com/codedokode/pasta/blob/master/student-list.md
Читал этот туториал? http://php.net/manual/ru/tutorial.php
HTML знаешь?
Если что-то конкретно непонятно, то спрашивай.
>Способы передачи инфы серверу, что ли. Сейчас я вижу только два - формы с постом/редко с гетом и ссылки с гетом
Да, все так. А что, тебе мало? Учи ajax, node.js и проч.
В твоем гитхабе в будущем. Пока есть задание с подробными комментариями и советами: https://github.com/codedokode/pasta/blob/master/student-list.md
>>447024
>> Это неудачное решение. Департамент не должен клонировать работников (но ты можешь сделать это отдельной функцией). Департамент
>> может принимать готовых работников либо по одному, либо массивом.
>Добавить функцию вне класса?
Можно функцию, можно отдельный класс.
>> Сама функция неудачно сделана. Что будет, если ее вызвать несколько раз подряд? Если не вызвать ни разу? Тогда объект начнет возвращать недостоверные данные. Если каждый класс в программе будет так работать, то ошибки в ней будут сыпаться как из рога изобилия.
> Вот это не понял.
Выполни такой код:
$manager = new Manager(2); // создаем менеджера 2 ранга
// пытаемся узнать его зарплату
var_dump($manager->income);
$manager->setRank( );
$manager->setRank( );
$manager->setRank( );
$manager->setRank( );
$manager->setRank( );
// пытаемся еще раз узнать его зарплату
var_dump($manager->income);
Этот код напечатает разные и не соответствующие действительности числа: http://ideone.com/nL5tUF
А должен в обоих случаях печатать 625 (500 + 25%).
То есть если у тебя есть поле, хранящее зарплату или метод, который ее считает, он должен всегда возвращать актуальные данные. А у тебя возвращает какую-то ерунду.
Ну и плюс у тебя ошибка в том, что одно поле (income) используется для хранения 2 разных вещей: базовой ставки и итоговой зарплаты, это создает путаницу.
> А как тогда сотрудников добавлять? Один объект - один сотрудник.
Не очень понял вопрос, но да, один объект класса Employee или его наследника соответствует одному сотруднику.
>>Я советую не менять никакие свойства.
> Вот это тоже не понял.
Я советую в income хранить базовую ставку (500 для менеджера например), а общую зарплату вычислять методом и не сохранять ее в поле income или куда-то еще.
В твоем гитхабе в будущем. Пока есть задание с подробными комментариями и советами: https://github.com/codedokode/pasta/blob/master/student-list.md
>>447024
>> Это неудачное решение. Департамент не должен клонировать работников (но ты можешь сделать это отдельной функцией). Департамент
>> может принимать готовых работников либо по одному, либо массивом.
>Добавить функцию вне класса?
Можно функцию, можно отдельный класс.
>> Сама функция неудачно сделана. Что будет, если ее вызвать несколько раз подряд? Если не вызвать ни разу? Тогда объект начнет возвращать недостоверные данные. Если каждый класс в программе будет так работать, то ошибки в ней будут сыпаться как из рога изобилия.
> Вот это не понял.
Выполни такой код:
$manager = new Manager(2); // создаем менеджера 2 ранга
// пытаемся узнать его зарплату
var_dump($manager->income);
$manager->setRank( );
$manager->setRank( );
$manager->setRank( );
$manager->setRank( );
$manager->setRank( );
// пытаемся еще раз узнать его зарплату
var_dump($manager->income);
Этот код напечатает разные и не соответствующие действительности числа: http://ideone.com/nL5tUF
А должен в обоих случаях печатать 625 (500 + 25%).
То есть если у тебя есть поле, хранящее зарплату или метод, который ее считает, он должен всегда возвращать актуальные данные. А у тебя возвращает какую-то ерунду.
Ну и плюс у тебя ошибка в том, что одно поле (income) используется для хранения 2 разных вещей: базовой ставки и итоговой зарплаты, это создает путаницу.
> А как тогда сотрудников добавлять? Один объект - один сотрудник.
Не очень понял вопрос, но да, один объект класса Employee или его наследника соответствует одному сотруднику.
>>Я советую не менять никакие свойства.
> Вот это тоже не понял.
Я советую в income хранить базовую ставку (500 для менеджера например), а общую зарплату вычислять методом и не сохранять ее в поле income или куда-то еще.
Если бы ты открыл инспектор в браузере (F12 или Ctrl + Shift + I) на вкладке Network, попробовал отправить форму и посмотрел бы что передается, то увидел бы что там нет поля submit.
> <button class="btn btn-default" type="submit">
В форме передаются только элементы у которых есть имя (name). У кнопки имя не задано и она не передается.
> форма из одинокого поля для поиска - уже стремно.
Почему? GET форма для поиска — идеальное решение.
> Или форма с кнопкой 'ударить' с десятком скрытых полей(хп, броня, там все дела) в воображаемой игре
Это да, игры обычно используют аякс и нажатие на кнопку не отправляет форму, а вызывает скрипт, который через аякс запрос имитирует отправку формы со всеми нужными полями. Ну и для удара незачем передавать все поля, хватит наверно идентификатора атакующего и идентификатора цели (юнит 12 атакует юнит 15 оружием 3).
Если ты пока не освоил яваскрипт и аякс, отправляй пока обычные формы.
Аякс — это HTTP-запросы, которые яваскрипт может отправлять в фоновом режиме (то есть без перезагрузки страницы и вообще незаметно для пользователя) асинхронно (то есть они не блокируют работу со страницей).
> Или ссылка с айдишкой статьи которая не является ссылкой, а служит для передачи айди для удаления и других операций.
GET запрос не должен использоваться для удаления данных и изменения данных на сервере. Потому ссылка для удаления не должна ничего удалять. а лишь вести на страницу с формой подтверждения удаления (а форма отправляется через POST). Или как вариант кнопка удаления может через аякс отправлять POST- или DELETE-запрос.
(да, в HTTP кроме GET и POST есть еще PUT, PATCH, DELETE и ты можешь добавлять свои методы. Но они работают только через аякс и только в новых браузерах, через форму слать такие запросы нельзя).
> Сейчас я вижу только два - формы с постом/редко с гетом и ссылки с гетом
Если что, в моем уроке по формам ( https://github.com/codedokode/pasta/blob/master/forms.md ) написана разница между GET и POST:
— GET должен использоваться только для форм, которые не меняют данные на сервере: форма поиска, форма перехода на определенную страницу. POST используется для любых форм (добавление, изменение, удаление информации)
— файлы можно прикладывать только к POST-формам, у которых enctype равен multipart/form-data
— GET-форма добавляет введенные данные в URL и потому пользователь может скопировать и сохранить или переслать ссылку на результаты (например на результат поиска). POST форма ничего не добавляет в URL, и при открытии этого URL мы увидим лишь пустую форму.
— объем данных в GET-форме ограничен 500-2000 символов (так как браузеры и серверы ограничивают длину URL)
> форма из одинокого поля для поиска - уже стремно.
Почему? GET форма для поиска — идеальное решение.
> Или форма с кнопкой 'ударить' с десятком скрытых полей(хп, броня, там все дела) в воображаемой игре
Это да, игры обычно используют аякс и нажатие на кнопку не отправляет форму, а вызывает скрипт, который через аякс запрос имитирует отправку формы со всеми нужными полями. Ну и для удара незачем передавать все поля, хватит наверно идентификатора атакующего и идентификатора цели (юнит 12 атакует юнит 15 оружием 3).
Если ты пока не освоил яваскрипт и аякс, отправляй пока обычные формы.
Аякс — это HTTP-запросы, которые яваскрипт может отправлять в фоновом режиме (то есть без перезагрузки страницы и вообще незаметно для пользователя) асинхронно (то есть они не блокируют работу со страницей).
> Или ссылка с айдишкой статьи которая не является ссылкой, а служит для передачи айди для удаления и других операций.
GET запрос не должен использоваться для удаления данных и изменения данных на сервере. Потому ссылка для удаления не должна ничего удалять. а лишь вести на страницу с формой подтверждения удаления (а форма отправляется через POST). Или как вариант кнопка удаления может через аякс отправлять POST- или DELETE-запрос.
(да, в HTTP кроме GET и POST есть еще PUT, PATCH, DELETE и ты можешь добавлять свои методы. Но они работают только через аякс и только в новых браузерах, через форму слать такие запросы нельзя).
> Сейчас я вижу только два - формы с постом/редко с гетом и ссылки с гетом
Если что, в моем уроке по формам ( https://github.com/codedokode/pasta/blob/master/forms.md ) написана разница между GET и POST:
— GET должен использоваться только для форм, которые не меняют данные на сервере: форма поиска, форма перехода на определенную страницу. POST используется для любых форм (добавление, изменение, удаление информации)
— файлы можно прикладывать только к POST-формам, у которых enctype равен multipart/form-data
— GET-форма добавляет введенные данные в URL и потому пользователь может скопировать и сохранить или переслать ссылку на результаты (например на результат поиска). POST форма ничего не добавляет в URL, и при открытии этого URL мы увидим лишь пустую форму.
— объем данных в GET-форме ограничен 500-2000 символов (так как браузеры и серверы ограничивают длину URL)
В PHP есть интерфейсы Traversable, Iterator, которые позволяют любому объекту задать методы для «перебора» содержимого через foreach. Было бы логично, что с такими напоминающими массивы объектами можно было работать через функции вроде array_filter, array_slice и прочими, но увы, это нельзя. Функции работают только с настоящими массивами.
Для работы с объектами, поддерживающими Traversable, есть аж три функции:
http://php.net/manual/ru/function.iterator-apply.php
http://php.net/manual/ru/function.iterator-count.php
http://php.net/manual/ru/function.iterator-to-array.php
Надеюсь, разработчики php найдут в будущих версиях возможность исправить эти противоречия.
Я думаю, нам не подходит ни одна и проще всего перебирать SplObjectStorage через foreach.
Вот информация про то, как делать похожие на массивы объекты в php: http://habrahabr.ru/post/127711/
Это странность функции a_diff.
там в мануале об этом вскользь написано:
> Два элемента считаются одинаковыми тогда и только тогда, если (string) $elem1 === (string) $elem2. Другими словами, когда их строковое представление идентично
То есть он все пытается привести к строке. Гуглинг дает нам ответ как сделать a_diff для объектов:
http://stackoverflow.com/a/6472227
использовать a_udiff, а в функции написать
return $a === $b; // не забудь про 3 знака равно
>>447109
Твоя регулярка примет любую строку внутри которой есть правильный телефон. Надо добавить символы для привязки к началу и концу строки.
>>447121
Что-то сложно. Там функция из 3-4 строк получается.
> findFib ($last, $current, $target) {
Почему у функции 3 аргумента? Должен быть ровно один — искомое число.
Так и быть, подскажу первые пару строк:
function fib($n) {
if ($n == 1) {
return 0; // первое число Фибоначчи равно 0
}
....
> //почему вот это эхается только в конце 1 раз, а не при каждой итерации
>\t\t//зато переносы строки эхаются все
Потому что твоя функция может вернуть в $next 2 разных значения:
— либо какое-то число, если сработал return $new;
— либо null если мы пошли другим путем и return нам не встретился. При этом на печати null раузмеется не выводится.
Ставь вместо echo var_dump и увидишь сам.
Это странность функции a_diff.
там в мануале об этом вскользь написано:
> Два элемента считаются одинаковыми тогда и только тогда, если (string) $elem1 === (string) $elem2. Другими словами, когда их строковое представление идентично
То есть он все пытается привести к строке. Гуглинг дает нам ответ как сделать a_diff для объектов:
http://stackoverflow.com/a/6472227
использовать a_udiff, а в функции написать
return $a === $b; // не забудь про 3 знака равно
>>447109
Твоя регулярка примет любую строку внутри которой есть правильный телефон. Надо добавить символы для привязки к началу и концу строки.
>>447121
Что-то сложно. Там функция из 3-4 строк получается.
> findFib ($last, $current, $target) {
Почему у функции 3 аргумента? Должен быть ровно один — искомое число.
Так и быть, подскажу первые пару строк:
function fib($n) {
if ($n == 1) {
return 0; // первое число Фибоначчи равно 0
}
....
> //почему вот это эхается только в конце 1 раз, а не при каждой итерации
>\t\t//зато переносы строки эхаются все
Потому что твоя функция может вернуть в $next 2 разных значения:
— либо какое-то число, если сработал return $new;
— либо null если мы пошли другим путем и return нам не встретился. При этом на печати null раузмеется не выводится.
Ставь вместо echo var_dump и увидишь сам.
Это задача о ранце, так что да, можно, используя массив. А можно и через рекурсию, но это будет более медленый (на зато более простой) способ.
>>447132
Нет наверно. Но я не знаю, насколько глубоко там изучается CSS.
Потому я бы советовал также решить и показать решения моих задачек на HTML/CSS. Если ты хорошо знаешь эти языки, ты же их за 5 минут решишь, верно?
>>447141
Это пока числа маленькие. Человек обычно выдает сдачу «жадным» алгоритмом, а если будут большие суммы и большое количество монет то скорее всего запнется.
Там же по сути ввод\вывод из базы данных, внимательно изучи эти темы, напиши пару гостевых книг и всё поймёшь.
Насчёт Специалиста, там уроки действительно очень неплохие. Там препод когда пишет в процедурном стиле использует такой подход написания кода, все функции которые используются на разных страницах сайта пишет в одном файле (например lb.php) а потом подключает его ко всем нужным страницам. мне это метод очень понравился я его всегда пытаюсь использовать, что скажете по поводу такого подхода? Такое применимо уже на уровне коммерческого написания кода?
Нет. В коммерческом коде применяют ООП и обычно его делают на основе CMS или фрйемворков, ничего с нуля не пишут.
Процедурный подход давно устарел, он его демонстрировал только для общего понимания, как все работает. Ведь по сути методы ООП это те же самые функции, просто грамотно сгруппированные по классам.
И это правильно. Начинать нужно с азов, потом снежным комом накатывать все более сложные вещи.
Только не стоит откладывать ООП на потом, как это делают во многих курсах. В ООП нет ничего сложного и это базовая часть языка. Потому у меня в учебнике ООП изучают раньше, чем например базы данных.
Откладывать не стоит, потому что с ООП мы можем использовать ООП-расширения вроде PDO, ООП-паттерны вроде DataMapper, и без проблем перейти на ООП-фреймворки вроде Slim.
Мануал на англ. http://docs.slimframework.com/
Робоперевод мануала (что-то понять можно): http://www.microsofttranslator.com/bv.aspx?from=&to=ru&a=http%3A%2F%2Fdocs.slimframework.com%2F%23Getting-Started
Погуглить русские мануалы: http://www.google.ru/search?sourceid=chrome&ie=UTF-8&q=slim+php+%D0%BF%D0%BE+%D1%80%D1%83%D1%81%D1%81%D0%BA%D0%B8
На Slim твое приложение должно выглядеть примерно так. В index.php пишем:
// подключение и инциализация Слима
...
// объявляем роуты
$app->get('/lala', function () {
...
});
...
// запускаем приложение
$app->run( );
Ну и так как гайдов нет, то задавай вопросы. Если хочешь спросить «с чего начать», то начни с того, что установи Слим и добейся чтобы работал пример из документации с hello world.
Ставить можно через композер ( http://habrahabr.ru/post/145946/ ) или вручную.
Если что, у меня еще есть гайд по командной строке, если понадобится тебе.
ну так ей передавать надо же не только что мы ищем, но и на каком этапе поиска находимся, имхо. Если просто передавать функции что мы ищем 10е число, то как она поймет, что мы уже на 8м например? Передаем ей тупо 2 числа в последовательности + сколько еще шагов сделать надо.
$result = array_udiff($array, $filter, function($a, $b) {return ($a === $b);})
Разобрался
Ссылку на твой учебник можно? А то я в шапке не нашел, хотя может я кривой. Продублируй линк, если что.
http://ideone.com/mWE8fL
> Если просто передавать функции что мы ищем 10е число, то как она поймет, что мы уже на 8м например?
Она поймет это по тому, что ей передали 8. То есть какое число мы ей передали, такое и хотим получить.
> Передаем ей тупо 2 числа в последовательности + сколько еще шагов сделать надо.
Ну это не соответствует задаче. Задача написать функцию, возвращающую N-е число Фибоначчи. У такой функции может быть только один аргумент— номер числа, которое мы хотим получить. И заметь, я там выше даже написал готовый код для случая когда N == 1.
Ты придумал, что должен быть какой-то диапазон, шаг и пытаешься все усложнить. Пытаешься тут сделать цикл, хотя я просил их не делать. Надо мыслить чуть по другому.
Посмотрим на определение числа Фибоначчи:
> - первое число равно 0
> - второе равно 1
> - третье и далее равно сумме 2 предыдущих чисел.
Их этого определения можно построить код функции:
Если (N == 1) {
вернуть 0;
}
Если (N == 2) {
...
}
Если (N == 3) {
вернуть сумму первого и второго числа;
}
Если (N == 4) {
вернуть сумму второго и третьего;
}
.....
> Если просто передавать функции что мы ищем 10е число, то как она поймет, что мы уже на 8м например?
Она поймет это по тому, что ей передали 8. То есть какое число мы ей передали, такое и хотим получить.
> Передаем ей тупо 2 числа в последовательности + сколько еще шагов сделать надо.
Ну это не соответствует задаче. Задача написать функцию, возвращающую N-е число Фибоначчи. У такой функции может быть только один аргумент— номер числа, которое мы хотим получить. И заметь, я там выше даже написал готовый код для случая когда N == 1.
Ты придумал, что должен быть какой-то диапазон, шаг и пытаешься все усложнить. Пытаешься тут сделать цикл, хотя я просил их не делать. Надо мыслить чуть по другому.
Посмотрим на определение числа Фибоначчи:
> - первое число равно 0
> - второе равно 1
> - третье и далее равно сумме 2 предыдущих чисел.
Их этого определения можно построить код функции:
Если (N == 1) {
вернуть 0;
}
Если (N == 2) {
...
}
Если (N == 3) {
вернуть сумму первого и второго числа;
}
Если (N == 4) {
вернуть сумму второго и третьего;
}
.....
Ты меня совсем запутал, как мне при этом сюда рекурсию прикручивать? Не вписывать же туда всю последовательность чисел.
я должен как-то в обратном порядке сделать рекурсию? Типа внутри функции вызывать саму себя с аргументом -1 ?
Вообще, главное различие в том что их нету в первом департаменте, но я сделал проверку если не будет ни одного совпадения, то цикл переходит к следующему департаменту.
http://ideone.com/xExp6Q
Наверно никак
>>447336
Молодец.
>>447300
Кстати, тебе наверно будет интересно прочесть, откуда взялись числа Фибоначчи (из задачи про число кроликов): http://elementy.ru/trefil/21136
>>447344
> е, для смены на боса Аналитика.) Я вручную подсчитал какие должны быть значения, как для базовой модели, так и для всех антикризисных. Гарантирую, в моей таблице все верно.
Похвально. Это хороший подход. Но недостаточно, чтобы результаты были верные. Мы должны еще проверить правильность кода.
Вообще, у тебя осталось не очень много замечаний для исправления. Код уже лучше, чем раньше.
> public function addEmployee($emp)
тут бы тайп-хинт не помешал
Тайп хинты позволяют указать, что аргумент функции должен быть определенного типа (например быть объектом определенного класса или его наследника). Тайп хинт делает код понятнее (так как видно какого типа переменная) и надежнее (так как PHP не позволит передать что-то неразрешенное и ты сразу увидишь ошибку). Используй их везде.
Мануал: http://php.net/manual/ru/language.oop5.typehinting.php
> ($key = array_search($emp, $this->employees
Во-первых, лучше бы не объединять if и присваивание значения переменной (так делают, но у нас учебная задача и образцовый код), во-вторых, в array-search надо передавать true чтобы он делал строгое сравнение. Почитай про сравнение объектов: http://php.net/manual/ru/language.oop5.object-comparison.php
Далее, метод getSalaryPagesRatio не работает и выдает ошибку деления на ноль. Как писать надежный код в таких условиях? Вот пример: http://ideone.com/lUL1Jt
Функция подсчета расходов на зарплату каждый раз выдает новое число. Как понять, какое правильное? http://ideone.com/EDj8bV
Как писать надежный код, если функция каждый раз выдает новый результат?
> class Manager extends Employee
> {
> }
Это наследование выглядит немного странно. Конечно, так можно делать, чтобы разные профессии имели разные классы. Но обычно в этом задании при наследовании переопределяют значения базовой ставки, потребления кофе так, что их не требуется передавать в конструктор.
Базовый класс Employee стоит сделать абстрактным ( http://php.net/manual/ru/language.oop5.abstract.php ). Это запрещает создавать объекты такого класса и говорит что он предназначен для наследования.
> function cmpRanks($emp1, $emp2)
Есть интересный хак, позволяющий написать функцию короче. Функция сортировки принимает не только +1/-1, а любые положительные/отрицательные числа и можно написать
return $a->getRank() - $b->getRank();
Я не говорю, что надо так делать, но ты можешь где-то это встретить в коде. Ну и в PHP7 хотят сделать spaceship operator для таких целей:
return $a->getRank() <=> $b->getRank( );
Ссылка на англ: https://wiki.php.net/rfc/combined-comparison-operator
> $randomEmp = array_rand($dep->getEmployees( ));
Тут ты кажется что-то не понял. Если инженеров недостаточно чтобы уволить нужное число, не надо увольнять случайного человека, ничего делать не надо.
То есть выбор должен быть сделан так: берем всех инженеров не-боссов в данном департаменте, выстраиваем их по возрастанию ранга и увольняем первые 40%.
Ну и мне кажется, отбор инженеров на увольнение удобнее было бы сделать через array_slice. Ну и не пришлось бы писать эти скобки везде: $engineers[$i]
> if($engineers[$i]->isBoss() !== true) {
Странная строчка. Ты же и так пропускаешь боссов при выборе кандидатов, откуда он здесь возьмется? Если ты хочешь защититься от своих ошибок, лучше написать ассерт:
assert(!$engineer->isBoss( ));
Он выдаст ошибку при несоблюдении условия.
> $newBoss = new Analyst(1100, 3, 75, 5, $boss=true);
> $dep->addEmployee($newBoss);
Тут тоже не совсем верно. Не надо добавлять босса со стороны, нового босса надо найти в департаменте (если там нет подходящей кандидатуры, то не увольнять существующего). Старого босса не надо выгонять из департамента — надо просто лишить его статуса босса.
Замена должна выглядеть так:
- если руководитель аналитик, не трогаем его
- если подходящих кандидатур на замену нет, не трогаем его
- иначе выбираем самого высокорангового аналитика из департамента и ставим его боссом, старого босса разжалуем в обычного сотрудника
> array_push($firstRankMan, $emp);
Короче наверно писать $firstRankMan[] = $emp;
> for($i = 0; $i < $firstRankLim; $i++) {
> $key = array_search($firstRankMan[$i], $depEmployees);
> $depEmployees[$key]->setRank(2);
Тебе не кажется, что код сложный? Зачем тут array_search? Просто составляешь массив менеджеров, берешь от него первые 50% и каждого в этом массиве повышаешь, у тебя ведь и так уже массив объектов.
> tryCrisisModel($clonedDeps1, 1);
Ты зря вводишь цифры для обозначения моделей. Модель — это функция, и раз так, надо передавать не ее номер, а указатель на нее (в php это делается передачей имени функции как строки):
tryCrisisModel($clonedDeps1, 'crisisModel1');
Заодно избавляемся от if/else и непонятных цифр.
> $inputArr[$i] = array_merge(["№" => $enum[$i]], $inputArr[$i]);
Это странный код. Зачем писать $enum[$i] если можно написать $i + 1?
> for($i = 0; $i < count($inputArr); $i++) {
Тут лучше использовать foreach, короче и проще получится.
Наверно никак
>>447336
Молодец.
>>447300
Кстати, тебе наверно будет интересно прочесть, откуда взялись числа Фибоначчи (из задачи про число кроликов): http://elementy.ru/trefil/21136
>>447344
> е, для смены на боса Аналитика.) Я вручную подсчитал какие должны быть значения, как для базовой модели, так и для всех антикризисных. Гарантирую, в моей таблице все верно.
Похвально. Это хороший подход. Но недостаточно, чтобы результаты были верные. Мы должны еще проверить правильность кода.
Вообще, у тебя осталось не очень много замечаний для исправления. Код уже лучше, чем раньше.
> public function addEmployee($emp)
тут бы тайп-хинт не помешал
Тайп хинты позволяют указать, что аргумент функции должен быть определенного типа (например быть объектом определенного класса или его наследника). Тайп хинт делает код понятнее (так как видно какого типа переменная) и надежнее (так как PHP не позволит передать что-то неразрешенное и ты сразу увидишь ошибку). Используй их везде.
Мануал: http://php.net/manual/ru/language.oop5.typehinting.php
> ($key = array_search($emp, $this->employees
Во-первых, лучше бы не объединять if и присваивание значения переменной (так делают, но у нас учебная задача и образцовый код), во-вторых, в array-search надо передавать true чтобы он делал строгое сравнение. Почитай про сравнение объектов: http://php.net/manual/ru/language.oop5.object-comparison.php
Далее, метод getSalaryPagesRatio не работает и выдает ошибку деления на ноль. Как писать надежный код в таких условиях? Вот пример: http://ideone.com/lUL1Jt
Функция подсчета расходов на зарплату каждый раз выдает новое число. Как понять, какое правильное? http://ideone.com/EDj8bV
Как писать надежный код, если функция каждый раз выдает новый результат?
> class Manager extends Employee
> {
> }
Это наследование выглядит немного странно. Конечно, так можно делать, чтобы разные профессии имели разные классы. Но обычно в этом задании при наследовании переопределяют значения базовой ставки, потребления кофе так, что их не требуется передавать в конструктор.
Базовый класс Employee стоит сделать абстрактным ( http://php.net/manual/ru/language.oop5.abstract.php ). Это запрещает создавать объекты такого класса и говорит что он предназначен для наследования.
> function cmpRanks($emp1, $emp2)
Есть интересный хак, позволяющий написать функцию короче. Функция сортировки принимает не только +1/-1, а любые положительные/отрицательные числа и можно написать
return $a->getRank() - $b->getRank();
Я не говорю, что надо так делать, но ты можешь где-то это встретить в коде. Ну и в PHP7 хотят сделать spaceship operator для таких целей:
return $a->getRank() <=> $b->getRank( );
Ссылка на англ: https://wiki.php.net/rfc/combined-comparison-operator
> $randomEmp = array_rand($dep->getEmployees( ));
Тут ты кажется что-то не понял. Если инженеров недостаточно чтобы уволить нужное число, не надо увольнять случайного человека, ничего делать не надо.
То есть выбор должен быть сделан так: берем всех инженеров не-боссов в данном департаменте, выстраиваем их по возрастанию ранга и увольняем первые 40%.
Ну и мне кажется, отбор инженеров на увольнение удобнее было бы сделать через array_slice. Ну и не пришлось бы писать эти скобки везде: $engineers[$i]
> if($engineers[$i]->isBoss() !== true) {
Странная строчка. Ты же и так пропускаешь боссов при выборе кандидатов, откуда он здесь возьмется? Если ты хочешь защититься от своих ошибок, лучше написать ассерт:
assert(!$engineer->isBoss( ));
Он выдаст ошибку при несоблюдении условия.
> $newBoss = new Analyst(1100, 3, 75, 5, $boss=true);
> $dep->addEmployee($newBoss);
Тут тоже не совсем верно. Не надо добавлять босса со стороны, нового босса надо найти в департаменте (если там нет подходящей кандидатуры, то не увольнять существующего). Старого босса не надо выгонять из департамента — надо просто лишить его статуса босса.
Замена должна выглядеть так:
- если руководитель аналитик, не трогаем его
- если подходящих кандидатур на замену нет, не трогаем его
- иначе выбираем самого высокорангового аналитика из департамента и ставим его боссом, старого босса разжалуем в обычного сотрудника
> array_push($firstRankMan, $emp);
Короче наверно писать $firstRankMan[] = $emp;
> for($i = 0; $i < $firstRankLim; $i++) {
> $key = array_search($firstRankMan[$i], $depEmployees);
> $depEmployees[$key]->setRank(2);
Тебе не кажется, что код сложный? Зачем тут array_search? Просто составляешь массив менеджеров, берешь от него первые 50% и каждого в этом массиве повышаешь, у тебя ведь и так уже массив объектов.
> tryCrisisModel($clonedDeps1, 1);
Ты зря вводишь цифры для обозначения моделей. Модель — это функция, и раз так, надо передавать не ее номер, а указатель на нее (в php это делается передачей имени функции как строки):
tryCrisisModel($clonedDeps1, 'crisisModel1');
Заодно избавляемся от if/else и непонятных цифр.
> $inputArr[$i] = array_merge(["№" => $enum[$i]], $inputArr[$i]);
Это странный код. Зачем писать $enum[$i] если можно написать $i + 1?
> for($i = 0; $i < count($inputArr); $i++) {
Тут лучше использовать foreach, короче и проще получится.
Молодец. А теперь убери ненужные переменные before, preBefore, current и переходи ко второй задаче.
>>447361
Инженеры есть не везде, их мало, все же Вектор это не инженерная компания.
По коду: неплохо, но надо разбить длинные строки (array_filter) переносами. Также, надо сделать свойство employees в департаменте непубличным (private или protected). А то ты прямо снаружи меняешь содержимое массива, не идеально как-то. В идеальном коде публичные свойства вообще не используются, все делается через методы, но тут хотя бы массив работников закрой.
> \treturn true;
Не очень понятно зачем. Он же в любом случае true вернет.
> ($this->departments as $departmentkey => $department) {
departmentkey не нужен тут
А лучше сделай все свойства непубличными. Давай-ка потихоньку приучаться делать все через методы. Напрямую мы лезли в свойствах только в первых задачах, так как это было проще, а сейчас ты уже опытный.
>Также, надо сделать свойство employees в департаменте непубличным (private или protected). А то ты прямо снаружи меняешь содержимое массива, не идеально как-то. В идеальном коде публичные свойства вообще не используются, все делается через методы, но тут хотя бы массив работников закрой.
Это я сделаю как заставлю функцию работать. У меня инженеры почему-то не увольняются.
> {return ($a != $b);}
надо использовать строгое сравнение, почитай http://php.net/manual/ru/language.oop5.object-comparison.php
Ну начать можно со сравнения первых символов маски и файла: если первая буква маски не спецсимвол и она не равна первой букве файла, то он не соответствует маске.
Если они равны, то результат равен разультату сравнения огрызков маски и файла, начинающихся со второго символа.
Если первая буква маски спецсимвол, то тут появляются варианты.
Спасибо, Абу!
Дело в том что со всеми переменными все ок. На пике я распринтовал переменную $focusEmployees - это отобранные сотрудники которых надо уволить. Следом за ней идет функция array_udiff, которая работает когда мы хотим уволить менеджеров за место инженеров
http://ideone.com/xExp6Q
А почему ты думаешь, что udiff не работает? Ты делал var_dump ($department->employees) до и после udiff?
Понимаю что неверно, но я хотя бы в правильном направлении двигаюсь? Эта ваша рекурсия сложная для меня штука, ведь если раньше я мог просто дампить каждый шаг, и вообще не заворачивать код в функцию если хотел, то тут нужно сразу писать функцию, плюс в голове все эти уровни ПРОНИКНОВЕНИЯ ВНУТРЬ продумывать, путает очень сильно.
Потому что это индексная страница на которой выводятся все сотрудники после того как вызывается сама функция увольнения
На всякий случай убедился и распринтовал сотрудников до и после udiff. Результат - все то же самое.
Да, ты прав, udiff работает не совсем так, как я думал. Она требует чтобы функция сравнения вернула -1, 0 или 1, то есть она требует чтобы объекты можно было отсортировать по какому-то критерию, например id. У нас нет id (и ты возвращаешь не число, а true/false), потому она не работает.
Можно конечно сравнивать spl_object_hash (он возвращает определенное число для каждого объекта). Это строка, так что такое сравнение еще и выглядит как костыль.
Другой вариант — использовать SplObjectStorage вместо массива. У него есть метод http://php.net/manual/ru/splobjectstorage.removeall.php
Ну или удалять как-то по другому. Например, сделать у департамента метод удалитьРаботника(работник) и просто в цикле всех по очереди туда передавать.
>и ты возвращаешь не число, а true/false
Кстати, я заметил такую особенность что 0 == false, а 1 == true. Так что должно сработать правильно. С менеджерами же работает. Странно что с инженерами не получилось.
>Другой вариант — использовать SplObjectStorage вместо массива. У него есть метод http://php.net/manual/ru/splobjectstorage.removeall.php
Мне нравиться этот вариант. Убьем сразу два зайца: и с SplObjectStorage разберемся и функцию сделаем. Единственное что мне не нравиться в нем, это то что к нему нужно самостоятельно писать функции. Я с ума сойду писать аналог usort для него.
А вот еще что подумал. Раз уж я пишу функции которые могут пригодиться другим, могу я куда-нибудь их выложить чтобы их потом добавили в новых версиях php?
> Раз уж я пишу функции которые могут пригодиться другим, могу я куда-нибудь их выложить чтобы их потом добавили в новых версиях php?
php пишется на Си :) Так что это маловероятно. Но ты мог бы сделать php-библиотеку, хотя по моему тут все же код ориентирован только на решение одной задачи про вектор.
Ну и если тебе интересно, как вносят изменения в php, ты можешь посмотреть тут:
https://wiki.php.net/rfc
Люди предлагают изменения, их обсуждают и разработчики php голосуют за/против принятия.
> Я с ума сойду писать аналог usort для него.
Я подумал, удобнее кандидатов на удаление сортировать и выбирать через массив, а вот хранить в департаменте их удобнее в SplObjectStorage. Ну и приделать метод для удаления.
Делаю родственнице сайт с тестами для школы. Там нужен большой и многофункциональный плагин для создания тестов с разными видами ответов (просто галочкой выбрать ответ или вписать правильный ответ в поле, сопоставить вопросы и ответы в таблице и прочие варианты ответов) и ведением статистики прохождения тестов (в каких заданиях теста наибольшее число ошибок было допущено группой проходивших тест, всё это показывается в виде графиков, типа вот таких: http://www.flotcharts.org/flot/examples/series-pie/index.html).
Помимо этого нужно допилить функционал WordPress только не гоните несвежими носовыми платками до такого, чтобы можно было регистрироваться через соцсети (для этого есть плагины) и создавать определённые группы учеников (это нужно для того, чтобы классы учеников различались и люди из 9"б" не могли проходить тест для 9"а").
Вот сколько такое может стоить на фрилансе и за сколько именно ты, бро, суперский программист, взялся бы реализовать такое? Отдельно плагин для тестов и отдельно регистрацию и разбиение на группы (что-то подумал, что в WP такое и изначально есть вроде бы, создание групп пользователей).
Буду благодарен за толковый ответ, спасибо!
Вопрос - почему глобальная переменная не видна. По идее на экран должна вывестись переменная, как массив.
<body>
<?php
echo 'GET: <pre>'.print_r($_GET,1).'</pre>';
?>
<div>
<form action="index.php" method="GET">
<input type="text" name="login" />
<input type="text" name="password" />
<input type="submit" name="submit" value="sabmit"
</form>
</div>
<div>
</div>
</body>
</html>
Нро когда я жму, то просто сервер не реагирует.
Стоит денвер
тебе на фриланс.
многое зависит от качества нужной работы + непонтяно, что с дизайном.
я не знаю вордпресса, но абстрактно, я думаю, такая задача стоит тысяч 30 (без дизайна, хотя бы гайдлайны).
А так задача слишком крупная, чтобы тебе кто-то предложил помочь за так, я думаю (лично мне лень морочиться с ВП, так бы помог).
Или какой лучше бесплатный/платный хостинг для практики взять
тебе зачем размещать?
если для тренировки, то WAMP/XAMP подойдёт (на линуксах всё самому поднять не проблема).
Если же хочешь расширять, то лучше взять что-то типа амазона (там вроде как бесплатный год). Доменное имя всё равно придётся купить, амазону за это тоже платить немного придётся, но реально немного.
1. Если я решился использовать DataMapper, то вся суть сводится к написанию класса, который бы обрабатывал каждую строчку результатов выполнения запроса SELECT, да? Обычно в класс входит объявление глобальных переменных, конструктора и набора методов. Здесь нужно, чтобы глобальные переменные соответствовали каждому столбцу результатов запроса, правильно я понимаю?
2. Я нихрена не понимаю предназначения файлов *mapper.php из проекта анона, который делает задачу про студентов. Зачем они нужны? Конкретно про эти файлы ничего в туториалах нет.
>Тебе не кажется, что код сложный? Зачем тут array_search? Просто составляешь массив менеджеров, берешь от него первые 50% и каждого в этом массиве повышаешь, у тебя ведь и так уже массив объектов.
Но ведь задача формулируется так:
В каждом департаменте повысить 50% (округляя в большую сторону) менеджеров 1-го и 2-го ранга на один ранг с целью расширить их полномочия. Т.е., как я понял, надо отделить из всего массива менеджеров, затем отделить 1ранговых от 2ранговых. После этого, повысить у 50% менеджеров в каждом массиве (1ранговых и 2ранговых) ранг на 1.
Например: есть 9ме1, 3ме2, 2ме3. После манипуляций с ними получится 4ме1, 6ме2, 4ме3. А если как ты сказал повысить 50% массива менеджеров, то просто получится:
2ме1, 10ме2, 2*ме3. Или я чего-то не понимаю?
Ну, я на фрилансах заказывал только копирайт-рерайт (тексты всякие), причём жутко был недоволен результатами, а один раз был кинут исполнителем на две недели, правда, потом он вернул предоплату. Всегда всё-таки искал братишек-энтузиастов и им платил по той цене, которая на фрилансе была, даже больше. Но это с текстами, тут я сам разбираюсь, а с плагинами и вообще кодом у меня проблемы.
>многое зависит от качества нужной работы + непонтяно, что с дизайном.
Качество, конечно, изначально нужно высокое, потому что проект будет масштабироваться до общегородского и, в пределе, общероссийского уровня, необходимо постоянное комментирование кода, возможность управлять группами пользователей и составлением статистики по разным параметрам. Я как-то изучал PHP по учебнику Савельевой, дошёл до баз данных, вроде даже с начальными знаниями языка это всё возможно?
А что ты имеешь в виду под дизайном? Просто окончательный вывод тестов перед пользователем? Ну, это уже я и сам могу просто через правку CSS. Примерные представления о том, как тесты в итоге должны выглядеть, у меня есть.
>тысяч 30
Выходит, там часов на 20-30 работы для профессионала? Ох щи, думал, что меньше...
Ну а что там конкретно понадобится для того, чтобы всё заработало, кроме PHP и JS? Я разрабатывал этот плагин с одним толковым братишкой, но он говорит, что ему скиллов не хватает. Мы обсуждали целый месяц тонкости настройки и все важные моменты, он сделал прототип плагина, но потом мы дошли до того, что захотели сделать копию http://www.proprofs.com/quiz-school/ - вот пока он прокачивает скиллы, я думал заказать такой плагин, а он бы отталкивался уже от него, например, была бы основа, на которую можно ориентироваться.
>А так задача слишком крупная, чтобы тебе кто-то предложил помочь за так, я думаю (лично мне лень морочиться с ВП, так бы помог)
Да, задача серьёзная, но радует то, что вполне разрешимая. Спасибо за ответ и советы.
Кстати, с высоты своего опыта не мог бы ты подсказать, как именно идентифицировать пользователей на сайте? Там нужны будут разделения на классы, для определённого класса будет определённый тест, некоторые тесты смогут проходить незарегистрированные пользователи, некоторые тесты смогут проходить зарегистрированные, но не относящиеся к определённому классу. Регистрация там должна быть в том числе и через соцсети. Вот нужны же различные ID для пользователей. Точнее, в этот ID должны входить разные маркеры (ID1 - зарегистрирован, отнесён к классу 9"а"; ID2 - незарегистрирован, не отнесён ни к одному классу; ID3 - зарегистрирован, не отнесён ни к одному классу) - вот как такое можно реализовать, чтобы пользователи тесты получали только те, которые им предназначаются? В самом плагине так же должно указываться, какая группа пользователей может проходить создаваемый тест.
Ну, я на фрилансах заказывал только копирайт-рерайт (тексты всякие), причём жутко был недоволен результатами, а один раз был кинут исполнителем на две недели, правда, потом он вернул предоплату. Всегда всё-таки искал братишек-энтузиастов и им платил по той цене, которая на фрилансе была, даже больше. Но это с текстами, тут я сам разбираюсь, а с плагинами и вообще кодом у меня проблемы.
>многое зависит от качества нужной работы + непонтяно, что с дизайном.
Качество, конечно, изначально нужно высокое, потому что проект будет масштабироваться до общегородского и, в пределе, общероссийского уровня, необходимо постоянное комментирование кода, возможность управлять группами пользователей и составлением статистики по разным параметрам. Я как-то изучал PHP по учебнику Савельевой, дошёл до баз данных, вроде даже с начальными знаниями языка это всё возможно?
А что ты имеешь в виду под дизайном? Просто окончательный вывод тестов перед пользователем? Ну, это уже я и сам могу просто через правку CSS. Примерные представления о том, как тесты в итоге должны выглядеть, у меня есть.
>тысяч 30
Выходит, там часов на 20-30 работы для профессионала? Ох щи, думал, что меньше...
Ну а что там конкретно понадобится для того, чтобы всё заработало, кроме PHP и JS? Я разрабатывал этот плагин с одним толковым братишкой, но он говорит, что ему скиллов не хватает. Мы обсуждали целый месяц тонкости настройки и все важные моменты, он сделал прототип плагина, но потом мы дошли до того, что захотели сделать копию http://www.proprofs.com/quiz-school/ - вот пока он прокачивает скиллы, я думал заказать такой плагин, а он бы отталкивался уже от него, например, была бы основа, на которую можно ориентироваться.
>А так задача слишком крупная, чтобы тебе кто-то предложил помочь за так, я думаю (лично мне лень морочиться с ВП, так бы помог)
Да, задача серьёзная, но радует то, что вполне разрешимая. Спасибо за ответ и советы.
Кстати, с высоты своего опыта не мог бы ты подсказать, как именно идентифицировать пользователей на сайте? Там нужны будут разделения на классы, для определённого класса будет определённый тест, некоторые тесты смогут проходить незарегистрированные пользователи, некоторые тесты смогут проходить зарегистрированные, но не относящиеся к определённому классу. Регистрация там должна быть в том числе и через соцсети. Вот нужны же различные ID для пользователей. Точнее, в этот ID должны входить разные маркеры (ID1 - зарегистрирован, отнесён к классу 9"а"; ID2 - незарегистрирован, не отнесён ни к одному классу; ID3 - зарегистрирован, не отнесён ни к одному классу) - вот как такое можно реализовать, чтобы пользователи тесты получали только те, которые им предназначаются? В самом плагине так же должно указываться, какая группа пользователей может проходить создаваемый тест.
Это отдельный класс для любого взаимодействия с бд, он либо что то возвращает из бд в нужно тебе виде, либо что то туда кладет
Не оп
под дизайном я имею в виду не только тесты, но и занесение этих тестов, отображение статистики (короче, админка -- не стоит это списывать со счетов).
>Качество, конечно, изначально нужно высокое
вот тут проблема, учитывая твои слова о
>как-то изучал
с первого раза написать хорошо расширяемый модуль невозможно, отвечаю (впрочем, шансов на то, что для тебя это сделает нонейм с фриланса, тоже маловато, если честно).
кроме js и php, нужно проектирование БД. точнее, БД у вас уже есть 100%, нужно спроектировать таблицу (если честно, это одно из самых тонких мест в плане расширяемости -- спроектируете плохо, потом будет очень трудно переделать).
> как именно идентифицировать пользователей на сайте
сразу скажу, что мои познания в бэкенде строго поднять ноду/рельсы и запилить апи для моего spa, поэтому дальше могу сморозить лютую хуету.
Так вот, тебе просто нужно создать таблицу с юзерами, в которой будет поле "класс", куда ты будешь записывать нужный идентификатор.
Затем в классе (уже класс php) добавить метод, который будет возвращать этот идентификатор, и по нему отдавать/не отдавать нужный класс.
з.ы. вообще, по вёрстке и js'у (d3 там для диаграм и логике) я могу помочь, если что, но в бэкенде, к сожалению, точно нет (нет желания писать на php).
>вроде даже с начальными знаниями языка это всё возможно
з.ы. да, возможно, но будет достаточно долго и криво (но если тебе для опыта, то это ок, заказчика, как правило, ебёт только одно -- работает или нет).
Два чаю тебе
>надо писать label input:checked
Такоей способ не работает почему-то http://jsfiddle.net/w3v31o9t/
Короче я не знаю, как здесь применить стиль к лейблу внутри которого чекнутый инпут. Я вижу только один выход: добавить внутрь лейбла после инпута <span> и все стили применять к нему, вместо лейбла, но тогда не будет работать first-child и last-child из-за разных родителей.
> как здесь применить стиль к лейблу внутри которого чекнутый инпут
Никак нельзя.
> Я вижу только один выход: добавить внутрь лейбла после инпута <span> и все стили применять к нему, вместо лейбла
да
> но тогда не будет работать first-child и last-child из-за разных родителей.
Будет: label:first-child > span
>не только тесты, но и занесение этих тестов, отображение статистики (короче, админка -- не стоит это списывать со счетов)
Да, там нужна в админке настройка вывода статистики, но сама статистика должна оказываться на общей странице группы и на личных страницах учеников. Тут тоже непонятно, как это всё собирать, через какие идентификаторы, но профессионалы должны себе представить сразу, я думаю.
>Так вот, тебе просто нужно создать таблицу с юзерами, в которой будет поле "класс", куда ты будешь записывать нужный идентификатор.
>Затем в классе (уже класс php) добавить метод, который будет возвращать этот идентификатор, и по нему отдавать/не отдавать нужный класс.
Хм, годно, спасибо!
Вот в такую таблицу по датам прохождения тестов графы с результатами, а вывод графиком через преобразующую функцию, - как на мой нубский взгляд это видится. График с общими результатами группы, график с частыми ошибками (опять же для вопросов нужны идентификаторы, ох щи, чтобы их как-то сравнивать...), график с результатами для каждого ученика.
>нужно спроектировать таблицу (если честно, это одно из самых тонких мест в плане расширяемости -- спроектируете плохо, потом будет очень трудно переделать)
Да, это очень важная часть, учитывая, сколько там всяких особенностей должно быть и разных выводов разных или одних и тех же данных.
>>447722
>з.ы. да, возможно, но будет достаточно долго и криво (но если тебе для опыта, то это ок, заказчика, как правило, ебёт только одно -- работает или нет)
Ну, мне для опыта, потому что планировал разобраться в работе кода. Программистом мне уже не стать - привык всё делать в лучшем виде, а для программирования слишком стар (30 лет) и слишком увлечён другими делами. Для понимания принципов того, как всё это будет устроено, - будет нормально, я думаю.
Спасибо за ответы, братишка, на многие хорошие мысли натолкнул. Попробую на досуге составить список всех возможных идентификаторов, которые будут у одного пользователя, начиная с фамилии и заканчивая конкретными результатами тестов.
>не только тесты, но и занесение этих тестов, отображение статистики (короче, админка -- не стоит это списывать со счетов)
Да, там нужна в админке настройка вывода статистики, но сама статистика должна оказываться на общей странице группы и на личных страницах учеников. Тут тоже непонятно, как это всё собирать, через какие идентификаторы, но профессионалы должны себе представить сразу, я думаю.
>Так вот, тебе просто нужно создать таблицу с юзерами, в которой будет поле "класс", куда ты будешь записывать нужный идентификатор.
>Затем в классе (уже класс php) добавить метод, который будет возвращать этот идентификатор, и по нему отдавать/не отдавать нужный класс.
Хм, годно, спасибо!
Вот в такую таблицу по датам прохождения тестов графы с результатами, а вывод графиком через преобразующую функцию, - как на мой нубский взгляд это видится. График с общими результатами группы, график с частыми ошибками (опять же для вопросов нужны идентификаторы, ох щи, чтобы их как-то сравнивать...), график с результатами для каждого ученика.
>нужно спроектировать таблицу (если честно, это одно из самых тонких мест в плане расширяемости -- спроектируете плохо, потом будет очень трудно переделать)
Да, это очень важная часть, учитывая, сколько там всяких особенностей должно быть и разных выводов разных или одних и тех же данных.
>>447722
>з.ы. да, возможно, но будет достаточно долго и криво (но если тебе для опыта, то это ок, заказчика, как правило, ебёт только одно -- работает или нет)
Ну, мне для опыта, потому что планировал разобраться в работе кода. Программистом мне уже не стать - привык всё делать в лучшем виде, а для программирования слишком стар (30 лет) и слишком увлечён другими делами. Для понимания принципов того, как всё это будет устроено, - будет нормально, я думаю.
Спасибо за ответы, братишка, на многие хорошие мысли натолкнул. Попробую на досуге составить список всех возможных идентификаторов, которые будут у одного пользователя, начиная с фамилии и заканчивая конкретными результатами тестов.
А какой тут смысл в first-child тогда, если у нас три лейбла и в каждом один элемент?
А, я понял, кажется. Все еще не разобрался в селекторах.
Но без "*" в маске пока. Думаю как впилить.
Подумай: если маска начинается со звездочки, как проверить что она равна имени файла?
Звездочка может соответствовать от 0 до любого количества любых символов. То есть она может «проглотить» любое количество начальных символов в имени.
Мы можем составить все возможные огрызки имени файла (имя целкиком, имя без первого символа, имя без первых 2 символов, иттд) и сравнить хвост маски с этими огрызками.
Ну типа если я встречаю звездочку в имени маски, то я должен забить на неё, и начать сравнивать то, что после звездочки в маске, с тем, что в конце имени? Не могу пока что осознать это. В решении без звездочки все правильно?
Перечитай внимательно мой пост. Если маска начинается со звездочки, то мы должны сравнить хвост этой маски со всеми возможными хвостами имени файла и найти хотя бы одно совпадение.
> Ну типа если я встречаю звездочку в имени маски, то я должен забить на неё,
Нет, не должен. Если бы на нее можно было забить, можно было бы вообще без всяких рекурсий вырезать все звездочки и сравнить строки.
> В решении без звездочки все правильно?
Решение будет правильное когда оно буде полностью соответствовать условиям задачи. Без звездочки его проверять нет смысла.
Объясняю самым простым языком. Допустим у нас есть маска
×1234
Где × - это звездочка, а 1234 - любые символы (возможно тоже содержащие звездочки).
Чтобы проверить, соответствует ли эта маска имени abcdefgh, мы должны проверить все возможные варианты:
- звездочка соответствует 0 символов
- звездочка соответтвует первому символу
- звездочка соответствует первым 2 символам
- звездочка соответствует первым 3 симвлам
....
Чтобы это проверить, мы должны по очереди сравнивать хвост маски 1234 с хвостами имени файла:
- abcdefgh
- bcdefgh
- cdefgh
...
Оп, посмотри пожалуйста:
Вопросы в index.php
https://github.com/f-v/applicants
Ты новую версию задания (с комментариями) читал или по старой делал? Вот эту читал: https://github.com/codedokode/pasta/blob/master/student-list.md ?
> //Нужно ли здесь заварачивать в try .. catch?
Ни в коем случае. Если что, вот мой урок по исключениям: https://gist.github.com/codedokode/65d43ca5ac95c762bc1a
В 99% try/catch не нужен, исключения должны пролетать выше.
> } catch (PDOException $e) {
> echo 'Database query error: '. $e->getMessage( );
Это тоже неправильный код кстати. Ты выводишь пользователю ошибку, в которой он ничего не понимает, а сам об этой ошибке никогда не узнаешь так как она не пишется в логи.
Исключения либо не ловят (в этом случае пользователь видит белую страницу, а исклчение логгируется) либо ловят на самом верхнем уровне, и при исключении пишут его в лог, а пользователю показывают страницу ошибки 503 с каким-то текстом или картинкой («Произошла ошибка, мы о ней знаем, попробуйте обновить страницу или перейти на главную.»).
> //Что еще должно быть в классе db? Он только берет на себя соединение и исполнение
В твоем случае класс db вообще не нужен, можно сразу использовать PDO. Ну или если ты хочешь, ты можешь написать свой класс для работы с базой, но там должен быть какой-то функционал, а у тебя ничего не добавлено. query ты можешь и напрямую через PDO сделать.
> //Все запросы должны формироваться в applicantsMapper и отправляться в db
Да. запросы не должны быть раскиданы по всему коду приложения. а должны быть собраны в одном месте.
> //Где должны проверяться введенные данные? Прямо в register.php или в Mapper?
Mapper занимается взаимодействием с БД. Проверять надо в отдельной функции или классе.
> // Почему тэг <? невсегда работает и приходится вставлять <?php ?
Потому что он отключается через конфиг php.ini. Не используй его.
Если ты не читал новую версию задачи с комментариями, прочитай пожалуйста и если найдешь у себя какие-то ошибки, попробуй исправить сам.
Если не сможешь или есть вопросы или что-то уточнить или хочешь показать промежуточный результат - пиши.
> //Нужно ли здесь заварачивать в try .. catch?
Ни в коем случае. Если что, вот мой урок по исключениям: https://gist.github.com/codedokode/65d43ca5ac95c762bc1a
В 99% try/catch не нужен, исключения должны пролетать выше.
> } catch (PDOException $e) {
> echo 'Database query error: '. $e->getMessage( );
Это тоже неправильный код кстати. Ты выводишь пользователю ошибку, в которой он ничего не понимает, а сам об этой ошибке никогда не узнаешь так как она не пишется в логи.
Исключения либо не ловят (в этом случае пользователь видит белую страницу, а исклчение логгируется) либо ловят на самом верхнем уровне, и при исключении пишут его в лог, а пользователю показывают страницу ошибки 503 с каким-то текстом или картинкой («Произошла ошибка, мы о ней знаем, попробуйте обновить страницу или перейти на главную.»).
> //Что еще должно быть в классе db? Он только берет на себя соединение и исполнение
В твоем случае класс db вообще не нужен, можно сразу использовать PDO. Ну или если ты хочешь, ты можешь написать свой класс для работы с базой, но там должен быть какой-то функционал, а у тебя ничего не добавлено. query ты можешь и напрямую через PDO сделать.
> //Все запросы должны формироваться в applicantsMapper и отправляться в db
Да. запросы не должны быть раскиданы по всему коду приложения. а должны быть собраны в одном месте.
> //Где должны проверяться введенные данные? Прямо в register.php или в Mapper?
Mapper занимается взаимодействием с БД. Проверять надо в отдельной функции или классе.
> // Почему тэг <? невсегда работает и приходится вставлять <?php ?
Потому что он отключается через конфиг php.ini. Не используй его.
Если ты не читал новую версию задачи с комментариями, прочитай пожалуйста и если найдешь у себя какие-то ошибки, попробуй исправить сам.
Если не сможешь или есть вопросы или что-то уточнить или хочешь показать промежуточный результат - пиши.
перед тем, как платить, надо проверять, сколько осталось долга, и если он меньше 5000, то платить только остаток и завершать цикл через break
http://ideone.com/cCCsJU
>>447825
Ну, и если хвост маски после звездочки, соответствует какому-то из этих хвостов, то значит что всё хорошо?
Типа у нас есть маска:
1289
и имя файла, 123456789
и мы так же кормим функции эту маску 89 и поочередно все
остатки к ней приставляем:
3456789 - неподошло, идем дальше =>
456789 - неподошло, дальше =>
..
89 - подошло, значит возвращаем true;
Вопрос такой: я могу это внутри функции циклом перебрать, или нужно еще 1 рекурсивное ответвление делать в этом случае??
подсказываю:
разбей все операции на действия, и расположи в логическом порядке, а не делай в одном выражении. Далее между этими действиями ты можешь втиснуть проверку на то, что если ты должен меньше 5000, то и заплатить стоит ровно столько, сколько ты должен, а не 5000.
Проблемка с сохранением файла.
Выдает ошибку
Error 500
move_uploaded_file(): The second argument to copy() function cannot be a directory
http://ideone.com/i82bFw
Подозреваю, что загвоздка здесь
$model->image->saveAs('images')
нужно указывать не только директорию, но и имя файла, что ли?
Бамп вопросу
У тебя эта сумма где прописана? Правильно, в переменной. Не в константе же. Нужна еще подсказка?
Э-э... Спасибо за содержательный ответ.
Вроде разобрался. Там короче надо было из массива $_FILES вынуть временное и текущее имя:
$model->image->saveAs(
'images/'.$_FILES['Image']['name']['image'],
$_FILES['Image']['tmp_name']['image']
);
Но теперь встает вопрос, что делать, если юзеры будут грузить одноименные пикчи, типа avatar.jpg
Ведь move_uploaded_file перезапишет файл. Или генерировать рандомное имя?
Неужели во фреймворке нет инструмента для автоматического переименования загружаемых файлов?
Поговорил сам с собой, день прошел не зря.
>>447853
>Вот эту читал: https://github.com/codedokode/pasta/blob/master/student-list.md
Спасибо. Это комментарии моей мечты просто.
> Неужели во фреймворке нет инструмента для автоматического переименования загружаемых файлов?
Может быть есть расширение? Я например такую статью нагуглил http://habrahabr.ru/post/156293/
ну и при загрузке файлов не забывай, что пользователь может попытаться загрузить тебе file.php (или .htaccess) и выполнить его.
Итак, начнем. Думаю, начать надо с добавления сотрудников, следовательно в классе Департамента (https://github.com/someApprentice/Vector-Com/blob/master/Classes/Department.php), перед тем как начать добавлять в него сотрудников, необходимо сделать переменную $employees не массивом и в конструкторе присвоить ей значение = new SplObjectStorage(), и в функции добавления добавлять их с помощью $this->employees->attach($employee). Если я правильно рассуждаю, то даже не придется переписывать все функции в это классе.
Теперь надо разобраться с классом управления (Direction: http://ideone.com/pCEZbY). В нем, я так же изменю присвою переменно $departments = new SplObjectStorage(). Однако, дальше начинается очередной разрыв мозга: функции фильтрации и сортировки нужно писать с нуля.
>>447529
>Я подумал, удобнее кандидатов на удаление сортировать и выбирать через массив, а вот хранить в департаменте их удобнее в SplObjectStorage. Ну и приделать метод для удаления.
Ну допустим, я не буду присваивать к $departments объект SplObjectStorage(). Мне тогда придется сделать пару методов для перевода объектов из SplObjectStorage() в массив, и обратно.
Это будет выглядеть примерно так:
function SplObjcStrgToArray($SplObjctStrg) {
foreach($SplObjectStrg as $object) {
$array[] = $object;
}
return $array;
}
Все правильно думаю?
> в конструкторе присвоить ей значение = new SplObjectStorage(), и в функции добавления добавлять их с помощью $this->employees->attach($employee).
Верно
> Если я правильно рассуждаю, то даже не придется переписывать все функции в это классе.
В правильно написанном ООП коде при внесении изменений обычно достаточно поменять несколько функций, не трогая код который их использует. За это ООП и любят.
> Однако, дальше начинается очередной разрыв мозга: функции фильтрации и сортировки нужно писать с нуля.
Я советую отбор работников на увольнение сделать через массивы.
> Мне тогда придется сделать пару методов для перевода объектов из SplObjectStorage() в массив, и обратно.
Норм, можно у департамента сделать метод получитьМассивРаботников, можно даже сделать метод получитьРаботниковОпределенногоТипа(тип)
> и обратно.
Обратно переводить не надо. Зачем это тебе нужна функция, которая заменяет всех работников в департаменте на переданных? Тебе хватит функции удаления одного работника.
Не, это слишком сложно для меня. Там автор пытается чуть ли не собственное расширение писать.
Валидация в Yii автоматическая, это я уже знаю. Достаточно в конфиге прописать правила. В данном случае пропустит только файлы 'jpg, gif, png' (искренне надеюсь, что валидация происходит по миме-типу, а не по расширению)
public function rules(){
return array(
array('image', 'file', 'types'=>'jpg, gif, png'),
);
}
Ладно.
Че-то тут кроме опа больше нет никого прошаренного, пойду срать на форум. А у вас молоко сбежало тред тонет.
>>447913
Да, ДатаМаппер служит для обмена информацией между объектом (например регистрационные данные пользователя) и базой данных.
Соответственно в классе Маппер обычно есть методы для вставки/удаления/апдейта/селекта и набор свойств, соответствующих полям таблицы.
http://habrahabr.ru/post/198450/
>Обратно переводить не надо. Зачем это тебе нужна функция, которая заменяет всех работников в департаменте на переданных? Тебе хватит функции удаления одного работника.
Чтобы можно было применить SplObjectStorage::removeAll. Хотя можно и по одному удалять. Пока не знаю что выбрать, наверно сделаю по одному, так логичней.
> искренне надеюсь, что валидация происходит по миме-типу, а не по расширению
По расширению.
Майм-тип надо определять самому. И в целях безопасности это бесполезно, так как php-код можно внедрить в файл-картинку. Главное, чтобы у файла расширение было не php, а что внутри не так принципиально (хотя конечно проверка по майм типу защитит от ошибок когда пользователь «конвертирует» bmp в jpg переименованием).
>>447928
> Хотя можно и по одному удалять.
Вот и удаляй. Ну можно еще сделать функцию, принимающую массив увольняемых и обходящую его циклом.
> if ($maskTail == $nameTail) {
>\t\t\t\t\treturn true;
Эта проверка не сработает когда в хвосте маски тоже есть вопросы и звездочки.
Также, у тебя там огромный if, его надо перевернуть.
Если у тебя есть код
if (условие) {
50 строк
} else {
2 строки
}
То его надо попробовать перевернуть, чтобы было
if (не выполняется условие) {
2 строки
} else {
50 строк
}
А еще лучше
if (не выполняется условие) {
2 строки;
return;
}
50 строк;
Также, сделай тесты к программе (чтобы и тебе, и мне было легче ее проверять). Сделай массив примеров вида [маска, имя, ожидаемый результат] и программу, которая проверяет функцию на этих примерах и пишет если что-то не так.
> if ($maskTail == $nameTail) {
>\t\t\t\t\treturn true;
Эта проверка не сработает когда в хвосте маски тоже есть вопросы и звездочки.
Также, у тебя там огромный if, его надо перевернуть.
Если у тебя есть код
if (условие) {
50 строк
} else {
2 строки
}
То его надо попробовать перевернуть, чтобы было
if (не выполняется условие) {
2 строки
} else {
50 строк
}
А еще лучше
if (не выполняется условие) {
2 строки;
return;
}
50 строк;
Также, сделай тесты к программе (чтобы и тебе, и мне было легче ее проверять). Сделай массив примеров вида [маска, имя, ожидаемый результат] и программу, которая проверяет функцию на этих примерах и пишет если что-то не так.
Ну и не думай, что это все. После того, как ты исправишь замечания, мы сделаем одну хитрую оптимизацию и может быть, переделаем задачу на нерекурсивный вариант (тесты пригодятся в обоих случаях, чтобы проверить что код по прежнему работает правильно).
>>447936
http://ideone.com/BzQEgK
Вот сделал вроде бы два замечания твоих. надеюсь понял про какой if идет речь.
а ок, про тесты не заметил.
Сделал так:
// Выводим список страниц
// Предыдущая и первая страницы
if ($page != 1) { // Если предыдущая страница существует
$prevpage = $page-1;
$url = $_SERVER['REQUEST_URI'];
$cut = '/&page=[0-9]+/';
$paste = "&page=1";
$urlFirstPage = preg_replace($cut, $paste, $url);
echo "<A href=" . $urlFirstPage ."><<</A> "; // Первая страница
$paste = "&page=" . $prevpage;
$urlPrevPage = preg_replace($cut, $paste, $url);
echo "<A href=" . $urlPrevPage . "><Назад</A> "; // Предыдущая страница
echo "Страница " .$page. " из " .$allpages . " "; // Активная страница
} else {
echo "Страница 1 из " .$allpages. " ";
}
// Следующая и последняя страницы
if ($page != $allpages) { // Если следующая страница существует
$url = $_SERVER['REQUEST_URI'];
$cut = '/&page=[0-9]+/';
$nextpage = $page+1;
$paste = "&page=" . $allpages;
$urlLastPage = preg_replace($cut, $paste, $url);
$paste = "&page=" . $nextpage;
$urlNetxtPage = preg_replace($cut, $paste, $url);
echo "<A href=" . $urlNetxtPage . ">Вперед></A> "; // Следующая страница
echo "<A href=" . $urlLastPage . ">>></A> "; // Последняя страница
Все ок, но при первом переходе из страницы поиска на страницу результатов в url нет параметра "page=", поэтому составить ссылку не получается. Как мне этот самый "page=1" запилить при первом переходе?
Сделал так:
// Выводим список страниц
// Предыдущая и первая страницы
if ($page != 1) { // Если предыдущая страница существует
$prevpage = $page-1;
$url = $_SERVER['REQUEST_URI'];
$cut = '/&page=[0-9]+/';
$paste = "&page=1";
$urlFirstPage = preg_replace($cut, $paste, $url);
echo "<A href=" . $urlFirstPage ."><<</A> "; // Первая страница
$paste = "&page=" . $prevpage;
$urlPrevPage = preg_replace($cut, $paste, $url);
echo "<A href=" . $urlPrevPage . "><Назад</A> "; // Предыдущая страница
echo "Страница " .$page. " из " .$allpages . " "; // Активная страница
} else {
echo "Страница 1 из " .$allpages. " ";
}
// Следующая и последняя страницы
if ($page != $allpages) { // Если следующая страница существует
$url = $_SERVER['REQUEST_URI'];
$cut = '/&page=[0-9]+/';
$nextpage = $page+1;
$paste = "&page=" . $allpages;
$urlLastPage = preg_replace($cut, $paste, $url);
$paste = "&page=" . $nextpage;
$urlNetxtPage = preg_replace($cut, $paste, $url);
echo "<A href=" . $urlNetxtPage . ">Вперед></A> "; // Следующая страница
echo "<A href=" . $urlLastPage . ">>></A> "; // Последняя страница
Все ок, но при первом переходе из страницы поиска на страницу результатов в url нет параметра "page=", поэтому составить ссылку не получается. Как мне этот самый "page=1" запилить при первом переходе?
Да, и в догонку, так же надо еще два параметра как-то передать для сортировки (по чему сортируем и в каком порядке).
> Делаю родственнице сайт с тестами для школы
Вообще, лучше поискать готовую CMS для этих целей. Есть CMS вроде Moodle, но у нее интерфейс нечеловеческий.
> Помимо этого нужно допилить функционал WordPress только не гоните несвежими носовыми платками до такого, чтобы можно было регистрироваться через соцсети (для этого есть плагины) и создавать определённые группы учеников
В вордпрессе нет групп же, это движок для блогов и того, что на них похоже.
> Вот сколько такое может стоить на фрилансе
зависит от потраченного времени
>>447607
> Вопрос - почему глобальная переменная не видна. По идее на экран должна вывестись переменная, как массив.
А что выводится вместо нее? По моему, так должно все выводиться.
> Нро когда я жму, то просто сервер не реагирует.
У тебя в теге инпут нет закрывающей скобки.
>>447618
Бесплатно, хотя по моему юкоз сейчас запретил создавать html сайты. Но ты можешь нагуглить любой другой html хостинг.Github pages например бесплатен и без рекламы для некоммерческих проектов.
> какой лучше бесплатный/платный хостинг
гугли сайты сравнения хостингов (бесплатные лучше брать зарубежные так как наши все с рекламой обычно)
>>447635
Это читал? https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md
Там есть пример как выглядит код работы с DataMapper
> Обычно в класс входит объявление глобальных переменных,
Это называется свойства или поля объекта. Глобальные переменные — это переменные, созданные снаружи классов и функций.
> конструктора и набора методов.
да
> Здесь нужно, чтобы глобальные переменные соответствовали каждому столбцу результатов запроса, правильно я понимаю?
Нет. DataMapper это класс который созраняет или загружает объекты-сущности из БД. Он не хранит результаты внутри себя. Ты читал статью и пример кода по ссылке? Читал это? http://design-pattern.ru/patterns/data-mapper.html
> Я нихрена не понимаю предназначения файлов
Маппер загружает/сохраняет объекты-сущности в базу данных. Потому он и маппер, что занимается отображением (сопоставлением) графа (набора) объектов на таблицы в базе данных.
Ты можешь написать упрощенный пример кода и показать и я скажу что там не так.
> Делаю родственнице сайт с тестами для школы
Вообще, лучше поискать готовую CMS для этих целей. Есть CMS вроде Moodle, но у нее интерфейс нечеловеческий.
> Помимо этого нужно допилить функционал WordPress только не гоните несвежими носовыми платками до такого, чтобы можно было регистрироваться через соцсети (для этого есть плагины) и создавать определённые группы учеников
В вордпрессе нет групп же, это движок для блогов и того, что на них похоже.
> Вот сколько такое может стоить на фрилансе
зависит от потраченного времени
>>447607
> Вопрос - почему глобальная переменная не видна. По идее на экран должна вывестись переменная, как массив.
А что выводится вместо нее? По моему, так должно все выводиться.
> Нро когда я жму, то просто сервер не реагирует.
У тебя в теге инпут нет закрывающей скобки.
>>447618
Бесплатно, хотя по моему юкоз сейчас запретил создавать html сайты. Но ты можешь нагуглить любой другой html хостинг.Github pages например бесплатен и без рекламы для некоммерческих проектов.
> какой лучше бесплатный/платный хостинг
гугли сайты сравнения хостингов (бесплатные лучше брать зарубежные так как наши все с рекламой обычно)
>>447635
Это читал? https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md
Там есть пример как выглядит код работы с DataMapper
> Обычно в класс входит объявление глобальных переменных,
Это называется свойства или поля объекта. Глобальные переменные — это переменные, созданные снаружи классов и функций.
> конструктора и набора методов.
да
> Здесь нужно, чтобы глобальные переменные соответствовали каждому столбцу результатов запроса, правильно я понимаю?
Нет. DataMapper это класс который созраняет или загружает объекты-сущности из БД. Он не хранит результаты внутри себя. Ты читал статью и пример кода по ссылке? Читал это? http://design-pattern.ru/patterns/data-mapper.html
> Я нихрена не понимаю предназначения файлов
Маппер загружает/сохраняет объекты-сущности в базу данных. Потому он и маппер, что занимается отображением (сопоставлением) графа (набора) объектов на таблицы в базе данных.
Ты можешь написать упрощенный пример кода и показать и я скажу что там не так.
> Или я чего-то не понимаю?
Для того чтобы повысить ранг тебе не нужен array_search вот то я имел в виду. У тебя есть объект-работник, ты можешь вызвать на нем любой метод но вместо этого ты ищешь его ключ в массиве, потом по ключу достаешь этот же самый объект. Зачем?
>>447686
> Качество, конечно, изначально нужно высокое, потому что проект будет масштабироваться до общегородского и, в пределе, общероссийского уровня,
Тогда надо перепиливать готовую CMS или писать свое на фреймворке.
> вроде даже с начальными знаниями языка это всё возможно?
Возможно но качество не будет высокое
> Выходит, там часов на 20-30 работы для профессионала?
на российском фрилансе 1000 р в час не платят, так что думаю оценку анон взял с потолка.
> толковым братишкой
> скиллов не хватает
Гм
> margin-right:-5px;
Это костыль. Он полагается на то, то ширина пробела равна 4px . С чего бы вдруг? То, что в твоем браузере это 4px не значит, что на всех других устройствах и браузерах это так же.
Я советую избавиться от пробела как-то по другому, например используя float или что-то еще из этой статьи http://css-live.ru/articles/zagadochnye-otstupy-mezhdu-inlajn-blokami.html
> span {
Этот стиль применяется ко всем спанам на странице. Твой переключатель по задумке должен вставляться на любую страницу и не должен ломать там верстку. Исправь, чтобы стили применялись только к переключателю.
По поводу тени мне кажется это выглядит более похоже:
box-shadow: inset 0px 3px 6px 0px rgba(0,0,0, 0.15)
А то с 0.05 тень какая-то совсем бледная.
А так, вообще, неплохо.
https://github.com/someApprentice/Vector-Com
Пока здесь только сделано одна функция. Завтра, а может даже сегодня, будет больше.
Еще, если у меня не возникнет проблем, то я сразу сделаю код с закрытыми параметрами. Я уже знаю как это сделать, поэтому думаю проблем не будет.
Перед тем как приступить у меня есть еще пару вопросов:
>>447932
>>447914
> можно даже сделать метод получитьРаботниковОпределенногоТипа(тип)
Если ты обратил внимание то наверно заметил, что я не стал разделять функцию удаления 40% сотрудников на отдельные подфункции. Просто я не знаю как понять где стоило бы написать все одной функцией, а где разделить на подфункции.
>Ну можно еще сделать функцию, принимающую массив увольняемых и обходящую его циклом.
А можно сделать такую функцию чтобы проверила что мы в нее передаем и дальше уже решала как удалять? Так правильно будет?
Забыл еще копипасту на индексной странице исправить. Завтра исправлю.
> if ($creditBalance >= 5000) {
Баланс надо проверять после того как банк начислил проценты. А то ты проверил что он меньше 5000, банк добавил проценты и оказалось что уже больше.
Надо сначала добавить проценты и комиссию, а потом делать проверку.
>>447910
Я тебе еще советую поменять все публичные свойства на непубличные и использовать доступ только через методы. Это делает код надежнее за счет инкапсуляции (свойства спрятаны внутри класса и только он имеет к ним прямой доступ).
https://ru.wikipedia.org/wiki/%D0%98%D0%BD%D0%BA%D0%B0%D0%BF%D1%81%D1%83%D0%BB%D1%8F%D1%86%D0%B8%D1%8F_(%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5)#PHP5
> $this->salary + ($this->salary × 0.25);
используй умножение на 1.25
>>447943
У тебя сейчас
if () {
1 строка
} elseif () {
много строк
} else {
1 строка
}
переверни if так, чтобы «много строк» шли после if.
> return true;
>\t\t\t\t\tbreak;
return выходит из функции и из всех циклов в ней.
> "неподходит"
Лучше true/false. Это же робот будет проверять.
Результаты тестов выводи так чтобы ожидаемый результат был малозаметен (1 строка), а несовпадение хорошо заметно.
> if ($creditBalance >= 5000) {
Баланс надо проверять после того как банк начислил проценты. А то ты проверил что он меньше 5000, банк добавил проценты и оказалось что уже больше.
Надо сначала добавить проценты и комиссию, а потом делать проверку.
>>447910
Я тебе еще советую поменять все публичные свойства на непубличные и использовать доступ только через методы. Это делает код надежнее за счет инкапсуляции (свойства спрятаны внутри класса и только он имеет к ним прямой доступ).
https://ru.wikipedia.org/wiki/%D0%98%D0%BD%D0%BA%D0%B0%D0%BF%D1%81%D1%83%D0%BB%D1%8F%D1%86%D0%B8%D1%8F_(%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5)#PHP5
> $this->salary + ($this->salary × 0.25);
используй умножение на 1.25
>>447943
У тебя сейчас
if () {
1 строка
} elseif () {
много строк
} else {
1 строка
}
переверни if так, чтобы «много строк» шли после if.
> return true;
>\t\t\t\t\tbreak;
return выходит из функции и из всех циклов в ней.
> "неподходит"
Лучше true/false. Это же робот будет проверять.
Результаты тестов выводи так чтобы ожидаемый результат был малозаметен (1 строка), а несовпадение хорошо заметно.
Теперь про оптимизации. Мы тут много раз режем строки с помощью mb_substr. Вообще. это не очень эффективно.
Конечно имя файла вряд ли будет большое, и вряд ли мы столкнемся с тем случаем, что скорость будет низкая, но чтобы размять мозги давай немного оптимизируем и усложним код.
Если подумать, то нам незачем резать строки на части. Ведь мы всегда откусываем только символы с начала строки. Раз так, вместо откусывания символов мы можем передавать в функицю дополнительно число — сколько символов в начале надо пропустить.
То есть вместо того чтобы вызывать функцию с обрезанными строками:
>return match(mb_substr($mask, 1), mb_substr($name, 1));
Можно просто передавать туда единички, мол, пропусти один символ в начале.
Далее, если ты это сделаешь, ты заметишь возможность для второй оптимизации. Если в начале имени и маски идут не-звездочки то нам незачем делать рекурсию. Нам достаточно увеличить номера текущих символов на 1 и продолжить сравнение.
Замени для тех случаев, когда в начале не звездочка, рекурсию на цикл.
Ну и третье изменение. Рекурсия это конечно хорошо, но на практике глубокая рекурсия работает неэффективно. В компилируемых языках компилятор умеет заменять хвостовую рекурсию (это когда функция заканчивается на return + рекурсивный вызов) на цикл, но php так не умеет. Вместо этого он просто ограничивает глубину вызовов и выдает ошибку при ее превышении, чтобы ты не писал слишком глубокие вызовы.
Избавься от рекурсии в функции, используя стек (в качестве стека подойдет массив). Стек — это структура данных, в которую можно добавлять сверху и снимать значения.
Вот может эти ссылки помогут (может нет конечно):
https://ru.wikipedia.org/wiki/%D0%A0%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D1%8F
https://ru.wikibooks.org/wiki/%D0%A0%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D1%8F
Теперь про оптимизации. Мы тут много раз режем строки с помощью mb_substr. Вообще. это не очень эффективно.
Конечно имя файла вряд ли будет большое, и вряд ли мы столкнемся с тем случаем, что скорость будет низкая, но чтобы размять мозги давай немного оптимизируем и усложним код.
Если подумать, то нам незачем резать строки на части. Ведь мы всегда откусываем только символы с начала строки. Раз так, вместо откусывания символов мы можем передавать в функицю дополнительно число — сколько символов в начале надо пропустить.
То есть вместо того чтобы вызывать функцию с обрезанными строками:
>return match(mb_substr($mask, 1), mb_substr($name, 1));
Можно просто передавать туда единички, мол, пропусти один символ в начале.
Далее, если ты это сделаешь, ты заметишь возможность для второй оптимизации. Если в начале имени и маски идут не-звездочки то нам незачем делать рекурсию. Нам достаточно увеличить номера текущих символов на 1 и продолжить сравнение.
Замени для тех случаев, когда в начале не звездочка, рекурсию на цикл.
Ну и третье изменение. Рекурсия это конечно хорошо, но на практике глубокая рекурсия работает неэффективно. В компилируемых языках компилятор умеет заменять хвостовую рекурсию (это когда функция заканчивается на return + рекурсивный вызов) на цикл, но php так не умеет. Вместо этого он просто ограничивает глубину вызовов и выдает ошибку при ее превышении, чтобы ты не писал слишком глубокие вызовы.
Избавься от рекурсии в функции, используя стек (в качестве стека подойдет массив). Стек — это структура данных, в которую можно добавлять сверху и снимать значения.
Вот может эти ссылки помогут (может нет конечно):
https://ru.wikipedia.org/wiki/%D0%A0%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D1%8F
https://ru.wikibooks.org/wiki/%D0%A0%D0%B5%D0%BA%D1%83%D1%80%D1%81%D0%B8%D1%8F
>Это читал?
>Ты читал статью и пример кода по ссылке? Читал это?
Да, перечитал все это до того, как писать вопросы.
>Ты можешь написать упрощенный пример кода и показать и я скажу что там не так.
Договорились, няша.
В твоем коде антипаттерн на антипаттерне.
> Как мне этот самый "page=1" запилить при первом переходе?
C помощью if
Если ты делаешь задачу про сайт абитуринтов, прочти новую версию задачи с пояснениями и комментариями: https://github.com/codedokode/pasta/blob/master/student-list.md
>>447973
> Просто я не знаю как понять где стоило бы написать все одной функцией, а где разделить на подфункции.
Хорошо, пусть пока не разделяется.
> А можно сделать такую функцию чтобы проверила что мы в нее передаем и дальше уже решала как удалять? Так правильно будет?
Нет. Удобнее когда у функции четко определено что она получает на вход (и что возвращает). Если она принимает что угодно то ты не заметишь ошибки при передаче неправильного значения.
Ну и плюс логика функции замусоривается кодом преобразования аргументов.
Хотя в библиотеках вроде jQuery ты можешь увидеть такие функции, мне это не очень нравится и в учебном задании конечно так делать нельзя.
Я еще советую переименовать:
makeEmployeesArray → getEmployeees
unsetEmployee → fireEmployee
И поменять public свойства на закрытые.
В твоем коде антипаттерн на антипаттерне.
> Как мне этот самый "page=1" запилить при первом переходе?
C помощью if
Если ты делаешь задачу про сайт абитуринтов, прочти новую версию задачи с пояснениями и комментариями: https://github.com/codedokode/pasta/blob/master/student-list.md
>>447973
> Просто я не знаю как понять где стоило бы написать все одной функцией, а где разделить на подфункции.
Хорошо, пусть пока не разделяется.
> А можно сделать такую функцию чтобы проверила что мы в нее передаем и дальше уже решала как удалять? Так правильно будет?
Нет. Удобнее когда у функции четко определено что она получает на вход (и что возвращает). Если она принимает что угодно то ты не заметишь ошибки при передаче неправильного значения.
Ну и плюс логика функции замусоривается кодом преобразования аргументов.
Хотя в библиотеках вроде jQuery ты можешь увидеть такие функции, мне это не очень нравится и в учебном задании конечно так делать нельзя.
Я еще советую переименовать:
makeEmployeesArray → getEmployeees
unsetEmployee → fireEmployee
И поменять public свойства на закрытые.
Хорошо, но пока не идеально.
Я добавил несколько тестов: http://ideone.com/kWOl8S
Некоторые проваливаются.
> мне сделать так что ли:
нет. Сделать так
if () {
1 строка
}
if () {
1 строка
}
много строк;
Всё, завтра постараюсь в этом разобраться. Сейчас я уже устал и хочу спать, посмотрю первую серию новой анимы попивая молоко с медом. Вообще когда я читаю твои задачи, мне тяжело воспринимать то, как сделать казалось бы простые исправления. Я в своём коде в этом, толком бывает не могу разобраться, это ведь нормально и дело просто в том, что у меня мало практики? Со временем буду щелкать многоуровневые ветвления и вложенные циклы с рекурсией как простую задачу на массивы из учебника сейчас?
Ну рекурсия действительно сложная штука, чтобы ее представлять в уме. Надо не пытаться построить всю цепочку вызовов, а научиться описывать задачу так, чтобы она была разбита на более мелкие части вроде:
маска соответствует имени файла
ЕСЛИ
первые символы совпадают
И
хвост маски соответствует хвосту имени файла (рекурсия)
Насчет оптимизаций, да, начинающему в них сложно разобраться, но я думаю, если ты помучаешься, то в итоге придешь к решению. Если что, я дам какую-нибудь подсказку. Это вообще задание больше для того, чтобы ты более свободно оперировал циклами и ветвлениями.
> Со временем буду щелкать многоуровневые ветвления и вложенные циклы с рекурсией как простую задачу на массивы из учебника сейчас?
Со временем будет легче. Но вообще, лучше писать код так, чтобы сильно вложенных ветвлений не было.
копипаста
вывод html через echo
парсинг входных параметров в том же месте где и вывод html
preg_replace для странных манипулиций с url
Допустим у тебя средних размеров приложение, в нем 5000 файлов с 5000 классами.
> Вот не пойму нахрена все-таки нужны приватные, защищенные свойства
Публичное свойство можно менять из любого места кода. Из любого из 5000 файлов. Допустим ты хочешь разрешить в него записывать только целые числа от 1 до 5. Как это сделать? Обойти все 5000 файлов. найти 100 мест где меняется это свойтсво и дописать туда 100 if?
В случае с приватным свойством решение очевидно: исправить метод, меняющий это свойство. Нам достаточно исправить лишь 1 класс из 5000.
Вторая причина — это делает код более понятным. Я программист, я хочу использовать чей-то чужой класс. Я смотрю какие методы публичные и понимаю, что их можно использовать, а приватные — нельзя, потому я на них не обращаю внимания и не трачу время. А без этого мне пришлось просмотреть бы все методы.
В общем, private/protected это ограничения, которые документируют код и мешают программисту сделать ошибку. Чем больше ограничений, тем лучше код.
Безопасность тут не при чем. Просто это защищает программиста от ошибок.
Условно говоря класс с публичными свойствами это пульт с кучей кнопок, причем при нажатии некоторых он взрывается вместе с тобой. А класс с ограничениями это пульт на который выведены только нужные кнопки, а ненужные спрятаны внутри.
> что все оно как-то избыточно замудрено
просто в твоем учебнике это плохо объясняется. В ООП все стройно и логично.
> Но я не представляю с какой стати мне должно взбрести в голову перезаписывать пароль без надобности и без четкого понимания что я делаю.
Это если у тебя 3 класса которые ты сам написал и помнишь что можно делать, а что нельзя. А если 5000 классов которые писал не ты? Ограничения защищают тебя от ошибки.
Автор класса определяет, что другие программисты могут делать с его классом, а что не могут. Запрещая лезть в потроха класса напрямую, он может гарантировать корректную работу и то, что класс содержит правильные данные. То есть он задает правила, как его класс можно использовать и как нельзя.
> Потом еще наследование.
Наследование используется для 2 вещей:
— сделать улучшенную/измененную версию какого-то класса. например Машина ездит (есть метод ехатьВТочкуX ), а Грузовик ездит + может перевозить груз (есть методы положитьГруз и вынутьГруз).
— объединить объекты, которые являются модификацией одного и того же. Например,
— Танк может ездить и стрелять
— Грузовик может ездить и перевозить груз
У них есть много общего: они оба являются средствами передвижения, оба умеют ездить (то есть у них есть координаты на карте, может быть скорость, запас топлива, еще что-то). Логично наследовать их от общего предка чтобы показать что это похожие вещи.
> Пост, тред, доска - что от чего они могут или должны наследовать - непонятно
Ничего. Это разные вещи.
При наследовании должно соблюдаться правило подстановки Лисков (это фамилия, а не название животных или существ). То есть потомок класса можно передать/использовать вместо предка и код не должен сломаться.
Если у тебя есть функция, что-то делающая с Машиной, она должна принимать и обрабатывать Грузовик тоже.
Ну и наоборот, если у Машины есть метод ехатьВТочку(точка) то ты не можешь в Грузовике убрать его или поменять число обязательных аргументов, так как в этом случае он станет не совсемстим с машиной.
PHP в части случаев обнаруживает такие ошибки и отказывается создавать класс-наследник, если ты не соблюдаешь правило подстановки Лисков.
Ладно, доделал я свои костыли, вроде работает, но хочется сделать правильно.
$data = array ('param1' => $_GET['param1'], 'param2' => $_GET['param2'], 'param3' => $_GET['param3'], ...);
$link = 'index.php?' . http_build_query($data);
Так нормально?
Но получается неудобно в том плане, что массив $data надо будет каждый раз объявлять перед построением URL, если я захочу там поменять какое-то значение на нужное. Сделать через функцию наверное, можно, но не пойму как - опять дофига входных параметров получается.
>Ты можешь написать упрощенный пример кода и показать и я скажу что там не так.
Оп, как и договаривались выкладываю простой тестовый проект, который так и не заработал. Все мои вопросы в комментариях, также отметил предположительную ошибку. Поясни, плз, по этим вопросам и другим проблемам.
http://dropmefiles.com/1ziFj
http://ideone.com/lRfSuD
Если ты пока не разобрался с гитхабом, можно файлы постить на gist.github.com, они там добавляются перетаскиванием и по моему даже регистрации не требуется. Всяко удобнее чем с архивами возиться.
> // Также не понимаю, как использовать autoload//
Автозагрузчик это функция которая вызывается при обращении к отсутствующему классу. Если она подключит нужный файл с классом, то выполнение программы продолжается, если нет то ошибка. Она позволяет избавиться от подключеняи классов вручную.
Мануал
http://php.net/manual/ru/function.spl-autoload-register.php
http://php.net/manual/ru/language.oop5.autoload.php
http://habrahabr.ru/post/136761/
> // Не догоняю, что здесь происходит //
Не копипасть код из других проектов, а пиши сам с нуля, тогда проблемы не будет.
> class Name
Странное название. Класс представляет собой информацию об имени или все же о человеке? Если второе то и называть надо соответственно. Правильные названия классов и функций это очень важно, чтобы код было легко понять.
> $STH->bindValue(":id", $this->DBH->lastInsertId()+1); // ОШИБКА ВОТ ТУТ//
lastInsertId можно вызывать только после вставки записи в базу, а не до. Более того, эта функция возвращает id только для полей которые умебт генерировать эти id (AUTO_INCREMENT). Почитать можно например тут
http://phpclub.ru/mysql/doc/example-auto-increment.html
http://phpclub.ru/mysql/doc/create-table.html (сделай поиск по слову)
http://blog.nagaychenko.com/2011/03/11/%D0%BE%D1%81%D0%BE%D0%B1%D0%B5%D0%BD%D0%BD%D0%BE%D1%81%D1%82%D0%B8-%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D1%8B-last_insert_id-%D0%B8-auto_increment-%D0%B2-mysql/
Если ты слабо знаешь MySQL (ты слабо знаешь) то стоит параллельно порешать задачки на SQL (ссылка в первом посте треда).
Ну и название папки conf наверно не подходит для хранения классов.
А так, ты примерно в правильном направлении движешься.
Если ты пока не разобрался с гитхабом, можно файлы постить на gist.github.com, они там добавляются перетаскиванием и по моему даже регистрации не требуется. Всяко удобнее чем с архивами возиться.
> // Также не понимаю, как использовать autoload//
Автозагрузчик это функция которая вызывается при обращении к отсутствующему классу. Если она подключит нужный файл с классом, то выполнение программы продолжается, если нет то ошибка. Она позволяет избавиться от подключеняи классов вручную.
Мануал
http://php.net/manual/ru/function.spl-autoload-register.php
http://php.net/manual/ru/language.oop5.autoload.php
http://habrahabr.ru/post/136761/
> // Не догоняю, что здесь происходит //
Не копипасть код из других проектов, а пиши сам с нуля, тогда проблемы не будет.
> class Name
Странное название. Класс представляет собой информацию об имени или все же о человеке? Если второе то и называть надо соответственно. Правильные названия классов и функций это очень важно, чтобы код было легко понять.
> $STH->bindValue(":id", $this->DBH->lastInsertId()+1); // ОШИБКА ВОТ ТУТ//
lastInsertId можно вызывать только после вставки записи в базу, а не до. Более того, эта функция возвращает id только для полей которые умебт генерировать эти id (AUTO_INCREMENT). Почитать можно например тут
http://phpclub.ru/mysql/doc/example-auto-increment.html
http://phpclub.ru/mysql/doc/create-table.html (сделай поиск по слову)
http://blog.nagaychenko.com/2011/03/11/%D0%BE%D1%81%D0%BE%D0%B1%D0%B5%D0%BD%D0%BD%D0%BE%D1%81%D1%82%D0%B8-%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D1%8B-last_insert_id-%D0%B8-auto_increment-%D0%B2-mysql/
Если ты слабо знаешь MySQL (ты слабо знаешь) то стоит параллельно порешать задачки на SQL (ссылка в первом посте треда).
Ну и название папки conf наверно не подходит для хранения классов.
А так, ты примерно в правильном направлении движешься.
Если бы я не глянул чужой код, то нужно было бы потратить в несколько раз больше времени на изучение каждого нюанса.
А все-таки ты не ответил на главные вопросы - что происходит с функцией setFields и как исправить ошибку, чтобы отправка имени заработала.
>Странное название. Класс представляет собой информацию об имени или все же о человеке?
Об имени, это же тестовая страничка где можно ввести одно только имя. Если что, я понимаю, для чего нужен этот класс.
>Если ты слабо знаешь MySQL (ты слабо знаешь)
А вот сам SQL я неплохо знаю - подрабатывал програмером mssql в крупной компании, готовил им аналитические отчеты. Давно это было, правда, но основное не забыто.
урок по древовидным структурам в БД читал? https://gist.github.com/codedokode/10539720
>>448135
> Почему это срабатывает (выводит приватное свойство предка при обращении в наследнике)?
Потому что доступ проверяется по тому, где объявлен метод, а не где он вызван.
То есть если у тебя свойство private то обращаться к нему можно из методов описанных в том же самом классе (то есть расположенных между открывающей закрывающей скобкой класса), а откуда и как вызван метод, неважно.
Вот более сложный пример c анонимной функцией:
class A {
private $x;
public function createCallback() {
// создаем анонимную функцию
return function() {
$this->x = 1;
}
}
}
$a = new A;
$callback = $a->createCallback( );
$callback( ); // все должно быть ок
Мы вызываем анонимную функцию снаружи класса, но она все равно имеет доступ к приватному свойству так как описана внутри класса. Главное где описан код, а не откуда он вызван (хотя в сложных ситуациях я не уверен что это правило соблюдается, если так то плохо конечно, потому что должно соблюдаться, но Php в этом плане богат на странности).
Суть private в том что доступ к нему имеет только программист, написавший класс. Соответственно обращаться к таким свойствам можно только из кода описанного в этом классе.
урок по древовидным структурам в БД читал? https://gist.github.com/codedokode/10539720
>>448135
> Почему это срабатывает (выводит приватное свойство предка при обращении в наследнике)?
Потому что доступ проверяется по тому, где объявлен метод, а не где он вызван.
То есть если у тебя свойство private то обращаться к нему можно из методов описанных в том же самом классе (то есть расположенных между открывающей закрывающей скобкой класса), а откуда и как вызван метод, неважно.
Вот более сложный пример c анонимной функцией:
class A {
private $x;
public function createCallback() {
// создаем анонимную функцию
return function() {
$this->x = 1;
}
}
}
$a = new A;
$callback = $a->createCallback( );
$callback( ); // все должно быть ок
Мы вызываем анонимную функцию снаружи класса, но она все равно имеет доступ к приватному свойству так как описана внутри класса. Главное где описан код, а не откуда он вызван (хотя в сложных ситуациях я не уверен что это правило соблюдается, если так то плохо конечно, потому что должно соблюдаться, но Php в этом плане богат на странности).
Суть private в том что доступ к нему имеет только программист, написавший класс. Соответственно обращаться к таким свойствам можно только из кода описанного в этом классе.
Вот, проверил что работает: http://ideone.com/rxFtSq
>>448147
> $this->salary = getSalary($salary);
у тебя нет функции getSalary. Есть такой метод в классе Employee, но методы можно вызывать только на объекте, то есть
$employee->getSalary(...);
или $this->getSalary(....); если ты хочешь вызвать этот метод на том же самом объекте который создается.
>>448174
> Если бы я не глянул чужой код, то нужно было бы потратить в несколько раз больше времени на изучение каждого нюанса.
Возможно что надо действительно потратить время, чтобы разобраться. В любом случае копипастить код не надо. Это тебе не дает никаких знаний, надо чтобы ты мог сам его написать. Нет никакого смысла переписывать чужой код чуть поменяв названия.
> - что происходит с функцией setFields и как исправить ошибку, чтобы отправка имени заработала.
Надо написать свою функцию с нуля, принцип действия которой ты понимаешь.
Ну и в качестве подсказки — ты читал урок по работе с формами? https://github.com/codedokode/pasta/blob/master/forms.md
> Об имени, это же тестовая страничка где можно ввести одно только имя. Если что, я понимаю, для чего нужен этот класс.
Я думаю все же о человеке. Там например еще id есть кроме имени.
> А вот сам SQL я неплохо знаю - подрабатывал програмером mssql в крупной компании,
Это хорошо. Тогда у тебя 20 минут займет решить первую задачу. заодно изучишь особенности MySQL которые ты не знал, AUTO_INCREMENT это же фишка MySQL, а MSSQL для этого по моему используется тип поля IDENTITY.
Вот, проверил что работает: http://ideone.com/rxFtSq
>>448147
> $this->salary = getSalary($salary);
у тебя нет функции getSalary. Есть такой метод в классе Employee, но методы можно вызывать только на объекте, то есть
$employee->getSalary(...);
или $this->getSalary(....); если ты хочешь вызвать этот метод на том же самом объекте который создается.
>>448174
> Если бы я не глянул чужой код, то нужно было бы потратить в несколько раз больше времени на изучение каждого нюанса.
Возможно что надо действительно потратить время, чтобы разобраться. В любом случае копипастить код не надо. Это тебе не дает никаких знаний, надо чтобы ты мог сам его написать. Нет никакого смысла переписывать чужой код чуть поменяв названия.
> - что происходит с функцией setFields и как исправить ошибку, чтобы отправка имени заработала.
Надо написать свою функцию с нуля, принцип действия которой ты понимаешь.
Ну и в качестве подсказки — ты читал урок по работе с формами? https://github.com/codedokode/pasta/blob/master/forms.md
> Об имени, это же тестовая страничка где можно ввести одно только имя. Если что, я понимаю, для чего нужен этот класс.
Я думаю все же о человеке. Там например еще id есть кроме имени.
> А вот сам SQL я неплохо знаю - подрабатывал програмером mssql в крупной компании,
Это хорошо. Тогда у тебя 20 минут займет решить первую задачу. заодно изучишь особенности MySQL которые ты не знал, AUTO_INCREMENT это же фишка MySQL, а MSSQL для этого по моему используется тип поля IDENTITY.
http://ideone.com/73IDN6
http://ideone.com/Z6SOLl
>$employee->getSalary(...);
>
>или $this->getSalary(....); если ты хочешь вызвать этот метод на том же самом объекте который создается.
>
Спасибо. Какой же я слепошарый.
Прочитал еще раз, с структурой БД особых вопросов пока нет, мне бы понять, как это все на страничке правильно расположить. Тут, как я понимаю, без яваскрипта уже не обойтись, ведь иначе не реализовать нормально ответы на комментарии, а не к основной ветке?
Алсо, еще тупой вопрос, ты тут писал >>446323
>Ты можешь скопировать библиотеки себе на сервер, зачем что-то грузить из интернета?
Это как вообще делается?
>Это тебе не дает никаких знаний, надо чтобы ты мог сам его написать
Дело в том, что я здесь особо не ищу знаний, а просто хочу решить свою задачу, которая возникла по мере реализации моего хобби. Поэтому мне главное понять основы на примере других, а потом я смогу смасштабировать все под свои требования.
А вот урок с формами пропустил как-то. Читну его скоро.
>Тогда у тебя 20 минут займет решить первую задачу
У меня ушло больше времени, и я не до конца понял, о каких взаимных лайках идет речь, поэтому не сделал эту колонку. Остальное вот (таблицы на скринах):
>SELECT names.id, names.name, COUNT(likes.id) AS obtained, temp.cnt AS put FROM names
>LEFT JOIN likes ON likes.liketoID = names.id
>LEFT JOIN (SELECT fk, COUNT(fk) AS cnt FROM likes GROUP BY fk) temp ON names.id = temp.fk
>GROUP BY likes.liketoID
>ORDER BY names.id
Один анон сделал так: он поставил радиокнопку перед каждым комментарием и внизу, и ты можешь выбрать на какой отвечаешь. Сообразительный анон, мне как-то такая мысль в голову не приходила, а ведь этот способ заработает даже на браузерах 20 летней давности и на любых устройствах.
За счет label и средств CSS3 ты можешь сделать, чтобы комментарий выбирался кликом и подсвечивался, а радиокнопку спрятать (но лучше не прятать чтобы старые браузеры тоже работали).
Ну или яваскрипт, да.
> Это как вообще делается?
заходишь на официальный сайт и скачиваешь. Что за библиотека? как ты ее подключал?
>Что за библиотека? как ты ее подключал?
Никак не подключал. Я хочу сделать поле для ввода даты, нашел такое, например: http://ruseller.com/lessons.php?rub=32&id=144
или такое: http://strawberry.goodgirl.ru/forum/topic/2906/
Как мне это заставить работать, если у меня нет инета на сервере?
Алсо, может, я вообще неправильно делаю и есть способ проще?
Вообще, это плохая идея подключать яваскрипт-библиотеки не зная яваскрипт.
Для подключения указанных библиотек интернет не нужен, то есть ты можешь скачать их и выложить на сервер, так же как ты выкладываешь css и html файлы.
например здесь
http://strawberry.goodgirl.ru/forum/topic/2906/
исплоьзуется библиотека mootools (сайт гуглится) и файл calendar.js который очевидно приложен в архиве к посту.
http://jsfiddle.net/dom3nm0v/1/ не понимаю, почему я не могу сделать на всю ширину блок при маленьком разрешении? я даже не могу сдвинуть его к краю, какие-то невидимые границы мне не дают, хотя я уже у всего чего можно указал абсолютную позицию и координаты, но блоки вообще никак не реагируют. Алсо, почему при display:block кнопки продолжают находиться на одной строке, пока им явно не укажешь ширину 100%?
http://ideone.com/XZ7rKo
Не понял. Что не так?
Employee -- абстрактный класс всех сотрудников, $employees -- свойство класса Depsrtment.
в этой задаче не обязательно создавать семейство департаментов. В принципе, ведь все департаменты делят общий функционал? То есть выводят общую сумму денег, объем кофе, кол-во страниц. Просто отличаются своим названием и сотрудниками. Поэтому можно создать один класс Департамент и в нем определить все эти методы. Ты зря в конструкторе определяешь з/п, кофе и т.д. Их нужно посылать как аргументы, иначе весь смысл конструктора теряется. Я так понимаю, ты хочешь упростить процесс создания объекта, но это лучше сделать, создав отдельную вспомогательную функцию. Ну и все твои геттеры неверны. Это должно быть что-то вроде:
public function getSalary() {
return $this->salary;
}
А у тебя в геттер посылается какой-то аргумент, и внутри происходит непонятно что.
public function getCoffee($coffee) {
if ($this->isBoss == true) {
$result = $coffee * 2;
}
return $result;
}
А что если оператор условия не выполнится? Естественно ошибка, что не существуют перемнной $result.
Пересмотри свой код, и еще раз подумай над архитектурой. Почитай про то, что такое объекты и $this.
Там ооооооооооочень много копипасты. Посаветуй как избавиться.
>Потому что доступ проверяется по тому, где объявлен метод, а не где он вызван.
>То есть если у тебя свойство private то обращаться к нему можно из методов описанных в том же самом классе (то есть расположенных между открывающей закрывающей скобкой класса), а откуда и как вызван метод, неважно.
Понятно, везде бы так писали.
Спасибо.
>Ты зря в конструкторе определяешь з/п, кофе и т.д. Их нужно посылать как аргументы, иначе весь смысл конструктора теряется.
Так эти значения зависят от двух параметров: от ранга сотрудника и от того, является ли он боссом. Их-то мы и сообщаем конструктору, а он на основании этих данных уже решает, что делать.
>Я так понимаю, ты хочешь упростить процесс создания объекта,
Ага.
>но это лучше сделать, создав отдельную вспомогательную функцию.
Этот момент не понял. Что она должна делать?
Алсо, мои геттеры -- совсем не геттеры.
Вот код посвежее, если надо: http://ideone.com/STbahh
Пропустил твоё сообщение, бро.
>Тогда надо перепиливать готовую CMS или писать свое на фреймворке.
Фреймворк был бы неплох, конечно, чтобы потом, когда дозреем до своей CMS, потом туда это всё перевести, но где взять хорошего программиста? Денег же нет ни хрена, 30к даже сложно найти сейчас на это. Но чувствую, что придётся искать деньги.
>на российском фрилансе 1000 р в час не платят, так что думаю оценку анон взял с потолка.
Как не платят? Там от 10$ до 30$ за час работы, как я погляжу.
>> толковым братишкой
>> скиллов не хватает
>Гм
Ну он только учится ещё, но многое умеет. Мы просто замахнулись с ним на те тесты, которые есть на proprofs.com, там реально годно и удобно. Хочется же сделать всё идеально, чтобы было удобно, вот ему для этого не хватает скиллов, он сейчас окунулся в изучение. Но время уходит, я думал это всё до конца учебного года запустить, до мая, но теперь вряд ли.
Ясно. Если ты не ищешь знаний, я тоже не смогу помочь. Здесь мы изучаем php начиная от простых задач и переходя к сложным. Когда я отвечал на вопросы, я думал что ты проходишь учебник и у тебя есть какой-то базовый уровень знаний (то есть ты сделал все предыдущие задания), а также ты пишешь код с нуля. Соответственно я в таких случаях комментирую написанный код, даю советы и замечания.
Если ты скопировал где-то код, то вопросы по нему лучше задавать автору кода. Ну или может кто-то мимопроходящий захочет разобраться.
По SQL задаче, зря я наверно предложил тогда тебе решать ее, я думал что ты уроки проходишь и хочешь лучше изучить MySQL. Ну надеюсь, ты хотя бы что-то полезное для себя извлек. Там можно обойтись без вложенного подзапроса (достаточно 2 джойнов) и твое решение не считает число взаимных лайков.
Мне кажется, это не совсем верно, что данные для инициализации так вшиты в сам код, если потребуется их изменить, то надо будет лезть в сам код и все менять. А в идеале, твое приложение или библиотека предоставляет некоторое множество функций, вызывая которые ты можешь изменять состояние объекта. Поэтому я думаю эти данные должны прямо поступать в конструтор, т.е.: __construct($salary, $rank, $coffe, $reports, $boss=false). Но писать код, который будет создавать объект такого класса не совсем удобно (придется писать 100 раз new Employee()). Есть паттерн "фабричный метод", который правильно создает объекты. Но в данной задаче можно обойтись обычной функцией (сорт оф фабрика). В которой можно задать вручную данные для инициализации.
А если понадобится у каких-то рабочих изменить какие-то условия, например при расчете антикризисных ситуаций, то тут на помощь должны прийти те самые функции, изменяющие состояние объекта
Тредик все ещё ведет некомпетентная пхп-макака с вахтер-резус статусом? :3 У меня для вас плохие новости, друзья. Не слушайте этого имбецила, лучше читайте книжки/доки, навроде:
http://php.net/manual/en/langref.php
http://php.net/manual/en/
Серьёзно, вы проебете кучу времени на этот ниадыкват, а тут вам и коротнеько язычок и либки. Из фреймворков самое популярное легко гуглиться: симфония, вордпресс.
Что нужно знать: пхп - всего лишь препроцессор и интерпритатор кода, однако в комплекте есть CGI - "сервер" для своих простеньких приложений, тестить.
Для чего-то крупнее простой странички - Apache на линухах.
Из хранилищ - загуглите сами. Подсказка: SQ / Mon / Post.
Дальше сами. Не скучайти в общем.
Мимо_пыхарь_со_стажем.
>>448334
Насчет классов департаментов: нет смысла делать разные классы так как Депараменты никак не различаются. У сотрудников хотя бы зарплата разная, а у департаментов все одинаково.
Насчет передачи зарплаты в конструктор: можно передавать, можно для каждой профессии прописать значения по умолчанию.
> while ($i < 9){
>\t $this->employees[] = new Manager(1, false);
Это в общем неправильно. У тебя депарматент продаж всегда содержит ровно 9 менеджеров. Эти данные лучше задавать снаружи, то есть сделать метод добавления сотрудника и добавлять откуда-то снаружи.
> while ($i < 9){
Тут уместнее цикл for. Он проще читается так как шаг и условия собраны в одном месте.
> public function getSalary($salary) {
Функция судя по названию сообщает чему равна зарплата сотрудника. Но зачем тогда ей передавать аргумент salary? Чтобы узнать зарплату мы должны передать функции зарплату? Где тут логика? Это выглядит примерно так:
(Босс) Иван, какая у тебя зарплата?
(Иван) Какая у меня зарплата?
(Босс) 10 тугриков
(Иван) Моя зарплата 10 тугриков.
надо либо переименовать все либо переделать.
> public function name () {
имя функции начинается с глагола: сделайЧтоТо()
>>448334
Насчет классов департаментов: нет смысла делать разные классы так как Депараменты никак не различаются. У сотрудников хотя бы зарплата разная, а у департаментов все одинаково.
Насчет передачи зарплаты в конструктор: можно передавать, можно для каждой профессии прописать значения по умолчанию.
> while ($i < 9){
>\t $this->employees[] = new Manager(1, false);
Это в общем неправильно. У тебя депарматент продаж всегда содержит ровно 9 менеджеров. Эти данные лучше задавать снаружи, то есть сделать метод добавления сотрудника и добавлять откуда-то снаружи.
> while ($i < 9){
Тут уместнее цикл for. Он проще читается так как шаг и условия собраны в одном месте.
> public function getSalary($salary) {
Функция судя по названию сообщает чему равна зарплата сотрудника. Но зачем тогда ей передавать аргумент salary? Чтобы узнать зарплату мы должны передать функции зарплату? Где тут логика? Это выглядит примерно так:
(Босс) Иван, какая у тебя зарплата?
(Иван) Какая у меня зарплата?
(Босс) 10 тугриков
(Иван) Моя зарплата 10 тугриков.
надо либо переименовать все либо переделать.
> public function name () {
имя функции начинается с глагола: сделайЧтоТо()
> однако в комплекте есть CGI - "сервер" для своих простеньких приложений, тестить.
Ты бы в википедии посмотрел как CGI расшифровывается, болезный.
Когда ты решаешь задачу на ООП, ты должен ответить на вопросы:
— какие есть сущности, для которых мы сделаем классы? (Сотрудник и Департамент)
— какие у них есть свойства (у Сотрудника есть ранг, базовая ставка, профессия, является ли боссом). Потребление кофе или зарплата не являются свойствами так как они вычисляются из других свойств и хранить их не надо.
— что мы хотим от них получить (какие у них должны быть методы). Например мы хотим узнать сколько сотрудник заработал или сколько он пьет кофе. От департамента мы наверно хотим получить сколько всего выпито кофе и заплачено денег.
— как сущности связаны? Очевидно, Сотрудник работает в каком-то Департаменте.
>>448183
Невозможно посчитать производительность труда в департаменте: http://ideone.com/VNVX8z
Босс: Клерк, какая у нас производителность труда?
(Клерк молча падает на пол)
> if(in_array($emp, $this->employees)) {
Надо использовать строгое сравнение. Почитай про сравнение объектов http://php.net/manual/ru/language.oop5.object-comparison.php и мануал по in_array https://php.net/manual/ru/function.in-array.php
> $this->totalCoffeeAmount = 0;
Почему это сделано свойством, а не обычной переменной? оно же больше все равно нигде не используется? Если не используется, зачем его хранить в объекте?
> $emp->setBossStatus(false);
>\t $newBoss = max($analysts);
>\t\t\t\t$newBoss->setBossStatus(true);
Эти манипуляции лучше делать через метод назначитьБосса(новыйБосс) в департаменте. Логично что у Департамента есть метод для назначения босса.
> $newBoss = max($analysts);
не понимаю. max же ищет самое большое значение в массив. Как его вообще можно применять к объектам? Если тебе нужен первый элемент то это $array[0]
> createEmployee($purchaseDep, "Manager", 2, 1, $boss=true);
Присваивание $boss=true это отдельная команда и его надо делать на отдельной строке. Хотя я не понимаю, зачем тут заводить переменную.
> foreach($allDeps as $department) {
> $clonedDeps1[] = clone $department;
Можно было сделать функцию клонирования или даже класс Компания содержащий департаменты. Можно впрочем и так оставить.
Когда ты решаешь задачу на ООП, ты должен ответить на вопросы:
— какие есть сущности, для которых мы сделаем классы? (Сотрудник и Департамент)
— какие у них есть свойства (у Сотрудника есть ранг, базовая ставка, профессия, является ли боссом). Потребление кофе или зарплата не являются свойствами так как они вычисляются из других свойств и хранить их не надо.
— что мы хотим от них получить (какие у них должны быть методы). Например мы хотим узнать сколько сотрудник заработал или сколько он пьет кофе. От департамента мы наверно хотим получить сколько всего выпито кофе и заплачено денег.
— как сущности связаны? Очевидно, Сотрудник работает в каком-то Департаменте.
>>448183
Невозможно посчитать производительность труда в департаменте: http://ideone.com/VNVX8z
Босс: Клерк, какая у нас производителность труда?
(Клерк молча падает на пол)
> if(in_array($emp, $this->employees)) {
Надо использовать строгое сравнение. Почитай про сравнение объектов http://php.net/manual/ru/language.oop5.object-comparison.php и мануал по in_array https://php.net/manual/ru/function.in-array.php
> $this->totalCoffeeAmount = 0;
Почему это сделано свойством, а не обычной переменной? оно же больше все равно нигде не используется? Если не используется, зачем его хранить в объекте?
> $emp->setBossStatus(false);
>\t $newBoss = max($analysts);
>\t\t\t\t$newBoss->setBossStatus(true);
Эти манипуляции лучше делать через метод назначитьБосса(новыйБосс) в департаменте. Логично что у Департамента есть метод для назначения босса.
> $newBoss = max($analysts);
не понимаю. max же ищет самое большое значение в массив. Как его вообще можно применять к объектам? Если тебе нужен первый элемент то это $array[0]
> createEmployee($purchaseDep, "Manager", 2, 1, $boss=true);
Присваивание $boss=true это отдельная команда и его надо делать на отдельной строке. Хотя я не понимаю, зачем тут заводить переменную.
> foreach($allDeps as $department) {
> $clonedDeps1[] = clone $department;
Можно было сделать функцию клонирования или даже класс Компания содержащий департаменты. Можно впрочем и так оставить.
> global $allTimes;
Глобальные переменные зло так как они делают поведение функции сложнопредсказуемым и добавляют побочные эффекты. Избавься от них. Функция должна возвращать результаты через return, а не обходными путями.
> $pathDone = [];
> $time = 0;
Почему ты пишешь это перед функцией? Как то у тебя код получается разбит на куски между функциями.
> {$transportName[$paths[$fastestPath[$i-1]][$fastestPath[$i]]['by']]}
Сделай дополнительные переменные, тяжело читать же такую длинную колбасу.
> $values
Надо переименовать в pathInfo или как-то так. values ничего не значит.
Я как-то пробовал, для HTML/CSS там есть интересные функции, но тормозит.
>>448244
> 11 задача
Вертикальные линии-разделители у тебя шириной 2px а надо 1px.
> span {
Этот стиль применится ко всем спанам на странице. Сделай, чтобы твои стили не конфликтовали при вставке переключателя на страницу (то есть добавь уникальный класс).
Ну и еще. Ты скрыл радиокнопку через display: none. Если ее скрыть каким-то другим способом, чтобы бразуер думал что она видна, то в фаерфоксе можно будет переключать кнопки стрелками на клавиатуре.
> почему я не могу сделать на всю ширину блок при маленьком разрешении? я
Ты не пробовал посмотреть инспектором (Ctrl + Shift + I)? Он пкоазывает и размеры элемента, и примененные стили, и вычисленииые значения свойств.
И я не очень понял о каком блоке речь. Если ты про белые поля справа и слева то они там потому что ты их сам добавил, посмотри CSS внимательно инспектором.
> Алсо, почему при display:block кнопки продолжают находиться на одной строке, пока им явно не укажешь ширину 100%?
Может этот стиль переопредлен другим, может быть на них стоит float или абс. поз. Ты инспектором смотрел?
Я как-то пробовал, для HTML/CSS там есть интересные функции, но тормозит.
>>448244
> 11 задача
Вертикальные линии-разделители у тебя шириной 2px а надо 1px.
> span {
Этот стиль применится ко всем спанам на странице. Сделай, чтобы твои стили не конфликтовали при вставке переключателя на страницу (то есть добавь уникальный класс).
Ну и еще. Ты скрыл радиокнопку через display: none. Если ее скрыть каким-то другим способом, чтобы бразуер думал что она видна, то в фаерфоксе можно будет переключать кнопки стрелками на клавиатуре.
> почему я не могу сделать на всю ширину блок при маленьком разрешении? я
Ты не пробовал посмотреть инспектором (Ctrl + Shift + I)? Он пкоазывает и размеры элемента, и примененные стили, и вычисленииые значения свойств.
И я не очень понял о каком блоке речь. Если ты про белые поля справа и слева то они там потому что ты их сам добавил, посмотри CSS внимательно инспектором.
> Алсо, почему при display:block кнопки продолжают находиться на одной строке, пока им явно не укажешь ширину 100%?
Может этот стиль переопредлен другим, может быть на них стоит float или абс. поз. Ты инспектором смотрел?
> while ($i < 9)
Ты используешь переменную до того как ее создал. Всегда в начале должно идти $i = ... а потом ее использование.
>>448298
Если ты про код в этом файле https://github.com/someApprentice/Vector-Com/blob/master/Classes/Direction.php то решение убрать слишком абстрактные методы которые используются лишь один раз. То есть вместо того чтобы делать метод повышения зарплаты любому типу работников, можно сделать 3 конкретных метода: антикризисный метод 1, 2 и 3.
> //Здесь идет очень много копипасты, и я не могу сообразить как с ней бороться,
Вообще можно было не делать абстрактные методы типа setSolary, setCoffee, setLeader. Можно было сделать метод
допустим провестиАнтикризисныйСценарий(компания) а в нем написать так:
для каждого департамента {
работники = отобрать работников()
отсортировать работников;
взять первые N;
для каждого работника {
задать ранг;
задать зарплату;
}
}
Но можно и поступить по другому. setSolary и setCoffee различаются только одной строкой:
> $employee->setSalary($salary);
> $employee->setCoffee($coffe);
раз так, можно вынести это в коллбек. Можно сделать функцию обработатьВсехРаботников(критерии, коллбек) и вызывать ее примерно так:
$this->findAndProcessWorkers('manager', 0.4, false, function ($e) {
$e->setSalary(...);
});
А можно сделать так, выбираем работников а потом что-то делаем:
$workers = findWorkers('manager', 0.4); // берем 40% менеджеров
foreach ($workers as $worker) {
....;
}
> if (count($filteredEmployees) == 0) {
>\t\t\t\tcontinue;
Это условие не обязательно
> $employees = $department->makeEmployeesArray( );
> $filteredEmployees = $this->getEmployeesType($employees, $type);
тут можно было сделать чтобы в getEmployeesType передавался сразу департамент.
> https://github.com/someApprentice/Vector-Com/blob/master/Classes/Employee.php#L45
Здесь надо поставить default + выброс исключения. ты думаешь что никто не передаст неправильный ранг, а его передадут.
> https://github.com/someApprentice/Vector-Com/blob/master/Classes/Employee.php#L90
Не ставь ?> в конце
> https://github.com/someApprentice/Vector-Com/blob/master/Classes/Direction.php#L6
> $array = array( );
Эта строка не нужна.
> $array
Почитай статью http://learn.javascript.ru/write-unmain-code#будьте-абстрактны-при-выборе-имени
> public function getLeader($employees) {
Этот метод наверно логичнее сделать у Департамента: ведь мы можем захотеть узнать кто сейчас босс.
> while ($i < 9)
Ты используешь переменную до того как ее создал. Всегда в начале должно идти $i = ... а потом ее использование.
>>448298
Если ты про код в этом файле https://github.com/someApprentice/Vector-Com/blob/master/Classes/Direction.php то решение убрать слишком абстрактные методы которые используются лишь один раз. То есть вместо того чтобы делать метод повышения зарплаты любому типу работников, можно сделать 3 конкретных метода: антикризисный метод 1, 2 и 3.
> //Здесь идет очень много копипасты, и я не могу сообразить как с ней бороться,
Вообще можно было не делать абстрактные методы типа setSolary, setCoffee, setLeader. Можно было сделать метод
допустим провестиАнтикризисныйСценарий(компания) а в нем написать так:
для каждого департамента {
работники = отобрать работников()
отсортировать работников;
взять первые N;
для каждого работника {
задать ранг;
задать зарплату;
}
}
Но можно и поступить по другому. setSolary и setCoffee различаются только одной строкой:
> $employee->setSalary($salary);
> $employee->setCoffee($coffe);
раз так, можно вынести это в коллбек. Можно сделать функцию обработатьВсехРаботников(критерии, коллбек) и вызывать ее примерно так:
$this->findAndProcessWorkers('manager', 0.4, false, function ($e) {
$e->setSalary(...);
});
А можно сделать так, выбираем работников а потом что-то делаем:
$workers = findWorkers('manager', 0.4); // берем 40% менеджеров
foreach ($workers as $worker) {
....;
}
> if (count($filteredEmployees) == 0) {
>\t\t\t\tcontinue;
Это условие не обязательно
> $employees = $department->makeEmployeesArray( );
> $filteredEmployees = $this->getEmployeesType($employees, $type);
тут можно было сделать чтобы в getEmployeesType передавался сразу департамент.
> https://github.com/someApprentice/Vector-Com/blob/master/Classes/Employee.php#L45
Здесь надо поставить default + выброс исключения. ты думаешь что никто не передаст неправильный ранг, а его передадут.
> https://github.com/someApprentice/Vector-Com/blob/master/Classes/Employee.php#L90
Не ставь ?> в конце
> https://github.com/someApprentice/Vector-Com/blob/master/Classes/Direction.php#L6
> $array = array( );
Эта строка не нужна.
> $array
Почитай статью http://learn.javascript.ru/write-unmain-code#будьте-абстрактны-при-выборе-имени
> public function getLeader($employees) {
Этот метод наверно логичнее сделать у Департамента: ведь мы можем захотеть узнать кто сейчас босс.
> letter-spacing:-5px;
Это подгонка под конкретный шрифт. предыдущий вариант подошел бы но надо было просто margin -1px добавить чтобы линии border наложились друг на друга.
Ну и в фаерфоксе по прежнему разделители шириной 2px.
Вот. Почему дисплей: блок зачеркивается? Или нужно медиа правило ставить в конец?
Далее, на div main медиа правило вообще не сработало.
Проверьте правильно ли составлено регулярное выражение? Может можно было проще сделать?
спасибо ОП, наверное, ты очень терпеливый. Только с 3 раза заметил, что в in_array() надо отправлять доп. параметр, чтобы производилось строгое сравнение. Убрал лишние свойства у департамента, добавил метод смены босса (а массив аналитиков сортируется по рангам, нам ведь нужно выбрать самого крутого аналитика, теперь я переделал так, что босс становится end(analytics)). А насчет производительности труда, я думаю, что вернее всего будет точно указать в чем проблема и завершить программу("Division by zero"), иначе человеку придется искать эту ошибку (если например возвращать null), или ты имеешь в виду, что сообщение об ошибке должно быть более user-friendly(тогда я сделал, так, что клерк падает, но успевает сообщить о раздолбайстве в департаменте)? Ну и насчет createEmployee() - это у меня вспомогательная функция, которая упрощает процесс создания объектов, я не понимаю в чем проблема переменной $boss. По умолчанию создается работник-не босс ($boss=false). Но если мы явно указываем, то работник-босс. То есть этот параметр затем идет в конструктор класса.
Заранее спасибо.
Вроде все понял, только теперь до меня дошло. Завтра переделаю. Там действительно все не так как я хотел из-за того, что медиа правило нужно вставить в конец, либо указать другое медиа правило для остального кода.
> . Почему дисплей: блок зачеркивается?
Посмотри внимательно, какое-то другое правило его перекрывает.
> на div main медиа правило вообще не сработало.
Может надо писать div#main без пробела?
А вообще, плохая идея использовать div в селекторе. это же не несет никакого смысла, id укникальны и можно просто писать #main.
>>448421
> margin:-1px;
Надо немного по другому написать. В твоем случае оба блока смещаются на 1px друг к другу и границы не накладываются.
>>448428
да, так лучше. Добавь еще уникальный класс чтобы стили не конфликтовали.
>font-size: 14px;
укажи line-height
> А насчет производительности труда, я думаю, что вернее всего будет точно указать в чем проблема и завершить программу
Лучше всего будет если метод будет считать и возвращать актуальные данные а не завершаться с ошибкой.
Ну и у тебя там все равно ошибка происходит, а exit не срабатывает.
> я не понимаю в чем проблема переменной $boss.
Зачем ты пишешь $boss= ? Когда ты вызываешь функцию ты пишешь конкретные значения аргументов, а не их имена:
func(1, 2, 3, true);
все я понял в чем проблема с производительностью. Вот переделанная версия:
http://ideone.com/3NIRQ2
Ставишь зачет?
> Можно сделать функцию обработатьВсехРаботников(критерии, коллбек)
>коллбек
А как его правильно передать? Я не могу нагуглить.
function Foo ($first, __CALLBACK__) {
//do something
}
На что надо заменить __CALLBACK__?
>https://github.com/someApprentice/Vector-Com/blob/master/Classes/Employee.php#L45
>Здесь надо поставить default + выброс исключения. ты думаешь что никто не передаст неправильный ранг, а его передадут.
Не разу не писал исключения. Что ж, попробую:
switch ($this->rang) {
...
default:
throw new Exception('Incorrect rang');
}
И потом где-то в месте вызова этой функции использовать try\catch
У меня это будет так:
<?php
try {
?>
<td>
<?=$employee->getSalary()?>
<?php
} catch (Exception $e) {
echo $e->getMessage();
}
?>
</td>
Правильно?
> Можно сделать функцию обработатьВсехРаботников(критерии, коллбек)
>коллбек
А как его правильно передать? Я не могу нагуглить.
function Foo ($first, __CALLBACK__) {
//do something
}
На что надо заменить __CALLBACK__?
>https://github.com/someApprentice/Vector-Com/blob/master/Classes/Employee.php#L45
>Здесь надо поставить default + выброс исключения. ты думаешь что никто не передаст неправильный ранг, а его передадут.
Не разу не писал исключения. Что ж, попробую:
switch ($this->rang) {
...
default:
throw new Exception('Incorrect rang');
}
И потом где-то в месте вызова этой функции использовать try\catch
У меня это будет так:
<?php
try {
?>
<td>
<?=$employee->getSalary()?>
<?php
} catch (Exception $e) {
echo $e->getMessage();
}
?>
</td>
Правильно?
Хм) надо будет с утра на свежую голову, еще раз попробовать по читать и наверное, сразу с вопросами сюда прикачу.
> На что надо заменить __CALLBACK__?
function x(callable $y) {
...
}
http://php.net/manual/ru/language.types.callable.php
callable это все, что можно вызвать как функцию. Под callable PHP понимает несколько видов указателей на функцию:
— строка с именем функции или именем статического метода
— массив из 2 элементов, указывающий на объект/класс иимя метода
— анонимная функция (в реальности экземпляр класса Closure)
— объект, реализующий магический метод invoke
Вызывается любая из них скобками, то есть просто пишешь $y( );
Пример кода (выполняется в командной строке):
php -r '$a=["DateTime", "createFromFormat"];var_dump($a("Y", 2014));'
> Не разу не писал исключения
Может быть урок поможет https://gist.github.com/codedokode/65d43ca5ac95c762bc1a
>И потом где-то в месте вызова этой функции использовать try\catch
не надо писать try/catch. PHP по умолчанию завершает программу с ошибкой если исключение долетит до самого верха. Да еще и в логи эту ошибку запишет в отличие от твоего кода.
> На что надо заменить __CALLBACK__?
function x(callable $y) {
...
}
http://php.net/manual/ru/language.types.callable.php
callable это все, что можно вызвать как функцию. Под callable PHP понимает несколько видов указателей на функцию:
— строка с именем функции или именем статического метода
— массив из 2 элементов, указывающий на объект/класс иимя метода
— анонимная функция (в реальности экземпляр класса Closure)
— объект, реализующий магический метод invoke
Вызывается любая из них скобками, то есть просто пишешь $y( );
Пример кода (выполняется в командной строке):
php -r '$a=["DateTime", "createFromFormat"];var_dump($a("Y", 2014));'
> Не разу не писал исключения
Может быть урок поможет https://gist.github.com/codedokode/65d43ca5ac95c762bc1a
>И потом где-то в месте вызова этой функции использовать try\catch
не надо писать try/catch. PHP по умолчанию завершает программу с ошибкой если исключение долетит до самого верха. Да еще и в логи эту ошибку запишет в отличие от твоего кода.
Читай, а то так и останешься безграмотной пхпмакакью: http://en.wikipedia.org/wiki/Common_Gateway_Interface
Там всё написано за тебя, существуют кучи плагинов, но чтобы допилить что-то своё, приходится перелопачивать тонны чужого говнокода.
>>448575
Схороняй в сессию, допустим так
$_SESSION['filters']=array($_POST['radiobutton'],$_POST['select'],$_POST['textarea']);
В сами инпуты подставляй значения из сессии, например в textarea так:
<textarea><?=$_SESSION['textarea']; ?></textarea>
В селекты и радиокнопки чуть сложнее, как-то так
<input type='checkbox' value='something' <?php if ($_SESSION['filters'][2]=='something') echo 'checked'; ?>>
Само собой лучше создать функцию session() чтобы не сыпались нотисы про пустую сессию если фильтров на странице нет. Ну и можно ассоциативным массивом схоронять чтоб понятнее было.
В конце страницы когда фильтры расставлены удаляй через unset ($_SESSION['filters'])
Спасибо, попробую.
>PHP Notice: Undefined variable: ...
Это критично? Если да, то как избегать?
http://ideone.com/EnWfbj
>>447985
И так, я два дня ебланил и мне очень стыдно, теперь к делу. Я немного не понял, должен ли я избавиться от функции mb_substr в первой оптимизации? Или я могу просто передавать параметр, который будет автоматом подставляться в mb_substr (), что бы сравнивать текущие символы? Я не представляю просто, как без этой функции мне их сравнивать? Вроде бы образаться к элементу строки как к элементу массива нельзя, и если я буду просто дергать $mask[3], то не получу 3 символ в случае с русскими буквами внутри. Заниматься разбиением имени и маски на массив символов перед тем как начинать их сравнивать?
>Это критично? Если да, то как избегать?
При первом цикле foreach переменные $consumption, $generation, $summary неизвестны. Это не критично, но так делать не надо.
Как избегать? Просто объявить переменную или использовать функцию isset().
http://php.net/manual/ru/language.variables.basics.php
>Полагаться на значения по умолчанию неинициализированных переменных довольно проблематично при включении файла в другой файл, использующий переменную с таким же именем. Это также большой риск в системе безопасности при включенной опции register_globals. В случае работы с неинициализированной переменной вызывается ошибка уровня E_NOTICE, за исключением случая добавления элементов в неинициализированный массив. Для обнаружения инициализации переменной может быть использована языковая конструкция isset().
И да, я код особо не смотрел, но скажу одно, избавься от копипасты. У тебя штук десять функций, которые делают одно и то же.
Шаблон:
'/^\\+?[7|8]\\s?\\(?-?[0-9]{3}\\s?\\)?-?[0-9]{3}-?[0-9][0-9]-?[0-9][0-9]$/'
Вообще ты можешь быстро эксперементировать на пикрилейтеде ссылку не пропускает макакас
только там надо ставить \( вместо \\( например, но там зато все подсвечивается и куда более интерактивно и отлаживается на ура, чем сидеть тупить над кодом, я вот моментально заметил что у тебя ошибка в последовательности ( и - идет.
Удачи в дальнейшем изучении.
Ну хотя бы. Пхп тоже знаю немного.
Думаю надо начать пробовать отсылать резюме и пытаться сделать тестовые задание. Если не потянешь, то дуй на продвинутые курсы.
пацаны, такая беда. короче есть у меня на сайте страничка, которую правит контент менеджер, поэтому встроил я туда ckeditor, работает это так. В этот едитор из файла загружается текстовая информация(с различными аштиэмель тегами) и он её правит, сохраняет, сохраняется в тот же файл. Используются функции fopen и fwrite. В этом редакторе есть функция вставки ссылки, но вот беда! Когда я проделываю операцию по вставке ссылки то всё происходит отлично. Но на хостинге что-то идет не так, ссылки после сохранения принимают вид www.mysite.com/"тут ссылка, которую прописал в ckeditor". Почему ссылка заносится в кавычки непонятно. Причем на локальном сервере такой проблемы нет, хотя всё то же. Сперва я думал, что дело в редакторе, поставил tinymce. Но проблема осталась та же. Выходит, что пхп записывая контент в файл экранирует ссылки что-ли? Очень нужна помощь, посоны. На всякий случай код: https://ideone.com/fkio5p
Благодарствую, но не совсем понятно про последовательность, в уроке написано что ? - означает что симол может либо присуствовать, либо отсуствовать, я думал что с вопросом последовательности не важны.
И ещё вопросик. Можно ли коротко, в одних скобках, описать то, что юзер может писать "-" в любом месте номера (как любят делать обладатели козырных номеров типа 12-555-55), или придётся в коде после каждой цифры вписывать тире? Типа "[0-9]-?[0-9]-?"?
У тебя тире после скобки стоит.
>Можно ли коротко, в одних скобках, описать то, что юзер может писать "-" в любом месте номера
Можно, "{^\+?[\d-\)\(\s]+$}", но ты должен понимать, что в таком случае юзер может развлекаться как хочет. И тебе нужно будет задействовать str_replace.
Чёрт, наконец допёрло, спасибо огромное.
Переделал задачку про расчет маршрута. У static подводных камней надеюсь нет, ибо как иначе это реализовать я не знаю.
http://ideone.com/AlIaDT
Да, кстати, там ошибочка небольшая, поэтому анимации нет, но это и к лучшему, вам не нужно видеть этот кошмар.
Бро, я сейчас на этой же задаче завис, даже ОП мне выделил еще задач, на рекурсию. Долго решал её? Долго вообще занимаешься изучением пхп?
http://ideone.com/6DtRyD
Про if() {
}
if(){
}
Ты имел в виду что вот так примерно должно выглядеть?
Как-то так должно получиться:
function calcAverage($company, $medthod) {
$summary = 0;
foreach ($company as $department) {
$summary = $summary + $department->$method;
}
return round($summary / count($company), 2);
}
Дня 3 наверно ковырял в общей сложности, то одно вылезет, то другое. Дольше всего вкуривал как время правильно посчитать. Рекурсией плохо владею, принцип понимаю, но применять тяжело. Пхп учу около месяца, не очень регулярно.
$method = 'methodName';
$department->$method();
Кстати, подобные вопросы легко гуглятся, если формулировать на английском.
Спасибо большое. На русском-то я загуглил.
Бамп вопросу.
Если не понятна моя ситуация, то попробую объяснить лучше: есть переменная, куда я сбрасываю результаты запроса
$mainData = $mapper->getAllData($code);
В самой функции getAllData(...) используется стандартный для объектов return:
return $STH->fetchAll(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, "Entry");
Если просто перебирать значения $mainData с помощью foreach, то проблем никаких нет. Но я хочу получить определенную строку из $mainData.
То есть, какого $mainData типа, и как достучаться в ней до N-ной строки?
> [А-Яа-я]
В Юникоде (стандарт описывающий символы в шрифтах) буква ё идет не после «е», а отдельно и потому надо писать а-яёА-ЯЁ.
Ну и чтобы не мучаться с регистром букв можно добавить в конце регулярки флаг i — пару лет назад его починили и он работает с русскими буквами (до этого не работал).
> (?<!\,\s)
Это странная конструкция. Она говорит «перед этим местом не должно быть запятой и пробела». Но ведь перед этим у тебя стоит [А-Яа-я]+ то есть пробел там никак не может быть.
Выражения для жы-ши можно объединить в одно. Выражения для «а» и «но» можно объединить.
> (?<!\,)[А-Яа-я]×\sа\s
Непонятно, зачем тут стоит условие с отсутствием запятой?
> for($i=0;$i<count($matches[0]);$i++){
Тут лучше применить foreach
>>448443
Хорошо. Но у тебя стоят глобальные стили, например если поместить твой переключатель на обычную страницу, то на ней исчезнут все радиокнопки. Это надо исправить.
>>448452
Почти. Можно код сделать еще чуть-чуть лучше.
> public function setNewBoss(Employee $emp)
Вот здесь, если передать босса не из департамента, то функция уволит существующего босса, нового не поставит, и никаких сообщений об ошике не будет. Это плохо по двум причинам:
— плохо когда функция делает работу частично. Хорошая функция либо делает свою задачу полностью, либо оставляет все объекты в исходном состоянии. А у тебя при ошибке департамент останется без босса.
— плохо когда ошибка молча игнорируется и программист о ней не узнает. Лучше при передаче неправильного босса выбросить исключение. И делать это конечно надо до увольнения старого.
То же (молчаливое игнорирование ошибок) у тебя сделано в функици fireEmployee. Функция либо должна называться fireEmployeeIfHeWorksHere либо выбрасывать исключение при ошибке.
Есть такой принцип: fail fast ( http://habrahabr.ru/post/218325/ ). Игнорируя ошибку ты лишь усложняешь себе отладку кода.
> exit("В этом департаменте одни бездельники!
исплоьзуй исключения (которые можно перехватить и обработать), а не колхозь свои решения. Урок по исключениям: https://gist.github.com/codedokode/65d43ca5ac95c762bc1a
> $this->totalSalary = 0;
Это в департаменте в clone забыл убрать.
> $inputArr[$i] = array_merge(["№" => $enum[$i]], $inputArr[$i]);
Можно писать проще:
$inputArr[$i]["№"] = ...;
В общем, у тебя сейчас все хорошо сделано, я вижу что ООП ты более-менее начинаешь понимать, исправь только еще эти мелкие замечания.
Ну и если я долго не проверяю задание, не жди меня, делай следующее.
> [А-Яа-я]
В Юникоде (стандарт описывающий символы в шрифтах) буква ё идет не после «е», а отдельно и потому надо писать а-яёА-ЯЁ.
Ну и чтобы не мучаться с регистром букв можно добавить в конце регулярки флаг i — пару лет назад его починили и он работает с русскими буквами (до этого не работал).
> (?<!\,\s)
Это странная конструкция. Она говорит «перед этим местом не должно быть запятой и пробела». Но ведь перед этим у тебя стоит [А-Яа-я]+ то есть пробел там никак не может быть.
Выражения для жы-ши можно объединить в одно. Выражения для «а» и «но» можно объединить.
> (?<!\,)[А-Яа-я]×\sа\s
Непонятно, зачем тут стоит условие с отсутствием запятой?
> for($i=0;$i<count($matches[0]);$i++){
Тут лучше применить foreach
>>448443
Хорошо. Но у тебя стоят глобальные стили, например если поместить твой переключатель на обычную страницу, то на ней исчезнут все радиокнопки. Это надо исправить.
>>448452
Почти. Можно код сделать еще чуть-чуть лучше.
> public function setNewBoss(Employee $emp)
Вот здесь, если передать босса не из департамента, то функция уволит существующего босса, нового не поставит, и никаких сообщений об ошике не будет. Это плохо по двум причинам:
— плохо когда функция делает работу частично. Хорошая функция либо делает свою задачу полностью, либо оставляет все объекты в исходном состоянии. А у тебя при ошибке департамент останется без босса.
— плохо когда ошибка молча игнорируется и программист о ней не узнает. Лучше при передаче неправильного босса выбросить исключение. И делать это конечно надо до увольнения старого.
То же (молчаливое игнорирование ошибок) у тебя сделано в функици fireEmployee. Функция либо должна называться fireEmployeeIfHeWorksHere либо выбрасывать исключение при ошибке.
Есть такой принцип: fail fast ( http://habrahabr.ru/post/218325/ ). Игнорируя ошибку ты лишь усложняешь себе отладку кода.
> exit("В этом департаменте одни бездельники!
исплоьзуй исключения (которые можно перехватить и обработать), а не колхозь свои решения. Урок по исключениям: https://gist.github.com/codedokode/65d43ca5ac95c762bc1a
> $this->totalSalary = 0;
Это в департаменте в clone забыл убрать.
> $inputArr[$i] = array_merge(["№" => $enum[$i]], $inputArr[$i]);
Можно писать проще:
$inputArr[$i]["№"] = ...;
В общем, у тебя сейчас все хорошо сделано, я вижу что ООП ты более-менее начинаешь понимать, исправь только еще эти мелкие замечания.
Ну и если я долго не проверяю задание, не жди меня, делай следующее.
> даже основы PHP которые в первой линке, даются как-то тяжело, ибо не понимаю, как и что использовать.
Напиши что именно непонятно, и на какой задаче или на какой теме ты застрял. Там некоторые задачи сложны для начинающего и я обычно даю по ним подсказки (или дополнительные более простые задачи).
>>448575
У чекбоксов и селектов можно ставить галочку и выделять элементы с помощью html аттрибутов. Не вижу проблемы.
> <input type="text" name="search" value=". $_GET(search)">
У тебя уязвимость XSS: https://github.com/codedokode/pasta/blob/master/security/xss.md
>Если у нас в базе несколько таблиц, то мы делаем несколько мапперов, по одному на каждую. Если требуется делать какие-то действия с несколькими таблицами сразу (скрытие новости и всех комментариев к ней), это иногда делают в маппере, содержащем главную сущность (новость), а иногда в классе-сервисе, находящемся выше уровня мапперов и управляющим ими.
У меня запрос подтягивает несколько таблиц, значит нужно создавать еще один класс? Как он должен выглядеть? И почему нельзя сделать просто еще один метод в том же маппере?
Оп, спасибо что указал на ошибки. С регулярками я действительно перемудрил.
CMS — Content Management System — это платформы для создания сайтов без или с минимальным количеством программирования. В идеале сайт создается через графический интерфейс в админке, в реальности обычно приходится делать и нарезать верстку под CMS.
Например на CMS Wordpress ты можешь создать себе блог с админкой и системой комментирования, не написав ни строчки кода.
Есть огромное множество платных и бесплатных CMS. Гугли «рейтинг CMS».
Популярные бесплатные CMS это Wordpress и Drupal.
Инструкции по использованию CMS, а также по изготовлению дизайна и написанию плагинов под них обычно находятся на официальном сайте, на английском. На русском для популярных CMS можно нагуглить статьи и переводы.
>>448607
Ты код не показал и трудно понять о чем речь: об объекте PDOStatement или массиве который возвращает fetchAll/fetch и подобные функции.
> Однако, когда я пытаюсь обратиться к определенной строчке это массива и хочу вытянуть данные $mainData[5]->getID()
наверно там в массиве лежат не объекты, а может быть тоже массивы. Без кода не сказать.
>>448626
Сессия тут излишня, так как все данные есть в GET.
> <textarea><?=$_SESSION['textarea']; ?></textarea>
У тебя XSS https://github.com/codedokode/pasta/blob/master/security/xss.md
>>448660
> Это критично?
Это ошибка в твоей программе. Конечно критично.
> Если да, то как избегать?
Надо сначала создать переменную ($x = 0;) а потом к ней обращаться, а не наоборот.
Советы и замечания по этому коду: https://ideone.com/VBC34a
> public function __construct($boss, $name, $managers1, $managers2, $managers3
не делай у функции больше 4-5 аргументов так как иначе глядя на код невозможно запомнить что какая цифра обозначает
Ну и вообще это неправильно. Ты не должен при создании департамента указывать сколько в нем человек. Лучше сделать метод для добавления объекта-работника. И этот метод можно вызывать как угодно. А у тебя например нельзя:
— добавить в департамент инженера 2 или 3 уровня
— добавить особого маркетолога с утроенной зарплатой
— добавить сотрудника другой профессии кроме указанных
> foreach ($this->employees as $employee) {
> $consumption = $consumption + $employee->coffee;
Надо присваивать переменной начальное значение, а ты используешь не существующую на тот момент перменнную.
> return round($toogreeks, 1);
Лучше возвращать точное значение, а округлять при выводе.
> abstract class Employee {
У классов и функций скобка ставится на отдельной строке. Вот пример оформления кода из стандарта: http://www.php-fig.org/psr/psr-2/ru/
> public function countSalary($salary) {
Это судя по названию функция которая сообщает какая у работника зарплата. Но почему тогда в нее надо что-то передавать?
> $this->salary = $this->countSalary($salary);
Ты хранишь в salary вычисленную зарплату. хорошо, а что если мы хотим повысить или понизить работника в ранге, как это сделать с твоим кодом? надо чтобы при изменении ранга зарплата пересчитывалась.
> for ($i = 0; $i < $length - $stlen; $i++) {
> $string = " " . $string;
Есть функция str_repeat
> function countAverageMoneyConsumption($company) {
> function countTotalMoneyConsumption($company) {
Эти функции очень похожи. Надо ли было их копипастить? Среднее можно вычислить из total поделив на число компаний.
Ну и тебе тоже советую сделать дополнительное задание про антикризисные меры в компании Вектор. Оно поможет тебе лучше изучить ООП.
CMS — Content Management System — это платформы для создания сайтов без или с минимальным количеством программирования. В идеале сайт создается через графический интерфейс в админке, в реальности обычно приходится делать и нарезать верстку под CMS.
Например на CMS Wordpress ты можешь создать себе блог с админкой и системой комментирования, не написав ни строчки кода.
Есть огромное множество платных и бесплатных CMS. Гугли «рейтинг CMS».
Популярные бесплатные CMS это Wordpress и Drupal.
Инструкции по использованию CMS, а также по изготовлению дизайна и написанию плагинов под них обычно находятся на официальном сайте, на английском. На русском для популярных CMS можно нагуглить статьи и переводы.
>>448607
Ты код не показал и трудно понять о чем речь: об объекте PDOStatement или массиве который возвращает fetchAll/fetch и подобные функции.
> Однако, когда я пытаюсь обратиться к определенной строчке это массива и хочу вытянуть данные $mainData[5]->getID()
наверно там в массиве лежат не объекты, а может быть тоже массивы. Без кода не сказать.
>>448626
Сессия тут излишня, так как все данные есть в GET.
> <textarea><?=$_SESSION['textarea']; ?></textarea>
У тебя XSS https://github.com/codedokode/pasta/blob/master/security/xss.md
>>448660
> Это критично?
Это ошибка в твоей программе. Конечно критично.
> Если да, то как избегать?
Надо сначала создать переменную ($x = 0;) а потом к ней обращаться, а не наоборот.
Советы и замечания по этому коду: https://ideone.com/VBC34a
> public function __construct($boss, $name, $managers1, $managers2, $managers3
не делай у функции больше 4-5 аргументов так как иначе глядя на код невозможно запомнить что какая цифра обозначает
Ну и вообще это неправильно. Ты не должен при создании департамента указывать сколько в нем человек. Лучше сделать метод для добавления объекта-работника. И этот метод можно вызывать как угодно. А у тебя например нельзя:
— добавить в департамент инженера 2 или 3 уровня
— добавить особого маркетолога с утроенной зарплатой
— добавить сотрудника другой профессии кроме указанных
> foreach ($this->employees as $employee) {
> $consumption = $consumption + $employee->coffee;
Надо присваивать переменной начальное значение, а ты используешь не существующую на тот момент перменнную.
> return round($toogreeks, 1);
Лучше возвращать точное значение, а округлять при выводе.
> abstract class Employee {
У классов и функций скобка ставится на отдельной строке. Вот пример оформления кода из стандарта: http://www.php-fig.org/psr/psr-2/ru/
> public function countSalary($salary) {
Это судя по названию функция которая сообщает какая у работника зарплата. Но почему тогда в нее надо что-то передавать?
> $this->salary = $this->countSalary($salary);
Ты хранишь в salary вычисленную зарплату. хорошо, а что если мы хотим повысить или понизить работника в ранге, как это сделать с твоим кодом? надо чтобы при изменении ранга зарплата пересчитывалась.
> for ($i = 0; $i < $length - $stlen; $i++) {
> $string = " " . $string;
Есть функция str_repeat
> function countAverageMoneyConsumption($company) {
> function countTotalMoneyConsumption($company) {
Эти функции очень похожи. Надо ли было их копипастить? Среднее можно вычислить из total поделив на число компаний.
Ну и тебе тоже советую сделать дополнительное задание про антикризисные меры в компании Вектор. Оно поможет тебе лучше изучить ООП.
> Или я могу просто передавать параметр, который будет автоматом подставляться в mb_substr (), что бы сравнивать текущие символы?
гм. Избавиться от mb_substr можно если передавать не строку, а массив символов.
> Вроде бы образаться к элементу строки как к элементу массива нельзя,
нельзя. Но можно разбить строку на массив букв.
> Заниматься разбиением имени и маски на массив символов перед тем как начинать их сравнивать?
да
Ну и не жди пока я отвечу, пиши код или решай другие задачи.
>>448712
Ты решашеь задачу про телефоны? Вот совет тебе в помощь:
Задачу про номера телефонов надо проверить на большом числе телефонов, чтобы убедиться что твой код правильный. Но руками подставлять номера — долго и скучно. Пусть работает робот, а не человек!
Для этого давай добавим в программу тесты, чтобы сразу было видно, верно все работает или нет. Сделай 2 списка номеров (правильные и нет), добавь их в программу и напиши цикл, который их по очереди прогоняет через регулярку и проверяет что они определяются как надо (если нет — надо вывести какой именно номер не распознается правильно).
Вот список номеров:
Правильные: array('84951234567', '+74951234567', '8-495-1-234-567', ' 8 (8122) 56-56-56', '8-911-1234567', '8 (911) 12 345 67', '8-911 12 345 67', '8 (911) - 123 - 45 - 67', '+ 7 999 123 4567', '8 ( 999 ) 1234567', '8 999 123 4567');
Неправильные: array('02', '84951234567 позвать люсю', '849512345', '849512345678',
'8 (409) 123-123-123', '7900123467', '5005005001', '8888-8888-88',
'84951a234567', '8495123456a',
'+1 234 5678901', // неверный код страны
'+8 234 5678901', // либо 8 либо +7
'7 234 5678901' // нет +
);
> Или я могу просто передавать параметр, который будет автоматом подставляться в mb_substr (), что бы сравнивать текущие символы?
гм. Избавиться от mb_substr можно если передавать не строку, а массив символов.
> Вроде бы образаться к элементу строки как к элементу массива нельзя,
нельзя. Но можно разбить строку на массив букв.
> Заниматься разбиением имени и маски на массив символов перед тем как начинать их сравнивать?
да
Ну и не жди пока я отвечу, пиши код или решай другие задачи.
>>448712
Ты решашеь задачу про телефоны? Вот совет тебе в помощь:
Задачу про номера телефонов надо проверить на большом числе телефонов, чтобы убедиться что твой код правильный. Но руками подставлять номера — долго и скучно. Пусть работает робот, а не человек!
Для этого давай добавим в программу тесты, чтобы сразу было видно, верно все работает или нет. Сделай 2 списка номеров (правильные и нет), добавь их в программу и напиши цикл, который их по очереди прогоняет через регулярку и проверяет что они определяются как надо (если нет — надо вывести какой именно номер не распознается правильно).
Вот список номеров:
Правильные: array('84951234567', '+74951234567', '8-495-1-234-567', ' 8 (8122) 56-56-56', '8-911-1234567', '8 (911) 12 345 67', '8-911 12 345 67', '8 (911) - 123 - 45 - 67', '+ 7 999 123 4567', '8 ( 999 ) 1234567', '8 999 123 4567');
Неправильные: array('02', '84951234567 позвать люсю', '849512345', '849512345678',
'8 (409) 123-123-123', '7900123467', '5005005001', '8888-8888-88',
'84951a234567', '8495123456a',
'+1 234 5678901', // неверный код страны
'+8 234 5678901', // либо 8 либо +7
'7 234 5678901' // нет +
);
Знания HTML/CSS это очень базовая вещь. Это как знание сложения и умножения.
Теоретически ты бы мог стать верстальщиком, но сейчас почти все верстальщики либо знают еще яваскрипт (jQuery + плагины, анимации, эффекты) либо же знают дизайн и умеют не только верстать, но и дизайнить. Либо ты бы мог подтянуть php и идти полноценным программистом.
Так что ты можешь попробовать поискать работу, но если у тебя есть возможность, то лучше развиваться дальше, так как с такими знаниями доступны только низкоквалицифированные задачи и большое число конкурентов.
Ну и тебе не обязательно покупать платные курсы. Ты можешь неплохо научиться верстать и по нашим бесплатным заданиям (есть в ОП посте). Там правда придется самому иногда гуглить нужную информацию.
>>448730
Мануал по редактору читать не пробовал? http://docs.ckeditor.com/#!/api/CKEDITOR.config-cfg-baseHref
Редакторы могут добавлять адрес сайта к относительным ссылкам. Ну и абсолютная ссылка начинается с http, а www.mysite это ссылка на папку с таким названием.
Тебе надо сначала почитать про то как утсроен URL, прежде чем браться за программирование: https://ru.wikipedia.org/wiki/URL
> Выходит, что пхп записывая контент в файл экранирует ссылки что-ли?
Нет конечно. Бред же. Чтобы экранировать ссылки он должен понимать что в файле HTML а не случайный набор символов.
Кавычки в ссылке очевидно из за того что в редакторе при вставке ссылки пользователь их добавляет. Либо твой код при выводе.
>>448734
? относится к символу или группе (заключенной в [] или ()) перед ним:
abc? — тут ? относится только к символу c
abc(def)? — тут к последовтельности def
abc[def]? — тут к [def]
> Можно ли коротко, в одних скобках, описать то, что юзер может писать "-" в любом месте номера
Можно
> "[0-9]-?[0-9]-?"
тут можно использовать повторение
>>448753
> {^\+?[\d-\)\(\s]+$}
Это неправильное выражение. Скобки {} задают число повторений
>>448767
> input{
>\tdisplay: none;
Если твои вкладки поместить на обычную страницу то этот код скроет все инпуты на ней. Такого быть не должно.
> #one, #two, #three, #four
Тут лучше использовать классы. Допустим, я захочу поместить на страницу несколько блоков с вкладками. Что, придется в куче мест править CSS? Избавься от id везде где это возможно.
> position: absolute;
>\ttop:-9999px;
Почему такой странный способ скрытия? Ради анимации? Что если табы поместить в низ страницы высотой 10000px? (10000px это примерно 15 экранов)
> - webkit-transition:top 2s;
Пробел после знака минус
> @media(max-width: 1000px){
> #main{
>\tposition: absolute;
Это неправильный код. У тебя в этом случае контент который идет ниже провалится под вкладки так как абс. поз. блок не занимает места в потоке.
Вот тут http://jsfiddle.net/jfghs7hx/1/ если сузить экран текст перед и после вкладок вообще не виден. Ты должен сделать не абстрактные вкладки в вакууме, а вкладки которые можно интегрировать в обычную верстку.
> #tab1:checked ~ #one, #tab2:checked ~ #two, #tab3:checked ~ #three, #tab4:checked ~ #four{
> \ttop:50px;
Это плохая идея, использовать абс. поз. везде так как твои вкладки не в потоке и не расталкивают текст под ними. А.п. используют для ситуаций когда например надо крестик в углу окошка поместить, а для создания вкладок оно не подходит.
> Анимация всплывающего текста правда не вышла.
Потому что ты пробел поставил лишний
Кавычки в ссылке очевидно из за того что в редакторе при вставке ссылки пользователь их добавляет. Либо твой код при выводе.
>>448734
? относится к символу или группе (заключенной в [] или ()) перед ним:
abc? — тут ? относится только к символу c
abc(def)? — тут к последовтельности def
abc[def]? — тут к [def]
> Можно ли коротко, в одних скобках, описать то, что юзер может писать "-" в любом месте номера
Можно
> "[0-9]-?[0-9]-?"
тут можно использовать повторение
>>448753
> {^\+?[\d-\)\(\s]+$}
Это неправильное выражение. Скобки {} задают число повторений
>>448767
> input{
>\tdisplay: none;
Если твои вкладки поместить на обычную страницу то этот код скроет все инпуты на ней. Такого быть не должно.
> #one, #two, #three, #four
Тут лучше использовать классы. Допустим, я захочу поместить на страницу несколько блоков с вкладками. Что, придется в куче мест править CSS? Избавься от id везде где это возможно.
> position: absolute;
>\ttop:-9999px;
Почему такой странный способ скрытия? Ради анимации? Что если табы поместить в низ страницы высотой 10000px? (10000px это примерно 15 экранов)
> - webkit-transition:top 2s;
Пробел после знака минус
> @media(max-width: 1000px){
> #main{
>\tposition: absolute;
Это неправильный код. У тебя в этом случае контент который идет ниже провалится под вкладки так как абс. поз. блок не занимает места в потоке.
Вот тут http://jsfiddle.net/jfghs7hx/1/ если сузить экран текст перед и после вкладок вообще не виден. Ты должен сделать не абстрактные вкладки в вакууме, а вкладки которые можно интегрировать в обычную верстку.
> #tab1:checked ~ #one, #tab2:checked ~ #two, #tab3:checked ~ #three, #tab4:checked ~ #four{
> \ttop:50px;
Это плохая идея, использовать абс. поз. везде так как твои вкладки не в потоке и не расталкивают текст под ними. А.п. используют для ситуаций когда например надо крестик в углу окошка поместить, а для создания вкладок оно не подходит.
> Анимация всплывающего текста правда не вышла.
Потому что ты пробел поставил лишний
>У чекбоксов и селектов можно ставить галочку и выделять элементы с помощью html аттрибутов. Не вижу проблемы.
Тупо через if?
>Ты код не показал и трудно понять о чем речь: об объекте PDOStatement или массиве который возвращает fetchAll/fetch и подобные функции
>наверно там в массиве лежат не объекты, а может быть тоже массивы. Без кода не сказать.
Вот код функции http://ideone.com/wV7mat
А вот код вызова http://ideone.com/8E0Gnn
Очень прошу помощи, так как уже день сижу и ничего не могу сделать из-за этой херни.
Считает неверно: 3 + 3 + 3 + 3 + 3 != 22
Попробуем посчитать второй маршрут: http://ideone.com/kqduT2
Как видишь он опять посчитал неверно, 6 + 6 + 6 это явно не 13 минут.
static это та же самая глобальная переменная, приносящая побочные эффекты. Вот пример. Сделаем чтобы сначала шел расчет короткого маршрута, а потом длинного: http://ideone.com/mjllRL
Как видишь теперь он пишет ерунду. Данные от первого расчета смешались с данными от второго.
Используя глобальные переменные в любой форме, ты лишь усложняешь себе отладку. Ну и еще в твоей программе массив static $allPaths; только заполняется и никогда не очищается. Если вызвать функцию много раз подряд, этот массив разрастется и программа упадет из-за нехватки памяти.
Теперь посмотрим на заголовок функции:
makeOneStep($paths, $pathDone, $time, $tempTime, $point, $target)
Все ли параметры нужны для расчета?
$paths — нужен
$point, $target — нужны
$pathDone, $time — наверно нужны
$tempTime — непонятно зачем это
> Ты имел в виду что вот так примерно должно выглядеть?
Почти. Но если первые 2 ифа исключают все варианты когда одна из переменных пуста, то третий иф вообще становится не нужен. Большие ифы это плохо, так как их тяжело читать.
> if (empty($name) != empty($mask)) {
тут лучше использовать ИЛИ
> PHP Warning: Missing argument 3 for match(), called in /home/pd15Bw/prog.php on line 62 and defined in /home/pd15Bw/prog.php on line 4
Это надо исправить.
> !!АЛЯРМ!! не подошло!! СБОЙ ПРОГРАММЫ
Это тоже
проверил: >>448970
>>448897
Мануал php перечитать, внешние ключи и транзакции в MySQL, отличия InnoDB от MyISAM, хранение древовидных данных в MySQL. ну и задачки порешать. Вот у меня есть для разминки: https://github.com/codedokode/pasta/blob/master/interview-tasks.md
Так, вообще не угадаешь что спросят.
>>448883
> То есть, какого $mainData типа
Должен быть массив объектов
> и как достучаться в ней до N-ной строки?
$mainData[12]->something
Если это не работает, сделай var_dump($mainData) и покажи результат.
>>448964
> У меня запрос подтягивает несколько таблиц, значит нужно создавать еще один класс?
Нет. Если например ты выбираешь список постов, а через джойн число комментов к ним, то это идет в маппер постов, а не комментов.
Но если ты хочешь например выбрать все комменты к посту то это надо делать в маппере комментов.
То есть смотри по смыслу какая таблица основная.
>>448998
Да
>>449000
> $tmp = $mainData[0]->getID( );
попробуй
$worker = $mainData[0]; // что за бредовое название переменной
var_dump($worker);
$id = $worker->getId( );
В старых версиях PHP вроде нельзя было обращаться напрямую к объекту из массива, в новых можно.
> так как уже день сижу и ничего не могу сделать из-за этой херни.
Учись отлаживать код, хотя бы var_dump-ом.
проверил: >>448970
>>448897
Мануал php перечитать, внешние ключи и транзакции в MySQL, отличия InnoDB от MyISAM, хранение древовидных данных в MySQL. ну и задачки порешать. Вот у меня есть для разминки: https://github.com/codedokode/pasta/blob/master/interview-tasks.md
Так, вообще не угадаешь что спросят.
>>448883
> То есть, какого $mainData типа
Должен быть массив объектов
> и как достучаться в ней до N-ной строки?
$mainData[12]->something
Если это не работает, сделай var_dump($mainData) и покажи результат.
>>448964
> У меня запрос подтягивает несколько таблиц, значит нужно создавать еще один класс?
Нет. Если например ты выбираешь список постов, а через джойн число комментов к ним, то это идет в маппер постов, а не комментов.
Но если ты хочешь например выбрать все комменты к посту то это надо делать в маппере комментов.
То есть смотри по смыслу какая таблица основная.
>>448998
Да
>>449000
> $tmp = $mainData[0]->getID( );
попробуй
$worker = $mainData[0]; // что за бредовое название переменной
var_dump($worker);
$id = $worker->getId( );
В старых версиях PHP вроде нельзя было обращаться напрямую к объекту из массива, в новых можно.
> так как уже день сижу и ничего не могу сделать из-за этой херни.
Учись отлаживать код, хотя бы var_dump-ом.
Не работает, как я и говорил. Вот var_dump($mainData):
array(2) {
\t[0]=> object(Entry)#5 (3) {
\t\t["ID":protected]=> string(2) "25" ["fullname":protected]=> string(4) "ntcn" ["company"]=> string(9) "iuytgfryu"
\t}
\t[1]=> object(Entry)#6 (3) {
\t\t["ID":protected]=> string(2) "26" ["fullname":protected]=> string(4) "тест" ["company"]=> string(6) "kjeokg"
\t}
}
В чем проявляется «не работает»? Сообщения об ошибках выводятся?
В PHP по умолчанию выключено отображение ошибок в браузере, так как обычному пользователю сайта эта информация ни к чему. Но тебе, как программисту, надо видеть эти ошибки. Вот, как можно их просмотреть:
- ошибки сохраняются в лог ошибок. Можно открыть его и почитать. Если ты запускаешь код на локалхосте, у себя, то лог хранится в папке Апача (обычно она называется logs) и имеет название вроде error.log (в линуксе в папку /var/log/apache2 ). Если на хостинге — там либо есть файл error.log либо раздел в панели управления, где лог можно посмотреть
- также, ты можешь включить отображение ошибок. Открой файл php.ini, поставь там display_errors = On и error_reporting = E_ALL и перезапусти сервер. Теперь ошибки должны выводиться на экран.
Проверить, работает ли вывод ошибок, можно запустив скрипт содержающий обращение к несуществующей переменной вроде echo $sdgasdad; и проверив, выведется ошибка или нет. Если все верно, то должна вывестись.
>$worker = $mainData[0]; // что за бредовое название переменной
>var_dump($worker);
>$id = $worker->getId( );
Вот вывод:
object(Entry)#5 (3) { ["ID":protected]=> string(2) "25" ["fullname":protected]=> string(4) "ntcn" ["company"]=> string(9) "iuytgfryu" }
>>449013
>В чем проявляется «не работает»? Сообщения об ошибках выводятся?
Ну я же уже показывал ошибку в одном из постов (кроме этой надписи страничка пустая):
>Fatal error: Call to a member function getID() on a non-object in D:\*\edit.php on line 17
>лог хранится в папке Апача
Мой Nginx в логах выдает только одну ошибку, и она дублируется из странички:
>[11-Mar-2015 11:22:06 Europe/Moscow] PHP Fatal error: Call to a member function getID() on a non-object in D:\*\edit.php on line 17
У меня php 5.3 и в php.ini уже включено отображение ошибок:
>error_reporting = E_ALL & ~E_NOTICE | E_STRICT
>display_errors = On
>Это неправильное выражение. Скобки {} задают число повторений
А мануал пишет, что их использовать можно.
http://php.net/manual/en/regexp.reference.delimiters.php
Для всех может быть полезно вот такое (добавь к себе в мануалы, плз):
if ((bool)$data) {
\t// выполняется только если $data не пустая. работает с массивами объектов
}
Ты что-то путаешь. Твой Var_dump показывает что в переменной объект:
> object(Entry)
>>449016
Зависит от того как они выводятся. Я не вижу тут сложностей. В HTML есть аттрибуты чтобы помечать выбранные варианты (checked/selected), остается только вывести эти атрибуты.
>>449018
> rror_reporting = E_ALL & ~E_NOTICE | E_STRICT
Это значит скрывать часть сообщений об ошибках. Странная настройка, логичнее ставить просто E_ALL. Я вообще не представляю, в чем смысл скрывать часть ошибок? Ошибки надо исправлять, а не скрывать.
У тебя проблема не в этом. Ты что-то перепутал, например запускаешь старую версию кода или не так прочитал номер строки или редактируешь не тот файл.
$array[12]->method() работает без проблем если в массиве есть нужный элемент.
Если его нет, должно выдаться предупреждение которое впрочем ты (или администратор сервера) успешно отключил через error_reporting.
>>449022
Ты прав. Я думал ты приводишь не все выражение целиком, а фрагмент.
Но использовать {} плохая идея так как {} исплоьзуется для задания числа повторов. Лучше нейтральные символы, вроде # или ! или /
> Странно другое - почему в цикле эта ошибка не возникает, а если обратиться к конкретному элементу - возникает.
ты обращаешься к несуществующему элементу в массиве. Проблема не в php а в твоем кривом коде и отключенных сообщениях об ошибках.
> if ((bool)$data) {
bool писать не надо так как if любые выражения приводит к bool сам. Мануал:
http://php.net/manual/ru/control-structures.if.php
http://php.net/manual/ru/language.types.boolean.php#language.types.boolean.casting
Пока в учебник добавить не могу так как сейчас мы там не проходим boolean, а давать магиеские непонятно как работающие конструкции я не могу, все должно объясняться.
Вижу пока решение - в контроллере в index вешаю условия - проверку существования get параметров со значениями фильтров, а там в зависимости от типа добавлять условия Like, =, between. Но мне решение кажется кривым, есть какие-то варианты сделать красиво?
Ну так зачем проверку передаваемых параметров пихать в роуты? Это же явно дело контроллера, в роуте просто указать допустипые значения, можно конечно валидацию на роутер повесить, но это будет через чур, хотя есть в ларавельке роут биндинг, вот пруф: http://laravel.com/docs/5.0/routing#route-model-binding
ссылка начиналась с http у меня, мануал читал, там написано по умолчанию он не добавляет адрес сайта. да и если это делает редактор, почему он на локальном сервере то-же самое не повторяет? я же говорю, всё точь в точь переношу на хостинг и начинается вот эта хуйня.
Решил проблему записью контента не в файл, а в бд.
> да и если это делает редактор, почему он на локальном сервере то-же самое не повторяет?
Разные настройки или разное имя домена. Ты можешь проверить, кто виноват, если откроешь инспектор в браузере (Ctrl + Shift + I) на вкладке Network и посмотришь что конкретно отправляется на сервер из редактора: HTML код с нормальными ссылками или искаженными.
> Решил проблему записью контента не в файл, а в бд.
Вряд ли дело в этом было.
>Считает неверно: 3 + 3 + 3 + 3 + 3 != 22
Это я в цикле вывода немного затупил, все ок считает.
>static это та же самая глобальная переменная, приносящая побочные эффекты.
Я понял недостатки, но как тогда заполнять массив? Если не использовать глобальные переменные и передавать массив в качестве аргумента, как $pathDone, то внутри if вместо добавления значения создается новый массив с единственным значением, вне if заполняется как надо. Я видимо чего-то просто не знаю, гугл говорит использовать глобальные переменные, может плохо искал.
>$tempTime — непонятно зачем это
Это затем, чтобы передавать только значение времени пройденного шага, иначе foreach выдаст сумму всех возможных шагов, а извне foreach не могу придумать, как еще добраться до единственного нужного значения.
До собеседования мне дали тестовое задание, где сверстать простую страничку на которой можно оставлять комментарии.
Сделал все норм, накосячил немного в верстке.
На собеседование дали тест с кучей элементарной теории типо "принципы ооп" и "Типы в пхп" , а я не помню нихрена этого, ну волновался еще, даже забыл, как строчку в бд вставить. Пиздос.
Не большой тест по практике норм прошел.
Потом спросил зачем я отдельный класс для мапера и комента сделал мол нужно было все в 1 или наследование какое нибудь сделать.
Сказал посмотрит других кандидатов и позвонит.
Чувствую впечатления я не произвел.
Данные которые нужны функции передавай через аргменты. Возвращай через return.
> Это затем, чтобы передавать только значение времени пройденного шага, иначе foreach выдаст сумму всех возможных шагов, а извне foreach не могу придумать, как еще добраться до единственного нужного значения.
Это можно сделать без лишнего аргумента. Например, сохранять время в какую-нибудь переменную.
Если ты не очень силен в рекурсии, могу дать дополнительные задачки на рекурсию (если я их не давал тебе раньше).
> зачем я отдельный класс для мапера и комента сделал мол нужно было все в 1 или наследование какое нибудь сделать.
Нужно было сказать что тебе (к примеру) больше нравится паттерн DataMapper и пересказать содержимое урока https://gist.github.com/codedokode/c4cbc4d7dc8e45ea074a или статьи http://habrahabr.ru/post/198450/ ну и схему из книги Мартина Фаулера нарисовать вдобавок: http://design-pattern.ru/patterns/data-mapper.html (сколько там классов? два).
Я думаю, судя по описанию, собеседующий ожидал решения на ActiveRecord. Может быть он например привык к фреймворку Yii где он используется или еще какие-то другие причины.
Ну и я думаю, если бы ты мог своими словами сказать, что написано выше, то это было бы ок, а если ты объяснить не можешь то это выглядит как будто ты сам не понимаешь что и зачем пишешь (ну мне кажется, к начинающему без опыта не надо предъявлять такие требования — все же в паттернах должен разбираться программист с каким-то опытом).
> а я не помню нихрена этого, ну волновался еще, даже забыл, как строчку в бд вставить.
Потому я советую перед собеседованием перечитать мануал php, желательно целиком. Там любят всякие вопросы вроде хитрого преобразования типов задавать, которые только на собедедовании и нужны.
Ну и судя по вопросам, тебе досталось не самое простое собеседование, у других анонам вроде попроще вещи спрашивали.
В любом случае стоит наверно не огорчаться, а исправлять пробелы в знаниях.
В рекурсии я не силен, да. Например ты говоришь сохранять время в переменную вместо аргумента, а как передать эту переменную следующему вызову функции, если не в аргументе? Кроме аргумента и глобальной переменной мне ничего в голову не приходит.
А зачем тебе ее передавать? Ты можешь приьавлять tempTime не после вызова, а до. А чтобы tempTime не складывались все в кучу, завести допольнительную переменную.
Задачки хочешь если не силен? Можно решать параллельно.
1) Сделай функцию, которая находит N-е число Фибоначчи. Числа Фибоначчи определяются так:
- первое число равно 0
- второе равно 1
- третье и далее равно сумме 2 предыдущих чисел.
Вот ряд чисел Фибоначчи: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144....
2) Дана маска и имя файла. Напиши функцию, определяющую, соответствует ли имя файла маске? В маске можно использовать символы вопроса ? который соответствует ровно одному любому символу, и звездочки, которая соответствует 0 или больше любых символов. Пустая маска соответствует только пустому имени файла. Пpимеры:
match("f???.txt", "file.txt") -> true
match("f×", "file.txt") -> true
match("f????×txt", "file.txt") -> false
match("×", "") -> true
× здесь обозначает звездочку
3) Есть синие, красные и зеленые шары. Синий стоит 1 тугрик и весит 5 килограмм. Красный стоит 3 тугрика и весит 3 килограмма. Зеленый стоит 5 тугриков и весит 2 кг. Помоги гному определить, какие шары надо купить, чтобы получить максимальное их количество. Гном может унести не более 50 кг и у него с собой только 50 тугриков.
Реши задачу таким образом, чтобы число шаров легко можно было поменять, например добавить оранжевые и желтые шары.
Если что, это задача о ранце (к ней же относится и задача про банкомат с любыми банкнотами). Она имеет нерекурсивное, оптимальное решение, но оно сложное и наша цель изучить рекурсию, так что реши ее рекурсивно.
А зачем тебе ее передавать? Ты можешь приьавлять tempTime не после вызова, а до. А чтобы tempTime не складывались все в кучу, завести допольнительную переменную.
Задачки хочешь если не силен? Можно решать параллельно.
1) Сделай функцию, которая находит N-е число Фибоначчи. Числа Фибоначчи определяются так:
- первое число равно 0
- второе равно 1
- третье и далее равно сумме 2 предыдущих чисел.
Вот ряд чисел Фибоначчи: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144....
2) Дана маска и имя файла. Напиши функцию, определяющую, соответствует ли имя файла маске? В маске можно использовать символы вопроса ? который соответствует ровно одному любому символу, и звездочки, которая соответствует 0 или больше любых символов. Пустая маска соответствует только пустому имени файла. Пpимеры:
match("f???.txt", "file.txt") -> true
match("f×", "file.txt") -> true
match("f????×txt", "file.txt") -> false
match("×", "") -> true
× здесь обозначает звездочку
3) Есть синие, красные и зеленые шары. Синий стоит 1 тугрик и весит 5 килограмм. Красный стоит 3 тугрика и весит 3 килограмма. Зеленый стоит 5 тугриков и весит 2 кг. Помоги гному определить, какие шары надо купить, чтобы получить максимальное их количество. Гном может унести не более 50 кг и у него с собой только 50 тугриков.
Реши задачу таким образом, чтобы число шаров легко можно было поменять, например добавить оранжевые и желтые шары.
Если что, это задача о ранце (к ней же относится и задача про банкомат с любыми банкнотами). Она имеет нерекурсивное, оптимальное решение, но оно сложное и наша цель изучить рекурсию, так что реши ее рекурсивно.
> Это я в цикле вывода немного затупил, все ок считает.
Тогда ждем работающую версию. Ну и чтобы можно было рассчитать нескоько маршрутов и ничего не ломалось.
И еще. Ты требуешь указать при вызове функции начальные значения переменных:
$pathDone = [];
func(...., $pathDone);
Это надо заменить на аргументы по умолчанию, чтобы pathDone не надо было передавать при первом вызове: http://php.net/manual/ru/functions.arguments.php
Ну он вообще не понимал зачем два класса для "одной сущности".
А я говорил что разделяю взаимодействие с бд и класс и то что читал что так лучше.
var_dump если ты отлаживаешь код и потом удалишь.
echo если программа должна что-то вывести.
Ну и echo выводить только строки и числа, а var_dump все что угодно.
>>449116
А название паттерна ты сказал? Видимо собеседующий привык к ActiveRecord или ты как-то криво реализовал DataMapper что не понятно, что это именно он. Ну или собеседующий не слышал про такой паттерн.
Хорошим выходом было бы наверно сказать «мне больше нравится Data Mapper по таким-то причинам, но если надо, я могу сделать реализацию ActiveRecord».
Ну то есть если ты будешь знать оба паттерна то сможешь угодить и тем кому нравится один (и Yii), и тем, кому другой (и Symfony 2).
>Тогда ждем работающую версию. Ну и чтобы можно было рассчитать нескоько маршрутов и ничего не ломалось.
На данный момент работающая версия выглядит так, если я правильно понял про твое пожелание по аргументам по умолчанию.
http://ideone.com/LE3NM5
Кроме переполнения памяти из-за применения глобальных переменных ей ничего не грозит вроде как.
>А зачем тебе ее передавать? Ты можешь приьавлять tempTime не после вызова, а до. А чтобы tempTime не складывались все в кучу, завести допольнительную переменную.
Не понимат, надо подумать.
Задачки потрогаю, но потом, хочется уже эту добить.
Нет, конечно проверка в контроллере. В целом - мне кажется
If (Input::get('product')) {
$prod->where('product', 'like', '%'.Input::get('product').'%');
}
If (Input::get('price')) {
$prod->where('price', '=', Input::get('price'));
}
чем то неправильным.
При 700 постах? Ты наверно новичок тут.
>>449142
Что неправильного? Query Builder как раз предназначен для составления запросов. Другой вопрос что это надо в модели делать наверно а не в контроллере, но тогда придется массив или объект критериев делать и передавать.
> where('price', '=', Input::get('price'));
А это экранируется? Там нет SQL inj?
>Сессия тут излишня, так как все данные есть в GET.
Писать обработчик на той же страничке что и форма? Я как-то привык всю дрочь с формами выносить в formhandler.php, а оттуда через сессию обратно, если это плохо поясни чем?
><textarea><?=$_SESSION['textarea']; ?></textarea>
>У тебя XSS
Ну я ж по-быстрому чисто идею передать.
А чего тогда тред на 4-й странице? /pr стал популярен на фоне "да мне пох на курс гравны, у меня зп в долларах на одеске"?
>Я как-то привык всю дрочь с формами выносить в formhandler.php, а оттуда через сессию обратно, если это плохо поясни чем?
Поясни за это вот.
тот анон, что задавал изначальный вопрос
Попробовал сделать твою задачу про номера, шаблон кое как допилил, чтобы все правильные номера показывались как правильные и наоборот, но никак не соображу, почему перечислив все номера и перед тем как завершить цикл, код выводит один лишний элемент? Я в else что-то не дописал? И ещё, что ему не нравится в строках 18 и 21?
http://ideone.com/qesP1N
>Может быть урок поможет https://gist.github.com/codedokode/65d43ca5ac95c762bc1a
Я прочел твой урок, и смог усвоить только то что лучше написать свой класс исключений чем пользоваться сразу всеми.
А вот насчет второго, так и не разобрался почему
>не надо писать try/catch. PHP по умолчанию завершает программу с ошибкой если исключение долетит до самого верха. Да еще и в логи эту ошибку запишет в отличие от твоего кода.
Как тогда этим пользоваться?
Вот давай, например, возьмем мою попытку написать исключение >>448470
Мне не нужно было писать try\catch только?
Алсо, я не очень понимаю как работают исключения и как написать функции с колбеком. Давай я напишу сейчас пару простых(по сложности на пару часов) программ, чтобы я увидел принцип их работы? Могу даже сам попробовать придумать себе задачу.
ну просто посылаешь все данные из формы не в index.php, это стремно как по мне, а в отдельную страницу которая нигде не выводится в браузер, а только черную работу делает. через <form action='formhandler.php'>
в этом формхандлере как обычно ловится субмит, геты, посты, выполняются все нужные действия (проверка, запись в базу, запись в сессию ошибок и вот этих значений что тебе нужны) и редирект обратно через header('Location'). возможно это плохая практика, я сам ньюфаг, пусть кто-то разубедит.
идет что-то типа выплаты, по фиксированной сумме, потом этот долг, становится меньше, а он продолжает платить ту же сумму и из-за этого, уходит в минус, а как сделать, чтоб допустим, он заплатил заместо 3тыщ, 2500 когда это нужно будет. хз понятно ли
Ну я бы сделал проверку: Если оставшаяся сумма меньше фиксированной ставки, то оставшейся сумме присваиваем ноль, а модуль от оставшейся суммы и фиксированной ставки мы возвращаем выплачивающему.
Модуль вычисляться с помощью функции abs($x);
http://php.net/manual/ru/function.abs.php
это вообще самый очевидный способ, можно сделать как-нибудь и посложней :3
//Не ОП//
>а модуль от разности оставшейся суммы и фиксированной ставки мы возвращаем выплачивающему.
fix
>всё плохо?
Ну вообще можно и так.
Дождись ОПа, это он задачку придумывал, он тебе скажет, если что-то не так :3
.....
Задание: напиши программу для учета расходов и результатов работы всего дружного коддектива компании «Вектор».
Пока ты решал задачу по выводу отчета о сотрудниках и департаментах, разразился мировой экономический кризис.
Доходы компании начали снижаться, и совет директоров поставил перед руководством задачу принять меры.
Менеджеры 3-го ранга, блестящие выпускники топовых экономических вузов столицы, быстро смогли разработать
три альтернативных антикризисных решения:
1. Сократить в каждом департаменте 40% (округляя в большую сторону) инженеров, преимущественно самого низкого ранга.
Если инженер является боссом, вместо него надо уволить другого инженера, не босса.
2. Увеличить в целях стимуляции умственной деятельности базовую ставку аналитика с 800 до 1100 тугриков,
а количество выпиваемого им кофе с 50 до 75 литров. В тех департаментах, где руководитель не является аналитиком,
заменить его на аналитика самого высшего ранга из этого департамента (а бывшего руководителя вернуть к обычной работе)
3. В каждом департаменте повысить 50% (округляя в большую сторону) менеджеров 1-го и 2-го ранга на один ранг с целью расширить их полномочия.
Совет директоров в затруднении: какой путь выбрать? Помоги им с этим, распечатав прогноз по потреблению и расходам
(аналогичный тому что требуется в задаче) после принятия каждой из мер.
-----
Я тебе советую сделать это задание, так как оно поможет лучше разбираться в ООП-подходе.
По моим прикидкам при правильном коде это потребует дописать строк 40-50, что на мой взгляд немного.
Сразу предупрежу, что антикризисный код вроде «уволить 30% сотрудников» не должен быть в классе Департамент
(так как бороться с кризисом задача руководства компании, а не департамента), но ты можешь написать в департаменте
универсальные методы вроде «уволить указанных сотрудников» или «выбрать N% сотрудников определенного типа».
Также, тебе скорее всего понадобится метод клонирования компании,
чтобы сделать несколько копий компании и принять в каждой из них нужные меры.
>Также, тебе скорее всего понадобится метод клонирования компании
Новый класс "Компания" описывать?
Или создать массив с клонами департаментов? Но в таком случае это не будет методом.
>В тех департаментах, где руководитель не является аналитиком,
заменить его на аналитика самого высшего ранга из этого департамента
А если в департаменте нет аналитика? Оставить как есть?
.....
Задание: напиши программу для учета расходов и результатов работы всего дружного коддектива компании «Вектор».
Пока ты решал задачу по выводу отчета о сотрудниках и департаментах, разразился мировой экономический кризис.
Доходы компании начали снижаться, и совет директоров поставил перед руководством задачу принять меры.
Менеджеры 3-го ранга, блестящие выпускники топовых экономических вузов столицы, быстро смогли разработать
три альтернативных антикризисных решения:
1. Сократить в каждом департаменте 40% (округляя в большую сторону) инженеров, преимущественно самого низкого ранга.
Если инженер является боссом, вместо него надо уволить другого инженера, не босса.
2. Увеличить в целях стимуляции умственной деятельности базовую ставку аналитика с 800 до 1100 тугриков,
а количество выпиваемого им кофе с 50 до 75 литров. В тех департаментах, где руководитель не является аналитиком,
заменить его на аналитика самого высшего ранга из этого департамента (а бывшего руководителя вернуть к обычной работе)
3. В каждом департаменте повысить 50% (округляя в большую сторону) менеджеров 1-го и 2-го ранга на один ранг с целью расширить их полномочия.
Совет директоров в затруднении: какой путь выбрать? Помоги им с этим, распечатав прогноз по потреблению и расходам
(аналогичный тому что требуется в задаче) после принятия каждой из мер.
-----
Я тебе советую сделать это задание, так как оно поможет лучше разбираться в ООП-подходе.
По моим прикидкам при правильном коде это потребует дописать строк 40-50, что на мой взгляд немного.
Сразу предупрежу, что антикризисный код вроде «уволить 30% сотрудников» не должен быть в классе Департамент
(так как бороться с кризисом задача руководства компании, а не департамента), но ты можешь написать в департаменте
универсальные методы вроде «уволить указанных сотрудников» или «выбрать N% сотрудников определенного типа».
Также, тебе скорее всего понадобится метод клонирования компании,
чтобы сделать несколько копий компании и принять в каждой из них нужные меры.
>Также, тебе скорее всего понадобится метод клонирования компании
Новый класс "Компания" описывать?
Или создать массив с клонами департаментов? Но в таком случае это не будет методом.
>В тех департаментах, где руководитель не является аналитиком,
заменить его на аналитика самого высшего ранга из этого департамента
А если в департаменте нет аналитика? Оставить как есть?
http://ideone.com/b9XzZo
пытаюсь задачу о гноме сделать. Пока что не могу понять, почему он стартует только с зеленых шаров.
Не могу понять, почему просто не проходит по всем возможным комбинациям. Видимо у меня такая же ошибка как в задаче с поиском пути, и я не понимаю какой-то нюанс.
а, ну я понял, наверное потому что циклы прерываются с первым ретерном, и ПРИЕХАЛИ. Нужно ретернить вне цикла как-то.
Нет, стоит.
Я знаю, что если строку записать в двойных кавычках, в нее можно подставить переменную: echo "Сумма равна $sum".
Что тогда происходит здесь, почему переменные php берутся в одинарные кавычки:
$query = "INSERT INTO tbl_name ( title, count ) VALUES ( '$title', '$count' )";
В sql запросе потому что можно поля таблиц и прочие можно в кавычки оборачивать, а можно и не оборачивать. Эти кавычки не мешают переменным подставляться, так как строка по прежнему обернута в двойные.
смотри сюда: http://ideone.com/XNwY6v
Ты можешь их убрать как бы и поэкспериментировать сам с этим всем.
Моя тупая голова до сих пор не может понять нахер нужны интерфейсы. Это же просто имена методов, так? И зачем?
Теория заебала, понимаю.
Попробуй написать что-то простое, чтобы понять как оно работает. Поймешь основы, дальше можно будет спокойно повышать сложность по нарастающей.
Например, вот такая элементарная задача. Напиши приложение, которое будет выводить из базы все статьи новостей, одна за другой.
Как в новостной ленте вк, или в бложиках, ну ты понял. Название, текст статьи, можно дату еще. Но не будем усложнять. Плюс тут же на странице форма для добавления новой статьи.
Смотри, какая тут логика. MVC подразумевает разделение кода на модель и контроллер (а также "представление", или вид, то есть голый ХТМЛ с подставляемыми пхп-переменными).
Модель и контроллер - это классы, которые содержат методы (плюс вспомогательные свойства).
В модели хранятся методы (функции) для работы с данными, в нашем случае очевиден вывод и сохранение статей в БД.
Я назвал эти методы getAllArticles для выборки и save для сохранения:
http://ideone.com/reN8hx
Контроллер имеет методы, которые дергаются в зависимости от того, по какому УРЛ пришел пользователь. В нашем случае это одностраничный бложик, поэтому метод только один, назовем его actionIndex.
В этом методе мы прописываем условие, что если человек пришел постом, т.е. он отправил форму (хочет добавить статью), то мы эту статью добавляем в БД, потом при помощи вышеупомянутого метода модели getAllArticles получаем объект, в котором хранится массив записей, которые мы и выводим в нашем хтмл-шаблоне.
За вывод у меня отвечает метод render. Это жалкая попытка написать свой шаблонизатор, но вроде бы достаточно наглядно.
http://ideone.com/iIvQwR
Шаблон
http://ideone.com/lAaYTr
Итак, подытожим. Как работает эта безделушка:
1) Пользователь запрашивает index.php, в котором создается экземпляр объекта контроллера $controller = new MainController; и дергается его метод $controller->actionIndex();
Фактически в этом файле только эти две строки, плюс инклюды классов модели и контроллера.
2) В этом методе, если пользователь пришел постом, то отправленные из формы данные добавятся в бд $model->save().
3) Далее запрашиваются записи из БД, мы получаем объект $data = $model->getAllArticles();
4) Теперь нам нужно получить хтмл на основе этих данных, то есть отрисовать, отрендерить статьи.
У меня этим занимается псевдо-шаблонизатор метод render при помощи стандартных функций file_get_contents и str_replace. Предварительно получаем сконкатенированную строку в цикле.
Вот теперь попробуй написать это приложение на основе моих черновиков. Я пропустил проверку форм, подготовленные запросы и т.д. Но в целом как-то так.
Теория заебала, понимаю.
Попробуй написать что-то простое, чтобы понять как оно работает. Поймешь основы, дальше можно будет спокойно повышать сложность по нарастающей.
Например, вот такая элементарная задача. Напиши приложение, которое будет выводить из базы все статьи новостей, одна за другой.
Как в новостной ленте вк, или в бложиках, ну ты понял. Название, текст статьи, можно дату еще. Но не будем усложнять. Плюс тут же на странице форма для добавления новой статьи.
Смотри, какая тут логика. MVC подразумевает разделение кода на модель и контроллер (а также "представление", или вид, то есть голый ХТМЛ с подставляемыми пхп-переменными).
Модель и контроллер - это классы, которые содержат методы (плюс вспомогательные свойства).
В модели хранятся методы (функции) для работы с данными, в нашем случае очевиден вывод и сохранение статей в БД.
Я назвал эти методы getAllArticles для выборки и save для сохранения:
http://ideone.com/reN8hx
Контроллер имеет методы, которые дергаются в зависимости от того, по какому УРЛ пришел пользователь. В нашем случае это одностраничный бложик, поэтому метод только один, назовем его actionIndex.
В этом методе мы прописываем условие, что если человек пришел постом, т.е. он отправил форму (хочет добавить статью), то мы эту статью добавляем в БД, потом при помощи вышеупомянутого метода модели getAllArticles получаем объект, в котором хранится массив записей, которые мы и выводим в нашем хтмл-шаблоне.
За вывод у меня отвечает метод render. Это жалкая попытка написать свой шаблонизатор, но вроде бы достаточно наглядно.
http://ideone.com/iIvQwR
Шаблон
http://ideone.com/lAaYTr
Итак, подытожим. Как работает эта безделушка:
1) Пользователь запрашивает index.php, в котором создается экземпляр объекта контроллера $controller = new MainController; и дергается его метод $controller->actionIndex();
Фактически в этом файле только эти две строки, плюс инклюды классов модели и контроллера.
2) В этом методе, если пользователь пришел постом, то отправленные из формы данные добавятся в бд $model->save().
3) Далее запрашиваются записи из БД, мы получаем объект $data = $model->getAllArticles();
4) Теперь нам нужно получить хтмл на основе этих данных, то есть отрисовать, отрендерить статьи.
У меня этим занимается псевдо-шаблонизатор метод render при помощи стандартных функций file_get_contents и str_replace. Предварительно получаем сконкатенированную строку в цикле.
Вот теперь попробуй написать это приложение на основе моих черновиков. Я пропустил проверку форм, подготовленные запросы и т.д. Но в целом как-то так.
>Используй в шаблоне версии конструкций if/foreach c двоеточием
ОП, а использование циклов в шаблоне не является тем, что похерит всю суть шаблонов?
Вообще, ты конечно мог бы тут обойтись без рекурсии. Взять например, алгоритм Дейкстры для поиска пути. Но раз уж ты захотел пойти по более сложному пути, это твое право конечно.
> работающая версия выглядит так
Она не работающая: http://ideone.com/luxX14
Она не работает потому, что ты используешь глобальную переменную, сваливаешь все результаты туда и когда мы вызываем функцию второй раз, оставшиеся в переменной результаты первого вызова искажают результат.
Я опять намекаю, что использовать глобальные переменные — плохая идея.
Сейчас у тебя функция ничего не возвращает. Но можно сделать так, чтобы она возвращала например найденный маршрут (или null если его проложить не удалось). Тогда глобальные переменные будут не нужны.
> Кроме переполнения памяти из-за применения глобальных переменных ей ничего не грозит вроде как.
Это тоже плохо.
> Задачки потрогаю, но потом, хочется уже эту добить.
Если ты понимаешь как, давай добьем. Если нет, то лучше более простые задачки порешать.
> если я правильно понял про твое пожелание по аргументам по умолчанию.
Я не вижу тут аргментов по умолчанию. Аргументы по умолчанию это когда пишут так:
function ($a, $b = 2) { ... }
почитай мануал http://php.net/manual/ru/functions.arguments.php#functions.arguments.default
Вообще, ты конечно мог бы тут обойтись без рекурсии. Взять например, алгоритм Дейкстры для поиска пути. Но раз уж ты захотел пойти по более сложному пути, это твое право конечно.
> работающая версия выглядит так
Она не работающая: http://ideone.com/luxX14
Она не работает потому, что ты используешь глобальную переменную, сваливаешь все результаты туда и когда мы вызываем функцию второй раз, оставшиеся в переменной результаты первого вызова искажают результат.
Я опять намекаю, что использовать глобальные переменные — плохая идея.
Сейчас у тебя функция ничего не возвращает. Но можно сделать так, чтобы она возвращала например найденный маршрут (или null если его проложить не удалось). Тогда глобальные переменные будут не нужны.
> Кроме переполнения памяти из-за применения глобальных переменных ей ничего не грозит вроде как.
Это тоже плохо.
> Задачки потрогаю, но потом, хочется уже эту добить.
Если ты понимаешь как, давай добьем. Если нет, то лучше более простые задачки порешать.
> если я правильно понял про твое пожелание по аргументам по умолчанию.
Я не вижу тут аргментов по умолчанию. Аргументы по умолчанию это когда пишут так:
function ($a, $b = 2) { ... }
почитай мануал http://php.net/manual/ru/functions.arguments.php#functions.arguments.default
Интерфейсы очень нужны ведущим программистам при проектировании архитектуры крупного проекта.
Полностью согласен, что только обдрысные мудаки забивают новичкам голову такими вещами в своих книгах или уроках.
Пока у тебя не будет хоть какого-то опыта, даже не пытайся понять.
Тебе достаточно знать, что интерфейс это абстрактный класс, который имеет только абстрактные методы. Все.
Не страдай над ебанутой теорией, пробуй что-то писать.
Скоро перекатимся.
>>449149
> Ну я ж по-быстрому чисто идею передать.
Учишь неправильному. Надо всегда писать код с экранированием символов чтобы те, кто копируют примеры, не делали ошибок.
>>449149
> если это плохо поясни чем?
Тем что сессия тут излишняя и все данные есть в GET. Передать их можно обычными переменными не создавая сессий.
>>449169
> PHP Notice: Undefined offset: 24 in /home/JFIn34/prog.php on line 18
Ты пытаешься взять из массива элемент с индексом 24, а его там нет. Это ошибка.
Если в массиве 7 элементов и они пронумерованы с 0, то индексы идут от 0 до 6, а 7-го там нету.
> \\s?-?\\s?\\(?\\s?[0-9]\\s?\\)?\\s?-?\\s?
Можно наверно было просто написать
1 цифра + любое число скобок, пробелов, минусов
Так было бы проще.
Исправь баг с undefined offset и я думаю, задача будет решена.
Скоро перекатимся.
>>449149
> Ну я ж по-быстрому чисто идею передать.
Учишь неправильному. Надо всегда писать код с экранированием символов чтобы те, кто копируют примеры, не делали ошибок.
>>449149
> если это плохо поясни чем?
Тем что сессия тут излишняя и все данные есть в GET. Передать их можно обычными переменными не создавая сессий.
>>449169
> PHP Notice: Undefined offset: 24 in /home/JFIn34/prog.php on line 18
Ты пытаешься взять из массива элемент с индексом 24, а его там нет. Это ошибка.
Если в массиве 7 элементов и они пронумерованы с 0, то индексы идут от 0 до 6, а 7-го там нету.
> \\s?-?\\s?\\(?\\s?[0-9]\\s?\\)?\\s?-?\\s?
Можно наверно было просто написать
1 цифра + любое число скобок, пробелов, минусов
Так было бы проще.
Исправь баг с undefined offset и я думаю, задача будет решена.
> лучше написать свой класс исключений чем пользоваться сразу всеми.
Это да. Свой класс исключений лучше, так как ты если ты захочешь их перехватывать, то сможешь перехватывать только их.
Но с другой стороны если программа маленькая и перехватывать их ты не будешь, можно и не делать, а использовать стандартный Exception или одно из SPL иключений: http://php.net/manual/ru/spl.exceptions.php
> так и не разобрался почему
>> PHP по умолчанию завершает программу с ошибкой если исключение долетит до самого верха. Да еще и в логи эту ошибку запишет в отличие от твоего кода.
Давай сравним 2 варианта:
1) не ловить исключения через try/catch
2) ловить исключения через try/catch и через echo выводить сообщение
— Пользователь видит подробности ошибки? 1 - настраивается в php.ini, 2 - всегда да.
— Информация об исключении пишется в логи? 1 — да, 2 — нет
Как видишь вариант 1 дает больше возможностей и требует меньше кода.
В веб-приложениях обычно исключения ловятся только на самом верхнем уровне, чтобы при исключении вывести страницу 503 ошибки с заглушкой.
> Мне не нужно было писать try\catch только?
да, не надо перехватывать исключение в данной ситуации так как это ничего не дает.
> я не очень понимаю как работают исключения
При непредвиденной ошибке ты выбрасываешь исключение. По умолчанию оно завершает программу, но тот кто вызывает функцию, может его перехватить с помощью try/catch если захочет и например что-то сделать в этом случае.
Но если например в функцию передали что-то неправильное и она выбросила исключение, то перехватывть такое исключение незачем. Надо просто исправить код чтобы в функцию не передавались неправильные аргументы.
> Давай я напишу сейчас пару простых(по сложности на пару часов) программ, чтобы я увидел принцип их работы? Могу даже сам попробовать придумать себе задачу.
Сделай свои аналоги функций array_map и array_filter. Как они работают, ты можешь увидеть в мануале. Если ты знаком с классом SplObjectStorage, то сделай чтобы они работали с этим классом. То есть принимали и возвращали объект этого класса.
> лучше написать свой класс исключений чем пользоваться сразу всеми.
Это да. Свой класс исключений лучше, так как ты если ты захочешь их перехватывать, то сможешь перехватывать только их.
Но с другой стороны если программа маленькая и перехватывать их ты не будешь, можно и не делать, а использовать стандартный Exception или одно из SPL иключений: http://php.net/manual/ru/spl.exceptions.php
> так и не разобрался почему
>> PHP по умолчанию завершает программу с ошибкой если исключение долетит до самого верха. Да еще и в логи эту ошибку запишет в отличие от твоего кода.
Давай сравним 2 варианта:
1) не ловить исключения через try/catch
2) ловить исключения через try/catch и через echo выводить сообщение
— Пользователь видит подробности ошибки? 1 - настраивается в php.ini, 2 - всегда да.
— Информация об исключении пишется в логи? 1 — да, 2 — нет
Как видишь вариант 1 дает больше возможностей и требует меньше кода.
В веб-приложениях обычно исключения ловятся только на самом верхнем уровне, чтобы при исключении вывести страницу 503 ошибки с заглушкой.
> Мне не нужно было писать try\catch только?
да, не надо перехватывать исключение в данной ситуации так как это ничего не дает.
> я не очень понимаю как работают исключения
При непредвиденной ошибке ты выбрасываешь исключение. По умолчанию оно завершает программу, но тот кто вызывает функцию, может его перехватить с помощью try/catch если захочет и например что-то сделать в этом случае.
Но если например в функцию передали что-то неправильное и она выбросила исключение, то перехватывть такое исключение незачем. Надо просто исправить код чтобы в функцию не передавались неправильные аргументы.
> Давай я напишу сейчас пару простых(по сложности на пару часов) программ, чтобы я увидел принцип их работы? Могу даже сам попробовать придумать себе задачу.
Сделай свои аналоги функций array_map и array_filter. Как они работают, ты можешь увидеть в мануале. Если ты знаком с классом SplObjectStorage, то сделай чтобы они работали с этим классом. То есть принимали и возвращали объект этого класса.
У меня есть урок про работу с формами, для тех кому интересно: https://github.com/codedokode/pasta/blob/master/forms.md
>>449226
> if ($creditBalance > $monthlyPayment) {
здесь ошибочка. Ты сравниваешь сумму до добавления процентов и комиссии. Например ты взял в долг 4000. Банк на них начислит проценты и комиссию и выйдет допустим 5120. И ты будешь выплчивать долг 2 месяца.
А твоя программа увидит что 4000 < 5000 и выплатит все сразу, не учтя проценты и комиссию.
надо сначала добавить проценты и комиссию, а потом сравнивать, а не наоборот.
>>449236
> Новый класс "Компания" описывать?
> Или создать массив с клонами департаментов?
как хочешь. Мне кажется сделать объект-компанию было бы неплохо.
> А если в департаменте нет аналитика? Оставить как есть?
да. Если заменить невозможно то оставляем какого есть.
>>449240
Решал бы наши задачи (из ОП поста) про список студентов и файлообменник, научился бы сам.
>>449254
> label{
Ты переопределяешь этим все лейблы на странице. Это плохая идея. Надо на корневой див твоего блока поставить какой-то уникальный класс и все селекторы начинать с этого класса. Чтобы они влияли только на твои элементы.
> .hiddencontent{
>\tposition: absolute;
>\ttop:-9999px;
Почему исплоьзуешь такой странный способ скрытия? Почему не display none?
Насчет анимации: действительно, display нельзя анимировать, а если элемент меняет состояние с видимого на скрытый то анимации не работают. Но вот тут (англ) описаны интересные обходные пути: http://www.taccgl.org/blog/css_transition_display.html
Может тебе что-то пригодится.
Попробуй сделать чтобы при переключении табов текст например менял прозрачность с полностью прозрачного на непрозрачный. И например выезжал из задвинутого на 30-50 пикселей влево состояния.
Кроме переходов (transiotion), в CSS есть покадровая (keyframe) анимация, читал про нее? Надо хотя бы знать что это такое.
А, и еще, раз ты верстку изучаешь, почитай что можно сделать из одного дива: http://habrahabr.ru/company/paysto/blog/251933/ (это конечно баловство, для таких вещей лучше SVG использовать).
> #tab1:checked ~ #one,
Это лучше сделать через классы. Тогда мы можем сделать несколько блоков с табами на странице.
У меня есть урок про работу с формами, для тех кому интересно: https://github.com/codedokode/pasta/blob/master/forms.md
>>449226
> if ($creditBalance > $monthlyPayment) {
здесь ошибочка. Ты сравниваешь сумму до добавления процентов и комиссии. Например ты взял в долг 4000. Банк на них начислит проценты и комиссию и выйдет допустим 5120. И ты будешь выплчивать долг 2 месяца.
А твоя программа увидит что 4000 < 5000 и выплатит все сразу, не учтя проценты и комиссию.
надо сначала добавить проценты и комиссию, а потом сравнивать, а не наоборот.
>>449236
> Новый класс "Компания" описывать?
> Или создать массив с клонами департаментов?
как хочешь. Мне кажется сделать объект-компанию было бы неплохо.
> А если в департаменте нет аналитика? Оставить как есть?
да. Если заменить невозможно то оставляем какого есть.
>>449240
Решал бы наши задачи (из ОП поста) про список студентов и файлообменник, научился бы сам.
>>449254
> label{
Ты переопределяешь этим все лейблы на странице. Это плохая идея. Надо на корневой див твоего блока поставить какой-то уникальный класс и все селекторы начинать с этого класса. Чтобы они влияли только на твои элементы.
> .hiddencontent{
>\tposition: absolute;
>\ttop:-9999px;
Почему исплоьзуешь такой странный способ скрытия? Почему не display none?
Насчет анимации: действительно, display нельзя анимировать, а если элемент меняет состояние с видимого на скрытый то анимации не работают. Но вот тут (англ) описаны интересные обходные пути: http://www.taccgl.org/blog/css_transition_display.html
Может тебе что-то пригодится.
Попробуй сделать чтобы при переключении табов текст например менял прозрачность с полностью прозрачного на непрозрачный. И например выезжал из задвинутого на 30-50 пикселей влево состояния.
Кроме переходов (transiotion), в CSS есть покадровая (keyframe) анимация, читал про нее? Надо хотя бы знать что это такое.
А, и еще, раз ты верстку изучаешь, почитай что можно сделать из одного дива: http://habrahabr.ru/company/paysto/blog/251933/ (это конечно баловство, для таких вещей лучше SVG использовать).
> #tab1:checked ~ #one,
Это лучше сделать через классы. Тогда мы можем сделать несколько блоков с табами на странице.
Вот еще может интересно будет почитать http://habrahabr.ru/post/247731/ (хотя опять же лучше бы SVG использовать).
>>449259
> Пока что не могу понять, почему он стартует только с зеленых шаров.
функция берет один зеленый шар, и вызывает себя рекурсивно. та добавляет еще один шар и вызвыает себя и так далее.
> потому что циклы прерываются с первым ретерном, и ПРИЕХАЛИ. Нужно ретернить вне цикла как-то.
да
>>449335
Ну если ты очень усердно будешь заниматься то может и за 3 месяца управишься, но я не уверен.
>>449350
Мануал
http://phpclub.ru/mysql/doc/literals.html
http://phpclub.ru/mysql/doc/string-syntax.html
По стандарту SQL нужны одинарные кавычки, но MySQL разрешает и двойные. В других базах данных двойные использовать нельзя.
Также, не вставляй переменные прямо в запрос. это ведет к SQL инъекциям:
> ( '$title', '$count' )";
Ты наверно учился по устаревшему учебнику. Сейчас все используют PDO и плейсхолдеры для полдстановки значений:
http://habrahabr.ru/post/137664/
Почитать про SQL инъекцию можно тут:
https://ru.wikipedia.org/wiki/%D0%92%D0%BD%D0%B5%D0%B4%D1%80%D0%B5%D0%BD%D0%B8%D0%B5_SQL-%D0%BA%D0%BE%D0%B4%D0%B0
http://forum.antichat.ru/thread43966.html
Вот еще может интересно будет почитать http://habrahabr.ru/post/247731/ (хотя опять же лучше бы SVG использовать).
>>449259
> Пока что не могу понять, почему он стартует только с зеленых шаров.
функция берет один зеленый шар, и вызывает себя рекурсивно. та добавляет еще один шар и вызвыает себя и так далее.
> потому что циклы прерываются с первым ретерном, и ПРИЕХАЛИ. Нужно ретернить вне цикла как-то.
да
>>449335
Ну если ты очень усердно будешь заниматься то может и за 3 месяца управишься, но я не уверен.
>>449350
Мануал
http://phpclub.ru/mysql/doc/literals.html
http://phpclub.ru/mysql/doc/string-syntax.html
По стандарту SQL нужны одинарные кавычки, но MySQL разрешает и двойные. В других базах данных двойные использовать нельзя.
Также, не вставляй переменные прямо в запрос. это ведет к SQL инъекциям:
> ( '$title', '$count' )";
Ты наверно учился по устаревшему учебнику. Сейчас все используют PDO и плейсхолдеры для полдстановки значений:
http://habrahabr.ru/post/137664/
Почитать про SQL инъекцию можно тут:
https://ru.wikipedia.org/wiki/%D0%92%D0%BD%D0%B5%D0%B4%D1%80%D0%B5%D0%BD%D0%B8%D0%B5_SQL-%D0%BA%D0%BE%D0%B4%D0%B0
http://forum.antichat.ru/thread43966.html
> поля таблиц и прочие
Идентификаторы в разных БД используют разные кавычки. MySQL использует косые, другие базы данных двойные кавычки или квадратные скобки.
>>449369
> примеры что я встречаю совершенно надуманные.
Согласен. А ты решал задачу про ООО вектор или кошки-мышки? Там по моему чуть менее надуманно (я голову сломал пока придумывал примеры для объяснения ООП).
> Типа, давайте создадим класс Животное
В приложениях это будут классы вроде: Студент, МапперСтудентовНаТаблицуВБазеДанных, СервисПоРаботеСоСтудентами, HTTPЗапрос, HTTPОтвет, Кука, КоллекцияЗаголовков.
Что ходить вокруг да около? Давай посмотрим на реальные ООП PHP библиотеки:
HTTP-клиент (библиотека для отправки запросов по протоколу HTTP, ей напрмиер можно скачать страницу сайта или файл) Guzzle: https://github.com/guzzle/guzzle
Микрофреймворк Slim: https://github.com/slimphp/Slim
Библиотека для отправки электронных писем swiftmailer: https://github.com/swiftmailer/swiftmailer
Посмотри эти проекты, посмотри какие там файлы. Это конечно сложно для начинающего (который не изучал паттерны проектирования), но ты ведь сам хотел хардкора? Тебе пока не обязательно понимать как все это работает, главное увидеть как вообще выглядит реальный ООП код.
Не бойся, тебя никто не заставит сразу писать аналогичный код. Сначала будут более легкие задачи.
> Вот я имиджборду хочу запилить, допустим, где тут эти птицы и рыбы?
Классы Пост, Тред, классы для сохранения их в БД, классы-контроллеры (контроллер это термин из MVC — класс который принимает запрос (например на добавление поста) от браузера пользователя пользователя, вызывает нужные методы модели и отображает результат пользователю).
Мы будем делать задачу про список студентов (заглянуть в будущее: https://github.com/codedokode/pasta/blob/master/student-list.md ) — там нужен ООП и никаких Рыб и Собак тебе делать не придется.
> Как мне должно приходить в голову "вот! эту проблему лучше всего решить с помощью абстрактного класса"?
Опыт. Большинство задач имеет готовое решение (это называется паттерны проектирования), если например ты используешь фреймворк то достаточно погуглить. А со временем ты все это запомнишь, я надеюсь.
Ну и есть подходы вроде MVC когда в код разбивается на Контроллер, Модель и Представление.
В ходе решения задач про студентов ты познакомишься с паттернами работы с БД и чуть-чуть с MVC.
> поля таблиц и прочие
Идентификаторы в разных БД используют разные кавычки. MySQL использует косые, другие базы данных двойные кавычки или квадратные скобки.
>>449369
> примеры что я встречаю совершенно надуманные.
Согласен. А ты решал задачу про ООО вектор или кошки-мышки? Там по моему чуть менее надуманно (я голову сломал пока придумывал примеры для объяснения ООП).
> Типа, давайте создадим класс Животное
В приложениях это будут классы вроде: Студент, МапперСтудентовНаТаблицуВБазеДанных, СервисПоРаботеСоСтудентами, HTTPЗапрос, HTTPОтвет, Кука, КоллекцияЗаголовков.
Что ходить вокруг да около? Давай посмотрим на реальные ООП PHP библиотеки:
HTTP-клиент (библиотека для отправки запросов по протоколу HTTP, ей напрмиер можно скачать страницу сайта или файл) Guzzle: https://github.com/guzzle/guzzle
Микрофреймворк Slim: https://github.com/slimphp/Slim
Библиотека для отправки электронных писем swiftmailer: https://github.com/swiftmailer/swiftmailer
Посмотри эти проекты, посмотри какие там файлы. Это конечно сложно для начинающего (который не изучал паттерны проектирования), но ты ведь сам хотел хардкора? Тебе пока не обязательно понимать как все это работает, главное увидеть как вообще выглядит реальный ООП код.
Не бойся, тебя никто не заставит сразу писать аналогичный код. Сначала будут более легкие задачи.
> Вот я имиджборду хочу запилить, допустим, где тут эти птицы и рыбы?
Классы Пост, Тред, классы для сохранения их в БД, классы-контроллеры (контроллер это термин из MVC — класс который принимает запрос (например на добавление поста) от браузера пользователя пользователя, вызывает нужные методы модели и отображает результат пользователю).
Мы будем делать задачу про список студентов (заглянуть в будущее: https://github.com/codedokode/pasta/blob/master/student-list.md ) — там нужен ООП и никаких Рыб и Собак тебе делать не придется.
> Как мне должно приходить в голову "вот! эту проблему лучше всего решить с помощью абстрактного класса"?
Опыт. Большинство задач имеет готовое решение (это называется паттерны проектирования), если например ты используешь фреймворк то достаточно погуглить. А со временем ты все это запомнишь, я надеюсь.
Ну и есть подходы вроде MVC когда в код разбивается на Контроллер, Модель и Представление.
В ходе решения задач про студентов ты познакомишься с паттернами работы с БД и чуть-чуть с MVC.
Интерфейс это набор требований к классу. «требование» здесь значит требование чтобы в классе был определенный метод.
Если класс реализует интерфейс, в нем обязаны быть эти методы.Обычно интерфйес представляет собой какое-то умение: классы, реализующие этот интерфейс, умеют что-то делать.
Допустим мы делаем сайт где можно ставить лайки постам и комментам. Допустим у нас есть классы User, Post и Comment.
Вот у нас есть пост и коммент, мы можем увеличить число лайков, допустим методом increaseLikeCount и узнавать сколько у них лайков методом getLikeCount, то есть у них есть что-то общее, но как описать это в коде? Как сказать что эти 2 класса в отличие от других умеют работать с лайками?
Второй пример, мы хотим сделать функцию, которая допустим ставит лайк от определенного пользователя определенному посту или комментарию:
function addLike(User $user, $object) ...
Мы сказали что $user должен быть объектом класса User, а как сказать что $object должен быть классом, умеющим работать с лайками?
Обе проблемы решают интерфейсы. Объявим интерфейс Likeable, который представляет собой умение получать лайки. Опишем какие методы обязаны реализовать такие классы:
interface Likeable
{
public function increaseLikeCount( );
public function getLikeCount( );
}
Теперь укажем в коде что посты и комменты можно лайкать:
class Post implements Likeable { ... }
class Comment implements Likeable { ... }
на этом этапе php проверит, не забыли ли мы реализовать в классах упомянутые методы. Если забыли — выдаст ошибку. Как удобно!
Ну и теперь мы можем использовать интерфейс чтобы указать какие аргументы принимает функция addLike:
function addLike(User $user, Likeable $object) { ... }
заметь что благодаря интферйесам наш код стал расиряем. Допустим завтра мы добавим класс Photo который тоже можно лайкать. Если он будет реализовывать интерфейс Likeable то функция вроде addLike сможет работать и с ним без переписывания кода.
В общем интерфейс представляет какую-то способность класса и требует от него реализовать определенные методы.
Задавай вопросы.
Интерфейс это набор требований к классу. «требование» здесь значит требование чтобы в классе был определенный метод.
Если класс реализует интерфейс, в нем обязаны быть эти методы.Обычно интерфйес представляет собой какое-то умение: классы, реализующие этот интерфейс, умеют что-то делать.
Допустим мы делаем сайт где можно ставить лайки постам и комментам. Допустим у нас есть классы User, Post и Comment.
Вот у нас есть пост и коммент, мы можем увеличить число лайков, допустим методом increaseLikeCount и узнавать сколько у них лайков методом getLikeCount, то есть у них есть что-то общее, но как описать это в коде? Как сказать что эти 2 класса в отличие от других умеют работать с лайками?
Второй пример, мы хотим сделать функцию, которая допустим ставит лайк от определенного пользователя определенному посту или комментарию:
function addLike(User $user, $object) ...
Мы сказали что $user должен быть объектом класса User, а как сказать что $object должен быть классом, умеющим работать с лайками?
Обе проблемы решают интерфейсы. Объявим интерфейс Likeable, который представляет собой умение получать лайки. Опишем какие методы обязаны реализовать такие классы:
interface Likeable
{
public function increaseLikeCount( );
public function getLikeCount( );
}
Теперь укажем в коде что посты и комменты можно лайкать:
class Post implements Likeable { ... }
class Comment implements Likeable { ... }
на этом этапе php проверит, не забыли ли мы реализовать в классах упомянутые методы. Если забыли — выдаст ошибку. Как удобно!
Ну и теперь мы можем использовать интерфейс чтобы указать какие аргументы принимает функция addLike:
function addLike(User $user, Likeable $object) { ... }
заметь что благодаря интферйесам наш код стал расиряем. Допустим завтра мы добавим класс Photo который тоже можно лайкать. Если он будет реализовывать интерфейс Likeable то функция вроде addLike сможет работать и с ним без переписывания кода.
В общем интерфейс представляет какую-то способность класса и требует от него реализовать определенные методы.
Задавай вопросы.
Также использование интерфейсов делает код более гибким. Если ты указываешь конкретный класс то можно передать только объект этого класса или наследников:
fucntion addLike(Post $post)
А если интерфейс то любой класс который его реализует. В том числе новые классы о которых не было известно в момент создания функции:
fucntion addlike(Likeable $likeable)
Ну и пока ты не берешься за фреймворки типа Yii, Symfony 2, интерфейсы особо не нужны. Но профессиональный программист конечно должен умело ими жонгшировать.
Еще интерфейсы помогают при написании библиотек. Ты пишешь какую-то функцию (которой будут пользоваться другие люди) и с помощью интерфейса ты можешь определить требования к объектам которые будут передавать в эту функцию. PHP не позволит их нарушить.
>>449387
У нас уже есть хорошее задание на список студентов с подробными комментариями. лучше наверно его сделать: https://github.com/codedokode/pasta/blob/master/student-list.md
Ну и вынужден прокомментировать твой пост, чтобы оградить людей от ошибок. Это хорошо, что ты помогаешь анону разобраться, спасибо, но неточности я должен исправить.
У тебя в коде SQL инъекция так как ты вставляешь данные прямо в запрос. Надо использовать плейсхолдеры. Не надо ради упрощения писать небезопасный код. Это путает.
> В этом методе мы прописываем условие, что если человек пришел постом, т.е. он отправил форму (хочет добавить статью)
для этого лучше сделать отдельное действие. Вывод списка статей и добавление все же разные вещи.
> За вывод у меня отвечает метод render
Очень неудачно сделано, так как у тебя «шаблонизатор» заточен на вывод данных из PDoStatement. Никто так не делает, обычно данные в шаблонизатор передают в виде массива. Шаблонизатор не должен быть привязан к базе данных. Этим ты размазываешь логику работы с Бд по всему приложению, это плохо.
Должен быть класс, который возвращает массив массивов (или лучше объектов) из БД и отдельно класс или функция выводящая переданные данные и не знающая о БД ничего.
Ну и прежде чем писать шаблонизатор почитай полезный совет под номером 6: http://habrahabr.ru/post/230737/
> $model = new Model;
Это тоже по сути ошибка. В реальных приложениях нет класса Model. Модель это не название класса, а общее название части кода которая занимается хранением и обработкой данных предметной области.
Твой класс по моему называется TableDataGateway (описание http://design-pattern.ru/patterns/table-data-gateway.html )
После обработки формы не надо выводить страницу, надо редиректить чтобы нажатие F5 не отправляло форму повторно.
Еще интерфейсы помогают при написании библиотек. Ты пишешь какую-то функцию (которой будут пользоваться другие люди) и с помощью интерфейса ты можешь определить требования к объектам которые будут передавать в эту функцию. PHP не позволит их нарушить.
>>449387
У нас уже есть хорошее задание на список студентов с подробными комментариями. лучше наверно его сделать: https://github.com/codedokode/pasta/blob/master/student-list.md
Ну и вынужден прокомментировать твой пост, чтобы оградить людей от ошибок. Это хорошо, что ты помогаешь анону разобраться, спасибо, но неточности я должен исправить.
У тебя в коде SQL инъекция так как ты вставляешь данные прямо в запрос. Надо использовать плейсхолдеры. Не надо ради упрощения писать небезопасный код. Это путает.
> В этом методе мы прописываем условие, что если человек пришел постом, т.е. он отправил форму (хочет добавить статью)
для этого лучше сделать отдельное действие. Вывод списка статей и добавление все же разные вещи.
> За вывод у меня отвечает метод render
Очень неудачно сделано, так как у тебя «шаблонизатор» заточен на вывод данных из PDoStatement. Никто так не делает, обычно данные в шаблонизатор передают в виде массива. Шаблонизатор не должен быть привязан к базе данных. Этим ты размазываешь логику работы с Бд по всему приложению, это плохо.
Должен быть класс, который возвращает массив массивов (или лучше объектов) из БД и отдельно класс или функция выводящая переданные данные и не знающая о БД ничего.
Ну и прежде чем писать шаблонизатор почитай полезный совет под номером 6: http://habrahabr.ru/post/230737/
> $model = new Model;
Это тоже по сути ошибка. В реальных приложениях нет класса Model. Модель это не название класса, а общее название части кода которая занимается хранением и обработкой данных предметной области.
Твой класс по моему называется TableDataGateway (описание http://design-pattern.ru/patterns/table-data-gateway.html )
После обработки формы не надо выводить страницу, надо редиректить чтобы нажатие F5 не отправляло форму повторно.
> а использование циклов в шаблоне не является тем, что похерит всю суть шаблонов?
Нет. Все шаблонизаторы их реализуют в той или иной мере, даже в XSLТ есть for-each. Как ты без циклов выведешь список?
И раз уж ты заговорил про «суть шаблонов», может ты объяснишь в чем она заключается?
По моему шаблон это штука которая выводит данные в соответствии с заложенными в него правилами.
У Фаулера кстати и для шаблонов (точнее представления) есть паттерны проектирования. Это TransformView (что-то странное и непрактичное: http://design-pattern.ru/patterns/transform-view.html ) и Template View (типичный шаблонизатор вроде PHP, Twig или XSLT: http://design-pattern.ru/patterns/template-view.html )
Ну и фактически шаблонизатор дает тебе отдельный язык программирования/разметки, а в языке программирования могут быть циклы, а почему нет?
>>449391
> очень нужны ведущим программистам при проектировании архитектуры крупного проекта.
Это неудачное обяъснение так как складывается впечатление что норимальным программистам они не нужны что неверно.
> Пока у тебя не будет хоть какого-то опыта, даже не пытайся понять.
Ты просто не можешь объяснить и запутываешь анона. Ничего сверхсложного в интерфейсах нет, если подобрать хорошие примеры.
> интерфейс это абстрактный класс, который имеет только абстрактные методы
Неверно. Интерфейс это не класс.
> , пробуй что-то писать.
У нас есть задания для этого. Где впрочем все равно придется повозиться с теорией.
И ты зря создаешь PDO прямо в классе работы с БД. Код будет аккуратнее если создавать его снаружи и передавать через констурктор (говоря по умному, сделать внедрение зависимости (Delendency Injection) через конструктор).
В общем и целом понял ошибку и исправил, единственный вопрос, нормально исправил, или это на костыль похоже?
http://ideone.com/qesP1N
(шаблон решил не менять, пробовал поиграться с другими последовательностями и *, но тут или там парочка верных номеров перестают соответствовать, хрен с ним уже, в любом случае спасибо, поднапрягся, понравилось:3
> нормально исправил, или это на костыль похоже?
Не нормально. Ты мог бы поменять <= на < а вместо этого нагородмл переменных. А еще лучше, использовать foreach
ps сильно не бей.
<?php
error_reporting(-1);
$opName = 'молодец';
$opTrueName = 'хуй';
$text = 'оп всё таки...';
$i = mt_rand(1,10);
for (echo $text; $i <= 10; $i++) {
\techo "$opTrueName/n";
\t$score++;
}
\t
Блядь, как то хуёво копировалось. Перепощу в новый тредж.
Вот и еще одно собеседование, которое я провел весьма достойно(не омежничал, ответил уверенно и хорошо на все вопросы, сделал практическую часть, ответил на теоретическую часть). АшЭр кивал и улыбался, Прогер сказал, что я малаца и все верно ответил\решил и вот мне сказали, что решение будет в среду максимум. Сегодня четверг, а это значит что меня в очередной раз пидорнули с вакансией. Ходить дальше думаю смысла нет, это не первый раз, а денег нет. Так вот думаю начать фрилансить помалой, но как начать? Посмотрел на одеск там какой-то пиздец, какие-то поиски в свою команду, какие-то тесты на fluent english по скайпу, какие-то требования, быть индусом\филипинцем. Как найти себе работу\подработку на пыхе? Кто фрилансит поясните нубу попонятней, плз.
сап, аноны, нужна помощь.
Делаю сайт. И вот дошел до момента, где необходимо перейти по адресу: localhost/tools/phpmyadmin чтобы создать БД. Но при переходе по данной ссылке выдает следующеее:
Добро пожаловать в phpMyAdmin
Ошибка
Ответ MySQL:
#2002 - .
Сервер не отвечает (либо локальный сокет сервера MySQL неверно настроен).
Ошибка при указании соединения для controluser в конфигурации.
попутылася запустить msql через командную строку - выдает ошибку 2003 - типа не модет установить соединение с базой
Вы видите копию треда, сохраненную 27 марта 2015 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.