Этого треда уже нет.
Это копия, сохраненная 9 декабря 2015 года.

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

Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
5 Кб, 204x204
58 Кб, 1366x768
663 Кб, 1920x1080
108 Кб, 1024x780
Клуб изучающих PHP 63 #578124 В конец треда | Веб
Добро пожаловать в наш уютный тредик. Тут мы изучаем язык PHP (а также JS/CSS/HTML/SQL), решаем задачки и даже делаем простые сайты! Зачем? Кто-то хочет научиться программировать, кто-то - делать сайты, кто-то - просто размять мозги и заняться чем-то полезным.

Почему PHP? Потому что фейсбук и википедия на нем написаны, и вакансий море, и учить легко.

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

Устанавливать пока что ничего не требуется, разве что редактор кода вроде Sublime Text 3, Notepad++, Netbeans PHP или PhpStorm (с ним будет удобнее).

Предыдущий тред был тут: >>569049 (OP) ( не OP)

Что самое главное для программиста? Умение аккуратно оформлять код (читай второй пост).

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

У нас есть уроки по основам 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.me/ru-php-the-right-way/ )
- По PHP: Профессиональное программирование на PHP Джордж Шлосснейгл
- По PHP: Мэтт Зандстра — PHP: Объекты, шаблоны, методики программирования
- JS: learn.javascript.ru
- Про Git: https://git-scm.com/book/ru/v1

Нужен ли ООП, фреймворки, MVC? — Да, однозначно. Посмотри любую вакансию.
Сайт опять упал!!!!! — Не паникуй, а открой http://rghost.net/45000175 и получи личную немного устаревшую копию сайта
Оформляй код аккуратно!!! — например пропусти через phpformatter.com . Также, если ты пользуешься IDE вроде PhpStorm, Netbeans, Eclipse, то в них эта опция встроена, подробнее: https://gist.github.com/codedokode/8759492
ОП, сделай за меня мою работу или домашнее задание? — Это конечно, хорошая идея, но нет.
Подскажи сайты для поиска работы, я не умею гуглить? — hh.ru, geekjob.ru, moikrug.ru (склеен с brainstorage.me), fl.ru, upwork.com (бывший одеск). Имей в виду, что кроме фриланса есть еще постоянная удаленная работа (remote job) когда тебе не надо тратить время на поиск заказов и переговоры с неадекватными заказчиками.
Самый важный пост #2 #578126
>>578124 (OP)
Еще. Код нужно писать не как попало, а аккуратно и по правилам. Почему? Потому, что на неакуратно написанный код не хочется даже смотреть.

Если тебе лень выравнивать код руками, закачай его на 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

------------------

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

Будь доброжелателен

Не годится: «Ты мануал хоть раз в жизни открывал, обезьяна?»
Не годится: «В гугле забанили?»
Не годится: «Твой код плохой»
Хорошо: «Вот, как можно улучшить этот код: ...»
Хорошо: «Ты неправильно используешь функцию abc(). Вот ее описание: ссылка, и как видишь ей надо передать строку, а не массив»

Не придирайся к знанию английского языка.

Объясняй

Не очень хорошо: «сделай как в этом коде»
Хорошо: «если ты вставляешь текст от пользователя в SQL запрос, то получается SQl-инъекция, которая позволяет взломать твой сервер (ссылки). Чтобы этого избежать, надо вставлять данные с помощью плейсхолдеров (ссылки)»
Хорошо: «Помни, что код пишется для людей. Если писать такие большие функции, то в них становится трудно разобраться...»

Не проповедуй

Мы учим использованию самых распространненных подходов, стандартов, библиотеки фреймворков. Если ты не любишь ООП, пробелы в коде, jQuery, сам PHP, то рассказать об этом стоит в каком-нибудь другом треде.

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

Ах да. Если тебе кажется, что что-то в учебнике или задачах можно сделать лучше — пиши, обратная связь всегда очень полезна.
Самый важный пост #2 #578126
>>578124 (OP)
Еще. Код нужно писать не как попало, а аккуратно и по правилам. Почему? Потому, что на неакуратно написанный код не хочется даже смотреть.

Если тебе лень выравнивать код руками, закачай его на 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

------------------

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

Будь доброжелателен

Не годится: «Ты мануал хоть раз в жизни открывал, обезьяна?»
Не годится: «В гугле забанили?»
Не годится: «Твой код плохой»
Хорошо: «Вот, как можно улучшить этот код: ...»
Хорошо: «Ты неправильно используешь функцию abc(). Вот ее описание: ссылка, и как видишь ей надо передать строку, а не массив»

Не придирайся к знанию английского языка.

Объясняй

Не очень хорошо: «сделай как в этом коде»
Хорошо: «если ты вставляешь текст от пользователя в SQL запрос, то получается SQl-инъекция, которая позволяет взломать твой сервер (ссылки). Чтобы этого избежать, надо вставлять данные с помощью плейсхолдеров (ссылки)»
Хорошо: «Помни, что код пишется для людей. Если писать такие большие функции, то в них становится трудно разобраться...»

Не проповедуй

Мы учим использованию самых распространненных подходов, стандартов, библиотеки фреймворков. Если ты не любишь ООП, пробелы в коде, jQuery, сам PHP, то рассказать об этом стоит в каком-нибудь другом треде.

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

Ах да. Если тебе кажется, что что-то в учебнике или задачах можно сделать лучше — пиши, обратная связь всегда очень полезна.
46 Кб, 500x644
Самый важный пост #3 #578127
225 Кб, 1920x1200
#4 #578128
>>578124 (OP)
Собственно ОП традиционно заслоупочил с созданием нового треда. А мне не хочется чтобы вопросы анонов уходили на 5 страницу /pr Так что создал новый тред. Надеюсь ОП прошлого треда меня не возненавидет за это.
#5 #578130
>>578124 (OP)
Алсо в следующий оп пост надо наверное таки добавить http://www.easyphp.org/ ибо для ньюфагов он проще.
#6 #578136
Уже минут двадцать гуглю, но так и не понял, как просто импортировать функцию из стороннего файла. Что за безобразие.
#7 #578141
>>578136
<?php
include ('funkciya.php');
?>
#8 #578164
>>578141
Ага, спасибо.
#9 #578168
Блин, пока писал вопрос - сам понял где затупил. Вот что двачи делают со мной.
#10 #578169
Аноны, у тебя бывали неудачные дни? Когда просто не компилится код и всё тут.Ну не работает нивкакую. Даже код который копипастится из примера не идёт. А потом, на следующий день запускаешь и всё отлично работает? Просто я сейчас сижу над таким проектом. Вчера вообще не работало просто всё. Всё выдавало ошибку. А сегодня я что-то закоментил, перелопатил немного бд. и всё работает. причём не особо много то и сделал.
#11 #578170
Пишешь "
Умный блокнот ставит ""
Запутался в кавычках
На тушение моего пердака можно вызывать всех пожарных Московской области.

Серьёзно блядь, кто считает что это удобно? В какой стране это удобно то? Какой вообще смысл ставить сразу две кавычки то?
#12 #578186
>>578170
Одно нажатие вместо двух, ты чего горишь?
#13 #578188
>>578186
Одно нажатие, печатаются сразу две кавычки. Такие дела.
(Notepad++, PHPStorm, Sublime)
#14 #578228
привет. я тут мимо пробегал. посоны, почему мой нетбинс забыл var_dump()? не автокомлитит его.
#15 #578240
Нашел вакансию php джуниора удаленно. Вроде бы по требованиям всё подходит, но есть сомнения. Вдруг не потяну, вдруг ещё надо поучиться. Что если меня возьмут, а я справляться не буду с работой? Судя по зарплате они многого ждут от претендента.
#16 #578243
>>578240

>Что если меня возьмут, а я справляться не буду с работой?


Тебя уволят тогда. Не благодари.
#17 #578244
>>578228
// Создадим три объекта (так как у нас будет 3 вопроса в тесте), и сохраним их в трех переменных:
$q1 = new Question;
$q2 = new Question;
$q3 = new Question;

// Выведем содержимое первого объекта
var_dump($q1);

Вопросы?
#18 #578245
>>578188
Чё от них толку, если после того как написал в кавычках нужно либо ещё раз кавычку тыкнуть, либо кнопку вправо?
#19 #578248
>>578245
В том то и дело, что нет. тыкаешь кавычку, начинаешь писать текст, в итоге у меня 2 кавычки текст и 2 кавычки. ЧЯДНТ?
#20 #578260
Допустим я захожу на сайт, где скриптом злоумышленник считывает у меня куки с авторизацией на каком-нибудь сайте, затем формирует у себя куки с тем же содержимым и пользуется моим аккаунтом. Возможен такой сценарий?
#21 #578269
>>578134
Почти ничего не знаю, хотя я уже файлообменник делаю. Вопросы по mysql вообще какой-то атомный пиздец, я такой теории ни в каких мануалах не встречал.
#22 #578272
>>578269
А сантиметров сколько набрал?
#23 #578280
Репост из мы вам перезвоним треда. Думаю, тутошние ананасики смогут помочь.
>>578146
>>578214
#24 #578283
>>578260
Куки видны только сайту, их отправившему. Для жс за пределами браузера стоят анальные ограничения. Куки можно спереть, запустив у пользователя на компьютере от его имени исполняемый файл.
#25 #578314
Как хорошо что я не остался на уровне пхп-макаки. Пацаны, все кто сидит в этом треде - учите пхп не для того, чтобы выучить пхп, а для того чтобы немножко научиться программировать. Когда простые вещи сможете на пыхе писать - перекатывайтесь на какой-нибудь вменяемый язык (джава, шарп и тд). С пхп вам ничего в жизни не светит, единственное разумное применение этого языка - подготовиться к более сложным и более хорошим языкам.

мимо перекатился с пхп на джаву уже год как, скоро буду зарабатывать 50к
#26 #578318
Всем привет. Сразу оговорюсь, не гоните и не закидывайте камнями... Такой вопрос: тока закончил учить пару книжек по html и css и вот перешел на php. Читаю книгу для самых раков
http://rutracker.org/forum/viewtopic.php?t=4172911 а потом думаю смотреть вот это http://rutracker.org/forum/viewtopic.php?t=4290480 стоит или нет это смотреть? или посоветуйте на чем вы учились. И как лучше качать скил в этом деле? ну т.е. где взять именно большое количество задач с простых и до сложных. Спасибо заранее.
#27 #578319
>>578318
Смотреть вот это http://nnm-club.me/forum/viewtopic.php?t=889322. Паралельно решать задачи ОПа.
#28 #578330
>>578318
Книжку 2010-го года смело можешь выкидывать. Видеокурсы и другие материалы от этого человека тоже не советую.

Если сильно хочется что-то прочесть - бери это: http://rutracker.org/forum/viewtopic.php?t=4979192
Только сильно не зацикливайся - решай задачи из ОПовского учебника и старайся побыстрее перейти к задаче про список студентов. Книга пусть идёт как бы фоном.
#29 #578331
>>578314
Еще лет 20 с такими советами и я стану просто богом программирования, знающим по 120 Яп, только вот нахуй, ведь я буду стар и немощен и уже будет пора на пенсию.
где взять шаблон сайта #30 #578332
Ананасы подскажите, хочу сайт+мобильное приложение.
Аккаунты, синхронизация, вот это все. Так вот я не хочу писать сайт на с нуля, я уже сделал авторизацию, и заебался это делать четно говоря. Нужен готовый сайт например с бутстраповским шаблоном на котором есть авторизация, аккаунты и кароче все сделано, в минимальной комплектации. Wordpress мне курить совсем не хочется.
Подскажите куда глядеть?
#31 #578333
>>578330
Благодарю тебя анон, бобра тебе большого
#32 #578334
>>578332
Скинул тебе за щеку - смотри.
31 Кб, 533x398
#33 #578338
Расскажу свою историю. Сначала я писал статейки, будучи копирайтером. Потом какой-то петушок закатился в наш тред и сказал дословно следующее: за месяц выучил верстку и уже через месяц зарабатываю 200к. Я выучил верстку и сделал 10 не особо адаптивных макетов. Потом тот же петушок сказал. что макеты должны быть адапитвными. Я сделал еще 3 адаптивных, потом тот же петушок закатился и сказал, что нужно выучить жквери и жаваскрипт. Я расковырял жиквери и прикрутил несколько плагинов. Потом тот же петушок закатился в тред и сказал, что этого недостаточно и нужно еще и php c mysql освоить и вот тогда-то точно будет 200к через месяц. Я пробежался по мануалу пхп, написал сайтик с бэкендом на 1й странице. Тот же петух пришел и сказал, что так не пойдет надо еще ООП с паттернами освоить и вот тогда уж точно будет 200к через месяц. Я прочтиал книгу из Оп поста и перепечатал все паттерны, проверив их работу. Тот же петушок вкатился и сказал, что так не пойдет, нужно еще фреймворки освоить. Я взялся за слим и Уи2, сделал на них по проекту. И вот теперь приходит этот петух и говорит мне, что пхп - это дно, нужно перекатываться в шарп или джаву. Такое ощущение, что надо мной кто-то просто сидит и издевается годами.
#34 #578346
>>578338

>тот же


>аиб


кхм...
#35 #578352
>>578338
Это всё хуйня. Учись продавать и будет тебе 200к.
#36 #578363
Знаю ПХП и немного хуже чем ПХП яваскрипт и джейквери, немного знаком с фреймворками, но как оказалось без вёрстки никуда, посоветуйте несколько хороших мест\курсов\учебников по которым можно за 1-2 месяца выучить КСС до такого уровня что бы можно было верстать из ПСД макета. У ОПа есть же уроки по КСС? Можете скинуть? Я нашёл только вот это https://gist.github.com/codedokode/58ebc90bd006baf4b35c
#37 #578365
>>578363

>как оказалось без вёрстки никуда


Где оказалось?
#38 #578366
>>578318
Насколько хорошо знаешь CSS? Умеешь верстать из ПСД макета? Если поможешь мне с CSS я помогу тебе с ПХП.
#39 #578367
>>578365
Туда где я пошёл работать, в итоге проработал месяц и ушёл.
#40 #578369
>>578367
А город какой?
#41 #578372
>>578365
Конечно в других местах может это и не так, но в любом случае хочу выучить по-нормальному вёрстку, что бы навсегда закрыть этот вопрос.
#42 #578373
>>578369
Областной, 500К населения, не буду говорить его название.
#43 #578379
>>578330

> вместо одной хуйни предлагает другую хуйню

9 Кб, 382x160
#44 #578382
>>578373

>не буду говорить его название


А то найдут и в рот выебут.
#45 #578383
>>578379
>>578382
Ты из какой попы вылез?
#46 #578385
>>578383
Из попы твоей мамки, очевидно же. Даже хуй еще не успел помыть.
#47 #578393
>>578382
Могут и найти, поэтому я немного остерегаюсь.
#48 #578395
Кстати, у Игоря Борисова есть курс по КСС и ХТМЛ? Мне нравится как это чувак поясняет, я скачал курс специалист по ХТМЛ и КСС но там кто-то другой поясняет.
#49 #578396
Ананасы, с битриксом кто-то работал? Подойдет ли в качестве первой работы или это пустая трата времени, и никаких полезных скиллов я не получу?
#50 #578399
>>578395
Есть. Поищи на nnm-club
22 Кб, 644x594
#51 #578408
>>578396
P.S. Охуеть. Я думал, в битриксах погромирование есть. Зашел почитать документацию, а там - пикрилейтед. А я программировать хочу, а не гуй дрочить.
А ведь уже отправил отклик в битрикс-контору, и от них пришёл ответ.
#52 #578414
>>578408

>гуй


Ой, у них это называется интерфейс ЭРМИТАЖ. Простите, забыл.
#53 #578415
>>578408
Есть там и "программирование", но отстойное, в основном дописывать корявые костыли. Битрикс это самое дно. Дрочи фреймворки.
#54 #578420
>>578396
Работал с битриксом когда только вкатывался в профессию. Битрикс это чистое легаси. Когда-то, много лет назад, запили вполне себе неплохую CMS. Но сегодня работать с ним это ад и израиль. Ты спокойно можешь найти код написанный лет 6-7 назад, запутанная архитектура, смешание кода (пхп, жс, css все в одной куче), несколько тысяч строк кода где вся с множеством if else. Вот это все. После полу года работы я сразу дрпонул ту конторку и зарекся работать с битркисом. Справедливости ради скажу что когда позже я шатал вордпресс/джумлу они вызывали не меньше ненависти. Так что если есть возможность сразу ищи работу на современных фреймворках. Легаси это всегда жопная боль.
#55 #578421
>>578415

>Дрочи фреймворки.


Я и дрочу, даже гитхаб им свой показал.
Только джуновакансий с фреймворками почти нет, хоть это и дс.
#56 #578425
>>578420
>>578415
Спасибо вам. Видимо, не зря в ответном письме спросили, готов ли я работать с битрикс.
Отвечу тогда, что не готов. Пусть решают, брать или нет.
#57 #578427
>>578425
Ну пару месяцев можно и походить, негативный опыт тоже опыт. Еще и кое-какие деньги заплатят.
#58 #578432
>>578427
Устраиваться на работу на пару месяцев мне кажется плохой идеей. Лучше, наверное, сидя дома, какой-нибудь Yii выучить и с базами данных поиграться за это время.
#59 #578435
>>578432
Зависит от состояния холодильника. Главное продолжать задрачивать пока вилкой чистишь битриксы.
#60 #578439
Скажут чистить вилкой битрикс, жумолу и вордпресс - будете сидеть и чистить, суки, еще и линукс администрировать.
#61 #578441
>>578435
После целого дня втыкания в экран (и битриксостраданий) снова втыкать в экран? Сомневаюсь, что я так смогу.
#62 #578442
>>578432
Никто тебя не возьмет на чистые фреймворки. В большинстве контор джунов садят чистить cms, потому что те больше ничего не умеют.
Ну а за что деньги платить? За то что ты сделал пару хелловорлдов на yii2 или симфони?
>>578441
Да, нужно успевать заниматься дерьмовой работой и параллельно учиться профессиональным навыкам у коллег.
#63 #578443
Вот это вы хорошо придумали с двумя тредами: пусть здесь будет чат хуесосов, а в легальном треде учеба. Никто не будет друг другу мешать.
#64 #578477
>>578442

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


Ага, сидишь такой, чистишь битрикс. Идешь пить кофе, там с сеньором обсуждаешь, че и почему он решил поменять в архитектуре нового проекта. А потом идешь опять допиливать интернет-магазин для ООО "Турнички в дом от Васяна".
Чушь несешь, по-моему.

>Ну а за что деньги платить?


А никто стажерам и джунам особо и не платит. И это нормально.
#65 #578527
>>578477
В каком-нить "Первый Бит" оно вполне так может и быть. Сам я то из сибирской мухосрани, тут работа есть но не особо. Летом искал работу, а так как у меня в резюме есть битрикс, то рекрутеры звонили сами. Вот мне позвонили из этой конторки и позвали битрикс чистить, на что я отказался. Через пару дней перезвонили и сказали, что им понравилось мое резюме приходите и у них есть внутренний проект (yii2, вебсокеты) на который бы они хотели меня пригласить. Чуваки, что чистят битрикс и чуваки что пилят этот проджект сидят в соседних кабинетах. И понятно дело что люди пересекаются на той же кухне и общаются.

>>578420 кун
98 Кб, 1409x571
sage #66 #578531
>>578124 (OP)
Аноны, я ньюфаг, помогите разобраться с позиционированием. Хочу запилить его в первых трех голубых дивах внутри красного и чтобы средний занимал все свободное пространство, но 3 вылазит впизду.
Заранее всем спасибо.
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Домашнее задание</title>
</head>
<style type="text/css">
.green1 {
width: 100%;
height: 1000px;
border:solid 2px green;
}
.red1 {
width: auto;
height: 150px;
border:solid 2px red;
margin:20px;
position: relative;
.red1 DIV{position:absolute;}
}
.red2 {
width: auto;
height: 100px;
border:solid 2px red;
margin:20px;
}
.red3 {
width: auto;
height: 450px;
border:solid 2px red;
margin:20px;
}
.red4 {
width: auto;
height: 180px;
border:solid 2px red;
margin:20px;
}
.blue1 {
width: 250px;
height: 120px;
border:solid 2px blue;
float:left;
}
.blue2 {
left:250px;
right:250px;
height: 120px;
border:solid 2px blue;
}
.blue3 {
width: 250px;
right:0;
height: 120px;
border:solid 2px blue;
}

.blue4 {
width: 20%;
height: 70px;
border:solid 2px blue;
margin:10px 10px 10px 10px;
float:left;
}
.blue5 {
width: 19%;
height: 70px;
border:solid 2px blue;
margin:10px 10px 10px 10px;
float:left;
}
.blue6 {
width: 19%;
height: 70px;
border:solid 2px blue;
margin:10px 10px 10px 10px;
float:left;
}
.blue7 {
width: 34%;
height: 70px;
border:solid 2px blue;
margin:10px 10px 10px 10px;
float:left;
}
.blue8 {
width: 20%;
height: 420px;
border:solid 2px blue;
margin:10px 10px 10px 10px;
float:left;
}
.blue9 {
width: 76%;
height: 420px;
border:solid 2px blue;
margin:10px 10px 10px 10px;
float:left;
}
.blue10 {
width: 20%;
height: 155px;
border:solid 2px blue;
margin:10px 10px 10px 10px;
float:left;
}
.blue11 {
width: 50%;
height: 155px;
border:solid 2px blue;
margin:10px 10px 10px 10px;
float:left;
}
.blue12 {
width: 24%;
height: 155px;
border:solid 2px blue;
margin:10px 10px 10px 10px;
float:left;
}
.yellow1 {
width: 50%;
height: 40px;
border:solid 2px yellow;
margin:10px;

}
.yellow2 {
width: 40%;
height: 40px;
border:solid 2px yellow;
margin:10px;

}
.yellow3 {
width: auto;
height: 190px;
border:solid 2px yellow;
margin:10px 10px 10px 10px;
float:bottom;
}
.yellow4 {
width: auto;
height: 190px;
border:solid 2px yellow;
margin:10px 10px 10px 10px;
float:bottom;
}
.yellow5 {
width: auto;
height: 60px;
border:solid 2px yellow;
margin:10px 10px 10px 10px;
float:bottom;
}
.yellow6 {
width: auto;
height: 60px;
border:solid 2px yellow;
margin:10px 10px 10px 10px;
float:bottom;
}
</style>
</head>
<body>
<div class="green1">
<div class="red1" >
<div class="blue1"></div>
<div class="blue2"></div>
<div class="blue3">
<div class="yellow1"></div>
<div class="yellow2"></div>
</div>
</div>
<div class="red2">
<div class="blue4"></div>
<div class="blue5"></div>
<div class="blue6"></div>
<div class="blue7"></div>
</div>
<div class="red3">
<div class="blue8"></div>
<div class="blue9">
<div class="yellow3"></div>
<div class="yellow4"></div>
</div>
</div>
<div class="red4">\t
<div class="blue10">
<div class="yellow5"></div>
<div class="yellow6"></div>
</div>
<div class="blue11"></div>
<div class="blue12"></div>
</div>
</div>
</body>
</html>
98 Кб, 1409x571
sage #66 #578531
>>578124 (OP)
Аноны, я ньюфаг, помогите разобраться с позиционированием. Хочу запилить его в первых трех голубых дивах внутри красного и чтобы средний занимал все свободное пространство, но 3 вылазит впизду.
Заранее всем спасибо.
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Домашнее задание</title>
</head>
<style type="text/css">
.green1 {
width: 100%;
height: 1000px;
border:solid 2px green;
}
.red1 {
width: auto;
height: 150px;
border:solid 2px red;
margin:20px;
position: relative;
.red1 DIV{position:absolute;}
}
.red2 {
width: auto;
height: 100px;
border:solid 2px red;
margin:20px;
}
.red3 {
width: auto;
height: 450px;
border:solid 2px red;
margin:20px;
}
.red4 {
width: auto;
height: 180px;
border:solid 2px red;
margin:20px;
}
.blue1 {
width: 250px;
height: 120px;
border:solid 2px blue;
float:left;
}
.blue2 {
left:250px;
right:250px;
height: 120px;
border:solid 2px blue;
}
.blue3 {
width: 250px;
right:0;
height: 120px;
border:solid 2px blue;
}

.blue4 {
width: 20%;
height: 70px;
border:solid 2px blue;
margin:10px 10px 10px 10px;
float:left;
}
.blue5 {
width: 19%;
height: 70px;
border:solid 2px blue;
margin:10px 10px 10px 10px;
float:left;
}
.blue6 {
width: 19%;
height: 70px;
border:solid 2px blue;
margin:10px 10px 10px 10px;
float:left;
}
.blue7 {
width: 34%;
height: 70px;
border:solid 2px blue;
margin:10px 10px 10px 10px;
float:left;
}
.blue8 {
width: 20%;
height: 420px;
border:solid 2px blue;
margin:10px 10px 10px 10px;
float:left;
}
.blue9 {
width: 76%;
height: 420px;
border:solid 2px blue;
margin:10px 10px 10px 10px;
float:left;
}
.blue10 {
width: 20%;
height: 155px;
border:solid 2px blue;
margin:10px 10px 10px 10px;
float:left;
}
.blue11 {
width: 50%;
height: 155px;
border:solid 2px blue;
margin:10px 10px 10px 10px;
float:left;
}
.blue12 {
width: 24%;
height: 155px;
border:solid 2px blue;
margin:10px 10px 10px 10px;
float:left;
}
.yellow1 {
width: 50%;
height: 40px;
border:solid 2px yellow;
margin:10px;

}
.yellow2 {
width: 40%;
height: 40px;
border:solid 2px yellow;
margin:10px;

}
.yellow3 {
width: auto;
height: 190px;
border:solid 2px yellow;
margin:10px 10px 10px 10px;
float:bottom;
}
.yellow4 {
width: auto;
height: 190px;
border:solid 2px yellow;
margin:10px 10px 10px 10px;
float:bottom;
}
.yellow5 {
width: auto;
height: 60px;
border:solid 2px yellow;
margin:10px 10px 10px 10px;
float:bottom;
}
.yellow6 {
width: auto;
height: 60px;
border:solid 2px yellow;
margin:10px 10px 10px 10px;
float:bottom;
}
</style>
</head>
<body>
<div class="green1">
<div class="red1" >
<div class="blue1"></div>
<div class="blue2"></div>
<div class="blue3">
<div class="yellow1"></div>
<div class="yellow2"></div>
</div>
</div>
<div class="red2">
<div class="blue4"></div>
<div class="blue5"></div>
<div class="blue6"></div>
<div class="blue7"></div>
</div>
<div class="red3">
<div class="blue8"></div>
<div class="blue9">
<div class="yellow3"></div>
<div class="yellow4"></div>
</div>
</div>
<div class="red4">\t
<div class="blue10">
<div class="yellow5"></div>
<div class="yellow6"></div>
</div>
<div class="blue11"></div>
<div class="blue12"></div>
</div>
</div>
</body>
</html>
64 Кб, 1475x724
#67 #578548
Решил выебнуться и сделал такой вот класс. Массив возвращает вар дампом, но выводится ошибка, что filed undefined. Неужели в слиме нужно каждую переменную запихивать в массив для рендера во вью в сером коде (он работает)?? Печально, печально.
#68 #578560
>>578527
Ну вот видишь, поставил себе высокую планку - тебе и дали норм инструменты, а так бы сидел чистил битрикс.
#69 #578687
Повторный вопрос совсем не/не совсем по пхп (но сайт на похапе, да).
Что есть для почтовых рассылок, какие сервисы? Сайт - магазин (конечно же лол), письма шлются при заказе клиенту и заказавшему + всякие там восстановления паролей и тд. 2к писем с smtp.google.com по пятницам может не хватать. Свой почтовый VPS/VDS сервер поднимать побаиваюсь, никогда не пробовал, что там делать представляю приблизительно (через пердольку поставить готовые велосипеды, настроить их), как через него отправлять - не представляю. Какие ещё есть решения?
#70 #578691
>>578439
Двачую. Сами зеленые джуниоры, а уже нос вертят от работы.
#71 #578696
>>578560
А я (другой анон) не только битриксы чищу, но и прочие cms. Хочу переползти на фреймворки, но как, если вакансий в этом мухосранске нет, всем cms говно подавай. Сил нет с этим возиться, эта работа меня убивает лол. Джунов на удаленку не берут?
#72 #578704
>>578696
Любая работа убивает. Фреймворки ничем не лучше. Просто работай как можно меньше, а денег требуй как можно больше. В рамках доступности, конечно. Рассмотри вакансии курьера или гей-шлюхи, может выгоднее получится, да и веселее.
#73 #578707
>>578704
Но ведь я хочу в погромирование. По вечерам тыкаю что-нибудь, но сейчас так заебывает, что никакого настроения и желание на изучение чего-то не остается.
#74 #578717
>>578696
Они наверное думают, что взять готовую цмсочку и "просто дописать пару функций" - гораздо быстрее, проще и дешевле, чем делать заново на целом фреймворке. Ну да, им там админка навороченная сразу крепится и не надо по нее макет придумывать. Хотя не особо понимаю эту логику. Если тебе нужен стандартный функционал - бери сам цмску и тыкай пальцем в админку, а если ковырять чужой айпи и вьюхи, то это должно оплачиваться гораздо дороже фреймворков.Тем более битрикс вообще платный и лагает при закачке, я даже скачать его не смог. В жумоле и вордпрессе вообще региться надо, вот очень мне хочется там еще и региться каждый раз.
#75 #578720
>>578707

> так заебывает, что никакого настроения и желание на изучение чего-то не остается.


У меня так было с любой работой. По языкам, работал на разных проектах на JS, C#, Java, Scala. Всё адски заёбывало, а ещё когда я пару недель похожу в офис, у меня начинается что-то типа нарколепсии, тогда вообще пиздец. Единственное решение этих проблем, которое я нашёл - просто не работать. Теперь пишу только то, что интересно, и мне это нравится делать на любом языке. Просто надо научиться жить экономнее и поднимать максимум бабла минимальными усилиями, тогда получится дольше и больше неработать.
#76 #578721
>>578717
Как мне говорили "можно нанять верстаков, обучить их тыкать кнопки в cms и вуаля, они могут делать сайты".

> а если ковырять чужой айпи и вьюхи


Ну там редко приходится его ковырять, документация есть, гуглишь, копипастишь, меняешь параметры метода.
С битриксом мало работаю (и на этом спасибо), но помимо него много чего ещё есть же. HostCMS, UMI, друпал. Да и на вордпрессах такого говна повидал, с дрожью вспоминаю. И вирусные скрипты все кому не лень льют. Ну правильно, систему с 00х не обновляют.
#77 #578726
>>578720
Но меня радуют задачи с программированием. Написать какой-то модуль. Даже простой костыль/велосипед. Всяко лучше, чем тыкать кнопочки. У меня это с работой в ворде ассоциируется, я сразу представляю себя какой-нибудь блондинкой секретаршей. Мне стыдно этим заниматься лол.
#78 #578752
Кто так вирус догадался назвать AppData/js/not-a-virus-dkfjdjfldjk.wav.js
#79 #578761
>>578721
Ну и нахрен мы тогда фреймворки и ООП учим, если можно просто синтаксис с функциями освоить и гоу макеты натягивать, регить в яндекс метрике и колипастить документацию жумолы? Все таки функционал в цмсках хоть и модифицируемый, но очень ограниченный, там даже не каждый шаблон натянешь. Т.е. их можно менять только в тех объемах, где мануал позволяет, чтобы не лезть в сам код цмски, а дописывать функции в их песочнице. А если клиент хочет вк или другой навороченный сайт на жумоле написать.
#80 #578827
>>578761
Мне-то зачем объясняешь, я понимаю и знаю, что хуитой занимаюсь, далекой от программирования.
#81 #578845
>>578691
Если чистить будешь битриксы, то так и останешься зеленым джуниором.
#82 #578865
За сколько дней можно выучить симфони? Накидайте годных видеоуроков на русском.
#83 #578890
>>578865

>За сколько дней можно выучить симфони?


Достаточно узкоспециализированный инструмент. Я освоил за два месяца. Лучше осиливай node.js, больше пользы будет.
Ответы на ответы #84 #578917
https://github.com/p-5ch/vector - анон, вот советы и замечанию по твоему решению: >>578831\t

https://github.com/never3ver/catsandmice - вот ответ >>578906\t

Ну и другие аноны, которые что-то спрашивали в старом треде >>569049 (OP) , всем постарался ответить. Если кого-то забыл, напомните о себе здесь.
#85 #578929
>>578917
Ты такой няша, что я хочу тебя встретить и напоить чаем.
30 Кб, 498x226
#86 #578934
Жс - это очень просто и понятно.
#87 #578940
>>578527

>Через пару дней перезвонили и сказали, что им понравилось мое резюме приходите и у них есть внутренний проект (yii2, вебсокеты) на который бы они хотели меня пригласить.


А сам Yii2 ты к тому моменту уже успел потрогать? Что у тебя в резюме вообще было написано?
#88 #578943
У меня есть форма и мне нужно при субмите отправить не только значения полей инпута, но и текст. Как это можно сделать, если текст находится в div'ах?
#89 #578945
>>578943
Жсом.
#90 #578946
>>578945
А кек?
#91 #578947
>>578946
Способ 1: делаешь у формы невидимое поле, содержимое которого меняется при изменении содержимого дивов.
Способ 2: делаешь кастомную кнопку отправки формы, при формировании POST-запроса пихаешь в него инфу из дивов и шлёшь на сервер аяксом.
Ты жс-то знаешь?
#92 #578949
>>578947

>Ты жс-то знаешь?


Конечно знаю. Просто я думал аяксом нужно, а способ с невидимыми полями мне больше понравился. Сам бы не догнал.
#93 #578976
Начал учиться по кодакадеми. Прошел все уроки до середины курса php.
Такое чувство , что там дают только какие то совсем азы и в целом код академи просто распиаренное говно и потом придется переучиваться.
Я прав?
#94 #578980
>>578976

>Такое чувство , что там дают только какие то совсем азы


Так и есть. Я, кстати, тоже проходил у них курс по PHP. Так и не закончил, мануал + оповский учебник + вопросы в треде дают более быстрый результат.
#95 #578984
>>578980
Доделаю пхп. Осталось 30%. Это быстро.
Дальше там идут руби и APIs. Оно в таком же стиле выполнено?
Хотя для совсем новичков годится, если времени много. Подкупает консоль, которая говорит ошибки. Хотя и глючная.
#96 #578986
>>578984
Codecademy - говно без задач. После него ты даже калькулятор не напишешь.
#97 #578987
>>578984
Бля, случайно отправил, не дописав. Так вот, лучше W3School.com проходи. Там гораздо более практический подход.
14 Кб, 718x406
#98 #579023
Как правильно вырезать заголовки из ответа сервера? Раньше делал как пикрелейтед, пока не узнал, что их может быть несколько (пикрелейтед, переменная $response2). Если использовать curl, то там можно решить с помощью CURLINFO_HEADER_SIZE, но если я какими-нибудь сокетами получаю, то нужен вот свой велосипед.
#99 #579029
>>578367
Дали задание сверстать по макету? И в чем оказалась непосильная сложность? Сел бы и обучался параллельно с версткой, я когда первый раз верстать сел на работе, у меня чувство фрустрации продолжалось неделю, дошло до того, что у меня уже депрессия началась и нервный тик, но в итоге вошел в курс дела.
#100 #579035
Оп такой долбоеб, только свои говнозадачки и умеет комментить. На чем-то сложнее уже сливается, как и подобает анимепидорасу.
#101 #579037
>>578240

Тестовые задания дали? Справился? С Главой проекта побеседовал?
А вообще не попробуешь - не узнаешь.
#102 #579041
>>579037
Так если выгонят, то тоже хреново будет.
#103 #579042
Поставил брэкетс, чет прям нравится очень. Для html, js, css она точно норм, а вот для php как? Работает кто-нибудь в ней?
#104 #579062
https://ideone.com/O1jLq3
Правильно ли сделан класс, и если да, то почему не работает?
#105 #579063
>>579037

>делать "тестовые"


>for free


Если хотят знать уровень - пусть смотрят код в гитхабе.
#106 #579067
>>579063
Вдруг он пизженый.
#107 #579070
>>579035
Все лучше чем петушиные бои в соседних тредах.
#108 #579071
>>579041
А какая альтернатива? Сидеть и боятся либо искать вакансию анального раба за 10килорублей.
Ну можно еще фрилансить и попутно совершенствоватся до нужного уровня, но все равно стремно.
Я считаю что шансы упускать нельзя.
#109 #579073
>>578934
А что тут непонятного?
#110 #579084
>>579073
Function на function и function погоняет.
#111 #579088
>>579084
И что?
Ты бы еще сказал "переменная на переменной".
#112 #579095
>>578940
Да, уже был опыт разработки.

Ну а резюме у меня вполне себе обычное. Технологии с которыми знаком, скилы, описание проектов в которых принимал участие.
#113 #579119
Поясните по MVC. Где должно проверятся то, что пришло через POST. Допустим у меня точка входа index.php, в контроллере я же не смогу проверить свои посты, да и геты получается тоже, потому что там классы, ну точнее смогу, но мне все-равно придется вызывать из index.php нужный метод в зависимости от того, что пришло. Получается, что мне все данные (для любой страницы сайта), которые приходят через POST или GET придется пропускать через index.php?
#114 #579121
>>579119
Даже если я в action='' укажу файл с нужным контроллером, то нихуя не произойдет, ибо там тупо лежит класс... Или в файлах с контроллерами можно не только классы размещать? Поясните короче по этой теме.
#115 #579123
>>579088
Сказал бы, если бы их можно было вкладывать друг в друга.
#116 #579172
>>579119
Массив POST (и все остальные которые начинаются с _) суперглобальный, то есть доступный в любом месте скрипта.
http://php.net/manual/ru/language.variables.superglobals.php

>в контроллере я же не смогу проверить свои посты


Почему это?

>потому что там классы


И что? Из метода (экшена) обращаешься к пост или гет.

>мне все-равно придется вызывать из index.php нужный метод


Не знаю, что у тебя в index.php, но там должен создаваться объект приложения, в котором будет разобран маршрут и вызван соответствующий ему контроллер и экшен (действие).

Смотри, грубая схема работы mvc приложения:
Есть класс приложения class Application
У него метод инициализации, пусть будет $app->init(), при вызове которого будет разобран url и вызван метод (экшен) нужного контроллера.
Например
public function init()
{
$requestURI = $_SERVER['REQUEST_URI']; // получаем из массива $_SERVER маршрут, по которому был запрос, например /page/view/123
// бьем эту строку по слешу и получаем в первом элементе массива строку 'page' (имя контроллера), во втором 'view' (action), все остальное гет-параметры, '123' в данном случае id страницы
$this->controller = 'page';
$this->action = 'view';
$this->params = array('123');
}

Теперь нам понадобится метод run приложения, чтобы вызвать полученный при инициализации контроллер и его действие.
public function run()
{
$controllerName = ucfirst($this->controller) . 'Controller';
$controller = new $controllerName;
$action = 'action' . ucfirst($this->action);
$controller->$action($params);
}

Теперь в index.php создаем экземпляр приложения, инициализируем его (init) и выполняем (run).
$app = new Application;
$app->init();
$app->run();

Естественно, понадобится класс контроллера, в данном случае он должен называться PageController. У него должен быть метод actionView
class PageController
{
public function actionView($id)
{
$model = Model::findById($id);
$app->render('templateName.php', array('model'=>$model));
}
}

В методе render берем шаблон и заменяем плейсхолдеры на значение переменных.
#116 #579172
>>579119
Массив POST (и все остальные которые начинаются с _) суперглобальный, то есть доступный в любом месте скрипта.
http://php.net/manual/ru/language.variables.superglobals.php

>в контроллере я же не смогу проверить свои посты


Почему это?

>потому что там классы


И что? Из метода (экшена) обращаешься к пост или гет.

>мне все-равно придется вызывать из index.php нужный метод


Не знаю, что у тебя в index.php, но там должен создаваться объект приложения, в котором будет разобран маршрут и вызван соответствующий ему контроллер и экшен (действие).

Смотри, грубая схема работы mvc приложения:
Есть класс приложения class Application
У него метод инициализации, пусть будет $app->init(), при вызове которого будет разобран url и вызван метод (экшен) нужного контроллера.
Например
public function init()
{
$requestURI = $_SERVER['REQUEST_URI']; // получаем из массива $_SERVER маршрут, по которому был запрос, например /page/view/123
// бьем эту строку по слешу и получаем в первом элементе массива строку 'page' (имя контроллера), во втором 'view' (action), все остальное гет-параметры, '123' в данном случае id страницы
$this->controller = 'page';
$this->action = 'view';
$this->params = array('123');
}

Теперь нам понадобится метод run приложения, чтобы вызвать полученный при инициализации контроллер и его действие.
public function run()
{
$controllerName = ucfirst($this->controller) . 'Controller';
$controller = new $controllerName;
$action = 'action' . ucfirst($this->action);
$controller->$action($params);
}

Теперь в index.php создаем экземпляр приложения, инициализируем его (init) и выполняем (run).
$app = new Application;
$app->init();
$app->run();

Естественно, понадобится класс контроллера, в данном случае он должен называться PageController. У него должен быть метод actionView
class PageController
{
public function actionView($id)
{
$model = Model::findById($id);
$app->render('templateName.php', array('model'=>$model));
}
}

В методе render берем шаблон и заменяем плейсхолдеры на значение переменных.
#117 #579224
>>579067
Пусть уник проверят.
138 Кб, 848x535
54 Кб, 955x624
159 Кб, 1347x684
#118 #579284

> В сообщении присутствует слово из спам-листа


Да как же это заебало.

>>578914
Скриншоты прикрепляю здесь, текст на pastebin
http://pastebin.com/fPqvnADt
#119 #579292
Вот на pastebin восхитительный счетчик. Только запостил, уже 61 просмотр. И не парятся ребята, а я тут и ботов отслеживаю, и с редисом извращаюсь.
#120 #579322
$app->get(
'/password',
function() use ($app)
{
$app->render('Password.php');
})->name('password');

$app->post(
'/password',
function() use ($app) {
/
$email=htmlspecialchars($_POST['email']);
$login=htmlspecialchars($_POST['login']);
$password=htmlspecialchars($_POST['password']);
$confirmPass=htmlspecialchars($_POST['confirmPass']);
$cookie=$app->request->cookies->get('username'); //setting cookies

/
$userpost = new UserPost;
$postarr = $userpost->post($_POST);
//var_dump($postarr);
$cookie = $app->getCookie('username'); //setting cookies
$db = $app->db;
$validator = new Validator($db);
$errors = $validator->getErrors($postarr);
// var_dump($errors);
if(!empty($errors)){

$app->render('Password.php', ['errors' => $errors]);

}

Почему шаблон не рендереится? Делаю вар дамп errors- массив передается во вью, но вью не рендерится.
#120 #579322
$app->get(
'/password',
function() use ($app)
{
$app->render('Password.php');
})->name('password');

$app->post(
'/password',
function() use ($app) {
/
$email=htmlspecialchars($_POST['email']);
$login=htmlspecialchars($_POST['login']);
$password=htmlspecialchars($_POST['password']);
$confirmPass=htmlspecialchars($_POST['confirmPass']);
$cookie=$app->request->cookies->get('username'); //setting cookies

/
$userpost = new UserPost;
$postarr = $userpost->post($_POST);
//var_dump($postarr);
$cookie = $app->getCookie('username'); //setting cookies
$db = $app->db;
$validator = new Validator($db);
$errors = $validator->getErrors($postarr);
// var_dump($errors);
if(!empty($errors)){

$app->render('Password.php', ['errors' => $errors]);

}

Почему шаблон не рендереится? Делаю вар дамп errors- массив передается во вью, но вью не рендерится.
#121 #579340
Попной боли от mysql/php ньюфага пост.

Мне было нужно хранить в базе статус (0/1).
Таблицу создавал в админере (ну приятней мне гуй тыкать).
Посоветовался с коллегой, какой тип юзать, а то там аж 7 типов в разделе "Двоичный тип" (нахуя?) он ответил "bool".
В списке админера его не нашел, поставил прямым запросом - оказалось, это тип binary. Ну ладно, не суть.
Дальше при создании дефолтным значением поля статуса (далее status) поставил 0. Ок, создал таблицу, добавил первое значение (status не задавал). Смотрю в админере, дефолтом ставится 30, а не 0. При этом похапе 30 понимает правильно, как false. Решил в админере задать в записи status = 0. Стало 00. Пхп понял как true. Если поставить status = 1 через mysql_query (скрипт для вспомогательной задачи, так что пдо, орм и тд я не юзал), то в админере будет 31 (пхп также поймет правильно, как true).
ЯННП. Спросил друга, он сказал заюзать tinyint(1), мол везде так делают. Я подумал, что странно, можно же и 9 туда засунуть (как оказалось и 255 туда можно засунуть, я думал 1 - это действительно длина, а это оказывается размер лол). Но с тайниинтом вышла другая проблема, напишу завтра, ещё раз повторно протестирую.
Что под это дело надо юзать? Зачем 7 типов? Что за хуйня в админере с 30ками?
#122 #579354
>>579284

Я так вижу запущенный хромиум - который потребляет ресурсы - для чистоты эксперимента стоилр бы на время тестов его закрыть, и запускать их из консоли (Ctrl + Alt + F1) или подключившись удаленно по ssh (с винды можно использовать putty). Также, стоит запускать ab c другого компьютера, чтобы он не тратил ресурсы (или ты так и сделал?).

Ты отчасти прав насчет слабого железа. На хорошем сервере твой код бы работал быстрее, по моей взятой с потолка оценке, может раз в 10-20. То есть мы бы могли получить бесплатную «оптимизацию», просто купив хороший сервер. Но даже на твоем «калькуляторе» можно выжать больше ценой потраченного времени на оптимизацию. Да и не всегда заказчик горит желанием покупать более дорогой сервер. Да и на хорошем сервере оптимизации могут дать выгоду (только мы пока не можем это проверить так как для этого надо делать тесты на нем).

Давай начнем с простых вещей. Выгоднее всего такие оптимизации, которые требуют минимума усилий но приносят результат. Фреймворк предоставляе возможность кеширования схемы БД: http://www.yiiframework.com/doc/blog/1.1/ru/final.deployment#sec-3

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

Далее, надо отключить dev режим. Если он тебе нужен, ты можешь поднять второй виртуал хост ссылающийся на ту же папку где он включен, либо включть его установкой куки (и набыдлокодить php скриптик с кнопкой включения/выключения). Дебаг режим обычно влияет на производительность в худшую сторону.

Проверь что всякие дебаг-логи отключены.

Код на гитхабе актуальный? Я там вижу такую штуку:

https://github.com/nsdvw/classifieds/blob/master/protected/config/main.php#L51

'eavCache' => array(
\t\t\t'class' => 'system.caching.CDummyCache'

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

Давай пока начнем с этого. Не забудь:

- после каждой меры оптимизации желательно запускать тест и записывать что изменилось (например как изменилось время обработки запроса)

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

Я наверно еще напишу пост с оьъяснением того что на скриншотах, а этот пост чтобы ты пока мог сам попробовать что-то пооптимизировать.
#122 #579354
>>579284

Я так вижу запущенный хромиум - который потребляет ресурсы - для чистоты эксперимента стоилр бы на время тестов его закрыть, и запускать их из консоли (Ctrl + Alt + F1) или подключившись удаленно по ssh (с винды можно использовать putty). Также, стоит запускать ab c другого компьютера, чтобы он не тратил ресурсы (или ты так и сделал?).

Ты отчасти прав насчет слабого железа. На хорошем сервере твой код бы работал быстрее, по моей взятой с потолка оценке, может раз в 10-20. То есть мы бы могли получить бесплатную «оптимизацию», просто купив хороший сервер. Но даже на твоем «калькуляторе» можно выжать больше ценой потраченного времени на оптимизацию. Да и не всегда заказчик горит желанием покупать более дорогой сервер. Да и на хорошем сервере оптимизации могут дать выгоду (только мы пока не можем это проверить так как для этого надо делать тесты на нем).

Давай начнем с простых вещей. Выгоднее всего такие оптимизации, которые требуют минимума усилий но приносят результат. Фреймворк предоставляе возможность кеширования схемы БД: http://www.yiiframework.com/doc/blog/1.1/ru/final.deployment#sec-3

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

Далее, надо отключить dev режим. Если он тебе нужен, ты можешь поднять второй виртуал хост ссылающийся на ту же папку где он включен, либо включть его установкой куки (и набыдлокодить php скриптик с кнопкой включения/выключения). Дебаг режим обычно влияет на производительность в худшую сторону.

Проверь что всякие дебаг-логи отключены.

Код на гитхабе актуальный? Я там вижу такую штуку:

https://github.com/nsdvw/classifieds/blob/master/protected/config/main.php#L51

'eavCache' => array(
\t\t\t'class' => 'system.caching.CDummyCache'

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

Давай пока начнем с этого. Не забудь:

- после каждой меры оптимизации желательно запускать тест и записывать что изменилось (например как изменилось время обработки запроса)

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

Я наверно еще напишу пост с оьъяснением того что на скриншотах, а этот пост чтобы ты пока мог сам попробовать что-то пооптимизировать.
#123 #579379
>>579322
Включи отображение ошибок
ini_set("display_errors", "on");
error_reporting(E_ALL);
Смотри логи.

>>579340
Очевидно неправильный тип поля таблицы. У тебя записывается строка '0', а не число.
Пользуйся клиентом командной строки mysql, чтобы руками писать запросы.
Для полей, которые могут принимать значение из предопределенного списка есть тип ENUM
#124 #579382
>>579340
Я не понял, что за шизобред я прочитал? Вот как я это решил.

if(isset($_POST['public'])){
$public ="1";
}
else {
$public="0";
}

<input type="checkbox" name="public" value='1'> Private File

В таблице enum и по умолчанию 0

\tpublic\t enum('1', '0')\tutf8_bin\t\tДа \t0
#125 #579387
>>579340
Типичное быдлецо уровня битрикса и прочих гуев, даже типы данных не различает.
#126 #579397
>>579382

>it is not advisable to define an ENUM column with enumeration values that look like numbers, because this can easily become confusing


https://dev.mysql.com/doc/refman/5.7/en/enum.html
#127 #579411
>>578124 (OP)
Я совсем тупой. Дошел до задачки про кредиты, ничего не понимаю. Мне суждено работать в макдаке?
#128 #579416
Посоны, как выбрать строку по её номеру в таблице? Добавить поле типа number не работает, потому что оно уже есть, и оно auto_increment.
#129 #579419
>>579411
Во, стоило мне поныть, как в голову сразу попала идея и я все сделал. Спасибо, тред. я серьезно
#130 #579451
>>579379

> Очевидно неправильный тип поля таблицы. У тебя записывается строка '0', а не число.


Это про 30ки?

> Пользуйся клиентом командной строки mysql, чтобы руками писать запросы.


По ssh не всегда доступ есть, что делать в других случаях? Когда только фтп.
Про enum посмотрю. Но не знаю, зачем юзать перечисляемый тип, если есть 7 двоичных.

>>579382
Сумбурно вышло, да. Тебя я тоже не понял, зачем мне инпуты и post, я про типы спрашивал и неочевидную для меня конвертацию одного в другое.
#131 #579455
Киньте ссылки на валидаторы и солирование, не могу найти. Алсо, если мне нужно проверять поля для регистрации и входа, то делать ли для них один класс с проверкой или два разных? И если один, то как его организовать?
#132 #579457
>>579397
I dont really care if it confusing for you or not, It's the only way it works properly.
#133 #579463
>>579451
В mysql нет "двоичных" типов. bool это всего лишь псевдоним tinyint(1).
Есть строки и числа, и их вариации.
http://phpclub.ru/mysql/doc/column-types.html
Тебе нужен int или его разновидность, а у тебя сейчас наверное varchar, поэтому строки конкатенируются, и получается лабуда типа '00', '30' и т.д.
Я не знаю, что такое админер, но в обычном phpmyadmin можно посмотреть и исправить тип колонок.
Выгода enum в том, что просто невозможно вбить другое значение кроме перечисленных, база его не примет. В случае tinyint ты можешь по ошибке вбить 3, тогда как рассчитывал хранить только 1 или 2.

По преобразованию в php: строка '0' преобразуется к false, так и должно быть. Строка '00' и любая другая к true.
http://php.net/manual/ru/language.types.boolean.php#language.types.boolean.casting

>>579457
Не работает оно properly, я тебе дал ссылку на оф.документацию, где объясняется, почему нельзя употреблять числа в качестве значений enum.
#134 #579466
Помню в одном из тредов (может в прошлом) был небольшой срач по поводу
<a href="javascript:void(0)>ссылка</a>
мол, нужно баттоны юзать.
А если юзать для псевдоссылок <a>ссылка</a> ?
#135 #579481
>>579463

> а у тебя сейчас наверное varchar, поэтому строки конкатенируются, и получается лабуда типа '00', '30' и т.д.


Да, ты прав, спасибо, но я всё равно не понимаю почему. Посмотрел в ascii таблице, 0 и 1 - это 30 и 31 (hex) символы. Не понял, почему вышел varchar. Когда я тип поля менял, делал запрос
ALTER TABLE table ALTER COLUMN status bool
буду грешить на админер. Завтра попробую поменять тип через mysql и через pma посмотреть значения.

Админер - как phpmyadmin, только не такой тяжелый (всего один php скрипт). Ну и функционала поменьше, но посмотреть/править тип колонок тоже можно.

> По преобразованию в php


Теперь понятно, большое спасибо.
#136 #579489
>>579466
В html5 вроде разрешили

>If the href attribute is not specified, the element represents a placeholder hyperlink.


http://www.w3.org/TR/html-markup/a.html#placeholder-hyperlink
Обрати внимание, что ссылка без href перестает быть ссылкой, то есть у нее убираются стили и она становится некликабельной, фактически приравниваясь к спану.
#137 #579494
>>579489
Хм, действительно. Интересно как браузер обрабатывает. Ну да ладно, фиксить просто.
#138 #579497
>>579489

Это называется не разрешили, а устали бороться с быдлокодерами и быдловерстальщиками и авторами неграмотных учебников. Так как на каждом углу вы видите эти href='#'

По той же причине в HTML5 приняли правило, что слеш в конце тега игнорируется и

<img /> равносильно <img>

Однако <div/> равносилен <div>, а не <div></div>, так что по сути они этим закладывают мину замедленного действия.
#139 #579499
>>579489

Хотя я могу ошибаться. Возможно что placeholder link (место для ссылки) предназначено не для совместимости с кривым кодом, а для тех случаев когда нам нужна штука которая никуда не ведет, например текущий пункт меню:

http://lists.w3.org/Archives/Public/public-html/2007Jun/0635.html

Хотя я сам таких проблем никогда не испытывал и не очень понимаю зачем все это.
#140 #579503
>>579497

>Так как на каждом углу вы видите эти href='#'


Я думал это и нужно юзать для якорей.
#141 #579508
>>579503

Что ты имеешь в виду под словом «якорь» ? Раньше так называли теги, отмечающие место на странице, к которому можно перейти c помощью ссылки вида #part1:

<a name="part1"></a>

Сейчас якорь не нужен, так как вместо него используется атрибут id на любом теге.
#142 #579510
>>579497

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


Это называется "было два года назад на дваче". <a> без href уже сколько лет. "anchor" он называется не от хорошей жизни, а от того что для адресов вида #yoba как раз такие теги и создавались. Это теперь только стало можно для этих целей любой тег с идом использовать.

>По той же причине в HTML5 приняли правило, что слеш в конце тега игнорируется


Стандарт перечитай. Слеш в конце тега топустим только у void-тегов типа meta, img, link, ... в целях похожести на хмл. <div/> это не корректный хтмл.
#143 #579511
>>579489

А тут http://lists.w3.org/Archives/Public/public-html/2007Jun/0639.html написано:

>the recommodation only states "Authors may also create an A element that specifies no anchors, i.e.,


that doesn't specify href, name, or id. Values for these attributes may be set at a later time through scripts."
То есть a без href это заготовка для ссылки, которая в дальнейшем будет заполнена скриптом. Мне вообще не очень нравится эта идея, если ссылка будет заполнена скриптом, то незачем ее пока отображать (вдруг скрипты отключены или не смогли загрузиться или произошла ошибка).
#144 #579512
>>579510

> "anchor" он называется не от хорошей жизни, а от того что для адресов вида #yoba как раз такие теги и создавались


да, я в курсе, раньше обязательно было указать один из атрибутов, либо name либо href. Сейчас можно не указывать ни одного и это называется «placeholder link» и в его назначении я и пытался разобраться. Возможно что действительно привычка верстать кнопки ссылками тут не при чем.
#145 #579516
>>579508

> Что ты имеешь в виду под словом «якорь»


То же, что и ты. Ну вот, как здесь
https://2ch.hk/pr/res/578124.html#top

Типа
<div id/name="top"></a>
.....
<a href="#top">вверх</a>

если href="#" то это в самый верх.
https://2ch.hk/pr/res/578124.html#
#146 #579518
Зачем писать сайты на PHP, если есть руби и нода?
#147 #579519
>>579518
А зачем нода? Я правда не знаю. Я читал и пытался понять, но не понял куда это всё. Есть сервер с апачем и мускулом, например, есть бэкенд похапе, например, есть фронтенд. А нода для чего? Я ньюфаг, да.
#148 #579520
>>579518

Зачем писать на руби и ноде когда есть php?

Как минимум под php есть куча CMS и фреймворков, не надо мучаться с настройкой линукса, не надо искать средство для прибивания приложения каждые N часов из-за утечек памяти. Ну и еще в PHP лучше с типизацией: у нас есть тайп-хинты, а у них нет. Да и с ORM там все плохо, насколько я знаю.
#149 #579522
>>579520
При чём тут вообще линукс?
#150 #579523
>>579519

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

PHP работает по-другому: браузер запрашивает страницу, PHP ее генерирует и отдает (а браузер показывает), соединение закрывается.

Node.JS и другие подобные технологии (в том числе библиотека ReactPHP или Twisted для Питона) позволяют сделать демон, поддерживающий долгоживующее соединение. Такие демоны можно использовать для создания чатов, систем уведомлений. Например во вконтакте страница поддерживает постоянное соединение с сервером. и когда кто-то лайкает тебя или пишет сообщение, именно по нему передается уведомление об этом.
#151 #579524
>>579522

Ты как свое приложение на ноде запускать собрался?
#152 #579525
>>579524
npm start, а что?
#153 #579526
>>579523
Пример с вк многое прояснил лол. А как это, часть запросов направлять на другой порт? Я очень мало знаю по этой части, почти не представляю, о чём идет речь, что можно почитать?
#154 #579528
>>579525

Ага, руками после каждой перезагрузки или падения заходить и писать команду? Хорошая идея.

Алсо не понимаю зачем для этого пакетный менеджер.
#155 #579531
>>579526

Для начала тебе надо вообще понять что такое порт. Это термин из протокола TCP, протокол TCP это стандарт по которому программы могут соединяться и передавать друг другу потоки данных.

Вот вырезка из урока по HTTP который я пишу уже который год:

--------------

## Интернет

Интернет - это всемирная сеть, объединяющая множество компьютеров и устройств. Устройство и принцип работы этой сети описаны в протоколе (протокол это стандарт, описывающий взаимодействие систем) IP.

У каждого узла сети есть свой уникальный идентификатор (он называется IP адрес), и указав его, узлы могут передавать друг другу по этой сети пакеты данных. Сейчас все еще используются IPv4-адреса, которые имеют вид вроде `102.34.23.20` (4 числа от 1 до 254), но так как эти адреса заканчиваются, в будущем мы перейдем на [IPv6](https://ru.wikipedia.org/wiki/IPv6), где адреса состоят из большего числа цифр.

Также, некоторые IP адреса имеют специальный смысл. IP-адреса вида `127.x.x.x`(например `127.0.0.1`) соответствуют так называемому loopback-интерфейсу и если попытаться отправить пакет на такой адрес, то он не уйдет в сеть, а останется на компьютере. Эта особенность используется программами, которые запущены на одном и том же узле и хотят обмениваться друг с другом данными.

Каждый IP-пакет содержит IP-адрес отправителя, получателя, а также примерно до 1600 байтов данных (байт это целое число от 0 до 255).

## TCP

Допустим, у нас есть 2 программы, A и B, запущенные на разных компьютерах (допустим, A на узле `1.1.1.1`, а B на `2.2.2.2`). Они могут использовать описанный выше протокол IP для передачи друг другу каких-то данных, но это не очень удобно:

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

Все эти проблемы решает более высокоуровневый протокол TCP (еще его называют TCP/IP, так как он в своей работе использует IP). Он добавляет к IP-адресам номер порта - число от 1 до 65535, которое идентифицирует программу-получателя или отправителя. Разные программы используют разные номера портов, и потому можно понять какой из них предназначены данные. Также, он обеспечивает повторную отправку пакетов при потере, и позовляет пересылать сколь угодно большой объем данных, разбивая их на пакеты при передаче и собирая обратно при получении.

Протокол TCP/IP в примере выше работает так:

- программа A на узле `1.1.1.1` хочет получать данные от программы B. Потому она открывает на компьютере порт с заранее обговоренным номером, например `2000`, и начинает ждать входящих соединений («слушать порт»). Если этот порт уже используется другой программой, повторно открыть его не удастся, и произойдет ошибка, если нет, то операционная система выделяет порт номер 2000 программе.
- программа B, которая хочет послать какие-то данные программе A, устанавливает TCP-соединение с узлом `1.1.1.1`, порт `2000`
- программа на узле A получает уведомление, что кто-то пытается установить соединение с ней с IP-адреса `2.2.2.2`. Она может принять это соединение, или отказаться, допустим она принимает его.
- с этого момента соединение установлено, и программы могут посылать друг другу в обе стороны данные любого объема
- когда передача закончена (или когда программа A не хочет больше получать данные), любая из программ может закрыть соединение на прием данных. Вторая программа получает уведомление об этом, и если она тоже закрывает соединение со своей стороны, то оно завершается.

Если программы запущены на одном и том же компьютере, то они могут использовать упомянутый выше IP-адрес `127.0.0.1`.

Если ты используешь Windows/linux/mac, ты можешь установить TCP-соединение с любым узлом и портом командой `telnet IP-адрес порт`, например:

```shell
telnet 8.8.8.8 80
```

Если порт и адрес указаны правильно (то есть есть узел с таким IP-адресом, на нем запущена программа, слушающая этот порт и она принимает твое соединение), то все, что ты печатаешь, кодируется в виде байт и посылается на удаленный узел, а все, что он пришлет, отображается на экране. Если нет, то подождав минуту-две, ты получишь сообщение об ошибке. Завершить сеанс связи можно, нажав Ctrl + C.

-----------

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

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

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

Например есть протокол WAMP который позволяет делать удаленный вызов процедур (RPC) по вебсокет-каналу: http://wamp-proto.org/

А библиотека http://autobahn.ws/ содержит готовую реализацию этого протокола.

Демона как я сказал, можно писать и на PHP, исплоьзуя библиотеку ReactPHP, и на ноде, и на других языках программирования.
#155 #579531
>>579526

Для начала тебе надо вообще понять что такое порт. Это термин из протокола TCP, протокол TCP это стандарт по которому программы могут соединяться и передавать друг другу потоки данных.

Вот вырезка из урока по HTTP который я пишу уже который год:

--------------

## Интернет

Интернет - это всемирная сеть, объединяющая множество компьютеров и устройств. Устройство и принцип работы этой сети описаны в протоколе (протокол это стандарт, описывающий взаимодействие систем) IP.

У каждого узла сети есть свой уникальный идентификатор (он называется IP адрес), и указав его, узлы могут передавать друг другу по этой сети пакеты данных. Сейчас все еще используются IPv4-адреса, которые имеют вид вроде `102.34.23.20` (4 числа от 1 до 254), но так как эти адреса заканчиваются, в будущем мы перейдем на [IPv6](https://ru.wikipedia.org/wiki/IPv6), где адреса состоят из большего числа цифр.

Также, некоторые IP адреса имеют специальный смысл. IP-адреса вида `127.x.x.x`(например `127.0.0.1`) соответствуют так называемому loopback-интерфейсу и если попытаться отправить пакет на такой адрес, то он не уйдет в сеть, а останется на компьютере. Эта особенность используется программами, которые запущены на одном и том же узле и хотят обмениваться друг с другом данными.

Каждый IP-пакет содержит IP-адрес отправителя, получателя, а также примерно до 1600 байтов данных (байт это целое число от 0 до 255).

## TCP

Допустим, у нас есть 2 программы, A и B, запущенные на разных компьютерах (допустим, A на узле `1.1.1.1`, а B на `2.2.2.2`). Они могут использовать описанный выше протокол IP для передачи друг другу каких-то данных, но это не очень удобно:

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

Все эти проблемы решает более высокоуровневый протокол TCP (еще его называют TCP/IP, так как он в своей работе использует IP). Он добавляет к IP-адресам номер порта - число от 1 до 65535, которое идентифицирует программу-получателя или отправителя. Разные программы используют разные номера портов, и потому можно понять какой из них предназначены данные. Также, он обеспечивает повторную отправку пакетов при потере, и позовляет пересылать сколь угодно большой объем данных, разбивая их на пакеты при передаче и собирая обратно при получении.

Протокол TCP/IP в примере выше работает так:

- программа A на узле `1.1.1.1` хочет получать данные от программы B. Потому она открывает на компьютере порт с заранее обговоренным номером, например `2000`, и начинает ждать входящих соединений («слушать порт»). Если этот порт уже используется другой программой, повторно открыть его не удастся, и произойдет ошибка, если нет, то операционная система выделяет порт номер 2000 программе.
- программа B, которая хочет послать какие-то данные программе A, устанавливает TCP-соединение с узлом `1.1.1.1`, порт `2000`
- программа на узле A получает уведомление, что кто-то пытается установить соединение с ней с IP-адреса `2.2.2.2`. Она может принять это соединение, или отказаться, допустим она принимает его.
- с этого момента соединение установлено, и программы могут посылать друг другу в обе стороны данные любого объема
- когда передача закончена (или когда программа A не хочет больше получать данные), любая из программ может закрыть соединение на прием данных. Вторая программа получает уведомление об этом, и если она тоже закрывает соединение со своей стороны, то оно завершается.

Если программы запущены на одном и том же компьютере, то они могут использовать упомянутый выше IP-адрес `127.0.0.1`.

Если ты используешь Windows/linux/mac, ты можешь установить TCP-соединение с любым узлом и портом командой `telnet IP-адрес порт`, например:

```shell
telnet 8.8.8.8 80
```

Если порт и адрес указаны правильно (то есть есть узел с таким IP-адресом, на нем запущена программа, слушающая этот порт и она принимает твое соединение), то все, что ты печатаешь, кодируется в виде байт и посылается на удаленный узел, а все, что он пришлет, отображается на экране. Если нет, то подождав минуту-две, ты получишь сообщение об ошибке. Завершить сеанс связи можно, нажав Ctrl + C.

-----------

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

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

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

Например есть протокол WAMP который позволяет делать удаленный вызов процедур (RPC) по вебсокет-каналу: http://wamp-proto.org/

А библиотека http://autobahn.ws/ содержит готовую реализацию этого протокола.

Демона как я сказал, можно писать и на PHP, исплоьзуя библиотеку ReactPHP, и на ноде, и на других языках программирования.
#156 #579533
>>579531
О господи, сотни нефти тебе, наконец-то понятно.
1004 Кб, 1366x768
sage #157 #579549
ОП

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

Попал я сразу на хард левел и на первой же лабе дали нам задание сделать на дому:

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

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

Оригинал задания на всякий случай.
Napisz klasę o nazwie Bank posiadającą trzy metody zwrotne typu double o nazwach wyplata, wplata oraz saldo. Metody te powinny operować na polu klasowym stan (typ double) zwracając za każdym razem jego wartość. Wykonaj odpowiednie testy jednostkowe.

Там дальше будут и другие задания усложненные от этого.

К тебе ряд вопросов:

1. Смогу ли я полноценно делать лабы на PHP или стоит пока не поздно перекатываться в Java или C#. Потому что также будет задание например сделать какое-то приложение, то мне можно например будет создать веб страничку которая будет в роли интерфейса приложения?

Может функций PHP для некоторых задач будет не достаточно?

2. По поводу самого задания, как я понял нужно создать класс "Банк", атрибут "Состояние" и три метода. Ну а вот дальше что? Что от меня хотят?

Буду благодарен за помощь или даже просто если скажешь, что ты по этому поводу думаешьмне пиздец
1004 Кб, 1366x768
sage #157 #579549
ОП

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

Попал я сразу на хард левел и на первой же лабе дали нам задание сделать на дому:

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

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

Оригинал задания на всякий случай.
Napisz klasę o nazwie Bank posiadającą trzy metody zwrotne typu double o nazwach wyplata, wplata oraz saldo. Metody te powinny operować na polu klasowym stan (typ double) zwracając za każdym razem jego wartość. Wykonaj odpowiednie testy jednostkowe.

Там дальше будут и другие задания усложненные от этого.

К тебе ряд вопросов:

1. Смогу ли я полноценно делать лабы на PHP или стоит пока не поздно перекатываться в Java или C#. Потому что также будет задание например сделать какое-то приложение, то мне можно например будет создать веб страничку которая будет в роли интерфейса приложения?

Может функций PHP для некоторых задач будет не достаточно?

2. По поводу самого задания, как я понял нужно создать класс "Банк", атрибут "Состояние" и три метода. Ну а вот дальше что? Что от меня хотят?

Буду благодарен за помощь или даже просто если скажешь, что ты по этому поводу думаешьмне пиздец
#158 #579555
>>579549
Бери С#, Java посложнее будет, мне кажется.
Качай учебник Библия С#, обмазывайся мсдн.
Удачи.
#159 #579559
>>579549

> задачки не решал, только теорию прочел


Это зря, без практики теория ООП плохо усваивается.

> "вплата"


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

> На паре говорили про модульные тесты


Это хорошо, что вас такому учат, это правильный и современный подход. У меня есть обзорный урок про автоматизированные тесты, если он тебе чем-то поможет:
https://gist.github.com/codedokode/8733007

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

> и препод рассматривал ситуации где массив равен нулю


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

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

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

> Смогу ли я полноценно делать лабы на PHP или стоит пока не поздно перекатываться в Java или C#


Я вижу тут некоторую проблему, так как в PHP например нельзя указать аргументу функции тип «double» как требуется в задаче. Этот вопрос стоит задать преподавателю, какие языки разрешены, а какие нет и будет ли отстутсвие статической типизации проблемой (в языках вроде C#/Java типы всех переменных указываются явно в коде и известны без выполнения программы, в PHP переменная может содержать значения любого типа, это называется динамическая типизация).

Я могу сказать, что если ты перейдешь на Java или C# то увидишь, что они очень похожи. ООП там почти такой же, тоже есть классы, поля, методы, переменные, if, for, массивы, те же виды скобок. Вот основные отличия:

- в Java/C# перед переменной не ставят знак доллара, вместо -> используют точку, и в них не обязательно писать $this. То есть в PHP $this->field, там this.field или просто field
- в Java/C# надо явно указывать типы всех переменных, аргументов и результата выполнения функции
- в Java/C# нельзя просто взять и написать скрипт, надо сделать минимум один класс, в нем метод main и в нем писать код. Также, там нет функций вне классов, вместо них используются обычные и статические методы. Эти языки поддерживают только ООП код.
- в Java/C# массив это структура где ключом может быть число от 0 до N без прпусков, и где элементы хранятся по возрастанию ключа. В PHP как ты помнишь, ключи и порядок может быть любой, такая структура там называется «словарь» (dictionary) или хеш-таблица (hash map)
- там есть стандартные функции и классы, но их надо подключать явно с помощью импортов
- там обычно пишут и запускают код в консоли (или в IDE в которую встроена консоль), а не в браузере.

> 2. По поводу самого задания, как я понял нужно создать класс "Банк", атрибут "Состояние" и три метода. Ну а вот дальше что? Что от меня хотят?


Давай я дам пасту про то как надо решать ООП задачи:

-------

Когда ты решаешь задачу на ООП, ты должен ответить на вопросы:

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

--------

В общем, я могу помочь так: выясни какой язык разрешен, прочитай быстренько про основы синтаксиса в нем и после этого можешь вкидывать свой код, я прокомментирую. Я понимаю и С# и Java, а ideone выполняет программы на этих языках, так что проблем не должно возникнуть. После этого напиши план тестирования, обсудим, и если все ок, напишешь юнит-тесты.

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

Хотя конечно по моему такие вещи надо изучать не в магистратуре, а на первом курсе, если это связанная с программированием специальность.
#159 #579559
>>579549

> задачки не решал, только теорию прочел


Это зря, без практики теория ООП плохо усваивается.

> "вплата"


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

> На паре говорили про модульные тесты


Это хорошо, что вас такому учат, это правильный и современный подход. У меня есть обзорный урок про автоматизированные тесты, если он тебе чем-то поможет:
https://gist.github.com/codedokode/8733007

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

> и препод рассматривал ситуации где массив равен нулю


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

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

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

> Смогу ли я полноценно делать лабы на PHP или стоит пока не поздно перекатываться в Java или C#


Я вижу тут некоторую проблему, так как в PHP например нельзя указать аргументу функции тип «double» как требуется в задаче. Этот вопрос стоит задать преподавателю, какие языки разрешены, а какие нет и будет ли отстутсвие статической типизации проблемой (в языках вроде C#/Java типы всех переменных указываются явно в коде и известны без выполнения программы, в PHP переменная может содержать значения любого типа, это называется динамическая типизация).

Я могу сказать, что если ты перейдешь на Java или C# то увидишь, что они очень похожи. ООП там почти такой же, тоже есть классы, поля, методы, переменные, if, for, массивы, те же виды скобок. Вот основные отличия:

- в Java/C# перед переменной не ставят знак доллара, вместо -> используют точку, и в них не обязательно писать $this. То есть в PHP $this->field, там this.field или просто field
- в Java/C# надо явно указывать типы всех переменных, аргументов и результата выполнения функции
- в Java/C# нельзя просто взять и написать скрипт, надо сделать минимум один класс, в нем метод main и в нем писать код. Также, там нет функций вне классов, вместо них используются обычные и статические методы. Эти языки поддерживают только ООП код.
- в Java/C# массив это структура где ключом может быть число от 0 до N без прпусков, и где элементы хранятся по возрастанию ключа. В PHP как ты помнишь, ключи и порядок может быть любой, такая структура там называется «словарь» (dictionary) или хеш-таблица (hash map)
- там есть стандартные функции и классы, но их надо подключать явно с помощью импортов
- там обычно пишут и запускают код в консоли (или в IDE в которую встроена консоль), а не в браузере.

> 2. По поводу самого задания, как я понял нужно создать класс "Банк", атрибут "Состояние" и три метода. Ну а вот дальше что? Что от меня хотят?


Давай я дам пасту про то как надо решать ООП задачи:

-------

Когда ты решаешь задачу на ООП, ты должен ответить на вопросы:

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

--------

В общем, я могу помочь так: выясни какой язык разрешен, прочитай быстренько про основы синтаксиса в нем и после этого можешь вкидывать свой код, я прокомментирую. Я понимаю и С# и Java, а ideone выполняет программы на этих языках, так что проблем не должно возникнуть. После этого напиши план тестирования, обсудим, и если все ок, напишешь юнит-тесты.

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

Хотя конечно по моему такие вещи надо изучать не в магистратуре, а на первом курсе, если это связанная с программированием специальность.
5664 Кб, Webm
#160 #579560
>>579549
Я не ОП.
А препод не прояснял на чем можно писать? Из тобою написанного мне кажется, что курс конкретно про яву.
Для этого задания тебе хватит пару страничек про синтаксис прочитать.
А что с с заданием не понятно? Класс Банк. Одно поле баланс(stan). Три метода: пополнить, снять, посмотретьБаланс. Все методы возвращают значение поля баланс. Ну и все происходит с одним типом данных double.

Оказывается бульбаши понимают польский.
#161 #579561
>>579549

Ссылка на урок про тесты не та, вот правильная: https://gist.github.com/codedokode/a455bde7d0748c0a351a
#162 #579562
>>579559

>Давай я дам пасту про то как надо решать ООП задачи


О, спасибо. Это есть в учебнике ОП-поста? Недавно начал читать.
#163 #579563
>>579560

Он и на русский похож, но некоторые вещи меня сбивают с толку, например «trzy» - из-за лишней буквы З трудно понять что это значит «три».
#164 #579564
>>579562

Пока нету. Но я даю ее всем кто спрашивает как решить задачу или показывает решение.
23 Кб, 630x610
12 Кб, 324x622
15 Кб, 445x625
#165 #579570
>>579555

Спасибо

>>579559
Я просто выбрал хардлвл. Придется все быстро зубрить.

Вообще препод сказал, что можно писать хоть на php, на паре мы рассматривали пример на Java, но я думаю, что начну изучать C#, он мне больше нравится чем Java. Как я понял, там есть фреймворк ASP.NET и на нем можно вкатываться в веб, а мне всегда веб был по душе, поэтому я и учил PHP. А как там Java устроено с вебом я не знаком, поэтому думаю, что C# будет полезней изучать.

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

> Но делать все тебе придется самому


Знаю, я и сам хочу научиться решать такие задания самостоятельно.

>Хотя конечно по моему такие вещи надо изучать не в магистратуре, а на первом курсе, если это связанная с программированием специальность.



Я поступил на магистратуру программирования, а до этого учился на радиофаке в Украине. Так уж вышло.

Алсо он нам еще рассказал про проект который начало которого должно быть готово сразу после нового года.

Придумать что-то инновационное и реализовать это.

План выглядит так.
1. Диаграмма вариантов использования и диаграмма классов.

2. Код слово не разобрал и документация.

3. Защита проекта

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

пикрелейтед второе и третье задание, а всего таких заданий будет семь + проект + экзамен в феврале и предмет закрыт

>>579560
Хоть PHP.
23 Кб, 630x610
12 Кб, 324x622
15 Кб, 445x625
#165 #579570
>>579555

Спасибо

>>579559
Я просто выбрал хардлвл. Придется все быстро зубрить.

Вообще препод сказал, что можно писать хоть на php, на паре мы рассматривали пример на Java, но я думаю, что начну изучать C#, он мне больше нравится чем Java. Как я понял, там есть фреймворк ASP.NET и на нем можно вкатываться в веб, а мне всегда веб был по душе, поэтому я и учил PHP. А как там Java устроено с вебом я не знаком, поэтому думаю, что C# будет полезней изучать.

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

> Но делать все тебе придется самому


Знаю, я и сам хочу научиться решать такие задания самостоятельно.

>Хотя конечно по моему такие вещи надо изучать не в магистратуре, а на первом курсе, если это связанная с программированием специальность.



Я поступил на магистратуру программирования, а до этого учился на радиофаке в Украине. Так уж вышло.

Алсо он нам еще рассказал про проект который начало которого должно быть готово сразу после нового года.

Придумать что-то инновационное и реализовать это.

План выглядит так.
1. Диаграмма вариантов использования и диаграмма классов.

2. Код слово не разобрал и документация.

3. Защита проекта

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

пикрелейтед второе и третье задание, а всего таких заданий будет семь + проект + экзамен в феврале и предмет закрыт

>>579560
Хоть PHP.
#166 #579581
>>579570

У Java и C# такие различия: Java старше, и C# новее и исправляет многие ее недостатки. Но с C# ты сильно завязан на софт и инструменты от МС (дорогие!), в то время как Ява кроссплатформенна. Сейчас MS потихоньку открывает асть своих фреймворков, но например WPF намертво привязан к винде и его вряд ли сделают кроссплатформенным.

> Как я понял, там есть фреймворк ASP.NET и на нем можно вкатываться в веб


Вот это плохая идея, как я понимаю, он намертво завязан на софт от МС. Есть открытая среда, Mono, но она по моему имеет различия с софтом от МС.

Ну и для веба Java/C# нужны если ты пишешь высоконагруженные сервисы. для большиснтва веб проектов гораздо больше подойдут динамические языки вроде PHP/Python/Ruby. На них быстрее получается сделать.

Соответственно, вот где применяют Java/C#:

- java: сложные и/или высоконагруженные проекты, в крупных компаниях
- с#: десктопные программы под винду, корпоративный софт (ну типа система учета какой-нибудь ерунды на предприятии), всякая государственная ерунда. Сюда же входит и ASP.NET, на котором могут писаться государственные или внутрикорпоративные веб приложения
- c# софт для виндофонов
- java: приложения для андроид
- java: десктопные приложения (например PhpStorm на яве), но они получаются медленноватые и память едят как не в себя

То есть я бы не сказал что они в вебе так часто используются.

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

> второе и третье задание


Я бы не беспокоился о них, если ты с первым сможешь разобраться, то дальше будет легче и легче.
#167 #579583
>>579549
Можно поподробнее? Как поступил? Сколько лет тебе?
#168 #579585
>>579570
Если выберешь яву то в итоге охуеешь.
Да поверхам и по коре это все няшно и просто.
Но когда полезешь в EE тебя ждет бамболейло.
Все эти aop, ioc, jpa, xa транзакции, хибернейт, сервера приложений, мертвые хуитки вроде jsp, jsf, конфиги в xml, по 3 или 5 способов сделать одно и то же но под разногл вендоора, а сверху полито чем то вроде spring security. Русской литературы нет или она неактуальна версиям. Три системы сборки, репозитории артифактов, аналкарнавал с жеплойментом.

Шарп покажется детским лепетом после такой явы
#169 #579586
>>579585
А ну да.
И это все с учтом того что на выходе в веб у тебя будет jax-rs или springmvc, если не повезет то jsf.
И поверх этого тебе еще фронтенд на js все равно пилить.
То что в джанго или рельсах делается парой строк с шаблонизаторами В яве придется пердолить руками.
Если пишешь бакенд под мобильное приложение то наверно норм. Если хочешь сделать сайтик уровня магазина - факап с фронтендом.
#170 #579587
>>579586
Но есть и плюсы.
Взяв эклипс, стек джейбоса и пострескл ты можешь бесплатно запилить йобасервис.
На шарпе тебе придется покупать чтудию, мсскл, шинду под хостинг.
46 Кб, 837x142
#171 #579623
Почему MySQL ругается на 19 строчку?
Выдает: Invalid datetime format: 1292 Incorrect datetime value: '09:23 2015-11-13' for column 'date' at row 1

Само значение даты я устанавливаю так:
$comment->setDateTime(date("H:i Y-m-d"));
#172 #579626
>>579623
У самой колонки date стоит тип datetimeю
#173 #579632
>>578130

Не понимаю, в чем смысл сборок? Установить PHP/Апач не так и сложно, я помню я это делал в первый день на первой работе без всяких подсказок. А вот от сборок мы получаем проблемы от их нестандартных конфигураций, то в консоли PHP не запускается, то еще что-то. И с вопросами почему-то идут к нам в тред, а не к автору сборки.

>>578169

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

>>578170

надо просто понять логику редактора и привыкнуть к ней. Когда ставится вторая пара кавычек, довольно удобно.

>>578260

Нет. Куки доступны только серверу на домене (например good.example.com) который их поставил и странице с этого домена. На других сайтах они не доступны.

>>578269

А что за вопросы?

>>578280

> Что написать в резюме PHP-джуна?


Погугли что надо писать в резюме. Там как минимум образование пишут еще.

> зачем нужно СОПРОВОДИТЕЛЬНОЕ ПИСЬМО?


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

>>578318

Учебник и задания в ОП посте видел? Там много задач разной сложности. Советую их проходить параллельно или вместо видеокурсов.

> Читаю книгу для самых раков http://rutracker.org/forum/viewtopic.php?t=4172911 а


Хочу предупредить, автор быдлокодер и не разбирается в веб-программировании. Но для ознакомления наверно сгодится. Также, помни что эта книга для тех кто уже знает HTML, CSS, и как работает браузер/веб-сервер. Если не знаешь, то изучи сначала эти технологии.
#173 #579632
>>578130

Не понимаю, в чем смысл сборок? Установить PHP/Апач не так и сложно, я помню я это делал в первый день на первой работе без всяких подсказок. А вот от сборок мы получаем проблемы от их нестандартных конфигураций, то в консоли PHP не запускается, то еще что-то. И с вопросами почему-то идут к нам в тред, а не к автору сборки.

>>578169

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

>>578170

надо просто понять логику редактора и привыкнуть к ней. Когда ставится вторая пара кавычек, довольно удобно.

>>578260

Нет. Куки доступны только серверу на домене (например good.example.com) который их поставил и странице с этого домена. На других сайтах они не доступны.

>>578269

А что за вопросы?

>>578280

> Что написать в резюме PHP-джуна?


Погугли что надо писать в резюме. Там как минимум образование пишут еще.

> зачем нужно СОПРОВОДИТЕЛЬНОЕ ПИСЬМО?


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

>>578318

Учебник и задания в ОП посте видел? Там много задач разной сложности. Советую их проходить параллельно или вместо видеокурсов.

> Читаю книгу для самых раков http://rutracker.org/forum/viewtopic.php?t=4172911 а


Хочу предупредить, автор быдлокодер и не разбирается в веб-программировании. Но для ознакомления наверно сгодится. Также, помни что эта книга для тех кто уже знает HTML, CSS, и как работает браузер/веб-сервер. Если не знаешь, то изучи сначала эти технологии.
#174 #579634
>>578331

Судя по твоему настрою, тебе уже пора на пенсию.

>>578332

Не знаю. Есть parse.com, это сервис предоставляющий бекенд для мобильных приложений - не подойдет?

>>578338

200к начинающему платят разве что в Беларуси.

>>578363

> У ОПа есть же уроки по КСС? Можете скинуть? Я нашёл только вот это


Уроков нет но в задании есть ссылки, ты смотрел? Также, пости решения задач на jsfiddle и вкидывай в тред, а я скажу правильно ты все понял или стоит что-то исправить. В конце там как раз верстка макета будет. В случае решения всех задач и макета (с исправлением всех замечаний), я думаю, у тебя будет достаточный уровень знаний.

По JS/jQuery у нас есть задания, смотри ОП пост. Ну а учебник по JS это конечно learn.javascript.ru

>>578395

А еще у нас в ОП посте неплохие задачки на верстку на мой взгляд.

>>578396

Скиллов не выучишь но может что полезное и извлечешь, опыт получишь.

>>578421

Продолжай учиться и активно искать работу

>>578441

Почему нет? Днем мучаешься натягивая верстку на битрикс, вечером решаешь задачки ОПа на HTML/CSS и наконец-то понимаешь почему у тебя футер все время уезжал. да и что сложного? Работа же не физическая, тяжести таскать не надо, сиди кнопки нажимай.

>>578531

Я тебе ответил в предыдущем треде: >>578913 (если кратко: упрости код и залей на jsfiddle, почитай блог про позицонирование)

>>578548

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


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

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

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

>>578687

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

> Свой почтовый VPS/VDS сервер поднимать побаиваюс


Там еще нужно настраивать все, чтобы твои письма не попадали в спам.
#174 #579634
>>578331

Судя по твоему настрою, тебе уже пора на пенсию.

>>578332

Не знаю. Есть parse.com, это сервис предоставляющий бекенд для мобильных приложений - не подойдет?

>>578338

200к начинающему платят разве что в Беларуси.

>>578363

> У ОПа есть же уроки по КСС? Можете скинуть? Я нашёл только вот это


Уроков нет но в задании есть ссылки, ты смотрел? Также, пости решения задач на jsfiddle и вкидывай в тред, а я скажу правильно ты все понял или стоит что-то исправить. В конце там как раз верстка макета будет. В случае решения всех задач и макета (с исправлением всех замечаний), я думаю, у тебя будет достаточный уровень знаний.

По JS/jQuery у нас есть задания, смотри ОП пост. Ну а учебник по JS это конечно learn.javascript.ru

>>578395

А еще у нас в ОП посте неплохие задачки на верстку на мой взгляд.

>>578396

Скиллов не выучишь но может что полезное и извлечешь, опыт получишь.

>>578421

Продолжай учиться и активно искать работу

>>578441

Почему нет? Днем мучаешься натягивая верстку на битрикс, вечером решаешь задачки ОПа на HTML/CSS и наконец-то понимаешь почему у тебя футер все время уезжал. да и что сложного? Работа же не физическая, тяжести таскать не надо, сиди кнопки нажимай.

>>578531

Я тебе ответил в предыдущем треде: >>578913 (если кратко: упрости код и залей на jsfiddle, почитай блог про позицонирование)

>>578548

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


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

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

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

>>578687

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

> Свой почтовый VPS/VDS сервер поднимать побаиваюс


Там еще нужно настраивать все, чтобы твои письма не попадали в спам.
#175 #579635
>>578717

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

> Ну да, им там админка навороченная сразу крепится и не надо по нее макет придумывать


Вообще это правильно, зачем изобретать то, что уже сделано? Под фреймворки впрочем тоже есть библиотеки вроде Sonata Bundle для создания админки.

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


Не понял. Для скачивания вордпресса нигде регистрироваться не надо.

>>578720

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

>>578865

За полгода (какой вопрос такой и ответ).

>>578929

Спасибо на добром слове

>>578934

Быдлокодить можно на любом языке. Алсо что там непонятного? Я с первого взгляда все понял. Решай наши задачки на JS из ОП поста и тоже будешь понимать.

>>578943

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

>>578976

У них курс просто для ознакомления, что это за язык. Не то чтобы он плохой, но он ознакомительный. Алсо чтобы проходить и понимать их курс по PHP надо сначала выучить HTML.

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

>>578984

По моим ощущениям, курсы там чисто ознакомительные, просто посмотреть нравится тебе или нет этот язык, и какие-то основы изучить.

>>578986

Почему, можно понять нравится тебе язык или нет, например.

>>579023

Взять готовую библиотеку-HTTP клиент, например Guzzle, которая умеет правильно разбирать заголовки. Ну или если не хочешь, бери спецификацию HTTP/1.1 ( http://tools.ietf.org/rfcmarkup?doc=7230#section-3 ) и пиши соответствуюий ей парсер.

> нужен вот свой велосипед.


Тогда изучай спецификацию.

>>579042

Он по моему только для верстки.
#175 #579635
>>578717

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

> Ну да, им там админка навороченная сразу крепится и не надо по нее макет придумывать


Вообще это правильно, зачем изобретать то, что уже сделано? Под фреймворки впрочем тоже есть библиотеки вроде Sonata Bundle для создания админки.

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


Не понял. Для скачивания вордпресса нигде регистрироваться не надо.

>>578720

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

>>578865

За полгода (какой вопрос такой и ответ).

>>578929

Спасибо на добром слове

>>578934

Быдлокодить можно на любом языке. Алсо что там непонятного? Я с первого взгляда все понял. Решай наши задачки на JS из ОП поста и тоже будешь понимать.

>>578943

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

>>578976

У них курс просто для ознакомления, что это за язык. Не то чтобы он плохой, но он ознакомительный. Алсо чтобы проходить и понимать их курс по PHP надо сначала выучить HTML.

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

>>578984

По моим ощущениям, курсы там чисто ознакомительные, просто посмотреть нравится тебе или нет этот язык, и какие-то основы изучить.

>>578986

Почему, можно понять нравится тебе язык или нет, например.

>>579023

Взять готовую библиотеку-HTTP клиент, например Guzzle, которая умеет правильно разбирать заголовки. Ну или если не хочешь, бери спецификацию HTTP/1.1 ( http://tools.ietf.org/rfcmarkup?doc=7230#section-3 ) и пиши соответствуюий ей парсер.

> нужен вот свой велосипед.


Тогда изучай спецификацию.

>>579042

Он по моему только для верстки.
#176 #579636
>>579062

> &$app,


Зачем тут & ?

> construct(\Slim\Slim &$app, $files){


Зачем ты в класс передаешь весь фреймворк целиком? Он весь ему нужен? Я уверен, что нет, значит надо передавать только отдельные компоненты которые нужны.

Вот у меня урок (он правда сложен для начинающего) про передачу зависимостей в класс: https://gist.github.com/codedokode/e1d31a31b37d5f635057

> abstract class Checkrights{


Я смотрю код класса и не могу понять, для чего он? Что представляет собой объект этого класса, какую информацию он хранит, что умеет делать?

> $obj = new Files();


> $obj->parseFile($this->files);


> $obj->CheckFormat();


> $this->cookieDB = $obj->cookie;


Тоже странный код, создаем какой-то непонятный объект (судя по названию он предназначен для хранения нескольких файлов внутри?), парсим что-то что нам пришло в files (что? непонятно), проверяем какой-то формат. Получаем какую-то базу данных кук. Абсолютно непонятно.

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

Решал ли ты наши задачки на Вектор или Кошки-Мышки? На них мы изучаем ООП, учимся делать классы, методы. Ну и дам тебе пасту про то как надо решать ООП-задачки:

----------

Когда ты решаешь задачу на ООП, ты должен ответить на вопросы:

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

-----------

Попробуй ответить на эти вопросы применительно к классу CheckRights.

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

> class Checkrights


Имена классов это существительные, а у тебя глагол (проверитьПрава). Так как объект это не действие, а сущность, над которой производятся действия.

То есть класс может назваться Файл, Права, ЗагружательФайлов.

> public $files;


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

> function GerFiles(){


Имена функций пишутся с маленькой буквы

> $this->cookieUser=$this->app->getCookie('username');


> $this->cookieDB = $obj->cookie;


> $obj->path = $this->preview;


Одинаковые вещи (cookieUser, username) надо называть одинаково.

> $this->public


Public это ключевое слово и им не стоит называть поля или переменные.

> $this->filesize


В твоем классе нет такого поля

> $obj


Это название ничего не значит. Нужно выбрать другое, более осмысленное название. Также, не надо сокращать слово ради 3 букв.

Почитай вот эту статью: http://learn.javascript.ru/write-unmain-code и помни что код пишется для людей.

>>579063

Твое право не делать тестовые задания, их право не брать тебя на работу.

>>579119

Если ты про задачу про студентов, то нигде. У меня есть урок про обработку форм: https://github.com/codedokode/pasta/blob/master/forms.md

Лучше всего из POST создавать объект-модель и затем проверять значения в ней. Проверку (валидацию) логично сделать в отдельном классе-валидаторе.

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

Плюс с моделью-объектом удобнее работать чем с массивом в котором может быть (или не быть) что угодно.

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

>>579121

Ты что-то не понимаешь. в MVC обычно используют роутинг, то есть произвольно назначают соответсвие контроллера и URl, и в action ты пишешь не путь к классу, а просто URL вроде /register/. А роутер уже определит что для этого URL надо вызвать метод indexAction у класса RegisterController.

Я не знаю, где ты изучаешь MVC но советую посмотреть как сделан роутинг в том же микрофреймворке Slim.

> Или в файлах с контроллерами можно не только классы размещать


В файле с классом нельзя размещать ничего кроме этого класса.

>>579172

> Массив POST (и все остальные которые начинаются с _) суперглобальный, то есть доступный в любом месте


Однако это не значит что стоит использовать его где угодно. Обработку и разбор POST-данных стоит оставить контроллеру.

> Есть класс приложения class Application


> У него метод инициализации


Неудачное название, потому что в твоем примере это фактически реализация паттерна Front Controller ( http://design-pattern.ru/patterns/front-controller.html ) и назвать его надо так же.

> $app->init();


> $app->run();


не могу не удержаться от вопроса: а почему тут 2 метода если можно сделать один initAndRun? Какая выгода вызвать 2 метода вместо одного?

> Model::findById


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

> В методе render берем шаблон и заменяем плейсхолдеры на значение переменных.


Прочитай совет №6 отсюда: http://habrahabr.ru/post/230737/
#176 #579636
>>579062

> &$app,


Зачем тут & ?

> construct(\Slim\Slim &$app, $files){


Зачем ты в класс передаешь весь фреймворк целиком? Он весь ему нужен? Я уверен, что нет, значит надо передавать только отдельные компоненты которые нужны.

Вот у меня урок (он правда сложен для начинающего) про передачу зависимостей в класс: https://gist.github.com/codedokode/e1d31a31b37d5f635057

> abstract class Checkrights{


Я смотрю код класса и не могу понять, для чего он? Что представляет собой объект этого класса, какую информацию он хранит, что умеет делать?

> $obj = new Files();


> $obj->parseFile($this->files);


> $obj->CheckFormat();


> $this->cookieDB = $obj->cookie;


Тоже странный код, создаем какой-то непонятный объект (судя по названию он предназначен для хранения нескольких файлов внутри?), парсим что-то что нам пришло в files (что? непонятно), проверяем какой-то формат. Получаем какую-то базу данных кук. Абсолютно непонятно.

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

Решал ли ты наши задачки на Вектор или Кошки-Мышки? На них мы изучаем ООП, учимся делать классы, методы. Ну и дам тебе пасту про то как надо решать ООП-задачки:

----------

Когда ты решаешь задачу на ООП, ты должен ответить на вопросы:

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

-----------

Попробуй ответить на эти вопросы применительно к классу CheckRights.

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

> class Checkrights


Имена классов это существительные, а у тебя глагол (проверитьПрава). Так как объект это не действие, а сущность, над которой производятся действия.

То есть класс может назваться Файл, Права, ЗагружательФайлов.

> public $files;


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

> function GerFiles(){


Имена функций пишутся с маленькой буквы

> $this->cookieUser=$this->app->getCookie('username');


> $this->cookieDB = $obj->cookie;


> $obj->path = $this->preview;


Одинаковые вещи (cookieUser, username) надо называть одинаково.

> $this->public


Public это ключевое слово и им не стоит называть поля или переменные.

> $this->filesize


В твоем классе нет такого поля

> $obj


Это название ничего не значит. Нужно выбрать другое, более осмысленное название. Также, не надо сокращать слово ради 3 букв.

Почитай вот эту статью: http://learn.javascript.ru/write-unmain-code и помни что код пишется для людей.

>>579063

Твое право не делать тестовые задания, их право не брать тебя на работу.

>>579119

Если ты про задачу про студентов, то нигде. У меня есть урок про обработку форм: https://github.com/codedokode/pasta/blob/master/forms.md

Лучше всего из POST создавать объект-модель и затем проверять значения в ней. Проверку (валидацию) логично сделать в отдельном классе-валидаторе.

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

Плюс с моделью-объектом удобнее работать чем с массивом в котором может быть (или не быть) что угодно.

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

>>579121

Ты что-то не понимаешь. в MVC обычно используют роутинг, то есть произвольно назначают соответсвие контроллера и URl, и в action ты пишешь не путь к классу, а просто URL вроде /register/. А роутер уже определит что для этого URL надо вызвать метод indexAction у класса RegisterController.

Я не знаю, где ты изучаешь MVC но советую посмотреть как сделан роутинг в том же микрофреймворке Slim.

> Или в файлах с контроллерами можно не только классы размещать


В файле с классом нельзя размещать ничего кроме этого класса.

>>579172

> Массив POST (и все остальные которые начинаются с _) суперглобальный, то есть доступный в любом месте


Однако это не значит что стоит использовать его где угодно. Обработку и разбор POST-данных стоит оставить контроллеру.

> Есть класс приложения class Application


> У него метод инициализации


Неудачное название, потому что в твоем примере это фактически реализация паттерна Front Controller ( http://design-pattern.ru/patterns/front-controller.html ) и назвать его надо так же.

> $app->init();


> $app->run();


не могу не удержаться от вопроса: а почему тут 2 метода если можно сделать один initAndRun? Какая выгода вызвать 2 метода вместо одного?

> Model::findById


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

> В методе render берем шаблон и заменяем плейсхолдеры на значение переменных.


Прочитай совет №6 отсюда: http://habrahabr.ru/post/230737/
#177 #579639
>>579284

Я кстати в старом треде ответ писал тебе про Visit Counter, может ты не видел: >>578910\t

> В top не понимаю некоторые вещи, в частности swap. Кажется, это раздел подкачки


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

У тебя вообще много неиспользуемой памяти (free). Обычно система использует свободную память под дисковый кеш (cached, buffers), но у тебя она не смогла все использовать. Это значит что памяти более чем достаточно.

> Установил iotop, но я в нем ничего не понимаю.


Ну он помогает увидеть если кто-то сильно мучает диск.

> ab write вырастает максимум до 1800 K/s.


Вот это не очень понятно, хорошо или плохо. Что там такое можно читать или писать в таком количестве?

> Я выбираю категории верхнего уровня для меню, код выглядит таким образом:


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

> Насколько я понимаю, индекс lft использован не будет.


Видимо да

> Но 3600 конечно не набирается, не понимаю откуда столько.


Может быть в выпадающем списке много значений?

> Браузер почему-то очень долго ждет картинки, которых нет на сервере.


Очевидно, так как файлов нет на диске, Апач их не может отдать, и вызвает фреймворк. И вся эта громада грузится (почему-то медленно, почему?) только ради того чтобы выдать страницу 404.

Кстати и JS/CSS файлы что-то медленно грузятся. Посмотри по заголовкам, они при участии или без участия PHP отдаются?

Решить эту проблему можно тем, что например в конфиге прописать что обращения к папке /images/, /css/, /js/ и подобным не должны передаваться фреймворку (для апача добавить RewriteCond, для нгинкса - location)

> Жесткий диск медленный (наверное).


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

> Скажи какой командой можно записать это в файл, я сделаю, потому что сам не знаю


на какие цифры смотреть.
Я имел в виду посмотреть top и iotop. Из них мы видим, что памяти достаточно, и процессор полностью загружен. Это хорошо, что он загружен и не проставивает, но вот то, что медленно все работает, это не хорошо.

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


Если потратить время на кеширование, то выжмешь.

Могу предложить такой план, идти от простых оптимизаций к сложным, на каждом шаге меряя результаты:

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

Давай поясню про последний пункт. У нас есть проблема - выбирается и создается куча тяжелых (для твоего игрушечного процессора) объектов, ради чего? Ради того чтобы вывести какой-нибудь ерундовый селект с городами. Мы можем закешировать это дело на нескольких уровнях:

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

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

На такой случай есть костыль - преобразовываем модели БД в маленькие простые классы с данными (паттерн DTO: http://design-pattern.ru/patterns/data-transfer-object.html ) и сериализуем их. Злые языки говорят что можно обойтись без классов, массивом сложной структуры, но это я написать без спойлера не решусь Минус: у нас появляется 2 класса для обозначения одной сущности, все еще сложнее и запутаннее.

- также, у нас есть второй уровень кеширования - кешировать на уровне HTML. Это наиболее неудобный способ, так как не дает никаких возможностей как-то поменять или что-то сделать с данными, но наиболее эффективный и тебе может помочь. Проще говоря, мы можем закешировать HTML код селекта с городами или блока последних объявлений и обойтись без запроса к БД, создания тяжелых моделей и их рендеринга. Но это темная сторона силы и по-хорошему лучше просто поставить сервер помощнее, а не усложнять приложение из-за нищехостинга.

Не забывай что при кешировании надо помнить:

- надо смотреть отношение hits/misses и не кешировать то, для чего оно плохое
- кешировать эффективно маленькие объемы тяжеловычисляемых данных
- кеш надо поддерживать в актуальном состоянии или сбрасывать при изменении исходных данных

Ну кеширование оставим как последний, отчаянный шаг, а до него давай настроим фреймворк. Жду также от тебя мыслей по выбору движка для кеша.

>>579292

Может они 60 прибавляют чтобы автору пасты не было грустно?

>>579322

> Почему шаблон не рендереится?


Надо смотреть шаблон

Алсо в коде куча ошибок, например htmlspecialchars который должен быть в шаблоне, а не тут, создание кучи объектов-сервисов в то время как правильнее их сделать синглтонами в Слиме.
#177 #579639
>>579284

Я кстати в старом треде ответ писал тебе про Visit Counter, может ты не видел: >>578910\t

> В top не понимаю некоторые вещи, в частности swap. Кажется, это раздел подкачки


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

У тебя вообще много неиспользуемой памяти (free). Обычно система использует свободную память под дисковый кеш (cached, buffers), но у тебя она не смогла все использовать. Это значит что памяти более чем достаточно.

> Установил iotop, но я в нем ничего не понимаю.


Ну он помогает увидеть если кто-то сильно мучает диск.

> ab write вырастает максимум до 1800 K/s.


Вот это не очень понятно, хорошо или плохо. Что там такое можно читать или писать в таком количестве?

> Я выбираю категории верхнего уровня для меню, код выглядит таким образом:


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

> Насколько я понимаю, индекс lft использован не будет.


Видимо да

> Но 3600 конечно не набирается, не понимаю откуда столько.


Может быть в выпадающем списке много значений?

> Браузер почему-то очень долго ждет картинки, которых нет на сервере.


Очевидно, так как файлов нет на диске, Апач их не может отдать, и вызвает фреймворк. И вся эта громада грузится (почему-то медленно, почему?) только ради того чтобы выдать страницу 404.

Кстати и JS/CSS файлы что-то медленно грузятся. Посмотри по заголовкам, они при участии или без участия PHP отдаются?

Решить эту проблему можно тем, что например в конфиге прописать что обращения к папке /images/, /css/, /js/ и подобным не должны передаваться фреймворку (для апача добавить RewriteCond, для нгинкса - location)

> Жесткий диск медленный (наверное).


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

> Скажи какой командой можно записать это в файл, я сделаю, потому что сам не знаю


на какие цифры смотреть.
Я имел в виду посмотреть top и iotop. Из них мы видим, что памяти достаточно, и процессор полностью загружен. Это хорошо, что он загружен и не проставивает, но вот то, что медленно все работает, это не хорошо.

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


Если потратить время на кеширование, то выжмешь.

Могу предложить такой план, идти от простых оптимизаций к сложным, на каждом шаге меряя результаты:

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

Давай поясню про последний пункт. У нас есть проблема - выбирается и создается куча тяжелых (для твоего игрушечного процессора) объектов, ради чего? Ради того чтобы вывести какой-нибудь ерундовый селект с городами. Мы можем закешировать это дело на нескольких уровнях:

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

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

На такой случай есть костыль - преобразовываем модели БД в маленькие простые классы с данными (паттерн DTO: http://design-pattern.ru/patterns/data-transfer-object.html ) и сериализуем их. Злые языки говорят что можно обойтись без классов, массивом сложной структуры, но это я написать без спойлера не решусь Минус: у нас появляется 2 класса для обозначения одной сущности, все еще сложнее и запутаннее.

- также, у нас есть второй уровень кеширования - кешировать на уровне HTML. Это наиболее неудобный способ, так как не дает никаких возможностей как-то поменять или что-то сделать с данными, но наиболее эффективный и тебе может помочь. Проще говоря, мы можем закешировать HTML код селекта с городами или блока последних объявлений и обойтись без запроса к БД, создания тяжелых моделей и их рендеринга. Но это темная сторона силы и по-хорошему лучше просто поставить сервер помощнее, а не усложнять приложение из-за нищехостинга.

Не забывай что при кешировании надо помнить:

- надо смотреть отношение hits/misses и не кешировать то, для чего оно плохое
- кешировать эффективно маленькие объемы тяжеловычисляемых данных
- кеш надо поддерживать в актуальном состоянии или сбрасывать при изменении исходных данных

Ну кеширование оставим как последний, отчаянный шаг, а до него давай настроим фреймворк. Жду также от тебя мыслей по выбору движка для кеша.

>>579292

Может они 60 прибавляют чтобы автору пасты не было грустно?

>>579322

> Почему шаблон не рендереится?


Надо смотреть шаблон

Алсо в коде куча ошибок, например htmlspecialchars который должен быть в шаблоне, а не тут, создание кучи объектов-сервисов в то время как правильнее их сделать синглтонами в Слиме.
#178 #579640
>>579340

Если это да/нет то надо использовать TINYINT(1) NOT NULL, если это статус то надо сделать ENUM('good', 'bad') NOT NULL так как статусов явно может быть больше 2.

> оказалось, это тип binary


Неверно, BOOL это синоним для TINYINT(1):

http://dev.mysql.com/doc/refman/5.7/en/numeric-type-overview.html

> BOOL, BOOLEAN


> These types are synonyms for TINYINT(1)



Ты что-то путаешь.

> Смотрю в админере, дефолтом ставится 30, а не 0.


Это что-то странное. Покажи-ка то выведет SHOW CREATE TABLE table;

> При этом похапе 30 понимает правильно, как false


Это вряд ли

В общем покажи SHOW CREATE TABLE а не то что где-то в каком-то интерфейсе выводится. Интуиция подсказывает что ты какой-то левый тип там поставил.

>>579379

> Пользуйся клиентом командной строки mysql, чтобы руками писать запросы.


В админере тоже можно руками писать

>>579382

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

>>579387

Уходи

>>579416

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

Если ты плохо знаешь БД, почему бы не прорешать наши задачки на SQL из ОП поста?

>>579451

> По ssh не всегда доступ есть,


Это плохо

> если есть 7 двоичных.


Напиши какие конкретно. Я думаю ты что-то путаешь.

>>579455

Обработка форм: https://github.com/codedokode/pasta/blob/master/forms.md
Соль: https://gist.github.com/codedokode/9576319

> Алсо, если мне нужно проверять поля для регистрации и входа, то делать ли для них один класс с проверкой или два разных?


Можно один, но с 2 методами или работающий в 2 разных режимах.

> И если один, то как его организовать?


Сделать 2 отдельных метода

>>579463

> Выгода enum в том, что просто невозможно вбить другое значение кроме перечисленных, база его не примет


Если ты не забыл включить строгий режим, иначе по моему примет и сохранит NULL либо пустую строку.

https://github.com/codedokode/pasta/blob/master/student-list.md#Строгий-режим-в-mysql

>>579466

Лучше юзать баттоны

>>579481

> ALTER TABLE table ALTER COLUMN status bool


по моему это неправильный синтаксис, надо писать MODIFY COLUMN: https://dev.mysql.com/doc/refman/5.7/en/alter-table.html

>>579623

> Incorrect datetime value: '09:23 2015-11-13


Надо '2015-11-12 00:00:00'

> $comment->setDateTime(date("H:i Y-m-d"));


Это тоже неправильно. Внутри модели дату надо хранить не в MysQL формате, а таймстампом или объектом DateTime (рекомендую). Потому что это модель, а не строка из базы данных. Если у тебя не ActiveRecord (я уверен что нет) то модель не должна ничего знать про базу данных и используемые ей форматы. Да и неудобно работать со строкой.

Также, date это ключевое слово, его надо брать в косые кавычки или переименовать.
#178 #579640
>>579340

Если это да/нет то надо использовать TINYINT(1) NOT NULL, если это статус то надо сделать ENUM('good', 'bad') NOT NULL так как статусов явно может быть больше 2.

> оказалось, это тип binary


Неверно, BOOL это синоним для TINYINT(1):

http://dev.mysql.com/doc/refman/5.7/en/numeric-type-overview.html

> BOOL, BOOLEAN


> These types are synonyms for TINYINT(1)



Ты что-то путаешь.

> Смотрю в админере, дефолтом ставится 30, а не 0.


Это что-то странное. Покажи-ка то выведет SHOW CREATE TABLE table;

> При этом похапе 30 понимает правильно, как false


Это вряд ли

В общем покажи SHOW CREATE TABLE а не то что где-то в каком-то интерфейсе выводится. Интуиция подсказывает что ты какой-то левый тип там поставил.

>>579379

> Пользуйся клиентом командной строки mysql, чтобы руками писать запросы.


В админере тоже можно руками писать

>>579382

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

>>579387

Уходи

>>579416

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

Если ты плохо знаешь БД, почему бы не прорешать наши задачки на SQL из ОП поста?

>>579451

> По ssh не всегда доступ есть,


Это плохо

> если есть 7 двоичных.


Напиши какие конкретно. Я думаю ты что-то путаешь.

>>579455

Обработка форм: https://github.com/codedokode/pasta/blob/master/forms.md
Соль: https://gist.github.com/codedokode/9576319

> Алсо, если мне нужно проверять поля для регистрации и входа, то делать ли для них один класс с проверкой или два разных?


Можно один, но с 2 методами или работающий в 2 разных режимах.

> И если один, то как его организовать?


Сделать 2 отдельных метода

>>579463

> Выгода enum в том, что просто невозможно вбить другое значение кроме перечисленных, база его не примет


Если ты не забыл включить строгий режим, иначе по моему примет и сохранит NULL либо пустую строку.

https://github.com/codedokode/pasta/blob/master/student-list.md#Строгий-режим-в-mysql

>>579466

Лучше юзать баттоны

>>579481

> ALTER TABLE table ALTER COLUMN status bool


по моему это неправильный синтаксис, надо писать MODIFY COLUMN: https://dev.mysql.com/doc/refman/5.7/en/alter-table.html

>>579623

> Incorrect datetime value: '09:23 2015-11-13


Надо '2015-11-12 00:00:00'

> $comment->setDateTime(date("H:i Y-m-d"));


Это тоже неправильно. Внутри модели дату надо хранить не в MysQL формате, а таймстампом или объектом DateTime (рекомендую). Потому что это модель, а не строка из базы данных. Если у тебя не ActiveRecord (я уверен что нет) то модель не должна ничего знать про базу данных и используемые ей форматы. Да и неудобно работать со строкой.

Также, date это ключевое слово, его надо брать в косые кавычки или переименовать.
#179 #579661
>>579581
>>579587

Мой вуз сотрудничает с майрософтом и у меня будет доступ к софту разработки для винды бесплатно.

Что-то на подобии вот этого, может именно это. Сам нагуглил.

https://www.dreamspark.com/Institution/Subscription.aspx
#180 #579665
>>579583
21, на платное берут всех и потом если тупишь, то отчисляют, не полностью, а можно вернуться за деньги, после какого провала передача экзамена тоже за деньги.

Это про частные вузы, они здесь в 2-3 раза дешевле, но если у тебя есть бабуля полька, то делаешь карту поляка и учишься в любом гос вузе бесплатно.
В общем стоит волноваться не как поступить, а как ты будешь учиться, чтобы тебя не пидорнули.
#181 #579675
>>579640
Нельзя в ENUM использовать числа, будут баги. Надо строки начинающиеся с букв
Именно преобразование строк в числа мне и нужны, ибо пхп не может сравнивать строки. Например, если я везде ставлю "false", то потом при сравнении if($public == "false") у меня выходит ошибка, чего не скажешь о числах, ведь числа пхп нормально сравнивает.
#182 #579678
>>579463
В оф. документации, маня, если ты не знаешь инглиш, написано, что они бы НЕ СОВЕТОВАЛИ. Там не пишут, что так делать запрещено, тем более, что все прекрасно работает и строки преобразуются в числа, как мне и нужно.
#183 #579697
Ребятки, а какие вопросы стоит задать работодателю на собеседовании?
#184 #579713
>>579678
А, ну раз не рекомендуется, тогда используй конечно.

>>579697
Сверься со стеком технологий, которые они используют. Потому что можно попасть в дно-контору, где не используют гитхаб например, а можно наоборот попасть туда, где используют экзотические инструменты, которые тебе придется осваивать.
Расспроси о командном взаимодействии, как поставлена работа. Как тимлид (если таковой имеется) будет тебя курьировать.
Какие проекты ведет контора, это важный детектор, потому что дно-конторы обычно своих проектов вообще не имеют, а занимаются "поддержкой" чужих (обычно под этим подразумевается, что тебе поручат исправлять творчество вована-фрилансера).
Спроси о рабочем графике. В некоторых местах, где бестолково организована работа, сначала неделями бездельничают, а затем с горящими жопами сидят ночами. Нет, если действительно нужно, то не вопрос пару раз в месяц остаться "на вторую смену", главное чтобы это не было систематичным.
#185 #579727
>>579697

Есть тест Джоэла:

http://russian.joelonsoftware.com/Articles/TheJoelTest.html
http://habrahabr.ru/company/jugru/blog/159689/

может тебе что-то из него пригодится.
#186 #579750
>>579727
Это наверное для профи, мы тут все джуниоры, хоть куда-то устроиться бы.

>Созданы ли спокойные условия для работы инженеров? Сколько человек ещё человек сидит в комнате, где будете сидеть Вы? Разговаривают ли люди у себя рабочем месте по мобильникам? Обсуждают ли что-нибудь прямо в комнате, отвлекая других?


О, для меня это критически важно. Я чувствую напряжение даже если просто сидеть в комнате с чужими людьми, не говоря уже о том, что они будут азазакать под ухом, когда нужно решить сложную задачу.
Кто где работает, отпишитесь как у вас с этим дела. Сколько человек в комнате и насколько буйные.
#187 #579752
>>579750

ОП работал в большом опенспейсе, мне норм. Я в общем ничего против других людей не имею.
#188 #579753
>>579727

>коридорное тестирование


Это еще что за хрень? Выловить бабу Нюру уборщицу и заставить ее потестить наш убер-сайт?

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

>>579752
Я против людей тоже ничего не имею, главное чтоб не галдели как гуси.
#189 #579754
>>579713
Какой ты пиздоглазый уебан, там черным по белому написано, что не рекомендуется ПОТОМУ ЧТО строки могут преобразоваться в int. Это мне и надо. Вот типичная педанская манька, без понимания сути и причин использования инструментов. НАПИСАНО ШО НАДО ЗНАЧИТ НАДО УАСЯ!
#190 #579755
>>579753

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


>То есть связи с заказчиком нет, тз непонятное, менеджер не в теме.


Не в ДС, надеюсь? Пушо если такое происходит в дсах, то я даже не знаю, что думать.
#191 #579756
>>579753

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

Лучше наверно посвятить это время учебе и после этого претендовать на более хорошую вакансию.
#192 #579757
>>579754

Кокой ты агрессивный. Хотел тебе сказать, где ты ошибаешься, но передумал.
#193 #579759
>>579755

>Не в ДС, надеюсь?


Перечитал, пиздоглазый я.
#194 #579774
>>579750
Я один в комнате и я не буйный. Мамка иногда шумит, когда с работы приходит, но я включаю музон погромче.
#195 #579788
Господа, возник следующий вопрос.
Вот когда мы вставляем/редактируем запись в БД, мы сначала проверяем состояние БД касательно этой записи (например, столбец является уникальным ключом, а данные формы содержат значение, которое уже есть в этом столбце - тогда посылаем соответствующий ответ пользователю).
Но что, если пользователи могут редактировать и удалять какую-то сущность. Допустим, есть два следующих друг за другом запроса от клиента: 1) на удаление, 2) на редактирование. Возможный порядок операций такой:
1. Отправлен запрос на удаление;
2. Отправлен запрос на редактирование;
3. Проверятся наличие сущности в базе по запросу на удаление - всё ок она есть;
4. Проверяется наличие сущности в базе по запросу на редактирование - она всё ещё есть (параллельный код удаления ещё не выполнился);
5. Удаляется сущность;
6. Неудачная попытка обновить сущность, приложение падает.

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

Это всё очень напрягает. У этой проблемы есть название? Какие правильные решения существуют?
Надеюсь, понятно изложил.
#196 #579790
>>578124 (OP)
Такой запрос будет трактоваться как либо логин совпадает ЛИБО емейл И пароль? Т.е. если логин совпадает, а пароль нет, то поле все равно выеберется?

SELECT * FROM users WHERE login=:login OR email=:email AND password=:password
#197 #579793
#198 #579801
>>579788

Транзакции и блокировки. Тебе бы надо разобраться что такое блокировки (пессимистичные), как база данных блокирует строки таблиц (пессимистично блокируются по умолчнанию измененные строки до конца транзакции), что такое транзакции.

В твоем случае чтение не заблокирует строку, но можно добавить команду SELECT ... FOR UPDATE и заблокирует.

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

> Неудачная попытка обновить сущность, приложение падает.


Если это делается командой UPDATE то не упадет. Если ты конечно не проверяешь после выполнения число измененных строк (affected_rows).

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


Если там стоит уникальный ключ по токену то вторая попытка добавить выдаст ошибку. Если нет то да, добавится 2 пользователя. Опять же тут можно использовать блокировку: при проверке наличия пользователя в базе блокировать эту запись до конца транзакции.
#199 #579802
>>579788
это называется concurrency
решается всякими локами таблиц/строк
#200 #579805
а так?
SELECT * FROM users WHERE login=:login AND password=:password OR email=:email AND password=:password
#201 #579807
>>579805

Не страдай дурью и просто используй скобки.
#202 #579809
>>579801

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


Вот я об этом, да.
#203 #579814
>>579801

>Опять же тут можно использовать блокировку: при проверке наличия пользователя в базе блокировать эту запись до конца транзакции.


То есть, второй запрос будет отклонён, так как транзакция не завершена? А если я хочу, чтоб СУБД подождала, пока завершится транзакция, и тут же обновила данные таблицы вторым запросом?
#204 #579816
А ничего если у меня класс валидатор в 107 строк? может на два класса разбить для ентера и регистера?
#205 #579817
Я заметил, что разработчики на других языках программирования, например на Питоне, любят рассказывать какие фракталы и велосипеды изобретают на PHP, и как все хорошо у них.

Но если мы почитаем историю с хабра то мы увидим противоположную картину: просто обычные неучи с завышенным чувством важности: http://habrahabr.ru/post/270799/
#206 #579822
>>579816

Класс в 107 строк это ничего. А вот если там метод в 107 строк то это плохо. если ты туда передаешь $app то это вдвойне плохо. И если в нем ты обращаешься к POST, GET, кукам, то втройне.

>>579814

Нет, не так. Когда первый поток делает SELECT FOR UPDATE, он блокирует строку и второй поток при попытке сделать SELECT будет ждать пока она освободится.

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

----------------

> Как вообще работает транзакция? Можно ли вставить миллион записей одной транзакцией, или оно пишется куда-то (в память, на диск, во временную таблицу), где есть лимит?


Транзакция это изолированный набор изменений, соответствующий принципам ACID:

https://ru.wikipedia.org/wiki/%D0%A2%D1%80%D0%B0%D0%BD%D0%B7%D0%B0%D0%BA%D1%86%D0%B8%D1%8F_(%D0%B8%D0%BD%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B0)
https://ru.wikipedia.org/wiki/ACID

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

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

В реальном мире частью требований можно жертвовать (менять уровень изоляции транзакций) в пользу производительности: https://ru.wikipedia.org/wiki/%D0%A2%D1%80%D0%B0%D0%BD%D0%B7%D0%B0%D0%BA%D1%86%D0%B8%D1%8F_(%D0%B8%D0%BD%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B0)
https://ru.wikipedia.org/wiki/%D0%A3%D1%80%D0%BE%D0%B2%D0%B5%D0%BD%D1%8C_%D0%B8%D0%B7%D0%BE%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D0%BE%D1%81%D1%82%D0%B8_%D1%82%D1%80%D0%B0%D0%BD%D0%B7%D0%B0%D0%BA%D1%86%D0%B8%D0%B9
http://habrahabr.ru/post/135217/

Вопросы по транзакциям любят задавать на собеседованиях. Я считаю это правильно.

Как реализовать изоляцию транзакций и параллельную их работу с минимумом задержек?

В MySQL в InnoDB используется так назваемая мультиверсионность:

https://en.wikipedia.org/wiki/Multiversion_concurrency_control
https://dev.mysql.com/doc/refman/5.0/en/innodb-multi-versioning.html

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

Также, еще одна вещь, которую надо понимать, это то, что MySQL гарантирует сохранность данных после успешного коммита. То есть перед тем как отчитаться что команда COMMIT завершена успешно, mysql сбрасывает данные (данные таблицы, а также изменившиеся индексы) на диск и дожидается от ОС подтверждения что они физически сохранены. Даже если питание выключится, коммит не пропадет (если оно выключится до коммита, то он пропадет, но база останется в согласованном состоянии которое было до коммита, а такого что половина данных записалась, а половина нет, быть не может. Это называется атомарность транзакции).

Соответственно если ты выполняешь запросы по одному, каждый идет отдельной транзакцией и mysql после каждого должна ждать диск. Это неэффективно. Если ты делаешь 100 запросов одной транзакцией, то mysql имеет право накапливать данные в памяти (или писать на диск без подтверждения и без ожидания), а сбросить на диск только в конце транзакции, и это работает быстрее.

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

Возвращаясь к MVCC - там для каждой строчки таблицы добавляется несколько скрытых полей, вроде таймстампа (время добавления) и номера транзакции. При изменениях в таблице (update/delete/insert) исходные данные не удаляются, а просто добавляются новые строчки. При выборке если есть несколько версий строки, по id транзакции и таймстампу выбирается самая новая видимая данному пользователю версия. При коммите новая версия становится видна всем, старая становится неактуальной и специальный фоновый тред очищает такие строки и помечает занимаемое ими место как свободное.

Условно говоря, у нас есть таблица такого вида:

id | text
1 | hello

В InnoDB она хранится с id транзакции которая ее вставила и таймстампом:

txn | timestamp | id | text
1000 | 12:00:00 | 1 | hello

Как мы видим эта строчка вставлена транзакцией 1000, которая (допустим) давно закоммичена.

Допустим 3 пользователя подключенных к базе параллельно открывают 3 транзакции. Первый (транзакция 1001) удаляет строчку (и пока не закоммитил транзакцию), второй (1002) и третий (1003) добавляют вторую строчку.Таблица выглядит так:

txn | timestamp | id | text
1000 | 12:00:00 | 1 | hello
1001 | 13:00:00 | 1 | (deleted)
1002 | 13:00:00 | 2 | world1
1003 | 13:00:00| 3 | world2

Пользователь внутри транзакции видит только закоммиченные чужие изменения, а также все свои. То есть транзакция 1001 видит изменения из закомиченной транзакции 1000 и незакомиченной 1001. Если пользователь сделает SELECT из этой транзакции, то база будет брать только строки транзакций 1000 и 1001, причем если эти строки соответствуют одному id, то база берет самую новую версию.

Транзакция 1001 видит только эти строки:

txn | timestamp | id | text
1000 | 12:00:00 | 1 | hello
1001 | 13:00:00 | 1 | (deleted)

Так как id одинаковый то она берет последнюю версию, которая помечена как удаленная. Больше строк нет потому SELECT вернет 0 строк.

Транзакция 1002 видит только строки от транзакций 1000 и свои, 1002. Транзакция 1003 видит строки от транзакций 1000 и 1003. Что они получат при выборке всех строк, подумай сам.

Допустим теперь транзакции 1002 и 1003 отменяются, а 1001 коммитится. Строки для отмененных транзакций стали неактуальными, и их позже удалит сборщик мусора. А так как 1001 теперь закоммичена то любой пользователь видит эту строку. При выборке он получит такие строки:

txn | timestamp | id | text
1000 | 12:00:00 | 1 | hello
1001 | 13:00:00 | 1 | (deleted)

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

Строка транзакции 1000 после коммита тран. 1001 стала неактуальной, и ее позже удалит сборщик мусора. А также строку 1001 которую после этого нет смысла хранить.

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

... продолжение следует...
#206 #579822
>>579816

Класс в 107 строк это ничего. А вот если там метод в 107 строк то это плохо. если ты туда передаешь $app то это вдвойне плохо. И если в нем ты обращаешься к POST, GET, кукам, то втройне.

>>579814

Нет, не так. Когда первый поток делает SELECT FOR UPDATE, он блокирует строку и второй поток при попытке сделать SELECT будет ждать пока она освободится.

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

----------------

> Как вообще работает транзакция? Можно ли вставить миллион записей одной транзакцией, или оно пишется куда-то (в память, на диск, во временную таблицу), где есть лимит?


Транзакция это изолированный набор изменений, соответствующий принципам ACID:

https://ru.wikipedia.org/wiki/%D0%A2%D1%80%D0%B0%D0%BD%D0%B7%D0%B0%D0%BA%D1%86%D0%B8%D1%8F_(%D0%B8%D0%BD%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B0)
https://ru.wikipedia.org/wiki/ACID

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

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

В реальном мире частью требований можно жертвовать (менять уровень изоляции транзакций) в пользу производительности: https://ru.wikipedia.org/wiki/%D0%A2%D1%80%D0%B0%D0%BD%D0%B7%D0%B0%D0%BA%D1%86%D0%B8%D1%8F_(%D0%B8%D0%BD%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B0)
https://ru.wikipedia.org/wiki/%D0%A3%D1%80%D0%BE%D0%B2%D0%B5%D0%BD%D1%8C_%D0%B8%D0%B7%D0%BE%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D0%BE%D1%81%D1%82%D0%B8_%D1%82%D1%80%D0%B0%D0%BD%D0%B7%D0%B0%D0%BA%D1%86%D0%B8%D0%B9
http://habrahabr.ru/post/135217/

Вопросы по транзакциям любят задавать на собеседованиях. Я считаю это правильно.

Как реализовать изоляцию транзакций и параллельную их работу с минимумом задержек?

В MySQL в InnoDB используется так назваемая мультиверсионность:

https://en.wikipedia.org/wiki/Multiversion_concurrency_control
https://dev.mysql.com/doc/refman/5.0/en/innodb-multi-versioning.html

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

Также, еще одна вещь, которую надо понимать, это то, что MySQL гарантирует сохранность данных после успешного коммита. То есть перед тем как отчитаться что команда COMMIT завершена успешно, mysql сбрасывает данные (данные таблицы, а также изменившиеся индексы) на диск и дожидается от ОС подтверждения что они физически сохранены. Даже если питание выключится, коммит не пропадет (если оно выключится до коммита, то он пропадет, но база останется в согласованном состоянии которое было до коммита, а такого что половина данных записалась, а половина нет, быть не может. Это называется атомарность транзакции).

Соответственно если ты выполняешь запросы по одному, каждый идет отдельной транзакцией и mysql после каждого должна ждать диск. Это неэффективно. Если ты делаешь 100 запросов одной транзакцией, то mysql имеет право накапливать данные в памяти (или писать на диск без подтверждения и без ожидания), а сбросить на диск только в конце транзакции, и это работает быстрее.

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

Возвращаясь к MVCC - там для каждой строчки таблицы добавляется несколько скрытых полей, вроде таймстампа (время добавления) и номера транзакции. При изменениях в таблице (update/delete/insert) исходные данные не удаляются, а просто добавляются новые строчки. При выборке если есть несколько версий строки, по id транзакции и таймстампу выбирается самая новая видимая данному пользователю версия. При коммите новая версия становится видна всем, старая становится неактуальной и специальный фоновый тред очищает такие строки и помечает занимаемое ими место как свободное.

Условно говоря, у нас есть таблица такого вида:

id | text
1 | hello

В InnoDB она хранится с id транзакции которая ее вставила и таймстампом:

txn | timestamp | id | text
1000 | 12:00:00 | 1 | hello

Как мы видим эта строчка вставлена транзакцией 1000, которая (допустим) давно закоммичена.

Допустим 3 пользователя подключенных к базе параллельно открывают 3 транзакции. Первый (транзакция 1001) удаляет строчку (и пока не закоммитил транзакцию), второй (1002) и третий (1003) добавляют вторую строчку.Таблица выглядит так:

txn | timestamp | id | text
1000 | 12:00:00 | 1 | hello
1001 | 13:00:00 | 1 | (deleted)
1002 | 13:00:00 | 2 | world1
1003 | 13:00:00| 3 | world2

Пользователь внутри транзакции видит только закоммиченные чужие изменения, а также все свои. То есть транзакция 1001 видит изменения из закомиченной транзакции 1000 и незакомиченной 1001. Если пользователь сделает SELECT из этой транзакции, то база будет брать только строки транзакций 1000 и 1001, причем если эти строки соответствуют одному id, то база берет самую новую версию.

Транзакция 1001 видит только эти строки:

txn | timestamp | id | text
1000 | 12:00:00 | 1 | hello
1001 | 13:00:00 | 1 | (deleted)

Так как id одинаковый то она берет последнюю версию, которая помечена как удаленная. Больше строк нет потому SELECT вернет 0 строк.

Транзакция 1002 видит только строки от транзакций 1000 и свои, 1002. Транзакция 1003 видит строки от транзакций 1000 и 1003. Что они получат при выборке всех строк, подумай сам.

Допустим теперь транзакции 1002 и 1003 отменяются, а 1001 коммитится. Строки для отмененных транзакций стали неактуальными, и их позже удалит сборщик мусора. А так как 1001 теперь закоммичена то любой пользователь видит эту строку. При выборке он получит такие строки:

txn | timestamp | id | text
1000 | 12:00:00 | 1 | hello
1001 | 13:00:00 | 1 | (deleted)

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

Строка транзакции 1000 после коммита тран. 1001 стала неактуальной, и ее позже удалит сборщик мусора. А также строку 1001 которую после этого нет смысла хранить.

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

... продолжение следует...
#207 #579824
>>579814

... продолжение пасты ...

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

Это позволяет выжать максимум производительности при параллельных операциях с таблицой. А ведь веб приложения как правило много процессные/многопоточные (если ты помнишь), и соответственно параллельно выполняется несколько SQL запросов от разных воркеров. Да и сервера как правило содержат много ядер и чтобы их загрузить нужно много потоков.

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

В redis тоже нет, но там однопоточное приложение (асинхронное) и параллельный доступ к данным невозможен. В MongoDB нету, там блокируется вся коллекция (до версии 3 - блокировалась вообще вся база) на время записи, но там и транзакций нет.

Обрати внимание что речь тут шла о блокировках для модификации данных. MVCC (почти) не требует их наличия. Но MySQL все равно блокирует строки, которые изменяются или удаляются. Это делается для того чтобы 2 транзакции не могли сделать противоречащие изменения (например записать разные значения в одну и ту же строку) и нарушить ACID. MySQL делает блокировки как минимум в таких случаях:

- есть 2 писателя (UPDATE/DELETE) для 1 и той же строки
- есть писатель + читатель (SELECT) для 1 и той же строки

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

https://dev.mysql.com/doc/refman/5.0/en/innodb-transaction-model.html
http://webew.ru/articles/1383.webew

В особо тяжелых слуаях можно словить взаимную блокировку - deadlock:

https://ru.wikipedia.org/wiki/%D0%92%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%B0%D1%8F_%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B0

Например транзакция A хочет апдейтить строку 1, за ней строку 2. Транзакия B хочет апдейтить сначала 2, потом 1. Каждая их них захватит блокировку по одной строке и никогда не получит блокировку по второй. MySQL обнаруживает дедлоки и решает их принудительным откатом одной из транзакций.

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

Подробности о работе и состоянии движка InnoDB можно получить запросом (попробуй это сделать):

SHOW ENGINE InnoDB STATUS\G

Увидеть список соединений и выполняющихся запросов можно командой SHOW FULL PROCESSLIST\G. Убить поток-воркер можно командой KILL 123; (принципы ACID и целостность данных это не нарушит).

Наконец, вернемся к этому вопросу:

> Можно ли вставить миллион записей одной транзакцией, или оно пишется куда-то (в память, на диск, во временную таблицу), где есть лимит?


В InnoDB есть пул страниц (InnoDB buffer pool) в памяти: https://dev.mysql.com/doc/refman/5.5/en/innodb-buffer-pool.html

Размер пула задается в конфиге mysql. В нем хранятся страницы (строки таблиц и куски индексов). При выборке данных mysql читает данные с диска в пул (если их там нет) и в нем уже делает выборку. При записи данные пишутся в пул, а при нехватке места сбрасываются на диск, также они надежно сбрасываются на диск при коммите транзакции.

Потому ответ на твой вопрос: данные пишутся в память пока есть место и на диск. Размер базы ограничен местом на диске, настройками конфига и встроенными ограничениями (вроде того что размер строки ограничен 65536 байтами).

Как ты понимаешь, от объема пула зависит часто ли базе придется обращаться к диску, а диск очень медленный. На серверах БД под пул выделяют 80-90% свободной памяти, также есть мнение что размер пула должен быть не меньше чем размер индексов (и «горячих» данных). Не редкость иметь например 100 Гб пула если на сервере много памяти.

А теперь вопросы для проверки.

1) Выше я написал что когда кто-то записывает данные (например изменяет строку) он должен брать эксклюзивную блокировку на эти данные, и другие не могут к ним обращаться, то есть читать или писать. Почему? Почему MyISAM блокирует таблицу на время апдейта одной строки?

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

2) Почему MVCC позволяет это не делать?

3) Более сложный вопрос, почему InnoDB блокирует строки, хотя MVCC позволяет это не делать? Почему строки блокируются на все время транзакции (а не на время выполнения запроса)? Что будет если не блокировать?

4) И еще, если программа выбирает какие-то данные (SELECT), меняет их и записывает назад в базу (UPDATE), как запретить другим в это время их менять?
#207 #579824
>>579814

... продолжение пасты ...

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

Это позволяет выжать максимум производительности при параллельных операциях с таблицой. А ведь веб приложения как правило много процессные/многопоточные (если ты помнишь), и соответственно параллельно выполняется несколько SQL запросов от разных воркеров. Да и сервера как правило содержат много ядер и чтобы их загрузить нужно много потоков.

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

В redis тоже нет, но там однопоточное приложение (асинхронное) и параллельный доступ к данным невозможен. В MongoDB нету, там блокируется вся коллекция (до версии 3 - блокировалась вообще вся база) на время записи, но там и транзакций нет.

Обрати внимание что речь тут шла о блокировках для модификации данных. MVCC (почти) не требует их наличия. Но MySQL все равно блокирует строки, которые изменяются или удаляются. Это делается для того чтобы 2 транзакции не могли сделать противоречащие изменения (например записать разные значения в одну и ту же строку) и нарушить ACID. MySQL делает блокировки как минимум в таких случаях:

- есть 2 писателя (UPDATE/DELETE) для 1 и той же строки
- есть писатель + читатель (SELECT) для 1 и той же строки

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

https://dev.mysql.com/doc/refman/5.0/en/innodb-transaction-model.html
http://webew.ru/articles/1383.webew

В особо тяжелых слуаях можно словить взаимную блокировку - deadlock:

https://ru.wikipedia.org/wiki/%D0%92%D0%B7%D0%B0%D0%B8%D0%BC%D0%BD%D0%B0%D1%8F_%D0%B1%D0%BB%D0%BE%D0%BA%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B0

Например транзакция A хочет апдейтить строку 1, за ней строку 2. Транзакия B хочет апдейтить сначала 2, потом 1. Каждая их них захватит блокировку по одной строке и никогда не получит блокировку по второй. MySQL обнаруживает дедлоки и решает их принудительным откатом одной из транзакций.

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

Подробности о работе и состоянии движка InnoDB можно получить запросом (попробуй это сделать):

SHOW ENGINE InnoDB STATUS\G

Увидеть список соединений и выполняющихся запросов можно командой SHOW FULL PROCESSLIST\G. Убить поток-воркер можно командой KILL 123; (принципы ACID и целостность данных это не нарушит).

Наконец, вернемся к этому вопросу:

> Можно ли вставить миллион записей одной транзакцией, или оно пишется куда-то (в память, на диск, во временную таблицу), где есть лимит?


В InnoDB есть пул страниц (InnoDB buffer pool) в памяти: https://dev.mysql.com/doc/refman/5.5/en/innodb-buffer-pool.html

Размер пула задается в конфиге mysql. В нем хранятся страницы (строки таблиц и куски индексов). При выборке данных mysql читает данные с диска в пул (если их там нет) и в нем уже делает выборку. При записи данные пишутся в пул, а при нехватке места сбрасываются на диск, также они надежно сбрасываются на диск при коммите транзакции.

Потому ответ на твой вопрос: данные пишутся в память пока есть место и на диск. Размер базы ограничен местом на диске, настройками конфига и встроенными ограничениями (вроде того что размер строки ограничен 65536 байтами).

Как ты понимаешь, от объема пула зависит часто ли базе придется обращаться к диску, а диск очень медленный. На серверах БД под пул выделяют 80-90% свободной памяти, также есть мнение что размер пула должен быть не меньше чем размер индексов (и «горячих» данных). Не редкость иметь например 100 Гб пула если на сервере много памяти.

А теперь вопросы для проверки.

1) Выше я написал что когда кто-то записывает данные (например изменяет строку) он должен брать эксклюзивную блокировку на эти данные, и другие не могут к ним обращаться, то есть читать или писать. Почему? Почему MyISAM блокирует таблицу на время апдейта одной строки?

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

2) Почему MVCC позволяет это не делать?

3) Более сложный вопрос, почему InnoDB блокирует строки, хотя MVCC позволяет это не делать? Почему строки блокируются на все время транзакции (а не на время выполнения запроса)? Что будет если не блокировать?

4) И еще, если программа выбирает какие-то данные (SELECT), меняет их и записывает назад в базу (UPDATE), как запретить другим в это время их менять?
#208 #579826
>>579822
>>579824
Спасибо за пасту, попробую разобраться.
#209 #579831
>>579822

>Вопросы по транзакциям любят задавать на собеседованиях.


Даже на джуниорских?
#210 #579832

> $app то это вдвойне плохо. И если в нем ты обращаешься к POST, GET, кукам, то втройне.



Именно так я и делаю, а что здесь плохого? Мониторишь мой комп что ли?
#211 #579833
Нет, ну а что, передавать пост в классы, где они обрабатываются - это удобно, и ап тоже. А как тогда контроллеры сокращать! Будет лапша в контроллерах, зря я что ли классы по всем правила ООП городил.
7 Кб, 192x200
#212 #579851
Антоши, как провести совместную валидацию в Yii2 в rules для двух параметров?

Например, у меня есть х и у, каждый из них провалидирован отдельно, но надо добавить, чтобы, проверялось условие х+у<5, как это сделать?
#213 #579862
>>579851
Прочитай сначала документацию, там все это описано (ответ на этот вопрос в частности в главе validating input). От документации никуда не денешься, иначе подобные вопросы будут возникать снова и снова.
Если есть проблемы с английским, то есть сайт memrise.com, где очень быстро можно поднять скилл, 3-4 тысяч слов хватит чтобы читать доки, за пару месяцев можно подтянуть.
7 Кб, 940x778
#215 #579868
>>579862
>>579863
Я читал это, но во всех примерах там проверяется один атрибут, как два пропихнуть в функцию-валидатор?
sage #216 #579876
>>579868
Значит ты читал невнимательно. Перечитай еще раз.

Даже сажу поставлю в знак порицания.
#217 #579891
Как в CSS на одном и том же месте разместить два дива? Например я хочу сделать так что бы при наведении мыши на див он немного приподымался при помощи transform а в том месте где он приподнялся было бы видно другой див, например с текстом или с какими-нибудь иконками.
#218 #579918
>>579891
Ты можешь следующий див переместить на место первого. Допустим редактируя параметр margin
#219 #579955
>>579634

> Не знаю, попробуй для начала погуглить «API для отправки писем» и посмотреть что найдется.


Пока что mailgun нашел, 10к в месяц бесплатно, цены вроде ок.

>Там еще нужно настраивать все, чтобы твои письма не попадали в спам.


Они и сейчас попадают, вот мне хостинг и посоветовал отдельный серв под это дело поднять.
#220 #579969
>>579727
Про баг-трекинг прокомментируйте, если там есть какие-то нюансы, которые я самостоятельно не нагуглю.
А еще что такое "code review"? Просто периодическая ручная проверка того что успели накидать в репозиторий, или может к этому делу тоже серьезно подходят, не знаю, какие-нибудь спец.инструменты для автоматической проверки или что-то в этом роде.
#221 #579970
Господа, помогите с задачей, я вроде написал, но выдает ошибки.
дано трех значное число, нужно сравнить все символы числа и вывести ответ: они одинаковые или нет. то есть, число 111 - удовлетворяет задаче, число 283 - нет, т.к. два все числа друг от друга отличаются. что-то я ни хрена не пойму.
сделал так: разбил число на массив и начал попарно сравнивать числа, если совпадает - то правильно, не совпадает - неправильно. число взял случайное
https://ideone.com/C54bym
#222 #579972
>>579970
а, разобрался, там лишняя скобочка была {
19 Кб, 400x308
#223 #579975
>>579970
Мы не господа, господа все в /b/.

Приведи к строке, затем substr_count для первого символа сравни с длиной строки.
86 Кб, 1914x907
#224 #580001
>>579972
не одна
14 Кб, 184x332
#225 #580003
>>579640

> Если это да/нет то надо использовать TINYINT(1) NOT NULL


Но ведь туда можно, например, 3 поставить, разве нет? До 127. Тоже не понял почему, вчера точно запомнил, что для tinyint(1) 255 ставилось, сейчас 127.

> Неверно, BOOL это синоним для TINYINT(1)


Я bool не мог найти, сменил тип поля через sql запрос (в том же админере) на bool, посмотрел какой тип у поля стал, увидел binary. Но это я ошибся в запросе (хотя админер написал, что запрос выполнен успешно), потому что сейчас получилось, сменил sql запросом на bool, поставился tinyint(1).

> покажи SHOW CREATE TABLE


`status` binary(1) NOT NULL DEFAULT '0',

> Это вряд ли


В консоли заселектил, значение поля записи binary = 0. Но в админере всё равно 30 показывает. Версия админера 4.2.1, актуальная вроде.

> > По ssh не всегда доступ есть,


> Это плохо


А я думал обычное дело. По фтп-то не всегда дают.

> > если есть 7 двоичных.


> Напиши какие конкретно. Я думаю ты что-то путаешь.


Ну в админере в смысле на выбор 7 даются. На него полагаться не надо, понял, буду читать документации.
#226 #580015
>>579750

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


>Кто где работает, отпишитесь как у вас с этим дела. Сколько человек в комнате и насколько буйные.


Я нервно прохихикал с этого пункта. В комнате не буйные, а вот куча манагеров ебущих мозг в скайпе по куче задач с криками СРОЧНО СРОЧНО, уведомления по почте по этим задачам, постоянные письма от клиента с другими задачами, запросы от его отдела по работе с их клиентами, сигналы начальника при каждом чихе клиента (видел? тебе письмо написали - серьезно?), мимокрокодилы, заглядывающие в офис (гыгыгы, интересное название компании, чем это вы занимаетесь, а где тут туалет), куча мороки из-за технологии разработки (гит/меркуриал? забудь) - всё это кладёт крест на моём спокойствии. А потом ещё и пританцовывает на нём.
#227 #580026
>>578910
Нет, запрещать роботу индексировать страницы я не хочу, это наверное плохо для сео.
Мне бы сделать так, чтобы можно было проверить, не является ли посетитель поисковым ботом, и только тогда засчитывать посещение.
Но я думаю, что боты не так часто ходят по страницам, чтобы набить кучу лишних визитов, так что ладно.

>Мне нравится низкоуровневый адаптер. Он проще в реализации и логика работы с редисом остается в 1 экземпляре в VC, а не копируется в каждый адаптер.


Я же с самого начала так сделал. Ладно, вернул все обратно.

Не помогло заполнение полей description и license, по прежнему не работает автозагрузка.
Не подгружает композер классы из этого пакета.
json пустого проекта, к которому я пытаюсь подключить это дело http://pastebin.com/SzaZsXiF
В index.php создаю объект редиски, тут нет ошибки. На следующей строке должен быть мой класс VisitCounter\Redis\RediskaAdapter($rediska), пишет class not found.

>DbAdapter необязательный? Странно конечно. Ведь вызов moveToDb может упасть с ошибкой.


Ну смотри. Api этой библиотеки имеет всего два публичных метода: VisitCounter::countVisit($pageID, $userIP) и VisitCounter::moveToDb(). Первый метод только "засчитывает" посещение, то есть проверяет, есть ли ключ вида "prefix:id:ip". Если нет, создает его и добавляет ip в очередь. Никакая бд на этом этапе не уперлась.
Этот метод вызывается при каждом посещении страницы.

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

Так вот, как быть? Первый метод не требует подключения к базе, так зачем нам заставлять создавать подключение и передавать его в наш адаптер, если оно не нужно?
А во втором случае оно необходимо, да. Пользователь библиотеки обязан после создания объекта еще дернуть сеттер.
Короче я наверное допишу параметр для конструктора с null по умолчанию, и чтобы проверялось при вызове метода moveToDb.

> considerVisit


> Придирка: consider значит «рассматривать, иметь в виду», лучше наверно написать countVisit


Гуглотранслейт говорит обратное. Второе значение "учитывать". Count в моем понимании это все-таки "считать".

>Почему окугление вниз? Что если длина очередь меньше размера транзакции?


Я же потом обрабатываю остаточек от деления, наверное это тогда еще не было закоммичено.

>DbAdapter


>Непонятно зачем тут этот конструктор.


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

> IN ({$pageList})";


> Нужно экранирование или проверка на то что это числа.


Это же склеенный массив айдишников, как там могут оказаться не числа?

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

Я польщен конечно, что ты считаешь меня прошаренным, но есть еще много пробелов. Я плохо знаю jquery да и вообще js. Тут нет сложностей, просто надо сесть и подучить.
Привести в порядок те проекты что уже есть, у меня их целых два, это файлообменник и сайт объявлений.
#227 #580026
>>578910
Нет, запрещать роботу индексировать страницы я не хочу, это наверное плохо для сео.
Мне бы сделать так, чтобы можно было проверить, не является ли посетитель поисковым ботом, и только тогда засчитывать посещение.
Но я думаю, что боты не так часто ходят по страницам, чтобы набить кучу лишних визитов, так что ладно.

>Мне нравится низкоуровневый адаптер. Он проще в реализации и логика работы с редисом остается в 1 экземпляре в VC, а не копируется в каждый адаптер.


Я же с самого начала так сделал. Ладно, вернул все обратно.

Не помогло заполнение полей description и license, по прежнему не работает автозагрузка.
Не подгружает композер классы из этого пакета.
json пустого проекта, к которому я пытаюсь подключить это дело http://pastebin.com/SzaZsXiF
В index.php создаю объект редиски, тут нет ошибки. На следующей строке должен быть мой класс VisitCounter\Redis\RediskaAdapter($rediska), пишет class not found.

>DbAdapter необязательный? Странно конечно. Ведь вызов moveToDb может упасть с ошибкой.


Ну смотри. Api этой библиотеки имеет всего два публичных метода: VisitCounter::countVisit($pageID, $userIP) и VisitCounter::moveToDb(). Первый метод только "засчитывает" посещение, то есть проверяет, есть ли ключ вида "prefix:id:ip". Если нет, создает его и добавляет ip в очередь. Никакая бд на этом этапе не уперлась.
Этот метод вызывается при каждом посещении страницы.

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

Так вот, как быть? Первый метод не требует подключения к базе, так зачем нам заставлять создавать подключение и передавать его в наш адаптер, если оно не нужно?
А во втором случае оно необходимо, да. Пользователь библиотеки обязан после создания объекта еще дернуть сеттер.
Короче я наверное допишу параметр для конструктора с null по умолчанию, и чтобы проверялось при вызове метода moveToDb.

> considerVisit


> Придирка: consider значит «рассматривать, иметь в виду», лучше наверно написать countVisit


Гуглотранслейт говорит обратное. Второе значение "учитывать". Count в моем понимании это все-таки "считать".

>Почему окугление вниз? Что если длина очередь меньше размера транзакции?


Я же потом обрабатываю остаточек от деления, наверное это тогда еще не было закоммичено.

>DbAdapter


>Непонятно зачем тут этот конструктор.


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

> IN ({$pageList})";


> Нужно экранирование или проверка на то что это числа.


Это же склеенный массив айдишников, как там могут оказаться не числа?

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

Я польщен конечно, что ты считаешь меня прошаренным, но есть еще много пробелов. Я плохо знаю jquery да и вообще js. Тут нет сложностей, просто надо сесть и подучить.
Привести в порядок те проекты что уже есть, у меня их целых два, это файлообменник и сайт объявлений.
#228 #580031
>>580003
енум, ставишь значения 0 или 1. По умолчанию ноль. При отмечании чего-то там = 1. Что неясно? Откуда у тебя там 30 вообще? Хоспаде ты ведь еще и работаешь где-то такой тупой.
Аноним #229 #580034
Вопрос близкий к пэ аш пэ. Что писать? Чем вы свои личные гиты наполняете? Хочется написать что-то не совсем бесполезное и не написанное уже по сто раз. Допустим, моего левела хватает чтоб написать с нуля фреймворк, форум, магазин, вот это всё. Но врядли хватит на что-то сильно продвинутое, типо хайлоадов, или каких-то <i>сложных</i> крудов с одной только декларацией бд на метр допустим (имею слабое представление правда, насколько на самом деле сложно делать грамотные транзакции, всё такое), но скорее тупо из-за малой заинтересованности.

Какое-то время назад один человек подкинул "оригинальную идею" накидать что-то типо веб-конструктора ксс+хтмл, я посмотрел как можно легко это сделать, прошел стадию proof-of-concept, в итоге понял что сделать его удобнее чем ручную запись кода в лесс+жейд не возможно по умолчанию.

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

Хуй знает что делать кароче, вроде хочется что-то делать, но от всего воротит, или не достаточно интересно чтобы удержать стимул, либо наоборот, требует гораздо больше знаний, опыта и ресурсов, чем те, которыми я распалагаю. Нахуй пишу это все - всё равно у этой проблемы решения нет потому что ты пидор ХЕХ%%.
#230 #580046
>>580031
У тебя синдром дефицита внимания?
#231 #580051
>>580046
да, поставь цифры в енум и съеби из треда, КОЛЛЕГА. здесь пхп обсуждают, а не психотерапия для даунов.
#232 #580053
>>580051
Тогда что ты здесь делаешь?
35 Кб, 560x587
#233 #580138
Это самое, ОП, я не понял, как делать задачку из твоего гайда, вот эту вот. Дай подсказку, что-ли.
#234 #580141
Хочу начать дрочить более-менее серьёзный фреймворк, что интереснее - Yii2 или Laravel4? Сам склоняюсь ко второму, ибо он основан на компонентах Symfony, а значит, будет потом проще вникать в него.
#235 #580142
>>580141

>Laravel4


Laravel5.

fix
#236 #580167
Не совсем понимаю, как реализовать такую вещь при помощи шаблонизатора. Мне нужно, чтобы вместе с $row в цикле выводились элементы разметки. Если делаю шаблонизатор при помощи str_replace, не выводится разметка
#237 #580168
>>580167
<?php
include 'connect.php';
$sql = "SELECT * FROM `cash` WHERE `categories_id`=1";
$query=$mysqli->query($sql);
while ($row=mysqli_fetch_assoc($query)) {

echo '<div class="col-lg-4 col-md-6"><div class="thumbnail">'.$row['img'].'<div class="caption"><p><span class="glyphicon glyphicon-list"></span> Артикул&nbsp'.$row['articul'].'</p><p> <span class="glyphicon glyphicon glyphicon-align-center"></span> Материал&nbsp'.$row['material'].'</p><p><span class="glyphicon glyphicon glyphicon-list-alt"></span> Состав 100% хлопок </p><p> <span class="glyphicon glyphicon glyphicon-resize-full"></span> Размер&nbsp'.$row['size'].'<p><span class="sp5"></span> Старая цена&nbsp'.$row['old_price'].'</p><p><span class="glyphicon glyphicon glyphicon-bookmark"></span> Новая цена&nbsp'.$row['price'].'рублей'.'</p><p><a href="#" class="btn btn-primary btna" role="button">Заказать</a> <a href="#" class="btn btn-default btn2" role="button">Подробнее</a></p></div></div></div>';

} Вот код с разметкой, как сделать, чтобы и дивы выходили?
Делаю как-то так
<?php
require_once('smarty-3.1.27/libs/Smarty.class.php');
include 'connect.php';

$smarty = new Smarty();
$smarty->template_dir = 'view';
$smarty->compile_dir = 'tmp';

$sql = "SELECT articul FROM cash";
$query = $mysqli->query($sql);

$array = array();

while ($row = mysqli_fetch_array($query)) {
array_push($array, $row);
}
$smarty->assign('articul', $array);
$smarty->display("template.tpl");

?> Но при этом элементы разметки надо писать по 5 раз. Как избавиться?
#237 #580168
>>580167
<?php
include 'connect.php';
$sql = "SELECT * FROM `cash` WHERE `categories_id`=1";
$query=$mysqli->query($sql);
while ($row=mysqli_fetch_assoc($query)) {

echo '<div class="col-lg-4 col-md-6"><div class="thumbnail">'.$row['img'].'<div class="caption"><p><span class="glyphicon glyphicon-list"></span> Артикул&nbsp'.$row['articul'].'</p><p> <span class="glyphicon glyphicon glyphicon-align-center"></span> Материал&nbsp'.$row['material'].'</p><p><span class="glyphicon glyphicon glyphicon-list-alt"></span> Состав 100% хлопок </p><p> <span class="glyphicon glyphicon glyphicon-resize-full"></span> Размер&nbsp'.$row['size'].'<p><span class="sp5"></span> Старая цена&nbsp'.$row['old_price'].'</p><p><span class="glyphicon glyphicon glyphicon-bookmark"></span> Новая цена&nbsp'.$row['price'].'рублей'.'</p><p><a href="#" class="btn btn-primary btna" role="button">Заказать</a> <a href="#" class="btn btn-default btn2" role="button">Подробнее</a></p></div></div></div>';

} Вот код с разметкой, как сделать, чтобы и дивы выходили?
Делаю как-то так
<?php
require_once('smarty-3.1.27/libs/Smarty.class.php');
include 'connect.php';

$smarty = new Smarty();
$smarty->template_dir = 'view';
$smarty->compile_dir = 'tmp';

$sql = "SELECT articul FROM cash";
$query = $mysqli->query($sql);

$array = array();

while ($row = mysqli_fetch_array($query)) {
array_push($array, $row);
}
$smarty->assign('articul', $array);
$smarty->display("template.tpl");

?> Но при этом элементы разметки надо писать по 5 раз. Как избавиться?
352 Кб, 1262x2422
someApprentice #238 #580175
>>576499

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


Тогда мы сделаем чтобы эта оценочная функция выбирала случайный ход из всех возможных ходов. Да, этот метод нужен всем животным, потому что именно он определяет их поведение. К тому же в одном из тредов ты сам настаивал на этом.


пруф: >>556079

>Теперь по поводу алгоритма выбора хода. Он состоит из нескольких частей:



>1. Получить список возможных ходов


>2. Оценить каждый с помощью оценочной функции


>3. Выбрать лучший


>4. Выполнить его



>Тут есть общие для всех животных, а есть разные части. Что у каждого животного свое? Очевидно, оценочная функция (каждое животное имеет свои интересы), получение списка ходов (так как ходят они по-разному). Также в 4-м пункте может быть разница в том, что кошки едят мышек, а мышки только ходят.



>Ну а сама последовательность этих 4 действий общая для всех.



>Потому очевидно функции должны быть размещены по классам так:



>- алгоритм выполнения хода из 4 шагов, функция выбора лучшего хода - можно в классе Animal


>- получение списка ходов, оценочная функция, выполнение хода - в классах соответствующих животных.





>>576499

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


Думаю следует оставить методы:
-полученияКоординат()
-полученияСкорости()
-полученияОбзора()
-полученияСимвола()
-движения()
-смерти()

Остальные делать защищенными.

Один вопрос: В каком порядке должны идти абстрактные, публичные и защищенные методы? Сначала абстрактные или публичные?

>>576499

>> public function isItNotOneOfTrack($x, $y, $tracks) {


>1) имя запутанное. Почему нельзя сделать функцию isOneOfTrack, у которой более короткое и понятное название?


>2) функция возвращает либо false либо объект. Но функции is... обычно возвращают true/false.


Почему-то если в этой функции за место $object поставить true или поменять местами false/$object(true), чтобы можно было переименовать функцию на isOneOfTrack и потом проверять в условии с помощью !isOneOfTrack, то программа начинает вести себя странно: Кошки через всю карту попадают в угл, а затем исчезают пикрелейтед. Мне кажется это очень странным, и я решил не тратить силы на выяснение причин. Наверно мне стоит это выяснить.

>>576499

>> abstract function rateMoves($moves, $search);


>Почему так запутанно? В моем понимании функция оценки берет на вход координаты клеточки и возвращает оценку. Просто и понятно. А что принимает эта функция? Массив ходов и какой-то непонятный массив search. Тебе не кажется что это как-то сложнее получается? Ради чего усложняем функцию?


>В моем понимании функция оценки берет на вход координаты клеточки и возвращает оценку.


Такая функция есть - называется rateMove($x, $y, $search) https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/Cat.php#L35
Правда избавиться от $search не получилось, но он нужен чтобы оценивать ход опираясь на искомое животное.

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

>>576499

>Наконец еще можно при съедении животного сразу делать $world->remove... то есть обращаться не к животному, а к миру.


Такое уже есть https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/Animal.php#L172

>>576499

>> if (($forX > $x and $forY > $y) or ($forX > $x and $forY < $y)


>Не понимаю что и зачем тут проверяется


Чтобы мышка пропускала ходы по диагонали.
352 Кб, 1262x2422
someApprentice #238 #580175
>>576499

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


Тогда мы сделаем чтобы эта оценочная функция выбирала случайный ход из всех возможных ходов. Да, этот метод нужен всем животным, потому что именно он определяет их поведение. К тому же в одном из тредов ты сам настаивал на этом.


пруф: >>556079

>Теперь по поводу алгоритма выбора хода. Он состоит из нескольких частей:



>1. Получить список возможных ходов


>2. Оценить каждый с помощью оценочной функции


>3. Выбрать лучший


>4. Выполнить его



>Тут есть общие для всех животных, а есть разные части. Что у каждого животного свое? Очевидно, оценочная функция (каждое животное имеет свои интересы), получение списка ходов (так как ходят они по-разному). Также в 4-м пункте может быть разница в том, что кошки едят мышек, а мышки только ходят.



>Ну а сама последовательность этих 4 действий общая для всех.



>Потому очевидно функции должны быть размещены по классам так:



>- алгоритм выполнения хода из 4 шагов, функция выбора лучшего хода - можно в классе Animal


>- получение списка ходов, оценочная функция, выполнение хода - в классах соответствующих животных.





>>576499

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


Думаю следует оставить методы:
-полученияКоординат()
-полученияСкорости()
-полученияОбзора()
-полученияСимвола()
-движения()
-смерти()

Остальные делать защищенными.

Один вопрос: В каком порядке должны идти абстрактные, публичные и защищенные методы? Сначала абстрактные или публичные?

>>576499

>> public function isItNotOneOfTrack($x, $y, $tracks) {


>1) имя запутанное. Почему нельзя сделать функцию isOneOfTrack, у которой более короткое и понятное название?


>2) функция возвращает либо false либо объект. Но функции is... обычно возвращают true/false.


Почему-то если в этой функции за место $object поставить true или поменять местами false/$object(true), чтобы можно было переименовать функцию на isOneOfTrack и потом проверять в условии с помощью !isOneOfTrack, то программа начинает вести себя странно: Кошки через всю карту попадают в угл, а затем исчезают пикрелейтед. Мне кажется это очень странным, и я решил не тратить силы на выяснение причин. Наверно мне стоит это выяснить.

>>576499

>> abstract function rateMoves($moves, $search);


>Почему так запутанно? В моем понимании функция оценки берет на вход координаты клеточки и возвращает оценку. Просто и понятно. А что принимает эта функция? Массив ходов и какой-то непонятный массив search. Тебе не кажется что это как-то сложнее получается? Ради чего усложняем функцию?


>В моем понимании функция оценки берет на вход координаты клеточки и возвращает оценку.


Такая функция есть - называется rateMove($x, $y, $search) https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/Cat.php#L35
Правда избавиться от $search не получилось, но он нужен чтобы оценивать ход опираясь на искомое животное.

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

>>576499

>Наконец еще можно при съедении животного сразу делать $world->remove... то есть обращаться не к животному, а к миру.


Такое уже есть https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/Animal.php#L172

>>576499

>> if (($forX > $x and $forY > $y) or ($forX > $x and $forY < $y)


>Не понимаю что и зачем тут проверяется


Чтобы мышка пропускала ходы по диагонали.
#239 #580176
>>580141
эскобар.жпг жи. Лично мне больше нравится йии2. Но кто-то угорает по ларавелю. А по работе скорее всего встретишься с обоими и разных версий.
#240 #580180
>>580176

>Лично мне больше нравится йии2.


А почему, можешь сказать?
31 Кб, 532x219
#241 #580244
>>578124 (OP)
Мужики,сколько месяцев примерно у меня уйдёт на изучение этого вашего пэхапэ, если заниматься часов по 4-5 в день,прежде чем я смогу,сам,запилить нормальный сайт.
16 Кб, 351x222
#242 #580246
>>580244
Забыл сказать что обладаю очень хорошим знанием англ. яз. хз важно это аль нет.
#243 #580366
>>580244

Первая задача, в которой мы делаем сайт - это задача про список студентов из Оп поста. Чтобы до нее дойти, надо пройти учебник PHP, узнать основы SQL, выучить основы верстки (HTML/CSS). Я бы ориентировался месяца на 2-4 в зависимости от твоего трудолюбия.

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

>>580175

Обычно порядок определений в классе такой:

- константы
- поля
- конструктор
- абстрактные методы
- публичные методы
- защищенные методы

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

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

> Почему-то если в этой функции за место $object поставить true или поменять местами false/$object(true), чтобы можно было переименовать функцию на isOneOfTrack....


Значит ты где-то сделал ошибку в логике. Может быть там мало поменять местами true/false, надо еще if в другое место переставить или что-то еще. Надо выяснить и сделать нормально.

Для проверки ты можешь натыкать echo и смотреть что приходит в функцию и что она возвращает и какой из ифов срабатывает.

> Правда избавиться от $search не получилось


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

>>Не понимаю что и зачем тут проверяется


> Чтобы мышка пропускала ходы по диагонали.


Я не смог догадаться, а значит и другию люди запутаются. В таких случаях надо как минимум писать комментарий, или делать переменные вида $isDiagonalMove.

Ну и проверку можно (нужно) было сделать проще:

$isStraightMove = ($x == $forx || $y == $forY);
....
#243 #580366
>>580244

Первая задача, в которой мы делаем сайт - это задача про список студентов из Оп поста. Чтобы до нее дойти, надо пройти учебник PHP, узнать основы SQL, выучить основы верстки (HTML/CSS). Я бы ориентировался месяца на 2-4 в зависимости от твоего трудолюбия.

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

>>580175

Обычно порядок определений в классе такой:

- константы
- поля
- конструктор
- абстрактные методы
- публичные методы
- защищенные методы

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

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

> Почему-то если в этой функции за место $object поставить true или поменять местами false/$object(true), чтобы можно было переименовать функцию на isOneOfTrack....


Значит ты где-то сделал ошибку в логике. Может быть там мало поменять местами true/false, надо еще if в другое место переставить или что-то еще. Надо выяснить и сделать нормально.

Для проверки ты можешь натыкать echo и смотреть что приходит в функцию и что она возвращает и какой из ифов срабатывает.

> Правда избавиться от $search не получилось


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

>>Не понимаю что и зачем тут проверяется


> Чтобы мышка пропускала ходы по диагонали.


Я не смог догадаться, а значит и другию люди запутаются. В таких случаях надо как минимум писать комментарий, или делать переменные вида $isDiagonalMove.

Ну и проверку можно (нужно) было сделать проще:

$isStraightMove = ($x == $forx || $y == $forY);
....
#244 #580369
>>579354
Отключение дебаг-режима и кеширование схемы бд почти не дало эффекта (5-6%, хотя это тоже неплохо для начала).
Результаты тестов: http://pastebin.com/DpJPT3Yq

>Нужно выбрать движок кеша (не наугад, а сравнив плюсы и минусы)


В yii следующие виды кешей:
CMemCache - зачем мне мемкеш, если у меня уже крутится редис?
CApcCache, CXCache, CEAcceleratorCache - не нужны, уже есть opcache
CFileCache - возможно пригодится для хранения страниц или кусков шаблона
Я кстати не понял, а можно ли одновременно использовать несколько кешей? Наверное, нужно их как-то объявить компонентами, как это сделано в библиотеке eavActiveRecord, где есть свой отдельный eavcache. Ладно, попробую разобраться.
CDbCache - сомнительная штука, сохранять кеш в бд наверное выгодно только при определенных требованиях (например обеспечить 100% гарантию, что он проживет положенный срок и не потеряется, как это возможно в memcache), но я смутно представляю, зачем это может потребоваться. Можно еще использовать простой sqlite для этого типа кеша, но спрашивается зачем, если есть файловый кеш?
CZendDataCache, CWinCache - не знаю что это такое и в чем преимущества данных штуковин перед перечисленными выше.
Ну и собственно CRedisCache.

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

>надо предусмотреть способ очистки кеша, когда схема БД меняется


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

>CDummyCache


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


Да это обычная пустышка для дебага, чтобы при отключенном кеше обращение к нему не роняло приложение.

>>579639

>Может быть в выпадающем списке много значений?


О, я кстати про него почему-то забыл. Но нет, не в нем дело. Там два списка для регионов и для городов (по хорошему надо будет заменить на select2). Загружается только список регионов для России, это всего 78 штук. Города для данного региона подгружаются аяксом при выборе оного.

>так как файлов нет на диске, Апач их не может отдать, и вызвает фреймворк


Это еще с какого перепуга? Не понимаю. Идет обращение к файлу-картинке, его нет. Ну так пусть апач скажет 404 и до свидания. А, это наверное из-за mod_rewrite. Там стоит стандартное
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php
Это значит, что даже если какой-то ресурс (скажем стиль или скрипт) не найден, то каждый раз будет вызываться index.php? Наверное надо поправить rewrite cond, чтобы там игнорились папки с ресурсами.

>Кстати и JS/CSS файлы что-то медленно грузятся. Посмотри по заголовкам, они при участии или без участия PHP отдаются?


На какой конкретно заголовок смотреть-то?
Server:Apache/2.4.7 (Ubuntu)
Но то же самое пишется и для отсутствующих картинок.

Ну ладно, я думаю с настройками более-менее понятно, как кешировать разобрались, теперь нужно решить что кешировать.
#244 #580369
>>579354
Отключение дебаг-режима и кеширование схемы бд почти не дало эффекта (5-6%, хотя это тоже неплохо для начала).
Результаты тестов: http://pastebin.com/DpJPT3Yq

>Нужно выбрать движок кеша (не наугад, а сравнив плюсы и минусы)


В yii следующие виды кешей:
CMemCache - зачем мне мемкеш, если у меня уже крутится редис?
CApcCache, CXCache, CEAcceleratorCache - не нужны, уже есть opcache
CFileCache - возможно пригодится для хранения страниц или кусков шаблона
Я кстати не понял, а можно ли одновременно использовать несколько кешей? Наверное, нужно их как-то объявить компонентами, как это сделано в библиотеке eavActiveRecord, где есть свой отдельный eavcache. Ладно, попробую разобраться.
CDbCache - сомнительная штука, сохранять кеш в бд наверное выгодно только при определенных требованиях (например обеспечить 100% гарантию, что он проживет положенный срок и не потеряется, как это возможно в memcache), но я смутно представляю, зачем это может потребоваться. Можно еще использовать простой sqlite для этого типа кеша, но спрашивается зачем, если есть файловый кеш?
CZendDataCache, CWinCache - не знаю что это такое и в чем преимущества данных штуковин перед перечисленными выше.
Ну и собственно CRedisCache.

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

>надо предусмотреть способ очистки кеша, когда схема БД меняется


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

>CDummyCache


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


Да это обычная пустышка для дебага, чтобы при отключенном кеше обращение к нему не роняло приложение.

>>579639

>Может быть в выпадающем списке много значений?


О, я кстати про него почему-то забыл. Но нет, не в нем дело. Там два списка для регионов и для городов (по хорошему надо будет заменить на select2). Загружается только список регионов для России, это всего 78 штук. Города для данного региона подгружаются аяксом при выборе оного.

>так как файлов нет на диске, Апач их не может отдать, и вызвает фреймворк


Это еще с какого перепуга? Не понимаю. Идет обращение к файлу-картинке, его нет. Ну так пусть апач скажет 404 и до свидания. А, это наверное из-за mod_rewrite. Там стоит стандартное
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php
Это значит, что даже если какой-то ресурс (скажем стиль или скрипт) не найден, то каждый раз будет вызываться index.php? Наверное надо поправить rewrite cond, чтобы там игнорились папки с ресурсами.

>Кстати и JS/CSS файлы что-то медленно грузятся. Посмотри по заголовкам, они при участии или без участия PHP отдаются?


На какой конкретно заголовок смотреть-то?
Server:Apache/2.4.7 (Ubuntu)
Но то же самое пишется и для отсутствующих картинок.

Ну ладно, я думаю с настройками более-менее понятно, как кешировать разобрались, теперь нужно решить что кешировать.
#245 #580376
Стоит ли использовать шаблонизатор Smarty, или он устарел? Мне нужно дивы в цикле вывести, и закрывающие тоже. Но тогда выходит, что шаблонизатор -- лишнее
#246 #580381
Такой вопрос, при разлогинивании пользователя кука удаляется на сайте или в таблице или и там и там?
#247 #580397
>>580369

> сомнительная штука, сохранять кеш в бд


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

> CApcCache, CXCache, CEAcceleratorCache - не нужны, уже есть opcache


А в opcache есть юзерские ключи? По моему в таких случаях (кеширование в shared памяти) надо APCu ставить, это APC без оп-кешера, только пользовательские ключи.

> а можно ли одновременно использовать несколько кешей?


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

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


но редис персистентный, не будем ли мы зря создавать дисковый трафик ради сохранения ненужных ключей, не увеличим ли мы потребляемый объем памяти и время перезапуска ( = время даунтайма сайта так как редиса-слейва у тебя нету)? Плюс, в редисе как я помню, нет вытеснения ключей при переполнении памяти, а в кеше обычно это желательно.

Если ключей немного и они небольшие, то это конечно не проблема... а если их будет больше?

В общем, я так понимаю, у нас из приемлемых вариантов: redis (персистентный), redis (неперсистентный), memcache, APCu. Попробуй все же сравнить преимущества и недостатки каждого варианта.

> Куски страниц наверное можно складывать в файлы.


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

Подумай сам: ноутбучный диск крутится со скоростью 5400 об/мин = 90 об/сек. Если мы хотим сделать запись в случайный сектор, мы в худшем случае должны ждать полный оборот диска, в среднем полоборота, то есть в среднем 1/90/2 ~ 1/180 мс. Это значит что больше 180 операций случайного доступа в секунду мы в принципе сделать не можем. Также, нам нужно время чтобы переместить головку к нужной дорожке. Это механическая операция, и на практике мы получаем задержку случайного доступа примерно в 10 мс (что в общем-то можно считать инженерным достижением).

Если размер одного секутора 4Кб это дает минимальную скорость записи 400 Кб/сек при случайном доступе.

Потому диск быстро пишет и читает только последовательные данные, например N секторов подряд. Обычно там скорость порядка десятков (или сотен, для хороших серверных дисков) Мб/сек.

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

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

> Кеширование схемы базы (если честно, не понимаю зачем оно вообще нужно)


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

> можно просто установить время жизни кеша около 15 минут, он будет сам обновляться время от времени.


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

> Наверное надо поправить rewrite cond, чтобы там игнорились папки с ресурсами.


Да

> На какой конкретно заголовок смотреть-то?


X-Engine: PHP или как-то так, я не помню, вызови index.php и найди там упоминание php.
#247 #580397
>>580369

> сомнительная штука, сохранять кеш в бд


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

> CApcCache, CXCache, CEAcceleratorCache - не нужны, уже есть opcache


А в opcache есть юзерские ключи? По моему в таких случаях (кеширование в shared памяти) надо APCu ставить, это APC без оп-кешера, только пользовательские ключи.

> а можно ли одновременно использовать несколько кешей?


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

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


но редис персистентный, не будем ли мы зря создавать дисковый трафик ради сохранения ненужных ключей, не увеличим ли мы потребляемый объем памяти и время перезапуска ( = время даунтайма сайта так как редиса-слейва у тебя нету)? Плюс, в редисе как я помню, нет вытеснения ключей при переполнении памяти, а в кеше обычно это желательно.

Если ключей немного и они небольшие, то это конечно не проблема... а если их будет больше?

В общем, я так понимаю, у нас из приемлемых вариантов: redis (персистентный), redis (неперсистентный), memcache, APCu. Попробуй все же сравнить преимущества и недостатки каждого варианта.

> Куски страниц наверное можно складывать в файлы.


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

Подумай сам: ноутбучный диск крутится со скоростью 5400 об/мин = 90 об/сек. Если мы хотим сделать запись в случайный сектор, мы в худшем случае должны ждать полный оборот диска, в среднем полоборота, то есть в среднем 1/90/2 ~ 1/180 мс. Это значит что больше 180 операций случайного доступа в секунду мы в принципе сделать не можем. Также, нам нужно время чтобы переместить головку к нужной дорожке. Это механическая операция, и на практике мы получаем задержку случайного доступа примерно в 10 мс (что в общем-то можно считать инженерным достижением).

Если размер одного секутора 4Кб это дает минимальную скорость записи 400 Кб/сек при случайном доступе.

Потому диск быстро пишет и читает только последовательные данные, например N секторов подряд. Обычно там скорость порядка десятков (или сотен, для хороших серверных дисков) Мб/сек.

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

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

> Кеширование схемы базы (если честно, не понимаю зачем оно вообще нужно)


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

> можно просто установить время жизни кеша около 15 минут, он будет сам обновляться время от времени.


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

> Наверное надо поправить rewrite cond, чтобы там игнорились папки с ресурсами.


Да

> На какой конкретно заголовок смотреть-то?


X-Engine: PHP или как-то так, я не помню, вызови index.php и найди там упоминание php.
#248 #580465
>>580397
У индексного файла заголовок
X-Powered-By:PHP/5.5.9-1ubuntu4.14
Но у стилей и скриптов этого заголовка нет, не знаю в чем дело. Напомню, мы выясняли, почему медленно грузятся ресурсы. Нет, вроде бы их отдает не php, тем более это прописано в htaccess.
По 200 мс грузятся jquery и прочие файлы стилей и скриптов.

>А в opcache есть юзерские ключи?


Нет, но они мне и не нужны. Я же правильно понимаю, что эти вещи (apc, eacelerator) это аналоги opcache для кеширования скомпилированного кода? Пусть оно само сохраняет, я не буду туда руками лезть и выставлять какие-то ключи, здесь это ни к чему.

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


Я пока еще не решил что кешировать, поэтому не знаю. Но судя по всему ключей будет немного, обновляться они будут редко, редис в режиме дозаписи (aof).
Не будет там такого уж страшного трафика.
На главной странице, пик2 >>579284
я думаю очевидно нужно закешировать данные для выпадающего списка регионов, меняется он чуть чаще чем никогда.
А также данные для виджета выбора категорий, они тоже меняются крайне редко.
Собственно и все. Данных немного, редис при правильной настройке пишет на диск не так часто, так что я думаю что вполне подходит хранение кеша в редисе.
В конце концов я не ставлю целью на дохлом ноутбуке поднять полноценный сервер, мне главное разобраться во всех этих технологиях, чтобы потом не было конфузов на работе.

>>580026
Бамп проблеме подключения библиотеки через композер, не получается автозагрузка.
И еще хотелось бы сделать счетчик интерактивным, то есть чтобы можно было не только хранить данные в очереди и периодически сбрасывать в базу, но и выбирать дельту, кол-во посещений, приплюсовывая к данным из базы, чтобы счетчик обновлялся интерактивно.
Это было бы очень легко сделать, если бы у нас была команда типа "взять из списка кол-во повторов указанного значения", но я подобной не наблюдаю. Ничего не могу пока придумать.
#249 #580487
>>580465

> Напомню, мы выясняли, почему медленно грузятся ресурсы. Нет, вроде бы их отдает не php, тем более это прописано в htaccess.


Это странно. Погоняй-ка под ab запрос какого-нибудь статического файла, лучше даже двух: маленький и большой и посмотри нагрузку на CPU/память/диск.

> Я же правильно понимаю, что эти вещи (apc, eacelerator) это аналоги opcache для кеширования скомпилированного кода?


Там обычно 2 раздела: кеш скриптов и кеш пользовательских ключей. Так что их можно использовать как key value хранилище. Для APC есть версия APCu которая содержит только кеш пользовательских ключей и не вмешивается в кешировние скриптов.

> Но судя по всему ключей будет немного


если немного то ок, а если много? Если мы захотим на странице каждого объявления что-то кешировать?

> Собственно и все.


А список последних объявоений?

Также, надо решить на каком уровне мы кешируем:

- выбранные модели
- промежуточные DTo-объекты или о ужас, массивы
- HTML

> Бамп проблеме подключения библиотеки через композер, не получается автозагрузка.


Достаточно вот тут правильно прописать autoload: https://github.com/nsdvw/visit-counter/blob/master/composer.json

Ты прописал? Протестировал (например сделав файл temp.php и из него проверив подгружаются ли классы?)? После того как добавил библиотеку в основной проект, сделал ли composer install или update?

> И еще хотелось бы сделать счетчик интерактивным


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

> если бы у нас была команда типа "взять из списка кол-во повторов указанного значения"


Список не позволяет такого, это неэффективно. Но возможно есть какая-то другая структура которая бы это позволила? Я впрочем не уверен что есть.
#249 #580487
>>580465

> Напомню, мы выясняли, почему медленно грузятся ресурсы. Нет, вроде бы их отдает не php, тем более это прописано в htaccess.


Это странно. Погоняй-ка под ab запрос какого-нибудь статического файла, лучше даже двух: маленький и большой и посмотри нагрузку на CPU/память/диск.

> Я же правильно понимаю, что эти вещи (apc, eacelerator) это аналоги opcache для кеширования скомпилированного кода?


Там обычно 2 раздела: кеш скриптов и кеш пользовательских ключей. Так что их можно использовать как key value хранилище. Для APC есть версия APCu которая содержит только кеш пользовательских ключей и не вмешивается в кешировние скриптов.

> Но судя по всему ключей будет немного


если немного то ок, а если много? Если мы захотим на странице каждого объявления что-то кешировать?

> Собственно и все.


А список последних объявоений?

Также, надо решить на каком уровне мы кешируем:

- выбранные модели
- промежуточные DTo-объекты или о ужас, массивы
- HTML

> Бамп проблеме подключения библиотеки через композер, не получается автозагрузка.


Достаточно вот тут правильно прописать autoload: https://github.com/nsdvw/visit-counter/blob/master/composer.json

Ты прописал? Протестировал (например сделав файл temp.php и из него проверив подгружаются ли классы?)? После того как добавил библиотеку в основной проект, сделал ли composer install или update?

> И еще хотелось бы сделать счетчик интерактивным


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

> если бы у нас была команда типа "взять из списка кол-во повторов указанного значения"


Список не позволяет такого, это неэффективно. Но возможно есть какая-то другая структура которая бы это позволила? Я впрочем не уверен что есть.
10 Кб, 234x208
#250 #580586
Вопрос по множеству элементов: сейчас некоторые части хтмл-кода, у меня генерируются, и многим элементам я автоматически присваиваю идентифкаторы, чтобы яваскрипт быстрее обращался к элементам по ним, да и весьма это удобно.

У меня вопрос: есть ли хоть одна веская причина, почему не стоит давать много идентифкаторов, причём со сложными длинными именами типа "header-widget-form-user-phone"?
#251 #580760
Интересно что в мобильном браузере Хром есть функция «Притвориться десктопным браузером»: http://cnet2.cbsistatic.com/hub/i/r/2012/04/18/2cfaf69c-fdc3-11e2-8c7c-d4ae52e62bcc/resize/370xauto/58ac04429843557aec906a878ee28e17/3.png

Но зачем? Кому в здравом уме захочется смотреть большую неудобную десктопную версию на маленьком экране?

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

Ну и абсурд: придумывать сначала мобильную версию сайта, а затем способ уклонения от попадания на мобильную версию.
#252 #580786

>The Eloquent ORM included with Laravel provides a beautiful, simple ActiveRecord implementation for working with your database.


Что же это за ORM такая, которая provides an ActiveRecord implementation, а не DataMapper implementation?
#253 #580788
>>580760
На планшетах с относительно большой диагональю и разрешением полноценная версия часто выглядит адекватнее, чем мобильная, заточенная под маленький экран телефончика.
someApprentice #254 #580800
>>580366

>Но главное что ты должен не ставить public/private от балды, а осознанно выбирать, что будет включено в список достпуных снаружи методов, а что скрыто.


Ты подумал что я делаю так? Я вроде оставил методы с которыми могут работать другие классы.

>>580366

>> Правда избавиться от $search не получилось


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


А как же DRY? Мы же в начале уже вызываем эту функцию https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/Cat.php#L78
Зачем её использовать по два раза?
#255 #580820
>>579675

Там не то преобразование, про которое ты думаешь.

Вот пример из статьи http://komlenic.com/244/8-reasons-why-mysqls-enum-data-type-is-evil/ :

CREATE TABLE test (foobar ENUM('0', '1', '2'));
INSERT INTO test VALUES ('1'), (1);
SELECT * FROM test;
+--------+
| foobar |
+--------+
| 1 |
| 0 |
+--------+

Отсюда и рекомендация.

> Например, если я везде ставлю "false", то потом при сравнении if($public == "false") у меня выходит ошибка,


Это ты где-то накосячил

>>579678

Пример выше показывает почему.

>>579753

Можно выловить коллег из соседнего отдела. А можно и бабу Нюру если она целевая аудитория сайта.

>>579832

Плохо что что размазываешь работу с GET/POST по всему приложению и передаешь в класс лишние данные. Ведь ты бы мог вместо этого передавать объект-модель.

>>579833

Нужно передавать модель, а не безликие массивы с неизвестным числом элементов.
#255 #580820
>>579675

Там не то преобразование, про которое ты думаешь.

Вот пример из статьи http://komlenic.com/244/8-reasons-why-mysqls-enum-data-type-is-evil/ :

CREATE TABLE test (foobar ENUM('0', '1', '2'));
INSERT INTO test VALUES ('1'), (1);
SELECT * FROM test;
+--------+
| foobar |
+--------+
| 1 |
| 0 |
+--------+

Отсюда и рекомендация.

> Например, если я везде ставлю "false", то потом при сравнении if($public == "false") у меня выходит ошибка,


Это ты где-то накосячил

>>579678

Пример выше показывает почему.

>>579753

Можно выловить коллег из соседнего отдела. А можно и бабу Нюру если она целевая аудитория сайта.

>>579832

Плохо что что размазываешь работу с GET/POST по всему приложению и передаешь в класс лишние данные. Ведь ты бы мог вместо этого передавать объект-модель.

>>579833

Нужно передавать модель, а не безликие массивы с неизвестным числом элементов.
Аноним #256 #580822
>>576499

>> public function isInsideMap($x, $y) {


>Результат который возвращает функция противоположен ее названию.


https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/World.php#L72
Почему? Название как бы говорит - "внутри карты?" если да, то соответственно возвращаем true, иначе false. Я не правильно перевел?
#257 #580824
>>579891

Абс/отн. позиционированием. Советую учебник на softwaremaniacs например почитать.

>>579969

code-review это когда перед тем как принять код в мастер его проверяют более старшие товарищи. Это хорошая штука так как без нее новичок придет и легко что-нибудь сломает или добавить код с уязвимостями или просто набыдлокодит. А новичок ознакамливается с правилами и принципами написания кода в данной организации.

Вот то-то вроде код ревью у разработчиков php фреймворка Юи 2: https://github.com/yiisoft/yii2/pulls

Вот код ревью разработчиков Хрома: https://codereview.chromium.org/

Багтрекер это просто программа где ведется список багов. Ну вот например багтрекер разработчиков фаерфокса: https://bugzilla.mozilla.org/buglist.cgi?product=Firefox&component=General&resolution=---

А вот багтрекер разработчиков Yii 2: https://github.com/yiisoft/yii2/issues

>>580003

> Но ведь туда можно, например, 3 поставить


Можно, но мы так делать не будем.

> В консоли заселектил, значение поля записи binary = 0. Но в админере всё равно 30 показывает. Версия админера 4.2.1, актуальная вроде.


Наверно консоль показывает содержимое как строку символов, а админер - коды символов.

> Ну в админере в смысле на выбор 7 даются.


Это двоичный тип в другом смысле. Не в смысле 0/1 а в смысле что позволяет хранить любые байты не интерпретируя их как символы или числа (строка например может при сравнении быть независимой от регистра или при вставке в строку могут отсекаться пробелы справа, а у бинарных данных такой особенности нет). Такой тип используется для хранения каких-то нечисловых и нетекстовы данных. Ну например зашифрованные данные. Или содержимое файла.
#257 #580824
>>579891

Абс/отн. позиционированием. Советую учебник на softwaremaniacs например почитать.

>>579969

code-review это когда перед тем как принять код в мастер его проверяют более старшие товарищи. Это хорошая штука так как без нее новичок придет и легко что-нибудь сломает или добавить код с уязвимостями или просто набыдлокодит. А новичок ознакамливается с правилами и принципами написания кода в данной организации.

Вот то-то вроде код ревью у разработчиков php фреймворка Юи 2: https://github.com/yiisoft/yii2/pulls

Вот код ревью разработчиков Хрома: https://codereview.chromium.org/

Багтрекер это просто программа где ведется список багов. Ну вот например багтрекер разработчиков фаерфокса: https://bugzilla.mozilla.org/buglist.cgi?product=Firefox&component=General&resolution=---

А вот багтрекер разработчиков Yii 2: https://github.com/yiisoft/yii2/issues

>>580003

> Но ведь туда можно, например, 3 поставить


Можно, но мы так делать не будем.

> В консоли заселектил, значение поля записи binary = 0. Но в админере всё равно 30 показывает. Версия админера 4.2.1, актуальная вроде.


Наверно консоль показывает содержимое как строку символов, а админер - коды символов.

> Ну в админере в смысле на выбор 7 даются.


Это двоичный тип в другом смысле. Не в смысле 0/1 а в смысле что позволяет хранить любые байты не интерпретируя их как символы или числа (строка например может при сравнении быть независимой от регистра или при вставке в строку могут отсекаться пробелы справа, а у бинарных данных такой особенности нет). Такой тип используется для хранения каких-то нечисловых и нетекстовы данных. Ну например зашифрованные данные. Или содержимое файла.
#258 #580826
>>580026

> Мне бы сделать так, чтобы можно было проверить, не является ли посетитель поисковым ботом, и только тогда засчитывать посещение.



Я же вроде писал 2 варианта:

1) взять 5-10 популярных ботов и сделать регулярку для проверки UA
2) использовать факт что большинство ботов не хранит куки и не выполняет JS

Попробуй их сравнить и подумать может какие еще варианты есть.

> json пустого проекта, к которому я пытаюсь подключить это дело http://pastebin.com/SzaZsXiF


Ок, можно сделать так. Расковырять файл vendor/autoload.php и файлы которые он подключает, засунуть вар дамп и посмотреть что не так.

Также, тебе не надо делать отдельный проект. Ты можешь в библиотеке или на одну папку выше добавить временно файл test.php и проверять из него. В гит его не коммить только.

> Никакая бд на этом этапе не уперлась.


Это да, но если мы делаем БД необязательной мы немного усложняем пользование классом. Как догадаться что БД нужна для вызова saveToDb? Может тогда ее в этот метод и передавать?

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


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

> Пользователь библиотеки обязан после создания объекта еще дернуть сеттер.


Это неочевидно. Тут надо как минимум комментариев натыкать, и я думаю проще сделать Db аргументом метода сохранения.

> Второе значение "учитывать"


Учитывать это в смысле: Please consider our suggestion too - Учтите (имейте в виду) и наше предложение.

Одно слово лучше искать в яндекс-словарях, там подробнее: https://slovari.yandex.ru/consider/%D0%BF%D0%B5%D1%80%D0%B5%D0%B2%D0%BE%D0%B4/#lingvo/

> Count в моем понимании это все-таки "считать".


Можно попробовать слово record, записать, тогда.

>>Непонятно зачем тут этот конструктор.


> А как мне передать соединение? Я знаю только про сеттеры и конструктор.


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

> Это же склеенный массив айдишников, как там могут оказаться не числа?


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

> Раз ты говоришь, что второй yii не очень отличается от первого, тогда и правда не буду делать на нем большой проект, надо придумать что-то простое, лишь бы было.


Как насчет портировать сайт объявлений на Юи 2? Изучи тогда все ли библиотеки которые ты используешь, или аналоги есть для Юи 2.

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


Инстаграм, твитер.

> Я плохо знаю jquery да и вообще js.


А у нас ведь есть задачки.

Да, плохо, и верстку ты не знаешь совсем, но процентов 70-80 кандидатов ее знают также как и ты.
#258 #580826
>>580026

> Мне бы сделать так, чтобы можно было проверить, не является ли посетитель поисковым ботом, и только тогда засчитывать посещение.



Я же вроде писал 2 варианта:

1) взять 5-10 популярных ботов и сделать регулярку для проверки UA
2) использовать факт что большинство ботов не хранит куки и не выполняет JS

Попробуй их сравнить и подумать может какие еще варианты есть.

> json пустого проекта, к которому я пытаюсь подключить это дело http://pastebin.com/SzaZsXiF


Ок, можно сделать так. Расковырять файл vendor/autoload.php и файлы которые он подключает, засунуть вар дамп и посмотреть что не так.

Также, тебе не надо делать отдельный проект. Ты можешь в библиотеке или на одну папку выше добавить временно файл test.php и проверять из него. В гит его не коммить только.

> Никакая бд на этом этапе не уперлась.


Это да, но если мы делаем БД необязательной мы немного усложняем пользование классом. Как догадаться что БД нужна для вызова saveToDb? Может тогда ее в этот метод и передавать?

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


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

> Пользователь библиотеки обязан после создания объекта еще дернуть сеттер.


Это неочевидно. Тут надо как минимум комментариев натыкать, и я думаю проще сделать Db аргументом метода сохранения.

> Второе значение "учитывать"


Учитывать это в смысле: Please consider our suggestion too - Учтите (имейте в виду) и наше предложение.

Одно слово лучше искать в яндекс-словарях, там подробнее: https://slovari.yandex.ru/consider/%D0%BF%D0%B5%D1%80%D0%B5%D0%B2%D0%BE%D0%B4/#lingvo/

> Count в моем понимании это все-таки "считать".


Можно попробовать слово record, записать, тогда.

>>Непонятно зачем тут этот конструктор.


> А как мне передать соединение? Я знаю только про сеттеры и конструктор.


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

> Это же склеенный массив айдишников, как там могут оказаться не числа?


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

> Раз ты говоришь, что второй yii не очень отличается от первого, тогда и правда не буду делать на нем большой проект, надо придумать что-то простое, лишь бы было.


Как насчет портировать сайт объявлений на Юи 2? Изучи тогда все ли библиотеки которые ты используешь, или аналоги есть для Юи 2.

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


Инстаграм, твитер.

> Я плохо знаю jquery да и вообще js.


А у нас ведь есть задачки.

Да, плохо, и верстку ты не знаешь совсем, но процентов 70-80 кандидатов ее знают также как и ты.
#259 #580829
Оп. а если я сделаю сайт с тестами (или с объявлениями, как другой анон) на Laravel, а не на Yii, ты посмотришь его?
#260 #580830
>>580034

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

Мой гитхаб уроками по PHP наполнен например.

> Допустим, моего левела хватает чтоб написать с нуля фреймворк, форум, магазин, вот это всё.


Сомневаюсь

> в итоге понял что сделать его удобнее чем ручную запись кода в лесс+жейд


сколько не видел кода на лесс - все быдлокод. Люди видимо используют его чтобы в CSS не разбираться. Городят каскады на несколько уровней вложенности в стиле div div .class span a { ... }

> Алсо, что делать если воротит от фреймоворков?


Ты наверно просто плохо знаешь ООП, паттерны, MVC или еще что-то пропустил, не можешь понять в чем суть и потому воротит.

> что делать кароче


Изучать пропущенное. Можно на наших задачках из Оп поста.

>>580138

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

Также, можно использовать функцию array_rand

>>580141

Юи 2 востребованнее

>>580167

> Если делаю шаблонизатор при помощи str_replace


Почитай совет номер 6: http://habrahabr.ru/post/230737/

>>580168

У тебя некоторые ошибки в коде. Например после

$query=$mysqli->query($sql);

нету if c проверкой на ошибку, смотри например примеры в мануале. Хотя это не виляет на результат, но это неправильно. Ты наверно изучал mysqli по каким-то неграмотным урокам раз их автор не знает про это.

----

### Вывод ошибок в mysqli

По умолчанию, если при работе с БД происходит ошибка, mysqli молчит как партизан и не выводит никаких предупреждений (а только возвращает false что мало помогает в поиске причины). Ты не узнаешь об ошибке и удивляешься почему ничего не работает.

Посмотри код в примерах: http://php.net/manual/ru/mysqli.quickstart.statements.php

Видишь, после каждого вызова функций mysqli стоит if с выводом сообщения об ошибке? То же самое надо сделать и тебе (а вот PDO кстати умеет сам выкидывать исключения и не трубет писать ифы). Только на реальном сайте ошибку лучше не показывать пользователю, а писать в логи или например выкидывать исключение.

Вот неплохая статья про mysqli и там тоже говорится про обработку ошибок: http://habrahabr.ru/post/141127/

После того как ты это сделаешь и увидишь причину ошибки, исправить ее будет наверно нетрудно.

----

> echo '<div class="col-lg-4 col-md-6"><


Не выводи HTML через echo используй шаблоны

> как сделать, чтобы и дивы выходили?


Не понял вопрос

> Но при этом элементы разметки надо писать по 5 раз.


Я не понял почему их надо писать по 5 раз. Также ты не написал что в файле template.tpl.
#260 #580830
>>580034

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

Мой гитхаб уроками по PHP наполнен например.

> Допустим, моего левела хватает чтоб написать с нуля фреймворк, форум, магазин, вот это всё.


Сомневаюсь

> в итоге понял что сделать его удобнее чем ручную запись кода в лесс+жейд


сколько не видел кода на лесс - все быдлокод. Люди видимо используют его чтобы в CSS не разбираться. Городят каскады на несколько уровней вложенности в стиле div div .class span a { ... }

> Алсо, что делать если воротит от фреймоворков?


Ты наверно просто плохо знаешь ООП, паттерны, MVC или еще что-то пропустил, не можешь понять в чем суть и потому воротит.

> что делать кароче


Изучать пропущенное. Можно на наших задачках из Оп поста.

>>580138

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

Также, можно использовать функцию array_rand

>>580141

Юи 2 востребованнее

>>580167

> Если делаю шаблонизатор при помощи str_replace


Почитай совет номер 6: http://habrahabr.ru/post/230737/

>>580168

У тебя некоторые ошибки в коде. Например после

$query=$mysqli->query($sql);

нету if c проверкой на ошибку, смотри например примеры в мануале. Хотя это не виляет на результат, но это неправильно. Ты наверно изучал mysqli по каким-то неграмотным урокам раз их автор не знает про это.

----

### Вывод ошибок в mysqli

По умолчанию, если при работе с БД происходит ошибка, mysqli молчит как партизан и не выводит никаких предупреждений (а только возвращает false что мало помогает в поиске причины). Ты не узнаешь об ошибке и удивляешься почему ничего не работает.

Посмотри код в примерах: http://php.net/manual/ru/mysqli.quickstart.statements.php

Видишь, после каждого вызова функций mysqli стоит if с выводом сообщения об ошибке? То же самое надо сделать и тебе (а вот PDO кстати умеет сам выкидывать исключения и не трубет писать ифы). Только на реальном сайте ошибку лучше не показывать пользователю, а писать в логи или например выкидывать исключение.

Вот неплохая статья про mysqli и там тоже говорится про обработку ошибок: http://habrahabr.ru/post/141127/

После того как ты это сделаешь и увидишь причину ошибки, исправить ее будет наверно нетрудно.

----

> echo '<div class="col-lg-4 col-md-6"><


Не выводи HTML через echo используй шаблоны

> как сделать, чтобы и дивы выходили?


Не понял вопрос

> Но при этом элементы разметки надо писать по 5 раз.


Я не понял почему их надо писать по 5 раз. Также ты не написал что в файле template.tpl.
#261 #580833
>>580168

Еще: зачем ты смешиваешь ООП- и процедурный стиль работы с mysqli? И зачем там цикл while если все записи можно выбрать одной функцией?

>>580175

> Да, этот метод нужен всем животным, потому что именно он определяет их поведение.


Хорошо, убедил, но тогда другой вопрос: а почему в базовом классе тогда нет реализации move по умолчанию, если все животные используют оценочную функцию, то алгоритм функции move() наверно одинаковый получается?

> Думаю следует оставить методы:


Ну хорошо.

>>580376

Старье. Я бы твиг изучал.

>>580381

В какой именно таблице? И зачем?

>>580586

Давать можно много, можно делать сложные, но тогда в них должна быть какая-то логика, хлороший пример это стиль БЭМ от яндекса.

Ну и вообще надо смотреть по ситуации. Может в твоем случае достаточно одного идентификатора на весь блок, а остальное средствами CSS просталвять.
#261 #580833
>>580168

Еще: зачем ты смешиваешь ООП- и процедурный стиль работы с mysqli? И зачем там цикл while если все записи можно выбрать одной функцией?

>>580175

> Да, этот метод нужен всем животным, потому что именно он определяет их поведение.


Хорошо, убедил, но тогда другой вопрос: а почему в базовом классе тогда нет реализации move по умолчанию, если все животные используют оценочную функцию, то алгоритм функции move() наверно одинаковый получается?

> Думаю следует оставить методы:


Ну хорошо.

>>580376

Старье. Я бы твиг изучал.

>>580381

В какой именно таблице? И зачем?

>>580586

Давать можно много, можно делать сложные, но тогда в них должна быть какая-то логика, хлороший пример это стиль БЭМ от яндекса.

Ну и вообще надо смотреть по ситуации. Может в твоем случае достаточно одного идентификатора на весь блок, а остальное средствами CSS просталвять.
#262 #580837
>>580822

На момент проверки у тебя она возвращаала false если объект в пределах карты и true если он за пределами. Если я не путаю.

>>580829

Посмотрю. Но тогда он должен соответстовать описанному в документации на лаварель стилю и принципам.
#263 #580840
>>580800

DRY значит что не надо копипастить код или например не надо какое-то число или параметр писать несколько раз в разных местах. Вызывать функцию несколько раз можно, для этого обычно код в функцию и выносится.
#264 #580841
>>580837

>Посмотрю. Но тогда он должен соответстовать описанному в документации на лаварель стилю и принципам.


Ок, тогда Laravel.
#265 #580844
>>580837

>На момент проверки у тебя она возвращаала false если объект в пределах карты и true если он за пределами. Если я не путаю.


А да точно. Я просто забыл что уже исправил это.

Спасибо.
#266 #580863
Аноны, конкурс по программированию (а также поиск сотрудников) на JS: http://habrahabr.ru/company/hola/blog/270847/

Единственное что компания Hola очень мутная: они выпускают расширение к браузеру якобы для обхода блокировок, а на деле ставят пользователю свой бекдор и потом продают возможность прогонять через него трафик.
#267 #580886
https://repl.it/B0Iz

Зацените мою функцию поиска максимального значения в массиве произвольной вложенности. Или я хуйнёй страдаю?
#268 #580913
>>580863
Это ботнет же, холу еще в чем-то уличали, кроме этого. Мол они сливают инфу пользователей, но насчет этого не уверен.
#269 #580920
>>580487
А, я кажется начинаю догадываться, почему медленно отдается статика. Несмотря на отсутствие заголовков, стили и скрипты действительно скорее всего отдаются при помощи фреймворка, хотя я пока не понимаю как.
В yii есть весьма странная на мой вгляд система ассетов, я в этой галиматье ничего не понял http://yiiframework.ru/doc/cookbook/ru/core.assets
Почему нельзя просто прописать тег script или link, зачем эта запутанная система каких-то регистраций и публикаций скрипта?
У меня в шаблоне стоит App.clientScript.registerCssFile(App.request.baseUrl~'/css/mainpage.css').
В диспетчере вроде бы подключается из файла Request URL: http://test/css/main.css
Казалось бы этот файл должен отдаваться сервером, но такое впечатление, что это не так. Я ничего не понимаю. Короче я лучше пропишу нормальный тег подключения вместо этой байды, благо твиг со своим наследованием очень выручает, можно переопределить шапку, где подлючаются скрипты и стили. Вот это единственная пожалуй польза от этих ассетов, без твига я бы не смог из местного шаблона изменить общую шапку например.

>а если много? Если мы захотим на странице каждого объявления что-то кешировать?


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

>Также, надо решить на каком уровне мы кешируем


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

>Достаточно вот тут правильно прописать autoload: https://github.com/nsdvw/visit-counter/blob/master/composer.json


>Ты прописал?


Ты переутомился что ли? Ты же сам видишь, что я прописал. Правильно или нет, я не знаю, если бы знал, то прописал бы правильно. Но судя по всему неправильно, не подключаются классы из библиотеки в основном проекте. Не знаю куда смотреть.
Вот здесь написано
https://getcomposer.org/doc/01-basic-usage.md#autoloading

> For libraries that specify autoload information, Composer generates a vendor/autoload.php file


А как сделать, чтобы моя библиотека specify автозагрузку? Я так понимаю, нужно что-то еще прописать, но не знаю где.
Вот это "autoload": { "psr-4": {"VisitCounter\\": "./"} } не помогает.

>Ты прописал? Протестировал (например сделав файл temp.php и из него проверив подгружаются ли классы?)? После того как добавил библиотеку в основной проект, сделал ли composer install или update?


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

>Придется где-то хранить эти дельты (например в отдельном хеше или ключах) и как-то атомарно их сбрасывать.


Сделаю тогда хеш, куда при посещении будет писаться id страницы в виде ключа, а значение увеличивать incr. Сбросить легче простого, нужно тупо очистить этот хеш, удалить все ключи из него.
Другое дело, что логика усложняется мы оперируем уже тремя структурами в нашем коде, и с усложнением приходится нервничать по поводу атомарности. Оберну в транзакцию, что делать.
Но я помню, что тебе не понравилось в низкоуровневой версии счетчика, что я заставлял под адаптер реализовывать каждую команду редиса, тогда получилось пять абстрактных методов. Сейчас понадобится еще 3 для обеспечения транзакции, плюс методы для работы с хешем. Хотя меня это устраивает на самом деле.

>>580826

>Я же вроде писал 2 варианта


Ты говорил, что парсинг UA для быдла. А как проверить, поддерживает ли агент куки - я не знаю.
setcookie ничего не гарантирует, как я понимаю
http://php.net/manual/ru/function.setcookie.php

> Если setcookie() успешно отработает, то вернет TRUE. Это, однако, не означает, что клиентское приложение (броузер) правильно приняло и обработало cookie.


Встает вопрос: как узнать, что браузер не поддерживает куки?
Как из php выяснить, поддерживает ли браузер джаваскрипт, тоже непонятно.
Ладно, я тогда сделаю говно-регулярку для ua вида /.+bot.+/

>Расковырять файл vendor/autoload.php и файлы которые он подключает


Я смотрел файл composer_psr4.php, в котором вроде бы должны подключаться файлы, но там return array();

>Также, тебе не надо делать отдельный проект.


Чего это не надо? Мне как раз нужно, чтобы я сделал composer install, эта библиотечка скачалась в папку vendor, а ее классы были доступны в основном проекте.
Если сделать файл temp.php в корне библиотеки, то в нем классы подключаются. Правда нужно еще в этой папке сгенерировать автозагрузку.
Но если попробовать создать объект класса из библиотеки в основном проекте, но class not found.

>Как догадаться что БД нужна для вызова saveToDb? Может тогда ее в этот метод и передавать?


Вот это верно подметил, сейчас сделаю.

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


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

>Как насчет портировать сайт объявлений на Юи 2?


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

>Инстаграм, твитер.


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

>верстку ты не знаешь совсем


Ну на уровне быдловерстальщика знаю, хотя не очень хорошо конечно.
Сейчас закончу со счетчиком и возней с кешами, завтра-послезавтра займусь версткой и js.
#269 #580920
>>580487
А, я кажется начинаю догадываться, почему медленно отдается статика. Несмотря на отсутствие заголовков, стили и скрипты действительно скорее всего отдаются при помощи фреймворка, хотя я пока не понимаю как.
В yii есть весьма странная на мой вгляд система ассетов, я в этой галиматье ничего не понял http://yiiframework.ru/doc/cookbook/ru/core.assets
Почему нельзя просто прописать тег script или link, зачем эта запутанная система каких-то регистраций и публикаций скрипта?
У меня в шаблоне стоит App.clientScript.registerCssFile(App.request.baseUrl~'/css/mainpage.css').
В диспетчере вроде бы подключается из файла Request URL: http://test/css/main.css
Казалось бы этот файл должен отдаваться сервером, но такое впечатление, что это не так. Я ничего не понимаю. Короче я лучше пропишу нормальный тег подключения вместо этой байды, благо твиг со своим наследованием очень выручает, можно переопределить шапку, где подлючаются скрипты и стили. Вот это единственная пожалуй польза от этих ассетов, без твига я бы не смог из местного шаблона изменить общую шапку например.

>а если много? Если мы захотим на странице каждого объявления что-то кешировать?


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

>Также, надо решить на каком уровне мы кешируем


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

>Достаточно вот тут правильно прописать autoload: https://github.com/nsdvw/visit-counter/blob/master/composer.json


>Ты прописал?


Ты переутомился что ли? Ты же сам видишь, что я прописал. Правильно или нет, я не знаю, если бы знал, то прописал бы правильно. Но судя по всему неправильно, не подключаются классы из библиотеки в основном проекте. Не знаю куда смотреть.
Вот здесь написано
https://getcomposer.org/doc/01-basic-usage.md#autoloading

> For libraries that specify autoload information, Composer generates a vendor/autoload.php file


А как сделать, чтобы моя библиотека specify автозагрузку? Я так понимаю, нужно что-то еще прописать, но не знаю где.
Вот это "autoload": { "psr-4": {"VisitCounter\\": "./"} } не помогает.

>Ты прописал? Протестировал (например сделав файл temp.php и из него проверив подгружаются ли классы?)? После того как добавил библиотеку в основной проект, сделал ли composer install или update?


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

>Придется где-то хранить эти дельты (например в отдельном хеше или ключах) и как-то атомарно их сбрасывать.


Сделаю тогда хеш, куда при посещении будет писаться id страницы в виде ключа, а значение увеличивать incr. Сбросить легче простого, нужно тупо очистить этот хеш, удалить все ключи из него.
Другое дело, что логика усложняется мы оперируем уже тремя структурами в нашем коде, и с усложнением приходится нервничать по поводу атомарности. Оберну в транзакцию, что делать.
Но я помню, что тебе не понравилось в низкоуровневой версии счетчика, что я заставлял под адаптер реализовывать каждую команду редиса, тогда получилось пять абстрактных методов. Сейчас понадобится еще 3 для обеспечения транзакции, плюс методы для работы с хешем. Хотя меня это устраивает на самом деле.

>>580826

>Я же вроде писал 2 варианта


Ты говорил, что парсинг UA для быдла. А как проверить, поддерживает ли агент куки - я не знаю.
setcookie ничего не гарантирует, как я понимаю
http://php.net/manual/ru/function.setcookie.php

> Если setcookie() успешно отработает, то вернет TRUE. Это, однако, не означает, что клиентское приложение (броузер) правильно приняло и обработало cookie.


Встает вопрос: как узнать, что браузер не поддерживает куки?
Как из php выяснить, поддерживает ли браузер джаваскрипт, тоже непонятно.
Ладно, я тогда сделаю говно-регулярку для ua вида /.+bot.+/

>Расковырять файл vendor/autoload.php и файлы которые он подключает


Я смотрел файл composer_psr4.php, в котором вроде бы должны подключаться файлы, но там return array();

>Также, тебе не надо делать отдельный проект.


Чего это не надо? Мне как раз нужно, чтобы я сделал composer install, эта библиотечка скачалась в папку vendor, а ее классы были доступны в основном проекте.
Если сделать файл temp.php в корне библиотеки, то в нем классы подключаются. Правда нужно еще в этой папке сгенерировать автозагрузку.
Но если попробовать создать объект класса из библиотеки в основном проекте, но class not found.

>Как догадаться что БД нужна для вызова saveToDb? Может тогда ее в этот метод и передавать?


Вот это верно подметил, сейчас сделаю.

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


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

>Как насчет портировать сайт объявлений на Юи 2?


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

>Инстаграм, твитер.


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

>верстку ты не знаешь совсем


Ну на уровне быдловерстальщика знаю, хотя не очень хорошо конечно.
Сейчас закончу со счетчиком и возней с кешами, завтра-послезавтра займусь версткой и js.
#270 #580951
>>580487

>А список последних объявоений?


Чего его кешировать? У нас же yoba-сайт с миллионами уников, по десять новых объявлений в секунду.
С другой стороны да, можно закешировать на маленькое время, скажем 5-15 секунд. Для пользователя задержка в обновлении почти незаметная, а выигрыш наверное неплохой.

Итак, что у меня получилось с этим кешированием.
Было Time per request: 1436.936
Были применены следующие шаги:
1. Отключен дебаг-режим. Дало около 2%
Time per request: 1407.330
2. Включаю кеширование схемы бд. Еще около 3%
Time per request: 1365.152
3. Кеширую фрагменты страницы. Выпадающий список с регионами:
Time per request: 1271.720
4. Виджет с выбором категорий:
Time per request: 835.195
5. Кеширую виджет с последними объявлениями (ради теста на 5 секунд)
Time per request: 501.750

Время загрузки сократилось в три раза, с 1.5 секунд до 0.5, я доволен. Еще бы разобраться, что за чертовщина происходит с этими ассетами и подгрузкой статики, было бы вообще замечательно.
#271 #580972
>>580833
Ну смотри, я сохраняю куку у пользователя на сайте. Потом кладу ее в таблицу тому же юзеру. Если его кука и кука в таблице совпадают, то ставлю его как залогированного, если нет, то разлогиненного. Так вопрос, мне куку в каком месте удалять, когда разлогируется?
#272 #580977
>>580972
Есть кука = залогинен.
Нет куки = разлогинен.
#273 #580978
>>580977
Хранить её в базе нет необходимости.
#274 #580995
>>580978
Каждой куке соответствует пароль и логин. Если юзер анонимный, то пароля и логина нет, он определяется только по куке в базе. Если он регится, то автоматом все добавленные им файлы вешаются на его юзера. Что неясно? Кука нужна в таблицах. По кукам сранивается, может ли юзер редактировать файл, как его автор, или только просматривать, как гест.
#275 #581003
А после удаления куки, как ты её собрался восстанавливать?
Тут тебе скорей всего придётся добавлять статус для незарегистрированного пользователя залогинен/разлогинен.

И ещё смотри если пользователь утратит куки, допустим почистит браузер. Как такой пользователь потом получит доступ к своим файлам?
я не ОП
#276 #581005
>>581003
сюда писал
>>580995
#277 #581007
>>580995

>По кукам сранивается, может ли юзер редактировать файл


Тогда файл юзера может отредактировать его мамка, хотя он вылогинен.
Фалы залитые из-под зарегистрированного аккаунта лучше сделать доступными для залогиненного юзера.
#278 #581014
>>580995

>Если он регится, то автоматом все добавленные им файлы вешаются на его юзера.


Незалогиненный юзер залил цп. Регистрируется мамка юзера, и весь пак оказывается у неё в личных файлах.
#279 #581015
Ну вот теперь куки перестали проставляться, это потому что они создаются в классе и туда же передается апп?
#280 #581016
#281 #581021
Вот теперь, опять ставится. Что за хрень?
#282 #581022
>>581021
я не знаю
#283 #581023
>>581003

> Как такой пользователь потом получит доступ к своим файлам?



Никак, почистил куки и не зарегился - теряешь доступ к файлам. Нередка встречалась такая система. Почистил куки - вошел в аккаунт, в таблице и куках проставляется новая кука. Скорее всего кука для пользователя берется из его старой таблицы. Напрягает только, что приходится куки в двух таблицах дублировать файлов и пользователей. Все равно придется делать запрос к таблице пользователя при выводе файла, чтобы получить логин пользователя. Так что наверное буду куку только в табл. польз. хранить.
#284 #581024
>>581007
Если не зарегин, то это уже его проблема, кто под его куками сможет файлы фиксить. А вот если залогинился и зарегился, то предварительно разлогиниваешься, чтобы твоя кука удалялсь и оставалась только в таблице, откуда возьмется вновь. Так на ргхосте.
#285 #581033
>>581024

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


Я в первую очередь про этот вариант: >>581014.
#286 #581036
>>580972
А как тогда в принципе возможно залогиниться/разлогиниться? Тут тогда проебал куки = проебал доступ к редактированию файлов. Это если нет аккаунта.
#287 #581132
>>581014
Зарегся, разрегся и лей цп.
#288 #581133
>>581036
>>581036
кука в таблице пишется также, а если пароль совпадает, то из таблице она пишется пользователю(токен).
#289 #581151
Вот я помню мы тут обсуждали архитектуру БД для стримингового сервиса, вот статья по теме, где упоминаются кое-какие подробности финансовой модели: http://m.geektimes.ru/company/audiomania/blog/265770/
19 Кб, 360x235
#290 #581167
>>581014

>Регистрируется мамка юзера, и весь пак оказывается у неё в личных файлах.


К Мамке приезжает ФСБ и сажает её в пативэн.
10 лет за распространение.
#291 #581236
Посоны, про АЛЬПАРИ (это форекс-биржа) кто что знает?
Зовут на скайп-собеседование на веб-джуна, я даже не откликался. У них на hh.ru даже такой вакансии нет, только с опытом.
#292 #581237
>>581236
Алсо, говорят, что активно юзают Symfony.
#293 #581239
>>581236
Джунов редко ищут по вакансиям.
#294 #581240
>>581239
То есть редко публикуют вакансии джунов?
#295 #581244
>>581240
Конечно. Тратить время специалистов на собеседования сеньеров-помидоров еще можно (все равно их 1.5 штуки будет), но вакансию джуна опубликуй, придет толпа васянов, и что ты с ними будешь делать?
#296 #581245
>>581244
Берут того васяна который go with the team (или как там эта идиома звучит), аля бухает тот же напиток что и собеседующий, подходит по цвету свитера или наклейке на ноуте. То есть обладает неким сходством с сидящими там уже аутистами.
Ну и СВЯЗИ никто не отменял.
#297 #581253
>>581244
А можешь тогда сказать, какая у эйчаров обычно политика рассылки предложений?
В письме мне написали, мол, моё резюме заинтересовало руководителя отдела. Но моё резюме - полупустое, указаны только навыки и ссылка на гитхаб. Увеличения числа просмотров репозиториев я не увидел.
#298 #581255
>>581239

По моему ты пишешь глупость.

http://spb.hh.ru/search/vacancy?text=php&salary=&currency_code=RUR&experience=noExperience&order_by=relevance&search_period=30&items_on_page=20&no_magic=true

165 вакансий при условии что опыта нет.

Как раз сотрудников более высокого уровня предпочитают искать через личные связи или выращивать, а не брать с улицы.
#299 #581259
>>581255

>165 вакансий при условии что опыта нет.


26 в ДС. Из них 18 нерелевантны. Остальные - битриксы и те, которые висят там перманентно.
#300 #581267
>>581253
Не могу, насчет таких подробностей я не в курсе. Можешь считать это личным наблюдением.
#301 #581269
>>581255

>165 вакансий при условии что опыта нет.


А теперь посмотри каждую и проверь, действительно ли нет там опыта. Я потыкал случайно - 1 из 4 такая. Т.е. 40 вакансий на огромную страну.
#302 #581275
Начал вчера ихучать пхп.

Через сколько времени смогу работать макакой?
34 Кб, 488x545
#303 #581277
Анон, такой вопрос. Есть самописный сайт на php, довольно простой, без мускуэлей, данные тупо в текстовых файликах. Есть самодельная cms для заполнения этих текстовых файлов. Есть файл, в который пишется лог посещений, сделано вот таким простым кодом.
От хостера пришло письмо:

"В ходе плановой проверки на Вашем аккаунте было обнаружено подозрительное, потенциально вредоносное, содержимое. Ниже приведены пути к найденным файлам, а также их описание:
//путь до этого текстового log-файла : {HEX}base64.inject.unclassed.7.UNOFFICIAL"//

Вопрос: что такого могло остаться в логах посещений, что возбудило робота хостера? И еще вопрос: что делает обведенный красным кусок кода? Я писал это говно в 2008-м году еще и нифига не помню, несмотря на свои же комментарии.
#304 #581284
>>581277
Охуенные у тебя комментарии.
На будущее: если пишешь комментарии, то не пиши "что" ты делаешь (это и так есть в коде), а пиши "зачем".
#305 #581287
>>581277
Был у меня один одногруппник, который ебашил такие же мразотные комменты, еще и неграмотно. Не делай так, пожалуйста, ты же не понимаешь что там происходит, и, на самом деле, нихуя не ясно даже что хотел сделать. Тут гадание какое-то.
someApprentice #306 #581290
>>576499
Фух, вроде бы все исправил: https://github.com/someApprentice/Cat-and-Mouse

Несколько комментариев:

>>580366
https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/Animal.php#L102

>> Почему-то если в этой функции за место $object поставить true или поменять местами false/$object(true), чтобы можно было переименовать функцию на isOneOfTrack....


>Значит ты где-то сделал ошибку в логике. Может быть там мало поменять местами true/false, надо еще if в другое место переставить или что-то еще. Надо выяснить и сделать нормально.


>


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


На самом деле тут не было ошибки (возможно только в названии), я изначально хотел пропускать ходы с животными которые неЯвляютсяОтслеживаемыми(). Использование true за место $object приводит к странному поведению, потому что при вызове функции определенияЖивотногоНаКоординате($x, $y), если на этой координате нет объекта, то эта функция возвращает false, и соответственно ход с пустой координатой не пропускается, а идет в список возможных ходов.

...

>>580366
>>580840

>> Правда избавиться от $search не получилось


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



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


https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/Mouse.php#L39
Вызывать метод получения искомых животных внутри этой функции я не стал, потому что заранее неизвестно какие животные будут искаться тех которых оно будет бояться или тех кого будет искать... Или в рамках отдельного класса животного можно определить это заранее самостоятельно? Как ты думаешь?
#307 #581303
Господа, в чем различие между майсоклом, ораклом и моного? И в чем последние превосходят первый?
#308 #581304
>>581277
Проиграл, комментов больше кода.
#309 #581308
>>581245

>с сидящими там уже аутистами.


Аутисты дома сидят, в конторках работает социальное быдлецо.
#310 #581310
>>581275
Через неделю, если ты общительное нейротипичное говно))
#311 #581314
>>581310
Новый форс в зекаче?
#312 #581315
>>581314
Мамкины домоседы все теперь считают себя аутистами.
#313 #581341
>>581308
Смотря где, видал и целые отделы жава-макак с испуганными глазами и дрожащими голосами, над которыми верховодил один социальный павиан.
#314 #581344
>>581341

>жава-макак


Как жава-кодер может быть макакой? Или может? А чо они тогда выёбываются? "Похапе - выбор абиззян, кококо."
#315 #581348
>>581344
В /зк/ только за макак их и считают.
#316 #581351
>>581348
Кого в зк вообще не считают за макак?
#317 #581353
>>581344
Любой кодер может быть макакой.
#318 #581357
>>581353
Ну джунов-джавистов же на собеседованиях вроде ебут деревьями, паттернами, алгоритмами. Или нет?
#319 #581358
>>581357
Обезьяна должна уметь лазить по деревьям, узнавать паттерны на шкуре леопарда и знать алгоритм поедания банана. Быть магистром компьютер сайнса или гением менеджмента для выживания вовсе не обязательно.
#320 #581359
>>581357
Из того что я знаю, (джава-андроид джун) ебать ебут и деревьями и под деревьями и на сортировке, и даже просят объяснить за преобразование фурье, только вот потом выбирают по причинам слабо относящимся к знаниям этих самых CS вещей.
223 Кб, 500x364
#321 #581360
Нужно сделать сайт с регистрацией, добавлением своих материалов, тегами и списком друзей.
Вопрос: На чем писать? Если на PHP, то можно использовать готовые CMS, которые я не знаю, и которые придется учить во время работы. Если Node.JS, то придеться все писать самому, однако возможного проеба с CMS не будет.
#322 #581361
>>581360
Бери Drupal.
#323 #581363
>>581360
Что знаешь на том и пиши.
84 Кб, 701x566
#324 #581371
Как решить задачку с вычислением и подсчета ростов? Все перепробовал - циклы с добавлением элементов в новый массив, простые условия, ошибки везде

Дан рост школьника и рост его одноклассников. Надо найти, сколько человек в классе выше, чем наш герой.
#325 #581372
>>581371
classmates.filter(m => m.height > anon.height).length
#326 #581375
>>581372
Зачем ты дал ему ответ в синтаксисе богомерзкого говноязыка?
#327 #581377
>>581375
Это сишарп?
#328 #581379
>>581371

>Все перепробовал - циклы с добавлением элементов в новый массив, простые условия, ошибки везде


Скидывай код, посмотрим что за ошибки. Или ты ждешь, что за тебя задачу с нуля решат?
#329 #581380
>>581371
У анона рост, как у меня.
#330 #581382
>>581371
Это олимпиадная задача, я сам ее решал 3 месяца.
#331 #581384
>>581380
Бильбо?
#332 #581386
#333 #581387
>>581371
Там класс баскетболисток что ли?
#334 #581388
>>581387
Ты в северной корее живешь что-ли?
#335 #581389
>>581379
Да просто скажи что применить нужно
#336 #581390
>>581389
Голову.
#337 #581396
>>581388
Нет.
Алсо, когда вижу человека ростом 175-180, мне кажется, что мы на одном уровне. 180-185 воспринимаются как чуть более высокие, чем я. Это если на отражающие поверхности не смотреть.
#338 #581401
Можно ли при помощи одного CSS сделать так что бы при наведении на какой-либо объект, допустим див мышкой, менялся не только его параметры, но и параметры какого-нибудь другого объекта? Можно ли использовать подобным образом hover?
#340 #581405
>>581403
Вот, то что надо, не знал про этот +, спасибо
#341 #581406
>>581371

Заведи переменную, положи в нее 0, каждый раз когда видишь высокого анона, увеличивай на 1.

>>581372

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

В C# для подсчета числа элементов есть функция Count:

list.Count(x => x < 5);

Это и есть правильное решение. А твое решение это решение человека который выучил одну функцию (больше наверно не осилил) и думает что он тут самый умный.
#342 #581407
>>581405
Советую почитать про селекторы
http://htmlbook.ru/css
#343 #581410
>>581406

>но решение плохое


Оно легко читается и при необходимости так же легко переделывается в оптимальное. Что в нем плохого?

>и неэффективное


Premature optimization is the root of all evil. Как будет потребность — заменит filter на reduce, цикл, или действительно добавит Array.prototype.count.
#344 #581411
>>581403
У меня, почему то не вращается:
http://jsfiddle.net/bp62hnv4/
#345 #581412
>>581411
Не ту ссылку скинул, извиняюсь:
http://jsfiddle.net/xrt7v0fj/
#346 #581413
>>581410

решение плохое тем что вместо того чтобы напрямую посчитать что нужно, все делается в обход на костылях. В ваш недоязык функцию count до сих пор не завезли что ли?
#347 #581415
>>581410

Также, этот даун даже не прочитал вопрос. Просили подсказать решение на PHP а не на недоязыке. Ты бы еще на руби ответ написал.
#348 #581416
>>581412
Селектор + между тегами A и B применяется к тегу B когда он идёт сразу же после тега A. В твоём случае cube вообще является родительским элементом для side2.
#349 #581417
>>581413

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


Лол. Если переписать то решение на ествественный язык, будет звучать так:
Выберем тех, кто выше, и посмотрим сколько их
Куда уж прямее?

>В ваш недоязык функцию count до сих пор не завезли что ли?


Лол-2. Все еще меряешься языками, не вырос из фанбойства?
>>581415
Даун тот, кто просит решать лабу за него. На подобные запросы и на yoba-lisp отвечать уместно.
#350 #581419
>>581417

Это PHP-тред для вопросов в том числе по задачам. Не тред для клоунов которые хотят похвастаться что они сегодня выучили новую функцию из недоязыка.

Вопрос абсолютно уместен в этом треде, ответ клоуна нет.

Прямее - не выбирать никого, а сразу посчитать сколько тех кто выше.
#351 #581421
>>581419
А я тоже клоун? >>580886
#352 #581423
>>581421

Почему? Нет.
#353 #581439
>>581423
Ну я тоже немножко выпендриваюсь.
#354 #581450
>>581416
В этом случае вращать куб при нажатии по его сторонам, можно только при помощи jQuery?
#355 #581478
>>581371
Могу скинуть код, но я его год назад писал.
#356 #581482
>>581450
Выходит что так.
86 Кб, 400x400
Поможите же #357 #581492
Пэхэпаны, не могу получить картинку да и вообще любые файлы с серверов, возвращает 0 байт. Что делать?
#358 #581493
>>581492
Код забыл.

$file = 'https://2ch.hk/pr/src/569049/14472479109330.png';

header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.$file);
header('Content-Length: ' . filesize($file));
exit(0);
11 Кб, 624x479
#359 #581517
Как сделать подобное тому что на картинке? Как можно разместить один див поверх другого?
58 Кб, 500x500
https://ideone.com/FmmyS8 #361 #581596
Здравствуйте. Оп, ты наверное по горло сыт кошками-мышками, но проверь, пожалуйста. https://ideone.com/FmmyS8. Моих кошек-мышек выкладываю первый раз. В тредах аноны часто выкладывают свое решение, я туда не смотрел, хотел решить без подсказок, так что возможно изобрел много велосипедов в своем коде. Ну правда подглядел пост где ты подсказал убрать копипаст 8 направлений, а отправлять животное конкретно в определенную координату, это я взял на вооружение.
#362 #581597
Хочу попробовать API вконтакте, создаю приложение вконтакте что бы получить необходимый токен и т.д. У меня openserver что указывать в графе Адрес сайта и базовый домен? Просто адрес сайта на своём компьютере? Писать localhost перед адресом? На Денвере писал, там работало, на open server ещё не пробовал.
#363 #581601
>>581596
Точка лишняя в ссылке. https://ideone.com/FmmyS8
#364 #581710
>>581493
ты не отдаешь сам файл, а только заголовки.
#365 #581719
Я тогда порешаю задачи по верстке, пока опа нет дома.

1 задание
http://jsfiddle.net/nf520e1p/
Условие невнятное. 66% от ширины родителя?
Что значит 34% - 10px?

2 задание
http://jsfiddle.net/ox9h3fws/2/

>ширина блока не превышает 600px


С учетом border?

3 задание

>из тегов можно использовать только <em>


Почему не span? Странно.
http://jsfiddle.net/82xe7woh/

4 задание
http://jsfiddle.net/hghj6q0h/
В той статье приводится 7 способов борьбы с пробелами между инлайн-блоками, мне нравятся только 2 самых простых: либо писать теги вплотную, убрав пробелы и переносы, либо не закрывать теги. Но в первом случае есть опасность, что кто-то потом по незнанию поставит переносы ради читабельности, и появятся косяки, причину которых бедняге будет не так легко найти. Второй способ не работает со вложенными дивами, например.

У меня на xfce дико лагает пипетка в инструментах мозиллы.

5 задание
http://jsfiddle.net/g3a9mrqj/
Наверное там какой-то подвох, что-то подозрительно легкое.
#365 #581719
Я тогда порешаю задачи по верстке, пока опа нет дома.

1 задание
http://jsfiddle.net/nf520e1p/
Условие невнятное. 66% от ширины родителя?
Что значит 34% - 10px?

2 задание
http://jsfiddle.net/ox9h3fws/2/

>ширина блока не превышает 600px


С учетом border?

3 задание

>из тегов можно использовать только <em>


Почему не span? Странно.
http://jsfiddle.net/82xe7woh/

4 задание
http://jsfiddle.net/hghj6q0h/
В той статье приводится 7 способов борьбы с пробелами между инлайн-блоками, мне нравятся только 2 самых простых: либо писать теги вплотную, убрав пробелы и переносы, либо не закрывать теги. Но в первом случае есть опасность, что кто-то потом по незнанию поставит переносы ради читабельности, и появятся косяки, причину которых бедняге будет не так легко найти. Второй способ не работает со вложенными дивами, например.

У меня на xfce дико лагает пипетка в инструментах мозиллы.

5 задание
http://jsfiddle.net/g3a9mrqj/
Наверное там какой-то подвох, что-то подозрительно легкое.
62 Кб, 720x540
#366 #581727
Аноны а не поздно ли вкатываться в веб в 24 года? Что то припеканус от 17 летних фрилансеров 2000$ долларов в день
#368 #581748
>>581727
Поздно.
#369 #581768
>>581748
Двачую.
#370 #581844
Проверьте верстку:
http://integer64.github.io/makeup/
#371 #581847
Сап, анончики, прошу о помощи моему тимлиду, который пишет сервер на php для моего приложения под ведроид. Конкретно - пояснить за INNER JOINы да и в общем по построению БДшек. Прошу скинуть ему на почту советы/ссылки на полезные материалы по данному сабжу.
его почта : pvs9@list.ru
#372 #581848
>>581245

>подходит по цвету свитера или наклейке на ноуте


А у меня даже ноута нет.
#373 #581858
>>579831

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

>>580369

> Можно еще использовать простой sqlite для этого типа кеша


Я бы не советовал. Непонятно, как у sqlite обстоят дела с параллельным доступом. Она позиционируется встраиваемая база данных, то есть она встраивается в приложение и используется только им. Ну например, скайп хранит контакты и переписку в sqlite (и ты кстати можешь просматривать эти базы если тебе интересно и если они не зашифрованы), хром - историю и закладки, а в андроиде и iOS многие приложения хранят там настройки. Но как она будет работать при параллельном доступе к базе из большого числа процессов? Как я понимаю, никаких MVCC там нет и там при записи блокируется вся база.

Почитай-ка на досуге https://www.sqlite.org/lockingv3.html .

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

> Но я думаю, что на рабочем сервере вряд ли кто-то будет менять схему базы,


Разработчик будет например применять миграции.

>>580786

Есть 2 основных подхода реализации ORM: ActiveRecord и DataMapper.

>>580886

Вообще, для рекурсивного обхода массива есть готовая функция: array_walk_recursive, логично использовать ее.

Также, есть такая штука как итераторы (объекты для перебора списков), и стандартный итератор для рекурсивного обхода массива: http://php.net/manual/ru/class.recursivearrayiterator.php

> $findMax = function($arr) use (&$max, &$findMax) {


Непонятно зачем тут анонимная функция. Что мешает сделать такую же, но не анонимную? Ссылка на не нужна так как макс. значение можно вернуть через return. Таким образом, это бессмысленное усложнение кода.

> function($arr)


Тут нужен type hint

Вообще, в твоем коде все анонимные функции можно заменить на обычные. Значит, они тут не особо и нужны. Они для других ситуаций, например для использования вместе с usort, array_map, array_filter и тд.

Ну и ты конечно должен избегать ситуаций когда надо найти максимум в вложенных массивах. Лучше использовать плоский одноуровневый массив.
#373 #581858
>>579831

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

>>580369

> Можно еще использовать простой sqlite для этого типа кеша


Я бы не советовал. Непонятно, как у sqlite обстоят дела с параллельным доступом. Она позиционируется встраиваемая база данных, то есть она встраивается в приложение и используется только им. Ну например, скайп хранит контакты и переписку в sqlite (и ты кстати можешь просматривать эти базы если тебе интересно и если они не зашифрованы), хром - историю и закладки, а в андроиде и iOS многие приложения хранят там настройки. Но как она будет работать при параллельном доступе к базе из большого числа процессов? Как я понимаю, никаких MVCC там нет и там при записи блокируется вся база.

Почитай-ка на досуге https://www.sqlite.org/lockingv3.html .

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

> Но я думаю, что на рабочем сервере вряд ли кто-то будет менять схему базы,


Разработчик будет например применять миграции.

>>580786

Есть 2 основных подхода реализации ORM: ActiveRecord и DataMapper.

>>580886

Вообще, для рекурсивного обхода массива есть готовая функция: array_walk_recursive, логично использовать ее.

Также, есть такая штука как итераторы (объекты для перебора списков), и стандартный итератор для рекурсивного обхода массива: http://php.net/manual/ru/class.recursivearrayiterator.php

> $findMax = function($arr) use (&$max, &$findMax) {


Непонятно зачем тут анонимная функция. Что мешает сделать такую же, но не анонимную? Ссылка на не нужна так как макс. значение можно вернуть через return. Таким образом, это бессмысленное усложнение кода.

> function($arr)


Тут нужен type hint

Вообще, в твоем коде все анонимные функции можно заменить на обычные. Значит, они тут не особо и нужны. Они для других ситуаций, например для использования вместе с usort, array_map, array_filter и тд.

Ну и ты конечно должен избегать ситуаций когда надо найти максимум в вложенных массивах. Лучше использовать плоский одноуровневый массив.
Юи #374 #581860
>>580920

> В yii есть весьма странная на мой вгляд система ассетов, я в этой галиматье ничего не понял


Я тоже не очень понимаю, но тебе надо разобраться. В общем-то системы ассетов нужны. Так как мы при разработке хотим работать с кучей маленьких CSS-, JS-файликов, а в продакшене мы хотим отдавать 1-2 больших файла, причем часто еще и обработенных, например сжатых.

Также, есть другие задачи обработки статики:

- изготовление картинок меньших разрешений (для устройств с разной плотностью экранов)
- генерация fallback растровых картинок для браузеров не понимающих SVG
- генерация css-спрайтов для продакшена из отдельных картинок
- препроцессинг JS/CSS, склеивание, сжатие, обфускация

И удобнее всего когда это реализуется на уровне фреймворка, а не сторонними инструментами (вроде gulp). Потому ассеты и нужны. Как они реализованы в Юи, я в деталях не знаю. Предлагаю тебе разобраться, и, если есть желание, например реализовать склейку CSS/JS.

> Почему нельзя просто прописать тег script или link


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

> зачем эта запутанная система каких-то регистраций и публикаций скрипта?


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

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


Проверь по заголовку X-Powered-By

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


Лучше разобраться в ассетах. Как ты будешь реализовывать тогда описанные выше задачи?

> Так зачем нам кешировать сырые данные, а потом еще тратить время в скрипте на преобразование этих данных в html?


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

Насчет кеширования, прочитай-ка эту презентацию:

http://lib.custis.ru/WebAppCaching
http://lib.custis.ru/images/6/6d/WebAppCache.pdf

При кешировании надо всегда думать о таких вещах, как инвалидация кеша (сброс/обновление). Например если ты кешируешь список городов, то как и при каких условиях кеш инвалидируется? Надо думать об эффективности кеша. Например если мы кешируем результат SQL запроса, не дублируем ли мы функционал БД которая тоже их кеширует?

Также, обрати внимание что в Юи есть готовые средства для кеширования HTML: http://www.yiiframework.com/doc/guide/1.1/ru/caching.fragment

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

> Возможно ты мне приведешь какие-то доводы или подводные камни в пользу кеширования моделей или массивов


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

> (ты же сам часто ругал за вложенные массивы, зачем теперь мне это предлагаешь?).


Я писал что можно сделать легкие DTO объекты.

> А как сделать, чтобы моя библиотека specify автозагрузку?


Ничего больше не надо. Вот проверка: клонируем твою библиотеку через git clone, делаем composer install, пишем тестовый скрипт (плохо что нет тестового адаптера, я воспользовался тем что конструктор не проверяет что ему дали):

<?php
error_reporting(-1);
require 'vendor/autoload.php';
$p = new VisitCounter\Db\PdoAdapter(1);
var_dump($p);

Все запускается и создается, значит автозагрузка прописана правильно. На всякий случай попробуем еще подключить библиотеку в сторонний проект. Я создал пустую папку, composer.json, написал в него кое-что, сделал composer require твоей библиотеки, скопировал test.php - все работает.

Значит, в библиотеке автозагрузка прописана правильно.

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

https://getcomposer.org/doc/02-libraries.md#publishing-to-a-vcs
https://getcomposer.org/doc/05-repositories.md#loading-a-package-from-a-vcs-repository

> Да, добавил библиотеку в проект, классы не подгружаются.


Проверь на пустом проекте. То есть создай composer.json, сделай install и запусти test.php с моим кодом. Ну и почитай ссылки выше.

> Сбросить легче простого, нужно тупо очистить этот хеш, удалить все ключи из него.


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

> Другое дело, что логика усложняется мы оперируем уже тремя структурами в нашем коде, и с усложнением приходится нервничать по поводу атомарности.


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

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


Ну ладно, они вроде низкоуровневые, пусть будут.

> Ты говорил, что парсинг UA для быдла


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

> Встает вопрос: как узнать, что браузер не поддерживает куки?


Выдать заголовок Set-Cookie и проверить придет ли кука со следующим запросом на сервер. Также, в JS есть по моему navigator.cookieEnabled или как-то так. Выясни, если надо.

> я тогда сделаю говно-регулярку для ua вида /.+bot.+/


Тут я против так как браузер может называться например Robot. Это слишком ненадежно. Нужен именно список названий. Ну и еще можно воспользоваться тем, что у некоторых ботов стоит в UA +http://...

> Но у всех классов наследников конструктор абсолютно одинаковый


Ну нет. Как минимум конструктор PdoAdapter принимает PDO, а MysqliAdapter например принимает объект MySqli.

Я бы не сказал что они одинаковые. Они как раз разные.

> Ну ладно, если оно того стоит, то перенесу конструктор из абстрактного в финальные.


Так и надо. У тебя сейчас вообще тайп хинта никакого нет, понять что надо передавать, очень трудно.

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


Твиттер можно читать без регистрации если зайти например через twitter.com/search или напрямую в чей-то блог.

А, есть еще интересная задача: сделать свой ютьюб со скрепами и блекджеком. Интересно там то, что придется поработать с очередью задач, конвертированием видеофайлов, изготовлением превьюшек.
Юи #374 #581860
>>580920

> В yii есть весьма странная на мой вгляд система ассетов, я в этой галиматье ничего не понял


Я тоже не очень понимаю, но тебе надо разобраться. В общем-то системы ассетов нужны. Так как мы при разработке хотим работать с кучей маленьких CSS-, JS-файликов, а в продакшене мы хотим отдавать 1-2 больших файла, причем часто еще и обработенных, например сжатых.

Также, есть другие задачи обработки статики:

- изготовление картинок меньших разрешений (для устройств с разной плотностью экранов)
- генерация fallback растровых картинок для браузеров не понимающих SVG
- генерация css-спрайтов для продакшена из отдельных картинок
- препроцессинг JS/CSS, склеивание, сжатие, обфускация

И удобнее всего когда это реализуется на уровне фреймворка, а не сторонними инструментами (вроде gulp). Потому ассеты и нужны. Как они реализованы в Юи, я в деталях не знаю. Предлагаю тебе разобраться, и, если есть желание, например реализовать склейку CSS/JS.

> Почему нельзя просто прописать тег script или link


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

> зачем эта запутанная система каких-то регистраций и публикаций скрипта?


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

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


Проверь по заголовку X-Powered-By

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


Лучше разобраться в ассетах. Как ты будешь реализовывать тогда описанные выше задачи?

> Так зачем нам кешировать сырые данные, а потом еще тратить время в скрипте на преобразование этих данных в html?


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

Насчет кеширования, прочитай-ка эту презентацию:

http://lib.custis.ru/WebAppCaching
http://lib.custis.ru/images/6/6d/WebAppCache.pdf

При кешировании надо всегда думать о таких вещах, как инвалидация кеша (сброс/обновление). Например если ты кешируешь список городов, то как и при каких условиях кеш инвалидируется? Надо думать об эффективности кеша. Например если мы кешируем результат SQL запроса, не дублируем ли мы функционал БД которая тоже их кеширует?

Также, обрати внимание что в Юи есть готовые средства для кеширования HTML: http://www.yiiframework.com/doc/guide/1.1/ru/caching.fragment

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

> Возможно ты мне приведешь какие-то доводы или подводные камни в пользу кеширования моделей или массивов


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

> (ты же сам часто ругал за вложенные массивы, зачем теперь мне это предлагаешь?).


Я писал что можно сделать легкие DTO объекты.

> А как сделать, чтобы моя библиотека specify автозагрузку?


Ничего больше не надо. Вот проверка: клонируем твою библиотеку через git clone, делаем composer install, пишем тестовый скрипт (плохо что нет тестового адаптера, я воспользовался тем что конструктор не проверяет что ему дали):

<?php
error_reporting(-1);
require 'vendor/autoload.php';
$p = new VisitCounter\Db\PdoAdapter(1);
var_dump($p);

Все запускается и создается, значит автозагрузка прописана правильно. На всякий случай попробуем еще подключить библиотеку в сторонний проект. Я создал пустую папку, composer.json, написал в него кое-что, сделал composer require твоей библиотеки, скопировал test.php - все работает.

Значит, в библиотеке автозагрузка прописана правильно.

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

https://getcomposer.org/doc/02-libraries.md#publishing-to-a-vcs
https://getcomposer.org/doc/05-repositories.md#loading-a-package-from-a-vcs-repository

> Да, добавил библиотеку в проект, классы не подгружаются.


Проверь на пустом проекте. То есть создай composer.json, сделай install и запусти test.php с моим кодом. Ну и почитай ссылки выше.

> Сбросить легче простого, нужно тупо очистить этот хеш, удалить все ключи из него.


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

> Другое дело, что логика усложняется мы оперируем уже тремя структурами в нашем коде, и с усложнением приходится нервничать по поводу атомарности.


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

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


Ну ладно, они вроде низкоуровневые, пусть будут.

> Ты говорил, что парсинг UA для быдла


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

> Встает вопрос: как узнать, что браузер не поддерживает куки?


Выдать заголовок Set-Cookie и проверить придет ли кука со следующим запросом на сервер. Также, в JS есть по моему navigator.cookieEnabled или как-то так. Выясни, если надо.

> я тогда сделаю говно-регулярку для ua вида /.+bot.+/


Тут я против так как браузер может называться например Robot. Это слишком ненадежно. Нужен именно список названий. Ну и еще можно воспользоваться тем, что у некоторых ботов стоит в UA +http://...

> Но у всех классов наследников конструктор абсолютно одинаковый


Ну нет. Как минимум конструктор PdoAdapter принимает PDO, а MysqliAdapter например принимает объект MySqli.

Я бы не сказал что они одинаковые. Они как раз разные.

> Ну ладно, если оно того стоит, то перенесу конструктор из абстрактного в финальные.


Так и надо. У тебя сейчас вообще тайп хинта никакого нет, понять что надо передавать, очень трудно.

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


Твиттер можно читать без регистрации если зайти например через twitter.com/search или напрямую в чей-то блог.

А, есть еще интересная задача: сделать свой ютьюб со скрепами и блекджеком. Интересно там то, что придется поработать с очередью задач, конвертированием видеофайлов, изготовлением превьюшек.
#375 #581861
>>580951

500 мс тоже многовато. А может сделать профайлинг с кешированием?

И что насчет инвалидации?

>>580972

Мое мнение такое. Если таблица это список пользователей, то добавлять куку в таблицу надо только когда пользвоатель что-то делает, например загружает файл. Иначе зачем нам нужна запись в таблице? Да и генерировать кук тоже кстати можно только при первом совершении какого-то действия.

Если пользователь явно регистрируется то мы просто прописываем ему емайл/пароль и помечаем что он явно зарегистрирован. Все ранее загруженные им файлы остаются в его аккаунте и к ним сохраняется доступ - прекрасно.

При разлогинивании очевидно удаляем только куку. А пользователь который не регистрировался явно, он ведь и разлогиниться не может. Значит ему эта функция вообще не нужна.

>>581003

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

>>581007

Если у пользователя создан аккаунт то при разлогине кука удаляется. Если не создан, то функции logout нету и да, мамка может редактировать и удалять.

>>581014

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

>>581015

Открой инспектор (Ctrl + Shift + I) на вкладке Network и смотри заголовок Set-Cookie.

>>581259

Если нет других вакансий, придется чистить битрикс. Ну еще можно удаленно поискать работу. Поискать на других сайтах, кроме hh.

Вот например вакансия, нужен всего год опыта: http://spb.hh.ru/vacancy/15129197?query=php
Вот вакансия в Воронеже без опыта: http://career.ru/vacancy/14431043?query=php
Вот Нижний без опыта: http://career.ru/vacancy/15054034?query=php

Кстати, я вижу во многих вакансиях требуют ООП и/или фреймворки. Видеокурсы с рутрекера вас нормально этому не научат, а вот наш тред - научит.
#375 #581861
>>580951

500 мс тоже многовато. А может сделать профайлинг с кешированием?

И что насчет инвалидации?

>>580972

Мое мнение такое. Если таблица это список пользователей, то добавлять куку в таблицу надо только когда пользвоатель что-то делает, например загружает файл. Иначе зачем нам нужна запись в таблице? Да и генерировать кук тоже кстати можно только при первом совершении какого-то действия.

Если пользователь явно регистрируется то мы просто прописываем ему емайл/пароль и помечаем что он явно зарегистрирован. Все ранее загруженные им файлы остаются в его аккаунте и к ним сохраняется доступ - прекрасно.

При разлогинивании очевидно удаляем только куку. А пользователь который не регистрировался явно, он ведь и разлогиниться не может. Значит ему эта функция вообще не нужна.

>>581003

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

>>581007

Если у пользователя создан аккаунт то при разлогине кука удаляется. Если не создан, то функции logout нету и да, мамка может редактировать и удалять.

>>581014

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

>>581015

Открой инспектор (Ctrl + Shift + I) на вкладке Network и смотри заголовок Set-Cookie.

>>581259

Если нет других вакансий, придется чистить битрикс. Ну еще можно удаленно поискать работу. Поискать на других сайтах, кроме hh.

Вот например вакансия, нужен всего год опыта: http://spb.hh.ru/vacancy/15129197?query=php
Вот вакансия в Воронеже без опыта: http://career.ru/vacancy/14431043?query=php
Вот Нижний без опыта: http://career.ru/vacancy/15054034?query=php

Кстати, я вижу во многих вакансиях требуют ООП и/или фреймворки. Видеокурсы с рутрекера вас нормально этому не научат, а вот наш тред - научит.
Кошки-мышки #376 #581862
>>581275

6-10 месяцев.

>>581277

Ты написал, ты и разбирай.

> что такого могло остаться в логах


Проще всего посмотреть лог

>>581493

Я также мимопроходил и предупреждаю что в свойстве filename= можно указывать только символы ASCII (латинницу, цифры, но не русские буквы).

>>581596

А ведь ты наверно Вектор не показывал? показал бы. Там интересное дополнение есть про антикризисный план, и можно проверить есть ли пробелы в понимании ООП.

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

> public function tryToMove($field, $game)


Функцию определения возможных ходов надо вынести отдельно.

> private function escape($field)


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

Вообще, таких гигантских функций быть не должно.

Также, хорошо бы потихоньку осваивать гит, гитхаб и выкладывать код туда. Учебник по гиту: https://git-scm.com/book/ru/v1/%D0%9E%D1%81%D0%BD%D0%BE%D0%B2%D1%8B-Git

> abstract protected function tryToMove($field, $game);


Неудобно везде передавать $field, лучше сделать его свойством класса. автоматически проставлять при добавлении животного на карту и убирать (ставить null) при снятии.

> $this->name = $name;


В классе Animal нет поля name, значит нельзя к нему обращаться. Надо либо перенести name в Animal либо убрать эту строчку.

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

> //Имя животного - мурзик, барсик etc.


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

> protected function nearbyAnimal


Имя функции надо начинать с глагола, сделайЧтоТо()

> //Метод будет искать ближайшего врага, иногда их будет несколько


Это лучше написать перед функцией, а не справа

> $nearbyAnimal = array();


> $nearbyAnimal[0] = $animal;


Это можно писать в одну строчку. также, в PHP5.4 вместо array() можно писать []

> protected function nearbyAnimal($animals)


Эта функция возвращает массив сложной структуры. Зачем если ее цель найти животное, и животное у нас представлено объектом. Значит надо возвращать объект.

> protected function getName($y, $x, $animals) //Метод определяющий имя животного по его координатам


Непонятно что этот метод делает в классе Animal. Очевидно за хранение списка животных и предоставление информации о них отвечает Field.

> if ($countSteps['x'] > $countSteps['y']) {


Есть функция max()

> protected function moveTo($direction)


Почему передается массив, а не координаты по отдельности? какое в этом преимущество?

> $this->searchForEnemies($field, $game);


Странно, функция называется «найти врагов», но она ничего не возвращает. Что же она делает с результатом?

> tryToMove($field, $game)


Нужно ставить тайп-хинты.

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

Мануал: http://php.net/manual/ru/language.oop5.typehinting.php

> if ($move['x'] < $field->width / 2) { //Ближе левый край


> if (($this->y - $game->mouseVision) < 1 ) {


Эти ифы можно заменить на min()/max()

> $regexpForCats = '/[K@]/ui'; //Ищем кошек


На надо так искать кошек, у тебя же есть объекты, а для них есть оператор проверки класса instanceof.

> private function searchForEnemies($field, $game)


Метод поиска животных в определенном квадрате логичнее поместить в Field.

> if ($move['x'] != 0 && //Ход не должен быть дальше карты


Это должно быть в Field

> private function searchForDogs($field, $game)


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

> class Field {


> public $field = array(); //Поле в двухмерном массиве


зачем хранить этот массив?

> public function placeTheAnimals(


Тут куча копипасты, удаляй.

> class Game


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

> public function start($field, $game)


Слишком длинный метод, разбивай на части

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

В общем, исправь пока это, и готовься, тут много переделывать, в итоге придется почти все переписать.
Кошки-мышки #376 #581862
>>581275

6-10 месяцев.

>>581277

Ты написал, ты и разбирай.

> что такого могло остаться в логах


Проще всего посмотреть лог

>>581493

Я также мимопроходил и предупреждаю что в свойстве filename= можно указывать только символы ASCII (латинницу, цифры, но не русские буквы).

>>581596

А ведь ты наверно Вектор не показывал? показал бы. Там интересное дополнение есть про антикризисный план, и можно проверить есть ли пробелы в понимании ООП.

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

> public function tryToMove($field, $game)


Функцию определения возможных ходов надо вынести отдельно.

> private function escape($field)


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

Вообще, таких гигантских функций быть не должно.

Также, хорошо бы потихоньку осваивать гит, гитхаб и выкладывать код туда. Учебник по гиту: https://git-scm.com/book/ru/v1/%D0%9E%D1%81%D0%BD%D0%BE%D0%B2%D1%8B-Git

> abstract protected function tryToMove($field, $game);


Неудобно везде передавать $field, лучше сделать его свойством класса. автоматически проставлять при добавлении животного на карту и убирать (ставить null) при снятии.

> $this->name = $name;


В классе Animal нет поля name, значит нельзя к нему обращаться. Надо либо перенести name в Animal либо убрать эту строчку.

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

> //Имя животного - мурзик, барсик etc.


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

> protected function nearbyAnimal


Имя функции надо начинать с глагола, сделайЧтоТо()

> //Метод будет искать ближайшего врага, иногда их будет несколько


Это лучше написать перед функцией, а не справа

> $nearbyAnimal = array();


> $nearbyAnimal[0] = $animal;


Это можно писать в одну строчку. также, в PHP5.4 вместо array() можно писать []

> protected function nearbyAnimal($animals)


Эта функция возвращает массив сложной структуры. Зачем если ее цель найти животное, и животное у нас представлено объектом. Значит надо возвращать объект.

> protected function getName($y, $x, $animals) //Метод определяющий имя животного по его координатам


Непонятно что этот метод делает в классе Animal. Очевидно за хранение списка животных и предоставление информации о них отвечает Field.

> if ($countSteps['x'] > $countSteps['y']) {


Есть функция max()

> protected function moveTo($direction)


Почему передается массив, а не координаты по отдельности? какое в этом преимущество?

> $this->searchForEnemies($field, $game);


Странно, функция называется «найти врагов», но она ничего не возвращает. Что же она делает с результатом?

> tryToMove($field, $game)


Нужно ставить тайп-хинты.

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

Мануал: http://php.net/manual/ru/language.oop5.typehinting.php

> if ($move['x'] < $field->width / 2) { //Ближе левый край


> if (($this->y - $game->mouseVision) < 1 ) {


Эти ифы можно заменить на min()/max()

> $regexpForCats = '/[K@]/ui'; //Ищем кошек


На надо так искать кошек, у тебя же есть объекты, а для них есть оператор проверки класса instanceof.

> private function searchForEnemies($field, $game)


Метод поиска животных в определенном квадрате логичнее поместить в Field.

> if ($move['x'] != 0 && //Ход не должен быть дальше карты


Это должно быть в Field

> private function searchForDogs($field, $game)


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

> class Field {


> public $field = array(); //Поле в двухмерном массиве


зачем хранить этот массив?

> public function placeTheAnimals(


Тут куча копипасты, удаляй.

> class Game


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

> public function start($field, $game)


Слишком длинный метод, разбивай на части

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

В общем, исправь пока это, и готовься, тут много переделывать, в итоге придется почти все переписать.
#377 #581863
>>581597

Создай себе хост вроде neko.local и пропиши в hosts

>>581719

1 задание

> Условие невнятное. 66% от ширины родителя?


Согласен. Идея в том что там поля 10px, и 66% считается от внутренней ширины.

У тебя решено верно.

2 задание

> С учетом border?


да.

> .parent {


> padding: 10px;


Можно было на body прописать

В общем верно, хотя можно было и без box-sizing обойтись. Можно и с ним.

3 задание

> Почему не span


Чтобы дать понять что любые свойства по умолчанию можно менять.

Решено правильно.

4 задание

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


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

В будущем когда везде будет поддерживаться flexbox, нам не придется использовать inline-block для горизонтального расположения элементов с выравниванием и проблема решится сама собой.

> <p class="yellow top">


Выбор тега неудачный, p обозначает абзац текста и тут явно не абзац. Лучше div/span.

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

> У меня на xfce дико лагает пипетка в инструментах мозиллы.


Гимп поставь и в нем меряй. Или отдельную программу-пипетку, если знаешь такие.

5 задание

> Наверное там какой-то подвох, что-то подозрительно легкое.


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

Решено верно.
#377 #581863
>>581597

Создай себе хост вроде neko.local и пропиши в hosts

>>581719

1 задание

> Условие невнятное. 66% от ширины родителя?


Согласен. Идея в том что там поля 10px, и 66% считается от внутренней ширины.

У тебя решено верно.

2 задание

> С учетом border?


да.

> .parent {


> padding: 10px;


Можно было на body прописать

В общем верно, хотя можно было и без box-sizing обойтись. Можно и с ним.

3 задание

> Почему не span


Чтобы дать понять что любые свойства по умолчанию можно менять.

Решено правильно.

4 задание

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


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

В будущем когда везде будет поддерживаться flexbox, нам не придется использовать inline-block для горизонтального расположения элементов с выравниванием и проблема решится сама собой.

> <p class="yellow top">


Выбор тега неудачный, p обозначает абзац текста и тут явно не абзац. Лучше div/span.

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

> У меня на xfce дико лагает пипетка в инструментах мозиллы.


Гимп поставь и в нем меряй. Или отдельную программу-пипетку, если знаешь такие.

5 задание

> Наверное там какой-то подвох, что-то подозрительно легкое.


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

Решено верно.
#378 #581864
>>581727

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

>>581738

> font: 14px/1.4 "Trebuchet MS";


Где фоллбек на один из стандартных шрифтов?

> .content {


> padding: 10px;


Можно на body поставить

> .clearfix:after {


Ты понимаешь что делает каждая строчка тут? Есть ли лишние?

Заголовок на картинке сделан не-жирным шрифтом, у тебя жирный.

> ul {


> margin: 0;


Ты меняешь стили для всех списков. Это неправильно, ведь в тексте тоже может встретиться список. Старайся менять только стили для нужного элемента, а не все подряд.

> li {


> line-height: 1.7em;


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

>>581844

Задание 1

> body{


> margin: 10px;


В некоторых браузерах поля могут быть заданы не на body, а на html, и не маргином а паддингом. Я бы на всяких случай их очистил.

> .purple-block {


> margin-left: 34%;


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

Задание 2

> overflow: hidden;


> text-overflow: clip;


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

В остальном верно.

Задание 3

> em {


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

Задание 4

> <p class="yellow-block one"


Тег p не очень подходит, он обозначает абзац текста.

> margin: 0 10px 0 -4px;


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

Задание 5

Ок, все верно.

Задание 6

> h1 {


> clear: right;


Не очень понятно зачем это, так как перед h1 нет ни одного флоата. Зачем это тут?

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

> nav {


> min-width: 200px;


Почему min-width? Меню может расти в ширину? А контент в этом случае отъедет вправо?

> min-height: 1px;


зачем?

> width: calc(100% - 230px);


Это наверно только в новых браузерах поддерживается? Я думаю, такую вещь как верстку в 2 колонки, можно сделать и без этого.

В данном случае все проще. Просто сделай контент обычным блоком с margin-left. Тогда он никуда не уедет со своего места даже если убрать nav.
#378 #581864
>>581727

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

>>581738

> font: 14px/1.4 "Trebuchet MS";


Где фоллбек на один из стандартных шрифтов?

> .content {


> padding: 10px;


Можно на body поставить

> .clearfix:after {


Ты понимаешь что делает каждая строчка тут? Есть ли лишние?

Заголовок на картинке сделан не-жирным шрифтом, у тебя жирный.

> ul {


> margin: 0;


Ты меняешь стили для всех списков. Это неправильно, ведь в тексте тоже может встретиться список. Старайся менять только стили для нужного элемента, а не все подряд.

> li {


> line-height: 1.7em;


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

>>581844

Задание 1

> body{


> margin: 10px;


В некоторых браузерах поля могут быть заданы не на body, а на html, и не маргином а паддингом. Я бы на всяких случай их очистил.

> .purple-block {


> margin-left: 34%;


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

Задание 2

> overflow: hidden;


> text-overflow: clip;


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

В остальном верно.

Задание 3

> em {


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

Задание 4

> <p class="yellow-block one"


Тег p не очень подходит, он обозначает абзац текста.

> margin: 0 10px 0 -4px;


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

Задание 5

Ок, все верно.

Задание 6

> h1 {


> clear: right;


Не очень понятно зачем это, так как перед h1 нет ни одного флоата. Зачем это тут?

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

> nav {


> min-width: 200px;


Почему min-width? Меню может расти в ширину? А контент в этом случае отъедет вправо?

> min-height: 1px;


зачем?

> width: calc(100% - 230px);


Это наверно только в новых браузерах поддерживается? Я думаю, такую вещь как верстку в 2 колонки, можно сделать и без этого.

В данном случае все проще. Просто сделай контент обычным блоком с margin-left. Тогда он никуда не уедет со своего места даже если убрать nav.
#379 #581906
Интересная статья про CSRF в VK Api: http://m.habrahabr.ru/post/271031/

Чтобы ее понять, вам надо разобраться с тем что такое JSONP (древний способ обмена данными со страницы с другим доменом).

Тут получается довольно интересный вывод, в случае использования JSONP нет надежного способа проверить домен-отправитель запроса, проверка по Referer не работает.
#380 #581932
>>581864

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


Почему ты так говоришь? Это же не правда.
#381 #581938
>>581932

Конечно неправда.
#382 #582013
>>581932
Тут суть не в возрасте, а в том что человек наверняка все эти годы бездельничал. А в программировании требуется огромная трудоспособность и желание этим заниматься, это занятие должно стать чуть ли не смыслом жизни.
Есть большие сомнения, что человек, провалявшийся до 30 лет на печи, вдруг станет трудолюбивым, ответственным и квалифицированным программистом.
Поэтому к таким относятся с подозрением.
В веб лезет очень много быдла, которое на сосаче наслушалось влажных фантазий студентов-первокурсников о больших зарплатах.

Одним словом, претензия не к возрасту а к лени.
#383 #582022
>>582013
Убедительно. Теперь я тоже так буду отвечать.
#384 #582025
>>582013

>Тут суть не в возрасте, а в том что человек наверняка все эти годы бездельничал.


На это могут закрыть глаза, если ты на собеседовании докажешь серьёзность своих намерений хорошими (для новичка) знаниями баз данных и пониманием (именном пониманием, а не вызубренными определениями) основных концепций ООП, например. А мне это не кажется невозможным.
#385 #582058
>>582013
Ты из тех кого мама в детстве запугала работой дворника, если не будешь ебашить 24\7?
#386 #582117
>>581860

>Там в документации есть пример где прямо в шаблоне пишется SQL запрос проверки актуальности кеша - он ужасен.


Я учусь по документации, если ты говоришь, что там неправильно, то тогда не знаю даже по каким материалам учиться.
Может, ты имеешь ввиду что нужно вынести зависимость в переменную и передавать ее из контроллера?
Вот это место?
<?php if($this->beginCache($id, array('dependency'=>array(
'class'=>'system.caching.dependencies.CDbCacheDependency',
'sql'=>'SELECT MAX(lastModified) FROM Post')))) { ?>
Я думаю, что они типа для краткости так сделали, чтобы не писать код и в контроллере, и в представлении, но это действительно только запутывает.

Встает тогда вопрос, каким запросом мне отслеживать эту актуальность кеша? Вот например таблица с городами или регионами, например из нее кто-то удаляет город (маловероятно, что это произойдет, обычно добавляют а не удаляют, но все же). Да, нужно при каждом запросе проверять, актуален ли кеш, потому что если у кого-то закешированые старые данные и он выберет город, который был удален, то все упадет, потому что такого id, по которому мы ищем, уже нет.
Проверочный запрос как будет выглядеть? Неужели мне специально придется добавить в таблицу городов и регионов колонку с временем создания/модификации? По-моему чудовищная избыточность ради сомнительной выгоды актуальности кеша.
Кроме времени модификации таблицы, не могу придумать, по какому признаку отслеживать актуальность кеша.
О, может засандалить отдельную табличку, которая будет содержать даты последнего обновления нужных таблиц?
Геморрой короче какой-то.
Не знаю, что делать с инвалидацией, или как это называется. Легче всего просто выставить время жизни элементам кеша, но без правил проверки актуальности могут быть конечно неприятности.

> Я создал пустую папку, composer.json, написал в него кое-что,


Что "кое-что"? Колись давай. Я же все равно не отстану.
-------------------------------------------------------------------
Тут было несколько десятков строк рейджа, но я их удалил, когда понял что сам протупил. http://pastebin.com/sFJWBP4s
-------------------------------------------------------------------
Упс, в результате оказалось, что я тупо ошибся в пространстве имен своего класса:
вместо $adapter = new VisitCounter\Redis\RediskaAdapter;
написал $adapter = new VisitCounter\Redis\Rediska;
Потому его и не находил автозагрузчик. Черт.
Ну что ж, не могу себя не похвалить за настойчивость, хотя с внимательностью надо что-то делать. Наверное, ложиться спать в 4 часа утра вредно для сообразительности, нужно менять график.

Тем не менее вопросы по автозагрузке композера у меня еще есть, именно к мутным местам мануала.
Например вот такая структура composer.json
{
"repositories": [
{
"type": "vcs",
"url": "https://github.com/username/hello-world"
}
],
"require": {
"acme/hello-world": "dev-master"
}
}
Вопрос: каким образом композер догадывается, к какому пакету из перечисленных в require, относится конкретный репозиторий из списка перечисленных в "repositories"?
По url? Да не похоже, ведь пакет у нас называется "acme/hello-world", а url заканчивается на "username/hello-world".
Может, по содержимому composer.json каждого из репозиториев? Он их в цикле перебирает, что ли?

Вот я запускаю composer install, он (скрипт композера) начинает перебирать перечисленные в require пакеты. Сначала он тыкается на packagist, если его там не находит, тогда просматривает блок "repositories". Вопрос в том, как он их (перечисленные в require пакеты и перечисленные в repositories источники) между собой связывает? Неужели при попытке найти "acme/hello-world" он будет в цикле лазить по всем перечисленным в repositories, пока не найдет в composer.json какого-то из них строку "name": "acme/hello-world"?
#386 #582117
>>581860

>Там в документации есть пример где прямо в шаблоне пишется SQL запрос проверки актуальности кеша - он ужасен.


Я учусь по документации, если ты говоришь, что там неправильно, то тогда не знаю даже по каким материалам учиться.
Может, ты имеешь ввиду что нужно вынести зависимость в переменную и передавать ее из контроллера?
Вот это место?
<?php if($this->beginCache($id, array('dependency'=>array(
'class'=>'system.caching.dependencies.CDbCacheDependency',
'sql'=>'SELECT MAX(lastModified) FROM Post')))) { ?>
Я думаю, что они типа для краткости так сделали, чтобы не писать код и в контроллере, и в представлении, но это действительно только запутывает.

Встает тогда вопрос, каким запросом мне отслеживать эту актуальность кеша? Вот например таблица с городами или регионами, например из нее кто-то удаляет город (маловероятно, что это произойдет, обычно добавляют а не удаляют, но все же). Да, нужно при каждом запросе проверять, актуален ли кеш, потому что если у кого-то закешированые старые данные и он выберет город, который был удален, то все упадет, потому что такого id, по которому мы ищем, уже нет.
Проверочный запрос как будет выглядеть? Неужели мне специально придется добавить в таблицу городов и регионов колонку с временем создания/модификации? По-моему чудовищная избыточность ради сомнительной выгоды актуальности кеша.
Кроме времени модификации таблицы, не могу придумать, по какому признаку отслеживать актуальность кеша.
О, может засандалить отдельную табличку, которая будет содержать даты последнего обновления нужных таблиц?
Геморрой короче какой-то.
Не знаю, что делать с инвалидацией, или как это называется. Легче всего просто выставить время жизни элементам кеша, но без правил проверки актуальности могут быть конечно неприятности.

> Я создал пустую папку, composer.json, написал в него кое-что,


Что "кое-что"? Колись давай. Я же все равно не отстану.
-------------------------------------------------------------------
Тут было несколько десятков строк рейджа, но я их удалил, когда понял что сам протупил. http://pastebin.com/sFJWBP4s
-------------------------------------------------------------------
Упс, в результате оказалось, что я тупо ошибся в пространстве имен своего класса:
вместо $adapter = new VisitCounter\Redis\RediskaAdapter;
написал $adapter = new VisitCounter\Redis\Rediska;
Потому его и не находил автозагрузчик. Черт.
Ну что ж, не могу себя не похвалить за настойчивость, хотя с внимательностью надо что-то делать. Наверное, ложиться спать в 4 часа утра вредно для сообразительности, нужно менять график.

Тем не менее вопросы по автозагрузке композера у меня еще есть, именно к мутным местам мануала.
Например вот такая структура composer.json
{
"repositories": [
{
"type": "vcs",
"url": "https://github.com/username/hello-world"
}
],
"require": {
"acme/hello-world": "dev-master"
}
}
Вопрос: каким образом композер догадывается, к какому пакету из перечисленных в require, относится конкретный репозиторий из списка перечисленных в "repositories"?
По url? Да не похоже, ведь пакет у нас называется "acme/hello-world", а url заканчивается на "username/hello-world".
Может, по содержимому composer.json каждого из репозиториев? Он их в цикле перебирает, что ли?

Вот я запускаю composer install, он (скрипт композера) начинает перебирать перечисленные в require пакеты. Сначала он тыкается на packagist, если его там не находит, тогда просматривает блок "repositories". Вопрос в том, как он их (перечисленные в require пакеты и перечисленные в repositories источники) между собой связывает? Неужели при попытке найти "acme/hello-world" он будет в цикле лазить по всем перечисленным в repositories, пока не найдет в composer.json какого-то из них строку "name": "acme/hello-world"?
#387 #582126
>>582117

Нет, инвалидацию кеша обычно делают очисткой ключа с городами при добавлении или удалении города (что редко случается). делать проверку каждый раз при чтении кеша неэффективно.
#388 #582162
>>582117

Для начала можно почитать про репозитории тут (ответа как композер знает где какой пакет там нет): https://getcomposer.org/doc/05-repositories.md#concepts

затем глянуть исходники:

https://github.com/composer/composer/blob/master/src/Composer/Command/InstallCommand.php

далее

https://github.com/composer/composer/blob/master/src/Composer/Installer.php#L403

затем

https://github.com/composer/composer/blob/master/src/Composer/DependencyResolver/Pool.php#L86

Он что-т делает с объектом $repo, для VCS это вот этот класс:

https://github.com/composer/composer/blob/master/src/Composer/Repository/VcsRepository.php#L153

Для гитхаба вызывается этот метод

https://github.com/composer/composer/blob/master/src/Composer/Repository/Vcs/GitHubDriver.php#L142

И вот здесь вот

https://github.com/composer/composer/blob/master/src/Composer/Repository/Vcs/GitHubDriver.php#L156

Скачивается файл composer.json через API гитхаба.

То есть видимо для каждого репозитория в списке (паккаджист + дополнительные) скачивается список пакетов в них. Для VCS репозитория это единственный пакет, опсианный в composer.json.

Если есть время, посмотри на код композера, он вроде достаточно современный и объектно-ориентированный, может что интересное увидишь.
#388 #582162
>>582117

Для начала можно почитать про репозитории тут (ответа как композер знает где какой пакет там нет): https://getcomposer.org/doc/05-repositories.md#concepts

затем глянуть исходники:

https://github.com/composer/composer/blob/master/src/Composer/Command/InstallCommand.php

далее

https://github.com/composer/composer/blob/master/src/Composer/Installer.php#L403

затем

https://github.com/composer/composer/blob/master/src/Composer/DependencyResolver/Pool.php#L86

Он что-т делает с объектом $repo, для VCS это вот этот класс:

https://github.com/composer/composer/blob/master/src/Composer/Repository/VcsRepository.php#L153

Для гитхаба вызывается этот метод

https://github.com/composer/composer/blob/master/src/Composer/Repository/Vcs/GitHubDriver.php#L142

И вот здесь вот

https://github.com/composer/composer/blob/master/src/Composer/Repository/Vcs/GitHubDriver.php#L156

Скачивается файл composer.json через API гитхаба.

То есть видимо для каждого репозитория в списке (паккаджист + дополнительные) скачивается список пакетов в них. Для VCS репозитория это единственный пакет, опсианный в composer.json.

Если есть время, посмотри на код композера, он вроде достаточно современный и объектно-ориентированный, может что интересное увидишь.
#389 #582163
>>582126
Ты как всегда прав, вот что значит опыт.
Тогда появляется следующая проблема, ну не проблема а скорее вопрос Кстати слово "проблема" пришло из греческого: у греков парламент назывался "буле", соответственно "пробулема" это всего лишь вопрос на повестке дня
Города и прочий контент будут редактироваться в админке. Админку может быть будет писать другой программист, ему придется дописать код очистки кеша при экшене удаления/добавления города, да и я сам не вспомню, что было закешировано.
Если речь идет о кешировании фрагментов страниц, то тут вообще код кеширования натыкан по представлениям.
Как-то нехорошо получается.

Кажется, эту проблему позволит решить система тегов, упомянутая тут http://lib.custis.ru/WebAppCaching
Мне тяжело если честно переварить такие объемы информации, что поделать, придется разбираться.
#390 #582170
>>582117

> То есть видимо для каждого репозитория в списке (паккаджист + дополнительные) скачивается список пакетов в них


Ну откуда в списке взялся паккаджист думаю. очевидно: он включен туда по умолчанию. Для него список пакетов хранится в package.json или нескольких таких файлах, это описано в документации, но это не очень важно если только ты не создаешь свой репозиторий.
#391 #582171
>>582163

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

И да, работу с кешем хорошо бы как-то поместить в класс.
#392 #582172
>>582163

А! Я вспомнил чем плох кеш в редисе! Его нельзя очистить без потери данных о посещениях.

Надо его как минимум в базе под отдельным номером хранить и может сделать cli скрипт очистки - он тебе же может и пригодится.
#393 #582174
>>582117

> Что "кое-что"? Колись давай.


если у тебя работает то теперь уже не важно. Там просто чуть подправленный кусок composer.json из документации.

> Упс, в результате оказалось, что я тупо ошибся в пространстве имен своего класса:


Вот потому важно при наличии бага иметь описание как его воспроизвести. Чтобы например я (или ты сам) мог повторить действия и увидеть что все сломалось или все работает. Ну то есть по шагам, создать папку, склонировать репозиторий, создать такой-то файл и тд.
#394 #582189
>>582174
Это ты меня подводишь к теме баг-трекеров? А я уже где-то выше про них спрашивал, ты привел пару ссылок на багтрекер мозиллы и yii2. >>580824
У yii в issues просто какой-то бложик, где чуваки своими словами говорят: "вот я короче пишу так-то и так-то, и оно не работает". Я себе представлял более формализованную систему, типа таблицы в бд.
У фаерфокса более похоже на строгую систему, но пока тоже не очень ясно, как с этим делом работать.

Может мне потрогать какую-нибудь популярную программу (или как это называется) для баг-трекинга конкретно в php?
Какие кстати самые популярные? (нагуглил пока mantis и redmine со слов беспруфных крокодилов с аскдев и stackoverflow). С какими сам работал, что рекомендуешь, какие у них есть преимущества и недостатки?

Хочется просто обезопасить себя, а то вот приду на работу, а мне скажут "напиши баг-репорт" или "пофикси баг под номером 12345", а я не буду знать, что это такое и как там все организовано. Вряд ли мне кто-то будет это сидеть и объяснять полдня, так что надо сейчас побольше нахвататься.
#395 #582196
>>578124 (OP)
ох, спасибо тебе, антоша, много полезного почерпнул. Добра тебе :3
37 Кб, 400x533
#396 #582245
Суровых дней сухие листья
Суровых взор морщины смерти
Я умираю вирус смерти
#397 #582338
>>582245
Я, кстати, так и не понял, как сделать эту задачу из ОПовского учебника.
Такие дела.
#398 #582339
>>582338
Еще не поздно понять.
#399 #582355
>>582338
Изи же. Пояснить?
#400 #582365
ОП, а ты в офисе работаешь или на удалёнке/фрилансишь?
42 Кб, 1288x416
#401 #582504
>>581860
Насчет меньших разрешений и прочих манипуляций с графикой, то в yii такого нет, насколько я знаю. Главная цель ассетов в том, чтобы Владимир и Василий, работающие над двумя разными модулями, могли одновременно создать файл style.css, чтобы не было конфликта имен. Этот самый ассет менеджер копирует ресурсы в папки, имена которых представляет хеш полного пути, таким образом все ресурсы собираются в одном месте и при этом их имена не конфликтуют.
Таким образом можно и через композер подгружать все клиентские штуковины, менеджер ресурсов их потом опубликует в доступную из веба директорию.
Но как это работает на внутреннем уровне я пока не могу разобраться, и у меня по прежнему статика отдается по 200 мс за штучку.
Что поделать, придется смотреть исходный код фреймворка, чтобы понять что происходит. Безблагодатность какая-то. Нет нормальных мануалов, все самому приходится выяснять, что за жизнь.

>Например если мы кешируем результат SQL запроса, не дублируем ли мы функционал БД которая тоже их кеширует?


А я вот об этом думал, казалось бы база должна кешировать запросы, а что-то не заметно. Ведь тогда кеширование на клиенте не дало бы эффекта, а у меня стало работать в полтора раза быстрее. Это наверное потому что база кеширует результат запроса в табличном виде, а у меня в приложении этот результат затем преобразуется в тяжелые модели, а потом еще и рендерится в html. Так что я считаю что вполне оправдано в данном случае "продублировать" кеш базы. Как минимум из-за рендера.

>>582171
События + отдельный класс, все по делу, данке шон.
>>582189
Только что установил мантис, оказывается это тупо графический интерфейс типа phpmyadmin, только еще более уебищный.
Например я минут пять искал при создании нового репорта, как же обозначить к какому проекту он относится? Выпадающий список с проектами оказался в правом верхнем углу, отдельно от прочих настроек и микроскопического размера (пикрелейтед).
Ну ладно, по крайней мере пощупал что это такое. Баг-трекер как я понял просто база (с каким-нибудь интерфейсом), в которой ведется учет ошибок (багов) в формальном (табличном) виде, таким образом ни одна ошибка не останется незамеченной и неисправлненной, можно получить отчет по тому, кто какие баги пофиксил (а возможно и чья жизнедеятельность стала причиной данного бага).

>>581864

> .clearfix:after { display: block; content: ""; clear: both; }


> Ты понимаешь что делает каждая строчка тут? Есть ли лишние?


По отдельности понимаю каждую строчку, а как они взаимодействуют в решении проблемы с выпадающим флоатом - не очень.
По поводу clear: both, то на htmlbook написана какая-то хуйня

>Устанавливает, с какой стороны элемента запрещено его обтекание другими элементами.


Как заметил в комментариях товарищ skvor, это неправильный перевод спецификации

>This property indicates which sides of an element's box(es) may not be adjacent to an earlier floating box.


http://www.w3.org/TR/CSS21/visuren.html
Показывает, какие стороны контейнера элемента не могут примыкать к предшествующему плавающему элементу. (Хотя мое знание английского тоже неважное конечно, здесь неясность относительно того, что они назвали box - контейнер элемента или сам элемент)
display: block нужен, потому что clear вроде бы работает только с блочными элементами.

> Applies to: \tblock-level elements


content:"" контент вроде бы является обязательным для псевдоэлементов before и after, иначе они будут проигнорированы. Но я не уверен.

Насчет line-height для элементов списка это конечно я от усталости, нужно было через margin.
Какой-то чувак начал делать синхронно со мной задачи на верстку. Наверное к дождю.

Седьмая задача.
http://jsfiddle.net/s1qnngxa/1/
42 Кб, 1288x416
#401 #582504
>>581860
Насчет меньших разрешений и прочих манипуляций с графикой, то в yii такого нет, насколько я знаю. Главная цель ассетов в том, чтобы Владимир и Василий, работающие над двумя разными модулями, могли одновременно создать файл style.css, чтобы не было конфликта имен. Этот самый ассет менеджер копирует ресурсы в папки, имена которых представляет хеш полного пути, таким образом все ресурсы собираются в одном месте и при этом их имена не конфликтуют.
Таким образом можно и через композер подгружать все клиентские штуковины, менеджер ресурсов их потом опубликует в доступную из веба директорию.
Но как это работает на внутреннем уровне я пока не могу разобраться, и у меня по прежнему статика отдается по 200 мс за штучку.
Что поделать, придется смотреть исходный код фреймворка, чтобы понять что происходит. Безблагодатность какая-то. Нет нормальных мануалов, все самому приходится выяснять, что за жизнь.

>Например если мы кешируем результат SQL запроса, не дублируем ли мы функционал БД которая тоже их кеширует?


А я вот об этом думал, казалось бы база должна кешировать запросы, а что-то не заметно. Ведь тогда кеширование на клиенте не дало бы эффекта, а у меня стало работать в полтора раза быстрее. Это наверное потому что база кеширует результат запроса в табличном виде, а у меня в приложении этот результат затем преобразуется в тяжелые модели, а потом еще и рендерится в html. Так что я считаю что вполне оправдано в данном случае "продублировать" кеш базы. Как минимум из-за рендера.

>>582171
События + отдельный класс, все по делу, данке шон.
>>582189
Только что установил мантис, оказывается это тупо графический интерфейс типа phpmyadmin, только еще более уебищный.
Например я минут пять искал при создании нового репорта, как же обозначить к какому проекту он относится? Выпадающий список с проектами оказался в правом верхнем углу, отдельно от прочих настроек и микроскопического размера (пикрелейтед).
Ну ладно, по крайней мере пощупал что это такое. Баг-трекер как я понял просто база (с каким-нибудь интерфейсом), в которой ведется учет ошибок (багов) в формальном (табличном) виде, таким образом ни одна ошибка не останется незамеченной и неисправлненной, можно получить отчет по тому, кто какие баги пофиксил (а возможно и чья жизнедеятельность стала причиной данного бага).

>>581864

> .clearfix:after { display: block; content: ""; clear: both; }


> Ты понимаешь что делает каждая строчка тут? Есть ли лишние?


По отдельности понимаю каждую строчку, а как они взаимодействуют в решении проблемы с выпадающим флоатом - не очень.
По поводу clear: both, то на htmlbook написана какая-то хуйня

>Устанавливает, с какой стороны элемента запрещено его обтекание другими элементами.


Как заметил в комментариях товарищ skvor, это неправильный перевод спецификации

>This property indicates which sides of an element's box(es) may not be adjacent to an earlier floating box.


http://www.w3.org/TR/CSS21/visuren.html
Показывает, какие стороны контейнера элемента не могут примыкать к предшествующему плавающему элементу. (Хотя мое знание английского тоже неважное конечно, здесь неясность относительно того, что они назвали box - контейнер элемента или сам элемент)
display: block нужен, потому что clear вроде бы работает только с блочными элементами.

> Applies to: \tblock-level elements


content:"" контент вроде бы является обязательным для псевдоэлементов before и after, иначе они будут проигнорированы. Но я не уверен.

Насчет line-height для элементов списка это конечно я от усталости, нужно было через margin.
Какой-то чувак начал делать синхронно со мной задачи на верстку. Наверное к дождю.

Седьмая задача.
http://jsfiddle.net/s1qnngxa/1/
#402 #582509
>>582355
Поясни. Без решения только.
#403 #582538
>>582509
Рандомь индексы.
#404 #582558
>>582504

Восьмое задание.
http://jsfiddle.net/thpsf41o/

>верстка должна позволять без изменения CSS дописать или убрать любое число абзацев,


Куда дописать? В правую колонку? Попытался предусмотреть.

>не задавай поля с помощью margin на <p>


Это еще почему? Или имеются ввиду внешние границы? В общем, сделал левую колонку плавающей влево и параграф с отступом слева.
#405 #582597
>>582538
Это слишком легко, есть возможность повторяющихся слов. А вот как заставить рандом исключать уже зарандомившийся индекс - не объясняется, мои две с половиной извилины сами до этого додуматься на могут. С задачкой на палиндромы такая же фигня, вроде понятно, и подсказочка есть, а на самом деле - непонятно. В общем, я реально тупой. Хорошо, что учу просто для души. Пойду книжки читать, гайд ОПа расчитан на молодых, умных и дерзких, видимо.
#406 #582605
>>582558
Девятое задание.
http://jsfiddle.net/veue2knj/

Надеюсь мне хоть на том свете зачтется старание.
#407 #582606
Какашки мамонта.

@package MantisBT
@copyright Copyright (C) 2000 - 2002 Kenzaburo Ito - kenito@300baud.org
<!-- # Edit Account Form BEGIN -->
<br />
<?php if ( $t_force_pw_reset ) { ?>
<center><div style="color:red; width:75%">
\t\t<?php
\t\t\techo lang_get( 'verify_warning' );
\t\t\tif ( helper_call_custom_function( 'auth_can_change_password', array() ) ) {
\t\t\t\techo '<br />' . lang_get( 'verify_change_password' );
\t\t\t}
\t\t?>
</div></center>
<br />
<?php } ?>
166 Кб, 1360x768
#408 #582608
>>579559
ОП, я немного задержался.
Я тот анон -> >>579549
Так как не было времени, сегодня вот сделал ту задачку, задача сама в принципе, вроде как, не сложная, но это только первая часть от одной лаб работы, еще тесты всякие там были, но для начала вот сама задача

https://ideone.com/5CwCaJ

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

Еще понатыкал везде this.peremennaya , даже может и там где можно было написать просто peremennaya. Не совсем понимаю где можно не писать.

Еще понатыкивал везде "public" так как тоже не знаю, где можно не писать, а где нужно. Ну со временем пойму.

Выбрал все-таки Java.
#409 #582669
>>582597
Заведи массивчик, в него при каждом вызове мтранд клади сам подумай, что. Также сам подумай когда и какого рода проверку делать с использованием этого массива. Ещё подумай, какие действия предпринимать по результатам этой проверки.
#410 #582675
>>582597

Функция array_rand выбирает нужное число случайных слов из массива.
#411 #582676
>>582669

Проще наверно удалять выпавшее слово или использовать array_rand.
#412 #582688
>>582676
Да, точно. Уже и забыл, как задание выглядит.
#413 #582755
В продолжение темы про User-Agent, вот как выглядит UA нового IE:

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.<OS build number>

https://msdn.microsoft.com/ru-ru/library/hh869301(v=vs.85).aspx

Такие дела.
#414 #582759
>>582755
Что это значит?
#415 #582763
https://github.com/V3N0m21/Uppu3

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

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

>У тебя есть форма на главной странице (форма загрузки файла), и ты явно не следовал алгоритму обработки форм из моих уроков, так как сделал в Слиме 2 обработчика, для GET и для POST и конечно в них одна копипаста. Надо объединить их вместе.



Вот этого не понял. Зачем их объеденять вместе? Как мне кажется от этого сильно страдает читабельность, ну и в чем заключается копипаста тоже не совсем ясно. В GET рендерится страница, в POST обрабатывается запрос, и общих строк у них нет.
14 Кб, 338x290
#416 #582770
Примечание прописаны тегом <aside>. Как мне его привязать ко второму абзацу текста, чтобы было также как на картинке? У меня он находится вверху.

clear: left у верхнего блока ничего не меняет.
#417 #582789
>>581642

>у тянки-стажерки за соседним столом 80к+


Такое вообще возможно?
#418 #582806
>>582763
Копипаста в том, что ты просто все скопипастил с готового материала.
(Наверное)
#419 #582823
>>582789
Это репост из треда бугуртящих лузеров? Съеби с этим говном.
#420 #582829
>>582823
Чо сразу лузеры-то? Просто аноны отчитываются в треде о своих попытках/похождениях, делятся мыслями и опытом.
#421 #582830
>>582770
Очевидно обернуть каждую пару "параграф-примечание" в свой контейнер.

>>582763
Перечитай еще раз оповскую статью, https://github.com/codedokode/pasta/blob/master/forms.md
там же четко объясняется, зачем объединять гет и пост (чтобы в случае неправильно заполненной формы можно тут же вывести сообщения об ошибках и подставить в поля те данные, которые ввел пользователь; редиректить на гет только если форма заполнена правильно).
Иначе у тебя будет повторяться один и тот же код в двух обработчиках.
#422 #582843
>>582763

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

У тебя конечно GET это всего 3 строки, но все равно, какой смысл выводить одну и ту же страницу в 2 местах? да и в дальнейшем может быть там строк будет больше.
#423 #582859
>>581862
Спасибо за быстрый ответ, начал переделывать. Не могу понять как правильно нужно расположить животных на поле, примерно вот так?
http://ideone.com/c5NxN0
#424 #582860
Тяжело мне даются регулярные выражения сколько не учи. Помогите вытащить значение между строкой '[penis=' и '] '
Это мои попытки:
preg_match('@^(?:[penis=)?([^])+$]',"[answer=2323]hgf", $matches);
#425 #582861
Небольшая задачка на SQL.

Допустим у нас есть пользователи и они могут ставить лайки. То есть А поставил лайк B и это записано в таблице. Пользователи называются связанными, если один из них поставил лайк другому.

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

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

Я знаю тут есть минимум один анон, который в SQL хорошо разбирается. Поломайте-ка голову.
#426 #582863
answer вместо penis*
#427 #582874
>>582859
Алсо, я не понял твой совет:

> abstract protected function tryToMove($field, $game);


Неудобно везде передавать $field, лучше сделать его свойством класса. автоматически проставлять при добавлении животного на карту и убирать (ставить null) при снятии.
Наверное он косвенно связан с вопросом:

> class Field {


> public $field = array(); //Поле в двухмерном массиве


зачем хранить этот массив?
Я не знаю как без двумерного массива который я таскаю по всему коду реализовать логику программы.
#428 #582875
Т.е. хэш от пароля нужно записывать в отдельную колонку для каждого юзера. При попытки проверки пароля этот хэш нужно брать у этого юзера, соединять с паролем, пропускать через ьд5 опять ил сравнивать? ужс
#429 #582885
Не, я не понимаю, если хэш генерится для каждого пользователя свой, то как узнать, для какого пользователя брать хэш, если он входит в систему? Я беру одновременно логин, мейл и пароль и если они совпадают, то выбираю пользователя. А мне сначала совпадения по логину надо проверять что ли? А только потом брать из таблицы хэш, добавлять введенный пароль и проверять?
#430 #582887
>>582606
Я так тоже пару лет назад писал, когда только начинал.
36 Кб, 925x549
#431 #582906
Я звезда-а-а.
#432 #582907
>>582874

А зачем нам нужен двухмерный массив букв если удобнее просто хранить список животных? У них ведь есть координаты так что массив с буквами избыточен.

>>582875

Ты что-то путаешь, почитай урок про соль.
#433 #582911
Алсо я добавил в генерацию хэша спецсимволы, но мд5 их автоматических перевел в цифро буквы md5($password . $hash);
Это нормально? или через мд5 лучше только пароль пропускать?
#434 #582913
>>582907
Это ты что-то путаешь, перечитай свой урок, черным по белому написано. Впрочем я слышал, что при некоторых случаях шизофрении может отрубать память.

Соль — случайно сгенерированная последовательность символов, которая хранится рядом с хешем. Дан пароль $pass = "123456", мы генерируем случайную соль например $salt = 'A&%6t*(k:' и получаем хеш от «соль + пароль»: $hash = md5($salt . $pass). В базу сохраняется отдельно использованная соль (она для каждого пользователя своя), отдельно хеш.
#435 #582917
>>582913

Вот. А где в твоем посте соль? Я вижу только какие-то непонятные хеши.
11 Кб, 391x436
#436 #582929
>>578124 (OP)
Как реализовать подобный перебор массива?
#437 #582930
>>582929
Не совсем понятно, подобный это какой?
#438 #582931
>>582930
В массиве содержится набор характеристик. А я хочу, чтобы массив перебрал все варианты без повторов и вывел на отдельную страницу, чем отличается кошка от собаки.
#439 #582956
>>582861
Одним запросом что ли выбрать группы и взаимные лайки? И по какому условию джойнить это дело?

Сделал пока отдельными двумя запросами.
Не обошлось без подзапроса, так как я не знаю, как положить в условие where колонку, созданную на лету через if. Алиас не помогает, говорит нет такой колонки.
sqlfiddle как всегда лагает http://sqlfiddle.com/#!9/77a26/1
Продублирую на пастбин http://pastebin.com/FezFNdAy

А причем тут индексы? Все связи ведь по первичным или внешним ключам.
#440 #582965
При использовании GET запросов в MVC столкнулся с проблемой, ибо тогда URI получается не такой как надо для обработке в роутере и определеение контроллера и экшена запаривается. Получается тогда использоват гет запросы в этом случае нельзя и вместо такого например site.com/?act=logout (выход) нужно использовать что-то такое site.com/act/logout ? Или в роутере как-то их отлавливать и обрабатывать?
#441 #582987
>>582931
Ну вот зацени мой велосипед.
http://ideone.com/iQ4cAI
Честно говоря задачка на первый взгляд хоть и простая, но заставила меня поломать голову. Работает, кстати, на любое количество свойств у животных, причем оно может быть у всех разным.
#442 #583000
>>582956

Нет, не совсем то. Надо взять человека, и найти на какие группы подписан он и те кто с ним связаны (кто ему поставил лайк или кому он поставил).
#443 #583013
>>582965
Что за хуйню я читаю? При логауте удаляешь куку у юзера и перенаправляешь на главную. При загрузке шапки, проверяешь есть ли кука, все.
#444 #583014
>>582917
class Salt {
public $salt;
public $hash;
public function __construct($password){
$this->password = $password;
}
public function getSalt(){
$password = $this->password;
$token = new Token;
$hash = $token->generatePassword(15);
$this->hash = $hash;
$salt = md5($password . $hash);
return $salt;
}
public function getHash(){
return $this->hash;
}
}
Аноним #445 #583022
>>582987
Ты охуенен! Можешь сделать сайтик, чтобы все генерировалось на отдельные статические странички. Конечно, не за бесплатно. Если да, отпиши на почту.
#446 #583023
#447 #583025
>>583014
Сохранил этот хаш в ДБ, правильно ли я его проверяю? Нужно потом вытащить из дб этот хаш для пользователя, прибавить к введенному паролю, провести через мд5 и сравнить с паролем в дб??
if(!empty($users)&&(isset($this->password))){
// $user->password = md5($this->password); //hash password
//$salt = new Salt($this->password);
foreach($users as $value){
$hash = $value['hash'];
$user->password = md5($this->password . $hash);
#449 #583037
>>583031
Сайт будет пользоваться бешеной популярностью, я гарантирую это.
#450 #583042
>>583000
А, найти общие группы для этого человека и (для) его "друзей".

Тогда так
http://sqlfiddle.com/#!9/ccc6e/1
Что-то у меня все свалилось в подзапросы, потом попробую переписать через джойны.

Вообще не отвлекай меня, я пытаюсь решить задания на верстку.
#451 #583044
>>583042

Я не уверен, можно ли назвать «общие».

Допустим есть человек X, он лайкнул Y, и получил лайк от Z. Допустим X подписан на группы a, b, c, Y подписан на c, d, e, Z подписан на c, d, f.

Запрос для X должен вернуть группы a, b, c, d, e, f.

То есть это не столько общие группы, а объединение всех групп на которые хотя бы один из них подписан.
#452 #583051
нахуй идите со своей версткой, котопсами и пабликами вбыдлятне.
13 Кб, 320x240
#453 #583090
#454 #583093
>>583044

Моя третья попытка понять, чего тебе надобно.
http://sqlfiddle.com/#!9/bb3e0/1
Если ты сейчас скажешь, что теперь нужно найти все рекурсивные зависимости, то я на люстру выскочу.

Кстати сначала попробовал объединить юнионом два результата, а потом подсунуть в условие IN, но оно почему-то ругается на ошибку.
select ug.group_id from users_groups ug where ug.user_id in ((select t1.from_user from users_likes t1 where t1.to_user = 1) union (select t2.to_user from users_likes t2 where t2.from_user = 1));
ERROR 1064 (42000): 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 'union (select t2.to_user from users_likes t2 where t2.from_user = 1))' at line 1

>>583051
Чем ты так огорчен, Володька?
11 Кб, 384x190
#455 #583106
Нехорошие люди, чтоб их пингвины покусали.

Дублирую на pastebin
http://pastebin.com/UCXD9ADw
527 Кб, 1280x1024
someApprentice #456 #583123
Мне анон в прошлом треде советовал через vmware запускать debain. Как включить интернет?
#457 #583125
Как научиться верстать из PSD?
#458 #583186
>>583125

>>583126


>>583127


>>583128


Верстаю PSD своей пиписькой, зарабатываю 4к евро в неделю.
#460 #583211
>>583013
Ты в глаза долбишься. Я же написал в MVC. Когда приходт реквест с гет запросом в урле, то бутсрап (он же фронтконтроллер) не правильно определяет контроллер и экшн, потому что этот гет запрос висит в $_SERVER['REQUEST_URI']
#461 #583229
>>583211
parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH)

Не благодари.
#462 #583234
>>583211
А ведь можно просто взять слим с готовым МВК и не мучиться.
#463 #583246
Репостну из жс-треда, может, кто что подскажет.

Пацаны, подскажите, как перестать быть говнокодером.

Я недавно начал основательно учить js, и в прошлом треде спрашивал про задание с рекурсией, где надо было вывести диапазон чисел типа (1, 10) => (2, 9). По итогу написал так:

function lol(a, b){
var arr = [];

function range(x, y){
if(x <= y){
arr.push(x);
return (range (x + 1, y));
}
else{
return x;
}
}

range(a, b);

var result = arr.slice(1, -1);

alert(result);
}

lol(1, 10);

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

Так вот, как прокачивать эту ебучую соображалку? Чтобы хватало мозгов сразу делать нормально, а не писать хуйню и думать, как бы ее переделать, чтобы не стремно было.
#463 #583246
Репостну из жс-треда, может, кто что подскажет.

Пацаны, подскажите, как перестать быть говнокодером.

Я недавно начал основательно учить js, и в прошлом треде спрашивал про задание с рекурсией, где надо было вывести диапазон чисел типа (1, 10) => (2, 9). По итогу написал так:

function lol(a, b){
var arr = [];

function range(x, y){
if(x <= y){
arr.push(x);
return (range (x + 1, y));
}
else{
return x;
}
}

range(a, b);

var result = arr.slice(1, -1);

alert(result);
}

lol(1, 10);

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

Так вот, как прокачивать эту ебучую соображалку? Чтобы хватало мозгов сразу делать нормально, а не писать хуйню и думать, как бы ее переделать, чтобы не стремно было.
107 Кб, 1344x675
#464 #583255
Вопрос по best practice верстки.
Вот адаптируют сайт под мобилки, тут все логично. Но почему не адаптируют под хайрез моники? Получается main с max-width: 960px и широченные полосы по бокам. Плюс милиписечные шрифты. Достаточно же указывать все размеры в vw.
Я пока надумал такие причины:
1) При скейлинге от vw на низких разрешениях сложно читается текст. И получается что-то типа фиксед вью-порта. Приходится больше пердолиться с медиа-кьюри.
2) Тупо никому это не надо, т.к. доля таких моников не покрывает сложности разработки.
3) На больших мониках pixel ratio почти всегда >= 2

У кого есть моник с 2560x1440, отпишите свой юзер экспириенс.
#465 #583273
>>583246
изучай чужой код, ну и пиши свой естественно, чем больше пишешь, тем лучше пишешь, со временем.
#466 #583275
>>583229
А вот за это спасибо, няша
#467 #583289
>>583255
Все не угомонишься?
#468 #583375
>>583255

Потому что ширина текста который может нормально читать человек, составляет от 40 до 80 символов. Шире делать смысла нет - читать неудобно.

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

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

Ну и насколько я знаю, пользователи больших мониторов просто не распахивают браузер на весь экран.
223 Кб, 1200x800
#469 #583380
Пацанэ, в чем разница между .tpl шаблонами и .php шаблонами? можно ли выполнить пхп код для рендера вьюхи в первых и так ли важно
использовать .tpl?
147 Кб, 1843x821
#470 #583395
>>583375
>>583255
Сосач вроде адаптируется, мне наоборот на маленьких экранах теперь неудобно работать. Тут открыл несколько окон и щурится не надо.
#471 #583412
Могу ли я, не вдаваясь в углублённое изучение языка, пользуясь графическим редактором (что видишь-то и получишь), создать не самый крутой, но и не донный, а просто приличный сайт?
#472 #583514
>>582504 >>582558 >>582605 >>583093 >>583106 >>583195

Одиннадцатое задание на верстку.
http://jsfiddle.net/eh3j5c65/
На скрине в задании тень какая-то неравномерная, градиентная что ли.
Я знаю только box-shadow, нужна подсказка где искать другие способы.
По поводу "плавного нажатия" кнопки, тоже не знаю как реализовать. Transition вроде бы работает только с hover, а мне нужна анимация не при наведении, а при изменении состояния (:checked).
#473 #583682
Есть какой-то способ быстро находить жабаскрипты навешанные на кнопки? А то когда проект большой, то можно заебаться их искать.
#474 #583715
>>583514

> Transition вроде бы работает только с hover,


Не только
#475 #583733
>>583682

Инспектором в разделе Events на вкладке DOM. правда если используется jQuery то там будет виден не обработчик, а функция jQuery. Почему авторы JQuery ничего не сделали для упрощения отладки, неясно, видимо они отладчиком не пользуются, чукча писатель а не читатель.

Также, в старых версиях jQuery можно было выделить элемент и написать в консоли
$($0).data('events') но в новых это не работает, нужно что-то другое писать. И это не сработает если обработчик находится выше в дереве DOM.

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

Еще можно сделать поиск по имени класса или id кнопки.

В общем:

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

<button onclick="doSomething()">

Но среди разработчиков jQuery почему-то это не принято.
#476 #583734
>>583682

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


Дело не в том что проект большой а в том что разработчикам наплевать на тех кто будет читать код.
#477 #583747
>>583733

> - я вообще предпочитаю ставить обработчики так



А если тебе потребуется повесить несколько обработчиков на элемент?
#478 #583766
>>583747

С чего мне понадобится повесить несколько обработчиков на одну кнопку? Одна кнопка обычно делает одно действие.
#479 #583778
>>583747

Ты бы мог привести более реалистичный пример: «а если у тебя большая таблица с кучей чекбоксов, ты на каждый будешь вешать обработчик?»

Нет конечно. В таких случаях мы можем написать в шаблоне

<скрипт>
initSomePage();
</скрипт>

А уже в функции initSomePage повесить один обработчик на все чекбоксы:

function initSomePage() {
$('.b-some-table').on('click', '.some-checkbox', onCheckboxClicked);
...

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

В общем должна быть какая-то система. А не так что человек берет и описывает

$('.xyz').click() где-то в js файле на 2000 строк и попробуй потом разебрись. Я сам такое видел много раз, среди верстальщиков конечно все с этим плохо, js код почти всегда нечитаемая лапша, если у вас большой проект то старший разработчик должен придумать и ввести какую-то систему.
#480 #583804
Пост на хабре про железную составляющую (сервера) для хайлоад-проекта: http://m.habrahabr.ru/company/rutube/blog/271143/

Обратите внимание, как их там много.
#481 #583807
>>583804
Можно где-нибудь почитать, как это работает?
#482 #583813
>>583778

если ты ОП, то обрати внимание на это, пожалуйста >>582608
#483 #583901
Не понимаю в чем дело, сделал редирект с кириллицей в .htaccess ругуляркой (.+) все работает нормально, пока в адресной строке не встречается символ х в сочетании с любым другим символом. На такие урлы мод реврайт просто перестаёт работать.
96 Кб, 1647x979
101 Кб, 1671x983
#484 #583944
>>583901
Вот прилагаю скриншоты. Как видно из них символ х может стоять только в самом конце строки. Если поставить его перед любой из букв, регулярка не принимает такой адрес.
#485 #584029
>>583944

Код отвечающий за редирект тоже покажи.
4 Кб, 475x115
#486 #584034
>>584029
Его я как только не переписывал, и без гет параметров пробовал
^test/(.*)/?$ test.php [NC]
по всякому и ни в какую не работает.
#487 #584039
>>584034

А почему он должен работать? Мы ведь не знаем в какой кодировке работает движок регулярных выражений в апаче и какие символы он поддерживает.

Ты не видел в мануале http://httpd.apache.org/docs/current/mod/mod_rewrite.html подробностей по поводу кодировок?
#488 #584041
Кириллица - унтер алфавит. Не люблю вообще в ней работать.
#489 #584042
>>584034

И еще вопрос, а если убрать ?test=$1 из правила и оставить просто test.php, что-то поменяется?
#490 #584043
>>584034

Также, это не редирект, а реврайт. Редирект это когда сервер отдает ответ с кодом 3xx и заголовком Location, а тут просто вызывается указанный php файл для обработки запроса.
74 Кб, 1662x797
110 Кб, 1654x983
#491 #584045
>>584042
По моему ничего не поменялось.
#492 #584046
>>584034

Если что, у Апача можно включить rewrite log в который будет писаться подробно по шагам процесс обработки запроса и применения правил:

http://stackoverflow.com/questions/9632852/how-to-debug-apache-mod-rewrite/9632952#9632952

http://httpd.apache.org/docs/2.4/mod/mod_rewrite.html#logging

Обрати внимание, там 2 варианта кода, для Апача 2.2 и 2.4 и также обрати внимание, это надо писать не в htaccess, а в конфиг сервера, в блок где описывается виртуал хост. И сервер не забудь перезапустить.

После этого ты можешь посомтреть логи и показать нам и мы попробуем понять, на каком этапе ошибка, на этапе проверки соответсивя регулярке либо же уже после.
#493 #584048
>>584045

Тут что-то не так. Я взял сервер Апач 2.2, сделал папку /tests/rewrite/, в нее поместил такой htaccess:

RewriteEngine On
RewriteBase /tests/rewrite/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^test/(.+) test.php

(RewriteBase нужен в версии 2.2)

затем я открываю

/tests/rewrite/test/абвгдеёжзиёклмнопрестуфхцчшщъыьэюя?a=1

И файл test.php вызывается.

Также, для проверки я дописал [NC] в RewriteRule и все равно все вызывается.

Попробуй-ка мой htaccess, только убери RewriteBase.
#494 #584049
>>583514
>>583715
А, действительно. Мне пора прекращать равняться на htmlbook, там только самая основная информация, о тонкостях либо не говорится вообще, либо могут ввести в заблуждение.

> http://htmlbook.ru/css/transition


> Устанавливает эффект перехода между двумя состояниями элемента, они могут быть определены с помощью псевдоэлемента :hover или :active, а также динамически через JavaScript.


Звучит так, будто анимировать можно только между текущим состоянием и тем, что прописаны в hover/active.

Добавил плавное изменение цвета кнопки при нажатии в 11 задании.
Правда, не сказал бы что мне нравится как это выглядит.
http://jsfiddle.net/eh3j5c65/1/

12 задание.
http://jsfiddle.net/03brL49g/
#495 #584051
>>584046
http://pastebin.com/980pFYyF вот лог ошибок, после того как поставил

LogLevel alert rewrite:trace8 в виртуалхостс.
#496 #584052
>>584048

>RewriteEngine On


>RewriteBase /tests/rewrite/


>RewriteCond %{REQUEST_FILENAME} !-f


>RewriteRule ^test/(.+) test.php



Да, с таким htaccesом работает. Получается у меня где-то ошибка в регулярке?
#497 #584054
>>584051

попробуй убрать флаг [NC] и заменить его на [NE] или

документация если что:

http://httpd.apache.org/docs/current/rewrite/flags.html
#498 #584055
>>584054
А вот это не помогло.
#499 #584057
>>584052

Ты не удалил ?test=... из RewriteCond либо забыл сохрнить файл. У меня есть версия что реврайт на

test.php

работает, а на

test.php?test=$1

нет так как получается URL со спецсиволами и там что-то ломается. Это что-то можно попроьовать исправить добавив флаг

B

в квадратных скобках.

Судя по логу регулярку оно проходит, ошибка где-то дальше.
4 Кб, 379x80
#500 #584062
>>584057
Вот такой реврайт у меня сейчас. Все сохранил, сервер перезапустил, но ошибка осталась. Сейчас убрал знак доллара в конце и всё заработало. Похоже, что причина именно в нём.
#501 #584080
Киньте кто-нибудь кусок кода, где показано, как делать соль. с работой с дб.
#502 #584107
>>584062

Странно. Я проверил еще Апач 2.4 под дебианом, правило как у тебя, с $ на конце, работает с любыми буквами.

Я даже пару иероглифов добавил в URL, все равно работает.
#503 #584113
>>584062
Ты там случайно не на денвере?
#504 #584115
>>584113

> денвере?


Упаси боже, какой денвер? Вон в логах выше полный путь к апачу.
156 Кб, 750x1334
#505 #584126
Добрый вечер, ребята. Уже 3й день бьюсь над одним косяком. Глаза уже полностью замылены, поэтому решил обратиться к знающим.

Есть страница в html к ней идут два СSS файла. Так вот, нужно сверстать адаптивно, то есть чтобы при просмотре этой страницы на планшетах и смартфонах, контент и лэйаут реагировал, а на определённых разрешениях блоки перестраивались.

Есть здесь кто нибудь, кто может мне помочь с подобным?
Если да - то скину код.

Благодарю за понимание. Выручайте, ребята.
#506 #584187
>>584126

Что же ты 3 дня ищешь если весь гугл в туториалах? https://www.google.ru/search?q=%D0%B0%D0%B4%D0%B0%D0%BF%D1%82%D0%B8%D0%B2%D0%BD%D0%B0%D1%8F+%D0%B2%D0%B5%D1%80%D1%81%D1%82%D0%BA%D0%B0&newwindow=1&gbv=1&sei=_fJNVpPDLcbRywPglpzwAw

Или ты и CSS вдобавок не знаешь? Тогда стоит начать с его изучения.
1254 Кб, 3264x2448
#507 #584193
>>584187

Я ничего не искал. Делал самостоятельно, но вот, наступил тот момент, когда я не обладаю нужным скилом.

У меня почти всё сделано, только нужно изменить меню и поправить шапку с тегами.

Ты можешь глянуть?
#508 #584233
>>584193

Боюсь, что нет, я не решаю задачи и не делаю работу. Но может кто-то другой захочет помочь.
#509 #584234
>>584233

Спасибо за фидбэк.
173 Кб, 788x527
223 Кб, 824x631
89 Кб, 377x475
#510 #584248
Продолжаю мучатся с Linux на VMware.

Подключил к мосту - безрезультатно.

Во время установки системы, в момент настройки сети, выдалась ошибка о том что не может соединится с DHCP.
#511 #584333
>>584248

Почему у тебя 2 адаптера? Ты хочешь иметь возможность с хоста подсоединяться к гостю?

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

-------

## Интернет

Интернет - это всемирная сеть, объединяющая множество компьютеров и устройств. Устройство и принцип работы этой сети описаны в протоколе (протокол это стандарт, описывающий взаимодействие систем) IP.

У каждого узла сети есть свой уникальный идентификатор (он называется IP адрес), и указав его, узлы могут передавать друг другу по этой сети пакеты данных. Сейчас все еще используются IPv4-адреса, которые имеют вид вроде `102.34.23.20` (4 числа от 1 до 254), но так как эти адреса заканчиваются, в будущем мы перейдем на [IPv6](https://ru.wikipedia.org/wiki/IPv6), где адреса состоят из большего числа цифр.

Также, некоторые IP адреса имеют специальный смысл. IP-адреса вида `127.x.x.x`(например `127.0.0.1`) соответствуют так называемому loopback-интерфейсу и если попытаться отправить пакет на такой адрес, то он не уйдет в сеть, а останется на компьютере. Эта особенность используется программами, которые запущены на одном и том же узле и хотят обмениваться друг с другом данными.

Каждый IP-пакет содержит IP-адрес отправителя, получателя, а также примерно до 1600 байтов данных (байт это целое число от 0 до 255). IP адрес либо задается администратором узла, либо узел получает его автоматически через DHCP.

Если быть точнее, то обычно IP адрес назначается не узлу, а сетевой карте. Если у узла несколько сетевых карт, у него может быть несколько Ip адресов. Более того, можно присвоить одной сетевой карте несклоько IP адресов, но как правило это не имеет смысла.

## Локальная сеть

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

В переделах локальной сети узлы могут пересылать пакеты без IP адресов, по MAC-адресам (MAC адрес это серийный номер сетевой карты, вшитый в нее. В отличие от него IP адрес задается системой программно). В переделах локальной сети пакеты пересылаются напрямую. А вот чтобы отправить пакет в другую сеть, узел передает пакет машрутизатору-шлюзу, который передает его в соседнюю сеть, там его передают дальше, и т.д. IP-адрес шлюза задается в настройках сети на узле либо администратором либо получается автоматически по DHCP.

Маршрутизатор немного меняет пакеты. Так как он принимает пакет на одной сетевой карте и передает с другой, то в пакете MAC-адрес отправителя заменяется на адрес маршрутизатора, а MAC-адрес получателя - на адрес шлюза во второй сети. IP-адреса и другая информация в пакете не меняется.

Ты можешь увидеть путь пакета через цепочку маршрутизаторов командой traceroute (на Windows она называется tracert):

(linux) /usr/sbin/traceroute google.com
(win) tracert google.com
(онлайн на сайте) http://ping.eu/

Компьютеры объединяются в локальную сеть с помощью свитча. Это устройство, у которого много сетевых разъемов к которым подсоединяются узлы. Свитч это прозрачное устройство, у которого нет ни MAC- ни IP-адресов - оно просто принимает пакет от одного компьютера и передает другим.

Компьютеры в локальной сети имеют общий префикс IP-адреса. Например если у нас маска сети 255.255.255.0 и адрес шлюза 10.10.10.1 то все другие узлы этой сети должны иметь IP адреса вида 10.10.10.x. Именно по этому признаку узел определяет находится он в одной сети с получателем (и может слать ему пакет напрямую по MAC адресу) или в разных (и пакет надо передать шлюзу). Сеть обычно называют по префиксу, то есть говорят «узел находится в сети 10.10.10.0».

## NAT

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

Но еще сети можно соединить с помощью NAT. В случае если мы включаем на маршрутизаторе между 2 сетями режим NAT, ситуация меняется. NAT принимает пакеты из внутренней сети и отправляет их во внешнюю от своего имени, заменяя IP адрес отправителя (допустим a.b.c.d) на свой. А когда извне приходит ответ, он передает этот пакет во внутреннюю сеть, меняя адрес получателя со своего IP адреса на a.b.c.d, то есть того, кто послал исходный пакет наружу.

Это приводит к тому что внутренняя сеть становится изолированной от внешней. Извне никто не видит узлы внутренней сети, снаружи ситуация выглядит как будто у нас один узел с одним IP адресом. Нельзя снаружи установить соединение с внутренним узлом (если только явно не пробросить порт через NAT).

Также, так как внутренние узлы не видны снаружи, мы не обязаны выдавать им белые уникальные IP адреса (которых мало и которые стоят денег). Мы можем выдать им «серые» адреса из диапазона 192.168.x.x или 10.x.x.x. В одной локальной сети IP адреса не могут повторяться, но в разных сетях (например у разных провайдеров), отделенных NAT, могут. Серые адреса уникальны только в пределах своей сети, а не во всем мире. Из-за неуникальности снаружи нельзя установить соединение с узлом у которого серый IP адрес. Именно потому NAT переписывает адрес отправителья на свой, «белый».

Большинство провайдеров помещает своих абонентов именно в изолированную сеть за NAT, из соображений экономии на IP адресах и безопасности. Если ты используешь дома роутер то в нем тоже есть NAT, у тебя создается изолированная домашняя сеть, и провайдер не видит устройства в ней, видит только роутер.

## Проброс порта

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

Давай повторим, чтобы не забыть:

- локальная сеть организуется на свитчах, IP адреса в ней начинаются с одного и того же префикса, узлы могут слать пакеты напрмямую по MAC адресу
- локальные сети объединяются маршрутизаторами, которые при передаче пакета не меняют IP адреса в них
- маршрутизатор может работать в режиме NAT, в этом случае он подменяет IP адреса в пакетах. Снаружи соединиться с узлом за NAT нельзя.

--------------

В виртуальных машинах есть виртуальный сетевой адаптер и в его настройках ты определяешь как именно и куда он подсоединен. А имеено:

- NAT (виртуальная машина подсоединяется к виртуальному роутеру с NAT который другим концом выходит в интернет)
- бридж (виртуальная сетевая карта разделяет физическую сетевую карту хоста)
- host-only network (виртуальная сетевая карта гостя подсоединяется к виртуальной локальной сети, и в нее же подсоединяется виртуальная сетевая карта хоста. Эта сеть доступна только на твоем компьютере и по умолчанию не связана с внешними сетями если только хост не работает в режиме маршрутизатора)
#511 #584333
>>584248

Почему у тебя 2 адаптера? Ты хочешь иметь возможность с хоста подсоединяться к гостю?

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

-------

## Интернет

Интернет - это всемирная сеть, объединяющая множество компьютеров и устройств. Устройство и принцип работы этой сети описаны в протоколе (протокол это стандарт, описывающий взаимодействие систем) IP.

У каждого узла сети есть свой уникальный идентификатор (он называется IP адрес), и указав его, узлы могут передавать друг другу по этой сети пакеты данных. Сейчас все еще используются IPv4-адреса, которые имеют вид вроде `102.34.23.20` (4 числа от 1 до 254), но так как эти адреса заканчиваются, в будущем мы перейдем на [IPv6](https://ru.wikipedia.org/wiki/IPv6), где адреса состоят из большего числа цифр.

Также, некоторые IP адреса имеют специальный смысл. IP-адреса вида `127.x.x.x`(например `127.0.0.1`) соответствуют так называемому loopback-интерфейсу и если попытаться отправить пакет на такой адрес, то он не уйдет в сеть, а останется на компьютере. Эта особенность используется программами, которые запущены на одном и том же узле и хотят обмениваться друг с другом данными.

Каждый IP-пакет содержит IP-адрес отправителя, получателя, а также примерно до 1600 байтов данных (байт это целое число от 0 до 255). IP адрес либо задается администратором узла, либо узел получает его автоматически через DHCP.

Если быть точнее, то обычно IP адрес назначается не узлу, а сетевой карте. Если у узла несколько сетевых карт, у него может быть несколько Ip адресов. Более того, можно присвоить одной сетевой карте несклоько IP адресов, но как правило это не имеет смысла.

## Локальная сеть

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

В переделах локальной сети узлы могут пересылать пакеты без IP адресов, по MAC-адресам (MAC адрес это серийный номер сетевой карты, вшитый в нее. В отличие от него IP адрес задается системой программно). В переделах локальной сети пакеты пересылаются напрямую. А вот чтобы отправить пакет в другую сеть, узел передает пакет машрутизатору-шлюзу, который передает его в соседнюю сеть, там его передают дальше, и т.д. IP-адрес шлюза задается в настройках сети на узле либо администратором либо получается автоматически по DHCP.

Маршрутизатор немного меняет пакеты. Так как он принимает пакет на одной сетевой карте и передает с другой, то в пакете MAC-адрес отправителя заменяется на адрес маршрутизатора, а MAC-адрес получателя - на адрес шлюза во второй сети. IP-адреса и другая информация в пакете не меняется.

Ты можешь увидеть путь пакета через цепочку маршрутизаторов командой traceroute (на Windows она называется tracert):

(linux) /usr/sbin/traceroute google.com
(win) tracert google.com
(онлайн на сайте) http://ping.eu/

Компьютеры объединяются в локальную сеть с помощью свитча. Это устройство, у которого много сетевых разъемов к которым подсоединяются узлы. Свитч это прозрачное устройство, у которого нет ни MAC- ни IP-адресов - оно просто принимает пакет от одного компьютера и передает другим.

Компьютеры в локальной сети имеют общий префикс IP-адреса. Например если у нас маска сети 255.255.255.0 и адрес шлюза 10.10.10.1 то все другие узлы этой сети должны иметь IP адреса вида 10.10.10.x. Именно по этому признаку узел определяет находится он в одной сети с получателем (и может слать ему пакет напрямую по MAC адресу) или в разных (и пакет надо передать шлюзу). Сеть обычно называют по префиксу, то есть говорят «узел находится в сети 10.10.10.0».

## NAT

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

Но еще сети можно соединить с помощью NAT. В случае если мы включаем на маршрутизаторе между 2 сетями режим NAT, ситуация меняется. NAT принимает пакеты из внутренней сети и отправляет их во внешнюю от своего имени, заменяя IP адрес отправителя (допустим a.b.c.d) на свой. А когда извне приходит ответ, он передает этот пакет во внутреннюю сеть, меняя адрес получателя со своего IP адреса на a.b.c.d, то есть того, кто послал исходный пакет наружу.

Это приводит к тому что внутренняя сеть становится изолированной от внешней. Извне никто не видит узлы внутренней сети, снаружи ситуация выглядит как будто у нас один узел с одним IP адресом. Нельзя снаружи установить соединение с внутренним узлом (если только явно не пробросить порт через NAT).

Также, так как внутренние узлы не видны снаружи, мы не обязаны выдавать им белые уникальные IP адреса (которых мало и которые стоят денег). Мы можем выдать им «серые» адреса из диапазона 192.168.x.x или 10.x.x.x. В одной локальной сети IP адреса не могут повторяться, но в разных сетях (например у разных провайдеров), отделенных NAT, могут. Серые адреса уникальны только в пределах своей сети, а не во всем мире. Из-за неуникальности снаружи нельзя установить соединение с узлом у которого серый IP адрес. Именно потому NAT переписывает адрес отправителья на свой, «белый».

Большинство провайдеров помещает своих абонентов именно в изолированную сеть за NAT, из соображений экономии на IP адресах и безопасности. Если ты используешь дома роутер то в нем тоже есть NAT, у тебя создается изолированная домашняя сеть, и провайдер не видит устройства в ней, видит только роутер.

## Проброс порта

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

Давай повторим, чтобы не забыть:

- локальная сеть организуется на свитчах, IP адреса в ней начинаются с одного и того же префикса, узлы могут слать пакеты напрмямую по MAC адресу
- локальные сети объединяются маршрутизаторами, которые при передаче пакета не меняют IP адреса в них
- маршрутизатор может работать в режиме NAT, в этом случае он подменяет IP адреса в пакетах. Снаружи соединиться с узлом за NAT нельзя.

--------------

В виртуальных машинах есть виртуальный сетевой адаптер и в его настройках ты определяешь как именно и куда он подсоединен. А имеено:

- NAT (виртуальная машина подсоединяется к виртуальному роутеру с NAT который другим концом выходит в интернет)
- бридж (виртуальная сетевая карта разделяет физическую сетевую карту хоста)
- host-only network (виртуальная сетевая карта гостя подсоединяется к виртуальной локальной сети, и в нее же подсоединяется виртуальная сетевая карта хоста. Эта сеть доступна только на твоем компьютере и по умолчанию не связана с внешними сетями если только хост не работает в режиме маршрутизатора)
#512 #584335
На первом адаптере, с помощью которого гость выходит в сеть, можно поставить NAT. Это позволит гостю соединяться с узлами снаружи, но не позволит подсоединиться снаружи к гостю.

вот тут упомянуто как работает NAT: https://gist.github.com/codedokode/420c8c12a1edae25f0ec#file-nat-md

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

https://www.vmware.com/support/ws4/doc/network_nat_ws.html

-----

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

https://www.vmware.com/support/ws4/doc/network_bridged_ws.html

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

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

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

Также, если твой провайдер использует динамическое выделение IP адреса (DHCP), он опять же может отказаться выдавать 2 адреса одному абоненту.

----

Теперь про то как подсоединиться снаружи внутрь гостя, например по SSH или к веб-серверу.

Тут описано как можно пробросить порт внутрь через NAT. Минус: придется менять номера портов, каждый порт надо прописать руками:

http://www.howtogeek.com/howto/vmware/allow-access-to-a-vmware-virtual-machinenat-from-another-computer/?PageSpeed=noscript

Или же можно как и в моем совете про виртуалбокс, попробовать настроить вторую сетевую карту.

Я думаю, что для нее стоит включить Host-Only Networking. Эта опция создает на хосте виртуальную сетевую карту, выделяет ей Ip адрес (или диапазон) и соединяет ее с виртуальной сетевой картой в госте.

https://www.vmware.com/support/ws4/doc/network_host_ws.html#1061835

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

Более того, вместе с host-only network ты можешь исплользовать встроенный в Windows NAT (который включается галочкой «разрешить другим пользователям использовать подключение к интернету»). Тогда первый адаптер, с NAT, не нужен.

При ипльзовании host-only стоит настроить Ip адреса статически. Их надо брать не от балды, а из диапазона который указан в настройках VMNet к которой ты подсоединен. Например для хоста можно исплоьзовать 192.168.xxx.1, а для гостя 192.168.xxx.2. IPадрес гостя прописывается в /etc/network/.., а хоста - в windows-свойствах вирутального адаптера.

В общем, я вижу такие конфигурации:

1) один адаптер с Host-Only-Networking, IP адрес можно прописать в госте статически. Выходит в интернет гость за счет встроенной в Windows возможности расшарить интернет (то есть встроенный в Windows NAT между виртуальной и физической сетевой картой).

2) два адаптера, первый с NAT для выходя гостя в сеть, второй Host-only для взаимодействия гостя и хоста. IP адреса на Host-only лучше настроить вручную.

Как настроить постоянный IP адрес в линуксе, написано тут (только IP адреса могут понадобиться другие): https://gist.github.com/codedokode/420c8c12a1edae25f0ec

Проверить связь с гостем проще всего пропинговав его командой ping a.b.c.d, линукс по умолчанию отвечает на пинги, винда вроде бы нет.
#512 #584335
На первом адаптере, с помощью которого гость выходит в сеть, можно поставить NAT. Это позволит гостю соединяться с узлами снаружи, но не позволит подсоединиться снаружи к гостю.

вот тут упомянуто как работает NAT: https://gist.github.com/codedokode/420c8c12a1edae25f0ec#file-nat-md

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

https://www.vmware.com/support/ws4/doc/network_nat_ws.html

-----

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

https://www.vmware.com/support/ws4/doc/network_bridged_ws.html

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

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

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

Также, если твой провайдер использует динамическое выделение IP адреса (DHCP), он опять же может отказаться выдавать 2 адреса одному абоненту.

----

Теперь про то как подсоединиться снаружи внутрь гостя, например по SSH или к веб-серверу.

Тут описано как можно пробросить порт внутрь через NAT. Минус: придется менять номера портов, каждый порт надо прописать руками:

http://www.howtogeek.com/howto/vmware/allow-access-to-a-vmware-virtual-machinenat-from-another-computer/?PageSpeed=noscript

Или же можно как и в моем совете про виртуалбокс, попробовать настроить вторую сетевую карту.

Я думаю, что для нее стоит включить Host-Only Networking. Эта опция создает на хосте виртуальную сетевую карту, выделяет ей Ip адрес (или диапазон) и соединяет ее с виртуальной сетевой картой в госте.

https://www.vmware.com/support/ws4/doc/network_host_ws.html#1061835

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

Более того, вместе с host-only network ты можешь исплользовать встроенный в Windows NAT (который включается галочкой «разрешить другим пользователям использовать подключение к интернету»). Тогда первый адаптер, с NAT, не нужен.

При ипльзовании host-only стоит настроить Ip адреса статически. Их надо брать не от балды, а из диапазона который указан в настройках VMNet к которой ты подсоединен. Например для хоста можно исплоьзовать 192.168.xxx.1, а для гостя 192.168.xxx.2. IPадрес гостя прописывается в /etc/network/.., а хоста - в windows-свойствах вирутального адаптера.

В общем, я вижу такие конфигурации:

1) один адаптер с Host-Only-Networking, IP адрес можно прописать в госте статически. Выходит в интернет гость за счет встроенной в Windows возможности расшарить интернет (то есть встроенный в Windows NAT между виртуальной и физической сетевой картой).

2) два адаптера, первый с NAT для выходя гостя в сеть, второй Host-only для взаимодействия гостя и хоста. IP адреса на Host-only лучше настроить вручную.

Как настроить постоянный IP адрес в линуксе, написано тут (только IP адреса могут понадобиться другие): https://gist.github.com/codedokode/420c8c12a1edae25f0ec

Проверить связь с гостем проще всего пропинговав его командой ping a.b.c.d, линукс по умолчанию отвечает на пинги, винда вроде бы нет.
1511 Кб, 3264x2448
#513 #584343
Привет, антоши, привет, ОП-няша. Давно не заходил, я тот анон, написавший проверялку js задачек, которая в шапке треда упоминается ^_^. У меня тут вопрос возник, мб тупой немножко, решил зайти спросить у ОПа. Может еще кому интересно будет. Я уже спросил в JS треде, но т.к. я здешнего ОПа очень уважаю, хотел у него спросить, а туда, я не знаю, заходит он или нет. Короче дублирую.

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

Если бы мне надо было показывать спиннер в обоих случаях, то всё было бы просто:
$('#spinner').show();
sort();
$('#spinner).hide();

Я подумал, окей, я буду ставить таймаут на 300 мс, потом вызывать мою функцию, а потом, если спиннер показался, скрывать его если же функция выполнилась быстрее чем 300 мс, то отменять таймаут:

var delayShowSpinner = setTimeout(function() { $('#spinner').show(); }, 300);
sort();
if ( $('#spinner').is(':visible') ) {
$('#spinner).hide();
} else {
cleartTimeout(delayShowSpinner);
}

Мне казалось, такая конструкция должна работать. Я знаю что, то, что мы запланировали в setTimeout, вызовется при первой возможности, так везде пишут по крайней мере. Только как-то не очень понятно что имеется в виду. Я почему-то думал что движок js проверяет, не подошло ли время какого-нибудь таймера, постоянно. Фразу "при первой возможности" я понимал так: если мы сказали "ок, выполни этот код через 35 мс", то по истечении 35 мс, если движок выполнял какую-то команду или выражение кода, то он закончит выполнять её, и потом сразу же выполнит код из таймера. Оказалось всё не так. По крайней мере в хроме. Если бы это было так, то код который я привел работал бы. Т.е. во время выполнения очередной итерации внутри sort() , у меня бы выполнился мой $('#spinner').show(); а потом, по завершении sort, мой спиннер благополучно скрывался бы.
Но нет, дебаггер показал, что у меня выполняется сорт, затем то, что ниже, и естесственно $('#spinner').show(); никогда не вызывается, т.к. таймер уже отменен. Так вот анон, поясни, пожалуйста, когда же всё-таки наступает этот момент выполнения кода, переданного в setTimeout? Когда вообще больше нечего выполнять? Или когда? Или ткни меня плиз лицом в место в спецификации или в понятное объяснение этого механизма, или своими словами объясни.

Конечно, если бы это был ajax вызов всё было бы просто. Я бы показал спиннер, сделал вызов, получил бы промиз, передал бы в него коллбек, в котором скрыл бы спиннер.
Но код в sort не делает http запросы, а стало быть выполняется синхронно а это значит (я прав?) что моему setTimeout просто не даётся шанса выполниться. В общем, вторая часть вопроса, это можно ли как-то сделать синхронный вызов асинхронным? И вообще что, ещё кроме ajax вызовов в JS является асинхронным? и как ajax вызовам удается быть асинхронными? Как они обходят однопоточную природу JS?

И да, как бы ты, анон, посоветовал решить эту задачу?
1511 Кб, 3264x2448
#513 #584343
Привет, антоши, привет, ОП-няша. Давно не заходил, я тот анон, написавший проверялку js задачек, которая в шапке треда упоминается ^_^. У меня тут вопрос возник, мб тупой немножко, решил зайти спросить у ОПа. Может еще кому интересно будет. Я уже спросил в JS треде, но т.к. я здешнего ОПа очень уважаю, хотел у него спросить, а туда, я не знаю, заходит он или нет. Короче дублирую.

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

Если бы мне надо было показывать спиннер в обоих случаях, то всё было бы просто:
$('#spinner').show();
sort();
$('#spinner).hide();

Я подумал, окей, я буду ставить таймаут на 300 мс, потом вызывать мою функцию, а потом, если спиннер показался, скрывать его если же функция выполнилась быстрее чем 300 мс, то отменять таймаут:

var delayShowSpinner = setTimeout(function() { $('#spinner').show(); }, 300);
sort();
if ( $('#spinner').is(':visible') ) {
$('#spinner).hide();
} else {
cleartTimeout(delayShowSpinner);
}

Мне казалось, такая конструкция должна работать. Я знаю что, то, что мы запланировали в setTimeout, вызовется при первой возможности, так везде пишут по крайней мере. Только как-то не очень понятно что имеется в виду. Я почему-то думал что движок js проверяет, не подошло ли время какого-нибудь таймера, постоянно. Фразу "при первой возможности" я понимал так: если мы сказали "ок, выполни этот код через 35 мс", то по истечении 35 мс, если движок выполнял какую-то команду или выражение кода, то он закончит выполнять её, и потом сразу же выполнит код из таймера. Оказалось всё не так. По крайней мере в хроме. Если бы это было так, то код который я привел работал бы. Т.е. во время выполнения очередной итерации внутри sort() , у меня бы выполнился мой $('#spinner').show(); а потом, по завершении sort, мой спиннер благополучно скрывался бы.
Но нет, дебаггер показал, что у меня выполняется сорт, затем то, что ниже, и естесственно $('#spinner').show(); никогда не вызывается, т.к. таймер уже отменен. Так вот анон, поясни, пожалуйста, когда же всё-таки наступает этот момент выполнения кода, переданного в setTimeout? Когда вообще больше нечего выполнять? Или когда? Или ткни меня плиз лицом в место в спецификации или в понятное объяснение этого механизма, или своими словами объясни.

Конечно, если бы это был ajax вызов всё было бы просто. Я бы показал спиннер, сделал вызов, получил бы промиз, передал бы в него коллбек, в котором скрыл бы спиннер.
Но код в sort не делает http запросы, а стало быть выполняется синхронно а это значит (я прав?) что моему setTimeout просто не даётся шанса выполниться. В общем, вторая часть вопроса, это можно ли как-то сделать синхронный вызов асинхронным? И вообще что, ещё кроме ajax вызовов в JS является асинхронным? и как ajax вызовам удается быть асинхронными? Как они обходят однопоточную природу JS?

И да, как бы ты, анон, посоветовал решить эту задачу?
#514 #584364
>>584343

https://learn.javascript.ru/settimeout-setinterval
http://habrahabr.ru/post/138062/

Ты не можешь крутить спиннер во время выполнения jS кода так как выполнение JS кода блокирует DOM и браузер не имеет права ничего делать со страницей в это время. и кстати даже show() может сработать не в момент вызова, а только когда скрипт завершится.

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

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

Также посмотри что в это время показывает диспетчер задач Windows, сколько % CPU и сколько памяти потребляет процесс браузера.

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

А еще кстати код может работать медленно если у тебя открыт отладчик на вкладке DOM. Закрой его и посмотри, вдруг причина в этом.
#515 #584373
>>584343

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

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

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

Ну и способ обойти это конечно есть. можно разбить работу на N частей и выполнять их например делая паузы с помощью setTimeout(.., 0). При этом браузер будет получать управление в перерыве, может реагировать на команды пользователя, рисовать анимацию. Это известный старый трюк:

http://stackoverflow.com/questions/672732/prevent-long-running-javascript-from-locking-up-browser/672784#672784

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

http://www.html5rocks.com/ru/tutorials/workers/basics/

Увы, доступно только в новых браузерах.

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

Ну и вдобавок скрипт который выполняется несколько секунд это плохо. Процессор греется, вентиляторы включаются, батарейка сажается. Web Worker никак от этого не защищает.
#516 #584379
>>584343

> и как ajax вызовам удается быть асинхронными? Как они обходят однопоточную природу JS?


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

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

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

Вот паста про потоки и асинхронщину:

------------

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

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

В общем ОС может выполнять программы как бы параллельно даже на одном ядре.

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

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

Создание нового потока это если проводить аналогии с PHP, вызов какой-то функции или include какого-то скрипта. То есть программа может взять функцию и запустить ее выполнение отдельным потоком параллельно с основным потоком. В PHP так не делают, PHP программы однопоточные, но так делают в других языках.

Если потоков в процессе несколько, то они все имеют доступ к одной и той же области памяти. То есть если это бы была программа на PHP то все потоки видят одни и те же переменные и функции.

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

-------------

Один асинхронный процесс с 1 потоком

Есть еще одна интересная архитектура. Здесь используется один поток, но используются неблокирующие (асинхронные) обращения к внешним ресурсам вроде файлов или сети. Все описанные выше архитектуры используют блокирующие вызовы. Это значит что когда поток просит ОС прочитать файл с диска или отправить пакет по сети, или хочет получить пакет из сети, он делает системный вызов и блокируется до тех пор пока не будут получены данные.

Асинхронный вызов работает по другому: поток просит ОС начать операцию ввода-вывода, и не блокируется, а продолжает выполняться, а позже может спрашивать у ОС каков статус операции и пришли ли данные. Очевидно что код для работы с асинхронными вызовами будет сложнее. Обычно он строится на так называемом событийном программировании (event-driven programming). То есть внутри программы ведется список выполняющихся операций и список функций которые надо вызвать по их завершении. Например, когда придет новый запрос от клиента, вызвать функцию processRequest. Когда прочитается в память файл X, вызвать функцию Y.

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

Сложно? Наверно. Но по сути это аналог предыдущей схемы, так называемые «зеленые потоки». Только если в предыдущей схеме переключением потоков занималась ОС, тут сама программа имитирует многопоточную работу, вызывая разные функции по очереди. Разница только в том, что с точки зрения ОС тут работает 1 поток, значит никаких переключений контекста делать не надо. На большом числе обрабатываемых запросов выгода получается огромная.

Минусы: обработчики должны работать быстро и не имеют права блокироваться (так как у нас 1 поток и все остальные будут его ждать). Блокироваться имеет право только основная функция, которая получает события от ОС. Так как на высоконагруженном сервере блокировку может вызвать даже операция выделения памяти, часто приходится применять разные трюки, например выделять всю нужную память при старте сервера.
Код надо писать в асинхронной манере.
Если происходит ошибка, то падает весь сервер, так как он весь в одном потоке. Все необработанные запросы теряются.
Если какой-то обработчик выделил память и забыл ее освободить, никто уже ее не освободит. Будет утечка памяти, если они повторяются то процесс рано или поздно займет всю доступную память и будет убит. В случае с процессами-рабочими проблема менее вероятна, так как рабочих можно периодически прибивать, освобождая память.
То есть требуется высокий уровень грамотности и ответственности разработчика.

Плюсы: расходы памяти на один зеленый тред могут быть в сотни раз меньше чем на поток/процесс. Также нет накладных расходов на переключение между ними. Это дает нам возможность иметь сотни тысяч или даже миллион зеленых потоков, хватило бы памяти (естественно при условии что каждый поток не использует много памяти). Используется 100% процессора.

По такой схеме работает веб-сервер nginx, кеш memcached, хранилище redis, платформа Node.JS (реализует веб-сервер на яваскрипте).

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

Заметь что все эти сервера (кроме node.js) не содержат в себе сложной логики, которая может долго выполняться и замедлять обработку запросов. nginx просто раздает файлы с диска по сети или проксирует данные из одного соединения в другое, мемкеш просто кладет небольшие кусочки данных в память или отдает их в сеть. А вот в случае с Node.js все зависит от умения разработчика, и там получить тормоза, утечки памяти довлоьно легко.

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

Эта архитектура стала ответом на проблему C10K - «как поддерживать 10 000 параллельных соединений».
#516 #584379
>>584343

> и как ajax вызовам удается быть асинхронными? Как они обходят однопоточную природу JS?


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

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

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

Вот паста про потоки и асинхронщину:

------------

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

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

В общем ОС может выполнять программы как бы параллельно даже на одном ядре.

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

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

Создание нового потока это если проводить аналогии с PHP, вызов какой-то функции или include какого-то скрипта. То есть программа может взять функцию и запустить ее выполнение отдельным потоком параллельно с основным потоком. В PHP так не делают, PHP программы однопоточные, но так делают в других языках.

Если потоков в процессе несколько, то они все имеют доступ к одной и той же области памяти. То есть если это бы была программа на PHP то все потоки видят одни и те же переменные и функции.

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

-------------

Один асинхронный процесс с 1 потоком

Есть еще одна интересная архитектура. Здесь используется один поток, но используются неблокирующие (асинхронные) обращения к внешним ресурсам вроде файлов или сети. Все описанные выше архитектуры используют блокирующие вызовы. Это значит что когда поток просит ОС прочитать файл с диска или отправить пакет по сети, или хочет получить пакет из сети, он делает системный вызов и блокируется до тех пор пока не будут получены данные.

Асинхронный вызов работает по другому: поток просит ОС начать операцию ввода-вывода, и не блокируется, а продолжает выполняться, а позже может спрашивать у ОС каков статус операции и пришли ли данные. Очевидно что код для работы с асинхронными вызовами будет сложнее. Обычно он строится на так называемом событийном программировании (event-driven programming). То есть внутри программы ведется список выполняющихся операций и список функций которые надо вызвать по их завершении. Например, когда придет новый запрос от клиента, вызвать функцию processRequest. Когда прочитается в память файл X, вызвать функцию Y.

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

Сложно? Наверно. Но по сути это аналог предыдущей схемы, так называемые «зеленые потоки». Только если в предыдущей схеме переключением потоков занималась ОС, тут сама программа имитирует многопоточную работу, вызывая разные функции по очереди. Разница только в том, что с точки зрения ОС тут работает 1 поток, значит никаких переключений контекста делать не надо. На большом числе обрабатываемых запросов выгода получается огромная.

Минусы: обработчики должны работать быстро и не имеют права блокироваться (так как у нас 1 поток и все остальные будут его ждать). Блокироваться имеет право только основная функция, которая получает события от ОС. Так как на высоконагруженном сервере блокировку может вызвать даже операция выделения памяти, часто приходится применять разные трюки, например выделять всю нужную память при старте сервера.
Код надо писать в асинхронной манере.
Если происходит ошибка, то падает весь сервер, так как он весь в одном потоке. Все необработанные запросы теряются.
Если какой-то обработчик выделил память и забыл ее освободить, никто уже ее не освободит. Будет утечка памяти, если они повторяются то процесс рано или поздно займет всю доступную память и будет убит. В случае с процессами-рабочими проблема менее вероятна, так как рабочих можно периодически прибивать, освобождая память.
То есть требуется высокий уровень грамотности и ответственности разработчика.

Плюсы: расходы памяти на один зеленый тред могут быть в сотни раз меньше чем на поток/процесс. Также нет накладных расходов на переключение между ними. Это дает нам возможность иметь сотни тысяч или даже миллион зеленых потоков, хватило бы памяти (естественно при условии что каждый поток не использует много памяти). Используется 100% процессора.

По такой схеме работает веб-сервер nginx, кеш memcached, хранилище redis, платформа Node.JS (реализует веб-сервер на яваскрипте).

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

Заметь что все эти сервера (кроме node.js) не содержат в себе сложной логики, которая может долго выполняться и замедлять обработку запросов. nginx просто раздает файлы с диска по сети или проксирует данные из одного соединения в другое, мемкеш просто кладет небольшие кусочки данных в память или отдает их в сеть. А вот в случае с Node.js все зависит от умения разработчика, и там получить тормоза, утечки памяти довлоьно легко.

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

Эта архитектура стала ответом на проблему C10K - «как поддерживать 10 000 параллельных соединений».
#517 #584387
>>584343

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

Потому разработчики ужом вертятся и придумывают способы обойтись без блокировок. Спецификация Web Worker так сделана, что скрипт в воркере не имеет доступа ни к DOM, ни к переменным в основном скрипте и вообще выполняется в каком-то отдельном изолированном пространстве. Так как нет параллельного доступа к одним и тем же данным из разных скриптов, не нужны и блокировки.
#518 #584462
>>584049
Забыл про адаптивность в 12 задании, поправил.
http://jsfiddle.net/wewnadt2/

Приступаю к макету.
Сходу несколько вопросов.
Некоторые шрифты мой фотошоп не находит, хотя отрисовывает правильно, что интересно. Впрочем фотошоп покалеченный репакерами и запущенный из под вайна.
Но тем не менее встает пара вопросов, во-первых что делать с этими конкретно шрифтами:
Lato Black, Lato Regular и прочие Lato-шрифты, а также ReklameScript RegularDEMO. Я посмотрел они вроде бесплатные, наверное возьму да и подключу. Но какие вообще шрифты являются стандартными? А то вдруг я наподключаю всякого лишнего мусора, что только замедлит сайт.

Дальше, шапку сайта делать фиксированной? Если да, то у меня мимоходом вопрос о поведении фиксированных элементов.
Почему если не указать у фиксированного слоя top-координату, то он начинает реагировать на марджин следующего за ним элемента? Что-то похожее на схлопывание.
http://jsfiddle.net/5s9gk7g3/
Причем лечится так же, как и схлопывание (указанием padding, border и т.д.)
#519 #584464
Как всё-таки разобраться с Вордпресс и другими КМС? Нигде не могу найти уроки как для разработчиков, кругом только уроки того как создать новую запись через админку, но судя по всему разработчик должен учить немного другое. Есть какие-нибудь книги, уроки, видеоматериалы именно как для разработчиков?
#520 #584465
>>584464
Попробуй вбить в гугл "документация cms_name", может повезет.
#521 #584474
>>584462

А не ты ли сдавал на проверку первые 6 заданий на HTML и так до сих пор и не исправил замечания которые я где-то выше написал? Стоит почитать замечания.

> Некоторые шрифты мой фотошоп не находит, хотя отрисовывает правильно


Потому что они у тебя не установлены. Отрисовывает он так как в документе вложен отрисованный текст.

> Но какие вообще шрифты являются стандартными?


Гарантированно работают везде только стандартные абстрактные названия serif, sans-serif, monospace, cursive, fantasy и по моему все.

Но есть шрифты, которые входят в поставку Windows, MacOS, и у многих линуксоидов стоят. Так называемые Web Safe Fonts:

http://www.cssfontstack.com/ (стоит ориентироваться на планку 97-99% на Windows)
http://www.wearymax.ru/webmasters/fonts/
http://web.mit.edu/jmorzins/www/fonts.html

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

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


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

Подключи, а потом посмотрим.

> Дальше, шапку сайта делать фиксированной?


Ни в коем случае, макет такого не предусматривает да и мне это не нравится.

> Почему если не указать у фиксированного слоя top-координату, то он начинает реагировать на марджин следующего за ним элемента?


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

Подсказки:
1) Коллапсинг не применяется к флоат и позиционированным элементам (включая fixed). И к header тоже.
2) absolute и fixed элементы вырываются из потока и не влияют на соседние и родительские элементы
3) Если не указать top/left/bottom/right то позиционированный элемент выводится в том месте, где вывелся бы текст будь он на месте этого элемента.

Ну а чтобы понять что происходит в твоем случае, открой отладчик и посмотри размер и расположение элемента body и html.
#521 #584474
>>584462

А не ты ли сдавал на проверку первые 6 заданий на HTML и так до сих пор и не исправил замечания которые я где-то выше написал? Стоит почитать замечания.

> Некоторые шрифты мой фотошоп не находит, хотя отрисовывает правильно


Потому что они у тебя не установлены. Отрисовывает он так как в документе вложен отрисованный текст.

> Но какие вообще шрифты являются стандартными?


Гарантированно работают везде только стандартные абстрактные названия serif, sans-serif, monospace, cursive, fantasy и по моему все.

Но есть шрифты, которые входят в поставку Windows, MacOS, и у многих линуксоидов стоят. Так называемые Web Safe Fonts:

http://www.cssfontstack.com/ (стоит ориентироваться на планку 97-99% на Windows)
http://www.wearymax.ru/webmasters/fonts/
http://web.mit.edu/jmorzins/www/fonts.html

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

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


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

Подключи, а потом посмотрим.

> Дальше, шапку сайта делать фиксированной?


Ни в коем случае, макет такого не предусматривает да и мне это не нравится.

> Почему если не указать у фиксированного слоя top-координату, то он начинает реагировать на марджин следующего за ним элемента?


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

Подсказки:
1) Коллапсинг не применяется к флоат и позиционированным элементам (включая fixed). И к header тоже.
2) absolute и fixed элементы вырываются из потока и не влияют на соседние и родительские элементы
3) Если не указать top/left/bottom/right то позиционированный элемент выводится в том месте, где вывелся бы текст будь он на месте этого элемента.

Ну а чтобы понять что происходит в твоем случае, открой отладчик и посмотри размер и расположение элемента body и html.
#522 #584478
>>584474

>не ты ли


Нет не я, мои первые шесть заданий ты уже проверил здесь.
>>581863
А 6-12 я тут уже наверное сутки бампаю, чтобы не утонули в флуде.
>>583514
>>584049

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

Да, с фиксированным хедером это я конечно обкурился. Но тем не менее интересно поведение фиксировных элементов.
1708 Кб, 1920x1200
#523 #584499
>>582608

ОП, обрати внимание
#524 #584529
Начал разбираться с битриксом путем допиливания функционала. Читаю код, а там при отправке данных через аякс передаются данные data: data + "&callback&x=1". x - типо флага какого-то. В скрипте в который идет отправка идет проверка
if( !isset($_POST['x']) )
{
\tdie("Hacking Attempt");
}
Как это вообще может помочь, если можно в скрипте в браузере посмотреть какие данные нужно отправить?
#525 #584560
>>584364

>Ты не можешь крутить спиннер во время выполнения jS кода так как выполнение JS кода блокирует DOM и браузер не имеет права ничего делать со страницей в это время.



Сдается мне, ты пиздишь. Я показываю спиннер (обычная гифка), вызываю функцию сорт. Почему моя функция помешает гифке крутиться?
177 Кб, 1164x557
#526 #584566
>>584560
Тащемта ты оказалася прав. $(spinner).show() хоть и выполняется, но гифка не показывается. Потом выполняется sort, а потом гифка благополучно скрывается не успев появиться...

Выкрутился из этого так:

angular.element('#overlay-loader').css('display', 'block');
$timeout(
function() {
$scope.items = $scope.sortAllocationList($scope.items, duration);
}, 0);

$timeout(function() {
console.log('hidden');
angular.element('#overlay-loader').css('display', 'none');
}, 0);

Т.е. вместо выполнения сорт в нормальном потоке, я вытащил его вместе с кодом скрытия спиннера и запланировал их на ближайшее время. То, что angular.element('#overlay-loader').css('display', 'block'); выполнилось раньше их везение или закономерность, которая следует из того что строка расположена выше по коду? Я не знаю. Интересный момент, который не раз уже замечал: Если идти по скрипту дебаггером, то всё работает не так, как когда скрипт выполняется без дебаггера. Например, в дебаггере моя дом манипуляция (show()) нормально выполнятся и элемент становится видимым. Потом отрабатывает сорт, а потом элемент скрывается. Без дебаггера всё не так, а как я описал выше. Почему так? Кто-нибудь знает?
#527 #584573
>>584560
лол поменял текст "загрузка..." на гифку. Она действительно не крутится пока работает сортировка. Почему-то я удивлен. ЧЗХ? Это же просто анимированная картинка? Разве JS как-то участвует в анимировании гифок?
#528 #584624
Как выловить ошибку Unable to open file!
не пишет ни строку ни файл который не может открыть (отображение ошибок включено)
#529 #584630
>>584624
Логи ошибок пхп драйвера по этому случаю ничего не отображают
#530 #584636
http://integer64.github.io/makeup/
Исправил замечания. Сделал 7 задание.
#531 #584643
>>584566
В чем можно дебажить под смартфоны как на пике?
#532 #584648
>>584566

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

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

Насчет отладчика, браузеры обображают изменения в ДОМ после завершения скрипта, а в случае с отладчиком видимо при выходе в отладчик, отсюда разница.

В любом случае тебе надо разобраться с ангуларом. Это не такая штука которую достаточно подключить и все само заработает. Нужно разбираться как именно оно работает, что в нем делать можно, а что не стоит. У тебя явно что-то криво сделано если оно тормозит.
#533 #584649
>>584624

Значит это не PHP ошибка. найди эти слова поиском по коду и посмотри кто это выводит.

>>584643

Хром и Сафари вроде можно отладчиком с компьютера отлаживать: https://developers.google.com/web/tools/chrome-devtools/debug/remote-debugging/remote-debugging

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

https://www.google.ru/search?q=mobile+browser+debugging&btnG=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA&newwindow=1&gbv=1
#535 #584652
Аноны, кого я не проверил, я постараюсь сегодня найти время посмотреть ваши решения начиная с самых старых, был занят, не ждите меня, решайте пока дальше задания.
#536 #584653
>>584650

Думаю там был вопрос про отладку на реальном устройстве.
#537 #584658
>>584566

Алсо, я еще вспомнил, если неправильно работать с DOM например удалять или скрывать элементы, не удаляя биндинги, то их тоже становится со временме много и страница может тормозить.
#538 #584676
>>584649
>>584650
Спасибо.
#539 #584807
http://integer64.github.io/makeup
8 задание.
Сделал 2 варианта, т.к. не до конца понял условия задачи.
Может оба не правильно сделал...
#540 #584810
>>584649
Всё, нашел в логе цмски.
#541 #584939
>>584648

>А, вот и секрет раскрылся. Ты наверно неправильно используешь ангулар и преодолел ограничение на 1000-2000 биндингов.



Что за ограничение? где про это подробней почитать можно?
#542 #584970
>>584939
Ну что ты за пидор? Кто за тебя гуглить будет.
Сложно набрать dirty checking 2000 bindings?
32 Кб, 720x400
#543 #585025
>>584335
АААААААААААААААААААААААААААААААААА
У меня уже какой-то консольный кретинизм возникает. Оп помоги плс.
#544 #585032
>>585025
nano /etc/network/interfaces
571 Кб, 1280x1024
#545 #585049
>>585032
АААААААААААААААААААААААААААААААААААААААААА
571 Кб, 1280x1024
#546 #585057
>>585049
Сори, горю просто очень сильно
#547 #585092
>>585057
Фаервол виртуальную машину не душит?
#548 #585096
Господа, как написать графический редактор, чтобы на входе принимал json массив, ну как граффити вконтакте и чатурелтке?
И вообще как воткнуть видео и аудио, чтобы два и больше человека через сайт по вебке общаться могли, как в чатрулетке и скайпе?
571 Кб, 1280x1024
#549 #585103
>>585092
Неа - он у меня перманентом выключен
#550 #585105
>>585103
Опять извиняюсь за репик - это макаба не убрала его после прошлого поста
#551 #585248
Если с одной работы погнали, это же не страшно, бывают же ебанутые начальники? Нельзя же требовать чего-то от спеца, если не можешь создать для него нормальные условия труда.
39 Кб, 775x580
#552 #585531
Можете подсказать косяки в решении/оформлении?
http://pastebin.com/PkL0s9WU
#553 #585545
>>585531
Чего вы все одновременно кинулись решать задачи на верстку?

Код лучше выкладывать на jsfiddle, там можно сразу посмотреть результат, css и html писать в разные окошки.
Так все правильно, только в условии еще требуется выставить по 10 пикселов слева, справа и сверху. А может быть и снизу. Кто знает, вдруг понадобится добавить еще один или несколько блоков снизу? Дописывать каждому margin-top, как ты сделал со вторым блоком?
Лучше всем блокам выставить одинаковый margin: 10px со всех сторон. Между блоками марджин не суммируется, а берется максимальный из двух, это называется margin collapse, или "схлопывание границ", как пытаются это перевести.
http://softwaremaniacs.org/blog/2005/09/05/css-layout-flow-margins/
#554 #585548
>>585545
Проходил курсы htmlacademy и решил, что двигаюсь слишком медленно.

До этого около месяца сидел в качестве неосилятора, периодически изучающего вёрстку и php.
#555 #585561
>>585531
Косяк сделал твой папка, когда не вытащил.
#556 #585564
#557 #585641
Вот тут пишут, что соль бесполезна при взломе, если уж решили ломануть. http://habrahabr.ru/post/145667/
Кстати, а как скрипт написать, который генерит пароли (ну это еще я знаю) и вводит их в инпут?
#558 #585705
Уф, полдня потратил на рисование. Аноны, кто изучает JS, и хочет подступиться к backbone или angular, посмотрите какое я вам интересное задание придумал под конец курса: https://github.com/codedokode/pasta/blob/master/js/spa.md

Впервые кстати рисовал картинку в Inkscape, намного удобнее чем в фотошопе.

Сейчас покушаю чего-нибудь и буду проверять не проверенные задачки.
#559 #585708
Есть ли смысл начинать смотреть вакансии на джуна, если освоил основы ООП и MVC, а в качестве примера небольшой ИМ с админкой в которой можно добавлять товары, редактировать уже добавленные и смотреть список заказов? Правда понятно, что там все совсем не идеально скорее всего реализовано. Хотелось бы уже на реальных задачах опыт получать. Или нужно еще движки какие-то знать? Сложно ли вообще в движках освоиться?
#560 #585718
>>585708

>начинать смотреть вакансии


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

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

>нужно еще движки какие-то знать


Нужно. Вакансий не так много, чтобы брезговать cms, а это в требуют в большинстве случаев.

>Сложно ли вообще в движках освоиться


Не сложно.
#561 #585727
>>585708

Можешь попробовать, почему нет?
#562 #585734
>>585705
Таскать дни и зажимать треугольники, вообще ахуеть, это все заказчики так уебищно задания описывают?
20 Кб, 200x256
#563 #585745
Вброшу пока свой макет, там все почти готово, сейчас только допилю адаптивные фичи.

http://nsdvw.github.io/template.html

Не знаю, насколько удачно я решил вопрос с центрированием блоков (вложил в каждый блок, который занимает 100% ширины экрана, еще один блок-контейнер с максимальной шириной). Может есть более красивые решения.

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

Мелкие картинки типа значка телефона или маркера гугл-карт надеялся найти в виде символа юникода, но там что угодно, но не то что нужно. Сделал спрайтом.

В фотошопе почему-то не получалось сохранять слои с прозрачностью в отдельный файл, появлялась либо белая обводка вдоль краев, либо зубчатые края. В общем, что-то связанное с антиалайзингом.
А в гимпе все четенько сохранилось, гимп не так уж и плох. Единственное что я пока не знаю, как в нем смотреть шрифты. В фотошопе есть специальная закладка с форматированием шрифтов, там и семейство, и размер шрифта.
https://github.com/someApprentice/Cat-and-Mouse/ #564 #585923
Дошла очередь и до кошек мышек. Вот немного замечаний.

>>581290

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


Ну рассмотрим функцию rateMoves которая находится в классе Mouse. Разумеется Мышь знает кого она боится (кошек), потому она знает какие животные ее интересуют. Потому передавать их снаружи не требуется.

Наоборот, этот аргумент функции только запустывает понимание кода. А что если я пишу животное которому безразличны окружающие, что я должен передавать в $serach? А если я пишу животное, которое боится одни виды и охотится за другими, что мне передавать в $serach?

Чтобы писать хороший и понятный ООП код, надо понимать за что каждый класс отвечает. В базовый класс Animal мы кладем общие методы, код, который не относится к конкретному животному, а который может пригодиться разным животным. А в конкретный класс животного, например, Mouse или Cat мы кладем методы, которые относятся только к этому животному, которые нужны только ему.

Так как абстрактная функция rateMoves объявлена в базовом классе Animal, она должна быть максимально универсальна. Я думаю что универсальнее всего не передавать в нее $search, а позволить реализации этой функции в конкретном животном самой получить нужные данные.

https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/World.php#L36

> foreach ($map as $object) {


> if ($this->determineTheObject($animal->getX(), $animal->getY())) {


Непонятно зачем здесь цикл foreach

> https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/World.php#L61


> if ($object == $animal) {


Неправильно сравниваешь объекты. Почитай мануал: http://php.net/manual/ru/language.oop5.object-comparison.php

Тебе нужно сравнивать объекты по идентичности, то есть что обе ссылки указывают на один и тот же объект.

> https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/World.php#L92


> if ($x > $this->width


Допустим ширина поля width = 10. Очевидно что это значит что карта имеет 10 клеточек в ширину. У тебя отсчет координат начинается с 0, и 10 клеточек имеют координаты от 0 до 9. Если у животного x = 10 то оно находится не на карте.

А твоя функция при x = 10 вернет true, что животное в пределах карты.

> https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/Animal.php#L32


> abstract function rateMoves($moves, $search);


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

А как ее реализовать, не очень понятно: функция принимает 2 переменных, массив (хотя тайп-хинта array почему-то нет) ходов $moves неизвестного формата и непонятная переменная $search. Что должно быть в $search например? $search переводится как «поиск», и что в этой переменной хранится?

Соответственно вопросы такие:

1) почему функция оценки хода принимает на вход не один ход, а массив ходов? Тебе не кажется что функция оценки одного хода - проще чем функция оценки нескольких ходов?

Ну то есть представь, я хочу сделать новое животное. Мне ведь проще написать функцию оценки одного хода, которая получает на вход координаты клеточки, а на выходе дает число баллов, а ты требуешь от меня еще дополнительно написать цикл где я перебираю все ходы в $moves и оцениваю по очереди. Но ведь это можно сделать в классе Animal, пусть цикл будет в нем, а от меня требуется только функция оценки одного хода.

2) зачем этой функции кроме самих ходов на вход подается еще одна какая-то непонятная переменная $search? Эта переменная нужна для оценки ходов и без нее не обойтись?

Конечно открыв код классса Mouse мы видим что в $search передается массив с кошками. Но зачем? Что, функция оценки сама не может этот массив получить? И если я делаю, например, новое животное, Слона, что я должен передавать вместо $search? Допустим слону безразличны кошки и мышки, и передавать массив кошек нет смысла.

> https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/Animal.php#L116


> protected function isItCorner($x, $y) {


Там какой-то странный способ определить что мы в углу. Не проще ли определить по координатам?

> https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/Mouse.php#L39


> public function rateMove($x, $y, $search) {


Ты можешь объяснить алгоритм работы этой функции? Я его не понимаю:

> $rate = 0;


> ...


> foreach ($search as $object) {


> ....


> $movesCount = $this->howManyMovesWillDoAnimal($object, $distance);


> $rate = $movesCount;


> ....


> }


С таким кодом $rate всегда будет равен расстоянию до последнего элемента в массиве $search. Зачем тогда нужен цикл? Зачем вычислять расстояние до первой, второй, третьей кошек если в $rate пойдет только расстояние до последнией?

И еще, есть такая вещь, как понятность и читабельность кода. Сможет ли другой человек разобраться в программе? У тебя с этим не очень хорошо. Например непонятно по каким критериям и как подсчитывается число баллов за ход. Непонятно, вообще какой ход лучше - где больше баллов или меньше? Почему бы не добавить краткий комментарий?
https://github.com/someApprentice/Cat-and-Mouse/ #564 #585923
Дошла очередь и до кошек мышек. Вот немного замечаний.

>>581290

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


Ну рассмотрим функцию rateMoves которая находится в классе Mouse. Разумеется Мышь знает кого она боится (кошек), потому она знает какие животные ее интересуют. Потому передавать их снаружи не требуется.

Наоборот, этот аргумент функции только запустывает понимание кода. А что если я пишу животное которому безразличны окружающие, что я должен передавать в $serach? А если я пишу животное, которое боится одни виды и охотится за другими, что мне передавать в $serach?

Чтобы писать хороший и понятный ООП код, надо понимать за что каждый класс отвечает. В базовый класс Animal мы кладем общие методы, код, который не относится к конкретному животному, а который может пригодиться разным животным. А в конкретный класс животного, например, Mouse или Cat мы кладем методы, которые относятся только к этому животному, которые нужны только ему.

Так как абстрактная функция rateMoves объявлена в базовом классе Animal, она должна быть максимально универсальна. Я думаю что универсальнее всего не передавать в нее $search, а позволить реализации этой функции в конкретном животном самой получить нужные данные.

https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/World.php#L36

> foreach ($map as $object) {


> if ($this->determineTheObject($animal->getX(), $animal->getY())) {


Непонятно зачем здесь цикл foreach

> https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/World.php#L61


> if ($object == $animal) {


Неправильно сравниваешь объекты. Почитай мануал: http://php.net/manual/ru/language.oop5.object-comparison.php

Тебе нужно сравнивать объекты по идентичности, то есть что обе ссылки указывают на один и тот же объект.

> https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/World.php#L92


> if ($x > $this->width


Допустим ширина поля width = 10. Очевидно что это значит что карта имеет 10 клеточек в ширину. У тебя отсчет координат начинается с 0, и 10 клеточек имеют координаты от 0 до 9. Если у животного x = 10 то оно находится не на карте.

А твоя функция при x = 10 вернет true, что животное в пределах карты.

> https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/Animal.php#L32


> abstract function rateMoves($moves, $search);


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

А как ее реализовать, не очень понятно: функция принимает 2 переменных, массив (хотя тайп-хинта array почему-то нет) ходов $moves неизвестного формата и непонятная переменная $search. Что должно быть в $search например? $search переводится как «поиск», и что в этой переменной хранится?

Соответственно вопросы такие:

1) почему функция оценки хода принимает на вход не один ход, а массив ходов? Тебе не кажется что функция оценки одного хода - проще чем функция оценки нескольких ходов?

Ну то есть представь, я хочу сделать новое животное. Мне ведь проще написать функцию оценки одного хода, которая получает на вход координаты клеточки, а на выходе дает число баллов, а ты требуешь от меня еще дополнительно написать цикл где я перебираю все ходы в $moves и оцениваю по очереди. Но ведь это можно сделать в классе Animal, пусть цикл будет в нем, а от меня требуется только функция оценки одного хода.

2) зачем этой функции кроме самих ходов на вход подается еще одна какая-то непонятная переменная $search? Эта переменная нужна для оценки ходов и без нее не обойтись?

Конечно открыв код классса Mouse мы видим что в $search передается массив с кошками. Но зачем? Что, функция оценки сама не может этот массив получить? И если я делаю, например, новое животное, Слона, что я должен передавать вместо $search? Допустим слону безразличны кошки и мышки, и передавать массив кошек нет смысла.

> https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/Animal.php#L116


> protected function isItCorner($x, $y) {


Там какой-то странный способ определить что мы в углу. Не проще ли определить по координатам?

> https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/Mouse.php#L39


> public function rateMove($x, $y, $search) {


Ты можешь объяснить алгоритм работы этой функции? Я его не понимаю:

> $rate = 0;


> ...


> foreach ($search as $object) {


> ....


> $movesCount = $this->howManyMovesWillDoAnimal($object, $distance);


> $rate = $movesCount;


> ....


> }


С таким кодом $rate всегда будет равен расстоянию до последнего элемента в массиве $search. Зачем тогда нужен цикл? Зачем вычислять расстояние до первой, второй, третьей кошек если в $rate пойдет только расстояние до последнией?

И еще, есть такая вещь, как понятность и читабельность кода. Сможет ли другой человек разобраться в программе? У тебя с этим не очень хорошо. Например непонятно по каким критериям и как подсчитывается число баллов за ход. Непонятно, вообще какой ход лучше - где больше баллов или меньше? Почему бы не добавить краткий комментарий?
#565 #585973
>>581303

В том что первые 2 это реляционные СУБД, а третья - NoSQL хранилище.

>>581601

Тебе ответил выше >>581862

>>582117

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


> Может, ты имеешь ввиду что нужно вынести зависимость в переменную и передавать ее из контроллера?


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

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

> Я думаю, что они типа для краткости так сделали, чтобы не писать код и в контроллере, и в представлении, но это действительно только запутывает.


Да, наверно.

> Не знаю, что делать с инвалидацией, или как это называется.


При добавлении/удалении города очищать кеш со списком городов.

>>582189

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

Еще Jira есть.

> У yii в issues просто какой-то бложик, где чуваки своими словами говорят


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

Обрати внимание, что есть и другие интересные инструменты организации совместной работы над проектами:

- basecamp от знаменитых 37signals (это люди которые сделали Ruby on Rails и написали книгу Getting real) - https://basecamp.com/
- trello (который сделала компания Джоэла Спольски, раньше он был известен своим блогом Joel on Software, а сейчас его знают как основателя Stack Overflow): https://trello.com/ Trello напоминает систему основанную на карточках из канбан.
- slack - популярный среди хипстеров чат

Вообще сейчас есть куча инструментов для совместной работы, видимо людей вдохновил успех 37signals.

> Я себе представлял более формализованную систему, типа таблицы в бд.


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

Нет, обычно просто есть какой-то общепринятый шаблон, по которому описывают баг. Например, шаги для повторения бага (how to reproduce), ожидаемый результат, фактический результат.

> Хочется просто обезопасить себя, а то вот приду на работу, а мне скажут "напиши баг-репорт" или "пофикси баг под номером 12345", а я не буду знать, что это такое и как там все организовано.


Я конечно сомневаюсь что с этим будут проблемы. Самые известные это наверно Redmine и Jira. Причем сам сайт redmine на нем же и сделан: http://www.redmine.org/projects/redmine/issues?set_filter=1&tracker_id=1

Я бы готовился к другому варианту: ты приходишь на работу, а там ни багтрекера, ни системы контроля версий, и надо верстку на вордпресс натягивать.
#565 #585973
>>581303

В том что первые 2 это реляционные СУБД, а третья - NoSQL хранилище.

>>581601

Тебе ответил выше >>581862

>>582117

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


> Может, ты имеешь ввиду что нужно вынести зависимость в переменную и передавать ее из контроллера?


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

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

> Я думаю, что они типа для краткости так сделали, чтобы не писать код и в контроллере, и в представлении, но это действительно только запутывает.


Да, наверно.

> Не знаю, что делать с инвалидацией, или как это называется.


При добавлении/удалении города очищать кеш со списком городов.

>>582189

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

Еще Jira есть.

> У yii в issues просто какой-то бложик, где чуваки своими словами говорят


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

Обрати внимание, что есть и другие интересные инструменты организации совместной работы над проектами:

- basecamp от знаменитых 37signals (это люди которые сделали Ruby on Rails и написали книгу Getting real) - https://basecamp.com/
- trello (который сделала компания Джоэла Спольски, раньше он был известен своим блогом Joel on Software, а сейчас его знают как основателя Stack Overflow): https://trello.com/ Trello напоминает систему основанную на карточках из канбан.
- slack - популярный среди хипстеров чат

Вообще сейчас есть куча инструментов для совместной работы, видимо людей вдохновил успех 37signals.

> Я себе представлял более формализованную систему, типа таблицы в бд.


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

Нет, обычно просто есть какой-то общепринятый шаблон, по которому описывают баг. Например, шаги для повторения бага (how to reproduce), ожидаемый результат, фактический результат.

> Хочется просто обезопасить себя, а то вот приду на работу, а мне скажут "напиши баг-репорт" или "пофикси баг под номером 12345", а я не буду знать, что это такое и как там все организовано.


Я конечно сомневаюсь что с этим будут проблемы. Самые известные это наверно Redmine и Jira. Причем сам сайт redmine на нем же и сделан: http://www.redmine.org/projects/redmine/issues?set_filter=1&tracker_id=1

Я бы готовился к другому варианту: ты приходишь на работу, а там ни багтрекера, ни системы контроля версий, и надо верстку на вордпресс натягивать.
Верстка #566 #585974
>>582365

на удаленке

>>582504

> Насчет меньших разрешений и прочих манипуляций с графикой, то в yii такого нет, насколько я знаю.


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

> Главная цель ассетов в том, чтобы Владимир и Василий, работающие над двумя разными модулями, могли одновременно создать файл style.css, чтобы не было конфликта имен.


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

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


Да, из-за этого.

> Только что установил мантис, оказывается это тупо графический интерфейс


Цвета интересные, напоминают официальный сайт PHP.

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


Убедись сначала что ты разобрался как работает clear, например тут: http://softwaremaniacs.org/blog/2005/12/01/css-layout-float/ (это по моему очень хороший учебник, я сам по нем учился)

clear можно применять как к обычным блокам, так и к флоатам. В обоих слуаях он добавляет отступ сверху (похожий на margin top) так, чтобы блок с clear оказался ниже чем нижний край флоатов перед ним.

Но свойство clear сдвигает блок, к которому оно применено. А можно ли как-то сделать чтобы блок охватывал содержщиеся в нем флоаты, растягиваясь до их высоты? Вообще да, можно просто в конец этого блока добавить элемент с clear:

<div class="wrap" title="Блок который содержит флоаты, мы хотим чтобы они из него не выпадали">
... флоаты ...
... контент ...
<div style="clear:both;" title="Див-помощник">
</div>

Элементу с clear будет добавлен отступ сверху такой, что он будет ниже всех флоатов. Соответственно и div.wrap растянется до нужной высоты (попробуй запустить этот код в jsfiddle).

clearfix делает то же самое, только с помощью псевдоэлемента (почитай про них если не читал), не требуя от нас вставлять в верстку бессмысленные дивы. Свойство content нужно чтобы псевдоэлемент появился, clear понятно зачем, а display: block нужен так как псевдоэлементы по умолчанию инлайновые и к ним видимо не применяется clear. Тут нет ни одного лишнего свойства, хотя конечно само наличие таких вот хаков показывает недоработки в CSS. Флоаты ведь предназначались для добавления картинок в текст, а не сложной верстки. Ну не беда, года через 3 перейдем на flexbox и забудем про это.

> здесь неясность относительно того, что они назвали box - контейнер элемента или сам элемент)


Бокс это воображаемый прямоугольник который соответствует позиции элемента на холсте, по моему так. Вот смотри, в начале спецификации написано:

http://www.w3.org/TR/CSS21/visuren.html#visual-model-intro

> In the visual formatting model, each element in the document tree generates zero or more boxes according to the box model.


То есть из дерева DOM генерируется дерево боксов (воображаемых прямоугольников), которые позже и отрисовываются на экране. Заметь что элемент в дереве DOM может не генерировать боксов вообще (если у него стоит display: none) или генерировать несколько (если есть псевдоэлементы или если требуется добавить анонимный бокс. Анонимный бокс появляется когда у нас например идет: див, текст, див. Текст оборачивается в блочный анонимный бокс в такой ситуации: http://www.w3.org/TR/CSS21/visuren.html#anonymous-block-level ).

Заметь что боксы - это абстрактная вещь, нужная для того чтобы объяснить процесс раскладки элементов на странице. Однако браузеры реализуют похожую схему, они тоже генерируют дерево боксов. Вот статья, которая описывает реализацию этой системы в браузере: http://www.html5rocks.com/ru/tutorials/internals/howbrowserswork/

Вот там это упомянуто:

> http://www.html5rocks.com/ru/tutorials/internals/howbrowserswork/#Render_tree_construction


> Во время построения дерева DOM браузер создает еще одну структуру – дерево отображения. В нем визуальные элементы размещаются в том порядке, в каком их необходимо вывести на экран. Это визуальное представление документа.



> content:"" контент вроде бы является обязательным для псевдоэлементов before и after, иначе они будут проигнорированы. Но я не уверен.


Иначе они не создаются.

> Седьмая задача.


Попробуй ввести что-то в инпут. Текст прилипает к левому краю и это некрасиво. В инпуте по умолчанию стоит 2px паддинг и ты не должен его убирать.

>>582558

> Восьмое задание.


Ой-ой-ой, от твоего HTML у меня глаза вытекают. Зачем ты нагородил лестницу из дивов? Давай-ка для начала изучим HTML раз ты эту тему проскочил.

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

Как можно сверстать документ на картинке? Ну очевидно, там идет абзац текста - <p>. За ним - примечание, его можно сделать дивом с классом, <p> с классом или HTML5 тегом <aside> который «can be used for typographical effects like pull quotes or sidebars, for advertising» (кстати, если ты не читал полный список HTML5 тегов, нагугли и прочитай чтобы знать).

Итак, вот неплохая на мой взгляд (сам себя не похвалишь...) верстка текста с картинки:

<p>Абзац 1<p>
<aside>Примечание</aside>
<p>Абзац2</p>

Трудно не заметить блестящее владение автором кода технологией HTML-разметки.

Сравни этот HTML код со своим. У тебя идут элементы .container, .wrapper - какую смысловую нагрузку они несут? Никакой, это костыли которые верстальщик вставил чтобы облегчить себе жизнь. Пришел и намусорил в коде. Прямо как в прошлом тысячелетии, когда использовалась табличная верстка и каждый тег заворачивался в <td>, <tr> и <table>, а маргины делались с помощью прозрачных картинок. Пусть ему будет стыдно.

Пожалуй текст из 2 абзацев скучноват, так что добавь в него еще заголовок и список:

<h1>Заголовок</h1>
<ul><li>Список</li><li>Список</li></ul>

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

> Куда дописать? В правую колонку? Попытался предусмотреть.


В правую колонку - любое число абзацев, заголовков, картинок, таблиц, в левую - любое число примечаний. Это правило для защиты от тех кто думает что у нас всегда ровно 2 абзаца справа.

> Это еще почему? Или имеются ввиду внешние границы? В общем, сделал левую колонку плавающей влево и параграф с отступом слева.


Ты сверстай, а мы посмотрим.
Верстка #566 #585974
>>582365

на удаленке

>>582504

> Насчет меньших разрешений и прочих манипуляций с графикой, то в yii такого нет, насколько я знаю.


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

> Главная цель ассетов в том, чтобы Владимир и Василий, работающие над двумя разными модулями, могли одновременно создать файл style.css, чтобы не было конфликта имен.


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

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


Да, из-за этого.

> Только что установил мантис, оказывается это тупо графический интерфейс


Цвета интересные, напоминают официальный сайт PHP.

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


Убедись сначала что ты разобрался как работает clear, например тут: http://softwaremaniacs.org/blog/2005/12/01/css-layout-float/ (это по моему очень хороший учебник, я сам по нем учился)

clear можно применять как к обычным блокам, так и к флоатам. В обоих слуаях он добавляет отступ сверху (похожий на margin top) так, чтобы блок с clear оказался ниже чем нижний край флоатов перед ним.

Но свойство clear сдвигает блок, к которому оно применено. А можно ли как-то сделать чтобы блок охватывал содержщиеся в нем флоаты, растягиваясь до их высоты? Вообще да, можно просто в конец этого блока добавить элемент с clear:

<div class="wrap" title="Блок который содержит флоаты, мы хотим чтобы они из него не выпадали">
... флоаты ...
... контент ...
<div style="clear:both;" title="Див-помощник">
</div>

Элементу с clear будет добавлен отступ сверху такой, что он будет ниже всех флоатов. Соответственно и div.wrap растянется до нужной высоты (попробуй запустить этот код в jsfiddle).

clearfix делает то же самое, только с помощью псевдоэлемента (почитай про них если не читал), не требуя от нас вставлять в верстку бессмысленные дивы. Свойство content нужно чтобы псевдоэлемент появился, clear понятно зачем, а display: block нужен так как псевдоэлементы по умолчанию инлайновые и к ним видимо не применяется clear. Тут нет ни одного лишнего свойства, хотя конечно само наличие таких вот хаков показывает недоработки в CSS. Флоаты ведь предназначались для добавления картинок в текст, а не сложной верстки. Ну не беда, года через 3 перейдем на flexbox и забудем про это.

> здесь неясность относительно того, что они назвали box - контейнер элемента или сам элемент)


Бокс это воображаемый прямоугольник который соответствует позиции элемента на холсте, по моему так. Вот смотри, в начале спецификации написано:

http://www.w3.org/TR/CSS21/visuren.html#visual-model-intro

> In the visual formatting model, each element in the document tree generates zero or more boxes according to the box model.


То есть из дерева DOM генерируется дерево боксов (воображаемых прямоугольников), которые позже и отрисовываются на экране. Заметь что элемент в дереве DOM может не генерировать боксов вообще (если у него стоит display: none) или генерировать несколько (если есть псевдоэлементы или если требуется добавить анонимный бокс. Анонимный бокс появляется когда у нас например идет: див, текст, див. Текст оборачивается в блочный анонимный бокс в такой ситуации: http://www.w3.org/TR/CSS21/visuren.html#anonymous-block-level ).

Заметь что боксы - это абстрактная вещь, нужная для того чтобы объяснить процесс раскладки элементов на странице. Однако браузеры реализуют похожую схему, они тоже генерируют дерево боксов. Вот статья, которая описывает реализацию этой системы в браузере: http://www.html5rocks.com/ru/tutorials/internals/howbrowserswork/

Вот там это упомянуто:

> http://www.html5rocks.com/ru/tutorials/internals/howbrowserswork/#Render_tree_construction


> Во время построения дерева DOM браузер создает еще одну структуру – дерево отображения. В нем визуальные элементы размещаются в том порядке, в каком их необходимо вывести на экран. Это визуальное представление документа.



> content:"" контент вроде бы является обязательным для псевдоэлементов before и after, иначе они будут проигнорированы. Но я не уверен.


Иначе они не создаются.

> Седьмая задача.


Попробуй ввести что-то в инпут. Текст прилипает к левому краю и это некрасиво. В инпуте по умолчанию стоит 2px паддинг и ты не должен его убирать.

>>582558

> Восьмое задание.


Ой-ой-ой, от твоего HTML у меня глаза вытекают. Зачем ты нагородил лестницу из дивов? Давай-ка для начала изучим HTML раз ты эту тему проскочил.

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

Как можно сверстать документ на картинке? Ну очевидно, там идет абзац текста - <p>. За ним - примечание, его можно сделать дивом с классом, <p> с классом или HTML5 тегом <aside> который «can be used for typographical effects like pull quotes or sidebars, for advertising» (кстати, если ты не читал полный список HTML5 тегов, нагугли и прочитай чтобы знать).

Итак, вот неплохая на мой взгляд (сам себя не похвалишь...) верстка текста с картинки:

<p>Абзац 1<p>
<aside>Примечание</aside>
<p>Абзац2</p>

Трудно не заметить блестящее владение автором кода технологией HTML-разметки.

Сравни этот HTML код со своим. У тебя идут элементы .container, .wrapper - какую смысловую нагрузку они несут? Никакой, это костыли которые верстальщик вставил чтобы облегчить себе жизнь. Пришел и намусорил в коде. Прямо как в прошлом тысячелетии, когда использовалась табличная верстка и каждый тег заворачивался в <td>, <tr> и <table>, а маргины делались с помощью прозрачных картинок. Пусть ему будет стыдно.

Пожалуй текст из 2 абзацев скучноват, так что добавь в него еще заголовок и список:

<h1>Заголовок</h1>
<ul><li>Список</li><li>Список</li></ul>

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

> Куда дописать? В правую колонку? Попытался предусмотреть.


В правую колонку - любое число абзацев, заголовков, картинок, таблиц, в левую - любое число примечаний. Это правило для защиты от тех кто думает что у нас всегда ровно 2 абзаца справа.

> Это еще почему? Или имеются ввиду внешние границы? В общем, сделал левую колонку плавающей влево и параграф с отступом слева.


Ты сверстай, а мы посмотрим.
Верстка и ява #567 #585975
>>582605

> Девятое задание.


Слишком много тегов. Чтобы ты не мучался, я предлагаю 2 варианта верстки блока:

<div title="блок">
<div title="картинка"></div>
<div title="контент">контент</div>
</div>

и второй который мне нравится больше:

<div title="блок">
<div title="картинка"></div>
контент
</div>

>>582606

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

>>582608
>>583813
>>584499

Меня напрягает что ты функцию main() засунул прямо в UserAccount. Ты уверен что это правильно и она нужна для работы класса UserAccount или все же она должна быть где-то отдельно?

> public void getbalance(){


> System.out.println(name + " have " + money + " dollars");


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

> public double money;


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

Вот еще паста про инкапсуляцию:

---------

Это так называемая инкапсуляция, когда свойства помечены как private/protected и прямой доступ к ним имеет только сам класс, а не вся программа. Это делает код более надежным, а классы менее связанными друг с другом (то есть один класс не лезет внутрь другого, а лишь вызвает разрешенные методы). Инкапсуляция особенно важна когда код станет большим и там будет не 1, а сотни и тысячи классов — в таком объеме без нее никак.

Сам представь: в случае инкапсуляции, чтобы найти все места, где меняется значение свойства, достаточно просмотреть один класс. Без инкапсуляции — весь код.

---------

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

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

Это упрощает понимание кода: тебе не надо читать и разбирать код класса, достаточно прочитать название метода (и может быть комментарий к нему).

Если привести аналогию из рельного мира, это кофемашина. Ты нажимаешь кнопку (=вызываешь метод) и получаешь кофе (=результат), но ты не можешь заглянуть внутрь, ты не можешь повлиять на процесс приготовления и потому тебе не надо в нем разбираться. Ты лишь жмешь кнопку и получаешь результат.

---------

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

> if (this.money <= 0){


> System.out.println("Not enough money");


> this.money += countMoney;


Это неправильно. Твой подход выглядит так:

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

А что если у нас будет более сложная система, где например при снятии денег на отдельные счета переводится комиссия и налог, а в журнал операций делается запись? Представляешь как непросто все это открутить обратно?

Лучше делать так:

- проверить, можно ли снять деньги
- если можно то снять, иначе нет

Наконец я не уверен что об ошибке надо сигнализировать так:

> System.out.println("Not enough money");



Ты не даешь тому, кто вызвал функцию, шанса перехватить и обработать ошибочную ситуацию. В мире ООП об исключительных ситуациях приянто сообщать с помощью исключений. Вот мой урок по теме, в Яве все примерно так же как в PHP: https://gist.github.com/codedokode/65d43ca5ac95c762bc1a

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

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


исключение решает эту проблему, так как до возврата дело просто не дойдет.

> Еще понатыкал везде this.peremennaya , даже может и там где можно было написать просто peremennaya. Не совсем понимаю где можно не писать.


Я не помню, возьми какую-нибудь статью или учебник по яве, или нагугли.

Ну и давай тесты готовить, можешь сначала словами описать что ты тестируешь и какой результат ждешь, а потом перенесем это в код.
Верстка и ява #567 #585975
>>582605

> Девятое задание.


Слишком много тегов. Чтобы ты не мучался, я предлагаю 2 варианта верстки блока:

<div title="блок">
<div title="картинка"></div>
<div title="контент">контент</div>
</div>

и второй который мне нравится больше:

<div title="блок">
<div title="картинка"></div>
контент
</div>

>>582606

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

>>582608
>>583813
>>584499

Меня напрягает что ты функцию main() засунул прямо в UserAccount. Ты уверен что это правильно и она нужна для работы класса UserAccount или все же она должна быть где-то отдельно?

> public void getbalance(){


> System.out.println(name + " have " + money + " dollars");


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

> public double money;


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

Вот еще паста про инкапсуляцию:

---------

Это так называемая инкапсуляция, когда свойства помечены как private/protected и прямой доступ к ним имеет только сам класс, а не вся программа. Это делает код более надежным, а классы менее связанными друг с другом (то есть один класс не лезет внутрь другого, а лишь вызвает разрешенные методы). Инкапсуляция особенно важна когда код станет большим и там будет не 1, а сотни и тысячи классов — в таком объеме без нее никак.

Сам представь: в случае инкапсуляции, чтобы найти все места, где меняется значение свойства, достаточно просмотреть один класс. Без инкапсуляции — весь код.

---------

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

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

Это упрощает понимание кода: тебе не надо читать и разбирать код класса, достаточно прочитать название метода (и может быть комментарий к нему).

Если привести аналогию из рельного мира, это кофемашина. Ты нажимаешь кнопку (=вызываешь метод) и получаешь кофе (=результат), но ты не можешь заглянуть внутрь, ты не можешь повлиять на процесс приготовления и потому тебе не надо в нем разбираться. Ты лишь жмешь кнопку и получаешь результат.

---------

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

> if (this.money <= 0){


> System.out.println("Not enough money");


> this.money += countMoney;


Это неправильно. Твой подход выглядит так:

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

А что если у нас будет более сложная система, где например при снятии денег на отдельные счета переводится комиссия и налог, а в журнал операций делается запись? Представляешь как непросто все это открутить обратно?

Лучше делать так:

- проверить, можно ли снять деньги
- если можно то снять, иначе нет

Наконец я не уверен что об ошибке надо сигнализировать так:

> System.out.println("Not enough money");



Ты не даешь тому, кто вызвал функцию, шанса перехватить и обработать ошибочную ситуацию. В мире ООП об исключительных ситуациях приянто сообщать с помощью исключений. Вот мой урок по теме, в Яве все примерно так же как в PHP: https://gist.github.com/codedokode/65d43ca5ac95c762bc1a

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

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


исключение решает эту проблему, так как до возврата дело просто не дойдет.

> Еще понатыкал везде this.peremennaya , даже может и там где можно было написать просто peremennaya. Не совсем понимаю где можно не писать.


Я не помню, возьми какую-нибудь статью или учебник по яве, или нагугли.

Ну и давай тесты готовить, можешь сначала словами описать что ты тестируешь и какой результат ждешь, а потом перенесем это в код.
#568 #585976
>>582770

Помести примечание между абзацами:

<p>1</p>
<aside>Примечание</aside>
<p>2</p>

Ну а дальше используй магию CSS.
#569 #585979
>>582859

Тебе вообще не нужен массив $field, достаточно иметь список животных с координатами. Конечно, чтобы вывести карту на экран, массив нужен, но ведь мы всегда можем его создать на основе информации о координатах животных, вывести на экран и выкинуть. Незачем хранить этот массив постоянно, мучаться с его обновлением при перемещении и съедении животных. Ты сам себе жизнь усложняешь.

> $field->animals = array($cat1, $cat2, $mouse1, $mouse2, $mouse3, $dog1);


Вот это как-то нехорошо, что ты снаружи в любой момент можешь поменять список животных внутри объекта. Лучше сделай у Field методы добавления и удаления животного:

addAnimal(Animal $animal)
removeAnimal(Animal $animal)
#570 #585980
>>582874

> Я не знаю как без двумерного массива который я таскаю по всему коду реализовать логику программы.


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

> Алсо, я не понял твой совет:


>> abstract protected function tryToMove($field, $game);


> Неудобно везде передавать $field, лучше сделать его свойством класса. автоматически проставлять при добавлении животного на карту и убирать (ставить null) при снятии.



Ну смотри, представь у нас есть класс A и почти всем методам в нем нужен объект другого класса B, который всегда один и тот же:

class A
{
public function f1(B $b) { .. }
public function f2(B $b) { .. }
public function f3(B $b) { .. }
}

Вопрос, а не проще ли передать этот объект один раз, через конструктор или метод setB(B $b) и после этого вызвать методы без аргументов?

class A
{
public function construct(B $b) { ... }
public function f1() { ... }
....
}
#570 #585980
>>582874

> Я не знаю как без двумерного массива который я таскаю по всему коду реализовать логику программы.


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

> Алсо, я не понял твой совет:


>> abstract protected function tryToMove($field, $game);


> Неудобно везде передавать $field, лучше сделать его свойством класса. автоматически проставлять при добавлении животного на карту и убирать (ставить null) при снятии.



Ну смотри, представь у нас есть класс A и почти всем методам в нем нужен объект другого класса B, который всегда один и тот же:

class A
{
public function f1(B $b) { .. }
public function f2(B $b) { .. }
public function f3(B $b) { .. }
}

Вопрос, а не проще ли передать этот объект один раз, через конструктор или метод setB(B $b) и после этого вызвать методы без аргументов?

class A
{
public function construct(B $b) { ... }
public function f1() { ... }
....
}
#571 #585983
>>582911
>>582913
>>583014
>>583025

Я плохо понял, что ты делаешь, но по моему ты делаешь неправильно. Давай я своими словами опишу алгоритм.

При регистрации мы получаем от пользователя пароль:

- генерируем сложную случайную соль
- берем hash = md5(соль . пароль)
- сохраняем в БД соль и hash

При логине ... подумай сам немного, что мы делаем для проверки пароля.

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

- проверить залогинен ли пользователь (по наличию корректных кук)
- залогинить пользователя под данным id (поставить куки)
- разлогинить пользователя (удалить куки)

У тебя я этого не вижу.

У тебя все как-то намешано без всякой логики. Попробуй переделать код, ну и если ты не решал наши задачи на ООП (вектор, кошки-мышки), я бы советовал решить как минимум вектор.
#572 #585985
>>583093

В твоем запросе сразу видна ошибка:

FROM users_likes ul
JOIN users_groups ug

Если пользователь никого не лайкнул и ничем не лайкнут, то твой запрос вернет 0 строк. А должен вернуть группы на которые подписан один этот пользователь.

Рекурсивно смотреть ничего не надо. Нас интересуют только группы:

- пользователя
- всех тех кого он лайкнул
- всех тех кто его лайкнул

--------------

В этом запросе http://sqlfiddle.com/#!9/ccc6e/1 и в этом http://sqlfiddle.com/#!9/77a26/1 ошибка в том что ты там проверяешь взаимность а этого не требуется в условии.

---------------

Вот еще примеры:

-------------------

Допустим есть человек A, он никого не лайкнул и не получил лайк. Допустим A подписан на группы a, b, c.

запрос должен вернуть a, b, c

--------------

Допустим есть человек P, он лайкнул Q, и R. Допустим P подписан на группы a, b, Q подписан на c, d, R подписан на e, f.

Запрос для P должен вернуть группы a, b, c, d, e, f.

---------------
#572 #585985
>>583093

В твоем запросе сразу видна ошибка:

FROM users_likes ul
JOIN users_groups ug

Если пользователь никого не лайкнул и ничем не лайкнут, то твой запрос вернет 0 строк. А должен вернуть группы на которые подписан один этот пользователь.

Рекурсивно смотреть ничего не надо. Нас интересуют только группы:

- пользователя
- всех тех кого он лайкнул
- всех тех кто его лайкнул

--------------

В этом запросе http://sqlfiddle.com/#!9/ccc6e/1 и в этом http://sqlfiddle.com/#!9/77a26/1 ошибка в том что ты там проверяешь взаимность а этого не требуется в условии.

---------------

Вот еще примеры:

-------------------

Допустим есть человек A, он никого не лайкнул и не получил лайк. Допустим A подписан на группы a, b, c.

запрос должен вернуть a, b, c

--------------

Допустим есть человек P, он лайкнул Q, и R. Допустим P подписан на группы a, b, Q подписан на c, d, R подписан на e, f.

Запрос для P должен вернуть группы a, b, c, d, e, f.

---------------
#573 #585987
>>583093

> у меня ошибка в синтаксисе


Это проблема на твоей стороне, IN работает с UNION, специально проверил:

SELECT ... WHERE id IN (SELECT 1 UNION SELECT 2);
#574 #585992
>>585103

Что я вижу на скриншоте:

- в виртуалке одна сетевуха, она подключена к host-only network, то есть объединена с таким же виртуальным адаптером на хосте
- физический адаптер на хосте имеет IP xxx.75 (видимо он выдан провайдером?), шлюз в сети провайдера имеет IP xxx.1.
- то есть физическая сетевая карта находится в сети 192.168.0.X
- для виртуальной сети выделен диапазон адресов 192.168.64.X
- адаптеру в виртуалке проставлен IP 192.168.0.75. То есть такой же адрес как и сетевуха хоста (и не соответствующий диапазону виртуальной сети). Шлюз прописанный в виртуалке не доступен в виртуальной сети.

Смотри, твоя физическая сетевая карта находится в сети 192.168.0.X. Это значит что все пакеты с такими IP отправленные с хоста пойдут в эту сеть. Они никогда не попадут в сеть host-only network в которой находится виртуалка. Нужно чтобы у этой сети был другой диапазон адресов, ну например 192.168.64.X. И вирутальная карта на хосте, и на госте должны использовать Ip из этого диапазона. Тогда мы получим такую правильную картинку:

(шлюз провайдера 192.168.0.1) ----------- (реальная сетевая карта 192.168.0.75) (твой хост-компьютер) (виртуальная сетевая карта хоста 192.168.64.1) --- виртуальная сеть VMNet0 --- (виртуальная карта гостя 192.168.64.2)

Посмотри на картинку. Все пакеты IP адреса которых начинаются с 192.168.0.X будут уходить с хоста влево, в сеть провайдера. Все пакеты, чьи IP адреса начинаются с 192.168.64.X будут уходить с хоста направо, в виртуальную сеть.

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

Ну а с гостем все проще - у него всего одна сетевая карта и все пакеты с нее пойдут на шлюз, то есть есть на виртуальную карту хоста.
#575 #585994
>>585103

Еще пара моментов:

- чтобы применить измнения в /etc/interfaces, надо сделать от рута команду service networking restart

- я там написал адреса 192.168.64. 1 и 2, я их взял из головы. Их еще надо прописать. Адрес виртуальной карты в виртуалке (и шлюз) задается в interfaces, а адрес виртуальной карты хоста - в настройках VMWare либо в свойствах этой виртуальной карты в настройке сетевых соединений в WIndows.
#576 #586001
>>585974

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


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

>Пусть ему будет стыдно.


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

http://jsfiddle.net/3xfdt66c/1/
Поправил восьмое задание.

Хм, мне тяжело пока за пять минут изменить привычные представления о контейнерной верстке, когда создаешь див и группируешь элементы по смыслу. Я так понял, ты предлагаешь избегать такого подхода, и писать все элементы сплошным потоком, меняя их положение только при помощи css?
Но тогда не имея перед глазами отрисованного в браузере документа будет сложно глядя на эту кашу понять, что к чему относится.
Вот ты мне предлагаешь такой html:
<p></p><aside><aside></aside><p></p>
Ну и простите как понять, к чему относится aside? К первому или второму параграфу? Или может это вообще какой-нибудь абсолютно позиционированный боковой блок с баннерами, не имеющий отношения к документу?
Ты мне немного озадачил.

Только попробуй макет обосрать, я так над ним корпел.
#577 #586005
>>585745

Вообще, подозрительно аккуратно. Ты наверно учел ошибки предыдущих разработчиков.

Вот краткий список советов, это не все, я еще более внимательно проверю.

- при переключении переключателя ALL / GRAPHIC / MOTION должны скрываться не подходящие под тему картинки портфолио
- сделай скрытие красивым и анимированным с помощью CSS3. Вдохновление и примеры поищи по словам вроде css3 animation demo
- логотип принято делать ссылкой на главную сайта
- не уверен, стоит ли ради 8 букв в логотипе подключать шрифт? Более того, ты роботам показываешь надпись ebpaint вместо webpaint.
- что у тебя с поддержкой экранов высокой плотности пикселей?
- социальные иконки мигают при первом наведении мыши. Нехорошо. Сделай faded картинки в том же спрайте, что и основные. Ну и справедливости ради, fade делается через opacity вообще без рисования картинок (еще и с теплым мерцанием за сет анимации). Мог бы что-нибудь посложнее сделать. Чтобы там надпись какая-нибудь выезжала например.
- 1.2Мб шрифтов это многовато. Текст не отображается пока не загрузится шрифт. С тех пор как в php мануале прикрутили мегабайт шрифтов, текст стал появляться намного позже. Надо будет подумать что сделать.
- телефон надо бы сделать tel:-ссылкой (чтобы он был кликаьбельным, на десктопе такие ссылки перехватывает скайп например), а адрес -ссылкой на Google/Yandex Maps.

><h5>Get in Touch</h5>


Это не заголовок 5 уровня. Где тогда 1, 2, 3, 4 уровни? Это заголовок 2 уровня.

Цифра после h это не порядковый номер. Это уровень вложенности:

h1
текст
---h2 раздел 1
-----h3 подраздел 1.1
текст
-----h3 подраздел 1.2
текст
---h2 раздел 2
текст
---h2 раздел 3
текст

Почитай где-нибудь про смысл этих тегов.

> alt="image thumbnail"


Это не описывает картинку. Лучше написать portfolio work, так как мы не знаем что это за работа конкретно

> <div class="service-icon service-icon-1"></div>


Бесполезный тег, предлагаю упростить верстку секции преимуществ

> <div class="service-name">Consectetur</div>


Это подзаголовок

Алсо, в каких браузерах тестироввал? ИЕ до какой версии поддерживается?
#577 #586005
>>585745

Вообще, подозрительно аккуратно. Ты наверно учел ошибки предыдущих разработчиков.

Вот краткий список советов, это не все, я еще более внимательно проверю.

- при переключении переключателя ALL / GRAPHIC / MOTION должны скрываться не подходящие под тему картинки портфолио
- сделай скрытие красивым и анимированным с помощью CSS3. Вдохновление и примеры поищи по словам вроде css3 animation demo
- логотип принято делать ссылкой на главную сайта
- не уверен, стоит ли ради 8 букв в логотипе подключать шрифт? Более того, ты роботам показываешь надпись ebpaint вместо webpaint.
- что у тебя с поддержкой экранов высокой плотности пикселей?
- социальные иконки мигают при первом наведении мыши. Нехорошо. Сделай faded картинки в том же спрайте, что и основные. Ну и справедливости ради, fade делается через opacity вообще без рисования картинок (еще и с теплым мерцанием за сет анимации). Мог бы что-нибудь посложнее сделать. Чтобы там надпись какая-нибудь выезжала например.
- 1.2Мб шрифтов это многовато. Текст не отображается пока не загрузится шрифт. С тех пор как в php мануале прикрутили мегабайт шрифтов, текст стал появляться намного позже. Надо будет подумать что сделать.
- телефон надо бы сделать tel:-ссылкой (чтобы он был кликаьбельным, на десктопе такие ссылки перехватывает скайп например), а адрес -ссылкой на Google/Yandex Maps.

><h5>Get in Touch</h5>


Это не заголовок 5 уровня. Где тогда 1, 2, 3, 4 уровни? Это заголовок 2 уровня.

Цифра после h это не порядковый номер. Это уровень вложенности:

h1
текст
---h2 раздел 1
-----h3 подраздел 1.1
текст
-----h3 подраздел 1.2
текст
---h2 раздел 2
текст
---h2 раздел 3
текст

Почитай где-нибудь про смысл этих тегов.

> alt="image thumbnail"


Это не описывает картинку. Лучше написать portfolio work, так как мы не знаем что это за работа конкретно

> <div class="service-icon service-icon-1"></div>


Бесполезный тег, предлагаю упростить верстку секции преимуществ

> <div class="service-name">Consectetur</div>


Это подзаголовок

Алсо, в каких браузерах тестироввал? ИЕ до какой версии поддерживается?
#578 #586008
>>585745

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


Какой формат использовал? Ты должен наизусть знать особенности, плюсы и минусы этих форматов:

JPEG, PNG8, PNG24, GIF, SVG

Также, знать чем отличается прозрачность от полупрозрачности, что такое matte color в фотошопе.

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

Вот статья для совсем начинающих от гугла (на русском!): https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/image-optimization

Хорошо бы минимально уметь оптимизировать картинки. Для начала можешь почитать этот раздел в блоге: http://chikuyonok.ru/category/graphics/ (не бойся, учить наизусть не надо)

Ну и погугли по слову pngcrush.
#579 #586014
>>586001

Да, согласен, я урок не написал где бы объяснялась сама идея HTML/CSS. Одна из идей в том что мы в идеале используем HTML только для смысловой разметки текста, CSS для оформления, JS для поведения. Мы не пишем цвет или размер шрифта в HTML. Мы не делаем классы red-text, а делаем класс вроде important-text или irony.

> Хм, мне тяжело пока за пять минут изменить привычные представления о контейнерной верстке, когда создаешь див и группируешь элементы по смыслу. Я так понял, ты предлагаешь избегать такого подхода, и писать все элементы сплошным потоком, меняя их положение только при помощи css?


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

HTML это в общем-то тоже код, и он как и любой код пишется для людей. То есть должен быть логичными и читабельным.

> ты предлагаешь избегать такого подхода, и писать все элементы сплошным потоком, меняя их положение только при помощи css?


Неверно. Вложенность определяется логически. Например элементы списка должны быть вложены в список. Аватарка должна быть вложена внутрь поста.

А вот примечание не обязано быть вложено в абзац.

Ну и кстати правила HTML запрещают класть внутрь p другие блочные элементы по моему.

> Ну и простите как понять, к чему относится aside?


Оно между ними очевидно. Если бы оно относилось к какому-то абзацу, оно бы наверно было внутри него.

> body {


> padding: 10px 10px 10px 120px;


Ну вот наконец-то дошло. Почему-то 100% анонов пытается сделать поля через margin-left на <p>. Я аж несколько раз предупреждение написал в задачах.

Теперь 8-е задание решено верно.
#580 #586018
>>586001

> <a href="home.html">HOME</a>


all-caps делается средствами CSS
#581 #586032
>>586001

Ну и раз ты изучаешь верстку, познакомься-ка с возможностями современного CSS (не без фанатизма сделано):

http://habrahabr.ru/company/paysto/blog/251933/
http://habrahabr.ru/post/161979/
http://habrahabr.ru/company/nordavind/blog/209462/

Хороший верстальщик конечно должен уметь все это делать, но не должен делать.
#582 #586034
>>586005

>Ты наверно учел ошибки предыдущих разработчиков.


В смысле подсматривал решения школьников? А вот это обидно, я вообще-то очень горделив, не допущу и мысли о том, чтобы подсмотреть чужое решение.
У тебя наверняка есть архив тредов, можешь проверить на авторское право.

>что у тебя с поддержкой экранов высокой плотности пикселей?


Первый раз слышу. Ладно, попробую погуглить.

>1.2Мб шрифтов это многовато


Могу порезать наверное, мельком слышал о такой возможости. Хотя особой охоты вникать в такие посторонние от веб-разработки темы не возникает.

>Цифра после h это не порядковый номер


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

>Это подзаголовок


Что такое подзаголовок? Ты так называешь теги h2-h6?

В браузерах из репозиториев
FF 42.0, Chromium 45.0, Opera 12.16.
Как мне тестить IE на убунте, ума не приложу. Под винду был какой-то ie-tester, а здесь не знаю. Может есть какой-нибудь онлайн-сервис?

>>586018
Больше скрупулезности богу скрупулезности.

>>586032
Почему-то вспомнились чуваки, которые клеят из спичек дома в натуральную величину, ну и другие безусловно полезные хобби.
Хотя мастерство впечатляет конечно. Такое усердие бы в хорошее русло.
Вообще удручает состояние науки. Вместо того чтобы делать что-то для развития цивилизации, не знаю, изобретать лекарства, строить космические корабли, талантливые люди работают над тем, чтобы добавить несколько свистоперделок в новый гейфон. Красиво, но абсолютно бесполезно.
#583 #586040
>>586034

Есть урок со ссылочками про IE https://gist.github.com/codedokode/855e3970124687b26a1c

>>586034

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

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

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

Роботы уже применяются на многих производствах. Роботизированные автомобили в будущем позволят снизить число аварий.

Ну и в биологии сейчас без компьютера никуда - только программа способна перемолоть миллиарды оснований ДНК и например найти участки генов отвечающие за какую-то болезнь:

http://habrahabr.ru/company/spbau/blog/143115/
http://geektimes.ru/post/137626/

В общем, ты как-то не замечаешь положительные стороны. Ну и космические корабли тоже строятся, вот SpaceX например все пытается сделать возвращаемую ракету. Можешь попробовать устроиться к ним на работу и лично внести вклад в будущее космической отрасли.
#584 #586097
>>585985
А, ну да, я выбрал только группы лайкеров, и забыл про id пользователя, которого нам дали на вход задачи.
Поправил.
Думаю теперь результат точно всегда возвращается правильный. http://sqlfiddle.com/#!9/5fc5f3/11
Вопрос только в том, насколько оптимально.
Из explain я могу пока понять только если дело совсем плохо: когда индекс не используется вообще, или не совсем тот что нужен, или составной используется частично.

Что ты можешь сказать по данному explain? Можно ли что-то улучшить?
Потому что я могу только еще раз тупо прочитать документацию по отдельным частям этого отчета, но без практических выводов от теории не могу далеко уйти.
Ну например я вижу "using temporary". Лезу в документацию: "To resolve the query, MySQL needs to create a temporary table to hold the result. This typically happens if the query contains GROUP BY and ORDER BY clauses that list columns differently."
И что? Это хорошо или плохо? Меня только это интересует.
Using join buffer - тут тоже я могу прочитать расшифровку, но к каким практическим действиям это меня должно подталкивать? Я не знаю, вдруг использование этого буффера вредно, и нужно стремиться избавляться от такого результата, или еще что-нибудь в этом роде.
Я хочу сказать, что мне нужны указания по конкретным действиям по оптимизации, в документации я пока вижу только справку по командам или отчетам.

Я говорю про оптимизацию, потому что в твоем первом посте условие

>найти эффективным запросом, хорошо использующим индексы


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

>>585974

> Текст прилипает к левому краю и это некрасиво. В инпуте по умолчанию стоит 2px паддинг и ты не должен его убирать.


Да я и не убирал вроде. Во всяком случае, не прописывал padding: 0.
Наверное, оно сбросилось, когда я изменил box-sizing или border. Хотя казалось бы где связь? Почему исчез левый и правый паддинг? Странное поведение, короче.
У меня в хроме кстати паддинги 1px по умолчанию, а не 2.
Выставил в 6, при высоте в 30 так симпатичнее.
http://jsfiddle.net/s1qnngxa/2/
#584 #586097
>>585985
А, ну да, я выбрал только группы лайкеров, и забыл про id пользователя, которого нам дали на вход задачи.
Поправил.
Думаю теперь результат точно всегда возвращается правильный. http://sqlfiddle.com/#!9/5fc5f3/11
Вопрос только в том, насколько оптимально.
Из explain я могу пока понять только если дело совсем плохо: когда индекс не используется вообще, или не совсем тот что нужен, или составной используется частично.

Что ты можешь сказать по данному explain? Можно ли что-то улучшить?
Потому что я могу только еще раз тупо прочитать документацию по отдельным частям этого отчета, но без практических выводов от теории не могу далеко уйти.
Ну например я вижу "using temporary". Лезу в документацию: "To resolve the query, MySQL needs to create a temporary table to hold the result. This typically happens if the query contains GROUP BY and ORDER BY clauses that list columns differently."
И что? Это хорошо или плохо? Меня только это интересует.
Using join buffer - тут тоже я могу прочитать расшифровку, но к каким практическим действиям это меня должно подталкивать? Я не знаю, вдруг использование этого буффера вредно, и нужно стремиться избавляться от такого результата, или еще что-нибудь в этом роде.
Я хочу сказать, что мне нужны указания по конкретным действиям по оптимизации, в документации я пока вижу только справку по командам или отчетам.

Я говорю про оптимизацию, потому что в твоем первом посте условие

>найти эффективным запросом, хорошо использующим индексы


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

>>585974

> Текст прилипает к левому краю и это некрасиво. В инпуте по умолчанию стоит 2px паддинг и ты не должен его убирать.


Да я и не убирал вроде. Во всяком случае, не прописывал padding: 0.
Наверное, оно сбросилось, когда я изменил box-sizing или border. Хотя казалось бы где связь? Почему исчез левый и правый паддинг? Странное поведение, короче.
У меня в хроме кстати паддинги 1px по умолчанию, а не 2.
Выставил в 6, при высоте в 30 так симпатичнее.
http://jsfiddle.net/s1qnngxa/2/
#585 #586109
>>585975

> div title


Что за title? Это ты обобщил, чтобы не писать id/class?

Исправил девятое задание.
Это было просто, поскольку в восьмом тот же прием с флотом и отрицательным марджином.
http://jsfiddle.net/h4mpx47n/

Бамп 10 >>583195 11 >>583514 12 >>584049

По макету довольно интересный момент с этими картинками в галерее портфолио. Если я правильно понял макет, каждая картинка занимает 270px, то есть свою натуральную величину. Между картинками по вертикали и горизонтали расстояние 10px. В одном ряду может быть максимум 4 картинки (поскольку мы ограничены шириной 1110px), причем первая и последняя в ряду плотно примыкает к своему краю.
Нужна подсказка, пока нет вариантов.
#586 #586249
>>585923

>


>> https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/Animal.php#L116


>> protected function isItCorner($x, $y) {


>Там какой-то странный способ определить что мы в углу. Не проще ли определить по координатам?


Мне все равно как определять. Мне просто не нравиться такое рутинное условие (($x == $map->with and $y == $map->height) or ($x == 0 and $y == $map->height) or ...), но если ты настаиваешь что должно быть так, я переделаю.

>>585923

>> https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/Mouse.php#L39


>> public function rateMove($x, $y, $search) {


>Ты можешь объяснить алгоритм работы этой функции? Я его не понимаю:


>


>> $rate = 0;


>> ...


>> foreach ($search as $object) {


>> ....


>> $movesCount = $this->howManyMovesWillDoAnimal($object, $distance);


>> $rate = $movesCount;


>> ....


>> }


>С таким кодом $rate всегда будет равен расстоянию до последнего элемента в массиве $search. Зачем тогда нужен цикл? Зачем вычислять расстояние до первой, второй, третьей кошек если в $rate пойдет только расстояние до последнией?


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

>>585923

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


Если честно, то я сам уже плохо понимаю что там происходит. Ты иногда предлагаешь все новые концепции игры о которых я изначально даже не мог подумать, и мне приходиться все подгонять под это. Теперь буду писать комментарии.
#586 #586249
>>585923

>


>> https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/Animal.php#L116


>> protected function isItCorner($x, $y) {


>Там какой-то странный способ определить что мы в углу. Не проще ли определить по координатам?


Мне все равно как определять. Мне просто не нравиться такое рутинное условие (($x == $map->with and $y == $map->height) or ($x == 0 and $y == $map->height) or ...), но если ты настаиваешь что должно быть так, я переделаю.

>>585923

>> https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/Mouse.php#L39


>> public function rateMove($x, $y, $search) {


>Ты можешь объяснить алгоритм работы этой функции? Я его не понимаю:


>


>> $rate = 0;


>> ...


>> foreach ($search as $object) {


>> ....


>> $movesCount = $this->howManyMovesWillDoAnimal($object, $distance);


>> $rate = $movesCount;


>> ....


>> }


>С таким кодом $rate всегда будет равен расстоянию до последнего элемента в массиве $search. Зачем тогда нужен цикл? Зачем вычислять расстояние до первой, второй, третьей кошек если в $rate пойдет только расстояние до последнией?


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

>>585923

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


Если честно, то я сам уже плохо понимаю что там происходит. Ты иногда предлагаешь все новые концепции игры о которых я изначально даже не мог подумать, и мне приходиться все подгонять под это. Теперь буду писать комментарии.
8 Кб, 237x21
48 Кб, 330x348
#587 #586288
>>585923

>> https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/World.php#L92


>> if ($x > $this->width


>Допустим ширина поля width = 10. Очевидно что это значит что карта имеет 10 клеточек в ширину. У тебя отсчет координат начинается с 0, и 10 клеточек имеют координаты от 0 до 9. Если у животного x = 10 то оно находится не на карте.


>


>А твоя функция при x = 10 вернет true, что животное в пределах карты.


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

https://github.com/someApprentice/Cat-and-Mouse/blob/master/game.php#L5
Вёрстка #588 #586313
1 задание -> http://jsfiddle.net/togxxk10/1/
2 задание -> http://jsfiddle.net/pLaL3917/1/
3 задание -> http://jsfiddle.net/qougtx5u/
4 задание -> http://jsfiddle.net/bwbekt4y/

Оп, если не затруднит - какие ошибки в решении/оформлении 4 всех задач?
#589 #586342
Допустим есть форма с полями, некоторые из которых юзер может оставить пустыми. Мне что теперь для каждого поля и их комбинаций свой запрос к соклу через Маппер делать?

if(!empty($_POST['tags']&&$_POST['description']&&$_POST['terminate']&&$_POST['public'])){
$tags = trim(htmlspecialchars($_POST['tags']));
$description = trim(htmlspecialchars($_POST['description']));
$public = htmlspecialchars($_POST['public']);
$terminate = htmlspecialchars($_POST['terminate']);
$foo = new Foo;
$foo->id = $file_id;
$foo->tags = $tags;
$foo->public = $public;
$foo->description = $description;
$foo->terminate = $terminate;
$foomapper = new FooMapper($db);
$foomapper->save($foo);
}

if(isset($foo->id)){
$sql = "UPDATE files SET terminate = :terminate, public=:public, tags = :tags, description = :description WHERE id = :id";

$statement = $this->db->prepare($sql);
$statement->bindParam("id", $foo->id);
$statement->bindParam("terminate", $foo->terminate);

$statement->bindParam("public", $foo->public, PDO::PARAM_INT);
$statement->bindParam("tags", $foo->tags);
$statement->bindParam("description", $foo->description);

$statement->execute();
#589 #586342
Допустим есть форма с полями, некоторые из которых юзер может оставить пустыми. Мне что теперь для каждого поля и их комбинаций свой запрос к соклу через Маппер делать?

if(!empty($_POST['tags']&&$_POST['description']&&$_POST['terminate']&&$_POST['public'])){
$tags = trim(htmlspecialchars($_POST['tags']));
$description = trim(htmlspecialchars($_POST['description']));
$public = htmlspecialchars($_POST['public']);
$terminate = htmlspecialchars($_POST['terminate']);
$foo = new Foo;
$foo->id = $file_id;
$foo->tags = $tags;
$foo->public = $public;
$foo->description = $description;
$foo->terminate = $terminate;
$foomapper = new FooMapper($db);
$foomapper->save($foo);
}

if(isset($foo->id)){
$sql = "UPDATE files SET terminate = :terminate, public=:public, tags = :tags, description = :description WHERE id = :id";

$statement = $this->db->prepare($sql);
$statement->bindParam("id", $foo->id);
$statement->bindParam("terminate", $foo->terminate);

$statement->bindParam("public", $foo->public, PDO::PARAM_INT);
$statement->bindParam("tags", $foo->tags);
$statement->bindParam("description", $foo->description);

$statement->execute();
#590 #586383
>>586342
Тащемта в поля формы обновления записи должны подставляться значения по умолчанию, старые значения из таблицы в базе. Пользователь должен отредактировать те из них, какие захочет, остальные оставить как есть.
Если пользователь хочет обнулить старое значение, то нужно привести полученную из данного инпута пустую строку к null, сделать это можно либо на стороне php, либо прямо в запросе.
#591 #586399
>>586383
Например у меня в поле лежит дата в формате даты 21-02-1977, в поле форме у меня стоит 1 day.
<select class="form-control" name="terminate">
<option>1 day</option>

Т.е. если при заливке файла установилась определенная дата в 1 день от даты заливки, а потом в едит форме выводить это значение и сохранять, то каждый раз дата удаления файла будет оттягиваться на 1 день. Так что этот варик я уже продумал и он не катит.
#592 #586416
>>586342
И почему ты делаешь htmlspecialchars ПЕРЕД вставкой в базу? Вставлять нужно как есть (используя подготовленные выражения конечно), пропускать через htmspecialchars нужно при рендере в шаблоне.
Представь, что ты работаешь в команде. Ты пишешь код сохранения в базу данных, я пишу фронтенд. Я не буду копаться в твоем коде, чтобы проверить, проставил ты htmlspecialchars или нет. Собственно я предположу что не проставил, потому что этого не надо делать, и еще раз пропущу данные через эту функцию. Собственно шаблонизатор твиг это делает по умолчанию. Догадайся, что получится на выходе.

>>586399

><option>1 day</option>


А что в value?

Попробуй так
<option value="старая дата из бд" selected>Не продлевать срок</option>
В остальных опциях храни в значениях не кол-во дней, а сегодняшнюю дату + срок хранения, или что у тебя там.
<option value="<?php echo date('d-m-Y', time() + 3600 x 24); ?>">Продлить на 1 день</option>
<option value="<?php echo date('d-m-Y', time() + 3600 x 24 x 7); ?>">Продлить на неделю</option>
#593 #586488
Не могу читать в электроне посоветуйте книгу для начинающих ?
#594 #586613
>>586288

> Вообще-то у меня от 0 до 10,


Тогда получается ширина поля 11 клеток (посчитай сам по картинке). А в конструкторе написано

https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/World.php#L8

> $width = 10


Согласись, нелогично как-то.
#595 #586699
А нельзя ли как-то сделать, чтобы timestamp в бд сохранялся не в формате datetime, а в date? Или обязательно сохранять в дейтам, а потом вытаскивать, конвертировать в time(), потом обратно в date('y-m-d')?
#596 #586741
>>586699

TIMESTAMP обозначает момент времени, так что нельзя. Но можно использовать DATE.

Не вижу в чем проблема в том чтобы сделать преобразование на стороне PHP. Ты ведь все равно его делаешь если хочешь например вывести дату в виде «3 марта».
#597 #586743
>>586699

В общем, я вижу что ты плохо знаешь типы данных. Изучи такие типы данных как

TIMESTAMP
DATETIME
DATE
YEAR

На английском они описаны в мануале http://dev.mysql.com/doc/refman/5.7/en/date-and-time-types.html но я думаю если погуглить можно найти и русский перевод.
187 Кб, 1280x901
#598 #586773
Со стака скопирую свой вопрос, очень нужно
I get this error when try to load page, sorry for asking so stupid question. File structure like this: src, views, web(here's index.php), vendor, autoload

Twig_Error_Loader in Chain.php line 115:
Template "layout.twig" is not defined.
My index.php:

$app->register(new Provider\TwigServiceProvider(array(
'twig.options' => array(
'cache' => false,
),
'twig.path' => __DIR__ . '/../views',
)
));

$app['twig.loader.filesystem']->addPath(__DIR__ . '/../views', 'Application');

//Register twig layout
$app->before(function () use ($app) {
$app['twig']->addGlobal('layout', $app['twig']->loadTemplate('layout.twig'));
});
Index controller:

return $app['twig']->render('index.twig', array(
'products' => $products,
)
);
187 Кб, 1280x901
#598 #586773
Со стака скопирую свой вопрос, очень нужно
I get this error when try to load page, sorry for asking so stupid question. File structure like this: src, views, web(here's index.php), vendor, autoload

Twig_Error_Loader in Chain.php line 115:
Template "layout.twig" is not defined.
My index.php:

$app->register(new Provider\TwigServiceProvider(array(
'twig.options' => array(
'cache' => false,
),
'twig.path' => __DIR__ . '/../views',
)
));

$app['twig.loader.filesystem']->addPath(__DIR__ . '/../views', 'Application');

//Register twig layout
$app->before(function () use ($app) {
$app['twig']->addGlobal('layout', $app['twig']->loadTemplate('layout.twig'));
});
Index controller:

return $app['twig']->render('index.twig', array(
'products' => $products,
)
);
#599 #586778
>>586743
Все я прекрасно знаю. Фишка в том, что таймстамп который ставит текущее время используется только совместно с дейтайм, потому что если ставить дейт, то выводит ошибку - типа низя таймстамп ставить на дейт. понял? и приходится брать дайнные в дейтайм, переводить их в тайм уникс, потом обратно ставить в дейт, это же пиздец, потом сравнивать с другой дейтой.
#600 #586780
>>586773
давно уже обсудили, что твиг к слиму не подключается.
#601 #586781
Это не слим а Silex
#602 #586782
>>586780
>>586781
Опять же не слим, а силекс
#603 #586799
Какую йобу можно запилить, чтобы хорошо поработать с ООП, паттернами, архитектурой? Делать планирую на фреймворке (Laravel или Yii).
147 Кб, 750x1000
#604 #586809
>>586799
Систему управления какую-нибудь, пили. Или интернет магазин с налогами и всеми плюшками. Как magento

>>586773
Вопрос отпал. Почитал исходники, подебагал и все встало на свои места
#605 #586835
Что лучше почитать по .htaccess? Нужно, чтобы было комплексно написано было по всем возможностям, а то нахожу только разрозненные обрывки и никак не могу в нем разобраться.
#606 #586868
ОП, не могу понять как с этой новой MYSQli сделать простую табличку из записей? Нужно в 4 строках разместить по 1 фотографии, потом, если есть ещё фотки и на 2 строке и так далее. Делаю так.
$link->real_query("SELECT * FROM photos");
$res = $link->use_result();
echo "<table border='1' align='top' width='100%'>";
while ($row = $res->fetch_assoc()) {
\techo "<tr><td>";
\tfor ($i = 0; $i <= 4; $i++)
\t{
\techo "<a href='redac.php?id=";
\techo $row['id'];
\techo "'>";
\techo "<img src=";
\techo 'img/';
\techo $row['jpgadress'];
\techo " width='200'></a>";
\t//$i++;
\t}
\techo "</td></tr>";
}
echo "</table>";
Делаю так, естественно получаю 4 одинаковые картинки на каждую строку таблицы.
Как написать код таким образом, чтобы при каждой итерации for - счётчик echo $row['id']; перекидывался на 1? Не предлагайте мне echo $row['id']+1. Возможно что ID просто напросто будет идти не по порядку.
#607 #586893
>>586780
В каком смысле не подключается?
#608 #586921
>>586868
НЕ ИСПОЛЬЗУЙ mysqlli блять, select надо вывести в отдельный объект маппера и active record, не мешай логику и отображение, почитай про mvc, не пиши echo </td> и т.п.

Файл должен выглядить примерно так

<?php foreeach ($res as $line): ?>
<img src="<?php echo $line->img;?>>
<address><?php echo $address; ?>
<?php endforeach; ?>
https://github.com/V3N0m21/Uppu3 #609 #586973
>>582763

> Вот этого не понял. Зачем их объединять вместе? Как мне кажется от этого сильно страдает читабельность, ну и в чем заключается копипаста тоже не совсем ясно. В GET рендерится страница, в POST обрабатывается запрос, и общих строк у них нет.



Потому что это одна страница, какой смысл писать для нее 2 обработчика? Вот представь тебе надо будет например передать какую-то переменную в шаблон. Тебе придется делать это в 2 местах. Более того, ты и сейчас это делаешь - строка $app->render у тебя скопипастена 2 раза.

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

> мне кажется от этого сильно страдает читабельность


Так как это общепринятый подход то наоборот, он выглядит привычно

> и общих строк у них нет.


Как минимум это $app->render, а по мере усложнения кода их будет больше.

----------

> https://github.com/V3N0m21/Uppu3/blob/master/comments.sql#L34


> `children` int(11) DEFAULT NULL,


Что это за поле? Что в нем хранится? Нужно добавить комментарий в таблицу. Ну вот как я глядя на SQL код догадаюсь что там лежит?

> https://github.com/V3N0m21/Uppu3/blob/master/comments.sql#L43


> KEY `fileId_2` (`fileId`),


Зачем 2 индекса на одно и то же поле? Удаляй лишний.

Также, значения path могут повторяться? Если нет то надо сделать его уникальным индексом.

Индексы можно создавать/удалять командами ALTER TABLE x ADD INDEX/DROP INDEX, погугли. Как начиняющему, я советую использовать для правки таблиц SQL команды (их можно вводить через phpmyadmin). Это поможет тебе лучше изучить язык SQL.

> https://github.com/V3N0m21/Uppu3/blob/master/files.sql#L38


> `uploadedBy` int(11) NOT NULL,


Что это за поле? Нужен комментарий. И внешний ключ если это ссылка на другую таблицу.

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

> https://github.com/V3N0m21/Uppu3/blob/master/app/bootstrap.php


Здесь стена текста. Я помню, что я сам тебе по этому коду давал какие-то советы, но сейчас, хоть убей, вспомнить не могу какие именно. И другию люди читающие код вряд ли его поймут.

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

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

> https://github.com/V3N0m21/Uppu3/blob/master/app/bootstrap.php#L13


> $cache = new \Doctrine\Common\Cache\MemcacheCache();


Если APC не подключен, ты используешь memcache. Это не логично. Ведь его может и не быть. В качестве резерва надо использовать FilesystemCache, который кеширует данные в файлах.

Конфиг базы данных надо вынести в отдельный файл, например config.php, а в README добавить напоминание что надо прописать реквизиты доступа к базе в этот файл. Причем там должны быть только настройки которые имеет смысл менять пользователю.

В этот же конфиг надо вынести параметр $isDevMode = true; который там намертво сейчас вшит в код.

> https://github.com/V3N0m21/Uppu3/blob/master/public/index.php#L27


> $isLogged = $app->loginHelper;


Одинаковые вещи называй одинаково

> https://github.com/V3N0m21/Uppu3/blob/master/public/index.php#L37


> $flash = '';


можно добавить это через appendData а не писать в каждой функции

> https://github.com/V3N0m21/Uppu3/blob/master/public/index.php#L41


> $app->get('/login', function () use ($app) {


У тебя 2 отдельных обработчика, для GET и POST. Если в форму надо будет передать какую-то переменную, придется писать это в 2 местах. Нехорошо, надо объединить в одну функцию. Тем более что именно так и советуется в моем уроке по работе с формами, у тебя есть какие-то причины почему твой вариант лучше?

То же самое относится к форме регистрации.

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

В форме регистрации мне не нравится, что ты всюду передаешь POST. Это массив в котором может быть любое число элементов любого типа. Крайне ненадежно с ним работать. Гораздо лучше передавать объект User, ну а пароль (которого в нем нет) передавать отдельной переменной.

То есть:

$validation->validateData($user, $password);
...
$userHelper->registerUser($user, $password);
....

> $cookie = $app->getCookie('salt');


> $app->setCookie('salt', $cookie, '1 month');


Это я не понимаю. почему ты соль хранишь в куках? Соль не нужна пользователю, она должна храниться только в БД. Что ты тут за собственный алгоритм изобрел?

Более того, ты еще и ищешь пользователей почему-то по соли. Это явно что-то не так.

Ну и код надо выносить в функции. Вот этот блок кода например:

> https://github.com/V3N0m21/Uppu3/blob/master/public/index.php#L50


> if ($user = $app->em->getRepository('Uppu3\Entity\User')


> ->findOneBy(array('login' => $_POST['login']))) {


> if($user->getHash() === HashGenerator::generateHash($_POST['password'], $user->getSalt()))


Однозначно стоит вынести в функцию:

$user = $someService->checkUser($login, $password, $error); // В $error вернется текст ошибки

Или можно так:

list($user, $error) = $someService->checkUser($login, $password);

> https://github.com/V3N0m21/Uppu3/blob/master/public/index.php#L49


> $_POST['login']


Я думаю лучше использовать $app->request вместо POST. Например он не выдает ошибку если элемента нет.

> $error = "Invalid login or password";


> $app->render('login_form.html', array('flash' => $error, 'data' => $_POST));


Это незачем писать 2 раза.

> https://github.com/V3N0m21/Uppu3/blob/master/public/index.php#L96


> if (file_exists($_FILES['load']['tmp_name'])) {


Тут надо бы проверку получше сделать, в PHP есть специальное поле которое хранит ошибку при загрузке файла: http://php.net/manual/ru/features.file-upload.errors.php

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

> \Uppu3\Helper\UserHelper::saveAnonymousUser($cookie, $app->em);


> \Uppu3\Helper\FileHelper::fileSave($_FILES, $user, $app->em);


замени статические методы на обычные. $em (а лучше конкретный репозиторий если можно) передавай как зависимсоть через конструктор.

> $file = $app->em->find('Uppu3\Entity\File', $id);


> $user = $app->em->getRepository('Uppu3\Entity\User')->findOneById($file->getUploadedBy());


Почему не $uploader = $file->getUploader()? Почему такие усложнения?

Более того, писать это в index.php не требуется, можно написать это в шаблоне.

> $comments = $app->em->getRepository('Uppu3\Entity\Comment')->findBy(array('fileId' => $id), array('path' => 'ASC'));


Слишком длинная строка, разбей на 2 с промежутойной переменной $commentRepo.

> $info = $file->getMediainfo();


Это не требуется писать в index.php, можно написать в шаблоне.

> https://github.com/V3N0m21/Uppu3/blob/master/public/index.php#L153


> foreach ($users as $user) {


> $filesCount[$user->getId() ] = count($app->em->getRepository('Uppu3\Entity\File')


Это неэффективно, делать запросы в цикле. Надо использовать запрос с GROUP BY (если у тебя меньше 1000-2000 файлов, если больше то и он не очень эффективен и надо заводить у пользователя поле с числом файлов и брать данные из него)

Если ты плохо знаешь SQL, рекомендую порешать мои задачки на SQL - GROUP BY сможешь с закрытыми глазами писать.

Если ты отправляешь пользователя залогинится, то надо сохранять текущий URL (например /login?from=/users/) а после логина редиректить, причем дополнительн проверять что URL нходится на твоем сайте, чтобы нельзя было пользователя отправить на левый сайт.

> https://github.com/V3N0m21/Uppu3/blob/master/public/index.php#L173


> foreach ($files as $file) {


Тут SQL запросы в цикле. Надо либо выбирать пользователей через SELECT WHERE ud IN (..) либо в первом запросе, где ты выбираешь файлы, сделать DQL запрос с джойном пользователей, чтобы доктрина выбрала и файлы и и тех кто их загрузил сразу.

(англ) http://doctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/reference/dql-doctrine-query-language.html#joins
(рус) http://odiszapc.ru/doctrine/dql-doctrine-query-language/#1322_JOIN

Обрати внимание что ты и без джойна можешь получить аплоадера по файлу, но это будет сделано за счет ленивой загрузки отдельным запросом. То есть мы получим проблему N + 1 селекта: http://www.krestjaninoff.ru/2011/06/n1-select.html

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

> https://github.com/V3N0m21/Uppu3/blob/master/public/index.php#L181


В функции отправки комментария нет валидации данных.

Еще я вижу что ты конструируешь ссылки руками: "user/$id". Разве это удобно? как ты относишься к идее сделать класс UrlHelper с методами вида getUserPage($userId)?

Пока качество кода меня не устраивает. Я думаю, что это можно сделать лучше.

Остальные файлы я пока не проверял.
https://github.com/V3N0m21/Uppu3 #609 #586973
>>582763

> Вот этого не понял. Зачем их объединять вместе? Как мне кажется от этого сильно страдает читабельность, ну и в чем заключается копипаста тоже не совсем ясно. В GET рендерится страница, в POST обрабатывается запрос, и общих строк у них нет.



Потому что это одна страница, какой смысл писать для нее 2 обработчика? Вот представь тебе надо будет например передать какую-то переменную в шаблон. Тебе придется делать это в 2 местах. Более того, ты и сейчас это делаешь - строка $app->render у тебя скопипастена 2 раза.

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

> мне кажется от этого сильно страдает читабельность


Так как это общепринятый подход то наоборот, он выглядит привычно

> и общих строк у них нет.


Как минимум это $app->render, а по мере усложнения кода их будет больше.

----------

> https://github.com/V3N0m21/Uppu3/blob/master/comments.sql#L34


> `children` int(11) DEFAULT NULL,


Что это за поле? Что в нем хранится? Нужно добавить комментарий в таблицу. Ну вот как я глядя на SQL код догадаюсь что там лежит?

> https://github.com/V3N0m21/Uppu3/blob/master/comments.sql#L43


> KEY `fileId_2` (`fileId`),


Зачем 2 индекса на одно и то же поле? Удаляй лишний.

Также, значения path могут повторяться? Если нет то надо сделать его уникальным индексом.

Индексы можно создавать/удалять командами ALTER TABLE x ADD INDEX/DROP INDEX, погугли. Как начиняющему, я советую использовать для правки таблиц SQL команды (их можно вводить через phpmyadmin). Это поможет тебе лучше изучить язык SQL.

> https://github.com/V3N0m21/Uppu3/blob/master/files.sql#L38


> `uploadedBy` int(11) NOT NULL,


Что это за поле? Нужен комментарий. И внешний ключ если это ссылка на другую таблицу.

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

> https://github.com/V3N0m21/Uppu3/blob/master/app/bootstrap.php


Здесь стена текста. Я помню, что я сам тебе по этому коду давал какие-то советы, но сейчас, хоть убей, вспомнить не могу какие именно. И другию люди читающие код вряд ли его поймут.

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

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

> https://github.com/V3N0m21/Uppu3/blob/master/app/bootstrap.php#L13


> $cache = new \Doctrine\Common\Cache\MemcacheCache();


Если APC не подключен, ты используешь memcache. Это не логично. Ведь его может и не быть. В качестве резерва надо использовать FilesystemCache, который кеширует данные в файлах.

Конфиг базы данных надо вынести в отдельный файл, например config.php, а в README добавить напоминание что надо прописать реквизиты доступа к базе в этот файл. Причем там должны быть только настройки которые имеет смысл менять пользователю.

В этот же конфиг надо вынести параметр $isDevMode = true; который там намертво сейчас вшит в код.

> https://github.com/V3N0m21/Uppu3/blob/master/public/index.php#L27


> $isLogged = $app->loginHelper;


Одинаковые вещи называй одинаково

> https://github.com/V3N0m21/Uppu3/blob/master/public/index.php#L37


> $flash = '';


можно добавить это через appendData а не писать в каждой функции

> https://github.com/V3N0m21/Uppu3/blob/master/public/index.php#L41


> $app->get('/login', function () use ($app) {


У тебя 2 отдельных обработчика, для GET и POST. Если в форму надо будет передать какую-то переменную, придется писать это в 2 местах. Нехорошо, надо объединить в одну функцию. Тем более что именно так и советуется в моем уроке по работе с формами, у тебя есть какие-то причины почему твой вариант лучше?

То же самое относится к форме регистрации.

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

В форме регистрации мне не нравится, что ты всюду передаешь POST. Это массив в котором может быть любое число элементов любого типа. Крайне ненадежно с ним работать. Гораздо лучше передавать объект User, ну а пароль (которого в нем нет) передавать отдельной переменной.

То есть:

$validation->validateData($user, $password);
...
$userHelper->registerUser($user, $password);
....

> $cookie = $app->getCookie('salt');


> $app->setCookie('salt', $cookie, '1 month');


Это я не понимаю. почему ты соль хранишь в куках? Соль не нужна пользователю, она должна храниться только в БД. Что ты тут за собственный алгоритм изобрел?

Более того, ты еще и ищешь пользователей почему-то по соли. Это явно что-то не так.

Ну и код надо выносить в функции. Вот этот блок кода например:

> https://github.com/V3N0m21/Uppu3/blob/master/public/index.php#L50


> if ($user = $app->em->getRepository('Uppu3\Entity\User')


> ->findOneBy(array('login' => $_POST['login']))) {


> if($user->getHash() === HashGenerator::generateHash($_POST['password'], $user->getSalt()))


Однозначно стоит вынести в функцию:

$user = $someService->checkUser($login, $password, $error); // В $error вернется текст ошибки

Или можно так:

list($user, $error) = $someService->checkUser($login, $password);

> https://github.com/V3N0m21/Uppu3/blob/master/public/index.php#L49


> $_POST['login']


Я думаю лучше использовать $app->request вместо POST. Например он не выдает ошибку если элемента нет.

> $error = "Invalid login or password";


> $app->render('login_form.html', array('flash' => $error, 'data' => $_POST));


Это незачем писать 2 раза.

> https://github.com/V3N0m21/Uppu3/blob/master/public/index.php#L96


> if (file_exists($_FILES['load']['tmp_name'])) {


Тут надо бы проверку получше сделать, в PHP есть специальное поле которое хранит ошибку при загрузке файла: http://php.net/manual/ru/features.file-upload.errors.php

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

> \Uppu3\Helper\UserHelper::saveAnonymousUser($cookie, $app->em);


> \Uppu3\Helper\FileHelper::fileSave($_FILES, $user, $app->em);


замени статические методы на обычные. $em (а лучше конкретный репозиторий если можно) передавай как зависимсоть через конструктор.

> $file = $app->em->find('Uppu3\Entity\File', $id);


> $user = $app->em->getRepository('Uppu3\Entity\User')->findOneById($file->getUploadedBy());


Почему не $uploader = $file->getUploader()? Почему такие усложнения?

Более того, писать это в index.php не требуется, можно написать это в шаблоне.

> $comments = $app->em->getRepository('Uppu3\Entity\Comment')->findBy(array('fileId' => $id), array('path' => 'ASC'));


Слишком длинная строка, разбей на 2 с промежутойной переменной $commentRepo.

> $info = $file->getMediainfo();


Это не требуется писать в index.php, можно написать в шаблоне.

> https://github.com/V3N0m21/Uppu3/blob/master/public/index.php#L153


> foreach ($users as $user) {


> $filesCount[$user->getId() ] = count($app->em->getRepository('Uppu3\Entity\File')


Это неэффективно, делать запросы в цикле. Надо использовать запрос с GROUP BY (если у тебя меньше 1000-2000 файлов, если больше то и он не очень эффективен и надо заводить у пользователя поле с числом файлов и брать данные из него)

Если ты плохо знаешь SQL, рекомендую порешать мои задачки на SQL - GROUP BY сможешь с закрытыми глазами писать.

Если ты отправляешь пользователя залогинится, то надо сохранять текущий URL (например /login?from=/users/) а после логина редиректить, причем дополнительн проверять что URL нходится на твоем сайте, чтобы нельзя было пользователя отправить на левый сайт.

> https://github.com/V3N0m21/Uppu3/blob/master/public/index.php#L173


> foreach ($files as $file) {


Тут SQL запросы в цикле. Надо либо выбирать пользователей через SELECT WHERE ud IN (..) либо в первом запросе, где ты выбираешь файлы, сделать DQL запрос с джойном пользователей, чтобы доктрина выбрала и файлы и и тех кто их загрузил сразу.

(англ) http://doctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/reference/dql-doctrine-query-language.html#joins
(рус) http://odiszapc.ru/doctrine/dql-doctrine-query-language/#1322_JOIN

Обрати внимание что ты и без джойна можешь получить аплоадера по файлу, но это будет сделано за счет ленивой загрузки отдельным запросом. То есть мы получим проблему N + 1 селекта: http://www.krestjaninoff.ru/2011/06/n1-select.html

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

> https://github.com/V3N0m21/Uppu3/blob/master/public/index.php#L181


В функции отправки комментария нет валидации данных.

Еще я вижу что ты конструируешь ссылки руками: "user/$id". Разве это удобно? как ты относишься к идее сделать класс UrlHelper с методами вида getUserPage($userId)?

Пока качество кода меня не устраивает. Я думаю, что это можно сделать лучше.

Остальные файлы я пока не проверял.
#610 #586976
>>582860

Вакаба съела символы из твоей регулярки. запости ее на pastebin или ideone. Также, напиши выдаются ли какие-то ошибки при выполнении этого кода.

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

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

Также, ты поступаешь в общем непраильно, пытаясь парсить BB-коды регулярками. По идее это надо разбивать на токены и обрабатывать парсером, например recusrive descent parser. Правда из тех примеров кода что я видел, 100% так же как и ты обрабатывают BB-код регулярками и в большинстве из них есть ошибки и уязвимости (XSS, урок: https://github.com/codedokode/pasta/blob/master/security/xss.md ). Ты хочешь присоединиться к этой компании?

>>582965

> ибо тогда URI получается не такой как надо для обработке в роутере


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

> Получается тогда использоват гет запросы в этом случае нельзя и вместо такого например site.com/?act=logout (выход) нужно использовать что-то такое site.com/act/logout


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

>>583125

Изучить HTML/CSS и как нарезать картинки в фотошопе.

>>583195

> em[data-ref]


> display: inline-block;


Зачем это? Попробуй выделить длинный многострочный кусок текста таким em

Надписи [1] находятся немного выше чем должны и не выровнены правильно с подчеркнутой надписью. Посмотри как на картинке.

> p {


> position: relative


Тут недостаток, что это будет работать только внутри p. А можно ли сделать чтобы работало внутри любого тега?

> img[src="http://lorempixel.com/350/250/cats"] {


Надо чтобы работало и при смене URL картинки

> max-width: 350px;


Не, так не пойдет. Откуда это магическое число? Надо чтобы работало с картинками неизвестного размера и любой шириной страницы.

Расстояние между «A cute cat» и «in the picture» у тебя больше чем на картинке-образце.
#610 #586976
>>582860

Вакаба съела символы из твоей регулярки. запости ее на pastebin или ideone. Также, напиши выдаются ли какие-то ошибки при выполнении этого кода.

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

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

Также, ты поступаешь в общем непраильно, пытаясь парсить BB-коды регулярками. По идее это надо разбивать на токены и обрабатывать парсером, например recusrive descent parser. Правда из тех примеров кода что я видел, 100% так же как и ты обрабатывают BB-код регулярками и в большинстве из них есть ошибки и уязвимости (XSS, урок: https://github.com/codedokode/pasta/blob/master/security/xss.md ). Ты хочешь присоединиться к этой компании?

>>582965

> ибо тогда URI получается не такой как надо для обработке в роутере


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

> Получается тогда использоват гет запросы в этом случае нельзя и вместо такого например site.com/?act=logout (выход) нужно использовать что-то такое site.com/act/logout


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

>>583125

Изучить HTML/CSS и как нарезать картинки в фотошопе.

>>583195

> em[data-ref]


> display: inline-block;


Зачем это? Попробуй выделить длинный многострочный кусок текста таким em

Надписи [1] находятся немного выше чем должны и не выровнены правильно с подчеркнутой надписью. Посмотри как на картинке.

> p {


> position: relative


Тут недостаток, что это будет работать только внутри p. А можно ли сделать чтобы работало внутри любого тега?

> img[src="http://lorempixel.com/350/250/cats"] {


Надо чтобы работало и при смене URL картинки

> max-width: 350px;


Не, так не пойдет. Откуда это магическое число? Надо чтобы работало с картинками неизвестного размера и любой шириной страницы.

Расстояние между «A cute cat» и «in the picture» у тебя больше чем на картинке-образце.
#611 #586977
>>583211

Ну так перепиши фронтконтроллер чтобы определял правильно.

>>583246

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

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

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

- range(x, y) где x > y вернет пустой массив
- иначе range(x, y) вернет массив содержащий x + числа которые вернет вызов range(x + 1, y)

(это если я правильно понял условие. ты его не написал).

Ну вот, осталось только в код это переписать.

> Так вот, как прокачивать эту ебучую соображалку? Чтобы хватало мозгов сразу делать нормально,


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

> как перестать быть говнокодером.


для начала попробуй почитать http://learn.javascript.ru/write-unmain-code

>>583380

Не знаю, по моему разница только в расширении. Что ты имеешь в виду под tpl-шаблоном?

>>583395

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

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

>>583412

Можешь, погугли «конструктор сайтов» а также «wysiwyg редактор сайтов». Сделать сайт ты сможешь, работать верстальщиком или программистом - нет.
#611 #586977
>>583211

Ну так перепиши фронтконтроллер чтобы определял правильно.

>>583246

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

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

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

- range(x, y) где x > y вернет пустой массив
- иначе range(x, y) вернет массив содержащий x + числа которые вернет вызов range(x + 1, y)

(это если я правильно понял условие. ты его не написал).

Ну вот, осталось только в код это переписать.

> Так вот, как прокачивать эту ебучую соображалку? Чтобы хватало мозгов сразу делать нормально,


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

> как перестать быть говнокодером.


для начала попробуй почитать http://learn.javascript.ru/write-unmain-code

>>583380

Не знаю, по моему разница только в расширении. Что ты имеешь в виду под tpl-шаблоном?

>>583395

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

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

>>583412

Можешь, погугли «конструктор сайтов» а также «wysiwyg редактор сайтов». Сделать сайт ты сможешь, работать верстальщиком или программистом - нет.
#612 #586978
>>583514

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

Шрифт великоват.

> Я знаю только box-shadow, нужна подсказка где искать другие способы.


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

> .buttons label span {


> width: 64px;


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

Все, что можно посчитать автоматически, должно считаться автоматически. В твоем CSS не должно быть лишних цифр.

> height: 32px;


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

И еще, подумай над клавиатурной навигацией. Если ты сделаешь обычные, видимые радиокнопки то можешь перемещаться по ним клавишами Tab и стрелками (проверь). Обрати внимание что клавиатурная навигация может не работать на сайтах типа jsfiddle, тестируй на html-файле.

Заметь что есть атрибут позволяющий сделать почти любой элемент фокусируемым: https://developer.mozilla.org/ru/docs/Web/HTML/Global_attributes/tabindex

Также атрибут задающий горячие клавиши: https://developer.mozilla.org/ru/docs/Web/HTML/Global_attributes/accesskey (тоже ужасно реализована: нет возможности получить список кнопок или подсветить активные элементы).

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

Вообще, я вижу что много где эта навигация сломана. Да и вариант который предлагает браузер по умолчанию, клавиша Tab тоже довольно убогий. В старой Опере были специальные кнопки, которые позволяли перемещаться по элементам в 4 направлениях и функция показа списка горячих клавиш по Shift + Esc.

>>583807

Конкретно rutube? Наверно можно http://habrahabr.ru/company/rutube/blog/270223/

>>584049

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


Тогда можешь найти эффект который тебе нравится больше, например погуглив «css3 button animations» и выбрав любой.

Главная идея конечно чтобы ты понял возможности CSS3 и не делал анимации яваскриптом когда это позволяет сделать CSS.

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

Похожую штуку ты можешь увидеть тут http://codeforces.com/problemset наведя мышь на меню «ЗАДАЧИ ОТОСЛАТЬ СТАТУС ПОЛОЖЕНИЕ ЗАПУСК»

Обрати внимание, в flexbox есть свойство order, позволяющее перестраивать элементы: http://frontender.info/a-guide-to-flexbox/#codeordercode но оно вряд ли анимируется и поможет тебе.

Кстати, на jsfiddle в редакторе HTML работает Emmet почитай про него, он ускоряет набор кода. заодно можешь и про HAML почитать.

12 задание

> input[type="radio"]:checked + label + article + article + article {


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

И тот же самый вопрос про клавиатурную навигацию.

> .tabs label {


> width: 20%;


Лучше чтобы определялось по ширине текста

> .tabs article {


> top: 153px;


Не, это не годится так как не хочется считать высоту при изменении верстки.

>>584529

Это может напугать какого-нибудь школьника - вдруг сайт запишет его IP адрес, найдет его и вызовет родителей в школу.
#612 #586978
>>583514

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

Шрифт великоват.

> Я знаю только box-shadow, нужна подсказка где искать другие способы.


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

> .buttons label span {


> width: 64px;


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

Все, что можно посчитать автоматически, должно считаться автоматически. В твоем CSS не должно быть лишних цифр.

> height: 32px;


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

И еще, подумай над клавиатурной навигацией. Если ты сделаешь обычные, видимые радиокнопки то можешь перемещаться по ним клавишами Tab и стрелками (проверь). Обрати внимание что клавиатурная навигация может не работать на сайтах типа jsfiddle, тестируй на html-файле.

Заметь что есть атрибут позволяющий сделать почти любой элемент фокусируемым: https://developer.mozilla.org/ru/docs/Web/HTML/Global_attributes/tabindex

Также атрибут задающий горячие клавиши: https://developer.mozilla.org/ru/docs/Web/HTML/Global_attributes/accesskey (тоже ужасно реализована: нет возможности получить список кнопок или подсветить активные элементы).

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

Вообще, я вижу что много где эта навигация сломана. Да и вариант который предлагает браузер по умолчанию, клавиша Tab тоже довольно убогий. В старой Опере были специальные кнопки, которые позволяли перемещаться по элементам в 4 направлениях и функция показа списка горячих клавиш по Shift + Esc.

>>583807

Конкретно rutube? Наверно можно http://habrahabr.ru/company/rutube/blog/270223/

>>584049

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


Тогда можешь найти эффект который тебе нравится больше, например погуглив «css3 button animations» и выбрав любой.

Главная идея конечно чтобы ты понял возможности CSS3 и не делал анимации яваскриптом когда это позволяет сделать CSS.

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

Похожую штуку ты можешь увидеть тут http://codeforces.com/problemset наведя мышь на меню «ЗАДАЧИ ОТОСЛАТЬ СТАТУС ПОЛОЖЕНИЕ ЗАПУСК»

Обрати внимание, в flexbox есть свойство order, позволяющее перестраивать элементы: http://frontender.info/a-guide-to-flexbox/#codeordercode но оно вряд ли анимируется и поможет тебе.

Кстати, на jsfiddle в редакторе HTML работает Emmet почитай про него, он ускоряет набор кода. заодно можешь и про HAML почитать.

12 задание

> input[type="radio"]:checked + label + article + article + article {


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

И тот же самый вопрос про клавиатурную навигацию.

> .tabs label {


> width: 20%;


Лучше чтобы определялось по ширине текста

> .tabs article {


> top: 153px;


Не, это не годится так как не хочется считать высоту при изменении верстки.

>>584529

Это может напугать какого-нибудь школьника - вдруг сайт запишет его IP адрес, найдет его и вызовет родителей в школу.
#613 #586979
>>584566

> То, что angular.element('#overlay-loader').css('display', 'block'); выполнилось раньше их везение или закономерность, которая следует из того что строка расположена выше по коду?


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

>>584573

Браузер и его пользовательский интерфейс (в Хроме - только вкладка) блокируется на время выполнения JS кода. Первые браузеры были банально однопоточные, ну и как я писал выше, чтобы например браузер мог обращаться к ДОМ параллельно с JS надо делать блокировки, а это усложнение кода и снижение производительности. Хотя вроде CSS анимации хотят как-то вынести в отдельный поток.

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

>>584636

> box-sizing:border-box;


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

>>584807

Вариант 8 (не 8.1) мне нравится больше.

По HTML: слишком много тегов. Упрости код до такого:

<p>....</p>
<aside class...>.....</aside>
<p>...</p>

также, добавь в текст справа заголовок и список, чтобы там были не только <p>. И прочитай примечание к задаче про padding.

> <p class="text">


А зачем тут класс? Что это, какой то особенный абзац, не такой как все?

> <div class="container">


Ты замусориваешь HTML код бесполезными тегами. Идея HTML разметки в том, что мы берем текст страницы и тегами размечаем его на блоки, показывая смысл этих блоков и их связь (а не думая как нам будет удобнее писать CSS код. Об этом мы будем думать потом). Этот тег никакой полезной информации читателю твоего кода не несет. Надо избегать (без фанатизма конечно) добавления лишних тегов ради оформления или раскладки страницы. Зачем тебе контейнер если у тебя уже есть body?

В HTML разметка отвечает за смысл элемента, а не за его внешний вид. Неправильно писать class="big-text-red", а правильно class="important-notice" или class="irony". Неправильно ради вывода иконки предупреждения писать <img...>Внимание!... (img для картинок и иллюстраций к статье, а не для элементов оформления) а правильно добавлять ее через CSS: <div class="warning">Внимание! ...</div>. Видишь разницу? В первом случае ты закладываешь в HTML оформелние, как текст выглядит, а во втором - его смысл.

>>584939

Поискать по словам «angular dirty check», «angular digest».

Также прочитай эту статью, про 2 варианта реализовать отслеживание изменений в View Model: http://habrahabr.ru/post/165275/

Статья неправильно дает список преимуществ и недостатков. Проблема knockout не в том что вид обновляется при каждом изменении (это легко решается). Проблема knockout в том, что в нем нет магии, ты должен специальным образом создавать свою модель, делая все через функции knockout. Это 1) неудобно 2) не волшебно 3) можно забыть что-то сделать, если ты джуниор 4) я хочу чтобы датабайндинг был сбоку, а не внутри моих объектов и хочу писать их как мне нравится, а не авторам фреймворка 5) возможно код не та удобно тестировать как в ангуларе. Ангулар же устроен магически: он сам без всякой помощи обнаруживает изменения значения переменной. Но за это приходится платить производительностью (надо иметь копию данных в $scope и делать рекурсивный обход сложности O(N), причем минимум 2 раза).

Как вариант, в новых браузерах можно будет использовать https://developers.google.com/web/updates/2012/11/Respond-to-change-with-Object-observe (для вложенных объектов придется вешать обработчик и на них).

Попробуй разобраться в том как в нем это устроено. Возможно тебе придется залезть в код фреймворка. Это важно знать, если ты хочешь действительно знать angular. Без понимания его внутреннего устройства эффективно его использовать не получится. Ну и я уверен, ты много нового узнаешь, может какие-то идеи для себя подчерпнешь.

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

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

>>585096

А что ты знаешь? Надо знать минимум HTML/JS/DOM на хорошем уровне.
#613 #586979
>>584566

> То, что angular.element('#overlay-loader').css('display', 'block'); выполнилось раньше их везение или закономерность, которая следует из того что строка расположена выше по коду?


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

>>584573

Браузер и его пользовательский интерфейс (в Хроме - только вкладка) блокируется на время выполнения JS кода. Первые браузеры были банально однопоточные, ну и как я писал выше, чтобы например браузер мог обращаться к ДОМ параллельно с JS надо делать блокировки, а это усложнение кода и снижение производительности. Хотя вроде CSS анимации хотят как-то вынести в отдельный поток.

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

>>584636

> box-sizing:border-box;


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

>>584807

Вариант 8 (не 8.1) мне нравится больше.

По HTML: слишком много тегов. Упрости код до такого:

<p>....</p>
<aside class...>.....</aside>
<p>...</p>

также, добавь в текст справа заголовок и список, чтобы там были не только <p>. И прочитай примечание к задаче про padding.

> <p class="text">


А зачем тут класс? Что это, какой то особенный абзац, не такой как все?

> <div class="container">


Ты замусориваешь HTML код бесполезными тегами. Идея HTML разметки в том, что мы берем текст страницы и тегами размечаем его на блоки, показывая смысл этих блоков и их связь (а не думая как нам будет удобнее писать CSS код. Об этом мы будем думать потом). Этот тег никакой полезной информации читателю твоего кода не несет. Надо избегать (без фанатизма конечно) добавления лишних тегов ради оформления или раскладки страницы. Зачем тебе контейнер если у тебя уже есть body?

В HTML разметка отвечает за смысл элемента, а не за его внешний вид. Неправильно писать class="big-text-red", а правильно class="important-notice" или class="irony". Неправильно ради вывода иконки предупреждения писать <img...>Внимание!... (img для картинок и иллюстраций к статье, а не для элементов оформления) а правильно добавлять ее через CSS: <div class="warning">Внимание! ...</div>. Видишь разницу? В первом случае ты закладываешь в HTML оформелние, как текст выглядит, а во втором - его смысл.

>>584939

Поискать по словам «angular dirty check», «angular digest».

Также прочитай эту статью, про 2 варианта реализовать отслеживание изменений в View Model: http://habrahabr.ru/post/165275/

Статья неправильно дает список преимуществ и недостатков. Проблема knockout не в том что вид обновляется при каждом изменении (это легко решается). Проблема knockout в том, что в нем нет магии, ты должен специальным образом создавать свою модель, делая все через функции knockout. Это 1) неудобно 2) не волшебно 3) можно забыть что-то сделать, если ты джуниор 4) я хочу чтобы датабайндинг был сбоку, а не внутри моих объектов и хочу писать их как мне нравится, а не авторам фреймворка 5) возможно код не та удобно тестировать как в ангуларе. Ангулар же устроен магически: он сам без всякой помощи обнаруживает изменения значения переменной. Но за это приходится платить производительностью (надо иметь копию данных в $scope и делать рекурсивный обход сложности O(N), причем минимум 2 раза).

Как вариант, в новых браузерах можно будет использовать https://developers.google.com/web/updates/2012/11/Respond-to-change-with-Object-observe (для вложенных объектов придется вешать обработчик и на них).

Попробуй разобраться в том как в нем это устроено. Возможно тебе придется залезть в код фреймворка. Это важно знать, если ты хочешь действительно знать angular. Без понимания его внутреннего устройства эффективно его использовать не получится. Ну и я уверен, ты много нового узнаешь, может какие-то идеи для себя подчерпнешь.

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

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

>>585096

А что ты знаешь? Надо знать минимум HTML/JS/DOM на хорошем уровне.
#614 #586981
>>585531

Код удален с пастебина, я проверить не могу.

>>585548

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

>>585641

Автор плохо разбирается в теме. То что он пишет - бред. Вскрыть пароль вроде «123456» можно вообще не имея базы - просто попробовать ввести его в форму логина. Значит ли это что мы не должны использовать хеширования и хранить пароль в открытом виде?

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

>>586034

>>Это подзаголовок


> Что такое подзаголовок?


Подзаголовок это заголовок большей вложенности. Ну если заголовок (h1) относится ко всей статье, то например подзаголовок (h2) относится только к одной ее части. Обычно на печати подзаголовок делается меньшего размера. В HTML 6 уровней заголовков, но на практике текстов где уровней больше 4 я не встречал.

Вот статья еще, не знаю в тему ли: http://artgorbunov.ru/bb/soviet/20150201/

Вот пример моей задачи, там используется 3 уровня заголовков: https://github.com/codedokode/pasta/blob/master/js/spa.md

> Сеошники с тобой не согласятся


Для СЕО как раз надо правильно расставлять заголовки. Поисковики могут придавать словам из заголовка больший вес.

> Больше скрупулезности богу скрупулезности.


Я же вроде писал что мы не закладываем (стараемся, без фанатизма) оформление в HTML. Стиль написания это тоже оформление.

>>586097

Ок, 6-е задание теперь верно. В комментарии конечно правильнее писать для чего он тут стоит.

> SQL код


Чтобы легче разбирать план, стоит вынести второй запрос отдельно из UNION и посмотреть план выполнения, сделав EXPLAIN EXTENDED, а затем SHOW WARNINGS.

Я пошел дальше и упростил запрос еще сильнее:

EXPLAIN EXTENDED SELECT ul. FROM users_likes ul WHERE (ul.from_user = 5 OR ul.to_user = 5)\G
SHOW WARNIGNS\G

id: 1
select_type: SIMPLE
table: ul
type: index
possible_keys: PRIMARY,to_user
key: to_user
key_len: 4
ref: NULL
rows: 4
filtered: 100.00
Extra: Using where; Using index

Он странный, но выглядит как твой. Там написано Using index, но ведь тут условие OR и в лучшем случае можно сделать 2 выборки по 2 индексам на таблице user_likes и смерджить результаты (взять те строки которые есть в обоих выборках).

Чтобы понять, что это значит, перечитаем документацию: http://dev.mysql.com/doc/refman/5.7/en/explain-output.html

Если ты глянешь на type то увидишь там: index, а не range или const. Это значит что у нас фулл-скан по индексу. Так как в индексе есть оба id то незачем читать строки таблицы, можно читать их из индекса. Но по прямому назначению - ускорить выборку двоичным поиском - индекс не используется. Это фуллскан, только по индексу.

Для сравнения, попробуем убрать OR: EXPLAIN EXTENDED SELECT ul.
FROM users_likes ul WHERE (ul.from_user = 5)\G
type: ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: const

Другое дело - в поле type стоит ref, а ref = const.

Может проблема в маленьком числе строк в таблице, MySQL не видит нужнда в оптимизации? Я закачал список id из большой таблицы, и попробовал повторить запрос:

CREATE TEMPORARY TABLE ids(id int AUTO_INCREMENT);
INSERT INTO ids VALUES (NULL), (NULL), (NULL), (NULL);
SELECT 1 FROM ids a JOIN ids As b; # FAIL - не работает с временными таблицами
SET @num =0; SELECT @num := @num + 1 FROM users a JOIN users b ; # дает 25 строк
INSERT INTO ids SELECT NULL FROM users a JOIN users b JOIN users c JOIN users d JOIN users e JOIN users f JOIN users g; # 78 000 строк
INSERT INTO users (id, name) SELECT id + 10, CONCAT('user', id + 10) FROM ids;
INSERT INTO users_likes (from_user, to_user) SELECT id + 10, 1 FROM ids;

Попробуем повторить запрос:

EXPLAIN EXTENDED SELECT ul.* FROM users_likes ul WHERE (ul.from_user = 5 OR ul.to_user = 5)\G
select_type: SIMPLE
table: ul
type: index_merge
possible_keys: PRIMARY,to_user
key: PRIMARY,to_user
key_len: 4,4
ref: NULL
rows: 3
filtered: 100.00
Extra: Using union(PRIMARY,to_user); Using where

То есть index merge заработал на большой таблице.

Теперь добавим джойн (джойн по условию OR - по моему почти всегда фуллскан): EXPLAIN EXTENDED SELECT DISTINCT ug.group_id FROM users_likes ul JOIN users_groups ug WHERE (ul.from_user = 5 OR ul.to_user = 5) AND (ul.from_user = ug.user_id OR ul.to_user = ug.user_id)\G

Теперь мы имеем другой план (сделай запрос и выясни какой). Сначала он делает выборку из users_likes с мерджем индекса (то есть бьстро и эффективно), а затем джойнит к ним users_groups с type = index делая фуллскан по индексу. Я думаю, ты догадываешься что фуллскан по индексу я правильным ответом на задачу не считаю.

То есть смотри: если OR в WHERE, он использует объединение 2 выборок по индексу которое эффективно. А когда видит OR в джойне, то не исплоьзует. А фуллскан при джойне - что это значит? Это значит такой алгоритм (nested join loop, погугли):

1) взять очередную 1 строку из users_likes
2) обойти таблицу users_groups фуллсканом и проверить каждую строку на соответствие условию джойна
3) перейти к п.1

То есть мы имеем не один фуллсканов, а целый цикл с фуллсканами. Впрочем, MySQL пытается облегчить себе задачу используя join buffer. С ним алгоритм меняется так:

1) взять несколько строк из users_likes, сколько влезет в буфер
2) обойти таблицу users_groups фуллсканом проверяя каждую строку по очереди на совпадение со строками в буфере
3) перейти к п.1

Тут фуллсканов выходит меньше, я думаю, около одного, но он получается более тяжелый. Но это все равно намного лучше так как фуллскан часто подразумевает чтение таблицы с диска, и тут чтений выходит меньше (в идеале одно), чем без join buffer (столько сколько строк выберется из users_likes). Эта оптимизация описана тут: https://dev.mysql.com/doc/internals/en/join-buffer-size.html

В общем мораль: не делай джойны без индексов. Фуллскан в джойне это смерть для базы.

И еще, я тестировал на версии 5.6, а в 5.7 вроде было добавлены новые оптимизации. Но тут лучше запрос переписать.

> Что ты можешь сказать по данному explain?


Все плохо. Мы имеем фуллскан при джойне.

> Ну например я вижу "using temporary".


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

> Это хорошо или плохо?


Зависит от ситуации.

> Я не знаю, вдруг использование этого буффера вредно


join buffer значит что mysql пытается сделать очень плохой запрос просто плохим.

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


Смотришь документацию - понимаешь что происходит - делаешь выводы хорошо это или плохо. Это непросто поначалу, но со временем научишься.

> Хотя вроде тут только первичные да внешние ключи


А целых 2 OR у тебя не вызывают ни малейших подозрений?
#614 #586981
>>585531

Код удален с пастебина, я проверить не могу.

>>585548

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

>>585641

Автор плохо разбирается в теме. То что он пишет - бред. Вскрыть пароль вроде «123456» можно вообще не имея базы - просто попробовать ввести его в форму логина. Значит ли это что мы не должны использовать хеширования и хранить пароль в открытом виде?

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

>>586034

>>Это подзаголовок


> Что такое подзаголовок?


Подзаголовок это заголовок большей вложенности. Ну если заголовок (h1) относится ко всей статье, то например подзаголовок (h2) относится только к одной ее части. Обычно на печати подзаголовок делается меньшего размера. В HTML 6 уровней заголовков, но на практике текстов где уровней больше 4 я не встречал.

Вот статья еще, не знаю в тему ли: http://artgorbunov.ru/bb/soviet/20150201/

Вот пример моей задачи, там используется 3 уровня заголовков: https://github.com/codedokode/pasta/blob/master/js/spa.md

> Сеошники с тобой не согласятся


Для СЕО как раз надо правильно расставлять заголовки. Поисковики могут придавать словам из заголовка больший вес.

> Больше скрупулезности богу скрупулезности.


Я же вроде писал что мы не закладываем (стараемся, без фанатизма) оформление в HTML. Стиль написания это тоже оформление.

>>586097

Ок, 6-е задание теперь верно. В комментарии конечно правильнее писать для чего он тут стоит.

> SQL код


Чтобы легче разбирать план, стоит вынести второй запрос отдельно из UNION и посмотреть план выполнения, сделав EXPLAIN EXTENDED, а затем SHOW WARNINGS.

Я пошел дальше и упростил запрос еще сильнее:

EXPLAIN EXTENDED SELECT ul. FROM users_likes ul WHERE (ul.from_user = 5 OR ul.to_user = 5)\G
SHOW WARNIGNS\G

id: 1
select_type: SIMPLE
table: ul
type: index
possible_keys: PRIMARY,to_user
key: to_user
key_len: 4
ref: NULL
rows: 4
filtered: 100.00
Extra: Using where; Using index

Он странный, но выглядит как твой. Там написано Using index, но ведь тут условие OR и в лучшем случае можно сделать 2 выборки по 2 индексам на таблице user_likes и смерджить результаты (взять те строки которые есть в обоих выборках).

Чтобы понять, что это значит, перечитаем документацию: http://dev.mysql.com/doc/refman/5.7/en/explain-output.html

Если ты глянешь на type то увидишь там: index, а не range или const. Это значит что у нас фулл-скан по индексу. Так как в индексе есть оба id то незачем читать строки таблицы, можно читать их из индекса. Но по прямому назначению - ускорить выборку двоичным поиском - индекс не используется. Это фуллскан, только по индексу.

Для сравнения, попробуем убрать OR: EXPLAIN EXTENDED SELECT ul.
FROM users_likes ul WHERE (ul.from_user = 5)\G
type: ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: const

Другое дело - в поле type стоит ref, а ref = const.

Может проблема в маленьком числе строк в таблице, MySQL не видит нужнда в оптимизации? Я закачал список id из большой таблицы, и попробовал повторить запрос:

CREATE TEMPORARY TABLE ids(id int AUTO_INCREMENT);
INSERT INTO ids VALUES (NULL), (NULL), (NULL), (NULL);
SELECT 1 FROM ids a JOIN ids As b; # FAIL - не работает с временными таблицами
SET @num =0; SELECT @num := @num + 1 FROM users a JOIN users b ; # дает 25 строк
INSERT INTO ids SELECT NULL FROM users a JOIN users b JOIN users c JOIN users d JOIN users e JOIN users f JOIN users g; # 78 000 строк
INSERT INTO users (id, name) SELECT id + 10, CONCAT('user', id + 10) FROM ids;
INSERT INTO users_likes (from_user, to_user) SELECT id + 10, 1 FROM ids;

Попробуем повторить запрос:

EXPLAIN EXTENDED SELECT ul.* FROM users_likes ul WHERE (ul.from_user = 5 OR ul.to_user = 5)\G
select_type: SIMPLE
table: ul
type: index_merge
possible_keys: PRIMARY,to_user
key: PRIMARY,to_user
key_len: 4,4
ref: NULL
rows: 3
filtered: 100.00
Extra: Using union(PRIMARY,to_user); Using where

То есть index merge заработал на большой таблице.

Теперь добавим джойн (джойн по условию OR - по моему почти всегда фуллскан): EXPLAIN EXTENDED SELECT DISTINCT ug.group_id FROM users_likes ul JOIN users_groups ug WHERE (ul.from_user = 5 OR ul.to_user = 5) AND (ul.from_user = ug.user_id OR ul.to_user = ug.user_id)\G

Теперь мы имеем другой план (сделай запрос и выясни какой). Сначала он делает выборку из users_likes с мерджем индекса (то есть бьстро и эффективно), а затем джойнит к ним users_groups с type = index делая фуллскан по индексу. Я думаю, ты догадываешься что фуллскан по индексу я правильным ответом на задачу не считаю.

То есть смотри: если OR в WHERE, он использует объединение 2 выборок по индексу которое эффективно. А когда видит OR в джойне, то не исплоьзует. А фуллскан при джойне - что это значит? Это значит такой алгоритм (nested join loop, погугли):

1) взять очередную 1 строку из users_likes
2) обойти таблицу users_groups фуллсканом и проверить каждую строку на соответствие условию джойна
3) перейти к п.1

То есть мы имеем не один фуллсканов, а целый цикл с фуллсканами. Впрочем, MySQL пытается облегчить себе задачу используя join buffer. С ним алгоритм меняется так:

1) взять несколько строк из users_likes, сколько влезет в буфер
2) обойти таблицу users_groups фуллсканом проверяя каждую строку по очереди на совпадение со строками в буфере
3) перейти к п.1

Тут фуллсканов выходит меньше, я думаю, около одного, но он получается более тяжелый. Но это все равно намного лучше так как фуллскан часто подразумевает чтение таблицы с диска, и тут чтений выходит меньше (в идеале одно), чем без join buffer (столько сколько строк выберется из users_likes). Эта оптимизация описана тут: https://dev.mysql.com/doc/internals/en/join-buffer-size.html

В общем мораль: не делай джойны без индексов. Фуллскан в джойне это смерть для базы.

И еще, я тестировал на версии 5.6, а в 5.7 вроде было добавлены новые оптимизации. Но тут лучше запрос переписать.

> Что ты можешь сказать по данному explain?


Все плохо. Мы имеем фуллскан при джойне.

> Ну например я вижу "using temporary".


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

> Это хорошо или плохо?


Зависит от ситуации.

> Я не знаю, вдруг использование этого буффера вредно


join buffer значит что mysql пытается сделать очень плохой запрос просто плохим.

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


Смотришь документацию - понимаешь что происходит - делаешь выводы хорошо это или плохо. Это непросто поначалу, но со временем научишься.

> Хотя вроде тут только первичные да внешние ключи


А целых 2 OR у тебя не вызывают ни малейших подозрений?
#615 #586983
>>586109

> задача 9


Теперь все верно.

> Если я правильно понял макет, каждая картинка занимает 270px, то есть свою натуральную величину. Между картинками по вертикали и горизонтали расстояние 10px. В одном ряду может быть максимум 4 картинки (поскольку мы ограничены шириной 1110px), причем первая и последняя в ряду плотно примыкает к своему краю.


Можно попробовать такой трюк: сделать контейнер справа на 15px шире. Но вообще, я бы просто сделал контейнер чуть шире. Там ведь все равно макет резиновый по моему и должен тянуться по ширине, ну скажем от 900 до 1200 px в центральной части.

>>586313

1 задача: все верно. Только советую писать margin сокращенной записью, то есть margin: x y z t;
2 задача: у тебя макс. ширина блока снаружи 622px, а надо 600
3 задача: размер шрифта маленький (ошибка в font), не указан fallback-шрифт serif, не сброшен курсив в em.
4 задача:

> width:auto;


Это не требуется писать, это по умолчанию так.

> margin-left: -.36em;


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

В остальном, верно, у тебя хорошо получается пока.

>>586342

Можно сделать метод с указанием какие поля надо обновить.

updatePartial($foo, ['description', 'tags']);

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

> trim(htmlspecialchars($_POST['tags']))


Это неправильно. В базе надо хранить данные как есть, а экранировать при выводе. Так как 1) с экранированными неудобно работать 2) если ты не пишешь htmlspecialchars в шаблоне, как проверить что данные 100% экранированы?

Теги ты сделал неправильно. Ты читал про нормализаию базы данных? твой подход не соответствует принципам нормализации, в частности требованию атомарности значений.

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


Надо показывать юзеру не пустую форму редактирования, а заполненную. Соответственно если он что-то сотрет то значит он так хочет. А как в твоем варианте стереть данные из поля?

>>586399

> Например у меня в поле лежит дата в формате даты 21-02-1977, в поле форме у меня стоит 1 day.


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

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


Это потмоу что ты хранишь данные неправильно. Вот скажи, как с твоей системой хранения узнать на сколько дней пользователь задал время жизни для файла? Очевидно правильно хранить дату загрузки + время жизни (хотя если нужно продление то тогда лучше сделать как написал анон выше). Опять же рекомендую тебе почитать про нормализацию базы данных и может порешать наши задачки на SQL из оп поста.
#615 #586983
>>586109

> задача 9


Теперь все верно.

> Если я правильно понял макет, каждая картинка занимает 270px, то есть свою натуральную величину. Между картинками по вертикали и горизонтали расстояние 10px. В одном ряду может быть максимум 4 картинки (поскольку мы ограничены шириной 1110px), причем первая и последняя в ряду плотно примыкает к своему краю.


Можно попробовать такой трюк: сделать контейнер справа на 15px шире. Но вообще, я бы просто сделал контейнер чуть шире. Там ведь все равно макет резиновый по моему и должен тянуться по ширине, ну скажем от 900 до 1200 px в центральной части.

>>586313

1 задача: все верно. Только советую писать margin сокращенной записью, то есть margin: x y z t;
2 задача: у тебя макс. ширина блока снаружи 622px, а надо 600
3 задача: размер шрифта маленький (ошибка в font), не указан fallback-шрифт serif, не сброшен курсив в em.
4 задача:

> width:auto;


Это не требуется писать, это по умолчанию так.

> margin-left: -.36em;


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

В остальном, верно, у тебя хорошо получается пока.

>>586342

Можно сделать метод с указанием какие поля надо обновить.

updatePartial($foo, ['description', 'tags']);

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

> trim(htmlspecialchars($_POST['tags']))


Это неправильно. В базе надо хранить данные как есть, а экранировать при выводе. Так как 1) с экранированными неудобно работать 2) если ты не пишешь htmlspecialchars в шаблоне, как проверить что данные 100% экранированы?

Теги ты сделал неправильно. Ты читал про нормализаию базы данных? твой подход не соответствует принципам нормализации, в частности требованию атомарности значений.

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


Надо показывать юзеру не пустую форму редактирования, а заполненную. Соответственно если он что-то сотрет то значит он так хочет. А как в твоем варианте стереть данные из поля?

>>586399

> Например у меня в поле лежит дата в формате даты 21-02-1977, в поле форме у меня стоит 1 day.


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

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


Это потмоу что ты хранишь данные неправильно. Вот скажи, как с твоей системой хранения узнать на сколько дней пользователь задал время жизни для файла? Очевидно правильно хранить дату загрузки + время жизни (хотя если нужно продление то тогда лучше сделать как написал анон выше). Опять же рекомендую тебе почитать про нормализацию базы данных и может порешать наши задачки на SQL из оп поста.
#616 #586984
>>586488

Не знаю, я хороших книг не знаю, а те что есть в ОП посте, они не совсем для начинающего.

>>586778

Значит надо на стороне PHP переводить в нужный формат при выводе.

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


На стороне SQL есть функции для работы с датой, в том числе который берут день из полного времени. Изучи мануал прежде чем жаловаться на mysql.

>>586780

Минимум у нескольких анонов подключилось. Ты вообще в теме разбираешься?

>>586799

Задание на тесты из ОП-поста видел? Но если ты начинающий, лучше начать со студентов или файлообменника. Еще один анон делает сайт объявлений на Yii.

>>586835

htaccess это файл для задания настроек Апача (директив) в данной папке (глобально настройки задаются в конфиге). Настройки Апача разбиты на группы, по модулям, и описаны в официальной документации на англ: https://httpd.apache.org/docs/2.4/mod/

кликаешь на любой модуль например mod_rewrite и читаешь: https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html Имей в виду что не любые директивы можно использовать в htaccess.

Так как документаия большая то выгоднее просто в поиск вбивать нужную директиву.

Если английский не осилил, гугли директиву на русском.

>>586921

htmlspecialchars забыл только
#616 #586984
>>586488

Не знаю, я хороших книг не знаю, а те что есть в ОП посте, они не совсем для начинающего.

>>586778

Значит надо на стороне PHP переводить в нужный формат при выводе.

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


На стороне SQL есть функции для работы с датой, в том числе который берут день из полного времени. Изучи мануал прежде чем жаловаться на mysql.

>>586780

Минимум у нескольких анонов подключилось. Ты вообще в теме разбираешься?

>>586799

Задание на тесты из ОП-поста видел? Но если ты начинающий, лучше начать со студентов или файлообменника. Еще один анон делает сайт объявлений на Yii.

>>586835

htaccess это файл для задания настроек Апача (директив) в данной папке (глобально настройки задаются в конфиге). Настройки Апача разбиты на группы, по модулям, и описаны в официальной документации на англ: https://httpd.apache.org/docs/2.4/mod/

кликаешь на любой модуль например mod_rewrite и читаешь: https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html Имей в виду что не любые директивы можно использовать в htaccess.

Так как документаия большая то выгоднее просто в поиск вбивать нужную директиву.

Если английский не осилил, гугли директиву на русском.

>>586921

htmlspecialchars забыл только
#617 #586985
>>586868

Тебе надо изуить сначала основы PHP, тебе пока рано с базой работать. Ведь ты например можешь выбрать данные в массив и потом как угодно их выводить. Или сделать подсчет итераций в цикле while. Серьезно, вернись сначала и изучи циклы и массивы.

Ну и не пиши HTML код внутри PHP файла.

>>586249

> Мне все равно как определять. Мне просто не нравиться такое рутинное условие (($x == $map->with and $y == $map->height) or ($x == 0 and $y == $map->height) or ...), но если ты настаиваешь что должно быть так, я переделаю.


Я не настаиваю, но по моему рутинное условие 1) проще 2) очевиднее 3) не требует цикла. Можешь оставить конечно свой вариант, но тогда хорошо бы написать комментарий и в нем пояснить что тут делается и почему например число ходов делится на 2.

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


Можно сделать 2 фактора с разным весом: расстояние до ближайшей кошки (более важное) и например число кошек в определенном радиусе (менее важное) или например сумма 1/d1 + 1/d2 ... 1/dN где d1..dN расстояние до кошки. Эта сумма характеризует как число кошек, так и расстояние до них, причем близкие кошки вносят в нее больший вклад. Это кстати напоминает формулу расчета потециала электрического поля от нескольких зарядов.

Только помни что важнейший фактор это все же расстояние до ближайшей из кошек.

> Теперь буду писать комментарии.


Может они и тебе самому помогут разобраться.
Горим тут #618 #586989
Если я кого-то забыл или не ответил на вопрос, не проверил задачку, напомните о себе

Ну и так как я тут немного занят, посидим еще день-два тут, незачем нам сейчас на главную лезть и по 100 постов в день набивать.
#619 #587026
>>578917
>>578906
ОП, переделал.
https://github.com/never3ver/catsandmice

>По моему это типичная ошибка off-by-1. Если в мире ширина = 5 клеток и отсчет координат идет с нуля, то в нем X может принимать значения 0, 1, 2, 3, 4, но не 5.


Нет, это таки не ошибка. если в моем коде задать размеры 5х5, то мир получится 6х6, все учтено. Именно поэтому для получения мира 10х10 указано 9х9:https://github.com/never3ver/catsandmice/blob/master/animals.php#L41
#620 #587028
>>587026

> Именно поэтому для получения мира 10х10 указано 9х9


Ну это же не логично. Ну подумай сам, ты подходишь к автомату по продаже билетов, жмешь купить один билет, а он тебе выдает 2.
#621 #587033
>>587028
А какая разница, если этап введения данных пользователем отутствует? Никто же не ноет что в массивах нумерация с 0 начинается.
#622 #587058
Час назад решил попробовать пых. Как сделать require "../somedir/somephpfile.php" ?
#623 #587123
>>587033

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

Почитай-ка статью: http://learn.javascript.ru/write-unmain-code
#624 #587138
>>586976

> em[data-ref]


> display: inline-block;


> Зачем это?


А, это чтобы before можно было назначить display:block, так как бифоры инлайновых документов не могут быть блочными.
Но я затем намутил абсолютное позиционирование, так что это стало ненужным.
Короче, просто не почистил мусор.

> p { position: relative }


>Тут недостаток, что это будет работать только внутри p. А можно ли сделать чтобы работало внутри любого тега?


У параграфа строго фиксированный левый край, я этим пользуюсь для привязки к этому краю абсолютно позиционированного before.
Можно к body, но я же не знаю, что еще будет лежать в body. Вдруг там скажем появится еще колонка слева, ну или просто изменится паддинг, и комментарий сместится в неугодную позицию. Пока считаю привязку к параграфу оптимальной для горизонтального выравнивания.

>Надписи [1] находятся немного выше чем должны и не выровнены правильно с подчеркнутой надписью.


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

> img[src=... селектор атрибута


> Надо чтобы работало и при смене URL картинки


Я бы назначил класс, но у тебя в условии стоит, что нельзя менять html. Я решил, что это специально для того, чтобы потренироваться на селекторах, а то все засоряют html кучей классов. Можно дописать класс? Или может быть взять селектор по alt-атрибуту?

>Расстояние между «A cute cat» и «in the picture» у тебя больше чем на картинке-образце


Не думал, что это так принципиально. Глазомер у меня еще не настолько развит, но раз ты говоришь что больше, поставлю от балды mt-3px. Значит надо на картинке в условии задачи провести гайдлайны с точным указанием отступов.
Общая высота этого блока с надписями кстати зафиксирована или вычисляется на основании содержимого + паддинги? Начинаю склоняться ко второму варианту, убрал свойство height у figcaption.
Но ты такие вещи прописывай в условии. Мало того, что задания сложные, так я еще должен гадать, что хочет от меня заказчик. (Хотя наверное irl так и будет, только задачи будут примитивные, а вот ебанутость заказчиков на порядок выше)

Пощу еще раз обновленную ссылку, но фактически я только убрал лишние правила, убрал max-width для картинки, заменил селектор по атрибуту на другой селектор по атрибуту. Главную фишку - выравнивание абсолютно спозиционированного before по вертикали - пока не знаю как сделать, нужна подсказка.
http://jsfiddle.net/8386u62u/2/
#624 #587138
>>586976

> em[data-ref]


> display: inline-block;


> Зачем это?


А, это чтобы before можно было назначить display:block, так как бифоры инлайновых документов не могут быть блочными.
Но я затем намутил абсолютное позиционирование, так что это стало ненужным.
Короче, просто не почистил мусор.

> p { position: relative }


>Тут недостаток, что это будет работать только внутри p. А можно ли сделать чтобы работало внутри любого тега?


У параграфа строго фиксированный левый край, я этим пользуюсь для привязки к этому краю абсолютно позиционированного before.
Можно к body, но я же не знаю, что еще будет лежать в body. Вдруг там скажем появится еще колонка слева, ну или просто изменится паддинг, и комментарий сместится в неугодную позицию. Пока считаю привязку к параграфу оптимальной для горизонтального выравнивания.

>Надписи [1] находятся немного выше чем должны и не выровнены правильно с подчеркнутой надписью.


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

> img[src=... селектор атрибута


> Надо чтобы работало и при смене URL картинки


Я бы назначил класс, но у тебя в условии стоит, что нельзя менять html. Я решил, что это специально для того, чтобы потренироваться на селекторах, а то все засоряют html кучей классов. Можно дописать класс? Или может быть взять селектор по alt-атрибуту?

>Расстояние между «A cute cat» и «in the picture» у тебя больше чем на картинке-образце


Не думал, что это так принципиально. Глазомер у меня еще не настолько развит, но раз ты говоришь что больше, поставлю от балды mt-3px. Значит надо на картинке в условии задачи провести гайдлайны с точным указанием отступов.
Общая высота этого блока с надписями кстати зафиксирована или вычисляется на основании содержимого + паддинги? Начинаю склоняться ко второму варианту, убрал свойство height у figcaption.
Но ты такие вещи прописывай в условии. Мало того, что задания сложные, так я еще должен гадать, что хочет от меня заказчик. (Хотя наверное irl так и будет, только задачи будут примитивные, а вот ебанутость заказчиков на порядок выше)

Пощу еще раз обновленную ссылку, но фактически я только убрал лишние правила, убрал max-width для картинки, заменил селектор по атрибуту на другой селектор по атрибуту. Главную фишку - выравнивание абсолютно спозиционированного before по вертикали - пока не знаю как сделать, нужна подсказка.
http://jsfiddle.net/8386u62u/2/
#625 #587145
>>587138

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


Боюсь что добавив margin-top. Если бы шрифт в примечании был такого же размера как и основной, margin можно было бы указать в em, а так видимо придется в пикселях.

> Можно дописать класс? Или может быть взять селектор по alt-атрибуту?


Используй тот факт что картинка внутри figure

> Общая высота этого блока с надписями кстати зафиксирована или вычисляется на основании содержимого + паддинги? Начинаю склоняться ко второму варианту, убрал свойство height у figcaption.


Конечно на основании содержимого.

> Мало того, что задания сложные, так я еще должен гадать, что хочет от меня заказчик.


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

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

> http://jsfiddle.net/8386u62u/2/


По ссылке картинка размером 350px растягивается больше своего исходного размера. Такого быть не должно. Растровые картинки нельзя увеличивать.
#626 #587208
>>586984
Да ты же дебил конченный, не так ли? Я тебе говорю, что да на стороне майсокла есть поле с датой. Но его нельзя поставить если в том же поле стоит таймстемп. Т.е. тамстемп всегда возвращается в формате дейтайм. На это я и жалуюсь, что если эту дататайм нужно сравнить с просто датой, то все нужно переводить в тайм. Че совсем ебанутый конченный идиот или нравится таким прикидываться?
Ты постоянно такую хуету пишешь и тупишь, как будто вообще не хочешь понимать, о чем тебе талдычат. Не понимаю, как с такой тупостью, ты жопу подтирать научился, не то что кодинг освоил.
#627 #587219
>>587145
Добавил выравнивание при помощи margin-top, на глаз получилось 3px.
Сделал display:inline-block у figure, чтобы оно подстраивалось под ширину картинки.

>Используй тот факт что картинка внутри figure


А если на странице будут еще картинки с фигой? Может для них эти стили будут неприемлемы?
Ну ладно, это неважно, мы наверное в этом упражнении просто тренируемся с селекторами, так я бы просто поставил класс.

http://jsfiddle.net/8386u62u/6/

>>586978

> Шрифт великоват.


У меня неплохо (как мне кажется) получается переносить с psd, где четенько все расписано и по семейству шрифтов, и по межстрочному расстоянию, по всем отступам, цветам и т.д. На глаз не получается определить точные характеристики элементов. Не говоря уже о том, когда дизайн нужно придумать самому, тут совсем беда.
Дай подсказку по семейству шрифта, кстати. Потому что там дело не в размере, а в начертании. У шрифта на скриншоте в задании строчные буквы почти такие же по высоте как и заглавные, наверное 4/5, а в tahoma (или что там у меня взято с потолка) около 3/5.
Короче, дело не в размере, а в умении подбирать шрифт.

Насчет тени это я что-то протупил, я же знал про смещение у box-shadow.

> label { width: 64px }


> То есть если я поменяю текст то я должен вручную высчитать его длину и прописать в CSS файл.


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

>Что делать людям у которых нет мыши?


Мы не в каменном двадцатом веке, скоро полностью перейдем на тачпады. И набор текста с клавиатуры это дикость. Наверняка скоро доведут до вменяемого состояния систему голосового набора.
Проставил tabindex. В jsfiddle работает, во всяком случае на хромиуме.
Я только не понял, почему не работает на label, только на span.

http://jsfiddle.net/eh3j5c65/3/
#627 #587219
>>587145
Добавил выравнивание при помощи margin-top, на глаз получилось 3px.
Сделал display:inline-block у figure, чтобы оно подстраивалось под ширину картинки.

>Используй тот факт что картинка внутри figure


А если на странице будут еще картинки с фигой? Может для них эти стили будут неприемлемы?
Ну ладно, это неважно, мы наверное в этом упражнении просто тренируемся с селекторами, так я бы просто поставил класс.

http://jsfiddle.net/8386u62u/6/

>>586978

> Шрифт великоват.


У меня неплохо (как мне кажется) получается переносить с psd, где четенько все расписано и по семейству шрифтов, и по межстрочному расстоянию, по всем отступам, цветам и т.д. На глаз не получается определить точные характеристики элементов. Не говоря уже о том, когда дизайн нужно придумать самому, тут совсем беда.
Дай подсказку по семейству шрифта, кстати. Потому что там дело не в размере, а в начертании. У шрифта на скриншоте в задании строчные буквы почти такие же по высоте как и заглавные, наверное 4/5, а в tahoma (или что там у меня взято с потолка) около 3/5.
Короче, дело не в размере, а в умении подбирать шрифт.

Насчет тени это я что-то протупил, я же знал про смещение у box-shadow.

> label { width: 64px }


> То есть если я поменяю текст то я должен вручную высчитать его длину и прописать в CSS файл.


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

>Что делать людям у которых нет мыши?


Мы не в каменном двадцатом веке, скоро полностью перейдем на тачпады. И набор текста с клавиатуры это дикость. Наверняка скоро доведут до вменяемого состояния систему голосового набора.
Проставил tabindex. В jsfiddle работает, во всяком случае на хромиуме.
Я только не понял, почему не работает на label, только на span.

http://jsfiddle.net/eh3j5c65/3/
#628 #587289
>>586978
12 задание
Поправил селекторы.
Минут 10 психовал, почему не работает селектор #tab1:checked ~ .articles .tab1, #tab2:checked ~ .articles .tab2, {}
Оказалось забыл убрать скопированную запятую.
Да, всегда лучше набирать текст по новой, даже если он почти идентичный, иначе могут получиться вот такие глупые запоры.

> .tabs article { top: 153px;


> Нет, это не годится так как не хочется считать высоту при изменении верстки.


Действительно. Но тогда возникла сложность с позиционированием элементов.
Вот у нас есть элемент с неизвестной высотой, которая вычисляется на основании шрифта + паддинги. За ним идут еще несколько элементов, каждый из которых должен распологаться строго под вышеупомянутым элементом, то есть на одной и той же позиции, перекрывая друг друга. Можно было бы позиционировать относительно верхнего края родительского элемента, но нам неизвестна высота элемента меню, непонятно что писать в top:?px. Можно позиционировать относительно нижнего края родительского элемента, совпадающего с нижним краем элемента меню. Но нам неизвестна высота элемента article, непонятно что писать в bottom:-?px.
Короче, не придумал ничего лучше как обернуть элементы с article в отдельный див, от него и позиционировать.
Я знаю ты неодобрительно относишься к вкладыванию элементов в какие-то левые контейнеры, но тут не знаю другого выхода.

http://jsfiddle.net/wewnadt2/1/
#629 #587295
Посаны, намекните что надо сделать в задании W4.2 про рулетку. W4.1 сделал без проблем, но вот тут вообще не могу понять с чего начать и что за рулетка :C . (Ньюфаг /pr , который выбрал первым языком - php.)
#630 #587333
>>587295
Я всё понял, оказалось не так сложно
#631 #587365
>>587219

Шрифт стандартный и без засечек, значит либо Arial, либо Tahoma, либо Verdana. Но Verdana пузатая, это не она, остается тахома или ариал. Если ты смотришь под Линуксом, шрифт может рендериться немного по-другому.

Arial узнать не очень сложно, это основной шрифт в CSS фреймворке bootstrap и из-за этого его можно увидеть на многих сайтах.

Скорее всего тут ариал 14-й.

>Я только не понял, почему не работает на label,


Потому что label не может быть сфокусирован. Он же предназначен для передачи фокуса инпуту.
#632 #587521
Помогите пожалуйста совладать с регулярным выражением.
Хочу для вот такой строки "департамент закупок: 9×ме1, 3×ме2, 2×ме3, 2×ма1, руководитель ме2" написать регулярное выражение.
Вот, что я написал
[code]$regexp = '#департамент\\s[\\S]+:(\\s[0-9]{1,10}[\\sxх×*]?((м(а|е)|(а|и)н))[1-3]){1,10}\\sруководитель\\s((м(а|е)|(а|и)н))[0-9]#u';[/code]
И preg_match говорит, что не подходит. Помогите разобраться пожалуйста.
#633 #587638
Аноны, ньюфаг-кун репогртин ин, запилил прототип анимированной менюшки в HTML5/SASS.
Реквестирую критику, в особенности в плане целесообразности и оптимальности использования тегов.
#634 #587639
#635 #587707
Ну так вот господа, нам нужны конкретные задачи на деревья (красно-черные) и принципы SOLID KISS, чтобы лучше понимать ООП с конкретными задачами и примерами реализации. Желательно еще на каждый существующий паттерн по задаче и реализации с использованием абстрактных классов и интерфейсов.
#636 #587719
Год работал на CI. Когда пришел нихуя не знал Php,ситуация не сильно изменилась, лол. Хорошо его освоил, недавно контора развалилась и я пошел в свободное плавание. Почти никогда не писал на чистом php.
Собственно вопрос, где есть годные мануалы конкретно о ООП и патернах. И еще,куда дальше копать, CI сейчас не особо популярен, думаю уйти в Symphony/Yii/Lavarel.
#637 #587754
>>586921
Мне это надо сделать для одной единственной странички 1 раз в жизни. Вот зачем мне громоздить
<?php foreeach ($res as $line): ?>
<img src="<?php echo $line->img;?>>
<address><?php echo $address; ?>
<?php endforeach; ?>
Алсо я знал что именно до HTML доебётесь. Но так проще показать что именно я хочу.

>НЕ ИСПОЛЬЗУЙ mysqlli блять


И что мне использовать тогда? Только давайте без технологий которые знают полтора хипстера.
>>586985

>Ведь ты например можешь выбрать данные в массив и потом как угодно их выводить.


Ты только что предложил мне по каждому запросу выводить 50000 записей в массив, а потом с массивом работать? И при этом говоришь что МНЕ рано с базой работать? Садись 2.
#638 #587757
>>586921
Ты либо что-то скрываешь, либо у тебя на выходе получится

<img src="1.1.jpg 2.jpg1.jpg 2.jpg1.jpg 2.jpg1.jpg 2.jpg1.jpg 2.jpg1.jpg 2.jpg1.jpg 2.jpg1.jpg 2.jpg1.jpg 2.jpg1.jpg 2.jpg1.jpg 2.jpg1.jpg 2.jpg1.jpg 2.jpg1.jpg 2.jpg1.jpg 2.jpg1.jpg 2.jpg1.jpg 2.jpg1.jpg 2.jpg1.jpg 2.jpg1.jpg 2.jpg1.jpg 2.jpg1.jpg 2.jpg1.jpg 2.jpgjpg 2.jpg1.jpg 2.jpg1.jpg 2.jpg1.jpg 2.jpg1.jpg 2.jpg1.jpg 2.jpg1.jpg 2.jpg">
<address>adres1 adres2 adres3adres1 adadres1 adres2 adres3adres1 adres2 adres3adres1 adres2 adres3adres1 adres2 adres3adres1 adres2 adres3adres1 adres2 adres3adres1 adres2 adres3adres1 adres2 adres3adres1 adres2 adres3adres1 adres2 adres3adres1 adres2 adres3adres1 adres2 adres3res2 adres3adres1 adres2 adres3adres1 adres2 adres3adres1 adres2 adres3adres1 adres2 adres3adres1 adres2 adres3adres1 adres2 adres3adres1 adres2 adres3adres1 adres2 adres3
#639 #587758
>>587757
Лол, даже вакабы это за вайп посчитала. Что-то тут не так!
#640 #587760
>>586921
>>586985
Повторю задачу!
Есть База данных. В ней есть 94017 записей. Каждая строка базы данных содержит 94 ячейки всякой инфы (не я проэктировал это).
Задача простая. Взять 2 поля, вывести одно из них в HTML файлик. Я знаю как это сделать в Mysql, причём просто и быстро, но он уже устарел. А по Mysqli в интернете есть только статья на хабре и перепечатка различного хлама с PHP.ru.
Да, конечно же можно взять кучу всяких фрэймворков, нагородить библиотек, обмазаться другими СУБД, а потом запустить это всё в облако и вообще дохрена советов. Но у меня есть конкретная задача. Вывести эти записи постранично, в таблицу, по 4 колонки, по одной фотке в каждой. Это даже не изобретение велосипеда! Это ровно 4 строки нативного кода которые применяются к Mysql. Просто непонятно почему тут они неприменимы и приходится городить странные конструкции ради 4 строчной задачи.
А ещё мне непонятно почему вместо нормального совета - я получил пространные "Учи PHP". Ну спасибо посоны! Помогли!
#641 #587861
Вот интересно, в некоторых вакансиях пишут требования вроде:

- умение работать на PHP без фреймворков

или

- умение писать на JS, работать с DOM без jQuery

Ну ведь абсурд, согласитесь? Как можно изучить фреймворк не зная PHP или изучить jQUery не зная DOM? Это то же самое что требовать «умение пользоваться текстовым редактором».

Но раз требования пишут, значит причина есть. Люди с мышлением конвейерного рабочего не хотят изучать язык, они хотят посмотреть видеокурс и нажимать те же кнопки. Приходится для их отсева писать такие вот абсурдные требования.
#642 #587868
Господа, а с каких это пор джунопыхарей ебут деревьями в тестовых заданиях, м? И паттернами чуть-чуть.
#643 #587870
Посоны, подскажите.
У меня есть обычная версия сайта и мобильная.
Мобильная идет субдоменом.
Я порылся и нашел вот такую штуку http://mobiledetect.net/
Окей, с помощью неё я определяю, что пользователь зашел с телефона и перенаправляю на мобильную версию.
Но как мне быть, если пользователь находясь на мобильной версии, щелкнул на "перейти на полную версию" и хочет работать с ней? ведь мой класс снова определит что он с мобильного и кинет его обратно.
36 Кб, 812x187
#644 #587871
Анончик, прошу помощи, как никогда не просил.

Хочу написать несколько сайтов для портфолио, а потом пойду устраиваться джуниором. Я понимаю в PHP некоторые вещи, у меня MVC-структурированный код, но во время рабочего процесса такие пиздецы попадаются, что руки падают.

Ищу того, кто смог бы мне за тупые косяки пояснять в скайпе.
Это важно. Мой скайп: http://codepaste.net/jjaqfn

Сейчас проблема:
Цикл проходит полностью, элементы в массиве присваиваются не все и не так, как я этого хочу. Есть четыре записи в базе, пикрелейтед. Переписывается в массив только одна. Как видите, эко проходит четыре раза, но почему происходит так, я понять не могу. Словно проходит четыре итерации и записывает только первый элемент.

Сам код: http://codepaste.net/2m74eg
Дамп: http://codepaste.net/japakg
#645 #587872
>>587871
И да, что я вообще пытаюсь сделать: я хочу сделать вывод постов с выдачей года и месяца поста. Пытаюсь запихнуть в массивы, даже этого не получается. Пиздец.
#646 #587873
>>587870
При нажатии на "перейти на полную версию" ставь куку-настройку. При заходе на сайт проверяй содержимое/наличие этой куки.
#647 #587875
>>587873
Алсо, я сам дилетант. Это первое, что пришло в голову.
#648 #587876
>>587873
мне тоже пришло, но я не уверен, что у домена и субдомена общие куки
#649 #587902
>>587876
Так идентифицируется устройство на домене же, если я правильно тебя понял. И на нем же принимается решение о перенаправлении. Есть кука - оставляем, нет куки - редиректим.
#650 #587919
>>587902
а если пользователь позже еще раз зайдет на оригинальный домен, но он не нажимал кнопки "полная версия". его не станет редиректить.

Кажется я придумал, ссылка на полную версию будет вида domain.com?fromMobile=true
И в случае наличия переменной fromMobile равной true уже будет записываться кука.
#651 #587927
>>587870

Альтернативная идея: не проще сделать адаптивную верстку?

А вообще этот >>587919 вариант работоспособен.
#652 #587933
>>587927
нет, не проще
#653 #587942
>>587871
Все там работает. Ты просто не понимаешь КАК оно у тебя работает. Года и месяцы везде одинаковые, ты берешь их в качестве индексов массива. Соответсвенно, на каждой итерации в одну и туже ячейку массива записываются новые данные.
Рекомендую учебник ОПа и его задачи решать. Там будет что в портфолио положить.
И научить код на github выкладывать.
#654 #587962
>>587219

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

Также, ты не очень удачно выбрал tabIndex, ты сделал так что на странице твои кнопки будут первыми получать фокус, а мне кажется логичнее ставить 0 чтобы они не вырывались из общего списка элементов.

Насчет голосового набора, он имеет такие сложности:

1) создает шум в помещении, представь опенспейс где сидит 30 программистов с голосовым набором
2) сложно вводить всякие программистские символы
3) можно устать говорить весь день

> скоро полностью перейдем на тачпады


Э? Тачпад хуже мыши по моим ощущениям. Им удобно разве что страницу прокручивать.

Или ты имел в виду тач скрин? Не уверен что он имеет смысл например на ноутбуке, так как рука загораживает экран и тяжело постоянно ее держать на весу (и экран наверно пачкается со временем?). С другой стороны, вполне возможно что в будущем основным устройством станут планшеты и тогда твой прогноз сбудется - они и сейчас уже неплохо продаются.
#655 #587978
>>587289

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

Также, текст в первой и второй вкладках не выделяется, не работают размещенные в них ссылки.

Это ведь ты писал что задания слишком простые? Вот видишь, я же предупреждал что дальше сложность возрастет.

> Я знаю ты неодобрительно относишься к вкладыванию элементов


Если очень надо то можно. Тут не стоит проявлять фанатизма.

>>587521

Тут лучше разбивать в несколько этапов:

1) разбить строку по выражению

департамент XXX: YYY

2) разбить состав департамента на части по запятым:

9×ме1, 3×ме2, 2×ме3, 2×ма1, руководитель ме2

3) проанализировать каждую часть, она может иметь такой вид:

ме1
3xме1
руководитель ме1

Ну и я не уверен, что это нужно делать, можно в программе например сразу написать

$people = ['3 ме1', '2 ин2'];

То есть облегчить себе задачу.

Не забудь потом код показать - многие люди в задаче делают ошибки + я дам дополнительное задание про компанию Вектор.

> И preg_match говорит, что не подходит.


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

В твоей регулярке по моему не хватает запятых, которые есть в строке.

[\\S] то же самое что \\S
[0-9] то же самое что \\d

>>587638

Точки маленькие, в них неудобно наводить мышку. Почему бы не добавить к активной зоне невидимую область вокруг?

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

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

HTML плохой. Автор явно плохо знает теги, так как использует только один вид элементов - div. В то время как меню обычно делают списком и иногда заворачивают в nav.

Куча лишних элементов в HTML, я уверен что тут хватило бы ul + li. Врапперы лишь показывают что у тебя пробелы в CSS. Большинство из них можно смело выкинуть.

Тестировал ли ты меню в ИЕ, в каких версиях?

Попробуй сделать пункт меню, состоящий из нескольких слов? у меня их завернуло наверх.

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

Ну например смотри, класс wrapper у тебя описан как внутри sidenav так и отдельным блоком. То есть он может быть внутри sidenav, а может быть и не внутри? Это здорово запутывает. зачем так делать?

Зачем для sidenav указано width 10% непонятно. Почему именно 10?

Нелогично что синий кружок превращается в черный, а не синий квадрат.

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

В общем, мне кажется тебе бы стоило подучить HTML, CSS. Немного странно что ты изучил препроцессор CSS, но не разобрался толком в самом CSS.
#655 #587978
>>587289

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

Также, текст в первой и второй вкладках не выделяется, не работают размещенные в них ссылки.

Это ведь ты писал что задания слишком простые? Вот видишь, я же предупреждал что дальше сложность возрастет.

> Я знаю ты неодобрительно относишься к вкладыванию элементов


Если очень надо то можно. Тут не стоит проявлять фанатизма.

>>587521

Тут лучше разбивать в несколько этапов:

1) разбить строку по выражению

департамент XXX: YYY

2) разбить состав департамента на части по запятым:

9×ме1, 3×ме2, 2×ме3, 2×ма1, руководитель ме2

3) проанализировать каждую часть, она может иметь такой вид:

ме1
3xме1
руководитель ме1

Ну и я не уверен, что это нужно делать, можно в программе например сразу написать

$people = ['3 ме1', '2 ин2'];

То есть облегчить себе задачу.

Не забудь потом код показать - многие люди в задаче делают ошибки + я дам дополнительное задание про компанию Вектор.

> И preg_match говорит, что не подходит.


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

В твоей регулярке по моему не хватает запятых, которые есть в строке.

[\\S] то же самое что \\S
[0-9] то же самое что \\d

>>587638

Точки маленькие, в них неудобно наводить мышку. Почему бы не добавить к активной зоне невидимую область вокруг?

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

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

HTML плохой. Автор явно плохо знает теги, так как использует только один вид элементов - div. В то время как меню обычно делают списком и иногда заворачивают в nav.

Куча лишних элементов в HTML, я уверен что тут хватило бы ul + li. Врапперы лишь показывают что у тебя пробелы в CSS. Большинство из них можно смело выкинуть.

Тестировал ли ты меню в ИЕ, в каких версиях?

Попробуй сделать пункт меню, состоящий из нескольких слов? у меня их завернуло наверх.

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

Ну например смотри, класс wrapper у тебя описан как внутри sidenav так и отдельным блоком. То есть он может быть внутри sidenav, а может быть и не внутри? Это здорово запутывает. зачем так делать?

Зачем для sidenav указано width 10% непонятно. Почему именно 10?

Нелогично что синий кружок превращается в черный, а не синий квадрат.

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

В общем, мне кажется тебе бы стоило подучить HTML, CSS. Немного странно что ты изучил препроцессор CSS, но не разобрался толком в самом CSS.
#656 #587989
Надо ли вообще переменные объявлять в классе? Вот например, я могу объявлять, могу не объявлять - одинаково работает. Надо ли их объявлять только если они статичные или приватные?
#657 #587997
>>587989
Класс это не набор рандомных переменных и функций. У класса есть четкая зона ответственности, сущность которую он описывает.
Следовательно свойствами (переменными) класса нужно объявлять именно те характеристики, которые есть у этой сущности.
Какие-то локальные переменные, которые зачем-то понадобились в конкретном методе, не нужно делать свойствами всего класса.
Хотя если одна и та же переменная понадобится в разных методах, тогда пожалуй можно сделать ее приватным свойством.
Кроме того это удобно в целях инъекции зависимости.
Например объект соединения с базой данных не нужно создавать в каждом методе, где он понадобится. Тем более что могут понадобиться разные конфиги соединения, не прописывать же их прямо в методе, где создается подключение? В таком случае лучше передать объект соединения снаружи, через конструктор или сеттер, и положить его в приватную переменную.
#658 #587998
>>587719

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

Ну если тебе нужны именно паттерны отдельно, вот например урок про паттерны БД: https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md

Изучать можно Yii2, Symfony 2, для Юи можно решить задачу на тесты из ОП поста или например сделать сайт объявлений на нем.

>>587754

Что значит 1 раз в жизни? Ты сделаешь одну страничку и закончишь свою карьеру программиста?

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

> И что мне использовать тогда?


Я не знаю, я не против mysqli

Но ты должен ее использовать правильно, как написано в мануале , например провеярть наличие ошибок через if, а ты этого не делаешь. Почему? Статьи

http://php.net/manual/ru/mysqli.quickstart.statements.php
http://habrahabr.ru/post/141127/

Иначе что-то не заработает, а ты даже не узнаешь причины.

Также для выборки данных удобнее использовать http://php.net/manual/ru/mysqli.query.php

> Садись 2.


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

>>587757

Ты ошибаешься, не получится.

>>587760

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

По Mysqli есть документация на оф сайте: http://php.net/manual/ru/book.mysqli.php

разумеется ты должен понимать каждую строчку и запятую в твоем коде. Взять код из интернета и поменять там пару строк - это не правильный метод.

> Просто непонятно почему тут они неприменимы и приходится городить странные конструкции ради 4 строчной задачи.


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

> Да, конечно же можно взять кучу всяких фрэймворков, нагородить библиотек,


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

А вот вынести HTML шаблон отдельно по моему логично, почитай лучше статью: http://www.phpinfo.su/articles/practice/shablony_v_php.html

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

> А ещё мне непонятно почему вместо нормального совета - я получил пространные "Учи PHP".


Потому что ты скорее всего его плохо знаешь. Например, зачем ты пишешь 2 цикла когда можно оставить 1 цикл и просто увеличивать счетчик? Я тебе об этом вроде написал выше.

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

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


Тут я опять запутался. Ты на одну страницу хочешь вывести 90 000 картинок или постранично? Если постранично то картинок на странице немного и можно использовать массив. ты уже опиши свою задачу нормально и я напишу что именно тебе надо изучить.
#658 #587998
>>587719

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

Ну если тебе нужны именно паттерны отдельно, вот например урок про паттерны БД: https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md

Изучать можно Yii2, Symfony 2, для Юи можно решить задачу на тесты из ОП поста или например сделать сайт объявлений на нем.

>>587754

Что значит 1 раз в жизни? Ты сделаешь одну страничку и закончишь свою карьеру программиста?

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

> И что мне использовать тогда?


Я не знаю, я не против mysqli

Но ты должен ее использовать правильно, как написано в мануале , например провеярть наличие ошибок через if, а ты этого не делаешь. Почему? Статьи

http://php.net/manual/ru/mysqli.quickstart.statements.php
http://habrahabr.ru/post/141127/

Иначе что-то не заработает, а ты даже не узнаешь причины.

Также для выборки данных удобнее использовать http://php.net/manual/ru/mysqli.query.php

> Садись 2.


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

>>587757

Ты ошибаешься, не получится.

>>587760

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

По Mysqli есть документация на оф сайте: http://php.net/manual/ru/book.mysqli.php

разумеется ты должен понимать каждую строчку и запятую в твоем коде. Взять код из интернета и поменять там пару строк - это не правильный метод.

> Просто непонятно почему тут они неприменимы и приходится городить странные конструкции ради 4 строчной задачи.


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

> Да, конечно же можно взять кучу всяких фрэймворков, нагородить библиотек,


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

А вот вынести HTML шаблон отдельно по моему логично, почитай лучше статью: http://www.phpinfo.su/articles/practice/shablony_v_php.html

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

> А ещё мне непонятно почему вместо нормального совета - я получил пространные "Учи PHP".


Потому что ты скорее всего его плохо знаешь. Например, зачем ты пишешь 2 цикла когда можно оставить 1 цикл и просто увеличивать счетчик? Я тебе об этом вроде написал выше.

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

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


Тут я опять запутался. Ты на одну страницу хочешь вывести 90 000 картинок или постранично? Если постранично то картинок на странице немного и можно использовать массив. ты уже опиши свою задачу нормально и я напишу что именно тебе надо изучить.
#659 #588001
>>587978
Спасибо, добрый человек, за советы по парсингу строки.
#660 #588006
>>587871

Ты по моему не понимаешь как работают массивы в PHP, почитай про них в мануале http://php.net/manual/ru/language.types.array.php или учебнике из Оп поста.

Алсо не понимаю зачем ты сделал многомерный массив. Явно же по ошибке?

Ну и у тебя еще минимум несколько ошибок:

> $post[$array_key]['date_added']


Не надо копипастить это выражение по несколько раз

надо давать переменным понятные имена, array_key это имя которое не значит ровным счетом ничего.

> unset($post[$array_key]);


Это бессмысленно так как foreach делает копию массива перед циклом.

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

Не представляю как ты пишешь MVC приложения не зная PHP.

> Хочу написать несколько сайтов для портфолио,


Я считаю рано.
#661 #588008
>>587989

Надо. Как иначе понять с первого взгляда какие у тебя есть поля? Как к ним добавлять комментарии?

То что они добавляются сами, это неправильно, лучше бы если выбрасывалась ошибка. Иначе как обнаружить что ты опечатался?
#662 #588028
Как в фотошопе выделить сразу несколько слоёв кликая мышкой по ним? Чтобы потом их можно было скопировать и вставить в новый файл? Какую клавишу надо зажимать?
#663 #588053
>>578124 (OP)
Самый адекватный, теплый и ламповый тред в /pr/
В остальных чувствую себя как в /b

ОП - молодец.

мимоджавист
#664 #588058
>>585923
https://github.com/someApprentice/Cat-and-Mouse

>>586985

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


>Можно сделать 2 фактора с разным весом: расстояние до ближайшей кошки (более важное) и например число кошек в определенном радиусе (менее важное) или например сумма 1/d1 + 1/d2 ... 1/dN где d1..dN расстояние до кошки. Эта сумма характеризует как число кошек, так и расстояние до них, причем близкие кошки вносят в нее больший вклад. Это кстати напоминает формулу расчета потециала электрического поля от нескольких зарядов.


Сори, я не успел это прочесть и уже сделал по своему :( Интересный кстати подход, может быть сделаю это позже.

Вроде все понятно пока.

Спасибо.
#665 #588070
>>587978

>Там есть один баг в анимации: скрытие и появление вкладок сделано так, что при переключении они мигают, так как сквозь них просвечивает фон.


А я не знаю, что с этим можно сделать. Суть проблемы в следующем: при клике по табу сначала мгновенно сбрасывается opacity у бывшего только что активным слоя, и медленно (в течение 0.5s) начинает набирать непрозрачность новый слой.
Казалось бы, решением будет анимировать не только переход прозрачности от 0 до 1, но и наборот, от 1 до 0.
Но попытка прописать transition в блоке, где opacity выставляется в 0, ничего не дала. Не понимаю почему.

Можно было бы выставить бекграунд у родительского дива, совпадающий с фоном article. Но я не могу задать ему высоту, 0 у него высота.

На счет того что текст не выделяется и ссылки некликабельны, это конечно мой недочет. Прозрачность слои меняют, а вот порядок - нет. Естественно не получится выделить текст в слое, который находится под другим, хоть и прозрачным.
z-index решил проблему.
http://jsfiddle.net/wewnadt2/2/

Вообще я очень плохо понимаю эту тягу к анимации, сам ее терпеть не могу. Очень отвлекает и раздражает, когда все дергается, прыгает, куда-то медленно уезжает.
Лично мне было бы удобнее, если бы анимации не было вообще. В случае с табами они должны переключаться мгновенно, тем более скучно ждать, когда оно там уже закончит свое плавание. Больше 0.5s ждать это вообще смертная мука.
Я думаю, это намеренная тенденция с целью задержать пользователей как можно дольше на странице, прямо как в онлайн-играх.

В макете у меня тоже проблема с анимацией. Не с анимацией, а с пониманием задания.
>>586005

>- сделай скрытие красивым и анимированным с помощью CSS3.


Что такое "красивое скрытие"? Опиши мне поведение, которое я должен реализовать, я сделаю.
Ну нет у меня фантазии и вкуса, чтобы придумать "красивую" анимацию.
Попробовал в галерее портфолио анимировать margin-left и opacity, чтобы картинки медленно съезжали вверх и влево, но выглядит это крайне уродливо.
http://nsdvw.github.io/template.html#portfolio
В общем, мне нужно четкое задание, описание поведения, сам я не в состоянии проявить фантазию. Я программист (воннаби), а не художник или дизайнер.

>>587962
Я говорил не о программистах, а о популяризации веба среди простых людей. Очевидно им проще пользоваться голосом, чем набирать двумя пальцами со скоростью 2 символа в секунду.
Тачскрин, да. Конечно планшеты. Ведь большинство людей пользуется компьютером только ради интернет-серфинга и скайпа.
Пеки уже почти вымерли среди юзеров. Очередь за ноутбуками. Ноутбуки еще живут только из-за офисных приложений и компьютерных игр.
#665 #588070
>>587978

>Там есть один баг в анимации: скрытие и появление вкладок сделано так, что при переключении они мигают, так как сквозь них просвечивает фон.


А я не знаю, что с этим можно сделать. Суть проблемы в следующем: при клике по табу сначала мгновенно сбрасывается opacity у бывшего только что активным слоя, и медленно (в течение 0.5s) начинает набирать непрозрачность новый слой.
Казалось бы, решением будет анимировать не только переход прозрачности от 0 до 1, но и наборот, от 1 до 0.
Но попытка прописать transition в блоке, где opacity выставляется в 0, ничего не дала. Не понимаю почему.

Можно было бы выставить бекграунд у родительского дива, совпадающий с фоном article. Но я не могу задать ему высоту, 0 у него высота.

На счет того что текст не выделяется и ссылки некликабельны, это конечно мой недочет. Прозрачность слои меняют, а вот порядок - нет. Естественно не получится выделить текст в слое, который находится под другим, хоть и прозрачным.
z-index решил проблему.
http://jsfiddle.net/wewnadt2/2/

Вообще я очень плохо понимаю эту тягу к анимации, сам ее терпеть не могу. Очень отвлекает и раздражает, когда все дергается, прыгает, куда-то медленно уезжает.
Лично мне было бы удобнее, если бы анимации не было вообще. В случае с табами они должны переключаться мгновенно, тем более скучно ждать, когда оно там уже закончит свое плавание. Больше 0.5s ждать это вообще смертная мука.
Я думаю, это намеренная тенденция с целью задержать пользователей как можно дольше на странице, прямо как в онлайн-играх.

В макете у меня тоже проблема с анимацией. Не с анимацией, а с пониманием задания.
>>586005

>- сделай скрытие красивым и анимированным с помощью CSS3.


Что такое "красивое скрытие"? Опиши мне поведение, которое я должен реализовать, я сделаю.
Ну нет у меня фантазии и вкуса, чтобы придумать "красивую" анимацию.
Попробовал в галерее портфолио анимировать margin-left и opacity, чтобы картинки медленно съезжали вверх и влево, но выглядит это крайне уродливо.
http://nsdvw.github.io/template.html#portfolio
В общем, мне нужно четкое задание, описание поведения, сам я не в состоянии проявить фантазию. Я программист (воннаби), а не художник или дизайнер.

>>587962
Я говорил не о программистах, а о популяризации веба среди простых людей. Очевидно им проще пользоваться голосом, чем набирать двумя пальцами со скоростью 2 символа в секунду.
Тачскрин, да. Конечно планшеты. Ведь большинство людей пользуется компьютером только ради интернет-серфинга и скайпа.
Пеки уже почти вымерли среди юзеров. Очередь за ноутбуками. Ноутбуки еще живут только из-за офисных приложений и компьютерных игр.
35 Кб, 437x373
#666 #588097
Не могу создать ссылку на скайп. Появляется ущербный алерт пикрелейтед. Или так и должно быть?
Мне кажется, клевета про злоумышленников, атакующих сайт, может вспугнуть клиентов, за такое пизды надо давать разработчикам браузеров.

Ссылка вида <a href="123456?call">123456</a>
#667 #588107
>>588070

> Но попытка прописать transition в блоке, где opacity выставляется в 0, ничего не дала. Не понимаю почему.


Может ты скрываешь блок? Анимация не работает если блок меняет состояние display на none. Возможно также смена z-index влияет, не знаю.

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


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

Ну и не знаю, можно ли это туда же отнести. В плеерах (вконтакте тоже по моему) при нажатии на паузу звук не отключается резко, а
плавно уменьшается громкость до нуля - иначе получается что-то вроде щелчка.

> В случае с табами они должны переключаться мгновенно, тем более скучно ждать, когда оно там уже закончит свое плавание. Больше 0.5s ждать это вообще смертная мука.


Возможно что на табах она не очень и нужна, согласен.

> Что такое "красивое скрытие"? Опиши мне поведение, которое я должен реализовать, я сделаю.


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

> Очевидно им проще пользоваться голосом, чем набирать двумя пальцами со скоростью 2 символа в секунду.


Да не уверен. В метро например набирать текст пальцами удобнее чем если все будут что-то надиктовывать (там и так уровень шума высокий).

> Пеки уже почти вымерли среди юзеров. Очередь за ноутбуками.


Поживем-увидим.

z-index ты неудачно поставил: http://jsfiddle.net/vb61s4o8/1/ - он перекрывает все остальные элементы. Изучи-ка z-index stacking и сделай так чтобы весь блок с вкладками на странице был в слое с z-index = 0 как и обычный контент.
#668 #588112
>>588097

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

https://developer.apple.com/library/ios/featuredarticles/iPhoneURLScheme_Reference/PhoneLinks/PhoneLinks.html
https://tools.ietf.org/html/rfc3966
https://developers.google.com/web/fundamentals/native-hardware/click-to-call/
http://www.mobilexweb.com/blog/click-to-call-links-mobile-browsers
#669 #588212
Привет, есть калькулятор:
http://azbukamam.ru/kalendar-vychislenie-daty-rodov/
Но если сделать запрос, то получаем ссылки типа:
http://azbukamam.ru/kalendar-vychislenie-daty-rodov/?mydate=10-11-2015
В такую ссылку можно передать вредоносный код.
Использовал регулярные выражения для пол с вводом даты:
<input id="calendar" name="mydate" type="text" pattern="([0-9]{2})-([0-9]{2})-([0-9]{4})" value="<?=$datePolVal;?>" onfocus="this.select();lcs(this)"
onclick="event.cancelBubble=true;this.select();lcs(this)">
Т.е. через поле нельзя передать всякой дряни, но через адресную строку можно :(
Например так:
http://azbukamam.ru/kalendar-vychislenie-daty-rodov/?mydate=%22%3E%3Cb%3E
(работает в FF).
Буду рад помощи.
#670 #588214
#671 #588223
>>588214
Спасибо. Раньше тоже спец. символы вроде убирал, но видимо натупил где-то. Теперь все ок наконец.
92 Кб, 1365x427
55 Кб, 1125x467
54 Кб, 732x381
#672 #588228
>>588107
Мы тут где-то выше пытались разобраться, почему долго грузится статика >>580487
грешили на mod_rewrite, что он перекидывает на yii, потом на ассет менеджер фреймворка.

Теперь делаю этот макет, и то же самое: несчастные 485 байт стилей отдаются 546ms. Первый скриншот.
Что самое интересное, по отдельности каждый ресурс отдается относительно быстро. Второй скриншот.

ab вообще гоняет за 2-3 милисекунды, третий скриншот.

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

Короче я наверное не на те цифры смотрю, сервер все нормально отдает, это браузер медленно отрисовывает. Или нет? Что конкретно означает число в колонке time? Время ожидания ответа от сервера или сюда входит время потраченного дохлым браузером на разбор и отрисовку полученного контента?
Что обозначают вот эти серые/зеленые полосочки в веб-инспекторе?
#673 #588231
>>588006
Биолся в одни ворота и не указал айди в качестве следующего индекса массива. Через $array_key привык писать, чтобы видеть что происходит. Сейчас же убрал эту часть и переписал.

Спасибо за ваш пост.
#674 #588250
>>588228

Наведи мышь на полоску со временем в инспекторе
#675 #588252
анон, можно ли складывать значения массива вот так
$arr[1]+$arr[2]?
#676 #588254
>>588252
Почему нет?
#677 #588259
>>588254
да у меня не получалось, оказалось, что я переменную массива криво записал. извините за наитупейший вопрос
#678 #588265
>>588250
И что? Появятся новые циферки и буковки, которые я не понимаю. Если б я мог сам нагуглить или понять написанное в документации, то наверное не спрашивал бы.
Queueing 1.996 ms
Stalled 270.603 ms
Request sent 1.257 ms
Waiting (TTFB) 1.288 ms
Content Download 46.104 ms

Смотрю доки хрома
https://developer.chrome.com/devtools/docs/network#resource-network-timing

> Stalled/Blocking


> Time the request spent waiting before it could be sent. This time is inclusive of any time spent in proxy negotiation. Additionally, this time will include when the browser is waiting for an already established connection to become available for re-use, obeying Chrome's maximum six TCP connection per origin rule.


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

Короче, я не понял, что такое "stalled" и чем вызвано такое большое время в этом поле.
#679 #588322
Как делать хайлоад сайты и юнит тесты?
14 Кб, 174x531
#680 #588325
Короч нужно запилить на странице продукта раздел "похожие продукты". А эти продукты должны указываться из админки. И чет я ничерта не могу представить, как это сделать. Связь один ко многим? Как сие пилится в yii и какой столб делать для нее в базе данных?
#681 #588329
>>588325
блять, или many to many, у меня уже крыша едет
#682 #588340
>>588053
Сасай мой хуй. Надеюсь, теперь ты чувствуешь себя как дома в /b.
#683 #588344
>>588325
Добавляешь колонку и пишешь в нее айди того продукта, с которым они схожи. При выводе берешь айди продукта и по нему ищешь в этой дополнительной колонке и выводишь похожие. я так думаю.
#685 #588363
>>588357
Давай, кинь мне еще учебник по информатике за 5 класс, где написано как компьютер включать.
#687 #588403
>>588265

Может ты не знал про такую фичу.

> что-то там связанное с прокси


Некоторые люди просматривают интернет через прокси-сервер, речь о них. Почитать: https://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%BE%D0%BA%D1%81%D0%B8-%D1%81%D0%B5%D1%80%D0%B2%D0%B5%D1%80

Тебя это вряд ли касается.

> Он что, под каждую картинку открывает новое соединение?


Тебе бы надо изучить HTTP протокол. Да, по умолчанию для получения каждого ресурса открывается новое соединение, отправляется запрос, получается ответ, соединение закрывается.

Но есть как минимум 2 варианта для повторного использования:

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

Разумеется браузер при возможности открывает несколько соединений и скачивает несколько ресурсов параллельно - в надежде загрузить канал как можно сильнее.

вот тут что-то про это написано: http://webo.in/articles/habrahabr/39-out-of-connections-limits/
http://webo.in/articles/habrahabr/34-streaming-chunking-finding-end/

стандарт HTTP и браузеры вводят ограничение на число одновременно открытых соединений с сервером - для того чтобы защитить тот от перегрузки.

Кстати, если посмотреть на диаграмму загрузки, там по моему как раз 6 параллельных линий.

Кстати, чтобы загружать в 6 потоков, в Апаче тоже должно быть разрешено создавать столько процессов-рабочих (по моему опция MaxChildren), так как один процесс там обрабатвает одно соединение.

Наконец, это еще не все. Еще нас ограничивает принцип разбора страницы. Сначала браузер загружает HTML файл, поточно парсит его и как только встречает ссылку на какой-то ресурс (скрипты, стили, картинки), добавляет его в список загрузки (и загружает если предел соединений не превышен). Однако, если браузер встретит JS скрипт то он должен сначала выполнить его, прежде чем анализировать HTML дальше (так как скрипт может внести изменения в поток данных через document.write). При этом если скрипт не в теле документа, а по ссылке, браузер должен сначала скачать его чтобы выполнить.

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

Возвращаясь к цифрам.

- Queuing скорее всего это время от добавления ресурса в очередь до момента когда браузер решает его загрузить
- Stalled это время в течение которого пришлось ждать возможности начать загрузку ресурса из-за каких-то ограничений (например открыто уже 6 соединений и новое открыть нельзя) или блокировок

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

Request sent - время на установку соединения и отправку запроса
TTFB - время между окончанием отправки запроса и получением первого байта ответа от сервера (для PHP скриптов обычно это время загрузки и выполнения скрипта до момента вывода)
Content Download - время получения ответа от первого байта до последнего

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

Обрати внимание на график: браузер загружает HTML файл, затем где-то 300-400 мс паузы прежде чем он начинает в 6 потоков скачивать другие ресурсы. Почему так? Что происходило эти 300 мс?

Если ты запускаешь браузер на слабом железе и есть возможность попробовать открыть сайт с более мощного компьютера, стоит попробовать и сравнить. может быть это просто Хром так долго пережевывал и разбирал HTML.

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

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

Внутренние инструменты Хрома спрятаны за ссылкой chrome://chrome-urls/

Во-первых, там есть chrome://net-internals/#capture который собирает события работы с сетью и может дать чуть больше информации. Возможно, ты сможешь в нем разобарться. То есть ты открываешь вкладку capture, в другой вкладке загружаешь сайт, после чего смотришь накопившиеся события.

Соответственно найти там событие отвечающее за загрузку CSS файла и посмотри подробности.

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

он находится вроде бы тут: chrome://tracing/ (он крутой) включаешь запись, загружаешь страницу, останавливаешь и смотришь результат. На нем мы должны увидеть что браузер делал после загрузки HTML файла, что он делал во время загрузки CSS файла.

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

В общем попробуй проверить разные гипотезы которые я там выше написал и посмотрим.
#687 #588403
>>588265

Может ты не знал про такую фичу.

> что-то там связанное с прокси


Некоторые люди просматривают интернет через прокси-сервер, речь о них. Почитать: https://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%BE%D0%BA%D1%81%D0%B8-%D1%81%D0%B5%D1%80%D0%B2%D0%B5%D1%80

Тебя это вряд ли касается.

> Он что, под каждую картинку открывает новое соединение?


Тебе бы надо изучить HTTP протокол. Да, по умолчанию для получения каждого ресурса открывается новое соединение, отправляется запрос, получается ответ, соединение закрывается.

Но есть как минимум 2 варианта для повторного использования:

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

Разумеется браузер при возможности открывает несколько соединений и скачивает несколько ресурсов параллельно - в надежде загрузить канал как можно сильнее.

вот тут что-то про это написано: http://webo.in/articles/habrahabr/39-out-of-connections-limits/
http://webo.in/articles/habrahabr/34-streaming-chunking-finding-end/

стандарт HTTP и браузеры вводят ограничение на число одновременно открытых соединений с сервером - для того чтобы защитить тот от перегрузки.

Кстати, если посмотреть на диаграмму загрузки, там по моему как раз 6 параллельных линий.

Кстати, чтобы загружать в 6 потоков, в Апаче тоже должно быть разрешено создавать столько процессов-рабочих (по моему опция MaxChildren), так как один процесс там обрабатвает одно соединение.

Наконец, это еще не все. Еще нас ограничивает принцип разбора страницы. Сначала браузер загружает HTML файл, поточно парсит его и как только встречает ссылку на какой-то ресурс (скрипты, стили, картинки), добавляет его в список загрузки (и загружает если предел соединений не превышен). Однако, если браузер встретит JS скрипт то он должен сначала выполнить его, прежде чем анализировать HTML дальше (так как скрипт может внести изменения в поток данных через document.write). При этом если скрипт не в теле документа, а по ссылке, браузер должен сначала скачать его чтобы выполнить.

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

Возвращаясь к цифрам.

- Queuing скорее всего это время от добавления ресурса в очередь до момента когда браузер решает его загрузить
- Stalled это время в течение которого пришлось ждать возможности начать загрузку ресурса из-за каких-то ограничений (например открыто уже 6 соединений и новое открыть нельзя) или блокировок

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

Request sent - время на установку соединения и отправку запроса
TTFB - время между окончанием отправки запроса и получением первого байта ответа от сервера (для PHP скриптов обычно это время загрузки и выполнения скрипта до момента вывода)
Content Download - время получения ответа от первого байта до последнего

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

Обрати внимание на график: браузер загружает HTML файл, затем где-то 300-400 мс паузы прежде чем он начинает в 6 потоков скачивать другие ресурсы. Почему так? Что происходило эти 300 мс?

Если ты запускаешь браузер на слабом железе и есть возможность попробовать открыть сайт с более мощного компьютера, стоит попробовать и сравнить. может быть это просто Хром так долго пережевывал и разбирал HTML.

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

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

Внутренние инструменты Хрома спрятаны за ссылкой chrome://chrome-urls/

Во-первых, там есть chrome://net-internals/#capture который собирает события работы с сетью и может дать чуть больше информации. Возможно, ты сможешь в нем разобарться. То есть ты открываешь вкладку capture, в другой вкладке загружаешь сайт, после чего смотришь накопившиеся события.

Соответственно найти там событие отвечающее за загрузку CSS файла и посмотри подробности.

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

он находится вроде бы тут: chrome://tracing/ (он крутой) включаешь запись, загружаешь страницу, останавливаешь и смотришь результат. На нем мы должны увидеть что браузер делал после загрузки HTML файла, что он делал во время загрузки CSS файла.

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

В общем попробуй проверить разные гипотезы которые я там выше написал и посмотрим.
#688 #588424
>>587754
PDO используй, вот
#689 #588425
>>587757
Получится на выходе.
<img src="igm1">
<adress>тыхуй</adress>
<img src="img2">
<adress>тыхуй2</adress>

пример, абстрактный
2 Кб, 259x194
#690 #588434
Пора взглянуть правде в лицо - за каждую джуниорскую позицию идет грызня не на жизнь, а на смерть.

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

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

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

Пора искать новые пути. Может быть, 3D?
#691 #588446
>>588434
Как искал работу - нашел за неделю.
Две позиции, на одну меня взяли.

Оп-кун, трабл, не могу раздуплить, что делаю не так
$saveQuery = $this->queryBilder
->insert('shop_products')
->values(array(
'name' => '?',
'description' => '?',
'price' => '?',
'image' => '?',
))
->setParameter(0, $data['name'])
->setParameter(1, $data['description'])
->setParameter(2, number_format($data['price'], 2))
->setParameter(3, $data['img']);

$this->db->query($saveQuery);

Выдает еррор, не подставляет данные с помощью setParameter, что за хрень, объясните, позя
#692 #588447
>>588446

что за ошибка? Что это за query builder? Самописное что-то?

И тут по моему именованные плейсхолдеры подошли бы лучше.
#693 #588449
>>588446

Алсо почему цену форматировнную в базе хранишь?
#694 #588451
>>588446

А, doctrine dbal.
#695 #588452
>>587998

> Что значит 1 раз в жизни? Ты сделаешь одну страничку и закончишь свою карьеру программиста?


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

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


Никто не будет. делаю для себя только.

>Но ты должен ее использовать правильно, как написано в мануале , например провеярть наличие ошибок через if, а ты этого не делаешь. Почему? Статьи


Крутой комментарий, вот только ты моего кода не видел совсем. Откуда такие выводы?
http://php.net/manual/ru/mysqli.quickstart.statements.php
http://habrahabr.ru/post/141127/
Все эти мануалы прочитаны и перечитаны вдоль и поперёк.
По ним и делал.

>Также для выборки данных удобнее использовать http://php.net/manual/ru/mysqli.query.php


Ну круто. Только я его уже использую.

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


Чел. У меня 1 php файлик который должен сделать ровно 1 функцию! ЗАЧЕМ МНЕ РАДИ НЕГО ПИСАТЬ 100500 ФУНКЦИЙ и 100500 файликов КОТОРЫЕ В ИТОГЕ БУДУТ ПРИМЕНЕНЫ 1 РАЗ? Я понимаю серьёзные проекты, улучшение производительности построение серьёзных систем с распределённой нагрузкой. Но я не проектирую датацентр. Мне нужно табличку получить здесь и сейчас.
В данном конкретном случае не нужно. Задача была сформулировано чётко и ясно, но в итоге всё свелось к каким-то теоретическим изысканиям про основы субд...
#696 #588454
>>588446

Также ты можешь посмотреть какой запрос получается.
#697 #588456
>>588452

Тебе написали (2 раза) 2 варианта:

1) выбирать строки в массив и работать с ним
2) считать ячейки в цикле while а не в отдельном цикле.

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

Это был совет по делу. Дальше бесполезный флуд.

> Ну круто. Только я его уже использую.


В коде >>586868 ее нет иначе бы я это не написал.

> Все эти мануалы прочитаны и перечитаны вдоль и поперёк.


> По ним и делал.


Судя по коду >>586868 ты их читал невинимательно. У тебя ифа нет. Иначе бы я это не написал.

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


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

> вот только ты моего кода не видел совсем.


Видел в этом посте >>586868

> ЗАЧЕМ МНЕ РАДИ НЕГО ПИСАТЬ 100500 ФУНКЦИЙ


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

И где-то выше ты или не ты, кто-то писал что он хочет сделать портфолио и устроиться на работу. Если это ты то опять же я считаю что сначала надо получше изучить язык программирования, а потом делать портфолио.
#697 #588456
>>588452

Тебе написали (2 раза) 2 варианта:

1) выбирать строки в массив и работать с ним
2) считать ячейки в цикле while а не в отдельном цикле.

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

Это был совет по делу. Дальше бесполезный флуд.

> Ну круто. Только я его уже использую.


В коде >>586868 ее нет иначе бы я это не написал.

> Все эти мануалы прочитаны и перечитаны вдоль и поперёк.


> По ним и делал.


Судя по коду >>586868 ты их читал невинимательно. У тебя ифа нет. Иначе бы я это не написал.

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


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

> вот только ты моего кода не видел совсем.


Видел в этом посте >>586868

> ЗАЧЕМ МНЕ РАДИ НЕГО ПИСАТЬ 100500 ФУНКЦИЙ


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

И где-то выше ты или не ты, кто-то писал что он хочет сделать портфолио и устроиться на работу. Если это ты то опять же я считаю что сначала надо получше изучить язык программирования, а потом делать портфолио.
#698 #588458
>>588452

Ты ведь просто не умеешь делать код с шаблонами и функциями, это очевидно, если бы ты умел ты бы не стал городить HTML теги в кавычках, потому что это неудобно.
#699 #588459
>>587998

>Я тебе посоветовал разобраться с работой с циклами так как вижу из твоих ответов что ты в них не разбираешься.


Поэтому я и написал сюда. Чтобы совет получить. Хотя вопрос был вовсе не в циклах. А в Mysqli.

>а потом понадобится еще что-то добавить, а потом еще и твой маленький монстр превратится в большого монстра.


Пока задача ровно одна! Появятся новые - буду думать о новых. Но за последние 5 лет ничего нового не появлялось.

>А вот вынести HTML шаблон отдельно по моему логично, почитай лучше статью:



Нелогично если у тебя всего 1 php файлик. Логично только если у тебя форум на овер 1000 страниц.

>Например, зачем ты пишешь 2 цикла когда можно оставить 1 цикл и просто увеличивать счетчик?


Вопрос то про MYsqli! Причём тут вообще счётчик? Хотя у бы хотел узнать как это можно сделать 1 циклом.

>Тут я опять запутался. Ты на одну страницу хочешь вывести 90 000 картинок или постранично?


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

>ты уже опиши свою задачу нормально и я напишу что именно тебе надо изучить.


Окай.
Мне нужно разместить полученные с помощью запроса данные в таблицу.
таблица имеет 4 столбца.
Первый столбец первой строки - запись 1. Второй столбец первой строки - запись 2. Третий столбец третьей строки - запись 3. Четвёртый столбец четвёртой строки - запись 4
Первый столбец второй строки - запись 5.
Ну и так далее!
Все остальные вопросы наподобие "Как не выбрать все записи из таблицы\как не вывести на страницу 90000 записей" - я знаю как решать.
У меня конкретный вопрос, как осуществить именно такой вывод применяя MYSQLi?
#700 #588460
>>588452

Более того если это твой пост >>587757 то ты демонстрируешь что не понимаешь принцип работы циклов, потому я выше и посоветовал тебе изучить их получше. Логично, если человек что-то знает плохо, посоветовать ему это изучить?
#701 #588462
>>588456

>1) выбирать строки в массив и работать с ним


>2) считать ячейки в цикле while а не в отдельном цикле.


Я пытаюсь хот твоих мыслей. Ну будет у меня подсчитано количество ячеек(хотя это вообще не циклом можно сделать), и что?
#702 #588463
>>588456

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


Не я. Алсо я в курсе что за такое портфолио меня никуда не возьмут.
#703 #588466
>>588459

> Хотя у бы хотел узнать как это можно сделать 1 циклом.


Можно выводить в цикле по 1 ячейке, а каждый 4-й шаг выводить пару /tr + tr. Хотя это не очень-то удобно.

> Вопрос то про MYsqli!


> У меня конкретный вопрос, как осуществить именно такой вывод применяя MYSQLi?


Мне кажется что ты что-то не понимаешь. Вот смотри, у тебя есть функция которая каждый раз возвращает новую строку из базы. При чем тут MySQL? Если мы уберем mysqli и заменим ее например на функцию которая генерирует данные случайно, что поменяется в программе? Или функцию которая возвращает числа от 1 до 100. Ровно ничего. Чтобы вывести числа таблицей нужен ровно тот же самый код что и вывести из базы.

Следовательно твой вопрос не про mysqli. Mysqli всего лишь делает запрос и возвращает результат построчно. твой вопрос про язык php: если есть функция, как мне вывести ее результат в виде таблицы.

Твой вопрос не про mysqli, он про язык php. Как сделать цикл который бы выводил данные в таблицу по 4 ячейки в строке.

Потому я и пытаюсь тебе объяснить что mysqli тут вообще не при чем.

Я даже могу это доказать, убрав из задачи баз данных: представь что у тебя есть функция getNumber() которая при первом вызове возвращает 1, при втором 2,... при сотом 100, а при сто первом и дальше - ноль. Можешь ли ты вывести числа которые она возвращает в виде таблицы из 4 колонок? Если у тебя сложности только с mysqli а язык ты знаешь хорошо, ты ведь легко ее решишь? А решив ты можешь заменить getNumber() на fetch_row и получить решение своей задачи.

Потому твой вопрос должен звучать так: как вывести массив данных, возвращаемый функцией по одному за раз, в виде таблицы из 4 колонок?

Очевидно нужно использовать какой-то цикл, напрмиер:

- выводить записи циклом, который будет считать на каждом шаге в какой он по счету ячейке и выводить нужные теги.
- или, выбрать все данные в массив, сделать 2 вложенных цикла для строк и колонок таблицы, в них вывести данные из массива в ячейки таблицы
#704 #588467
>>588459

Серьезно, давай упростим задачу. Дан массив чисел, например [1, 3, 5, 7, 9, 13, 15, 19, 20]. Выведи его в виде HTML-таблицы в 4 колонки.

Если ты сделаешь эту задачу, ты на 80% решишь свою задачу про фотографии. Как видишь в этой задаче нет базы данных и разбираться в mysqli не требуется.
#705 #588468
>>588467
Чел, я уже решил эту задачу! Спасибо.
Только у меня Mysql. А мне интересно, как сделать это в Mysqli. Но инфы именно по такой расфасовке данных у меня нет. Пока нет! Но я обязательно найду.
#706 #588469
>>588466
Ладно, спасибо что вытерпел меня анон. Постараюсь разобраться дальше что к чему.
#707 #588470
>>588468

По моему ты меня троллишь. Переход от библиотеки mysql на mysqli просто заключается в замене функций например mysql_query на $mysqli->query(), сам алгоритм и код точно такой же.
#708 #588473
>>588469
Он вообще святой человек. Порой не понимаю как кто-то кого-то вообще здесь терпит. Спасибо, что вы существуете, ребята.
#709 #588483
>>586868
Тебе вместо for надо
foreach ($row as $jopeg)
и дальше уже $jopeg юзать.
что-то типа echo"\t\t<td>$jopeg </td>\n";
#710 #588484
>>588468
Я тупой просто.
#711 #588515
#712 #588860
Сап двощь, есть одна тян, зовут ее Битрикс и она делает мне больно.
В общем суть в чем, написал я свой модуль комментариев, но не пойму с чего коммент проходит только если предварительно очистить кеш через панель и сделать ссылку вида:
http://site.ru/lavka/antikvariat/udolfskie-tayny/?clear_cache=Y
Делал эксперимент - выходил с сайта (разавторизировался или как там это сказать) и добавлял в конец URL ?clear_cache=Y, но не помогло - комментарий не отправляется.
Вот собственно код (защиты и пр. еще нет, но это и не интересует, интересует в чем проблема - буду очень благодарен).
<?\t$cnstComments = 0;
\t\t\t\t\t\tif($USER->GetLogin()){
\t\t\t\t\t\t\t$name = $USER->GetLogin();
\t\t\t\t\t\t}
\t\t\t\t\t\telse {
\t\t\t\t\t\t\t$name = $_POST['name'];
\t\t\t\t\t\t}\t\t\t\t
\t\t\t\t\t\t$msgs = $_POST['msgs'];
\t\t\t\t\t\t$statya = $arResult['CODE'];
\t\t\t\t\t\tif($msgs){
\t\t\t\t\t\t$DB->PrepareFields("mycomments");
\t\t\t\t\t\t$arFields = array(
\t\t\t\t\t\t\t"name" => "'".$name."'",
\t\t\t\t\t\t\t"msgs" => "'".$msgs."'",
\t\t\t\t\t\t\t"statya" => "'".$statya."'"
\t\t\t\t\t\t\t);
\t\t\t\t\t\t$DB->StartTransaction();
\t\t\t\t\t\t\t$ID = $DB->Insert("mycomments", $arFields, $err_mess.__LINE__);
\t\t\t\t\t\t\t$new="Y";
\t\t\t\t\t\t$ID = intval($ID);
\t\t\t\t\t\t$DB->Commit();
\t\t\t\t\t\t}\t\t\t\t\t\t
\t\t\t\t\t?>
#712 #588860
Сап двощь, есть одна тян, зовут ее Битрикс и она делает мне больно.
В общем суть в чем, написал я свой модуль комментариев, но не пойму с чего коммент проходит только если предварительно очистить кеш через панель и сделать ссылку вида:
http://site.ru/lavka/antikvariat/udolfskie-tayny/?clear_cache=Y
Делал эксперимент - выходил с сайта (разавторизировался или как там это сказать) и добавлял в конец URL ?clear_cache=Y, но не помогло - комментарий не отправляется.
Вот собственно код (защиты и пр. еще нет, но это и не интересует, интересует в чем проблема - буду очень благодарен).
<?\t$cnstComments = 0;
\t\t\t\t\t\tif($USER->GetLogin()){
\t\t\t\t\t\t\t$name = $USER->GetLogin();
\t\t\t\t\t\t}
\t\t\t\t\t\telse {
\t\t\t\t\t\t\t$name = $_POST['name'];
\t\t\t\t\t\t}\t\t\t\t
\t\t\t\t\t\t$msgs = $_POST['msgs'];
\t\t\t\t\t\t$statya = $arResult['CODE'];
\t\t\t\t\t\tif($msgs){
\t\t\t\t\t\t$DB->PrepareFields("mycomments");
\t\t\t\t\t\t$arFields = array(
\t\t\t\t\t\t\t"name" => "'".$name."'",
\t\t\t\t\t\t\t"msgs" => "'".$msgs."'",
\t\t\t\t\t\t\t"statya" => "'".$statya."'"
\t\t\t\t\t\t\t);
\t\t\t\t\t\t$DB->StartTransaction();
\t\t\t\t\t\t\t$ID = $DB->Insert("mycomments", $arFields, $err_mess.__LINE__);
\t\t\t\t\t\t\t$new="Y";
\t\t\t\t\t\t$ID = intval($ID);
\t\t\t\t\t\t$DB->Commit();
\t\t\t\t\t\t}\t\t\t\t\t\t
\t\t\t\t\t?>
129 Кб, 1263x640
#713 #588864
Блядь, простите за \t\t\t\t
Код прикрепил в img
#714 #588878
>>588860
Ну наверное надо очищать кеш при добавлении нового комментария. Кеш для того и предназначен, чтобы хранить данные, которые не меняются. Если данные изменились, нужно сбросить кеш.

А что за кеш? Мемкеш, apc, файловый?
Короче, гугли документацию битрикса и найди апи, отвечающее за сброс кеша, пропиши эти буквы после своего кода добавления нового комментария.

И проверь базу, может у тебя ошибка в коде и комментарий вообще не добавляется и кеширование не при чем.
#715 #588881
>>588878
Коммент добавляется в БД заносит, но только если именно предварительно очистить кешь. Если не очищать то в БД не идет, что-то мне кажется где-то я надрурил все же.
#716 #588926
>>588881

Ты запрос на добавление комментария методом GET или POST добавляешь? Я не знаю как работает кеш в битриксе, это просто догадка.

> Если не очищать то в БД не идет, что-то мне кажется где-то я надрурил все же.


Ты можешь вместо расплывчатых слов взять отладчик в браузере и посмотреть на влкдаке Network запрос на отправку комметария, что отправляется, что приходит?
#717 #588987
>>586981
Я смутно понял твой рассказ, но основную мысль кажется уловил.
Во всяком случае я понял, что тип index в explain говорит о фуллскане индекса, что не очень хорошо, и от него нужно избавляться, стремиться к const или ref.
Ну и с условием OR конечно облажался, я ведь знал в теории о том что один индекс должен покрывать обе части условия, два индекса не будут использованы.

Попытался переписать без условий типа and/or, сделал выборку айдишников пользователей подзапросом с юнионами, полученный результат подсунул в IN основного селекта.
http://sqlfiddle.com/#!9/5fc5f3/18
Но в explain теперь что-то совсем жуткое, не понимаю как трактовать то что там вижу.
Например в первой строке explain стоит type:index, мы вроде говорили что он используется при фуллскане, только не таблицы а индекса и с ним нужно бороться. Хотя нет, наверное в данной ситуации просто выборка идет из индекса, наоборот это хорошо, что он не лезет в таблицу, а берет прямо из индекса?
Дальше, первый раз вижу такую штуку как func в колонке ref, в документации такого не вижу. Остается только догадываться, что здесь берутся const данные, но на основе подзапроса, поэтому func.
#718 #588998
>>588987

> Например в первой строке explain стоит type:index, мы вроде говорили что он используется при фуллскане, только не таблицы а индекса и с ним нужно бороться. Хотя нет, наверное в данной ситуации просто выборка идет из индекса, наоборот это хорошо, что он не лезет в таблицу, а берет прямо из индекса?


У тебя там в таблице всего 3 строки и возможно mysql подумал что обойти их фуллсканом быстрее чем брать по очереди значения из IN (которых может быть много) и искать каждое в индексе двоичным поиском.

Вообще, на крошечных таблицах mysql фуллскан может быть и выгоднее.

Потому сделай таблицу на 100 000 записей и повтори запрос (у меня в посте есть конкретные SQL запросы как набить столько записей за полминуты).

Насчет EXPLAIN, в случае UNION он сложновато выглядит, в таком случае можно делать EXPLAIN по отдельности для отдельных входящих в UNION подзапросов (опять же именно так я и делал в прошлом посте).

По поводу func, я тоже первый раз вижу, в мануале http://dev.mysql.com/doc/refman/5.7/en/explain-output.html есть пояснение:

> The ref column shows which columns or constants are compared to the index named in the key column to select rows from the table.



> If the value is func, the value used is the result of some function. To see which function, use EXPLAIN EXTENDED followed by SHOW WARNINGS. The function might actually be an operator such as an arithmetic operator.



На sqlfiddle SHOW WARNINGS не работает, сделай это у себя.

И кстати, в прошлом посте я упомянул объединение индексов которое не работало при джойне, но может работать с WHERE. Проверь-ка, можно ли заменить 2 запроса из UNION на один с WHERE ... OR
283 Кб, 1532x815
259 Кб, 1515x789
#719 #589005
>>588926
Вот что происходит еслм я залогинен и очистил кеш:
269 Кб, 1898x750
#720 #589007
>>588926
А вот что если я вышел
#721 #589033
>>586978

>подумай над клавиатурной навигацией. Если ты сделаешь обычные, видимые радиокнопки то можешь перемещаться по ним клавишами Tab и стрелками (проверь)


Проверил, таб работает, стрелки нет. Chromium под xfce.

> accesskey


Ну и какой пользователь в здравом уме будет сидеть и заучивать эти дурацкие комбинации?
Мы же делаем сайты не для задротов, а для простых людей.
Короче, не считаю нужным заморачиваться над бесполезными фичами.

>>587978

>Это ведь ты писал что задания слишком простые? Вот видишь, я же предупреждал что дальше сложность возрастет.


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

>>586005
В макете как мог исправил замечания.
http://nsdvw.github.io/template.html
- Скрытие картинок портфолио при выборе другого тега
- анимировал это скрытие, правда получилось очень уродливо, но главное что теперь есть навык css-анимации
- логотип сделал картинкой в ссылке на главную, соответственно выбросил лишний шрифт
- сделал затухание социальных иконок через opacity; правда выглядит странно, наверное при наведении мышки на конкретную иконку она должна подсвечиваться, то есть становиться ярче, а у меня наоборот тухнет
- порезал шрифты при помощи fontsquirrel
- ссылки на телефон и гугл-карты

Про теги-заголовки так и не понял.

>We are Webpaint


Можно заключить в h1? Если нет, почему?

>digital & branding agency based in Jupiter and we would love to turn ideas into beautiful things


Слоган, или как это называется. В какой тег его заключать? Может это вообще не заголовок, положить в параграф что ли?

Дальше секция services с четырьмя элементами вида "Consectetur": "несколько предложений".

> <div class="service-name">Consectetur</div>


> Это подзаголовок


Подзаголовок h2? Их может быть несколько в одной секции?

Тогда

> Our Featured Works


Это h2 или h3? Если это h2, может тогда заголовки секции services сделать h3, а то меня коробит что куча пунктов в одной секции имеют тот же вес, что и название другой секции.
Я правильно понимаю логику? h1 для главного заголовка, h2 для названия секций, в случае services названия секции нет, но есть подзаголовки h3.

Еще вопрос по поводу вертикального выравнивания. Я знаю два основных способа.
1. Если текст однострочный (какое-нибудь меню), то можно выставить line-height равный высоте родителя.
2. Для многострочного блока, который должен быть отцентрирован по вертикали внутри своего родителя можно сделать родителя display:table, а дочерний элемент display:table-cell, таким образом он станет вести себя как ячейка с применением vertical-align.
Есть ли у этих способов недостатки, или может есть другое более правильное решение?
#721 #589033
>>586978

>подумай над клавиатурной навигацией. Если ты сделаешь обычные, видимые радиокнопки то можешь перемещаться по ним клавишами Tab и стрелками (проверь)


Проверил, таб работает, стрелки нет. Chromium под xfce.

> accesskey


Ну и какой пользователь в здравом уме будет сидеть и заучивать эти дурацкие комбинации?
Мы же делаем сайты не для задротов, а для простых людей.
Короче, не считаю нужным заморачиваться над бесполезными фичами.

>>587978

>Это ведь ты писал что задания слишком простые? Вот видишь, я же предупреждал что дальше сложность возрастет.


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

>>586005
В макете как мог исправил замечания.
http://nsdvw.github.io/template.html
- Скрытие картинок портфолио при выборе другого тега
- анимировал это скрытие, правда получилось очень уродливо, но главное что теперь есть навык css-анимации
- логотип сделал картинкой в ссылке на главную, соответственно выбросил лишний шрифт
- сделал затухание социальных иконок через opacity; правда выглядит странно, наверное при наведении мышки на конкретную иконку она должна подсвечиваться, то есть становиться ярче, а у меня наоборот тухнет
- порезал шрифты при помощи fontsquirrel
- ссылки на телефон и гугл-карты

Про теги-заголовки так и не понял.

>We are Webpaint


Можно заключить в h1? Если нет, почему?

>digital & branding agency based in Jupiter and we would love to turn ideas into beautiful things


Слоган, или как это называется. В какой тег его заключать? Может это вообще не заголовок, положить в параграф что ли?

Дальше секция services с четырьмя элементами вида "Consectetur": "несколько предложений".

> <div class="service-name">Consectetur</div>


> Это подзаголовок


Подзаголовок h2? Их может быть несколько в одной секции?

Тогда

> Our Featured Works


Это h2 или h3? Если это h2, может тогда заголовки секции services сделать h3, а то меня коробит что куча пунктов в одной секции имеют тот же вес, что и название другой секции.
Я правильно понимаю логику? h1 для главного заголовка, h2 для названия секций, в случае services названия секции нет, но есть подзаголовки h3.

Еще вопрос по поводу вертикального выравнивания. Я знаю два основных способа.
1. Если текст однострочный (какое-нибудь меню), то можно выставить line-height равный высоте родителя.
2. Для многострочного блока, который должен быть отцентрирован по вертикали внутри своего родителя можно сделать родителя display:table, а дочерний элемент display:table-cell, таким образом он станет вести себя как ячейка с применением vertical-align.
Есть ли у этих способов недостатки, или может есть другое более правильное решение?
#722 #589064
>>588998
show warnings показывает какое-то говно, с этим я уже точно не в состоянии разобраться

explain extended SELECT DISTINCT ug.group_id FROM users_groups ug WHERE ug.user_id IN ( SELECT from_user AS u_id FROM users_likes WHERE to_user = 3 UNION SELECT to_user AS u_id FROM users_likes WHERE from_user = 3 UNION SELECT 3 AS u_id ) \G
1. row
id: 1
select_type: PRIMARY
table: ug
type: index
possible_keys: NULL
key: group_id
key_len: 4
ref: NULL
rows: 5
filtered: 100.00
Extra: Using where; Using index
2. row
id: 2
select_type: DEPENDENT SUBQUERY
table: users_likes
type: eq_ref
possible_keys: PRIMARY,to_user
key: PRIMARY
key_len: 8
ref: func,const
rows: 1
filtered: 100.00
Extra: Using index
3. row
id: 3
select_type: DEPENDENT UNION
table: users_likes
type: eq_ref
possible_keys: PRIMARY,to_user
key: PRIMARY
key_len: 8
ref: const,func
rows: 1
filtered: 100.00
Extra: Using index
4. row
id: 4
select_type: DEPENDENT UNION
table: NULL
type: NULL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: NULL
filtered: NULL
Extra: No tables used
5. row
id: NULL
select_type: UNION RESULT
table: <union2,3,4>
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: NULL
filtered: NULL
Extra:
5 rows in set, 1 warning (0.00 sec)
Note (Code 1003): select distinct `likes_extended`.`ug`.`group_id` AS `group_id` from `likes_extended`.`users_groups` `ug` where <in_optimizer>(`likes_extended`.`ug`.`user_id`,<exists>(select 1 from `likes_extended`.`users_likes` where ((`likes_extended`.`users_likes`.`to_user` = 3) and (<cache>(`likes_extended`.`ug`.`user_id`) = `likes_extended`.`users_likes`.`from_user`)) union select 1 from `likes_extended`.`users_likes` where ((`likes_extended`.`users_likes`.`from_user` = 3) and (<cache>(`likes_extended`.`ug`.`user_id`) = `likes_extended`.`users_likes`.`to_user`)) union select 3 AS `u_id` having (<cache>(`likes_extended`.`ug`.`user_id`) = <ref_null_helper>(3))))

Что-то не помогло увеличение количества записей, результат тот же самый.

Пробую explain по частям запроса.
mysql> explain extended SELECT from_user AS u_id FROM users_likes WHERE to_user = 3 \G
id: 1
select_type: SIMPLE
table: users_likes
type: ref
possible_keys: to_user
key: to_user
key_len: 4
ref: const
rows: 1
filtered: 100.00
Extra: Using index
1 row in set, 1 warning (0.00 sec)
Note (Code 1003): select `likes_extended`.`users_likes`.`from_user` AS `u_id` from `likes_extended`.`users_likes` where (`likes_extended`.`users_likes`.`to_user` = 3)

Тут вроде все хорошо: ref, const, все дела. Внешний запрос:
mysql> explain extended SELECT DISTINCT ug.group_id FROM users_groups ug WHERE ug.user_id IN (5) \G
id: 1
select_type: SIMPLE
table: ug
type: ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: const
rows: 1
filtered: 100.00
Extra: Using where; Using index
1 row in set, 1 warning (0.00 sec)
Note (Code 1003): select distinct `likes_extended`.`ug`.`group_id` AS `group_id` from `likes_extended`.`users_groups` `ug` where (`likes_extended`.`ug`.`user_id` = 5)

Я все равно ничего не понял, хорош запрос в плане производительности или нет.
#722 #589064
>>588998
show warnings показывает какое-то говно, с этим я уже точно не в состоянии разобраться

explain extended SELECT DISTINCT ug.group_id FROM users_groups ug WHERE ug.user_id IN ( SELECT from_user AS u_id FROM users_likes WHERE to_user = 3 UNION SELECT to_user AS u_id FROM users_likes WHERE from_user = 3 UNION SELECT 3 AS u_id ) \G
1. row
id: 1
select_type: PRIMARY
table: ug
type: index
possible_keys: NULL
key: group_id
key_len: 4
ref: NULL
rows: 5
filtered: 100.00
Extra: Using where; Using index
2. row
id: 2
select_type: DEPENDENT SUBQUERY
table: users_likes
type: eq_ref
possible_keys: PRIMARY,to_user
key: PRIMARY
key_len: 8
ref: func,const
rows: 1
filtered: 100.00
Extra: Using index
3. row
id: 3
select_type: DEPENDENT UNION
table: users_likes
type: eq_ref
possible_keys: PRIMARY,to_user
key: PRIMARY
key_len: 8
ref: const,func
rows: 1
filtered: 100.00
Extra: Using index
4. row
id: 4
select_type: DEPENDENT UNION
table: NULL
type: NULL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: NULL
filtered: NULL
Extra: No tables used
5. row
id: NULL
select_type: UNION RESULT
table: <union2,3,4>
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: NULL
filtered: NULL
Extra:
5 rows in set, 1 warning (0.00 sec)
Note (Code 1003): select distinct `likes_extended`.`ug`.`group_id` AS `group_id` from `likes_extended`.`users_groups` `ug` where <in_optimizer>(`likes_extended`.`ug`.`user_id`,<exists>(select 1 from `likes_extended`.`users_likes` where ((`likes_extended`.`users_likes`.`to_user` = 3) and (<cache>(`likes_extended`.`ug`.`user_id`) = `likes_extended`.`users_likes`.`from_user`)) union select 1 from `likes_extended`.`users_likes` where ((`likes_extended`.`users_likes`.`from_user` = 3) and (<cache>(`likes_extended`.`ug`.`user_id`) = `likes_extended`.`users_likes`.`to_user`)) union select 3 AS `u_id` having (<cache>(`likes_extended`.`ug`.`user_id`) = <ref_null_helper>(3))))

Что-то не помогло увеличение количества записей, результат тот же самый.

Пробую explain по частям запроса.
mysql> explain extended SELECT from_user AS u_id FROM users_likes WHERE to_user = 3 \G
id: 1
select_type: SIMPLE
table: users_likes
type: ref
possible_keys: to_user
key: to_user
key_len: 4
ref: const
rows: 1
filtered: 100.00
Extra: Using index
1 row in set, 1 warning (0.00 sec)
Note (Code 1003): select `likes_extended`.`users_likes`.`from_user` AS `u_id` from `likes_extended`.`users_likes` where (`likes_extended`.`users_likes`.`to_user` = 3)

Тут вроде все хорошо: ref, const, все дела. Внешний запрос:
mysql> explain extended SELECT DISTINCT ug.group_id FROM users_groups ug WHERE ug.user_id IN (5) \G
id: 1
select_type: SIMPLE
table: ug
type: ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: const
rows: 1
filtered: 100.00
Extra: Using where; Using index
1 row in set, 1 warning (0.00 sec)
Note (Code 1003): select distinct `likes_extended`.`ug`.`group_id` AS `group_id` from `likes_extended`.`users_groups` `ug` where (`likes_extended`.`ug`.`user_id` = 5)

Я все равно ничего не понял, хорош запрос в плане производительности или нет.
99 Кб, 1355x474
52 Кб, 1236x374
#723 #589137
>>588403
Пик1 загрузка страницы с диска, пик2 зашел с пеки (там тоже не ахти какая машина, но все же ядра по 2.8, а не 1.3 как на ноутбуке).

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

>в медленной загрузке может быть виноват браузер или какие-то программы (фаерволл? антивирус?)


Антивируса по понятным причинам нет. А что с фаерволом на убунте?
Нагуглил команду
$ sudo iptables-save
# Generated by iptables-save v1.4.21 on Wed Nov 25 20:54:26 2015
*filter
:INPUT ACCEPT [704:381331]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [739:101247]
COMMIT
# Completed on Wed Nov 25 20:54:26 2015
Не понимаю что мне делать с этим набором букв.

> sudo ufw status verbose


> Состояние: неактивен.


Вот, так гораздо лучше. Правда не уверен, что это означает что фаервол выключен. ufw это же только настройка над iptables?

Инструменты хрома покликал, интересно конечно для общего развития, но я думаю это все же для профессионалов.
#724 #589166
>>588446
Не подставляет же данные просто, запрос тот, что нужен, но вместо values( param1, param2...) знаки вопроса. Что за хрень
87 Кб, 1280x776
#725 #589186
>>589166

попробуй сдампить собранный в билдере запрос.

>>589137

Если ты не включал файерволл то он отключен. Ну то есть фаерволл в ядре линукса конечно всегда включен но в твоем случае он никак особо ни на что не влияет.

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

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

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

Процессор Core 2 Duo, двухядерный, если что, довольно старый но не очень медленный.

У тебя были паузы больше, но может это из-за того что отрисовка делалась медленнее?
#726 #589203
>>589137

Смотри еще какая штука. Хром многопоточный. Если ты посмотришь запись tracing, то увидишь что у него есть как минимум потоки:

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

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

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

Это предположение конечно. Если ab показывает что файл статики отдается за несколько мс, то значит тормоза не на стороне Апача.
#727 #589213
>>589137

Если мы вернемся к скриншотам с >>588228 то видно что сеть не загружена на 100% и там довольно много пауз. Я подозреваю (без tracing конечно подтвердить это трудно) что просто процессора не хватило и оттого большие паузы - в это время выполнялись какие-то другие процессы, может Апач, может рендеринг в Хроме.

Можно еще попробовать посмотреть htop в процессе загрузки сайта объявлений в Хроме. Если там CPU будет загружен на 100% и вверху будет Хром (а не апачи) то скорее всего именно CPU не хватает.
#728 #589238
>>589064

По поводу запроса: MySQL в данном случае решил переписать твой запрос в более оптимальном виде. Тут http://dev.mysql.com/doc/refman/5.7/en/explain-extended.html поясняются некоторые обозначения.

Судя по <exists> (если я не ошибаюсь) он решил превратить запрос SELECT .. WHERE IN (...) в запрос SELECT ... WHERE EXISTS (...).

Если ты не знаешь что такое EXISTS, погугли.

Это мне не очень нравится так как это получается примерно такой алгоритм:

- обходим по очереди строки таблицы users_groups (если посмотреть на type: index то видно что обход идет по индексу group_id, логично ведь мы только это поле и выбираем)

- для каждой строки выполняем подзапрос c UNION внутри EXISTS (судя по строкам 2,3,4 этот подзапрос использует индексы) и проверяем вернет ли он хоть одну строку

подзапрос выглядит примерно так:

SELECT 1 FROM users_likes WHERE to_user = 3 AND from_user = :user_id
UNION
SELecT 1 FROM user_likes WHERE from_user = 3 AND to_user = :user_id
UNION
SELECT 3 HAVING ... (тут я не очень понял)

:user_id это id из таблицы users_groups который мы выбрали на первом шаге.

как видишь подзапросы внутри EXISTS сводятся к проверке наличия в индексе пары (from_user, to_user) с известными значениями.

Много ли у тебя строк в users_groups? Есть ли в ней индекс с user_id в начале (я посмотрел, вроде есть)?

Мне кажется что там немного строк или индекса нет, иначе такая оптимизация выглядит довольно невыгодной. Ведь вместо того чтобы обходить user_groups мы бы могли поступить так:

- получить небольшой список id юзеров из подзапроса
- для каждого id выбрать в users_groups по индексу строчки и взять с них group_id
#728 #589238
>>589064

По поводу запроса: MySQL в данном случае решил переписать твой запрос в более оптимальном виде. Тут http://dev.mysql.com/doc/refman/5.7/en/explain-extended.html поясняются некоторые обозначения.

Судя по <exists> (если я не ошибаюсь) он решил превратить запрос SELECT .. WHERE IN (...) в запрос SELECT ... WHERE EXISTS (...).

Если ты не знаешь что такое EXISTS, погугли.

Это мне не очень нравится так как это получается примерно такой алгоритм:

- обходим по очереди строки таблицы users_groups (если посмотреть на type: index то видно что обход идет по индексу group_id, логично ведь мы только это поле и выбираем)

- для каждой строки выполняем подзапрос c UNION внутри EXISTS (судя по строкам 2,3,4 этот подзапрос использует индексы) и проверяем вернет ли он хоть одну строку

подзапрос выглядит примерно так:

SELECT 1 FROM users_likes WHERE to_user = 3 AND from_user = :user_id
UNION
SELecT 1 FROM user_likes WHERE from_user = 3 AND to_user = :user_id
UNION
SELECT 3 HAVING ... (тут я не очень понял)

:user_id это id из таблицы users_groups который мы выбрали на первом шаге.

как видишь подзапросы внутри EXISTS сводятся к проверке наличия в индексе пары (from_user, to_user) с известными значениями.

Много ли у тебя строк в users_groups? Есть ли в ней индекс с user_id в начале (я посмотрел, вроде есть)?

Мне кажется что там немного строк или индекса нет, иначе такая оптимизация выглядит довольно невыгодной. Ведь вместо того чтобы обходить user_groups мы бы могли поступить так:

- получить небольшой список id юзеров из подзапроса
- для каждого id выбрать в users_groups по индексу строчки и взять с них group_id
#729 #589394
Новый трэд.
Перекатывайтесь уже.
>>588512 (OP)
>>588512 (OP)
>>588512 (OP)
#730 #589395
>>589394

Можете перекатываться кто хочет, но я пока не всем ответил так что пока горим тут.
#731 #589606
>>589238

> Много ли у тебя строк в users_groups?


Немного, я ж скопипастил твои заклинания из поста >>586981
Там наполнения этой таблицы не было.
Пришлось даже самому придумывать как ее наполнить.
INSERT IGNORE users_groups (user_id, group_id) SELECT x FROM (SELECT users.id AS user_id, groups.id AS group_id FROM users JOIN groups) AS tmp

Нет, результат explain остался таким же после наполнения таблицы users_groups.

id: 1
select_type: PRIMARY
table: ug
type: index
possible_keys: NULL
key: group_id
key_len: 4
ref: NULL
rows: 234893
filtered: 100.00
Extra: Using where; Using index

select distinct `likes_extended`.`ug`.`group_id` AS `group_id` from `likes_extended`.`users_groups` `ug` where <in_optimizer>(`likes_extended`.`ug`.`user_id`,<exists>(select 1 from `likes_extended`.`users_likes` where ((`likes_extended`.`users_likes`.`to_user` = 3) and (<cache>(`likes_extended`.`ug`.`user_id`) = `likes_extended`.`users_likes`.`from_user`)) union select 1 from `likes_extended`.`users_likes` where ((`likes_extended`.`users_likes`.`from_user` = 3) and (<cache>(`likes_extended`.`ug`.`user_id`) = `likes_extended`.`users_likes`.`to_user`)) union select 3 AS `u_id` having (<cache>(`likes_extended`.`ug`.`user_id`) = <ref_null_helper>(3))))
#732 #589840
>>589186
У тебя на скрине тоже по 300-700 мс отдаются некоторые файлы, так что я спокоен.
Просто слабый процессор на ноутбуке, ну не справляется, что поделать.
Но я лучше впредь буду тестить фронтенд на другом компе.

Допилил интерактивную часть счетчика посещений, или как ее назвать. В смысле теперь можно в любой момент обращаться к редису из приложения за дельтой посещений, прилепить эту дельту к значению из бд и показывать актуальные данные о посещениях.
https://github.com/nsdvw/visit-counter

>>581860

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


>А статья мейл ру как эту проблему решает? Транзакцией на уровне БД?


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

Посмотри еще что можно делать с обработкой ошибок. Я пока повыбрасывал в каждом методе клиента редиса исключение, не совсем понял как их теперь ловить.
Я правильно понял, что теперь придется писать отдельный класс унаследованный от Exception и ловить только его экземпляры в глобальном коде?
А какие сообщения выдавать? У меня в принципе простой случай, ошибка только когда редис либо не отвечает, либо вернул ошибку. Так что сообщение мне кажется везде можно поставить одинаковое, типа "Ошибка редиса". Может добавить туда еще имя метода, в котором она вывалилась?
#732 #589840
>>589186
У тебя на скрине тоже по 300-700 мс отдаются некоторые файлы, так что я спокоен.
Просто слабый процессор на ноутбуке, ну не справляется, что поделать.
Но я лучше впредь буду тестить фронтенд на другом компе.

Допилил интерактивную часть счетчика посещений, или как ее назвать. В смысле теперь можно в любой момент обращаться к редису из приложения за дельтой посещений, прилепить эту дельту к значению из бд и показывать актуальные данные о посещениях.
https://github.com/nsdvw/visit-counter

>>581860

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


>А статья мейл ру как эту проблему решает? Транзакцией на уровне БД?


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

Посмотри еще что можно делать с обработкой ошибок. Я пока повыбрасывал в каждом методе клиента редиса исключение, не совсем понял как их теперь ловить.
Я правильно понял, что теперь придется писать отдельный класс унаследованный от Exception и ловить только его экземпляры в глобальном коде?
А какие сообщения выдавать? У меня в принципе простой случай, ошибка только когда редис либо не отвечает, либо вернул ошибку. Так что сообщение мне кажется везде можно поставить одинаковое, типа "Ошибка редиса". Может добавить туда еще имя метода, в котором она вывалилась?
#733 #590078
>>589840

Ловить исключения не надо. Если не удалось соединиться с редисом или редис не смог выполнить операцию, то все, приложение аварийно завершается (если пользователь библиотеки захочет это поменять, он может ловить исключения и обрабатывать их).
#734 #590079
>>589840

То есть это не ты должен решать что делать при ошибке. Твоя задача - выбросить исключение, а пользователь библиотеки как хочет, так с ним и поступает. Попробуй осознать какая это продуманная и удобная штука, исключения.
#735 #590082
>>589840

Также, не забудь про README и комментарий с объяснением алгоритма. Если ты хочешь например показывать эту библиотеку как пример кода работодателю, то он в первую очередь захочет почитать описание и комментарии, а не разбирать алгоритм самостоятельно.
#736 #590083
>>589840

Что нужно писать в README, я тебе по моему скидывал несколько тредов назад, если ты не сохранил, напиши, я найду.
#737 #590091
>>589840

> if( !$key->append($value) ) throw new \Exception($this->errorMessage);


Вот это не годится. Смотри, как нехорошо получается:

- ты просишь библиотеку rediska сделать операцию
- она соединяется с редисом (тут может произойти ошибка), отправляет команду (в ответ может придти ошибка)
- ты никуда не сохраняешь текст и подробности ошибки, а просто выкидываешь ничего не говорящее «Redis Error». Хуже того, ты еще и используешь стандартный класс так что твое исключение нельзя перехватить.

Надо это исправить:

- не терять подробности ошибки
- использовать кастомный класс для исключений, причем этот класс является частью API твоей библиотеки и в идеале надо чтобы все драйверы редиса использовали его.
#738 #590096
>>589840

А так, твое исключение малополезно. Ну представь ты увидел в логе несколько Redis error, и что дальше? Как ты будешь отлаживать проблему?

Должны быть подробности, как минимум:

- выполняемая операция
- подробности ошибки

То есть чтобы идеале только глядя на запись в логе ты мог понять причины ошибки.
#739 #590103
>>589840

Вот пример хорошего сообщения об ошибке:

Failed to open file '/etc/config' for reading: Access denied.

А вот более высокоуровневое сообщение:

Failed to read user list: Failed to open file '/etc/config' for reading: Access denied.

Или вот так:

Failed to read some data from API: failed to GET 'http://example.com/url': server returned error 500 Temporary Unavailable, body: '{"error": "Some problems"}'
#740 #590244
>>590082
>>590083
Да не забыл я про него, напишу в последнюю очередь, когда все будет готово. Не хочу опять видеть в гитлоге десятки коммитов вида "update readme".

>>590091
Вот я если честно не представляю кроме ошибки соединения, какие могут произойти ошибки. Тем более что редиска походу и не сообщает об ошибках, а просто возвращает null. Или так и должно быть?
Вот например у меня есть метод-обертка над ltrim, при помощи которого я удаляю обработанные айдишники из очереди.
Допустим, список-очередь был удален перед вызовом этого метода. Ну и что, это ошибка или нет? Клиент редиса вообще пофигист, говорит всегда ОК, даже если списка, который мы пытаемся обрезать, не существует.
Так что я думаю это не ошибка, во всяком случае в нашем приложении со счетчиком это не приведет к проблемам, при новом посещении там просто создастся новая очередь. Но тем не менее странно.

>>590096
Редиска вроде дает достаточно подробный отчет (при ошибке подключения, другие не знаю как смоделировать), так что я пока просто перехватываю исключения Rediska_Exception и бросаю свой класс.

Ладно, может завтра на всежую голову.
#741 #590264
>>590244

> Вот я если честно не представляю кроме ошибки соединения, какие могут произойти ошибки


Ты с протоколом редиса знаком? Он тут вроде описан http://redis.io/topics/protocol

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

> Тем более что редиска походу и не сообщает об ошибках, а просто возвращает null. Или так и должно быть?


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

Это абсурдно, в случае каких-то проблем просто возвращать null, который никто не проверит. Это верный путь к быдлокодерству.

> Допустим, список-очередь был удален перед вызовом этого метода. Ну и что, это ошибка или нет?


Надо почитать документацию либо подсоединиться к редису и выполнить эту команду (через redis-cli). Второй вариант наверно проще всего.

В документации особо ничего нет, так что я зашел на http://try.redis.io/ и попробовал там:

LTRIM demo1 100 200
LTRIM demo1 -100 200
LTRIM demo1 asda asdasd
SET demo1 100
LTRIM demo1 100 200

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

Многие ситуации это не ошибка. Например удаление несуществующего ключа не ошибка (так и задумано). А попытка удалить если сервер в режиме read only - уже ошибка.

> Клиент редиса вообще пофигист, говорит всегда ОК, даже если списка, который мы пытаемся обрезать, не существует.


Значит это не ошибка. Ошибка это если он говорит ERR.

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


Есть ситуации когда сервер вернет ERR и их надо превращать в исключения.

> так что я пока просто перехватываю исключения Rediska_Exception и бросаю свой класс.


Вот тут кстати я задумался, а должны ли мы делать исключения частью интерфейса? Может правильнее возвращать нативные?

Кстати когда ты преобразуешь исключение в свое, не забудь в него вложить исходное исключение параметром $previous ( http://php.net/manual/ru/class.exception.php ). Чтобы оно (и стек трейс в нем) не потерялось.
#741 #590264
>>590244

> Вот я если честно не представляю кроме ошибки соединения, какие могут произойти ошибки


Ты с протоколом редиса знаком? Он тут вроде описан http://redis.io/topics/protocol

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

> Тем более что редиска походу и не сообщает об ошибках, а просто возвращает null. Или так и должно быть?


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

Это абсурдно, в случае каких-то проблем просто возвращать null, который никто не проверит. Это верный путь к быдлокодерству.

> Допустим, список-очередь был удален перед вызовом этого метода. Ну и что, это ошибка или нет?


Надо почитать документацию либо подсоединиться к редису и выполнить эту команду (через redis-cli). Второй вариант наверно проще всего.

В документации особо ничего нет, так что я зашел на http://try.redis.io/ и попробовал там:

LTRIM demo1 100 200
LTRIM demo1 -100 200
LTRIM demo1 asda asdasd
SET demo1 100
LTRIM demo1 100 200

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

Многие ситуации это не ошибка. Например удаление несуществующего ключа не ошибка (так и задумано). А попытка удалить если сервер в режиме read only - уже ошибка.

> Клиент редиса вообще пофигист, говорит всегда ОК, даже если списка, который мы пытаемся обрезать, не существует.


Значит это не ошибка. Ошибка это если он говорит ERR.

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


Есть ситуации когда сервер вернет ERR и их надо превращать в исключения.

> так что я пока просто перехватываю исключения Rediska_Exception и бросаю свой класс.


Вот тут кстати я задумался, а должны ли мы делать исключения частью интерфейса? Может правильнее возвращать нативные?

Кстати когда ты преобразуешь исключение в свое, не забудь в него вложить исходное исключение параметром $previous ( http://php.net/manual/ru/class.exception.php ). Чтобы оно (и стек трейс в нем) не потерялось.
#742 #590618
>>590264

>должны ли мы делать исключения частью интерфейса? Может правильнее возвращать нативные?


Да я тоже не понимаю, к чему все это? Клиент (наверное) сам выбрасывает исключения, так зачем мне писать свой класс для исключений?
Если человек пользуется нашей библиотекой и редиской в качестве клиента, пусть ловит Rediska_Exception, для другого клиента соответствующий класс.
Насчет того, какие ошибки обрабатывает редиска и что возвращает, то в документации как всегда об этом ни слова не сказано
http://rediska.geometria-lab.net/documentation/
а заучивать исходный код я не подписывался.

То есть получается, что мне в библиотеке вообще не нужен код обработки ошибок? Например зачем перехватывать исключение клиента и преобразовывать в свое? Только ради собственного формата отчета об ошибке?
#743 #590654
>>590618

Вот жаль что ты этот момент не понял. Я-то надеялся что ты разобрался с ООП и исключениями.

Смотри, допустим мы исплоьзуем драйвер XRedis который при ошибке выбрасывает исключение XException. Допустим мы хотим его обрабатывать:

$redisAdapter = new XRedis(...);

try {
$redisAdapter->hset(....);
} catch (XEception $e) {
...
}

Завтра, допустим, мы решаем перейти с драйвера XRedis на YRedis. При этом код $redisAdapter->hset(....); нам переписывать не надо: все адаптеры редиса предоставляют нам единый, независимый от драйвера редиса интерфейс. Метод hset по задумке работает одинаково в любом адаптере.

Одинаково ли? Если он работает одинаково, то код не сломается от замены XRedis на YRedis, верно?

Сломается. try/catch перестанет работать так как он ловит XException, а новый драйвер бросает YException.

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

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

Исключения это часть интерфейса твоего класса или метода (в данном примере метода hset). Ты определил независимые от драйвера методы работы с редисом; почему же обработку ошибок от них ты оставляешь драйверозависимой?

Поясню еще раз «Исключения это часть интерфейса твоего класса». Что я имею в виду под словами «интерфейс класса»? Это набор публичных методов и их свойства: какие у них есть аргумнты, что они возвращают. Что они выбрасывают - это не менее важная информация чем что они возвращают.

В Ява это ограничение можно ставить на уровне языка: для метода можно определить какие исключения ему разрешено выбрасывать. Наследники не могут переопределить этот список и выбросить не указанное в нем исключение - код просто не скомпилируется.

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

А теперь обсудим аргументы против приведения исключений к единому виду. Это усложнение кода, в каждом адаптере придется писать перехватчики ошибок/исключений. Более того, придется сделать единый класс исключений еще и для драйверов БД.

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

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

Если она при получении ERR от редиса выкидывает исключение - хорошо. Если она игнорирует или просто сохраняет ошибку в каком-то поле - надо обнаруживать такую ситуацию и выбрасывать исключение. То есть в любом случае не должно быть такого что какая-то операция работы с редисом проваливается и скрипт продолжет выполняться. Это будет нарушением принципа fail fast ( http://habrahabr.ru/post/218325/ ) и я пожалуй против нарушения.

Однако, если в редиске, как в PDO ( http://php.net/manual/ru/pdo.error-handling.php ), можно задавать какой-то опцией способ реакции на ошибки и там можно включить исключения - ничего не требуется делать. В таком случае выбор способа реакци на ошибки это осознанный выбор пользователя.

Чтобы понять как она реагирует на ERR, придется по диагонали почитать ее код. Если ты собираешься заниматься программированием, тебе это не раз придется делать, так что можешь считать это тренировкой.
#743 #590654
>>590618

Вот жаль что ты этот момент не понял. Я-то надеялся что ты разобрался с ООП и исключениями.

Смотри, допустим мы исплоьзуем драйвер XRedis который при ошибке выбрасывает исключение XException. Допустим мы хотим его обрабатывать:

$redisAdapter = new XRedis(...);

try {
$redisAdapter->hset(....);
} catch (XEception $e) {
...
}

Завтра, допустим, мы решаем перейти с драйвера XRedis на YRedis. При этом код $redisAdapter->hset(....); нам переписывать не надо: все адаптеры редиса предоставляют нам единый, независимый от драйвера редиса интерфейс. Метод hset по задумке работает одинаково в любом адаптере.

Одинаково ли? Если он работает одинаково, то код не сломается от замены XRedis на YRedis, верно?

Сломается. try/catch перестанет работать так как он ловит XException, а новый драйвер бросает YException.

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

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

Исключения это часть интерфейса твоего класса или метода (в данном примере метода hset). Ты определил независимые от драйвера методы работы с редисом; почему же обработку ошибок от них ты оставляешь драйверозависимой?

Поясню еще раз «Исключения это часть интерфейса твоего класса». Что я имею в виду под словами «интерфейс класса»? Это набор публичных методов и их свойства: какие у них есть аргумнты, что они возвращают. Что они выбрасывают - это не менее важная информация чем что они возвращают.

В Ява это ограничение можно ставить на уровне языка: для метода можно определить какие исключения ему разрешено выбрасывать. Наследники не могут переопределить этот список и выбросить не указанное в нем исключение - код просто не скомпилируется.

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

А теперь обсудим аргументы против приведения исключений к единому виду. Это усложнение кода, в каждом адаптере придется писать перехватчики ошибок/исключений. Более того, придется сделать единый класс исключений еще и для драйверов БД.

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

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

Если она при получении ERR от редиса выкидывает исключение - хорошо. Если она игнорирует или просто сохраняет ошибку в каком-то поле - надо обнаруживать такую ситуацию и выбрасывать исключение. То есть в любом случае не должно быть такого что какая-то операция работы с редисом проваливается и скрипт продолжет выполняться. Это будет нарушением принципа fail fast ( http://habrahabr.ru/post/218325/ ) и я пожалуй против нарушения.

Однако, если в редиске, как в PDO ( http://php.net/manual/ru/pdo.error-handling.php ), можно задавать какой-то опцией способ реакции на ошибки и там можно включить исключения - ничего не требуется делать. В таком случае выбор способа реакци на ошибки это осознанный выбор пользователя.

Чтобы понять как она реагирует на ERR, придется по диагонали почитать ее код. Если ты собираешься заниматься программированием, тебе это не раз придется делать, так что можешь считать это тренировкой.
#744 #590656
>>590618

Также, вспомнил статью по теме: принцип дырявых абстракций: http://russian.joelonsoftware.com/Articles/LeakyAbstractions.html

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

С другой стороны, конечно делать единые исключения - усложнять код, а часто ли они нужны? В 99% случаев пользователь наверно и не будет их ловить, если сломался редис, все равно ничего не поделать.

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

В общем, хотелось бы чтобы ты сделал осознанный аргументированный выбор, а не «неужели это нужно только для собственного формата сообщений об ошибке».
#745 #590660
>>590618

Наконец, есть еще четвертый аргумент: мы предполагаем что любой желающий может написать драйвер редиса, используя наш абстрактный класс как основу. Реализовать 6 методов сможет каждый, более того, PHP не даст загрузить класс если в нем не будут реализованы все методы. А вот как заставить людей перехатывать и выбрасывать исключения? Как проверить что они делают это правильно?

В PHP в отличие от Явы нет средств чтобы принудить пользователя это сделать. Да что там исключения, в текущей версии мы не можем даже заставить возвращать результат определенного типа! (в PHP7 хотят это исправить: https://wiki.php.net/rfc/return_types и я считаю это хорошо. Увы, ошибка будет обнаруживаться только при попытке вернуть значение, а не на этапе компиляции как в Яве).
10 Кб, 343x231
unexpected TELSE #746 #590938
Пыханы! У меня сейчас истерика будет!
блять сука все перепробовал, но все равно сука
"Parse error: syntax error, unexpected T_ELSE in ... line 9"
Что я делаю не так? я блять просто не могу больше( Подскажите ебаному нубу плиииз!
#747 #590959
>>590938
Точка с запятой после if();
Ставь IDE, там подсвечиваются ошибки синтаксиса и не только.
56 Кб, 403x604
#748 #591000
>>590959
спасибо тебе, о великий мудрец!
http://nsdvw.github.io/template.html #749 #591165
Кажется я ответил на все посты в этом треде. Не могу поверить что скоро мы его закроем.

>>585745

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

Также, кисточка на логотипе у тебя темная, темнее чем на макете.

Вес текста «agency based in J...» должен быть 100 (если я не путаю), у тебя там font-weight: bold.

В портфолио между кнопками и картинками на макете меньшее расстояние. Также как и между «Our Featured» и «Sed sequi, maxime nisi ». Проверь вертикальные отступы хотя бы на глаз. Кнопки выбора в портфолио намакете ниже чем у тебя.

> <div class="service-icon service-icon-1"></div>


Этот бессмысленный элемент можно убрать. Используй псевдоэлементы например.

> <div class="service-name">


Это явно заголовок. По поводу уровней, я думаю так:

h1 - We are Webpaint
h2 - Our Featured Works, Get in Touch (заголовки секций)
h3 - Consectetur, Tristiquet (подзаголовки внутри секций)

> <div class="service-description">


Это можно заменить на просто <p>.

> <label for="tag-motion" class="button-red">motion</label>


> <br>


не используй br для верстки. Лучше заключи блок переключателей в div.

> section class="slider">


> <div class="center">


Эти дивы конечно избыточны, но что-то я не очень представляю как обойтись без них. Придется оставить. Только название center плохое, лучше назвать section-content, а то мы оформление в HTML тащим.

> <h6>Vestibulum id ligula porta felis euismod semper


Это обычный текст, а не заголовок. Так же как и слоган «best branding agency»

> <div class="contact">


Обрати внимание что в HTML есть тег address с таким определением:

> The address element represents the contact information for its nearest article or body element ancestor. If that is the body element, then the contact information applies to the document as a whole.



Может он тут бы подошел. Ну и еще, есть такая штука как микроразметка: http://habrahabr.ru/company/yandex/blog/211638/

Для контактной информации есть микроразметка hCard: https://yandex.ru/support/webmaster/hcard/general.xml

Попробуй-ка добавить ее, чтобы научиться ее использовать.

> font: 16px/1.3 "Lato Regular", arial;


В конце списка должен стоять стандартный шрифт вроде serif.

> .header-container {


> height: 100%;


процентная высота работает только если у всех предков (родитель и далее) элемента высота тоже в процентах или пикселах.

> font: 13px "Lato Black";


Нужно указывать в конце универсальный шрифт

> font-family: "Lato Light";


> font-family: "Lato Black";


я тут подумал, это не очень правильно. Это одно и то же семейство (font-family), просто шрифты имеют разный вес: https://www.google.com/fonts/specimen/Lato

Значит и у себя сделай один шрифт. А то, я подозреваю, вот это вот local("Lato Black") работать не будет.

Про код подключения шрифта: тут конечно http://caniuse.com/#feat=ttf написано что современные браузеры поддерживают ttf, но есть наверно какие-то старые браузеры, и для них пригодится более универсальный синтаксис: http://habrahabr.ru/post/113136/

Тем более что этот синтаксис позволит подключить в новых браузерах WOFF который эффективнее сжат. Почитай какие бывают форматы веб-шрифтов и какие браузеры что поддерживают.

> .button-big {


> width: 200px;


> height: 50px;


Размеры должны определяться текстом + паддингом. Неудобно при смене текста менять еще и CSS.

> border-top-left-radius: 5px;


Есть же просто border-radius который позволяет сразу задать все 4 радиуса

> .services-container::after


Имей в виду что этот синтаксис с 2 доветочиями из CSS3 могут не поддерживать более дрвение CSS2 браузеры вроде IE8.

Насчет адаптивной верстки, может тебе пригодится сайт с размерами экранов разных устройств: http://mydevice.io/devices/

Так, в общем, верстка этого макета у тебя неплохо получилась, и по объему меньше полмегабайта вышло (эх, а были времена, сайт можно было в 100-150 Кб сверстать).

Что насчет ИЕ? Ты смотрел мой урок про тестирование под ИЕ? https://gist.github.com/codedokode/855e3970124687b26a1c

Алсо есть такой (бесплатно можно юзать) сервис: https://www.browserstack.com/screenshots/1766a5eb3f26e63e5db6c8a85f2b04a6f07b5774

Посмотри скриншоты хотя бы там, но имей в виду что если всерьез заниматься фронтендом, надо иметь либо виртуальные машины с ИЕ, либо еще что-нибудь. На modern.ie предлагаются разные варианты решения проблемы.

Если ты заметил синюю рамку на картинках: это нормально и не противоречит стандартам. Ие так выделяет ссылки, и это легко отключить через CSS.

Под ИЕ6/7 я думаю красивую верстку делать не требуется, если просто текст будет читаться то хорошо. А ИЕ8 поддерживает CSS2.1 так что с ним проблемы быть не должно.
http://nsdvw.github.io/template.html #749 #591165
Кажется я ответил на все посты в этом треде. Не могу поверить что скоро мы его закроем.

>>585745

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

Также, кисточка на логотипе у тебя темная, темнее чем на макете.

Вес текста «agency based in J...» должен быть 100 (если я не путаю), у тебя там font-weight: bold.

В портфолио между кнопками и картинками на макете меньшее расстояние. Также как и между «Our Featured» и «Sed sequi, maxime nisi ». Проверь вертикальные отступы хотя бы на глаз. Кнопки выбора в портфолио намакете ниже чем у тебя.

> <div class="service-icon service-icon-1"></div>


Этот бессмысленный элемент можно убрать. Используй псевдоэлементы например.

> <div class="service-name">


Это явно заголовок. По поводу уровней, я думаю так:

h1 - We are Webpaint
h2 - Our Featured Works, Get in Touch (заголовки секций)
h3 - Consectetur, Tristiquet (подзаголовки внутри секций)

> <div class="service-description">


Это можно заменить на просто <p>.

> <label for="tag-motion" class="button-red">motion</label>


> <br>


не используй br для верстки. Лучше заключи блок переключателей в div.

> section class="slider">


> <div class="center">


Эти дивы конечно избыточны, но что-то я не очень представляю как обойтись без них. Придется оставить. Только название center плохое, лучше назвать section-content, а то мы оформление в HTML тащим.

> <h6>Vestibulum id ligula porta felis euismod semper


Это обычный текст, а не заголовок. Так же как и слоган «best branding agency»

> <div class="contact">


Обрати внимание что в HTML есть тег address с таким определением:

> The address element represents the contact information for its nearest article or body element ancestor. If that is the body element, then the contact information applies to the document as a whole.



Может он тут бы подошел. Ну и еще, есть такая штука как микроразметка: http://habrahabr.ru/company/yandex/blog/211638/

Для контактной информации есть микроразметка hCard: https://yandex.ru/support/webmaster/hcard/general.xml

Попробуй-ка добавить ее, чтобы научиться ее использовать.

> font: 16px/1.3 "Lato Regular", arial;


В конце списка должен стоять стандартный шрифт вроде serif.

> .header-container {


> height: 100%;


процентная высота работает только если у всех предков (родитель и далее) элемента высота тоже в процентах или пикселах.

> font: 13px "Lato Black";


Нужно указывать в конце универсальный шрифт

> font-family: "Lato Light";


> font-family: "Lato Black";


я тут подумал, это не очень правильно. Это одно и то же семейство (font-family), просто шрифты имеют разный вес: https://www.google.com/fonts/specimen/Lato

Значит и у себя сделай один шрифт. А то, я подозреваю, вот это вот local("Lato Black") работать не будет.

Про код подключения шрифта: тут конечно http://caniuse.com/#feat=ttf написано что современные браузеры поддерживают ttf, но есть наверно какие-то старые браузеры, и для них пригодится более универсальный синтаксис: http://habrahabr.ru/post/113136/

Тем более что этот синтаксис позволит подключить в новых браузерах WOFF который эффективнее сжат. Почитай какие бывают форматы веб-шрифтов и какие браузеры что поддерживают.

> .button-big {


> width: 200px;


> height: 50px;


Размеры должны определяться текстом + паддингом. Неудобно при смене текста менять еще и CSS.

> border-top-left-radius: 5px;


Есть же просто border-radius который позволяет сразу задать все 4 радиуса

> .services-container::after


Имей в виду что этот синтаксис с 2 доветочиями из CSS3 могут не поддерживать более дрвение CSS2 браузеры вроде IE8.

Насчет адаптивной верстки, может тебе пригодится сайт с размерами экранов разных устройств: http://mydevice.io/devices/

Так, в общем, верстка этого макета у тебя неплохо получилась, и по объему меньше полмегабайта вышло (эх, а были времена, сайт можно было в 100-150 Кб сверстать).

Что насчет ИЕ? Ты смотрел мой урок про тестирование под ИЕ? https://gist.github.com/codedokode/855e3970124687b26a1c

Алсо есть такой (бесплатно можно юзать) сервис: https://www.browserstack.com/screenshots/1766a5eb3f26e63e5db6c8a85f2b04a6f07b5774

Посмотри скриншоты хотя бы там, но имей в виду что если всерьез заниматься фронтендом, надо иметь либо виртуальные машины с ИЕ, либо еще что-нибудь. На modern.ie предлагаются разные варианты решения проблемы.

Если ты заметил синюю рамку на картинках: это нормально и не противоречит стандартам. Ие так выделяет ссылки, и это легко отключить через CSS.

Под ИЕ6/7 я думаю красивую верстку делать не требуется, если просто текст будет читаться то хорошо. А ИЕ8 поддерживает CSS2.1 так что с ним проблемы быть не должно.
https://github.com/never3ver/catsandmice/ #750 #591166
>>587026

В общем, нелогично если ты указываешь $width = 9 а на самом деле это значит 10. Это ведет к ошибкам. Название переменной должно соответствовать тому что в ней хранится. так что в твоем случае надо либо переименовать переменную как $widthMinusOne либо сделать чтобы в ней хранилась настоящая ширина. Первый способ запутывает код, так что лучше исправить чтобы все было нормально.

https://github.com/never3ver/catsandmice/blob/master/classes/World.php#L42

> $key = array_search($animal, $this->critters, TRUE);


> if ($key) {


Тут ошибка. Для самого первого животного $key == 0 и if не сработает. Надо писать $key !== false. Почитай чем отличается == от ===:

http://php.net/manual/ru/language.operators.comparison.php
http://php.net/manual/ru/types.comparisons.php

> return $this->world->getHeight() - min($turns);


Это усложнение. Проще разрешить отрицательные оценки и возвращать -min($turns). Либо считать 1 / $turns.

> https://github.com/never3ver/catsandmice/blob/master/classes/Cat.php#L105


> if ($tempX > $tempY) {


> return $tempX;


Тут можно использовать min() или max() вместо if.

>>587219

По поводу 12 задания. Я подумал, все же позиционироваться относительно p не очень надежно. А если у нас список или абзац с отступом слева? Лучше наверно позиционироваться относительно родителя, в данном случае body.

В остальном все верно.

>>587707

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

> и принципы SOLID KISS, чтобы лучше понимать ООП с конкретными задачами и примерами реализации.


Задачи Вектор и Кошки-мышки из учебника решал для начала?

> Желательно еще на каждый существующий паттерн по задаче и


Это довольно бессмысленно. Паттерны лучше разбрать по примерам использования.
https://github.com/never3ver/catsandmice/ #750 #591166
>>587026

В общем, нелогично если ты указываешь $width = 9 а на самом деле это значит 10. Это ведет к ошибкам. Название переменной должно соответствовать тому что в ней хранится. так что в твоем случае надо либо переименовать переменную как $widthMinusOne либо сделать чтобы в ней хранилась настоящая ширина. Первый способ запутывает код, так что лучше исправить чтобы все было нормально.

https://github.com/never3ver/catsandmice/blob/master/classes/World.php#L42

> $key = array_search($animal, $this->critters, TRUE);


> if ($key) {


Тут ошибка. Для самого первого животного $key == 0 и if не сработает. Надо писать $key !== false. Почитай чем отличается == от ===:

http://php.net/manual/ru/language.operators.comparison.php
http://php.net/manual/ru/types.comparisons.php

> return $this->world->getHeight() - min($turns);


Это усложнение. Проще разрешить отрицательные оценки и возвращать -min($turns). Либо считать 1 / $turns.

> https://github.com/never3ver/catsandmice/blob/master/classes/Cat.php#L105


> if ($tempX > $tempY) {


> return $tempX;


Тут можно использовать min() или max() вместо if.

>>587219

По поводу 12 задания. Я подумал, все же позиционироваться относительно p не очень надежно. А если у нас список или абзац с отступом слева? Лучше наверно позиционироваться относительно родителя, в данном случае body.

В остальном все верно.

>>587707

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

> и принципы SOLID KISS, чтобы лучше понимать ООП с конкретными задачами и примерами реализации.


Задачи Вектор и Кошки-мышки из учебника решал для начала?

> Желательно еще на каждый существующий паттерн по задаче и


Это довольно бессмысленно. Паттерны лучше разбрать по примерам использования.
https://github.com/someApprentice/Cat-and-Mouse #751 #591167
>>588028

Нельзя, но можно открыть новый файл рядом и перетащить слои туда по одному. И может быть еще как-то можно через копировать/вставить.

>>588058

https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/Animal.php#L86

> protected function foundTheNearestAnimal($search) {


> protected function isItNotOneOfTrack($x, $y, $tracks) {


Добавь тайп-хинт array здесь. И везде где они не проставлены.

> //Будет ли лучше\короче обойтись без return true: if (!$isItCorner) return false;?


Лучше написать return $isItCorner;, не понятно зачем вообще тут if.

> https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/Animal.php#L124


Эта строка очень длинная. Нужно разбить ее переносом строки на 4 строки. А после подумай как можно заменить 8 условий на 4 условия. Ну к примеру $x == 1 там повторяется 2 раза.

> https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/Mouse.php#L39


Вот тут не очень понятно как вычисляется число очков. Можешь кратко словами объяснить?

В остальном пока больше замечаний нет.
#752 #591168
>>588070

Чтобы вкладки не мигали, можно сделать фон под ними (.articles) такого же цвета как и они. Для этого конечно надо чтобы .articles соответствовал самой высокой вкладке.

Вот кстати статья, которая может тебе подскажет как это сделать: http://chikuyonok.ru/2009/04/dl-tabs/

> Можно было бы выставить бекграунд у родительского дива, совпадающий с фоном article. Но я не могу задать ему высоту, 0 у него высота.


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

>>588322

Обзорный урок про автоматическое тестирование: https://gist.github.com/codedokode/a455bde7d0748c0a351a

Про хайлоад, почитай для начала это:

http://ruhighload.com/
https://www.insight-it.ru/highload/

>>589005
>>589007

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

Разберись какой кеш и с какими настройками включен в этой CMS.

Тут например https://dev.1c-bitrix.ru/user_help/settings/settings/cache.php написано:

> Очистка кеша:


> если в публичной части сайта происходит POST данных (например, добавление комментария или голосование), то сбрасывается соответствующая часть кеша;



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

Я не знаю какой кеш и как подключен на твоем сайте, тебе придется с этим разобраться самому.
#752 #591168
>>588070

Чтобы вкладки не мигали, можно сделать фон под ними (.articles) такого же цвета как и они. Для этого конечно надо чтобы .articles соответствовал самой высокой вкладке.

Вот кстати статья, которая может тебе подскажет как это сделать: http://chikuyonok.ru/2009/04/dl-tabs/

> Можно было бы выставить бекграунд у родительского дива, совпадающий с фоном article. Но я не могу задать ему высоту, 0 у него высота.


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

>>588322

Обзорный урок про автоматическое тестирование: https://gist.github.com/codedokode/a455bde7d0748c0a351a

Про хайлоад, почитай для начала это:

http://ruhighload.com/
https://www.insight-it.ru/highload/

>>589005
>>589007

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

Разберись какой кеш и с какими настройками включен в этой CMS.

Тут например https://dev.1c-bitrix.ru/user_help/settings/settings/cache.php написано:

> Очистка кеша:


> если в публичной части сайта происходит POST данных (например, добавление комментария или голосование), то сбрасывается соответствующая часть кеша;



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

Я не знаю какой кеш и как подключен на твоем сайте, тебе придется с этим разобраться самому.
#753 #591169
>>589033

> Проверил, таб работает, стрелки нет.


У радиокнопок должно быть одинаковое имя чтобы они были объединены в группу.

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


Но это не дополнительная фича. Это фича которая была изначально и которую сломал твой CSS код.

>>We are Webpaint


> Можно заключить в h1? Если нет, почему?


Можно.

> Слоган, или как это называется. В какой тег его заключать?


div

> Подзаголовок h2? Их может быть несколько в одной секции?


Если у тебя h2 это заголовок секции то логичнее наверно h3

> > Our Featured Works


> Это h2 или h3?


h2

> Если это h2, может тогда заголовки секции services сделать h3, а то меня коробит что куча пунктов в одной секции имеют тот же вес, что и название другой секции.


Да

> Я правильно понимаю логику? h1 для главного заголовка, h2 для названия секций, в случае services названия секции нет, но есть подзаголовки h3.


Да

> Еще вопрос по поводу вертикального выравнивания.


А погугли по словам <вертикальное выравнивание CSS>. Я к сожалению по памяти не помню все их особенности, так что лучше если бы ты для себя собрал все способы и примерно представлял их достоинства и недостатки. Хорошее выравниване есть в flexbox который пока плохо поддерживается, есть еще способ с transform, тоже для новых браузеров.

> Есть ли у этих способов недостатки,


В случае с table недостатки как минимум в том что ее не всегда просто спозиционировать (например может не работать float или абс. поз.), также ты должен помнить что у таблиц width/height понимаются как min-width/min-height если только не поменять table-layout на fixed (это влияет только на ширину).

>>589606

ну значит mysql переоптимизировал, кстати такое редко бывает. Мне почему-то кажется что если выбирать строки по индексу, было бы быстрее, чем обходить таблицу. Подумай можно ли переписать запрос (например заменив WHERE IN на джойн) чтобы он более оптимально выбирал данные.

Хотя вообще медленно/быстро лучше оценивать сделав запрос и посмотрев время. фуллскан таблицы на 200к записей будет заметен даже если все данные в памяти.
#753 #591169
>>589033

> Проверил, таб работает, стрелки нет.


У радиокнопок должно быть одинаковое имя чтобы они были объединены в группу.

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


Но это не дополнительная фича. Это фича которая была изначально и которую сломал твой CSS код.

>>We are Webpaint


> Можно заключить в h1? Если нет, почему?


Можно.

> Слоган, или как это называется. В какой тег его заключать?


div

> Подзаголовок h2? Их может быть несколько в одной секции?


Если у тебя h2 это заголовок секции то логичнее наверно h3

> > Our Featured Works


> Это h2 или h3?


h2

> Если это h2, может тогда заголовки секции services сделать h3, а то меня коробит что куча пунктов в одной секции имеют тот же вес, что и название другой секции.


Да

> Я правильно понимаю логику? h1 для главного заголовка, h2 для названия секций, в случае services названия секции нет, но есть подзаголовки h3.


Да

> Еще вопрос по поводу вертикального выравнивания.


А погугли по словам <вертикальное выравнивание CSS>. Я к сожалению по памяти не помню все их особенности, так что лучше если бы ты для себя собрал все способы и примерно представлял их достоинства и недостатки. Хорошее выравниване есть в flexbox который пока плохо поддерживается, есть еще способ с transform, тоже для новых браузеров.

> Есть ли у этих способов недостатки,


В случае с table недостатки как минимум в том что ее не всегда просто спозиционировать (например может не работать float или абс. поз.), также ты должен помнить что у таблиц width/height понимаются как min-width/min-height если только не поменять table-layout на fixed (это влияет только на ширину).

>>589606

ну значит mysql переоптимизировал, кстати такое редко бывает. Мне почему-то кажется что если выбирать строки по индексу, было бы быстрее, чем обходить таблицу. Подумай можно ли переписать запрос (например заменив WHERE IN на джойн) чтобы он более оптимально выбирал данные.

Хотя вообще медленно/быстро лучше оценивать сделав запрос и посмотрев время. фуллскан таблицы на 200к записей будет заметен даже если все данные в памяти.
#754 #591170
Этот тред закрыт. Пожалуйста переходите в новый >>588512 (OP)

Если я кому-то не ответил, напомните о себе там.
#755 #591177
>>591170
Мой счетчик можешь еще последний раз глянуть на грубые ошибки в проектировании. Сейчас только ридми допишу.
https://github.com/nsdvw/visit-counter
#756 #591186
>>591177

В новом треде глянул мельком.
#757 #591832
Сам, пхп тред, накидайте пожалуйста годных статей про кеширование, постоянно на слуху, что кеширование запросов в бд ускоряет работу сайта, вот решил может ОП или знающие аноны посоветуют литературу на этот счет
#758 #591875
>>591832

Мы уже в новом треде: >>588512 (OP) этот тред закрыт.

> постоянно на слуху, что кеширование запросов в бд ускоряет работу сайта


Это спорное утверждение. Вообще-то в БД уже есть кеш. Скорее всего те кто так говорят плохо разбираются в теме. Лучше оптимизировать запросы так, чтобы в кешировании не было надобности.

для начала можешь почитать слайды из презентации:

https://vimeo.com/66739605
http://www.slideshare.net/custisppt/ss-22208427

Кеширование это крайняя мера для всяких хайлоад сайтов с огромной нагрузкой. На более простых сайтах часто можно обойтись без него или тем, что встроено в фреймворк.
#759 #591879
>>591875
Спасибо огромное за ответ, почитаю сейчас.
#760 #592122
Анон, насколько реально устроиться junior php developer-ом после прохождения 2х месячных курсов. проходили основы, ооп, писали собственный mvc, само собой sql, немного javascript, ajax, jquery.
#761 #592132
>>591167

>> https://github.com/someApprentice/Cat-and-Mouse/blob/master/Classes/Mouse.php#L39


>Вот тут не очень понятно как вычисляется число очков. Можешь кратко словами объяснить?


Берется сумма всех расстояний от видимых кошек, если кошка является ближайшей, то к общей сумме добавляется еще половина расстояния от этой кошки, и если ход не является углом, то к нему добавляется еще половина этой суммы.

Может лучше переделать как ты писал тут? >>586985

>>591167

>В остальном пока больше замечаний нет.


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

К этой задаче я пока возвращаться не хочу и допиливать её на JS. Может быть позже , когда дойдет дело до его изучения.

Следующим шагом я хочу заняться задачей для студентов: https://github.com/codedokode/pasta/blob/master/student-list.md

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

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

Спасибо ограмнющие тебе, господин ОуПи.
#762 #592635
Анон помоги! Только начал учить php.

$c = 10;
$e = 2;
echo "Сумма равна $c + $e " . "<br> Разность равна " . $c - $e . "<br> Произведение равно ". $c * $e ."<br>Частное равно ". $c / $e;

Выводит -

-2
Произведение равно 20
Частное равно 5

Вопрос
Куда деваются текст где сложение и разность? Почему в произведении и делении все нормально?
#763 #592993
>>592635

Виноват приоритет операций.

попробуй сделать

echo ("text" . 1) + 2;
echo "text" . (1 + 2);

Поставь скобки так чтобы операции выполнялись в нужном тебе порядке.
#764 #592999
Этот тред закрыт переходите в новый >>588512 (OP)

>>592122

Я не знаю что вы там проходили так что точно сказать не могу. Попробуй пройти собеседование и узнаешь.

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

>>592132

> Берется сумма всех расстояний от видимых кошек, если кошка является ближайшей, то к общей сумме добавляется еще половина расстояния от этой кошки,


То есть 1.5 × cat1 + cat2 + cat3 + .. + catN (где catN - расстояние до N-й кошки)

Довольно странная сумма на мой взгляд.

Допустим ход А дает такое расстояние до кошек: 1, 4, 4 и число очков 1.5 + 4 + 4 = 9.5
Ход B дает расстояние 2, 2, 3 и сумму 2 × 1.5 + 2 + 3 = 8

Получается ход A навстречу кошке лучше чем ход B?

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

Я уже писал выше, что можно использовать такую формулу:

w1 × a + w2 × b + w3 × c

Где a, b, c - факторы, w1, w2, w3 - их веса (важность)

Ну например первым фактором (a) может быть расстояние до ближайшей кошки
Вторым (b) - среднее расстояние до остальных кошек (среднее, чтобы не зависело от числа кошек)
Третьим (c) - угол это или нет

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

К примему, если b и с меняются от 0 до 10, то мы можем в качестве w1 поставить 20, а w2 и w3 = 1. Тогда изменение фактора a на 1 весит столько же сколько изменение b и c от 0 до 10.

В общем, хотелось бы чтобы ты подумал над этим, придумал формулу, описал ее словами и только потом реализовал в коде.

> Следующим шагом я хочу заняться задачей для студентов


Хорошо

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


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

Вещи, которые ты описал, лучше получатся с использованием хотя бы микрофреймвока Slim, шаблонизатора Twig, то есть лучше бы это прикручивать ко второй задаче про файлообменник. Либо прикрутить микрофрейморк и шаблонизатор к первой задаче.

Переходи в новый тред и вбрось туда ссылку на свой пост в этом треде. Код кошек-мышек я внимательно посмотрю позже.
#764 #592999
Этот тред закрыт переходите в новый >>588512 (OP)

>>592122

Я не знаю что вы там проходили так что точно сказать не могу. Попробуй пройти собеседование и узнаешь.

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

>>592132

> Берется сумма всех расстояний от видимых кошек, если кошка является ближайшей, то к общей сумме добавляется еще половина расстояния от этой кошки,


То есть 1.5 × cat1 + cat2 + cat3 + .. + catN (где catN - расстояние до N-й кошки)

Довольно странная сумма на мой взгляд.

Допустим ход А дает такое расстояние до кошек: 1, 4, 4 и число очков 1.5 + 4 + 4 = 9.5
Ход B дает расстояние 2, 2, 3 и сумму 2 × 1.5 + 2 + 3 = 8

Получается ход A навстречу кошке лучше чем ход B?

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

Я уже писал выше, что можно использовать такую формулу:

w1 × a + w2 × b + w3 × c

Где a, b, c - факторы, w1, w2, w3 - их веса (важность)

Ну например первым фактором (a) может быть расстояние до ближайшей кошки
Вторым (b) - среднее расстояние до остальных кошек (среднее, чтобы не зависело от числа кошек)
Третьим (c) - угол это или нет

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

К примему, если b и с меняются от 0 до 10, то мы можем в качестве w1 поставить 20, а w2 и w3 = 1. Тогда изменение фактора a на 1 весит столько же сколько изменение b и c от 0 до 10.

В общем, хотелось бы чтобы ты подумал над этим, придумал формулу, описал ее словами и только потом реализовал в коде.

> Следующим шагом я хочу заняться задачей для студентов


Хорошо

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


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

Вещи, которые ты описал, лучше получатся с использованием хотя бы микрофреймвока Slim, шаблонизатора Twig, то есть лучше бы это прикручивать ко второй задаче про файлообменник. Либо прикрутить микрофрейморк и шаблонизатор к первой задаче.

Переходи в новый тред и вбрось туда ссылку на свой пост в этом треде. Код кошек-мышек я внимательно посмотрю позже.
Geekbrains vs Специалист #765 #593878
Собсссно вопрос.... Кто что смотрел\проходил и какие реальные отзывы. ИМХО гики не нравятся, до Борисова еще не дошел...
#766 #593888
>>593878

Мы уже в новом треде >>588512 (OP) , здесь никого нету.

Давай там и обсудим эту тему.
Я не был готов к такому. #767 #594672
Двач, спасай, две чашки кофе спасителю.

Определить интерфейс student_interface с методами: show_info, set_debts, show_debts, show_students
В файле index.php описать класс students, который реализует интерфейс student_interface и содержит следующие свойства и методы:
Свойства:
$name - имя студента. Значение свойства должно быть доступно только в контексте класса;
$group - группа. Значение свойства должно быть доступно только в контексте класса;
$n_assignments - количество выполненных заданий;
$n_absents - количество пропущенных лекций;
$debts - boolean, false - нет долгов, true - есть долги;
$n_questions - количество вопросов на зачете.
Константы:
N_LECT - число прочитанных лекций;
N_LAB - число лабораторных заданий.
Методы:
show_info - выводит информацию: имя студента, группу, количество выполненных заданий, количество пропущенных лекций, количество посещенных лекций;
set_debts - устанавливает значение переменной $debts, true - если есть пропущенные лекции и остались невыполненные задания, false - иначе; устанавливает значение $n_questions = числу пропущенных лекций;
show_debts - выводит "нет долгов" если $debts=false, иначе выводит "есть долги" и информацию: количество вопросов на зачете, количество невыполненных лабораторных.
Добавить в класс конструктор, принимающий 4 аргумента: имя студента, номер группы, количество выполненных заданий, количество пропущенных лекций и устанавливающий значение свойств $name, $group, $n_assignments и $n_absents соответственно
Определить метод __clone() так, чтобы при создании копии объекта класса students сбрасывались значения свойств $n_assignments, $n_absents, $debts, $n_questions
Добавить в класс статическое свойство $n_students - счетчик объектов и метод show_students для вывода текущего количества объектов класса students. Добавить деструктор класса и модифицировать конструктор для учета числа объектов
Создать несколько объектов класса, передав в конструктор различные значения параметров. Вывести информацию о студенте (show_info) для произвольного объекта
Создать копию $copy произвольного объекта. Вывести информацию show_info для $copy
Вызвать метод set_debts, а затем вывести долги конкретного студента с помощью show_debts
Создать класс child_students, наследующий класс students. Переопределить метод show_debts таким образом, чтобы при выводе $n_questions учитывались пропуски лекций по-болезни (пропущенная по-болезни лекция считается посещенной). Для этого добавьте в класс child_students свойство $n_reports и переопределите конструктор
С помощью final запретить перегрузку метода show_debts в классе students. Объяснить возникновение ошибки
Я не был готов к такому. #767 #594672
Двач, спасай, две чашки кофе спасителю.

Определить интерфейс student_interface с методами: show_info, set_debts, show_debts, show_students
В файле index.php описать класс students, который реализует интерфейс student_interface и содержит следующие свойства и методы:
Свойства:
$name - имя студента. Значение свойства должно быть доступно только в контексте класса;
$group - группа. Значение свойства должно быть доступно только в контексте класса;
$n_assignments - количество выполненных заданий;
$n_absents - количество пропущенных лекций;
$debts - boolean, false - нет долгов, true - есть долги;
$n_questions - количество вопросов на зачете.
Константы:
N_LECT - число прочитанных лекций;
N_LAB - число лабораторных заданий.
Методы:
show_info - выводит информацию: имя студента, группу, количество выполненных заданий, количество пропущенных лекций, количество посещенных лекций;
set_debts - устанавливает значение переменной $debts, true - если есть пропущенные лекции и остались невыполненные задания, false - иначе; устанавливает значение $n_questions = числу пропущенных лекций;
show_debts - выводит "нет долгов" если $debts=false, иначе выводит "есть долги" и информацию: количество вопросов на зачете, количество невыполненных лабораторных.
Добавить в класс конструктор, принимающий 4 аргумента: имя студента, номер группы, количество выполненных заданий, количество пропущенных лекций и устанавливающий значение свойств $name, $group, $n_assignments и $n_absents соответственно
Определить метод __clone() так, чтобы при создании копии объекта класса students сбрасывались значения свойств $n_assignments, $n_absents, $debts, $n_questions
Добавить в класс статическое свойство $n_students - счетчик объектов и метод show_students для вывода текущего количества объектов класса students. Добавить деструктор класса и модифицировать конструктор для учета числа объектов
Создать несколько объектов класса, передав в конструктор различные значения параметров. Вывести информацию о студенте (show_info) для произвольного объекта
Создать копию $copy произвольного объекта. Вывести информацию show_info для $copy
Вызвать метод set_debts, а затем вывести долги конкретного студента с помощью show_debts
Создать класс child_students, наследующий класс students. Переопределить метод show_debts таким образом, чтобы при выводе $n_questions учитывались пропуски лекций по-болезни (пропущенная по-болезни лекция считается посещенной). Для этого добавьте в класс child_students свойство $n_reports и переопределите конструктор
С помощью final запретить перегрузку метода show_debts в классе students. Объяснить возникновение ошибки
#768 #594688
>>594672

Этот тред закрыт. Здесь никого нет. Все в новом треде: >>588512 (OP)
#769 #594904
Антош выручай. После смены версии пыха перестало работать

Parse error: syntax error, unexpected '[' in

if (in_array($mmmm,["a","b"])) {}
#770 #595330
Поясните за фриланс. Допустим есть заказ на правки в верстке и допиливание функционала. Как это выполняется? Мне доступ к админке что ли дадут? А если я там снесу всё к хуям и редирект на лошадей с хуями поставлю.
#771 #596286
Есть картинка. Нужно из неё сделать 200 картинок с мельчайшими изменениями, незаметными глазу. Т.е. взять пиксель, рандомно изменить значение цвета в пределах, вставить обратно. Либо же просто взять картинку и пересохранить её в таком-то проценте качества, чтобы md5 изменилось. Как это лучше осуществить?
#772 #596795
>>594904
После изменения в нижнюю сторону, что-ли?
Такой синтаксис массивов в 5.4 добавили.
if (in_array($mmmm,array("a","b"))) {}
90 Кб, 600x509
#773 #596954
У кого нибудь была проблема что хром подгружает какую то вашу страничку если просто написать ее в адресной строке? У меня из за этой хуйни вызвался скрипт который добавляет данные в базу.
Какие есть способы для борьбы с этим?
47 Кб, 444x472
#774 #597074
что не так делаю? Надо чтобы каждое предложение начинались с заглавной буквы.
http://ideone.com/0lwFWs
#775 #597158
>>597074
>>596954
>>596795

Этот тред закрыт неделю назад. Тут никого нету. Переходите в новый >>588512 (OP)
62 Кб, 604x604
#776 #599294
>>578124 (OP)
Вкатываемся
Общаемся о пыхе, и не только. Рады всем. Олдфаги обсуждают, нюфаги учатся.
https://telegram.me/joinchat/B7jvXAM6xvnPmfWwDCibPw
#777 #599365
>>599294

Няша, это 63-й тред, а все уже в 65-м. >>597909 (OP)
#778 #599831
>>581361
спасиб
#779 #600216
RewriteEngine on
RewriteRule ^([a-z])& index.php?get=$1 [L]
site.ru/get -> site.ru/?get=get
Не работает. Как правильно?
Тред утонул или удален.
Это копия, сохраненная 9 декабря 2015 года.

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

Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
« /pr/В начало тредаВеб-версияНастройки
/a//b//mu//s//vg/Все доски