Это копия, сохраненная 14 мая 2015 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
Это тред для начинающих. Не написал за свою жизнь ни одной программы? Ты наш человек.
Устанавливать пока что ничего не требуется, разве что редактор кода вроде Sublime Text 3, Notepad++, Netbeans PHP или PhpStorm (необязательно).
Предыдущий тред был тут: >>454789
Правила: ведем себя воспитанно, помогаем новичкам, постим ссылки на решения задачек, ОП их проверяет и дает советы и замечания. ОП отвечает даже на самые нубские вопросы. ОП заходит где-то раз в день, не жди его, решай задачки дальше.
У нас есть уроки по основам PHP, они собраны и выложены по адресу http://archive-ipq-co.narod.ru/ Это учебник для изучающих с нуля, то есть если ты вообще ничего не знаешь, то надо начать с него. Он простой и понятный (по крайней мере в начале). Там есть задачи, их надо решать обязательно (чтобы стать программистом, надо писать код — иначе никак). Пости ссылки на решения в тред, мы их проверим, напишем замечания и дадим советы по улучшению.
Если не знаешь как решать, запости код, напиши в каком месте остановился и попроси подсказку.
Учебник дает основы языка PHP, но чтобы делать сайты, этого недостаточно. Если ты его прошел, то надо переходить в более серьезным задачкам, которые научат тебя как выдавать страницы в браузер, работе с таблицами в БД, работе с формами, MVC.
- Простая, но полезная задача сделать список студентов: https://github.com/codedokode/pasta/blob/master/student-list.md
- Более сложная задача сделать файлообменник на микрофреймворке 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:
Подскажи сайты для поиска работы, я не умею гуглить? brainstorage.me, geekjob.ru, hh.ru
Нужен ли ООП, фреймворки, 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
Что делать, если не третью задачу ОПа?
Сделал файлообменик, стал ходить по собеседованием, делал простенькие тестовые задания, немного js дрочил, а сейчас совсем завист.
Нужно всё таки yii2 дрочить.
Может мне подскажешь что-нибудь? Я вот пытаюсь с ООП разбираться на примере вектора. И в общем как удалять объекты? Я не могу уволить долбанных инженеров из департамента. Нихера не получается что-то. Вроде прочитал про деструкторы. Ну а что толку, у меня чет ничего не работает.
Попробова что-то такое, и вроде бы удаляет через unset http://ideone.com/fm5DZw
Но в моем коде не хочет почему-то.
http://ideone.com/fzwKZy
Я особо не разбирался(учебник ОПа не читал),
но почему нельзя просто удалить работника из массива воркеров?
ну я пишу unset($работник)
И это не дает у меня никакого эффекта. В мануале написано, что так удаляется объект.
А так я не могу удалять просто из массива работников, я сначала выбираю тех кого мне надо удалить в другой массив, и потом уже удаляю только тех кто мне нужен.
Нет, если я вардампаю его, то у меня он как был так и остается. делать форич через & тоже не помогает.
http://ideone.com/57jbdT
слайс тебе точно не нужен
мне лень вникать, но ты же можешь идти по общему массиву воркеров, проверять нужные условия и делать унсет?
объекты не по ссылке передаются в переменные, а копируются
http://ideone.com/qbhspj
Кто- то из нас кого-то не понимает.
Я говорю о ускорении в ~100 раз. Может есть совершенно другой подход?
%^*! Не то написал. По логике надо из изначального массива "увольнять", а из TargetEngineers брать индексы.
Ну думаю раз с браузера все ок, значит с хеадером затупил. Прописал всякие юзер агенты, кодировки - таже 500 ошибка.
Я хз меня может там забанили? До этого пару месяцев работало, а тут приключения какие то. Я и курл пробовал, даже пост запросы отправлял - не работает ничего. Почему так?
я извлекаю не массив, а объект, как ты мог заметить. Через массив то ясно как получить названия. Мне нужно именно через mysql_fetch_object
Объект удаляется сборщиком мусора когда на него не остается ни одной ссылки. но тебе не надо уничтожать объект. Тебе достаточно удалить его из массива сотрудников в департементе (у нас же задача уволить а не уничтожить сотрудника).
Как удалить элемент из масссива?
1) unset $array[$key];
2) array_splice(...)
Найти $key можно например функцией array-search. Перед тем как искать объект в массиве прочитай про строгое и нестрогое сравнение объектов http://php.net/manual/ru/language.oop5.object-comparison.php (в 99% тебе нужно строгое сравнение так как тебе надо уволить конкретного человека а не другого с такими же значениями свойств)
Это разумеется надо делать не снаружи департамента, а изнутри (так надежнее, чем когда каждый сможет делать что угодно с массивом). Удобно сделать метод уволитьРаботника(работник) например. У тебя же есть метод добавитьРаботника? Логично сделать и метод для увольнения.
Кстати, если тебе надо именно уничтожать сотрудника (например он проиграл битву и был убит в игре) то для этого удобно сделать поле $alive и менять его с true на false.
>>461375
Также ты можешь яваскрипт помучать и задачу по SQL если не делал ее. Ну и Юи тоже неплохо, хотя там задача довольно большая.
>>461376
> $fireHim->__destruct( );
Деструктор не уничтожает объект (так же как конструктор не создает). Он лишь вызывается перед ничтожением.
> //unset($fireHim);
Это не удаляет объект из списка работников департамента, это удаляет лишь локальную переменную.
Объект удаляется сборщиком мусора когда на него не остается ни одной ссылки. но тебе не надо уничтожать объект. Тебе достаточно удалить его из массива сотрудников в департементе (у нас же задача уволить а не уничтожить сотрудника).
Как удалить элемент из масссива?
1) unset $array[$key];
2) array_splice(...)
Найти $key можно например функцией array-search. Перед тем как искать объект в массиве прочитай про строгое и нестрогое сравнение объектов http://php.net/manual/ru/language.oop5.object-comparison.php (в 99% тебе нужно строгое сравнение так как тебе надо уволить конкретного человека а не другого с такими же значениями свойств)
Это разумеется надо делать не снаружи департамента, а изнутри (так надежнее, чем когда каждый сможет делать что угодно с массивом). Удобно сделать метод уволитьРаботника(работник) например. У тебя же есть метод добавитьРаботника? Логично сделать и метод для увольнения.
Кстати, если тебе надо именно уничтожать сотрудника (например он проиграл битву и был убит в игре) то для этого удобно сделать поле $alive и менять его с true на false.
>>461375
Также ты можешь яваскрипт помучать и задачу по SQL если не делал ее. Ну и Юи тоже неплохо, хотя там задача довольно большая.
>>461376
> $fireHim->__destruct( );
Деструктор не уничтожает объект (так же как конструктор не создает). Он лишь вызывается перед ничтожением.
> //unset($fireHim);
Это не удаляет объект из списка работников департамента, это удаляет лишь локальную переменную.
> В мануале написано, что так удаляется объект.
Ты удаляешь только локальную переменную в которой хранится ссылка на объект. Ссылку на объект в массиве работников ты при этом не трогаешь и она остается.
Удаляя переменную ты не удаляешь объект, так как в ней только ссылка на него.
>>461396
Из таргет ничего не удаляется, это легко проверить через вар дамп. Он удаляет просто локальную переменную.
>>461395
А зачем ты выбираешь данные объектом-псевдомассивом? Выбирай их в массив.
>>461399
> Нет, если я вардампаю его, то у меня он как был так и остается.
Потому что ты ничего из него не удалял. смотри, в массиве хранится ссылка (идентификатор) объекта. Форич копирует его (идентификатор) в переменную. Ты уничтожаешь переменную. Массив от этого не меняется, сам объект тоже.
> делать форич через & тоже не помогает.
Потому что это удаляет ссылку а не элемент из массива. Прочти раздел про ссылки если ты их используешь: http://php.net/manual/ru/language.references.php
>>461401
Ну и что? Удалить идентификатор объекта из массива можно точно также как удалить строку, той же командой.
>>461412
У тебя запрос неправильно написан. Я тебе написал что подзапросы и ORDER BY RAND неэффективны и могут быть причной тормозов. Значит надо от них избавиться а не искать «другие подходы».
Тебе надо сначала изучить SQL и почитать про оптимизацию запросов и команду EXPLAIN, прежде чем браться за такие задачи. Или найти того кто разбирается и поручить это ему.
> В мануале написано, что так удаляется объект.
Ты удаляешь только локальную переменную в которой хранится ссылка на объект. Ссылку на объект в массиве работников ты при этом не трогаешь и она остается.
Удаляя переменную ты не удаляешь объект, так как в ней только ссылка на него.
>>461396
Из таргет ничего не удаляется, это легко проверить через вар дамп. Он удаляет просто локальную переменную.
>>461395
А зачем ты выбираешь данные объектом-псевдомассивом? Выбирай их в массив.
>>461399
> Нет, если я вардампаю его, то у меня он как был так и остается.
Потому что ты ничего из него не удалял. смотри, в массиве хранится ссылка (идентификатор) объекта. Форич копирует его (идентификатор) в переменную. Ты уничтожаешь переменную. Массив от этого не меняется, сам объект тоже.
> делать форич через & тоже не помогает.
Потому что это удаляет ссылку а не элемент из массива. Прочти раздел про ссылки если ты их используешь: http://php.net/manual/ru/language.references.php
>>461401
Ну и что? Удалить идентификатор объекта из массива можно точно также как удалить строку, той же командой.
>>461412
У тебя запрос неправильно написан. Я тебе написал что подзапросы и ORDER BY RAND неэффективны и могут быть причной тормозов. Значит надо от них избавиться а не искать «другие подходы».
Тебе надо сначала изучить SQL и почитать про оптимизацию запросов и команду EXPLAIN, прежде чем браться за такие задачи. Или найти того кто разбирается и поручить это ему.
ну так извлекай массив. Объект конечно можно преобразовать в массив, но логичнее сразу массив и получать.
Тем более что у тебя не настоящий объект а объект-массив. stdObjeсt это не «настоящий» объект, а фактически массив.
>>461440
q = .$id
может точка виновата? Алсо, вставлять данные в строку запроса надо через процентное кодирование (вики: https://ru.wikipedia.org/wiki/URL#.D0.9A.D0.BE.D0.B4.D0.B8.D1.80.D0.BE.D0.B2.D0.B0.D0.BD.D0.B8.D0.B5_URL ) и urlencode
И ещё пару вопросов по самому сайту, такой сайт лучше всего делать с нуля? или быть может пользоваться какой-то КМС? Хочу дизайн для него такого стиля как например на Хабре или вот на этом сайте http://mtrpl.ru, дизайн такого типа имеет какое-то название?
http://ideone.com/Mbu5l5
ОП, прокомментируй пожалуйста как дойдут руки?
Да, я в общем понимал то, что я работаю лишь со ссылками на объект. И я думал что таким образом можно удалить объект, а оказывается так работает только если у тебя всего 1 ссылка на него, ну и ты такой ансетаешь переменную с этой ссылкой, и соответственно объект удаляется. Но у меня то там много лапши все не так. В общем спасибо за помощь
Да норм дизайн вроде бы, я заметил примерно года 2-3 назад массовый переход многих сайтов на подобный дизайн, вот только не могу понять как он называется, где можно найти подобные шаблоны?
> $allEngineers = array_filter($dep->workers, "Antycrisis::findEngineer");
> $notLeaderEngineers = array_filter($allEngineers, "Antycrisis::findNotLeader");
тут лучше написать анонимную функцию, заодно объединив 2 этих команды. Все равно findEngineer нужен тебе только один раз.
Также, где сортировка? Там надо в первую очередь сотрудников определенного ранга удалять.
> public function fireEmployee($employee)
> {
> \tforeach ($this->workers as $num => $worker) {
Тут лучше использовать array_search, прочти про нее в мануале
> if (is_array($employee)) {
> $this->workers = array_merge($this->workers, $employee);
> } else {
> $this->workers[] = $employee;
это плохо что функция принимает значения разных типов. Это не позволит заметить ошибку когда ты вместо объекта передаешь что-то не то, и не позволяет использовать тайп хинты. Сделай 2 функции с различающимися именами и с тайп хинтами
Некоторые библиотеки/фреймворки используют такой подход (особенно в JS, например jQuery), но я считаю его вредным, усложняющим код и провоцирующим ошибки. Функция которая принимает только объект определенного класса проще и надежнее.
Также, давай закроем массив public $workers = array( ); в депатаменте от публичного доступа и оставим только возможность менять его через методы. А то слишком много свободы получается.
Более того, я не могу представить ни одной ситуации когда тебе нужно на самом деле уничтожать объект. Всегда достаточно удалить ссылку на него из массива или заменить ее на null в таких случаях:
$department->boss = new Manager(...)
$department->boss = null;
А остался этот объект в памяти или удалился это не принципиально.
>>461475
Вот статья про тенденции в дизайне http://habrahabr.ru/post/255287/
Опять работы на три дня :( ну ладно, я сейчас ухожу и вечером постараюсь начать ковыряться.
>Вот статья про тенденции в дизайне http://habrahabr.ru/post/255287/
Спасибо то что надо, я так понял мне нужен Twitter Bootstrap или Flat Design, я в дизайне не разбираюсь практически вообще и никогда почти его не делал, я так понимаю если писать сайт на чистом ПХП всегда можно найти какой-нибудь шаблон для сайта? И прицепить его будет довольно легко?
Зависит от ситуации и от объема выбираемых данных. У меня правильно написанные запросы работают за 1-2 мс.
С выборкой случайного значения без ORDEr BY RAND конечно получается хорошая задача, нам надо оптимизировать запрос так,чтобы он мог использовать индексы и не обходить большое число записей. Реализовать это можно так.
Допустим у нас есть таблица с миллионом записей и надо выбрать случайную. Добавим в нее индексированную колонку random, пропишем в нее числа от 1 до 1 000000. Теперь сгенерируем случайное число от 1 до 100000 и сделаем запрос
SELECT WHERE random >= ? ORDER BY random LIMIT 1
Он прекрасно ложится на индекс и выбирает лишь одну запись.
Но тебе (судя по тому какой ты запрос написал) пока рановато такие вещи делать, тебе надо сначала сам SQL получше изучить. Я тебе давал ссылку на задачки: https://gist.github.com/codedokode/10539213 — там есть и ссылки (в том числе объясняющие индексы), и задачи для проверки знаний. Я советую почитать теорию и решить задачки, запостить решения и я проверю. Лучше потратить время сейчас на изучение, тебе эти знания не раз помогут.
p.s. Мой пример с выборкой случайного элемента будет работать очень быстро при правильных настройках и на нормальном железе, можешь сам проверить. Уж точно не 400 мс.
ну и добавлю еще. Мой способ при некоторых подходах может привести к тому что вероятность выпадения некоторых записей будет выше. Например если у нам были записи с такими значениями random:
random
1
2
3
..
10
А потом по каким-то причинам мы удалили записи с random от 2 до 5:
1
6
7
...
То запись с кandom = 6 будет выпадать гораздл чаще. Чтобы этого избежать, можно периодически крон сркиптом перепроставлять random во всей таблице. В InnoDB чтение вроде не блокиурется так что проблем это вызвать не должно.
Пытаюсь разобрать шаблон http://matthewjamestaylor.com/blog/equal-height-columns-cross-browser-css-no-hacks
(Пикрилейтед)
Итак, почему все три колонки имеют приблизительно одинаковый left (отличается незначительно довольно незначительно)?
html-код странички:
<div id="container3">
<div id="container2">
<div id="container1">
<div id="col1">Column 1</div>
<div id="col2">Column 2</div>
<div id="col3">Column 3</div>
</div>
</div>
</div>
css:
[code]
#container3 {
\tclear:left;
\tfloat:left;
\twidth:100%;
\toverflow:hidden;
\tbackground:#89ffa2; / column 3 background colour: light green /
}
/this container is positioned relatively to the page, it has 100% width, and to right - 33%
For relatively positioned elements, the right property sets the right edge of an element to a unit to the left/right to its normal position.
This means it has offset to the left (from right, sure) by amount of percents (33.333% by default)
/
#container2 {
\tclear:left;
\tfloat:left;
\twidth:100%;
\tposition:relative;
\tright:33.333%;
\tbackground:#ffa7a7; / column 2 background colour: pink/red /
}
/
This container is positioned relatively to the container2
by default it is positioned by 33.33% to the right of its parent,
it is located 66.663% to the right of the page (when evaluating using defaults)
/
#container1 {
\tfloat:left;
\twidth:100%;
\tposition:relative;
\tright:33.33%;
\tbackground:#fff689; / column 1 background colour: yellow /
}
#col1 {
\tfloat:left;
\twidth:29.33%;
\tposition:relative;
\tleft:68.67%;
\toverflow:hidden;
}
#col2 {
\tfloat:left;
\twidth:29.33%;
\tposition:relative;
\tleft:72.67%;
\toverflow:hidden;
}
#col3 {
\tfloat:left;
\twidth:29.33%;
\tposition:relative;
\tleft:76.67%;
\toverflow:hidden;
}
[/code]
css:
[code]
#container3 {
\tclear:left;
\tfloat:left;
\twidth:100%;
\toverflow:hidden;
\tbackground:#89ffa2; / column 3 background colour: light green /
}
/this container is positioned relatively to the page, it has 100% width, and to right - 33%
For relatively positioned elements, the right property sets the right edge of an element to a unit to the left/right to its normal position.
This means it has offset to the left (from right, sure) by amount of percents (33.333% by default)
/
#container2 {
\tclear:left;
\tfloat:left;
\twidth:100%;
\tposition:relative;
\tright:33.333%;
\tbackground:#ffa7a7; / column 2 background colour: pink/red /
}
/
This container is positioned relatively to the container2
by default it is positioned by 33.33% to the right of its parent,
it is located 66.663% to the right of the page (when evaluating using defaults)
/
#container1 {
\tfloat:left;
\twidth:100%;
\tposition:relative;
\tright:33.33%;
\tbackground:#fff689; / column 1 background colour: yellow /
}
#col1 {
\tfloat:left;
\twidth:29.33%;
\tposition:relative;
\tleft:68.67%;
\toverflow:hidden;
}
#col2 {
\tfloat:left;
\twidth:29.33%;
\tposition:relative;
\tleft:72.67%;
\toverflow:hidden;
}
#col3 {
\tfloat:left;
\twidth:29.33%;
\tposition:relative;
\tleft:76.67%;
\toverflow:hidden;
}
[/code]
Спасибо за качественные ответы няша, понял.
Вообще этот метод есть на русском: http://chikuyonok.ru/2009/06/float-columns/
Сам способ довольно замороный, к счастью в большинстве случаев он не требуется и хватает простой верстки с флоатами.
> почему все три колонки имеют приблизительно одинаковый left
А сколько должно быть по твоему? Ты смотрел верстку инспектором в браузере?
Флоат-блоки сами по себе выстраиваются слева направо и если их переносить на разное расстояние то они будут накладываться друг на друга.
Сгенерировать предложение:
"В этом предложении ровно 36 символов"
Хард моде:
"В этом предложении ровно сорок два символа"
Ну я вот делал проект вообще без дизайна, анончик в прошлом треде посоветовал бутстрап - в итоге где-то день заняло все оформить более-менее красиво, учитывая тот факт, что я в дизайне тоже разбираюсь не лучше, чем свинья в апельсинах.
И хочешь еще одну мысль? Если у тебя ширина колонок известна заранее (например 30 + 50 + 20%) то фон можно сделать проще. Мы можем сделать его с помощью абс. поз. дивов, задвинутых на задний план с помощью отрицательного z-index:
<div class="wrapper">
<div class="bg-1"></div><!-- фон для колнки 1-->
<div class="bg-2"></div>
<div class="bg-3"></div>
<div class="col-1">колонка 1</div>
<div class="col-2">колонка 2</div>
<div class="col-3">колонка 3</div>
</div>
Стиль будет вроде такого:
.bg-1 {
pos: a;
h: 100%;
left: 0;
width: 30%;
bg: red;
}
Ну а колонки делаем обычными float + width без relative.
По моему моя схема в разы проще получается.
Она точно так же применима если у нас смешанные размеры, например (200px + сколько осталось + 400px) и в боле сложных случаях типа (200px + (40% + 60% от оставшегося места)) за счет того что а.п. дивы можно вкладывать друг в друга.
Заметь что я использовал h:100% в фоновом диве. Это свойство работает на а.п. дивах, но на обычных оно работает только если у рдителя известна ширина (то есть почти никогда не работает).
Чем мой способ луше способа в статье? 1) проще рассчиытать значения, не надо вычислять на сколько сместить куда колонку 2) проще понять верстку, нет никаких хитрых хаков, все тривиально.
Я бы использовал мой способ.
Но способ в статье я тебе советую изучить потому что это хороший пример для изучения того как работают флоаты в сложных случаях. В качестве задачи попробуй например сделать аналогичную верстку для 2 или 4 колонок и попробуй сделать ширину не в % а например в пикселях (200px + оставшаяся ширина).
Если есть какие-то еще вопросы, я буду рад ответить. Флоаты все же очень важная тема.
И хочешь еще одну мысль? Если у тебя ширина колонок известна заранее (например 30 + 50 + 20%) то фон можно сделать проще. Мы можем сделать его с помощью абс. поз. дивов, задвинутых на задний план с помощью отрицательного z-index:
<div class="wrapper">
<div class="bg-1"></div><!-- фон для колнки 1-->
<div class="bg-2"></div>
<div class="bg-3"></div>
<div class="col-1">колонка 1</div>
<div class="col-2">колонка 2</div>
<div class="col-3">колонка 3</div>
</div>
Стиль будет вроде такого:
.bg-1 {
pos: a;
h: 100%;
left: 0;
width: 30%;
bg: red;
}
Ну а колонки делаем обычными float + width без relative.
По моему моя схема в разы проще получается.
Она точно так же применима если у нас смешанные размеры, например (200px + сколько осталось + 400px) и в боле сложных случаях типа (200px + (40% + 60% от оставшегося места)) за счет того что а.п. дивы можно вкладывать друг в друга.
Заметь что я использовал h:100% в фоновом диве. Это свойство работает на а.п. дивах, но на обычных оно работает только если у рдителя известна ширина (то есть почти никогда не работает).
Чем мой способ луше способа в статье? 1) проще рассчиытать значения, не надо вычислять на сколько сместить куда колонку 2) проще понять верстку, нет никаких хитрых хаков, все тривиально.
Я бы использовал мой способ.
Но способ в статье я тебе советую изучить потому что это хороший пример для изучения того как работают флоаты в сложных случаях. В качестве задачи попробуй например сделать аналогичную верстку для 2 или 4 колонок и попробуй сделать ширину не в % а например в пикселях (200px + оставшаяся ширина).
Если есть какие-то еще вопросы, я буду рад ответить. Флоаты все же очень важная тема.
Поясни, что дано на входе и что надо получить на выходе. Например должно ли предложение быть осмысленным?
А, top забыл!
.bg-1 {
top: 0;
}
Когда используешь а.п. не забывай указать 4 значения для расположения/размера.
Ну это же старая задачка, количество символов в предложении должно совпадать с числом, указанным в предложении.
"В этом предложении ровно сорок два символа".length = 42
Тогда это элементарно:
abcdefghij12
Пишем число и добиваем буквами алфавита до нужной длины.
Совпадает? Совпадает.
потрогал страничку в редакторе в браузере. Получается, нужно рассчитать оптимальный left для последней колонки и подставить его во все колонки. Мне казалось, что left для col2=left для col1 - width col2
У тебя флоаты выстраиваются слева направо:
(колонка 1) (колонка 2) (колонка 3)
их надо сдвинуть вправо на одинаковое расстояние чтобы они не накладывались.
left в относительном поз. показывает на сколько надо сдвинуть блок вправо (надеюсь ты это знаешь), а не где он будет находиться. Это относительное позиционирование, а не абсолютное.
> Мне казалось, что left для col2=left для col1 - width col2
Почитай про относ. позиционирование, мне кажется ты не понял как оно работает. left не задает отступ от левого края экрана. Он задает на сколько элемент смещен вправо: http://softwaremaniacs.org/blog/2005/08/03/css-layout-positioning/
>>left в относительном поз. показывает на сколько надо сдвинуть блок вправо (надеюсь ты это знаешь),
say wut?
Я и правда это не понял, да
вправо относительно непосредственного родителя?
Это не предложение.
Вот я нагуглил тебе еще подобных предложений для примера. Подобные где-то после 130.
http://golovolomka.hobby.ru/humour/selfref.shtml
С одной стороны все три колонки имеют одного родителя. Так как они имеют одинаковое свойство left, то они должны накладываться, так как имеют одинаковое смещение отн. предка
С другой стороны:
На w3school читал, что блок с position:relative ведет себя так же как и обычный блок, а значит, что при обработке браузером разметки блоки "сдвигаются"
if (isset($_SESSION['errors'])) {
print_r($_SESSION['errors'])
}
Или же лучше в логике сделать функцию
function errors() {
if (isset($_SESSION['errors'])) {
print_r($_SESSION['errors'])
} else return;
}
а в шаблоне только
<?=errors(); ?>
Или как еще лучше?
копии объектов? Сомневаюсь что-то, что у меня объекты клонируются, если я пложу разные массивы, в которых они "лежат"
Относительно того места где он был бы без специального позиционирования. Относительное позиционирование просто смещает изображение блока относительно его расположения в потоке. Прочти описание, тут все подробно разжевано: http://softwaremaniacs.org/blog/2005/08/03/css-layout-positioning/
Также тут описано: http://htmlbook.ru/samlayout/blochnaya-verstka/pozitsionirovanie-elementov
Кстати, у нас есть задания на HTML/CSS, которые учат в том числе подобным тонкостям, в первом посте треда есть ссылка.
>>461551
> Так как они имеют одинаковое свойство left, то они должны накладываться, так как имеют одинаковое смещение отн. предка
Неверно. Прочти ссылку.
> На w3school читал, что блок с position:relative ведет себя так же как и обычный блок, а значит, что при обработке браузером разметки блоки "сдвигаются"
Мне кажется ты не совсем понимаешь, о чем речь. Прочти ссылку.
При отн. поз. сначала вычисляется где будет расположен блок без учета позиционирования, а потом он рисуется на экране со смещением указанным в left/top/right/bottom. При этом исходное место в потоке он продолжает занимать. Прочти ссылку.
Объекты клонируются только когда ты пишешь clone, во всех остальных случаях нет.
Клонирование неглубокое. Это значит что объекты внутри клонируемого объекта не клонируются, а копирутся ссылки на них. Ну то есть если ты клонируешь департамент то сотрудники в нем не клонируются, а просто копируются ссылки.
мануал http://php.net/manual/ru/language.oop5.cloning.php
>>461575
Ты что-то путаешь
Проверить клонируется ли объект можно с помощью var_dump. Он выводит уникальный номер объекта по которому можно понять один и тот же это объект или разные.
Смотри номера тут: http://ideone.com/Bcgstx
так я то так и думал, отталкиваясь от вчерашнего коммента ОП-а, о том, что у меня объекты лежат сами по себе и не меняются, а всякие массивы с этими "объектами" по факту лишь ссылки на них
> Если в шаблоне нужно вывести ошибки или вообще любое сообщение допустимо ли в нем писать такое
Нет, это плохая идея. Лучше передавать в него переменную вроде $errors
Хранить ошибки в сессии тоже не лучшая идея. Сессия общая для всех вкладок браузера. Что если пользователь откроет несколько вкладок с формами, не будут ли ошибки из первой вкладки отображаться во второй?
> Или же лучше в логике сделать функцию
Лучше передавать в шаблон переменную $errors, а откуда она берется это не его дело. Шаблон должен выводить те данные которые ему дали и не задумываться откуда они берутся.
Я советую тебе натыкать var_dump и своими глазами проверить что оно копируется или нет. И если увиденное не соответствует твоим ожиданиям то разобраться почему или написать в тред.
>Хранить ошибки в сессии тоже не лучшая идея. Сессия общая для всех вкладок браузера. Что если пользователь откроет несколько вкладок с формами, не будут ли ошибки из первой вкладки отображаться во второй?
А если ошибку убивать unset'ом сразу после вывода?
Ок, понятно, а как насчет стилей, допустим я хочу поле в котором возникла ошибка подсветить красным, вот это будет нормально в шаблоне?
<input class="<?=($errors['username']) ? error : basic-input ; >">
Ну как-то так
<header>шляпа</header>
<?
$include=$_GET['page']
switch ($include) {
case 'registration' : include 'register.php'; break;
case 'profile' : include 'profile.php'; break;
...
}
Вынести ее HTML-код в отдельный файл и писать
require 'header.phtml'
в начале шаблона.
>>461592
Это выглядит как костыль который может быть будет работать. а что если скрипт добавления ошибок в сессию сработал, а страница с формой не загрузилась? Ошибки останутся там до следующего раза.
А зачем вообще хранить ошибки в сессии? Что мешает их сразу выводить?
>>461593
> \tforeach($x as $value) {
>\t\t$value = $i;
$value это не элемент массива, а его копия. Ты меняешь лишь копию.
>>461601
Да, только ты кавычки забыл
>>461607
Не, наверно проще будет шапку/подвал вынести в отдельные файлы и подключать их из основного шаблона.
Вынести ее HTML-код в отдельный файл и писать
require 'header.phtml'
в начале шаблона.
>>461592
Это выглядит как костыль который может быть будет работать. а что если скрипт добавления ошибок в сессию сработал, а страница с формой не загрузилась? Ошибки останутся там до следующего раза.
А зачем вообще хранить ошибки в сессии? Что мешает их сразу выводить?
>>461593
> \tforeach($x as $value) {
>\t\t$value = $i;
$value это не элемент массива, а его копия. Ты меняешь лишь копию.
>>461601
Да, только ты кавычки забыл
>>461607
Не, наверно проще будет шапку/подвал вынести в отдельные файлы и подключать их из основного шаблона.
>А зачем вообще хранить ошибки в сессии? Что мешает их сразу выводить?
У меня ошибка выводится в другом месте, куда я попадаю через header location. По-другому не додумался, как ее сохранить.
Не редиректить при ошибке, а сразу выводить форму. Это общепринятый подход. редиректить надо только при успешном заполнении и обработке формы.
>$value это не элемент массива, а его копия. Ты меняешь лишь копию.
А как поменять элемент массива? В мануале написано что нужно использовать символ &, но даже в таком случае он не работает:
http://ideone.com/JmVoH1
Хочу вот такой эффект сделать http://getbootstrap.com/javascript/#tabs
не совсем понял, что нужно ещё сделать с списком ссылок, вроде всё так же присвоил, и классы и айди дивов.
Вообще-то это все описано в мануале. Читал? http://php.net/manual/ru/control-structures.foreach.php
способ 1
foreach ($a as $k => $v) {
$a[$k] = 1;
способ 2 (хуже)
foreach ($a as &$v) {
$v = 1;
При использовании способа 2 легко допустить ошибку, потому прежде чем им пользоваться прочти мануал http://php.net/manual/ru/language.references.php
Это не важно. Важно что после успешной обработки формы надо делать редирект (хоть на ту же самую форму) чтобы при обновлениии страницы запрос не отправлялся повторно. А при ошибках редиректить не надо.
Это описано в моем уроке про формы. Читал? https://github.com/codedokode/pasta/blob/master/forms.md
Вообще, у меня вся проблема в том, что инклюд не дает использовать ссылки с ? в конце имени файла, а мне этот знак нужен, чтобы нормально формировать ссылки на сортировку через GET.
> что инклюд не дает использовать ссылки с ? в конце имени файла
В именах файлов под WIndows нельзя использовать знак вопроса. И зачем ты пытаешься дать файлу такое странно имя?
> а мне этот знак нужен, чтобы нормально формировать ссылки на сортировку через GET.
Не понимаю при чем тут include и знак вопроса в имени файла. Ты что-то путаешь.
И при чем тут формы? Прочти пожалуйста мой урок про формы. Там описан универальный алгоритм работы с формами. просто сделай как там описано и все будет работать.
Видимо, затык в том, что у меня один action.php на все случаи жизни. Если из него наделать обработчиков под каждую форму, то все будет нормально. Сейчас с тренировки приду и попробую переделать.
Помоги с задачкой на палиндром. Короче, все понял, все сделал, но
>Аа роза упала на лапу Азора
Считает палиндромом, а
>А роза упала на лапу Азора
Не считает.
https://ideone.com/ovXTK6
https://ideone.com/ovXTK6
https://ideone.com/ovXTK6
Вот тут например при $i = 0
>$a = mb_substr($text3, $i, 1);
>$b = mb_substr($text3, -$i, 1);
$a и $b один и тоже элемент $text3[0]
ещё подсказки нужны?
Спасибо, любопытно, что во всех решениях которые я потом искал через гугл была допущена такая ошибка.
Я не понимаю, в чем условия задачи. Ты написал:
> Сгенерировать предложение:
> "В этом предложении ровно 36 символов"
> Хард моде:
> "В этом предложении ровно сорок два символа"
Ну смотри, допустим я сделаю программу:
$sentence = "В этом предложении ровно 36 символов";
это решение? В этом вся задача? Я просто не понимаю, что должно даваться программе на вход и что она будет делать на выходе.
Если на вход дается число, а на выходе надо составить осмымленное предложение на русском языке, то это не задача для ньюфага, ее даже профессионал не каждый сможет решить.
На входе ничего нет, такие предложения нужно найти. Ты знаешь, что такое квайн? Это чем-то похоже на квайн. И решается так же.
Я не думал, что сама формулировка задачи такая сложная для понимания, позже выложу пример решения на js и распишу подробнее.
А, кажется я понимаю. решение должен найти человек, а программу тут писать не требуется, так? Потому что с цифрами решение элементарно: находим сколько букв в фразе «В этом предложении ровно XY символов» и вставляем вместо XY.
Ответ должен быть около 61270 так что придется потратить еще время. Это задача непростая, на ней все спотыкаются.
У тебя тут ошибка: если долг маленький (то есть когда срабатывает if) ты выплачиваешь остаток, но не начисляешь перед этим на него процент и комиссию, оттого и расхождение.
Также, надо постить ссылку в добавок к или вместо скриншота, а то я не могу скопипастить оттуда код.
Также. некоторые выражения у тебя скопированы 2 раза, например
creditbalance × percent + servicePayment
Попробуй сделать чтобы эта формула встречалась только один раз. Ну сам подумай, это же неудобно, если мы захотим поменять формулу то придется в 2 местах менять, и разобраться в такой программе сложнее.
Названия функций, часть с подчеркиваниями, часть с camelCase, часть и с тем и с другим. Везде передаются массивы сложной структуры которые собираются по частям, так что чтобы понять что именно там есть, надо анализировать всю цепочку функций. Переменные называются в стиле $var1 (правда, так и есть), константы не используются и можно увидеть что-то вроде
if ($type == 3) // что такое 3???
Ну и конечно никаких проверок на ощибки, функция не вернула результат? да и фиг с ним, продолжаем выполнение дальше.
Сразу предупреждаю: в нашем треде за такой код полагается расстрел.
Доброе утро.
Если процент и комиссию не начислять в последнем месяце то по идеи так должно быть.
http://ideone.com/8Rq7aT
Должно получиться около 61270. Перепроверь свой код.
Вот тебе другие числа для проверки:
если брать в кредит 1000 то надо вернуть 2030
если брать в кредит 4000 то надо вернуть около 6123
С таким подходом и никакого компьютера не надо, ведь можно все посчитать руками.
Пример решения
http://ideone.com/mrg5NT
Как видно, мы можем поменять части предложений, а результат останется все равно верным.
В хард моде разумеется не все так просто. Мало перевести число в правильное числительное, нужно так же правильно подобрать окончание для слова "символ".
Разумеется, не обязательно использовать конкретно такое предложение, главное, что бы предложение было правдивым, ну и отвечало всем правилам русского языка.
Вариант решения, полный костылей
http://ideone.com/30ufuD
Вот есть у меня микроскопический блог написанный простой стеной текста.
Как мне начать его превращать в расширяемую штуку на ООП?
Для начала в голову идет то, что можно написать класс для работы с базой данных? Это самое простое.
Допустим будет два метода:
1. Запросить все записи из базы.
2. Добавить запись в базу.
У меня собственно такие вопросы: тут нужны объекты? Или можно сделать абстрактный класс? Или нужно создавать объект когда пользователь обращается к скрипту, и например в этот объект сохранять взятые из базы посты, что бы не болтались по коду массивом?
А, нет, уже посмотрел в треде. Какое совпадение.
http://ideone.com/nmyBed
private $pdo;
function selectUser($id) {
$sql = 'SELECT * FROM `users` WHERE `id`= ?';
$this->pdo->query($sql,[$id]);
}
где
function query($sql, array $parameters) {
$query = $this->prepare($sql);
...
$x=0;
foreach ($parameterss as $param) {
$query->bindValue($x++, $param);
}
...
$result = $query->execute();
}
(опустил часть кода для краткости)
Вроде все просто и понятно, но смущает что в каждом методе надо руками писать sql-запрос. Либо же, другая идея - добавить в класс DB методы select,update,insert,delete которые составляют запрос и исполняют. Но тогда надо гонять массивы, что вроде как плохо.
function selectUser($id) {
$this->pdo->select(
`users`, //таблица
['email', 'info'], //поля которые нужно взять
[['and', 'id','<>','15'],['or', 'age','>','18'],['and','gender','=','male']], //условия для where, тут вообще полный ад, т.к. надо предусмотреть возможность запроса типа ...WHERE true AND `id`<>'15' OR `age`>18 AND `gender`='male'
['firstname,'lastname'] //сортировка
['0','20'] //limit
);}
И это еще без джоинов. В общем-то выглядит как полная жопа, при том что на деле используются довольно простые запросы, но как же программирование, разве суть не в том чтобы автоматизировать повторяющиеся действия, в данном случае составление sql-запроса? Спасибо что дочитали до конца.
private $pdo;
function selectUser($id) {
$sql = 'SELECT * FROM `users` WHERE `id`= ?';
$this->pdo->query($sql,[$id]);
}
где
function query($sql, array $parameters) {
$query = $this->prepare($sql);
...
$x=0;
foreach ($parameterss as $param) {
$query->bindValue($x++, $param);
}
...
$result = $query->execute();
}
(опустил часть кода для краткости)
Вроде все просто и понятно, но смущает что в каждом методе надо руками писать sql-запрос. Либо же, другая идея - добавить в класс DB методы select,update,insert,delete которые составляют запрос и исполняют. Но тогда надо гонять массивы, что вроде как плохо.
function selectUser($id) {
$this->pdo->select(
`users`, //таблица
['email', 'info'], //поля которые нужно взять
[['and', 'id','<>','15'],['or', 'age','>','18'],['and','gender','=','male']], //условия для where, тут вообще полный ад, т.к. надо предусмотреть возможность запроса типа ...WHERE true AND `id`<>'15' OR `age`>18 AND `gender`='male'
['firstname,'lastname'] //сортировка
['0','20'] //limit
);}
И это еще без джоинов. В общем-то выглядит как полная жопа, при том что на деле используются довольно простые запросы, но как же программирование, разве суть не в том чтобы автоматизировать повторяющиеся действия, в данном случае составление sql-запроса? Спасибо что дочитали до конца.
http://ideone.com/vmPxtz
http://ideone.com/U0ALlF
Оп, я конечно тебя люблю, но... То решение, которое предлагал ты в учебинике, с подсчётом всех символов, потом сравнивание половины с другой половиной... Это так запутанно и сложно. Я честно хотел скатать решение у того парня из треда, но сделал решение через strrev.
Проверь. Нормально, или нужно переделывать?
> Надеюсь, вы прекрасно осознаете, что нельзя вот так вот просто взять и вывести картинку посреди HTML-кода в том же самом скрипте (если не осознаете, прочтите внимательно эту статью):
Интересно, что там было написано (ссылка не рабочая)? Почему нельзя?
открой отладчик в браузере (Ctrl+ Shift + I), вкладку Scripts, найди там нужный скрипт, поставь точку останова на строке var val =.... и пройди эти строки по шагам, изучая чему равны переменные. Ну и сюда запости, я гляну.
Вот тебе помощь по отладчику
http://habrahabr.ru/post/143767/
http://habrahabr.ru/post/149430/
Изучи его если не работал с ним, это не раз пригодится.
Оно ?
Individual form controls automatically receive some global styling. All textual <input>, <textarea>, and <select> elements with .form-control are set to width: 100%; by default. Wrap labels and controls in .form-group for optimum spacing.
http://getbootstrap.com/css/#forms
> правильно ли я понимаю что его методы должны выглядеть примерно так:
Да, только возвращать лучше объекты (класса User), а не массивы. Иначе это не совсем маппер, а что-то другое.
> foreach ($parameterss as $param) {
> $query->bindValue($x++, $param);
не забудь что есть еще именованные плейсхолдеры вроде :field
> Вроде все просто и понятно, но смущает что в каждом методе надо руками писать sql-запрос.
Что плохого в SQL? Это язык для написания запросов, он довольно удобен, понятен и является стандартом который все знают.
Сколько запросов тебе надо написать? 3-4 простых запроса на весь маппер. Это разве много?
Конечно бывают случаи когда появляются одинаковые запросы.
Если у тебя несколько мапперов (маппер файлов, маппер комментариев, и тд), то там появляются похожие запросы типа
getFileById
getCommentBYId
В таком случае чтобы избежать копипасты можно их реализовать в базовом классе протектед функцией типа
getRowById($table, $id)
Если у тебя есть много однотипных функций с поиском по условию типа
findById
findByName
findByAge
то можно сделать общий метод findByField($field, $value) опять же не забудь пометить его protected.
Насчет insert — это может быть удобно, сделать метод insert который принимает таблицу и массив значений, причем сделать его можно как в классе PDO, так и в базовом классе маппера. Я бы сделал в базовом классе маппера чтобы не было соблазна работать с БД в обход мапперов.
> Либо же, другая идея - добавить в класс DB методы select,update,insert,delete которые составляют запрос и исполняют.
Я думаю тут это не даст выгоды, так как запросов всего несколько.
> $this->pdo->select(
> `users`, //таблица
> ['email', 'info'], //поля которые нужно взять
> [['and', 'id','<>','15'],
На мой взгляд SQL запрос
SELECT email, info FrOM users WHERE id <> 15
читается гораздо лучше (а пишется быстрее) так как в нем меньше скобок и кавычек. По твоему, это не так?
Ну и я приведу еще один аргумент. Допустим завтра окажется что запрос надо поменять как-то хитро:
— добавить DISTINCT
— добавить алиасы вроде SELECT a + b AS c
— добавить группировку
— добавить JOIN
— добавить UNION
- добавить ORDER по выражению
— добавить оптимизационный совет USE INDEX
в твоем массивоориентированном генераторе есть поддержка таких вещей? У нас уже есть язык для написания запросов (SQL), а ты пытаешься поверх него сделать свой язык запросов на массивах сложной структуры.
Ну и опять же мое мнение, когда у тебя задача оптимизировать запросы то работать с SQL кодом удобнее чем с его массивоориентированным представлением.
Тем более ты сам признаешь:
> условия для where, тут вообще полный ад,
> В общем-то выглядит как полная жопа
Молодец, это правильные мысли.
> разве суть не в том чтобы автоматизировать повторяющиеся действия, в данном случае составление sql-запроса?
Да, это правильная идея, но реализоывать ее гораздо удобнее вынесением общего кода в метод датамаппера, а не созданием усложненного класса для работы с БД.
То, что ты пытаешься реализовать, называется Query Builder (построитель запросов) и он используется в случаях когда запрос меняется в зависимости от условий, и нам приходится строить его по частям. Вот в моем уроке про работу с БД пример Query Builder:
https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md#query-builder
Разумеется, QB пишется не на массивах, а на ООП. Вот пример хорошего QB из Doctribe DBAL:
http://doctrine-dbal.readthedocs.org/en/latest/reference/query-builder.html
Обрати внимание, там составление условий сделано на ООП, а не на массивах.
Заметь также что в DBAL там реализованы дополнительные методы для выполнения простых запросов:
delete: http://doctrine-dbal.readthedocs.org/en/latest/reference/data-retrieval-and-manipulation.html#delete
insert: http://doctrine-dbal.readthedocs.org/en/latest/reference/data-retrieval-and-manipulation.html#insert
update: http://doctrine-dbal.readthedocs.org/en/latest/reference/data-retrieval-and-manipulation.html#update
Но мне не нравится UPDATE, мне кажется запрос читается лучше чем функция с несколькими массивами.
> правильно ли я понимаю что его методы должны выглядеть примерно так:
Да, только возвращать лучше объекты (класса User), а не массивы. Иначе это не совсем маппер, а что-то другое.
> foreach ($parameterss as $param) {
> $query->bindValue($x++, $param);
не забудь что есть еще именованные плейсхолдеры вроде :field
> Вроде все просто и понятно, но смущает что в каждом методе надо руками писать sql-запрос.
Что плохого в SQL? Это язык для написания запросов, он довольно удобен, понятен и является стандартом который все знают.
Сколько запросов тебе надо написать? 3-4 простых запроса на весь маппер. Это разве много?
Конечно бывают случаи когда появляются одинаковые запросы.
Если у тебя несколько мапперов (маппер файлов, маппер комментариев, и тд), то там появляются похожие запросы типа
getFileById
getCommentBYId
В таком случае чтобы избежать копипасты можно их реализовать в базовом классе протектед функцией типа
getRowById($table, $id)
Если у тебя есть много однотипных функций с поиском по условию типа
findById
findByName
findByAge
то можно сделать общий метод findByField($field, $value) опять же не забудь пометить его protected.
Насчет insert — это может быть удобно, сделать метод insert который принимает таблицу и массив значений, причем сделать его можно как в классе PDO, так и в базовом классе маппера. Я бы сделал в базовом классе маппера чтобы не было соблазна работать с БД в обход мапперов.
> Либо же, другая идея - добавить в класс DB методы select,update,insert,delete которые составляют запрос и исполняют.
Я думаю тут это не даст выгоды, так как запросов всего несколько.
> $this->pdo->select(
> `users`, //таблица
> ['email', 'info'], //поля которые нужно взять
> [['and', 'id','<>','15'],
На мой взгляд SQL запрос
SELECT email, info FrOM users WHERE id <> 15
читается гораздо лучше (а пишется быстрее) так как в нем меньше скобок и кавычек. По твоему, это не так?
Ну и я приведу еще один аргумент. Допустим завтра окажется что запрос надо поменять как-то хитро:
— добавить DISTINCT
— добавить алиасы вроде SELECT a + b AS c
— добавить группировку
— добавить JOIN
— добавить UNION
- добавить ORDER по выражению
— добавить оптимизационный совет USE INDEX
в твоем массивоориентированном генераторе есть поддержка таких вещей? У нас уже есть язык для написания запросов (SQL), а ты пытаешься поверх него сделать свой язык запросов на массивах сложной структуры.
Ну и опять же мое мнение, когда у тебя задача оптимизировать запросы то работать с SQL кодом удобнее чем с его массивоориентированным представлением.
Тем более ты сам признаешь:
> условия для where, тут вообще полный ад,
> В общем-то выглядит как полная жопа
Молодец, это правильные мысли.
> разве суть не в том чтобы автоматизировать повторяющиеся действия, в данном случае составление sql-запроса?
Да, это правильная идея, но реализоывать ее гораздо удобнее вынесением общего кода в метод датамаппера, а не созданием усложненного класса для работы с БД.
То, что ты пытаешься реализовать, называется Query Builder (построитель запросов) и он используется в случаях когда запрос меняется в зависимости от условий, и нам приходится строить его по частям. Вот в моем уроке про работу с БД пример Query Builder:
https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md#query-builder
Разумеется, QB пишется не на массивах, а на ООП. Вот пример хорошего QB из Doctribe DBAL:
http://doctrine-dbal.readthedocs.org/en/latest/reference/query-builder.html
Обрати внимание, там составление условий сделано на ООП, а не на массивах.
Заметь также что в DBAL там реализованы дополнительные методы для выполнения простых запросов:
delete: http://doctrine-dbal.readthedocs.org/en/latest/reference/data-retrieval-and-manipulation.html#delete
insert: http://doctrine-dbal.readthedocs.org/en/latest/reference/data-retrieval-and-manipulation.html#insert
update: http://doctrine-dbal.readthedocs.org/en/latest/reference/data-retrieval-and-manipulation.html#update
Но мне не нравится UPDATE, мне кажется запрос читается лучше чем функция с несколькими массивами.
В общем, методы insert/delete/update есть в других DBAL, но для update/delete я предпочитаю SQL из-за понятности и читабельности.
Для select существуют Query Builder но они используются когда запрос надо строить по частям, а если он известного вида то удобнее написать SQL.
В SQL нет ничего плохого. Копипаста из однотипных запросов это не очень хорошо и от нее можно как-то попробовать избавиться.
Тебе советую не писать свой DBAL, а изучить доктриновский. Ну или хотя бы сначала посмотреть доктриновский, а только после изобретать свой велосипед если тебе захотелось написать свой DBAL.
ФОрма растягивается на ширину родителя. Меняй его ширину либо с помощью CSS свойства Width либо с помощью классов для задания ширины (рекомендуется):
http://getbootstrap.com/css/#grid
Ну и я бы сделал подписи к форме лейблами, а то серые нашлепки разной ширины сморятся негармонично.
При преобразовании из utf-8 в cp1251 мы теряем часть символов, так как в cp1251 всего 256 символов. Мы конечно используем только русские буквы, но все равно, неаккуратненько как-то.
Ты бы мог бы разбить строку на массив символов, перевернуть массив через array_reverse и склеить назад в строку. Это не требует посимвольного обхода и работает со всеми символами в utf-8. Тоже надо ровно 3 строки.Не хочешь попробовать?
А то у тебя функция какая-то неуниверсальная получилась.
> $overHours=$overHours+($weekHours-$normalHours);
Тут можно испльзовать += для краткости
> // Ищем с конца буквы до заглавной и заменяем их на "."
проще отрезать первую букву через mb_substr и приписать к ней точку. Твой код не сработает с фамилией с дефисом типа Тянь-Шанский
> for($i = 0;$i < $length; $i++){
> $space=$space." " ;
Есть str_repeat для этого
В остальном, все хорошо. Там следующаяя задача про вектор будет посложнее.
http://www.php5.ru/articles/image вот статья, если что. Я просто пытаюсь понять смысл этого предложения, и зачем вообще эти функции нужны.
Хорошо, попробую. Спасибо, ты великолепен.
Черт, мне просто не приходило в голову завести базовый Mapper и вынести туда однотипные selectById. Даже обидно как-то.
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'group, email, mark, emailMatch) VALUES ('0', '0', '0', '0', '0', '0', '0')' at line 1' in E:\OpenServer\domains\localhost\php\students\lib\Student.php:120 Stack trace: #0 E:\OpenServer\domains\localhost\php\students\lib\Student.php(120): PDOStatement->execute() #1 E:\OpenServer\domains\localhost\php\students\lib\action.php(36): Student->insertErrorsIntoDB(Array) #2 {main} thrown in E:\OpenServer\domains\localhost\php\students\lib\Student.php on line 120
Нельзя удалить символы из строки через unset, но есть str_replace, preg_replace, strtr и похожие функции.
>>462123
> INSERT INTO 'errors'
Ты уверен что имена таблиц можно брать в одиночные кавычки? Читани-ка мануал
http://phpclub.ru/mysql/doc/legal-names.html
http://phpclub.ru/mysql/doc/literals.html
Также, чтобы вставить число как число PARAM_INT недостаточно. Само число должно быть числом типа int, то есть надо писать
$STH->bindValue(':birth', intval($errors['birth']), PDO::PARAM_INT);
явно превращая строку в число (кстати почему они у тебя там в виде строк хранятся?)
> в самих переменных лежат 1 и 0 числовые
Там есть тип bool который соответствует tinyint, обычно используют либо его (при этом негласно договариваясь использовать толкьо 0 и 1) либо ENUM, ну и не забывай писать NOT NULL чтобы нельзя было вставить NULL.
https://dev.mysql.com/doc/refman/5.0/en/numeric-type-overview.html
> BOOL, BOOLEAN
> These types are synonyms for TINYINT(1). A value of zero is considered false. Nonzero values are considered true:
Спасибо попробую так.
ДИЯВОЛ, КАК У ТЕБЯ STRREV() НА КИРИЛЛИЦЕ РАБОТАЕТ?
мимо-тот кун у которого ты хотел стыбздить решение
Он перевел строку в 1-байтную кдировку где 1 символ = 1 байт.
>>462136
Мануал php. На собеседовании любят задачи с подвохом.
Ну и у нас еще такие есть: https://github.com/codedokode/pasta/blob/master/interview-tasks.md
>Да, только возвращать лучше объекты (класса User), а не массивы. Иначе это не совсем маппер, а что-то другое.
А, еще про это хотел кратенько спросить, вот в классе db я возвращаю результат в виде ассоциативного массива, допусти так
public function query($sql, array $parameters) {
...
$result->fetchAll(PDO::FETCH_OBJ);
...
}
Возникает желание в методах маппера прямо передать его в конструктор, т.е. в getUserById($id) делать так:
$userobj = $this->pdo->query('SELECT FROM users WHERE id = ?',[1]);
return new User($userobj);
вместо вот этого
$userobj = $this->pdo->query('SELECT FROM users WHERE id = ?',[1]);
$username = $userobj['username'];
$password = $userobj['password'];
$email =$userobj['email'];
...
return new User($username, $password, $email...)
Но и на всякий случай сохранить возможность создавать Юзера через передачу параметров, а не объекта, допустим проверяя что передано в конструктор.
Я снова что-то намудрил или первый способ правильный, или может второй?
Спасибо.
> Но и на всякий случай сохранить возможность создавать Юзера через передачу параметров, а не объекта, допустим проверяя что передано в конструктор.
Обычно это делают не так. Обычно у конструктора нет аргументов:
$user = new User( );
$user->name = 'aaa'; // альтернатива: $user->setName('aaa')
и заодно делают метод $user->setAttributes($values); который проставляет значения из массива. Как дополнение, можно сделать статический конструктор который создает юзера из массива: $user = User::createFromArray(...);
Но стоит помнить что превращение массива в объект это все же задача маппера, а в классе User не должно быть ничего относящегося к базам данных. Например преобразование даты из SQL в php формат должно делаться в маппере, то же самое с преобразованием из 0/1 в true/false. Удобно в маппере сделать 2 метода, преобразоание записи в БД в объект и наоборот.
В простых ситуациях можно сразу создавать объект через
$stmt->setFetchMode(PDO::FETCH_CLASS, 'SomeClass');
$objects = $stmt->fetchAll( );
Минусы тут в том что не вызываются твои методы, соответственно ты не можешь например сделать какие-то проверки или действия. Ну к примеру ты не можешь запретить присвоить неправильное значение и выкинуть исключение, так как свойства проставляются напрямую, даже если они приватные. А если бы это делалось через метод то проверку можно было бы сделать.
Также, по умолчанию эта штука сначала ставит значения свойств, а только потом вызывает конструктор (что противоречит здравому смыслу так конструктор всегда должен вызываться первым при создании объекта). Для обхода этого там есть флаг
PDO::FETCH_CLASS|PDO::FETCH_PROPS_LATE
который говорит сначала вызывать конструктор.
ссылка http://php-zametki.ru/php-prodvinutym/57-pdo-konstanty-vyborki-dannyx.html
> Но и на всякий случай сохранить возможность создавать Юзера через передачу параметров, а не объекта, допустим проверяя что передано в конструктор.
Обычно это делают не так. Обычно у конструктора нет аргументов:
$user = new User( );
$user->name = 'aaa'; // альтернатива: $user->setName('aaa')
и заодно делают метод $user->setAttributes($values); который проставляет значения из массива. Как дополнение, можно сделать статический конструктор который создает юзера из массива: $user = User::createFromArray(...);
Но стоит помнить что превращение массива в объект это все же задача маппера, а в классе User не должно быть ничего относящегося к базам данных. Например преобразование даты из SQL в php формат должно делаться в маппере, то же самое с преобразованием из 0/1 в true/false. Удобно в маппере сделать 2 метода, преобразоание записи в БД в объект и наоборот.
В простых ситуациях можно сразу создавать объект через
$stmt->setFetchMode(PDO::FETCH_CLASS, 'SomeClass');
$objects = $stmt->fetchAll( );
Минусы тут в том что не вызываются твои методы, соответственно ты не можешь например сделать какие-то проверки или действия. Ну к примеру ты не можешь запретить присвоить неправильное значение и выкинуть исключение, так как свойства проставляются напрямую, даже если они приватные. А если бы это делалось через метод то проверку можно было бы сделать.
Также, по умолчанию эта штука сначала ставит значения свойств, а только потом вызывает конструктор (что противоречит здравому смыслу так конструктор всегда должен вызываться первым при создании объекта). Для обхода этого там есть флаг
PDO::FETCH_CLASS|PDO::FETCH_PROPS_LATE
который говорит сначала вызывать конструктор.
ссылка http://php-zametki.ru/php-prodvinutym/57-pdo-konstanty-vyborki-dannyx.html
Я не понял что-то по первой задачке. Дан массив чисел, найдите 2 наибольших.
Подвох: в массиве [1, 2, 2, 2, 3, 3] надо вернуть числа 2 и 3. Подвох: массив может содержать 0 или 1 элемент.
Что надо возвращать, если в массиве 1 элемент. Два раза одно значение? А если массив пустой? Я не догоняю до чего-то здесь?
> , если в массиве 1 элемент.
Одно значение один раз
> А если массив пустой?
То ничего (например пустой массив или 2 раза null)
тогда вот
function twoMax(Array $arr) {
\t$result = [];
\twhile (count($result) !== 2 && !empty($arr) ) {
\t\t$max = max($arr);
\t\t$result[] = $max;
\t\t$arr = array_diff($arr, $result);
\t}
\treturn $result;
}
Если ты решишь так, то скорее всего тебя попросят сделать то же самое с обходом массива за 1 раз.
Ну или как альтернатива можно переформулировать задачу: дан список чисел в файле, каждое на отдельной строке. Найдите 2 наибольших. Алгоритм должен иметь потребление памяти O(1) (то есть независимо от размера файла, программа должна потреблять один и тот же объем памяти и загружать файл целиком в память не разрешается, так как он может быть большой).
Суть такова. Есть таблица, у которой в первом столбце чекбоксы, с помощью которых хочу удалять содержимое строки по нажатию кнопки внизу таблицы. Чекбоксы делаю примерно так:
<TD><form method="post" action="<action.php>"><input type="checkbox" name="delete" value="<?=$row['id']?>"></label></form></TD>
Как сделать кнопку для сабмита вне формы я еще нагуглил вроде бы. Но ведь у меня тут куча чекбоксов, как сделать так, чтобы в целевой скрипт отправлялся массив со значениями, как это происходит, если все чекбоксы в одной форме с одинаковым именем?
Ты делаешь неправильно. Во первых надо сделать одну форму которая все охватывает. Во вторых изучи как собираются данные для формы в браузере. Не знаю, где про это можно прочесть но принцип такой: все элементы формы, у которых есть имя и которые не отключены (disabled) записываются в виде имя=значение и передаются на сервер. Для чекбоксов и радиокнопок передаются только отмеченные кнопки. Если у тебя 5 чекбоксов и 2 из них нажаты то на сервер отправится
checkbox1=value1
checkbox2=value2
Если у них одинаковое имя то конечно второй затрет первый когда php будет разбирать эти данные. Но если ты сделаешь имя в виде name[] то php просто сделает из них массив
http://php.net/manual/ru/faq.html.php#faq.html.arrays
http://php.net/manual/ru/language.variables.external.php
В общем надо больше читать мануал и меньше читать неправильные учебники и видеокурсы которые не объясняют важные вещи.
>name[]
У меня так и есть, забыл написать. Попробую обернуть все в одну форму. Кстати, можно сделать форму внутри другой формы?
Тут и пробовать нечего, тебе нужна одна форма на одно действие и все, никаких вложенных или отдельных форм для каждой радиокнопки. По нажатию на submit на сервер отправятся данные из всех инпутов что в нее вложены, каждый будет доступен в массиве POST по атрибуту name. Также не понятно зачем выносить submit за форму когда можно сделать так
<form>
<table>
<tr>
<td><input type='checkbox' ...></td>
</tr>
<tr>
<td><input type='checkbox'...></td>
</tr>
...
<tr>
<td><input type='submit'...></td>
</tr>
</table>
</form>
У тега <form> есть атрибут method в котором и указываем, каким методом передавать данные.
<form method="GET"> - GET
<form method="POST"> - POST
>>462262
http://htmlbook.ru/html/form
И вообще, держи ресурс на заметке при изучении CSS и HTML.
Я как бы в курсе. Имелось в виду, что мне могут понадобиться как GET переменные так и POST на одной страничке. Например, GET я использую для пагинатора, а POST - для работы с базой.
Работай с суперглобальными переменными, $_SERVER и более подходящую под твою задачу $_REQUEST
Пример:
GET запрос на example.com/ololo.php?var1=value&var2=val2
PHP код:
var_dump($_SERVER['REQUEST_URI']);
var_dump($_REQUEST);
Результат:
string(29) "/ololo.php?var1=value&var2=val2"
array(2) {
["var1"]=>
string(5) "value"
["var2"]=>
string(4) "val2"
}
Опять не про то я хочу сказать. Про $_SERVER и $_REQUEST я тоже в курсе. Смотри, у меня пагинтор и функция создания ссылок для сортировки строк таблицы берет урл из $_SERVER['REQUEST_URI'] и потом с ним играется по всякому, составляя ссылки для перехода другие страницы и сортировки соответственно. Думаю, лучше будет написать обработчик, который будет составлять урл из SQL запроса или вообще сделать всю навигацию не ссылками, а кнопками с опять же отправкой значений через POST (так, кстати, можно? через скрытые инпуты что ли передавать параметры для навигации?).
Я на грани от сна, не совсем понимаю твой запрос.
>Смотри, у меня пагинтор и функция создания ссылок для сортировки строк таблицы берет урл из $_SERVER['REQUEST_URI'] и потом с ним играется по всякому, составляя ссылки для перехода другие страницы и сортировки соответственно.
Ну так введи дополнительные параметры для сортировки, например page - номер страницы, sort - название поля по которому нужно сортировать, type - тип сортировки(ASC|DESC)
>Думаю, лучше будет написать обработчик, который будет составлять урл из SQL запроса
Это ещё что за лисапеды придумываешь?
>сделать всю навигацию не ссылками, а кнопками с опять же отправкой значений через POST (так, кстати, можно? через скрытые инпуты что ли передавать параметры для навигации?)
Зачем? Что тебе мешает держать номер страницы в GET параметре?
Короче, пили сырцы, либо го тимвивер OR скупе, ванговать в условиях недопонимания задачи сложно.
>Ну так введи дополнительные параметры для сортировки, например page - номер страницы, sort - название поля по которому нужно сортировать, type - тип сортировки(ASC|DESC)
Это все есть и в гет, и ничего не мешает их там держать. Я сам тут уже засыпаю, так что лучше завтра попробую объяснить. Или на свежую голову сам додумаюсь, как мне правильно все сделать.
Необучаемых людей не существует =)
Балуюсь позапэ с 9 класса, зашел как-то на аккаунт php.su - охуел от вопросов которые задавал.
Я уже сам не понимаю, лол. Три часа ночи, не спал с раннего утра. Пойду поваляюсь хоть немного.
Декомпозиция, алгоритм решения задачи, отсутствие понимания, как 10 операторами сделать, чтобы все работало.
Вот эти проблемы вызывают трудность.
Задавай конкретные вопросы.
Пиши, что именно непонято. Например если ты не можешь решить задачу запости код который смог написать, и напиши что именно непонятно, тебе подскажут.
Также, если ты плохо понял какую-то тему, то попроси допольнительных задачек.
> Думаю, лучше будет написать обработчик, который будет составлять урл из SQL запроса или вообще сделать всю навигацию не ссылками, а кнопками с опять же отправкой значений через POST
Для сортировки и постраничной навигации удобнее GET (и ссылки) так как в этом случае мы можем переслать URL, сохранить его в закладки, открыть ссылку в новом окне, вернуться назад и т.д. Не надо делать их через POST, это неудобно.
> который будет составлять урл из SQL запроса
не очень понятно, о чем речь. При чем тут SQL запрос?
> Имелось в виду, что мне могут понадобиться как GET переменные так и POST на одной страничке. Например, GET я использую для пагинатора, а POST - для работы с базой.
Ну так они друг другу не мешают. Во-первых, ты можешь передавать значения в POST через скрытые поля:
<input type="hidden" name="x" value="1">
Во-вторых, ты можешь передать и GET параметры в POST форме, так как они идут в URL:
<form method="POST" action="list.php?x=1&y=2">
....
(заметь я пишу & так как по правилам HTML & это спецсимвол и чтобы вписать знак & надо писать & — подробнее тут: https://ru.wikipedia.org/wiki/%D0%9C%D0%BD%D0%B5%D0%BC%D0%BE%D0%BD%D0%B8%D0%BA%D0%B8_%D0%B2_HTML )
> Кстати, можно сделать форму внутри другой формы?
Нет.
Это все приходит с практикой. Если сложность в этом то надо просто решать больше разных задачек (и показывать ответы чтобы тебе написали что можно улучшить).
>>462286
Двачую вот этих господ, сам очень медленно ползу, но если взглянуть назад, то вспоминаю как не мог понять как загрузить файл на сервер, пугался когда пхп в перемешку с html было, и все в таком духе. Сейчас вот пытаюсь уже ооп-задачи решать, тоже туго и плохо понимаю все. Вот ОП мне накидал комментариев, а я ничего не понимаю как делать там.>>461489
сижу и боюсь опять подходить к этому. Прочитал про Анонимные функции, вообще не понял как и для чего они, примеры на php.ner реально омск. Думаю что отложить пока это и послушать лекции специалиста и поделать тамошние лабораторные, для того что бы закрыть мелкие пробелы.
Покажешь как? Чтобы вот этому удовлетворяло:
assert('twoMax([1, 2, 3, 4, 5, 6 , 7, 5 ,6, 7, 8, 8]) == [8, 7]');
assert('twoMax([1]) == [1]');
assert('twoMax([]) == []');
Сдается мне, не существует алгоритма, который делал бы это за O(1), ведь по-любому надо обойти массив хотя бы один раз т.е. в самом лучшем случае это будет O(n), не? Тогда как-то так получается: https://ideone.com/YPvLbP
>и заодно делают метод $user->setAttributes($values);
То есть?
$result = $this->pdo->query(...);
$data = $this->sqlToArray($result);
$user = new User;
$user->setAttribute($data);
Пожалуй это самое лаконичное.
А вот еще. Норм ли использовать метод маппера который возвращает объект для проверки типа
if (selectUser($id, $password)) {
//такой юзер существует, залогиниваем
Session::set('logged_in', true);
Session::set('user', $id);
...
}
В логическом контексте возвращенный объект, конечно, true, но немного коряво выглядит. Может завести похожий метод exists() который будет возвращать строго true или false.
Вот где бы почитать что должны принимать и возвращать типовые методы типовых классов - db, mapper, user, session, cookie? Можно и даже лучше без внутренней реализации, просто имя класса-метод-вход-выход, ну как про стандартные функции в мануале.
[CODE]#PHP
LoadModule php5_module "c:/Web/WAMP/php5.6.7/php5apache24.dll"
AddHandler application/x-httpd-php .php
#Конфигурирование пути к php.ini
PHPIniDir "c:/Web/WAMP/php5.6.7/"[/CODE]
Но не работают ни xdebug ни mb_string, которые подключены в php.ini. Команда php.exe -m выводид следующее. http://pastebin.com/h9PjCErf
То есть если напрямую обращаться к php - все подключено и работает как надо, но php как модуль apach не подключены не mbstring не xdebug.
Можно конечно подключить как CGI или FastCGI, но мне все же интересно было бы найти решение проблемы.
Плохо гуглил. Проблема решилась путем добавления папки с php в path. И обязательный ребут после этого, так как просто перезапустить апач не помогло, хотя из командной строки можно было обращаться к php без перехода в папку с ним.
Есть табличка с данными с сортировкой по столбцам, есть пагинатор, и есть кнопки удаления строк этой таблицы. Я хочу, чтобы после нажатия кнопки удаления (естественно это через POST) пользователь оставался на той же странице с той же сортировкой. Так и получается, но пагинатор, который берет данные из строки урл, дает неверные ссылки (ибо урл-то пустой, я же передавал запрос на удаление через POST).
>не очень понятно, о чем речь. При чем тут SQL запрос?
По этому запросу формируется сортировка таблицы и текущая страница. Вот думаю, пусть пагинатор из него данные берет, если страница сформирована с помощью гет-запроса и из урла он ничего взять не сможет (как в примере выше).
Крутил лайки - не банят, баны в основном идут за вступления в группы.
При лайкодрочерстве изредка капчу ловит.
Тебе кун уже ответил ><form method="POST" action="list.php?x=1&y=2">
И для удаления юзай AJAX, намного кошернее будет.
шаблон registration.php передает данные через пост в скрипт Action.php там с помощью создания экземпляра класса Student методами класса обрабатываются ошибки и возвращается массив с Булевыми TRUE/FALSE по каждому отправленной переменной из формы регистрации, в итоге массив (array('name' => 0, 'surname' => 1 ..)) такого типа обрабатывается уже в другом объекте и сохраняется в таблицу errors (TINYINT) с привязкой к куке, так вот, хотел чтобы после этого из action.php редиректило в шаблон регистрации в котором подключен файл FormInspect.php который должен доставать по текущей куке этот массив с ошибками, потом обрабатывается и выдает уже текстовую расшифровку, так вот, проблема в том, что на странице регистрации не видит куку установленную во время обработки в Action.php, код раскидан по разным файлам - если надо будет - залью на гит.
Оп, я перепробовал все возможные комбинации, и пустые кавычки в имплоуд добавлял, и вообще. А начал изначально совсем с других функций, в итоге дошёл до того что у тебя всё чёрным по белому написано, как нужно. И всё равно нихуя...
Очевидно какая то ебаная нубская ошибка на уровне яслей. Ткни носом, пожалуйста.
http://ideone.com/3CQMcJ
><form method="POST" action="list.php?x=1&y=2">
То есть передадутся и те инпуты, что в форме и "x=1&y=2"?
Там же внизу написаны ошибки, причем конкретно указаны строки, в которых ошибка.
>PHP Warning: explode() expects at least 2 parameters, 1 given in /home/svTejN/prog.php on line 14
Ты передаешь в функцию один параметр, а нужно 2. Explode принимает не только массив, но и разделитель, иначе как он по твоему узнает как делить строку? Читай мануал
http://php.net/explode
>PHP Warning: array_reverse() expects parameter 1 to be array, null given in /home/svTejN/prog.php on line 15
Передается null вместо массива, но это следствие предыдущей ошибки, так как explode не сработал и не возвратил массив.
>PHP Warning: implode(): Argument must be an array in /home/svTejN/prog.php on line 16
То же самое, что и в предыдущем пункте. Исправь первую ошибку, все остальное должно заработать.
>Да, тебе пример написать?
Не, я уже сделал, пришлось, правда заморочиться немного - у меня там еще смена значений каждой записи в виде селекта в каждой строчке, пришлось все-таки сделать форму внутри формы, но оно все работает и сортировка вся сохраняется и пагинатор нормально работает и нет изменения базы через GET. Да, насчет безопасности, я сделал вот так: <form method="POST" action="<?=$url?>"> (где $url - это переменная со значением текущего урла, немного обработанная (например, page=1, если page пришла пустая)) - это нормально, никто мне ничего не сможет передать чего-нибудь нехорошего?
Про это я читал, в моем случае вроде все нормально будет, но вдруг чего не учел.
P.S. Пожалуйста
1) сортируем массив (sort)
2) удаляем повторяющиеся знаечния (array_unique)
3) слайсим первые 2 элемента
Я не помню, меняет array_unique порядок элементов или нет. если да то надо ставить его до сортировки.
>>462304
А ты не бойся.
Анонимные функции это функции, у которых нет имени и которые можно сохранить в переменную или передать куда-то. Вот сравнение:
Обычные функции:
— живут вечно (до завершения программы)
— имеют имена, которые не могут повторяться, нельзя второй раз создать функцию с тем же именем
Анонимные:
— живут до тех пор пока у тебя есть на нее ссылка в какой-нибудь переменной
— не имеют имени потому можно создать сколько угодно копий одной функции
— умеют захватывать с собой переменные через use (это называется замыкание: функция + захваченные ей переменные)
— ссылка на них хранится в переменной, и через нее можно ее вызвать:
$x = function ($n) {
echo "$n\n";
}
$x(1); // выведет 1
$x(2); // выведет 2
Вот пример замыкания:
$a = 1;
$x = function ($n) use ($a) {
echo "a=$a, n=$n\n";
}
$x(10); // a=1,n=10
$a = 2;
$x(5); // a=1, n=5
При использовании use функция сохраняет копию указанной переменной и делает ее доступной внутри. Заметь что сохраняется именно копия: если мы меняем потом переменную, внутри функции остается копия старого значения.
Чтобы сохранить не копию, а ссылку на исходную переменную, надо использовать &:
$a = 1;
$b = 2;
$x = function ($n) use (&$a, $b) {
echo "a=$a, b=$b, n=$n\n";
}
$x(10); // a=1,b=2,n=10
$a = 3;
$b = 3;
$x(5); // a=3, b=2, n=5
Ну и если ты передаешь ссылку на переменную то функция изнутри может ее менять.
Анонимные функции удобно передавать в функции вроде array_filer, array_map, usort, preg_replace_callback. Если ты хочешь, я могу дать простые задачки чтобы лучше с этой темой разобраться.
1) сортируем массив (sort)
2) удаляем повторяющиеся знаечния (array_unique)
3) слайсим первые 2 элемента
Я не помню, меняет array_unique порядок элементов или нет. если да то надо ставить его до сортировки.
>>462304
А ты не бойся.
Анонимные функции это функции, у которых нет имени и которые можно сохранить в переменную или передать куда-то. Вот сравнение:
Обычные функции:
— живут вечно (до завершения программы)
— имеют имена, которые не могут повторяться, нельзя второй раз создать функцию с тем же именем
Анонимные:
— живут до тех пор пока у тебя есть на нее ссылка в какой-нибудь переменной
— не имеют имени потому можно создать сколько угодно копий одной функции
— умеют захватывать с собой переменные через use (это называется замыкание: функция + захваченные ей переменные)
— ссылка на них хранится в переменной, и через нее можно ее вызвать:
$x = function ($n) {
echo "$n\n";
}
$x(1); // выведет 1
$x(2); // выведет 2
Вот пример замыкания:
$a = 1;
$x = function ($n) use ($a) {
echo "a=$a, n=$n\n";
}
$x(10); // a=1,n=10
$a = 2;
$x(5); // a=1, n=5
При использовании use функция сохраняет копию указанной переменной и делает ее доступной внутри. Заметь что сохраняется именно копия: если мы меняем потом переменную, внутри функции остается копия старого значения.
Чтобы сохранить не копию, а ссылку на исходную переменную, надо использовать &:
$a = 1;
$b = 2;
$x = function ($n) use (&$a, $b) {
echo "a=$a, b=$b, n=$n\n";
}
$x(10); // a=1,b=2,n=10
$a = 3;
$b = 3;
$x(5); // a=3, b=2, n=5
Ну и если ты передаешь ссылку на переменную то функция изнутри может ее менять.
Анонимные функции удобно передавать в функции вроде array_filer, array_map, usort, preg_replace_callback. Если ты хочешь, я могу дать простые задачки чтобы лучше с этой темой разобраться.
По памяти O(1), а не по времени. То есть потребление памяти не зависит от размера файла. А по времени получается O(N).
> Тогда как-то так получается
Вот что плохо:
> if ( !isset($second) ) {
Это плохо когда переменная может сущестовать, а может нет. Такой код трудно понять и легко сделать ошибку. Более того с ним неудобно работать, так как надо постоянно задумываться. а есть переменная к этому моменту или нет.
Для first, second в качестве начальных значений лучше выбрать либо первый элемент массиа либо null.
Ну и условия очень запутанные. Я ничего не понял, а рисовать диаграммы на бумаге мне лень. Попробуй упростить код и обойтись парой-тройкой простых ифов.
Ну и если ты добавишь к своему коду несколько тестов, проверять его будет удобнее. Добавь пожалуйста, достаточно просто использовать assert.
> В логическом контексте возвращенный объект, конечно, true, но немного коряво выглядит. Может завести похожий метод exists() который будет возвращать строго true или false.
Я думаю, непринципиально. Можно сделать и так и так.
> Вот где бы почитать что должны принимать и возвращать типовые методы типовых классов - db, mapper, user, session, cookie?
В документации фреймворка Симфони 2 (точнее, за работу с БД там отвечает ORM Doctrine 2). Там это грамотно сделано.
Ну вот тебе пример как используются репозитории в Doctrine 2 (репозиторий это что-то вроде маппера, называется репозиторий потому что он как бы хранит в себе все сущности):
http://doctrine-orm.readthedocs.org/en/latest/reference/working-with-objects.html (англ, но примеры кода-то ты поймешь)
http://odiszapc.ru/doctrine/working-with-objects/ (то же самое по русски но не очень читабельно)
Doctrine 2 реализует паттерн DataMapper, то есть она может отображать в базу любые объекты, для которых ты в конфиге описал соответствие между полями таблицы и полями объекта.
Также, примеры некоторых классов можно посмотреть в Yii2 (у него есть документация на русском), но он не такой «правильный» как доктрина.
Ну и наконец, сами паттерны вроде dataMapper описаны в книге Фаулера «шаблоны проектирования/архитектура корпоративных приложений» (Patterns of Enterprise Application Architecture). Вот описание dataMapper оттуда:
http://design-pattern.ru/patterns/data-mapper.html
Вот похожий паттерн TableDataGateway: http://design-pattern.ru/patterns/table-data-gateway.html
Вот паттерн Domain Model, который в твоем случае реализуется классом User: http://design-pattern.ru/patterns/domain-model.html
Вот еще 2 паттерна используемых в доктрине:
http://design-pattern.ru/patterns/metadata-mapping.html
http://design-pattern.ru/patterns/repository.html
Имей в виду что описания паттернов расчитаны не на начинающих потому их не очень просто понять.
Ну и также порекомендую мой урок про работу с БД: https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md
> типовые методы типовых классов - db, mapper, user, session, cookie
Обычно это делается по другому.
> db
Посмотри doctrine DBAL как пример, или PDO
> mapper
Посмотри мой урок или паттерн datamapper
> user
Просто делаешь объект с информацией о пользователе и все. Это же просто модель.
> session
Можно посмотреть в симфони: http://symfony.com/doc/current/components/http_foundation/sessions.html
> cookie
Обычно там есть объект Request описывающий запрос пользователя и пришедшие от него куки. Чтобы выставить куку, мы создаем ее и добавляем в объект Response, который опсиывает ответ пользователю. Вот симфони:
http://symfony.com/doc/current/book/http_fundamentals.html
Вот примеры кода:
// получение
$value = $request->cookies->get('myCookie');
// установка
$cookie = new Cookie('myCookie', 'contentOfMyCookie');
$response->headers->setCookie($cookie);
Что я хочу сказать: это все реализовано во фреймворках. Если ты не хочешь их изучать а будешь делать свои велосипеды то ты наделуешь кучу ошибок и скорее всего получится какая-нибудь лапша где все перемешано в кучу и сделано на массивах, я такое видел не раз.
Ну и можешь мне задавать вопросы, я постараюсь объяснить
Ну и если ты добавишь к своему коду несколько тестов, проверять его будет удобнее. Добавь пожалуйста, достаточно просто использовать assert.
> В логическом контексте возвращенный объект, конечно, true, но немного коряво выглядит. Может завести похожий метод exists() который будет возвращать строго true или false.
Я думаю, непринципиально. Можно сделать и так и так.
> Вот где бы почитать что должны принимать и возвращать типовые методы типовых классов - db, mapper, user, session, cookie?
В документации фреймворка Симфони 2 (точнее, за работу с БД там отвечает ORM Doctrine 2). Там это грамотно сделано.
Ну вот тебе пример как используются репозитории в Doctrine 2 (репозиторий это что-то вроде маппера, называется репозиторий потому что он как бы хранит в себе все сущности):
http://doctrine-orm.readthedocs.org/en/latest/reference/working-with-objects.html (англ, но примеры кода-то ты поймешь)
http://odiszapc.ru/doctrine/working-with-objects/ (то же самое по русски но не очень читабельно)
Doctrine 2 реализует паттерн DataMapper, то есть она может отображать в базу любые объекты, для которых ты в конфиге описал соответствие между полями таблицы и полями объекта.
Также, примеры некоторых классов можно посмотреть в Yii2 (у него есть документация на русском), но он не такой «правильный» как доктрина.
Ну и наконец, сами паттерны вроде dataMapper описаны в книге Фаулера «шаблоны проектирования/архитектура корпоративных приложений» (Patterns of Enterprise Application Architecture). Вот описание dataMapper оттуда:
http://design-pattern.ru/patterns/data-mapper.html
Вот похожий паттерн TableDataGateway: http://design-pattern.ru/patterns/table-data-gateway.html
Вот паттерн Domain Model, который в твоем случае реализуется классом User: http://design-pattern.ru/patterns/domain-model.html
Вот еще 2 паттерна используемых в доктрине:
http://design-pattern.ru/patterns/metadata-mapping.html
http://design-pattern.ru/patterns/repository.html
Имей в виду что описания паттернов расчитаны не на начинающих потому их не очень просто понять.
Ну и также порекомендую мой урок про работу с БД: https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md
> типовые методы типовых классов - db, mapper, user, session, cookie
Обычно это делается по другому.
> db
Посмотри doctrine DBAL как пример, или PDO
> mapper
Посмотри мой урок или паттерн datamapper
> user
Просто делаешь объект с информацией о пользователе и все. Это же просто модель.
> session
Можно посмотреть в симфони: http://symfony.com/doc/current/components/http_foundation/sessions.html
> cookie
Обычно там есть объект Request описывающий запрос пользователя и пришедшие от него куки. Чтобы выставить куку, мы создаем ее и добавляем в объект Response, который опсиывает ответ пользователю. Вот симфони:
http://symfony.com/doc/current/book/http_fundamentals.html
Вот примеры кода:
// получение
$value = $request->cookies->get('myCookie');
// установка
$cookie = new Cookie('myCookie', 'contentOfMyCookie');
$response->headers->setCookie($cookie);
Что я хочу сказать: это все реализовано во фреймворках. Если ты не хочешь их изучать а будешь делать свои велосипеды то ты наделуешь кучу ошибок и скорее всего получится какая-нибудь лапша где все перемешано в кучу и сделано на массивах, я такое видел не раз.
Ну и можешь мне задавать вопросы, я постараюсь объяснить
ЕОМВМ, Есть один массив в массиве. Надо присвоить переменную его ключу и значению. Как это дело провернуть?
foreach ($matches as $dick => $size) не выйдет,
ибо $size - array
Ответил тут: >>462486\t
>>462363
Да, чтобы применить изменения в PATH надо либо разлогиниться из винды либо перезагрузиться.
>>462365
займись лучше чем-нибудь более полезным
>>462371
Запиши сортировку и номер страницы в скрытые поля в форме либо в URL в атрибуте action. Мне кажется, со скрытыми полями удобнее.
>>462377
Он начинающий, он должен сначала в совершенстве изучить просто формы, потом яваскрипт а потом уже за аякс браться. А то получится что он бездумно код скопирует из интернета и все.
> Я хочу, чтобы после нажатия кнопки удаления (естественно это через POST) пользователь оставался на той же странице с той же сортировкой
После успешной обработки пост запроса надо делать редирект чтобы при обновлении страницы запрос не отправлялся повтрно и нормально работали переходы назад/вперед по истории.
Сам догадался, чет я затупил.
> код раскидан по разным файлам - если надо будет - залью на гит.
Это было бы хорошо, удобнее обсуждать конкретный код
> в итоге массив (array('name' => 0, 'surname' => 1 ..)) такого типа обрабатывается уже в другом объекте и сохраняется в таблицу errors (TINYINT) с привязкой к куке
Я думаю, ты немного переусложнил реализацию. тут не нужна таблица. При ошибке ты можешь сразу же показать форму с ошибками и тебе не надо их никуда сохранять.
Читал ли ты мой урок по работе с формами? https://github.com/codedokode/pasta/blob/master/forms.md - там дан готовый алгоритм
> так вот, проблема в том, что на странице регистрации не видит куку установленную во время обработки в Action.php,
У куки есть такой параметр как path, то есть путь, и куки доступна только на страницах которые с него начинаются. Например если путь равен /abc то кука будет передаваться барузером только на страницы вроде /abcd, /abc/def но не на /xyz
Почитай тут:
http://citforum.ru/internet/html/cookie.shtml
https://ru.wikipedia.org/wiki/HTTP_cookie
Соответвтенно когда ставишь куку задавай path = '/' чтобы не иметь проблем.
Также ты можешь просмотреть свойства кук в настройках твоего браузера. В старом Хроме это делается тут:
параметры -> расширенные -> настройки содержания -> все файлы cookie
И там ты можешь просмотреть свойства любой куки. В фаерфоксе куки доступны через свойства страницы по моему. Поищи и научись этим пользоваться, это тебе еще пригодится наверняка.
Увидеть какие куки передает сервер можно также инспектором (Ctrl + SHift + I) на вкладке Network в заголовке Set-Cookie. Инспектор надо открыть ДО загрузки страницы.
> код раскидан по разным файлам - если надо будет - залью на гит.
Это было бы хорошо, удобнее обсуждать конкретный код
> в итоге массив (array('name' => 0, 'surname' => 1 ..)) такого типа обрабатывается уже в другом объекте и сохраняется в таблицу errors (TINYINT) с привязкой к куке
Я думаю, ты немного переусложнил реализацию. тут не нужна таблица. При ошибке ты можешь сразу же показать форму с ошибками и тебе не надо их никуда сохранять.
Читал ли ты мой урок по работе с формами? https://github.com/codedokode/pasta/blob/master/forms.md - там дан готовый алгоритм
> так вот, проблема в том, что на странице регистрации не видит куку установленную во время обработки в Action.php,
У куки есть такой параметр как path, то есть путь, и куки доступна только на страницах которые с него начинаются. Например если путь равен /abc то кука будет передаваться барузером только на страницы вроде /abcd, /abc/def но не на /xyz
Почитай тут:
http://citforum.ru/internet/html/cookie.shtml
https://ru.wikipedia.org/wiki/HTTP_cookie
Соответвтенно когда ставишь куку задавай path = '/' чтобы не иметь проблем.
Также ты можешь просмотреть свойства кук в настройках твоего браузера. В старом Хроме это делается тут:
параметры -> расширенные -> настройки содержания -> все файлы cookie
И там ты можешь просмотреть свойства любой куки. В фаерфоксе куки доступны через свойства страницы по моему. Поищи и научись этим пользоваться, это тебе еще пригодится наверняка.
Увидеть какие куки передает сервер можно также инспектором (Ctrl + SHift + I) на вкладке Network в заголовке Set-Cookie. Инспектор надо открыть ДО загрузки страницы.
Все значения атрибутов надо обрабатывать функцией htmlspecialchars. Хотя бы потому что по правилам HTML & должен записываться как &
Должно быть
<x a="<?= htmlspceiclahrs($a, ENT_QUOTES) ?>">
>>462452
DAO если верить вики ( https://en.wikipedia.org/wiki/Data_access_object ) это что-то придуманное Sun для своего фреймворка потому лучше всего обратиться к их документации: http://www.oracle.com/technetwork/java/dataaccessobject-138824.html (там есть картинки если ты не понимаешь английский)
По моему это что-то специфичное для сановского фреймворка и в PHP не используется. А так да, это тоже какой-то похожий на DataMapper объект для отображения объектов на таблицу базы данных.
там же есть пример того какие методы есть у DAO:
// Interface that all CustomerDAOs must support
public interface CustomerDAO {
public int insertCustomer(...);
public boolean deleteCustomer(...);
public Customer findCustomer(...);
public boolean updateCustomer(...);
public RowSet selectCustomersRS(...);
public Collection selectCustomersTO(...);
...
}
Как по мне так это напоминает TableDataGateway у Фаулера: http://design-pattern.ru/patterns/table-data-gateway.html
Все значения атрибутов надо обрабатывать функцией htmlspecialchars. Хотя бы потому что по правилам HTML & должен записываться как &
Должно быть
<x a="<?= htmlspceiclahrs($a, ENT_QUOTES) ?>">
>>462452
DAO если верить вики ( https://en.wikipedia.org/wiki/Data_access_object ) это что-то придуманное Sun для своего фреймворка потому лучше всего обратиться к их документации: http://www.oracle.com/technetwork/java/dataaccessobject-138824.html (там есть картинки если ты не понимаешь английский)
По моему это что-то специфичное для сановского фреймворка и в PHP не используется. А так да, это тоже какой-то похожий на DataMapper объект для отображения объектов на таблицу базы данных.
там же есть пример того какие методы есть у DAO:
// Interface that all CustomerDAOs must support
public interface CustomerDAO {
public int insertCustomer(...);
public boolean deleteCustomer(...);
public Customer findCustomer(...);
public boolean updateCustomer(...);
public RowSet selectCustomersRS(...);
public Collection selectCustomersTO(...);
...
}
Как по мне так это напоминает TableDataGateway у Фаулера: http://design-pattern.ru/patterns/table-data-gateway.html
Документацию читать не пробловал? Там есть и для пользователя, и для разработчика, и часть даже переведена.
codex.wordpress.org по моему
Хочется посмотреть уроки, посмотреть как кто-то делает, тогда всё понятнее становится. Что касается ПХП то я выполняю задания которые должны делать джуниоры, но для устройства в одно место мне необходим вордпресс, и я никак не могу его выучить, даже начать не могу, хотя бы знать как натягивать на вордпресс макет. помогите котаны, наверное многие из вас уже учили вордпресс.
Это бы ничего не поменяло так как путь по умолчанию определяется из URL в адресной строке браузера. Браузеру нет никакого дела, какой из файлов на твоем сервере выполняет setcookie (тем более что он этого и не знает).
>>462536
Читай документацию на http://codex.wordpress.org/
Вот часть страниц что на русском: http://codex.wordpress.org/%D0%97%D0%B0%D0%B3%D0%BB%D0%B0%D0%B2%D0%BD%D0%B0%D1%8F_%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D0%B0
Чтение официальной документации это первое что должно приходить тебе в голову. Какой смысл смотреть видеокурсы? Ну увидишь ты как чувак там жмет какие-то кнопки и правит код и что это тебе даст? Ничего. Максимум ты научишься повторять то, что он делает, не понимая как это работает.
Теперь поговорим про то как сделать сайт на вордпрессе. Вордпресс расширяется двумя путями:
1) написание и установка своей темы. Тема задает внешний вид сайта, ты можешь либо скачать одну из тысяч готовых либо сделать свою на основе существующей верстки (надо знать HTML/CSS)
2) написание и установка плагина. Плагин это код который позволяет добавлять новые возможности, страницы, а также изменять поведение существующего кода. Плагины опять же можно брать готовые, а можно писать самому.
Плагин изменяет поведение вордпресса за счет хуков. Хук — это функция, которая вызывается при совершении определенного действия, например входе в админку, добавлении комментария, вывода поста. Ты можешь сделать в плагине свою функцию, которая вызывается в этих случаях и что-то делает или меняет.
Как создать тему или плагин, описано в документации.
Также, тебе понадобится изучить API вордпресса. API это набор функций которые ты можешь вызывать из тем или плагинов и набор событий, для которых ты можешь создавать свои функции-хуки.
Вот стартовая страница с информацией по созданию темы: http://codex.wordpress.org/%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5_%D1%82%D0%B5%D0%BC
Вот стартовая страница по созданию плагина: http://codex.wordpress.org/%D0%9D%D0%B0%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BB%D0%B0%D0%B3%D0%B8%D0%BD%D0%B0
Ты можешь также погуглить другие уроки (например http://www.google.ru/search?sourceid=chrome&ie=UTF-8&q=habr+%D0%B2%D0%BE%D1%80%D0%B4%D0%BF%D1%80%D0%B5%D1%81%D1%81+%D1%82%D0%B5%D0%BC%D0%B0 ) но документацию ты должен читать в любом случае. Потому что в уроках показывают как сделана та или иная вещь но не объясняют подробностей как работают использованные функции, зачем нужен этот файл и тд
Если ты хочешь хорошо изучить вордпресс, я могу придумать тебе задание сделать сайт на вордпрессе, в ходе решения которого тебе придется изучить и темы (и сверстать свою тему), и плагины. Задание будет выглядеть, как «сделать сайт похожий на example.com c такими-то возможностями» Его выполнение займет наверно недели 2-5 в зависимости от того сколько ты времени будешь уделять ему в день и от твоего уровня знаний PHP/SQL/HTML/CSS. И разумеется документацию придется читать не раз. Но зато ты получишь неплохие навыки.
>>462536
Читай документацию на http://codex.wordpress.org/
Вот часть страниц что на русском: http://codex.wordpress.org/%D0%97%D0%B0%D0%B3%D0%BB%D0%B0%D0%B2%D0%BD%D0%B0%D1%8F_%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D0%B0
Чтение официальной документации это первое что должно приходить тебе в голову. Какой смысл смотреть видеокурсы? Ну увидишь ты как чувак там жмет какие-то кнопки и правит код и что это тебе даст? Ничего. Максимум ты научишься повторять то, что он делает, не понимая как это работает.
Теперь поговорим про то как сделать сайт на вордпрессе. Вордпресс расширяется двумя путями:
1) написание и установка своей темы. Тема задает внешний вид сайта, ты можешь либо скачать одну из тысяч готовых либо сделать свою на основе существующей верстки (надо знать HTML/CSS)
2) написание и установка плагина. Плагин это код который позволяет добавлять новые возможности, страницы, а также изменять поведение существующего кода. Плагины опять же можно брать готовые, а можно писать самому.
Плагин изменяет поведение вордпресса за счет хуков. Хук — это функция, которая вызывается при совершении определенного действия, например входе в админку, добавлении комментария, вывода поста. Ты можешь сделать в плагине свою функцию, которая вызывается в этих случаях и что-то делает или меняет.
Как создать тему или плагин, описано в документации.
Также, тебе понадобится изучить API вордпресса. API это набор функций которые ты можешь вызывать из тем или плагинов и набор событий, для которых ты можешь создавать свои функции-хуки.
Вот стартовая страница с информацией по созданию темы: http://codex.wordpress.org/%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5_%D1%82%D0%B5%D0%BC
Вот стартовая страница по созданию плагина: http://codex.wordpress.org/%D0%9D%D0%B0%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BB%D0%B0%D0%B3%D0%B8%D0%BD%D0%B0
Ты можешь также погуглить другие уроки (например http://www.google.ru/search?sourceid=chrome&ie=UTF-8&q=habr+%D0%B2%D0%BE%D1%80%D0%B4%D0%BF%D1%80%D0%B5%D1%81%D1%81+%D1%82%D0%B5%D0%BC%D0%B0 ) но документацию ты должен читать в любом случае. Потому что в уроках показывают как сделана та или иная вещь но не объясняют подробностей как работают использованные функции, зачем нужен этот файл и тд
Если ты хочешь хорошо изучить вордпресс, я могу придумать тебе задание сделать сайт на вордпрессе, в ходе решения которого тебе придется изучить и темы (и сверстать свою тему), и плагины. Задание будет выглядеть, как «сделать сайт похожий на example.com c такими-то возможностями» Его выполнение займет наверно недели 2-5 в зависимости от того сколько ты времени будешь уделять ему в день и от твоего уровня знаний PHP/SQL/HTML/CSS. И разумеется документацию придется читать не раз. Но зато ты получишь неплохие навыки.
Вы не серчайте. Есть один запрос.
"Подсчитать общие суммы заказов каждому клиенту среди средняя сумма
заказов которых превышает $ 20000 ( название компании , общая сумма заказов ) "
Вот что я написал -
SELECT COMPANY, SUM(AMOUNT)
FROM ORDERS, CUSTOMERS
WHERE CUST = CUST_NUM
AND AVG(AMOUNT) > 20000
GROUP BY COMPANY
ORDER BY 1
Люто бешено выдает ошибку, предположительно в этом виновата четвёртая строка. Помогите, пожалуйста.
Таблица CUSTOMERS содержит по одной строке для каждого из клиентов
CUST_NUM - уникальный номер клиента (первичный ключ)
COMPANY - название компании клиента
Таблица ORDERS содержит по одной строке для каждого из заказов
CUST - номер клиента, сделавшего заказ
AMOUNT - сумма заказа.
Ещё и сажа прилипла, извините.
Ты не можешь использовать агрегатную функцию (AVG) которая работает с группой строк внутри WHERE так как WHERE видит только текущую строку. Вот смотри, в каком порядке выполняется запрос:
- выбираются все строки из таблицы
- если указан JOIN, к ним приджойниваются строки из других таблиц
- затем из получившегося набора берется каждая строка по очереди и проверяется на соответствие WHERE. Если она не соответствует то она откидвывается, если соответствует то остается
- оставшиеся строки группируются вместе по условию GROUP BY, тут же вычисляются значения агрегатных функций вроде MAX, SUM
- затем они (группированные строки) фильтруются по условию HAVING
- затем они сортируются по ORDER (если ORDER не указан то по GROUP BY, если его нет то не сортируются вообще)
- если указаны LIMIT (MySQL)/TOP (SQL) то отбирается часть строк
- из них отбираются указаннаые в SELECT поля
- результат возвращается пользователю
Теперь посомтри внимтельно. Когда выполняется WHERE, строки еще не сгруппированы и ты не можешь получить значение AVG. Оно доступно после группировки в условии HAVING. HAVING это аналог WHERE который применяется к сгруппированным строкам.
А, и еще. Примеры кода лучше постить не кодом, а ссылкой на SQlfiddle, там можно увидеть не только код, а еще и результат выполнения.
Кстати
FROM ORDERS, CUSTOMERS
WHERE CUST = CUST_NUM
это лучше писать в виде джойна,
FROM ORDERS JOIN CUSTOMERS ON ....
ради читабельности. Ведь фактически у тебя джойн тут.
А, и еще. Если ты хочешь получше изучить SQL и порешать задачки посложнее, у нас они есть: https://gist.github.com/codedokode/10539213
А твоя задачка это самые основы, на знание JOIN, GROUP BY и HAVING.
Ну такого я пока ещё не видел.
>>462583
Я и так только только начинаю.
>>462581
Теперь ясно. То есть что-то вроде:
SELECT COMPANY, SUM(AMOUNT)
FROM ORDERS, CUSTOMERS
WHERE CUST = CUST_NUM
GROUP BY COMPANY
HAVING AVG(AMOUNT) > 20000
ORDER BY 1
А что собственно за сайтик SQlfiddle? Анальная регистрация? Там можно свою базу написать и с ней работать/тренироваться?
А ещё мне вот дали вот такой пример:
Вывести имена и общие суммы заказов для всех клиентов, чей лимит кредита превышает 50000.
SELECT COMPANY, T_ORDERS FROM CUSTOMERS, (SELECT CUST, SUM(AMOUNT) AS T_ORDERS FROM ORDERS GROUP BY CUST) WHERE CREDIT_LIMIT > 50000 AND CUST_NUM = CUST
Как такую магию делать? Я ничего не понял.
Без регистрации. Слева пишешь CREATE TABLE/INSERT который создает таблицы, справа запросы к этим таблицам и потом можно поделиться ссылочкой. Поддерживает разные БД (MySQL, Oracle, MSSQL, Postgre, SQlite). Офигенная вещь.
> Там можно свою базу написать и с ней работать/тренироваться?
да
> Как такую магию делать? Я ничего не понял.
Я бы делал на джойнах, без подзапросов. Подзапросы по моему не оптимизируются и тормозят (как минимум в MySQL, наверняка не только в ней) и плохо читаются. Изучи джойны, это несложно.
https://ru.wikipedia.org/wiki/Join_(SQL)
http://potapov.com.ua/library/21/
Я не знаю, какую базу ты изучаешь, но в MySQL одназначно с джойном будет и читабельнее и быстрее.
> Вывести имена и общие суммы заказов для всех клиентов, чей лимит кредита превышает 50000.
Отбираешь клиентов подходящих под условие, приджойниваешь к ним таблицу их заказов и группируешь это по клиентам (чтобы посчитать суммы заказов)
Ты можешь использовать неявный JOIn через
FROM a, b
WHERE a.someId = b.id
Это как минимум короче чем лепить подзапрос. Но если тебе надо с подзапросами, то не знаю.
Вот тут такая статья про джойны в интербейс гуглится: http://www.ibase.ru/devinfo/joins.htm — может там что полезное найдешь.
Используеться, я собственно говоря увидел этот паттерн в топике, где сеньер жаловался на тестовое задания, что ему его придеться писать. Он на php пишет. Спасибо, я уже разобрался. Я вообще сначала пошел к java-истам, но у них тихо
openshift?
Сейчас посмотрел опеншифт, это же не vps, скорее paas, типа хероку
мне нужно получить записи в порядке, определенном вложенным запросом:
SELECT * FROM realestate WHERE id IN (SELECT realestate_id FROM realestate_service as rs WHERE service_id IN (SELECT service_id FROM realestate_service WHERE realestate_id = 1) GROUP BY realestate_id ORDER BY COUNT(service_id) DESC)
В итоге вложенный запрос возвращает интересующий меня порядок id (3,5,1,8) - в порядке большего совпадения. Но сам запрос возвращает просто записи по порядку - 1,3,5,8! Как быть?
Доброе утро, спасибо за пояснеие, стало понятнее немного, и в принципе ясно зачем ты рекомендуешь мне сделать анонимные функции, что бы не объявлять функцию ради того, что бы 1 раз её использовать, но и не писать её тело в том месте куда она подставляется как callable
Но вот незадача, у меня не получается что-то их вызывать:
http://ideone.com/J1uYY8
http://ideone.com/E8WLWu
Не работает так же и у меня в браузере.
Окей, а вот пример с php.net почему-то работает, хотя ошибок я не вижу в предыдущх примерах >>462740
В следующий раз не спрашивая сразу кидай задачки, что бы когда я увидел твой пост, то сразу мог приступить и пробовать что-то решать, а так я пока сижу ничего не делаю
играю в покер на фантики
http://ideone.com/1TY4MQ
После закрывающей скобки этой функции должна быть точка с запятой: };
http://ideone.com/doeQZJ
http://ideone.com/Hae8Vb
http://ideone.com/sbGo5u
Посоны, я задебажил код самого ОП-а!!
Сейчас в общем приступлю к переделке, кое какое понимание появилось
после турнира с возможностью выиграть пол бакса
Да, но есть несколько способов:
1. вместо echo "\n"; попробуй echo "<br>";
2. В начале скрипта пропиши echo "<pre>";
3. Либо пропиши header("Content-Type: text/plain; charset=utf-8");
да
http://giexv6.axshare.com
Сап, помогите написать вот такую программку десктопную.
Как она работает: отмечая галочками чекбоксы, в форме появляются слова тут они почему-то заменяются, а должны идти через запятую, также можно добавлять чекбоксы и удалять я забыл в акшуре это показать, создавать свои списки и редактировать их. Повторный клик по чекбоксу должен убирать слово из формы. Направьте на путь истинный.
Не ахуел ли я так решать?
Чому в echo нельзя вычитать переменные?
Хотел так записать
echo "{$month} месяц спустя: долг = 0 руб, выплачено всего {$paymentTotal - abs($creditBalance)} руб. \n";
Пришлось так
$paymentTotal = $paymentTotal - abs($creditBalance);
echo "{$month} месяц спустя: долг = 0 руб, выплачено всего {$paymentTotal} руб. \n";
> я починил...
> 13 месяц спустя: долг = 0 руб, выплачено всего 65000 - abs(-3729.8132554793) руб.
В общем вот, первые попытки править по твоим комментариям. Разобрался вроде бы с анонимными функциями, очень долго пытался разобраться как их подключать, если я их "описал" наряду с остальными методами, даже стену нытья накатал что ничего не работает, хотя я их как только не пытался вызывать, и как метод, и как к свойству обращался, и как к статике, но в итоге додумался засунуть прямо внутрь метода и всё наконец-то заработало!
>тут лучше написать анонимную функцию, заодно объединив 2 этих команды. Все равно findEngineer нужен тебе только один раз.
Там по моей логике нельзя объединять их, так как нам нужно сначала посчитать всех Инженеров в депертаменте, включая лидеров, а от этого числа будет зависеть уже сколько человек увольнят. Если сразу из этой цифры убирать лидера, то будет погрешность. Поэтому сначала считаем всех, решаем сколько уволить, потом уже выкидываем из массива лидера, и увольняем кого нужно.
Алсо попробовал поклонировать, ну вроде легко и просто всё.
http://ideone.com/imq8s4
Я думаю причина в том что у тебя лишний отступ. Сдвинь все строки влево на 4 пробела. Отступы в YAML учитываются.
Если хочешь попробовать сам разобраться то вот описание формата YAML, ты там где-то с синтаксисом накосячил: http://www.yaml.org/spec/1.2/spec.html (осторожно, много букв на англ.)
Ну и добавлю еще от себя, что маппинги гораздо удобнее делать через аннотации в классе сущности. В этом слуае когда ты что-то меняешь, тебе не надо лезть в YML файл и синхронизировать изменения.
>>462698
Перенеси сортировку в наружный запрос, а не во внутренний. Ну и подзапросы конечно ужасно смотрятся, по моему лучше нормально на джойнах это делать.
А, и отвыкай работать из под рута. Заведи нормального пользователя (команда adduser по моему), а когда надо сделать то-то требующее прав админа, используй sudo. Не используй рутовую консоль вообще никогда.
>>462800
Парсеры будут постоянно ломаться и постоянно придется их править.
>>462838
Не знаю, чтобы ответить на этот вопрос наверно надо профайлить IDE и смотреть что там тормозит.
> отвыкай работать из под рута
уже случайно снёс пару файлов,
но у меня чего-то судо нормально не хочет работать
Надо разобраться почему. Что пишет, «you are not in sudoers file, incident reported»?
Если так то ты должен разрешить пользователю использовать sudo. Разрешения на использование sudo задаются в файле sudoers и ты не должен его править напрямую, а должен использовать команду visudo
В Убунту/Дебиане также достаточно добавить пользователя в группу sudo:
sudo adduser <username> sudo
Если ты хочешь отредактировать файл то надо набрать команду
EDITOR=названиередактора visudo
Если ты не укажешь название редактора то откроется vi и хорошо если ты умеешь им пользоваться.
В файле вписываешь себя: username ALL= (ALL) ALL
Но как я написал выше проще добавить себя в группу.
Промотреть файл sudoers: sudo cat /etc/sudoers
Описание синтаксиса файла: man sudoers
> no space left on device
Диск закончился, удали что-нибудь ненужное.
Команда du -sh /× покажт сколько места занято в каждой папке, × это звездочка
Не надо ничего переустанавливать. Выясни почему и кто это место занимает и в чем причина. Я уже написал же как это сделать, командой du -sh /(звездочка) выясняешь самые захламлденные папки, затем проверяешь что в них. Если ты не найдешь причину то проблема снова повторится.
Возможно кстати что проблема в том что ты все запускал из под рута, а домашнаяя директория рута находится в корневой 300 Мб системе, а не в /home где много места. Тем более если ты запускал графическую оболочку и браузер (который кеширует все что скачиваеся) из под рута.
В этом случае просто удали все файлы из папки /root включая скрытые. В Линукс ты можешь полностью очистить домашний каталог и ничего не сломается, только настройки потреяются и все.
Переустанавливать линукс — это крайняя мера, тут она не требуется.
А, и не перезагружайся а то из-за нехватки места не сможешь войти в систему.
раз уж подняли эту тему спрошу
как поставить второй sublime, то который я поставил не хочет поддклячать emmet и yt hf,jnf.n ytrjnjhst [jnrtb
У меня под WIndows работает Emmet в Sublime Text 3.
Там есть предупреждение:
> Warning: this plugin may not work at all in some OSes since it written in JavaScript and uses PyV8 and Google V8 binaries to run.
Может это как-то связано? Нет каких-то ошибок в консоли Sublime (Ctrl + ~) при запуске?
Я бы не советовал ставить вторую версию, она старая и там нет перехода по имени функции/класса.
Точки с запятой не хватает (ты вроде это уже заметил сам)
>>462744
> В следующий раз не спрашивая сразу кидай задачки
ну давай начнем с задачки про города. Сделай массив с информацией о городах, городов 5-10 хватит, в которых хранится название, страна, население. Можно взять отсюда: https://ru.wikipedia.org/wiki/%D0%A1%D0%B0%D0%BC%D1%8B%D0%B5_%D0%BD%D0%B0%D1%81%D0%B5%D0%BB%D1%91%D0%BD%D0%BD%D1%8B%D0%B5_%D0%B3%D0%BE%D1%80%D0%BE%D0%B4%D1%81%D0%BA%D0%B8%D0%B5_%D0%B0%D0%B3%D0%BB%D0%BE%D0%BC%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8
$cities = array(
array('name' => 'Джакарта', 'country' => 'Индонезия', 'population' => 30539000),
....
);
Теперь напиши программу которая:
1) выведет количество городов с населением больше 20 млн человек (array_filter)
2) выведет 3 самых населенных города по убыванию (используй функции usort, array_slice, может быть array_map)
3) выведет список стран где находятся эти города, без повторов (array_column/array_unique)
Вторая задача на preg_replace_callback. Сделай микрошаблонизатор, то есть функцию, которая на вход получает строку-шаблон и массив с переменными и подставляет их в шаблон:
$template = 'Осталось времени: {time} мин., осталось попыток: {attempts}';
$data = array('time' => 10, 'attempts' => 4);
$result = renderTemplate($template, $data); // Осталось времени: 10 мин., осталось попыток: 4
Третья задача: дан массив вида array('k1' => 'v1', 'k2' => 'v2'), преобразуй его в строку вида "k1=v1, k2=v2" (тут поможет array_map)
Точки с запятой не хватает (ты вроде это уже заметил сам)
>>462744
> В следующий раз не спрашивая сразу кидай задачки
ну давай начнем с задачки про города. Сделай массив с информацией о городах, городов 5-10 хватит, в которых хранится название, страна, население. Можно взять отсюда: https://ru.wikipedia.org/wiki/%D0%A1%D0%B0%D0%BC%D1%8B%D0%B5_%D0%BD%D0%B0%D1%81%D0%B5%D0%BB%D1%91%D0%BD%D0%BD%D1%8B%D0%B5_%D0%B3%D0%BE%D1%80%D0%BE%D0%B4%D1%81%D0%BA%D0%B8%D0%B5_%D0%B0%D0%B3%D0%BB%D0%BE%D0%BC%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%B8
$cities = array(
array('name' => 'Джакарта', 'country' => 'Индонезия', 'population' => 30539000),
....
);
Теперь напиши программу которая:
1) выведет количество городов с населением больше 20 млн человек (array_filter)
2) выведет 3 самых населенных города по убыванию (используй функции usort, array_slice, может быть array_map)
3) выведет список стран где находятся эти города, без повторов (array_column/array_unique)
Вторая задача на preg_replace_callback. Сделай микрошаблонизатор, то есть функцию, которая на вход получает строку-шаблон и массив с переменными и подставляет их в шаблон:
$template = 'Осталось времени: {time} мин., осталось попыток: {attempts}';
$data = array('time' => 10, 'attempts' => 4);
$result = renderTemplate($template, $data); // Осталось времени: 10 мин., осталось попыток: 4
Третья задача: дан массив вида array('k1' => 'v1', 'k2' => 'v2'), преобразуй его в строку вида "k1=v1, k2=v2" (тут поможет array_map)
В итоге, это работает:
require 'vendor/autoload.php';
$app = new \Slim\Slim();
$app->get('/', function(){
echo "hello";
});
$app->run();
А это нет. Выдает 404 ошибку.
require 'vendor/autoload.php';
$app = new \Slim\Slim();
$app->get('/hello/:name', function($name){
echo "hello, $name";
});
$app->run();
Почему?
В твоем случае да, так как ты уже используешь HTML. Но лучше бы ты его не использовал. Ну посмотри сам, тебе приходится добавлять шапку из HTML кода, хотя можно обойтись без нее. Просто поставь в начале программы
header("Content-Type: text/plain; charset=utf-8");
Это заставит браузер воспринимать то, что выводит твоя программа, как обычный текст, а не HTML, и уважать переносы строк в нем (так как в языке HTML перенос строки равносилен пробелу).
Иначе перенос строки будет в исходном коде страницы (его можно увидеть нажав Ctrl + U), но на самой странице его не будет.
То есть если ты не используешь возможности HTML, зачем загрязнять программу лишними тегами? Скорее всего ты это делаешь потому что в твоем учебнике так научили, хотя как по мне так теги там не нужны.
>>462788
> Либо пропиши header("Content-Type: text/plain; charset=utf-8");
Тогда надо еще все HTML теги удалить иначе они выведутся как есть
>>462807
В чем заключается помощь? То ты из этого можешь сделать сам, а что непонятно? яваскрипт знаешь? DOM знаешь? HTML/CSS знешь? Если нет то надо сначала изучить.
>>462815
> Чому в echo нельзя вычитать переменные?
чтобы не было соблазна писать там код. сделай отдельную переиенную и выводи ее.
> if ($creditBalance > 0) {
это лучше заменить на
if (баланс равен или меньше нуля) {
выйти из цикла;
}
> $paymentTotal = $paymentTotal - abs($creditBalance);
Это выглядит как костыль. Нельзя ли сделать так, чтобы баланс не уходил ниже нуля? Я думаю, можно.
Надо смотреть чему равен остаток долга и обрабатывать ситуацию, когда она маленький, а не выплачивать сразу же 5000 вот в этом месте: ... + $servicePayment - $monthlyPayment;
Попробуй переписать код внутри цикла примерно так:
- прибавляем проценты и комиссию к остатку долга
- если остаток маленький, выплачиваем сколько осталось и уходим
- иначе платим 5000
«Платим» здесь значит уменьшаем долг и увеличиваем общую сумму выплаченного.
В твоем случае да, так как ты уже используешь HTML. Но лучше бы ты его не использовал. Ну посмотри сам, тебе приходится добавлять шапку из HTML кода, хотя можно обойтись без нее. Просто поставь в начале программы
header("Content-Type: text/plain; charset=utf-8");
Это заставит браузер воспринимать то, что выводит твоя программа, как обычный текст, а не HTML, и уважать переносы строк в нем (так как в языке HTML перенос строки равносилен пробелу).
Иначе перенос строки будет в исходном коде страницы (его можно увидеть нажав Ctrl + U), но на самой странице его не будет.
То есть если ты не используешь возможности HTML, зачем загрязнять программу лишними тегами? Скорее всего ты это делаешь потому что в твоем учебнике так научили, хотя как по мне так теги там не нужны.
>>462788
> Либо пропиши header("Content-Type: text/plain; charset=utf-8");
Тогда надо еще все HTML теги удалить иначе они выведутся как есть
>>462807
В чем заключается помощь? То ты из этого можешь сделать сам, а что непонятно? яваскрипт знаешь? DOM знаешь? HTML/CSS знешь? Если нет то надо сначала изучить.
>>462815
> Чому в echo нельзя вычитать переменные?
чтобы не было соблазна писать там код. сделай отдельную переиенную и выводи ее.
> if ($creditBalance > 0) {
это лучше заменить на
if (баланс равен или меньше нуля) {
выйти из цикла;
}
> $paymentTotal = $paymentTotal - abs($creditBalance);
Это выглядит как костыль. Нельзя ли сделать так, чтобы баланс не уходил ниже нуля? Я думаю, можно.
Надо смотреть чему равен остаток долга и обрабатывать ситуацию, когда она маленький, а не выплачивать сразу же 5000 вот в этом месте: ... + $servicePayment - $monthlyPayment;
Попробуй переписать код внутри цикла примерно так:
- прибавляем проценты и комиссию к остатку долга
- если остаток маленький, выплачиваем сколько осталось и уходим
- иначе платим 5000
«Платим» здесь значит уменьшаем долг и увеличиваем общую сумму выплаченного.
нельзя писать выражения внутри строки. заведи отдельную переменную и выводи ее.
>>462869
> Employee
> public function __destruct(){
> \tunset($this);
Что это? зачем это? Никогда не пиши unset($this) так как $this это не настоящая переменная, а указатель на текущий объект.
Более того, деструктор не нужен в 99% случаев. В наших учебных задачах он никогда не нужен.
> public $workers = array( );
Сделай это свойство закрытым на всякий случай, а то любой может с массивом делать что угожно, нехорошо.
> public function fireEmployee($employee)
> {
> \tforeach ($this->workers as $num => $worker) {
> \t\tif ($employee === $worker) {
Чтобы найти элементв массиве, удобнее использовать array_search, почитай мануал по ней
> public function addEmployee($employee)
> {
> if (is_array($employee)) {
Я же тебе писал это в прошлый раз. Не делай функцию которая принирмает разные типы данных. Сделай 2 отдельных функции. такие функции запутывают код и позволяют ошибкам оставваться незамеченными.
> $askEngineer = function ($worker) {
>\t\t\treturn (get_class($worker) == "Engineer");
>\t\t};
Для проверки на класс лучше использовать instanceof, а не странные пляски с get_class. Мануал http://php.net/manual/ru/language.operators.type.php
Также, не надо заводить переменную, удобнее передать анонимную функцию прямо в array_filter:
$x = array_filter($y, function () {
...
});
> return ($worker->leader != 1);
Разве там не true/false?
> foreach ($targetEngineers as $name => $fireHim) {
В name действительно хранится имя? Если нет то зачем запутывать того кто читает твой код? Пиши
foreach ($targetEngineers as $engineer)
> $vector1 = clone $vector;
Это клонирует только объект Organisation, департаменты и сотрудники в них не клонируются (это легко увидеть глянув на число сотрудников в отчетах). Тебе надо сделать метод вроде copy() который будет все это делать. Удобно сделать такой метод и на департаменте, и на организации.
нельзя писать выражения внутри строки. заведи отдельную переменную и выводи ее.
>>462869
> Employee
> public function __destruct(){
> \tunset($this);
Что это? зачем это? Никогда не пиши unset($this) так как $this это не настоящая переменная, а указатель на текущий объект.
Более того, деструктор не нужен в 99% случаев. В наших учебных задачах он никогда не нужен.
> public $workers = array( );
Сделай это свойство закрытым на всякий случай, а то любой может с массивом делать что угожно, нехорошо.
> public function fireEmployee($employee)
> {
> \tforeach ($this->workers as $num => $worker) {
> \t\tif ($employee === $worker) {
Чтобы найти элементв массиве, удобнее использовать array_search, почитай мануал по ней
> public function addEmployee($employee)
> {
> if (is_array($employee)) {
Я же тебе писал это в прошлый раз. Не делай функцию которая принирмает разные типы данных. Сделай 2 отдельных функции. такие функции запутывают код и позволяют ошибкам оставваться незамеченными.
> $askEngineer = function ($worker) {
>\t\t\treturn (get_class($worker) == "Engineer");
>\t\t};
Для проверки на класс лучше использовать instanceof, а не странные пляски с get_class. Мануал http://php.net/manual/ru/language.operators.type.php
Также, не надо заводить переменную, удобнее передать анонимную функцию прямо в array_filter:
$x = array_filter($y, function () {
...
});
> return ($worker->leader != 1);
Разве там не true/false?
> foreach ($targetEngineers as $name => $fireHim) {
В name действительно хранится имя? Если нет то зачем запутывать того кто читает твой код? Пиши
foreach ($targetEngineers as $engineer)
> $vector1 = clone $vector;
Это клонирует только объект Organisation, департаменты и сотрудники в них не клонируются (это легко увидеть глянув на число сотрудников в отчетах). Тебе надо сделать метод вроде copy() который будет все это делать. Удобно сделать такой метод и на департаменте, и на организации.
Sublime? Не знаю, у меня пробная версия. Emmet бесплатен, вот гитхаб: https://github.com/sergeche/emmet-sublime
>>462974
Один класс-маппер соответствует обычно одной таблице в БД. Сколько таблиц (сущостей) столько и мапперов.
>>463044
> А это нет. Выдает 404 ошибку.
А какой URL ты в браузере набрал? Там должно быть http://localhost/hello/ivan
Также, добавил ли ты htaccess который перенаправляет все обращения к серверу на index.php?
У меня phpstorm, поэтому вот как-то так получается: http://localhost:63342/FileSharing/hello/ivan
Теперь обнаружил, что и при обращении к стандартному index.php, который в vendor'е при установке Slim'а появился, то же самое происходит.
То есть, к '/' get нормально проходит, а в другие места не работает.
А в .htaccess по-умолчанию такое написано:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [QSA,L]
Вроде как RewriteRule же заменить нужно? И формат какой-то странный, это не регулярки же вроде.
Формат описан тут http://habrahabr.ru/company/sprinthost/blog/129560/
И в офиц. док-и на англ. http://httpd.apache.org/docs/current/mod/mod_rewrite.html
> У меня phpstorm, поэтому вот как-то так получается:
Что значит получается? У phpStorm какой-то свой встроенный сервер или что? Если встроенный (например php с флагом -s) то он не пойдет так как он скорее всего не интерпретирует htaccess. Нужен Апач либо если используется php -s нужен скрипт роутинга: http://php.net/manual/ru/features.commandline.webserver.php
> это не регулярки же вроде.
^ это регулярка которая соовтетствует любой строке. RewriteCond говорит что правило не должно применяется если URL указывает на существующий файл или папку.
Надо разобраться какой сервер используется и поддерживает ли он htaccess.
Если ты исплоьзуешь это https://www.jetbrains.com/phpstorm/help/php-built-in-web-server.html
то тебе нужно настроить скрипт роутинга который будет запускать index.php. Вот в мануале написано
> To have a specific script always executed upon the server start-up, select the Use router script check box and specify the path to the script in the text box.
Я думаю, можно в качестве скрипта роутинга сделать скипт router.php который проверяет: если URL указывает на статический файл, то return false, иначе запускаем index.php
Ну или ты можешь установить и настроить Апач. Мне кажется написание скрипта роутинга было бы неплохим управжнением.
Ну и помни что этот сервер ты можешь запустить и без phpStorm, просто из командной строки, как описано в мануале.
Фриланс тебе чем не угодил?
Фриланс или удаленная работа, но с «низкими и поверхностными» знаниями будет сложно пробиться. Потому советую все свободное время посвящать улучшению уровня знаний, а параллеьно прочесывать сайты вроде branistorage/fl.ru в поисках заказов или работы.
Дан массив элементов. Каждый элемент имеет следующие параметры:
"Id" — уникальный числовой идентификатор
"ParentId" — идентификатор родителя, если таковой имеется, иначе 0
"Text" — текст.
Необходимо вывести элементы в виде дерева.
И далее следует многомерный массив навроде
$arr = array(
array(
'id' => '1',
'name' => 'Имя раздела 1',
'parentid' => '0'
),
array(
'id' => '2',
'name' => 'Имя раздела 2',
'parentid' => '0'
Сказать что я охуел - ничего не сказать. В голову идут только мысли создать какую-нибудь рекурсивную функцию, чтобы вкладывала один массив внутрь другого в родительском порядке, но как это сделать - хуй знает...Как развивать вот это абстрактное мышление? Функции то я заучил, а мыслить не научился.
Делаю поиск по сайту, под капотом которого друпал
Я наверное немного неправильно выразился, надо сделать навигационное меню, что бы все ссылки и выпадающие списки, располагались не горизонтально, вверху экрана, а справа и располагались вертикально.
Смотри примеры на страничке документации, там есть один подобный, но не очень красивый.
Вкинь сам массив пожалуйста? Я вот не понимаю как он у тебя оформлен, или тебе надо ему самому создать перед тем как выводить?
У тебя там массив сам в виде дерева, или просто в виде нескольких слоев?
> Это выглядит как костыль. Нельзя ли сделать так, чтобы баланс не уходил ниже нуля?
Переделал http://ideone.com/zMQExR
> То есть если ты не используешь возможности HTML, зачем загрязнять программу лишними тегами? Скорее всего ты это делаешь потому что в твоем учебнике так научили, хотя как по мне так теги там не нужны.
Сразу решил писать в IDE, а она создает проект сразу с тегами HTML. Из учебников, только твой сайт в шапке.
http://symfony.in.ua/symfony2-jobeet-day-3-the-data-model.html
в yml файлах абсолютно точно нет ошибок, табов и лишних пробелов
и мне выдаёт такую хуйню, права у деректорий везде 777
Что я делаю не так?
$templates=array(
array("Id"=>1,"ParentId"=>0,"Text"=>"Тестовое задание для PHP-программиста"),
array("Id"=>2,"ParentId"=>1,"Text"=>"Тестовое задание для PHP-программиста2"),
array("Id"=>3,"ParentId"=>1,"Text"=>"Тестовое задание для PHP-программиста3"),
array("Id"=>4,"ParentId"=>2,Text"=>"<Тестовое задание для PHP-программиста4"),
array("Id"=>5,"ParentId"=>3,"Text"=>"Тестовое задание для PHP-программиста5"),
array("Id"=>6,"ParentId"=>2,"Text"=>"Тестовое задание для PHP-программиста6"),
array("Id"=>7,"ParentId"=>0,"Text"=>"Тестовое задание для PHP-программиста7")
)
И надо сделать как то так
<Родитель id-text>
<Дочерний элемент id-text>
<Дочерний элемент id-text>
<Дочерний элемент id-text>
<Родитель id-text>
<Дочерний элемент id-text>
<Дочерний элемент id-text>
<Дочерний элемент id-text>
у меня так же всё
В общем я хотел было тебе помочь, а потом пока тебя ждал, сам заинтересовался, как бы написать хуйню похожую по функционалу на print_r();
Но я пиздец какой-то тупой и не могу просчитать где должны быть переносы и прочие "пробелы" все через жопу, сижу даже методом подбора не могу сделать.
Может кто другой подскажет где дыра в моей логике.
http://ideone.com/O5M9c7
Очередной черновик, знаю, что там не работает проверка почты при редактировании. Хочу по структуре услышать советы, знаю что выглядит это всё огромной кучей в которой сложно разобраться, что убрать и что переделать?
Аноны, помогите? Как реализовать это говнецо? Если массив в виде дерева, то как его вывезти на экран, что бы просто все "дети" имели отступ больше чем их родитель.
Вот решение моей задачи http://ideone.com/gt1dkf .
Разберись, и твоя совсем простой покажется.
делаю это http://symfony.in.ua/symfony2-jobeet-day-3-the-data-model.html
получлось это https://ideone.com/DbMzfE
этой штуке опять что-то не нравится
Там ведь в эти поля должна поставиться текушая дата и время, я правильно понимаю?
Он же пишет в чем причина:
> created_at cannot be null
Причина в том что в базе поле created_at помечено как не NULL, а ты пытаешься сохранить сущность в которой там стоит NULL.
Ты не должен бездумно копировать код из урока, от этого не будет никакой пользы. Ты должен в каждом случае разбираться что проиходит. А ты именно копируешь не разбираясь.
Ну и конечно надо читать документацию по доктрине параллельно с уроками.
Так что остановись и разберись почему у тебя там null и какое решение в уроке предлагается чтобы проставлять знаечния этого поля автоматически.
Вот мануал по доктрине:
(англ) http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/
(рус) http://odiszapc.ru/doctrine/
> Там ведь в эти поля должна поставиться текушая дата и время, я правильно понимаю?
сама по себе она не проставится. С чего бы? Доктрина просто сохраняет в базу значения свойств объекта которые ты указал в yaml файле и никакие даты не проставляет. А твой yml файл просто описывает соответствие между колонками БД и полями модели.
Однако там есть специальные события, когда доктрина перед сохранением вызывает помеченный метод у твоей сущности, и этот метод может проставить нужные знаечния полей.
Если тебе что-то непонятно по доктрине, задавай конкретные вопросы.
Вот мануал по событиям:
http://odiszapc.ru/doctrine/events/
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/events.html
Обрати внимние, там есть несколько вариантов:
— методы модели будут вызываться при определенном событии, если методы в ней пометить нужной аннотацией (так как в модели недоступен DI container то эти методы могут делать только простые вещи с самой моделью)
— также можно подписаться снаружи через EventManager
Доктрина довольно мощная ORM и чтобы в ней разобраться, надо читать мануал, может даже заглядывать в API docs или исходники. Только копируя код в учебнике ты ее не изучишь.
Я там прикрепил код с методом, в котором, как раз проставлен new DateTime, но он почему то всё равно не работает
Да бро, с html средствами это легко, а я хотел написать свою годную функцию, которая просчитывает все это говно сама, и делает отступов сколько надо.
http://ideone.com/PJ33hc
А ты этот метод вызываешь? Ты можешь сделать
var_dump($job_sensio_labs)
и помотреть что там в объекте.
И тебе все равно надо прочесть документацию по доктрине. В учебнике практически ничего не объяснятся, так ты ничему не научишься.
1. Есть таблица remembered с полями user_id и hash.
2. Во время залогинивания, если пользователь поставил галочку в чекбокс 'запомнить' ищем его айди в таблице. Если нет - генерируем новый хэш, записываем в таблицу, записываем в кукиз. Если пользователь там уже есть достаем значение хэша, записываем в кукиз.
3. При входе смотрим есть ли в кукиз хэш, если есть - ищем его в таблице, возвращаем user_id, автоматически залогиниваем, если нет то ничего не делаем.
Собственно, все нормально работает, смущает только вот что - стоит пользователю один раз поставить галочку и хэш уже никогда не изменится в базе. Вроде бы ничего страшного, но мало ли.
>1. Есть таблица remembered с полями user_id и hash.
А скажи вот мне, у тебя в этой таблице только это? Бывают две записи с 1 user_id? Если нет, то почему просто не добавить столбец hash в таблицу users например?
> Если пользователь там уже есть достаем значение хэша, записываем в кукиз.
А почему бы не перезаписывать хэш в этом пункте?
>Если нет, то почему просто не добавить столбец hash в таблицу users например?
Не знаю даже, при желании с натяжкой можно назвать отдельной сущностью. Типа это просто пользователи, а это пользователипожелавшиечтобихзапомнили. Просто в просто пользователях уже и так столбцов нехило так.
>А почему бы не перезаписывать хэш в этом пункте?
Вот в этом случае действие как будто лишнее. Но я как обычно, только отправил пост и сразу придумал что запись и из базы в том числе можно удалять при логауте же.
Идти по задачам из шапки
bootstrap templates загугли, ну епт.
Лучше YII, а не симфони. А еще лучше - уползать от php-зашквара.
Не пытайся с самого начала решить все-все задачи средствами фреймворка - это бывает сложно, потому что реальные задачи часто отличаются от маняфантазий авторов классов фреймворка. Иногда приходится велосипедить. Поначалу лучше относиться к фреймворку просто как к MVC + фишечки вроде авторизации, но не забывать и о начитывании референса по фичам, которые ты реализовал велосипедом из-за нехватки знаний по фреймворку. В идеале - делаешь свой форк фреймворка и по мере закрытия проектов скидываешь полезные фичи в код, чтобы потом быстро пулить с гита и хуячить новый проект уже на своих наработках.
Вот в этом учебнике (https://jhayes73.files.wordpress.com/2011/07/php-for-the-web-visual-quickstart-guide-4th-edition2011bbs.pdf) на страницах 148-149 объясняют, как с помощью цикла for сгенерировать список из <option>, внутри которого будут дни месяца. Но почему-то у меня в браузере не генерируется. Денвер перезапускал, код прямо из книги копировал, но ничего не меняется.
1) Унылое community. Кругом неосиляторы с книжкой "пхп за 24 часа" и студенты с лабами. Кругом мастера по натягиванию джумлы, которые не могут осилить никакую нестандартную задачу (хорошо, 1 из 50 может). Оче мало всяких конференций и мастер-классов (битрикс в расчет не берем, по понятным соображениям).
2) Ужасный, омерзительный код большинства проектов. Хотя когда я ковырял пару ява-проектов - код там был не уебищен по своей сути, но сам язык приучает хоть как-то структурировать свой код.
3) Вот это $ дерьмо, тысячи стандартных функций в общем неймспейсе, вот это { } ; дерьмо, омерзительная типизация с унылыми параноидальными приведениями типов (ты же не запомнишь все 250 вариантов, как препроцессор будет приводить типы по дефолту). Тысячи их, все писали уже неоднократно.
4) Любая задача посложнее, чем запрос ебануть и html вывести, превращается в ебучую содомию отладки и ужасный говнокод - сложная математика, работа с изображениями, с большими данными, с деревьями. Это просто пиздец, кто сталкивался, тот поймет - везде различные варианты unset() для очистки памяти (хотя казалось бы данных немного) потому что дебил пхп сам хуево чистит. Везде абсолютно неожиданные подводные камни с типизацией и хуй пойми чем, из-за которых надо покрывать каждый чих тестами, если хочешь, чтобы оно работало.
Здесь вообще не должно быть этого треда, как и 1С-треда. Пусть лучше хаскеллисты пердолятся - от них хоть что-то интересное узнаешь.
И какой у тебя стаж?
Вообще что могу сказать, вместо потреблядского отношения к треду, мог бы и посоветовать что-то.
Тут дохуя вопрошающих, а человек который всем отвечает - один.
Ошибки нет, но результат постоянно сортирован по айди.
Подозреваю, что в bindParam(':order', $order, PDO::PARAM_STR) как-то не так подставляется название колонки таблицы, то ли в кавычках, то ли еще какая оказия.
Упрощенный пример на одной страничке: http://ideone.com/I9EYmF
Что я делаю не так?
Из того что я нагуглил за два с лишним часа, вроде бы понял, что нельзя использовать плейсхолдеры для подстановки названия колонки, только для подстановки значений.
http://stackoverflow.com/questions/2542410/how-do-i-set-order-by-params-using-prepared-pdo-statement
Вопрос более-менее снят, но все-таки прошу ОПа прокомментировать, как появится.
используй mb_str*- функции
Понял тебя, так и сделаю. В программировании много от боевых искусств востока, и я полон смирения методично задрачивать знания по указанному тобой пути.
Открой инспектор (Ctrl + Shift + I) и изучи какие свойства и правила CSS применены к элементам. Вот статья: http://habrahabr.ru/post/143767/
>>463423
Yii полезен, да, но Симфони все же более сложный и продвинутый фреймворк. Я бы изучал по очереди, Yii 2 -> Symfony 2
> уползать от php-зашквара.
Назови «незашкварные» технологии, которые ты знаешь хотя бы на четверку. И которые востребованы работодателями. Сразу предупрежу что нода/руби/монго для меня в несколько раз «зашкварнее» чем php потому что люди просмотрев несколько видеоуроков думают, что они что-то умеют, а на самом деле они даже языка толком не знают.
> Не пытайся с самого начала решить все-все задачи средствами фреймворка - это бывает сложно, потому что реальные задачи часто отличаются от маняфантазий авторов классов фреймворка.
Может ты просто плохо в нем разбираешься? Что не решается средствами фреймворков, приведи примеры.
>В идеале - делаешь свой форк фреймворка
Не стоит, имхо, так как уйдет куча времени на поддержку и синхронизацию с апстримом. Свои доработки лучше делать в виде сторонних библиотек. Благо та же Симфони позволяет исплоьзовать свои (не зависящие от ее классов) контроллеры, модели и т.д. А вот Юи, кстати, не позволяет, что имхо его минус.
Ну и да, некоторые делают что-то вроде бойлерплейта, когда берется фремворк/CMS, ставятся нужные плагины/расширения, но это нужно только если ты клепаешь сайты со скоростью 1 сайт за 3 дня. Если проект долговременный, то это не нужно, тем более что зависимости ставятся через тот же композер.
Посмотри какие ошибки выводятся.
В PHP по умолчанию выключено отображение ошибок в браузере, так как обычному пользователю сайта эта информация ни к чему. Но тебе, как программисту, надо видеть эти ошибки. Вот, как можно их просмотреть:
- ошибки сохраняются в лог ошибок. Можно открыть его и почитать. Если ты запускаешь код на локалхосте, у себя, то лог хранится в папке Апача (обычно она называется logs) и имеет название вроде error.log (в линуксе в папку /var/log/apache2 ). Если на хостинге — там либо есть файл error.log либо раздел в панели управления, где лог можно посмотреть
- также, ты можешь включить отображение ошибок. Открой файл php.ini, поставь там display_errors = On и error_reporting = E_ALL и перезапусти сервер. Теперь ошибки должны выводиться на экран.
Проверить, работает ли вывод ошибок, можно запустив скрипт содержающий обращение к несуществующей переменной вроде echo $sdgasdad; и проверив, выведется ошибка или нет. Если все верно, то должна вывестись.
> Унылое community. Кругом неосиляторы с книжкой "пхп за 24 часа" и студенты с лабами.
Я вижу другое, я вижу что у нас многие аноны стараются научиться писать правильный и хороший код. А если где-то это не так, то это потому что там коммьюнити в котором собираются студенты в лабами и никто не направляет в правильную сторону.
> Оче мало всяких конференций и мастер-классов
Мне они и не нужны (и я не уверен, что мало). Для меня например пролистать PDF доклада или прочитать статью гораздо быстрее чем смотреть длинную запись и тем более угробить день (да еще и деньги за это платить) чтобы на это посмотреть ИРЛ.
> Ужасный, омерзительный код
можно написать на любом языке
> тысячи стандартных функций в общем неймспейсе
как они тебе мешают? Напиши конкретный пример когда это помешало тебе решить задачу. Намекаю: посместив свой код в отдельный неймспейс ты надежно от них изолируешься.
> вот это { } ; дерьмо,
Руби тред в другой стороне. Я тебе скажу, что меня наоборот бесят дебилы которые из фанатизма сделали яваскрипт на отступах, CSS на отступах и даже HTML на отступах который невозможно ни читать ни использовать в реальных проектах. Я бы в общем спокойно к ним относился но они зомбируют людей и даже в php проекте ты можешь с этими недоязыками столкнуться. Вот это действительно плохо. Я думаю, уж ты-то поймешь мои чувства.
> омерзительная типизация с унылыми параноидальными приведениями типов
Это да, но на практике я очень редко сталкиваюсь с проблемами из за этого.
> Любая задача посложнее, чем запрос ебануть и html вывести, превращается в ебучую содомию отладки и ужасный говнокод
Не согласен. У меня не превращается. Может ты просто чего-то не знаешь? Я например пишу (пока не дописал) свой движок регуярных выражений на php и все вроде нормально: ООП, тесты, кодогенерация.
> везде различные варианты unset() для очистки памяти
Это не требуется.
> отому что дебил пхп сам хуево чистит
Неправда
> из-за которых надо покрывать каждый чих тестами, если хочешь, чтобы оно работало.
может это ты так код пишешь что у тебя ничего не работает? Я с таким не сталкивался
> Здесь вообще не должно быть этого треда, как и 1С-треда.
Не заходи. К тому же интуиция подсказывает мне что ты и хаскелла не знаешь. Тебе же без нашего треда даже выговориться негде будет.
> Унылое community. Кругом неосиляторы с книжкой "пхп за 24 часа" и студенты с лабами.
Я вижу другое, я вижу что у нас многие аноны стараются научиться писать правильный и хороший код. А если где-то это не так, то это потому что там коммьюнити в котором собираются студенты в лабами и никто не направляет в правильную сторону.
> Оче мало всяких конференций и мастер-классов
Мне они и не нужны (и я не уверен, что мало). Для меня например пролистать PDF доклада или прочитать статью гораздо быстрее чем смотреть длинную запись и тем более угробить день (да еще и деньги за это платить) чтобы на это посмотреть ИРЛ.
> Ужасный, омерзительный код
можно написать на любом языке
> тысячи стандартных функций в общем неймспейсе
как они тебе мешают? Напиши конкретный пример когда это помешало тебе решить задачу. Намекаю: посместив свой код в отдельный неймспейс ты надежно от них изолируешься.
> вот это { } ; дерьмо,
Руби тред в другой стороне. Я тебе скажу, что меня наоборот бесят дебилы которые из фанатизма сделали яваскрипт на отступах, CSS на отступах и даже HTML на отступах который невозможно ни читать ни использовать в реальных проектах. Я бы в общем спокойно к ним относился но они зомбируют людей и даже в php проекте ты можешь с этими недоязыками столкнуться. Вот это действительно плохо. Я думаю, уж ты-то поймешь мои чувства.
> омерзительная типизация с унылыми параноидальными приведениями типов
Это да, но на практике я очень редко сталкиваюсь с проблемами из за этого.
> Любая задача посложнее, чем запрос ебануть и html вывести, превращается в ебучую содомию отладки и ужасный говнокод
Не согласен. У меня не превращается. Может ты просто чего-то не знаешь? Я например пишу (пока не дописал) свой движок регуярных выражений на php и все вроде нормально: ООП, тесты, кодогенерация.
> везде различные варианты unset() для очистки памяти
Это не требуется.
> отому что дебил пхп сам хуево чистит
Неправда
> из-за которых надо покрывать каждый чих тестами, если хочешь, чтобы оно работало.
может это ты так код пишешь что у тебя ничего не работает? Я с таким не сталкивался
> Здесь вообще не должно быть этого треда, как и 1С-треда.
Не заходи. К тому же интуиция подсказывает мне что ты и хаскелла не знаешь. Тебе же без нашего треда даже выговориться негде будет.
По моему дерево построить относительно несложно, если у узла A есть родитель B то надо взять B и добавить в его список детей A. И так для каждого узла из исходного списка.
Ну и тестовое задание должно проверять твои знания, не наши. А я пожалуй твое задание для других анонов включу в наш список заданий с собеседований, может им пригодится.
>>463188
Часть знаний можно исплоьзовать (про рекурсию например), но надо помнить что в php другие правила действуют и не пытаться писать как на Си++. Например, деструкторы в php для освобождения памяти не нужны.
>>463216
> как ты относишься к тому, что на php можно начать говнкодить почти сразу и привыкнуть
я отношусь к этой идее плохо и думаю что надо учиться писать хороший, правильный ООП код. Чему мы в нашем треде и учим.
>>463231
Если на сайте бутстрапа такого нет, то либо ищи готоовый код либо сверстай сам. Если ты знаешь CSS то это не проблема, если не знаешь — давай изучать, у нас есть неплохие задания на него (в первом посте).
>>463238
О, почти идеально, а можно еще чуть-чуть код улучшить? Я вижу там строки
> $paymentTotal = $paymentTotal + $monthlyPayment;
> echo "{$month} месяц спустя: долг =
повторяются 2 раза, можешь сделать чтобы не повторялись?
> Сразу решил писать в IDE, а она создает проект сразу с тегами HTML.
Это настраивается, и тебе лучше это отключить так как в реальных проектах никто не заключает каждый php файл в HTML теги. В реальных проектах HTML код хранится отдельно от логики.
>>463252
Ок, все верно решено.
По моему дерево построить относительно несложно, если у узла A есть родитель B то надо взять B и добавить в его список детей A. И так для каждого узла из исходного списка.
Ну и тестовое задание должно проверять твои знания, не наши. А я пожалуй твое задание для других анонов включу в наш список заданий с собеседований, может им пригодится.
>>463188
Часть знаний можно исплоьзовать (про рекурсию например), но надо помнить что в php другие правила действуют и не пытаться писать как на Си++. Например, деструкторы в php для освобождения памяти не нужны.
>>463216
> как ты относишься к тому, что на php можно начать говнкодить почти сразу и привыкнуть
я отношусь к этой идее плохо и думаю что надо учиться писать хороший, правильный ООП код. Чему мы в нашем треде и учим.
>>463231
Если на сайте бутстрапа такого нет, то либо ищи готоовый код либо сверстай сам. Если ты знаешь CSS то это не проблема, если не знаешь — давай изучать, у нас есть неплохие задания на него (в первом посте).
>>463238
О, почти идеально, а можно еще чуть-чуть код улучшить? Я вижу там строки
> $paymentTotal = $paymentTotal + $monthlyPayment;
> echo "{$month} месяц спустя: долг =
повторяются 2 раза, можешь сделать чтобы не повторялись?
> Сразу решил писать в IDE, а она создает проект сразу с тегами HTML.
Это настраивается, и тебе лучше это отключить так как в реальных проектах никто не заключает каждый php файл в HTML теги. В реальных проектах HTML код хранится отдельно от логики.
>>463252
Ок, все верно решено.
Это лучше делать по другому. Просто передавай в свою функцию дополнительный параметр, «отступ». Его можно передавать либо числом (число пробелов) либо строкой. А при рекурсивном вызове увеличивай его.
>>463280
Все правильно
Тоже все верно
О, ты с массивом сделал? молодец, все правильно.
Тут тоже все правильно сделано.
Такое ощущение, что где-то в настройках апача или php установлен таймаут. Можно как-нибудь эту проблему решить, чтобы страница грузилась сколько нужно, а не с таймаутом?
> О, почти идеально, а можно еще чуть-чуть код улучшить?
> повторяются 2 раза, можешь сделать чтобы не повторяли
Так лучше? https://ideone.com/xX2q96
Эт снова я, с мапперами. Потихоньку все пишется, методы достающие юзеров из базы работают так.
function getUserByEmail($email) {
$result = $query->getFirst();
$user_attributes = $this->objectToArray($result);
$user = new User();
$user->setAttributes($user_attributes);
return $user;
Все ок.
Теперь же надо их еще и добавлять. Метод вроде
function insertNewUser($user_attributes) {
...
$sql = 'INSERT INTO users VALUES (?,?,?,?,?)';
$db->query($sql,[]);
...
}
что должен принимать - массив или объект User? По идее массив проще но нужно внимательно следить за порядком аргументов. В случае же с объектом его надо будет все равно внутри переразбивать в массив. Причем создаваться он будет вне маппера и что самое нелепое - из массива, как-то так
$user_attributes = ['id' = '','username' = 'alex', 'password' = 'qwerty',...];
$user = new User();
$user->setAttributes($user_attributes);
> знаю что выглядит это всё огромной кучей в которой сложно разобраться,
Чтобы такого не было, вынеси те скрипты, которые можно вызывать из браузера, в корень, а которые нельзя (классы и функции) оставь в lib. Также, называй файлы с классами точно так же как назвается класс, Class -> Class.php
Весь HTML код должен быть в папке templates.
Также, надо бы избавиться от кучи require. Сделай файл с названием init.php или boostrap.php в папке lib, и пусть он делает все нужные приготовления: создает объект соединения с БД, подключает все нужные файлы. Чтобы инициализация была только в одном месте, а не размазана по всему коду.
Также, некоторые файлы названы неудачно и имя не соответствует содержанию, их надо переименовать. Вот они:
Cookie.php — c большой буквы пишутся только файлы с классами, назови файл xsrf-protection.php. Также, лучше бы сделать эти функции статическими методами в классе, например XsrfProtection
action.php — название файла не говорит о том что он делает. action ничего не значит так как любой файл делает какие-то действия. Назови например save-student.php и вынеси в корень.
BaseRedirect.php - надо переименовать в соответствии с именем класса
check.php — перенести содержимое в bootstrap.php
FormInspect.php — назови просто student-form.php и вынеси в корень.
ListAction.php — назови list.php и вынеси в корень
pager.php — HTML код вынеси в отдельный файл-шаблон, саму функцию можешь оставить
PDO.php — перенеси в bootsrap.php
SearchAction.php — переименый в search.php и помести в корень
Student.php — исправь форматирование, например через сайт phpformatter.com
Тогда твой проект станет гораздо полнятнее.
Давай для начала ты перенесешь/переименуешь файлы и исправишь вот эти замечания от робота, а потом мы сможем посмотреть на код более внимательно. Замечания от робота:
Ты используешь функции mb_xxx в своем коде, а указал ли ты для них используемую кодировку с помощью mb_internal_encoding(...)? Без этого эти функции могут неправильно обрабатывать строки.
В файле ./lib/BaseRedirect.php:
Согласно PSR-0 и PSR-4 имя файла с классом должно соответствовать имени класса с точностью до регистра букв, например MyAwesomeClass => MyAwesomeClass.php. Имя файла с классом «ErrorsMapper» не соответствует этим правилам.
Задал ли ты кодировку соединения с базой при работе через PDO? Это можно сделать либо параметром charset= при соединении либо командой SET NAMES в PDO::MYSQL_ATTR_INIT_COMMAND. Мануал: http://php.net/manual/ru/ref.pdo-mysql.connection.php
В файле ./lib/action.php:
Не используй короткий открывающий тег <? так как он может быть отключен в настройках. Используй либо длинный открывающий тег <?php для кода, либо короткий <?= для вывода значений в шаблонах.
В файле ./errors:
Файл с SQL дампом принято называть с расширением .sql, например students.sql
Кажется, ты не используешь строгий режим в MySQL. Зря. MySQL более тщательно проверяет твои запросы и вместо предупреждений (которые ты не увидишь) выдает ошибки при попытке вставить неправильные данные. Ну к примеру, если у тебя есть колонка типа varchar(200) и ты попытаешься вставить в нее строку из 300 символов, в нестрогом режиме MySQL молча отрежет лишнее (и в базе окажется обрезанная строка), а в строгом выдаст ошибку.
Использование строгого режима экономит твое время на исправление неправильно вставленных данных. Статья на хабре: http://habrahabr.ru/post/116922/
Включить строгий режим можно сделав при соединении с БД запрос SET sql_mode='STRICT_ALL_TABLES'. В PDO это удобно сделать опцией PDO::MYSQL_ATTR_INIT_COMMAND при создании объекта PDO.
В файле ./css/css/bootstrap.css:
Похоже, что ты правил файл .\css\css\bootstrap.css, который является частью библиотеки bootstrap-3.3.4. Не делай так. Ты думал, робот это не заметит?
Изменять файлы из стронних библиотек плохая идея по двум причинам. Во-первых, человек, разбирающийся в твоем коде, вряд ли сможет найти твои правки в куче кода. Он будет наивно думать что библиотека не изменена. Во-вторых, когда библиотеку захотят обновить, либо потеряются твои правки, либо эти правки придется переносить как-то вручную. Представь себе какой это объем труда. К тому же эти изменения могут еще и оказаться несовместимыми с новой версией библиотеки.
Никогда не меняй файлы внешних библиотек.
Или же ты просто используешь неофициальную или нестандартную сборку? Лучше использовать официальную.
Вот список изменений (в формате https://ru.wikipedia.org/wiki/Diff ):
> @@ -2916,7 +2916,7 @@
> .form-inline .input-group .input-group-addon,
> .form-inline .input-group .input-group-btn,
> .form-inline .input-group .form-control {
> - width: auto;
> + width: 100%;
> }
> .form-inline .input-group > .form-control {
> width: 100%;
В этой задаче минимум 2 поля, для которых стоит использовать тип ENUM — это пол и место жительства. У тебя ENUM исплоьзован всего 1 раз, что странно.
Похоже что ты не использовал тип YEAR для хранения года рождения, а ведь такой тип специально для этого придуман. Если ты про него не знал, то почитай про то какие типы есть в MySQL:
http://phpclub.ru/mysql/doc/column-types.html
(конец замечаний от робота)
> знаю что выглядит это всё огромной кучей в которой сложно разобраться,
Чтобы такого не было, вынеси те скрипты, которые можно вызывать из браузера, в корень, а которые нельзя (классы и функции) оставь в lib. Также, называй файлы с классами точно так же как назвается класс, Class -> Class.php
Весь HTML код должен быть в папке templates.
Также, надо бы избавиться от кучи require. Сделай файл с названием init.php или boostrap.php в папке lib, и пусть он делает все нужные приготовления: создает объект соединения с БД, подключает все нужные файлы. Чтобы инициализация была только в одном месте, а не размазана по всему коду.
Также, некоторые файлы названы неудачно и имя не соответствует содержанию, их надо переименовать. Вот они:
Cookie.php — c большой буквы пишутся только файлы с классами, назови файл xsrf-protection.php. Также, лучше бы сделать эти функции статическими методами в классе, например XsrfProtection
action.php — название файла не говорит о том что он делает. action ничего не значит так как любой файл делает какие-то действия. Назови например save-student.php и вынеси в корень.
BaseRedirect.php - надо переименовать в соответствии с именем класса
check.php — перенести содержимое в bootstrap.php
FormInspect.php — назови просто student-form.php и вынеси в корень.
ListAction.php — назови list.php и вынеси в корень
pager.php — HTML код вынеси в отдельный файл-шаблон, саму функцию можешь оставить
PDO.php — перенеси в bootsrap.php
SearchAction.php — переименый в search.php и помести в корень
Student.php — исправь форматирование, например через сайт phpformatter.com
Тогда твой проект станет гораздо полнятнее.
Давай для начала ты перенесешь/переименуешь файлы и исправишь вот эти замечания от робота, а потом мы сможем посмотреть на код более внимательно. Замечания от робота:
Ты используешь функции mb_xxx в своем коде, а указал ли ты для них используемую кодировку с помощью mb_internal_encoding(...)? Без этого эти функции могут неправильно обрабатывать строки.
В файле ./lib/BaseRedirect.php:
Согласно PSR-0 и PSR-4 имя файла с классом должно соответствовать имени класса с точностью до регистра букв, например MyAwesomeClass => MyAwesomeClass.php. Имя файла с классом «ErrorsMapper» не соответствует этим правилам.
Задал ли ты кодировку соединения с базой при работе через PDO? Это можно сделать либо параметром charset= при соединении либо командой SET NAMES в PDO::MYSQL_ATTR_INIT_COMMAND. Мануал: http://php.net/manual/ru/ref.pdo-mysql.connection.php
В файле ./lib/action.php:
Не используй короткий открывающий тег <? так как он может быть отключен в настройках. Используй либо длинный открывающий тег <?php для кода, либо короткий <?= для вывода значений в шаблонах.
В файле ./errors:
Файл с SQL дампом принято называть с расширением .sql, например students.sql
Кажется, ты не используешь строгий режим в MySQL. Зря. MySQL более тщательно проверяет твои запросы и вместо предупреждений (которые ты не увидишь) выдает ошибки при попытке вставить неправильные данные. Ну к примеру, если у тебя есть колонка типа varchar(200) и ты попытаешься вставить в нее строку из 300 символов, в нестрогом режиме MySQL молча отрежет лишнее (и в базе окажется обрезанная строка), а в строгом выдаст ошибку.
Использование строгого режима экономит твое время на исправление неправильно вставленных данных. Статья на хабре: http://habrahabr.ru/post/116922/
Включить строгий режим можно сделав при соединении с БД запрос SET sql_mode='STRICT_ALL_TABLES'. В PDO это удобно сделать опцией PDO::MYSQL_ATTR_INIT_COMMAND при создании объекта PDO.
В файле ./css/css/bootstrap.css:
Похоже, что ты правил файл .\css\css\bootstrap.css, который является частью библиотеки bootstrap-3.3.4. Не делай так. Ты думал, робот это не заметит?
Изменять файлы из стронних библиотек плохая идея по двум причинам. Во-первых, человек, разбирающийся в твоем коде, вряд ли сможет найти твои правки в куче кода. Он будет наивно думать что библиотека не изменена. Во-вторых, когда библиотеку захотят обновить, либо потеряются твои правки, либо эти правки придется переносить как-то вручную. Представь себе какой это объем труда. К тому же эти изменения могут еще и оказаться несовместимыми с новой версией библиотеки.
Никогда не меняй файлы внешних библиотек.
Или же ты просто используешь неофициальную или нестандартную сборку? Лучше использовать официальную.
Вот список изменений (в формате https://ru.wikipedia.org/wiki/Diff ):
> @@ -2916,7 +2916,7 @@
> .form-inline .input-group .input-group-addon,
> .form-inline .input-group .input-group-btn,
> .form-inline .input-group .form-control {
> - width: auto;
> + width: 100%;
> }
> .form-inline .input-group > .form-control {
> width: 100%;
В этой задаче минимум 2 поля, для которых стоит использовать тип ENUM — это пол и место жительства. У тебя ENUM исплоьзован всего 1 раз, что странно.
Похоже что ты не использовал тип YEAR для хранения года рождения, а ведь такой тип специально для этого придуман. Если ты про него не знал, то почитай про то какие типы есть в MySQL:
http://phpclub.ru/mysql/doc/column-types.html
(конец замечаний от робота)
Насчет внешних библиотек типа бутстрапа: ничего в них не меняй. Распакуй ее как есть в папку css или static (чтобы там была папка вроде bootstrap) и ничего не меняй и не переименовывай файлы.
Также, ты неправильно используешь ENUM тут:
https://github.com/Si0n/register2/blob/master/students.sql#L36
Прочитай про этот тип http://phpclub.ru/mysql/doc/enum.html
ENUM используется как ENUM('a', 'b') NOT NULL, то есть ты перечисляешь возможные варианты значений.
Еще странность:
> <form id="register" method="post" action="./../lib/action.php"
Тут ты указываешь путь к обработчику не относительно файла шаблона, а относительно URL где выводится форма. Если твоя форма выводится по адресу
http://localhost/some/form.php
то от него и отсчитывается путь.
Тут не нужна таблица. Проще для пользователя хранить в той же таблице код и ставить в куки ему этот код + user_id.
Если ты перезаписывешь хеш то получаешь проблему что другое устройство пользователя (например айпад) разлогинивается. Если не перезаписываешь то этот хеш будучи один раз похищенным, позволяет залогиниваться потом. Потому надо его менять например при смене пароля (можно даже хеш от пароля и использовать).
>>463395
Начинать с более простых задач. Но вот я тебе скопирую объяснение про MVC из одной нашей задачи:
Подход MVC заключается в том, что мы разбиваем приложение на 3 слабо связанных части: Модель (Model), Представление (View) и Контроллер (Controller).
Модель хранит и обрабатывает данные приложения, не взаимодействуя с внешним миром. Например, сохранение информации в БД, проверка правильности введенных данных — это задача Модели, но вывод информации — нет. Модель не должна обращаться к внешним переменным вроде $_GET/$_POST/$_SESSION/$_COOKIE и не должна ничего выводить. В этой задаче модель может состоять из классов, описывающих абитуриента и работающих с БД.
Представление отображает данные. Оно не должно обращаться к внешним переменным или к базе данных, его задача просто выводить те данные, которые ему передал контроллер. В этой задаче представление скорее всего будет содержать только шаблоны.
Контроллер отвечает за взаимодействие с внешним миром (пользователем) и управление всем процессом. Обычно контроллер разбирает параметры запроса из $_POST/$_GET, обращается к модели, чтобы получить какие-то данные или сделать какое-то действие, и в конце вызывает Представление, чтобы отобразить результат. Здесь контроллерами могут быть скрипты, которые отвечают за вывод списка и обработку формы редактирования/регистрации.
Если ты будешь искать в интернете информацию о MVC, учти что этот подход изначально придуман в 80-е годы для десктопных приложений (с окошечками и кнопочками), а не веб-приложений и «MVC для десктопа» чуть-чуть отличается от «MVC для веба», так как десктопные приложения в отличие от PHP-скрипта, не завершаются после вывода информации на экран, а продолжают работать. Но общие принципы те же.
Если следовать MVC, разделяя код на части, то он будет проще и надежнее.
Тут не нужна таблица. Проще для пользователя хранить в той же таблице код и ставить в куки ему этот код + user_id.
Если ты перезаписывешь хеш то получаешь проблему что другое устройство пользователя (например айпад) разлогинивается. Если не перезаписываешь то этот хеш будучи один раз похищенным, позволяет залогиниваться потом. Потому надо его менять например при смене пароля (можно даже хеш от пароля и использовать).
>>463395
Начинать с более простых задач. Но вот я тебе скопирую объяснение про MVC из одной нашей задачи:
Подход MVC заключается в том, что мы разбиваем приложение на 3 слабо связанных части: Модель (Model), Представление (View) и Контроллер (Controller).
Модель хранит и обрабатывает данные приложения, не взаимодействуя с внешним миром. Например, сохранение информации в БД, проверка правильности введенных данных — это задача Модели, но вывод информации — нет. Модель не должна обращаться к внешним переменным вроде $_GET/$_POST/$_SESSION/$_COOKIE и не должна ничего выводить. В этой задаче модель может состоять из классов, описывающих абитуриента и работающих с БД.
Представление отображает данные. Оно не должно обращаться к внешним переменным или к базе данных, его задача просто выводить те данные, которые ему передал контроллер. В этой задаче представление скорее всего будет содержать только шаблоны.
Контроллер отвечает за взаимодействие с внешним миром (пользователем) и управление всем процессом. Обычно контроллер разбирает параметры запроса из $_POST/$_GET, обращается к модели, чтобы получить какие-то данные или сделать какое-то действие, и в конце вызывает Представление, чтобы отобразить результат. Здесь контроллерами могут быть скрипты, которые отвечают за вывод списка и обработку формы редактирования/регистрации.
Если ты будешь искать в интернете информацию о MVC, учти что этот подход изначально придуман в 80-е годы для десктопных приложений (с окошечками и кнопочками), а не веб-приложений и «MVC для десктопа» чуть-чуть отличается от «MVC для веба», так как десктопные приложения в отличие от PHP-скрипта, не завершаются после вывода информации на экран, а продолжают работать. Но общие принципы те же.
Если следовать MVC, разделяя код на части, то он будет проще и надежнее.
Встроенных видимо нет
>>463507
Нельзя использовать плейсходдеры для вставки имен полей. Только значения.
Выход такой: вставлять $order напрямую, перед этим поставив проверку по белому списку, которая позволяет например вставить только указанные в массиве тут же значения. Если нет то заменяем на стандартное значение или выбрасываем исключение.
Проверка должна быть тут же, чтобы тот кто читает код видел что уязвимости тут нет.
p.s. Вместо SET NAMES лучше дописать ;charset=utf8 в DSN при создании PDO.
>>463583
strtoupper работает только с латинницей. Подробнее: https://gist.github.com/codedokode/ff99e357e9860ea169b8
>>463661
> setlocale(LC_ALL, "russian");
Локаль это фактически имя (точнее часть имени) файла где-то в системе. Если у тебя не установлена эта локаль то она работать не будет. Также, локали имеют разные имена на Linux и Windows, на linux это что-то вроде ru_RU.utf-8 или как-то так.
У локалей есть и другие проблемы, например нельзя поставить разные локали в разных потоках (а под WIndows php внутри апача многопоточный).
Я советую их не использовать и написать/найти код для вывода нужных названий самому. Это быстрее чем отлаживать причину ошибки если где-то код не заработает.
> А если я эти же скрипты вызываю через свое веб приложение (т.е. вывод будет не на консоли, а на веб страницы), то страница грузится где-то полминуты и потом работа скрипта обрывается на половине примерно:
В веб-сервере и в php предусмотрены таймауты. Веб-сервер не для запуска длинных скриптов (и это все равно неудобно, например ты не можешь видеть прогресс и сообщение по ходу выполнения).
> Можно как-нибудь эту проблему решить, чтобы страница грузилась сколько нужно, а не с таймаутом?
Можно (в конфиге Апача есть что-то, а в опциях php есть max_execution_time) но я не советую, так как это может привести к каким-то проблемам, эти опции сделаны как защита от потребления ресурсов сошедшими с ума скриптами. Я советую либо использовать консоль либо сделать нормальную админку для запуска которая будет запускать и отслеживать скрипты через систему фоновых задач вроде Gearman.
Если погуглить по Geaarman monitor то можно найти готовые админки, вроде http://gaspaio.github.io/gearmanui/
В общем, советую тебе сделать нормально.
О, этот палиндром я еще не видел.
> $textUpper
> $textWithoutSpace
Так как эти переменные хранят то же что и text и так как text нам больше не нужна, то лучше результат назад в нее и класть. А то ты как хаскеллист, они тоже каждый раз новую переменную создают (потому что в хаскелле у переменных нельзя менять значения).
Цикл можно сделать проще. Во-первых, нам достаточно пройти половину (округлять можно в любую сторону) символов строки. Во-вторых вместо того чтобы считать число совпадений и делать странные увеличения/уменьшения на 1, можно при первом несовпадении помечать что строка не палиндром и выходить из цикла.
Также, вот тут
> for ($i = 0; $i <= $saveLenght; $i ++) {
Лучше заменить <= на < , а не уменьшать длину на 1, так как я на минуту задумался, а почему длина уменьшается на 1. Это неочевидно, и комментария с объяснением тоже не было. ну то есть каждое действие должно иметь какую-то причину, и почему длина уменьшается на 1 догадаться непросто.
Что касается этой строки
> mb_substr($textWithoutSpace, $lengthStr, 1);
можно вместо ведения отдельного счетчика просто вычислять позицию через $i (-1 дает нам последний символ, -2 предпоследний и т д)
>>463726
> $creditBalanceAnon -=
> $paymentTotal +=
Это повторяется 2 раза. Попробуй сделать чтобы не повторялось. Например можно внутри if задавать переменную определяющую размер выплаты в этом месяце а все остальное вынести наружу.
О, этот палиндром я еще не видел.
> $textUpper
> $textWithoutSpace
Так как эти переменные хранят то же что и text и так как text нам больше не нужна, то лучше результат назад в нее и класть. А то ты как хаскеллист, они тоже каждый раз новую переменную создают (потому что в хаскелле у переменных нельзя менять значения).
Цикл можно сделать проще. Во-первых, нам достаточно пройти половину (округлять можно в любую сторону) символов строки. Во-вторых вместо того чтобы считать число совпадений и делать странные увеличения/уменьшения на 1, можно при первом несовпадении помечать что строка не палиндром и выходить из цикла.
Также, вот тут
> for ($i = 0; $i <= $saveLenght; $i ++) {
Лучше заменить <= на < , а не уменьшать длину на 1, так как я на минуту задумался, а почему длина уменьшается на 1. Это неочевидно, и комментария с объяснением тоже не было. ну то есть каждое действие должно иметь какую-то причину, и почему длина уменьшается на 1 догадаться непросто.
Что касается этой строки
> mb_substr($textWithoutSpace, $lengthStr, 1);
можно вместо ведения отдельного счетчика просто вычислять позицию через $i (-1 дает нам последний символ, -2 предпоследний и т д)
>>463726
> $creditBalanceAnon -=
> $paymentTotal +=
Это повторяется 2 раза. Попробуй сделать чтобы не повторялось. Например можно внутри if задавать переменную определяющую размер выплаты в этом месяце а все остальное вынести наружу.
> Теперь же надо их еще и добавлять. Метод вроде
function insertNewUser($user_attributes) {
Ты мыслишь массиво-ориентированным программированием. В DataMapper это делается так:
$user = new User( );
$iser->setName('Ivan'); // или $user->name = 'Ivan'
$mapper->save($user);// сохраняет юзера и проставляет $user->id
Вот мой урок про мапперы где есть такой код: https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md#datamapper
Вот пример из доктрины: http://odiszapc.ru/doctrine/working-with-objects/#83
Заметь что есть и другие паттерны, когда сохранение делается по другому.
> что должен принимать - массив или объект User?
Объект
> Причем создаваться он будет вне маппера и что самое нелепое - из массива
Почему? Это уже как программист захочет, так и создаст.
Объект лучше массива так как очевидно какие у него поля, а с массивами ты быстро начнешь путаться.
Также, при сохранении тебе может понадобиться сделать преобразования вроде объект DateTime -> строка с датой или true -> 1. Это как раз задача маппера.
>>463770
Запости код, напиши что именно неясно, дадим подсказку.
Да я потому и спросил что руки чешутся сделать на массиве, а из урока да и здесь ты настаиваешь на объекте.
Первое что смущает:
$user->setName('Ivan');
$user->setLastname('Petrov');
$user->setEmail('sdf@dg.fg');
И еще 5-6 строк вместо $values = ['ivan', 'petrov','dfg@dfg.gh',...]; Ну это ладно, допустим можно сделать setAll().
Но вот второе.. Внутри маппера его методы обращаются к методу pdo->query() который у меня реализован как на пике.
То есть мне придется либо переданный в метод маппера User преобразовывать в массив(а че б тогда сразу не передавать массив - спрашивает любитель массивов внутри меня), либо как-то перепиливать query() под прием параметров объектом что делает меня грустить ибо он очень послушно работает.
Объекты однозначно лучше. У нас есть объект User представляющий пользователя. Почему все остальные функции работают с объектом, а функция вставки в БД с массивом? Неудобно же, если у меня уже есть объект на руках, мне его придется даунгрейдить до массива (и гадать какие поля нужно передать, а какие не обязательно).
> И еще 5-6 строк вместо $values = ['ivan', 'petrov','dfg@dfg.gh',...];
на практике у тебя мало где будет ручная простановка значений. А теперь посмотри на свой «оптимизированный» код:
['ivan', 'petrov','dfg@dfg.gh', 15, 0, 0, 0, 1, 'asdasdasda', '12456543', '234543'];
Все понятно?
Если у тебя программа на 90% состоит из setName может это и повод оптимизировать тут код, но на практике это не так. И помни что код пишется в первую очередь для людей, которые его будут читать.
> Внутри маппера его методы обращаются к методу pdo->query() который у меня реализован как на пике.
Это уже твои проблемы что ты выбрал такой подход
> (а че б тогда сразу не передавать массив - спрашивает любитель массивов внутри меня)
А то что объект лучше массива. У него известен и документирован набор полей, и есть методы. Ну например для того чтобы поставить дату обновления на текущее время мы можем вызвать
$user->updateTime( );
Более того, мы можем запретить ставить имя длиннее 100 символов в setName:
if (mb_strlen($name) > 100) {
throw new Exception(...);
}
Мы можем сделать метод для получения инициалов:
echo $user->getInitials( );
А с массивом? В общем, массивы источник бардака и запутанного кода. Особенно когда проект растет и массивы начинают передаваться между функциями, расползаться по всему приложению и очень трудно понять где какой массив.
В общем, преимущества и удобство использования объектов однозначно перевешивают массивы. Вот в друпале сделали все на массивах и там в функциях передаются массивы у которых по 30 полей (а иногда еще и многомерные), и фиг разберешься где какие поля.
> либо как-то перепиливать query() под прием параметров объектом что делает меня грустить ибо он очень послушно работает.
Сделай метод извлекающий свойства из объекта в массив. Нашел из-за чего грустить. То, что ты предлагаешь, хуже: у тебя часть функций будет работать с объектами, часть с массивами непонятной и нигде не документированной структуры.
Ну и на практике, если ты не пишешь свою систему мапперов, а используешь например Doctrine 2, то тебе не придется этот код вообще писать. Там ты просто описываешь какое поле объекта какой колонке соответствует, а доктрина предоставляет свой готовый маппер для работы с БД. То есть в реальных приложениях тебе код маппинга вручную писать не придется.
Объекты однозначно лучше. У нас есть объект User представляющий пользователя. Почему все остальные функции работают с объектом, а функция вставки в БД с массивом? Неудобно же, если у меня уже есть объект на руках, мне его придется даунгрейдить до массива (и гадать какие поля нужно передать, а какие не обязательно).
> И еще 5-6 строк вместо $values = ['ivan', 'petrov','dfg@dfg.gh',...];
на практике у тебя мало где будет ручная простановка значений. А теперь посмотри на свой «оптимизированный» код:
['ivan', 'petrov','dfg@dfg.gh', 15, 0, 0, 0, 1, 'asdasdasda', '12456543', '234543'];
Все понятно?
Если у тебя программа на 90% состоит из setName может это и повод оптимизировать тут код, но на практике это не так. И помни что код пишется в первую очередь для людей, которые его будут читать.
> Внутри маппера его методы обращаются к методу pdo->query() который у меня реализован как на пике.
Это уже твои проблемы что ты выбрал такой подход
> (а че б тогда сразу не передавать массив - спрашивает любитель массивов внутри меня)
А то что объект лучше массива. У него известен и документирован набор полей, и есть методы. Ну например для того чтобы поставить дату обновления на текущее время мы можем вызвать
$user->updateTime( );
Более того, мы можем запретить ставить имя длиннее 100 символов в setName:
if (mb_strlen($name) > 100) {
throw new Exception(...);
}
Мы можем сделать метод для получения инициалов:
echo $user->getInitials( );
А с массивом? В общем, массивы источник бардака и запутанного кода. Особенно когда проект растет и массивы начинают передаваться между функциями, расползаться по всему приложению и очень трудно понять где какой массив.
В общем, преимущества и удобство использования объектов однозначно перевешивают массивы. Вот в друпале сделали все на массивах и там в функциях передаются массивы у которых по 30 полей (а иногда еще и многомерные), и фиг разберешься где какие поля.
> либо как-то перепиливать query() под прием параметров объектом что делает меня грустить ибо он очень послушно работает.
Сделай метод извлекающий свойства из объекта в массив. Нашел из-за чего грустить. То, что ты предлагаешь, хуже: у тебя часть функций будет работать с объектами, часть с массивами непонятной и нигде не документированной структуры.
Ну и на практике, если ты не пишешь свою систему мапперов, а используешь например Doctrine 2, то тебе не придется этот код вообще писать. Там ты просто описываешь какое поле объекта какой колонке соответствует, а доктрина предоставляет свой готовый маппер для работы с БД. То есть в реальных приложениях тебе код маппинга вручную писать не придется.
Кстати почему query у тебя public? Это же внутренний метод только для использования мапперами?
И еще. Почему ты пишешь _pdo? так делали во времена php4 из-за отстутвия private/public. Стандарты прямо говорят не использовать подчеркивание как замену private: http://www.php-fig.org/psr/psr-2/ru/
> НЕ СЛЕДУЕТ начинать название свойства с подчёркивания для обозначения приватной или защищённой видимости.
В общем, попробуй понять что концепция когда один объект сохраняет в базу другой красивее и удобнее чем когда передаются непонятные массивы непонятной структуры.
> и там человечек учит прогонять пришедшие от пользователя данные через trim и strip_tags.
trim это хорошая идея, так как пробелы с краев невидимы, а компьютер их считает различием. Пользователь ввел в поле логина
username_
вместо
username
И компьютер пишет: логин не правльный, а на глаз понять в чем ошибка, нельзя. trim это хорошая идея для данных введенных вручную.
А вот strip_tags плохая. Это напоминает суеверие: на практике не всегда работает и не всегда работает правильно, но на душе спокойнее становится.
Ну и я могу придумать примеры где strip_tags не защитит от XSS, например при вставке значения в атрибут input:
<input value="<?= $value ?>">
даже если value обработать strip_tags можно вырваться за предылы атрибута и вставить яваскрипт. Этот пример есть в моем уроке по XSS.
> Так вот, насколько разумно будет использовать функцию которая прогоняет через все три пришедшее от пользователя?
Ты должен понимать как работает каждая из уязвимостей и как работает защита от нее. Если ты бездумно ставишь функции в надежде «очистить» (лол, очистить! это почти как освятить) данные, то это неправильный путь. Ты с таким же успехом можешь компьютер святой водой побрызгать.
> Интересно мнение реального разработчика.
Изучить как все это работает. Если проект новый то писать сразу нормально, если старый с кучей быдоокода то смотреть по обстоятельствам.
> и там человечек учит прогонять пришедшие от пользователя данные через trim и strip_tags.
trim это хорошая идея, так как пробелы с краев невидимы, а компьютер их считает различием. Пользователь ввел в поле логина
username_
вместо
username
И компьютер пишет: логин не правльный, а на глаз понять в чем ошибка, нельзя. trim это хорошая идея для данных введенных вручную.
А вот strip_tags плохая. Это напоминает суеверие: на практике не всегда работает и не всегда работает правильно, но на душе спокойнее становится.
Ну и я могу придумать примеры где strip_tags не защитит от XSS, например при вставке значения в атрибут input:
<input value="<?= $value ?>">
даже если value обработать strip_tags можно вырваться за предылы атрибута и вставить яваскрипт. Этот пример есть в моем уроке по XSS.
> Так вот, насколько разумно будет использовать функцию которая прогоняет через все три пришедшее от пользователя?
Ты должен понимать как работает каждая из уязвимостей и как работает защита от нее. Если ты бездумно ставишь функции в надежде «очистить» (лол, очистить! это почти как освятить) данные, то это неправильный путь. Ты с таким же успехом можешь компьютер святой водой побрызгать.
> Интересно мнение реального разработчика.
Изучить как все это работает. Если проект новый то писать сразу нормально, если старый с кучей быдоокода то смотреть по обстоятельствам.
Ну и если это уроки, то они должны объяснять что именно делает каждая функция и для чего она. А не учить в стиле «поставьте эти функции в начале для того чтобы очистить данные».
Если обрабатывать все через strip_tags то как минимум знаки больше/меньше в тексте сообщения сломаются, например:
Если a<b то уравнение имеет 2 решения.
Вот что выводится: http://ideone.com/faJjl9
> Если a
В противоположность этому, в моем уроке по XSS ( https://github.com/codedokode/pasta/blob/master/security/xss.md ) объясняется (надеюсь что понятно) суть уязвимости и меры борьбы.
Аналогично с XSRF: https://github.com/codedokode/pasta/blob/master/security/xsrf.md
Благодарю за объяснение. Собственно поэтому и написал, что бы разобраться. Почитаю
>Почему все остальные функции работают с объектом, а функция вставки в БД с массивом? Неудобно же, если у меня уже есть объект на руках, мне его придется даунгрейдить до массива
У меня же тут вроде как обратная ситуация, объекта еще нет, есть массив $_POST с данными формы, ну или уже проверенный валидатором, казалось бы передай мапперу и забудь. Но да, нелогично, ведь остальные работают с объектом. А тут нужно сперва апгрейдить до объекта, а внутри обратно даунгрейдить до массива.
В общем, ты меня убедил насчет объектов, а что все же посоветуешь переделать query или добавить метод objectToArray?
>>463820
Ну я думал это чтоб с первого взгляда было понятно что переменная приватная, а не листать вверх класса. Само собой, я объявлял через private, но и подчеркивание дополнительно ставил.
Cтроку еще и как массив можно использовать, например
$string = 'abcd';
echo $string[2]
выведет 'с', тру стори я не тролль.
Ну это я всегда знал, а вот то, что можно написать, например, $variable = "var_dump" и передать потом любой аргумент в $variable и это будет работать я узнал только сейчас.
> У меня же тут вроде как обратная ситуация, объекта еще нет, есть массив $_POST с данными формы,
Ты очень узко мыслишь. Ты думаешь, что маппер нужен только для сохранения данных из POST-формы. С чего бы? маппер позволяет сохранить любой объект пользователя в базу, неважно откуда он взялся. Может из формы, а может это ты решил ботов нагенерировать программно.
Ну и главная идея, что когда ты пишешь универсальные функции, код становится проще для понимания. Функция которая сохраняет любой объект класса User в базу проще и надежнее чем функция которая предполагает что данные пришли из POST формы и использует это как-то.
> А тут нужно сперва апгрейдить до объекта, а внутри обратно даунгрейдить до массива.
Это пока, а позже тебе понадобится например проверка введеных данных. Что мы будем передавать в функцию проверки — массив или объект? А потом понадобится добавить или переименовать колонку. А потом еще что-нибудь.
> а что все же посоветуешь переделать query или добавить метод objectToArray?
mapUserToArray
> Ну я думал это чтоб с первого взгляда было понятно что переменная приватная, а не листать вверх класса
Если ты внутри объекта то тебе неважно приватная или нет. Если ты знакомишься с чужим классом то посмотришь заголовок класса и увидишь что приватное а что нет. Ну и часто принято публичных полей вообще не делать, а весь доступ через методы.
>>463835
Не как функцию, а как указатель на функцию. Там есть больше способов: http://php.net/manual/ru/language.types.callable.php
Это плохая идея так как [2] берет 2-й байт, а не вторую букву и в случае с кириллицей вернет мусор. Потому не надо так никогда делать.
https://github.com/krbn/students
А я пока вечером прикручу джаваскрипты и поле поиска на аяксе.
> то при первом запуске при отключенном xdebug и уровне ошибок для продакшн все будет работать как надо.
А ты в логи смотрел (под виндой они в папке Апача)? То что ошибки не выводятся не значит что их нет.
Разумеется правильно работающая программа не издает ни единого предупреждения.
Я вообще советую тебе поставить в начало кода такую конструкцию:
set_error_handler(function ($errno, $errstr, $errfile, $errline) {
if (!error_reporting()) {
// Allow silencing
return;
}
throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
});
Она превращает любую мельчайшую ошибку в исключение и помогает не остаться ошибкам незамеченными.
Но как лучше в моем случае поступать? Инициализировать пустые переменные? isset и if(что мне кажется весьма громоздким)?
Для тех кто совсем не знает с чего начать, подсказка: Заметь, что Бернард знает день и некоторых дней достаточно для того, чтобы угадать месяц, а некоторых нет. Фраза «но я знаю, что Бернард тоже не знает» подсказывает нам о том, какой день (и соовтетственно месяц) может быть и какой не может. Во второй фразе Бернард, используя эту информацию о месяце от Альберта, определяет ответ
сделать так чтобы переменные всегда существовали. Что это за программа в которой переменная может быть, а может и не быть?
А как избежать ошибки undefined index при работе с $_GET или $_POST массивами? Ведь например как получается - юзер впервые открывает страницу, и нужным нам ключей нет. Они появятся только после отправки(например ситуации когда надо сохранить введенные в поля данные, если юзер заполнил какое то неверно). Это и не совсем переменная, а индекс.
Вот есть у меня класс с полями. Я хочу их заполнить. Юзаю форму. Делаю инклуд класса и в параметре action формы пишу не ебаную страницу, а например вызываю функцию этого класса fill, куда передаются эти параметры.
Есть какие нибудь шаблоны для этого дела?
Или с js. Хочу проверить правильно ли заполнена форма, и заполнена ли она. После нажатия сабмита формы, как запустить сначала скрипт проверки, а потом уже перейти на другую страницу и передать параметры? В action же не вписать и скрипт и страницу.
>mapUserToArray
Ох и неслабый тут подводный камень. Сделал. Не работает. Битый час ищу ошибку, функция вроде нормально отрабатывает, возвращает массив. Делаю вардамп. Так как уже перед глазами плывут эти юзеры, имейлы и айди сперва не понимаю в чем дело, вроде как все на месте. Потом замечаю что в ключи скопировались имена свойств объекта со странным префиксом перед именем, вместо firstname там стоит Userfirstname. Перечитываю каждую строчку кода. Что за чудеса, откуда там берется это 'User...'? Гугол: convert object to array, везде такие же решения как у меня с перебором свойств и присвоением ключам. Танцы с бубном, смотрю, а свойства-то приватные. Гугол: да так и есть
>к закрытым полям класса (private) спереди будет дописано имя класса; к защищенным полям класса (protected) спереди будет добавлен символ '*'. Эти добавленные значения с обоих сторон также имеют нулевые байты. Это может вызвать несколько неожиданное поведение:
Они назвали это НЕСКОЛЬКО НЕОЖИДАННЫМ ПОВЕДЕНИЕМ, Карл
Есть урок по работе с формами, читал? https://github.com/codedokode/pasta/blob/master/forms.md
Ну и также ты можешь посмотреть как это реализовано в фреймворках, например, Yii 2.
> После нажатия сабмита формы, как запустить сначала скрипт проверки, а потом уже перейти на другую страницу и передать параметры?
На самом деле можно, если ты обрабатываешь событие onsubmit то твой скрипт может его отменить и предотвратить отправку формы:
http://javascript.ru/tutorial/events/intro#deystvie-brauzera-po-umolchaniyu
https://learn.javascript.ru/default-browser-action
Я думаю тебе надо сначала полностью разобраться с обработкой форм без яваскрипта.
> Они назвали это НЕСКОЛЬКО НЕОЖИДАННЫМ ПОВЕДЕНИЕМ, Карл
Ты вообще не можешь получить доступ к приватным свойствам и тем более не должен пытаться преобразовать объект в массив (так как у него могут быть свойства которые не надо сохранять в БД). Не надо изобретать странные способы, если у тебя есть геттеры, то получай через них, либо руками
$result['name'] = $user->getName( );
либо прописав массив соответствий:
$mapping = [
'name' => 'getName',
....
];
> I'm currently porting a rails app to Laravel and the speed boost has been pretty remarkable, not to mention not ever having to install gems whose only purpose is to reboot unicorn when the memory leaks hit a certain threshold.
Я сейчас переношу приложение с руби он рельс на Lavarel и прирост в скорости весьма впечатляет, не говоря о том что мне больше не требуются плагины, перезагружающие сервер при утечке памяти выше определенного порога.
Так-то!
Апач из оп поста багнутый. категорически отказывается стартовать на винде. Дали-бы хоть сслку нормальную.
Анон, то просто офигенен! Ты лучше всех! Спасибо тебе няша за ссыль, танкер добра тебе няша!
> Попробуй сделать чтобы не повторялось.
https://ideone.com/AO639d
> Так как эти переменные хранят то же что и text и так как text нам больше не нужна, то лучше результат назад в нее и класть.
Так IDE бугуртит, говорит, что я должен использовать только одно назначение переменной You should use only 1 assignment(s) (3 used), аргументируя это тем, что to avoid accidentally overwriting it and make your code easier to read. Но компилирует.
Переделал https://ideone.com/2P445g
В качестве службы виндоус установил? Запустил?
Уже так и сделал, но сперва показалось что переприсвоить все поля в ключ=>значение будет изящнее чем руками, т. к. лишних свойств не было.
Вот я рак, увидел только первый коммент:
>Точки с запятой не хватает (ты вроде это уже заметил сам)
А второй просмотрел и сижу жду не знаю чего, уже думал что ты не увидел мой запрос.
В общем первую задачу вроде бы сделал с некоторым непониманием 2 пункта в плане реализации, и 3 пункта, в плане того, что от меня там вообще требуется. Ведь я просто мог вывести все страны из первого пункта и был бы верный ответ.
http://ideone.com/qCI36p
Вскоре приступаю и ко второй задаче.
А еще я наконец-то нашел работку, в небольшой студии на 4 часовой рабочий день за 10к.
Если кто помнит, то я зимой писал что нашел работу ничего не зная.
Сказали ознакомиться с Бутстрапом и Кодигнайтером. Как понимаю буду ковырять какой-то бэкэнд в основном. Кто-нибудь может подсказать за этот фреймворк? Вроде бы не устаревший, а еще используется и разрабатывается.
Кодеигнитайер это все же не новый фреймворк, он из эпохи PHP4 и php5.2, и по моему компания-разработчик в итоге его забросила. Но он простой, думаю, ты быстро с ним разберешься.
А, и еще по моему, на современном PHP он сыплет предупреждениями и там не применяется подход fail fast ( http://habrahabr.ru/post/218325/ ) — при ошибке или предупрежеднии выполнение программы не останавливается. Это плохо так как из-за этого ошибки никто не исправляет.
В фигурных скобках, например:
$sql = "INSERT INTO tbl_name (name, email) VALUES ({$_POST['name']}, {$_POST['email']})";
Если серьезно, то нельзя подставлять в sql данные от пользователя. Как минимум их необходимо обработать какой-нибудь mysql_real_escape_string, а еще лучше использовать подготовленные запросы.
https://ru.wikipedia.org/wiki/CodeIgniter
Говорят что 3.0 вышла как раз месяц назад. Так что вроде бы не сильное старье. Обидно конечно если придется на работе изучать устаревшую технологию, которая нужна только для поддержки старых проектов, но что поделать, я и так уже 8 месяцев фигней всякой страдаю, вместо работы, проебал годную тян из-за этого уже. В общем выебываться я не буду в любом случае, буду работать и изучать что от меня затребуют, а после испытательного будет видно. Как минимум на примере этого фреймворка можно освоить MVC и вообще работу с фреймворками на php, так что это уже профит в виде опыта и нескольких строчек в резюме.
Ну ты и дерзкий уебан конечно, но вообще у тебя
$_POST['sectionParent'] и одинарные кавычки ломают этот самый запрос. Так как mysql принимает как запросы уровня SELECT 'id' FROM 'users' WHERE login='bydlo'
так и SELECT id FROM users WHERE login=bydlo
Сечешь? попробуй через склеивание строчки сделать:
query = "SELECT id FROM users WHERE login=" . $_POST['sectionParent'];
Будто кроме хохлов им кто-то пользуется.
да я хз, везде в крутых конторах требуют yii или симфони, так что в свободное от работы время наверное буду их ковырять.
С таким отношением мало найдется желающих подсказывать
>>464165
Это SQL инъекция. Нельзя так писать и тем боле нельзя давать такие примеры начинающим, надо давать пример с плейсхолдерами в PDO/mysqli.
Вот он:
$stmt = $pdo->prepare("INSERT INTO t(a, b) VALUES(:a, :b)");
$stmt->execute(array(
'a' => $a,
'b' => $b
));
Мануал: http://habrahabr.ru/post/137664/
Ну и не стоит смешивать код работы с формами и код работы с БД, лучше разнести это по разным объектиам/функциям
Не надо давать в качестве примеров код с SQL инъекцией. Давай примеры с исопльзованием плейсхолдеров. Если человек учился по неправильным учебникам, надо его переучивать.
Как в джаваскрипте можно подставлять имена свойств и методов?
Вот в php есть возможность сделать так:
function foo(){}
$method = 'foo';
$method();
В js это не работает https://gist.github.com/anonymous/8881007d13c557bffd3b
>>463872
ОП, жду советов по оптимизации этого творения.
В целом я все делал по аналогии с yii, но наверняка наделал косяков.
this.x равносильно this['x']
В яваскрипте точка и квадратные скобки делают одно и то же (берут поле объекта). Дальше думаю ты и сам сообразишь.
Но я от себя добавлю несколько вещей. Во-первых, пары ключ-значение удобнее передавать через словарь:
{
name: 'Ivan',
surname: 'Ivanov'
}
(кстати если ты это еще не знаешь, запомни что словари несортированы и не сохраняют порядок ключей, в отличие от php массивов)
Во-вторых, зачем ты городишь все это массиво ориентированное программирование? ЧТо мешает написать так:
var user = new User( );
user.name = 'Ivan';
user.surname = 'Ivanov';
По читабельности это гораздо лучше чем твой странный вариант с кучей скобок.
Справедливости ради, в некоторых библиотеках в конструктор можно передавать словарь значений (backbone может быть? не помню).
А, и еще, у нас есть задания на JS если тебе интересно, в ОП посте.
> ОП, жду советов по оптимизации этого творения.
Да, я постараюсь сегодня проверить
this.x равносильно this['x']
В яваскрипте точка и квадратные скобки делают одно и то же (берут поле объекта). Дальше думаю ты и сам сообразишь.
Но я от себя добавлю несколько вещей. Во-первых, пары ключ-значение удобнее передавать через словарь:
{
name: 'Ivan',
surname: 'Ivanov'
}
(кстати если ты это еще не знаешь, запомни что словари несортированы и не сохраняют порядок ключей, в отличие от php массивов)
Во-вторых, зачем ты городишь все это массиво ориентированное программирование? ЧТо мешает написать так:
var user = new User( );
user.name = 'Ivan';
user.surname = 'Ivanov';
По читабельности это гораздо лучше чем твой странный вариант с кучей скобок.
Справедливости ради, в некоторых библиотеках в конструктор можно передавать словарь значений (backbone может быть? не помню).
А, и еще, у нас есть задания на JS если тебе интересно, в ОП посте.
> ОП, жду советов по оптимизации этого творения.
Да, я постараюсь сегодня проверить
Пардон, затупил.
В js к свойству объекта можно обратиться не только через точку, но и через квадратные скобки, например this['name'].
Так работает: https://gist.github.com/anonymous/61f2b595ff787f69cf15
ОП, подкинь пожалуйста ссылок, где доходчиво объясняется типизация в js. Что такое html-коллекция? Это массив или объект?
Является ли функция объектом? Является ли анонимная функция каким-то особенным объектом, как замыкания в пхп?
Я так понял, что даже простые типы данных вроде строки или числа тоже объекты. Может, есть какое-то дерево объектов, как в случае с DOM?
Пока слабое понимание всех этих моментов.
>>464323
О, ты уже тут, пока я писал.
В этом примерчике суть в том, что мы не знаем, как будут называться свойства объекта.
На самом деле это у меня поля формы. А какие будут поля (и сколько), неизвестно.
Мы не знаем, что человек передаст при создании объекта.
Поэтому пытаюсь написать класс, который будет принимать массив полей с их названиями и значениями, чтобы конструктор в цикле их разложил по полочкам.
>зачем ты городишь все это массиво ориентированное программирование?
Хочу реализовать в js сложный класс валидатора, как в пхп.
https://github.com/krbn/students/blob/master/protected/classes/Validator.php
Если я буду писать отдельную функцию для каждого правила валидации, то в глобальной области будут валяться десятки непонятных функций. А так они буду связаны классом.
Даже если так никто не делает, хочется попробовать написать такой класс just for lulz, для повышения сноровки.
Как вообще в js обстоит дело с ООП? Пишут классы, или скидывают все функции в кучу-библиотеку?
Я не могу решить вторую задачу. Я просто не могу врубиться в принцип работы preg_replace_callback.
Перечитал мануал по ней 2 раза и все равно не догоняю пока. Очень тупой.
Сделал для начала вот так, как будто из урока на регулярки: http://ideone.com/gzeegM
Вообще, то, что ты знаком с Юи и пытался сделать что-то похожее, это хорошо. Я вижу что ты например понимаешь что такое шаблоны или что такое контроллер. Но кое-какие замечания к твоему коду все равно есть.
Если что-то непонятно или ты не согласен, напиши.
По базе данных:
Таблицу лучше назвать students, так как list не говорит нам что в ней хранится.
Похоже что ты не использовал тип YEAR для хранения года рождения, а ведь такой тип специально для этого придуман. Если ты про него не знал, то почитай про то какие типы есть в MySQL:
http://phpclub.ru/mysql/doc/column-types.html
> CREATE DATABASE students CHARACTER SET utf8 COLLATE utf8_general_ci;
Не надо это добавлять в файл, так как у меня например уже есть готовая база данных, и у нее может быть другое имя. Достаточно CREATE TABLE
> `mark` TINYINT UNSIGNED
Tinyint у нас вроде от 0 до 255, этого хватит?
> `gender` ENUM
> `residence` ENUM
NOT NULL почему не указал? Это же обязательные поля вроде.
> function __autoload($class){
> require_once 'protected/classes/'.$class.'.php';
Когда ты пишешь автолоадер, надо проверять есть ли такой файл и только если есть то подключать его. Иначе когда ты подключишь стороннюю библиотеку и она попытается подключить свой класс, твой автолоадер выдаст ошибку о несуществующем файле.
> class Application
Это правильнее наверно было бы назвать FrontController, так как твой класс реализует этот паттерн ( http://design-pattern.ru/patterns/front-controller.html ). Ну и название «Application» как бы намекает что это универсальный класс, который подойдет к любому приложению. Но ведь это не так. Твой класс заточен под список студентов. Раз так, то и называй его StudentListApplication или StudentListFrontController чтобы из названия все было ясно.
> public function init()
> public function run()
не вижу почему нам надо вызывать 2 функции. не проще ли сделать одну функцию, run, а init вызывать из нее?
Также, init я бы переименовал в route() так как она занимается роутингом — определяет какой контроллер/действие вызвать.
Также, я бы упростил if чтобы уменьшить глубину вложенности. Например можно убрать else во всех if.
> class DataBase
Название ни о чем не говорит, я бы его поменял (например на DbConnectionCreator), более того, я бы вообще этот класс удалил так как он ничего полезного не делает. Вместо испльзования синглтона (который в общем плохой паттерн) я бы лучше например сделал в Application метод getDb()
> }catch(Exception $e){
> header('Content-type:text/html;charset=utf8');
Это плохая идея, так обрабатывать исключения. Почему ты обрабатываешь исключение только от соединения с базой, а в других случаях нет? Если ты хочешь реализовать красивую страницу заглушку, то лучше установить универсальный обработчик исключений с помощью set_exception_handler или обернув Application#run в try/catch.
Вот мой урок про исключения: https://gist.github.com/codedokode/65d43ca5ac95c762bc1a
Также, ты не записываешь подробности ощибки в лог. У тебя сайт полдня лежал, а ты об этом даже не узнаешь. Это по твоему нормально? Если бы ты не перехватывал исключение, все бы записалось. Но если ты его перехватываешь то фиксируй ошибку функцией error_log.
Также, зачем ты показываешь пользователю код ошибки? Это ему ничего не говорит.
Также, ты должен при ошибке выдавать HTTP-код 5xx. Например поисковый робот увидев этот код не станет индексировать страницу. Прочти про коды HTTP и выучи наизучть хотя бы эти коды: 200, 301, 401, 403, 404, 500, 503: https://ru.wikipedia.org/wiki/%D0%A1%D0%BF%D0%B8%D1%81%D0%BE%D0%BA_%D0%BA%D0%BE%D0%B4%D0%BE%D0%B2_%D1%81%D0%BE%D1%81%D1%82%D0%BE%D1%8F%D0%BD%D0%B8%D1%8F_HTTP
Ну и в будущем всегда выставляй правильный HTTP-код (200 можно не выставлять, так как PHP по умолчанию все страницы с этим кодом отдает).
> $db_config = parse_ini_file('protected/config.ini');
Ты используешь относительный путь который зависит от текущего каталога. При запуске из командной строки например этот файл может не найтись. Я бы явно прописал абсолютный путь через _ _ DIR _ _ .
> protected/classes/Pager.php
Это что-то непонятное и требует исправления.
> "SELECT COUNT(×) as rowCount FROM (SELECT `id`,`name`,`surname`,`group`,`mark` FROM list) AS tmp"
Это абсолютно неэффективно, выбирать все записи только чтобы посчитать количество. Почему ты не напишешь сразу SELECT COUNT(..) FROM list?
Если ты слабо знаешь SQL, я советую порешать задания на SQL из первого поста. Хорошее знание баз данных поможет тебе выбрать изначально правильную структуру БД и сэкономить время на исправлениях проблем из-за выбора неправильной.
Также, вся работа с базой должна быть в мапперах, а не размазана по коду.
> if(isset($_GET['page'])
Лучше делать независимый от внешнего окружения класс где номер страницы передается параметром, а не привзяан к конкретной GET переменной. Это сделает код универсальнее и аккуратнее. И в базу данных тоже лучше не лезть. А ты вместо того чтобы разнести работу с внешними переменными, базой, пагинацией в разные классы все перемешал.
> and $_GET['page']==true){
GET-переменнае никогда не может быть равна true. Там может быть только строка или массив.
В общем, я вижу что это какой-то странный класс, думаю надо переписать его целиком.
> SiteController
Я бы назвал StudentListController
> Если пользователь зарегистрирован, выведет список студентов, иначе перебросит на регистрацию
В задаче вроде анонимные пользователи могут простматривать список
> $user = new User(
$_POST['register']['name'],
$_POST['register']['surname'],
....
Не, это плохая идея делать функции с 8-9 аргументами так как запомнить в каком они порядке идут нереально. Не делай больше 4-5 аргументов. В данном случае гораздо лучше сделать метод $user->setAttributes(array $values) который берет значения из массива. Тем более что в Юи что-то похожее есть: http://www.yiiframework.com/doc/api/1.1/CModel#setAttributes-detail
Ну и помни что этот метод должен проверять какие поля он стаивт и не позволять например перезаписать поле вроде «isAdmin» (если такое есть).
> $userID = (int)$_COOKIE['id'];
Это ненадежно. Любой злоумышленник так может подставить себе любой id. Почитай комментарии к заданию, там описан код который позволяет сделать защиту.
> $view = 'students';
А почему не students.php? По моему если написать имя файла целиком то будет гораздо понятнее. Более того, тут можно было бы и переменную не заводить, а сразу вписать имя.
> https://github.com/krbn/students/blob/master/protected/classes/SiteController.php#L33
После успешной обработки формы надо делать редирект, а не выводить список. Это позволяет защититься от повторной отправки при обновлении страницы и сделать чтобы перемещение по истории назад/вперед нормально работало. Прочти мой урок про работу с формами внимательно, там написано: https://github.com/codedokode/pasta/blob/master/forms.md
> foreach($variables as $var=>$value){
> $$var = $value;
Есть функция extract
> https://github.com/krbn/students/blob/master/protected/classes/UserMapper.php#L5
> public $id;
Почему id это свойство маппера? Что за ерунда? Это свойство пользователя по моему, у каждого пользователя свой id а не общий на всю таблицу.
Соответственно после вставки пользователя в таблицу ты проставляешь id на объекте User.
Вообще, то, что ты знаком с Юи и пытался сделать что-то похожее, это хорошо. Я вижу что ты например понимаешь что такое шаблоны или что такое контроллер. Но кое-какие замечания к твоему коду все равно есть.
Если что-то непонятно или ты не согласен, напиши.
По базе данных:
Таблицу лучше назвать students, так как list не говорит нам что в ней хранится.
Похоже что ты не использовал тип YEAR для хранения года рождения, а ведь такой тип специально для этого придуман. Если ты про него не знал, то почитай про то какие типы есть в MySQL:
http://phpclub.ru/mysql/doc/column-types.html
> CREATE DATABASE students CHARACTER SET utf8 COLLATE utf8_general_ci;
Не надо это добавлять в файл, так как у меня например уже есть готовая база данных, и у нее может быть другое имя. Достаточно CREATE TABLE
> `mark` TINYINT UNSIGNED
Tinyint у нас вроде от 0 до 255, этого хватит?
> `gender` ENUM
> `residence` ENUM
NOT NULL почему не указал? Это же обязательные поля вроде.
> function __autoload($class){
> require_once 'protected/classes/'.$class.'.php';
Когда ты пишешь автолоадер, надо проверять есть ли такой файл и только если есть то подключать его. Иначе когда ты подключишь стороннюю библиотеку и она попытается подключить свой класс, твой автолоадер выдаст ошибку о несуществующем файле.
> class Application
Это правильнее наверно было бы назвать FrontController, так как твой класс реализует этот паттерн ( http://design-pattern.ru/patterns/front-controller.html ). Ну и название «Application» как бы намекает что это универсальный класс, который подойдет к любому приложению. Но ведь это не так. Твой класс заточен под список студентов. Раз так, то и называй его StudentListApplication или StudentListFrontController чтобы из названия все было ясно.
> public function init()
> public function run()
не вижу почему нам надо вызывать 2 функции. не проще ли сделать одну функцию, run, а init вызывать из нее?
Также, init я бы переименовал в route() так как она занимается роутингом — определяет какой контроллер/действие вызвать.
Также, я бы упростил if чтобы уменьшить глубину вложенности. Например можно убрать else во всех if.
> class DataBase
Название ни о чем не говорит, я бы его поменял (например на DbConnectionCreator), более того, я бы вообще этот класс удалил так как он ничего полезного не делает. Вместо испльзования синглтона (который в общем плохой паттерн) я бы лучше например сделал в Application метод getDb()
> }catch(Exception $e){
> header('Content-type:text/html;charset=utf8');
Это плохая идея, так обрабатывать исключения. Почему ты обрабатываешь исключение только от соединения с базой, а в других случаях нет? Если ты хочешь реализовать красивую страницу заглушку, то лучше установить универсальный обработчик исключений с помощью set_exception_handler или обернув Application#run в try/catch.
Вот мой урок про исключения: https://gist.github.com/codedokode/65d43ca5ac95c762bc1a
Также, ты не записываешь подробности ощибки в лог. У тебя сайт полдня лежал, а ты об этом даже не узнаешь. Это по твоему нормально? Если бы ты не перехватывал исключение, все бы записалось. Но если ты его перехватываешь то фиксируй ошибку функцией error_log.
Также, зачем ты показываешь пользователю код ошибки? Это ему ничего не говорит.
Также, ты должен при ошибке выдавать HTTP-код 5xx. Например поисковый робот увидев этот код не станет индексировать страницу. Прочти про коды HTTP и выучи наизучть хотя бы эти коды: 200, 301, 401, 403, 404, 500, 503: https://ru.wikipedia.org/wiki/%D0%A1%D0%BF%D0%B8%D1%81%D0%BE%D0%BA_%D0%BA%D0%BE%D0%B4%D0%BE%D0%B2_%D1%81%D0%BE%D1%81%D1%82%D0%BE%D1%8F%D0%BD%D0%B8%D1%8F_HTTP
Ну и в будущем всегда выставляй правильный HTTP-код (200 можно не выставлять, так как PHP по умолчанию все страницы с этим кодом отдает).
> $db_config = parse_ini_file('protected/config.ini');
Ты используешь относительный путь который зависит от текущего каталога. При запуске из командной строки например этот файл может не найтись. Я бы явно прописал абсолютный путь через _ _ DIR _ _ .
> protected/classes/Pager.php
Это что-то непонятное и требует исправления.
> "SELECT COUNT(×) as rowCount FROM (SELECT `id`,`name`,`surname`,`group`,`mark` FROM list) AS tmp"
Это абсолютно неэффективно, выбирать все записи только чтобы посчитать количество. Почему ты не напишешь сразу SELECT COUNT(..) FROM list?
Если ты слабо знаешь SQL, я советую порешать задания на SQL из первого поста. Хорошее знание баз данных поможет тебе выбрать изначально правильную структуру БД и сэкономить время на исправлениях проблем из-за выбора неправильной.
Также, вся работа с базой должна быть в мапперах, а не размазана по коду.
> if(isset($_GET['page'])
Лучше делать независимый от внешнего окружения класс где номер страницы передается параметром, а не привзяан к конкретной GET переменной. Это сделает код универсальнее и аккуратнее. И в базу данных тоже лучше не лезть. А ты вместо того чтобы разнести работу с внешними переменными, базой, пагинацией в разные классы все перемешал.
> and $_GET['page']==true){
GET-переменнае никогда не может быть равна true. Там может быть только строка или массив.
В общем, я вижу что это какой-то странный класс, думаю надо переписать его целиком.
> SiteController
Я бы назвал StudentListController
> Если пользователь зарегистрирован, выведет список студентов, иначе перебросит на регистрацию
В задаче вроде анонимные пользователи могут простматривать список
> $user = new User(
$_POST['register']['name'],
$_POST['register']['surname'],
....
Не, это плохая идея делать функции с 8-9 аргументами так как запомнить в каком они порядке идут нереально. Не делай больше 4-5 аргументов. В данном случае гораздо лучше сделать метод $user->setAttributes(array $values) который берет значения из массива. Тем более что в Юи что-то похожее есть: http://www.yiiframework.com/doc/api/1.1/CModel#setAttributes-detail
Ну и помни что этот метод должен проверять какие поля он стаивт и не позволять например перезаписать поле вроде «isAdmin» (если такое есть).
> $userID = (int)$_COOKIE['id'];
Это ненадежно. Любой злоумышленник так может подставить себе любой id. Почитай комментарии к заданию, там описан код который позволяет сделать защиту.
> $view = 'students';
А почему не students.php? По моему если написать имя файла целиком то будет гораздо понятнее. Более того, тут можно было бы и переменную не заводить, а сразу вписать имя.
> https://github.com/krbn/students/blob/master/protected/classes/SiteController.php#L33
После успешной обработки формы надо делать редирект, а не выводить список. Это позволяет защититься от повторной отправки при обновлении страницы и сделать чтобы перемещение по истории назад/вперед нормально работало. Прочти мой урок про работу с формами внимательно, там написано: https://github.com/codedokode/pasta/blob/master/forms.md
> foreach($variables as $var=>$value){
> $$var = $value;
Есть функция extract
> https://github.com/krbn/students/blob/master/protected/classes/UserMapper.php#L5
> public $id;
Почему id это свойство маппера? Что за ерунда? Это свойство пользователя по моему, у каждого пользователя свой id а не общий на всю таблицу.
Соответственно после вставки пользователя в таблицу ты проставляешь id на объекте User.
> https://github.com/krbn/students/blob/master/protected/classes/UserMapper.php#L10
> public function insert($data)
Здесь (и в других аналогичных случаях) нужен тайп хинт.
Тайп хинты позволяют указать, что аргумент функции должен быть определенного типа (например быть объектом определенного класса или его наследника). Тайп хинт делает код понятнее (так как видно какого типа переменная) и надежнее (так как PHP не позволит передать что-то неразрешенное и ты сразу увидишь ошибку). Используй их везде.
Мануал: http://php.net/manual/ru/language.oop5.typehinting.php
> public function select($pager)
Мне кажется объект который ты передаешь правильнее назвать не pager, а criteria. Обычно так называют объект хранящий условия выборки/фильтрации данных. Там позже можно будет и поиск вкрутить.
> На самом деле проверка белым списком уже осуществлялась в конструкторе класса Page,
> так что здесь повтор только ради удобства чтения кода
Тут ты ошибаешься. Во-первых, проверка должна быть именно здесь чтобы с одного взгляда было видно безопасен код или нет и мне не надо было изучать все твое приложение и пытаться найти все места где меняется значение sort. Во-вторых, sort публичное свойство и кто угодно может вписать туда что угодно в обход всяких проверок.
ну и было бы удобнее есть getById и select (которую надо переименовать в getAll/findAll) возвращали бы не массивы, а объекты. Ведь у нас есть прекрасный класс User, и он во много раз лучше какого-то безликого массива.
> public function update($data, $id)
Мне кажется, id должен быть в объекте User, а не отдельно. Это же свойство пользователя.
> $arr = $stmt->fetchAll(PDO::FETCH_ASSOC);
> return $arr[0];
Во-первых, что если массив будет пустой и в нем нет нулевого элемента? Во-вторых, у PDO есть методы fetch и fetchColumn.
> https://github.com/krbn/students/blob/master/protected/classes/Validator.php#L99
> $sql = "SELECT email FROM list WHERE email=:email";
Вся работа с базой должна быть в мапперах, а не размазана по коду
> public $errorMsg; // Сюда сохраняем отчет об ошибке
Лучше сделать это свойство закрытым и получать через метод. А то сейчас у тебя возможна такая ситуация:
$v = new Validator($user);
var_dump($v->errorMsg); // А где ошибки? Почему он их не выводит?
Не очевидно, что я сначала должен вызвать validate. В ООП за счет правильного проектирования ты должен стараться сделать так, чтобы объектом нельзя было воспользоваться неправильно. Наример выкидывать иключение пи поптыке получить результат до валидации. Или сделать еще умнее: сделать чтобы сообщения об ошибке возвращала функция валидации и их нельзя было получить не вызвав ее.
> DataBase::getInstance( )->getDB( );
Вот это тоже в общем плохой паттерн, лучше передавать маппер в конструктор.
> Если мы не желаем проверять конкретное поле, нужно создать элемент с ключом, содержащим его имя,
> например array('email'=>false)
Ой, как запутанно. Почему бы не сделать параметр $skip задающий пропускаемые поля: $skip = ['email', 'name']?
> <?php echo $_SERVER['SCRIPT_NAME'];?>
Это не очень хорошая идея, лезть во внешние переменные из шаблона. Может лучше явно вписать тут register.php? Я думаю, что лучше вписать явно.
> https://github.com/krbn/students/blob/master/protected/views/students.php#L33
> <td class="name"><?php echo $row['name'];?></td>
А где экранирование спецсимволов? Ну-ка прочти урок про XSS: https://github.com/codedokode/pasta/blob/master/security/xss.md
Также, вместо <?php echo лучше и короче написать <?=
> http_build_query($pager->getParams())."&page=$i";
Это тоже надо экранировать так как знак & в HTML записывается как &
Почитай про спецсимволы в HTML:
http://htmlbook.ru/samhtml/tekst/spetssimvoly
http://htmlbook.ru/faq/kak-otobrazit-tegi-na-veb-stranitse
Также, формы редактирования и регистрации очень похожи. Значит, их можно объединить в один шаблон и избежать копипасты.
Также, я вижу ты верстаешь формы таблицами. Не хочешь порешать наши задачки на HTML/CSS в шапке треда и научиться пользоваться всеми возможностями CSS?
Далее я напишу замечания от робота.
> https://github.com/krbn/students/blob/master/protected/classes/UserMapper.php#L10
> public function insert($data)
Здесь (и в других аналогичных случаях) нужен тайп хинт.
Тайп хинты позволяют указать, что аргумент функции должен быть определенного типа (например быть объектом определенного класса или его наследника). Тайп хинт делает код понятнее (так как видно какого типа переменная) и надежнее (так как PHP не позволит передать что-то неразрешенное и ты сразу увидишь ошибку). Используй их везде.
Мануал: http://php.net/manual/ru/language.oop5.typehinting.php
> public function select($pager)
Мне кажется объект который ты передаешь правильнее назвать не pager, а criteria. Обычно так называют объект хранящий условия выборки/фильтрации данных. Там позже можно будет и поиск вкрутить.
> На самом деле проверка белым списком уже осуществлялась в конструкторе класса Page,
> так что здесь повтор только ради удобства чтения кода
Тут ты ошибаешься. Во-первых, проверка должна быть именно здесь чтобы с одного взгляда было видно безопасен код или нет и мне не надо было изучать все твое приложение и пытаться найти все места где меняется значение sort. Во-вторых, sort публичное свойство и кто угодно может вписать туда что угодно в обход всяких проверок.
ну и было бы удобнее есть getById и select (которую надо переименовать в getAll/findAll) возвращали бы не массивы, а объекты. Ведь у нас есть прекрасный класс User, и он во много раз лучше какого-то безликого массива.
> public function update($data, $id)
Мне кажется, id должен быть в объекте User, а не отдельно. Это же свойство пользователя.
> $arr = $stmt->fetchAll(PDO::FETCH_ASSOC);
> return $arr[0];
Во-первых, что если массив будет пустой и в нем нет нулевого элемента? Во-вторых, у PDO есть методы fetch и fetchColumn.
> https://github.com/krbn/students/blob/master/protected/classes/Validator.php#L99
> $sql = "SELECT email FROM list WHERE email=:email";
Вся работа с базой должна быть в мапперах, а не размазана по коду
> public $errorMsg; // Сюда сохраняем отчет об ошибке
Лучше сделать это свойство закрытым и получать через метод. А то сейчас у тебя возможна такая ситуация:
$v = new Validator($user);
var_dump($v->errorMsg); // А где ошибки? Почему он их не выводит?
Не очевидно, что я сначала должен вызвать validate. В ООП за счет правильного проектирования ты должен стараться сделать так, чтобы объектом нельзя было воспользоваться неправильно. Наример выкидывать иключение пи поптыке получить результат до валидации. Или сделать еще умнее: сделать чтобы сообщения об ошибке возвращала функция валидации и их нельзя было получить не вызвав ее.
> DataBase::getInstance( )->getDB( );
Вот это тоже в общем плохой паттерн, лучше передавать маппер в конструктор.
> Если мы не желаем проверять конкретное поле, нужно создать элемент с ключом, содержащим его имя,
> например array('email'=>false)
Ой, как запутанно. Почему бы не сделать параметр $skip задающий пропускаемые поля: $skip = ['email', 'name']?
> <?php echo $_SERVER['SCRIPT_NAME'];?>
Это не очень хорошая идея, лезть во внешние переменные из шаблона. Может лучше явно вписать тут register.php? Я думаю, что лучше вписать явно.
> https://github.com/krbn/students/blob/master/protected/views/students.php#L33
> <td class="name"><?php echo $row['name'];?></td>
А где экранирование спецсимволов? Ну-ка прочти урок про XSS: https://github.com/codedokode/pasta/blob/master/security/xss.md
Также, вместо <?php echo лучше и короче написать <?=
> http_build_query($pager->getParams())."&page=$i";
Это тоже надо экранировать так как знак & в HTML записывается как &
Почитай про спецсимволы в HTML:
http://htmlbook.ru/samhtml/tekst/spetssimvoly
http://htmlbook.ru/faq/kak-otobrazit-tegi-na-veb-stranitse
Также, формы редактирования и регистрации очень похожи. Значит, их можно объединить в один шаблон и избежать копипасты.
Также, я вижу ты верстаешь формы таблицами. Не хочешь порешать наши задачки на HTML/CSS в шапке треда и научиться пользоваться всеми возможностями CSS?
Далее я напишу замечания от робота.
От робота:
Кажется, ты не используешь строгий режим в MySQL. Зря. MySQL более тщательно проверяет твои запросы и вместо предупреждений (которые ты не увидишь) выдает ошибки при попытке вставить неправильные данные. Ну к примеру, если у тебя есть колонка типа varchar(200) и ты попытаешься вставить в нее строку из 300 символов, в нестрогом режиме MySQL молча отрежет лишнее (и в базе окажется обрезанная строка), а в строгом выдаст ошибку.
Использование строгого режима экономит твое время на исправление неправильно вставленных данных. Статья на хабре: http://habrahabr.ru/post/116922/
Включить строгий режим можно сделав при соединении с БД запрос SET sql_mode='STRICT_ALL_TABLES'. В PDO это удобно сделать опцией PDO::MYSQL_ATTR_INIT_COMMAND при создании объекта PDO.
В файле ./protected/views/main.php:
Используй <?= вместо <?php echo в шаблоне, так как он короче и лучше читается.
Похоже, что ты не используешь htmlspecialchars. Это плохая идея, так как в этом случае легко получить уязвимость XSS (злоумышленник может вывести произвольный HTML код на страницу). Прочти мой урок на эту тему: https://github.com/codedokode/pasta/blob/master/security/xss.md
В файле ./protected/classes/Validator.php:
Слеш в конце одиночного тега (<br/>) используется только в XHTML и XML, в HTML он не ставится.
В файле ./protected/views/main.php:
Слеш в конце одиночного тега (<link rel="stylesheet" href="c…ss"/>) используется только в XHTML и XML, в HTML он не ставится.
В файле ./protected/views/register.php:
Слеш в конце одиночного тега (<input type="text" name="regis…e]"/>) используется только в XHTML и XML, в HTML он не ставится.
От робота:
Кажется, ты не используешь строгий режим в MySQL. Зря. MySQL более тщательно проверяет твои запросы и вместо предупреждений (которые ты не увидишь) выдает ошибки при попытке вставить неправильные данные. Ну к примеру, если у тебя есть колонка типа varchar(200) и ты попытаешься вставить в нее строку из 300 символов, в нестрогом режиме MySQL молча отрежет лишнее (и в базе окажется обрезанная строка), а в строгом выдаст ошибку.
Использование строгого режима экономит твое время на исправление неправильно вставленных данных. Статья на хабре: http://habrahabr.ru/post/116922/
Включить строгий режим можно сделав при соединении с БД запрос SET sql_mode='STRICT_ALL_TABLES'. В PDO это удобно сделать опцией PDO::MYSQL_ATTR_INIT_COMMAND при создании объекта PDO.
В файле ./protected/views/main.php:
Используй <?= вместо <?php echo в шаблоне, так как он короче и лучше читается.
Похоже, что ты не используешь htmlspecialchars. Это плохая идея, так как в этом случае легко получить уязвимость XSS (злоумышленник может вывести произвольный HTML код на страницу). Прочти мой урок на эту тему: https://github.com/codedokode/pasta/blob/master/security/xss.md
В файле ./protected/classes/Validator.php:
Слеш в конце одиночного тега (<br/>) используется только в XHTML и XML, в HTML он не ставится.
В файле ./protected/views/main.php:
Слеш в конце одиночного тега (<link rel="stylesheet" href="c…ss"/>) используется только в XHTML и XML, в HTML он не ставится.
В файле ./protected/views/register.php:
Слеш в конце одиночного тега (<input type="text" name="regis…e]"/>) используется только в XHTML и XML, в HTML он не ставится.
Ты его установил как службу? В винде ты можешь открыть окно управления службами (Пуск -> services.msc) и проверить есть ли там служба Апача и какое у нее состояние. Там же ты можешь запустить или остановить ее.
Я бы советовал научиться сначала руками ставить и настраивать Апач, а только потом браться за сборки.
>>464013
Ок, задача про айфон решена верно. Только вот это
> while ($creditBalanceAnon != 0);
я бы заменил на
> while ($creditBalanceAnon > 0);
Так как компьютерная математика приближенная и если там вдруг получится -0.0000000001 то он у тебя уйдет в вечный цикл, а у меня нет.
> Так IDE бугуртит, ....Но компилирует.
Потому что IDE только дает предупрежедния, а компилирует не она, а РHP который это ошибкой не считает.
> You should use only 1 assignment(s) (3 used), аргументируя это тем, что to avoid accidentally overwriting it and make your code easier to read.
Это в общем правильная идея, для каждого значения использовать свою переменную, но у нас один и тот же текст, и нет особого смысла заводить 3 переменных, опять же читать код в котором меньше разных названий, проще. Но вообще, это не принципиально, хочешь, можешь делать отдельные перемнные. Я бы сделал одной.
Ок, задача про палиндром решена верно.
Ты его установил как службу? В винде ты можешь открыть окно управления службами (Пуск -> services.msc) и проверить есть ли там служба Апача и какое у нее состояние. Там же ты можешь запустить или остановить ее.
Я бы советовал научиться сначала руками ставить и настраивать Апач, а только потом браться за сборки.
>>464013
Ок, задача про айфон решена верно. Только вот это
> while ($creditBalanceAnon != 0);
я бы заменил на
> while ($creditBalanceAnon > 0);
Так как компьютерная математика приближенная и если там вдруг получится -0.0000000001 то он у тебя уйдет в вечный цикл, а у меня нет.
> Так IDE бугуртит, ....Но компилирует.
Потому что IDE только дает предупрежедния, а компилирует не она, а РHP который это ошибкой не считает.
> You should use only 1 assignment(s) (3 used), аргументируя это тем, что to avoid accidentally overwriting it and make your code easier to read.
Это в общем правильная идея, для каждого значения использовать свою переменную, но у нас один и тот же текст, и нет особого смысла заводить 3 переменных, опять же читать код в котором меньше разных названий, проще. Но вообще, это не принципиально, хочешь, можешь делать отдельные перемнные. Я бы сделал одной.
Ок, задача про палиндром решена верно.
Читать доки? Или все-таки...
По моему эта экономия того не стоит. Но преобразование объекта в массив через (array) ты точно делать не должен так как тут много побочных эффектов и разобраться потом в твоем коде будет очень тяжело.
> т. к. лишних свойств не было.
Код развивается. Что если это новое свойство допишут завтра и у тебя отвалится сохранение в базу данных? Видишь, код построенный таким образом становится хрупким и тебе придется потом тратить время на его исправление. Лучше писать сразу надежный код который не развалится.
Если при добавлении свойства в объект отваливается сохранеие в БД, это плохой код. Объекты для того и придуманы чтобы в них можно было добавлять свойства и ничего ломаться не должно.
В общем, хорошо решено.
> return array_filter($cities, $condition);
В таких случаях удобно вписывать функцию сразу в аргументы и не заводить переменных:
return array_filter($cities, function (...) {
....
});
> function printCities($cities) {
А можешь эту функцию сделать без цикла c использованием array_map?
> А еще я наконец-то нашел работку,
Ну это хорошо, но не забывай только что пока ты наичнающий ты должен развиваться и изучать что-то новое, иначе так и останешься на нынешнем уровне.
> ОП, подкинь пожалуйста ссылок, где доходчиво объясняется типизация в js
Не знаю, то это или нет, но вот ссылки:
https://learn.javascript.ru/types-intro
https://learn.javascript.ru/types-conversion
преобразование к логическому значению (какие значения превращаются в false и считаются falsy, а какие truthy) стоит выучить наизусть, там всего 5 или 6 значений.
Странные преобразования типа +[] + "" + {} учить не надо, но они могут встретиться на собеседованиях (но я все равно считаю что учить это безумие). Что даст эта формула ты можешь увидеть в консоли браузера (Ctrl + Shift + J, заходи туда почаще)
Также напоминаю, у нас в шапке треда есть задачки на JS, и часть из них даже проверяется роботом.
> Что такое html-коллекция? Это массив или объект?
Это из темы под названием «DOM». DOM это набор объектов который позволяют яваскрипту видеть и менять содержимое страницы.
HTML коллекция это объект из DOM, который возвращают функции вроде getElementsByTagName.
HTML коллекция это не массив, а объект-псевдомассив. Псевдомассивом он назвается так как у него есть свойство length и к элементам можно обращаться через скобки. Попробуй поэкспериментировать в консоли браузера (Ctrl + shift + J):
var elements = document.getElementsByTagName('body')
> undefined
dir(elements)
> NodeList[1] // объект «класса» NodeList
elements.length
> 1
elements[0]
> <body class="replypage makaba">…</body>
Но он не является массивом так как не «унаследован» от Array и не содержит методов вроде slice, shift:
elements instanceof Array
> false
elements.slice
> undefined
Кстати, коллекция которую возвращает getElementsBytagName, «живая». Она изменяется при добавлении/удалении элементов в документ.
Псевдомассивом также является например объект arguments хранящий аргументы функции.
Документация по NodeList: https://developer.mozilla.org/ru/docs/Web/API/NodeList
DOM важная тема и если что-то непонятно, спрашивай.
> Что такое html-коллекция? Это массив или объект?
Это из темы под названием «DOM». DOM это набор объектов который позволяют яваскрипту видеть и менять содержимое страницы.
HTML коллекция это объект из DOM, который возвращают функции вроде getElementsByTagName.
HTML коллекция это не массив, а объект-псевдомассив. Псевдомассивом он назвается так как у него есть свойство length и к элементам можно обращаться через скобки. Попробуй поэкспериментировать в консоли браузера (Ctrl + shift + J):
var elements = document.getElementsByTagName('body')
> undefined
dir(elements)
> NodeList[1] // объект «класса» NodeList
elements.length
> 1
elements[0]
> <body class="replypage makaba">…</body>
Но он не является массивом так как не «унаследован» от Array и не содержит методов вроде slice, shift:
elements instanceof Array
> false
elements.slice
> undefined
Кстати, коллекция которую возвращает getElementsBytagName, «живая». Она изменяется при добавлении/удалении элементов в документ.
Псевдомассивом также является например объект arguments хранящий аргументы функции.
Документация по NodeList: https://developer.mozilla.org/ru/docs/Web/API/NodeList
DOM важная тема и если что-то непонятно, спрашивай.
http://ideone.com/qCI36p
В общем переделал сразу по горячим следам, но мне не нравится так, я не могу понять как эти функции отформатировать читабельно, что бы было ясно, что это всего лишь параметр другой функции.
>А можешь эту функцию сделать без цикла c использованием array_map?
Сделал
>Ну это хорошо, но не забывай только что пока ты наичнающий ты должен развиваться и изучать что-то новое, иначе так и останешься на нынешнем уровне.
Так в этом и проблема, что я сидя дома очень медленно расту, я твою задачу с вектором делаю уже 3 недели наверное, потому что там куча дыр и я не знаю как переделывать некоторые правки. Но на самом деле просто у меня дома атмосфера не рабочая и я по большей части пинаю хуи. А на работе я надеюсь что буду ебашить по хардкору, как я когда неделю работал зимой, то изучил как за месяц ништяков всяких.
Что кстати можешь сказать про Кодэгнайтер, будет польза на будущее если я его освою? Или нужно его будет рассматривать онли как учебный и вечерами ковырять Yii и Симфони?
Насчет объектов: не все в JS является объектом. Есть примитивы (строки, числа, NaN, Infinity, boolean, null, undefined), а все остальное это объекты.
Также есть объекты-обертки примитивов: String, Number, Boolean. Js автоматически создает временные объекты когда ты пытаешься работать с примитивом как с объектом (это называется боксинг значения, то есть оборачивание примитива в объект):
"asd".length
Фактически выполняется так:
var tmp = new String("asd');
tmp.length
Это описано в моем наборе задач: https://gist.github.com/codedokode/ce30e7a036f18f416ae0#%D0%91%D0%BE%D0%BA%D1%81%D0%B8%D0%BD%D0%B3 (там еще и другие полезные вещи описаны)
Советую поэкспериментировать с этим в консоли браузера.
> Является ли функция объектом?
Да. Это объект встроенного класса Function что легко проверить введя в консоли:
(function() {}) instanceof Function
> true
dir(function() {})
> function () {} (тут можно раскрыть ее и увидеть ее методы и свойства)
> Является ли анонимная функция каким-то особенным объектом, как замыкания в пхп?
Нет, в JS все функции и методы равнозначны и все захватывают окружающие переменные (по ссылке, то есть сами переменные а не их копии) в момент создания.
Метод в JS это функция которая сохранена в свойстве объекта:
var obj = {};
obj.method = function () {...};
> Я так понял, что даже простые типы данных вроде строки или числа тоже объекты.
Нет, но они могут в них превращаться
> Может, есть какое-то дерево объектов, как в случае с DOM?
Есть набор встроенных объектов:
https://learn.javascript.ru/native-prototypes
https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects (это подробный список, включающий как старые ES3 классы так и новые из ES5/ES6. Es3/5/6 это версии яваскрипта, первая древняя и работает везде, последняя толком нигде пока не поддерживается).
Почти все объекты «наследуются» в итоге от Object.
> Пока слабое понимание всех этих моментов.
Читай ссылки, экспериментируй в консоли, задавай вопросы.
Насчет объектов: не все в JS является объектом. Есть примитивы (строки, числа, NaN, Infinity, boolean, null, undefined), а все остальное это объекты.
Также есть объекты-обертки примитивов: String, Number, Boolean. Js автоматически создает временные объекты когда ты пытаешься работать с примитивом как с объектом (это называется боксинг значения, то есть оборачивание примитива в объект):
"asd".length
Фактически выполняется так:
var tmp = new String("asd');
tmp.length
Это описано в моем наборе задач: https://gist.github.com/codedokode/ce30e7a036f18f416ae0#%D0%91%D0%BE%D0%BA%D1%81%D0%B8%D0%BD%D0%B3 (там еще и другие полезные вещи описаны)
Советую поэкспериментировать с этим в консоли браузера.
> Является ли функция объектом?
Да. Это объект встроенного класса Function что легко проверить введя в консоли:
(function() {}) instanceof Function
> true
dir(function() {})
> function () {} (тут можно раскрыть ее и увидеть ее методы и свойства)
> Является ли анонимная функция каким-то особенным объектом, как замыкания в пхп?
Нет, в JS все функции и методы равнозначны и все захватывают окружающие переменные (по ссылке, то есть сами переменные а не их копии) в момент создания.
Метод в JS это функция которая сохранена в свойстве объекта:
var obj = {};
obj.method = function () {...};
> Я так понял, что даже простые типы данных вроде строки или числа тоже объекты.
Нет, но они могут в них превращаться
> Может, есть какое-то дерево объектов, как в случае с DOM?
Есть набор встроенных объектов:
https://learn.javascript.ru/native-prototypes
https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects (это подробный список, включающий как старые ES3 классы так и новые из ES5/ES6. Es3/5/6 это версии яваскрипта, первая древняя и работает везде, последняя толком нигде пока не поддерживается).
Почти все объекты «наследуются» в итоге от Object.
> Пока слабое понимание всех этих моментов.
Читай ссылки, экспериментируй в консоли, задавай вопросы.
> На самом деле это у меня поля формы. А какие будут поля (и сколько), неизвестно.
> Мы не знаем, что человек передаст при создании объекта.
Тогда это не объект а массив. В объекте всегда известно какие у него есть поля и методы. И это делает код понятным и надежным в отличие от кода на массивах.
Ну или ты можешь сделать валидатор в таком стиле:
var v = new Validator;
v.addRule(....);
v.addRule(...);
var errors = v.validate(data);
Но тогда тебе нет необходимости проставлять свойства из массива.
> Мы не знаем, что человек передаст при создании объекта.
Мы не знаем, но набор разрешенных полей должен быть известен иначе это бардак какой-то.
> Поэтому пытаюсь написать класс, который будет принимать массив полей с их названиями и значениями, чтобы конструктор в цикле их разложил по полочкам.
Не пытайся из класса сделать массив. Если ты хочешь проставлять поля из массива то лучше сделай отдельный метод для этого почему ты его встраиваешь в конструктор и запрещаешь вызвыать его отдельно?
> Как вообще в js обстоит дело с ООП?
Печально, там задумывалось что все будут использовать «прототипное программирование», когда объекты создаются не из классов, а из других объектов, но по факту никто его не исопльзует и все имитируют привычное наследование на классах из PHP. Тебе надо научиться работать с такими «классами», создавать их и использовать:
https://learn.javascript.ru/prototypes
В ES6 будет синтаксис для классов под которым будут скрыты те же прототипы: http://habrahabr.ru/post/175371/ Так что изучать прототипы все равно придется.
> На самом деле это у меня поля формы. А какие будут поля (и сколько), неизвестно.
> Мы не знаем, что человек передаст при создании объекта.
Тогда это не объект а массив. В объекте всегда известно какие у него есть поля и методы. И это делает код понятным и надежным в отличие от кода на массивах.
Ну или ты можешь сделать валидатор в таком стиле:
var v = new Validator;
v.addRule(....);
v.addRule(...);
var errors = v.validate(data);
Но тогда тебе нет необходимости проставлять свойства из массива.
> Мы не знаем, что человек передаст при создании объекта.
Мы не знаем, но набор разрешенных полей должен быть известен иначе это бардак какой-то.
> Поэтому пытаюсь написать класс, который будет принимать массив полей с их названиями и значениями, чтобы конструктор в цикле их разложил по полочкам.
Не пытайся из класса сделать массив. Если ты хочешь проставлять поля из массива то лучше сделай отдельный метод для этого почему ты его встраиваешь в конструктор и запрещаешь вызвыать его отдельно?
> Как вообще в js обстоит дело с ООП?
Печально, там задумывалось что все будут использовать «прототипное программирование», когда объекты создаются не из классов, а из других объектов, но по факту никто его не исопльзует и все имитируют привычное наследование на классах из PHP. Тебе надо научиться работать с такими «классами», создавать их и использовать:
https://learn.javascript.ru/prototypes
В ES6 будет синтаксис для классов под которым будут скрыты те же прототипы: http://habrahabr.ru/post/175371/ Так что изучать прототипы все равно придется.
Что за хуйню ты говоришь? Читать умеешь?
Скорее всего там имелась ввиду сборка Homestead и предлагалось установить ее в vbox на windows.
> Перечитал мануал по ней 2 раза и все равно не догоняю пока
preg_replace_callback работает так:
- найти все места в тексте соотв. регулярке
- для каждого найденного места {
вызвыаем коллбек передавая ему массив совпадений
то, что вернет коллбек вставляем вместо найденного куска текста
}
то есть твоя функция отвечает на вопрос: «что вставим вместо этого куска текста?»
Соответственно ты можешь сделать поиск в тексте всех конструкций вида { .... } и твоя функция будет их заменять на значение переменной.
Твое решение не сработает если в одном из значений для подстановки содержится конструкция {abc} — она будет заменена, а этого не должно быть.
Более того, в твоем случае вообще preg_replace не нужен, хватило бы str_replace или strtr (который лишен описанного выше недостатка так как проходит строку один раз).
Читать доки
>>464386
> я не могу понять как эти функции отформатировать читабельно, что бы было ясно, что это всего лишь параметр другой функции.
Для меня твой нынешний вариант читабелен. Думаю, и ты привыкнешь со временем.
Вот примеры замыканий из стандарта PSR-2: http://www.php-fig.org/psr/psr-2/ru/#6.-Замыкания
> array_map(function($city) {
>\t\techo " ", $city["name"] . "(" . $city["population"] . ")";
ну не, array_map же делает замену, сделай тут return вместо echo.
> Что кстати можешь сказать про Кодэгнайтер, будет польза на будущее если я его освою?
ну может немного полезных вещей узнаешь но в общем он староват и мне многие реешния в нем не нравятся.Yii2/Symfony 2 новее и лучше.
>>464388
Не знаю, где ты это прочел?
Думаю, что можно не ставить. думаю что и на винду без виртуалки его реально поставить, PHP кроссплатформенн.
>>464395
так, не ругайся тут
Читать доки
>>464386
> я не могу понять как эти функции отформатировать читабельно, что бы было ясно, что это всего лишь параметр другой функции.
Для меня твой нынешний вариант читабелен. Думаю, и ты привыкнешь со временем.
Вот примеры замыканий из стандарта PSR-2: http://www.php-fig.org/psr/psr-2/ru/#6.-Замыкания
> array_map(function($city) {
>\t\techo " ", $city["name"] . "(" . $city["population"] . ")";
ну не, array_map же делает замену, сделай тут return вместо echo.
> Что кстати можешь сказать про Кодэгнайтер, будет польза на будущее если я его освою?
ну может немного полезных вещей узнаешь но в общем он староват и мне многие реешния в нем не нравятся.Yii2/Symfony 2 новее и лучше.
>>464388
Не знаю, где ты это прочел?
Думаю, что можно не ставить. думаю что и на винду без виртуалки его реально поставить, PHP кроссплатформенн.
>>464395
так, не ругайся тут
Да, апач или енжиникс, ну и базу данных еще.
Оу, замечаний оказалось чуть больше, чем я предполагал.(((
Завтра исправлю, что смогу.
>Таблицу лучше назвать students, так как list не говорит нам что в ней хранится
Да, надо привыкать серьезно подходить к делу. А то на мелких заданиях привыкаешь давать названия от фонаря, в более крупных проектах это может аукнуться, согласен.
>не использовал тип YEAR для хранения года рождения
Не подумал, та же причина (что-то среднее между невнимательностью и неаккуратностью).
>Не надо добавлять в файл CREATE DATABASE... , так как у меня например уже есть готовая база данных
Кстати, а сколько проектов может использовать одну базу? Я привык под каждую безделушку делать новую базу.
А как принято?
> `mark` TINYINT UNSIGNED Tinyint у нас вроде от 0 до 255, этого хватит?
TINYINT[(M)] [UNSIGNED] [ZEROFILL]
Диапазон со знаком от -128 до 127. Диапазон без знака от 0 до 255.
> `residence` ENUM
>NOT NULL почему не указал? Это же обязательные поля вроде.
Да, пропустил по невнимательности.
>Когда ты пишешь автолоадер, надо проверять есть ли такой файл
Да, не подумал об этом.
>Это правильнее наверно было бы назвать
Отсутствие опыта сказывается. Названия пока беру от балды.
Как примелькается код фреймворков и паттернов с их устоявшимися именами классов и полей, придет и понимание, как правильно именовать все эти штуки, я надеюсь.
>урок про исключения
>записывать подробности ощибок в лог
Почитаю об этом.
Ладно, завтра попытаюсь переварить остальные замечания и что-то исправить.
Оу, замечаний оказалось чуть больше, чем я предполагал.(((
Завтра исправлю, что смогу.
>Таблицу лучше назвать students, так как list не говорит нам что в ней хранится
Да, надо привыкать серьезно подходить к делу. А то на мелких заданиях привыкаешь давать названия от фонаря, в более крупных проектах это может аукнуться, согласен.
>не использовал тип YEAR для хранения года рождения
Не подумал, та же причина (что-то среднее между невнимательностью и неаккуратностью).
>Не надо добавлять в файл CREATE DATABASE... , так как у меня например уже есть готовая база данных
Кстати, а сколько проектов может использовать одну базу? Я привык под каждую безделушку делать новую базу.
А как принято?
> `mark` TINYINT UNSIGNED Tinyint у нас вроде от 0 до 255, этого хватит?
TINYINT[(M)] [UNSIGNED] [ZEROFILL]
Диапазон со знаком от -128 до 127. Диапазон без знака от 0 до 255.
> `residence` ENUM
>NOT NULL почему не указал? Это же обязательные поля вроде.
Да, пропустил по невнимательности.
>Когда ты пишешь автолоадер, надо проверять есть ли такой файл
Да, не подумал об этом.
>Это правильнее наверно было бы назвать
Отсутствие опыта сказывается. Названия пока беру от балды.
Как примелькается код фреймворков и паттернов с их устоявшимися именами классов и полей, придет и понимание, как правильно именовать все эти штуки, я надеюсь.
>урок про исключения
>записывать подробности ощибок в лог
Почитаю об этом.
Ладно, завтра попытаюсь переварить остальные замечания и что-то исправить.
так и есть
> Кстати, а сколько проектов может использовать одну базу?
Обычно 1 проект = 1 база, но у меня например много проектов от анонов и если в каждом будет прописана база students то будут конфликты потому я прописываю каждому свою и потому ты не должен добавлять CREATE DATABASE в дамп. У меня эта база будет по другому называться.
> Диапазон без знака от 0 до 255.
Я не очень разбираюсь в ЕГЭ, но там вроде же максимум можно набрать 100 баллов, а в сумме по 3 предметам например 300. Или я путаю что-то? Мне кажется, лучше взять SMALLINT тогда.
Вот вопрос нагуглил, где фигурирует цифра 300: http://otvet.mail.ru/question/168497348
>>464404
Это слухи. Тем более что сайтом на твоем компьютере будет пользоваться 1 человек.
> так что в продакшене будет nginx, поэтому и разрабатывать на nginx сразу надо, чтобы потом сюрпризов не было
это хороший аргумент, хотя опять же лучше писать так чтобы в нгинксе не было запутанной конфигурации.
>Читать доки
А что если я необучаемый не совсем вдупляю что там происходит?
Когда-то давно писал дерьмо "все в одном файле", <b><? echo "Пользователь: '.mysql_query("SELECT 1 FROM table WHERE x = $x");.' </b>"; ?>
Ну ты понял.
Ты же написал что ты не новичок, и я из этого исходил. Если не «вдупляешь» то можешь либо тут вопросы задавать со ссылкой на конкретную страницу, я постараюсь пояснить, либо поискать какие то другие варианты, но мое мнение если ты документацию не осилил то ты и код нормально писать не сможешь.
Если бугор даст добро попробуй самый простой фреймворк из всех что я знаю
http://simplemvcframework.com/php-framework
Читнул один раздел из документации - попробовал как он работает, разобрался, молодец, нет - спросил советов мудрых, перекатываешься в следующий. Это если просто хочешь начать клепать странички. А если по-отцовски, то открываешь классы которые грузятся по порядку, читаешь и переписываешь руками в свой форк, все подряд не надо, только самое основное.
Я мимо проходил, посмотрел документацию, и она плохая.
1) обвешана рекламой
2) нет туториала вроде Get Started где делается простое приложение
далее, это микрофреймворк который никак не может быть заменой среднему фреймворку вроде Лаварель.
Если уж брать микрофреймворки, я бы советовал Slim или Silex (вот еще недавно появился микрофреймворк Lumen от создателей Лавареля).
Если брать другие средние фреймворки, я бы посоветовал Yii 2.
> Ок, задача про айфон решена верно.
Вот она же через функции https://ideone.com/dZS8aq
Сколько можно передать аргументов функции? Хоть сколько?
>нет туториала вроде Get Started где делается простое приложение
Есть причем в скринкастах http://simplemvcframework.com/screencasts/v2.1
Господи Иисусе, тебе даже не надо вытирать пальцы от кальмаров чтобы пролистнуть стенку текста, просто откидываешься в кресле и смотришь попутно подтягивая скилл восприятия инглиша на слух. Есть ли что-то подобное в слиме?
>обвешана рекламой
Не иметь адблока в 2015.
Лучшее русское комьюнити у иии, это точно.
https://ideone.com/afEcjy
А вообще можно ведь записать специально криво, например 8(911-50-656-56. Можно ли как то проверять если вначале после 8 стоит скобочка, то и закрываться тоже должно скобочкой?
Ну на вскидку можно сделать регулярку в духе
/8\(911\)\d{7}|8911\d{7}/
Либо номер без скобок, либо номер с корректными скобками подойдет, в 8(9115065656 забракует
Бро, подскажи как в бутстрапе разбираться? Я вот сегодня только начал. Сижу ковыряюсь в http://www.w3schools.com/bootstrap/bootstrap_get_started.asp
Я вот только начинаю въезжать что это такое. С html css немного знаком, но не настолько что бы самому сверстать сайт и даже не знаю всех тегов и css стилей.
В общем тут собраны заготовки и мне нужно лишь разобраться какой класс что выдает? И прописывать для своих элементов соответствующие классы и можно не заморачиваться с написанием css?
getbootstrap.com
Я копирую код с готовых примеров и компоную с них то что мне надо.
А почему бы не выучить html с css? Это же не долго и всяко полезнее чем шаманить с бутстрапом, ничего в нем не понимая.
Что-то у меня совсем плохо с джаваскрипт. Не получается написать даже проверку полей на заполнение. То есть в процедурном виде конечно могу накидать бессвязных функций, но хотелось бы таки в иерархическом ООП-стиле.
Например, как передать параметр при назначении событию какого-то метода класса?
function Hello(){
this.sayHello = function(word){
alert('Hello, ' + word);
};
}
var hello = new Hello();
someElement.onclick = hello.sayHello;
Ладно, придется идти учить матчасть.
>Каноны, в бутстрапе есть возможность при выборе из выпадающего списка формы сделать загрузку без нажатия кнопки формы submit (аякс это делает есть не ошибаюсь)
И без бутстрапа можно и с ним, без разницы:
<select onChange="this.form.submit()">
Если бы все было так просто.
При записи типа
var foo = function(param){ return 'ХУЙ ТЕБЕ!!!111' };
obj.onclick = foo(param);
произойдет именно вызов функции, в obj.prop придет в лучшем случае то что она возвращает. А мне нужно, чтобы туда скопировалась декларация функции.
$this->view->generate($template, array $data);
Пример
$article1 = new Article;
$article2 = new Article;
...
$this->view->generate('articles.html', [$articleA, $articleB,...]);
Но часто помимо основной инфы надо передать например ошибки или сообщения об успешной вставке данных, если форма добавления, редактирования находятся на одной странице со списком статей. В этом случае массив усложняется:
$errors = $model->getErrors();
$message = $model->getMessage();
$data = ['errors' => $errors, 'message' =>$message, 'users'=>...]
Думаю сделать класс.. допустим, DataManager чтоб работало так
$this->view->generate($template, DataManager $data);
А во вью делать
$data->getErrors();
$data->getMessage();
$data->getArticles();
Правильно мыслю? А если делать, чтоб не только статьи пересылать, но даже небо с аллахом, как обозвать универсальный метод, $data->getData() звучит странно. Чет ничего другого на ум не идет.
><select onChange="this.form.submit()">
Спасибо большое то что надо, не подскажешь случайно как сделать так, что бы после выбора и произошедшего действия, в поле выбора был выбранный пункт?
У меня, например, вот так:
<select onChange="this.form.submit()" size=1>
<option value="Пользователь" <?if ($userRules=="Пользователь") {?>selected<?}?>>Пользователь</option>
<option value="Администратор" <?if ($userRules=="Администратор") {?>selected<?}?>>Администратор</option>
<option value="Разработчик" <?if ($userRules=="Разработчик") {?>selected<?}?>>Разработчик</option>
</select>
Нормально или нужно всё переделывать? А если нужно переделывать то что? Только не говорите упростить что-то, у меня к этому генетическая неспособность.
http://ideone.com/OBeZI1
хуйня
где классы?
где паттерны?
где гибкая и расширяемая архитектура?
ничего не понятно
переделывай
Ясно.
>Также, робот жалуется:
>И еще ему не нравится что у тебя в файлах бутстрапа стоит 2012 год вместо 2013. Ты какую-то неофициальную сборку качал? Откуда она?
Отсюда http://bootstrap-ru.com/
Поработал над замечаниями на досуге.
https://github.com/tokotun/uppy
Потому что скобки обозначают вызов функции. Если ты пишешь
var x= fn(y);
Это читается так:
— вызвать функцию fn c аргументом y
— сохранить то, что она вернет в x
А тебе надо это:
var x = fn;
// скопировать ссылку (так как функция это объект а объекты копируются по ссылке, а не клонируются) на функцию в переменную x
Почувствуй разницу.
Ну и пока ты изучаешь события ты конечно можеь использовать onclick, но переучиайся на более удоюный способ добавления через addEventListener. На learn.javascript.ru тема события подробно описана, прочти там ее целиком если не читал.
> someElement.onclick = hello.sayHello;
Это копирует ссылку на функцию в onlick. Но тут есть подвох.
Когда ты вызваешь hello.sayHello() то функции в качестве this передается hello. А вот когда вызывается
someElement.onclick() то вызывается та же функция но ей передается someElement в качестве this и все ломается.
решений 2:
1) использовать замыкание:
onclick= function () { .... }
2) использовать Function.bind которая создает новую функцию с привязанным bind
Подробнее:
https://learn.javascript.ru/bind
https://learn.javascript.ru/object-methods
https://learn.javascript.ru/objects-more
Заметь что bind появился только в ES5 и его нет в старых браузерах включая IE8-
Ошибки у тебя из-за того, что ты не изучил сам язык яваскрипт, а берешься за DOM и события. Отсюда и проблемы. И если ты не изучишь сам JS то они будут и дальше, в этом языке много подвохов. Не надо проскакивать темы.
Ну и я бы советовал порешать наши задачки из первого поста :)
> someElement.onclick = hello.sayHello;
Это копирует ссылку на функцию в onlick. Но тут есть подвох.
Когда ты вызваешь hello.sayHello() то функции в качестве this передается hello. А вот когда вызывается
someElement.onclick() то вызывается та же функция но ей передается someElement в качестве this и все ломается.
решений 2:
1) использовать замыкание:
onclick= function () { .... }
2) использовать Function.bind которая создает новую функцию с привязанным bind
Подробнее:
https://learn.javascript.ru/bind
https://learn.javascript.ru/object-methods
https://learn.javascript.ru/objects-more
Заметь что bind появился только в ES5 и его нет в старых браузерах включая IE8-
Ошибки у тебя из-за того, что ты не изучил сам язык яваскрипт, а берешься за DOM и события. Отсюда и проблемы. И если ты не изучишь сам JS то они будут и дальше, в этом языке много подвохов. Не надо проскакивать темы.
Ну и я бы советовал порешать наши задачки из первого поста :)
Хоть сколько, но больше 4-5 аргументов использовать не надо так как человек не может их удержать в голове и запутается.
Если надо больше то передавай массивом или (позже, когда пройдешь эту тему) объектом.
Сумму 7777 надо добавлять к сумме долга, чтобы на нее тоже начислялись проценты, а то у тебя слишком мало анон заплатил.
> и смотришь попутно подтягивая скилл восприятия инглиша на слух.
Это дело вкуса. Я не люблю видео, так как читать удобнее и быстрее, алсо есть в наушниках неудобно, а есть и читать удобно.
> Не иметь адблока в 2015.
Принципиально не ставлю расширения из-за того что это небезопасно и никакой системы защиты от зловредов там нет.
>>464549
Там лучше написать так:
цифра скобки-тире-пробелы цифра скобки-тире-пробелы ...
«склейки» нет, но можно обработать строку перед проверкой ее регуляркой. Но в этой задаче это не требуется.
Задачу про номера телефонов надо проверить на большом числе телефонов, чтобы убедиться что твой код правильный. Но руками подставлять номера — долго и скучно. Пусть работает робот, а не человек!
Для этого давай добавим в программу тесты, чтобы сразу было видно, верно все работает или нет. Сделай 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' // нет +
);
Хоть сколько, но больше 4-5 аргументов использовать не надо так как человек не может их удержать в голове и запутается.
Если надо больше то передавай массивом или (позже, когда пройдешь эту тему) объектом.
Сумму 7777 надо добавлять к сумме долга, чтобы на нее тоже начислялись проценты, а то у тебя слишком мало анон заплатил.
> и смотришь попутно подтягивая скилл восприятия инглиша на слух.
Это дело вкуса. Я не люблю видео, так как читать удобнее и быстрее, алсо есть в наушниках неудобно, а есть и читать удобно.
> Не иметь адблока в 2015.
Принципиально не ставлю расширения из-за того что это небезопасно и никакой системы защиты от зловредов там нет.
>>464549
Там лучше написать так:
цифра скобки-тире-пробелы цифра скобки-тире-пробелы ...
«склейки» нет, но можно обработать строку перед проверкой ее регуляркой. Но в этой задаче это не требуется.
Задачу про номера телефонов надо проверить на большом числе телефонов, чтобы убедиться что твой код правильный. Но руками подставлять номера — долго и скучно. Пусть работает робот, а не человек!
Для этого давай добавим в программу тесты, чтобы сразу было видно, верно все работает или нет. Сделай 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' // нет +
);
> Можно ли как то проверять если вначале после 8 стоит скобочка, то и закрываться тоже должно скобочкой?
Регулярные выражения могут делать такие вещи, но это сложно и регулярка получается довольно запутанной. Вот статья если интересно: http://habrahabr.ru/post/171667/
Потому советую не заморачиваться, либо сделать проверку отдельно, например циклом пройтись и посчитать число и порядок скобок.
>>464562
Эта регулярка не пройдет все тесты (смотри мой список номеров) так как там есть номера где больше 3 цифр в скобках.
>>464564
Ок, все верно
>>464576
Явскрипт. Но это не всегда удобно. ЧТо если пользователь выбрал не тот пункт и хотел исправить? Страница перезагрузится и вырвет селект у него из рук.
> но не настолько что бы самому сверстать сайт и даже не знаю всех тегов и css стилей.
Тогда изучи HTML/CSS. В первом посте треда есть хорошие задания, которые помогут тебе в них разобраться на нужном уровне (ты сможешь не то что сайт сверстать, ты сможешь читать исходники бутстрапа).
> И прописывать для своих элементов соответствующие классы и можно не заморачиваться с написанием css?
так ничего не выйдет. Как только понадобится что-то поменять ты начнешь лепить быдлокод из поставленных наугад свойств. Изучай HTML/CSS.
>>464606
> То есть в процедурном виде конечно могу накидать бессвязных функций, но хотелось бы таки в иерархическом ООП-стиле.
Я бы советовал не гнаться за сложными абстракциями, а сделать по-простому. Не набор бессвязных функций, а например что-то вроде этого:
var v = new Validator;
v.addRule('name', 'maxlength', 50);
....
var values = getFormValues(...);
var errors = v.validate(values);
Заметь как я отвязал логику проверки значений (Validator) от работы с DOM (getFormValues) и отображения ошибок.
Обычно такие вещи на массивах и делаются:
$this->render('some.phtml', [
'x' => 1,
'y' => 2
]);
Такой код ты можешь увидеть в куче фреймворков.
А теперь давай разберем твой класс «DataManager». Название ни о чем не говорит: «управление данными» так как любой класс управляет какими-то данными. С таким же успехом ты мог назвать класс Aasdasd
Такие классы обычно называются ViewModel, то есть модель представления (класс, хранящий информацию о выводимых на странице элементах). И соответственно под каждый шаблон мы пишем свой класс:
StudentListViewModel
StudentEditFormViewModel
классы нужны разные так как на разных страницах отображаются разные элементы.
ViewModel обычно используется в связке с data binding (если дойдешь до библиотек knockout, angular в яваскрипте, узнаешь что это такое. Если кратко data binding это когда мы привязываем часть страницы к классу-модели и при изменении значений в модели страница сама обновляет выводимые данные).
Обычно архитектуру с использованием ViewModel называют MVVM: Model View ViewModel: https://en.wikipedia.org/wiki/Model_View_ViewModel
Заметь что такая архитектура не используется на сервере, а используется на клиентских приложениях на JS или в десктопных приложениях. На сервере твой скрипт умирает после обработки запроса и делать дата байндинг нет смысла.
В твоем случае использовать ViewModel особо смысла нет, так как этот класс по сути будет массивом с ограничением на число и тип полей. Так как data binding на сервере не реализовать, то и ViewModel писать незачем. Проще передавать обычный массив.
Обычно такие вещи на массивах и делаются:
$this->render('some.phtml', [
'x' => 1,
'y' => 2
]);
Такой код ты можешь увидеть в куче фреймворков.
А теперь давай разберем твой класс «DataManager». Название ни о чем не говорит: «управление данными» так как любой класс управляет какими-то данными. С таким же успехом ты мог назвать класс Aasdasd
Такие классы обычно называются ViewModel, то есть модель представления (класс, хранящий информацию о выводимых на странице элементах). И соответственно под каждый шаблон мы пишем свой класс:
StudentListViewModel
StudentEditFormViewModel
классы нужны разные так как на разных страницах отображаются разные элементы.
ViewModel обычно используется в связке с data binding (если дойдешь до библиотек knockout, angular в яваскрипте, узнаешь что это такое. Если кратко data binding это когда мы привязываем часть страницы к классу-модели и при изменении значений в модели страница сама обновляет выводимые данные).
Обычно архитектуру с использованием ViewModel называют MVVM: Model View ViewModel: https://en.wikipedia.org/wiki/Model_View_ViewModel
Заметь что такая архитектура не используется на сервере, а используется на клиентских приложениях на JS или в десктопных приложениях. На сервере твой скрипт умирает после обработки запроса и делать дата байндинг нет смысла.
В твоем случае использовать ViewModel особо смысла нет, так как этот класс по сути будет массивом с ограничением на число и тип полей. Так как data binding на сервере не реализовать, то и ViewModel писать незачем. Проще передавать обычный массив.
То есть давай я все же попробую объяснить что такое data binding. Я вижу, ты сообразительный и тебе это может пригодиться.
Итак, как ты наверно слышал, яваскрипт это язык, программы на котором можно встраивать в веб-страницы и они выполняются в браузере. Он позволяет делать как простые вещи вроде проверки правильности заполнения формы без перезагрузки страницы, так и писать приложения вроде Google Maps, Google Docs, редакторы рисунков и схем, и т.д.
Обычно яваскрипт-приложению надо как читать данные из страницы (например прочитать введенный пользователем в поле ввода текст), так и менять содержимое страницы (выводить какие-то данные).
По умолчанию для этого используется библиотека вроде jQuery. Вот код, читаюший текст из поля ввода:
var text = $('input['name="x"]').val( );
Вот код, меняющий текст в определенном месте старницы:
var text = 'У вас ' + points + ' очков';
$('.some-selector').text(text);
Тут напрямую прописаны имена и классы HTML элементов на странице. И получается что это смешивает вместе HTML и логику работы нашего приложения, что плохо. Это то же самое что смешать php и вывод HTML через echo.
дата байндинг позволяет создать связь между данными на странице и обычным объектом (ViewModel). Когда пользователь вводит текст, в модели меняется значение поля. Когда мы меняем значение поля в модели, на странице меняется текст.
Это упрощает код, так как теперь мы работаем с моделью и нам не приходится смешивать вместе логику приложения и логику работы с HTML кодом на странице (заметь, та же проблема что мы решаем в php вынесением HTML в шаблон). Логика нашего приложения теперь не трогает саму страницу, она меняет только значения в ViewModel.
Выглядит это примерно так. прочитать введенный текст:
var text = viewModel.getText( );
поменять число очков:
viewModel.setPoints(500);
Благодаря этому код становится чище, а также мы можем например тестировать логику вне браузера, без взаимодейтсвия с HTML.
Советую тебе изучить data binding когда дойдешь до этой темы.
То есть давай я все же попробую объяснить что такое data binding. Я вижу, ты сообразительный и тебе это может пригодиться.
Итак, как ты наверно слышал, яваскрипт это язык, программы на котором можно встраивать в веб-страницы и они выполняются в браузере. Он позволяет делать как простые вещи вроде проверки правильности заполнения формы без перезагрузки страницы, так и писать приложения вроде Google Maps, Google Docs, редакторы рисунков и схем, и т.д.
Обычно яваскрипт-приложению надо как читать данные из страницы (например прочитать введенный пользователем в поле ввода текст), так и менять содержимое страницы (выводить какие-то данные).
По умолчанию для этого используется библиотека вроде jQuery. Вот код, читаюший текст из поля ввода:
var text = $('input['name="x"]').val( );
Вот код, меняющий текст в определенном месте старницы:
var text = 'У вас ' + points + ' очков';
$('.some-selector').text(text);
Тут напрямую прописаны имена и классы HTML элементов на странице. И получается что это смешивает вместе HTML и логику работы нашего приложения, что плохо. Это то же самое что смешать php и вывод HTML через echo.
дата байндинг позволяет создать связь между данными на странице и обычным объектом (ViewModel). Когда пользователь вводит текст, в модели меняется значение поля. Когда мы меняем значение поля в модели, на странице меняется текст.
Это упрощает код, так как теперь мы работаем с моделью и нам не приходится смешивать вместе логику приложения и логику работы с HTML кодом на странице (заметь, та же проблема что мы решаем в php вынесением HTML в шаблон). Логика нашего приложения теперь не трогает саму страницу, она меняет только значения в ViewModel.
Выглядит это примерно так. прочитать введенный текст:
var text = viewModel.getText( );
поменять число очков:
viewModel.setPoints(500);
Благодаря этому код становится чище, а также мы можем например тестировать логику вне браузера, без взаимодейтсвия с HTML.
Советую тебе изучить data binding когда дойдешь до этой темы.
А почему у тебя 4 таблицы, а не одна?
Вообще, есть 3 стандартных паттерна для реализаии наследования в БД:
http://design-pattern.ru/patterns/single-table-inheritance.html
http://design-pattern.ru/patterns/class-table-inheritance.html
http://design-pattern.ru/patterns/concrete-table-inheritance.html
Может тебе какой-то подойдет.
>>464729
Уходи
>>464726
> $paymentTotal = ($paymentTotal + $monthlyPayment);
> $creditBalance = ($creditBalance - $monthlyPayment);
эти строчки скопированы 2 раза. Попробуй избавиться от повторов.
Также,
$a = $a + $b;
можно записать как
$a += $b;
А почему у тебя 4 таблицы, а не одна?
Вообще, есть 3 стандартных паттерна для реализаии наследования в БД:
http://design-pattern.ru/patterns/single-table-inheritance.html
http://design-pattern.ru/patterns/class-table-inheritance.html
http://design-pattern.ru/patterns/concrete-table-inheritance.html
Может тебе какой-то подойдет.
>>464729
Уходи
>>464726
> $paymentTotal = ($paymentTotal + $monthlyPayment);
> $creditBalance = ($creditBalance - $monthlyPayment);
эти строчки скопированы 2 раза. Попробуй избавиться от повторов.
Также,
$a = $a + $b;
можно записать как
$a += $b;
Это конечно странная сборка, так как номер версии там такой же как на англйиском сайте, а год другой (а больше различий нет). Я сейчас переделал робота, чтобы можно было добавлять несколько версий с одинаковым номером, но не знаю, лучше наверно качать с официального сайта
>>464775
3-я ветка не совместима со второй из-ха того что там сделали box-sizing: border-box по умолчанию. Потому многие до сих пор сидят на второй, и там последняя версия 2.3.2: http://getbootstrap.com/2.3.2/
Мне не нравится это решение, но аноны разумеется могут исопльзовать ту версию которая им нравится, хоть вторую, хоть третью.
А качать, конечно, стоит с официального сайта. Было бы вообще здорово использовать какой-нибудь bower, но ведь он тянет ноду и требует возни с системой сборки, которая начинающих только запутает (да и если честно что grunt что gulp мне одинаково неприятны. bash- и make- скрипты которые я писал в свое время на мой взгляд в несколько раз читабельнее).
> FOREIGN KEY (`file_id`) REFERENCES `files` (`id`)
>\tON DELETE RESTRICT
Такие вещи стоит комментировать в SQL файле. Я сейчас например смотрю и не понимаю, зачем это сделано? Нельзя удалять файл если у него есть комментарии? А если в этом файле что-то запрещенное и нам надо его удалить все равно?
Также, в MySQL ты можешь добавлять комментарии к колонкам и таблицам конструкцией COMMENT: http://stackoverflow.com/questions/2162420/alter-mysql-table-to-add-comments-on-columns
Эти комментарии сохраняются в БД и отображаются программами для работы с БД.
Для полей ID3, path я думаю комментарий бы не помешал.
> CREATE TABLE `file_info` (
> `id` int(11) NOT NULL AUTO_INCREMENT,
> `file_id` int(11) NOT NULL,
Если эта таблица связана связью 1:1 с файлами, то поле id не нужно. Первичным ключом будет file_id так как он уникально идетифицирует запись.
У тебя же отношение 1:M так как мы можем вставить несколько записей с ID3 ссылающихся на один файл.
Если ты не изучил, выучи наизусть виды отношений в таблицах: 1:1, 1:M, M:N и как они реализуются. Вот тут есть описание: http://jtest.ru/bazyi-dannyix/sql-dlya-nachinayushhix-chast-3.html (упс, отшошение 1:1 там реализовано как раз неудачно, лучше бы в address добавить колонку customer_id и сделать ее первичным и внешним ключом).
Конфиг надо вынести в отдельный файл config.php
Зачем делают отдельный файл? Для того, чтобы не надо было редактировать код. У тебя же чтобы поменять пароль к базе надо лезть и менять код. Нехорошо.
Например, если ты работаешь в команде и кто-то меняет у себя пароль к базе в index.php то эти изменения пойдут в репозиторий и передадутся всем остальным. А когда у нас отдельный конфиг, мы можем внести его в gitignore и менять как нам хочется.
Соответственно комментарии что какая переменная делает, тоже лучше перенести в конфиг.
А, и еще вопрос. А почему ты медиаинформацию вынес в отдельную таблицу, а не добавил колонку в files? На мой взгляд это усложнение и у должна быть причина делать именно так.
>>464815
Ой, у тебя есть config.php, я не заметил.
> $app->render('notFoundFile.html.twig', array() );
Вот это лучше реализовать по другому. Твой код отдает страницу с кодом HTTP200, что непраивльно. Если файл не найден, код должен быть 404. Прочитай про HTTP коды и выучи хотя бы эти: 200, 301, 401, 403, 404, 500, 503: https://ru.wikipedia.org/wiki/%D0%A1%D0%BF%D0%B8%D1%81%D0%BE%D0%BA_%D0%BA%D0%BE%D0%B4%D0%BE%D0%B2_%D1%81%D0%BE%D1%81%D1%82%D0%BE%D1%8F%D0%BD%D0%B8%D1%8F_HTTP
В Слиме есть обработчик страницы 404, и ты можешь его переопределить. Соответственно при отстутствии файла ты должен вызывать его, а также ты должен переопределить этот обработчик чтобы выводить свой шаблон, а не слимовский. Тогда твой шаблон будет выводиться и при вводе неправильного адреса вроде /asdasdasdasd/sdadasd
Мануал: http://docs.slimframework.com/errors/404/
Заметь что можно установить свой шаблон и для страницы 500 (ошибка или исключение в твоем приложении).
Еще,
> $app->get('/upload'
> $app->get('/main',
> $app->get('/:key'
А есть какая-то гарантия что key не может быть 'main', 'upload' и тд? Может для файла лучше сделать URL вроде /f/:key?
Нужно обрабатывать каждую значение, или как? Как-то очень запутано получается.
https://ideone.com/CXIh6z
Открыл сайт из ОП-поста, тоже не фонтан. Инфа подана очень скомкано и не последовательно.
Так вот, есть где годные уроки, в которых все рассказывается максимально доступно, наглядно и с примерами? Желательно конечно в видеоформате, но и в текстовом тоже сойдет.
Подробно и последовательно, очевидно же. Вот например сразу же во втором уроке упоминаются функции, при этом не рассказывается их принцип работы и нахуй они вообще нужны. Просто говорится, мол ну вот есть функции и они делают то-то.
ОП конечно молодец, что много усилий приложил ради анончиков, но мне бы хотелось более глубокого понимания, а не просто поверхностного знакомства.
> Вот например сразу же во втором уроке упоминаются функции, при этом не рассказывается их принцип работы и нахуй они вообще нужны.
Эм, как ты так читал? Смотри пикрелейтед.
Это слишком кратко и не передает всей сути. Я вижу, что там еще есть более подробный урок, но зачем тогда упоминать их так рано, не раскрывая полностью, да еще и задачку давать с их использованием? Это и есть непоследовательность, которая препятствует грамотному усваиванию информации.
В общем я не критиковать чужие труды сюда пришел, а за тем, чтобы мне посоветовали подробный курс уроков.
У тебя какие-то глупые претензии. В том куске текста все, что тебе нужно знать о предназначении функций. Никто еще не жаловался, после прохождения этого учебника.
Нет, ведь ты его еще не прошел.
>классы нужны разные так как на разных страницах отображаются разные элементы.
Вот это мне и не понравилось, заводить одинаковые классы с чуть разными названиями под каждую страницу. Поэтому возникла идея сделать один класс, по аналогии с такой манерой именования - AnythingViewModel (конечно не так, это просто для понимания). Чтоб у него был метод, допустим, getData(), возвращающий ну как бы самой основную информацию - студентов, статьи, что угодно. И несколько вспомогательных свойств и их гетеров. Из тех что уже нужны:
errors() - массив ошибок, в формате 'поле' => 'сообщение', например ['password'=>"пароль должен содержать от 6 до 40 символов. Вы ввели $х"]
message() - сообщение типа "Привет, $username", 'Статья успешно отредактирована'. По идее хватит строки
inputs() - массив сохраненных значений полей если форма не прошла валидацию
Пока не могу представить что еще потребуется хранить, но мало ли.
В принципе да,
>этот класс по сути будет массивом с ограничением на число и тип полей
так и получается.
Но если так норм
$this->view->generate('articles.html' , [
'errors' => $model ->getErrors(),
'inputs' => $model ->getInputs()
])
то оставлю как есть
Что касается data binding, ну пока не вижу где можно применить у себя, на заметку возьму. JS на хиленьком уровне знаю. А кстати, почему нельзя реализовать на сервере, через ajax например? Потому что модель умерла вместе со скриптом?
Ну курсы от "специалиста" глянь. Только там море воды, около 50 часов лекций, практических примеров мало и они не наглядные, зато неплохо объясняет теорию.
>я бы советовал порешать наши задачки из первого поста
Если честно не совсем понимаю смысл этого обучении. Если человек знает, как решить эти задачи, он их решит.
Если не знает, то и не решит.
Хотя возможно в некоторых случаях по мере решения заданий могут возникнуть вопросы по поведению программы, тогда это не совсем бесполезно.
Например, в первой задаче https://gist.github.com/codedokode/ce30e7a036f18f416ae0#%D0%97%D0%B0%D0%B4%D0%B0%D1%87%D0%BA%D0%B8-%D0%BD%D0%B0-js
решение конечно очевидно, но что именно происходит, не очень понятно.
https://gist.github.com/anonymous/b6b4a52537bcce923d76
Каким образом локальные переменные сохраняются в функции после ее отработки?
Догадываюсь, что так как функция вроде бы объект, то все ее переменные падают в соответствующие поля этого объекта. Или объекта-родителя, через который произошло замыкание.
В объект validator = sequence(10, 3); приходит объект, у которого есть переменные step и start, которые были объявлены в родителе (объекте sequence).
Таким образом получается, что в отличие от других языков локальные переменные функции не уничтожаются после ее отработки, а сохраняются в поля объекта, я правильно понимаю?
Тогда как их посмотреть? Как узнать текущие значения его свойств? Если я обращусь как window.sequence.step, выдаст undefined. Может есть какая служебная конструкция вроде var_dump в пхп?
> 2. Также, нужна функция take(gen, x) которая вызвает функцию gen заданное число (x) раз и возвращает массив с результатами вызовов. Она нам пригодится для отладки.
https://gist.github.com/anonymous/ec23bc759a6b7ef89dab
> Напиши функцию map(fn, array), которая принимает на вход функцию и массив, и обрабатывает каждый элемент массива этой функцией, возвращая новый массив.
https://gist.github.com/anonymous/972af96587af7f78e27c
>>465000
Нет, в случае с функциями это не канает, выведет декларацию функции, а это нам не уперлось:
var foo = function(x){alert(x)};
console.log(foo); // выведет function(x){alert(x)}, а мне нужно знать именно локальные переменные; я ожидаю увидеть что-то типа:
Object {name: "", arguments: 1, length: 1, step: 3, start: 10, ... и так далее, где-то я такое видел, где не понмю}
>4. Напиши функцию fmap(a, gen)
https://gist.github.com/anonymous/04d06e58b44b6dbeec17
Пойду перекушу, а то весь тред завайпал этой фигней.
А в чем суть проблем с производительностью собственно то? 1 таблица же лучше чем две.
Анон, я говнокодер на делфи. Завтра нужно сдавать курсач с тупым заданием, но я нихуя не могу придумать.
Суть. Нужно преобразовать IP - адрес в число и на основе этого числа должна выдаваться инфа по этому ип адресу.
http://www.codeguru.com.ua/article/a-222.html
Нашел вот это. Что можно придумать до утра? Может быть на пхп попробовать что-нибудь написать?
Используй разные шаблоны представления для каждой категории.
При нажатии на объявление у тебя должен формироваться урл с соответствующими параметрами, например govnosayt.ru/index.php?cat=2&id=891.
Затем роутер должен разобрать этот урл, вызвать соответствующий контроллер/экшн, который и отрендерит правильный шаблон.
Короче, за пять минут это не объяснишь.
Читай про mvc, учи фреймворки.
А пока повесь какие-нибудь сопли типа
switch( $_GET['cat'] ) { case 1: include_once "category2.php"; break; case 2: include_once "category2.php"; break; .......}
Где в categoryN.php шаблоны содержимого объявления.
Он состоит из тех же элементов, что есть и в других языка - переменные, методы, функции.
Что в нем такого легкого?
>Нужно преобразовать IP - адрес в число
По какому принципу должно быть преобразование?
>и на основе этого числа должна выдаваться инфа по этому ип адресу.
Опять же по какому принципу она выделяется и какая инфа?
Я бы хотел тебе помочь, но ты даже задание сформулировал через жопу.
Не, у тебя слишком сложная регулярка. Ты просто наделал шаблонов под номера. Такую регулярку тяжело читать и трудно в ней разобраться.
Надо сделать проще, регулярку примерно такого вида:
в начале +7 или 8, за ней 10 цифр между которыми могут быть скобки, минусы, пробелы.
>>464851
Если ты хочешь максимально подробное описание, почему не открыть официальный мануал? Более подробный и точный источник трудно найти.
Учебник у меня не подробный, так как он фокусируется на самых важных вещах и рассчитан на начинающих, кто ничего не знает. Ну например я не буду там описывать битовые операции, так как они почти никогда не используются, а прежде чем с ними разбираться, надо выучить двоичную систему счисления.
> Инфа подана очень скомкано и не последовательно.
Да, есть проблемы. Но я пытался за минимальный объем времени дать как можно больше информации.
>>464854
Это да, нет подробностей. Но ведь это всего второй урок, читатель только-только научился команде echo, не запомнил еще толком что такое переменная, и подробно рассказывать про функции, аргументы еще пока рано. Пока достаточно сказать ему что $a = floor($b) это такая штука, которая округляет число в меньшую сторону.
> но мне бы хотелось более глубокого понимания
Тогда тебе нужен мануал + изучение библиотек, фрейморков. У нас кстати есть задания в первом посте треда, про студентов, файлообменник, ты их не смотрел? Как это тебе, слишком просто или слишком сложно пока?
>>464861
Это не второй урок, это позже идет.
>>464867
> но зачем тогда упоминать их так рано,
Потому что они нужны уже во втором уроке.
> Это и есть непоследовательность, которая препятствует грамотному усваиванию информации.
Ну тут я не совсем согласен. Начинающему не обязательно учиться сразу создавать свои функции, для начала вполне хватит умения пользоваться готовыми.
>>464868
Не, тот анон высказал правильные мысли. Может быть, действительно, стоило добавить абзац про функции в общих чертах. Тем более, он уже знаком с php и воспринимает учебник по другому.
Не, у тебя слишком сложная регулярка. Ты просто наделал шаблонов под номера. Такую регулярку тяжело читать и трудно в ней разобраться.
Надо сделать проще, регулярку примерно такого вида:
в начале +7 или 8, за ней 10 цифр между которыми могут быть скобки, минусы, пробелы.
>>464851
Если ты хочешь максимально подробное описание, почему не открыть официальный мануал? Более подробный и точный источник трудно найти.
Учебник у меня не подробный, так как он фокусируется на самых важных вещах и рассчитан на начинающих, кто ничего не знает. Ну например я не буду там описывать битовые операции, так как они почти никогда не используются, а прежде чем с ними разбираться, надо выучить двоичную систему счисления.
> Инфа подана очень скомкано и не последовательно.
Да, есть проблемы. Но я пытался за минимальный объем времени дать как можно больше информации.
>>464854
Это да, нет подробностей. Но ведь это всего второй урок, читатель только-только научился команде echo, не запомнил еще толком что такое переменная, и подробно рассказывать про функции, аргументы еще пока рано. Пока достаточно сказать ему что $a = floor($b) это такая штука, которая округляет число в меньшую сторону.
> но мне бы хотелось более глубокого понимания
Тогда тебе нужен мануал + изучение библиотек, фрейморков. У нас кстати есть задания в первом посте треда, про студентов, файлообменник, ты их не смотрел? Как это тебе, слишком просто или слишком сложно пока?
>>464861
Это не второй урок, это позже идет.
>>464867
> но зачем тогда упоминать их так рано,
Потому что они нужны уже во втором уроке.
> Это и есть непоследовательность, которая препятствует грамотному усваиванию информации.
Ну тут я не совсем согласен. Начинающему не обязательно учиться сразу создавать свои функции, для начала вполне хватит умения пользоваться готовыми.
>>464868
Не, тот анон высказал правильные мысли. Может быть, действительно, стоило добавить абзац про функции в общих чертах. Тем более, он уже знаком с php и воспринимает учебник по другому.
> . Поэтому возникла идея сделать один класс, по аналогии с такой манерой именования - AnythingViewModel (конечно не так, это просто для понимания). Чтоб у него был метод, допустим, getData(),
Тогда это какая-то извращенная форма массива. Если класс принимает любые данные, зачем он нужен? Передавай сразу массив тогда.
> Из тех что уже нужны:
> errors
> message
> inputs
Не, тут ты просто создаешь себе рамки. Ну например errors не обязано быть массивом, это может быть объект ErrorList, inputs не обязано быть массивом, часто удобнее передать объект Student, сообщение не обязано быть ровно одно, и т.д. Я не понимаю, какая польза от этого класса если мы сразу можем передать нужные переменные массивом.
> Но если так норм
> $this->view->generate('articles.html' , [
Да, так все и делают.
> Что касается data binding, ну пока не вижу где можно применить у себя,
Он на клиенте (в браузере) применяется, JS будешь изучать может быть дойдешь до этой темы.
> А кстати, почему нельзя реализовать на сервере, через ajax например?
Не имеет смысла, так как аякс запрос будет обрабатывать другой экземпляр скрипта, не тот что создал страницу.
> Потому что модель умерла вместе со скриптом?
Да. Data binding нужен когда мы хотим изменить кусочек существующей страницы. А на сервере мы всегда генерируем ее с нуля целиком. А если поменять концепцию (держать в памяти сервера модель страницы для каждого посетителя и вносить в нее изменения) то это не соответсвует REST и мы получаем кучу проблем: начиная с не-масштабируемости на несколько серверов, и заканчивая тем что память будет расходоваться только так.
ты про эти? http://geekbrains.ru/professions/1
> Так может выглядеть Ваше резюме после прохождения обучения и стажировки
> Желаемая зарплата 70 000 руб.
Я сильно сомневаюсь, что кто-то захочет платить джуниору с 0 опыта такие деньги, даже в Москве, даже с учетом курса рубля. Это напоминает недобросовествную рекламу, с расчетом на то что покупатель курсов не разбирается в особенностях рынка труда и вообще плохо представляет что такое программирование. Ну и 4 часа в день работать джуниор тоже вряд ли будет.
Также, там не изучаются сторонние фреймворки и библиотеки, что по моему минус.
> Вашим куратором и наставником от Geekbrains будет Игорь Долгов - замечательный программист, великолепный преподаватель и консультант по личной эффективности, владеющий техниками НЛП,
ой-ой. Обещания завышенной зарплаты после месяца обучения видимо часть НЛП?
Ну и в курсе по яваскрипту, на сам Js/DOM отведено только 1 занятие.
По моим ощущениям там изучают только основы. С другой стороны, некоторым платные курсы лучше даются и лучше мотивируют.
Меня интересует больше эффективность данных курсов, а не цена. Тем более что они уже лежат на трекерах совершенно бесплатно.
Ну и там форум есть, изучи его например. Может там что-то еще интересное выяснится.
Ну и обрати внимание что сам сайт как-то связан с proglive, то ли лендинг, то ли партнерка.
>>464895
Вроде верно
>>464996
> Если честно не совсем понимаю смысл этого обучении. Если человек знает, как решить эти задачи, он их решит. Если не знает, то и не решит.
Если он не знает, то он почитает советы и ссылки и что-то новое выучит. Если у него есть пробелы в знаниях, то он их увидит. Там задачи подобраны чтобы сконцентрироваться на разных особенностях JS вроде замыканий, прототипов и прочего, которые надо знать чтобы полноценно писать код на этом языке.
А по твоей логике, никакие задачи вообще не нужны.
Ну вот ты пишешь, что задачи не нужны, а выясняется что на первой задаче у тебя есть вопросы. Разве это не значит, что тебе они были бы полезны?
> решение конечно очевидно, но что именно происходит, не очень понятно
А как ты его написал, если тебе непонятно?
> Каким образом локальные переменные сохраняются в функции после ее отработки?
В JS все функции это замыкания, то есть они при создании привязывают к себе ссылки на переменные из окружающих областей видимости. Вот в предисловии к задачам (которое ты видимо пропустил, а зря) это упомянуто: https://gist.github.com/codedokode/ce30e7a036f18f416ae0#%D0%A4%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8-%D0%B8-%D0%B7%D0%B0%D0%BC%D1%8B%D0%BA%D0%B0%D0%BD%D0%B8%D1%8F
Там даже пример есть и написано какая функция какие переменные видит.
> что так как функция вроде бы объект, то все ее переменные падают в соответствующие поля этого объекта.
Нет. Поля это поля, переменные это переменные. Просто функция в момент создания запоминает ссылки на окружающие ее переменные. И даже если ты эту функцию вызываешь в другом месте, ссылки сохраняются.
https://learn.javascript.ru/closures
Ты можешь проверить что переменные не сохранены в полях объекта, выведя например такие значения:
generator.start // undefined
'start' in generator // false
Заметь, что неважно в каком месте мы вызываем функцию. Важно, в каком месте она создана так как именно в этот момент она сохраняет ссылки на переменные.
В твоем примере ты создаешь внутреннюю функцию и она сохраняет связь с переменными start и step. Обычно при выходе из функции локальные переменные (start и step) уничтожаются, но в нашем случае внутренняя функция удерживает внутри ссылки на них и переменные не удаляются сборщиком мусора.
Если тебе интересны подробности реализации, то в JS замыкания сделаны не так, как в PHP. В PHP замыкание на самом деле является объектом класса Closure и хранит переданные ему через use переменные и ссылки в скрытых полях. Но в JS реализация другая. Когда ты заходишь в функцию, создается специальный временный объект, LexicalEnvironment, в котором хранятся локальные переменные этой функции. Когда ты в этой функции создаешь замыкание, оно запоминает ссылку на LE и может в нем искать переменные.
Если функции вложены внутрь друг друга, то внутренняя функция хранит в своем LE ссылку на LE родительской, родительская на LE своего родителя, и так получается цепочка ссылок. Благодаря цепочке переменная ищется сначала в текущем LE, затем в родительском, затем в родителе родителя и так далее.
Эти объекты (и переменные в них) удалятся когда ссылок на них не останется, то есть когда ты выйдешь из функции и когда будут уничтожены все созданные внутри нее замыкания.
Это наверно довольно сложная концепция. Мне кажется, замыкания проще понять глянув на пример кода по ссылке выше, где написано какая функция какие переменные видит.
> Таким образом получается, что в отличие от других языков локальные переменные функции не уничтожаются после ее отработки, а сохраняются в поля объекта, я правильно понимаю?
В JS любые объекты удаляются только когда на них не остается ни одной ссылки. В данном случае замыкание generator удерживает ссылки на step и start (точнее на LE в котором они находятся). Если ты удалишь функцию например написав
generator = null;
то ссылки исчезнут и переменные (и сама функция) будет позже удалены сборщиком мусора.
Ну вот пример:
var a= {}; // ссылка на объект хранится в a
var b= a; // ссылка на объект хранится в a и b
var c = function () { return b; }; // функция c содержит ссылку на переменную b но это не поможет объекту выжить
a = null; // ссылка на объект осталась только в b
b = null; // ссылок на объект не осталось, он стал недоступен из программы и будет позже удален сборщиком мусора
> Тогда как их посмотреть? Как узнать текущие значения его свойств?
Лучше всего инспектором (Ctrl + Shift + i). Им ты можешь остановить программу в любом месте и просмотреть любые переменные. Пользоваться инспектором обязательные навык для JS-программиста. Прочитай: http://habrahabr.ru/post/143767/
Там же есть удобная консоль в которой можно выполнять короткие кусочки кода. Попробуй, понравится.
> Может есть какая служебная конструкция вроде var_dump в пхп?
Есть console.log(var) но я советую использовать отладчик в инспекторе, он мощнее и удобнее.
Ну и там форум есть, изучи его например. Может там что-то еще интересное выяснится.
Ну и обрати внимание что сам сайт как-то связан с proglive, то ли лендинг, то ли партнерка.
>>464895
Вроде верно
>>464996
> Если честно не совсем понимаю смысл этого обучении. Если человек знает, как решить эти задачи, он их решит. Если не знает, то и не решит.
Если он не знает, то он почитает советы и ссылки и что-то новое выучит. Если у него есть пробелы в знаниях, то он их увидит. Там задачи подобраны чтобы сконцентрироваться на разных особенностях JS вроде замыканий, прототипов и прочего, которые надо знать чтобы полноценно писать код на этом языке.
А по твоей логике, никакие задачи вообще не нужны.
Ну вот ты пишешь, что задачи не нужны, а выясняется что на первой задаче у тебя есть вопросы. Разве это не значит, что тебе они были бы полезны?
> решение конечно очевидно, но что именно происходит, не очень понятно
А как ты его написал, если тебе непонятно?
> Каким образом локальные переменные сохраняются в функции после ее отработки?
В JS все функции это замыкания, то есть они при создании привязывают к себе ссылки на переменные из окружающих областей видимости. Вот в предисловии к задачам (которое ты видимо пропустил, а зря) это упомянуто: https://gist.github.com/codedokode/ce30e7a036f18f416ae0#%D0%A4%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B8-%D0%B8-%D0%B7%D0%B0%D0%BC%D1%8B%D0%BA%D0%B0%D0%BD%D0%B8%D1%8F
Там даже пример есть и написано какая функция какие переменные видит.
> что так как функция вроде бы объект, то все ее переменные падают в соответствующие поля этого объекта.
Нет. Поля это поля, переменные это переменные. Просто функция в момент создания запоминает ссылки на окружающие ее переменные. И даже если ты эту функцию вызываешь в другом месте, ссылки сохраняются.
https://learn.javascript.ru/closures
Ты можешь проверить что переменные не сохранены в полях объекта, выведя например такие значения:
generator.start // undefined
'start' in generator // false
Заметь, что неважно в каком месте мы вызываем функцию. Важно, в каком месте она создана так как именно в этот момент она сохраняет ссылки на переменные.
В твоем примере ты создаешь внутреннюю функцию и она сохраняет связь с переменными start и step. Обычно при выходе из функции локальные переменные (start и step) уничтожаются, но в нашем случае внутренняя функция удерживает внутри ссылки на них и переменные не удаляются сборщиком мусора.
Если тебе интересны подробности реализации, то в JS замыкания сделаны не так, как в PHP. В PHP замыкание на самом деле является объектом класса Closure и хранит переданные ему через use переменные и ссылки в скрытых полях. Но в JS реализация другая. Когда ты заходишь в функцию, создается специальный временный объект, LexicalEnvironment, в котором хранятся локальные переменные этой функции. Когда ты в этой функции создаешь замыкание, оно запоминает ссылку на LE и может в нем искать переменные.
Если функции вложены внутрь друг друга, то внутренняя функция хранит в своем LE ссылку на LE родительской, родительская на LE своего родителя, и так получается цепочка ссылок. Благодаря цепочке переменная ищется сначала в текущем LE, затем в родительском, затем в родителе родителя и так далее.
Эти объекты (и переменные в них) удалятся когда ссылок на них не останется, то есть когда ты выйдешь из функции и когда будут уничтожены все созданные внутри нее замыкания.
Это наверно довольно сложная концепция. Мне кажется, замыкания проще понять глянув на пример кода по ссылке выше, где написано какая функция какие переменные видит.
> Таким образом получается, что в отличие от других языков локальные переменные функции не уничтожаются после ее отработки, а сохраняются в поля объекта, я правильно понимаю?
В JS любые объекты удаляются только когда на них не остается ни одной ссылки. В данном случае замыкание generator удерживает ссылки на step и start (точнее на LE в котором они находятся). Если ты удалишь функцию например написав
generator = null;
то ссылки исчезнут и переменные (и сама функция) будет позже удалены сборщиком мусора.
Ну вот пример:
var a= {}; // ссылка на объект хранится в a
var b= a; // ссылка на объект хранится в a и b
var c = function () { return b; }; // функция c содержит ссылку на переменную b но это не поможет объекту выжить
a = null; // ссылка на объект осталась только в b
b = null; // ссылок на объект не осталось, он стал недоступен из программы и будет позже удален сборщиком мусора
> Тогда как их посмотреть? Как узнать текущие значения его свойств?
Лучше всего инспектором (Ctrl + Shift + i). Им ты можешь остановить программу в любом месте и просмотреть любые переменные. Пользоваться инспектором обязательные навык для JS-программиста. Прочитай: http://habrahabr.ru/post/143767/
Там же есть удобная консоль в которой можно выполнять короткие кусочки кода. Попробуй, понравится.
> Может есть какая служебная конструкция вроде var_dump в пхп?
Есть console.log(var) но я советую использовать отладчик в инспекторе, он мощнее и удобнее.
Ага, хорошо, вроде верно. Ты задачи проверяешь нашей автоматической проверялкой http://dkab.github.io/jasmine-tests/ ?
>>465004
Верно
> Нет, в случае с функциями это не канает, выведет декларацию функции, а это нам не уперлось:
Инспектор используй. Там ты можешь остановить программ в любой точке.
>>465010
http://dkab.github.io/jasmine-tests/?spec=4 говорит что у тебя там ошибки:
> Возвращаемая функция
> должна принимать любое количество аргументов и передавать их функции fn
> должна вызывать функцию mixin для результатов фунцкии fn
Сначала убеди робота принять решение (но вообще в роботе иногда бывают ошибки, так что если сомневаешься, пиши, я ему вправлю мозги)
>>465074
> Или валить все в одну таблицу, но тогда много полей, проблемы с производительностью.
Мерял? Если нет то с чего ты взял что будут проблемы? Не страдай ерундой и храни все в одной таблице
>>465096
Для таких вещей придуман паттерн EAV (Entity-Attribute-Value).
> но так как у всех категорий разные параметры я не знаю как мне прописать что выводить, то есть надо писать для каждой категории свои параметры для вывода?
надо где-то хранить соответсвие категория -> возможные опции. Можно в коде прописать, можно в БД, если надо чтобы это менялось из админки.
> я не знаю как мне прописать что выводить, то есть надо писать для каждой категории свои параметры для вывода?
По моему это элементарно. Получаешь массив атрибутов объявления и выводишь все что есть.
Ага, хорошо, вроде верно. Ты задачи проверяешь нашей автоматической проверялкой http://dkab.github.io/jasmine-tests/ ?
>>465004
Верно
> Нет, в случае с функциями это не канает, выведет декларацию функции, а это нам не уперлось:
Инспектор используй. Там ты можешь остановить программ в любой точке.
>>465010
http://dkab.github.io/jasmine-tests/?spec=4 говорит что у тебя там ошибки:
> Возвращаемая функция
> должна принимать любое количество аргументов и передавать их функции fn
> должна вызывать функцию mixin для результатов фунцкии fn
Сначала убеди робота принять решение (но вообще в роботе иногда бывают ошибки, так что если сомневаешься, пиши, я ему вправлю мозги)
>>465074
> Или валить все в одну таблицу, но тогда много полей, проблемы с производительностью.
Мерял? Если нет то с чего ты взял что будут проблемы? Не страдай ерундой и храни все в одной таблице
>>465096
Для таких вещей придуман паттерн EAV (Entity-Attribute-Value).
> но так как у всех категорий разные параметры я не знаю как мне прописать что выводить, то есть надо писать для каждой категории свои параметры для вывода?
надо где-то хранить соответсвие категория -> возможные опции. Можно в коде прописать, можно в БД, если надо чтобы это менялось из админки.
> я не знаю как мне прописать что выводить, то есть надо писать для каждой категории свои параметры для вывода?
По моему это элементарно. Получаешь массив атрибутов объявления и выводишь все что есть.
Не, твой подход не лучшая идея, так как сводится к копипасте.
Тут логичнее ввести такую сущность, как «атрибут объявления», сделать массив атрибутов объявления, сделать список возможных атрибутов у категории, и один большой шаблон (или много маленьких) для вывода каждого атрибута.
> index.php?cat=2&id=891
Cat тут лишний так как категория указана в самом объявлении
>>465168
Потому что на PHP быстрее научиться делать сайты чем на другом языке. Также на него много вакансии самого разного уровня.
Переменные и функции это основы, на практике нужно умение делать сайты или приложения, а не создавать переменные.
>>465200
Посмотри, внизу ошибка о том что ты используешь несуществующую еще в тот момент переменную:
> PHP Notice: Undefined variable: paymentTotal in /home/jLTkCO/prog.php on line 14
Ее надо исправить. И тогда скорее всего все будет правильно.
>>465202
думаю что эффективность пиратских курсов относительно низкая так как нет обратной связи, никто не проверяет твои задания, некому задать вопрос и т.д. Сила платных курсов не в каком-то эксклюзивном материале, а именно в возможности обратной связи, когда преподаватель видит пробелы и помогает их исправить, поясняет сложные места. Также, некоторых людей факт того. что они потратили деньги мотивирует больше.
Не, твой подход не лучшая идея, так как сводится к копипасте.
Тут логичнее ввести такую сущность, как «атрибут объявления», сделать массив атрибутов объявления, сделать список возможных атрибутов у категории, и один большой шаблон (или много маленьких) для вывода каждого атрибута.
> index.php?cat=2&id=891
Cat тут лишний так как категория указана в самом объявлении
>>465168
Потому что на PHP быстрее научиться делать сайты чем на другом языке. Также на него много вакансии самого разного уровня.
Переменные и функции это основы, на практике нужно умение делать сайты или приложения, а не создавать переменные.
>>465200
Посмотри, внизу ошибка о том что ты используешь несуществующую еще в тот момент переменную:
> PHP Notice: Undefined variable: paymentTotal in /home/jLTkCO/prog.php on line 14
Ее надо исправить. И тогда скорее всего все будет правильно.
>>465202
думаю что эффективность пиратских курсов относительно низкая так как нет обратной связи, никто не проверяет твои задания, некому задать вопрос и т.д. Сила платных курсов не в каком-то эксклюзивном материале, а именно в возможности обратной связи, когда преподаватель видит пробелы и помогает их исправить, поясняет сложные места. Также, некоторых людей факт того. что они потратили деньги мотивирует больше.
> Пробовал с инета стянуть скрипты, но они работать не хотят
Какой смысл скопировать код не понимая как он работает? Цель этого задания научить тебя как сделать простое приложение, а копируя ты ничему не учишься. Мы же тебе денег за сделанное задание все равно не дадим, единственное что ты можешь получить, это знания и навыки. Я советую нормально изучить JS/DOM/jQuery и так далее.
> как при клике на другие пункты меню менять им класс на active, а у остальных на noactive?
Там вряд ли нужен класс noactive, я думаю в бутстрапе достаточно класса active. Более того, с бутстрапом в комплекте идет яваскрипт который реализует переключение табов и ты скорее всего его просто не подключил.
А так, вообще, если ты пишешь вкладки с нуля, то ты яваскриптом ставишь обработчик клика и в нем меняешь классы. Но тебе надо сначала изучить JS/DOM прежде чем это делать.
Если тебе хочется посмотреть на готовый код из бутстрапа, то вот он, в исходниках есть: https://github.com/twbs/bootstrap/blob/master/js/tab.js но учти что для твоего уровня это скорее всего пока сложновато. Но если ты будешь изучать JS, затем DOM, затем jQuery то сможешь его понять и даже написать что-то аналогичное.
И кстати, в нашем курсе задач по HTML/CSS есть табы на CSS3, работающие без яваскрипта. Я советую тебе и эти задачки пройти от начала до конца.
>Посмотри, внизу ошибка о том что ты используешь несуществующую еще в тот момент переменную.
Починил. А почему она выскочила то? Разве она не создается автоматически, когда я ей какое-либо значение присваиваю? И почему код работал, если ошибка была?
У тебя там еще куча ошибок в коде, например:
> id="dropclick"
id не могут повтряться и должны быть уникальными.
Я советую тебе показать мне потом код на проверку, чтобы найти и исправить все ошибки.
Также, надо не копировать куски кода, а читать документацию. Вот вкладки описаны на официальном сайте бутстрапа: http://getbootstrap.com/2.3.2/components.html#navs (правда, вкладки там не переключаются, но думаю это баг именно в документации)
> Разве она не создается автоматически, когда я ей какое-либо значение присваиваю?
У тебя был такой код:
$a += $b;
он равносилен
$a = $a + $b;
Чтобы присвоить что-то $a мы должны сначала найти сумму $a + $b, а в этот момент переменная $a еще не существует, отсюда ошибка.
> И почему код работал, если ошибка была?
Это такая особенность php, что некоторые ошибки не завершают программу а просто выводят сообщение и продолжают выполнение. На мой взгляд это вредная и неудачная идея, я придерживаюсь принципа fail fast: http://habrahabr.ru/post/218325/
В php есть куча видов ошибок и большая часть из них не фатальные: http://habrahabr.ru/post/161483/ (да, мне это не нравится, мне нравится когда при любой ошибке выбрасывается исключение)
А, все, дошло, спасибо. Да, думаю ты прав, ошибки должны показываться, это от многих проблем в будущем может избавить.
Я когда HTML/CSS учил, то нашел потом работу в интернете, где надо было различные иностранные сайты копировать. И боже, сколько же там ошибок было в коде, я охуевал просто. Вместо того, чтобы просто скопировать я еще сидел и ошибки в коде исправлял, сам не знаю зачем. В итоге на один сайт наверное в два раза больше времени тратил, чем мог бы.
Я и знал. Только это больше года назад было и я за прошедшее время почти все забыл. Сейчас вот петух в жопу клюнул в виде пиздеца в рашке, поэтому и решил бросить игрушки и начать учить языки программирования, дабы трактор завести поскорей, пока совсем поздно не стало.
>8. напиши функцию pluck, которая берет массив объектов и возвращает массив значений определенного поля:
https://gist.github.com/anonymous/bd275b27656a4622d3a0
робот ок
>9. напиши функцию filter, которая принимает функцию-предикат и массив. Возвращает она массив значений, для которых предикат вернет true.
https://gist.github.com/anonymous/04067dff73e7e92e467d
робот ок
>10. Напиши функцию, считающую число свойств в объекте:
https://gist.github.com/anonymous/b2ffe3fc217f11dd2877
робот ок
Эти три задания показались элементарными. Задания 5, 6, 7 не имею понятия, как решать.
>>465210
>Если он не знает, то он почитает советы и ссылки и что-то новое выучит.
Реквестирую советы и ссылки на статьи, где объясняется, как из вышестоящего контекста обратиться к локальным переменным функции (это как я понимаю задание про partial application); как изменить контекст this тоже не представляю.
> Каким образом локальные переменные сохраняются в функции после ее отработки?
>В JS все функции это замыкания, то есть они при создании привязывают к себе ссылки на переменные из окружающих областей видимости. Вот в предисловии к задачам (которое ты видимо пропустил, а зря) это упомянуто
Нет, не пропустил. Читал это и в твоей статье, и в других местах. Но неправильно понимал. Я думал, что внутренняя функция имеет доступ к переменным родительской только изнутри.
function foo(){
var x = 'world';
function say(word){
console.log(word + ' ' + x); // я думал, что х доступен только здесь
}
}
Теперь понимаю, что локальная переменная x будет продолжать жить в памяти, если функция foo вернет какой-то объект (анонимную ф.), содержащий ссылки на определенные переменные: function foo(){ var x='world'; return function(word){ return word + x;};}
>функция в момент создания запоминает ссылки на окружающие ее переменные. И даже если ты эту функцию вызываешь в другом месте, ссылки сохраняются.
>Обычно при выходе из функции локальные переменные (start и step) уничтожаются, но в нашем случае внутренняя функция удерживает внутри ссылки на них и переменные не удаляются сборщиком мусора.
>Когда ты заходишь в функцию, создается специальный временный объект, LexicalEnvironment, в котором хранятся локальные переменные этой функции. Когда ты в этой функции создаешь замыкание, оно запоминает ссылку на LE и может в нем искать переменные.
Теперь вроде бы ясно.
>8. напиши функцию pluck, которая берет массив объектов и возвращает массив значений определенного поля:
https://gist.github.com/anonymous/bd275b27656a4622d3a0
робот ок
>9. напиши функцию filter, которая принимает функцию-предикат и массив. Возвращает она массив значений, для которых предикат вернет true.
https://gist.github.com/anonymous/04067dff73e7e92e467d
робот ок
>10. Напиши функцию, считающую число свойств в объекте:
https://gist.github.com/anonymous/b2ffe3fc217f11dd2877
робот ок
Эти три задания показались элементарными. Задания 5, 6, 7 не имею понятия, как решать.
>>465210
>Если он не знает, то он почитает советы и ссылки и что-то новое выучит.
Реквестирую советы и ссылки на статьи, где объясняется, как из вышестоящего контекста обратиться к локальным переменным функции (это как я понимаю задание про partial application); как изменить контекст this тоже не представляю.
> Каким образом локальные переменные сохраняются в функции после ее отработки?
>В JS все функции это замыкания, то есть они при создании привязывают к себе ссылки на переменные из окружающих областей видимости. Вот в предисловии к задачам (которое ты видимо пропустил, а зря) это упомянуто
Нет, не пропустил. Читал это и в твоей статье, и в других местах. Но неправильно понимал. Я думал, что внутренняя функция имеет доступ к переменным родительской только изнутри.
function foo(){
var x = 'world';
function say(word){
console.log(word + ' ' + x); // я думал, что х доступен только здесь
}
}
Теперь понимаю, что локальная переменная x будет продолжать жить в памяти, если функция foo вернет какой-то объект (анонимную ф.), содержащий ссылки на определенные переменные: function foo(){ var x='world'; return function(word){ return word + x;};}
>функция в момент создания запоминает ссылки на окружающие ее переменные. И даже если ты эту функцию вызываешь в другом месте, ссылки сохраняются.
>Обычно при выходе из функции локальные переменные (start и step) уничтожаются, но в нашем случае внутренняя функция удерживает внутри ссылки на них и переменные не удаляются сборщиком мусора.
>Когда ты заходишь в функцию, создается специальный временный объект, LexicalEnvironment, в котором хранятся локальные переменные этой функции. Когда ты в этой функции создаешь замыкание, оно запоминает ссылку на LE и может в нем искать переменные.
Теперь вроде бы ясно.
PHP не занимается отправкой писем. Он только отдает соответствующие данные (smtp) серверу через функцию mail.
Точно так же, как php не работает с бд напрямую, а через субд (mysql, oracle и т.д.).
Соответственно тебе надо установить почтовый сервер.
Проверьте рулеточку :3 Что-то великовато получилось.
Если известны точные значения, лучше использовать switch вместо elseif-ов (необязательно, но он же для этих случаев и предназначен).
Названия переменных на транслите типа $otvet режут глаза.
Зачем exit в каждом ифе?
Если в if(true), то интерпретатор даже не будет заглядывать в другие ветки условий.
А вот в случае со свитчем break нужен, да.
http://ideone.com/qFMCsM
Задачку с телефонным номером вроде решил, а вот с "Grammar Nazi" чет разобраться не могу. Насколько я понял, нужно в регулярном выражении по скобкам разбросать все варианты ошибок и когда в тексте будет находиться ошибка из регулярного выражения, то ее значение будет передано в ячейку массива, который потом надо вывести, так?
Но оно почему-то не работает, т.к. находится первая ошибка и все, дальше текст не обрабатывается. Или я неправильно записываю? Разные выражения для поиска же через "|" пишутся?
Вот на вклад в банке задачка. Так, хватит на сегодня. Пойду баюшки.
Мне нужен пример, я не могу понять что и как там, вообще не догоняю. 4й раз за пару дней сажусь, перечитываю мануал, пытаюсь выявить как мне сделать даже простейшую финкцию, и не понимаю. Из мануала не нужно только, там непонятные.
>Напиши программу, которая отберет и выведет N самых населенных городов по убыванию числа жителей.
https://gist.github.com/anonymous/14a221b135f11028bba9
Но вопрос, насколько правильно делать вот так:
<?php
require 'Slim/Slim.php';
\Slim\Slim::registerAutoloader();
$app = new \Slim\Slim(); $app->get('/', function () use ($app) {
\trequire_once 'lib/mysql.php';
\t$db = connect_db();
\t$result = $db->query( 'SELECT id, name, job FROM friends;' );
\twhile ( $row = $result->fetch_array(MYSQLI_ASSOC) ) {
\t\t$data[] = $row;
\t}
\t$app->render('friends.php', array(
\t\t\t'page_title' => "Your Friends",
\t\t\t'data' => $data
\t\t)
\t);
});
$app->run();
\t\tчто-то сломалось
Сессия, куки.
if(!isset($_COOKIE['counter'])){
$counter = 1;
}else{
$counter = (int)$_COOKIE['counter'] + 1;
}
setcookie('counter', $counter, time() + 606024*365);
echo "Вы посещали эту страницу $counter раз(а).";
Спасибо, но это не совсем то. Нужна цифра в стиле КЛИЕНТОВ РАБОТАЕТ С НАШЕЙ КОМПАНИЕЙ. То есть, она должна быть одна для всех, с какого бы браузера не заходили.
Тебе нужна реальная цифра или просто какая-то цифра? Если первое, то тебе нужно считать сколько клиентов в БД, если второе то просто впиши цифру и все.
Второе. Но как так сделать, чтобы эта цифра росла время от времени, и при этом была одинакова при посещении сайта с любой точки?
>чтобы эта цифра росла время от времени, и при этом была одинакова при посещении сайта с любой точки
>время от времени
>время
>одинаково для всех
>растет время от времени
Сделай это число зависимым от текущего времени.
>при этом была одинакова при посещении сайта с любой точки?
С какой точки, блять? Ты просто взрываешь мне мозг, сука. Браузер запрашивает страничку на сервере, сервер отвечает страничкой, если ты впишешь на страничку цифру, сервер будет ее отдавать. Серверу похуй, кому отдавать, васе в залупинске или пете в мухосранске.
Просто напиши скрипт, который будет каждый день увеличивать кол-во "довольных клиентов" на определенное число, например от одного до трех. Никто не будет следить за тем, как часто и с каким интервалом у тебя этот счетчик обновляется.
>Но как так сделать, чтобы эта цифра росла время от времени, и при этом была одинакова при посещении сайта с любой точки?
Она будет расти сама по себе всякий раз когда в базу будет добавляться новый клиент.
При посещении сайта 'с любой точки' скрипт спрашивает у бд сколько клиентов добавлено на данный конкретный момент и сообщает в браузер. Если через секунду в бд добавится новый клиент, а через две секунды ты посетишь страницу 'с любой точки' то получишь новое число (старое+1).
У меня было так же бро. Просто нужно больше практики с ними, тема по обширности сравнима с любой из предыдущих.
как слим фрамеворк осилить? не до конца насчет него вдупляю, доки не очень у него.
Ну одно дело практиковаться, когда только некоторые моменты не понимаешь, а я вообще нихуя практически не понимаю, как эти самые выражения строить, кроме совсем уж примитивных.
Ну так начни с самых примитивных. Давай разберем с самого начала. Для примера возьмем то что уже есть у ОП-а в учебнике в виде примеров.
Начинается у него с проверки на соответствие.
http://ideone.com/dhowv0
Тут еще вопрос что ты конкретно не понимаешь, либо ты путаешься в самом синтаксисе регулярок, либо в php - функциях, которые с ними работают.
Вот на этом простом примере сделай несколько подобных:
1.
Сделай скрипт, который проверяет дату рождения, поданную ему в формате DD-MM-YYYY
DD (Дни) могут быть от 1 до 31
MM (Месяцы) до 1 до 12
YYYY (Год) - пусть будет любой.
Как сделаешь это - пиши, придумаем тебе еще что-нибудь.
во вконтактике, офк
поясни для дауна, мне кароч нужны аватарки всех подписчиков паблика, их 1к, как их скачать?
Для дауна слишком долго пояснять. Ты делаешь запрос к апи, чтобы получить данные в формате JSON, там будет вся нужная инфа. Самый наглядный способ это сделать - вбить адрес в адресную строку бразуера. Как должен выглядеть запрос и что передавать смотри на vk.com/dev
Скачал, установил все вроде.
Делаю хэллоуворлд отсюда
http://www.codeigniter.com/user_guide/tutorial/news_section.html
Вроде бы все сделал как в описании, но не корректно работают новости. Если кликнуть на какую-то новость, то кидает на 404. Всё перепроверил на 2 раза.
спасибо, анон, буду разбираться, добра тебе
ЛОЛ, у меня точно такая же проблема была, ты случайно не сайт объявлений делаешь?
эти знания тебе ничего не дают, на каждом втором сайте авторизация также устроена. из клиента ты никак не можешь записать что-то в сессию на сервере, а там это происходит лишь в том случае если введены верные логин и пароль.
Нет, у меня типа диплом (потом кулстори расскажу, если сдам нормально). Как решил проблему-то?
>>464813
>\tON DELETE RESTRICT
Тут мой затуп, ни чего более.
>>464816
>А почему ты медиаинформацию вынес в отдельную таблицу, а не добавил колонку в files? На мой взгляд это усложнение и у должна быть причина делать именно так.
Захотелось сделать класс MediaInfo не статичным, дабы информация о файле передавалась в шаблон через объект, принадлежащий этому классу.
Потом смотрю у классов file и coment есть свой мэппер, вот и для MediaInfo тоже свой мэппер сделал.
В итоге, что файл сохраняется через fileMappe, а ID3 через MediaInfoMapper. Так и появилась отдельная таблица.
В общем решение появилось само собой, наобум. Если это быдлокод, то переделаю.
>>464818
>А есть какая-то гарантия что key не может быть 'main', 'upload' и тд?
Гарантия стопроцентная. key - строка десятизначная.
Однако, придется помнить что не стоить делать страничку с десятизначными путями,
$app->get('/:TenSymbols'), дабы избежать 1 к 600 000 000 000 000 вероятности создания ключа совпадающего с путём странички =)
>Может для файла лучше сделать URL вроде /f/:key?
Данное решение заимствовано с rghost. Лишние слеши в строке адреса не нужны я так думаю.
Не могу превозмочь прокастинацию. Дал бы мне кто-нибудь пиздов для мотивации.
писал простейший троян в батнике но во вк не отправляется т.к защита. можно почтой но она заподозрит
Я использовала вот этот класс "form-inline" для формы, в некоторых моментах выравнивал всё <br> но кажется это не самый лучший метод
Вот почему ты такой долбоеб? Нахуй ты свое и наше время пытаешься тратить на такое говно? Ты сильно в жопу ужаленный? То что тебя там обидели, это лишь твоя вина. Крыса ебаная в /b пиздуй плакаться.
как слим фрамеворк осилить? не до конца насчет него вдупляю, доки не очень у него.
Не понимать ваш сарказм.
> Задания 5, 6, 7 не имею понятия, как решать.
Почитай про Function#apply, call и bind:
https://learn.javascript.ru/objects-more (я вообще советую этот учебник, очень полезный)
> >8. напиши функцию pluck, которая берет массив объектов
Верно
> >9. напиши функцию filter, которая принимает функцию-предикат и массив.
Верно
> >10. Напиши функцию, считающую число свойств в объекте:
В принципе программа работает, но вообще при переборе стоит проверять принадлежит ли ключ объекту или его прототипам с помощью hasOwnProperty: https://learn.javascript.ru/prototype#%D0%BC%D0%B5%D1%82%D0%BE%D0%B4-hasownproperty
Если ты не знаешь, что такое прототипы, то заодно почитай.
> Реквестирую советы и ссылки на статьи, где объясняется, как из вышестоящего контекста обратиться к локальным переменным функции
Снаружи никак нельзя получить локальные переменные функции. Там надо иcпользовать apply/call
> Теперь понимаю, что локальная переменная x будет продолжать жить в памяти, если функция foo вернет какой-то объект
Я тебе советую вообще не задумываться про освобождение памяти. В JS автоматический сборщик мусора и он удаляет объекты только когда на них нет ни одной ссылки и ты никак до них добраться уже не сможешь. То есть ничего что доступно через переменные, замыкания, поля, он не удалит. Если у тебя есть знакомство с другими языками (Вроде Си), то не пытайся применять знания об их особенностях к яваскрипту (например, в Си локальные переменные хранятся на стеке и освобождаются при выходе их фукнции. В JS это не так, там локальные переменные хранятся в LexicalEnvironment в куче).
exit писать не надо, так как в цепочке if/elseif выполнится только один блок.
А так, верно.
>>465342
Компактнее будет не свич, а массив.
>>465354
По ссылке задача про миллион в банке. Решено верно.
$year = $year + 1; можно писать как $year += 1 или $year++;
>>465356
Неплохо, но надо проверить задачу на других номерах.
Задачу про номера телефонов надо проверить на большом числе телефонов, чтобы убедиться что твой код правильный. Но руками подставлять номера — долго и скучно. Пусть работает робот, а не человек!
Для этого давай добавим в программу тесты, чтобы сразу было видно, верно все работает или нет. Сделай 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' // нет +
);
> Но оно почему-то не работает, т.к. находится первая ошибка и все, дальше текст не обрабатывается.
А ты какую функцию используешь? preg_match ищет только первое совпадение, надо preg_match_all чтобы найти все. Запости код, посомтрим.
exit писать не надо, так как в цепочке if/elseif выполнится только один блок.
А так, верно.
>>465342
Компактнее будет не свич, а массив.
>>465354
По ссылке задача про миллион в банке. Решено верно.
$year = $year + 1; можно писать как $year += 1 или $year++;
>>465356
Неплохо, но надо проверить задачу на других номерах.
Задачу про номера телефонов надо проверить на большом числе телефонов, чтобы убедиться что твой код правильный. Но руками подставлять номера — долго и скучно. Пусть работает робот, а не человек!
Для этого давай добавим в программу тесты, чтобы сразу было видно, верно все работает или нет. Сделай 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' // нет +
);
> Но оно почему-то не работает, т.к. находится первая ошибка и все, дальше текст не обрабатывается.
А ты какую функцию используешь? preg_match ищет только первое совпадение, надо preg_match_all чтобы найти все. Запости код, посомтрим.
> нужно в регулярном выражении по скобкам разбросать все варианты ошибок и когда в тексте будет находиться ошибка из регулярного выражения, то ее значение будет передано в ячейку массива, который потом надо вывести, так?\
примерно так, да.
>>465365
Задачку про айфон-то запости, а то ты ее переписал задачей про банк.
>>465369
Ну вот тебе пример заменяющий букву x на число, попробуй его запустить:
$text = "x человек на сундук x мертвецов";
$re = "/x/ui";
$result = preg_replace_callback($re, function ($m) {
var_dump($m);
return '100500';
}, $text);
var_dump($result);
http://ideone.com/UefG2g
Поиграйся с ним, попробуй написать другое выражение, попробуй в функцию какое-нибудь условие засунуть и несколько вариантов возврата. Например чтобы x заменялся на случайное четное число, а y на случайное нечетное.
Не, это не пойдет. Код очень запутанный, и тяжело его разобрать. Надо упростить код, выкинуть все эти циклы и свести его к 3-4 строчкам.
Ты тут похоже алгоритм сортировки изобрел? Ну вот посмотри сколько их уже изобретено: https://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%81%D0%BE%D1%80%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B8
Мое предложение:
— отсортировать массив городов готовой функцией (да, в JS есть функция сортировки массива)
— взять первые N элементов готовой функцией
— вывести
Ты спросишь, какой такой функцией. Почитай учебник и найди сам:
https://learn.javascript.ru/array-methods
https://learn.javascript.ru/data-structures
В общем, можно, но лучше работу с базой данных не засовывать в index.php, а сделать класс-маппер для этого. И вместо массивов использовать объекты класса Friend.
Читал урок про работу с БД? https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md
Ну конечно если у тебя весь сайт состоит из однйо этой функции, то можно оставить как у тебя, незачем файлы лишние создавать. Но если сложнее то стоит разнести на части.
require_once не стоит ставить внутри функции. Зачем создавать путаницу? Ставь его в самом начале файла.
> while ( $row = $result->fetch_array(MYSQLI_ASSOC) ) {
Есть метод чтобы получить все записи сразу, попробуй его найти в мануале: http://php.net/manual/ru/class.mysqli-result.php
>>465425
Выбирай из базы данных число клиентов и выводи.
>>465441
Давай более простые задачи порешаем. Например, как тебе такая задача:
— пользователь вводит почтовый индекс. Проверь, правильный ли он (индекс состоит ровно из 6 цифр и никаких других симолов быть не должно)
127001 — правильно
127000001 — нет
127001 текст — нет
123 — нет
— дан текст, в нем может быть (а может не быть) записан адрес сайта (начинается с http:// или https://, дальше содержит любые символы кроме пробела, символов должно быть не менее 3). Сделай программу, выводящую есть ли в тексте ссылка или нет и если да, то какая
Пример:
заходите на http://example.com — есть
заходите на http, http://, example.com — нету
заходите на http://ex — нету (мало символов)
если сложности, запости код и на чем остановился, дам подсказку.
В общем, можно, но лучше работу с базой данных не засовывать в index.php, а сделать класс-маппер для этого. И вместо массивов использовать объекты класса Friend.
Читал урок про работу с БД? https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md
Ну конечно если у тебя весь сайт состоит из однйо этой функции, то можно оставить как у тебя, незачем файлы лишние создавать. Но если сложнее то стоит разнести на части.
require_once не стоит ставить внутри функции. Зачем создавать путаницу? Ставь его в самом начале файла.
> while ( $row = $result->fetch_array(MYSQLI_ASSOC) ) {
Есть метод чтобы получить все записи сразу, попробуй его найти в мануале: http://php.net/manual/ru/class.mysqli-result.php
>>465425
Выбирай из базы данных число клиентов и выводи.
>>465441
Давай более простые задачи порешаем. Например, как тебе такая задача:
— пользователь вводит почтовый индекс. Проверь, правильный ли он (индекс состоит ровно из 6 цифр и никаких других симолов быть не должно)
127001 — правильно
127000001 — нет
127001 текст — нет
123 — нет
— дан текст, в нем может быть (а может не быть) записан адрес сайта (начинается с http:// или https://, дальше содержит любые символы кроме пробела, символов должно быть не менее 3). Сделай программу, выводящую есть ли в тексте ссылка или нет и если да, то какая
Пример:
заходите на http://example.com — есть
заходите на http, http://, example.com — нету
заходите на http://ex — нету (мало символов)
если сложности, запости код и на чем остановился, дам подсказку.
Можешь тут задавать конкретные вопросы, желательно с конкретными примерами «как сделать X в Слиме» или с примерами кода.
Общий принцип написания приложения на слиме такой:
— перенаправляем все обращения к серверу на index.php с помощью файла htaccess и правил mod_rewrite
— В index.php пишем:
<?php
// подключение и настройка Слима
...
$app = new \Slim\Slim( );
// задаем URL и обработчики для них, то есть какую функцию вызывать при обращении пользователя по такому-то адресу
// Если пользователь зайдет на страницу http://localhost/hello то увидит этот текст
$app->get('/hello', function () {
echo "Oh you";
});
$app->get('/about', function () {
// выводим код из шаблона
$app->render('about.html');
});
// запускаем Слим и он либо запускает один из наших обработчиков либо выводит страницу 404
$app->run( );
Можешь тут задавать конкретные вопросы, желательно с конкретными примерами «как сделать X в Слиме» или с примерами кода.
Общий принцип написания приложения на слиме такой:
— перенаправляем все обращения к серверу на index.php с помощью файла htaccess и правил mod_rewrite
— В index.php пишем:
<?php
// подключение и настройка Слима
...
$app = new \Slim\Slim( );
// задаем URL и обработчики для них, то есть какую функцию вызывать при обращении пользователя по такому-то адресу
// Если пользователь зайдет на страницу http://localhost/hello то увидит этот текст
$app->get('/hello', function () {
echo "Oh you";
});
$app->get('/about', function () {
// выводим код из шаблона
$app->render('about.html');
});
// запускаем Слим и он либо запускает один из наших обработчиков либо выводит страницу 404
$app->run( );
В документации в самом начале есть пример простого hello-world приложения. Ты его повторил? Работает?
>>465521
Хорошая задачка, советую попробовать анону решить. Если затрудения, пости код и пиши на чем завис, подскажем.
>>465564
> ибо форма горизонтальная и он переходит на следующую строчку
В бутстрапе есть класс для горизонтальных форм , доки читал? http://getbootstrap.com/css/#forms-inline
Я тебе советую пролистать документацию целиком и может даже выписать или как-то пометить интересные примеры. Иначе ты всеми возможностями пользоваться не научишься и будешь терять время на поиск обходных путей или написание того что уже написано давно. Пролистай все разделы документации, там много полезного.
>>465599
Ты тоже документацию не читаешь, значит. Зря.
У тебя константы объявлены внутри конструктора. Это нелогично. Во-певрых, у тебя до создания объекта константы не существуют. Как их тогда передать в конструктор?
Во-вторых, в константах не хранят данные вроде цены. Константа это число или строка. Стоимость надо хранить в отдельном массиве.
Ну и наконец нет никакой логики в том что ты для каждого объекта пересоздаешь заново таблицу цен. Зачем, если это можно сделать один раз в начале программы?
Вот как надо сделать константы:
Hamburger.SIZE_SMALL = 'small';
Вот как лучше сделать цены/калории:
details[Hambuerger.SIZE_SMALL] = {...};
Hamburger.details = details;
Либо можно сделать статическую (не на прототипе) функцию:
Hamburger.getPrices = function () {
var details = ....;
return details;
}
Далее, добавок может быть несколько, и их можно добавить позже, а у тебя нельзя. Я советую сделать массив добавок и метод добавления добавки. Должна быть проверка, существует ли такая добавка вообще и не пытаешься ли ты добавить второй раз одно и то же.
size, filling должны быть константами. А у тебя это не так. По твоей задумке надо писать что-то вроде
var h = new Hamburger('small' ,... );
Вот это очень плохая идея. Это назывеатся магические строки и это плохо, так как во-первых непонятно что такое small во-вторых, нигде нет списка возможных значений. с константами все становится логично:
var h = new Hamburger(Hamburger.SIZE_SMALL, ...)
Сразу видно о чем речь.
> }catch(e){
> console.log('Вы ввели неправильный тип гамбургера, на
чинки или добавки.');
Функция не должна ничего выводить так как она должна быть универсальной. Может мы хотим использовать ее на веб странице где консоль не видна. Функция должна просто выкидывать исключение, а тот кто ее вызвал, пусть ее ловит.
И еще ты не проверяешь исключение. Ты на любое исключение выводишь «вы выбрали неправильное что-то» хотя это неврено. Может у тебя ошибка в программе и надо ее исправить, но твоя программа об этом не скажет, она скажет что виноват пользователь потому что любую ошибку она интерпретирует как вину пользователя. Это неправильный подход. Я думаю, надо сделать свой класс исключений и проверять относится ли пойманное исключение к нему или нет.
Вот мой урок про исключения в PHP, почитай, про общие принципы работы с исключениями: https://gist.github.com/codedokode/65d43ca5ac95c762bc1a
У тебя константы объявлены внутри конструктора. Это нелогично. Во-певрых, у тебя до создания объекта константы не существуют. Как их тогда передать в конструктор?
Во-вторых, в константах не хранят данные вроде цены. Константа это число или строка. Стоимость надо хранить в отдельном массиве.
Ну и наконец нет никакой логики в том что ты для каждого объекта пересоздаешь заново таблицу цен. Зачем, если это можно сделать один раз в начале программы?
Вот как надо сделать константы:
Hamburger.SIZE_SMALL = 'small';
Вот как лучше сделать цены/калории:
details[Hambuerger.SIZE_SMALL] = {...};
Hamburger.details = details;
Либо можно сделать статическую (не на прототипе) функцию:
Hamburger.getPrices = function () {
var details = ....;
return details;
}
Далее, добавок может быть несколько, и их можно добавить позже, а у тебя нельзя. Я советую сделать массив добавок и метод добавления добавки. Должна быть проверка, существует ли такая добавка вообще и не пытаешься ли ты добавить второй раз одно и то же.
size, filling должны быть константами. А у тебя это не так. По твоей задумке надо писать что-то вроде
var h = new Hamburger('small' ,... );
Вот это очень плохая идея. Это назывеатся магические строки и это плохо, так как во-первых непонятно что такое small во-вторых, нигде нет списка возможных значений. с константами все становится логично:
var h = new Hamburger(Hamburger.SIZE_SMALL, ...)
Сразу видно о чем речь.
> }catch(e){
> console.log('Вы ввели неправильный тип гамбургера, на
чинки или добавки.');
Функция не должна ничего выводить так как она должна быть универсальной. Может мы хотим использовать ее на веб странице где консоль не видна. Функция должна просто выкидывать исключение, а тот кто ее вызвал, пусть ее ловит.
И еще ты не проверяешь исключение. Ты на любое исключение выводишь «вы выбрали неправильное что-то» хотя это неврено. Может у тебя ошибка в программе и надо ее исправить, но твоя программа об этом не скажет, она скажет что виноват пользователь потому что любую ошибку она интерпретирует как вину пользователя. Это неправильный подход. Я думаю, надо сделать свой класс исключений и проверять относится ли пойманное исключение к нему или нет.
Вот мой урок про исключения в PHP, почитай, про общие принципы работы с исключениями: https://gist.github.com/codedokode/65d43ca5ac95c762bc1a
давай подробности, кто выводит 404? Апач? Фреймворк? Что в адресной строке? Функция в контроллере выполняется? Выполняется ли index.php?
>>465595
Мы тут доброаноны и не занимаемся такими делами. IP подменять ты вряд ли можешь.
>>465662
> Захотелось сделать класс MediaInfo не статичным, дабы информация о файле передавалась....
Смотри, в данном случае (и в большинстве других случаев) база тут это сердце приложения. От того, как ты ее проектируешь, зависит как будет выглядеть приложение. Потому к этому проектированию надо подходить максимально внимательно и его надо делать до написания php кода. И разумеется структуру БД надо делать максимально логичной, с учетом нормализации, правильно строить связи между таблицами, расставлять ключи, UNIQUE, выбирать типы и т.д.
А ты из-за того что у тебя там 3 класса вместо 2, заводишь третью таблицу. Это неправильно. Ты сначала делаешь таблицу правильно, и php код под нее подстраивается, а не наоборот.
Потому, давай сначала базу переделаем чтобы было логично и правильно, а потом будем под нее подстраивать код.
Мое мнение — медиаинформаию логично хранить в той же таблице, закодированной например в формате JSON. В PHP коде удобно сделать так:
— есть объект File хранящий информацию о файле
— у него может быть поле mediaInfo в котором лежит объект хранящий информацию о свойствах видео, аудио и тд
— маппер файлов при сохранении и загрузке корректно соххраняет/восстанавливает эту медиаинформацию в таблице
Мапперы обычно делаются 1 на 1 таблицу, так что сколько у тебя таблиц, столько же будет и мапперов.
> Данное решение заимствовано с rghost.
На rghost хитрее, там id только из цифр состоит.
В любом случае, главная мысль это то, что ты должен при проектировании схемы URL думать про конфликты и лучше закладывать гарантии, что пути не перепутаются. Вот у меня в уроке кое-какие мысли: https://gist.github.com/codedokode/772a4ccc03e41d6b7cba
давай подробности, кто выводит 404? Апач? Фреймворк? Что в адресной строке? Функция в контроллере выполняется? Выполняется ли index.php?
>>465595
Мы тут доброаноны и не занимаемся такими делами. IP подменять ты вряд ли можешь.
>>465662
> Захотелось сделать класс MediaInfo не статичным, дабы информация о файле передавалась....
Смотри, в данном случае (и в большинстве других случаев) база тут это сердце приложения. От того, как ты ее проектируешь, зависит как будет выглядеть приложение. Потому к этому проектированию надо подходить максимально внимательно и его надо делать до написания php кода. И разумеется структуру БД надо делать максимально логичной, с учетом нормализации, правильно строить связи между таблицами, расставлять ключи, UNIQUE, выбирать типы и т.д.
А ты из-за того что у тебя там 3 класса вместо 2, заводишь третью таблицу. Это неправильно. Ты сначала делаешь таблицу правильно, и php код под нее подстраивается, а не наоборот.
Потому, давай сначала базу переделаем чтобы было логично и правильно, а потом будем под нее подстраивать код.
Мое мнение — медиаинформаию логично хранить в той же таблице, закодированной например в формате JSON. В PHP коде удобно сделать так:
— есть объект File хранящий информацию о файле
— у него может быть поле mediaInfo в котором лежит объект хранящий информацию о свойствах видео, аудио и тд
— маппер файлов при сохранении и загрузке корректно соххраняет/восстанавливает эту медиаинформацию в таблице
Мапперы обычно делаются 1 на 1 таблицу, так что сколько у тебя таблиц, столько же будет и мапперов.
> Данное решение заимствовано с rghost.
На rghost хитрее, там id только из цифр состоит.
В любом случае, главная мысль это то, что ты должен при проектировании схемы URL думать про конфликты и лучше закладывать гарантии, что пути не перепутаются. Вот у меня в уроке кое-какие мысли: https://gist.github.com/codedokode/772a4ccc03e41d6b7cba
>В бутстрапе есть класс для горизонтальных форм , доки читал?
Читал, но мне нужна вертикальная форма, а если делать форму в форме, то все равно не работает (видимо, класс берется из формы уровнем выше).
тогда можно переопределить в своем CSS для него width: auto
Либо поставить один из классов для указания размера.
Либо засунуть внутрь дива-обертки нужного размера
С размером-то все нормально (я ему кстати и так выдаю ручками width), я не пойму как сделать, чтобы этот селект был на одной строчке рядом с кнопкой.
Есть масса способов сделать это - таблицы, флоаты, позишн, инлайн-блоки, в зависимости от ситуации тот или иной лучше. Бутстрап тебе не заменит базовых знаний по CSS и уж тем более одна строчка display:inline-block это лучше, чище чем, упаси господи, вкладывание формы в форму.
Спасибо, до дома доберусь, попробую.
>>465725
>В документации в самом начале есть пример простого hello-world приложения. Ты его повторил? Работает?
Да, сначала на локалхосте запускал, работало.(ubuntu, lamp) Роутинг работал, потом я что-то где-то сломал(конфиг трошгал немного) и все, потом все удалял(в том числе в папке /етс/) и снова устанавливал... хтаццесс в порядке, выдает 404. Ну ладно, на впс буду вылаживать.
<form class="form-inline">
<div class="form-group">
<label class="sr-only" for="exampleInputEmail3">Email address</label>
<input type="email" class="form-control" id="exampleInputEmail3" placeholder="Enter email">
</div>
<div class="checkbox">
<label>
<input type="checkbox"> Remember me
</label>
</div>
<button type="submit" class="btn btn-default">Sign in</button>
</form>
Мне это до безумия интересно, но я ленивое хуйло и постоянно отвлекаюсь чтобы попить страйк и поглядеть японские мультики про трусы, или в ммо здарочу. Пиздец. Думаю вот вот завтра проснусь, начну кодить 24/7 и стану йоба погроммистом через полгода. Пока не оче.
>>465723
Спасибо, я потихоньку разбираюсь уже, задачки решаю по очереди. Только с заменой еще не очень понятно. Как например в той задачке на исправление ошибок в тексте исправить ошибку с отсутствием пробела после знаков препинания? Ведь если писать регулярку как ",\s", то он этот самый символ "сжирает", когда заменяешь найденный результат на запятую с пробелом.
Смотри, что получилось. ID3 информация и функции работающие с ней теперь нафодятся в классе file.
https://github.com/tokotun/uppy
>На rghost хитрее, там id только из цифр состоит.
Не всегда.
http://rghost.ru/8L6m6mh6H
Алсо, что подразумевается под сильными знаниями PHP, MySQL, JavaScript, HTML/CSS в вакансии на джуниора?
И как вкатыватся на удаленную работу? Вот например найду вакансию, пот описание, которой вроде даже подхожу.
Но пробуюсь первый раз и потому не уверен, что справлюсь. Тут просто пробоватся и будь что будет? И осваиватся на месте?
Нужна помощь по "Условия и игра в кубики". Я вообщем вроде сделал задание, но мне кажется что все неправильно, хотя вроде бы все работает. Вообщем проверьте пожалуйста. И еще, вопрос, на пике. Где результат пишется, нет пробела и выглядит убого. Так и должно быть?
Собственное мой высер: https://gist.github.com/gennsmir/aa16c70f3acfcd5a9000#file-gistfile1-txt
После {$PCDice2} \n поставь и будет тебе пробел. Ну и проверку суммы бросков лучше писать через один if else, а не через 2 if. И нафиг ты exit пишешь? А так в принципе все норм.
более_продвинутый_ньюфаг
> После {$PCDice2} \n поставь и будет тебе пробел.
Спасибо.
> И нафиг ты exit пишешь?
Честно говоря сам не заметил. Я просто копировал, вставлял и меня. exit даже не стал трогать, думая что он на что-то влияет.
Старайся всегда свой код читать до тех пор, пока на 100% не поймешь что каждая строчка делает. А то понакопировать конечно что угодно можно и это даже возможно будет работать, вот только таким образом хорошим кодером явно не станешь.
Я написал на свой лад, что было дано в учебнике для чайников. А копировал я похожие строчки, где надо изменить один символ, просто в экономии времени. Я разобрался в нем полностью, но упускаю такие мелочи как \n. Вроде такая хрень, а я не так и мог найти куда ее вписать, что бы выглядело нормально.
Ну если так, то гуд. \n это перевод строки же, поэтому можно в любую текстовую строчку добавлять, после которой нужно на следующей строке текст выводить.
>Не имеет смысла, так как аякс запрос будет обрабатывать другой экземпляр скрипта, не тот что создал страницу.
А кстати, о птичках. Аякс и mvc нормально дружат? Так сразу не могу представить как и главное куда правильнее слать запрос. Догадываюсь что надо в контроллере сделать метод ajax(), а в клиенте что-то такое (articles - контроллер, ajax - метод)
$.ajax ({
url: '/public/articles/ajax',
success: function(){
alert('success');
}
});
С меня нихуя кроме разных мотиваций заниматься собой и менять свою жизнь, всё такое.
Вне зависимости от того, что тебе видно, мне это помогло не заходить на двач неделю. Сейчас возникла идея попросить у местного анона помощи. Как только найдется кто-то, если мне повезет вообще с этим, я снова заблочу двач и не буду на него заходить еще очень долго.
<script>
\t\t$(document).ready(function(){
\t\t\tvar $menu = $("#target");
\t\t\t$(window).scroll(function(){
if ( $(this).scrollTop() > 200 && $menu.hasClass("default") ){
$menu.removeClass("default").addClass("fixed");
} else if($(this).scrollTop() <= 200 && $menu.hasClass("fixed")) {
$menu.removeClass("fixed").addClass("default");
}
\t\t\t});
\t\t});
</script>
200 - это сколько пикселей нужно прокрутить прежде чем элемент прилипнет кверху, подбирается под положение конкретного элемента
css:
.default {}
.fixed {
position:fixed;
z-index:999;
top:10px;
}
и еще, на голом css ты этого не сделаешь никак.
Ты неправильно поступаешь. У тебя цель научиться или цель какими-то костылями сделать чтобы оно работало до следующей поломки?
Лучше разбираться последовательно:
1) работает ли перенаправление через htaccess? Поставь там вместо index.php test.html, а в файл test.html напиши например It works. Теперь проверь, что вводя любой путь в URL (http://localhost/dasda/dsadad) мы видим надпись
2) работает ли роутинг в слиме? Верни htaccess в прежнее состояние, и поставь пару echo, в начале index.php и в одной из функций и проверь, срабатывают они или нет.
И уже тогда со всеми подробностями пиши. а пока я даже от тебя ответ на некоторые вопросы не услышал
По моему опыту, обычно «не работает» не Слим. а htaccess. То есть аноны не разобрались с тем как настроить свой сервер, а считают что виноват Слим, хотя он как раз работает как часы.
Вот тебе статья про работу mod_rewrite в htacess: http://habrahabr.ru/company/sprinthost/blog/129560/
Если у тебя отключен модуль mod_rewrite или отключено чтение htaccess файлов в настройках Апача то разумеется ничего работать не будет.
>>465885
Что это? Кусок кода без единого вопроса или комментария.
>>465893
Нет, паст нету.
Я в этом треде никого никогда не мотивирую. Если например анон месяц делает простую задачу, я ничего по этому поводу не говорю — пусть делает столько времени, сколько хочет, хоть год.
Потому советую лучше создать мотивационный тред в более подходящем разделе, например /b (заполненным опытными прокрастинаторами чуть менее чем полностью) или /wrk. Также на хабре или гиктаймсе каждую неделю появляется пост на эту тему.
Ну и если тебе игры интереснее, может ты хочешь какую-нибудь игру сам написать? Конечно, полноценную навороченную игру начинающему сделать сложно, но тот же арканоид (где надо шариком кирпичики разбивать) или что-то аналогичное сделать реально изучив лишь яваскрипт и DOM и у нас есть задачка на эту тему.
>>465928
Ты можешь скобками захватывать часть строки и при замене подставлять захваченное содержимое:
$text = preg_replace("/a([0-9])/u", "b$1", "a0 a1 a2");
// b0 b1 b2
Здесь мы в первые скобки захватываем цифру и при замене вставляем ее назад.
Мануал: http://php.net/manual/ru/function.preg-replace.php
>>465931
Наберем сначала 600-700 постов, а то каждую неделю новый тред делать — слишком часто.
> что подразумевается под сильными знаниями
Не знаю, на этот вопрос может ответить только представитель работодателя, я думаю.
> пробуюсь первый раз и потому не уверен, что справлюсь.
И что, если ты не справишься, то тебя побьют?
Ты же ничего не теряешь, кроме времени. В худшем случае тебе просто не заплатят денег. Если ты не подходишь по знаниям то тебя не возьмут. Если тебя взяли значит ты подошел.
По коду
> file_key
> dateLoad
Вот это неаккуратно. Ты пишешь код один, и не можешь придерживаться единого стиля.
> COMMENT 'Description branches for comment. Number of comments and the number of his parents.
Тут лучше было написать «materialized path of a comment», так как это общепринятое название паттерна и любой нормальный программист это поймет или нагуглит. Это не обязательно исправлять.
По поводу класса File: мне кажется, не надо было объединять классы, а надо было работу с медиаданными поместить в класс MeiaInfo. И в File сделать поле для хранения объекта. Мне кажется, что это было бы уместно вынести в отдельный класс, так как это явно отдельный функционал, который можно использовать даже отдельно от класса File и отдельно от базы данных (например в простой программе которая принимает файл и выводит информацию о нем). Ведь в ООП объект это данные + методы для работы с ними и медиаданные тянут на отдельный объект.
Но если у тебя есть причины оставить это в классе File, можно оставить.
> public function getDownloadLink($hostname)
Когда ты делал этот метод, ты наверно заметил что в класс File он не очень вписывается, так как у класса File нет информации об окружении в котором он работает. Это значит, что метод лучше было сделать не в классе File, а снаружи:
$file = new File;
...
$url = $x->getFilePageUrl($file);
Где это можно сделать? Ну во-первых, для этого можно завести класс вроде FileHelper или FileManager или FileService. Во-вторых, немного странно в маленьком приложении создавать класс ради одного метода, потому можно сделать это в каком-нибудь классе Util/Helper вместе с другими аналогичными методами (которые некуда поместить) или даже добавить метод в $app:
$app->getFileUrl = function () { ...} (кажется, в Слиме можно так делать, http://docs.slimframework.com/di/overview/ )
Это впрочем имеет минус, так легко заполнить index,php кучей функций и в нем будет трудно ориентироваться.
> https://github.com/tokotun/uppy/blob/master/uppy/app/File.php#L43
> +-\.
Минус в квадратных скобках надо экранировать так как он обозначает диапазон от «плюса» до «бекслеша» в данном случае. Надо писать
+\-.
> "$this->id _ $fileName _";
зачем тут проблеы? Ты забыл что пременную можно в фигурные скобки поместить?
Некоторые функции можно было бы вынести из File так как они явно универсальные и могут использовать где-то еще: вывод размера в байтах, перекодировки имен файлов. тут это не требуется, но в более сложном приложении они могли бы использоваться где-то еще.
> strtoupper(substr(PHP_OS, 0, 3)) === 'WIN'
Чтобы ты знал, эта константа не идентифицирует текущую ОС. она обозначает ОС под которой компилировался PHP, и если завтра виндоуз версию начнут компилировать под линуксом, это перестанет работать. Вот смотри, что написано в мануале:
http://php.net/manual/ru/function.php-uname.php
> Для вывода названия операционной системы используется константа PHP_OS. Обратите внимание, что эта константа содержит название операционной системы, на которой PHP был собран (built)
Ну и мы можем проверить откуда берется эта константа поиском по исходникам php: https://github.com/php/php-src/search?l=c&q=php_os&utf8=%E2%9C%93
Найденных файлов конечно недостаточно, потому я подключил интуицию и нашел определение тут: https://github.com/php/php-src/blob/master/configure.in#L1286
Это скрипт сборки PHP и видно что значение PHP_OS определяется на этапе компиляции.
продолжение следует.
> что подразумевается под сильными знаниями
Не знаю, на этот вопрос может ответить только представитель работодателя, я думаю.
> пробуюсь первый раз и потому не уверен, что справлюсь.
И что, если ты не справишься, то тебя побьют?
Ты же ничего не теряешь, кроме времени. В худшем случае тебе просто не заплатят денег. Если ты не подходишь по знаниям то тебя не возьмут. Если тебя взяли значит ты подошел.
По коду
> file_key
> dateLoad
Вот это неаккуратно. Ты пишешь код один, и не можешь придерживаться единого стиля.
> COMMENT 'Description branches for comment. Number of comments and the number of his parents.
Тут лучше было написать «materialized path of a comment», так как это общепринятое название паттерна и любой нормальный программист это поймет или нагуглит. Это не обязательно исправлять.
По поводу класса File: мне кажется, не надо было объединять классы, а надо было работу с медиаданными поместить в класс MeiaInfo. И в File сделать поле для хранения объекта. Мне кажется, что это было бы уместно вынести в отдельный класс, так как это явно отдельный функционал, который можно использовать даже отдельно от класса File и отдельно от базы данных (например в простой программе которая принимает файл и выводит информацию о нем). Ведь в ООП объект это данные + методы для работы с ними и медиаданные тянут на отдельный объект.
Но если у тебя есть причины оставить это в классе File, можно оставить.
> public function getDownloadLink($hostname)
Когда ты делал этот метод, ты наверно заметил что в класс File он не очень вписывается, так как у класса File нет информации об окружении в котором он работает. Это значит, что метод лучше было сделать не в классе File, а снаружи:
$file = new File;
...
$url = $x->getFilePageUrl($file);
Где это можно сделать? Ну во-первых, для этого можно завести класс вроде FileHelper или FileManager или FileService. Во-вторых, немного странно в маленьком приложении создавать класс ради одного метода, потому можно сделать это в каком-нибудь классе Util/Helper вместе с другими аналогичными методами (которые некуда поместить) или даже добавить метод в $app:
$app->getFileUrl = function () { ...} (кажется, в Слиме можно так делать, http://docs.slimframework.com/di/overview/ )
Это впрочем имеет минус, так легко заполнить index,php кучей функций и в нем будет трудно ориентироваться.
> https://github.com/tokotun/uppy/blob/master/uppy/app/File.php#L43
> +-\.
Минус в квадратных скобках надо экранировать так как он обозначает диапазон от «плюса» до «бекслеша» в данном случае. Надо писать
+\-.
> "$this->id _ $fileName _";
зачем тут проблеы? Ты забыл что пременную можно в фигурные скобки поместить?
Некоторые функции можно было бы вынести из File так как они явно универсальные и могут использовать где-то еще: вывод размера в байтах, перекодировки имен файлов. тут это не требуется, но в более сложном приложении они могли бы использоваться где-то еще.
> strtoupper(substr(PHP_OS, 0, 3)) === 'WIN'
Чтобы ты знал, эта константа не идентифицирует текущую ОС. она обозначает ОС под которой компилировался PHP, и если завтра виндоуз версию начнут компилировать под линуксом, это перестанет работать. Вот смотри, что написано в мануале:
http://php.net/manual/ru/function.php-uname.php
> Для вывода названия операционной системы используется константа PHP_OS. Обратите внимание, что эта константа содержит название операционной системы, на которой PHP был собран (built)
Ну и мы можем проверить откуда берется эта константа поиском по исходникам php: https://github.com/php/php-src/search?l=c&q=php_os&utf8=%E2%9C%93
Найденных файлов конечно недостаточно, потому я подключил интуицию и нашел определение тут: https://github.com/php/php-src/blob/master/configure.in#L1286
Это скрипт сборки PHP и видно что значение PHP_OS определяется на этапе компиляции.
продолжение следует.
Пытаюсь настроить поиск, изкаробки он ищет только отдельные слова.
Не могу въехать в мэппинг, токинайзеры, аналайзеры - что где когда применять? Как задавать веса полей?
Теперь разберем реализацию MPath, как я понимаю, у тебя путь имеет вид
001.002.005
c ограничением на 1000 комментариев-детей и глубину вложенности 10 (которое нигде не проверяется, как я вижу).
Вот тут довольно хитро вычисляется путь. Ты берешь не максимального ребенка комментария, а максимального потомка:
https://github.com/tokotun/uppy/blob/master/uppy/app/CommentsMapper.php#L62
Было бы наверно гораздо проще, если бы было поле parent_id и мы могли взять максимального из детей с указанным parent_id, и увеличить последнюю цифру в нем. А так, алгоритм конечно работает, но довольно запутанный.
Также, есть другой способ строить путь. В нем мы записываем id комментариев-предков. Так как id типа INT занимает до 10 цифр, то мы используем 16-чную систему счисления, где id займет ровно 8 цифр или символов a-f. Так как длина id фиксированна, разделители необязательны. Если у комментария родители имеют id 00001200, 00023456, а сам комментарий id 0fff1234 то путь имеет вид:
00001200 00023456 0fff1234
Преимущество метода: мы можем из path получить id предков не обращаясь к базе. Минус: нельзя вычислить path, пока мы не сохранили комментарий и не получили id, получаются длинные пути, если мы хотим использовать BIGINT вместо INT то id занимает уже 16 символов, что много.
> https://github.com/tokotun/uppy/blob/master/uppy/app/Uploader.php#L25
> public function resizeImage($filename, $uploadPath, $maxSize = 200)
непонятно зачем передавать второй раз uploadPAth если он есть в конструкторе. Более того, ниже он захардкожен:
> imagejpeg($thumb, "uppy/container/thumbs/$filename");
Надо бы этот префикс uppy/container/ вынести в поле объекта или метод. Нехорошо, что он размазан по всему коду. Есть такой принцип DRY — Don't Repeat Yourself — такие вещи должны быть ровно в 1 месте.
> https://github.com/tokotun/uppy/blob/master/uppy/app/FileMapper.php#L13
> public function getLastId()
Эта функция реализована неправильно. Что, если 2 плоьзователя загружают файлы и 2 скрипта параллельно делают INSERT, а затем каждый вызывает эту функию? Они получат оба один и тот же id
В PDO есть функция lastInsertId http://php.net/manual/ru/pdo.lastinsertid.php
Она возвращает значение MySQL переменной (или функции?) с таким же названием:
http://phpclub.ru/mysql/doc/example-auto-increment.html
https://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_last-insert-id
Эта функция возвращает последний сгенерированный ID в данном сеансе связи, то есть для разных скриптов она вернет разные ID.
Ты можешь проверить ее работу, подсоединившись к MySQL с 2 консолей и сделав 2 вставки, и сделав SELECT LAST_INSERT_ID() в каждой консоли.
Простановку и получение id надо сделать здесь:
> public function saveFile(\Uppy\File $file)
а не в index.php
Вообще я бы код загрузки отсюда https://github.com/tokotun/uppy/blob/master/index.php#L100 тоже бы перенес в Uploader.
Ну и тут еще логическая ошибка:
if (move_uploaded_file($file->tmpName, $target)) {
...
}
$app->response->redirect("file/$file->key", 301);
Получается при ошибке перемещения мы все равно редиректим.
> https://github.com/tokotun/uppy/blob/master/uppy/app/FileMapper.php#L45
> public function getFiles()
здесь ты возвращаешь не полностью заполненные объекты File, причем никакой возможности отличить заполненный от незаполненного объект нету. Это создает путаницу и приводит к ошибкам, вроде такого:
if (!$file->isVideo()) {
// упс, все файлы возвращенные getFiles окажутся не-видео так как поле id3 пусто
}
Надо либо выбирать все поля, либо возвращать не объект, а массив если полей меньше.
Представь себе незаполненные объекты не в простой программе, а в большой программе с десятками таблиц и тысячами функций. Это мина замедленного действия.
> https://github.com/tokotun/uppy/blob/master/uppy/templates/download.html.twig#L63
> (comment.path|length
тут лучше сделать метод comment.getDepth() и тем самым скрыть от шаблона информацию о том, как хранятся комментарии в базе. А то у нас логика хранения комментариев в базе протекает в шаблон, плохо.
> https://github.com/tokotun/uppy/blob/master/uppy/templates/main.html.twig#L15
> file.getSize
тут скобки наверно нужны?
Далее, хотя у тебя путь к сайту вынесен в конфиг, но например путь к бустрапу его не уиывает. Плохо: https://github.com/tokotun/uppy/blob/master/uppy/templates/base.html.twig#L6
Также, он не учитывается при генерации ссылки на картинки.
Я заметил что ты не стремишься вынести пути куда-то отдельно, а пишешь их как придется. Это тебя подведет когда ты например хохочешь поднять боевой и тестовый сервер с разными настройками.
Ты можешь сам проверить этот баг, переименовав папку с сайтом и путь в конфиге, и посмотреть, заработает или нет.
Если не выбрать файла, а нажать кнопку upload, выводится странное сообщение:
> The file no greater than 16384 KB in size. Sorry, there was a problem uploading your file.
Лучше написать, что надо выбрать файл. Также, можно попробовать поставить HTML5 атрибут required: http://htmlbook.ru/html/input/required но я не знаю, работает ли он с файлами.
Если ни одного файла не загружено, страница последних файлов пустая, можно было бы хотя бы
написать «пока ни одного файла не загружено. Хотите [загрузить первый]?».
Далее, папки container нет в гите. Из-за этого если скачать твой проект, он падает при попытке загрузить файл:
> Slim Application Error
> Message: move_uploaded_file(D:\www\host1\tokotun/uppy/container/1 _ 2-red-cats-walk.jpg _): failed to open stream: No such file or directory
В гит конечно нельзя закоммитить пустую папку, так как это система управления файлами, но можно закоммитить файл .placeholder в ней (если бы ты погуглил ты бы сам нашел этот совет).
То же с папкой thumbs
Тут оставил отладочный код: https://github.com/tokotun/uppy/blob/master/uppy/app/functions.php#L5
по моему заголовки нельзя выводить если ты уже вывел какой-то текст.
Если ты хочешь отладить то я советую заменить X-Sendfile на X-Test и убрать Content-Disposition и тогда можно будет отладчиком в браузере смотреть заголовки.
Ну и у меня скачивание не работает, Апач показывает 404: The requested URL /tokotun/index.php was not found on this server.
Я думаю причина либо в пути к файлу (работа относительных путей описана тут: https://tn123.org/mod_xsendfile/ , может лучше использовать путь от корня сайта?) либо в пробелах в имени файла — может их надо кодировать как-то (urlencode?).
У тебя работает скачивание? Или это только у меня не работает?
Далее, при попытке загрузить GIF файл я получаю исключение:
> Message: imagecreatefromjpeg(): gd-jpeg: JPEG library reports unrecoverable error:
Ты не учел что картинки бывают в разных форматах. getImagesize возвращает формат картинки.
превьюшки у меня не отображаются. У тебя отображаются? У них странные имена вроде
> 2 _ 2-red-cats-walk.jpg _
C пробелами. Пробелы, как и другие специсмволы, в ссылках надо кодировать процентным кодированием. Ссылка не может содержать пробелы.
также, тут https://github.com/tokotun/uppy/blob/master/uppy/templates/download.html.twig#L11 2 кавычки подряд идут.
По моему, ты зря вообще добавляешь пробелы в имена. Это только к проблемам приводит. Напиши, работают ли у тебя превьюшки.
Получилось конечно немного сумбурное описание, но общая мысль в том что пока у тебя много багов и приложение пока не работает.
Теперь разберем реализацию MPath, как я понимаю, у тебя путь имеет вид
001.002.005
c ограничением на 1000 комментариев-детей и глубину вложенности 10 (которое нигде не проверяется, как я вижу).
Вот тут довольно хитро вычисляется путь. Ты берешь не максимального ребенка комментария, а максимального потомка:
https://github.com/tokotun/uppy/blob/master/uppy/app/CommentsMapper.php#L62
Было бы наверно гораздо проще, если бы было поле parent_id и мы могли взять максимального из детей с указанным parent_id, и увеличить последнюю цифру в нем. А так, алгоритм конечно работает, но довольно запутанный.
Также, есть другой способ строить путь. В нем мы записываем id комментариев-предков. Так как id типа INT занимает до 10 цифр, то мы используем 16-чную систему счисления, где id займет ровно 8 цифр или символов a-f. Так как длина id фиксированна, разделители необязательны. Если у комментария родители имеют id 00001200, 00023456, а сам комментарий id 0fff1234 то путь имеет вид:
00001200 00023456 0fff1234
Преимущество метода: мы можем из path получить id предков не обращаясь к базе. Минус: нельзя вычислить path, пока мы не сохранили комментарий и не получили id, получаются длинные пути, если мы хотим использовать BIGINT вместо INT то id занимает уже 16 символов, что много.
> https://github.com/tokotun/uppy/blob/master/uppy/app/Uploader.php#L25
> public function resizeImage($filename, $uploadPath, $maxSize = 200)
непонятно зачем передавать второй раз uploadPAth если он есть в конструкторе. Более того, ниже он захардкожен:
> imagejpeg($thumb, "uppy/container/thumbs/$filename");
Надо бы этот префикс uppy/container/ вынести в поле объекта или метод. Нехорошо, что он размазан по всему коду. Есть такой принцип DRY — Don't Repeat Yourself — такие вещи должны быть ровно в 1 месте.
> https://github.com/tokotun/uppy/blob/master/uppy/app/FileMapper.php#L13
> public function getLastId()
Эта функция реализована неправильно. Что, если 2 плоьзователя загружают файлы и 2 скрипта параллельно делают INSERT, а затем каждый вызывает эту функию? Они получат оба один и тот же id
В PDO есть функция lastInsertId http://php.net/manual/ru/pdo.lastinsertid.php
Она возвращает значение MySQL переменной (или функции?) с таким же названием:
http://phpclub.ru/mysql/doc/example-auto-increment.html
https://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_last-insert-id
Эта функция возвращает последний сгенерированный ID в данном сеансе связи, то есть для разных скриптов она вернет разные ID.
Ты можешь проверить ее работу, подсоединившись к MySQL с 2 консолей и сделав 2 вставки, и сделав SELECT LAST_INSERT_ID() в каждой консоли.
Простановку и получение id надо сделать здесь:
> public function saveFile(\Uppy\File $file)
а не в index.php
Вообще я бы код загрузки отсюда https://github.com/tokotun/uppy/blob/master/index.php#L100 тоже бы перенес в Uploader.
Ну и тут еще логическая ошибка:
if (move_uploaded_file($file->tmpName, $target)) {
...
}
$app->response->redirect("file/$file->key", 301);
Получается при ошибке перемещения мы все равно редиректим.
> https://github.com/tokotun/uppy/blob/master/uppy/app/FileMapper.php#L45
> public function getFiles()
здесь ты возвращаешь не полностью заполненные объекты File, причем никакой возможности отличить заполненный от незаполненного объект нету. Это создает путаницу и приводит к ошибкам, вроде такого:
if (!$file->isVideo()) {
// упс, все файлы возвращенные getFiles окажутся не-видео так как поле id3 пусто
}
Надо либо выбирать все поля, либо возвращать не объект, а массив если полей меньше.
Представь себе незаполненные объекты не в простой программе, а в большой программе с десятками таблиц и тысячами функций. Это мина замедленного действия.
> https://github.com/tokotun/uppy/blob/master/uppy/templates/download.html.twig#L63
> (comment.path|length
тут лучше сделать метод comment.getDepth() и тем самым скрыть от шаблона информацию о том, как хранятся комментарии в базе. А то у нас логика хранения комментариев в базе протекает в шаблон, плохо.
> https://github.com/tokotun/uppy/blob/master/uppy/templates/main.html.twig#L15
> file.getSize
тут скобки наверно нужны?
Далее, хотя у тебя путь к сайту вынесен в конфиг, но например путь к бустрапу его не уиывает. Плохо: https://github.com/tokotun/uppy/blob/master/uppy/templates/base.html.twig#L6
Также, он не учитывается при генерации ссылки на картинки.
Я заметил что ты не стремишься вынести пути куда-то отдельно, а пишешь их как придется. Это тебя подведет когда ты например хохочешь поднять боевой и тестовый сервер с разными настройками.
Ты можешь сам проверить этот баг, переименовав папку с сайтом и путь в конфиге, и посмотреть, заработает или нет.
Если не выбрать файла, а нажать кнопку upload, выводится странное сообщение:
> The file no greater than 16384 KB in size. Sorry, there was a problem uploading your file.
Лучше написать, что надо выбрать файл. Также, можно попробовать поставить HTML5 атрибут required: http://htmlbook.ru/html/input/required но я не знаю, работает ли он с файлами.
Если ни одного файла не загружено, страница последних файлов пустая, можно было бы хотя бы
написать «пока ни одного файла не загружено. Хотите [загрузить первый]?».
Далее, папки container нет в гите. Из-за этого если скачать твой проект, он падает при попытке загрузить файл:
> Slim Application Error
> Message: move_uploaded_file(D:\www\host1\tokotun/uppy/container/1 _ 2-red-cats-walk.jpg _): failed to open stream: No such file or directory
В гит конечно нельзя закоммитить пустую папку, так как это система управления файлами, но можно закоммитить файл .placeholder в ней (если бы ты погуглил ты бы сам нашел этот совет).
То же с папкой thumbs
Тут оставил отладочный код: https://github.com/tokotun/uppy/blob/master/uppy/app/functions.php#L5
по моему заголовки нельзя выводить если ты уже вывел какой-то текст.
Если ты хочешь отладить то я советую заменить X-Sendfile на X-Test и убрать Content-Disposition и тогда можно будет отладчиком в браузере смотреть заголовки.
Ну и у меня скачивание не работает, Апач показывает 404: The requested URL /tokotun/index.php was not found on this server.
Я думаю причина либо в пути к файлу (работа относительных путей описана тут: https://tn123.org/mod_xsendfile/ , может лучше использовать путь от корня сайта?) либо в пробелах в имени файла — может их надо кодировать как-то (urlencode?).
У тебя работает скачивание? Или это только у меня не работает?
Далее, при попытке загрузить GIF файл я получаю исключение:
> Message: imagecreatefromjpeg(): gd-jpeg: JPEG library reports unrecoverable error:
Ты не учел что картинки бывают в разных форматах. getImagesize возвращает формат картинки.
превьюшки у меня не отображаются. У тебя отображаются? У них странные имена вроде
> 2 _ 2-red-cats-walk.jpg _
C пробелами. Пробелы, как и другие специсмволы, в ссылках надо кодировать процентным кодированием. Ссылка не может содержать пробелы.
также, тут https://github.com/tokotun/uppy/blob/master/uppy/templates/download.html.twig#L11 2 кавычки подряд идут.
По моему, ты зря вообще добавляешь пробелы в имена. Это только к проблемам приводит. Напиши, работают ли у тебя превьюшки.
Получилось конечно немного сумбурное описание, но общая мысль в том что пока у тебя много багов и приложение пока не работает.
А exit зачем везде ставить? Эта команда завершает скрипт и в оригинальном коде он поставлен для того, чтобы при нахождении даблов код далее не выполнялся и не проверялись другие условия.
У тебя в коде сейчас этого нет и вот что получается: http://ideone.com/1B2caC
> У тебя выпало 2 и 2
> У компьютера выпало 4 и 4
> Дабл! Ты победил!
> Поражение!
> нет пробела и выглядит убого
Ты \n или пробел забыл вписать в echo
Еще по коду, имена переменных принято писать с первой маленькой буквы.
Ну и можешь не беспокоиться по поводу того что ты делаешь ошибки, для начинающего это нормально.
А что плохого в md5? Есть какие-то серьезные аргументы против него? Не на уровне «я слышал что он старый и надо использовать bcrypt».
>>465994
> Так сразу не могу представить как и главное куда правильнее слать запрос.
В MVC все запросы обрабатывают контроллеры. Аякс запрос отличается от обычного только тем что ты после обработки не выводишь шаблон, а отдаешь JSON в ответ. В остальном все точно так же. Называть его ajax не обязательно, лучше например /articles/getAll или как-то так.
>>466045
Лучше поискать готовый скрипт. Ты не можешь от таблицы оторвать шапку и там создается вторая невидимая таблица с такой же шапкой и она показывается/скрывается когда надо ее закрепить. Если есть время и желание попрактиковаться, можешь сделать такой плагин к jquery сам, я даже могу подсказать (ну вот уже идею реализации подсказал), но только если ты уже знаешь JS, DOM, jQUery, иначе сначала надо изучить это.
>>466061
Твой скрипт не делает то, что анон просил. Переитай пост. И там есть еще одна плохо сделанная вещь: ты при каждом событии scroll пишешь в DOM. Если барузер шлет событие scoll 60 раз в секунду, ты 60 раз пишешь в DOM. По идее конечно если класс уже есть, браузер не должен ничего делать, но на практике я видел что бразеры делают reflow/repaint и при тяжелой верстке это прилично тормозит прокрутку.
Потому лучше завести переменную, хранящую состояние шапки и если оно не поменялось то ничего не делать.
также, проверку hasClass можно вынести в переменную.
Также, вместо числа 200 лучше определять высоту меню через height() и не забывать ее пересчитывать при событии resize() окна. С браузером ты почти никогда не знаешь высоту элемента заранее.
В общем, хорошо что ты хотел помочь, но это не лучший скрипт, учитывая что ты вбросил его в тред для начинающих, желающих научиться писать правильный код.
Ну и то что делает твой скрипт в будущих браузерах будет делаться через position: sticky
>>466107
Я не работал с ним, но ты документацию читал? Там этого нет?
Токенайзеры скорее всего разбивают текст на слова, но я бы сверился с доками.
А что плохого в md5? Есть какие-то серьезные аргументы против него? Не на уровне «я слышал что он старый и надо использовать bcrypt».
>>465994
> Так сразу не могу представить как и главное куда правильнее слать запрос.
В MVC все запросы обрабатывают контроллеры. Аякс запрос отличается от обычного только тем что ты после обработки не выводишь шаблон, а отдаешь JSON в ответ. В остальном все точно так же. Называть его ajax не обязательно, лучше например /articles/getAll или как-то так.
>>466045
Лучше поискать готовый скрипт. Ты не можешь от таблицы оторвать шапку и там создается вторая невидимая таблица с такой же шапкой и она показывается/скрывается когда надо ее закрепить. Если есть время и желание попрактиковаться, можешь сделать такой плагин к jquery сам, я даже могу подсказать (ну вот уже идею реализации подсказал), но только если ты уже знаешь JS, DOM, jQUery, иначе сначала надо изучить это.
>>466061
Твой скрипт не делает то, что анон просил. Переитай пост. И там есть еще одна плохо сделанная вещь: ты при каждом событии scroll пишешь в DOM. Если барузер шлет событие scoll 60 раз в секунду, ты 60 раз пишешь в DOM. По идее конечно если класс уже есть, браузер не должен ничего делать, но на практике я видел что бразеры делают reflow/repaint и при тяжелой верстке это прилично тормозит прокрутку.
Потому лучше завести переменную, хранящую состояние шапки и если оно не поменялось то ничего не делать.
также, проверку hasClass можно вынести в переменную.
Также, вместо числа 200 лучше определять высоту меню через height() и не забывать ее пересчитывать при событии resize() окна. С браузером ты почти никогда не знаешь высоту элемента заранее.
В общем, хорошо что ты хотел помочь, но это не лучший скрипт, учитывая что ты вбросил его в тред для начинающих, желающих научиться писать правильный код.
Ну и то что делает твой скрипт в будущих браузерах будет делаться через position: sticky
>>466107
Я не работал с ним, но ты документацию читал? Там этого нет?
Токенайзеры скорее всего разбивают текст на слова, но я бы сверился с доками.
Не могу выполнить вторую задачку на массивы (про рост школьников), я безнадежен?
Все остальные задачи с этой страницы выполнил легко.
> — дан текст, в нем может быть (а может не быть) записан адрес сайта (начинается с http:// или https://, дальше содержит любые символы кроме пробела, символов должно быть не менее 3)
Тоже решил решить эту задучу, вроде верно http://ideone.com/wICFv8
>>465198
> Надо сделать проще, регулярку примерно такого вида:
> в начале +7 или 8
Это просто.
> за ней 10 цифр между которыми могут быть скобки, минусы, пробелы.
А это в голове не укладываеться. Как проверить что там 10 цифр?
http://ideone.com/FUAf5G
Спасибо.
http://ideone.com/GcMV5i
>>466133
Там же пример выше есть, пиши [0-9]{10}.
> Там же пример выше есть, пиши [0-9]{10}.
Это не будет работать если записано так 566-566-888-1 к примеру.
Ну так подумай, что с возможными скобками, пробелами и тире делать. Дам маленькую подсказку, необязательно писать сразу [0-9]{10}, можно эти десять цифр на несколько частей разделить.
<table>
<tr>
<td><form name='form1'></form></td>
<td><form name='form2'></form></td>
</tr>
</table>
Сейчас прохожу обучение из шапки сразу 2 вопроса:
дан набор массивов:
$word1 = ...;
$word2 = ...;
$word3 = ...;
.
.
.
$word10 = ...;
Можно ли как то выполнить в цикле конструкцию $word{$i}?
т.е.
for ($i = 1; i>11; i++) {
$wrd{i} = $word{i}()...;
}
Или у меня руки из жопы? Как правильно то?
2)В конструкции preg_split("//u",....
Что за ключ /u и какие ещё есть?
Не понял что ты хочешь, но для массивов есть специальный цикл foreach, который работает пока все ячейки в массиве не кончатся.
в обучашке есть задание - дано 5 массивов где в каждой ячейке по слову. Нужно из каждого массива выбрать рандомное слово и сложить в стих. Так вот я хотел замутить решение с помощью циклов а не чемто вроде
error_reporting(-1);
$word1 = array('Чудесных', 'Суровых', 'Занятных', 'Внезапных');
$word2 = array('слов', 'зим', 'глаз', 'дней', 'лет', 'мир', 'взор');
$word3 = array('прикосновений', 'поползновений', 'судьбы явлений',
'сухие листья', 'морщины смерти', 'долины края', 'замены нету',
'сухая юность', 'навек исчезнув');
$word4 = array('обретаю', 'понимаю', 'начертаю', 'закрываю', 'оставляю',
'вынимаю', 'умираю', 'замерзаю', 'выделяю');
$word5 = array('очертания', 'безысходность', 'начертанья', 'смысл жизни',
'вирус смерти', 'радость мира');
$rnd1 = mt_rand(1,count($word1));
$rnd2 = mt_rand(1,count($word2));
$rnd3 = mt_rand(1,count($word3));
$rnd4 = mt_rand(1,count($word4));
$rnd5 = mt_rand(1,count($word5));
$rnd6 = mt_rand(1,count($word1));
$rnd7 = mt_rand(1,count($word2));
$rnd8 = mt_rand(1,count($word3));
$wrd1 = $word1[$rnd1];
$wrd2 = $word2[$rnd2];
$wrd3 = $word3[$rnd3];
$wrd4 = $word4[$rnd4];
$wrd5 = $word5[$rnd5];
$wrd6 = $word1[$rnd6];
$wrd7 = $word2[$rnd7];
$wrd8 = $word3[$rnd8];
$str1 = $wrd1 . " " . $wrd2 . " " . $wrd3;
$str2 = $wrd6 . " " . $wrd7 . " " . $wrd8;
$str3 = $wrd4 . " " . $wrd5;
echo "$str1\n$str2\nЯ $str3";
в обучашке есть задание - дано 5 массивов где в каждой ячейке по слову. Нужно из каждого массива выбрать рандомное слово и сложить в стих. Так вот я хотел замутить решение с помощью циклов а не чемто вроде
error_reporting(-1);
$word1 = array('Чудесных', 'Суровых', 'Занятных', 'Внезапных');
$word2 = array('слов', 'зим', 'глаз', 'дней', 'лет', 'мир', 'взор');
$word3 = array('прикосновений', 'поползновений', 'судьбы явлений',
'сухие листья', 'морщины смерти', 'долины края', 'замены нету',
'сухая юность', 'навек исчезнув');
$word4 = array('обретаю', 'понимаю', 'начертаю', 'закрываю', 'оставляю',
'вынимаю', 'умираю', 'замерзаю', 'выделяю');
$word5 = array('очертания', 'безысходность', 'начертанья', 'смысл жизни',
'вирус смерти', 'радость мира');
$rnd1 = mt_rand(1,count($word1));
$rnd2 = mt_rand(1,count($word2));
$rnd3 = mt_rand(1,count($word3));
$rnd4 = mt_rand(1,count($word4));
$rnd5 = mt_rand(1,count($word5));
$rnd6 = mt_rand(1,count($word1));
$rnd7 = mt_rand(1,count($word2));
$rnd8 = mt_rand(1,count($word3));
$wrd1 = $word1[$rnd1];
$wrd2 = $word2[$rnd2];
$wrd3 = $word3[$rnd3];
$wrd4 = $word4[$rnd4];
$wrd5 = $word5[$rnd5];
$wrd6 = $word1[$rnd6];
$wrd7 = $word2[$rnd7];
$wrd8 = $word3[$rnd8];
$str1 = $wrd1 . " " . $wrd2 . " " . $wrd3;
$str2 = $wrd6 . " " . $wrd7 . " " . $wrd8;
$str3 = $wrd4 . " " . $wrd5;
echo "$str1\n$str2\nЯ $str3";
Используй array_rand же. Он возвращает значение случайного ключа массива. Тоже помнится с этой задачкой застопорился, пока не нашел эту функцию.
http://php.net/manual/ru/function.array-rand.php
Спасибо, анон! Странно, что этого нет в гайде. А по ключикам не подскажешь?
>В конструкции preg_split("//u",....
Что за ключ /u и какие ещё есть?
Хз, особо в подробности не вдавался, знаю только что они на все регулярное выражение действуют. u позволяет с кириллицей работать, а i делает все выражение регистронезависимым. Других не знаю пока.
Например, юзер ввел в логине недопустимые символы, как юзеру об этом сказать без js?
спасибо, брат.
Задача про расшифровочку.
http://ideone.com/EmMB7U
И про Льва толстого
Пошел кушать рисовый омлетик
*Толстого. Лол, как смысл сразу поменялся.
> !^(-|\s\(|\(|\s\(\s|)!
Где тут знак вопроса поставить, чтобы мол всех этих значений может и не быть?
> !^((-|\s\(|\(|\s\(\s|)?)!
Так?
> А это в голове не укладываеться. Как проверить что там 10 цифр?
Все ОП я здаюсь, не представляю как решить эту задачу, каждый раз когда хочу сделать проще, регулярка получаеться еще сложнее и в итоге нехера не работает.
http://ideone.com/ryNIXt
поверят правильность через условия, если условия не выполняются else { error}
ну ты понял в чем суть
> дан набор массивов:
Не делай 10 однотипынх переменных, делай массив из 10 элементов:
$word[1] = ...
$word[2] = ...
> Что за ключ /u и какие ещё есть?
Ключ u говорит что мы используем текст и выражение в кодировке utf-8. Без него русские буквы (и другие не входящие в ascii символы) не будут работать или будут работать через раз.
Полный список флагов в мануале: http://php.net/manual/ru/reference.pcre.pattern.modifiers.php
Из интересных например есть флаг i который говорит что при сравнении надо игнорировать регистр символов.
Спасибо за понятный и подробный ответ!
preg_split('//u' работает примерно так:
Функция preg_split находит подстроки соответствующие регулярке, и разбивает строку, вырезая их, на куски.
пустое регулярное выражение // соответствует промежуткам между буквами и краям выражения (оно соответствует именно промежуткам между буквами, а не буквам, чтобы оно соответствовало буквам надо писать /./)
соответственно split разбивает строку по эти границам:
abcde -> |a|b|c|d|e| -> ['', 'a', 'b', 'c', 'd', 'e', '']
Флаг u нужен чтобы строка разбивалась по границам букв, без него она разобьется по границам байтов и будут не буквы, а битые куски букв (в utf-8 русская буква состоит из 2 байтов).
Флаг NO_EMPTY позволяет удалить из массива крайние 2 пустых строки. Он описан в мануале: http://php.net/manual/ru/function.preg-split.php
Анон ты душка :3
Проще всего совместить их в одном файле и сделать как описано в моем уроке про формы. там описан универсальный алгоритм: https://github.com/codedokode/pasta/blob/master/forms.md
>>466216
Знак вопроса ставится после буквы или скобок которых может не быть:
abc? — буква с может быть, может не быть
a(bc)? — буквы bc могут либо обе быть, либо обе не быть
В твоем коде это смотрится странно:
(\s|)
зачем тут вертикальная линия? Если ты хочешь написать что пробел необязателен можно написать \s?
>>466133
> задача про URL
> (htt(p|ps)
Что так сложно? Пиши просто
https?
> |(^$)
Что это значит? Пустая строка?
> [\S]
Тут скобки не оьязательны. \S можно использовать сам по себе
Вот он URL с пробелами внутри считает праивльным: http://ideone.com/c140yR
Проще всего совместить их в одном файле и сделать как описано в моем уроке про формы. там описан универсальный алгоритм: https://github.com/codedokode/pasta/blob/master/forms.md
>>466216
Знак вопроса ставится после буквы или скобок которых может не быть:
abc? — буква с может быть, может не быть
a(bc)? — буквы bc могут либо обе быть, либо обе не быть
В твоем коде это смотрится странно:
(\s|)
зачем тут вертикальная линия? Если ты хочешь написать что пробел необязателен можно написать \s?
>>466133
> задача про URL
> (htt(p|ps)
Что так сложно? Пиши просто
https?
> |(^$)
Что это значит? Пустая строка?
> [\S]
Тут скобки не оьязательны. \S можно использовать сам по себе
Вот он URL с пробелами внутри считает праивльным: http://ideone.com/c140yR
>Шедевр верстки из прошлого века.
лучше все равно ничего не придумано, это хоть работает как ак-47.
> Что так сложно? Пиши просто
Без первой скобочки?
> Что это значит? Пустая строка?
Да.
> Вот он URL с пробелами внутри считает праивльным
Почему \S не работает?
> if (preg_match_all($regexpWord, $text, $error)) {
preg_match_all не надо писать внутри if, так как если она ничего не найдет, будет просто пустой массив и цикл не выполнится
> [^a-zA-Z]
это найдет ввобще все, что не является латинской буквой, то есть цифры, запятые, пробелы, и т.д.
> $regexpWord = ....
Что-то это выражение какое-то сложное. по моему ты его переусложнил. Можно просто написать выражение
(любые буквы)(латинская, за ней русская или русская, за ней латинская)(любые буквы)
> $engSymbols = array
> $rusSymbols = array
Такие пары букв лучше писать в один массив чтобы было видно какая какой соответствует:
$letters = array(
'a' => 'a',
'o' => 'o',
...
);
А так, неплохо, программа работает вроде.
> Задача про расшифровочку.
Хорошо, все правильно
> про Льва толстого
Тоже все верно.
>>466226
Тут что-то сложное и запутанное. надо просто написать что 10 раз повторяется такая штука:
1 цифра + доп. символы
>>466241
Все правильно решено, только при первом же несовпадении можно выходить из цикла, незачем остальные буквы проверять.
>>466271
Придумано, прочитай про CSS. Во-первых, ты можешь в CSS сделать то же через display: table, во-вторых, тут вообще больше подошло бы inline-block или float
Таблицы использовать для задания расположения блоков недопустимо, таблицы используются только для верстки самих таблиц.
>>466275
> Без первой скобочки?
Не знаю, смотри по ситуации
> Почему \S не работает?
Он работает, у тебя просто нет условия что регулярка должна доходить до конца строки
>>466289
Число 5000 повторяется много раз и неудобно его менять. Надо вынести его в переменную. Также, переменную с ценой лучше вынести из функции наружу, чтобы получилась универсальная функция.
> $price = $price + ($price * $creditPerc / 100) + $commission;
Эта строка повторяется 2 раза. Попробуй избавиться от повторов.
Также, у тебя там ошибка внизу:
> PHP Notice: Undefined variable: summ in /home/aeJ8We/prog.php on line 14
Ты используешь переменную до того как создал ее.
$sum += 5000 равносильно $sum = $sum + 5000 и в первый раз переменная $sum еще не существует и php не может вычислить правую часть выражения.
> Задача про расшифровочку.
Хорошо, все правильно
> про Льва толстого
Тоже все верно.
>>466226
Тут что-то сложное и запутанное. надо просто написать что 10 раз повторяется такая штука:
1 цифра + доп. символы
>>466241
Все правильно решено, только при первом же несовпадении можно выходить из цикла, незачем остальные буквы проверять.
>>466271
Придумано, прочитай про CSS. Во-первых, ты можешь в CSS сделать то же через display: table, во-вторых, тут вообще больше подошло бы inline-block или float
Таблицы использовать для задания расположения блоков недопустимо, таблицы используются только для верстки самих таблиц.
>>466275
> Без первой скобочки?
Не знаю, смотри по ситуации
> Почему \S не работает?
Он работает, у тебя просто нет условия что регулярка должна доходить до конца строки
>>466289
Число 5000 повторяется много раз и неудобно его менять. Надо вынести его в переменную. Также, переменную с ценой лучше вынести из функции наружу, чтобы получилась универсальная функция.
> $price = $price + ($price * $creditPerc / 100) + $commission;
Эта строка повторяется 2 раза. Попробуй избавиться от повторов.
Также, у тебя там ошибка внизу:
> PHP Notice: Undefined variable: summ in /home/aeJ8We/prog.php on line 14
Ты используешь переменную до того как создал ее.
$sum += 5000 равносильно $sum = $sum + 5000 и в первый раз переменная $sum еще не существует и php не может вычислить правую часть выражения.
Есть один код на js с использованием jquery
https://ideone.com/pMVx3H
Всё работает, в конце становиться всё на места, и изображение тоже имеет класс edit, но теперь по клику на него ничего не происходит. Как быть, чтобы функция была многоразовая?
Спасибо большое, анон! И тут же вопрос:
>На тот случай, если ты не изучал протокол HTTP (что плохо)
Что именно стоит почитать? Если не сложно, можешь статейку кинуть какую-нибудь для ознакомления с этим вот всем?
>display: table
мне нравится когда тыкнул ктрл+шифт+и в нужном месте и сразу видишь как все устроено, а не чистишь вилкой в свойствах где там флоат, где дисплей.
>inline-block
пердолинг с вертикальным выравниванием неравных по высоте элементов, пердолинг с пробелами
>float
вырывание из потока, клеарфикс и оверфлоу-костыли, пердолинг с фоном.
и если говорить о семантике флоат как и таблицы тоже не для верстки блоков придуман, а чтоб текст картинку обтекал.
так что пока в3с не завезут нативный грид пусть пердолятся сами с собой.
> Он работает, у тебя просто нет условия что регулярка должна доходить до конца строки
\S+ разве не должно находить все что угодно, кроме пробела?
http://ideone.com/BMhOf0
>preg_match_all не надо писать внутри if
В смысле? Если он ничего не находит, то просто переходит к else и выводит "Ошибок не найдено".
>(любые буквы)(латинская, за ней русская или русская, за ней латинская)(любые буквы)
Можешь в рабочем виде написать? А то чет я не понимаю, как оно выглядеть должно. В том виде что я пишу неправильно работает.
http://ideone.com/xLZcFJ
Алсо, добавить забыл. Как ошибки исправлять то, если массив с симолами один будет? Там же нужно два разных указывать, не?
вопрос такой
как сделать цикл по данным массива
чтоб определял сколько из них больше определеного значения
Все, уже разобрался.
Создаешь цикл foreach, в котором на каждой ступени рост анона сравниваешь с ростом другого школьника и если рост школьника выше, то увеличиваешь значение $i на 1. Потом выводишь значение $i и вот тебе кол-во школьников, которые выше анона.
Анон, я конечно могу за тебя код написать, но смысл? Главное ведь, чтобы ты понимал как делать. Открой уроки про циклы и массивы, почитай их, посмотри на похожие примеры и все поймешь.
Но вообще там же есть уже массив foreach вроде, просто добавь проверку на то, что если рост анона меньше, то $number++.
Напиши пожалуйста чтоб я понял свою ошибку и мог на других примерах испытать свои силы после этого
ты просто наверно CSS не знаешь если для тебя 2 флоата или инлайн блока сверстать проблема. При чем тут инспектор в браузере? Он флоаты точно так же показывает.
Про то почему таблицы это плохо последние 15 лет на всех сайтах пишут и мне пересказывать нет смысла. Ты просто не знаешь или ленишься изучать CSS. Оставайся в своем 2000 году без нас.
>>466364
Ну он и находит до первого пробела, а дальше уже не проверяет. preg_match не проверяет по умолчанию, всю строку, ему достаточно частичного совпадения.
То есть регулярка /ab/u сработает со строкой 23456abvvddd
>>466412
Заводишь переменную, кладешь в нее 0. Когда находишь школьника выше анона, увеличиваешь ее на 1.
> foreach ($number = 0; $anonHeight<=$height; $number++)
c 3 командами пишется for, а не foreach
http://php.net/manual/ru/control-structures.for.php
http://php.net/manual/ru/control-structures.foreach.php
http://ideone.com/XwfuBh
Я вчера как-то решил красиво задачку про айфон в кредит. Сегодня уже не могу. Мне кажется,можно как-то проще сделать, чтобы выполнять цикл до какого-то действия.
ЧЯДНТ?
Проходи курсы на HTML Academy. Наверное один из самых легких и быстрых способов освоить HTML. Вот бы для PHP кто-нибудь подобное запилил.
Wow, fascinating!
Обязательно пройду в ближайшие дни. Но сейчас нужен именно мануал по блочной верстке, краткий, но информативный. Как справочник.
Просто у меня сейчас есть работа, которую нужно сделать. Поверхностное понимание блоков есть, как и всего css, html, но его недостаточно, сейчас очень нуждаюсь именно в кратком, информативном мануальчике по блочной верстке. Гугл выдает какую-то малополезную хуйню, вот и заскочил к вам на огонек, может есть у кого что-то полезное по теме.
Но, блядь, HTML Academy просто 10 из 10, анон!
Мануала у меня нет. Спрашивай, что конкретно не понятно. Блочная верстка проще пареной репы же.
У меня блоки накладываются друг на друга и я не знаю как мне расположить хедер, футер, левый блок, центральный и правый, чтобы они стояли на своих местах и можно было бы заняться конкретно их внешним видом.
Честно, подзабыл уже HTML/CSS, но насколько я помню я указывал им размеры, затем выставлял в ряд через float:left и отступами расставлял их так, как нужно.
Да, почему нет? Может это конечно и не особо правильно ( честно говоря я не в курсе), но зато железно работает.
Охренеть. Сотни нефти тебе, анон, и сотни заказов с адекватными заказчиками. Спасибо!
https://ideone.com/VAajeT
Насколько это корректно? Какие есть решения поэлегантнее?
Хорошая попытка, Сатана, но Черную Библию я читать не буду.
http://ideone.com/oZQjP5
> Ну он и находит до первого пробела, а дальше уже не проверяет. preg_match не проверяет по умолчанию, всю строку, ему достаточно частичного совпадения.
Вот переделал http://ideone.com/Ogt3XN и еще больше запутался.
Разве это регулятора не ограничивает строку до htt(p|ps):// + 3 любых символа и все, почему она вообще все не забраковала? $ говорит ведь что мол все конец?
> !^htt(p|ps)://([^\s]+){3}$|(^$)!
Просто я все же хочу научиться сайты делать, а не задачки на PHP решать. В общем, много ли я потеряю, если не буду их выполнять?
Эта тема называется позиционирование. Вот (один из) учебников рассказывающий про то какие есть способы располагать блоки: http://softwaremaniacs.org/blog/category/primer/ (читать снизу вверх)
>>466534
Там есть сложные для начинающих моменты вроде флоатов, позиционирования, и тд.
>>466545
Тебе надо нормально изучить позиционирование, а не ставить свойства от балды.
>>466548
Надо знать CSS а не ставить свойства наугад.
Они служат несколькими целям: попрактиковаться с использованием ранее изученных вещей (циклов, массивов, функций), научиться разбивать код на функции и писать код большего объема (особенно в задаче про числа), я с их помощью могу выявить пробелы в знаниях. Так что думаю, имеют. Если ты прекрасно знаешь ранее пройденные темы, ты их минут за 20-30 решишь каждую (это же немного?), если плохо знаешь, то конечно придется подольше помучаться.
Но ты можешь запостить решения на проверку и не тратя времени, сразу переходить к следующим темам.
По моим впечатлениям, мало кто может задачу про числа прописью решить правильно и аккуратно с первого раза. Обычно там достаточно много замечаний набирается. Люди городят сложные конструкции, прибегают к копипасте и лучше всего такие ошибки исправлять на раннем этапе, пока они не привыкли так писать, потому что в задачах на сайты кода будет еще больше.
Так что если ты их выполнишь, ты будешь более легко и свободно пользоваться разными возможностями php. А если пропустишь, наверняка у тебя останутся пробелы в знаниях. и будет довлоьно глупо при выполнении более сложных задач на них спотыкаться.
А что ты хотел сказать такой сложной конструкцией?
([^\s]+){3}
В-первых, [^\s] короче пишется как \S (большая буква вместо маленькой)
Во-вторых, что значит {3}? Выражение в скобках должно сработать ровно 3 раза? Почему ровно 3?
Чтобы написать «3 или больше не-пробельных символов» есть конструкция {3,}. На худой конец можно написать что-то вроде \S{3}\S× (× это звездочка)
Чтобы написать «ровно 3 не-пробельных символа» надо писать
\S{3}
У меня есть ощущение что ты переставляешь конструкции наугад в надежде что код заработает (я подумал так, потому что ты пишешь усложненное выражение, которое можно записать проще). Это плохая идея. Если что-то еще непонятно, задавай вопросы.
Вот тебе еще страница мануала в помощь: http://php.net/manual/ru/regexp.reference.repetition.php
> Разве это регулятора не ограничивает строку до htt(p|ps):// + 3 любых символа
Твоя конструкция значит «содержимое скобок должно совпасть ровно 3 раза», и она равносильна такому выражению:
([^\s]+){3} => (\S+){3} => \S+\S+\S+
это выражение соответствует не ровно 3, а 3 и больше символам. Но его можно было записать в более простой форме.
А что ты хотел сказать такой сложной конструкцией?
([^\s]+){3}
В-первых, [^\s] короче пишется как \S (большая буква вместо маленькой)
Во-вторых, что значит {3}? Выражение в скобках должно сработать ровно 3 раза? Почему ровно 3?
Чтобы написать «3 или больше не-пробельных символов» есть конструкция {3,}. На худой конец можно написать что-то вроде \S{3}\S× (× это звездочка)
Чтобы написать «ровно 3 не-пробельных символа» надо писать
\S{3}
У меня есть ощущение что ты переставляешь конструкции наугад в надежде что код заработает (я подумал так, потому что ты пишешь усложненное выражение, которое можно записать проще). Это плохая идея. Если что-то еще непонятно, задавай вопросы.
Вот тебе еще страница мануала в помощь: http://php.net/manual/ru/regexp.reference.repetition.php
> Разве это регулятора не ограничивает строку до htt(p|ps):// + 3 любых символа
Твоя конструкция значит «содержимое скобок должно совпасть ровно 3 раза», и она равносильна такому выражению:
([^\s]+){3} => (\S+){3} => \S+\S+\S+
это выражение соответствует не ровно 3, а 3 и больше символам. Но его можно было записать в более простой форме.
Посчитай внимательно число и расположение фигурных скобок {}. У тебя открывающих больше чем закрывающих.
Если бы ты правильно ставил отступы в коде (делая тело цикла и if с отступом) то отстутсвующая скобка была бы видна невооруженным глазом. Поэтому надо стараться выравнивать код правильно.
> Мне кажется,можно как-то проще сделать, чтобы выполнять цикл до какого-то действия.
да, ты можешь выйти из цикла через команду break, например если долг дошел до нуля.
Ну я примерное представление имею о том, как оно все должно делаться. Просто я бы лучше попрактиковался делая что-нибудь такое, что реально пригодится в создании сайтов.
HTML/CSS не хочешь поизучать? У нас есть задания на верстку, но там тоже длинный путь получается, аж 13 задач.
Также есть задачки на JS/DOM/jQuery, но там тоже вначале придется просто с JS возиться на простых задачках.
Ну и я не думаю, что это не пригодится. Это задания на закрепление знаний PHP, а на PHP кода писать надо будет много. И если начинающий обычно делает ошибки в коде на 200 строк (числа прописью) , сколько он их сделает в коде на 5000 строк? Или ты планируешь сайты без использования PHP писать? Тогда HTML/CSS/JS изучай пока.
Просто без хороших знаний самого PHP ты будешь спотыкаться при решении более сложных задач. Они ведь предполагают, что ты его хорошо знаешь. Если хочешь, почитай сам следующие уроки и посмотри какие там задачи.
Да HTML я знаю более-менее, даж несколько сайтов сверстал. Вот например один из первых http://kinoruletka.hol.es/. Надо только освежить память как-нибудь, по-быстрому перепройдя курс.
JS и фреймворки всякие потом изучать буду, когда PHP выучу.
Ладно, похуй, сделаю я эти задачки. Подскажи только, как эти самые числа вычленять, а то я чет не догоняю. Ну т.е. с последними и первыми цифрами все ясно, а что делать с теми, которые посередине?
Я тут, как то отписал что меня могут взять на работу с Симфони2 при этом сам я где-то на уровне задачи ОПа с Йии2.
Так вот меня согласились взять, но сказали 3 мясяца испытательный срок и никаких документов, зарплату якобы выплатят.
Но я ни одной бумажки не подписал и деЮре 3 дня уже работаю за спасибо.
Котора эта по сути ИП и 3 человека,мне сказали сделать карточку сберавскую для зарплаты.
Вообще все это очень мутно, но с другой стороны смысла наебывать меня немного, так как пока я мало пользы приношу.
Что думаете, товарищи?
Ну я вот тоже думаю до конца месяца потусоваться, полезно же поработать и на симфони покодить, пусть и бесплатно.
Ты прав, всё лучше чем сидеть как сыч
Элсо по хорошему на собеседования в рашкоконторы приходить с диктофоном и записывать, потом найти людей которые смогут подтвердить, что ты там работал. Потом, если тебе не платят стучаться во все инстанции (Суд, трудовая комисия, налоговая) твой начальник будет готов выложить неплохие деньги за то, чтобы ты заявы забрал, а если и нет, то сможешь понаблюдать за весёлой клоунадой и богровой рожи горе - ип
Это просто, вот 2 волшебных команды:
// получить последние 3 цифры числа:
echo 1234567 % 1000; // выведет 567
// получить число миллионов
echo floor(1234678 / 1000000); // выведет 12
Комбинируя их, можно получить что угодно.
Соответственно ты можешь сначала отрезать N последних цифр, а потом M первых от них.
>>466640
Если без документов то конечно могут и не выплатить. зачем платить, если можно не платить? Или могут заплатить, но меньше. Ты отзывы по названию компании, по контактам и по фамилии директора не пробовал гуглить?
Имей также в виду, что по нашему законодательству, даже если не заключен договор, но ты ходил 3 месяца на работу, то он считается как бы заключенным и в суде работодатель не отвертится. А трудовая инспекция может заинтересоваться и провести проверку для предпринимателя, практикующего серые и черные зарплаты. Там наверняка еще много чего интересного выяснится.
Ну и почитай сайты-черные списки вроде antijob.net, там много прохладных историй можно найти. Также могут быть какие-то отзывы на местных форумах.
Так что я не знаю, что посоветовать. Симфони за бесплатно можно и дома изучать. Я работал без оформления, но там зарплата была 2 раза в месяц и ее ни разу не задерживали.
А изучить верстку не пробовал? Там просто фиксированная ширина прописана.
Блоки лезут если они сверстаны неправильно. Увеличение масштаба равносильно уменьшению ширины окна и хорошая верстка от этого не ломается.
Потому мой совет тебе не копировать сомнительное решение с ленты, а лучше изучить CSS.
>>466649
У нас есть задачи (в шапке треда) и есть хороший учебник learn.javascript.ru с теорией. Если что-то непонятно, можешь задавать вопросы.
>>466651
Бесплатно и дома можно кодить, с большим комфортом.
>>466653
Да, трудовая инспекция и налоговая могут заинтересоваться таким бизнесом, и я подозреваю что нарушений там можно найти на гораздо большую сумму чем сэкономленная зарплата анона. Суд тут менее полезен, через него можно только зарплату назад отсудить и все.
Ну и как всегда напомню, аноны, чем больше вы знаете и умеете, тем больше у вас выбор компаний, куда вы можете попасть.так что учитесь хорошо.
Спасибо.
Это потому что тут написано, что цифры должна идти 10 раз подряд без знаков между ними. Но ты можешь переделать это выражение на
(цифра + любое число знаков) повторяется 10 раз подряд
>>466226
Не сдавайся. Чем дольше ты сражаешься с регулярными выражениями, тем лучше узнаешь врага.
Тут выражение нерабочее. Посмотри сам:
вначале у тебя идет условие что должны быть 3 или 4 цифры в коде города
затем 1, 2, 3 или 7 цифр
Это не гарантирует что после 8 там будет ровно 10 цифр.
Я думаю, лучше сделать такое условие:
— вначале 7 или +8
— за ней ровно 10 цифр, между которыми могут быть другие символы (скобки, минусы, пробелы) в любом количестве
> $price = $price + ($creditPerc × 4 / 100)
зачем проценты умножаешь на 4? Неправильно же. Надо прибавлять (долг × процент / 100)
В yobabank должно получаться 61268 если ты не поменял процент и комиссию, у тебя вышло меньше чем должно.
Ты можешь проверить на более простой сумме. Например если сумму кредита сделать 4000 то полная выплата в yobabank будет около 6120 (это легко проверить, посчитав кредит вручную или в екселе).
> $pay = 5000;
Я думаю, эту переменную красивее будет вынести из функции, тогда у нас в функцию можно будет передать любое значение
> calcCreditSum(2, 0, 39999) + 7777;
Прибавлять надо не после всех выплат, а до. В твоем случае на эти 7777 не начисляются проценты и комиссия.
>— за ней ровно 10 цифр, между которыми могут быть другие символы (скобки, минусы, пробелы) в любом количестве
+8())(()()(---
Какой ужасный код, как тяжело его читать. Это из-за того что все написано в одну длинную строчку, куча скобок, точек и кавычек, и HTML смешан с JS. Более того, там еще обработчики событий вложены друг в друга.
Этот код отвратителен и я очень надеюсь что он не используется в реальном проекте. Я советую сделать рефакторинг и сделать аккуратный код без вложенных друг в друга функций и кучи точек в одной строке.
> в конце становиться всё на места, и изображение тоже имеет класс edit, но теперь по клику на него ничего не происходит.
Потому что ты удаляешь из DOM старый элемент .edit и с ним вместе удаляется обработчик события который ты на него навесил. Либо навешивай его заново, либо используй делегацию событий, по моему через on, когда обработчик ставится не на сам элемент, а выше и ловит всплывающие события.
> .trigger("focus");
Что за ерунда? ЧТобы поставить курсор в поле есть метод focus()
Ты в курсе что в российском суде не принимаются в кач-ве вещдоков аудиозаписи если ее участники не предупреждены?
О, вот это платиновый вопрос, потому что я не знаю ни одной нормальной полной и понятной русскоязычной статьи про HTTP (но это не значит что их нет, я просто про них не знаю).
Вот что можно почитать:
http://habrahabr.ru/post/215117/
http://portscan.ru/article-protocol-http.html
https://ru.wikipedia.org/wiki/HTTP
Слова, которые ты должен знать и понимать из HTTP: клиент, сервер, метод HTTP (GET/POST), ресурс, заголовки ответа, заголовки запроса, HTTP код ответа, перенаправление, куки. Ну и хорошо бы представлять как происходит загрузка страницы, отправка формы с испльзованием протокола HTTP.
Увидеть HTTP-запросы в браузере проще всего нажав Ctrl + Shift + I, перейдя на влкадку Network и открыв любой сайт.
Хорошо бы также уметь телнетом подсоединиться к какому-нибудь сайту на порт 80 и вручную отправить запрос для получения заглавной страницы сайта.
>>preg_match_all не надо писать внутри if
> В смысле? Если он ничего не находит, то просто переходит к else и выводит "Ошибок не найдено".
Гм. Ну пусть тогда if остается.
>>(любые буквы)(латинская, за ней русская или русская, за ней латинская)(любые буквы)
> Можешь в рабочем виде написать? А то чет я не понимаю, как оно выглядеть должно. В том виде что я пишу неправильно работает.
Какая часть непонятна? Как написать «любая буква»? «латинская буква»?
Что я хотел сказать. Что главная особенность слова с опечаткой это то, что там идет либо латинская буква сразу за русской, либо наоборот. Соответственно не надо городить сложные условия, достаточно найти слово где есть пара букв из разных алфавитов, идущих друг за другом. А какие остальные буквы в этом слове, уже не важно.
Ты не учел что числа 11-19 в русском языке являются исключением из правил:
1 год
2 года
5 лет
-
11 лет
12 лет
15 лет
-
21 год
22 года
25 лет
Соответственно первой проверкой лучше проверить не входит ли 2 последних цифры в диапазон 11-19.
Но вообще, молодец, что попытался сделать такую сложную вещь в этой задаче. Через несколько уроков будет задача, где надо будет склонять слова, и тебе это пригодится.
Ну ты можешь из него сделать 2 массива ключей и значений через array_keys и array_values. Просто человеку удобнее работать (и труднее сделать ошибку при работе) с массивом где буква и ее пара связаны друг с другом.
>>466425
И как должен работать этот цикл? В начале ставим i = 1, на каждом шаге проверяем больше ли рост чем у анона, если да то увеличиваем i, если нет то выходим?
>>466563
Если честно код оформлен ужасно, и его тяжело читать, скобки расставлены как попало. Ну ведь есть же сайт phpformatter который сам за тебя код отформатирует, есть фооматирование одной кнопкой в IDE, неужели сложно это сделать?
Названия переменным можно было дать получше.
xDiapason -> xRange, xMax
переменную z можно было и не заводить а сразу писать if ($x % $y) ...
Это хорошо, что ты пытаешься решить такую задачу, но код надо стараться делать еще и читаемым.
Теперь о том что можно исправить.
Во-первых, не надо делить на все числа от x до 1. Достаточно пройтись от x до (корень из x). Так как если например 100 делится на 50 (которое больше 10) то оно же делится и на 2 (которое меньше 10).
Во-вторых, не надо находить все делители. Если ты нашел хотя бы один делитель, можно завершать цикл — число не простое.
Дальше, я не очень понимаю, почему ты пишешь цикл от большего числа к меньшему. Есть какая-то веская причина? Потому что читать цикл от 1 до N гораздо проще.
Ну и наконец, алгоритм «делим на все числа подряд» довольно медленный и неэффективный. Прочти в википедии про более оптимальные алгоримты. Например, древние греки (да, древние греки) придумали так называемое «решето Эратосфена»:
https://ru.wikipedia.org/wiki/%D0%A0%D0%B5%D1%88%D0%B5%D1%82%D0%BE_%D0%AD%D1%80%D0%B0%D1%82%D0%BE%D1%81%D1%84%D0%B5%D0%BD%D0%B0
http://mech.math.msu.su/~shvetz/54/inf/perl-problems/chPrimes_sIdeas.xhtml
http://habrahabr.ru/post/133037/
Кстати, если тебе интересно, простые числа (с огромным числом знаков) используются в алгоритмах шифрования вроде RSA ( https://ru.wikipedia.org/wiki/RSA ) и алгоритмах, которые например защищают данные при HTTPS-соединении. Так что то, что ты делаешь имеет, хоть и очень отдаленное, отношение к работе сайтов и интернета.
Также, есть специальные формулы, которые позволяют искать большие простые числа, с их помощью например математики их ищут:
https://ru.wikipedia.org/wiki/%D0%A7%D0%B8%D1%81%D0%BB%D0%B0_%D0%9C%D0%B5%D1%80%D1%81%D0%B5%D0%BD%D0%BD%D0%B0
http://www.ega-math.narod.ru/Quant/Primes.htm
Ну ты можешь из него сделать 2 массива ключей и значений через array_keys и array_values. Просто человеку удобнее работать (и труднее сделать ошибку при работе) с массивом где буква и ее пара связаны друг с другом.
>>466425
И как должен работать этот цикл? В начале ставим i = 1, на каждом шаге проверяем больше ли рост чем у анона, если да то увеличиваем i, если нет то выходим?
>>466563
Если честно код оформлен ужасно, и его тяжело читать, скобки расставлены как попало. Ну ведь есть же сайт phpformatter который сам за тебя код отформатирует, есть фооматирование одной кнопкой в IDE, неужели сложно это сделать?
Названия переменным можно было дать получше.
xDiapason -> xRange, xMax
переменную z можно было и не заводить а сразу писать if ($x % $y) ...
Это хорошо, что ты пытаешься решить такую задачу, но код надо стараться делать еще и читаемым.
Теперь о том что можно исправить.
Во-первых, не надо делить на все числа от x до 1. Достаточно пройтись от x до (корень из x). Так как если например 100 делится на 50 (которое больше 10) то оно же делится и на 2 (которое меньше 10).
Во-вторых, не надо находить все делители. Если ты нашел хотя бы один делитель, можно завершать цикл — число не простое.
Дальше, я не очень понимаю, почему ты пишешь цикл от большего числа к меньшему. Есть какая-то веская причина? Потому что читать цикл от 1 до N гораздо проще.
Ну и наконец, алгоритм «делим на все числа подряд» довольно медленный и неэффективный. Прочти в википедии про более оптимальные алгоримты. Например, древние греки (да, древние греки) придумали так называемое «решето Эратосфена»:
https://ru.wikipedia.org/wiki/%D0%A0%D0%B5%D1%88%D0%B5%D1%82%D0%BE_%D0%AD%D1%80%D0%B0%D1%82%D0%BE%D1%81%D1%84%D0%B5%D0%BD%D0%B0
http://mech.math.msu.su/~shvetz/54/inf/perl-problems/chPrimes_sIdeas.xhtml
http://habrahabr.ru/post/133037/
Кстати, если тебе интересно, простые числа (с огромным числом знаков) используются в алгоритмах шифрования вроде RSA ( https://ru.wikipedia.org/wiki/RSA ) и алгоритмах, которые например защищают данные при HTTPS-соединении. Так что то, что ты делаешь имеет, хоть и очень отдаленное, отношение к работе сайтов и интернета.
Также, есть специальные формулы, которые позволяют искать большие простые числа, с их помощью например математики их ищут:
https://ru.wikipedia.org/wiki/%D0%A7%D0%B8%D1%81%D0%BB%D0%B0_%D0%9C%D0%B5%D1%80%D1%81%D0%B5%D0%BD%D0%BD%D0%B0
http://www.ega-math.narod.ru/Quant/Primes.htm
> 13 месяц спустя: долг = 0 руб, выплачено всего 61270.186744521 руб.
> 14 месяц спустя: долг = 0 руб, выплачено всего 62270.186744521 руб.
> 15 месяц спустя: долг = 0 руб, выплачено всего 63270.186744521 руб.
Если долг == 0, зачем платить?
>>466612
Считает правильно, но у тебя вот тут сомнительное место:
> if ($creditBalance <= $monthlyPayment / $percent - $servicePayment ) {
> $monthlyPayment = $creditBalance × $percent + $servicePayment;
Выглядит как-то сложно и ненадежно. Я думаю, лучше чуть подправить программу и обойтись без этого.
Надо смотреть чему равен остаток долга и обрабатывать ситуацию, когда она маленький, а не выплачивать сразу же 5000 вот в этом месте: ... + $servicePayment - $monthlyPayment;
Попробуй переписать код внутри цикла примерно так:
- прибавляем проценты и комиссию к остатку долга
- если остаток маленький, выплачиваем сколько осталось и уходим
- иначе платим 5000
«Платим» здесь значит уменьшаем долг и увеличиваем общую сумму выплаченного.
Я могу ошибаться, но просто диктофонная запись или фото силы в суде не имеют, более того, ты еще и виноватым можешь оказаться в том что записывал людей без предупреждения.
>>466678
Тут нету 10 цифр. Также, в начале может быть либо 8 либо +7, но не +8
>>466682
Потому что их можно подделать, например можно вырезать или переставить часть слов.
>>466683
Видимо с юкозом что-то.
Скачай пока копию сайта с rghost: http://rghost.ru/45000175
Ясно. Но гуглить по контактам/скайпам/email все равно полезно, так как если кого-то раньше обманули, он скорее всего всю эту информацию выложит не в одном месте.
>>466703
Да, нелегко понять. Попробуй поставить маленькую сумму кредита (4000) и сделай вывод через echo каждый месяц суммы долга. Там все должно быть просто (я посчитал для второго банка):
первый месяц 4000 + 3%/комиссия 1000 = 5120, выплаичваем 5000, остается 120
второй месяц начисляются проценты, получается 1123, выплачиваем их
Есть класс-сущность, вроде Article, если при работе с ней нужны связи один-ко-многим или многие-ко-многим, допустим, темы (ну там sport, business, health) я хочу вынести в отдельную таблицу. Может ли, или должен ли класс-сущность уметь залезать в базу ( само собой через маппер) ? Т. е. метод getSubject() будет реализован как
class Article {
function getSubject() {
$sql = 'SELECT * FROM `subjects` WHERE `article_id` = ?';
...
$this->subjectmapper->getSubjectByArticleId($this->id);
...
return $subject;
}
}
Во вью:
<?='Subject: '.$article->getSubject(); ?>
Если нет, то как добыть инфу из посторонней таблицы, не относящейся к сущности.
Передаю через аякс текст, он передается нормально и при выводе из файла, в который передаю, отображается как следует. но в sql запросе происходит что-то неведомое мне, и в базу попадают кракозябры. Вместо "привет!" - "Привет!".
Кодировки файлов одинаковые.
Гуглил, странно, что iconv ничего не дает.
Помогите, пожалуйста.
Спасибо.
а как не мешать js с html? я не понимаю как это возможно :(
И вообще все вот говорят нельзя мешать языки, а я не понимаю как.
Если я делаю рефакторинг то появляются ненужные отступы. И если пишу не в одну строку.
| player_id | city | и | team_id | city |
О ужас, города-то дублируются. Вторая мысль - дополнительная таблица
| id | city |
| player_id | city_id |
| team_id | city_id |
Вроде все ок, но что это за тип связи такой? Вроде и не 1-к-М т. к. на каждую связь получается 2 таблицы, а не 1, но и не М-к-М.
в базу в utf-8 хранится?
Извиняюсь, поспешил, над этим >>466721 еще сам подумаю
ОП, зацени задачку про суммы прописью. Весь вечер мучался с ней, но в итоге вроде решил. Правда так и не врубился, как женский род к тысячам врубить. Вроде прописал параметр $isFemale, однако ж он не работает. Ну и еще почему-то парсер гонит на пробел в значении переменной. Так и должно быть?
>>466639-кун
https://jsfiddle.net/79nq2Lg7
Вопрос: обязательно ли задавать блоку margin-right: auto, если указана ширина 66%? Если не указать, результат получается тем же, блок будет слева.
>чтобы решить это задание, необходимо сначала изучить такие свойства CSS: font, line-height, etc.
Пардон, там же нет ни одного символа, к чему текстовые стили?
https://jsfiddle.net/u72f2whL/
Делал сначала в браузере, а оказалось, что он не может сжиматься по ширине как шакал.
А я думал, что это из-за неправильного использования max-width, и потратил немного лишних нервов. В jsfiddle все корректно, удобная вещь.
Пара мелких вопросов. Обязательно ли писать те свойства, которые заданы по умолчанию? Например, align-left для текста.
Как правильно записывать формат цвета? Все варианты работают, но может есть какой-нибудь стандарт? #ffffff, #fff, #FFF, white, rgb(255,255,255)?
> $percent = 1.03; / Банк начисляет 3% в месяц от суммы /
> 1.03
Почему 1.03? Не могу вдуплить.
Все равно не понял. Ведь:
> Школьник решил купить айфон и для этой цели взял кредит. Сумма кредита — 40000 р., банк каждый месяц начисляет 3%
3%=(40000/100)умножить на 3 = 1200
т.е. я без проблем могу писать и 1200? Не понимаю по поводу откуда единица взялась, если 40000/0.03=1200, а 40000/1.03=38834.951456 WTF?
А нахуй ты делишь то? Тебе ведь надо каждый месяц к текущей сумме добавлять по 3% от этой суммы, а не отнимать.
Это просто оптимизация кода. Вместо
{ $procent = 0.03$debt;
$debt = $debt + $procent; }
можно записать
{ $debt = 1.03; }
Впрочем, если тебе пока сложно делать эти промежуточные рассчеты в голове, пиши как удобно.
С опытом прийдет.
>>467076
>40000/0.03=1200, а 40000/1.03=38834.951456
Что за мура?
40 тысяч рублей умножить на 3 процента будет 1200 рублей, правильно.
40 тысяч рублей умножить на 103 процента будет 41200 рублей.
Повторяю, ты можешь посчитать так:
$начисление_за_месяц = 0.03 $сумма_долга;
$сумма_долга = $сумма_долга + $начисление_за_месяц;
Но гораздо короче будет так:
$сумма_долга = 1.03
В общем, это не ошибка, со временем научишься упрощать код.
Ну вот смотри, раз я такой даун. 1200 это 3%, 3% добавляю в текущей и сумме и получается следующее выражение:
$creditBalance = ( $creditBalance + $percent ) + $servicePayment - $monthlyPayment;
Верно?
Вот теперь понял. Спасибо.
>>467086
Верно-верно. Просто слишком длинная запись.
Это же элементарный вынос за скобки множителя:
x = x + x`0.03;
x = x(1 + 0.03);
Или совсем короткая программистская запись
x `= 1.03;
Уже понял, еще раз спасибо.
>не ставь слеш в конце одиночного тега: <br /> — правильно будет <br>. Слеш использовался только в XML и XHTML.
Почему тогда плагин emmet разворачивает одиночные теги со слешом?
Из всех инпутов тоже удалять слеши, что ли? Валидатор на них не ругается, тогда почему они попали в немилость?
На всякий случай, эммет же не знает какой у тебя доктайп.
потому что он старый
http://ideone.com/x8QGcE
Задача из http://archive-ipq-co.narod.ru/
>Undefined variable: mountlyPayment in /home/OD9bGK/prog.php on line 15, 19, 20
Компилятор тебе человеческим языком тебе описал ошибку.
Если не знаешь английского, пользуйся гуглтранслейт.
Добра тебе, анон.
https://gist.github.com/anonymous/3ed3e71bafb6af4f3cab
Вот ты и дошел до темной стороны ORM (ORM — это сопоставление объектов с строками в базе данных, идеальный ORM создает видимость что базы нет, и все объекты находятся прямо в памяти. Идеального ORM не существует).
Отношения между объектами — сложная штука. Реализуются они по разному.
В Yii, где используется ACtiveRecord (который умеет себя грузить из базы), для отношений создется функция и она при первом обращении делает SQL запрос (а при последующих по моему возвращает сохраненное значение, хотя я не уверен):
$subjects = $arcticle->getSubjects( );
(что надо писать в getSubjects описано например тут: http://www.sitepoint.com/yii-2-0-activerecord-explained/ или тут http://developer.uz/blog/activerecord-yii2-and-yii1/ )
В Doctrine все сложнее. Там модель не может лезть в базу, потому там предусмотрено 2 способа загрузки связанных сущностей: жадное и ленивое. При жадном, когда ты загружаешь из БД объект, доктрина загружает указанные тобой связанные объекты, например статью + темы и вставляет коллекцию тем в объект статьи.
Соответственно
$article->getSubjects( );
Возвращает эту коллекцию.
Если же ты не указал загружать темы жадно, то доктрина их не загружает. Вместо них она вставляет прокси-коллекцию. Эта прокси-коллекция при первом обращении к ее содержимому подгружает данные из базы и возвращает их:
$subjects = $article->getSubjects( );
// в subjects прокси-коллекция
// При попытке доступа к содержимому (до выполнения foreach) происходит выбор тем из БД
foreach ($subjects as $subject){
...
}
Описано тут:
http://odiszapc.ru/doctrine/working-with-objects/#82 (рус)
http://doctrine-orm.readthedocs.org/en/latest/reference/working-with-associations.html (англ, подробно)
В общем, все довольно сложно, если ты захочешь например посмотреть код который это внутри реализует.
Потому если ты хочешь изучить как устроены ORM подробно, я советую сначала изучить Doctrine 2 (например прочесть мануал и сделать простую программку с ее использованием), а затем уже лезть в ее недра и изучать.
Заметь что с ленивой загрузкой связана так называемая проблема N + 1 запроса (когда мы в цикле обращаемся к лениво загружаемым связям и вызвыаем N запросов на выборку):
http://www.krestjaninoff.ru/2011/06/n1-select.html
http://rails-junior.com/posts/rails-N-1-problem
http://use-the-index-luke.com/sql/join/nested-loops-join-n1-problem
> Может ли, или должен ли класс-сущность уметь залезать в базу
Нет, не может (это будет бардак если SQL код будет размазан по всему приложению). Обычно также сущность не содержит в себе ссылок на маппер (так как это не ее задача, что-то загружать из базы).
Алсо ты при выводе забыл экранирование специсмволовв HTML.
Вот ты и дошел до темной стороны ORM (ORM — это сопоставление объектов с строками в базе данных, идеальный ORM создает видимость что базы нет, и все объекты находятся прямо в памяти. Идеального ORM не существует).
Отношения между объектами — сложная штука. Реализуются они по разному.
В Yii, где используется ACtiveRecord (который умеет себя грузить из базы), для отношений создется функция и она при первом обращении делает SQL запрос (а при последующих по моему возвращает сохраненное значение, хотя я не уверен):
$subjects = $arcticle->getSubjects( );
(что надо писать в getSubjects описано например тут: http://www.sitepoint.com/yii-2-0-activerecord-explained/ или тут http://developer.uz/blog/activerecord-yii2-and-yii1/ )
В Doctrine все сложнее. Там модель не может лезть в базу, потому там предусмотрено 2 способа загрузки связанных сущностей: жадное и ленивое. При жадном, когда ты загружаешь из БД объект, доктрина загружает указанные тобой связанные объекты, например статью + темы и вставляет коллекцию тем в объект статьи.
Соответственно
$article->getSubjects( );
Возвращает эту коллекцию.
Если же ты не указал загружать темы жадно, то доктрина их не загружает. Вместо них она вставляет прокси-коллекцию. Эта прокси-коллекция при первом обращении к ее содержимому подгружает данные из базы и возвращает их:
$subjects = $article->getSubjects( );
// в subjects прокси-коллекция
// При попытке доступа к содержимому (до выполнения foreach) происходит выбор тем из БД
foreach ($subjects as $subject){
...
}
Описано тут:
http://odiszapc.ru/doctrine/working-with-objects/#82 (рус)
http://doctrine-orm.readthedocs.org/en/latest/reference/working-with-associations.html (англ, подробно)
В общем, все довольно сложно, если ты захочешь например посмотреть код который это внутри реализует.
Потому если ты хочешь изучить как устроены ORM подробно, я советую сначала изучить Doctrine 2 (например прочесть мануал и сделать простую программку с ее использованием), а затем уже лезть в ее недра и изучать.
Заметь что с ленивой загрузкой связана так называемая проблема N + 1 запроса (когда мы в цикле обращаемся к лениво загружаемым связям и вызвыаем N запросов на выборку):
http://www.krestjaninoff.ru/2011/06/n1-select.html
http://rails-junior.com/posts/rails-N-1-problem
http://use-the-index-luke.com/sql/join/nested-loops-join-n1-problem
> Может ли, или должен ли класс-сущность уметь залезать в базу
Нет, не может (это будет бардак если SQL код будет размазан по всему приложению). Обычно также сущность не содержит в себе ссылок на маппер (так как это не ее задача, что-то загружать из базы).
Алсо ты при выводе забыл экранирование специсмволовв HTML.
Связей всего 3 вида: 1:1, 1:N, M:N
> У Футболиста есть родной город,
Много к одному
> Команды есть город
Много к одному
> Первая мысль - по одной таблице на каждую сущность
Сущностей у тебя 3: футболист, команда, город и таблицы будет 3
> Вроде и не 1-к-М т. к. на каждую связь получается 2 таблицы, а не 1, но и не М-к-М
Две отдельных связи вида «1:N». Кстати ты еще забыл связь игрок — команда.
Что же ты будешь делать когда узнаешь что таблица может быть сама с собой связана (комментарий — родитель или подчиненный — менеджер).
завтра
>>466965
> который принимает массив
Опять за старое взялся.
Кстати раз ты ORM пишешь почитай еще про паттерны сопуствующие:
http://merle-amber.blogspot.ru/2009/02/orm.html
Ну и описание паттернов гуглится отдельно например : http://design-pattern.ru/patterns/identity-map.html
> обязательно ли задавать блоку margin-right: auto, если указана ширина 66%? Если не указать, результат получается тем же, блок будет слева.
Нет
Зачем box-sizing? Можно же и без него сделать.
А так, верно.
> там же нет ни одного символа, к чему текстовые стили?
Задачи для изучающих с нуля. Сначала они должны научиться текст раскрашивать, а потом за позиционирование браться.
>>467051
2 дива — слишком много для простой задачи, думаю тут хватит одного.
Когда указываешь font-size всегда указывай line-height иначе он унаследуется от родителя.
> Обязательно ли писать те свойства, которые заданы по умолчанию?
Нет, не надо писать. Текст во всех браузерах по умолчанию влево выровнен.
> Как правильно записывать формат цвета? Все варианты работают, но может есть какой-нибудь стандарт?
Как больше нравится. Совсем древние браузеры не поддержат rgb()
> width: 100%;
Зачем? У блоков и так auto работает как 100%
Если уменьшать ширину то появляется горизантальная линейка прокрутки.
также, если используешь box-sizing, пиши вендорные префиксы. Не такой и старый FF24 например понимает только -moz-box-sizing (в новых бразерах префиксы не используются, но FF24 и куча браузеров вышли до того как от них отказались)
> обязательно ли задавать блоку margin-right: auto, если указана ширина 66%? Если не указать, результат получается тем же, блок будет слева.
Нет
Зачем box-sizing? Можно же и без него сделать.
А так, верно.
> там же нет ни одного символа, к чему текстовые стили?
Задачи для изучающих с нуля. Сначала они должны научиться текст раскрашивать, а потом за позиционирование браться.
>>467051
2 дива — слишком много для простой задачи, думаю тут хватит одного.
Когда указываешь font-size всегда указывай line-height иначе он унаследуется от родителя.
> Обязательно ли писать те свойства, которые заданы по умолчанию?
Нет, не надо писать. Текст во всех браузерах по умолчанию влево выровнен.
> Как правильно записывать формат цвета? Все варианты работают, но может есть какой-нибудь стандарт?
Как больше нравится. Совсем древние браузеры не поддержат rgb()
> width: 100%;
Зачем? У блоков и так auto работает как 100%
Если уменьшать ширину то появляется горизантальная линейка прокрутки.
также, если используешь box-sizing, пиши вендорные префиксы. Не такой и старый FF24 например понимает только -moz-box-sizing (в новых бразерах префиксы не используются, но FF24 и куча браузеров вышли до того как от них отказались)
>>467054
Потому что увеличить число на 3% равносильно взять 103% от числа (103% на 3% больше чем 100%). А 103% от числа это 1.03 умножить на число. ЧТобы найти процент надо умножать.
>>467065
Реферат уровня /pr :3
>>467076
Не можешь так как процент берется от суммы долга, а долг каждый месяц уменьшается.
>>467097
наверно ты с настройками намудрил. У меня emmet в саблайме генерирует HTML ( br -> <br>) без всяких слешей.
Тут написано что он смотрит на документ: http://docs.emmet.io/customization/syntax-profiles/
Также в настройках есть такая настройка:
>\t// Try to automatically detect XHTML dialect in HTML documents.
>\t// With this option enabled, your custom profile for HTML documents may not work.
>\t"autodetect_xhtml": true,
может он видит слеши и думает что у тебя XHTML
Валидатор не ругается? Скорее всего потому, что в HTML5 разрешили писать слеш в конце (но обрати внимание, в XHTML <div/> значит <div></div>, в HTML5 слеш игнорируется, и это же значит просто <div> — и из-за этого легко наделать багов потому я и считаю что это плохая идея. Более того если слеш игнорируется, зачем тогда его писать?). Разрешили так как выросло поколение гм, неучей, которые учились по плохим XHTML-учебникам (были раньше фанатики которые думали что XHTML это будущее и везде его пихали), растащили этот синтаксис по всему интернету (включая сайты вроде кодеакадеми) и проще оказалось разрешить слеш, чем с ними бороться.
Вот тема на SO: http://stackoverflow.com/a/3558200
История про XHTML и почему он не прижился несмотря на пиар (потому что его никто не использовал; люди просто ставили лишние слеши в HTML коде, но не переключали тип на XHTML): http://softwaremaniacs.org/blog/2005/12/19/xhtml-you-say/
>>467054
Потому что увеличить число на 3% равносильно взять 103% от числа (103% на 3% больше чем 100%). А 103% от числа это 1.03 умножить на число. ЧТобы найти процент надо умножать.
>>467065
Реферат уровня /pr :3
>>467076
Не можешь так как процент берется от суммы долга, а долг каждый месяц уменьшается.
>>467097
наверно ты с настройками намудрил. У меня emmet в саблайме генерирует HTML ( br -> <br>) без всяких слешей.
Тут написано что он смотрит на документ: http://docs.emmet.io/customization/syntax-profiles/
Также в настройках есть такая настройка:
>\t// Try to automatically detect XHTML dialect in HTML documents.
>\t// With this option enabled, your custom profile for HTML documents may not work.
>\t"autodetect_xhtml": true,
может он видит слеши и думает что у тебя XHTML
Валидатор не ругается? Скорее всего потому, что в HTML5 разрешили писать слеш в конце (но обрати внимание, в XHTML <div/> значит <div></div>, в HTML5 слеш игнорируется, и это же значит просто <div> — и из-за этого легко наделать багов потому я и считаю что это плохая идея. Более того если слеш игнорируется, зачем тогда его писать?). Разрешили так как выросло поколение гм, неучей, которые учились по плохим XHTML-учебникам (были раньше фанатики которые думали что XHTML это будущее и везде его пихали), растащили этот синтаксис по всему интернету (включая сайты вроде кодеакадеми) и проще оказалось разрешить слеш, чем с ними бороться.
Вот тема на SO: http://stackoverflow.com/a/3558200
История про XHTML и почему он не прижился несмотря на пиар (потому что его никто не использовал; люди просто ставили лишние слеши в HTML коде, но не переключали тип на XHTML): http://softwaremaniacs.org/blog/2005/12/19/xhtml-you-say/
В HTML не ставится слеш в конце никогда. У одиночных тегов вроде img, br, input нет закрывающего тега потому писать ничего не надо.
>>467226
Через PDO например или другую библиотеку. Слим не предоставляет ничего для работы с БД так как это микрофреймворк.
Также советую почитать мой урок про работу с БД https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md
>>467253
Код лучше бы постить на jsbin/jsfiddle/codepen.io чтобы был виден результат. Хотя на гитхаб удобнее ссылки давать.
> var classes = node.getAttribute('class');
есть свойство (не атрибут, почитай где-нибудь в чем разница) className: node.className — с ним как минимум короче и вроде все так пишут
> if( classes === '' || undefined ){
Что значит undefiend? Это всегда ложно и ничего не делает. Ты наверно === забыл?
> classes.split(/\s/);
Лучше \s+ так как классы могут быть разделены любым числом пробелов и переводов строк
> https://gist.github.com/anonymous/3ed3e71bafb6af4f3cab#file-gistfile1-js-L21
Нет проверки что такой класс уже есть и можно надобавлять кучу одинаковых классов
> https://gist.github.com/anonymous/3ed3e71bafb6af4f3cab#file-gistfile1-js-L23
> return true;
зачем? Ты будешь проверять что вернет addClass? И что ты сделаешь если она вернет не true?
Если произошла непоправимая ошибка лучше использовать исключения, вот мой урок про них: https://gist.github.com/codedokode/65d43ca5ac95c762bc1a
> https://gist.github.com/anonymous/3ed3e71bafb6af4f3cab#file-gistfile1-js-L29
Это плохая идея. выводить что-то в консоль. Ты же не знаешь где будет использоваться твоя функция, зачем зря в консоль мусорить сообщениями которые никто не прочтет? Или которые наоборот, будут мешать прочитать другие сообщения.
Также, если класса нет то делать ничего не надо. Это не ошибка.
> if( classes === '' || undefined ){
Если ты хотел написать «класс пустой или undefined» то ты написал неправильно. || так не работает, это не человеческое слово «ИЛИ», а логический оператор, он объединяет условия, а не отдельные значения. Сначала вычисляются выражения справа и слева, приводятся к true/false, а потом выполняется «или»:
Попробуй выполнить такой код:
var a = 3;
if (a === 1 || 2) {
console.log('YES');
}
что он выведет? а на самом деле? Почитай
https://learn.javascript.ru/comparison
https://learn.javascript.ru/logical-ops
> https://gist.github.com/anonymous/3ed3e71bafb6af4f3cab#file-gistfile1-js-L40
> classes.splice(index, 1);
Класс может быть вписан несколько раз подряд
Ну и если тебе интересно как эти функции делают другие то пожалуйста (там можно подчерпнуть интересные мысли)
Prototype JS https://github.com/sstephenson/prototype/blob/d9411e5/src/prototype/dom/dom.js#L2493
jQuery https://github.com/jquery/jquery/blob/master/src/attributes/classes.js
В HTML не ставится слеш в конце никогда. У одиночных тегов вроде img, br, input нет закрывающего тега потому писать ничего не надо.
>>467226
Через PDO например или другую библиотеку. Слим не предоставляет ничего для работы с БД так как это микрофреймворк.
Также советую почитать мой урок про работу с БД https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md
>>467253
Код лучше бы постить на jsbin/jsfiddle/codepen.io чтобы был виден результат. Хотя на гитхаб удобнее ссылки давать.
> var classes = node.getAttribute('class');
есть свойство (не атрибут, почитай где-нибудь в чем разница) className: node.className — с ним как минимум короче и вроде все так пишут
> if( classes === '' || undefined ){
Что значит undefiend? Это всегда ложно и ничего не делает. Ты наверно === забыл?
> classes.split(/\s/);
Лучше \s+ так как классы могут быть разделены любым числом пробелов и переводов строк
> https://gist.github.com/anonymous/3ed3e71bafb6af4f3cab#file-gistfile1-js-L21
Нет проверки что такой класс уже есть и можно надобавлять кучу одинаковых классов
> https://gist.github.com/anonymous/3ed3e71bafb6af4f3cab#file-gistfile1-js-L23
> return true;
зачем? Ты будешь проверять что вернет addClass? И что ты сделаешь если она вернет не true?
Если произошла непоправимая ошибка лучше использовать исключения, вот мой урок про них: https://gist.github.com/codedokode/65d43ca5ac95c762bc1a
> https://gist.github.com/anonymous/3ed3e71bafb6af4f3cab#file-gistfile1-js-L29
Это плохая идея. выводить что-то в консоль. Ты же не знаешь где будет использоваться твоя функция, зачем зря в консоль мусорить сообщениями которые никто не прочтет? Или которые наоборот, будут мешать прочитать другие сообщения.
Также, если класса нет то делать ничего не надо. Это не ошибка.
> if( classes === '' || undefined ){
Если ты хотел написать «класс пустой или undefined» то ты написал неправильно. || так не работает, это не человеческое слово «ИЛИ», а логический оператор, он объединяет условия, а не отдельные значения. Сначала вычисляются выражения справа и слева, приводятся к true/false, а потом выполняется «или»:
Попробуй выполнить такой код:
var a = 3;
if (a === 1 || 2) {
console.log('YES');
}
что он выведет? а на самом деле? Почитай
https://learn.javascript.ru/comparison
https://learn.javascript.ru/logical-ops
> https://gist.github.com/anonymous/3ed3e71bafb6af4f3cab#file-gistfile1-js-L40
> classes.splice(index, 1);
Класс может быть вписан несколько раз подряд
Ну и если тебе интересно как эти функции делают другие то пожалуйста (там можно подчерпнуть интересные мысли)
Prototype JS https://github.com/sstephenson/prototype/blob/d9411e5/src/prototype/dom/dom.js#L2493
jQuery https://github.com/jquery/jquery/blob/master/src/attributes/classes.js
В базе данные в какой кодировке? Какая кодировка соединения?
Определить кодировку можно так:
var_dump(bin2hex($s));
И посмотреть какие коды выведутся — в utf8 там характерные 2-байтовые последовательности у русских букв c D0/D1, достаточно 1 раз увидеть чтобы узнавать. Вот они: http://ru.stackoverflow.com/questions/147190/%D0%94%D0%B5%D0%BA%D0%BE%D0%B4%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D1%81%D1%82%D1%80%D0%BE%D0%BA%D0%B8-utf-8-hex-%D0%B2-%D1%87%D0%B8%D1%82%D0%B0%D0%B1%D0%B5%D0%BB%D1%8C%D0%BD%D1%8B%D0%B9-%D0%B2%D0%B8%D0%B4
А в 1251 коды у букв такие: http://kvodo.ru/tablitsa-windows-1251.html
Ну и вот еще инструмент для сравнения кодов: http://foxtools.ru/Hex
Какие заголовки отдаются с AJAX ответом? (посмотреть на вкладке nEtwork в инспекторе в браузере (Ctrl + SHift + I))
Пока не годится. Во-первых, у тебя 2 скопипащенных функции, а копипаста это страшное зло — убери копипасту.
Далее, формулы какие-то странные, ты сначала все вычитаешь из price, а потом прибавляешь назад. Я предлагаю сделать проще: пусть в price текущий долг (который уменьшается), а сумму выплаченного сделать в отдельной переменной которая только увеличивается.
Ну и
$price = $price - $pay;
можно напиать как
$price -= $pay;
Отступы не так страшно. лишние вещи можно выносить в переменные, например вместо
$('aaa').a().b( );
$('aaa').c( );
можно написать
var aaa = ('aaa');
aaa.a( );
aaa.b( );
aaa.c( );
Например у тебя повторяется $(this)? Повторяется, и это плохо. Вынеси это в переменную с объясняющим названием.
Более того, может быть эти переменные можно вынести наверх, чтобы не искать элемент каждый раз заново.
Не вкладывать функции друг в друга. В твоем случае обработчики можно сделать на одном уровне.
Также можно перенести обработчик на элемент выше чем тот который ты заменяешь, чтобы он не удалялся вместе с элементом.
Вместо вставки кусков HTML часто достаточно поменять значение атрибута или скрыть/показать существующий блок. Может это твой вариант? Переключить 2 блока местами можно всего лишь добавлением/убавлением одного класса и HTML писать в коде не придется.
Если тебе надо вставить HTML в страницу то можно вынести его в шаблон в script как описано тут:
https://learn.javascript.ru/template-lodash
https://learn.javascript.ru/templates
Отступы не так страшно. лишние вещи можно выносить в переменные, например вместо
$('aaa').a().b( );
$('aaa').c( );
можно написать
var aaa = ('aaa');
aaa.a( );
aaa.b( );
aaa.c( );
Например у тебя повторяется $(this)? Повторяется, и это плохо. Вынеси это в переменную с объясняющим названием.
Более того, может быть эти переменные можно вынести наверх, чтобы не искать элемент каждый раз заново.
Не вкладывать функции друг в друга. В твоем случае обработчики можно сделать на одном уровне.
Также можно перенести обработчик на элемент выше чем тот который ты заменяешь, чтобы он не удалялся вместе с элементом.
Вместо вставки кусков HTML часто достаточно поменять значение атрибута или скрыть/показать существующий блок. Может это твой вариант? Переключить 2 блока местами можно всего лишь добавлением/убавлением одного класса и HTML писать в коде не придется.
Если тебе надо вставить HTML в страницу то можно вынести его в шаблон в script как описано тут:
https://learn.javascript.ru/template-lodash
https://learn.javascript.ru/templates
> $incline = $word5;
Тут незачем заводить переменную, можно сразу return писать
> $hundredsRound > 10
явно опечатка: число сотен кратно 100 а не 10
> PHP Notice: Undefined index: in /home/qmwzt6/prog.php on line 73
Ты обращаешься к несуществующему элементу массива, это ошибка. Я думаю. виноваты эти строки:
> $digits = " ";
> $spelling[$digits];
Вместо того, чтобы возиться с склеиванием слов и учетом пробелов, я советую сделать массив и класть слова в него, а в конце функции сделать implode. И если в числе нет сотен то не добавлять элемент в массив.
Аналогично можно сделать в функции numberToText($number)
Проверку на ноль проще всего сделать отдельным ифом.
В конце файла лучше не писать ?> так как за ним могут остаться пробелы и когда ты будешь делать сайт, эти пробелы тебе дадут ошибку при попытке отправить заголовок. Лучше сразу приучаться не ставить ?>
Вообще, неплохо, код довольно хороший получился.
> как женский род к тысячам врубить.
Если (род женский и число заканчивается на 1 или 2) берем слово для единиц из другого массива (где «одна» и «две»).
> Ну и еще почему-то парсер гонит на пробел в значении переменной. Так и должно быть?
не должно быть таких ошибок
>>467031
тут у тебя долг в минус уходит и пишет что 2 месяца платить, а на самом деле один: http://ideone.com/lgVWFj
Также, тут явно формула скопирована:
>$balance = $creditBalance × $percent + $servicePayment;
попробуй избавиться от повторения
Надо смотреть чему равен остаток долга и обрабатывать ситуацию, когда она маленький, а не выплачивать сразу же 5000 вот в этом месте: ... + $servicePayment - $monthlyPayment;
Попробуй переписать код внутри цикла примерно так:
- прибавляем проценты и комиссию к остатку долга
- если остаток маленький, выплачиваем сколько осталось и уходим
- иначе платим 5000
«Платим» здесь значит уменьшаем долг и увеличиваем общую сумму выплаченного.
> как женский род к тысячам врубить.
Если (род женский и число заканчивается на 1 или 2) берем слово для единиц из другого массива (где «одна» и «две»).
> Ну и еще почему-то парсер гонит на пробел в значении переменной. Так и должно быть?
не должно быть таких ошибок
>>467031
тут у тебя долг в минус уходит и пишет что 2 месяца платить, а на самом деле один: http://ideone.com/lgVWFj
Также, тут явно формула скопирована:
>$balance = $creditBalance × $percent + $servicePayment;
попробуй избавиться от повторения
Надо смотреть чему равен остаток долга и обрабатывать ситуацию, когда она маленький, а не выплачивать сразу же 5000 вот в этом месте: ... + $servicePayment - $monthlyPayment;
Попробуй переписать код внутри цикла примерно так:
- прибавляем проценты и комиссию к остатку долга
- если остаток маленький, выплачиваем сколько осталось и уходим
- иначе платим 5000
«Платим» здесь значит уменьшаем долг и увеличиваем общую сумму выплаченного.
http://ideone.com/eukL2f
Пофиксил все ошибки. Только лень было переделывать и добавлять слова в массив и вместо этого просто добавил новый ключ 'null' с пустым значением в массив $spelling и ошибка с обращением к несуществующей ячейке массива теперь не выдается.
Плюс еще добавил проверку на $isFemale == 1 и заменой на слова женского рода. Правда почему-то array_replace не сработал и пришлось ручками добавлять. Почему?
> Не сдавайся. Чем дольше ты сражаешься с регулярными выражениями, тем лучше узнаешь врага.
http://ideone.com/PRYKzT
О черт, это реально слишком сложно, особенно doctrine. но пока суть да дело я возложил эту функцию на маппер усложнив запрос через join-ы так:
function getArticleById($id) {
//было $sql = 'SELECT FROM articles WHERE id = ?';
//стало
$sql = 'SELECT FROM articles LEFT JOIN subjects ON articles.subject_id=subjects.id WHERE articles.id = ?';
$query = $this->db->query($sql,[$id]);
\t\tif ($query->count()==1) {
\t\t\t$result = $query->getFirst();
\t\t\t$article_attributes = $this->sqlObjectToArray($result);
\t\t\t$article = new Article();
\t\t\t$article ->setAttributes($article_attributes);
\t\t\treturn $article;
\t\t} else {
\t\t\treturn false;
\t\t}
\t}
На удивление все четко работает. Смущают три момента
1. ArticleMapper делает джоин с 'чужой' таблицей.
2. Надо следить за именами полей либо использовать алиасы, чтобы при джоине не возник конфликт имен полей
3. Если вынести в отдельную таблицу авторов и еще что-нибудь запрос получится размером с Техас и сложным как синхрофазотрон.
Если это отстой, то есть еще идея :3
>Если это отстой, то есть еще идея :3
А, ну собственно, вот тут она
http://www.sitepoint.com/yii-2-0-activerecord-explained/
Добывать темы и авторов в той модели с которой работает контроллер и которая рулит маппером. Но тут подводный камень: у автора эта же модель (у него наз. Articles) создает сущности (Article) и присваивает им атрибуты, в том числе авторов и теги, а у меня их возвращает маппер, уже готовыми. И мне придется либо передавать автора и тему в маппер наравне с id требуемой статьи, либо доприсваивать их после возвращения, и то и то как-то не очень. Походу это фишка activerecord-а.
Анон, я переделал в соответствии с рекомендациями. Мне кажется, что логично считать платежи через $i*$платёж + остаток, ведь $i считает сколько раз сделан платёж, зачем заводить отдельную функцию?
http://ideone.com/lU65Yv
function __get($name) {
return $this->$name
}
Первая функция считает по месяцам (наприме условие - 4% и 500р в месяц переплаты) вторая - когда переплата за весь кредит (7777р за весь кредит и 2% в месяц)
третья попытка.
https://jsfiddle.net/r85x0nbj/
>У тебя может возникнуть желание поставить обработчик события на каждую клеточку. Не делай так, это неэффективно, достаточно одного обработчика на всю таблицу
Не понимаю.
>Чтобы поменять цвета всех клеточек сразу, необязательно обходить их в цикле. Если помечать нажатые клетки определенным классом, то перекрасить их все одновременно можно, поменяв класс на самой таблице.
Не понимаю.
Добавлю, заходил через main.php
https://gist.github.com/gennsmir/cd7ca9423bec93c2d842
Больше или равно пишется <= а не =< как у тебя. Еще лишняя скобка в той же строке.
Выкладывай код на ideone, там можно посмотреть результат.
http://ideone.com/56jNQS
В каком редакторе ты работаешь? У тебя не включена подсветка синтаксиса?
Ставь netbeans или phpstorm.
>Надо сделать проще, регулярку примерно такого вида:
Внезапно другой нюфак. Правильно ли я сделал? Как сделать по-человечески?
/(8|[+]7)([)( -]?[0-9]){10}/
Не строка, потому что ковычек нет, и не число.
Но я вообще хуй простой, так что подожди компетентного человека.
Ну дык даж если в кавычки запихать, то один хуй. Просто я думал, что можно заменить плюсы и минусы переменной, которая один из этих знаков содержит и результат посчитается как обычно. Но или я как-то неправильно записываю или так делать нельзя.
1. <meta charset="UTF-8"> - в html
2. new PDO("mysql:host={$host}; dbname={$db}; charset=UTF8" - в php
3. Сравнение: ut8_general_ci - в sql
http://ideone.com/ZIP2rD
https://github.com/someApprentice/Cat-and-Mouse
Задача с Кошками-Мышками оказалась не такой простой для меня.
Мне очень сложно создать среду для игры. А именно, не получается сделать так, чтобы объекты не выходили за рамки карты.
Объекты с карты могут просто так исчезнуть. Хотя, наверно это все вытекает из первого.
В общем, дай критику пожалуйста, ОП.
никак нельзя. Пиши через if/else
$a.$b.$c просто склеивает строки в одну строку и все. Он не выполняет написанный в них код.
>$a.$b.$c просто склеивает строки в одну строку и все. Он не выполняет написанный в них код.
и потом eval()
Анон, я тебя просил в прошлый раз одну вещь сделать. Вынести скрипты, к которым мы обращаемся из браузера, в корень репозитория. Чтобы было:
/search.php
/list.php
/lib (тут файлы к которым напрямую нельзя обращаться)
/templates
И соответственно с большой буквы называть только файлы с классами.
Я конечно все равно проверю код, но это надо переделать в любом случае.
И почему ты каждый раз новый репозиторий создаешь? Зачем?
События в браузере происходят не только на кликнутом элементе. Событие сначала (фаза захвата/capture) спускается по дереву DOM от документа к конкретному элементу, а затем поднимается вверх к документу (фаза всплытия/bubble)
Это описано тут https://learn.javascript.ru/event-delegation
https://learn.javascript.ru/events-and-interfaces
Я советую тебе найти время и прочесть учебник по ссылке целиком. Он хороший и там много полезного. Ну и разумеется я всегда готов на вопросы ответить.
> Не понимаю.
Представь что у нас есть CSS-правило: если на таблице стоит класс black то клеточки в ней имею черный фон. В таком случае чтобы поменять цвет всех клеток на черный нам достаточно сделать одно действие — добавить класс black на таблицу.
Код я проверю позже, пока вижу такие замечания:
— надо убрать цикл который меянет цвета клеток при toggle colors
— надо чтобы был один обработчик клика, а не на каждой клетке
— знаешь ли ты в чем разница между событиями mousedown и click? Если нет, надо выучить.
Если работает, значит правильно. Ты же запускал код, перед тем как запостить сюда?
У меня получилось так.
http://ideone.com/qRvVh0
Хотя может и это не совсем оптимально. Меня напрягает та часть выражения, где юзер может засандалить кучу скобок, дефисов и пробелов.
третий стремящийся
Я каждый раз делаю у себя на локалке новый вариант, в котором начинаю заново делать проект с нуля но копирую по одному файлу из старого проекта если он подходит и переделываю его, мне так проще отследить что уже сделано, а что надо сделать чем брать весь проект целиком и искать по файлам то что мне нужно, плюс гит ругается при попытке отправить изменения в старый проект.
По файлам - я думал нужно вынести шаблоны в папку temp, видимо я тогда не понимаю, что такое шаблоны, думал это файлы которые содержат преимущественно html и которые загружаются при необходимости вывода инфы. Мне бы по самому содержимому, по логике больше хотелось услышать замечания, счас то я переделаю текущий вариант, размещу по папкам как надо, а потом выйдет так, что там придется всё изменять по самому содержимому.
Это уже лучше, но посмотри что она пишет:
> 13 месяц спустя: долг = 1270.1867445207 руб, выплачено всего 65000 руб .
а должно быть всего около 61280
> if ($creditBalance == 0) {
Лучше поставить <= 0 так как дробные числа в компьютере хранятся в приближенном виде и у тебя может получиться не ровно 0, а -0.0000000001 например. С <= код будет надежнее.
>>467311
> добавил новый ключ 'null'
Название лучше было дать другое, конечно, чтобы не спутать строку 'null' с значением null. Но это мелочи.
> На вашем счету семьдесят
Тут 2 пробела, надо хотя бы trim поставить. Хотя по моему ,с массивом конечно получилось бы красивее. Ну и код получился бы чуть понятнее.
Вот еще вещь, которую можно упростить:
> $totalResult = $wordsHundreds.' '.$inclineWordsHundreds;
> $totalResult = $wordsThousands.' '.$inclineWordsThousands.' '.$wordsHundreds.' '.$inclineWordsHundreds;
> $totalResult = $wordsMillions.' '.$inclineWordsMillions.' '.$wordsThousands.' '.$inclineWordsThousands.' '.$wordsHundreds.' '.$inclineWordsHundreds;
Это громоздко и тяжело читается.
Тут явно можно переделать на более простую схему, вроде:
если (есть миллионы) {
добавляем число миллионов;
}
если (есть тысячи) {
...
}
если (есть единицы) {
....
}
А так. неплохо сделано.
>>467340
О, программа работает верно. Это хорошо. Но я бы упростил конечно регулярку, вот это место, где у тебя перечислены возможные дополнительные символы, я бы записал как
цифра, (любое число скобок/минусов/пробелов)
Ну или если тебе не нравится «любое число» то можно написать например
цифра, (от 0 до 5 скобок/минусов/пробелов)
Почему именно так? Потому что регулярка станет проще и ее будет проще читать и исправлять если надо. Не хочешь упростить регулярку еще?
Это уже лучше, но посмотри что она пишет:
> 13 месяц спустя: долг = 1270.1867445207 руб, выплачено всего 65000 руб .
а должно быть всего около 61280
> if ($creditBalance == 0) {
Лучше поставить <= 0 так как дробные числа в компьютере хранятся в приближенном виде и у тебя может получиться не ровно 0, а -0.0000000001 например. С <= код будет надежнее.
>>467311
> добавил новый ключ 'null'
Название лучше было дать другое, конечно, чтобы не спутать строку 'null' с значением null. Но это мелочи.
> На вашем счету семьдесят
Тут 2 пробела, надо хотя бы trim поставить. Хотя по моему ,с массивом конечно получилось бы красивее. Ну и код получился бы чуть понятнее.
Вот еще вещь, которую можно упростить:
> $totalResult = $wordsHundreds.' '.$inclineWordsHundreds;
> $totalResult = $wordsThousands.' '.$inclineWordsThousands.' '.$wordsHundreds.' '.$inclineWordsHundreds;
> $totalResult = $wordsMillions.' '.$inclineWordsMillions.' '.$wordsThousands.' '.$inclineWordsThousands.' '.$wordsHundreds.' '.$inclineWordsHundreds;
Это громоздко и тяжело читается.
Тут явно можно переделать на более простую схему, вроде:
если (есть миллионы) {
добавляем число миллионов;
}
если (есть тысячи) {
...
}
если (есть единицы) {
....
}
А так. неплохо сделано.
>>467340
О, программа работает верно. Это хорошо. Но я бы упростил конечно регулярку, вот это место, где у тебя перечислены возможные дополнительные символы, я бы записал как
цифра, (любое число скобок/минусов/пробелов)
Ну или если тебе не нравится «любое число» то можно написать например
цифра, (от 0 до 5 скобок/минусов/пробелов)
Почему именно так? Потому что регулярка станет проще и ее будет проще читать и исправлять если надо. Не хочешь упростить регулярку еще?
> Правда почему-то array_replace не сработал и пришлось ручками добавлять. Почему?
Покажи кусочек кода, который не работает, так трудно понять. Скорее всего ты неправильно использовал функцию или не до конца понял принцип ее работы.
Заменить ключи можно такой конструкцией:
$a = $b + $a; // порядок важен!
как работает знак + для массивов, описано в мануале: http://php.net/manual/ru/language.operators.array.php
либо такой:
$a = array_merge($a, $b); // порядок важен
но она перенумеровывает цифровые ключи и тут не подойдет.
Я тут подумал, будет лучше если я не буду сразу говорить ответ, а буду давать подсказки.
Во-первых, вот какими принципами ты должен руководствоваться:
— функция всегда возвращает точный и правдивый результат, в любых условиях. Это значит что если у тебя есть объект $article и ты вызываешь $article->getSubjects() то этот метод должен вернуть точные и актуальные данные. Недопустимо чтобы он например вернул пустой массив из-за того что ты забыл загрузить дополнительные данные в модель. Если ты не соблюдаешь этот принцип, то с кодом невозможно нормально работать, и будут постоянно возникать проблемы.
— SQL код не должен быть размазан по приложению, а должен быть собран в каком-то
ограниченном числе классов
— при использовании паттерна ActiveRecord код работы с базой находится в самой модели (тут ты мог бы заметить что в AR связи реализовать было бы проще), при использовании DataMapper — в мапперах
Теперь вернемся к выборке данных для 2 таблиц. Выбирать можно 2 способами: одним запросом с джойном или двумя последовательными без джойнов (сначала статьи, потом их темы). В случае выборки одним запросом тебе надо написать код, который преобразует выбранные из БД данные в набор связанных объектов. С другой стороны, джойн дает возможность делать более гибкие и сложные выборки, так как ты можешь ставить условия используя обе таблицы (выбрать все новые статьи на определенную тему).
Наконец ты мог бы придумать еще третий вариант: не добавлять вообще метод getSubjects в модель, а сделать этот метод например в маппере тем.
> ArticleMapper делает джоин с 'чужой' таблицей.
Что поделать.
> Надо следить за именами полей либо использовать алиасы, чтобы при джоине не возник конфликт имен полей
Да. Доктрина например генерирует запросы такого вида SELECT t0.id AS id1, t0.name AS name1, .... t1.id AS id2, ...
> Если вынести в отдельную таблицу авторов и еще что-нибудь запрос получится размером с Техас и сложным как синхрофазотрон.
Ты должен сначала проектировать базу, а потом писать работающий с ней код. Если ради красивой структуры БД надо сделать синхрофазотрон, значит надо его сделать. Ты же захочешь хранить дополнительную информацию об авторах, значит это отдельная сущность в отдельной таблице. Если ты не читал, то погугли про нормализацию данных в БД. Отказ от нормализации приведет к плохой структуре БД и к проблемам, например при изменении или обновлении данных.
Ну и люди, читающие твой код, скорее всего ожидают что ты будешь использовать общепринятые подход с нормализацией, а не изобретать свои. Никому не охота в велосипедах разбираться.
И тут я добавлю, что доктрина может сэкономить тебе много сил и времени, так как она предоставляет уже готовые мапперы и она может маппить сложные связи между таблицами на наборы классов. Именно поэтому те, кто работает с базой со связями, предпочитают использовать ORM, потому что без нее тебе придется руками писать джойны на 3-4 таблицы и тебе это быстро надоест. А доктрина пишет запросы сама, без твоего участия.
А если ты все делаешь сам, то да, придется немного пострадать.
Конечно можно обойтись без доктрины и вообще без ООП, писать руками джойны и передавать массивы (причем каждый раз с разным набором полей, попробуй разберись). Это однозначно тупиковый путь, так как в реальном мире мы имеем десятки таблиц, десятки связей между ними и десятки полей в каждой. И при таком подходе у нас в коде будет куча однообразной копипасты SQL запросов, куча массивов (все разного формата). И ты будешь тратить кучу времени на то, чтобы понять какие там поля и откуда пришел этот массив и как туда добавить еще пару полей и не сломается ли код.
По моему, это шаг назад. Друпал так делал, в нем куча массивов толком не описанных в документации. Единственный способ узнать какие в них поля — это натыкать var_dump, причем каждая функция возвращает массив со своим набором полей (они иногда возвращают объекты, но все объекты одного класса и по сути являются массивами).
Вот для примера схема базы данных MediaWiki, движка, на котором работает Википедия: https://upload.wikimedia.org/wikipedia/commons/f/f7/MediaWiki_1.24.1_database_schema.svg (тут почему-то нет стрелочек, показывающих связи, скорее всего потому что у них не прописаны внешние ключи. Не делай так, они это делают из-за необходимости поддержки разных БД)
Вот SQL: https://git.wikimedia.org/blob/mediawiki%2Fcore.git/HEAD/maintenance%2Ftables.sql
Попробуй сам подумать, какой сложный код получается, работающий с такой базой данных и как там много связей.
По поводу твоего кода: как я понимаю, у тебя Subject это отдельная сущность. Тогда я не вижу, где она создается. Ты создаешь только одну статью (new Article), а new Subject я не вижу. То есть должно быть как-то так:
$s = new Subject;
$s->setAttributes($subjectData);
$a = new Article;
$a->setAttributes($articleData);
$a->setSubject($s);
> $this->sqlObjectToArray
не проще сразу данные в виде массива выбирать? Зачем это улсожнение?
Я тут подумал, будет лучше если я не буду сразу говорить ответ, а буду давать подсказки.
Во-первых, вот какими принципами ты должен руководствоваться:
— функция всегда возвращает точный и правдивый результат, в любых условиях. Это значит что если у тебя есть объект $article и ты вызываешь $article->getSubjects() то этот метод должен вернуть точные и актуальные данные. Недопустимо чтобы он например вернул пустой массив из-за того что ты забыл загрузить дополнительные данные в модель. Если ты не соблюдаешь этот принцип, то с кодом невозможно нормально работать, и будут постоянно возникать проблемы.
— SQL код не должен быть размазан по приложению, а должен быть собран в каком-то
ограниченном числе классов
— при использовании паттерна ActiveRecord код работы с базой находится в самой модели (тут ты мог бы заметить что в AR связи реализовать было бы проще), при использовании DataMapper — в мапперах
Теперь вернемся к выборке данных для 2 таблиц. Выбирать можно 2 способами: одним запросом с джойном или двумя последовательными без джойнов (сначала статьи, потом их темы). В случае выборки одним запросом тебе надо написать код, который преобразует выбранные из БД данные в набор связанных объектов. С другой стороны, джойн дает возможность делать более гибкие и сложные выборки, так как ты можешь ставить условия используя обе таблицы (выбрать все новые статьи на определенную тему).
Наконец ты мог бы придумать еще третий вариант: не добавлять вообще метод getSubjects в модель, а сделать этот метод например в маппере тем.
> ArticleMapper делает джоин с 'чужой' таблицей.
Что поделать.
> Надо следить за именами полей либо использовать алиасы, чтобы при джоине не возник конфликт имен полей
Да. Доктрина например генерирует запросы такого вида SELECT t0.id AS id1, t0.name AS name1, .... t1.id AS id2, ...
> Если вынести в отдельную таблицу авторов и еще что-нибудь запрос получится размером с Техас и сложным как синхрофазотрон.
Ты должен сначала проектировать базу, а потом писать работающий с ней код. Если ради красивой структуры БД надо сделать синхрофазотрон, значит надо его сделать. Ты же захочешь хранить дополнительную информацию об авторах, значит это отдельная сущность в отдельной таблице. Если ты не читал, то погугли про нормализацию данных в БД. Отказ от нормализации приведет к плохой структуре БД и к проблемам, например при изменении или обновлении данных.
Ну и люди, читающие твой код, скорее всего ожидают что ты будешь использовать общепринятые подход с нормализацией, а не изобретать свои. Никому не охота в велосипедах разбираться.
И тут я добавлю, что доктрина может сэкономить тебе много сил и времени, так как она предоставляет уже готовые мапперы и она может маппить сложные связи между таблицами на наборы классов. Именно поэтому те, кто работает с базой со связями, предпочитают использовать ORM, потому что без нее тебе придется руками писать джойны на 3-4 таблицы и тебе это быстро надоест. А доктрина пишет запросы сама, без твоего участия.
А если ты все делаешь сам, то да, придется немного пострадать.
Конечно можно обойтись без доктрины и вообще без ООП, писать руками джойны и передавать массивы (причем каждый раз с разным набором полей, попробуй разберись). Это однозначно тупиковый путь, так как в реальном мире мы имеем десятки таблиц, десятки связей между ними и десятки полей в каждой. И при таком подходе у нас в коде будет куча однообразной копипасты SQL запросов, куча массивов (все разного формата). И ты будешь тратить кучу времени на то, чтобы понять какие там поля и откуда пришел этот массив и как туда добавить еще пару полей и не сломается ли код.
По моему, это шаг назад. Друпал так делал, в нем куча массивов толком не описанных в документации. Единственный способ узнать какие в них поля — это натыкать var_dump, причем каждая функция возвращает массив со своим набором полей (они иногда возвращают объекты, но все объекты одного класса и по сути являются массивами).
Вот для примера схема базы данных MediaWiki, движка, на котором работает Википедия: https://upload.wikimedia.org/wikipedia/commons/f/f7/MediaWiki_1.24.1_database_schema.svg (тут почему-то нет стрелочек, показывающих связи, скорее всего потому что у них не прописаны внешние ключи. Не делай так, они это делают из-за необходимости поддержки разных БД)
Вот SQL: https://git.wikimedia.org/blob/mediawiki%2Fcore.git/HEAD/maintenance%2Ftables.sql
Попробуй сам подумать, какой сложный код получается, работающий с такой базой данных и как там много связей.
По поводу твоего кода: как я понимаю, у тебя Subject это отдельная сущность. Тогда я не вижу, где она создается. Ты создаешь только одну статью (new Article), а new Subject я не вижу. То есть должно быть как-то так:
$s = new Subject;
$s->setAttributes($subjectData);
$a = new Article;
$a->setAttributes($articleData);
$a->setSubject($s);
> $this->sqlObjectToArray
не проще сразу данные в виде массива выбирать? Зачем это улсожнение?
> в той модели с которой работает контроллер
Я не понял, при чем тут контроллер? А что без контроллера модель будет работать как-то по другому? Тогда это плохая модель.
> Но тут подводный камень: у автора эта же модель (у него наз. Articles) создает сущности (Article) и присваивает им атрибуты,
Это ActiveRecord, когда модель умеет сама себя загружать из базы. Она описана в моем уроке https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md
Минусы AR в том, что мы смешиваем код работы с БД и код модели вместе. Все же DataMapper более продвинутый подход, особенно когда логика становится сложной. Ну и в случае с AR ты обязан наследовать свои модели от определенного класса, что не всегда удобно.
> а у меня их возвращает маппер, уже готовыми. И мне придется либо передавать автора и тему в маппер наравне с id требуемой статьи, либо доприсваивать их после возвращения, и то и то как-то не очень.
Да, как я тебе говорил раньше, доктрина при загрузке сущности из БД либо вставляет в нее связанные сущности, либо прокси-объекты которые лениво их подгружают при первом обращении. DataMapper более продвинутый и более универсальный, но более сложный в реализации паттерн.
> Походу это фишка activerecord-а.
Да, в AR это проще делается. Но обычно люди не пишут код маппинга руками, а используют готовый (Doctrine 2 например).
для начала надо исправиь ошибки (смотри внизу):
> PHP Notice: Undefined variable: perc in /home/T3Fkzj/prog.php on line 15
> PHP Notice: Undefined variable: perc in /home/T3Fkzj/prog.php on line 15
Ты обращаешься к несуществующей переменной.
Также, у тебя там две почти одинаковых функции. Копипаста это зло и недопустимо, особенно в учеюных заданиях. Объедини их в одну. Можно просто для 2 других кредитов указать дополнительный платеж как 0.
Когда исправишь, посмотрим еще раз.
> Мне кажется, что логично считать платежи через $i*$платёж + остаток
Да, хорошо, если остаток правильно считается то можно исплользовать эту формулу.
Тут есть недостаток, при таком подходе ты не можешь перехватить обращение к полю с помощью функции. Лучше, мне кажется, сделать перехват так:
если (есть функция getSomething) {
вызываем ее;
} иначе {
возвращаем поле;
}
Или же ты можешь магическим методом call перехватывать обращения к функциям getXxx и как бы имитировать их наличие.
Также должна быть проверка и выброс исключения при обращении к несуществующему полю (например если программист опечатался).
Также если ты реализуешь get, не забудь про магические методы set и isset.
Ну и хорошо бы было конечно если ты перед написанием велосипедов изучал существующие библиотеки (да, я намекаю на доктрину).
Посмотри как магические методы работают в Yii2: https://github.com/yiisoft/yii2/blob/master/framework/base/Component.php#L125
Это базовый класс, от которого в том числе наследуются модели.
Замечу так же что Yii2 не очень хорош как учебный пример, на мой взгляд они там намешали все в кучу, а первый Юи вообще был велосипедом из велосипедов.
Ну и раз ты делаешь свои модели, почитай еще как модели сделаны в Юи2:
https://github.com/yiisoft/yii2/blob/master/docs/guide-ru/structure-models.md
Там еще у моделей есть такая штука как behaviours — она позволяет добавлять дополнительное поведение моделям: https://github.com/yiisoft/yii2/blob/master/docs/guide/concept-behaviors.md
Почему нельзя? думаю, можно.
>>467586
> table.setAttribute('class', 'field');
Лучше использовать свойство className, и добавлять/удалять классы через функцию написанную в предыдущей задаче.
У тебя все смешано в одну огромную функцию, более того, в нее вложены другие функции. Это ужасный стиль, так как код тяжело читать. Разбей код на отдельные функции, например:
— функция создания таблицы
— функции добавления/удаления класса
— функция-обработчик клика
— функция-обработчик нажатия на кнопку
Функции не должны вкладываться друг у друга, а должны идти на одном уровне.
> var tds = document.getElementsByTagName('td');
Это неправильный подход, так как твой код сломается если на странице будут еще другие таблицы. Надо перебирать только относящиеся к таблице td (точнее, в этой задаче их вообще перебирать не надо, надо просто добавлять/убирать класс с таблицы)
> //window.onload
Чтобы не было проблем достаточно поставить вызов функции ниже чем теги. Если ты вызываешь функцию раньше то конечно в этот момент код ниже еще не распарсен и элементы еще не созданы.
> TABLE.field {
> BUTTON#toggle {
> DIV#wrapper {
Я думаю, что table (почему большие буквы?) писать тут не надо. Класс field сам по себе однозначно указывает на таблицу и тег писать не нужно. Это только усложняет чтение твоего css и появляются вопросы вроде «а что, тут класс field может и на другие элементы, кроме таблицы, ставиться? »
Тем более для id, который всего один на странице, ничего дополнительно писать не надо.
> box-sizing: border-box;
Если тебе паддинг мешает так обнули его явно, а не заставляй догадываться об этом. Если ставишь хотя бы ставь еще версии с вендорными префиксами (-moz, -webkit-).
А, и может тебе поможет, может нет, обрати внимание что у элемента table есть коллекция строк rows, а у строки коллекция ячеек cells, а у ячейки номер строки и столбца:
https://developer.mozilla.org/ru/docs/Web/API/HTMLTableElement
https://developer.mozilla.org/ru/docs/Web/API/HTMLTableRowElement
https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableCellElement
> var i=0; i < 12;
Цифру стоит вынести в переменную с объясняющим названием
Почему нельзя? думаю, можно.
>>467586
> table.setAttribute('class', 'field');
Лучше использовать свойство className, и добавлять/удалять классы через функцию написанную в предыдущей задаче.
У тебя все смешано в одну огромную функцию, более того, в нее вложены другие функции. Это ужасный стиль, так как код тяжело читать. Разбей код на отдельные функции, например:
— функция создания таблицы
— функции добавления/удаления класса
— функция-обработчик клика
— функция-обработчик нажатия на кнопку
Функции не должны вкладываться друг у друга, а должны идти на одном уровне.
> var tds = document.getElementsByTagName('td');
Это неправильный подход, так как твой код сломается если на странице будут еще другие таблицы. Надо перебирать только относящиеся к таблице td (точнее, в этой задаче их вообще перебирать не надо, надо просто добавлять/убирать класс с таблицы)
> //window.onload
Чтобы не было проблем достаточно поставить вызов функции ниже чем теги. Если ты вызываешь функцию раньше то конечно в этот момент код ниже еще не распарсен и элементы еще не созданы.
> TABLE.field {
> BUTTON#toggle {
> DIV#wrapper {
Я думаю, что table (почему большие буквы?) писать тут не надо. Класс field сам по себе однозначно указывает на таблицу и тег писать не нужно. Это только усложняет чтение твоего css и появляются вопросы вроде «а что, тут класс field может и на другие элементы, кроме таблицы, ставиться? »
Тем более для id, который всего один на странице, ничего дополнительно писать не надо.
> box-sizing: border-box;
Если тебе паддинг мешает так обнули его явно, а не заставляй догадываться об этом. Если ставишь хотя бы ставь еще версии с вендорными префиксами (-moz, -webkit-).
А, и может тебе поможет, может нет, обрати внимание что у элемента table есть коллекция строк rows, а у строки коллекция ячеек cells, а у ячейки номер строки и столбца:
https://developer.mozilla.org/ru/docs/Web/API/HTMLTableElement
https://developer.mozilla.org/ru/docs/Web/API/HTMLTableRowElement
https://developer.mozilla.org/en-US/docs/Web/API/HTMLTableCellElement
> var i=0; i < 12;
Цифру стоит вынести в переменную с объясняющим названием
>>467654
Как это ничего понять не можешь? Ты разве не сам это написал? Если не сам то сотри и попробуй написать сам, копировать код нет смысла. Также, ты можешь попробовать сначала решить следующую задачу про вклад в банк, она проще.
код внутри цикла должен быть примерно такой:
- прибавляем проценты и комиссию к остатку долга
- если остаток маленький, выплачиваем сколько осталось и уходим
- иначе платим 5000
Ну и код у тебя в минус уходит, посмотри:
> 13 месяц спустя: долг = -3729.8132554793 руб, выплачено всего 65000 руб.
А должно быть долг = 0, выплачено 61270
>>467664
Регулярка с виду выглядит нормально, но надо ее проверить на списке номеров.
Задачу про номера телефонов надо проверить на большом числе телефонов, чтобы убедиться что твой код правильный. Но руками подставлять номера — долго и скучно. Пусть работает робот, а не человек!
Для этого давай добавим в программу тесты, чтобы сразу было видно, верно все работает или нет. Сделай 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' // нет +
);
>>467681
Если в кавычки запихать то это просто строка из символа плюс и он ничего не значит.
> Просто я думал, что можно заменить плюсы и минусы переменной, которая один из этих знаков содержит и результат посчитается как обычно.
нельзя
>>467693
Через if/elseif
>>467696
Да, так. Еще в редакторе кода сохранять все в utf8 без BOM (что за бом? вики https://ru.wikipedia.org/wiki/%D0%9C%D0%B0%D1%80%D0%BA%D0%B5%D1%80_%D0%BF%D0%BE%D1%81%D0%BB%D0%B5%D0%B4%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%BE%D1%81%D1%82%D0%B8_%D0%B1%D0%B0%D0%B9%D1%82%D0%BE%D0%B2 )
Еще в коде поставить
mb_internal_encoding(...)
чтобы mb-функции корректно работали.
>>467724
Лучше писать не if ($creditBalance == 0) { а $creditBalance <= 0 так как в компьютере приближенные вычисления и может получиться -0.00000000001 вместо нуля.
А так, верно.
>>467727
Условия выполнить мало, надо еще чтобы код был аккуратным, переменные хорошо названы, не было копипасты и код легко читался.
>>467739
Согласен, хороший. Только помни что бекслеш там пишется один раз.
В PHP: \\s или \s
На сайте \s
В PHP (чтобы найти бекслеш): строго \\\\
На сайте: \\
Это потому что в PHP строка обрабатывается 2 раза: сначала распознаются бекслеш-последовательности в строке, потом бекслеш последовательности в регулярке. А на сайте только бекслеш последовательности в регулярке и удваивать бекслеш не надо.
Ну и код у тебя в минус уходит, посмотри:
> 13 месяц спустя: долг = -3729.8132554793 руб, выплачено всего 65000 руб.
А должно быть долг = 0, выплачено 61270
>>467664
Регулярка с виду выглядит нормально, но надо ее проверить на списке номеров.
Задачу про номера телефонов надо проверить на большом числе телефонов, чтобы убедиться что твой код правильный. Но руками подставлять номера — долго и скучно. Пусть работает робот, а не человек!
Для этого давай добавим в программу тесты, чтобы сразу было видно, верно все работает или нет. Сделай 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' // нет +
);
>>467681
Если в кавычки запихать то это просто строка из символа плюс и он ничего не значит.
> Просто я думал, что можно заменить плюсы и минусы переменной, которая один из этих знаков содержит и результат посчитается как обычно.
нельзя
>>467693
Через if/elseif
>>467696
Да, так. Еще в редакторе кода сохранять все в utf8 без BOM (что за бом? вики https://ru.wikipedia.org/wiki/%D0%9C%D0%B0%D1%80%D0%BA%D0%B5%D1%80_%D0%BF%D0%BE%D1%81%D0%BB%D0%B5%D0%B4%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%BE%D1%81%D1%82%D0%B8_%D0%B1%D0%B0%D0%B9%D1%82%D0%BE%D0%B2 )
Еще в коде поставить
mb_internal_encoding(...)
чтобы mb-функции корректно работали.
>>467724
Лучше писать не if ($creditBalance == 0) { а $creditBalance <= 0 так как в компьютере приближенные вычисления и может получиться -0.00000000001 вместо нуля.
А так, верно.
>>467727
Условия выполнить мало, надо еще чтобы код был аккуратным, переменные хорошо названы, не было копипасты и код легко читался.
>>467739
Согласен, хороший. Только помни что бекслеш там пишется один раз.
В PHP: \\s или \s
На сайте \s
В PHP (чтобы найти бекслеш): строго \\\\
На сайте: \\
Это потому что в PHP строка обрабатывается 2 раза: сначала распознаются бекслеш-последовательности в строке, потом бекслеш последовательности в регулярке. А на сайте только бекслеш последовательности в регулярке и удваивать бекслеш не надо.
> не получается сделать так, чтобы объекты не выходили за рамки карты.
Когда делаешь ход, надо ограничивать координату:
$newX = $this->clamp($newX, 0, $mapWidth - 1);
Где функция clamp ограничивает значение в указанных рамках c помощью min и max.
> $mouse->move($world, $cat);
Это явно тупиковый путь, а что если у нас будет много кошек, ты их все будешь передавать в мышь? Я думаю, кошки и мышки должны храниться внутри World. А присоединяется к миру мышь в момент добавления:
$world = new World;
$mouse = new Mouse;
$world->addAnimal($mouse); // мышь добвалена в мир, в этот момент в мышь передается ссылка на $world и она может к нему обращаться
$world->removeAninal($mouse);// мышь удаляется из мира,а из мыши удаляется ссылка на мир
Заметь что при таком подходе мы можем иметь аж несколько миров и перемещать животных между ними (мир живых, и мир мертвых где мышки едят кошек например или рай и ад).
> private function createMap($m = 10, $n = 10) {
> \t$this->m = $m;
Вот это серьезная ошибка, назвать свойство $m. Это ничего не говорит о его содержимом. Ну представь код где-то:
public function getV()
{
return $this->m + $this->x - $this->y; // попробуй разберись
}
И прочти статью: https://learn.javascript.ru/write-unmain-code
> $this->map = array_fill(0, $m, array_fill(0, $n, ''));
Зачем вообще нужно это свойство map? По моему без него код был бы короче и проще. Например можно убрать метод public function moveAnimal(array $from, array $to) целиком. Ты сам себе усложняешь жизнь создавая этот массив и поддерживая его актуальность.
Более того, у тебя сейчас нет очень важных методов вроде
$world->getAllMice()
По моему проще сделать один массив Животные и все.
> \tprivate function createMap($m = 10, $n = 10) {
Эта функция написана так что передать в нее другие значения никак невозможно. Я думаю, размеры мира удобнее указывать в конструкторе.
> https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/World.php#L36
Здесь ты пишешь return false. Разумеется, во всех местах, где ты используешь эту функцию, ты проверяешь, что она вернет? Если нет то это выглядит как ошибка. Зачем возвращать значение которое никому не нужно? Зачем скрывать ошибку и притворяться что ничего не произошло?
Если тебе передали неправильный массив, лучше всего выбросить исключение (а еще лучше вообще не использовать тут массивы и тогда не придется их проверять). Вот описание принципа fail fast: http://habrahabr.ru/post/218325/
Вот урок по исключениям: https://gist.github.com/codedokode/65d43ca5ac95c762bc1a
> switch ($to['y']) {
>\t\t\tcase ($to['y'] > $this->m):
Switch это тебе не if/else и этот код не работает. Потому что switch будет делать сравнение в таком виде:
if ($to['y'] == ($to['y'] > $this->m)) { ... }
То есть он будет сравнивать число, например, 5 с логическим значением true или false (операция > возвращает именно true или false). мануал:
http://php.net/manual/ru/control-structures.switch.php
http://php.net/manual/ru/language.operators.comparison.php
> https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/Animal.php#L21
> public function getCoordinate() {
По моему проще сделать методы getX и getY и обойтись без лишнего массива и его проверки.
> public function searchTheAnimal(World $world, Animal $animal) {
Я не понимаю, зачем нужна эта функция. Она выглядит как усложненная версия того, что можно сделать проще. Зачем перебирать все клеточки? Если ты хочешь проверить видишь ты животное или нет, проще посчитать расстояние до него и сравнить с радиусом зрения.
Насчет выбора хода, я предлагаю сделать это более удобным алгоритмом:
— создаем список всех возможных ходов, включая стоять на месте (на этом этапе можно отсеять запрещенные ходы за край карты)
— оцениваем каждый ход в баллах
— выбираем наиболее выгодный
— делаем ход
Что касается этого адского if:
https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/Cat.php#L20
То он делается проще, по типу такого:
$dx = 0;
если (мышь правее) {
$dx = 1;
} иначе если она левее {
$dx = - 1;
}
Где dx это направление шага по оси x.
Но как я написал выше, мне кажется лучше поставить универсальный алгоритм с очками, тем более он подходит для обоих животных.
> не получается сделать так, чтобы объекты не выходили за рамки карты.
Когда делаешь ход, надо ограничивать координату:
$newX = $this->clamp($newX, 0, $mapWidth - 1);
Где функция clamp ограничивает значение в указанных рамках c помощью min и max.
> $mouse->move($world, $cat);
Это явно тупиковый путь, а что если у нас будет много кошек, ты их все будешь передавать в мышь? Я думаю, кошки и мышки должны храниться внутри World. А присоединяется к миру мышь в момент добавления:
$world = new World;
$mouse = new Mouse;
$world->addAnimal($mouse); // мышь добвалена в мир, в этот момент в мышь передается ссылка на $world и она может к нему обращаться
$world->removeAninal($mouse);// мышь удаляется из мира,а из мыши удаляется ссылка на мир
Заметь что при таком подходе мы можем иметь аж несколько миров и перемещать животных между ними (мир живых, и мир мертвых где мышки едят кошек например или рай и ад).
> private function createMap($m = 10, $n = 10) {
> \t$this->m = $m;
Вот это серьезная ошибка, назвать свойство $m. Это ничего не говорит о его содержимом. Ну представь код где-то:
public function getV()
{
return $this->m + $this->x - $this->y; // попробуй разберись
}
И прочти статью: https://learn.javascript.ru/write-unmain-code
> $this->map = array_fill(0, $m, array_fill(0, $n, ''));
Зачем вообще нужно это свойство map? По моему без него код был бы короче и проще. Например можно убрать метод public function moveAnimal(array $from, array $to) целиком. Ты сам себе усложняешь жизнь создавая этот массив и поддерживая его актуальность.
Более того, у тебя сейчас нет очень важных методов вроде
$world->getAllMice()
По моему проще сделать один массив Животные и все.
> \tprivate function createMap($m = 10, $n = 10) {
Эта функция написана так что передать в нее другие значения никак невозможно. Я думаю, размеры мира удобнее указывать в конструкторе.
> https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/World.php#L36
Здесь ты пишешь return false. Разумеется, во всех местах, где ты используешь эту функцию, ты проверяешь, что она вернет? Если нет то это выглядит как ошибка. Зачем возвращать значение которое никому не нужно? Зачем скрывать ошибку и притворяться что ничего не произошло?
Если тебе передали неправильный массив, лучше всего выбросить исключение (а еще лучше вообще не использовать тут массивы и тогда не придется их проверять). Вот описание принципа fail fast: http://habrahabr.ru/post/218325/
Вот урок по исключениям: https://gist.github.com/codedokode/65d43ca5ac95c762bc1a
> switch ($to['y']) {
>\t\t\tcase ($to['y'] > $this->m):
Switch это тебе не if/else и этот код не работает. Потому что switch будет делать сравнение в таком виде:
if ($to['y'] == ($to['y'] > $this->m)) { ... }
То есть он будет сравнивать число, например, 5 с логическим значением true или false (операция > возвращает именно true или false). мануал:
http://php.net/manual/ru/control-structures.switch.php
http://php.net/manual/ru/language.operators.comparison.php
> https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/Animal.php#L21
> public function getCoordinate() {
По моему проще сделать методы getX и getY и обойтись без лишнего массива и его проверки.
> public function searchTheAnimal(World $world, Animal $animal) {
Я не понимаю, зачем нужна эта функция. Она выглядит как усложненная версия того, что можно сделать проще. Зачем перебирать все клеточки? Если ты хочешь проверить видишь ты животное или нет, проще посчитать расстояние до него и сравнить с радиусом зрения.
Насчет выбора хода, я предлагаю сделать это более удобным алгоритмом:
— создаем список всех возможных ходов, включая стоять на месте (на этом этапе можно отсеять запрещенные ходы за край карты)
— оцениваем каждый ход в баллах
— выбираем наиболее выгодный
— делаем ход
Что касается этого адского if:
https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/Cat.php#L20
То он делается проще, по типу такого:
$dx = 0;
если (мышь правее) {
$dx = 1;
} иначе если она левее {
$dx = - 1;
}
Где dx это направление шага по оси x.
Но как я написал выше, мне кажется лучше поставить универсальный алгоритм с очками, тем более он подходит для обоих животных.
Молодец, все верно.
>>467781
Убери копипасту. Из двух функций надо оставить только одну. В остальном, верно.
>>467799
В /wrk истории
>>467807
Можно попробовать, но убедись что знаешь ООП хотя бы
>>467853
> Если работает, значит правильно.
Нет, этого недостаточно. Надо еще чтобы я не нашел копипасты, неправильно названных переменных, сложных конструкций, запутанного кода.
Ты тесты сделал не очень удачно, так как с первого взгляда неясно, правильно программа работает или нет. Надо в функцию checkRegExp передавать ожидаемый результат и если что-то не так, выводить какой-то заметный знак, чтобы с первого взгляда было видно что не так.
Регулярка вполне правильная.
> Меня напрягает та часть выражения, где юзер может засандалить кучу скобок, дефисов и пробелов.
Ну больше 4 подряд он не засандалит, так что ничего страшного. Да и цель программы тут в первую очередь отсеять явные ошибки, опечатки (забыли ввести цифру) и случаи когда пользователь не понял что от него хотят (и вводит что-то левое).
Молодец, все верно.
>>467781
Убери копипасту. Из двух функций надо оставить только одну. В остальном, верно.
>>467799
В /wrk истории
>>467807
Можно попробовать, но убедись что знаешь ООП хотя бы
>>467853
> Если работает, значит правильно.
Нет, этого недостаточно. Надо еще чтобы я не нашел копипасты, неправильно названных переменных, сложных конструкций, запутанного кода.
Ты тесты сделал не очень удачно, так как с первого взгляда неясно, правильно программа работает или нет. Надо в функцию checkRegExp передавать ожидаемый результат и если что-то не так, выводить какой-то заметный знак, чтобы с первого взгляда было видно что не так.
Регулярка вполне правильная.
> Меня напрягает та часть выражения, где юзер может засандалить кучу скобок, дефисов и пробелов.
Ну больше 4 подряд он не засандалит, так что ничего страшного. Да и цель программы тут в первую очередь отсеять явные ошибки, опечатки (забыли ввести цифру) и случаи когда пользователь не понял что от него хотят (и вводит что-то левое).
Ты делаешь неправильно. Лучше учиться последовательно менять код, ведь в реальных проектах никто не создает каждый раз новую папку, а правит существующий код. Привыкай сразу делать правльно.
> но копирую по одному файлу из старого проекта если он подходит и переделываю его, мне так проще отследить что уже сделано, а что надо сделать чем брать весь проект целиком и искать по файлам то что мне нужно
Ну у тебя же всего пара десятков файлов, выпиши на бумажку или в отдельный файл какие хорошие, какие нет, и плохие удаляй.
> думал это файлы которые содержат преимущественно html и которые загружаются при необходимости вывода инфы.
Да, верно. Вот это вот: https://github.com/Si0n/register3/blob/master/template/edit.php хороший пример шаблона.
А вот это плохой: https://github.com/Si0n/register3/blob/master/template/main.php так как ты туда засунул проверку кук, и ее в шаблоне не должно быть.
> Мне бы по самому содержимому, по логике больше хотелось услышать замечания, счас то я переделаю текущий вариант, размещу по папкам как надо, а потом выйдет так, что там придется всё изменять по самому содержимому.
Пока замечания будут по тому, что ты код не туда поместил. Сначала мы его должны разложить аккуратно по файлам, а потом уже в самом коде ошибки искать. Я не могу нормально разбираться в коде который раскидан кусками по разным файлам.
> плюс гит ругается при попытке отправить изменения в старый проект.
Надо бы разобраться почему. Напиши что ты делаешь и что выводит гит.
Сейчас еще напишу.
Итак, начать придется с четкого разделения на публичные файлы (вызываются из браузера), файлы с классами и логикой (в папке lib) и шаблоны с HTML кодом.
По файлам: как я написал выше, вынеси файлы, которые вызвыаются из браузера, в корень, чтобя я их легко мог увидеть. Назови их с маленькой буквы, с большой только файлы с классами.
Также из браузера не должно быть обращения напрямую к шаблонам, как у тебя:
> header("Location: http://localhost/php/students/template/main.php?page=registration");
Обращаться из браузера нужно только к размещенным в корне скриптам. Чтобы я и любой другой программист сразу видели, где публичные скрипты, где непубличные, где шаблоны.
По поводу таблицы errors и хранения ошибок в таблице, мне не очень нравится эта идея. Мне кажется ты переусложнил то, что можно сделать проще, без лишней таблицы.
Вот что плохо:
— ты в качестве ключа используешь куку. Тут это не критично, но кука общая для всех вкладок браузера. если ты применишь этот подход на другом сайте, и пользователь откроет несколько форм одновременно то сообщения об ошибках будут выводиться во всех формах сразу. Путаница.
— ты не сохраняешь текст ошибки, а только факт ее наличия. У тебя не может быть разнообразия в сообщениях, например «Вы ввели 2 символа в номере группы, а надо ввести минимум 5»
— при ошибке в заполнении формы регистрации все введенные данные теряются. Как ты думаешь, приятно ли будет пользователю об этом узнать?
Все эти недостатки можно исправить если сделать работу с формами как описано у меня в уроке: https://github.com/codedokode/pasta/blob/master/forms.md
При ошибке мы никуда не редиректим, а просто выводим форму с введенными данными и текстом ошибки. И таблица нам становится не нужна.
Если тебе что-то непонятно из того что там написано, задавай вопросы. Если у тебя есть свой подход, и ты не согласен с моим, приведи какие-то аргументы, чем твой подход лучше.
Инициализацию удобнее делать не в виде класса, а обычным файлом. Ну и require_once должен стоять в самом верху файла, и не должен быть внутри функций, классов (кроме каких-то особых случаев, но тут явно не особый случай).
Далее, открой эту страницу: https://github.com/Si0n/register3/blob/master/template/dashboard.php
Видишь, знак & подсвечен красным? потому что по правилам языка HTML символы &, <, > должны вставляться в исходный код как HTML-мнемоники про которые можно прочесть тут http://htmlbook.ru/samhtml/tekst/spetssimvoly
Вот тут вот https://github.com/Si0n/register3/blob/master/template/edit.php я вижу что ты выводишь данные их переменных без экранирования спецсимволов (тех самых & > <). Тут может быть уязвимость XSS, если еще не читал то почитай мой урок: https://github.com/codedokode/pasta/blob/master/security/xss.md
Далее, из шаблонов ты не должен подключать файлы с логикой (можно только другие шаблоны подключать): https://github.com/Si0n/register3/blob/master/template/list.php#L7 — иначе получается бардак и все запутанно.
То же самое тут: https://github.com/Si0n/register3/blob/master/template/register.php#L2
> include('./../lib/FormInspect.php');
Не подключай логику из шаблона. Шаблон просто выводит те переменные, которые ему передали, и все.
В этом файле половина РHP, половина HTML. HTML надо перенести в шаблон: https://github.com/Si0n/register3/blob/master/lib/pager.php
> aria-hidden="true"
ты знаешь что значит этот атрибут? Если не знаешь, то удаляй, у себя в коде ты должен понимать каждую строчку.
> https://github.com/Si0n/register3/blob/master/lib/StudentsMapper.php#L72
> while ($students = $srchStudents->fetch()) {
Есть функция fetchAll для этого, не надо писать циклы как в старых учебниках
Если тебе что-то непонятно, ты с чем-то не согласен, задавай вопросы. Я постараюсь на все ответить.
Итак, начать придется с четкого разделения на публичные файлы (вызываются из браузера), файлы с классами и логикой (в папке lib) и шаблоны с HTML кодом.
По файлам: как я написал выше, вынеси файлы, которые вызвыаются из браузера, в корень, чтобя я их легко мог увидеть. Назови их с маленькой буквы, с большой только файлы с классами.
Также из браузера не должно быть обращения напрямую к шаблонам, как у тебя:
> header("Location: http://localhost/php/students/template/main.php?page=registration");
Обращаться из браузера нужно только к размещенным в корне скриптам. Чтобы я и любой другой программист сразу видели, где публичные скрипты, где непубличные, где шаблоны.
По поводу таблицы errors и хранения ошибок в таблице, мне не очень нравится эта идея. Мне кажется ты переусложнил то, что можно сделать проще, без лишней таблицы.
Вот что плохо:
— ты в качестве ключа используешь куку. Тут это не критично, но кука общая для всех вкладок браузера. если ты применишь этот подход на другом сайте, и пользователь откроет несколько форм одновременно то сообщения об ошибках будут выводиться во всех формах сразу. Путаница.
— ты не сохраняешь текст ошибки, а только факт ее наличия. У тебя не может быть разнообразия в сообщениях, например «Вы ввели 2 символа в номере группы, а надо ввести минимум 5»
— при ошибке в заполнении формы регистрации все введенные данные теряются. Как ты думаешь, приятно ли будет пользователю об этом узнать?
Все эти недостатки можно исправить если сделать работу с формами как описано у меня в уроке: https://github.com/codedokode/pasta/blob/master/forms.md
При ошибке мы никуда не редиректим, а просто выводим форму с введенными данными и текстом ошибки. И таблица нам становится не нужна.
Если тебе что-то непонятно из того что там написано, задавай вопросы. Если у тебя есть свой подход, и ты не согласен с моим, приведи какие-то аргументы, чем твой подход лучше.
Инициализацию удобнее делать не в виде класса, а обычным файлом. Ну и require_once должен стоять в самом верху файла, и не должен быть внутри функций, классов (кроме каких-то особых случаев, но тут явно не особый случай).
Далее, открой эту страницу: https://github.com/Si0n/register3/blob/master/template/dashboard.php
Видишь, знак & подсвечен красным? потому что по правилам языка HTML символы &, <, > должны вставляться в исходный код как HTML-мнемоники про которые можно прочесть тут http://htmlbook.ru/samhtml/tekst/spetssimvoly
Вот тут вот https://github.com/Si0n/register3/blob/master/template/edit.php я вижу что ты выводишь данные их переменных без экранирования спецсимволов (тех самых & > <). Тут может быть уязвимость XSS, если еще не читал то почитай мой урок: https://github.com/codedokode/pasta/blob/master/security/xss.md
Далее, из шаблонов ты не должен подключать файлы с логикой (можно только другие шаблоны подключать): https://github.com/Si0n/register3/blob/master/template/list.php#L7 — иначе получается бардак и все запутанно.
То же самое тут: https://github.com/Si0n/register3/blob/master/template/register.php#L2
> include('./../lib/FormInspect.php');
Не подключай логику из шаблона. Шаблон просто выводит те переменные, которые ему передали, и все.
В этом файле половина РHP, половина HTML. HTML надо перенести в шаблон: https://github.com/Si0n/register3/blob/master/lib/pager.php
> aria-hidden="true"
ты знаешь что значит этот атрибут? Если не знаешь, то удаляй, у себя в коде ты должен понимать каждую строчку.
> https://github.com/Si0n/register3/blob/master/lib/StudentsMapper.php#L72
> while ($students = $srchStudents->fetch()) {
Есть функция fetchAll для этого, не надо писать циклы как в старых учебниках
Если тебе что-то непонятно, ты с чем-то не согласен, задавай вопросы. Я постараюсь на все ответить.
Интересно, почему? Довольно странно, что такого функционала в PHP нет.
>>467873
Хорошо, учту твои замечания по оптимизации кода на будущее.
>>467876
Ну я пытался в массиве $spelling заменить значение ключей [1] и [2] значениями таких же ключей из массива $femaleSpelling. Записал как array_replace($spelling, $femaleSpelling), но почему-то не сработало.
Алсо, чекни задачку про калькулятор. Вначале не догнал как ее решать, поэтому немножко подсмотрел принцип решения у других. Но как только понял суть, дальше решал уже сам. Добавил деление, но как я понял там вся суть в том, что число может дробное получиться и по умолчанию программа эту дробь округляет до каких-то там тысячных, поэтому итоговое значение может получиться не совсем верным. Оставить ли все как есть или стоит что-то с этим сделать?
Пили новый тред, заебал.
http://ideone.com/EFeXlg
спасибо большое, очень хочется прекратить говнокодить, но не знаю как найти литературу, в которой было бы описано не как что-то сделать на пхпх, или скажем на js, а как это всё грамотно совместить, чтобы не получалась куча говна как у меня.. Хочется быть нормальным человеком, адекватным, а не быдлом. Вот я не понимаю как можно не мешать html и php. Сам я не могу до этого додуматься, наверное, я тупой.
Доктрина отображает записи в базе на объекты потому надо просто поменять данные в управляемой доктриной модели.
// Загрузить модель
$article = $em->getRepository('Articles')->find($id);
// поменять в ней данные
$article->setTitle('New title');
$article->setDate(new DateTime('2015-02-02 12:00:00'));
// сохранить изменения (вызывает поиск и сохранение изменений в БД)
$em->flush( );
Если тебе надо сделать много изменений, то делай все изменения, а потом в конце 1 раз вызови flush чтобы сохранить их в БД одной транзакцией.
> Если ты не читал, то погугли про нормализацию данных в БД.
Именно после прочтения статьи про нормализацию я понял насколько убого было иметь поле authors с несколькими одинаковыми авторами в articles.
>В случае выборки одним запросом тебе надо написать код, который преобразует выбранные из БД данные в набор связанных объектов
А зачем нужно именно разносить их по разным объектам? В случае с джоинами Тема, Автор же просто попадут отдельными полями в результирующую таблицу выборки статей и их можно напрямую присвоить Статье в setAttributes($articleDate - тема и автор уже тут). Этот вопрос о том самом:
>как я понимаю, у тебя Subject это отдельная сущность. Тогда я не вижу, где она создается. Ты создаешь только одну статью (new Article), а new Subject я не вижу
Т. е. я не понимаю зачем здесь может понадобиться new Subject.
Само собой для добавления/редактирования самих Тем и Авторов в других моделях и своем маппере они будут нужны.
>Конечно можно обойтись без доктрины и вообще без ООП
Я хочу запилить вот этот текущий проект, не погружаясь во фреймворки и доктрины. Сосредоточиться только на ООП, MVC, паттернах, таких как datamapper (кстати, чтоб еще такого же полезного взять на вооружение?). Возможно где-то хлебнуть горя, изобрести велик, но зато в следующем взяться за что-то серьезное, может symfony, и просто начать УБИВАТЬ. Ладно, это такое. Допустим, использовать доктрину я не хочу ни в какую.
Остаются четыре стула
1. JOIN с темами в маппере статей. Сложные запросы я готов пережить, заодно качну SQL.
>передавать массивы (причем каждый раз с разным набором полей, попробуй разберись)
Но это намного хуже, я же только завязал с массивами, правда он тут и так и так передается в setAttributes(), без этого никак. Но если как ты говорил нужно разносить данные по разным объектам после джоина, то все резко усложняется. А почему набор полей будет разным, ведь всем статьям нужны темы и авторы?
2. Добываем Статью в модели, потом Тему и Автора по отдельности, каждую сущность своим маппером. Иии... делаем метод createUltimateHardcoreAllTogetherArticle который их миксует в конечный объект для выдачи во вью. Но что-то тут не так. И тут я внезапно понимаю что ты имел ввиду
>если у тебя есть объект $article и ты вызываешь $article->getSubjects() то этот метод должен вернуть точные и актуальные данные. Недопустимо чтобы он например вернул пустой массив из-за того что ты забыл загрузить дополнительные данные в модель
Да, выходит что у Статьи при создании появляется метод который до заполнения всех свойств в модели возвращает пустоту. Не круто. И придумать особо нечего.
3. Добываем Темы и Авторов в модели и передаем их в метод
$this->articlemapper->getArticleById($id, $subjects, $authors);
Грязновато смотрится - взятьПоАйДи(), а передается цыганский табор. Хотя и получше чем вернуть статью, потом что-то доприсвоить и вернуть конечный результат. Все равно крутого мало.
4. >не добавлять вообще метод getSubjects в модель, а сделать этот метод например в маппере тем
А вызывать маппер тем внутри маппера статей - это норм? Я думал это харам. Так-то может выйти неплохо.
КУДА СЕСТЬ? Уже не терпится кодить.
> Если ты не читал, то погугли про нормализацию данных в БД.
Именно после прочтения статьи про нормализацию я понял насколько убого было иметь поле authors с несколькими одинаковыми авторами в articles.
>В случае выборки одним запросом тебе надо написать код, который преобразует выбранные из БД данные в набор связанных объектов
А зачем нужно именно разносить их по разным объектам? В случае с джоинами Тема, Автор же просто попадут отдельными полями в результирующую таблицу выборки статей и их можно напрямую присвоить Статье в setAttributes($articleDate - тема и автор уже тут). Этот вопрос о том самом:
>как я понимаю, у тебя Subject это отдельная сущность. Тогда я не вижу, где она создается. Ты создаешь только одну статью (new Article), а new Subject я не вижу
Т. е. я не понимаю зачем здесь может понадобиться new Subject.
Само собой для добавления/редактирования самих Тем и Авторов в других моделях и своем маппере они будут нужны.
>Конечно можно обойтись без доктрины и вообще без ООП
Я хочу запилить вот этот текущий проект, не погружаясь во фреймворки и доктрины. Сосредоточиться только на ООП, MVC, паттернах, таких как datamapper (кстати, чтоб еще такого же полезного взять на вооружение?). Возможно где-то хлебнуть горя, изобрести велик, но зато в следующем взяться за что-то серьезное, может symfony, и просто начать УБИВАТЬ. Ладно, это такое. Допустим, использовать доктрину я не хочу ни в какую.
Остаются четыре стула
1. JOIN с темами в маппере статей. Сложные запросы я готов пережить, заодно качну SQL.
>передавать массивы (причем каждый раз с разным набором полей, попробуй разберись)
Но это намного хуже, я же только завязал с массивами, правда он тут и так и так передается в setAttributes(), без этого никак. Но если как ты говорил нужно разносить данные по разным объектам после джоина, то все резко усложняется. А почему набор полей будет разным, ведь всем статьям нужны темы и авторы?
2. Добываем Статью в модели, потом Тему и Автора по отдельности, каждую сущность своим маппером. Иии... делаем метод createUltimateHardcoreAllTogetherArticle который их миксует в конечный объект для выдачи во вью. Но что-то тут не так. И тут я внезапно понимаю что ты имел ввиду
>если у тебя есть объект $article и ты вызываешь $article->getSubjects() то этот метод должен вернуть точные и актуальные данные. Недопустимо чтобы он например вернул пустой массив из-за того что ты забыл загрузить дополнительные данные в модель
Да, выходит что у Статьи при создании появляется метод который до заполнения всех свойств в модели возвращает пустоту. Не круто. И придумать особо нечего.
3. Добываем Темы и Авторов в модели и передаем их в метод
$this->articlemapper->getArticleById($id, $subjects, $authors);
Грязновато смотрится - взятьПоАйДи(), а передается цыганский табор. Хотя и получше чем вернуть статью, потом что-то доприсвоить и вернуть конечный результат. Все равно крутого мало.
4. >не добавлять вообще метод getSubjects в модель, а сделать этот метод например в маппере тем
А вызывать маппер тем внутри маппера статей - это норм? Я думал это харам. Так-то может выйти неплохо.
КУДА СЕСТЬ? Уже не терпится кодить.
> А зачем нужно именно разносить их по разным объектам? В случае с джоинами Тема, Автор же просто попадут отдельными полями в результирующую таблицу выборки статей и их можно напрямую присвоить Статье в setAttributes
Ну у меня такие мысли:
— во-первых, это приводит к дупликации данных. У тебя есть имя автора в Статье и есть отдельно объект Автор, и в нем тоже имя автора. И ты меняешь это имя, а в Статье оно не меняется. Также, нелогично что имя автора хранится в 2 местах. Логичнее когда в Статье хранится объект-автор.
— тебе может понадобиться какая-то другая информация, например не только имя автора, а дата его регистрации, и как ты это получишь из Статьи?
— так делают при работе с доктриной и другими ORM. делают именно отдельные объекты и связи между ними. ORM же создает видимость что у тебя все объекты в памяти и связаны наиболее логичным образом и ты всегда можешь получить Автора имея Статью.
То есть если у тебя Автор это отдельная сущность то логично для него сделать отдельную модель.
> Но если как ты говорил нужно разносить данные по разным объектам после джоина, то все резко усложняется.
да не так и усложняется. Раньше тебе надо было создавать только Статьи, сейчас надо будет создавать Статьи и Авторов и сопоставлять друг с другом.
> Добываем Статью в модели, потом Тему и Автора по отдельности, каждую сущность своим маппером.
Это тоже вариант. Первый маппер берет все нужные статьи, загружает авторов для них вторым маппером и присоединяет к статьям.
> Да, выходит что у Статьи при создании появляется метод который до заполнения всех свойств в модели возвращает пустоту. Не круто. И придумать особо нечего.
Вот-вот. Я же предупреждал что писать свой ORM это боль.
> Добываем Темы и Авторов в модели и передаем их в метод
В смысле, загружаем из базы всех существующих авторов? Это плохая идея если их много.
> Грязновато смотрится - взятьПоАйДи(), а передается цыганский табор.
Да
>> не добавлять вообще метод getSubjects в модель, а сделать этот метод например в маппере тем
Я имел в виду получать темы примерно так:
$subject = $subjMapper->getSubjectForArticle($article);
То есть мы не храним тему внутри article вообще, и у него нет метода getSubjects и часть проблем отпадает. Ну и конечно можно сделать еще метод для массового получения тем:
$subjects = $subjMapper->getSubjectsForManyArticles($articles);
Ну и еще 5 вариант, использовать ActiveRecord.
> А вызывать маппер тем внутри маппера статей - это норм?
Это может оказаться меньшим из зол.
> А зачем нужно именно разносить их по разным объектам? В случае с джоинами Тема, Автор же просто попадут отдельными полями в результирующую таблицу выборки статей и их можно напрямую присвоить Статье в setAttributes
Ну у меня такие мысли:
— во-первых, это приводит к дупликации данных. У тебя есть имя автора в Статье и есть отдельно объект Автор, и в нем тоже имя автора. И ты меняешь это имя, а в Статье оно не меняется. Также, нелогично что имя автора хранится в 2 местах. Логичнее когда в Статье хранится объект-автор.
— тебе может понадобиться какая-то другая информация, например не только имя автора, а дата его регистрации, и как ты это получишь из Статьи?
— так делают при работе с доктриной и другими ORM. делают именно отдельные объекты и связи между ними. ORM же создает видимость что у тебя все объекты в памяти и связаны наиболее логичным образом и ты всегда можешь получить Автора имея Статью.
То есть если у тебя Автор это отдельная сущность то логично для него сделать отдельную модель.
> Но если как ты говорил нужно разносить данные по разным объектам после джоина, то все резко усложняется.
да не так и усложняется. Раньше тебе надо было создавать только Статьи, сейчас надо будет создавать Статьи и Авторов и сопоставлять друг с другом.
> Добываем Статью в модели, потом Тему и Автора по отдельности, каждую сущность своим маппером.
Это тоже вариант. Первый маппер берет все нужные статьи, загружает авторов для них вторым маппером и присоединяет к статьям.
> Да, выходит что у Статьи при создании появляется метод который до заполнения всех свойств в модели возвращает пустоту. Не круто. И придумать особо нечего.
Вот-вот. Я же предупреждал что писать свой ORM это боль.
> Добываем Темы и Авторов в модели и передаем их в метод
В смысле, загружаем из базы всех существующих авторов? Это плохая идея если их много.
> Грязновато смотрится - взятьПоАйДи(), а передается цыганский табор.
Да
>> не добавлять вообще метод getSubjects в модель, а сделать этот метод например в маппере тем
Я имел в виду получать темы примерно так:
$subject = $subjMapper->getSubjectForArticle($article);
То есть мы не храним тему внутри article вообще, и у него нет метода getSubjects и часть проблем отпадает. Ну и конечно можно сделать еще метод для массового получения тем:
$subjects = $subjMapper->getSubjectsForManyArticles($articles);
Ну и еще 5 вариант, использовать ActiveRecord.
> А вызывать маппер тем внутри маппера статей - это норм?
Это может оказаться меньшим из зол.
> Довольно странно, что такого функционала в PHP нет.
Потому что он никому практически не нужен, и есть eval (который запутывает код и опасен и лучше не использовать)
> записал как array_replace($spelling, $femaleSpelling), но почему-то не сработало.
она создает и возвращает новый массив, ты его сохранил?
> Добавил деление, но как я понял там вся суть в том, что число может дробное получиться и по умолчанию программа эту дробь округляет до каких-то там тысячных, поэтому итоговое значение может получиться не совсем верным. Оставить ли все как есть или стоит что-то с этим сделать?
Ничего не поделать. Единственное решение это сделать полноценную работу с дробями чтобы например 1/3 хранилось как дробь (кстати это было в одной из продвинутых старых версий задачи и по моему кто-то даже это сделал, по моему на Питоне).
Решено верно, но что-то код очень знакомый.
>>467957
Надо смотреть хорошие примеры кода, например в известных фреймворках (для PHP это Симфони 2 например) и библиотеках. Книги про качество кода есть («Совершенный код» например), но там не упоминается ни php ни JS, а общие принципы.
Ну и общие принципы такие, что не надо все смешивать в кучу, код должен писаться для людей, чтобы им было максимально легко его понять и исправить, чтоюы там не было подводных камней и трудно было сделать ошибку при правке.
Вот например статья про то как надо называть переменные: https://learn.javascript.ru/write-unmain-code
Еще есть хороший сайт http://phptherightway.ru/
> Вот я не понимаю как можно не мешать html и php. Сам я не могу до этого додуматься, наверное, я тупой.
использовать шаблоны. Вот статья: http://www.phpinfo.su/articles/practice/shablony_v_php.html
Ну и делай наши задачки (которые в первом посте), мы тебя научим писать правильно.
> Довольно странно, что такого функционала в PHP нет.
Потому что он никому практически не нужен, и есть eval (который запутывает код и опасен и лучше не использовать)
> записал как array_replace($spelling, $femaleSpelling), но почему-то не сработало.
она создает и возвращает новый массив, ты его сохранил?
> Добавил деление, но как я понял там вся суть в том, что число может дробное получиться и по умолчанию программа эту дробь округляет до каких-то там тысячных, поэтому итоговое значение может получиться не совсем верным. Оставить ли все как есть или стоит что-то с этим сделать?
Ничего не поделать. Единственное решение это сделать полноценную работу с дробями чтобы например 1/3 хранилось как дробь (кстати это было в одной из продвинутых старых версий задачи и по моему кто-то даже это сделал, по моему на Питоне).
Решено верно, но что-то код очень знакомый.
>>467957
Надо смотреть хорошие примеры кода, например в известных фреймворках (для PHP это Симфони 2 например) и библиотеках. Книги про качество кода есть («Совершенный код» например), но там не упоминается ни php ни JS, а общие принципы.
Ну и общие принципы такие, что не надо все смешивать в кучу, код должен писаться для людей, чтобы им было максимально легко его понять и исправить, чтоюы там не было подводных камней и трудно было сделать ошибку при правке.
Вот например статья про то как надо называть переменные: https://learn.javascript.ru/write-unmain-code
Еще есть хороший сайт http://phptherightway.ru/
> Вот я не понимаю как можно не мешать html и php. Сам я не могу до этого додуматься, наверное, я тупой.
использовать шаблоны. Вот статья: http://www.phpinfo.su/articles/practice/shablony_v_php.html
Ну и делай наши задачки (которые в первом посте), мы тебя научим писать правильно.
>Событие сначала (фаза захвата/capture) спускается по дереву DOM от документа к конкретному элементу, а затем поднимается вверх к документу (фаза всплытия/bubble)
Про всплытие слышал и читал много заумных статей, ничего не понял.
За ссылки спасибо, вот тут все коротко и понятно. learn.javascript наверное единственный полноценный мануал по js.
>если на таблице стоит класс black то клеточки в ней имею черный фон. В таком случае чтобы поменять цвет всех клеток на черный нам достаточно сделать одно действие — добавить класс black на таблицу.
Чо? Погоди, ведь в таком случае вся таблица перекрасится в белый/черный цвет, а я пытался реализовать, чтобы если часть клеток черная, их цвет менялся на белый, а у тех что белые — на черный. Или я неправильно понял задание?
>знаешь ли ты в чем разница между событиями mousedown и click? Если нет, надо выучить.
Ну в описании задания у тебя сказано, что
>событие click срабатывает после отпускания левой кнопки мыши, а mousedown — при нажатии (любой) и с ним получается ощущение более быстрого отклика.
значит знаю.
>>467888
>Лучше использовать свойство className, а не setAttribute (или classList.add)
Исправил. Но почему лучше?
>добавлять/удалять классы через функцию написанную в предыдущей задаче
Не хотеть. Это уж слишком громоздко для такого простого задания. Может еще ООП сюда залепить?
>window.onload
>Чтобы не было проблем достаточно поставить вызов функции ниже чем теги.
Так где все-таки правильно прописывать скрипты? В head или внизу страницы перед закрывающими body или html?
Много видел споров на эту тему, но лень вникать.
Можешь коротко расписать плюсы и минусы?
> TABLE.field
> BUTTON#toggle
> DIV#wrapper
> Я думаю, что table (почему большие буквы?) писать тут не надо.
Во-первых это чисто ради удобства чтения стилей. Я сразу вижу, что есть таблицы с классом field, и что #toggle это именно элемент button. Большими буквами опять-таки просто ради красоты, чтобы не было однородного текста. Ну я думаю это не критично. У серьезных контор наверняка есть какие-то стандарты, но я точно не собираюсь становиться верстальщиком.
А вот в случае с nodeName обязательно писать в верхнем регистре (это я понял на ошибке в этом примере). Почему так? Это какие-то xml-ные таинства?
>box-sizing
>Если тебе паддинг мешает так обнули его явно
Не паддинг, а бордер. В задании указано, что ячейки должны быть 28px, поэтому я сделал уже наверняка этот размер с учетом рамки. Впрочем, про рамку в задании ничего не говорилось, можно было и не делать. Правда тогда белая таблица на белом фоне была бы не видна.
В общем, исправил что мог.
https://jsfiddle.net/5onv70t3/
>Событие сначала (фаза захвата/capture) спускается по дереву DOM от документа к конкретному элементу, а затем поднимается вверх к документу (фаза всплытия/bubble)
Про всплытие слышал и читал много заумных статей, ничего не понял.
За ссылки спасибо, вот тут все коротко и понятно. learn.javascript наверное единственный полноценный мануал по js.
>если на таблице стоит класс black то клеточки в ней имею черный фон. В таком случае чтобы поменять цвет всех клеток на черный нам достаточно сделать одно действие — добавить класс black на таблицу.
Чо? Погоди, ведь в таком случае вся таблица перекрасится в белый/черный цвет, а я пытался реализовать, чтобы если часть клеток черная, их цвет менялся на белый, а у тех что белые — на черный. Или я неправильно понял задание?
>знаешь ли ты в чем разница между событиями mousedown и click? Если нет, надо выучить.
Ну в описании задания у тебя сказано, что
>событие click срабатывает после отпускания левой кнопки мыши, а mousedown — при нажатии (любой) и с ним получается ощущение более быстрого отклика.
значит знаю.
>>467888
>Лучше использовать свойство className, а не setAttribute (или classList.add)
Исправил. Но почему лучше?
>добавлять/удалять классы через функцию написанную в предыдущей задаче
Не хотеть. Это уж слишком громоздко для такого простого задания. Может еще ООП сюда залепить?
>window.onload
>Чтобы не было проблем достаточно поставить вызов функции ниже чем теги.
Так где все-таки правильно прописывать скрипты? В head или внизу страницы перед закрывающими body или html?
Много видел споров на эту тему, но лень вникать.
Можешь коротко расписать плюсы и минусы?
> TABLE.field
> BUTTON#toggle
> DIV#wrapper
> Я думаю, что table (почему большие буквы?) писать тут не надо.
Во-первых это чисто ради удобства чтения стилей. Я сразу вижу, что есть таблицы с классом field, и что #toggle это именно элемент button. Большими буквами опять-таки просто ради красоты, чтобы не было однородного текста. Ну я думаю это не критично. У серьезных контор наверняка есть какие-то стандарты, но я точно не собираюсь становиться верстальщиком.
А вот в случае с nodeName обязательно писать в верхнем регистре (это я понял на ошибке в этом примере). Почему так? Это какие-то xml-ные таинства?
>box-sizing
>Если тебе паддинг мешает так обнули его явно
Не паддинг, а бордер. В задании указано, что ячейки должны быть 28px, поэтому я сделал уже наверняка этот размер с учетом рамки. Впрочем, про рамку в задании ничего не говорилось, можно было и не делать. Правда тогда белая таблица на белом фоне была бы не видна.
В общем, исправил что мог.
https://jsfiddle.net/5onv70t3/
Впрочем, было бы легко, в вузах учились бы полгода, а не пять-шесть лет, да.
ОП, обнадежь меня и скажи, что занимаешься этим уже 10 лет с 15-летнего возраста, поэтому вкачал себе макс-левел.
Но неужели все в пхп-треде этим занимаются, потому что им весело делать сайты?
Программирование это такой специфический род деятельности, когда работу ты обязан выполнять или отлично, или никак. Без любви к своему делу ты будешь выполнять работу на отъебись. А это вызывает закономерную ненависть и презрение тех людей, которым придется чистить за тобой говно.
Хотя бы минимальный интерес и любовь к написанию кода должен быть. Понятно, что те ребята, которые с детства именно с энтузиазмом увлекаются программированием, с высокой вероятностью придут к большому саксэсу, станут тимлидами, может даже напишут свои фреймворки или крупные проекты.
Лично я не сказать чтобы обожаю решать головоломки и нестандартные задачи. У меня это идет натужно и с неохотой.
Очевидно, что я никогда не стану тимлидом, да и вообще сеньором, но по крайней мере уровня грамотного квалифицированного мидла я стремлюсь достичь, чтобы решать банальные рутинные задачи уровня запилить стандартный модуль на популярном фреймворке.
Я понимаю, что решение сложных задач поможет утрамбовать в голове знания, даст понимание тонких нюансов и особенностей работы скрипта.
Так что хоть мне тоже не особо нравится решать всратые задания опа, нельзя не признать их полезность.
Что-то тред скатывается в тренинги личностного роста.
Щас я осилю задание на игру сапер, хоть разбавлю это кодом.
>а что если у нас будет много кошек, ты их все будешь передавать в мышь?
А что такого?
Здесь мы лишь указываем какое Животное нам нужно. Далее, мы ищем это животное в своем поле зрения, и если кошек будет несколько, то Мышка соответственно будет принимать какие-то действия... Я не понимаю что не так с этим? У тебя вроде в задаче есть такое условие.
>Я думаю, кошки и мышки должны храниться внутри World.
Они и так хранятся в массиве $map.
>А присоединяется к миру мышь в момент добавления
У меня так и происходит: При создании Животного конструктор автоматически добавляет его на карту.
>Заметь что при таком подходе мы можем иметь аж несколько миров и перемещать животных между ними (мир живых, и мир мертвых где мышки едят кошек например или рай и ад).
А у меня можно и так сделать. Для этого нужно будет написать:
$heaven = new World();
$mouse = new Mouse($heaven, $x, $y, $view, $speed); //конструктор автоматически добавит Животное в новый мир
или
$world = new World();
$heaven = new World();
$mouse = new Mouse($world, $x, $y, $view, $speed);
//Убираем уже созданное Животное в другом Мире, и добавляем его в новый Мир.
$world->removeAnimalFromMap($mouse);
$heaven->addAnimalToMap($mouse);
>Зачем вообще нужно это свойство map? По моему без него код был бы короче и проще. Например можно убрать метод public function moveAnimal(array $from, array $to) целиком. Ты сам себе усложняешь жизнь создавая этот массив и поддерживая его актуальность.
Я тоже недавно думал что можно обойтись без этого свойства, а просто сделать SplObjectStorage со всеми объектами, но мне было не понятно как вывести это все на экран. Можешь что-нибудь посоветовать по этому поводу?
> public function searchTheAnimal(World $world, Animal $animal) {
>Я не понимаю, зачем нужна эта функция. Она выглядит как усложненная версия того, что можно сделать проще. Зачем перебирать все клеточки? Если ты хочешь проверить видишь ты животное или нет, проще посчитать расстояние до него и сравнить с радиусом зрения.
Мышка не должна знать, что где-то существует Кошка, если она находится вне поле зрения.
Кстати, здесь, если не использовать свойство $map, то будет вставать проблема с поиском животного в своем поле зрения.
>Насчет выбора хода, я предлагаю сделать это более удобным алгоритмом:
>— создаем список всех возможных ходов, включая стоять на месте (на этом этапе можно отсеять запрещенные ходы за край карты)
Это будет делаться каждый раз перед ходом или все возможные ходы(вверх\вниз, направо\налево, по диагонали, на месте) будут хранится где-то?
>— оцениваем каждый ход в баллах
А как оценить каждый ход? Пройтись по всему списку возможных ходов и проверять какой из наиболее дальний\ближний от нужного нам животного?
>а что если у нас будет много кошек, ты их все будешь передавать в мышь?
А что такого?
Здесь мы лишь указываем какое Животное нам нужно. Далее, мы ищем это животное в своем поле зрения, и если кошек будет несколько, то Мышка соответственно будет принимать какие-то действия... Я не понимаю что не так с этим? У тебя вроде в задаче есть такое условие.
>Я думаю, кошки и мышки должны храниться внутри World.
Они и так хранятся в массиве $map.
>А присоединяется к миру мышь в момент добавления
У меня так и происходит: При создании Животного конструктор автоматически добавляет его на карту.
>Заметь что при таком подходе мы можем иметь аж несколько миров и перемещать животных между ними (мир живых, и мир мертвых где мышки едят кошек например или рай и ад).
А у меня можно и так сделать. Для этого нужно будет написать:
$heaven = new World();
$mouse = new Mouse($heaven, $x, $y, $view, $speed); //конструктор автоматически добавит Животное в новый мир
или
$world = new World();
$heaven = new World();
$mouse = new Mouse($world, $x, $y, $view, $speed);
//Убираем уже созданное Животное в другом Мире, и добавляем его в новый Мир.
$world->removeAnimalFromMap($mouse);
$heaven->addAnimalToMap($mouse);
>Зачем вообще нужно это свойство map? По моему без него код был бы короче и проще. Например можно убрать метод public function moveAnimal(array $from, array $to) целиком. Ты сам себе усложняешь жизнь создавая этот массив и поддерживая его актуальность.
Я тоже недавно думал что можно обойтись без этого свойства, а просто сделать SplObjectStorage со всеми объектами, но мне было не понятно как вывести это все на экран. Можешь что-нибудь посоветовать по этому поводу?
> public function searchTheAnimal(World $world, Animal $animal) {
>Я не понимаю, зачем нужна эта функция. Она выглядит как усложненная версия того, что можно сделать проще. Зачем перебирать все клеточки? Если ты хочешь проверить видишь ты животное или нет, проще посчитать расстояние до него и сравнить с радиусом зрения.
Мышка не должна знать, что где-то существует Кошка, если она находится вне поле зрения.
Кстати, здесь, если не использовать свойство $map, то будет вставать проблема с поиском животного в своем поле зрения.
>Насчет выбора хода, я предлагаю сделать это более удобным алгоритмом:
>— создаем список всех возможных ходов, включая стоять на месте (на этом этапе можно отсеять запрещенные ходы за край карты)
Это будет делаться каждый раз перед ходом или все возможные ходы(вверх\вниз, направо\налево, по диагонали, на месте) будут хранится где-то?
>— оцениваем каждый ход в баллах
А как оценить каждый ход? Пройтись по всему списку возможных ходов и проверять какой из наиболее дальний\ближний от нужного нам животного?
>У тебя есть имя автора в Статье и есть отдельно объект Автор, и в нем тоже имя автора. И ты меняешь это имя, а в Статье оно не меняется. Также, нелогично что имя автора хранится в 2 местах.
Эмм, нет же. Сейчас набросаю базу и запрос. Вот.
В таблице статьи поля автор нет, только поле с внешним ключом, связанным с таблицей авторы, где и хранятся их имена(и при необходимости все остальные данные).
А запрос с джоинами возвращает вот эту, ну не знаю как сказать, временную или результирующую таблицу которая дальше преобразуется в массив и через setAttributes() присваивается по свойствам. Таким образом среди них окажутся и author и subject. Ничего не дублируется.
Ну вот мной в основном деньги и иммиграция движут. Ну и у работы в IT сфере еще куча плюсов, которыми большинство профессий не располагает.
Не то чтобы мне совсем не интересен кодинг был, довольно прикольно создавать всякие сайтики и вдыхать в них жизнь. Но я явно не фанатик этого дела и если подвернется вариант получше, то я ни разу не сожалея выберу его.
Понятное дело, что я не выдержу конкуренции с теми, кто с пеленок живет программированием, но я себе такой цели и не ставил. Вообще, я бы хотел в кодерской среде пообтесаться, вкурить что к чему и основать свою фирму. Думаю навыков к этому у меня больше, чем у большинства программистов.
спасибо, надо как-то выкраивать время, потому что на работе нету времени пытаться писать аккуратно, начальство гонит в шею, приходиться делать быстро, но как умею, а когда прихожу домой после 9 часов кодинга уже как-то не тянет делать что-то связанное с программированием. хуй знает как выбраться из этого круга, но понимаю, что надо учиться делать аккуратно, ведь когда-то мой код увидит кто-то кроме меня. и мне не хотелось бы, чтобы его судьба была такой же как у меня.
> Про всплытие слышал и читал много заумных статей, ничего не понял.
Разобраться надо, события очень важная вещь
> Погоди, ведь в таком случае вся таблица перекрасится в белый/черный цвет, а я пытался реализовать, чтобы если часть клеток черная, их цвет менялся на белый, а у тех что белые — на черный. Или я неправильно понял задание?
Я привел для наглядности пример как одним движением закрасить таблицу черным. Пошевели мозгами и подумай как одним движением поменять цвет клеток на противоположный. это скорее вопрос по CSS чем по JS
> Исправил. Но почему лучше?
Короче, удобнее и так везде пишут, в JS-библиотеках. Я кому-то же выше давал примеры реализации add/removeClass в 2 библиотеках, там именно classNameиспользуют
В новых браузерах есть classList где список классов представлени в виде коллекции и есть готовые методы удаления/добаления:
https://developer.mozilla.org/en-US/docs/Web/API/Element/classList
http://caniuse.com/#feat=classlist
> Много видел споров на эту тему, но лень вникать.
От программистов, тем более начинающих, обычно ожидают другого отношения
> Так где все-таки правильно прописывать скрипты? В head или внизу страницы перед закрывающими body или html?
Здесь есть несколько моментов:
— надо помнить что страница загружается и отображается последовательно сверху вниз, даже если она не догрузилась до конца, то пользователь уже видит ее часть и может взаимодействовать с ней
— скрипты блокируют загрузку страницы (то есть пока скрипт не загрузится страница дальше не отрисовывается, это упрощает жизнь), css и картинки нет
Соовтетственно, скрипты должны загрузиться до того как ты испльзуешь их в каком-то обработчике. Например если у тебя есть код <button onclick="doSomething()"> то очевидно функция должна быть определена выше чтобы не было такого что пользователь нажал кнопку, а она не работает.
С другой стороны если твой скрипт обращается к DOM элементам то он должен запускаться после того как они загрузятся, то есть вызов функции должен быть ниже.
onload плох тем что срабатывает только после полной загрузки страницы со всеми картинками и достаточно одной картинки с подвисшего хоста, чтобы задержать инициализацию яваскрипта. Особенно тяжко это будет на мобильном устройстве где соединение часто подвисает. Страница видна, а скрипты еще не работают. Если ты будешь использовать jQuery, там есть другое событие ready которое срабатывает после загрузки HTML файла не дожидаясь остальных.
> внизу страницы перед закрывающими body или html?
это глупый совет. Его мотивируют тем что скрипты блокируют страницу и перемещение вниз ускоряет загрузку, но при таком подходе пользователь получает страницу которая уже отображается, но на которой (пока не загрузились скрипты) не работает яваскрипт, кнопки не нажимаются, и понять почему, невозможно. Потому это плохая идея, ухудшать надежность. Ну и насчет ускорения загрузки — это тоже спорная вещь, так как если скрипт расположен в шапке то браузер доходит до него и начинает загружать его раньше.
Ну и наконец там еще есть асинхронная загрузка скриптов (но с ней связано еще больше подводных камней).
По моему, лучше по старинке подключать в HEAD чтобы скрипты загрузились до содержимого страницы.
> Во-первых это чисто ради удобства чтения стилей.
это как раз неудобно, так как ты пишешь по второму разу то, что записано в HTML коде. Почему бы тогда не пойти дальше и не вспомнить родителей элемента?
HTML BODY DIV#WRAPPER DIV#HEAD TABLE TBODY TR TD.BLACK { .. }
(и если ты думаешь что никто так не пишет, то поверь такой код ты можешь встретить).
> Я сразу вижу, что есть таблицы с классом field,
Ты можешь это увидеть и в HTML, и инспектором в браузере
> А вот в случае с nodeName обязательно писать в верхнем регистре
Не обязательно. Регистр имени элемента в CSS не имеет значения. Более того, это смотрится ужасно так как ты сам не следуешь своему стилю оформления и смешиваешь большие буквы и маленькие.
В JS коде nodeName хранит имя большими буквами, так принято с древних времен, и единообразие тут лучше чем если бы каждый браузер поступал по своему.
По коду:
— класс white избыточен. Достаточно оставить 2 состояния: нет класса и есть класс black. таким образом код будет проще и короче.
> function toggleTableColor(button, table){
Ты зря вкладываешь большую функцию внутрь другой. Это плохо смотрится, особенно когда кода или уровень вложенности станет больше. Ладно, если бы в функции было 2 строчки, но у тебя там много кода, лучше написать так:
function handleButtonClick(e) {
...
}
button.addEventListener('click', handleButtonClick, false);
table.addEventListener(...);
Имя функции надо поменять ибо оно не соответствует тому что она делает и путает людей. «toggleTableColor» значит поменять цвет, но функция ничего не меняет. Она ставит обработчик потому ее надо называть вроде setButtonClickListener.
> if(target.className === 'white'){
> target.className = 'black';
Это мина замедленного действия. Если потом кто-то захочет добавить какие-то еще классы к ячейкам, все это сломается. Потому надо использовать addClass/hasClass чтобы твой код был легко расширяем и чтобы он не ломался от малейших изменений. Понятно, что это учебный пример, который никто не будет расширять, но ведь если мы тебя не переучим, ты и в реальных приложениях будешь точно так же делать.
В чем сложность? ты же писал эти функции в прошлом задании, надо их всего лишь скопировать, я же не прошу написать их с нуля. Не нравятся твои функции — возьми из какого-нибудь prototype js готовые. Ну или напиши функции в 3 строчки на classList.
Ну и подумай, как сделать инвертирования цвета клеточек добавлением 1 класса на таблицу. Это проще и читабельнее, чем циклы писать.
> Про всплытие слышал и читал много заумных статей, ничего не понял.
Разобраться надо, события очень важная вещь
> Погоди, ведь в таком случае вся таблица перекрасится в белый/черный цвет, а я пытался реализовать, чтобы если часть клеток черная, их цвет менялся на белый, а у тех что белые — на черный. Или я неправильно понял задание?
Я привел для наглядности пример как одним движением закрасить таблицу черным. Пошевели мозгами и подумай как одним движением поменять цвет клеток на противоположный. это скорее вопрос по CSS чем по JS
> Исправил. Но почему лучше?
Короче, удобнее и так везде пишут, в JS-библиотеках. Я кому-то же выше давал примеры реализации add/removeClass в 2 библиотеках, там именно classNameиспользуют
В новых браузерах есть classList где список классов представлени в виде коллекции и есть готовые методы удаления/добаления:
https://developer.mozilla.org/en-US/docs/Web/API/Element/classList
http://caniuse.com/#feat=classlist
> Много видел споров на эту тему, но лень вникать.
От программистов, тем более начинающих, обычно ожидают другого отношения
> Так где все-таки правильно прописывать скрипты? В head или внизу страницы перед закрывающими body или html?
Здесь есть несколько моментов:
— надо помнить что страница загружается и отображается последовательно сверху вниз, даже если она не догрузилась до конца, то пользователь уже видит ее часть и может взаимодействовать с ней
— скрипты блокируют загрузку страницы (то есть пока скрипт не загрузится страница дальше не отрисовывается, это упрощает жизнь), css и картинки нет
Соовтетственно, скрипты должны загрузиться до того как ты испльзуешь их в каком-то обработчике. Например если у тебя есть код <button onclick="doSomething()"> то очевидно функция должна быть определена выше чтобы не было такого что пользователь нажал кнопку, а она не работает.
С другой стороны если твой скрипт обращается к DOM элементам то он должен запускаться после того как они загрузятся, то есть вызов функции должен быть ниже.
onload плох тем что срабатывает только после полной загрузки страницы со всеми картинками и достаточно одной картинки с подвисшего хоста, чтобы задержать инициализацию яваскрипта. Особенно тяжко это будет на мобильном устройстве где соединение часто подвисает. Страница видна, а скрипты еще не работают. Если ты будешь использовать jQuery, там есть другое событие ready которое срабатывает после загрузки HTML файла не дожидаясь остальных.
> внизу страницы перед закрывающими body или html?
это глупый совет. Его мотивируют тем что скрипты блокируют страницу и перемещение вниз ускоряет загрузку, но при таком подходе пользователь получает страницу которая уже отображается, но на которой (пока не загрузились скрипты) не работает яваскрипт, кнопки не нажимаются, и понять почему, невозможно. Потому это плохая идея, ухудшать надежность. Ну и насчет ускорения загрузки — это тоже спорная вещь, так как если скрипт расположен в шапке то браузер доходит до него и начинает загружать его раньше.
Ну и наконец там еще есть асинхронная загрузка скриптов (но с ней связано еще больше подводных камней).
По моему, лучше по старинке подключать в HEAD чтобы скрипты загрузились до содержимого страницы.
> Во-первых это чисто ради удобства чтения стилей.
это как раз неудобно, так как ты пишешь по второму разу то, что записано в HTML коде. Почему бы тогда не пойти дальше и не вспомнить родителей элемента?
HTML BODY DIV#WRAPPER DIV#HEAD TABLE TBODY TR TD.BLACK { .. }
(и если ты думаешь что никто так не пишет, то поверь такой код ты можешь встретить).
> Я сразу вижу, что есть таблицы с классом field,
Ты можешь это увидеть и в HTML, и инспектором в браузере
> А вот в случае с nodeName обязательно писать в верхнем регистре
Не обязательно. Регистр имени элемента в CSS не имеет значения. Более того, это смотрится ужасно так как ты сам не следуешь своему стилю оформления и смешиваешь большие буквы и маленькие.
В JS коде nodeName хранит имя большими буквами, так принято с древних времен, и единообразие тут лучше чем если бы каждый браузер поступал по своему.
По коду:
— класс white избыточен. Достаточно оставить 2 состояния: нет класса и есть класс black. таким образом код будет проще и короче.
> function toggleTableColor(button, table){
Ты зря вкладываешь большую функцию внутрь другой. Это плохо смотрится, особенно когда кода или уровень вложенности станет больше. Ладно, если бы в функции было 2 строчки, но у тебя там много кода, лучше написать так:
function handleButtonClick(e) {
...
}
button.addEventListener('click', handleButtonClick, false);
table.addEventListener(...);
Имя функции надо поменять ибо оно не соответствует тому что она делает и путает людей. «toggleTableColor» значит поменять цвет, но функция ничего не меняет. Она ставит обработчик потому ее надо называть вроде setButtonClickListener.
> if(target.className === 'white'){
> target.className = 'black';
Это мина замедленного действия. Если потом кто-то захочет добавить какие-то еще классы к ячейкам, все это сломается. Потому надо использовать addClass/hasClass чтобы твой код был легко расширяем и чтобы он не ломался от малейших изменений. Понятно, что это учебный пример, который никто не будет расширять, но ведь если мы тебя не переучим, ты и в реальных приложениях будешь точно так же делать.
В чем сложность? ты же писал эти функции в прошлом задании, надо их всего лишь скопировать, я же не прошу написать их с нуля. Не нравятся твои функции — возьми из какого-нибудь prototype js готовые. Ну или напиши функции в 3 строчки на classList.
Ну и подумай, как сделать инвертирования цвета клеточек добавлением 1 класса на таблицу. Это проще и читабельнее, чем циклы писать.
Ну я с дества программированием интересуюсь и мне оно легко дается, все кажется понятным и логичным. А сколько времени ты занимаешься в неделю?
>>468189
Скорее в вузе учебник рассказали бы за одну лекцию, препод скучным голосом прочитал бы перепутав некоторые вещи и не заметив этого.
>>468250
А я люблю головоломки когда есть на них время. Ну и тебе они не нравятся наверно потому что ты сразу за сложные берешься. Если начинать с простых задач то можно при желании и олимпиадные задачи научиться решать. Те же самые олимпиадники очень много времени практикуются, изучают всякие алгоритмы и тд, это не врожденное умение, хотя наверно кому-то оно легче дается, кому-то труднее.
> нельзя не признать их полезность.
Это радует :)
>А что такого?
Здесь мы лишь указываем какое Животное нам нужно. Далее, мы ищем это животное в своем поле зрения, и если кошек будет несколько, то Мышка соответственно будет принимать какие-то действия... Я не понимаю что не так с этим? У тебя вроде в задаче есть такое условие.
У тебя пока программа поддерживает 1 кошку и 1 мышку. Ты сможешь переделать например чтобы их было по 5 штук?
> но мне было не понятно как вывести это все на экран. Можешь что-нибудь посоветовать по этому поводу?
— создаем пустой массив
— вставляем в него животных циклом
— преобразуем в строку
По моему мы что-то похожее делали в задаче про буквы по кругу.
> Кстати, здесь, если не использовать свойство $map, то будет вставать проблема с поиском животного в своем поле зрения.
Никаких проблем нет. Пишем в World функцию получитьВсехивотныхВрадиусе(x, y, r) которая вернет только тех, кого видно из этой точки.
>Это будет делаться каждый раз перед ходом
Конечно каждый. Ситуация ведь меняется и вчерашний набор ходов неактуален.
> А как оценить каждый ход? Пройтись по всему списку возможных ходов и проверять какой из наиболее дальний\ближний от нужного нам животного?
Для кошки очевидно чем ближе мышка тем больше баллов. Для мышки наоборот. Также, ходы на край доски и в угол должны цениться ниже так как там у мышки меньше выходов и ее проще поймать. Также, количество кошек тоже вносит вклад, лучше идти туда где их плотность меньше. Ну вообще, конкретную формулу ты должен вывести, подумав насколько важен каждый из факторов и какой вклад он вносит в сумму. И проверить практически, какая будет выживаемость с этой формулой.
> Таким образом среди них окажутся и author и subject. Ничего не дублируется.
Дублируется. У тебя есть поле author в Article и есть поле name в Author. И они хранят одно и то же. Вопрос, почему одно поле отображается на 2 объекта? И почему в Article хранится только огрызок от автора, а не объект Author целиком?
Ну и если у тебя есть класс Author то как получить Author из Article? Например как узнать дату регистрации автора статьи? Его id? Ссылку на его страницу?
>>468264
Не знаю, даже что посоветовать. Ну попробуй хотя бы потихоньку развиваться, маленькими шагами, по одной вещи за раз. Ну и ты можешь в наш тред вбрасывать кусочки кода, а я скажу как их можно улучшить.
Просто если ты не будешь развиваться то так и будешь все время заниматься однообразной работой. А потом тебя заменят на студента который умеет то же, но знаком с новым фреймворком X и готов работать по 10 часов в день на энтузиазме.
Ну и наконец число часов (или строк кода) не показатель. Программист который грамотно использует библиотеки и фреймворки может за меньшее число времени сделать больше. А если он пишет более надежный и менее запутанный код, то он еще меньше времени потратит на отладку и исправление ошибок.
да, понимаю, это и движет мной. насчет кусочков кода - хорошая идея. особо интересующие меня вещи буду вбрасывать, когда буду чувствовать, что наговнокодил
Это копия, сохраненная 14 мая 2015 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.