Сохранен 780
https://2ch.hk/pr/res/1033564.html
24 декабря Архивач восстановлен после серьёзной аварии. К сожалению, значительная часть сохранённых изображений и видео была потеряна. Подробности случившегося. Мы призываем всех неравнодушных помочь нам с восстановлением утраченного контента!

Клуб изучающих PHP и webdev #92

 Аноним 28/07/17 Птн 20:27:19 #1 №1033564 
14995976883300.png
14995976883311.jpg
14995976883322.jpg
14995976883333.png
Шапка - https://pastebin.com/cHL6CPfd
Прошлый - https://arhivach.org/thread/282397/
Аноним 28/07/17 Птн 21:09:35 #2 №1033594 
Решил задачу про айпад, проверяйте:

http://ideone.com/J6qMaX
Аноним 28/07/17 Птн 21:15:17 #3 №1033599 
>>1033100
>Также, у тебя в коде SQL инъекция, нельзя вставлять данные прямо в запрос

Так норм?

$escaped = pg_escape_string($data);
$query = "INSERT INTO searches (data) VALUES ('{$escaped}') RETURNING id";
Аноним 29/07/17 Суб 15:54:15 #4 №1033907 
>>1033599
php.net/manual/ru/book.pdo.php
Аноним 29/07/17 Суб 16:47:48 #5 №1033942 
>>1033594
Проценты же можно было бы не считать самому же, а в переменную $percent ввести сам процент и посчитать типа как $creditBalance*$percent/100 же.
Аноним 29/07/17 Суб 17:09:28 #6 №1033947 
>>1033942
А можно ли как-то передавать аргумент по умолчанию напрямую?
Вот например print_r(rateBank(1.02, 0, 7777));
Как можно запихнуть туда 7777 третьим параметром, не передавая 0 вторым?
Аноним 29/07/17 Суб 17:19:58 #7 №1033952 
>>1033947
Нет.
Только, если ты переставишь третий параметр на второе место.
Аноним 29/07/17 Суб 17:32:33 #8 №1033965 
>>1033952
Жаль.
Из-за этого можно внезапно обосраться, если по ошибке передать значение параметра.
Аноним 29/07/17 Суб 17:35:05 #9 №1033966 
>>1033965
Ты можешь передавать в функцию JSON в качестве единственного параметра, а уже внутри функции разбирать JSON на массив и проверять, существует ли пара ключ => значение в массиве. Всегда так делаю.
Аноним 29/07/17 Суб 17:39:51 #10 №1033969 
>>1033966

Что мешает вместо JSON сразу передать массив?
Аноним 29/07/17 Суб 17:40:56 #11 №1033970 
>>1033969
Тоже можно.
Аноним 29/07/17 Суб 18:51:38 #12 №1034016 
>>1033966
Наркоман.
>>1033965
Просто на этапе преэктирования все необязательные параметры ставь в конце и давай им дефолтное значение.
Аноним 29/07/17 Суб 18:57:50 #13 №1034020 
>>1034016
>Наркоман
Ваше мнение очень важно для нас. Как думаешь, что будет читабельнее?

function givePassport($name, $surname, $lastname, $age, $city, $region, $country, $birth)

или

function givePassport($data)

?
Аноним 29/07/17 Суб 19:08:41 #14 №1034031 
>>1034020
Ебанат, он задачку из оп-поста решает какой нахуй JSON.

>>1034020
>function givePassport($data)
Лiл.

Будет читабельнее
public function getPassword() : string

Аноним 29/07/17 Суб 19:12:47 #15 №1034034 
Есть ли для PHP аналоги js'овского Babel, чтобы писать на нормальном языке и не блевать от каждой строки, а он бы потом переводил все это в PHP код?
Аноним 29/07/17 Суб 19:14:39 #16 №1034036 
>>1034031
Ты пытаешься съехать с темы, школяр. Вопрос был конкретно о том, как передать в функцию третий параметр, не передавая второй. Я ответил, что можно передать JSON. Либо, как подметил анон, массивом. А ты полез меня оскорблять зачем-то. В принципе, не удивительно. В последнее время неадекватных детей на Дваче всё больше. Спасибо,
Абу!
Аноним 29/07/17 Суб 19:15:21 #17 №1034038 
>>1034034
Ебу я как-то твою мамашу в рот, а через 9 месяцев появился ты.
Аноним 29/07/17 Суб 19:22:45 #18 №1034046 
>>1034038

Прекращайте.

>>1033966

Как я выше написал, вместо JSON уместнее использовать массив, чтобы избежать лишних преобразований.

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

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

Потому, если в примере ниже данные о пользователе используются много где, лучше будет сделать объект Пользователь и передавать его.
Аноним 29/07/17 Суб 21:25:12 #19 №1034123 
Я правильно понимаю, что https://github.com/nikic/PHP-Parser умеет только парсить код в AST и модифицировать его, но не исполнять? То есть если я хочу получить вычисляемое в коде значение, то этот пакет мне не подойдёт. Есть небольшая идея как улучшить отчёт функции assert, сейчас она всегда false возвращает, что неудобно. Было бы круто, если бы она ещё выводила значения переменных, которые использовались в условии assert'а.
Аноним 29/07/17 Суб 21:38:34 #20 №1034131 
>>1034123

Да, чтобы выполнить код, нужно AST преобразовать в строку с кодом и сделать eval.
Аноним 29/07/17 Суб 21:48:55 #21 №1034135 
Аноны, а ОП из предыдущего треда (если этот создал не он) пропал куда-то что ли?
Аноним 29/07/17 Суб 21:50:48 #22 №1034137 
>>1034135

Оп предыдущего треда сидит пока в предыдущем треде.
Аноним OP 29/07/17 Суб 21:51:46 #23 №1034140 
>>1034135
Да, он куда-то пропал и не перекатывал тред, из-за чего он ушел в бамплимит и тот тред теперь трудно найти.
Поэтому я сделал перекат за него.
Аноним 29/07/17 Суб 21:59:47 #24 №1034142 
>>1034135
Он занятой человек и работает много похоже, уже давно не сидит каждый день в тредах. Я вообще удивляюсь как он до сих пор спустя 4-5 лет умудряется заходить и стараться каждому нуфагу дать ответы вываливая большущие такие посты.

>>1034140
Он сам перекатит когда всем там ответит, нуфаг сука. Тут и по 1000 постов треды были и ничего, наоборот хорошо когда он утоплен, в нем нет словестного поноса по 200 постов в день.
Аноним 29/07/17 Суб 22:10:53 #25 №1034150 
>>1034142
>Он сам перекатит когда всем там ответит, нуфаг сука
Почему бы ему отвечать на старые вопросы там, а новые пусть будут скапливаться здесь? Часто в тред люди заходят с напрямую /pr, особенно впервые.
>в нем нет словестного поноса по 200 постов в день
Наоборот же хорошо, может на вопросы будут отвечать и другие люди. Иначе тред какой-то полумертвый получается.
Аноним 30/07/17 Вск 10:06:34 #26 №1034294 
>>1034131
Понял. В таком случае при eval значения всех суперглобальных переменных вроде $_GET и $_POST будут утеряны? Так же как и аргументы командной строки...
На случай, если из моего предыдущего сообщения не очень понятны мои мотивы: я хочу, чтобы зафейлившийся assert выдавал подробную информацию о переменных, участвовавших в условии assert'а. Например:
$a = 10;
$b = 25;
Custom\assert($a >= $b); // должно вывалиться исключение с сообщением "Expected ($a >= $b), $a is 10, $b is 25".
Тут преимущества, что assert'ы выглядят естественно, не нужны эти бесконечные assertCountEquals/assertGreaterThanOrEqual. Мне кажется, что такие assert'ы - изначально путь неправильный.
Аноним 30/07/17 Вск 17:55:57 #27 №1034443 
Что ньюфагу почитать про алгоритмы и структуры?
Чтобы знать как сортировочку написать, там про графы, деревья почитать.
Кормена?
Аноним 30/07/17 Вск 18:43:17 #28 №1034483 
>>1034294

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

eval не меняет суперглобальные переменные или аргументы командной строки.

Насчет того, хорошая ли у тебя идея, не знаю.
Аноним 30/07/17 Вск 19:36:39 #29 №1034527 
>>1033947
Можно в Питоне (Keyword Arguments), в PHP нельзя. Тут https://wiki.php.net/rfc/named_params что-то пытались реализовать, но сейчас всё глухо.

>>1034443
Кормен для новичка не подойдёт, ты бы хоть отзывы почитал (не на этом сайте). Гораздо доступнее учебник: http://aliev.me/runestone/

>>1034483
Без исполнения кода я смогу только фразу "Expected ($a >= $b)" вывести, а хотелось бы включить ещё и значения переменных $a и $b.
eval плохой, когда туда суют пользовательский ввод.
Я сам понимаю, что подводных камней огромное количество и написать такую штуку будет непросто.
Аноним 30/07/17 Вск 21:43:32 #30 №1034588 
Прошу прощения, но шапка, перенесенная на пастебин нечитабельна
Аноним 30/07/17 Вск 23:36:53 #31 №1034668 
мой котик все еще одиноко возглавляет эти треды. ._.
Аноним 30/07/17 Вск 23:53:39 #32 №1034678 
>>1034588
Хорошо, куда ее перенести?
Вернуть как раньше или на гитхаб?
Аноним 31/07/17 Пнд 00:56:20 #33 №1034705 
>>1034678
На гитхаб было бы просто идеально. Особенно если разметить как следует, с заголовками, с картиночками.
Аноним 31/07/17 Пнд 01:28:30 #34 №1034714 
>>1034705
Лучше всего сделать шапку как и было раньше, постом, чтобы не надо было ходить не по каким ссылкам.
Аноним 31/07/17 Пнд 13:02:23 #35 №1034810 
Клуб анонимных геев здесь?
Аноним 31/07/17 Пнд 13:11:47 #36 №1034813 
>>1034810
Здесь просто дауны сидят, тебе сюда: https://2ch.hk/pr/res/1030264.html
Аноним 31/07/17 Пнд 13:31:09 #37 №1034823 
>>1034810
сгинь, безработный студент
Аноним 31/07/17 Пнд 16:20:11 #38 №1034925 
Сделал вам шапку на гитхабе:

https://github.com/phpguron/php_thead/wiki
Аноним 31/07/17 Пнд 20:02:18 #39 №1035041 
>>1034925
Нафиг не нужна, тебе же раз 5 сказали в обоих тредах, что по ссылкам никто ходить не будет. Шапка в ОП-посте придаёт треду ламповость, а ты всё портишь, прекращай.
Аноним 31/07/17 Пнд 20:52:50 #40 №1035065 
Должен признаться, что я пхпшник и я гей.
Аноним 31/07/17 Пнд 22:45:56 #41 №1035171 
Кстати очень годные задачи есть на кодеварс, там именно по программированию, а не по вебмакакингу
Аноним 01/08/17 Втр 04:54:44 #42 №1035335 
>>1035171
Да там годные только для совсем совсем ньюфагов разьве что.
Аноним 01/08/17 Втр 06:22:23 #43 №1035338 
>>1035171
Это какие же? Игру написать, или сеть? По бигдате что-то высчитать? Когда говорят о чем-то крутом, я себе представляю сразу актуальные нерешенные задачи. Или программирование - это пердолиться с тем что уже решено 20 лет назад френкенштейня новый велосипед, под предлогом того что это развивает тебя и без БАЗЫ НИКУДА И НИКАК?
Аноним 01/08/17 Втр 08:03:46 #44 №1035347 
>>1035338
А что в бигдате сложного то? Вообще никогда этого не понимал. Вся сложность в том, что нужно щепетильно оптимизировать, чтобы сократить время перелопачивания бигдаты. Ну и знать буквально 2 приёма которые сокращают время выполнения обхода на 22%. Хотя я почти с дивана говорю, я только 4 терабайта лопатил. Может в больших масштабах всё сложнее?
Аноним 01/08/17 Втр 09:38:42 #45 №1035361 
Аноний, подскажи годный курс-вспоминалку PHP+SQL+JS.
Скоро дипломный экз в специалисте, а я уже нихера не помню, так как работа связана совершенно с другим.
(Ну и доступный, так как смотрю на foreach и нихуища не понимаю)
Аноним 01/08/17 Втр 09:44:42 #46 №1035365 
>>1035361
Перепройди курс специалиста, делов то.
Аноним 01/08/17 Втр 11:34:39 #47 №1035388 
>>1035365
Ну сколько воды льёт Борисов в уши, я бы лучше PHP The Right Way использовал и почитал бы эпизодически Котерова или подобное. А видеокурсы это долго и неэффективно, когда во второй и более раз.
Аноним 01/08/17 Втр 15:26:29 #48 №1035482 
Анончики, помогите пожалуйста. Сделал задачку с циклами, где нужно показать таблицу умножение от 1 до 9. Не получается перенести строчку множителей вместе с произведением.

http://ideone.com/F3qKIr
Аноним 01/08/17 Втр 15:58:58 #49 №1035498 
>>1035482
Там всякие символы перевода каретки и прочая ересь, не слышал?
\n
Аноним 01/08/17 Втр 16:07:14 #50 №1035505 
Untitled.png
>>1035498
Если бы это было так легко сделать, я бы сюда не писал, верно?
Аноним 01/08/17 Втр 16:09:14 #51 №1035506 
>>1035482
>нужно показать таблицу умножение от 1 до 9. Не получается перенести строчку множителей вместе с произведением.
Эх, я сам когда-то таким был, на держи нормальную версию таблицы умножения http://ideone.com/9MobUt
Аноним 01/08/17 Втр 16:11:53 #52 №1035507 
>>1035506
Благодарствую, анон про \r я не знал
Аноним 01/08/17 Втр 16:13:09 #53 №1035509 
>>1035507
С \n на самом деле тоже работает, просто ты его не туда ставишь.
Аноним 01/08/17 Втр 16:14:21 #54 №1035510 
>>1035509
Нужно было в начало ставить? в чём различие между \r и \n?
Аноним 01/08/17 Втр 16:22:27 #55 №1035515 
>>1035510
>Нужно было в начало ставить?
Сам подумай. Спецсимвол разбивает строку ровно в том месте, где ты его поставил.
>в чём различие между \r и \n?
Дела дней давно минувших. Изначально, \r возврат каретки - это переход в начало строки, без перехода на новую строку, а \nперевод строки - переход на новую строку без постановки курсора в начало строки.
Сейчас разницы нет, и то, и то переведет в начало следующей строки.
Аноним 01/08/17 Втр 18:40:28 #56 №1035615 
>>1035515
cпасибо за пояснение
Аноним 02/08/17 Срд 00:38:09 #57 №1035838 
>>1034925
спасибо! Лично мне удобно зафоркать к себе в профиль определенный гайд и следовать ему. Все равно гитхаб часто открыт у меня. Это удобнее, чем метаться между тредами фронт-энда и пхп. Добавил шапку в гитхабе и на двачи не заходишь
Аноним 02/08/17 Срд 09:13:51 #58 №1035930 
>>1035510
С \r и \n интересная история. \r по задумке переводит курсор в начало строки, а \n - на следующую строку. В принтерах это использовалось (и до сих пор работает) для печати одних символов поверх других, например подчеркивания поверх буквы.

В тестовых файлах раньше Маки использовали \r для обозначения конца строки, а линуксы/юниксы - \n. Когда делали ДОС, для совместимости решили там обозначать конец строки как \r\n, и это перекочевало в Windows (например, блокнот исопльзует такой формат). Маки давно уже перешли на \n, так что теперь осталось только 2 варианта - либо \n, либо \r\n. IDE обычно позволяют выбирать вид конца строки, рекомендация PSR рекомендует использовать \n.

\r в консоли переводит курсор в начале строки, что позволяет обновлять информацию, перепечатывя ту же строку заново. Например, для вывода бегущей шкалы прогресса.
Аноним 02/08/17 Срд 09:24:46 #59 №1035936 
>>1035388
>PHP The Right Way
Dzjakuu
Аноним 02/08/17 Срд 09:27:46 #60 №1035937 
>>1035930
> Когда делали ДОС, для совместимости решили там обозначать конец строки как \r\n
Было джва, получилось три, как обычно в таких случаях. Кстати, раз ты такой умный, то может знаешь, что такое вертикальная табуляция (\v)? Я сейчас читаю один любопытный документ (ISO/IEC 14977 ENBF), там встречается описание этого символа. Что такое горизонтальная табуляция - понятно, а что такое вертикальная? И что такое форм фид (\f) заодно?
Аноним 02/08/17 Срд 09:28:27 #61 №1035938 
>>1035937
т.е. EBNF, но не суть
Аноним 02/08/17 Срд 09:29:36 #62 №1035939 
>>1035937
Символ вертикальной табуляции(\v) переводит курсор на следующую позицию вертикальной табуляции, и вывод текста продолжается с этой позиции.
Он указывает число строк, которые должны быть пропущены на странице перед началом печати очередной порции данных.
Этот символ влияет только на печать документов. Он не влияет на вывод текста на экран.
мимокрест
Аноним 02/08/17 Срд 10:41:42 #63 №1035967 
>>1035937
В принтере form feed вызывает переход на новую страницу: https://en.wikipedia.org/wiki/Page_break

Про табы история тут: https://en.wikipedia.org/wiki/Tab_key - исторически в принтерах позиции табуляции задавались механически и горизонтальный/вертикальный таб перемещал печатающую головку к следующей позиции. Использовалось для печати данных в формах.

Ну и про другие управляющие символы тут:

https://en.wikipedia.org/wiki/Control_character
https://en.wikipedia.org/wiki/C0_and_C1_control_codes

Подавляющее большинство из них сегодня не используется.

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

Или другой пример: кодировка ASCII - принята аж в 1963 году, опять же не только для компьютеров, которые тогда только появлялись, а вообще для передачи данных по проводам ( https://en.wikipedia.org/wiki/ASCII ).
Аноним 02/08/17 Срд 10:46:54 #64 №1035973 
>>1035967
Интересно, а по 3d принтерам тоже всякого понапридумывают?
Аноним 02/08/17 Срд 11:00:30 #65 №1035982 
А норм книги для новичков есть? Что там за хуита на пастебине? Ещё и с анимевасяносайтом.
Аноним 02/08/17 Срд 11:27:48 #66 №1036001 
>>1035982
>Что там за хуита на пастебине? Ещё и с анимевасяносайтом.
Вам нужно проследовать обратно в /b. Вы похоже заблудились.
Аноним 02/08/17 Срд 11:49:40 #67 №1036007 
>>1035982
Ты предложи книги, может быть кто-то их уже читал. Вот там выше есть отзыв на "пхп 7 в подлиннике" например >>1033797

Аноним 02/08/17 Срд 12:25:15 #68 №1036024 
>>1035982
>Что там за хуита на пастебине?
Вот новая шапка на гитхабе
https://github.com/phpguron/php_thead/wiki
>с анимевасяносайтом
Вполне себе годный сайт с уроками.
Аноним 02/08/17 Срд 13:25:11 #69 №1036054 
Почему у этого треда PHP ассоциируется с котиками и причем тут Аниме тян?
Аноним 02/08/17 Срд 13:28:20 #70 №1036056 
>>1036054
Скрытая пропаганда руби
Аноним 02/08/17 Срд 15:49:53 #71 №1036119 
Посоны, а по html тоже можно здесь спросить? А то я треда подходящего не нашел
Аноним 02/08/17 Срд 17:59:26 #72 №1036201 
>>1036119
в wrk фронтенд тред
Аноним 03/08/17 Чтв 01:34:58 #73 №1036494 
>>1036119
Можно, веб-разработка же
Аноним 03/08/17 Чтв 01:37:36 #74 №1036501 
>>1033564 (OP)
Существует ли аналог Джавы Раш для пхп?
Аноним 03/08/17 Чтв 03:04:29 #75 №1036525 
http://www.zendexam.com/

Нет ли такого же по 7-му рнр?
Если нет онлайн, где бы спиратить тестовый тест?

Есть несколько приложений на ведроиде, но они дико бесят рекламой, выскакивающей прямо поверх обучения.
Аноним 03/08/17 Чтв 10:11:49 #76 №1036616 
Считается ли нормальной практикой изменение файлов RBAC в Yii2 если меня к примеру не устраивает предоставленный функционал и мне нужно его расширить мне нужны мини-админки для каждого родительского аккаунта, и чтобы он мог создавать роли для дочерних аккаунтов и назначить эти роли своим дочерним аккаунтам, в стандартной комплектации названия ролей теоретически могут конфликтовать? Или нужно пилить отдельный модуль и подключать так же как подключен стандартный?
Аноним 03/08/17 Чтв 10:27:25 #77 №1036623 
>>1036616
Ну очевидно же, что тогда ты не сможешь обновлять стандартную библиотеку
Аноним 03/08/17 Чтв 10:42:15 #78 №1036636 
>>1036623
Ну по факту, её обновления мне будут и не нужны, так как я её всё равно изменю
Аноним 03/08/17 Чтв 12:23:37 #79 №1036689 
>>1036616

Ни в коем случае не меняйте ничего в сторонних библиотеках. Причины:

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

А что тебе мешает сделать изменения средствами, предусмотренными фреймворком? Если ты не в силах разобраться, передай задачу тому, кто может.
Аноним 03/08/17 Чтв 13:21:10 #80 №1036711 
>>1036689
>А что тебе мешает сделать изменения средствами, предусмотренными фреймворком? Если ты не в силах разобраться, передай задачу тому, кто может
При чем тут не в силах разобраться, разобраться можно с чем угодно. Я вот и спрашиваю - нормальный ли вариант взять за основу стандартный модуль RBAC и сделать отдельный модуль изменив то, что мне нужно
Аноним 03/08/17 Чтв 13:24:49 #81 №1036714 
>>1036711
Абсолютно нормально.
Аноним 03/08/17 Чтв 14:57:05 #82 №1036780 
анон, помоги.
Необходимо изучить фреймворк yii. но каких-то хороших уроков или мануалов найти не могу. а для работы требуется его знание. А я по своей глупости сам в нем разобраться не могу.
Знаешь ли что по этой теме и с чего начать?
(студент, знаю ооп, html, php и тд на базовом уровне, ибо лентяй да и соответствующей практики не было)
Аноним 03/08/17 Чтв 15:01:06 #83 №1036786 
>>1036780
Документация на офф.сайте?
Аноним 03/08/17 Чтв 15:05:54 #84 №1036790 
>>1036786
теория.
мне б понять на практике.
там был пример создания их блога, но на 3 пункте при создании выходила ошибка, решить которую я не смог(гугл не помог)
Аноним 03/08/17 Чтв 15:10:38 #85 №1036793 
>>1036790
http://www.yiiframework.com/doc/blog/ ?
ну а чем не практика? ты хочешь туториал, который гарантировано исключит любые твои же ошибки? как это?
Аноним 03/08/17 Чтв 15:18:20 #86 №1036796 
>>1036793
http://www.yiiframework.com/doc/blog/1.1/ru/prototype.auth

вот на этой странице идет настройка Аутентификации. Выполнив все что здесь написано, решил проверить. захожу на сайт. пытаюсь войти. он выдает ошибку, что пароль неверен. Как я понял, он захэшировал пароль в БД, но не хэширует пароль проверяемый с тем, что в БД. Как происходит сравнение паролей не понимаю (да тупой и там на сайте буквально все расписано, но я даун.)
Аноним 03/08/17 Чтв 15:47:20 #87 №1036820 
>>1036796
ну и начинай отлаживать, ты же "знаешь php"
Аноним 03/08/17 Чтв 16:01:02 #88 №1036835 
>>1036820
значит пойду переучивать все с начала самого, и воспользуюсь гайдом с шапки. чувствую себя днищем
Аноним 03/08/17 Чтв 17:39:55 #89 №1037002 
Есть ли в PHP не просто ссылки, а вложенные ссылки? Что-то вроде переменного количества звёзд с Сях.
Аноним 03/08/17 Чтв 18:46:27 #90 №1037064 
Хуй знает сюда ли надо писать
Есть сервак-файлопомойка, на него я заливаю картиночки, выдает прямую ссылку на них. Так вот, втентакле никак не хочет распознавать картинку с ссылки (т.е. скопипастил линк в сообщение, обычно картинка прикрепляется автоматически, а тут нихуя). В чем может быть проблема?
Аноним 03/08/17 Чтв 18:54:19 #91 №1037066 
>>1037064

<head>
<meta property="og:image" content="https://pp.vk.me/c629531/v629531034/3172e/xEBYyER1WE4.jpg" />
<link rel="image_src" href="https://pp.vk.me/c629531/v629531034/3172e/xEBYyER1WE4.jpg">
</head>
Аноним 03/08/17 Чтв 19:36:51 #92 №1037094 
>>1037064
MIME type?
Аноним 04/08/17 Птн 02:55:32 #93 №1037486 
Не пострадает ли мой PhP от того, что вместе с ним я начну повторять C ? Mrmrmrmrmr
Аноним 04/08/17 Птн 02:58:12 #94 №1037488 
Блять тут же HTML синтаксис или [strong]как[/strong] это [em]называется[/em]
Аноним 04/08/17 Птн 03:17:29 #95 №1037497 
>>1037486
Только выиграет.
Аноним 04/08/17 Птн 03:40:16 #96 №1037510 
>>1037497
Спасибо за совет анон, а то Кернигана половину прошел.
Аноним 04/08/17 Птн 09:06:13 #97 №1037565 
IMG20170804042439.jpeg
>>1036525
Бамп...
Аноним 04/08/17 Птн 11:24:52 #98 №1037634 
Помогите советом или еще чем.
нужно написать курсач по php. Но не знаю какую тему выбрать. ничего придумать не могу. Нужно что-то интересное
Аноним 04/08/17 Птн 12:13:00 #99 №1037669 
Как готовится к собеседованию на мидла?
С джуном всё ясно, там всегда стандартный набор и похожие задачи.
А на мидлов всегда всё по разному, не понятно...
Аноним 04/08/17 Птн 12:51:42 #100 №1037680 
>>1037634
Способы ускорения выполнения программ на РНР
Аноним 04/08/17 Птн 13:02:31 #101 №1037686 
>>1037634
блог - самое банальное
если знаешь про long polling, то сделай лобби для онлайн игры. типа, чтобы всё как в вк без обновления
Аноним 04/08/17 Птн 14:33:48 #102 №1037758 
123.JPG
gghg.JPG
Подскажите, застрял на первой задачке про вклад в банке. Если считать по 10% на 10 т.р каждый год то понятно, но если начисление идёт на вклад и на проценты от вклада за предыдущие года то как написать эту формулу? До меня это никак не доходит. И как потом посчитать количество лет до 1 миллиона? count() не считает мб из за того что числа выводятся слитно... [email protected] моё фейкомыло, если не хотите палить ответ в треде.
Аноним 04/08/17 Птн 14:37:53 #103 №1037764 
duckanduniverse-Комиксы-3491752.png
>>1037758
if ( Locale::getDefault() == 'ru-RU' ) {
exit('Произошла инфляция, валюта вклада обесценилась, пенсии отменены, вы проиграли');
}
Аноним 04/08/17 Птн 14:48:08 #104 №1037775 
>>1037764
спасибо помог, прям как оп завещал
Аноним 04/08/17 Птн 15:17:05 #105 №1037789 
>>1037758

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

Вот тут написано как увеличить число на N% https://otvet.mail.ru/question/24786316

Аноним 04/08/17 Птн 17:15:16 #106 №1037905 
как.PNG
пук.PNG
пись.PNG
Я где-то наебался или нет?
Мимохуй
Аноним 04/08/17 Птн 17:59:04 #107 №1037942 
>>1037905
Ты в последнем месяце платишь дважды.
Аноним 04/08/17 Птн 19:48:13 #108 №1038034 
Петухач, как в пхп можно сделать дамп всей бд или отдельных таблиц, как это сделано в phpmyadmin или в миграциях симфони и ларавел? Наверняка же есть простой метод в пару строк.
Аноним 04/08/17 Птн 20:42:43 #109 №1038063 
нид халп. дали задание сделать А/Б тестинг плагин для вордпресса. Дали кучу параметров типа conbersional rate (типа сколько пользователей зашло и откуда и сколько вернулось и купило продукт). Посоны, я в глаза этот А-Б тестинг не видел, как эти параметры высчитывать-та???
Аноним 04/08/17 Птн 22:25:14 #110 №1038131 
Господа помогите пожалуйста. Мне нужно, чтобы value чекбокса содержало value инпута. Как это можно воплотить в жизнь. Через форму не получилось, пытался сделать переменную инпута равной переменной чекбокса и тоже ничего не вышло.

Как то вот так пытался: $order = $amount1; где order это чекбокс, а amount1 это инпут.

<div class="input-group">
<span class="input-group-addon">
<input type="checkbox" class="form" name="order">
</span>
<input type="text" class="form-control" name="amount1">
</div><!-- /input-group -->
Так же пытался вводить в value(чекбокса) пхп код содержащий переменную инпута(тоесть с name инпута) и всё равно ничего, уже все перепробовал и никак.

Опишу даже суть идеи, чтобы было прям вот понятно, что я хочу сделать. Вообщем есть сайт-магазин с мелким оптом. Товар 1 вида но разных цветов поэтому делать корзину ну я считаю незачем. На нем вообщем фотки с цветами и подписан id цвета и внизу есть чекбокс и инпут, в котором по задумке клиент должен вводить количество товара. Далее когда клиент выставит чекбоксы на нужных товарах, а так же выставит количество он доходит до формы оформления и всё это отправляется в базу sql.
Аноним 04/08/17 Птн 23:56:15 #111 №1038177 
>>1038034
Миграции и дампы - вещи разные. Миграции описывают изменения структуры таблиц во времени, дампы содержат ещё и данные в этих таблицах. Если в миграциях происходит наполнение таблиц данными (видел такое), то автор неправильно использует миграции.

> Наверняка же есть простой метод
Да, mysqldump

>>1037486
Будет особенно полезно, если реализуешь хотя бы простые структуры данных на Си (связанные списки, стек, очереди, деревья).

>>1037002
В PHP вообще нет указателей, а указателей на указатели - подавно. Указатель - это переменная, содержащая информацию о том, где в памяти размещён какой-то объект.

>>1037669
А смысл готовиться? Рассказывай о интересных проектах, в которых участвовал, приведи профиль на GitHub'е в порядок. Мидлов не просят сортировки на листочке писать. Да и толковых джунов тоже, если с ними есть о чём говорить.
мимо-джун-прошедший-много-собесов
Аноним 04/08/17 Птн 23:56:50 #112 №1038178 
15018561165041.png
>>1037942
Действительно. Надо было вот так, видимо
Спасибо
Аноним 05/08/17 Суб 00:01:27 #113 №1038185 
>>1038177
>Указатель - это переменная, содержащая информацию о том, где в памяти размещён какой-то объект.
Но ведь любая переменная фактически ссылается на какой-то участок памяти, в котором расположен объект. Ну, в питоне так, по крайней мере, в пхп тоже, вроде.
Аноним 05/08/17 Суб 00:04:51 #114 №1038188 
>>1038185
Пиздец я хуйню написал. Забудьте
Аноним 05/08/17 Суб 12:54:26 #115 №1038407 
Анон, как в пехапе преобразовать структуру типа mysite/mamka.php в mysite/somefolder/mamka/14 ? Во всех нормальных фреймворках это искаропки, а делать такие пути я еще не научился.
Аноним 05/08/17 Суб 13:04:52 #116 №1038413 
>>1038407
https://www.youtube.com/playlist?list=PLSdH7dYnlGYgQ6ElbHRpG2zRXbkgkO3zQ

https://www.youtube.com/playlist?list=PLZFDSY0g9advV820J80psX3aP_oXGQDT2

https://www.youtube.com/playlist?list=PLi3gxGWPyGGRKRn6ThK4ApcmUjN2EOn8x
Аноним 05/08/17 Суб 16:40:04 #117 №1038546 
m1i8wdh-jeg.jpg
>>1038131
зачем вообще обрабатывать этот чекбокс на сервере, если покупатель ввёл количество товара нужного цвета?
Аноним 05/08/17 Суб 18:38:12 #118 №1038628 
>>1038546
потому что я вот так решил и теперь не понимаю, как это сделать(ну я вроде понимаю но чет нихуя не выходит совершенно)
Аноним 05/08/17 Суб 20:01:43 #119 №1038689 
>>1038177
>А смысл готовиться? Рассказывай о интересных проектах, в которых участвовал, приведи профиль на GitHub'е в порядок. Мидлов не просят сортировки на листочке писать. Да и толковых джунов тоже, если с ними есть о чём говорить.
>мимо-джун-прошедший-много-собесов

А вот нет, просят написать какой нибудь запрос, спроектировать структуру проекта и много вопросов по паттернам всяким, олимпиадные задачки попадаются, вопросы по CS.
Для джунов я паттерн собеседований понял, а вот мидлов/суньёров нет.
К тому же, у меня например сейчас считай пустой github, так как моей конторе это не интересно, а свободного времени на реализацию чего-то что можно показать нет.
Аноним 05/08/17 Суб 22:59:13 #120 №1038785 
какие преимущества можно получить, храня сессии в БД, а не в файлах?
Аноним 05/08/17 Суб 23:16:20 #121 №1038790 
>>1038785
Нормальную архитектуру.
Аноним 05/08/17 Суб 23:21:53 #122 №1038794 
>>1038790
нене, конкретику давай, в чём плюс?

доступ к файлам быстрее работает, например.
Аноним 05/08/17 Суб 23:42:56 #123 №1038799 
>>1038794
> нене, конкретику давай, в чём плюс?
Отобразить список залогиненных на сайте пользователей со всей инфой. Гомогенный подход. Для начала тебе пойдет.
Аноним 06/08/17 Вск 00:07:48 #124 №1038807 
В зеленом слонике оказывается есть трейты как в Scala? Почему вы тогда их не используете в своем коде?
Аноним 06/08/17 Вск 01:50:13 #125 №1038841 
>>1038807
Повсюду в Laravel используются. Только вот в трейтах мало хорошего - это по сути автоматизированный копипаст, который неудобно юнит-тестировать: http://blog.ircmaxell.com/2011/07/are-traits-new-eval.html
Пример - Laravel Dusk - пакет для написания браузерных тестов, весь функционал которого построен на трейтах, вот один из них: https://github.com/laravel/dusk/blob/1.0/src/Concerns/InteractsWithElements.php
По коду видно, что трейту нужен какой-то resolver (непонятно какой именно класс), какой-то driver и ещё используется метод waitUsing, который тоже непонятно откуда будет браться. Если не читать весь код трейта, то непонятно какие нужны объекты и методы, чтобы переиспользовать этот трейт. Подход с DI гораздо логичнее, проще, не нарушает инкапсуляцию, не порождает сильную связанность.

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

> у меня например сейчас считай пустой github, так как моей конторе это не интересно
Ей и не должно быть интересно. Но если ты идёшь на мидла без своего кода, который можно показать, то тебя засмеют.
Аноним 06/08/17 Вск 02:44:31 #126 №1038858 
>>1037758
Банковский процент считается так:
A=B(1+%)^n
A, В, % тебе известны. Осталось найти n(кол-во лет )
Аноним 06/08/17 Вск 03:14:35 #127 №1038863 
Анон, в Blade можно запилить блок с форматированием и просто его всюду вставлять с нужными данными? Обычный шаблон тут не подходит, ведь блоков на странице могут быть десятки, компонент, как я понял, опциональная вещь и выводится один или ноль раз.
Аноним 06/08/17 Вск 03:33:44 #128 №1038868 
>>1038863
https://laravel.com/docs/5.4/blade#including-sub-views

Суть в следующем:
1. Создаёшь отдельный blade-файл
2. Подключаешь его в нужных местах с аргументами, как-то так:
@include('macros/button.blade.php', [
'isAdmin' => $isAdmin,
...
])
Аноним 06/08/17 Вск 03:38:23 #129 №1038869 
>>1038868
Спасибо. Сейчас так попробовал, а подшаблон три раза подключился почему-то.
Аноним 06/08/17 Вск 09:26:46 #130 №1038910 
>>1038841
>это база, которую как раз у джунов спрашивают,
У джунов спрашивают про принципы ООП и пузырьковую сортировку.
А не про фабрики, очереди и прочее, и уж точно не просят спроектировать модуль или проект.

Никто не поверит на слово про интересные проекты, всем нужны пруфы или в виде кода(хотя всё равно любят пихать тестовое задание на 5-6 дней работы!) или в виде решения каких то задач на собеседование, что бы посмотреть, как кандидат соображает.
В одной конторе мне дали онлайн тесты лол, там были вопросы в стиле "B наследует A, что выведет метод C". Дропнул их сразу сказав что дальше мне не интересно. И они искали именно Middle PHP программиста.

>Но если ты идёшь на мидла без своего кода, который можно показать, то тебя засмеют.
И когда ты предлагаешь мне пилить свои петпроджекты?
После работы, когда ты уже устал и особо нет сил, к тому же есть ещё и другие дела, или на выходных, когда всё же хочется отдохнуть?
Большинство гитхаб кода людей что я видел, написано ими в рабочее время, для нужд компании. Да и к тому же, как правило народ выкладывает не большие модули, мне кажется по ним сложно сделать вывод о компетентности человека.
Аноним 06/08/17 Вск 11:09:34 #131 №1038926 
>>1038869
Это не нормально, ищи ошибку. Если не установлен laravel-debugbar, то поставь, он показывает отрендереные вьюшки: https://github.com/barryvdh/laravel-debugbar

>>1038910
Спрашивали у меня в аутсорс конторах на джуна как раз про фабрики и очереди. Мне ещё сыграло на руку то, что мог назвать примеры применения тех или иных паттернов в коде Symfony и Laravel (в свободное время просто люблю почитывать исходный код фреймворков, чтобы лучше их понимать). Насчёт свободного времени - понимаю, но ты можешь посидеть недельку-две дома, запилить пару проектов на хорошо знакомых технологиях с тестами. Для толкового мидла это не сложно.
Аноним 06/08/17 Вск 13:16:28 #132 №1038984 
Прошу небольшой помощи:
Есть сайт на yii2, есть модель (в которой есть только tableName(), rules() и attributeLabels() ) вот я захотел расширить эту модель, дописал новые свойства, делаю во вьюхе $form->field($model, 'newProp') и получаю ошибку.
Гугл кидает на перегрузку виртуальных атрибутов (но это ведь не то?)
Аноним 06/08/17 Вск 13:29:40 #133 №1038994 
Ребят, почему про Bootstrap говорят, что он не нужен?
Аноним 06/08/17 Вск 13:31:26 #134 №1038996 
>>1038994
>Включает в себя HTML- и CSS-шаблоны оформления для типографики, веб-форм, кнопок, меток, блоков навигации и прочих компонентов веб-интерфейса, включая JavaScript-расширения.
Лол блядь, что то типа Muse?

Все тот же анон
Аноним 06/08/17 Вск 13:37:40 #135 №1038997 
>>1038996
Это когда кричали, что верстка таблицами не семантична и делали квадратно-гнездовым методом на дивах. Конвейер, короче.
Аноним 06/08/17 Вск 14:21:33 #136 №1039018 
>>1038997
Понял. Но ведь верстка таблицами это тупо, разве нет?
Аноним 06/08/17 Вск 14:23:33 #137 №1039019 
>>1038994
верстальщики выёбываются
Аноним 06/08/17 Вск 14:29:22 #138 №1039026 
Котаны, стоит ли покупать пожизненный доступ https://courses.devu.com/ тут на курсы по SQL, JQuery, JS и т.д? Препод ахуительный просто, объясняет просто пизже любой книги или руководства, даже ресурсы дает. Но жаль, что у него PHP нет. Но вот я думаю, стоит ли оно того?
Аноним 06/08/17 Вск 14:33:46 #139 №1039034 
>>1039018
Гораздо тупее вёрстка таблиц дивами. Видел такое не раз.
Аноним 06/08/17 Вск 15:31:24 #140 №1039074 
Как в MVC заставить пользователя абстрактного класса Controller передавать в шаблон некоторый объект (в моем случае собственный UrlHelper)? Объект используется в базовом twig шаблоне от которого наследуются остальные шаблоны (в нав баре имеются ссылки получаемые через UrlHelper). У твиг есть какой-то для этого функционал? Пока что на ум приходит только использовать декоратор для Twig где в методе Twig::render() в качестве аргумента с массивом шаблон-переменных уже будет urlHelper, а декоратор сделает array_merge() к этому массиву.
Аноним 06/08/17 Вск 16:22:21 #141 №1039110 
Поясните за шаблонизаторы,

они вообще ещё нужны? РНР же и сам нормальный шаблонизатор, по сути, с производительностью в 7 ветке тоже проблем нет. Нужны тогда эти твиги-хуиги?
Аноним 06/08/17 Вск 16:35:25 #142 №1039116 
>>1039110
Вкусовщина, я считаю PHP хорошо справляется.
Аноним 06/08/17 Вск 16:56:40 #143 №1039125 
Анон, расскажи как правильно отлаживать php функции. Допустим, есть проект движок сайта, а в нем в недрах есть функция
[code]
function foo($variable, $array){

}
[/code]
Как можно поставить брейкопоинт на вход этой функции чтобы я мог в окне увидеть значения $variable, $array когда дело дойдет до нее? Чтобы в браузере открыть тестовый домен, а аргументы как-то увидеть не дописывая вручную дамп в файл в эту функцию. Все таки 2017 год уже
Аноним 06/08/17 Вск 19:23:24 #144 №1039253 
>>1038177
>В PHP вообще нет указателей, а указателей на указатели - подавно. Указатель - это переменная, содержащая информацию о том, где в памяти размещён какой-то объект.
"Reference" переводится, как "ссылка", и я о них в мануале читал, их не может не быть. Мануал я на самом деле прочитал, так что просто скажи: есть ли у ссылок более одного уровня.........

Так, стоп, в мануале же ничего не написано об этом.
Аноним 06/08/17 Вск 20:44:54 #145 №1039365 
>>1039034
а как ты предлагаешь делать адаптивные таблицы?
Аноним 06/08/17 Вск 21:05:54 #146 №1039394 
Есть regexp-функция вида
preg_replace( '/(бла-бла)(мяу-мяу)/u', function($2), $string);
То есть, я хочу заменить текст в исходной строке $string на хуйню, которая выцеплена второй подмаской регулярки, но при этом хочу обработать эту хуйню функцией. Пхп не разрешает обрабатывать хуйню функцией, что мне не нравится. Вопрос: как добиться аналогичного эффекта законными средствами? Спасибо.
Аноним 06/08/17 Вск 21:09:46 #147 №1039404 
>>1039394
На самом деле не заменить в исходной строке, а создать новую с заменой в нужном месте, извините за неточность
Аноним 06/08/17 Вск 22:56:22 #148 №1039605 
Сап. Приступил к задаче с циклами.
Цикл просто не запускается, хз почему.
Укажите на ошибку, пожалуйста, пробовал по-всякому вычислить ошибку:
дебагил с помощью echo, но цикл просто не запускается, видимо, ошибка где-то в условиях.
http://ideone.com/bnrFXe
Аноним 06/08/17 Вск 23:00:05 #149 №1039612 
>>1039605
https://secure.php.net/manual/ru/control-structures.for.php
>В начале каждой итерации оценивается выражение expr2. Если оно принимает значение TRUE, то цикл продолжается
Аноним 06/08/17 Вск 23:03:34 #150 №1039614 
>>1039394
В чём проблема перед preg_replace вызвать функцию?
Аноним 06/08/17 Вск 23:06:57 #151 №1039617 
>>1039614
В том, что я с помощью непосредственно регулярок указываю на то, к каким символам в строке применить функцию.
Аноним 06/08/17 Вск 23:08:50 #152 №1039619 
>>1039612
Блин, только что сам открыл другой источник, перечитал и осознал.
Соре за невнимательность, всё получилось!
Аноним 06/08/17 Вск 23:20:15 #153 №1039631 
>>1039617
Тогда я не знаю чем тебе помочь.

Ты можешь, конечно, сначала сохранить те символы в отдельную переменную, обработать функцией, а затем заново выполнить замену.
Аноним 06/08/17 Вск 23:40:07 #154 №1039648 
>>1039631
Впихнул preg_replace_callback(), вопрос снят
Аноним 07/08/17 Пнд 08:15:32 #155 №1039833 
>>1038799
Какого блять начала

В принципе есть смысл лазить в БД лишний раз на каждой странице? Это же медленнее в несколько десятков раз.
Аноним 07/08/17 Пнд 09:05:54 #156 №1039847 
Кто занимался подобным, можете поделиться? - Сложно ли создавать сайты типа Amazon ?
Аноним 07/08/17 Пнд 16:02:28 #157 №1040039 
>>1039847

> Капитализация компании Amazon в ходе торгов 26 июля впервые превысила $500 млрд, передает Financial Times.

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

>>1039833

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

>>1039394

preg_replace_callback. PHP правильно делает что запрещает флаг e, так как это ведет к уязвимостям.

>>1039253

Думаю, нету. Думаю, при попытке взять ссылку на ссылку ты получишь ссылку на конечный объект (попробуй протестировать сам).

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

>>1039125

Да, нужно установить и настроить расширение xdebug (это больно), а потом настроить IDE (или другой клиент xdebug) для взаимодействия с ним. И тогда можно отлаживать код, выполнять пошагово, ставить брейкпойнты и тд.
Аноним 07/08/17 Пнд 16:02:48 #158 №1040040 
>>1039110

Написано подробно на главной твига https://twig.symfony.com/

>>1039074

Есть такие варианты:

- переопределить render($template, $data) в базовом классе, чтобы он туда добавлял нужные переменные
- сделать отдельную функицию renderWithAdditionalVariables(..) которая добавит нужные переменные
- создать отдельный объект Twig_Environment, в него добавить переменные через addGlobal, и этот объект твига уже передать в контроллер с помощью DI (ну или можно в контроллере его и создать)
- сделать отдельный хелпер/контроллер предоставляющий данные для вывода шапки/подвала/меню

Ну и может еще какие-то варианты.

>>1039034

Таблицы надо верстать таблицами, а раскладку делать в CSS. И по моему, таблицы можно через CSS застаивть отображаться как дивы, или нельзя?

>>1039018

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

>>1038994

Я думаю, нужен или не нужен - зависит от ситуации.
Аноним 07/08/17 Пнд 16:03:06 #159 №1040041 
>>1038984

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

>>1038910

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

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

>>1038926

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

>>1038841

Ага, у меня иногда ощущение, что трейты просто пытаются использовать ради того, чтобы они были. Хотя может какие-то случаи для их использования и есть.
Аноним 07/08/17 Пнд 16:03:24 #160 №1040042 
>>1038794

> доступ к файлам быстрее работает, например.
пруфы есть?

>>1038785

Их еще в редисе можно хранить.

>>1038177

Почему же, если мы например миграцией добавляем таблицу стран, почему бы сразу и не заполнить ее, чтобы не надо было делать это вручную?

>>1038131

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

>>1038063

Гуглить, искать статьи, примеры кода и решения

>>1037905

Решается примерно так:

- прибавляем проценты и комиссию к остатку долга (!не вычитаем ничего пока!)
- если остаток маленький, выплачиваем сколько осталось и уходим
- иначе платим 5000

«Платим» здесь значит уменьшаем долг и увеличиваем общую сумму выплаченного.
Аноним 07/08/17 Пнд 16:06:16 #161 №1040045 
>>1034527

> Без исполнения кода я смогу только фразу "Expected ($a >= $b)" вывести, а хотелось бы включить ещё и значения переменных $a и $b.

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

Потому в phpunit используют $this->assertGreaterThen($a, $b);

Ну и еще есть другие варианты (как в JS) вроде Assert($a)->isGreaterThan($b);

Аноним 07/08/17 Пнд 16:09:26 #162 №1040050 
>>1034527

assert($a, '>', $b) - не подходит?

> Тут преимущества, что assert'ы выглядят естественно, не нужны эти бесконечные assertCountEquals/assertGreaterThanOrEqual. Мне кажется, что такие assert'ы - изначально путь неправильный.

Ну они по крайней мере работают.

В твоем подходе проблема в том что надо получить переменные из скопа родительской функции, и я не уверен, что это вообще возможно сделать (хотя надо посмотреть функции - может что-то и есть, в текущей функции можно получить переменные через get_defined_vars)
Аноним 07/08/17 Пнд 18:18:26 #163 №1040138 
>>1040041
>И? Тебе всего лишь нужно ответить на них
Я не жалуюсь, я изначально спрашивал про паттерн собеседований, а потом рассказывал отличие джунских и мидловых собеседований, которые я видел.
Но тестовое задание больше чем на один вечер это перебор.
Я ведь не в одну контору в этот момент собеседуюсь, если каждый даст задание на 16 часов работы, я ни одно не успею, особенно если я не уволился ещё с текущей работы(это вроде нормально).
>Толковый мидл наверно может рассказать о своем опыте работы, о своем вкладе
Нужно поднять скилл красноречия, а то я обычно говорю мол "Чем не занимался, всё говно какое то", хотя это неверно.

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


>Почему же, если мы например миграцией добавляем таблицу стран
Если это константные значения, то не нужно их хранить в базе.
Если нет, то они могут быть не нужны в другом проекте.
Аноним 07/08/17 Пнд 18:20:16 #164 №1040140 
>>1040138
Пиздец, как я криво всё расписал, но вроде ясно.
Аноним 07/08/17 Пнд 23:20:33 #165 №1040356 
Сделал задачку на перевод числительных в текстовый формат. Пришлось попердеть я новичок. Нужны ваши комментарии, где особенно плохой код и почему.
http://ideone.com/V8DrXU
Аноним 08/08/17 Втр 03:56:04 #166 №1040419 
>>1038413
> youtube
А в текстовом формате не завезли?
Аноним 08/08/17 Втр 05:25:01 #167 №1040429 
>>1040039
Ну впринципе логично да. Шикарно наверное быть на месте этих инженеров. Или нет?
Аноним 08/08/17 Втр 07:37:07 #168 №1040462 
Лол, сегодня осознал, что 1000 строчек кода это не так круто как мне казалось раньше. Гораздо круто это когда эти строчки написаны на PHP.
Хм, да и то думаю, что местные ветераны посмеются над этим.
Аноним 08/08/17 Втр 09:00:22 #169 №1040488 
>>1040462
Как-то начал задрачивать phalcon и настрочил 5 тыс. строк кода поверх фреймворка, чтобы получилась CMS на phalcon+mongodb. В итоге запутался в блядских наркоманских депенденси инжекшенах, а также понял, что дебажить это соколиное говно проктически невозможно, т.к. нет php-исходников фреймворка, и не понятно, что за нахуй там в нём происходит. Так и забил.
Аноним 08/08/17 Втр 09:37:58 #170 №1040505 
14921157368850.jpg
Реквестирую гайд по DI для даунов.
Аноним 08/08/17 Втр 09:54:39 #171 №1040511 
>>1040505
Как сделать себе такой вид из окна?
Аноним 08/08/17 Втр 10:13:03 #172 №1040514 
>>1040511
Переехать в Гонконг.
Аноним 08/08/17 Втр 10:20:35 #173 №1040517 
chetayazaebalsy.jpg
ОП, объясни как вообще со Slim'ом работать.
Я создаю свой контроллер, потом свою модель, в модели будут использоваться методы slim. В index.php я создаю объект слима $app = new Slim.
Мне этот $app в $container засунуть и тащить его через всё приложение в аргументах что бы я мог им в модели воспользоваться? FrontConroller>FileDownloadConroller>FileDownloadModel
Я явно делаю всё не так.
Я читал доки, но многое не понятно, собственно что касается DI и Middleware.
Аноним 08/08/17 Втр 10:53:21 #174 №1040525 
>>1040514
Виза нужна? Сколько стоит в месяц сычевальня с таким видом из окна?
Аноним 08/08/17 Втр 11:41:47 #175 №1040549 
>>1040517
>FrontConroller>FileDownloadConroller>
Что-то явно не так, зачем контроллер дёргает контроллер?

>Мне этот $app в $container засунуть и тащить его через всё приложение в аргументах что бы я мог им в модели воспользоваться?
А зачем тебе $app в твоей модели изначально?
Аноним 08/08/17 Втр 12:21:55 #176 №1040588 
>>1040505
https://github.com/codedokode/pasta/blob/master/arch/di.md
Вот же он.
Аноним 08/08/17 Втр 13:21:37 #177 №1040613 
2017-08-08 (1).jpg
Снимок.JPG
>>1040549
>Что-то явно не так, зачем контроллер дёргает контроллер?
Эм, это паттерн вообще такой. Есть главный контроллер, который определяет какому не главному контроллеру передать запрос.

>>1040549
>А зачем тебе $app в твоей модели изначально?
Загрузка файлов осуществляется с использованием возможностей фреймворка.
Аноним 08/08/17 Втр 13:39:29 #178 №1040618 
>>1040488
Я так понял это обычная рутина.
Аноним 08/08/17 Втр 13:46:34 #179 №1040626 
>>1040613
>Эм, это паттерн вообще такой. Есть главный контроллер, который определяет какому не главному контроллеру передать запрос.
Не вижу ни единой причины тебе использовать его. В твоём случае Slim - фронт контроллер.

>Загрузка файлов осуществляется с использованием возможностей фреймворка.
https://www.slimframework.com/docs/cookbook/uploading-files.html
Документация говорит, что то делается в одну строчку
$uploadedFiles = $request->getUploadedFiles();
Т.е. тебе нужен лишь request, а никак не $app. Твои классы не должны зависиоть от $app.

Аноним 08/08/17 Втр 13:49:04 #180 №1040629 
>>1040618
Ну типа да.
Аноним 08/08/17 Втр 14:20:34 #181 №1040646 
Подскажите с 10% и миллионом, пожалуйста.
http://ideone.com/yG2PB6
Аноним 08/08/17 Втр 14:25:04 #182 №1040648 
>>1040525
>Виза нужна?
Две недели без визы можно
>Сколько стоит в месяц сычевальня с таким видом из окна?
Как на пике 2к$ за микростудию в месяц
Если искать не в Гонконге, а в Коулуне - то можно от 1к$.
Аноним 08/08/17 Втр 14:34:47 #183 №1040652 
>>1040648
Дорого.
Аноним 08/08/17 Втр 14:50:34 #184 №1040661 
>>1040646
Мда, echo было внутри цикла, я понял.
Аноним 08/08/17 Втр 15:06:46 #185 №1040679 
Как из контроллера получить содержимое представления в переменную?
Ну то есть обычный require сразу отобразит содержимое файла представления, а если нужно взять шаблон в строку, чтобы передать куда-то дальше (в объект Response например)?

Покопался в исходниках слима, там используют буфферизацию типа
ob_start();
include $template;
$output = ob_get_clean();
return Response($output);

Это общепринятый подход? Я имею ввиду, когда не использую фреймворк типа слима, а только библиотеку HttpFoundation.
Аноним 08/08/17 Втр 15:16:56 #186 №1040690 
>>1040629
Хуя.
Аноним 08/08/17 Втр 23:32:01 #187 №1041066 
Посоветуйте книгу по ларавелю на русском
Аноним 09/08/17 Срд 00:49:10 #188 №1041103 
>>1040626
Если slim - frontcontroller, то мне делать толстый index.php, в котором описывать какому контроллеру отправлять запрос? Все getы и postы обрабатывать в нем?
Аноним 09/08/17 Срд 02:28:02 #189 №1041133 
>>1040505
Смотрю и ссусь, там же так высоко, и как люди работают только.
Аноним 09/08/17 Срд 07:19:22 #190 №1041161 
>>1033564 (OP)
Был же сайт с уроками, куда делся?
Аноним 09/08/17 Срд 07:21:46 #191 №1041162 
>>1041161
http://archive-ipq-co.narod.ru/
Он в пасте.
Аноним 09/08/17 Срд 10:41:55 #192 №1041207 
>>1041103
Ну да. Микрофреймворк, у тебя же не расрастется там проект до тысяч рестов. Да ещё и слой контроллеров достаточно тонкий обычно, ты же там будешь сервисы дёргать, а вся логика в них.
антоны стоит ли учиться навечку в cms? или забить и вкатиться в ворпресст.п.? 09/08/17 Срд 11:31:09 #193 №1041228 
антоны стоит ли учиться навечку в cms?
или забить и вкатиться в ворпресс\т.п.?
Аноним 09/08/17 Срд 11:33:27 #194 №1041230 
>>1041228
сережка стоит тебе учиться в книги?
или забить и вкатиться в романы\т.п.?
Аноним 09/08/17 Срд 11:33:58 #195 №1041232 
>>1041228
Стоит учиться в велосипед
или вкатиться в самокат?
Аноним 09/08/17 Срд 11:34:39 #196 №1041234 
>>1041228
Стоит плавать на байдарках?
Или забить и плавать в надувной уточке?
Аноним 09/08/17 Срд 14:03:27 #197 №1041336 
В чем смысл паттерна Фабрика?
В интернете много примеров шаблонов проектирования, но не объясняется, в чем преимущество их использования.

$factory = new FirstFactory();
$firstProduct = $factory->getProduct(); //в getProduct просто return new FirstProduct
$factory = new SecondFactory();
$secondProduct = $factory->getProduct(); // return new SecondProduct

Что мешает написать new Product прямо, не прибегая к созданию фабрики и вызова ее методов?
Может это сделано, чтобы эта часть кода была универсальной, не требовала правок, ну то есть изменения можно было вносить внутри фабрики, не меняя основной код?
Можно реальный пример, где видны преимущества использования?

Вот еще дурацкий пример
https://habrahabr.ru/sandbox/19322/

$obj = Car_Factory::factory('Big_Car');
$obj -> buildEngine();
$obj -> attachWheels();
$obj -> testing();

Что мешает в первой строчке сделать $obj = new BigCar; ?
Аноним 09/08/17 Срд 14:09:05 #198 №1041337 
>>1041336
>В чем смысл паттерна Фабрика
модно, молодежно
Аноним 09/08/17 Срд 14:10:47 #199 №1041339 
>>1041336
Я использую фабрику в том случае, когда мне требуется создавать много объектов, требующих одинаковой настройки. В этом случае я могу один раз при создании фабрики задать ее параметры и она будет отдавать мне уже правильно настроенные объекты. Я не могу привести пример из мира php, но в JDK можно увидеть пример использования, например, в DocumentBuilderFactory.
>Вот еще дурацкий пример
По ссылке не ходил. Если в этом весь пример, то он действительно дурацкий.
Аноним 09/08/17 Срд 14:14:46 #200 №1041342 
>>1041336
Фабрики нужны для ленивого создания/получения объектов (возможно, с приватным конструктором). Например, ты обращаешься к фабрике:

$doc = Factory::getDocument();

Сам документ может не существовать до этого вызова. А после вызова существует. Повторный вызов Factory::getDocument() возвращает уже имеющийся объект. Кроме того, фабрика, например, может возвращать объект разных классов одним и тем же методом в зависимости от своих настроек. А ещё используются для IoC, которая, как и DI, ломает к хуям всю инкпасуляцию, поэтому не нужна.

Короче, фабрики не нужны.
Аноним 09/08/17 Срд 14:17:14 #201 №1041343 
>>1041342
>Повторный вызов Factory::getDocument() возвращает уже имеющийся объект
Тогда это уже Provider, а не фабрика. Фабрика подразумевает как раз создание нового экземпляра на каждый вызов, кеширование в ее обязанности не входит.
Аноним 09/08/17 Срд 14:21:15 #202 №1041344 
>>1041339
> в том случае, когда мне требуется создавать много объектов, требующих одинаковой настройки
Цикл?
Аноним 09/08/17 Срд 14:22:52 #203 №1041345 
>>1041342
> Повторный вызов Factory::getDocument() возвращает уже имеющийся объект
>>1041343
> Provider
Ты напутал с singleton.
Вообще, призываю новичков критически относиться к ответом ИТТ,
некоторые просто провайдят дремучие заблуждения.

По поводу фабрик, держи пример с описанием: http://ideone.com/h6Kvos
Аноним 09/08/17 Срд 14:23:07 #204 №1041346 
>>1041344
Ну и при чем тут цикл? Мне же не обязательно в одном и том же месте потребуются эти 100500 экземпляров. В одном методе один, в другом методе один, где тут цикл-то?
Аноним 09/08/17 Срд 14:23:51 #205 №1041347 
>>1041343
Ну, ок. Хотя на практике такое называется фабрикой. Например, в джумле:

https://api.joomla.org/cms-3/classes/JFactory.html

Они там в ней собрали говно со всего фреймворка и пользуются этой фабрикой вместо глобалов.
Аноним 09/08/17 Срд 14:26:00 #206 №1041350 
>>1041345
>Ты напутал с singleton.
Я-то не напутал, это он напутал. Фабрика производит на каждый вызов новый экземпляр. Провайдер отдает необходимый результат в ответ на запрос с возможностью кеширования. Синглтон - нечто 100% в единственном экземпляре с ленивой инициализацией.
Аноним 09/08/17 Срд 14:29:12 #207 №1041352 
>>1041347
Ну хорошо, в джумле какой-то Раджеш Кутапали решил, что неплохо было бы назвать это фабрикой. А еще где?
Аноним 09/08/17 Срд 14:29:51 #208 №1041353 
>>1041352
Джумла - это серьёзный игрок в мире PHP так-то.
Аноним 09/08/17 Срд 14:31:35 #209 №1041355 
>>1041353
Ну я не пойму, здесь паттерны обсуждают или... вэйт. Я же в пхп-треде. Ладно, хуй с вами.
Аноним 09/08/17 Срд 14:32:52 #210 №1041356 
>>1041355
Приведи контр-пример тогда, а не требуй дополнительных подтверждений, которых тебе всегда будет мало, и для которых ты найдёшь оправдание в стиле Раджеш Кутапали.
Аноним 09/08/17 Срд 14:37:07 #211 №1041357 
>>1041345
По поводу твоего примера, он тоже ни о чем не говорит, зачем писать
$r = $ShapeFactory->getShape('R');
$s = $ShapeFactory->getShape('S');
$c = $ShapeFactory->getShape('C');

Если можно
$r = new RectangleShape();
$s = new SquareShape();
$c = new CircleShape();

Единственный весомый аргумент, который привели выше, это сложная инициализация объекта, ну то есть когда кроме
$obj = new Obj();
для каждого экземпляра нужна рутина типа
$obj->setProp1();
$obj->setProp2();
$obj->doSmth3();
// 100500 строк кода
Хотя почему бы не перенести эту рутину в конструктор?
Аноним 09/08/17 Срд 14:43:01 #212 №1041360 
>>1041356
При чем тут контр-пример? Речь о терминологии идет. Терминология паттернов описана в книжке от gang of four, предлагаю тебе в нее заглянуть. Сам, кстати, заглянул специально чтобы ткнуть носом, но, как ни странно, не нашел там вообще такого паттерна, как просто фабрика. Тем не менее, если взять абстрактную фабрику, то в ней явно речь идет о том, что каждый вызов порождает новый объект.
>>1041357
>Хотя почему бы не перенести эту рутину в конструктор?
1. Нехуй в конструкторе делать что-то помимо создания объекта.
2. Настраивать, как правило, можно по разному, не будешь же ты 20 аргументов передавать в к-тор на все случаи жизни.
3. В стороннюю либу ты вообще залезть не сможешь.
Аноним 09/08/17 Срд 14:44:49 #213 №1041362 
>>1041357
> можно
> почему бы
Тебя никто не заставляет, можно так и ещё 1001 способом.

Паттерны -- это не законы, которые надо выполнять, а некоторые выработанные шаблоны.
Зачем -- затем, что иногда так удобно. Например, в другой части программы ты не знаешь и не хочешь знать типы фигур, а работаешь с одним объектом -- их фабрикой.
Аноним 09/08/17 Срд 14:48:04 #214 №1041365 
>>1041357
> он тоже ни о чем не говорит
Ничего не говорит тебе, тут же не пример виноват.

> весомый аргумент
как будто тебя тут уговаривают, блять,
ну пожалуйста, используй паттерны, а то 40 лет программирования до этого уйдут в пустую
Аноним 09/08/17 Срд 14:48:26 #215 №1041366 
>>1041352
https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/beans/factory/BeanFactory.html
Такой пример тебя устроит?

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

>>1041360
>1. Нехуй в конструкторе делать что-то помимо создания объекта.
Если после создания твой объект непригоден к использованию, то у тебя хуевый конструктор.

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


Аноним 09/08/17 Срд 14:55:38 #216 №1041373 
>>1041366
> говножаба вместо языка программирования

К тому же твой пример работает против тебя же:
> Return an instance, which may be shared or independent
Аноним 09/08/17 Срд 14:57:04 #217 №1041376 
>>1041357
>для каждого экземпляра нужна рутина типа
>$obj->setProp1();
>$obj->setProp2();
>$obj->doSmth3();
это другой паттерн, http://ideone.com/IrT4LL

>Единственный весомый аргумент
короче, хватит высирать своё детский сад сюда, учи мат.часть, ссука, потом вякай тут про аргументы
Аноним 09/08/17 Срд 14:58:11 #218 №1041379 
>>1041373
> говножаба вместо языка программирования
Пехапе тебе не язык, жаба тебе не язык. Ты из какого треда сюда повыебываться пришёл?

>К тому же твой пример работает против тебя же
Если бы ты хоть что-то написал с использованием Spring, ты бы знал, что большая часть компонентов имеет singleton scope. А так то да: ты там и своих скоупов наклепать можешь, вперёд. От этого фабрика быть фабрикой не перестанет и в банальный сборщик объекта по имени не превратится.
Аноним 09/08/17 Срд 14:58:21 #219 №1041381 
>>1041207
ОП, ты подтверждаешь? Idex будет выполнять роль фронт-контроллера?
Аноним 09/08/17 Срд 15:00:50 #220 №1041383 
>>1041379
> isSingleton(String name)
> Is this bean a shared singleton? That is, will getBean(java.lang.String) always return the same instance?
Но эта фабрика возвращает шаред синглтоны точно так же как Джумла, ссылку на апи которой я тебе давал выше. Что ты хочешь мне доказать?
Аноним 09/08/17 Срд 15:02:37 #221 №1041385 
>>1041383
Так я с тобой и согласен. Я писал тому парню, которому джумловские фабрики - не фабрики.
Аноним 09/08/17 Срд 15:25:13 #222 №1041402 
>>1041336

Вообще, "фабрика" - это функция или объект, создающий другие объекты.

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

class MyFActory { ... }
$myFacrtory = new MyFactory;
$otherObject = new OtherObject;
$otherObject->setFactory($myFactory);
// PROFIT

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

Главное только слишком не увлекаться этими паттернами, а то получится как в статье https://habrahabr.ru/post/153225/

Тут вот https://en.wikipedia.org/wiki/Abstract_factory_pattern приведен хороший пример: фабрика в GUI фреймворке, которая создает разные элементы GUI в зависимости от платформы. также, там в начале в Overview указано, какие проблемы решает паттерн.

Заметь, что есть еще паттерн Factory Method https://en.wikipedia.org/wiki/Factory_method_pattern

Также, можно поискать реальные случаи использования Factory, например в Симфони, таким запросом: https://www.google.ru/search?q=site%3Aapi.symfony.com+factory&btnG=%D0%9F%D0%BE%D0%B8%D1%81%D0%BA&newwindow=1&gbv=1 (понять впрочем будет довольно сложно)

ну и конечно примеры с "машинами", или с кошками, которые наследуются от Животного, они сильно оторваны от реальных примеров кода. На мой взгляд, авторам лучше использовать более реалистичные примеры классов.
Аноним 09/08/17 Срд 15:54:20 #223 №1041418 
>>1041402
>Тогда ты просишь автора библиотеки запилить там фабрику
ахахахахаха
Аноним 09/08/17 Срд 16:08:40 #224 №1041428 
>>1041418
Нервный ребёнок-даун детектед.
Что смешного он написал, по-твоему?
Аноним 09/08/17 Срд 16:11:37 #225 №1041431 
>>1041428
я как автор, тебя бы нахуй послал
Аноним 09/08/17 Срд 16:12:51 #226 №1041432 
>>1041431
ну не все ж такие ебланы
Аноним 09/08/17 Срд 16:23:03 #227 №1041444 
>>1041373

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

Что касается утверждения "фабрика обязана всегда создавать новый объект (а не возвращать ранее созданный)", тут я не уверен, что это должно быть строго так.

Аноним 09/08/17 Срд 16:24:44 #228 №1041446 
>>1041357

Если у тебя буква не задана в коде, а приходит откуда-то, то заменить $r = $ShapeFactory->getShape('R'); на $r = new RectangleShape(); не получится.
Аноним 09/08/17 Срд 16:33:30 #229 №1041450 
Эй, четырехглазые, кто за еду возьмется сайт делать? Функционал: обменник электронных валют. Есть варианты дизайна, есть четкие требования и идеи.
Обоссаные фрилансеры охуели и заряжают неадекватные ценники, поэтому обращаюсь к сосачу.
Деньги готовы платить. Пишите мне на мыло, обсудим [email protected]
Аноним 09/08/17 Срд 16:35:45 #230 №1041451 
>>1041450
>кто за еду возьмется сайт делать?
>Деньги готовы платить.
Чё-т взаимоисключающие параметры.
Олсо, если уж российские фрилансеры для тебя дорого, то я даже не знаю.
Аноним 09/08/17 Срд 16:40:23 #231 №1041453 
>>1041450
>обменник валют
>нет денег на прогера
>нет денег на российского фрилансера
Тебе что, 12 лет и мамка денег на сайт не даёт?
Аноним 09/08/17 Срд 16:46:42 #232 №1041459 
>>1040517

В Слиме контроллеры - это функции которые ты описываешь вместе с роутами ($app->get(роут, контроллер)). По задумке, Слим предназначен для маленьких приложений, где контроллеров мало и они маленькие и прекрасно влезают в один файл.

Однако, можно реализовать и контроллеры в виде отдельных классов. Обрати внимание на этот пункт в мануале: https://www.slimframework.com/docs/objects/router.html#container-resolution

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

> Мне этот $app в $container засунуть и тащить его через всё приложение в аргументах что бы я мог им в модели воспользоваться?
Нет, ты должен передавать в модель только то, что ей нужно, а не весь контейнер с сервисами и настройками. Ты читал мой урок по DI?

> но многое не понятно, собственно что касается DI
читал мой урок по DI? https://github.com/codedokode/pasta/blob/master/arch/di.md

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

Они обычно используются для таких целей:

- логгирование
- отладка (например, дописать в конец страницы все выполненные во время ее генерации SQL запросы)
- кеширование страницы целиком
- сжатие страницы gzip (если клиент поддерживает это)
- фильтрация запросов/ограничение доступа (например ограничение числа запросов с 1 IP за секунду или требование решить капчу перед доступом к сайту)
- иногда для защиты от CSRF (у меня есть урок про CSRF)
- модификация ответа (например: найти все ссылки и что-нибудь к ним дописать)
- шифрование кук: перед обработкой запроса пришедшие куки расшифровываются, а после генерации ответа отправляемые куки зашифровываются, браузер видит зашифрованные куки, а код видит куки в открытом виде. То есть мы добавляем шифрование прозрачно для кода, не требуя его переписывания (правда для того, кто разбирается в коде, это может оказаться сюрпризом)

То есть они работают на уровне протокола HTTP, с запросами, ответами, заголовками. Вот например список middleware в фреймворке Джанго: https://docs.djangoproject.com/en/1.11/ref/middleware/

Попробуй например сделать middleware, которое дает доступ к сайту только после решения капчи.

> Загрузка файлов осуществляется с использованием возможностей фреймворка.
Нужно отделить модель и логику сохранения файла от самого Слима.
Аноним 09/08/17 Срд 16:48:05 #233 №1041460 
>>1041453
>>1041451
Поставили ценник 60к. Это адекватно за одностраничный сайт с готовым дизайном?
Аноним 09/08/17 Срд 16:49:45 #234 №1041461 
>>1040679

Да, если ты не используешь шаблонизатор, только может стоит еще обработку исключений добавить (отменять буферизацию при вылете исключения). Это можно сделать с помощью catch или finally.

Если шаблонизатор, то там обычно есть метод для получения шаблона в виде строки.
Аноним 09/08/17 Срд 16:51:23 #235 №1041463 
>>1040505

За такими пейзажами ехать далеко не надо. Вид почти как в Кудрово, ну может только дома этажей на 5-6 повыше и улица чуть пошире.
Аноним 09/08/17 Срд 16:53:48 #236 №1041465 
>>1041460
Да.
Аноним 09/08/17 Срд 16:59:18 #237 №1041469 
>>1041460
>Поставили ценник всего в 1000$
>Это адекватно?
Ну конечно да.
Аноним 09/08/17 Срд 17:03:19 #238 №1041470 
>>1041460
Ну так-то функция поиска яндекс/google тоже на одной странице умещается. Да и дизайна там немного, можно готовый взять.

Олсо, в цене проекта нужно учитывать не только время работы, а ещё и разбор шизы заказчика, отладку, первичные поддержку и обучение, etc. -- иначе ничего хорошего не выйдет.
Аноним 09/08/17 Срд 17:04:19 #239 №1041471 
>>1041460
Ответ на твой вопрос будет сильно различаться, в зависимости от того, в каком сообществе - заказчиков или фрилансеров - спрашивать.
Аноним 09/08/17 Срд 17:10:42 #240 №1041472 
>>1041470
кокойнить грабер котировок, который их пиздит, схороняет в бд, потом показывает на сраничке. нехуевый такой сайтик.
Аноним 09/08/17 Срд 21:17:13 #241 №1041597 
Короче решил перекатиться из недоФРОНТЕНДЕРА в бекенд, так как хуево с фантазией создания анимашек на сайтах. Выбрал похапе, все правильно делаю?
Аноним 09/08/17 Срд 21:37:05 #242 №1041609 
>>1041597
Вряд ли. Сейчас работаю с проектом, который походу писался во времена PHP 4 (в коде var'ы, идентификатор сессии передаётся через GET-параметр, постоянно натыкаюсь на вот такие шедевры: https://pastebin.com/KhEix3UE ) и как-то кайфа мало.

>>1041472
Разве там просто граббер и не нужно работать с API платёжек для обмена электронных валют?

>>1041066
Доки + исходники. Книги нужно по фундаментальным вещам читать.

>>1041350
> Провайдер отдает необходимый результат в ответ на запрос с возможностью кеширования.
Бред какой-то, есть ссылка на GoF?

>>1041450
> четырехглазые, кто за еду
С таким отношением проследуй вон из треда.
Аноним 09/08/17 Срд 21:45:39 #243 №1041616 
>>1041609
>проектом, который походу писался во времена PHP 4 (в коде var'ы, идентификатор сессии передаётся через GET-параметр, постоянно натыкаюсь на вот такие шедевры: https://pastebin.com/KhEix3UE ) и как-то кайфа мало.

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

someApprentice 10/08/17 Чтв 03:21:19 #244 №1041713 
>>1040027
>То есть, тебе стоило бы для начала хотя бы немного изучить теорию про gpg
Я пытался это сделать, то есть я пробежался по википедии, затем зашел в "Введение" библиотеки, в котором нашел ссылку на проект GnuPG, и в котором была ссылка на этот мануал https://www.gnupg.org/documentation/manuals/gnupg/ , в котором ничего не понятно. Мне почему-то не пришло в голову просто загуглить "gpg manual".

Меня одновременно поражает как легко вы сломали эту библиотеку и и глубоко расстраивает что я не смог сделать это самостоятельно. Я даже не знаю почему мне это сразу не далось. Даже если бы я загуглил "gpg manual" я бы не обратил внимания на вторую ссылку т.к. посчитал бы что это мануал о том как обращаться именно с консольной версией.

Невозможность находить ответ в таких неочевидных местах, это делает мне больно.

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

Исходя из манаула https://www.gnupg.org/gph/en/manual.html#AEN26
При выполнении команды генерации ключа, происходит диалог в котором устанавливаются опции. Чтобы передать все опции программно нужно несколько раз выполнить exec(...)?

Например:
exec("gpg --gen-key");
exec("1"); //DSA and ElGamal
exec("2048"); //keysize
exec("0"); //key does not expire
exec($id); //user ID
exec($password); //passphrase

$privateKey = exec("gpg --armor --export-secret-key {$id}");
$publicKey = exec("gpg --armor --export {$id}");

Я попытался проверить, и в ответ получил пустую строку. Думаю, это потому что нет доступа для пользователя www-data. Загуглив как дать доступ на определённые команды (linux ubuntu) получил результаты как давать разрешения на папку/файлы и как дать доступ к sudo. Загуглив "linux gpg program directory" получил результаты о том как зашифровывать директории. ??? Попробовал поискать эту директорию на диске, получить несколько папок. Для не опытного linux пользователя мне сложно что-то придумать.

Так сложно ещё никогда не было. Я делаю что-то не так?

>You must provide a user ID in addition to the key parameters. The user ID is used to associate the key being created with a real person.
>
>You need a User-ID to identify your key; the software constructs the user id
>from Real Name, Comment and Email Address in this form:
> "Heinrich Heine (Der Dichter) <[email protected]>"
>
>Real name:
Что за глупость? Может мне ещё адрес проживания указать?

К тому же, мне не дали указать "Real name" цифрами, но это ничего т.к. можно указать имейл вместо этого. Нужно ещё указать какой-то comment (зачем это нужно?).

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

Я подумал, что если сделать это через консоль так сложно, то может быть получиться найти библиотеку, которая может сгенерировать ключи. Но с этим тоже не так всё просто, единственную библиотеку которая удалось найти это http://pear.php.net/package/Crypt_GPG/ , но она заявляет что не поддерживает генерацию ключей, хотя такой класс есть:

http://pear.php.net/package/Crypt_GPG/docs/latest/Crypt_GPG/Crypt_GPG_KeyGenerator.html
http://pear.php.net/manual/en/package.encryption.crypt-gpg.generate-key.php
>Crypt_GPG does not yet support generating GnuPG keys. Generating a GnuPG key for use with Crypt_GPG is much the same as generating any other GnuPG key on a system.

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


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

>Вообще, opengpg
Я тоже путаю OpenPGP и GnuPG

OpenPGP, это стандарт не использующий запатентованные алгоритмы

А GnuPG, это его реализация под лицензией GNU General Public License

>Плюс, я тут подумал, может это позволит как-то интегрироваться с GPG, то есть, например, обмениваться сообщениями с теми, кто использует обычную почту с шифрованием через gpg.
Да, я думал что можно ещё использовать мессенджер как почтовый ящик, но это будет уже совсем другая задача. То что вы не только помогаете мне изучать программирование, но и как бы ещё курируете мои проекты, предлагая идеи которые совпадают с моими... это очень мотивирует.
someApprentice 10/08/17 Чтв 03:28:27 #245 №1041714 
Я ещё нечаянно запостил в закрытый тред пару вопросов о частичной подгрузке сообщений >>1040147
Аноним 10/08/17 Чтв 05:24:43 #246 №1041719 
http://ideone.com/0x14nZ
http://php.net/manual/en/spldoublylinkedlist.rewind.php

why.jpg
Аноним 10/08/17 Чтв 05:35:26 #247 №1041720 
>>1041719
Я понимаю что происходит в коде, но я не понимаю чего ты хотел то?
Аноним 10/08/17 Чтв 05:56:37 #248 №1041723 
>>1041720
Я хотел использовать функцию rewind в коде, но не смог. По ссылке - минимальный код с ошибкой.

Какого чёрта ревайнду нужен аргумент?
Аноним 10/08/17 Чтв 05:58:05 #249 №1041724 
14907967490320.jpg
>>1041723
>Я хотел использовать функцию rewind в коде, но не смог.
Ну я даже не знаю.
Аноним 10/08/17 Чтв 05:59:39 #250 №1041725 
Хотел вопрос задать, когда были внедрены псевдо-классы. А потом наткнулся на строчку где об этом написано, они были всегда. Только новые добавлялись с CSS2. Я так понимаю, этой функцией занимался только JS и только потом стали добавлять новые псевдо-классы чтобы не ибаца?
Аноним 10/08/17 Чтв 06:00:28 #251 №1041727 
>>1041724
Ещё раз, для скептиков:
>public void SplDoublyLinkedList::rewind ( void )
>PHP Warning: rewind() expects exactly 1 parameter

Ничего не смущает?
Аноним 10/08/17 Чтв 06:03:19 #252 №1041728 
>>1041727
Ревайнд чего блять?
Аноним 10/08/17 Чтв 06:03:58 #253 №1041729 
>>1041727
Давай по другому. Приведу аналогию чтобы было понятнее.
Ты создаёшь переменную, присваиваешь ей число 1. А потом пытаешься получить то, что было до 1?
Аноним 10/08/17 Чтв 06:04:50 #254 №1041730 
>>1041728
Это какой-то толстый трлоллинг по моему. Я вот тоже не пойму что он в коде то хочет.
Аноним 10/08/17 Чтв 06:15:31 #255 №1041731 
>>1041724
>>1041720
>>1041728
>>1041729
>>1041730
Вы совсем больные? Вы код на идеоне открыли? Я могу сюда запостить его, чтобы вам мышью не кликать лишний раз.
<?php

// your code goes here

$ks=new SplDoublyLinkedList();
$ks.rewind();
?>

И вывод:

PHP Warning: rewind() expects exactly 1 parameter, 0 given in /home/UNfUFN/prog.php on line 6
PHP Recoverable fatal error: Object of class SplDoublyLinkedList could not be converted to string in /home/UNfUFN/prog.php on line 6

На кой ляд ревайнду нужен аргумент, если в мануале написано, что аргументов нет?
Аноним 10/08/17 Чтв 06:18:20 #256 №1041732 
14907971703000.png
>>1041731
Прекрати пожалуйста.
Аноним 10/08/17 Чтв 06:19:24 #257 №1041733 
>>1041731
>>1041729
Аноним 10/08/17 Чтв 06:23:44 #258 №1041734 
>>1041733
>This rewinds the iterator to the beginning.
Вот это я хочу.
Аноним 10/08/17 Чтв 06:28:25 #259 №1041736 
>>1041734
http://ideone.com/2naBpu
Все работает, ты что-то делаешь не так.
Аноним 10/08/17 Чтв 06:31:45 #260 №1041737 
>>1041734
У тебя ничего нет в >beginning
Ты и получаешь ничего.
Аноним 10/08/17 Чтв 06:34:29 #261 №1041738 
>>1041737
>>1041736
>>1041733
>>1041732
>>1041730
>>1041729
>>1041728
>>1041724
>>1041723
>>1041720
Реально больные (и один нормальный, хотя бы попытался помочь). По привычке написал . для обращения к методу вместо -> , а в РНР это конкатенация строк, и никто из вас это не увидел.
Аноним 10/08/17 Чтв 06:37:55 #262 №1041740 
>>1041738
Так ты же сам не обьяснил чего хотел то. А потом удивляешься что никто не смог помочь...
Аноним 10/08/17 Чтв 06:40:05 #263 №1041741 
>>1041740
Я дал ссылку на код с ошибкой и дал ссылку на метод, который я хочу использовать.
Аноним 10/08/17 Чтв 06:42:55 #264 №1041742 
maxresdefault.jpg
d1b47da9340d2b0738626cc90d16ee54.jpg
>>1041741
А, ну тогда всё нормально.
Аноним 10/08/17 Чтв 08:32:41 #265 №1041757 
>>1041738
>вы все пидорасы от вас никако-ко-ko-го толку, я сам в итоге разобрался.
Молодец.
>По привычке написал . для обращения к методу вместо -> , а в РНР это конкатенация строк, и никто из вас это не увидел.
А я сначала прихуел, а потом смотрю что не дает фатал эрора, и подумал что это новомодная плюха в пхп7.1 или типа того, что бы заменять Pidor::ebatsaVSraku на Pidor.ebatsaVSraku
Аноним 10/08/17 Чтв 08:55:22 #266 №1041764 
2.jpg
Снимок.JPG
>>1041459
>Однако, можно реализовать и контроллеры в виде отдельных классов. Обрати внимание на этот пункт в мануале: https://www.slimframework.com/docs/objects/router.html#container-resolution
Кажется я тупой. Как путь к классу прописывать? Почему в доках ни слова про путь? Я уже все возможные пути испробовал, даже этот файл раскидал по всем папкам, может блядь нашёл хотя бы корневую директорию откуда он начинает поиск, но и тут фейл. Полез в гитхаб, стал искать проекты на слиме, нашёл пример в котором использовался данный пример вызова контроллера, но ёбаный врот, там никакой логики в указании пути к контроллеру.
Аноним 10/08/17 Чтв 09:20:22 #267 №1041771 
>>1041764
А всё, он использует пространства времён.
Аноним 10/08/17 Чтв 09:50:57 #268 №1041786 
>>1041719

Сейчас конечно легко говорить, но тебе стоило бы обратить внимание на второе сообщение: PHP Recoverable fatal error: Object of class SplDoublyLinkedList could not be converted to string in /home/UNfUFN/prog.php on line 6

А так, rewind($fd) это функция изменения позиции чтения/записи в открытом файле.

>>1041724
>>1041732

Ваши комментарии пользы не несут и тут не нужны. Идите упражняться в остроумии в любой другой тред.
Аноним 10/08/17 Чтв 09:56:37 #269 №1041790 
>>1041764

Ты смешиваешь разные проблемы. Поиск и загрузка файла с классом - это не задача Слима, он этим не занимается. Этим занимается автозагрузчик, почитай урок https://github.com/codedokode/pasta/blob/master/php/autoload.md

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

Что касается синтаксиса, там в мануале описано, что можно указать в качестве контроллера:

- имя сервиса в контейнере + метод. В этом случае ты можешь задать, как именно будет создаваться объект контроллера, определить его зависимости
- имя класса + метод (Слим создаст объект сам как описано в мануале, передав экземпляр $app в конструктор)
- callable (что это такое, описано в мануале PHP http://php.net/manual/ru/language.types.callable.php)

> Как путь к классу прописывать? Почему в доках ни слова про путь?
Потому что Слим не занимается загрузкой классов и ему неинтересно, где он находится. Он просто создает объект через new.
Аноним 10/08/17 Чтв 10:05:08 #270 №1041793 
Снимок.JPG
2.jpg
>>1041790
>
>- имя сервиса в контейнере + метод. В этом случае ты можешь задать, как именно будет создаваться объект контроллера, определить его зависимости

Всё думал как передать зависимости в контроллер.

Так правильно?
Аноним 10/08/17 Чтв 10:15:19 #271 №1041796 
>>1041793

Имя плохое для сервиса так как похоже на имя класса и создает путаницу. Назови просто file_download_controller или FileDownloadController.

В конструкторе для view надо указать тайп-хинт.
Аноним 10/08/17 Чтв 10:20:19 #272 №1041799 
>>1041796
>Имя плохое для сервиса так как похоже на имя класса и создает путаницу.
Он взял из примера в документации, там именно так и сделали.
Аноним 10/08/17 Чтв 11:37:40 #273 №1041840 
посоны, а зачем приписывать -k в командной строке при установку апача? во всех гайдах это есть, но зачем - не объясняют
Аноним 10/08/17 Чтв 11:58:45 #274 №1041851 
>>1041840

Мануал https://httpd.apache.org/docs/2.4/programs/httpd.html

> -k install|config|uninstall
> Install Apache httpd as a Windows NT service; change startup options for the Apache httpd service; and uninstall the Apache httpd service.

Дополнительно https://httpd.apache.org/docs/2.4/platform/windows.html#winsvc

Чтобы Апач добавил себя в список сервисов (сервисы в Windows - это процессы, которые работают в фоновом режиме, могут стартовать при загрузке ОС: https://ru.wikipedia.org/wiki/%D0%A1%D0%BB%D1%83%D0%B6%D0%B1%D1%8B_Windows )
Аноним 10/08/17 Чтв 12:20:45 #275 №1041866 
>>1041851
вроде разобрался, спасибо
Аноним 10/08/17 Чтв 13:39:12 #276 №1041913 
опчик глянь https://ideone.com/tQKFG0, какой регекс лучше?
Аноним 10/08/17 Чтв 13:41:22 #277 №1041914 
>>1041597
Нахуя тебе бэк? Нахуя тебе пхп? Ничему новому ты не научишься, точно также будешь писать вебговнину, оторванную от сути программирования. Выбирай что-нибудь хардкорное, ту же няшечку, раст, или хотя бы го, и вперед, алгоритмы, хуитмы, интересно же.

мимо фронтендер
Аноним 10/08/17 Чтв 13:46:56 #278 №1041917 
>>1041914
> вебговнину, оторванную от сути программирования
Ловите наркомана.
Аноним 10/08/17 Чтв 13:54:09 #279 №1041927 
>>1041917
В вебе одна часть (фронтенд) оторвана от сути программирования, остальное нет.
Аноним 10/08/17 Чтв 13:58:37 #280 №1041932 
>>1041927
Чем тебе фронтенд не программирование? Или ты считаешь, что крудопараша на беке - это тру, а двигающиеся картинки на фронте - не тру?
Аноним 10/08/17 Чтв 14:13:59 #281 №1041940 
>>1041460
Я вполне допускаю, что даже одностраничный сайт может влететь в копеечку. Если сложный дизайн + мобильный дизайн + дизайн для планшетов. Плюс внутренняя логика.

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

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

вебдев
Аноним 10/08/17 Чтв 14:34:14 #282 №1041949 
>>1041932
В смысле крудопараша? Ты не понимаешь сути бекэнда и никогда не понимал. Нас никто не заставляет выбирать тот или иной фреймворк, также как и тебя не засталяют использовать ангуляр. На бекэнде есть куча вещей, которых никто не видит - парсинги XML файлов, всякие алгоритмы поиска, пагинации, различные абстракции и многое другое.
Аноним 10/08/17 Чтв 15:03:02 #283 №1041959 
>>1041949
Сорян, я бекенд пишу. И всё, что ты описал, вкладывается в слово крудопараша. Парсинг xml ему программирование, а фронтенд нет, я хуею.
Аноним 10/08/17 Чтв 15:15:07 #284 №1041967 
>>1041959
Фронтэнд вообще не нужен, через три года не будет никакого фронтэнда. Только HTML+CSS, джаваскрипт не нужен.
Аноним 10/08/17 Чтв 15:20:08 #285 №1041970 
>>1041967
Апи из css дёргать будешь или из html?
Аноним 10/08/17 Чтв 15:22:27 #286 №1041971 
>>1041970
Лолшто. Какой апи, куда дёргать, что ты несешь, наркоман?
Аноним 10/08/17 Чтв 16:31:25 #287 №1042003 
Подскажите с генератором имен пожалуйста. Как так возможно сделать чтобы рандомный индекс совпадал с рандомным значением? Или и так правильно?
http://codepad.org/g7q1F03u
Аноним 10/08/17 Чтв 16:44:54 #288 №1042008 
>>1042003
> error_reporting(-1);
Да ты охуел.
Аноним 10/08/17 Чтв 17:06:07 #289 №1042016 
CfLOPssUAAA6b4O.jpg:large.jpeg
>>1041970
Всё с тобой, с наркоманом, ясно. Пездуй!
Аноним 10/08/17 Чтв 17:16:22 #290 №1042018 
>>1042008

Что не так?
Аноним 10/08/17 Чтв 17:28:43 #291 №1042028 
пхп про банк.jpg
>>1037758
есть проблема: ответ не совпадает с необходимым, хотя за каждый год добавляется 10% ко вкладу.
У меня выходит 72 года против 49 в учебнике ЧЯДНТ?
Аноним 10/08/17 Чтв 17:31:10 #292 №1042030 
>>1042003
Почему \n не работает на компьютере(sublime xampp)? Приходится использовать <br>, в онлайн редакторах работает нормально.
Про генератор так и не понял, верно или нет.

Шифровка.
http://ideone.com/IEUykS
Аноним 10/08/17 Чтв 17:51:21 #293 №1042043 
>>1042030
> Про генератор так и не понял, верно или нет.
Не совсем понятно, что тебе нужно. Всё правильно же выводит.
Аноним 10/08/17 Чтв 17:58:16 #294 №1042049 
>>1042043
Я не понимаю должно ли и если да, то как сделать чтобы при выводе номера соответствовали слогам по тому порядку, которому они записаны в массиве. Или там смысл просто в рандоме?
Аноним 10/08/17 Чтв 18:01:41 #295 №1042054 
>>1042049
Но они и так соответствуют.
Аноним 10/08/17 Чтв 18:02:39 #296 №1042055 
>>1042028
Попробуй в цикле считать возраст, вместо денег. И используй *=.
Аноним 10/08/17 Чтв 18:05:16 #297 №1042059 
>>1042054
Как?
>Выпало число 2, слог дзу
Слог дзу никак не может быть под индексом два или где я сам себе мозги ебу?
Аноним 10/08/17 Чтв 18:09:26 #298 №1042063 
>>1042059
> $letters = array(
> 'ко', 'и', 'дзу', 'ми',
0 => 'ко', 1 => 'и', 2=> 'дзу', 3 => 'ми'
Аноним 10/08/17 Чтв 18:13:22 #299 №1042064 
>>1042063
Спасибо большое, запомнил теперь про 0. Значит верно.
Аноним 10/08/17 Чтв 18:25:18 #300 №1042069 
>>1042055
спасибо, но проблема оказалась в другом. я вместо 10 тысяч на старте прописал 1
Аноним 10/08/17 Чтв 18:36:55 #301 №1042073 
Как хорошо, что в пыхе нет такой хуйни как тысяча фреймворков
Аноним 10/08/17 Чтв 18:39:17 #302 №1042074 
>>1042073
Есть, как минимум, десяток.
Аноним 10/08/17 Чтв 19:11:08 #303 №1042090 
>>1042030
Лев толстой, но что-то я в начале говно какое-то сделал, а потом только подсказку посмотрел, сейчас буду пытаться сделать по-человечески.
https://ideone.com/WWErg2
Аноним 10/08/17 Чтв 21:26:59 #304 №1042168 
>>1042090
Не понимаю подсказку в уроке, совсем тугой, может кто объяснить?
>В каждый элемент массива мы кладем массив вариантов слова или строки, из которого надо сделать выбор: [$word1, $word2, $word3, ["\n"], ...]
То есть, нужно из этих трех массивов $wordi сделать один, а потом как-то, видимо через foreach пройти и взять по рандомному слову. Но не выходит! через слияние получается чушь. http://ideone.com/7QemuM
Аноним 10/08/17 Чтв 22:09:12 #305 №1042190 
>>1042168
Извиняюсь, засрал тред. Опять Лев Толстой.
https://ideone.com/0TX8fS
Но опять, как я понимаю это не тот способ, что был в подсказке.
Аноним 10/08/17 Чтв 23:54:26 #306 №1042240 
>>1042190
Как же ты меня заебал...

http://ideone.com/1lYYW7
Аноним 11/08/17 Птн 00:10:58 #307 №1042243 
>>1042240
Спасибо. Реально круто!
Аноним 11/08/17 Птн 00:13:35 #308 №1042246 
>>1042168

Идея такая: чтобы не писать руками однотипный код вида:

- выбрать случайно первое слово из первого массива
- выбрать случайно второе слово из второго массива
- ....

Мы вместо этого можем использовать цикл по массиву. То есть мы делаем массив такого вида:

$source = [
[массив вариантов первого слова],
[массив вариантов второго слова],
...
];

И обходим этот массив в цикле. На каждом шаге цикла мы берем массив вариантов N-го слова, выбираем из него одно слово и добавляем в стихотворение.

>>1042240

Давай ты свои негативные эмоции будешь где-нибудь в другом месте изливать?

Также, мне кажется не очень хорошая идея игнорировать часть ошибок с помощью error_reporting (легко убедиться, открыв мануал со списком видов ошибок). Я не понимаю, почему ты не хочешь выводить все ошибки? Не уверен в качестве кода?
Аноним 11/08/17 Птн 00:19:46 #309 №1042251 
>>1042168

Во-первых, операция + не совсем "склеивает" массивы, тебе нужен array_merge, посмотри мануал:

- http://php.net/manual/ru/function.array-merge.php
- http://php.net/manual/ru/language.operators.array.php

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

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

Тебе нужен массив из массивов (двухмерный массив): массив, содержащий в качестве элементов массивы из слов.

$source = [
['abc', 'def'],
['ghi', 'jkl'],
...
];

Аноним 11/08/17 Птн 00:32:35 #310 №1042256 
>>1042246
Тогда последний вариант с циклом - самый подходящий и является близким к верному? Как проснусь буду пробовать через merge. Такое слияние через + увидел у котерова и стал ковырять, а до merge буквально пару страниц не дочитал.
Аноним 11/08/17 Птн 00:46:45 #311 №1042261 
>>1042256

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

>>1042030

\n работает, если открыть в браузере исходный код страницы (Ctrl + U) то там будет виден перенос строки. Просто по правилам языка разметки HTML перенос строки эквивалентен пробелу.

----

Чтобы переносы строк нормально работали и в браузере и в ideone (и в консоли), можно использовать для этого \n, а в начале программы поставить

header("Content-Type: text/plain; charset=utf-8");

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

Иначе перенос строки будет в исходном коде страницы (его можно увидеть нажав Ctrl + U), но на самой странице его не будет.
Аноним 11/08/17 Птн 00:59:31 #312 №1042267 
>>1042030

Расшифровка сделана неправильно: ты расшифровываешь не зашифрованный текст, а исходный. Надо расшифровывать содержимое $cipher

Также, если сделать это исправление, ты увидишь, что твой шифр не расшифровывает все буквы и часто возвращает неверный результат.

>>1042003

Все верно.

>>1041913

> ([ \-()])*
Здесь круглые скобки не нужны

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

Аноним 11/08/17 Птн 01:09:58 #313 №1042271 
>>1041738

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

>>1041725

Что значит "этой функцией занимается JS"? Какой?

Псевдоклассы нужны для применения CSS правил к элементам в определенном состоянии (:hover - при наведении мыши) или в определенном положении (:first-child - первый элемент среди соседних).

Я не знаю точно, когда они появились, но в CSS2 они были, а он был придуман очень давно, лет 10 или 15 назад.


Аноним 11/08/17 Птн 01:22:44 #314 №1042278 
>>1042267
почему {N} к [ \-()] не относится, они же в скобках?
Аноним 11/08/17 Птн 01:51:18 #315 №1042290 
Foreach'ем по строкам нельзя проходиться, да?
Аноним 11/08/17 Птн 04:29:16 #316 №1042313 
изображение.png
>>1042290
Какой сложный вопрос, даже не знаю как долго ты гуглил перед тем как спросить в треде. Ладно уж, помогу перспективному программисту.
Аноним 11/08/17 Птн 04:48:09 #317 №1042318 
>>1041713

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

> Значит нужно будет сгенировать ключ с помощью командной строки... это интересно т.к. открывает простор к ещё большим возможностям. Я ещё не смотрел на php с такой стороны.

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

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

Нет. Каждый новый вызов exec запускает новый процесс. Чтобы передать что-то на вход команде, нужно передать ей данные на стандартный ввод (stdin).

Для начала, стоит разобраться, как работает ввод-вывод в linux. Когда программа хочет прочитать какие-то данные из файла или записать в файл, она открывает файл на запись или чтение (в PHP это делается функцией fopen) с помощью обращения к ядру linux. В случае успеха ядро создает "поток ввода-вывода" (абстракция, в которую можно писать или из которой можно читать данные) и возвращает файловый дескриптор этого потока ввода-вывода - целое число, которое является его идентификатором. Дескрипторы начинаются с нуля, то есть самый первый открытый процессом поток получит дескриптор 0, второй - дескрипитор 1 и так далее. Далее, программа делает чтение или запись вызовом функций fwrite/fread, передавая в них файловый дескриптор. Когда программа закончила операции с файлом, она закрывает (уничтожает) поток вызовом fclose().

В линуксе можно "открыть" на чтение/запись не только обычные файлы, но и так называемые "файлы устройств" (вроде /dev/console, /dev/sda1 или /dev/dsp). Для программы они выглядят как файлы, но чтение/запись в них приводит к передаче данных определенному драйверу устройства в ядре. Ну например, /dev/console соответствует, как следует название, консоли, и чтение/запись с этого устройства приводит к выводу текста в консоль или его вводу с клавиатуры. /dev/sda1 позволяет читать (или перезаписать) содерждимое жесткого диска посекторно, а /dev/dsp раньше позволял передавать данные драйверу звуковой карты и вопроизводить/записывать звук (сейчас это не работает). Есть еще и другие устройства, если интересно:

- https://ru.wikipedia.org/wiki/%D0%A1%D0%BF%D0%B5%D1%86%D0%B8%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D0%B9_%D1%84%D0%B0%D0%B9%D0%BB_%D1%83%D1%81%D1%82%D1%80%D0%BE%D0%B9%D1%81%D1%82%D0%B2%D0%B0
- http://rus-linux.net/lib.php?name=/MyLDP/proc/proc.htm
- http://gentoo.theserverside.ru/book/secrets_of_dev.html

Кроме /dev, есть еще специальные псевдофайлы в /proc, которые при чтении возвращают информацию о запущенных процессах и настройках ядра.

Так вот, даже если программа не открыла ни один файл явно, предполагается, что ей при запуске родитель передаст 3 "стандартных" дескриптора: 0, 1, 2 - стандартный ввод (stdin), стандартный вывод (stdout) и поток для вывода ошибок/отладочных сообщений (stderr). Когда ты запускаешь что-то в консоли, то эти потоки соответствуют либо устройству /dev/ttyN (в случае запуска в реальной консоли) либо /dev/pts/N (эмулятору терминала в случае запуска в GUI терминале). Соответственно, программе не надо думать, откуда ей вводить и куда выводить данные по умолчанию - она использует стндартные потоки.

Ну например, echo в PHP выводит данные в поток 1 (stdout).

В Линукс при создании нового процесса он наследует список открытых файлов (дескрипторов) от родителя, потому какие-то специальные усилия прилагать для передачи этих дескрипторов не требуется. Если ты используешь GUI терминал, то при запуске программа-терминал создает виртуальную консоль (/dev/ptyN), открывает ее на чтение/запись и запускает оболочку (bash например), передавая ей полученные дескрипторы. Ну и соответственно, все, что запускается из bash, наследует эти стандартные дескрипторы, если ты только в команде не задашь перенаправление ввода-вывода.

Увидеть эти потоки можно, набрав команду ls /proc/self/fd -l . ls - это команда вывода списка файлов, однако здесь мы обращаемся к специальной файловой системе proc, которая предоставляет информацию о процессах в виде файлов, в данном случае /proc/self/fd - это псевдокаталог, который содержит "файлы", каждый из которых соответствует открытому файловому дескриптору текущего процесса (процесса ls). Вот что выводится у меня:

0 -> /dev/pts/1
1 -> /dev/pts/1
2 -> /dev/pts/1
3 -> /proc/8200/fd

Мы видим, что потоки 0-2 привязаны к псевдотерминалу, и есть еще поток 3, это видимо поток, открытый программой ls для каких-то своих целей (наверно, это поток для чтения списка файлов в каталоге - в линукс чтение списка файлов в каталоге тоже похоже по сути на чтение файла).

Соответственно, если ты хочешь, чтобы программа читала данные не с клавиатуры, ты должен перенаправить stdin, передав в качестве него дескриптор какого-то файла, например, так: command < file.txt. Тогда она будет читать данные из файла, а не с клавиатуры: http://xgu.ru/wiki/%D0%A1%D1%82%D0%B0%D0%BD%D0%B4%D0%B0%D1%80%D1%82%D0%BD%D1%8B%D0%B5_%D0%BF%D0%BE%D1%82%D0%BE%D0%BA%D0%B8_%D0%B2%D0%B2%D0%BE%D0%B4%D0%B0/%D0%B2%D1%8B%D0%B2%D0%BE%D0%B4%D0%B0

Вот пример команд, которые заставляют bash запустить программу ls с перенаправлением стандартных потоков:

touch /tmp/1.txt
ls /proc/self/fd -l < /tmp/1.txt 2> /tmp/2.txt

lr-x------ 0 -> /tmp/1.txt
lrwx------ 1 -> /dev/pts/1
l-wx------ 2 -> /tmp/2.txt
lr-x------ 3 -> /proc/8206/fd

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

То есть ты мог бы использовать перенаправление, чтобы программа читала данные из файла. Но зачем создавать файл? В Линуксе есть более интересная штука под названием "пайп", точнее, даже 2 штуки:

- просто пайп (pipe), или "анонимный пайп", который создается в памяти
- именованный пайп (named pipe) или FIFO, который создается на диске и нам не очень интересен сейчас

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

Пайп создает bash, когда ты используешь символ | . Например, команда

echo "Yes" | cat

Создаст пайп и 2 дочерних процесса (echo и cat). Она передаст один конец пайпа в качестве stdout для echo, а другой - в качестве stdin для cat.

В PHP пайп создать вручную нельзя. Но там есть 2 интересных функции:

- http://php.net/manual/ru/function.popen.php
- http://php.net/manual/ru/function.proc-open.php

Которые позволяют создать дочерний процесс, связанный через пайп(ы) с родителем. proc_open более гибкая - она позволяет явно указать, какие дескрипторы передать дочернему процессу. Используя ее, ты можешь создать процесс, stdin/stderr/stdout которого соединены пайпами с родителем, и ты получаешь полный контроль над вводимыми/выводимыми данными.
Аноним 11/08/17 Птн 04:48:40 #318 №1042319 
>>1041713

Правда, работать с этими функциями трудно. Ведь чтение/запись идет асинхронно и тебе надо следить за 3 пайпами, при любой ошибке твоя программа заблокируется, перестанет читать/писать в пайпы, и дочерний процесс так же заблокируется в ожидании готовности пайпа. Я когда-то писал такое, и там придется потратить время на отладку. Лучше использовать обертки вроде Symfony Process, которые берут эти сложности на себя и предоставляют простой интерфейс (впрочем, после опыта с ручным написанием я и в нем нашел пару косяков - например, в некоторых случаях передача данных через пайп идет медленно).

Но тут стоит остановиться и посмотреть, а нет ли блоее простого варианта? Может быть, gnupg просто позволяет указать параметры ключа в опциях командной строки? Гугление дает ответ:

- https://www.gnupg.org/documentation/manuals/gnupg/Unattended-GPG-key-generation.html
- https://gist.github.com/woods/8970150

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

Я тут конечно много букв написал, но это в любом случае важно знать, если ты хочешь запускать процессы. Советую поэксперименировать с запуском простых команд linux через Symfony Process, и перехватом их ввода/вывода.

exec() у тебя использован неудачно - ты даже не проверяешь код выхода (exit code) программы. А это надо делать, чтобы отслеживать ошибки при запуске/выполнении дочернего процесса.

В твоем примере ты не перенаправляешь ввод-вывод и процесс gpg унаследует потоки от php. При запуске в консоли он будет пытаться читать данные с консоли, при запуске внутри веб-сервера - читать из того, что сервер поставил себе как stdin.

Вторая команда exec('1') попытается запустить команду '1', это вызовет ошибку, которую ты скорее всего не увидишь, так как не отслеживаешь код выхода и поток ошибок дочернего процесса (разве что в логе ошибок ты увидишь что-то вроде sh: 1: command not found, так как PHP перенаправляет stderr программы в лог ошибок).

> Я попытался проверить, и в ответ получил пустую строку.
Тебе нужно правильно обрабатывать ошибки, чтобы видеть сообщения о них, а не гадать.

> Думаю, это потому что нет доступа для пользователя www-data.
Это вряд ли, так как gpg создает файлы в домашнем каталоге пользователя, который обычно доступен ему на запись. Хотя, кто знает, где у www-data домашний каталог (нужно посмотреть в /etc/passwd).

> Так сложно ещё никогда не было.
Это из-за не очень сильного знания линукса.

> Что за глупость? Может мне ещё адрес проживания указать?
Я думаю, что реальное имя указывать не требуется, ник или числовой id вполне сойдет. Как и email.

> Нужно ещё указать какой-то comment (зачем это нужно?).
Это ведь для почты делалось, чтобы можно было указать имя, ник и адрес email. comment - это, я думаю, ник.

> Ещё нужно сгенерировать рандомное количество байт делая всякие рандомные вещи (нажимать рандомные клавиши, водить мышкой, удалять что-нибудь с диска), что мне не представляется как сделать это программно.
По идее случайные данные должны браться из /dev/random, возможно их там мало и они закончились? тут бы помог аппаратный генератор случайных чисел, но он наверно дорого стоит. В новых серверных процессорах intel такой есть встроенный.

Вот тут вроде похожий случай описан: https://serverfault.com/questions/691120/how-to-generate-gpg-key-without-user-interaction

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

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

- https://habrahabr.ru/company/mailru/blog/273147/
- https://www.linux.org.ru/forum/talks/12608246
- https://wiki.archlinux.org/index.php/Random_number_generation
- https://www.8host.com/blog/ispolzovanie-prostogo-demona-entropii-haveged/

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

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

Главная проблема c созданием своей библиотеки - где гарантия, что ты не допустишь ошибку, которая сделает все шифрование уязвимым? Проекты вроде GnuPG проверяются и анализируются, в отличие от твоего самодельного кода. А в криптографии очень легко допустить ошибку. Если ты занимаешься криптографией, хорошо бы знать хотя бы общие принципы, а также известные атаки, чтобы не оставить уязвимость. Ну или хотя бы использовать проверенный, надежный код.

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

Я тут погуглил, нашел еще это:

- https://paragonie.com/book/pecl-libsodium
- https://github.com/jedisct1/libsodium-php

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

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

Вот еще вопросы на SO:

- https://stackoverflow.com/questions/9262109/simplest-two-way-encryption-using-php

И вот еще, может тут есть что-то полезное: https://www.owasp.org/index.php/Guide_to_Cryptography

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

Аноним 11/08/17 Птн 04:49:15 #319 №1042320 
>>1040147

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

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

class Api {
// Получить последние N сообщений
function loadLastMessages(limit) { ... } // -> Promise<MessageBatch>

// Получить новые сообщения после since через API
function loadNewMessages(since) { ... } // -> Promise<MessageBatch>
}

// Контроллер - пишем код прямо в него, кто нам запретит
class SomeCtrl {
init() {
api.loadLastMessages(SOME_LIMIT).then(
function (batch) {
that.renderBatch(batch); // вывести полученные сообщения
that.queueRefresh(batch.lastUpdate)
},
this.handleLoadError(...).bind(this)
);
}

queueRefresh(lastUpdate) {
setTimeout(function () { that.loadNewMessages(lastUpdate); }, SOME_TIMEOUT);
}

loadNewMessages(lastUpdate) {
api.loadNewMessages(since).then(
function (batch) {
that.renderBatch(batch);
that.queueRefresh(batch.lastUpdate)
},
this.handleUpdateError(...).bind(this)
);
}
}

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

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

Теперь попробуем запилить то же, но с моделью. Мы перенесем получение и обновление данных в модель, и используем паттерн observer (взял первое, что пришло в голову):

class MessageListModel {

construct () {
// Событие получения новых сообщений
this.updateEvent = new EventEmitter;

// Событие изменения статуса связи (успешная/идут ошибки)
// Используется для вывода иконок и уведомлений о проблемах
// с соединением с сервером.
this.statusChangeEvent = new EventEmitter;

// Пдробная информация об ошибках со связью
this.errorEvent = new EventEmitter;

// Время последнего обновления
this.lastUpdate = null;
},
// Подписка на события обновления списка сообщений
// обновления будут приходить только после загрузки
// начальных сообщений
subscribeToUpdates(callback) { // -> eventId
this._startUpdateLoop();
return this.updateEvent.subscribe(callback);
},
// отписка
unsubscribeFromUpdates(eventId) {
this.updateEvent.unsubscribe(eventId);
this._stopUpdateLoopIfNoSubscribersExist(); // надеюсь суть понятна из названия
},
// Получить последние N сообщений
getLastMessages(limit) { // -> Promise<MessageBatch>, никогда не реджектится
var result = new Promise(function (resolve, reject) {
this._loadLastMessages(limit, resolve);
});

return result;
},

// Отправляет запрос на получение сообщений
_loadLastMessages(limit, resolver) {
api.getLastMessages(limit).then(
function (batch) {
this.setConnectionStatus(true);
this.lastUpdate = batch.updateTime;
resolve(batch);
},
function (error) {
this.errorEvent.emit(error);
this.setConnectionStatus(false);
setTimeout(function () {

that._loadLastMessages(limit, resolver);

}, RETRY_TIMEOUT);
}
);
},

// Запускает процесс обновления данных
_startUpdateLoop() {
if (loop is started) {
return;
}

this._queueUpdate();
},

_stopUpdateLoopIfNoSubscribersExist() {
...
},

_cancelUpdateTimeout() {
....
},

_queueUpdate() {
this.timeoutId = setTimeout(
function () { that._loadMoreMessages(); },
SOME_TIMEOUT
);
},

_loadMoreMessages() {
if (!this.lastUpdate) {
// Мы еще не получили начальный набор сообщений
this._queueUpdate();
return;
}

api.loadNewMessages(this.lastUpdate).then(
function (batch) {
this._setConnectionStatus(true);
this.updateEvent.emit(batch, false);
this.lastUpdate = batch.updateTime;
this._queueUpdate();
},
function (error) {
this.errorEvent.emit(error);
this._setConnectionStatus(false);
this._queueUpdate();
}
)
}
}

Тут я вижу недостаточек: мы храним время последнего обновления в поле this.lastUpdate, и это затрудняет понимание кода и проверку правильности. Так как трудно понять, в какой момент там хранится какое значение. Можно ли уже его использовать или нет? Из-за этого мы ставим костыль с проверкой его на не-пустоту в _loadMoreMessages(). То есть везде, где оно используется, мы в теории должны лепить такую проверку, иначе есть риск допустить ошибку.

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

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

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

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

Вот пример использования модели в контроллере. При инициализации мы просто пописываемся на интересующие нас события:

class SomeCtrl {
init() {

this.renderConnectionStatus(STATUS_LOADING);

// Обрабатывать ошибки не требуется, это делает модель
this.msgListModel.getLastMessages(SOME_LIMIT).then(function (batch) {
this.renderInitialMessages(batch);
});

this.msgListModel.onConnectionStatusChange(function (newStatus) {
this.renderConnectionStatus(newStatus);
});

this.msgListModel.subscribeToUpdates(function (batch) {
this.renderNewMessages(batch);
this.deleteOldMessages();
});
}
}

Желательно также во view предусмотреть ограничение числа сообщений и удалять старые по мере добавления новых, чтобы DOM и потребление памяти не росли неограниченно при долгой работе (чем больше узлов DOM, тем медленнее все будет работать).
Аноним 11/08/17 Птн 04:50:13 #320 №1042321 
>>1040147

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

Вообще, код довольно топорный, так что тут можно подумать, как его можно улучшить. Ну например, есть такая штука как "реактивное программирование" (FRP). Не пригодится ли оно тут?

- https://gist.github.com/staltz/868e7e9bc2a7b8c1f754 (я что-то такое вроде читал когда-то, но ничего не помню)
- http://reactivex.io/intro.html
- http://reactivex.io/rxjs/

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

Более того, вроде есть библиотеки и шаблонизаторы, заточенные на работу с Observables.

Соответственно, наш список сообщений может быть смоделирован с помощью observable - первое событие в нем это начальный список сообщений, а последующие события - это обновления. Мы можем представить его как список блоков сообщений (Observable<MessageBatch>), или список отдельных сообщений (Observable<Message>). Что лучше, я не знаю.

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

// Святые угодники, вы только посмотрите на этот интерфейс
// и сравните с первой версией кода!
class MessageListModel {
getMessagesStream(initalCount) { .. } // -> Observable(Message)
getConnectionStatusStream() { ...} // -> Observable(NetworkStatus)
}

class MessageListCtrl {
init(msgListModel) {
msgListModel.getMessagesStream(INITIAL_COUNT).subscribe(function (message) {
this.appendMessage(message);
// можно this.view.appendMessage, это не принципиально
});

msgListModel.getConnectionStatusStream().subscribe(function (status) {
this.displayNetworkStatus(status);
});
}
}

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

Вот тут кстати есть интересный момент. Мы передаем initialCount, значит если мы сделаем 2 вызова:

var stream1 = model.getMessagesStream(10);
var stream2 = model.getMessagesStream(20);

то мы получим 2 независимых потока сообщений. Вопрос: можно ли при этом избежать двойных запросов к API на получение новых сообщений и вместо этого делать один запрос для обоих потоков? Я думаю, что можно, оставим реализацию этого как упражнение читателю.

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

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

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

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

Код наверно съедет, потому вот ссылка на нормальный отформатированный пост с подсветкой: https://gist.github.com/codedokode/6dfde1f0ec3d895bc940b67e7919cc29

Аноним 11/08/17 Птн 04:51:37 #321 №1042322 
>>1042290

Можно наверно, но ты будешь получать байты, а не буквы. Так как в utf-8 буква занимает от 1 до 6 байт, а foreach про это не знает. Смысла нет.
Аноним 11/08/17 Птн 05:05:07 #322 №1042323 
>>1042322

Да нельзя блядь, теоретики хуевы. 1 минуту сука потратить на проверку вида: http://ideone.com/ji1SOx или гуглежку http://php.net/manual/ru/control-structures.foreach.php

Хотя знаешь, твой ответ достоин вопроса, норм высер.
Аноним 11/08/17 Птн 08:45:56 #323 №1042342 
>>1042323
Можно блять.

http://ideone.com/1dfWhm
Аноним 11/08/17 Птн 08:49:04 #324 №1042343 
<form enctype="multipart/form-data" action="__URL__" method="POST">
<!-- Поле MAX_FILE_SIZE должно быть указано до поля загрузки файла -->
<input type="hidden" name="MAX_FILE_SIZE" value="30000" />
<!-- Название элемента input определяет имя в массиве $_FILES -->
Отправить этот файл: <input name="userfile" type="file" />
<input type="submit" value="Send File" />
</form>

Поясните как отправить файл на сервер БЕЗ нажатия на кнопку "отправить", а после выбора файла на компе и нажатия кнопки "открыть".
Все примеры что гуглятся идут именно с такой допотопной системной и сабмитом "отправить".
Аноним 11/08/17 Птн 11:19:02 #325 №1042444 
>>1042342

Разбить строку на массив символов (точнее, unicode codepoints) еще можно так

preg_split('//u', $string, null, PREG_SPLLIT_NO_EMPTY);

// соответствует промежутками между символами и разбивает строку на символы
NO_EMPTY убирает 2 пустых элемента, получающихся в начале и конце массива
Аноним 11/08/17 Птн 12:07:54 #326 №1042463 
>>1042342
>>1042444

--МОЖНО ЛИ ФОРИЧЕМ ОБОЙТИ СТРОКУ
@
-НЕТ, ТОЛЬКО МАССИВ\ОБЪЕКТ, ВОТ ПРУФ:
@
--РЯЯЯ, НЕТ МОЖНО, СМОТРИ КАК Я МОГУ
@
РАЗБИВАЕТ СТРОКУ НА МАССИВ И КОРМИТ ЕГО ФОРИЧУ

Блядь как же я проорал с этой логики, но энивей молодца. В этом и есть дух программизма.
Аноним 11/08/17 Птн 12:24:36 #327 №1042469 
Норот.
Помогите с проблемой.
Кароч есть скрипт для CLI. Изначально был сделан для работы в связке с AJAX. AJAX продолжал вызывать скрипт с разными параметрами, пока не было встречено определенное условие. Затем поставили задачу переделать под работу с CRON. CRON подходит в качестве инициатора, но не связующего звена, т.к. может выполняться не чаще раза в минуту, а скрипт должен вызывать сам себя, как только текущая операция завершена.
Сделал следующее:
передал register_shutdown_function коллбэк, в котором делаю дисконнект с БД и затем использую команду passthru, чтобы начать следующую итерацию.
В итоге столкнулся с проблемой "открыто слишком много файлов". Скрипт выполняет под рутом и где-то на 50-ой итерации php крашится, т.к. рут превышает ulimit использования файлов.
Подозреваю, что это вызвано тем, что изначальный скрипт никогда толком не завершается и ждет результата выполнения passthru. По сути, получается рекурсия, которая сжирает ресурсы.
Вопрос: как решить задачу связывания вызовов скрипта и при этом высвобождать ресурсы?
Аноним 11/08/17 Птн 13:00:50 #328 №1042486 
>>1042469
Где-нибудь вне функции:

while(true) {
myFunc();
}
Аноним 11/08/17 Птн 13:07:47 #329 №1042492 
>>1042486
>>1042469
В общем, на freenode ##php порекомендовали в passthru передавать в следующем виде
>nohup php thescript.php >/dev/null 2>&1 &
Таким образом вывод от работы скрипта уходит "в никуда", а сам скрипт запускается в фоновом режиме. инициатор получает пустой вывод от работы вызванной команды и благополучно закрывается.
Аноним 11/08/17 Птн 13:10:55 #330 №1042494 
>>1042492
PHP-то всё равно падать будет (только теперь ты об этом не узнаешь).
Аноним 11/08/17 Птн 13:11:27 #331 №1042495 
>>1042486
Не сработает это. У него скрипт тупо превысит лимит выполнения и тупо крашнется или если быть упоротым и пытаться бесконечно выполнять скрипт отключив лимиты в конфигах, то всё равно похоже дело не взлетит. Идеально конечно же дергать пхп аяксом, и получая ответ о завершении дергать опять и так до бесконечности.

Вот нагуглил тему, советую прочитать. https://php.ru/forum/threads/beskonechnyj-skript-kak-sdelat.29629/page-2 Там автор как-то замутил что бы два скрипта дергали сами себя по кругу, мб нашему товарищу это подойдет.
В итоге полагаю что проблема засерания памяти и краша из-за превышения таймаута исчезает.
Аноним 11/08/17 Птн 13:13:29 #332 №1042496 
>>1042495
set_time_limit(0);
Аноним 11/08/17 Птн 13:14:57 #333 №1042497 
>>1042496
Я хоть погуглил, а ты хуй. Иди на себя.
Аноним 11/08/17 Птн 13:21:05 #334 №1042501 
>>1042497
Какое-то окаменевшее говно мамонта за прошлый век нашел и сидит довольный.
Аноним 11/08/17 Птн 13:32:17 #335 №1042506 
>>1042501
>Думает что с каждой версией пхп кто-то будет переписывать какие-то фундаментальные вещи.

Ебать ору с дауна.
Аноним 11/08/17 Птн 13:34:53 #336 №1042507 
>>1042506
Дебил? Дебил.
Аноним 11/08/17 Птн 13:36:34 #337 №1042509 
>>1042267
Про расшифровку очень сложно, он проходит по символу например "1185" и дешифрует как "11_8_5, вместо "1_18_5". Как жить то? Логика не ясна
http://ideone.com/a74KGq
Аноним 11/08/17 Птн 14:03:23 #338 №1042533 
>>1042494
Тесты показали, что не падает. Благополучно работает. Вывод в файл сделал. Туда же можно отладочную инфу.
Аноним 11/08/17 Птн 16:12:39 #339 №1042596 
>>1042469

Это все кривые костыли. Во-первых, зачем register_shutdown, когда можно просто вызывать код в цикле? Какое-то переусложнение, не говоря о том, что такое использование resgister_shutdown вообще не предусмотрено.

Если тебе надо выполнять задачи в фоне, то нужен демон вроде gearman https://ruhighload.com/index.php/2010/07/09/gearman-%D0%B8-php-%D0%B0%D1%81%D0%B8%D0%BD%D1%85%D1%80%D0%BE%D0%BD%D0%BD%D1%8B%D0%B5-%D0%B7%D0%B0%D0%B4%D0%B0%D1%87%D0%B8/

Он вроде даже позволяет отслеживать прогресс выполнения фоновой задачи.

Ну и конечно, надо проверить, что там задачи не теряются даже при ошибках, падениях скрипта и тд.
Аноним 11/08/17 Птн 16:19:04 #340 №1042599 
>>1042509
>Логика не ясна
Ну ты сам сделал такой шифр который можно обратно понимать двусмысленно.
у тебя are превращается в 1185 который можно дешифровать в итоге двумя способами.

Судя по твоему примеру компилятор делает замены в словах с конца, при этом ищет наиболее длинное совпадение.
То есть он видит 1185
и сначала видит что есть 5, для неё есть замена в твоем шифре - e
идет дальше, смотрит есть ли для комбинации из 5 и предудущего символа замена - для 85, такой не находит. Значит решает что 5 - это e

Ок го некст - 8 это h
Но после этого он опять идет проверять дальше, и смотрит что есть замена не просто для 8, а для 18, а вот для 118 уже нету и стало быть решено что 18 меняем на r

Ну и остается только 1, которую никуда не деть кроме как заменить на a

Вот малость подшаманил с твоим кодом, и смотри что получается: http://ideone.com/0q49n2

Всё так и работает. Ищет совпадения начиная с конца а не с начала. В общем у тебя ошибка не в коде, а в логике шифра, что ты допустил двусмысленность.
Аноним 11/08/17 Птн 16:19:33 #341 №1042600 
>>1042596
Исполнение в цикле предполагает серьезное переписывание скрипта.
Gearman тоже рекомендовали. Потом гляну. Спс.
Аноним 11/08/17 Птн 21:09:23 #342 №1042807 
>>1041970
>API из CSS или HTML
А че нельзя чтоле? По сути есть HTML5.2, CSS3, SVG и JS На-ху-й не-ну-жен ибо половину функций уже вхуярили в HTML (В том числе и ваше ебаное API), страшно подумать что в будущем сделают.
Аноним 11/08/17 Птн 21:11:08 #343 №1042810 
>>1042807
Хотя в HTML и современный CSS3 вписывают упрощенки всякие.
Аноним 12/08/17 Суб 08:19:42 #344 №1042966 
А есть ли разница между установкой размера шрифта в px и em, кроме той, что em отталкивается от значения родителя?

Просто замечаю, что при вёрстке с psd-макетов, значения в пикселях из макета зачем-то переводят в em, хотя смысла в этом получается нет и только тратится время.
Аноним 12/08/17 Суб 08:35:10 #345 №1042968 
>>1042966

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

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

Если длина привязана к размеру текста, ты пишешь N em.

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

А если ты например хочешь, чтобы ширина блока была равна половине ширины родителя, ты пишешь 50%.

Плюс em в том, что если завтра ты решишь увеличить размер шрифта на сайте, заданные в em размеры элементов изменятся пропорционально. Ну и при чтении видно, что размер элемента привязан к размеру символов.

То есть выбор величины определяется логикой, по которой рассчитывается размер элемента, привязан он к размеру шрифта, еще чему-то или нет. На практике по моему это довольно редко нужно (если не согласны, приведите мне примеры, где это нужно).
Аноним 12/08/17 Суб 08:36:50 #346 №1042969 
>>1042966

А вообще, в верстке очень много неграмотных людей, которые ничего не понимают, а просто бездумно копируют то, что написано в какой-нибудь статье на сайте для фронтендщиков. Когда я смотрю чей-то чужой CSS/JS код, мне хочется разбить лицо рукой. Понабирали вкатывальщиков.
Аноним 12/08/17 Суб 09:31:06 #347 №1042982 
Очередной вкатывальщик в треде.
Сделал классическую "считалочку": http://ideone.com/RxqmIo
Чё там происходит: массив с позициями участниками перебирается циклом с двумя счётчиками - один отсчитывает количество слогов, когда они заканчиваются, маркирует позицию крестиком; второй непосредственно "проходится" по массиву и переводит отсчёт на начало строки, когда его значение превышает длину массива. (типа по кругу ёпт...)
В какой-то момент я подумал, что можно задать рекуррентное соотношение, доказать его и тупо вставлять переменные в формулу, но я слишком тупой для этого. Короче, там можно было проще сделать или нет?
Аноним 12/08/17 Суб 09:34:41 #348 №1042983 
>>1042313
Да я заметил, что нельзя, просто это гнойно пиздец. Всё равно строки индексируются, могли бы и сделать.
Аноним 12/08/17 Суб 11:25:45 #349 №1043040 
>>1042343
Сабмитить js-ом
Аноним 12/08/17 Суб 12:01:39 #350 №1043059 
>>1042969
Я вот думаю, это привычка с xml или просто нежелание учиться семантике? Кому тогда драфты хуеву тучу пишут на консорциуме?
Аноним 12/08/17 Суб 14:30:49 #351 №1043125 
буду писать нейроночку на пхп :3
Аноним 12/08/17 Суб 16:10:26 #352 №1043190 
бляя, я не знаю как установить Fann на винду ((
Аноним 12/08/17 Суб 18:33:19 #353 №1043252 
>>1043190
Через PECL, например.
Аноним 12/08/17 Суб 19:16:15 #354 №1043267 
>>1043252
БЛЯТЬ КАК Я НЕНАВИЖУ ВИНДУ ЭТА ЕБЛЯ С БУБНОМ ПРИ УСТАНОВКЕ КАЖДОГО ЭКСТЕНШЕНА.
НАДО БУДЕТ ФЛЕШКУ КУПИТЬ И ЗАПИСАТЬ НА НЕГО ОБРАЗ УБУНТЫ СИЛ НЕТ
Аноним 12/08/17 Суб 20:15:56 #355 №1043298 
привет!
ребят, подскажите пожалуйста, а как вот на PHP cURL сделать вот такое:
curl -F file=@/path/to/file.txt "http://localhost:5001/ipfs/api/v0/add?recursive=false"
как вот именно -F (--form) бахнуть? Не могу понять что тут получается.
это же POST запрос вроде бы получается такой
Аноним 13/08/17 Вск 04:35:17 #356 №1043526 
Няши, не знаете случайно какой нибудь крутой сайт с набором шаблонов для верстки, вместе с PSD?
Аноним 13/08/17 Вск 04:57:36 #357 №1043529 
>>1042983
Индексируются там байты. Обращаться к элементу строки как к элементу массива можно только когда там однобайтная кодировка и каждый байт совпадает с 1 символом поэтому прокатывает такое:

$a = 'asdfe'
echo $a[3];
//f

На таком ты уже пролетаешь:

$a = 'йцукенг'
echo $a[3];
//нихуя
Аноним 13/08/17 Вск 07:00:41 #358 №1043533 
От чего зависит скорость загрузки страницы, от сервера или все же от кода? Да я рак.
Аноним 13/08/17 Вск 07:15:56 #359 №1043534 
>>1043125
Уже есть
Аноним 13/08/17 Вск 07:17:50 #360 №1043535 
>>1043533
И от сервера, и от кода.
Аноним 13/08/17 Вск 07:20:00 #361 №1043536 
>>1043059
Лол, какая привычка для типикал вкатывальщика
Аноним 13/08/17 Вск 10:52:06 #362 №1043567 
>>1043535>>1043533
Еще от того какие там запросы в базу идут и как быстро она их отдает. Там еще различают скорость выполнения запроса, и скорость доставки.
Аноним 13/08/17 Вск 11:26:40 #363 №1043579 
Пару недель назад анон тут >>1029961 просил проверить задачи про опечатки, вывод числа, и тд. С запозданием, но все же проверил: >>1043577

Аноним 13/08/17 Вск 12:24:09 #364 №1043617 
>>1025540

Ответ на старый вопрос про чат.

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

Если честно, не очень красиво и выглядит как баг (что там должны быть сообщения, но они не отрисовались).

По твоему CSS - я плохо понимаю логику.

> position: absolute;
> top: 70%;
Почему именно 70%? Не проще ли просто bottom: 0?

Ты ведь вроде делал мои задачи на HTML, значит, ты наверно сможешь решить проблему. Давай начнем с простой задачи (реально простая):

- есть див известной высоты (например, 300px или 100% от высоты страницы)
- в него вложено содержимое неизвестной высоты
- если оно маленькое, оно должно прижиматься к низу контейнера
- если содержимого много, то должна появляться прокрутка

Затем задачу можно усложнить:

- имеется див-контейнер определенной высоты (например, 300px или 100% страницы)
- в нем внизу есть область фиксированной высоты (для отправки сообщений), например 200px (еще более сложная версия: область, высота которой не задана, а определяется содержимым)
- в оставшейся области должны выводиться сообщения как в предыдущей задаче

Я в том сообщении ( https://2ch.hk/pr/res/1000416.html#1007389 ) предложил возможные подходы, нужно просто их перебрать и посмотреть, реально их тут применить или нет. Если вообще никак, то придется использовать вычисление высоты через яваскрипт (с пересчетом при ресайзе окна), но конечно средствами CSS решить эту задачу было бы гораздо лучше (но в реальных задачах иногда приходится прибегать и к яваскрипту).

Также, мне не нравится вот это:
> resize: none;

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

Кстати, для прокрутки списка сообщений в конец можно еще использовать интересный метод scrollIntoView: https://developer.mozilla.org/ru/docs/Web/API/Element/scrollIntoView (там написано, что это экспериментальный метод, но это относится только к опциям, без опций код работает даже в ИЕ6. то есть реально везде).
Аноним 13/08/17 Вск 12:45:56 #365 №1043639 
Вот еще на один старый вопрос не ответил:

>>1025530

> В файлообменнике сущность файл должна агрегировать массив сущностей комментариев? Если да, то класс FileGateway должен агрегировать CommentGateway?

Хороший вопрос.

Логика понятна: если у файла есть комментарии, то логично бы иметь массив комментариев внутри объекта-файла. Но если попытаться воплотить это в реальности, то возникнет проблема: мы теперь должны при загрузке файла загружать все комментарии к нему, даже если они нам не нужны. Хочешь вывести 10 последних файлов - загрузи 1000 комментариев к ним. Очень неэффективно.

То есть наша "идеальная" объектная модель никак не учитывает тот факт, что данные находятся где-то далеко, в базе данных, и их получение не бесплатно. Вот какие есть решения:

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

2) использовать "ленивую загрузку" и паттерн прокси: помещать в файл не массив комментариев, а прокси-объект, который представляет список комментариев к файлу, но загружает их только при первом обращении к нему:

function getFileById($id) {
...
$data = $pdo->fetch();
$file = new File;
$file->id = $data['id'];
$file->name = $data['name'];
$file->size = $data['size'];
$file->comments = new CommentsCollectionProxy($file->id, $commentsGateway);
return $file;
}

При этом получение комментариев будет выглядеть так:

// метод getAll вызывает обращение к БД и загрузку комментов в прокси-объект
$comments = $file->comments->getAll();

// Возвращает ранее сохраненный масив комментариев
$comments = $file->comments->getAll();

а еще можно делать например так:

// делает запрос SELECT COUNT(...) и сохраняет результат внутри объекта
$count = $file->comments->getCount();

Разумеется, вместо публичного поля мы можем хранить прокси в приватном поле, а в объекте File сделать метод getComments() который будет возвращать комментарии.

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

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

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

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

> Если да, то класс FileGateway должен агрегировать CommentGateway?
Я бы не назвал это "агрегацией", но да, FileGateway может содержать ссылку на CommentGateway. Агрегация - это отношение вида "целое - часть", но CommentGateway не является частью FileGateway, он просто содержит ссылку на этот объект.


Аноним 13/08/17 Вск 13:16:20 #366 №1043660 
И еще, ответил в старом треде на старый вопрос про форму комментариев в файлообменнике: >>1043657
Аноним 13/08/17 Вск 15:55:18 #367 №1043769 
Задания по верстке с гитхаба ОПа проверить можно? Кинуть на почту или здесь ссылки оставить?
Аноним 13/08/17 Вск 15:57:06 #368 №1043773 
>>1043769

Здесь оставить ссылки.
Аноним 13/08/17 Вск 18:04:01 #369 №1043881 
Что происходит в этой функции?

echo random_int(0, 1) ? -1 : 1;

Почему тернарный оператор возвращает -1 или 1 независимо от того, выпал 0 или 1??
Аноним 13/08/17 Вск 18:29:49 #370 №1043912 
>>1043881
Что блять?
Аноним 13/08/17 Вск 19:39:32 #371 №1043985 
>>1042982
Это задача Иосифа Флавия.
Аноним 13/08/17 Вск 20:08:20 #372 №1044012 
>>1043881
это что-то из учебника, чтобы ты понял приведение типов:
0 == false
1 == true

1 и -1 возвращает не новое слово, которое ты только что выучил, а echo.
Аноним 13/08/17 Вск 20:08:47 #373 №1044014 
>>1044012
и не возвращает, а выводит, но не суть
Аноним 13/08/17 Вск 20:28:41 #374 №1044028 
Хм, а PHP умеет JS программы выполнять? Не знал:
http://php.net/manual/ru/class.v8js.php
Аноним 13/08/17 Вск 20:31:18 #375 №1044030 
>>1044028
Осталось дело за малым - PHP в браузере запустить.
Аноним 13/08/17 Вск 20:50:53 #376 №1044043 
>>1044030
Скоро можно будет, было бы зачем
Аноним 13/08/17 Вск 20:53:12 #377 №1044048 
>>1044043
Я имею ввиду грядущую WebAssembly;
Кто-нибудь из гуру, скомпилируйте PHP под выполнение там, когда время будет?
Аноним 13/08/17 Вск 21:06:05 #378 №1044063 
Привет, аноны.
Хочу сделать следующее:
Чтобы было меню статичное и чтобы в этом меню я мог выбрать, например, калькулятор или что-нибудь проще, типа перевода из одной системы единиц в другую, ну вы понели.
Как это делать? Ajax, фреймы?
Аноним 13/08/17 Вск 21:08:45 #379 №1044065 
>>1044063
фреймы уже не модно (но можно),

без них -- ajax, либо, если у тебя немного инфы, можешь прямо на одной странице по клику на пункт меню показывать с помощью js+css нужный блок и скрывать ненужные остальные.
Аноним 13/08/17 Вск 21:50:21 #380 №1044099 
>>1044043
Должен остаться только один ©
Аноним 13/08/17 Вск 22:19:45 #381 №1044131 
>>1044065
Если блоки будут hidden, то они не будут налазить друг на друга?
Аноним 13/08/17 Вск 23:30:12 #382 №1044147 
>>1044131
Если правильно сделаешь, то не будут.
Аноним 13/08/17 Вск 23:39:11 #383 №1044155 
>>1044147
я имею ввиду, правильно спозиционируешь в css

олсо, при использовании display:none такие блоки вообще не влияют на остальные
Аноним 13/08/17 Вск 23:56:30 #384 №1044157 
>>1044155
Во, спасибо.
display: none;
Аноним 14/08/17 Пнд 01:57:20 #385 №1044204 
Ребят, пытаюсь файл загрузить через форму и переместить его в отдельную папку. Когда делаю это через move_uploaded_file, то при попытке этот файл открыть/изменить мне пишет, что у меня нету доступа. Когда делаю все через copy, то все открывается. Почему ?
Аноним 14/08/17 Пнд 02:15:16 #386 №1044210 
>>1044204
Помогла смена дефолтной директории временного хранения файлов на свою (upload_tmp_dir в php.ini)
Аноним 14/08/17 Пнд 03:24:38 #387 №1044216 
Сап, не знаю куда писать, напишу сюда, сильно не пинайте.

Проработал в одной компании 10 лет, разрабатывал мимоходом для них всякое ПО на PHP+Mysql особо навороченные системы которые (одну из которых) ВНЕЗАПНО сейчас стали использовать по всему миру (В 2016 внедрили в Индии, США, Нидерландах, Малайзии ну и в России) Потому что то, что писал я опять же ВНЕЗАПНО, не падает и тупит процентов на 90 меньше всего остального (я у мамы байтоёб). Соответственно сейчас настало время воровать трактор и уплывать на нём в Канаду и я заблаговременно готовлю резюме. А посему вопрос.
Как можно в Резюме упомянуть это ПО, не в даваясь в подробности, вообще можно о таком упоминать? И можно ли рассказывать о функционале ПО? Можно говорить какие технологии использовались? Я просто никогда до этого не прыгал по вакансиям, почти всю жизнь на одном месте и хотелось бы у более опытных людей узнать что к чему. Или лучше написать что так мол и так, разработал такую штуку, но коммерческая тайна не позволяет рассказывать подробности.
Аноним 14/08/17 Пнд 07:15:55 #388 №1044243 
>>1044216
непонятно, жалуешься ты или хвастаешься, но вопрос скорее к юристам. Если всё так, чому не переведёшься в канадский офис своей конторы?
Аноним 14/08/17 Пнд 07:23:35 #389 №1044245 
За что все так ненавидят php? И насколько он сейчас востребован?
И с чего лучше начать - пхп или жс?
Аноним 14/08/17 Пнд 07:28:13 #390 №1044246 
>>1044243
Могут трансфернуть через полтора года в Техас или ОАЭ, но я хочу именно в Канаду. А там у нас 1 проект и полтора айтишника.
Относительно проекта, я подписывал документы о неразглашении, но не знаю относится ли это именно к проекту. Ну и могу я тогда в резюме просто рассказать мол разработал такой вот проект но подробностей не скажу ибо коммерческая тайна. Это ведь не будет выглядеть странно?
Аноним 14/08/17 Пнд 07:30:48 #391 №1044247 
>>1044245
>насколько он сейчас востребован?
Веб стек на 90% состоит из PHP.
>За что все так ненавидят php?
Рашкинский менталитет. Никто не хочет конкуренции. Не стоит слушать хейт. PHP - это всего-лишь инструмент. Если этим инструментом удобно работать - работай. Если бы PHP был бы хоть на 10% настолько плох как про него говорят, никто-бы его не использовал.
>И с чего лучше начать - пхп или жс?
Это разные как-бы вещи. Если ты во фронтенд, то жс, если бэкэнд, то PHP. Решать тебе.
Аноним 14/08/17 Пнд 07:31:15 #392 №1044248 
>>1044245
В первую очередь за его долю в 80% рынка

Вкатывальщики уже в принципе не нужны,
а начинать надо не с языка, а с теории и общих основ. Ну может быть в PHP более понятное ООП и в последних версиях type hinting а-ля Java. Если JavaScript -- то хотя бы с TypeScript.
Аноним 14/08/17 Пнд 07:33:06 #393 №1044250 
>>1044246
Ну и попроси трансфер в канадский офис, будешь сидеть с этими полуторами айтишниками?

Изучи, что ты там наподписывал, и проконсультируйся с юристом.
Аноним 14/08/17 Пнд 07:33:45 #394 №1044251 
>>1044250
Спасибо анон.
Аноним 14/08/17 Пнд 07:43:56 #395 №1044252 
изображение.png
Принес задачу желающим немного размяться. Если есть вопросы то спрашивайте.
Аноним 14/08/17 Пнд 07:52:15 #396 №1044253 
>>1044248
>Вкатывальщики уже в принципе не нужны
Хочешь сказать, что вкатиться в профессию уже нельзя?
>а начинать надо не с языка, а с теории и общих основ.
О чем ты конкретно? Теория и основы рассказываются в учебниках по любому языку.
>>1044247
>Это разные как-бы вещи.
Я понимаю. Под "лучше" я имел в виду "больше вакансий, выше з/п, интереснее работать".
Нет, я не хочу "и рыбку съесть..", просто хочу представлять реальную картину.
Аноним 14/08/17 Пнд 08:01:35 #397 №1044255 
>>1044253
>>1044248
Вот почему вы мне ОБА противны?
Аноним 14/08/17 Пнд 08:18:30 #398 №1044256 
>>1044253
Вакансии в основном идут сразу и на то и на то, редко кому-то нужны чисто JS или PHP.
Аноним 14/08/17 Пнд 08:57:24 #399 №1044268 
>>1044255
потому что ты решил повыёбываться, очевидно %)
Аноним 14/08/17 Пнд 10:15:57 #400 №1044316 
>>1044253
можно, конечно, но будет примерно как в начале нулевых, когда до плебса дошло, что выгодно быть юристом-экономистом, кекус
Аноним 14/08/17 Пнд 10:45:42 #401 №1044351 
Господа, почти доделал задачу по ООП "Вектор", но вот что то последняя функция не хочет работать, когда без класса и функции делал, все считало и выводило, хотел оптимизировать все, сделать через класс, с автоматическим созданием объектов, но чет накосячил, сейчас не могу разобраться что надо сделать, помогите, сам код: https://ideone.com/jd5aXv
Осталось совсем чуток блин, все считает идеально правильно, как же я намучился с этой задачей
Аноним 14/08/17 Пнд 11:37:58 #402 №1044374 
687474703a2f2f692e696d6775722e636f6d2f324d476757316b2e706e67.png
Объясните пожалуйста. Если ширина меню слева 200px, почему тогда она такая узкая?
Аноним 14/08/17 Пнд 11:41:07 #403 №1044376 
>>1044374
кто "она"?
Аноним 14/08/17 Пнд 11:43:31 #404 №1044377 
>>1044376
стрелка/меню/боковая панель
Аноним 14/08/17 Пнд 11:44:20 #405 №1044378 
>>1044374

Картинка нарисована не в масштабе 1:1 и не соблюдает пропорции.
Аноним 14/08/17 Пнд 11:44:51 #406 №1044379 
>>1044374
upd: https://github.com/codedokode/pasta/blob/master/html/html.md, 6 задание
Аноним 14/08/17 Пнд 11:48:51 #407 №1044380 
>>1044378
ок, тогда что означает "100% - 230px"
Аноним 14/08/17 Пнд 11:58:44 #408 №1044389 
>>1044380

Это значит "сколько останется". Смысл в том, что левая колонка всегда имеет ширину 200px, а правая - сколько останется места за вычетом левой колонки и отступов. Получается 100% ширины окна - 230px.
Аноним 14/08/17 Пнд 12:07:00 #409 №1044392 
>>1044389
ладно, спасибо. вроде бы разобрался..
Аноним 14/08/17 Пнд 12:43:56 #410 №1044403 
>>1043985
Ага. В "Конкретной математике" приводилась в начале самом.
Аноним 14/08/17 Пнд 12:51:52 #411 №1044407 
>>1043529
А в божественном третьем питоне все строки по умолчанию в юникоде...
Аноним 14/08/17 Пнд 12:53:01 #412 №1044409 
>>1044407
>индексируются
Фихс
Аноним 14/08/17 Пнд 17:58:07 #413 №1044543 
>>1044351
Бамп вопросу, где он?!
Аноним 14/08/17 Пнд 18:29:47 #414 №1044553 
Насколько php чуствителен к версиям? Книги из шапки нюфаг-треда давно протухли. Как выбрать что-то хорошее и свежее?
Аноним 14/08/17 Пнд 19:01:17 #415 №1044560 
>>1042966
Смысл есть.

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

Em - относительная величина. Хочешь сделать шрифт покрупнее, просто ставишь допустим body { font-size: 17px; } и у тебя весь сайт преображается. Очень удобно.
Аноним 14/08/17 Пнд 19:38:30 #416 №1044570 
>>1044560

> Задумал сделать шрифт покрупнее - придется вручную менять везде.

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

> Хочешь сделать шрифт покрупнее, просто ставишь допустим body { font-size: 17px; } и у тебя весь сайт преображается. Очень удобно.
А возможно, все разъедется и будет выглядеть неаккуратно.

Если ты хочешь призвать делать все в em, то это выглядит как нездоровый фанатизм. Вообще, я плохо себе представляю дизайн, в котором можно просто взять и поменять размер шрифта. Такое редко бывает.
Аноним 14/08/17 Пнд 19:56:45 #417 №1044578 
>>1044570
>Почему мы должны менять размеры всех элементов пропорционально

Ну потому что.

Шрифт 19px с междустрочным интервалом 30px смотрится хорошо.

При увеличении шрифта до 32px междустрочный интервал нужно увеличивать до 45px (согласно golden ratio https://pearsonified.com/typography/). Иначе параграфы будут выглядеть "сплюснуто".

С em'ами нужно лишь изменить базовый размер. А с пикселями нужно менять в двух местах (font-size и line-height).

>А возможно, все разъедется и будет выглядеть неаккуратно.
У профессионального девелопера ничего не разъезжается. Он умно сочетает различные техники (пиксели, vw, проценты и em'ы). "Разъезжание" элементов типичная ошибка фронтэнд-нубов.
Аноним 14/08/17 Пнд 20:08:57 #418 №1044583 
>>1044578

line-height можно (и обычно принято) указывать относительным, вроде 1.4. Я имел в виду другие вещи: отступы, поля, ширину колонок, размеры картинок.

Потому em должен использоваться только для тех элементов, которые привязаны к размеру шрифта в текущем элементе.

> У профессионального девелопера ничего не разъезжается. Он умно сочетает различные техники (пиксели, vw, проценты и em'ы). "Разъезжание" элементов типичная ошибка фронтэнд-нубов.

Это теоретические рассуждения или практический опыт? Разъедется, я не уверен, что я вообще когда-то видел сайт , который бы выдержал заметное изменение размера шрифта без ущерба. Если у тебя картинка размером 200px, она сама по себе до 220px не увеличится например. Наверно, в теории можно было бы продумать такую верстку, которая бы выдерживала изменение размера шрифта, но этим, я думаю, никто не занимается, включая профессионалов, из принципа YAGNI.
Аноним 14/08/17 Пнд 20:10:39 #419 №1044586 
>>1044578

Также, если мне не изменяет память, ситуацию усложняет тот факт, что не для всех элементов HTML размер шрифта наследуется (я не уверен, возможно что это исправляется через font-size: inherit). Это относится к элементам форм, таблицам.
Аноним 14/08/17 Пнд 21:07:00 #420 №1044604 
>>1044583
Бля, какой ты душный зануда, пиздос. Уже объяснил тебе концепт абсолютных и относительных значений. Em'ы повсюду используют в основном адепты сеток, чтобы добиться равномерности и пропорциональности столбцов/контента, такой контент лучше зумится на различных девайсах, лучше оптимизирован под ретину и проч.

Нельзя однозначно сказать, плохо это или хорошо, это просто такая техника. Как есть объектно-ориентированное программирование, а есть функциональное.
Аноним 14/08/17 Пнд 21:20:45 #421 №1044608 
>>1044583
>не уверен, что я вообще когда-то видел сайт , который бы выдержал заметное изменение размера шрифта без ущерба
Так увидь. Ситуации когда нужно плясать от 18px базового на больших экранах, от 16px на средних и от 14px на планшетах не редки. Соответственно, нужно и размер контент менять.
Аноним 15/08/17 Втр 01:04:44 #422 №1044719 
Сейчас взялся за задачу с тестхабом и уже пожалел и охренел от сложности. Такого сайта хватит на вакансию джуна?
Аноним 15/08/17 Втр 05:18:18 #423 №1044743 
>>1044351
Я не ОП, но у тебя же код обрывается на последней 294 строчке. Программа вообще не запускается из-за синтаксиса.

И я еще не понял, ideone внезапно перестал поддерживать функции вида mb_strlen()? Я так-то в phpstorm сейчас делаю, хотел свой вариант этой задачи выложить, а он ругается на отсутствие функции.
Вот вроде здесь нормально работает
http://sandbox.onlinephpfunctions.com/code/31702a84a5de8daae8b982621e907d9681bfd666
Как я сделал - класс для компании, класс для департамента, создал четыре объекта для каждого департамента, потом отдельно классы для каждой профессии. В каждом объекте департамента я сделал массив с аналогом штатного расписания, в котором перечислены ставки, а потом уже на основании этого массива я заполнил ставки, код получился довольно коротким, если не считать описания классов. Есть идея вообще отказаться от создания отдельных объектов департаментов, а сделать одну большую таблицу примерно как в условии задачи изображено.

А можно махнуть рукой и двинуться дальше :-)
Аноним 15/08/17 Втр 07:47:19 #424 №1044750 
>>1044743
Зачем ты ему отвечаешь? Там какой-то блядь кек а не код. Я глянул, нашел эрор за 5 сек, понял что там долбоеб, который даже не хочет ошибку прочитать и закрыл нахуй. Если бы там реальная какая-то проблема была в решении, то конечно же стоит отвечать и пытаться помочь, а так нахуй таких.
Аноним 15/08/17 Втр 07:58:04 #425 №1044753 
>>1044750
Да ладно тебе, не ругайся с утра.

Лучше объясните по хардкору, какие-то есть отличия в коде при отправке формы по get и post. В случае с get у меня все работает, массив $_GET нормально заполняется, меняю все на метод post и массив возвращается пустой. В мануале сказано мельком про Content-Type application/x-www-form-urlencoded или multipart/form-data. Или вообще не в этом дело?
Вот мой HTML, генерируется редактором, ничего не менял, добавил только форму из мануала:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Title</title>
</head>
<body>
<form action="_tmp.php" method="get">
Имя: <input type="text" name="username" /><br />
Email: <input type="text" name="email" /><br />
<input type="submit" name="submit" value="Отправь меня!" />
</form>
</body>
</html>

Вот скрипт:
<?php
var_dump($_GET);
?>

При замене на post массив пуст.
Аноним 15/08/17 Втр 08:29:50 #426 №1044756 
>>1044750
ахаха, может он в инглиш не может. не догадался прочитать ошибку.
Аноним 15/08/17 Втр 08:31:50 #427 №1044757 
504880486.jpg
>>1044753
надеюсь ты method = "get" и $_GET оба на post меняешь?
Аноним 15/08/17 Втр 08:32:46 #428 №1044758 
>>1044604

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

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

>>1044608

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

>>1044756

Такие комментарии тут не нужны. Не засоряй тред.

>>1044750

И такие наверно тоже.
Аноним 15/08/17 Втр 08:35:34 #429 №1044760 
>>1044553
Бамп, все ещё в поисках хорошей литературы. Пока что прохожу курс из шапки и читаю мануал на php.net.
Аноним 15/08/17 Втр 08:38:21 #430 №1044761 
>>1044753

Данные, из POST формы передаются в теле HTTP запроса и помещаются в $_POST: http://php.net/manual/ru/language.variables.external.php

>>1044743

На ideone при обновлении php забыли mbstring. Я им писал несколько месяцев назад, можешь, если хочешь, тоже написать.

>>1044719

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

Аноним 15/08/17 Втр 08:59:49 #431 №1044766 
>>1044761
Работу за типовую задачку? Вы чо?
Аноним 15/08/17 Втр 09:09:59 #432 №1044770 
>>1044743

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

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

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

Также, этого пока в коде нет, но хочу предупредить, что нельзя в базовом классе обращаться к полям/методам, которые не описаны в текущем классе и появятся только в наследниках. Ну например, в твоем коде методы класса Employee не должны обращаться к полям вроде rate, так как это поле не описано в базовом классе. Так как есть вероятность, что кто-то унаследует класс, но не объявит поле, и будет ошибка.

Далее, поля пишутся до методов, а не после. Рекомендуемый порядок (для удобства чтения кода) такой:

- константы
- публичные поля
- непубличные поля
- конструктор(ы)
- публичные методы
- непубличные методы

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

Поле employeesTable нужно убрать. Это не свойство департамента, а лишь вспомогательное поле, которое используется у тебя для его заполнения. Оно никак не связано с задачами, которые выполняет департамент. Оно не требуется, мы можем заполнить и использовать департамент без него. То есть, если его убрать, Департамент не потеряет ни одной полезной функции. Значит, надо убрать.

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

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

Я бы советовал в классе Департамента сделать конструктор с аргументом $name, чтобы показать, что нельзя создать департамент без названия. Аналогично, в классе работника с помощью конструктора можно указать обязательные для его создания данные.

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

Также, надо закрыть поля $employees/$departments. Сейчас они открыты и с ними можно делать что угодно, потому лучше их закрыть и сделать методы вроде addEmployee(Employee $e), которые позволяют добавлять в поле только объекты определенного класса.

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

-----

Инкапсуляция. У этого слова есть разные определения, в том числе такие что ничего не понять, потому объясню простыми словами.

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

Это упрощает понимание кода: тебе не надо читать и разбирать код класса, достаточно прочитать название метода (и может быть комментарий к нему). Также, это упрощает изменение кода: если какое-то свойство имеет уровень private то доступ к нему возможен только из того же класса и тебе не надо бегать по всему коду и смотреть что там с этим свойством делается, тебе достаточно просмотреть один файл с этим классом.

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

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

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

-----

Имена методов принято писать с маленькой буквы. Я не уверен, есть ли это требование в PSR, но вроде все крупные проекты вроде Симфони так делают.

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

Чтобы сделать код еще более понятным, около полей с объектами можно подписать их типы, используя синтаксис phpDoc:

/** @var Employee[] Список работников */
private $employees;

Ждем также версию с антикризисными мерами.
Аноним 15/08/17 Втр 09:32:50 #433 №1044771 
>>1044761
Вопрос с GET и POST снят, на апаче все корректно работает, проблема, видимо, во встроенном веб-сервере phpstorm, не работает метод post, да и ладно, на данном этапе это не принципиально, буду делать все через get. Может так и задумано.

Написал на ideone, посмотрим, подождем.
Аноним 15/08/17 Втр 09:37:12 #434 №1044774 
>>1044771
facepalm.
среду разработки на локалке разверни.
Аноним 15/08/17 Втр 10:03:42 #435 №1044779 
>>1044351

В твоем коде синтаксическая ошибка, то есть где-то там скобки неправильно стоят или опечатка какая-нибудь.

Судя по тексту: PHP Parse error: syntax error, unexpected end of file, expecting '{' in /home/Mzm5qE/prog.php on line 294 причина в том, что у тебя в конце идет определение функции и оно обрывается на полуслове.

По коду:

> public $endStavka; // окончательная ставка, вычисляется через функцию EndStavka

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

Код плохо отформатирован, используй phpformatter.com

> $endStavkaB
Название непонятное, что значит буква B непонятно.

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

Еще, я думаю, что эти поля нужно убрать:

> public $engeenerA; //1 rang
> public $engeenerB; //2 rang
> public $engeenerC; //3 rang

Они используются для заполнения департамента в начале, но почему этот код заполнения должен быть в самом департаменте? Эти поля не нужны для его работы, он может легко работать без них, значит, их надо убрать. Вместо них в департаменте лучше сделать метод addWorker(Worker $w) и добавлять работников через него. Также, кроме метода приема на работу, можно сделать метод увольнения работника, он понадобится в антикризичных мерах.

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

Соответственно, классы вроде MarketDivision тогда вообще не понадобятся. Департаменты все одинаковы, они ничем не различаются и нет смысла для них делать разные классы. Тут можно спросить: а как же работники? В принципе, их тоже можно сделать одним классом, если хочется, но наверно с наследованием просто проще задавать им параметры.

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

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

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

----

Инкапсуляция. У этого слова есть разные определения, в том числе такие что ничего не понять, потому объясню простыми словами.

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

Это упрощает понимание кода: тебе не надо читать и разбирать код класса, достаточно прочитать название метода (и может быть комментарий к нему). Также, это упрощает изменение кода: если какое-то свойство имеет уровень private то доступ к нему возможен только из того же класса и тебе не надо бегать по всему коду и смотреть что там с этим свойством делается, тебе достаточно просмотреть один файл с этим классом.

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

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

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

----

Аноним 15/08/17 Втр 10:05:14 #436 №1044781 
>>1044774

Ты уверен, что у тебя в коде нет ошибки? Что-то не верится, что в phpstorm так все плохо.

>>1044351

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

abstract class Worker
- $rang;
- $dicrementcoffe;
- $stavka;
- $mainingDocument;
- $endStavka;
- $boss = false;
- __construct()
- getendStavka()

Что мы тут видим? Во-первых, неаккуратно написанные названия (stavka -> salary/rate, getendStavka -> getEndStavka). Если ты пишешь код прямо на ideone, то советую обзавестись редактором кода вроде Notepad++, Sublime, Eclipse PDT, Netbeans, PHPStorm (платный).

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

Далее, видна избыточность. Для получения конечной ставки есть поле endStavka и метод getendStavka - что мы должны использовать?

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

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

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

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

Проектировать можно "сверху вниз" (начиная c гостиницы) или "снизу вверх" (начиная с номеров и броней), как удобнее. Я описываю только публичные поля и методы (так как к приватным все равно нельзя обратиться снаружи). Я сделаю такие классы:


// бронь
// При создании указываем диапазон дат и число гостей
class Reservation
- construct(DateTime $startDate, DateTime $endDate, $guestCount)
- getLength() // считает длительность в днях
- getGuestCount()
- getStartDate()
- getEndDate()

// номер
class Room
// указываем номер, вместимость, цену за сутки
- construct($number, $capacity, $pricePerNight)
- getNumber()
- getCapacity()
- getPricePerNight()
// забронировать номер, не позволяет забронировать номер на те дни,
// на которые уже есть бронь
- addReservation(Reservation $r)
- getReservations() // получить список броней
// подходит ли номер под условия брони, свободен ли он
// в указанные дни?
- canReserve(Reservation $r)
// сколько будет стоить проживание за весь период
- getPriceForReservation(Reservation $r)
// Занят ли номер в этот день?
- isOccupied(DateTime $date)


class Hotel
- construct()
- addRoom(Room $room) // добавить новый номер в отель
- getAllRooms()
- getRoomCount()
- getRoomByNumber($number) // найти номер
// найти все свободные номера, в которые можно
// поселить гостей
// с указанными параметрами
- findVacantRooms(Reservation $r)
// Посчитать число занятых номеров на данную дату
- getOccupiedCount(DateTime $date)
// Посчитать доходы за период времени
- getProfit(DateTime $fromDate, DateTime $endDate)

Класс DateTime - это встроенный в PHP класс для описания дат: http://php.net/manual/ru/class.datetime.php

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

Постарайся и свою структуру классов сделать такой же логичной. Если ты чувствуешь, что у тебя пока плохо с проектированием классов, можешь попросить дополнительное задание что-нибудь спроектировать.
Аноним 15/08/17 Втр 10:06:23 #437 №1044783 
>>1044774
Да ладно, я бы не был столь категоричен, для отладки именно php-кода, а я до сегодняшнего дня этим и занимался, встроенная в phpstorm среда выполнения очень удобна и быстра, не надо никуда переключаться в браузер. Как настроить автодеплой на веб-сервер я пока не знаю, буквально не до этого, да и невозможно же все одновременно изучать. На локалке развернут php, в апаче не было необходимости, развернуть - дело нехитрое, сам же понимаешь.
А по поводу метода post в phpstorm - реальный баг, гуглится на раз. Только в силу небольшого опыта я подумал, что это у меня руки кривые, а оно вон оно как, причем люди пишут об этом еще с 10 версии, а сейчас у меня стоит версия 2017, но проблема не устранена, видимо. Да и не проблема это, так-то.
Аноним 15/08/17 Втр 10:17:29 #438 №1044790 
>>1044781
Насчет отсутствия ошибки не уверен, но у других тоже такая ошибка возникает, правда большинство жалующихся отмечают, что они новички, может действительно, что-то надо еще сделать. С другой стороны, все в один голос утверждают, что на обычном сервере - апач, или xamp, например, все работает нормально.
Я не думаю, что в phpstorm все плохо, думаю, что наоборот.
Аноним 15/08/17 Втр 10:21:16 #439 №1044792 
>>1044783

Ты бы мог запускать встроенный в php сервер - он очень просто запускается и не требует настройки Апача:

https://github.com/codedokode/pasta/blob/master/soft/web-server.md#Встроенный-в-php-сервер
http://php.net/manual/ru/features.commandline.webserver.php

Аноним 15/08/17 Втр 12:07:54 #440 №1044819 
>>1044761
>хотя бы студентов сначала надо сделать
Я уже делал студентов месяца 4 назад.
>>1044766
А что же тогда там требуется? Эта задача вроде как покрывает все требования к джунам или я заблуждаюсь? Я даже знаю людей, которые с фреймворками и ооп не были знакомы, но их принимали на работу.
Аноним 15/08/17 Втр 14:04:01 #441 №1044862 
>>1044553
Мало чувствителен, на всех php >= 5.2 работает нормально. Исключение 7-ка, там некоторые вещи выпилили, но её редко встретишь.
Аноним 15/08/17 Втр 14:17:57 #442 №1044869 
4939021.jpg
>>1044750
Бокал шабли этому джентльмену!
Аноним 15/08/17 Втр 17:40:48 #443 №1044989 
>>1044862
То есть учиться сейчас лучше на 5-ой версии? А я сдури понаставил седьмой версии. Кстати, вопрос, связана ли как-то разрядность версии php и apache? То есть если сборка php 5 версии 32-разрядная, то апач тоже только 32-разрядный надо ставить, или 64-разрядный тоже можно? А то у меня при установке какие-то танцы с бубном получились как-то раз, не сразу подружил апач и php, но сейчас уже думаю, что не были установлены последние VC рантаймы.
Аноним 15/08/17 Втр 18:04:05 #444 №1044997 
>>1044989
А тебе не похуй? Рили, зачем тебе знать про версии, ты же все равно и десятой части возможностей даже допотопной четверки не осилишь. Будто бы если я скажу, что лучше учить семерку и ты такой, "о спасибо дружище, мне как раз анонимных классов не хватало, а уж биндинги в замыканиях как надоели! Хорошо, что теперь есть метод call()!".
Аноним 15/08/17 Втр 18:17:16 #445 №1045003 
>>1044989

Если ты хочешь использовать PHP как модуль Апача (mod_php), то они должны быть:

- однаковой архитектуры (битности)
- с одинаковым параметром TS/NTS (thread safe)
- желательно собраны одинаковым комилятором

Что касается VC Runtime, они скачиваются с сайта майкрософт. Проверить, есть ли у тебя нужные библиотеки или нет, можно программой вроде dependency walker. Она показывает наличие или отстутвие нужных программе dll. Этой программой надо проверить исполняемые файлы Апача (httpd.exe) и php.exe. Если там не хватает библиотеки вроде MSVCR90.dll то нужен соответствующий рантайм. Вообще, обычно об этом написано на странице скачивания Апача или PHP, надо внимательно читать ее.

Аноним 15/08/17 Втр 18:18:01 #446 №1045005 
>>1044989

Ой, в смысле "php должен быть с поддержкой thread safe, то есть TS, а не NTS".
Аноним 15/08/17 Втр 18:46:00 #447 №1045018 
>>1044048
> компилировать из пхп
Зачем? Если так хочется анальных наслаждений, то проще+удобнее+лучше из того же питона компилять.
Аноним 15/08/17 Втр 19:57:16 #448 №1045047 
Подскажите идею для сайта. Это должно быть что то вроде портфолио на примере которого я показываю свои скилы. Но при этом нахуя на моём личном сайте какая то регистрация и прочая хуйня?
Или лучше запилить на гитхабе самую простую страничку портфолио и в ней накидать ссылок (с описанием) на несколько говносайтов, но при этом со всеми плюшками?
Второй вариант вроде как лучше.
Аноним 15/08/17 Втр 19:57:45 #449 №1045048 
У меня тут проблема. Как сохранить данные переменной между вызовами разных функций одного скрипта? Просто я тяну данные по API и потом юзер должен их выбрать с помощью AJAX, соответственно данные из переменной вымываются и мне придется заного делать API запрос, а там уже хуй поймешь пришло ли тебе тоже самое.
Аноним 15/08/17 Втр 20:00:27 #450 №1045050 
>>1044770
Промежуточный вариант с учетом замечаний, но не всех, так как возникли вопросы
http://sandbox.onlinephpfunctions.com/code/eba580db69d1172fe803b119dbb4c5c19b084ca1
В компании и департаментах закрыл доступ к переменным, добавил методы add() и get(), реализовано не полностью, не обращай внимания, по сути заглушки, чтобы код не сломать, завтра попробую переписать нормально.

Больше вопрос по классам с работниками и по таблице штатного расписания.
По работникам - может вообще тогда отказаться от отдельных классов - базового Employee и наследников-профессий типа Manager. А сделать один класс, в котором будет содержаться полная информация:
class Employee
{
public $profession;
public $rate;
public $rank;
public $isBoss = false;
public $cofee;
public $reports;
}
И уже при добавлении объекта заносить все данные на основании штатного расписания. В уроке сказано, что кофе и отчеты можно вычислять, но не проще ли их сразу в объекте хранить, а не бегать куда-то в справочник?
И второй вопрос по поводу списка должностей. Есть идея запихнуть все в один большой массив типа
employeesTable = array(
["Департамент закупок", "Manager", 9, 1, 0],
["Департамент закупок", "Manager", 3, 2, 0],
.............
["Департамент продаж", "Manager", 3, 2, 0],
["Департамент рекламы", "Manager", 1, 2, 1],
);
Ну и конечно же хранить это в совершенно отдельной переменной, вынести из класса департамента. И одной функцией заполнять всю структуру, одновременно создавая объекты для сотрудников и для департаментов.
Аноним 15/08/17 Втр 20:02:18 #451 №1045051 
>>1044760
> Бамп, все ещё в поисках хорошей литературы. Пока что прохожу курс из шапки и читаю мануал на php.net.
В шапке устаревшая хуйня дял анимедаунов. Если нужны основы, то на ютубе найди канал ntschool и там видосы по php за июль.
Книги по php тоже устаревшая дрисня. Такой популярный язык, а с книгами беда. Парадокс.
Аноним 15/08/17 Втр 21:33:32 #452 №1045092 
изображение.png
>>1045051
В изучении пхп проблемы не в книгах.

Всё что тебе надо знать о языке есть и в книгах за 2013-15 год. Если ты реально дотошный то можешь всегда актуальные изменения тут читать: http://php.net/manual/ru/migration71.php а не ждать пока тебе книгу напишут.

Другое дело это научиться строить архитектуру и классы правильно в приложении, это уже блядь другая история.
Чет полагаю за познанием грамотного ооп и паттернов вообще придется еще глубже нырять в еще более дальнюю классику. Зандстра в своей книге рекомендует вообще прочитать https://ru.wikipedia.org/wiki/Design_Patterns


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


http://ideone.com/YdFkQ0
Аноним 15/08/17 Втр 21:40:48 #453 №1045097 
>>1045092
Ты акромя пхп ничего не знаешь?
Аноним 15/08/17 Втр 23:09:57 #454 №1045133 
>>1045092
> В изучении пхп проблемы не в книгах.
Ну бля как у такого популярного языка может быть книг меньше (а 99% ещё и старое говно) чем у ...не знаю..у питона, например.
Аноним 16/08/17 Срд 00:36:00 #455 №1045161 
>>1045092

Вот например функция:

function findRoomByNumber(int $number) : Room { }

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

Вообще, до этого тип обычно указывали как phpDoc, в комментарии перед функцией, а тут сделали синтаксис для этого.

Плюс, IDE тоже может читать эти типы и когда ты напишешь

$room = findRoom(1);
$room->

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

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

Статическая типизация - это хорошо. Если ты пишешь большой проект без типизации, например, на JS, ты будешь просто время тратить на понимание, что вернет та или иная функция, а потом на отладку, когда она вернет что-то не то. Поэтому для JS придумали надъязыки TypeScript и Flow, добавляющие в JS статическую типизацию.

Аноним 16/08/17 Срд 00:38:13 #456 №1045162 
>>1045092

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

>>1045133

Мануал есть официальный, если ты знаком с программированием в общем, то его достаточно. Ну и плюс познакомиться с популярными фреймворками и библиотеками.
Аноним 16/08/17 Срд 07:23:45 #457 №1045206 
Привет, помогите с настройкой Apache на VPS с debian, (apache 2.4).

Как сделать, чтобы по адресу ххх.ххх.ххх.ххх/project запускался проект (index.php), который лежит в /var/www/project/src/server/public/ ?

прописал в /etc/apache2/sites-available/000-default.conf
<VirtualHost :80>
DocumentRoot /var/www/project/src/server/public/
<Directory /var/www/project/src/server/public/>
...
RewriteRule ^(.
)$ index.php [QSA,L]
...

по адресу сервера ххх.ххх.ххх.ххх загружается Apache2 Debian Default Page, по адресу ххх.ххх.ххх.ххх/project или ххх.ххх.ххх.ххх/project/src/server/public/ выдает ошибку с кодом 500
Аноним 16/08/17 Срд 07:29:10 #458 №1045208 
Урок про методы в классах на страницеЩсновы ООП и другие пасты

>Допиши код, используя конструкторы, напиши недостающие функции padLeft/padRight, сделай вывод колонки «Всего». Не переусложняй код, там достаточно использовать 2 функции mb_strlen и str_repeat.

>Допиши код, используя конструкторы

Это как, научите?
Аноним 16/08/17 Срд 07:56:08 #459 №1045216 
>>1045208
Про конструкторы, в примере при создании сотрудника добавляется только имя и ставка, часы добавляются отдельной строкой, надо чтобы строка тоже передавалась как параметр в функцию, я оказывается забыл в своем варианте это сделать. А ты сделай :-)
То есть создание сотрудника должно быть в виде
$ivan = new Employee("Иванов Иван", ставка, часов в неделю);

Функции padleft и padright нужны для форматирования таблицы, они должны дополнить строку пробелами до нужной длины, тогда будет формироваться табличка.

То есть было:
test1
test123

а должно быть
.........test1
......test123
примерно так

Подскажите, пожалуйста, есть массив с объектами, у объектов свойство - имя, к примеру. Мне нужно сохранить уникальность этого свойства, то есть при добавлении нового объекта я должен сделать проверку на наличие. Как это правильно делается? У меня пока только идея бежать по всему массиву и в каждом объекте сравнивать это свойство.
Аноним 16/08/17 Срд 08:04:38 #460 №1045219 
>>1045216
Да вопрос в другом был, а именно про конструкторы в множественном числе. Как с ними взаимодействовать если их больше чем 1 в классе?
Аноним 16/08/17 Срд 08:17:30 #461 №1045223 
>>1045216
Так чтоли?

public function __construct($name, $rate, $hours)
{
// задаем имя и часовую ставку
$this->name = $name;
$this->rate = $rate;
$this->hours = $hours;
}



}
$ivan = new Employee("Иванов Иван", 10, $a = array (40, 10, 40, 50));
Аноним 16/08/17 Срд 08:51:09 #462 №1045228 
>>1045223
Ну да, конструктор один и должен быть.
Аноним 16/08/17 Срд 08:56:40 #463 №1045229 
1.jpg
>>1045228
>ы
Изза этой блядской буквы я уже 4 часа прокрастинирую, спасибо.
Аноним 16/08/17 Срд 10:32:00 #464 №1045257 
14636240677430.jpg
>>1045229
А я только сейчас понял, почему буква ы выделена, лол.
Аноним 16/08/17 Срд 11:11:25 #465 №1045273 
>>1045206

Посмотри лог ошибок Апача (/var/log/apache2/error.log или как-то так) и там причину ошибки.

Также, почему у тебя Rewriet Rule внутри блока Directory?
Аноним 16/08/17 Срд 11:23:45 #466 №1045277 
>>1045208

Имеется в виду "конструкторы" как концепция, то есть я не имел в виду, что их должно быть несколько. Разумеется, обычный конструктор в классе может быть только один (есть еще такая вещь как статические конструкторы, ты сможешь их написать, если изучишь статические методы).

>>1045223

Вместо $a = array(....) правильно писать просто array(...). Ты создаешь лишнюю переменную, которая никак не используется.

Аноним 16/08/17 Срд 13:44:30 #467 №1045341 
перед array_rand() всегда приходится сначала юзать array_flip(), чтобы получить не порядковый номер элемента ?, а сам элемент
это ок?
Аноним 16/08/17 Срд 15:19:13 #468 №1045398 
>>1045341

Нет, это приведет к ошибкам, если в массиве есть повторяющиеся элементы. Надо брать ключ (который вернет array_rand) и по ключу находить элемент, если ты не знаешь как, то посмотри заново урок про массивы.
someApprentice 16/08/17 Срд 15:20:18 #469 №1045400 
>>1042318
>В Линукс при создании нового процесса он наследует список открытых файлов (дескрипторов) от родителя
На примере апача и php

Апач наследует дескрипторы от какого-то "файла устройств" (или ещё какого-нибудь абстрактного родителя, неважно на самом деле интересно, но пусть это останется на самостоятельное изучение)
А php наследует дескрипторы Апача

Соответственно, если php-скрипт выполняется через консоль, то php наследует дескрипторы от неё

Я правильно понимаю?

>>1042319
>> Я попытался проверить, и в ответ получил пустую строку.
>Тебе нужно правильно обрабатывать ошибки, чтобы видеть сообщения о них, а не гадать.
При тестировании функции proc_open, я получил в stderr такую ошибку:

gpg: fatal: can't create directory `/var/www/.gnupg': Permission denied
secmem usage: 0/0 bytes in 0/0 blocks of pool 0/65536

Затем я поменял домашний каталог у www-data в /etc/passwd на каталог сервера (на который я вроде давал неограниченный доступ chmod -R 777) и всё заработало - ключ успешно сгенерировался.

Наверно следовало давать доступ на чтение/запись только для php.

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

...+++++
.+++++
............+++++
+++++
gpg: key 447224CD marked as ultimately trusted
gpg: done
gpg: checking the trustdb
gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
gpg: depth: 0 valid: 5 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 5u

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


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


>Symfony Process
Для генерации ключей, очевидно, нужно запускать процесс асинхронно, потому что, у меня на виртуальной машине, уходит на это несколько секунд используя кстати демон haveged для энтропии. А что насчет получения ключей? На это не должно уходить много времени. Стоит ли здесь выполнять процесс асинхронно?
Аноним 16/08/17 Срд 16:27:26 #470 №1045428 
Подскажите, как подружиться с урл в fetch или в XMLHttpRequest в javaScript в проекте. У меня получилось, что на локальной машине ссылки для API запросов отличаются от ссылок которые будут в финальном проекте. Как делать так, чтобы при переносе проекта на хостинг не пришлось вручную менять все ссылки?
Аноним 16/08/17 Срд 18:31:27 #471 №1045485 
>>1044989
> 5
Нет! Привыкай сразу к хорошему, считай что тебе повезло.
Аноним 16/08/17 Срд 18:32:09 #472 №1045486 
>>1045018
Блэть, затем.
Аноним 16/08/17 Срд 18:35:08 #473 №1045489 
>>1045428
Введи константу а-ля BASE_URL и храни там путь
Аноним 16/08/17 Срд 18:37:43 #474 №1045492 
>>1045161
Это не просто документация, а проверка типа на выходе прямо в рантайме, очень удобно.
Аноним 16/08/17 Срд 20:30:30 #475 №1045537 
Фриланс для бэкендера не существует? Или нужно иметь овер9000 скилла? Мне нравится программировать. Писать именно код. Решать какие-то сложные задачи. Но нужен хлеб, поэтому я решил попытаться совместить приятное с полезным - кодить и получать деньги. Начал учить php, т.к. в инете только и пишут, что он сейчас очень востребованный. Так вот если знать php на достаточном хорошем уровне, реально ли заработать деньги фрилансом, при этом зная HTML, CSS и JS только на базовом уровне? Ну или не фрилансом? Я не люблю верстать. Мне по душе копаться во внутренней части сайта, заниматься логикой. А на биржах фриланса я чет не нашел работы для пхпшника. Или может я не так или не там ищу? В общем, хелп, добрый анон. Спасибо.
Аноним 16/08/17 Срд 20:43:55 #476 №1045542 
>>1045537
Я бы хотел услышать ответ на твой вопрос, но тут, к сожалению, никто скорее всего тебе не ответит. Вот бы конфу какую-нибудь, где можно за жизнь поговорить и совета спросить.
Аноним 16/08/17 Срд 20:49:26 #477 №1045546 
Мой начальник ебанулся и заставляет писать ВСЕ парсеры на пыхе. Сегодня написал парсер, разбивающий изображение попиксельно и выводящий массив пикселей с координатами и цветом. Ебануться. В жс для этого либа есть.
А как ваши дела?
Аноним 16/08/17 Срд 20:49:36 #478 №1045547 
Аноны, выручайте, пожалуйста! Что это такое? Почему не импортируется база? Мне что, руками заполнять лол?
Аноним 16/08/17 Срд 20:49:58 #479 №1045548 
db.png
Пик отклеился
Аноним 16/08/17 Срд 20:53:27 #480 №1045551 
>>1045537

Изучи вёрстку и жс на среднем уровне. Это сейчас легко. Bootstrap, AMP, Vue.js
И ебашь сайты васянам. По пыхе работа в основном на вордпрессе, но там тоже уметь верстать надо.
Аноним 16/08/17 Срд 20:54:02 #481 №1045552 
>>1045547
Права выдай юзеру чтоб с базами работать, дурак.
Аноним 16/08/17 Срд 20:59:30 #482 №1045553 
>>1045552
А как?
Аноним 16/08/17 Срд 21:08:34 #483 №1045559 
db.png
Все, погуглил, но он все равно ругается. Не ввел пароль? А куда его вводить? Хелп!
Аноним 16/08/17 Срд 21:33:37 #484 №1045570 
>>1045559
ты пытаешься не приведенного ванным юзером дать самому себе права. Зайди под рутом.
Аноним 16/08/17 Срд 21:37:16 #485 №1045573 
>>1045570
База на фри хостинге и они дали мне только мой логин. Может быть я что то не понимаю, не кидайся говном плс
Аноним 16/08/17 Срд 21:42:40 #486 №1045578 
>>1045537
А что тебе мешает JS выучить?
Аноним 16/08/17 Срд 21:51:42 #487 №1045587 
>>1045573
Изучи их тарифные планы, на бесплатном тарифе скорее всего доступна только одна база.

Для учебы лучше развернуть сервер на локальной машине, или на виртуальной, гайды в оп-посте.
Аноним 16/08/17 Срд 22:09:40 #488 №1045596 
>>1045573

На бесплатных хостингах тебе никто не даст права администратора в БД. И создать дополнительную базу можно разве что через админку, если они это позволяют.
Аноним 16/08/17 Срд 22:52:18 #489 №1045608 
>>1045537
Для начинающего "бекендера" -- практически не существует
Аноним 16/08/17 Срд 22:54:49 #490 №1045610 
>>1045608
И куда тогда податься начинающему бекендеру?
Аноним 16/08/17 Срд 22:57:23 #491 №1045612 
>>1045546
Типа есть либа на жс и нет на рнр? Ты траль? Или не нашёл "либы" с тупо одним циклом функции http://php.net/manual/en/function.imagecolorat.php по файлу?
Аноним 16/08/17 Срд 22:58:34 #492 №1045614 
>>1045608
Ага, а нахуя я учу php, разрешите спросить?
Аноним 16/08/17 Срд 22:58:54 #493 №1045615 
>>1045548
У тебя есть глаза? Как ты работаешь, если не в состоянии прочитать одну строку? Давай, что написано на красной плашке?
Аноним 16/08/17 Срд 23:01:28 #494 №1045616 
>>1045610
В идеале - примерно в 2000-й. Будешь крутым челом, все захотят с тобой работать на удалёнке.
Аноним 16/08/17 Срд 23:02:11 #495 №1045617 
>>1045614
Чтобы пройти длинный путь с начала до конца
Аноним 16/08/17 Срд 23:11:00 #496 №1045622 
То есть начинающий бекендер должен сначала работать на постоянной работе в офисе?
Аноним 16/08/17 Срд 23:17:03 #497 №1045623 
>>1045622
>Тебе повезло - ты не такой как все
Аноним 16/08/17 Срд 23:18:36 #498 №1045624 
>>1045617
И пройду!
хотя сейчас задумываюсь, мб прогать микроконтроллеры прикольней?
Аноним 16/08/17 Срд 23:18:54 #499 №1045625 
>>1045623
Что?
Аноним 16/08/17 Срд 23:19:36 #500 №1045626 
>>1045625
>ты работаешь в офисеееее
Аноним 16/08/17 Срд 23:21:25 #501 №1045627 
>>1045537
Работы дофига, больше чем ты сможешь проглотить. Особенно на апворках и проч, но нужно просто любить бекэнд. Алгоритмов хватает - самых разных, начиная от парсинга XML/JSON, создание всяких бэкгранд тасков, работа с базой, API-интерфейсы, админки, работа с фронтэндом (типа общение с мордой посредством server-sent events) и так далее.

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

Насчёт нужно ли знать JS? Конечно нужно. Если ты кодишь на php как бог, но при этом на js пишешь будто второклассник, то и дело вылетают функции TypeError: functionName is not a function, то это лютый фейл.

фриланс-бекэндер
Аноним 16/08/17 Срд 23:25:06 #502 №1045628 
>>1045627
Поведай нам свою историю успеха. Когда начинал? Как взял свой первый заказ? Работал ли ирл? Сколько уже кодишь?
Аноним 16/08/17 Срд 23:38:36 #503 №1045641 
>>1045627
> Начинающий
> профессионализм
Лол
Аноним 16/08/17 Срд 23:40:20 #504 №1045642 
>>1045622
Можешь форкнуть любую либу или плагин и допилить его. Наберешься опыта, потом во фриланс. На самом деле похуй, что там пугают мол начинающему нельзя и проч... Можно! В сети куча работодателей-долбоебов, которым просто нужен сайт. Любых индусов нанимают, потом смотришь в код, там ужоснах, вообще удивительно как это всё работает. После индусов я думаю даже у российских школьников есть шанс.

>>1045628
Лет 5 назад, когда твиттер бутстрап ещё только появился. Заказ взял просто, буквально наверно с 5ой попытки, написал американцу и буквально за 2 дня срубил сотню баксов. Просек эту фишку, с тех я ни одного дня в офисе не проработал, ибо нах надо. Пару часиков в день поработал и нормик, в остальное время хочу по кафешкам, слушаю лекции, развиваюсь, читаю. Денюжки тем временем на банковский счет капают. Делаю в основном темы для вордпресса, до этого года 2 был безработным, пытался пилить тему. До этого работал на днищеработе в своем мухосранске, c++ кодер, писал прошивки для роутеров за 12 тысяч в месяц.

тот-же-фрилансер
Аноним 16/08/17 Срд 23:53:24 #505 №1045651 
>>1045642
За копейки -- может быть
Аноним 17/08/17 Чтв 00:01:35 #506 №1045658 
>>1045642
>c++ кодер, писал прошивки для роутеров за 12 тысяч в месяц
Страна возможностей, блин
Аноним 17/08/17 Чтв 00:03:11 #507 №1045660 
>>1045642
>написал американцу и буквально за 2 дня срубил сотню баксов
А сейчас уже такой трюк не пройдёт? И где искать таких заказчиков (если не секрет)?
>c++ кодер
Нихуя себе, туда вкатиться раз в десять сложнее, чем в веб.
Аноним 17/08/17 Чтв 00:18:00 #508 №1045672 
>>1045612

Просто на пыхе это не удобно, например. Там можно получить массив пикселей одной строкой, а тут писать 20. А ещё потом переводить формат MSAccess в хекс.
Аноним 17/08/17 Чтв 01:09:06 #509 №1045685 
Как называется хуйня которая накатывает вычищая вилкой абсолютно все мысли и не дает соображать. Хочется просто сидеть и тупо пялить в монитор пуская слюньку.
Я заебался уже, хочется учить, но не получается - приходится подстраиваться под эту дичь пропуская дни, недели.
Аноним 17/08/17 Чтв 01:10:12 #510 №1045686 
Может курить бросить, черт
Аноним 17/08/17 Чтв 01:12:27 #511 №1045688 
>>1045685
>вычищая вилкой абсолютно все мысли и не дает соображать
Галоперидол.
Аноним 17/08/17 Чтв 01:15:33 #512 №1045689 
>>1045688
Коварная мамка, чего она добивается?
Аноним 17/08/17 Чтв 01:23:42 #513 №1045690 
>>1045689
Пойди прогуляйся. Подыши воздухом. Мне при затыках помогает.
>>1045686
Не стоило и начинать. Такое ощущение что при курении интеллект сразу -20 минимум становится. Да и усидчивость теряется как таковая.
Аноним 17/08/17 Чтв 02:29:41 #514 №1045708 
>>1045690
То чувство, когда у тебя и без курения интеллект -20 и нет усидчивости.
Аноним 17/08/17 Чтв 04:52:35 #515 №1045728 
>>1045660
>А сейчас уже такой трюк не пройдёт? И где искать таких заказчиков (если не секрет)?
Да и сейчас свободно пройдет, 50 баксов в день это в принципе небольшие деньги для зарубежного фриланса.

>Нихуя себе, туда вкатиться раз в десять сложнее, чем в веб.
Да везде можно легко вкатиться, потому что тратить время экспертов на какую-нибудь софтину для ООО Вектор нерационально, да и сам профессионал не станет из-за копеек, а вот для джуиниора как подработка норм.
Аноним 17/08/17 Чтв 08:22:13 #516 №1045740 
>>1045551
Спасибо, возьму на заметку.

>>1045578
Я просто думаю, что это мне не нужно. Считаю, что лучше время направить не на изучение JS, а на улучшение навыков программирования в целом, читая книги Стива Макконнелли, Кормена, всякие статьи про php, sql, построение баз данных, паттерны и т.д.

>>1045608
А не "начинающий" бэкендер это кто? Какие у него должны быть навыки? Можешь хотя бы вкратце описать?

>>1045627
Спасибо. Короче нужно иметь не только хорошие навыки кодинга, но и знать английский.

Можешь посоветовать какие-нибудь книги? Не для чайников, а уже более продвинутого уровня? Или ты их не читаешь? Можно на английском.
Аноним 17/08/17 Чтв 10:50:29 #517 №1045767 
Сделал задачу Опа по вектору, решил сделать таблицу в HTML но я вот не понял, как вставить в HTML, PHPкод/
Вот кусочек моего кода: https://ideone.com/pph7Xm
someApprentice 17/08/17 Чтв 10:56:50 #518 №1045770 
>>1043617
> position: absolute;
>> top: 70%;
>Почему именно 70%? Не проще ли просто bottom: 0?
Если поставить bottom: 0, то почему-то не появляется прокрутка.

>Ты ведь вроде делал мои задачи на HTML, значит, ты наверно сможешь решить проблему. Давай начнем с простой задачи (реально простая):
>
>- есть див известной высоты (например, 300px или 100% от высоты страницы)
>- в него вложено содержимое неизвестной высоты
>- если оно маленькое, оно должно прижиматься к низу контейнера
>- если содержимого много, то должна появляться прокрутка
Стыдно признавать, но у меня даже не появляется идей как это сделать обычными средствами. Это нужно сделать с помощью flex?

>Я в том сообщении ( https://2ch.hk/pr/res/1000416.html#1007389 ) предложил возможные подходы, нужно просто их перебрать и посмотреть, реально их тут применить или нет. Если вообще никак, то придется использовать вычисление высоты через яваскрипт (с пересчетом при ресайзе окна), но конечно средствами CSS решить эту задачу было бы гораздо лучше (но в реальных задачах иногда приходится прибегать и к яваскрипту).
Меня немного смущает прибегать к флексу, потому что он не рассчитан на старые браузеры. Хотя в старых браузерах только слегка поломается отображение, это не так критично.

Вариант с табличным отображением я не рассматриваю, потому что, как вы писали, всё равно придётся прибегнуть к js.


У меня ещё есть вопрос по js. Опять про обработчики...

Установка обработчика, это часть контроллера или отображения?

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

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

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

В таком ключе становиться не важно кто устанавливает обработчик контроллер или отображение.

Я в правильном направление мыслю насчет роутера?
Аноним 17/08/17 Чтв 11:22:37 #519 №1045785 
>>1045770

Первая задача решается просто. У нас есть блок сообщений, и мы хотим прокрутку при превышении размера. Значит, нужно поставить max-height: 100% и overflow: auto;. По условиям задачи, высота контейнера у нас жестко задана (а не вычисляется из содержимого), потому мы можем использовать 100% здесь.

Получаем блок, который по высоте будет равен или меньше родителя. Остается только прижать его к низу контейнера за счет pos: absolute, width 100% (для АП элементов ширина по умолчанию определяется содержимым, а мы этого не хотим), bottom: 0;

У тебя не появлялась прокрутка из-за того, что ты наверно пытался ставить overflow на контейнер. То есть у тебя была ситуация:

- контейнер с overflow
- ребенок с position absolute, по высоте превышающий контейнер, с контентом, вываливающимся выше верхней границы контейнера

Тут есть один момент: прокрутка работает только для контента, который "вываливается" (overflows) из родителя вправо или вниз. Контент, который уходит влево или вверх, просто обрезается: https://jsfiddle.net/uusLtkku/

Я попытался найти документацию по этому поведению в описании свойства overflow в CSS2.1, а также в дополнениях из CSS3 и CSS4:

- https://www.w3.org/TR/CSS2/visufx.html#q11.0
- https://www.w3.org/TR/css-overflow-3/#scrolling-direction
- https://www.w3.org/TR/css-overflow-4/

Объяснение нашлось тут:

https://www.w3.org/TR/css-overflow-3/#scrolling-direction

> Due to Web-compatibility constraints (caused by authors exploiting legacy bugs to surreptitiously hide content from visual readers but not search engines and/or speech output), UAs must clip the scrollable overflow region of scroll containers on the block-start and inline-start sides of the box (thereby behaving as if they had no scrollable overflow on that side).

Block-start - это верхний край и inline-start это левый край для языков, где пишут справа налево и сверху вниз.
Аноним 17/08/17 Чтв 12:14:06 #520 №1045795 
Наконец-то смог запустить свою поделку на VPS!
http://195.181.244.246/
Исходники https://github.com/enotocode/birthday_reminder

Доделал реал-тайм валидацию на стороне клиента и на сервере. Вынес запросы к АПИ в отдельный слой.

Потратил пару дней на поиск и исправление ошибок. Зато теперь я уверен, что мои исходники можно запустить еще где-то кроме моего ноута. Сейчас я понимаю, почему ОП четыре раза говорил отказаться от компиляции кода в дев версии. Пересобирать скрипт после каждого чиха заметно увеличивает время на разработку.
Аноним 17/08/17 Чтв 12:45:05 #521 №1045806 
>>1045708
А чего сумбит неработает?
Аноним 17/08/17 Чтв 13:05:26 #522 №1045813 
Стоит ли учить фалькон?
Я знаю только чистый пхп.
Если да, то киньте гайдиков хороших, или книгу сразу, пожалуйста.
читаю на английском вполне хорошо, но информация лучше усваивается на родном все же
Аноним 17/08/17 Чтв 13:30:48 #523 №1045824 
Про основы Yii2 можно тут спросить?

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

Таблица clients, страница view\site\clients, контроллер \controllers\SiteController
public function actionClients()
{
if(Yii::$app->request->isAjax){
$idRow = Yii::$app->request->post('id');//принимаем id записи из js скрипта
$model = new Clients();
$model = Clients::find()->where(['id' => $idRow])->one();
$model->delete();
}
$listClients = Clients::find()->all();
return $this->render('clients', compact('listClients'));
}
Аноним 17/08/17 Чтв 16:39:59 #524 №1045906 
>>1045824
И ещё вопрос про логику контроллера. Я правильно понимаю, что если на странице есть несколько кнопок, которые делают разное (передают через пост/гет/аякс данные), то все действия с ними надо писать в контроллере этой страницы, т.е. для страницы clients всё пишется в actionClients?

Получается, внутри нужно ставить проверки "пришло ли чего в аякс/гет/пост?", а если кнопок, оправляющих, к примеру, постом, несколько, то внутри ещё и проверки "пришло ли post('id'), или пришло post(name')?"

Или я опять не понял?
Аноним 17/08/17 Чтв 17:23:29 #525 №1045919 
Есть вообше сервисы, предоставляюшие MySQL базу данных в аренду, для удаленного подключения? Мне нужна только база, без хостинга и прочего.
Аноним 17/08/17 Чтв 20:25:08 #526 №1045967 
>>1045906

Насчет нескольких форм на странице (вообще, такое не очень часто требуется), есть 2 варианта.

Первый - обрабатывать все в одном контроллере.

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

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

Второй вариант - сделать для каждой формы свою отдельную страницу, свой URL, который и выводит ее, и обрабатывает POST запрос. И формы с главной страницы просто отправляют данные на эту страницу.

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

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

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

> а если кнопок, оправляющих, к примеру, постом, несколько,
Кнопки отправляют собственное имя, по которому можно определить, какая из них нажата.

Аноним 17/08/17 Чтв 20:33:38 #527 №1045968 
>>1045967

Дополнение: Юи испоьзует довольно хитрый трюк для аякс-валидации форм. По мере заполнения формы он отправляет ее данные на тот же URL, на который она отправляется, но добавляет признак, что это аякс-запрос для валидации. И в этом случае вместо обработки формы происходит только проверка данных и возврат результата, на основании которого код показывает иконки ошибки.

Что касается твоего кода тут >>1045824 то там много странностей.

Например:

- почему ты используешь isAjax вместо какого-то явного признака, что это аякс запрос? При отладке ты вряд ли догадаешься что от какого-то второстепенного HTTP заголовка меняется поведение

- соответственно удаление логичнее делать в другом действии, не в том же, что и вывод списка

- при аякс-запросе результат обычно отдают в виде JSON, у тебя же почему-то в ответ на запрос рендерится и отдается HTML страница. Зачем?

- если ты работаешь с аяксом, прочти мой урок про правильное использование аякса https://github.com/codedokode/pasta/blob/master/js/ajax.md

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

Также, ты не привел тут JS код.
Аноним 17/08/17 Чтв 20:33:52 #528 №1045970 
Ты смешал в один экшн отображение всех клиентов и удаление какого-то кокретного, это неправильно. Создай actionDelete и туда отсылай аякс-запросы на удаление.

>>1045824
> $model = new Clients();
Строка лишняя.

>$model = Clients::find()->where(['id' => $idRow])->one();
> $model->delete();
Тут 2 SQL-запроса, а хватило бы одного.

И тебе нужно JSON-ответ возвращать, а не HMTL: https://github.com/samdark/yii2-cookbook/blob/master/book/response-formats.md#json-response
Ты с HTTP знаком? У ОПа на гитхабе есть пасты.

Алгоритм примерно такой:
1) Шлёшь аякс-запрос на удаление сущности
2) На стороне PHP удаляешь из базы сущность, возвращаешь JSON-ответ success: true, если неудачно то success: false
3) На стороне JS разбираешь этот JSON-ответ - если успешно - удаляешь нужный элемент из DOM-дерева.

>>1045906
На каждое действие (удаление, обновление и т.д) отдельный action, ты же сам понимаешь, что городишь неподдерживаемый код.

>>1045919
Бесплатно и быстро у хероку, но там постгрес. Платно у амазон.
Аноним 18/08/17 Птн 01:59:42 #529 №1046089 
ОП, короче сделал твою задачу, немного допилить нужно, но уже завтра, проверяй за щекойhttps://ideone.com/2Ozdw1
Многие обсирали мой код, но он работает.
Аноним 18/08/17 Птн 05:03:36 #530 №1046105 
Всем привет!

Имеется сайт на выделенном сервере с Ubuntu, PHP, nginx, Laravel. Сайт смотрит в обычный интернет, любой желающий может на него попасть через свой браузер.

Вопрос: возможно ли средствами PHP запилить get-запрос на другой сайт, но уже расположенный в зоне .onion, Т.е. Tor.

И если возможно, то как?
Аноним 18/08/17 Птн 06:34:40 #531 №1046119 
>>1044770

ОП, посмотри мой код, пожалуйста, это про компанию Вектор. Убрал из паблика все свойства. Переписал полностью классы департаментов и сотрудников. Начальные данные о составе департаментов и данные о ставках вынес в отдельные массивы, правда не очень логичным кажется постоянная передача этих данных в методы объектов ($manningTable и $staffList). Может имеет смысл их глобальными сделать.
В общем жду замечаний, а сам дальше буду пилить вторую часть задачи про антикризисные меры.

https://github.com/telepok/php-test/blob/master/oop4.php

В учебнике http://archive-ipq-co.narod.ru/ почему-то в хроме не работают ссылки в меню в левом столбце, приходится в другом браузере открывать, это только у меня так?
Аноним 18/08/17 Птн 07:33:34 #532 №1046124 
re.png
vcqg0bbcjk.png
Заебался чет, хули я такой тупой
Аноним 18/08/17 Птн 07:37:45 #533 №1046125 
Выравнивание колонок должо пилиться в функции или в методе? Наверное хватит думать будто оп хочет решение именно то которое и задумал автор мурзилки?
Аноним 18/08/17 Птн 07:52:12 #534 №1046127 
sooqa.png
debil.png
Мдааааааа
Аноним 18/08/17 Птн 07:52:59 #535 №1046128 
1.png
>>1046127
Падлефт не допилена, не обоссывай
Аноним 18/08/17 Птн 07:53:27 #536 №1046129 
>>1046128
Ой, прилипло
Аноним 18/08/17 Птн 08:10:45 #537 №1046130 
>>1046119
Лучше приступай к списку студентов, ООП ты уже знаешь
Аноним 18/08/17 Птн 08:47:32 #538 №1046135 
200s.gif
>>1046130
Никогда не думал, что ебучий список студентов может быть таким трудным.

мимоСинуб
Аноним 18/08/17 Птн 08:52:52 #539 №1046138 
>>1046130
Ну, так-то да, склоняюсь к этому, ну хотелось чтобы еще раз глянули код. Но за совет спасибо, пойдем дальше.
Кстати, по поводу списка студентов хотел спросить, точнее про шаблонизацию, стоит ли сразу пробовать какой-нибудь шаблонизатор, типа смарти, например? Или пока можно руками шаблоны делать? Впервые просто с этим сталкиваюсь.
Отписались разрабы с Идеона:
thanks for the report. The Multibyte String library is now not available on Ideone, but we keep these reports. When the number of the similar suggestions is big we add the requested library. We will tell you when we decide to do it.

Просто странно, никому не нужны мультибайт строки, или их поддержку так сложно добавить.
Аноним 18/08/17 Птн 08:58:10 #540 №1046139 
>>1046135
Че в пыху то перекатился?
>>1046138
Я сам говнокодер похуже тебя, чуть выше свое решение по вектору кинул, у меня там таблица в хтмл, просто знаю людей которые забили вообще на эту задачу и пошли дальше. Вот вам в помощь https://www.youtube.com/watch?v=ba3M3_Myrqg&t=1s
Аноним 18/08/17 Птн 09:04:11 #541 №1046140 
>>1046139
Да как-то я скептически к учебным роликам отношусь, мне комфортнее текст воспринимать с картинками. Хотя справедливости ради скажу, что Интенсивы от HTML Академии мне хорошо зашли, но там в придачу к видеокурсу были и рабочие материалы, макеты в PSD те же.
someApprentice 18/08/17 Птн 09:38:54 #542 №1046153 
>>1045785
Тогда во второй задаче, если высота формы не определяется содержимым, то нужно так же на неё поставить pos:absolute, bottom: 0, height: x;
А для блока с сообщениями задать bottom: x; и высчитать max-height: calc(100% - x);
Не уверен что функция calc имеет здесь место, но мне приходит в голову только такое решение.

https://jsfiddle.net/55khok9f/2/

Если высота формы определяется содержимым, то здесь у меня тоже возникают трудности. Можно ещё подсказку?
Аноним 18/08/17 Птн 10:00:39 #543 №1046164 
Без названия.jpg
Ребят, собираюсь вкатываться в Пыху, алсо вообще в веб-разработку, на стороне Си подучиваю. (Да я тот самый что спрашивал, стоит ли параллельно с ПхП учить Си, сказали ток лучше будет) И думаю вкатиться с этой книжкой. Любая же литература подойдет?
Да и книжка тоже параллельно с http://php.net/ читаться будет. Хотел ваше мнение об книжке спросить просто. Покупать не хочу, 30$ стоит.
>>1046139
Веб разработка как мне кажется приятней и проще рабочее место найти.
>>1046140
Я даже к книжкам с картинками скептически отношусь, как мне кажется там больше воды. Т.е хорошая книжка как правило дорого стоит. Я вообще CSS и HTML5 по этим ресурсам изучаю:
https://www.w3.org/TR/html51/
https://drafts.csswg.org/
Ибо там все до атомов разбирается, как работает синтаксис, даже примеры ввели. А там же еще и ответвления, типа вот
https://www.w3.org/TR/2011/REC-CSS2-20110607/#minitoc
И представь как я еще не заебался это все скроллить? Поэтому полюбил книжки, ибо там все кратко. Но тем не менее, захожу на спецификаций дабы подробнее изучить некоторые вещи. В книжках алсо дают эту информацию но в аспекте который обязательно нужно знать, а все детали типа white_space_separate_tokens опускаются.
Аноним 18/08/17 Птн 10:42:28 #544 №1046174 
>>1045967
Я пытаюсь разобраться в Yii2. Нашёл видеоуроки https://www.youtube.com/channel/UCo8uH16xQsZCJL5VqZ-g9QA прошёл их, и теперь пытаюсь повторить что-то такое уже самостоятельно, поэтому в основном копипащу оттуда. Разобраться, конечно, нужно, но пока нереально. То есть, по ходу дела разбираюсь в чём-то, просто повторяя то, что работает. Ну не могу я окинуть всё взглядом и полностью разобраться во всём сразу.

>Первый - обрабатывать все в одном контроллере.
То есть, в контроллере нужно делать проверку, какая именно форма сработала, так?
>если кнопок, оправляющих, к примеру, постом, несколько, то внутри ещё и проверки "пришло ли post('id'), или пришло post(name')?"

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

>Второй вариант - сделать для каждой формы свою отдельную страницу
Это тоже понятно.

>Если это обработчик аякс-запроса, то так делать смысла нет. Для него нужен отдельный контроллер.
Насколько я понял, для каждой страницы может быть только один контроллер. И это прибито гвоздями (должны совпадать их имена). То есть, для страницы view\site\clients.php есть один и только один контроллер с именем controllers\SiteController.php

>>1045968
>почему ты используешь isAjax вместо какого-то явного признака, что это аякс запрос?
Так было в примере. И какие могут быть другие признаки аякса, кроме isAjax? Это вроде логично выглядит.
>соответственно удаление логичнее делать в другом действии, не в том же, что и вывод списка
Да. Но я не знаю, как их разделить. При отправке из view\site\clients.php, срабатывает контроллер SiteController, а в нём public function actionClients(). Как я уже писал, в уроках было написано, что это всё жёстко определено. Сам вижу, что пихать разные действия в одну фнкцию как-то неправильно, но как разделить не знаю.
>при аякс-запросе результат обычно отдают в виде JSON, у тебя же почему-то в ответ на запрос рендерится и отдается HTML страница. Зачем?
Логика такая:
Во вью написано: <button type='button' onclick='deleteRow(<?=$id?>, <?=$table?>);'>Удалить</button>
В JS-скрипте deleteRow(id, table) собирает со страницы id записи и имя таблицы, а затем передаёт аяксом на url:"index.php?r=site/clients". Хм. Получается, можно и не туда передавать, а в отдельный метод? Например, site/delete, и в контроллере прописать для него этот метод public function actionDelete(). Я правильно понял?
Но возвращаюсь к текущей логике. Данные аяксом уходят в контроллер, в actionClients(). Контроллер удаляет выбранную строку из таблицы, и мне нужно, чтобы он обновил вью страницы, показав таблицу без удалённой строки. Ага, получается, вместо обновления страницы, рендер уходит, как ответ success аяксу JS-скрипта? Получается, что обновлением должен заниматься JS-скрипт? Блин, у меня мозги в трубочку от этой хрени заворачиваются.
>Ну так написано в твоем коде.
У меня проблемы с пониманием, что движок делает за меня, а что нет.
>>1045970
>Создай actionDelete и туда отсылай аякс-запросы на удаление.
Попробую.
>Тут 2 SQL-запроса, а хватило бы одного.
Такого?
$model = Clients::find()->where(['id' => $idRow])->one()->delete();
>И тебе нужно JSON-ответ возвращать
Да, уже понял, что обновление должен делать JS, а ему для этого нужно что-то дать. В уроках этот момент не был освещён, там после принятия данных через аякс, контроллер сам обновлял вью.

В общем, спасибо, буду мучать Yii дальше.
Аноним 18/08/17 Птн 11:18:27 #545 №1046181 
Предложили мне тут работенку жуниор разработчика на Magento. Опыта у меня на уровне задачки про студентов и недоделанного файлообменника, сказали обучат меня всему что нужно. Кто-то с этой самой мажентой работал? Судя по описанию это какой-то монстр прямо, оно вообще нормально для жуниора? Расскажите про подводные камни.
Аноним 18/08/17 Птн 11:18:43 #546 №1046182 
>>1046174

> И какие могут быть другие признаки аякса, кроме isAjax?
Как по твоему Yii определяет значение этого поля? Как он догадывается, что запрос отправлен аяксом?
Аноним 18/08/17 Птн 11:26:10 #547 №1046186 
>>1046164
Я конечно извиняюсь, но с атомами ты загнул, имхо, это же не наука, а прикладная область. В реальной практике пригодятся ли тебе такие тонкости?

И еще по поводу книги. Если ты про 4 издание на английском, то оно в первой ссылке гугла даром скачивается. Зачем покупать-то. Я вообще считаю, что не стоит покупать то, что не обернется материальной выгодой. Но это уже лирика. В общем именно книжка с картинки скачивается на раз, 800 страниц, могу почтой выслать, лол.
Аноним 18/08/17 Птн 11:31:08 #548 №1046188 
>>1046182
>Как по твоему Yii определяет значение этого поля? Как он догадывается, что запрос отправлен аяксом?
ВААААХ! ХАЙТАН-МАШИН АЯКС ПРИШЙОЛ!
Пока что это для меня чёрный ящик
Аноним 18/08/17 Птн 11:49:42 #549 №1046194 
somnambula.jpg
Нужна помощь - реализуемо ли, по каким названиям функций гуглить.
На моём сайте в странице условный код JS:
<script>
readFile("http://МОЙСАЙТ/data.php");
</script>
data.php возвращает текстовый файл.
Итак, вопрос, можно ли сделать, если ссылку http://МОЙСАЙТ/data.php скопировать в адресную строку, браузер покажет мою заглушку, но никак не текстовый файл. А скрипту js на странице возвращает нужный текстовый файл.
Аноним 18/08/17 Птн 11:56:49 #550 №1046197 
>>1046181
>Magento
Не работал, но скажу что важно помнить что это CMS т.е. один из многих продуктов на PHP и то что, возможно, некоторые вещи, могут быть, реализованы в ней не канонично и не по стандартам.
Всегда стоит подтягивать знания по фундаментальным вещам и смотреть современные фреймворки, не ограничивая свои знание одной из тысячи CMS.
Аноним 18/08/17 Птн 12:15:35 #551 №1046204 
>>1046197
Я так почитал, эта мажента написана на зенд фреймворке, так что возможно там все норм. Только там какое-то свое видение MVC, с какими-то блоками, шаблоны как-то грузятся с помощью XML(что бы это значило, хуй поймешь).
Аноним 18/08/17 Птн 13:02:20 #552 №1046214 
>>1046186
Так я же об этом написал, мои намеки конеш тупые. Я имел ввиду >Покупать не хочу всмысле я ее спизжу. Просто хотел мнение узнать анонов, может кто читал, авось рецензию свою даст.
В принципе O'relly говна не пишут же?
Аноним 18/08/17 Птн 14:06:57 #553 №1046258 
>>1046214
Я бы порекомендовал идти по урокам ОПа, дополнительно гуглить и спрашивать тут. Или там какой-то простенький курс по основам на ютубе посмотреть. А учебники по пхп то еще говнище в основном. Есть только 2-3 годных, но они далкео не для ньюфагов.
Аноним 18/08/17 Птн 14:40:32 #554 №1046265 
CI.png
Привет, котоны. Занимаюсь сейчас разработкой проекта системы управления абонентами для местного провайдера. Суть в том, что часто приходится работать с IP-адресами, вследствие чего получается лютый говнокод т.к. приходится разбивать диапазоны на адреса, адреса на октеты, высчитывать подсети и т.д. Есть какие-нибудь библиотеки для удобной работы с IP? Пишу на Codeigniter 3 и для него точно таких либ нет, но зато находил просто на PHP, но что-то у меня с ними не срослось.
Аноним 18/08/17 Птн 14:44:20 #555 №1046268 
>>1046135
Да я сам в шоке был.
Аноним 18/08/17 Птн 15:18:30 #556 №1046282 
Почему в пхп так много перекатившихся из си?
Аноним 18/08/17 Птн 17:13:38 #557 №1046364 
>>1046194
Авторизация клиент-сервер
Сохраняешь куку на клиенте
При обращении к http://МОЙСАЙТ/data.php проверяешь на сервере куку -> авторизованный? отдаешь файл -> нет? отдаешь заглушку.
Аноним 18/08/17 Птн 17:42:17 #558 №1046376 
изучил пхп.теперь нихуя не знаю,как начать проэктировать сайт наподобии форума
Аноним 18/08/17 Птн 18:00:08 #559 №1046393 
>>1046265
>приходится разбивать диапазоны на адреса, адреса на октеты, высчитывать подсети и т.д.
Напиши сам библиотеку, я вот в период изучения диапазонов и масок вообще хотел пет-проджект сделать - ip-калькулятор. Вообще и сейчас не теряю надежды, вот выучу сейчас пхп и обязательно сделаю :-)

>>1046258
Двачую оратора. В книжках, особенно если быстро надо освоить, начинаешь читать, читаешь, читаешь, предисловие, благодарности женам, любовницам, потом главу про то, каким крутым ты станешь, а потом когда доходишь до примерно 400-500 страницы, осознаешь, что еще 500-600 осталось, и начинается выгорание. А практического опыта-то и нет, и время потратил. В общем двойственно это все. Почему везде и советуют идти в офис, потому что нужны именно практические навыки, то есть результат, причем работающий.

К слову про атомы, я когда физиком должен был стать, так вот препод нам говорил слова одного ученого: Теория без практики мертва, практика без теории слепа. Такие дела.
Аноним 18/08/17 Птн 18:08:57 #560 №1046399 
x35711a3b.jpg
>>1046376
Я, конечно, извиняюсь, но как же ты выучил пхп, если ты даже задачку "Grammar Nazi" из учебника ОП не сделал?
Аноним 18/08/17 Птн 18:12:29 #561 №1046401 
>>1046376

В шапке есть задача про студентов, файлообменник и про тестхаб - почитай их описания, попробуй решить и после этого форум не будет для тебя представлять проблемы.
Аноним 18/08/17 Птн 18:29:51 #562 №1046413 
14606737719371.webm
>>1046265

Хочу сгенерить хеш файла для параметра integrity
( https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity )

Делаю так:
integrity="sha512-<?=hash_file( 'sha512', $_SERVER['DOCUMENT_ROOT'].'/s/js/script.js' ); ?>"

Получаю ошибку в браузере:
Failed to find a valid digest in the 'integrity' attribute for resource 'http://blablabla.ru/s/js/opt/main.min.js' with computed SHA-256 integrity 'i/EDj3xxy4ipuu4jpvF0fEo5QEHK3FG7Yu4Olqgpnjc='. The resource has been blocked.

Уже битый час бьюсь, не могу понять причину.
ЧЯДНТ? Чому хэши не сходятся?
Аноним 18/08/17 Птн 18:56:20 #563 №1046425 
>>1046105
Да, через прокси в тор
Аноним 18/08/17 Птн 18:57:30 #564 №1046426 
magspace.ruVonni139827.jpeg
>>1046124
Аноним 18/08/17 Птн 19:01:06 #565 №1046427 
>>1046282
PHP написан на C
Синтаксис похож
Аноним 18/08/17 Птн 19:03:07 #566 №1046428 
>>1046413
Да, в ошибке почему-то SHA256,
Но если ставить этот или любой алгоритм из списка -- всё равно не сходится
Аноним 18/08/17 Птн 19:54:10 #567 №1046456 
>>1046426
Проорал
Аноним 18/08/17 Птн 20:05:09 #568 №1046466 
Вопрос по оптимизации. Избавился от N+1 при выводе страницы за счёт джойнов и группировок, количество SQL-запросов уменьшилось, а вот peak memory usage увеличился на 7-10%, судя по показаниям тулбара Yii2. Из-за чего это могло произойти и что значит этот peak memory usage? Может ли гидрация связей быть тому виной?
Вообще проблема в том, что сайт недоступен при большом количестве посетителей. Это ведь возможно из-за нехватки оперативы? Например зашло 100 пользователей, каждый скрипт отъел 10 мб, итого 1ГБ. И если на сервере оперативы меньше, то для 101-го пользователя места уже не будет? Меня интересуют скорее общие советы и рекомендации при оптимизации, в первый раз с таким сталкиваюсь.
Аноним 18/08/17 Птн 20:16:27 #569 №1046470 
>>1046427
Тогда почему все любят С и ненавидят рнр?
Аноним 18/08/17 Птн 20:54:01 #570 №1046482 
Посоветуйте книг по фалькону. Или русских гайдов годных.
Чтоб за неделю осилить и переписать ядро сайта на это.
Аноним 18/08/17 Птн 21:17:34 #571 №1046494 
>>1046470
По беспределу
Аноним 18/08/17 Птн 22:42:07 #572 №1046531 
>>1046466
Возможно.

Как именно сайт "недоступен", что происходит?
Аноним 19/08/17 Суб 00:07:09 #573 №1046579 
Что не так?
https://ideone.com/fork/523cQA
Суть такова, что есть ряд чисел, нужно вывести количество пятёрок в нём. У меня выводит количество всех чисел.
Аноним 19/08/17 Суб 00:08:23 #574 №1046580 
>>1046579
https://ideone.com/t9gMBC
Аноним 19/08/17 Суб 00:15:25 #575 №1046585 
>>1046580
https://ideone.com/wvMekM Тут я вообще не могу понять, что вышло.
Аноним 19/08/17 Суб 01:02:14 #576 №1046604 
>>1045740
>Можешь посоветовать какие-нибудь книги? Не для чайников, а уже более продвинутого уровня?
Почти не читаю, но мне понравилось "Modern PHP: New Features and Good Practices", норм книга.

>>1046164
Для начинающего в принципе норм.
Аноним 19/08/17 Суб 01:18:54 #577 №1046610 
>>1046585
Пиздец ты криворукий, сравнение это ==, а = это присваивание. Ты в if не сравниваешь, а присваиваешь.

Вот как всё должно быть
https://ideone.com/60gE6g
Аноним 19/08/17 Суб 10:04:20 #578 №1046695 
изображение.png
изображение.png
изображение.png
>>1046119
>Пикрил.жпг
А что так стоит делать? Я думал лучше в отдельном классе создавать объект Департамента и в функцию адд департмент уже сам объект кормить.

public function addDep (Department $dep) {
...
}

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

>пик 3
Похоже что элегантная задумка, но для меня как для стороннего разраба ковыряющего твой код это выглядит как адовый костыль.
Вместо инфы в самих классах я вижу что это сторонний хардкод где-то в середине программы, который хз каким функциям кормится и хз как с ним вообще работать :(
Аноним 19/08/17 Суб 10:08:53 #579 №1046697 
>>1046265
Опытный игнайтеромакак в треде, что конкретно у тебя не получилось? Ты не смог либу подрубить в коде или что? И почему говнокод? Не можешь модель написать для работы с ip?

Приведи пример что ли типовых задач, интересно даже стало.
Аноним 19/08/17 Суб 10:11:44 #580 №1046699 
>>1044252
>0 попыток решить
>задача по сложности для тех кто осилил первые уроки опа

Бля, я расстроен с вас :(
Аноним 19/08/17 Суб 10:40:31 #581 №1046709 
Сап анон. Настроил в PhpStorm depluyment на сервер через FTP. Если в папке с проектом удалить файл и залить ее на сервер, то на сервере файл останется. Что я сделал не так?
Аноним 19/08/17 Суб 12:24:31 #582 №1046769 
>>1046709
Ты заменил на сервере все файлы кроме удаленного вангую.
Аноним 19/08/17 Суб 13:41:44 #583 №1046810 
Кто-нибудь пользуется VS? Подходит для создания сайтов?
Аноним 19/08/17 Суб 15:04:07 #584 №1046870 
>>1046610
Братиш не хочешь стать моим ментором
Аноним 19/08/17 Суб 17:43:51 #585 №1046985 
>>1046695
Если я правильно понял Опа, мы не должны самостоятельно создавать объекты, а действовать через методы. В данном случае у нас есть компания, в которой есть департаменты, о которых мы знаем только название,и в этих департаментах есть сотрудники, о которых мы знаем тоже только относящуюся к ним информацию. Проще же передать в качестве параметра название, а остальное за нас пусть делает сам объект. То же самое и с сотрудниками - есть департамент, нужно добавить туда сотрудника - одна строчка кода, остальное - "магия". Это по первому и второму пикам.
По поводу штатного расписания. Везде по разному, конечно, но в некоторых организациях штатное расписание утверждается на целый год, а иногда в него не вносятся изменения и несколько лет подряд, если, собственно, не меняется штатная численность. Такой, своего рода, hard-code. Но это именно так и есть, потому что это расписание утверждается на самом высоком уровне, ведь это и фонд оплаты труда, и налогообложение и т.д. Так что для меня реальность, что это не меняется ежесекундно. Аналогично и с свойствами должностей-профессий. Оклады меняются еще реже, чем штатная численность.К сожалению.
А в плане технической реализации - ну вот я сам себе такой вариант придумал, в ентерпрайз решениях понятно, что это все может выглядеть совершенно иначе. Ну и браться это будет не из кода, очевидно, а из базы данных, ну так задача-то не о том :-)

ЗЫ. И по поводу кофе. Сейчас как раз приняты антикризисные меры. На всё введены нормы. В то числе на туалетную бумагу. И вот кончилась бумага в середине квартала - никто тебе не побежит еще закупать, ну ты понел.
Аноним 19/08/17 Суб 17:51:31 #586 №1046988 
>>1044252
Лично я уже ускакал студентов пилить. Но можно и эту задачу посмотреть. У меня подозрение, что через рекурсию можно сделать, еще не пробовал. Можно и в лоб.
Я одного только не понял, почему функция называется persistence? Что это означает?
Аноним 19/08/17 Суб 18:24:45 #587 №1047003 
>>1046413
>>1046428
Бамп вопросу федерального значения
Аноним 19/08/17 Суб 19:20:14 #588 №1047024 
>>1046709

Может быть там настройки в стиле "только добавлять"? Удалять файлы на сервере (которых нет локально) может быть опасно, так как это может быть какой-то нужный файл.

>>1046119

> В учебнике http://archive-ipq-co.narod.ru/ почему-то в хроме не работают ссылки в меню в левом столбце, приходится в другом браузере открывать, это только у меня так?

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

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

По поводу добавления департаментов/работников (должен ли департамент создавать работников или ему должны передавать готовых) - здесь есть 2 подхода, аггрегация и композиция: https://ru.wikipedia.org/wiki/%D0%90%D0%B3%D1%80%D0%B5%D0%B3%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_(%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5)

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

Ты явно пытаешься тут реализовать композицию, когда депртаменты не могут существовать вне компании, а работники - вне департамента. У нее такие недостатки:

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

- нельзя использовать для работников другие классы, так как в коде жестко прописано new Employee

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

> public function getSalary($staffList)
Вот это не красиво. Почему мы для того, чтобы просто узнать зарплату, должны что-то передавать? Ну представь, что ты в коде получил объект Компании, из него доста Департамент, из него Работника, и хочешь узнать его зарплату:

$dep = $company->getByName(...);
$employee = $dep->findEmployee(...);
echo $employee->getSalary($staffList);

Ты должен передать справочник зарплат. Но почему этот справочник должен знать ты, а не Работник, Департамент или Компания? Где должен храниться справочник - в Компании или у того, кто хочет ее как-то использовать? У тебя, получается, Компания не знает, какие зарплаты у ее работников.

То есть я вижу такие варианты:

- вынести расчет зарплаты в специальный объект КалькуляторЗарплаты, и хранить ссылку на него в Работнике. работник использует Калькулятор для расчета своей зарплаты. Выгода в том, что можно поменять зарплату всем работникам одним изменением в Калькуляторе. Трудно поменять зарплату индивидуально одному работнику.
- поместить Калькулятор в Департамент или Компанию, и сделать так, что узнать зарплату работника можно только через них ($company->getEmployeeSalary($employee)). Можно даже сделать Калькулятор частью компании.
- поместить в работника информацию, нужную для расчета своей зарплаты. Выгода в том, что можно задавать зарплату каждого работника индивидуально, но для повышения зарплаты всем придется обойти всех в цикле.

> $coffee = $staffList[$this->profession][1];
Вот это вот трудно понять. Что такое 1? Почему именно 1? Лучше было бы $staffList[$this->profession]['coffee']; или хотя бы $staffList[$this->profession][self::FIELD_COFFEE];

> ($company->getByName($manningTableItem[0]))->addEmployee($manningTableItem[1], $manningTableItem[3],
$manningTableItem[4]);
Это тяжело читать, сложное выражение, лучше было бы сделать так:

list($depName, $rank, $count, $x, $y) = $tableItem;
$departament = $company->getByName($depName);
$departament->addEmployee($rank, $z, $w, $x, $y);

Сравни, насколько лучше читается.

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

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

> правда не очень логичным кажется постоянная передача этих данных в методы объектов ($manningTable и $staffList).
Правильно кажется.

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

> Я понимаю что если еще это можно оправдать реальностью, и как бы сама организация ирл будет рожать подразделения, то вот пик два уже не очень.
С работниками, да, композиция плохо подходит, так как у нас может быть 2 компании и работники могут переходить из одной в другую, а композиция подразумевает, что вложенный объект не может существовать без родительского и работник уничтожается вместе с компанией.
Аноним 19/08/17 Суб 19:20:36 #589 №1047025 
>>1046695

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

>>1046579

Тебе уже написали про =/==, а я дополню еще что ты непраивльно работаешь со строками. strlen() и $string[$i] работают только для строк на латиннице, не будут работать например с кирилицей: https://github.com/codedokode/pasta/blob/master/php/strings-utf8.md

>>1046466

peak memory usage это максимальное потребление памяти за время работы скрипта. Возможно, ты выбираешь больше данных из БД, например. Если тебя интересует поиск места, где выделяется много памяти, то придется заморочиться с xdebug, который умеет делать среди прочего 2 вещи:

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

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

Ну и есть еще "ручная" трассировка - расстановка вручную в коде команд, выводящих время выполнения/потребление памяти в текущий момент.

> Вообще проблема в том, что сайт недоступен при большом количестве посетителей. Это ведь возможно из-за нехватки оперативы? Например зашло 100 пользователей, каждый скрипт отъел 10 мб, итого 1ГБ. И если на сервере оперативы меньше, то для 101-го пользователя места уже не будет? Меня интересуют скорее общие советы и рекомендации при оптимизации, в первый раз с таким сталкиваюсь.
Это другая проблема и решается другим способом. Для начала надо сделать общий обзор ситуации, найти, где узкое место, каких ресурсов не хватает для обработки запроса. Для этого в линуксе есть много инструментов:

https://habrahabr.ru/post/114082/
https://habrahabr.ru/company/ua-hosting/blog/281519/

Ну например, если ты увидишь, что диск загружен на 100%, а CPU на 50% - станет понятно, что узкое место все же в дисковой подсистеме.

Заодно стоит проверить логи (/var/log) - там может быть например информация о завершении процессов OOM-killer'ом из-за нехватки памяти. В логах веб-сервера может быть информация о превышении каких-то ограничений.

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

Для использования инструментов нужно иметь права администратора. Эксперименировать на продакшене может быть нежелательно, тогда можно имитировать систему у себя, используя ab или siege для искуственного создания нагрузки. Разумеется, копия системы в вируталке может не соответствовать реальной системе на продакшене, так что top лучше бы запускать там.

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

Также, стоит проверить настройки Юи. Не используешь ли ты dev режим на продакшене?

> Например зашло 100 пользователей, каждый скрипт отъел 10 мб, итого 1ГБ. И если на сервере оперативы меньше, то для 101-го пользователя места уже не будет?
Примерно это так, но на деле все сложнее - так как есть виртуальная память и своппинг. Также, если скрипт работает быстро, то он сгенерирует страницу и освободит память. А вот если медленно то, да, число параллеьно работающих скриптов и потребление памяти начинает расти. Ну и на веб-сервере обычно есть лимит на число соединений, и лишние ставятся в очередь.
Аноним 19/08/17 Суб 19:20:56 #590 №1047027 
>>1046413

В каком формате выдает данные функция вычисления хеша в PHP и в каком требуется их указывать в HTML? Ведь сам по себе хеш - это большое двоичное число, которое трудно представить в виде символов. Обычно используют какую-то форму, например, шестнадцатеричный вид или base64.

В PHP - http://php.net/manual/ru/function.hash-file.php

> Возвращает строку, содержащую вычисленный хеш-код в шестнадцатеричной кодировке в нижнем регистре. Если raw_output задан как TRUE, то возвращается хеш-код в виде бинарных данных.

В HTML:

> You use the Subresource Integrity feature by specifying a base64-encoded cryptographic hash of a resource (file) you’re telling the browser to fetch, in the value of the integrity attribute of any <script> or <link> element.
> An integrity value begins with at least one string, with each string including a prefix indicating a particular hash algorithm (currently the allowed prefixes are sha256, sha384, and sha512), followed by a dash, and ending with the actual base64-encoded hash.

У тебя явно используются разные способы представления хеша, попробуй сдампить результат hash_file()

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

>>1046265

Попробуй погуглить библиотеки, можно на phptrends или packagist.org

>>1046214

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

Скидывайте названия или ссылки на книги в тред, я потом как-нибудь пролистаю и прокомментирую.
Аноним 19/08/17 Суб 19:21:36 #591 №1047028 
>>1046194

Ты понимаешь принцип работы протокола HTTP? Что мешает пользователю подсмотреть передаваемый с сервера трафик? Что мешает ему воспользоваться инструментами отладки в браузере?

>>1046188

ну так открыл бы документацию или код Юи и поискал, как оно выставляется. Мне не нравится идея использовать это поле. Для аякс-действий логично делать отдельные URL.

>>1046186

Вообще, это не очень хорошо что скачивается бесплатно. Кто будет писать хорошие книги, если за них никто не заплатит?

>>1046174

>>Первый - обрабатывать все в одном контроллере.
> То есть, в контроллере нужно делать проверку, какая именно форма сработала, так?
Да.

> Насколько я понял, для каждой страницы может быть только один контроллер. И это прибито гвоздями (должны совпадать их имена). То есть, для страницы view\site\clients.php есть один и только один контроллер с именем controllers\SiteController.php
Во-первых, нет, погугли про роуты (маршруты). То что ты описал - это схема по умолчанию (кстати, плохая для SEO) и можно задавать шаблоны URL страниц явно.

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

> для страницы view\site\clients.php
Когда я говорил про второй вариант, я имел в виду отдельные страницы для каждой формы, с отдельными URL, контроллерами и шаблонами.

> Да. Но я не знаю, как их разделить. При отправке из view\site\clients.php, срабатывает контроллер SiteController, а в нём public function actionClients(). Как я уже писал, в уроках было написано, что это всё жёстко определено. Сам вижу, что пихать разные действия в одну фнкцию как-то неправильно, но как разделить не знаю.
Сделать для аякс-запроса другой URL и другой контроллер.

> Получается, можно и не туда передавать, а в отдельный метод?
Да

> Получается, что обновлением должен заниматься JS-скрипт?
Есть разные варианты, можно просто удалять строчку из DOM, можно генерировать новую таблицу и яваскриптом подменять содерждимое. Удалять одну строчку конечно лучше, так как при подмене могут быть нежелательные эффекты вроде потери фокуса, содержимого инпутов и тд.

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

> У меня проблемы с пониманием, что движок делает за меня, а что нет.
нужно читать документацию (не уроки) и исходный код - благо Юи относительно простой и прямолинейный. Почитаешь исходный код, и думаю, вопросы отпадут.
Аноним 19/08/17 Суб 19:22:08 #592 №1047029 
>>1046164

> Я вообще CSS и HTML5 по этим ресурсам изучаю:
Правильно. Я их тоже когда-то читал. Но хотел бы (нескромно) посоветовать мой курс задач на HTML/CSS из шапки - там ты сможешь проверить применение теоретических знаний на практике.

>>1046186

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

>>1046153

Можно, так, хотя calc работает не везде: https://caniuse.com/#search=calc - на некоторых платформах только с конца 2013 года. А без поддержки calc сообщения будут обрезаться.

А что насчет варианта, когда высота формы неизвестна и определяется содержимым? Тут я вижу ровно 2 варианта:

- таблица с 2 ячейками. Плюс: хорошая поддержка в браузерах, есть вертикальное выравнивание. Проблема: если контейнером является ячейка таблицы, мы не можем использовать на ней position: absolute/relative, overflow, не можем для детей использовать проценты в height/max-height (так как проценты в height на непозиционированных элементах работают только когда высота родителя известна или вычисляется).
- flex позволяет сделать вертикальную ось, на ней 2 элемента, и задать политику распределения свободного места так, что нижняя часть получает сколько ей нужно, а верхняя - все остальное. Проблема: разные баги и поддержка браузеров.

Баги flex:

- http://css-live.ru/articles/uporyadochivanie-bagov-krossbrauzernosti-flexbox.html
- https://github.com/philipwalton/flexbugs

Поизучай описание flex, и заодно посмотри, может можно сделать какую-то альтернативу для старых браузеров (например чтобы в них просто выводилось 2 блока без overflow, и сообщения прокручивались за счет прокрутки всей страницы).

>>1046138

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

>>1046135

Если сложности с ООП, то стоит вернуться на шаг назад и порешать мои задачи на ООП из учебника. Также, внимательно изучить комментарии к самой задаче - там много информации.
Аноним 19/08/17 Суб 19:22:39 #593 №1047030 
>>1046125

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

>>1046127

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

Не называй переменные ничего не значащими именами вроде array.

>>1046105

Поднять у себя на сервере тор-прокси и обращаться к нему.

>>1046089

Ты предыдущие замечания исправил? Какой смысл мне писать то же самое второй или третий раз?

Прочитай пожалуйста внимательно этот пост с замечаниями сначала >>1044779

>>1045770

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

display: block; / для старых /
display: flex; / для новых, переопределит предыдущую строку /

желательно конечно оставлять комментарии в таких сложных случаях.

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

> Установка обработчика, это часть контроллера или отображения?
Я не знаю, думаю, что можно делать и так и так, лишь бы это было единообразно в приложении.

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

var contactList = new ContactListWidget(...);
var messagesList = new MessagesWidget(...);

contactList.addOnSelectHandler(function(contact) {
var messages = findMessages(contact);
messagesList.loadMessages(messages);
});

Тут 2 виджета не знают друг о друге. Их связывает вышестоящий код.

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

var messageModel = new MessageModel;
var messageList = new MessageListWidget(messageModel);
var formWidget = new SendMessageFormWidget();
formWidget.onMessageSent(function (message) {
messageModel.sendMessage(message);
});

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

> Создается впечатление, что должно быть что-то вроде роутера, который держит все виджеты и устанавливает обработчики на них, которые занимаются взаимодействиями между друг другом.
Это и есть вышестоящий контроллер. То есть виджет отвечает только за свою область, а контроллер манипулирует виджетами и отвечает за состояние всей страницы.
Аноним 19/08/17 Суб 19:23:03 #594 №1047031 
>>1045767

Маркер <?php работает только вне PHP кода. Ты используешь его внутри и потому он не рабоатет. МАнуал:

- http://php.net/manual/ru/language.basic-syntax.phpmode.php
- http://web.archive.org/web/20161119062218/http://www.phpinfo.su/articles/practice/shablony_v_php.html

Лучше всего сделать шаблон в отдельном файле, если это невозможно, то можно в функции, такого вида:

function renderTable(...) {

?>

HTML код

<?php
}

>>1045658

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


>>1045587

по виртуальной машине как раз гайдов нет ((

>>1045537

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

>>1045428

Проще всего использовать относительные ссылки без хоста: /some/url. Если ты хочешь запускать проект из папки, придется как-то передавать с сервера или задавать в конфиге базовый путь.

>>1045400

> Апач наследует дескрипторы от какого-то "файла устройств"
Обычно сервисы запускает systemd, я думаю что на stdin он дает /dev/null, а stderr ловит и отправляет в логи. Но зависит от настроек. Глянул у себя в Дебиане:

$ ps ax --format 'pid,ppid,wchan,cmd' | grep apache
1707 1 poll_s /usr/sbin/apache2 -k start
17353 1707 inet_c /usr/sbin/apache2 -k start
17354 1707 inet_c /usr/sbin/apache2 -k start

# управляющий процесс
$ sudo ls -l /proc/1707/fd/
lr-x------ 1 root root 64 Aug 16 12:37 0 -> /dev/null
l-wx------ 1 root root 64 Aug 16 12:37 1 -> /dev/null
lr-x------ 1 root root 64 Aug 16 12:37 10 -> /dev/urandom
lrwx------ 1 root root 64 Aug 16 12:37 11 -> /tmp/.ZendSem.EPXa2M (deleted)
l-wx------ 1 root root 64 Aug 16 12:37 12 -> /run/lock/apache2/proxy.1707 (deleted)
l-wx------ 1 root root 64 Aug 16 12:37 13 -> /run/lock/apache2/rewrite-map.1707 (deleted)
l-wx------ 1 root root 64 Aug 16 12:37 14 -> /run/lock/apache2/mpm-accept.1707 (deleted)
l-wx------ 1 root root 64 Aug 16 12:37 2 -> /var/log/apache2/error.log
lrwx------ 1 root root 64 Aug 16 12:37 3 -> socket:[12811]
lrwx------ 1 root root 64 Aug 16 12:37 4 -> socket:[12812]
lr-x------ 1 root root 64 Aug 16 12:37 5 -> pipe:[116001]
l-wx------ 1 root root 64 Aug 16 12:37 6 -> pipe:[116001]


Видно, что 0 и 1 указывают на устройство /dev/null, а 2 - на лог (который скорее всего сам Апач и открыл). Ссылки на удаленные файлы - это временные файлы, которые создаются и сразу же удаляются из каталога, но остаются на диске, пока они открыты. Пайпы и сокеты либо используются для коммуникации с воркерами либо просто забыли закрыть.

# Рабочий процесс
$ sudo ls -l /proc/17353/fd/
lr-x------ 1 root root 64 Aug 16 12:39 0 -> /dev/null
l-wx------ 1 root root 64 Aug 16 12:39 1 -> /dev/null
lr-x------ 1 root root 64 Aug 16 12:39 10 -> /dev/urandom
lrwx------ 1 root root 64 Aug 16 12:39 11 -> /tmp/.ZendSem.EPXa2M (deleted)
l-wx------ 1 root root 64 Aug 16 12:39 12 -> /run/lock/apache2/proxy.1707 (deleted)
l-wx------ 1 root root 64 Aug 16 12:39 13 -> /run/lock/apache2/rewrite-map.1707 (deleted)
l-wx------ 1 root root 64 Aug 16 12:39 14 -> /run/lock/apache2/mpm-accept.1707 (deleted)
lrwx------ 1 root root 64 Aug 16 12:39 15 -> anon_inode:[eventpoll]
l-wx------ 1 root root 64 Aug 16 12:39 2 -> /var/log/apache2/error.log
lrwx------ 1 root root 64 Aug 16 12:39 3 -> socket:[12811]
lrwx------ 1 root root 64 Aug 16 12:39 4 -> socket:[12812]
lr-x------ 1 root root 64 Aug 16 12:39 5 -> pipe:[116001]
l-wx------ 1 root root 64 Aug 16 12:39 6 -> pipe:[116001]

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

> Соответственно, если php-скрипт выполняется через консоль, то php наследует дескрипторы от неё
> Я правильно понимаю?
да.

> Затем я поменял домашний каталог у www-data в /etc/passwd на каталог сервера (на который я вроде давал неограниченный доступ chmod -R 777) и всё заработало - ключ успешно сгенерировался.
Вообще, достаточно было поменять переменную окружения HOME перед запуском программы - это не требует правки /etc/passwd.

> Почему-то в stderr передается обычный вывод, который не должен быть ошибкой:
Обычно у программ есть опции для управления уровнем подробностей при выводе данных. тут например https://www.gnupg.org/documentation/manpage.html есть опция quiet. А также опция "Use batch mode. Never ask, do not allow interactive commands."

> А что насчет получения ключей? На это не должно уходить много времени. Стоит ли здесь выполнять процесс асинхронно?
Ты намучаешься с асинхронными операциями в php, так что лучше их избегать. Тем более, ты вроде ключи хотел хранить в БД.
Аноним 19/08/17 Суб 19:33:30 #595 №1047034 
>>1046985

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

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

$company->getSalaryInDepartment('marketing');

и

$marketingDep = $company->findDepartment('marketing');
$marketingDep->getSalary();

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

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

Также, а что насчет сценария "работник уволился из одного департамента или компании и перешел на работу с другую"? В случае когда департамент создает работников, это невозможно.

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

> спойлер
Ну вот видишь, моя задача очень жизненная, не то что эти глупые задачи про наследование моделей машин и кошечек с методом sayMeow() из других учебников.
Аноним 19/08/17 Суб 19:37:00 #596 №1047036 
Тупа не могу решить задачку про айфон в кредит, дайте подсказку.
Аноним 19/08/17 Суб 19:38:58 #597 №1047038 
>>1047036

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

Попробуй переписать код внутри цикла примерно так:

- прибавляем проценты и комиссию к остатку долга (!не вычитаем ничего пока!)
- если остаток маленький, выплачиваем сколько осталось и уходим
- иначе платим 5000

«Платим» здесь значит уменьшаем долг и увеличиваем общую сумму выплаченного.
Аноним 19/08/17 Суб 20:15:50 #598 №1047049 
>>1046870
Я и так здесь помогаю иногда, просто на всё здесь отвечать некогда, надо пилить плагины, плагины сами себя не запилят. Всё что тебе нужно - это просто сильная мотивация изучить PHP.

>>1047034
Мельком прочел ответы и код, слишком много буков, но навскидку, основные ошибки автора этого кода:

1) Непонимание dependency injection в PHP, то есть в методе не нужно ничего создавать, в метод нужно передавать уже созданный экземпляр.
2) Злоупотребление абстракциями, читай про бритву Оккама. То есть не нужно плодить новые сущности. Если скажем, должности можно сделать отдельным двумерным массивом, то отдельный класс для этого не нужен. В статистике есть информационные критерии Акаике, Шварца и Байесовский критерий, используются для оценки моделей. Если у модели слишком много параметров, за это начисляется штраф. Т.е. нужно находить наипростейшее решение.
3) Нерациональное использование памяти и игнорирование стандартных генераторов, типа yield. Зачем изобретать велосипеды с foreach, когда есть array_search().
Аноним 19/08/17 Суб 20:25:44 #599 №1047050 
>>1047049

Генераторы тут при чем? И dependency injection? Что тут от чего зависит?
Аноним 19/08/17 Суб 20:30:22 #600 №1047051 
Тогда и я спрошу. Задача про айфон.
http://ideone.com/sw0x5e
Как сделать цикл так, чтобы обойтись одним echo?
Аноним 19/08/17 Суб 20:33:28 #601 №1047054 
>>1047025
Спасибо за ответ по оптимизациям и поиску уязвимых мест, буду изучать новые инструменты и выяснять причины. Очень заинтересовало нагрузочное тестирование.
Аноним 19/08/17 Суб 20:35:02 #602 №1047057 
>>1047051
Добавлю: не вводя новую переменную и т.п.
Аноним 19/08/17 Суб 21:27:39 #603 №1047067 
>>1047050
>Генераторы тут при чем? И dependency injection?
Это ответ не конкретно тебе, а вообще всей дискуссии. Вот здесь >>1046695 первая картинка, нерационально хранить массив в переменной класса. Если бы там было не 3-5 департаментов, а например миллион департаментов, то все эти экземпляры, что он наплодил, сидели бы в памяти. Для этого и нужен yield, который выдает 1 департамент за раз.

Там же в методе addDepartment() образец dependency injection, там нужно передавать ссылку на уже созданный экземпляр (хотя лучше бы просто избавится от класса и сделать массивом).
Аноним 19/08/17 Суб 22:23:50 #604 №1047090 
>>1047051
Я конечно извиняюсь, но почему ты не использовал блок-схему предложенную в теории к задаче. Я уж не говорю про однострочник, который ты в в условие for впихнул, я конечно учусь, но это же тяжело читать постороннему человеку.
Ладно, это эмоции :-)
Я делал по схеме, предложенной изначально, если ее адаптировать к твоему варианту, то как-то так получается (идеология начальной задачи) - брейк - выход из цикла делаем когда кредит выплачен. Ты хотел одно эхо? Ты его получил!

http://ideone.com/E3Ez3g

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

http://ideone.com/h8vBRT

И скромно замечу - в твоем коде сильно не хватает пробелов, не говоря уже об инициализации переменных.
Аноним 20/08/17 Вск 03:34:51 #605 №1047160 
Пытаюсь написать бота для втентакля, и вроде всё получается, но есть одна проблема — он флудит сообщениями. Т.е. вместо того, чтобы отправить одно, шлёт по 3 с разницей от 2 до 10 секунд. С чем это связано? Для проверки юзаю хостинг cloud9, может, это из-за него такая хуйня? Ответ тантаклю echo 'ok' отправляю.
Аноним 20/08/17 Вск 04:14:03 #606 №1047166 
>>1047160
Всё, разобрался, это сам сервер Cloud9 возвращает помимо 'ok' кучу всякой хуйни, а впаше нужно именно две буквы. Теперь бы ещё понять, как это отключить.
Аноним 20/08/17 Вск 04:33:33 #607 №1047169 
>>1047166
Понятно. Надо было создать .htaccess и туда прописать настройки. Вроде он перестал ошибки запихивать и вк больше не выёбывается. Спасибо, пацаны.
Аноним 20/08/17 Вск 06:16:03 #608 №1047176 
>>1046985
>Но это именно так и есть, потому что это расписание утверждается на самом высоком уровне, ведь это и фонд оплаты труда, и налогообложение и т.д. Так что для меня реальность, что это не меняется ежесекундно. Аналогично и с свойствами должностей-профессий. Оклады меняются еще реже, чем штатная численность.К сожалению.

Ты не должен так рассуждать. Тебя и пытаются научить тут тому, что у тебя в системе должна быть гибкость и расширяемость и везде должна быть подстелена соломка. Изменились зарплаты? Уволены сотрудники? Кончилось кофе? Менеджерам дали премии? У тебя должен быть предусмотрен механизм для этого! Пусть не впилен заранее, но инфа в объектах должна храниться так, что бы у тебя была возможность легко без кучи костылей и не нарушая общий стиль всё это вписать, понимаешь?

Просто по задумке у тебя сферическая контора в вакууме, а в реальности в итоге будет любой кавардак случаться. И лучше всё это дело учитывать. Попробуй решить антикризисные меры со своим кодом и ты всё мб поймешь о чем я, вангую что с твоим подходм у тебя будет дикий обсер и демотивация :( (Но ты не переживай, ведь антикризисные меры из дополнения к этой задаче - и есть реальная задача которую нужно тут решить - понимаешь?)
Аноним 20/08/17 Вск 06:28:35 #609 №1047177 
>>1047160
>>1047166
>>1047169
Не покажешь свой код? Как примерно всё это устроено? Немного интересно это, но всегда думал что в таких системах защита от ботов на самом деле стоит.
Аноним 20/08/17 Вск 06:46:05 #610 №1047178 
>>1047090
Хм, ну так тоже можно.

Я знаю, что криво оформил, делал наспех.
Мне не нравится конструкция ОПа из-за условия ($month<=20). Пример: анон взял кредит 400000, а выплачивает по 20000. Тогда код ОПа выведет только первые 20 месяцев, а мой вариант будет работать как надо.

И еще я не понял, зачем ОП использует конструкцию вроде {$month} вместо простого вывода переменной без фигурных скобок.
Аноним 20/08/17 Вск 07:55:27 #611 №1047185 
Мне нужно было отправить POST запрос из php. Узнал, что POST-запрос можно отправить используя контексты потоковых операций PHP. Но я не понимаю что это за потоки, контексты. Где можно почитать подробное разъяснение всего этого? В документации это разъяснено не подробно, или я просто тупой.
Аноним 20/08/17 Вск 08:04:49 #612 №1047187 
>>1047185
https://stackoverflow.com/questions/5647461/how-do-i-send-a-post-request-with-php

погуглил за тебя, не благодари
Аноним 20/08/17 Вск 08:11:03 #613 №1047190 
>>1047187
Проблема в том что у меня нет никакого понимания как это все работает, все эти потоки и контексты. Я могу конечно скопипастить, нихуя не поняв что я сделал, но как то не круто это. Но все равно спасибо.
Аноним 20/08/17 Вск 08:32:14 #614 №1047196 
>>1047190
http://php.net/manual/ru/intro.stream.php
http://php.net/manual/ru/function.stream-context-create.php

Ну вот прочитай, мб разберешься. Я тоже не могу понять некоторые вещи полностью и воспринимаю просто как инструмент. Ты же не пытаешься копать глубже в нативные функции языка и как например внутри устрен там mt_rand() или mb_substr()? Просто знаешь что подать на вход и что ожидается при этом на выход. Вот и тут так же, прочитай и пойми как использовать и этого будет достаточно. Это даже знать не обязательно. Я на самом деле это не сейчас нагуглил, а 2 года назад на работе, когда нужно было сделать рассылку post запросов с нашего сервиса на чужой. Просто держу теперь в голове и когда надо будет снова воспользуюсь.
Аноним 20/08/17 Вск 14:47:31 #615 №1047341 
>>1047049
>2) Злоупотребление абстракциями, читай про бритву Оккама. То есть не нужно плодить новые сущности.
А как это тогда лучше реализовывать? Типа вместо наследования и всего такого ты делаешь 1 класс общий и отдельный класс с отличающимися конфигурациями?
А при создании экземпляра просто передаешь инфу о том какая конфигурация нужна?
Накидал кливо но быстро http://ideone.com/4vjBfF
Я то думал что везде нужно обмазываться в итоге наследованием и parent::__construct()
Аноним 20/08/17 Вск 16:49:28 #616 №1047432 
>>1047341
Что-то типа этого http://ideone.com/C94uot

Начнешь плодить классы для каждой отдельной сущности и увязнешь в абстракциях и неочевидных ошибках.
Аноним 20/08/17 Вск 18:10:00 #617 №1047484 
>>1047432
Сложно и неочевидно это.
В итоге так и предполагается, что никто в итоге не использует "чистое ООП" с тем как оно там задумано изначально с цепочками наследований и прочими инкапсуляциями, придется всю жизнь наверное в это "въезжать"
http://ideone.com/nuAT2v
Аноним 20/08/17 Вск 19:04:57 #618 №1047531 
>>1047067

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

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

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

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

> Там же в методе addDepartment() образец dependency injection
Нет, Департамент - это не зависимость класса Компания. Это сущности, которыми она управляет. Разберись внимательнее, что такое зависимость.

> там нужно передавать ссылку на уже созданный экземпляр (хотя лучше бы просто избавится от класса и сделать массивом).
Чем лучше? Массив только хуже, в нем не определена структура, нет комментариев, методов и констант. Единственное, что кода чуть меньше получается, но зато он менее понятный и с ним труднее работать. И это задача на ООП, чтобы учиться исопльзовать классы, а ты предалагешь тут вместо этого на массивах написать нечитаемую лапшу.

Ты какие-то вредные советы даешь.

> Зачем изобретать велосипеды с foreach, когда есть array_search().
Потому что array_search не ищет по полю класса.

> То есть не нужно плодить новые сущности. Если скажем, должности можно сделать отдельным двумерным массивом, то отдельный класс для этого не нужен.
Можно сделать разные классы для профессий, и можно сделать один класс. Оба варианта допустимы. Если у профессий будет разное поведение, то придется делать отдельные классы.

>>1047341

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

>>1047432

У тебя какой-то массиво-ориентированный код. Ну то есть вместо того, чтобы сделать в классе поле salary, ты сделал в нем массив со свойствами и зарплату надо искать через $this->current_worker['salary']. Зачем ты внутрь объекта кладешь массив, если можно просто сделать поле $this->salary? Это усложнение, которое не дает никакой выгоды, такое ощущение, что тебе объекты не нравятся, а нравится везде использовать массивы.

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

Функция get_worker_salary зачем-то содержит return false. Это усложеняет ее использование, так как мы теперь должны при каждом вызове проверять ее результат. Не нужно так делать.

Профессии стоило бы сделать константами.

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

>>1047484

> В итоге так и предполагается, что никто в итоге не использует "чистое ООП" с тем как оно там задумано изначально с цепочками наследований и прочими инкапсуляциями, придется всю жизнь наверное в это "въезжать"
Это просто он усложняет код.
Аноним 20/08/17 Вск 20:16:48 #619 №1047579 
Кстати, для тех, кто изучает промисы, простая задачка на их понимание.

Напишите функции:

- isFinished(p) - возвращает, завершен ли промис (то есть true если он rejected/resolved, false если еще pending)
- extractValue(p) - если промис разрезолвлен, возвращает его значение, иначе null
- isResolved(p) - возвращает true если промис разрезолвлен

Писать можно как на PHP, так и на JS, в случае с JS предполагаем что промисы соответствуют спецификации Promise/A+, в случае PHP - что они соответствуют PromiseInterface: https://github.com/reactphp/promise/blob/master/src/PromiseInterface.php
Аноним 20/08/17 Вск 20:37:06 #620 №1047594 
>>1047579

Поправка: я тут заметил, что с JS промисами это скорее всего невозможно, так что задача остается только для PHP промисов.
Аноним 21/08/17 Пнд 09:22:26 #621 №1047802 
>>1046697
Ну ок, сейчас все распишу.
Текущая задача: Есть таблица абонентов, им выделяется определенный диапазон адресов (например 20.20.20.6/29, 8 адресов тобишь), также есть таблица услуг абонентов, услуги могут быть следующие: ТВ, телефония и интернет. В таблице услуг на ТВ и телефонию выделяется один фиксированный IP, а на интернет диапазон и хранится в базе он в таком виде: 20.20.20.6-20.20.20.8. На странице нужно отобразить какой адрес под какую услугу выделен и какие остались свободны. Получается если просто делать выборку из таблицы услуг, то получится получить только все занятые адреса (и то с адресами для интернета приходится повозиться). А вот чтобы показать свободные адреса приходится сильно говнокодить. https://ideone.com/LJ6xdf
А на счет библиотеки, вот например нашел такую https://github.com/tapmodo/php-ipv4
Игнайтер при инициализации библиотеки запускает конструктор, а конструктор этой либы запрашивает какое-то число типа long, я в принципе не знаю чего он хочет. Ну вот как-то так.
Аноним 21/08/17 Пнд 09:51:53 #622 №1047807 
>>1047802
И еще вопрос такой: чтобы не пилить в контроллерах методы по 500 строк их лучше разбить на отдельные функции, и вызывать их в контроллере. А сами функции где лучше описывать, в этом же контроллере, в модели или в библиотеке?
Аноним 21/08/17 Пнд 10:02:01 #623 №1047808 
>>1047029
>Сложности ООП
Да я даже до того раздела не дошел, дропнул на моменте когда нужно было надрачивать код, чтобы закрепить знания все, практики 5.5% было. Дропнул не потому, что не интересно стало, а потому что проблемы начались. Прошел год почти, но я все вспоминаю уже, щас посмотрю ОП-шапку и после того как ее закончу с CSS и HTML то потом буду ебош делать PHP и C. После чего перекачусь в C++ и на стороне буду закреплять PHP. Мне никакой мотивации не нужно, у меня жопа прижата. Извиняюсь за каламбур.
А да, книжки пока что те что я скинул, на стороне Керниган с Ритчи. А так я думаю более чем достаточно в спецификации PHP будет написано.
У кого тоже есть желание написать сначала PhP и потом вы опоминаетесь и осознаете что это зашквар?
Аноним 21/08/17 Пнд 11:53:00 #624 №1047835 
Такой вопрос: сгенерировал я CRUD через gii:
к примеру у меня есть таблица city (id, country_id) и есть таблица city_language (city_id, language_id, name)
в таблице city поле `id` автоинкремент и праймери ключ, в city_language есть праймери ключ city_id который является внешним ключом city.id. Так вот вопрос, у меня сгенерированная форма (actionIndex со стандартным _search) предлагает мне искать по ID, я к примеру хочу добавить поле City Name который бы искал совпадения по таблице city_language по полю name, как мне расширить поиск на другую модель/таблицу?
Аноним 21/08/17 Пнд 12:02:26 #625 №1047838 
>>1047835
А всё, нашел способ. Но готов послушать советы
Аноним 21/08/17 Пнд 15:47:33 #626 №1047916 
Я никак понять логику Yii не могу, касательно извлечения данных из MySQL.
Есть таблица с двумя полями: id и client.
Есть готовая переменная $client с именем клиента.
Всё что мне нужно от жизни - вытащить из таблицы соответствующий ему id.
Элементарно же. Но я уже четвёртый час и так и сяк пробую, нихрена не получается.
А ещё непонятно, почему не получается. Консоль показывает только "SyntaxError: JSON.parse: unexpected character at line 3 column 1 of the JSON data", ну или ещё какою невнятную ерунду. А что там внутре у него происходит - чёрт его знает.
Аноним 21/08/17 Пнд 16:02:46 #627 №1047928 
>>1047916
Таки родил велосипед.

$rows = (new \yii\db\Query())
->select(['id'])
->from('clients')
->where(['client'=>$nameNewClient])
->one();
foreach ($rows as $key => $value) {
$rows = $value;
}
$json_data = array(0 => $rows);
echo json_encode($json_data);$rows = (new \yii\db\Query())
->select(['id'])
->from('clients')
->where(['client'=>$nameNewClient])
->one();
foreach ($rows as $key => $value) {
$rows = $value;
}
$json_data = array(0 => $rows);
echo json_encode($json_data);
Аноним 21/08/17 Пнд 16:04:13 #628 №1047929 
>>1047928
Случайно код дважды скопировал.
Аноним 21/08/17 Пнд 16:12:00 #629 №1047934 
http://ideone.com/Xy4dTS
Как мне сделать СплСтак с несколькими элементами, не пуша их по-одному?
Аноним 21/08/17 Пнд 18:53:37 #630 №1048053 
Делаю задание про студентов, возник вопрос.
Есть класс Student c переменными $name, $surname (и другими). Есть конструктор:
function __construct($name, $surnametб ...)
{
$this->name = $name;
$this->surname = $surname;
...
}
Всё бы ничего но: при про получении данных из бд я хочу, что бы эти данные заносились в класс Student, ставлю мод FETCH_CLASS, но выдаётся ошибка, что я не заполняю конструктор:
PHP Fatal error: Uncaught ArgumentCountError: Too few arguments to function Student::__construct(), 0 passed and exactly 8 expected in
При этом если убрать конструктор из класса, то всё будет работать. Почему так происходит я понимаю, вопрос вот в чём: как сохранить конструктор в классе и работать с FETCH_CLASS?
Аноним 21/08/17 Пнд 19:47:14 #631 №1048076 
>>1048053
У тебя там видимо ещё и ID в таблице хранится. Так что делай свойство $id
Аноним 21/08/17 Пнд 20:26:43 #632 №1048101 
>>1048076
Свойство $id есть. Вопрос не в этом.
Вопрос в том, что при использовании метода FETCH_CLASS мне нужно заполнить конструктор, но мой конструктор нужно заполнять данными, которые я получаю из FETCH_CLASS
https://github.com/enotocode/birthdayreminder Аноним 21/08/17 Пнд 22:19:04 #633 №1048196 
>>1045795

Что-то у тебя в package.json все перепутано: в dependencies стоит webpack-dev-server, а сам webpack в devDependencies. Ты пробовал на продакшене использовать npm install --production и проверить, все ли работает?

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

.babelrc наверно лишний, если опции указаны в конфиге webpack.

У тебя подключен webpack.HotModuleReplacementPlugin - но используется ли он? Как я понимаю из документации, приложение должно явно поддерживать возможность обновления. Также, непонятно, зачем добавлен NoErrorsPlugin - вроде судя по описанию он предназначен для игнорирования синтаксических ошибок.

Насчет директорий - думаю, не стоит создавать лишние уровни вложенности и стоит вместо этого сделать в корне папки client, server, и может быть, там же templates и public (или внутри server).

В ридми не описана команда для генерации собранного скрипта (там есть watch, но надо бы описать и build).

https://github.com/enotocode/birthday_reminder/blob/master/src/client/index.js - тут у тебя слишком много импортов, многие из которых не используются.

Насчет импортов - а не лучше было бы писать не так:

createStore()

а так?

redux.createStore()

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

> Replace the path in RewriteBase directive with path that you use to access to the project
В Apache2.4 вроде бы RewriteBase уже не нужен. Ну и я бы советовал сделать публичную папку корневой.

Хорошо бы сделать поддержку для встроенного в PHP сервера - для отладки он вполне годится и не требует возни с Апачом ( http://php.net/manual/ru/features.commandline.webserver.php ) . Можно это сделать лиюо файлом server.php, либо в index.php с помощью проверки php_sapi() или как-то так.

Далее, почему-то объем собранного скрипта составляет 1Мб. Не многовато ли для простейшего приложения? Там конечно что-то можно выжать минификацией, может быть сжатием, но конечно, как-то жирно получается.

Скомпилировано все как-то плохо, потому что у меня в Chromium выдается ошибка на аргументы по умолчанию (в reducers.js). То есть у тебя на выходе получается ES6 файл, а не ES5. А хорошо бы еще для ES3 браузеров добавить полифиллы для поддержки ES5 (хотя я сомневаюсь, что это возможно, так как в ES5 есть штуки вроде defineProperty(), которые по идее в ES3 эмулировать нельзя. Но в ES3 браузерах были похожие нестандартные функции, может полифилл их использует). Если что, информация по браузерам: https://caniuse.com/#search=es5

Я нашел, как исправить проблему, но предоставлю тебе возможность подумать самостоятельно.

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

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

- для пользователей с поддержкой ES6 (уровень поддержки: https://caniuse.com/#search=es6 )
- для пользователей с ES5
- для пользователей без ES5 дополнительно давать полифиллы в надежде, что заработает

Транспиляция скорее всего делает код менее эффективным и более громоздким, и если браузер поддерживает ES6, почему бы не давать ему более оптимальный код в ES6?

Если компиляци идет долго, можно было бы в теории сохранять промежуточные результаты и перекомпилировать только изменившиеся файлы - в Си так делают уже лет 40. Но не знаю, поддерживает ли вебпак такое. Впрочем, это open source, никто не запрещает допилить такую возможность. Также в режиме watch промежуточные результаты можно кешировать в оперативной памяти.

Далее, после транспиляции кода в ES5 у меня происходит ошибка тут:

> Uncaught TypeError: Cannot read property 'userName' of undefined
> validate @ VM909 validator.js:21

Это из-за того, что ты там перекрываешь внешнюю переменную локальной:

> https://github.com/enotocode/birthday_reminder/blob/master/src/client/services/validator.js
> inputsValidationRules = inputsValidationRules)

Это компилируется в

> var inputsValidationRules = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : inputsValidationRules;

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

Дальше, мне не нравится идея что надо где-то в исходниках править пути. Я предлагаю либо сделать папку public корневой, либо передавать пути с сервера. Зачем клиентскому коду свой конфиг? Пусть нужные данные передает сервер.

Ну например, проще всего было бы при выдаче страницы из PHP передавать нужные данные:

<script>
startApplication(param1, param2, param3);
</script>

Дальше, ошибки никак не отображаются. Например, я задал неправильный URL сервера, и при попытке отправки формы ничего не происходит. Должна быть реакция на действия пользователя, почитай урок https://github.com/codedokode/pasta/blob/master/js/ajax.md

Что касается валидации, которая идет в фоне - в принципе, там сетевые ошибки не так критичны (так как валидация будет произведена при отправке формы). Там можно сделать так:

- если поле прошло валидацию, показывать зеленую галочку
- если не пррошло - ошибку
- если не удалось проверить - ничего не показывать

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

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

Ответ на запрос на валидацию (POST /validate) очень странный - 201 Created. Код ответа выбран неправильно.

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


Серверная часть

https://github.com/enotocode/birthday_reminder/blob/master/src/server/Services/autoloader.php - это надо убрать и заменить на автозагрузку в композере. Желательно также использовать PSR-4.

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

https://github.com/enotocode/birthday_reminder/blob/master/src/server/public/index.php#L29
> $data = json_decode($request->getContent(), true);
> $request->request->replace(is_array($data) ? $data : array());
Нет проверки на ошибку декодирования, также, а не лучше ли класть данные в какое-то отдельное место, чтобы не путать с обычными пост-данными?

Папку Classes надо переименовать так как название ничего не значит.

> static public function loadValidatorMetadata(ClassMetadata $metadata) {
У этого подхода есть недостаток в том, что нельзя делать правила валидации, которые используют сервисы через DI. Например, проверки по БД. Или вызов внешнего класса-валидатора.
https://github.com/enotocode/birthdayreminder Аноним 21/08/17 Пнд 22:19:41 #634 №1048197 
>>1045795

Клиентская часть

Мне не нравится то, что функции плохо организованы и просто беспорядочно свалены внутри модуля. Ну например, возьмем services/validator.js. Вот API этого модуля:

- validator(dispatch, index, valueName, value, inputsValidationRules = inputsValidationRules)
- validator.asyncValidation(fn)
- validator.VALIDATE_WITH_API
- validator.validateWithAPI(value, valueName, index, dispatch)

Зачем экспортируется константа VALIDATE_WITH_API? Почему модуль содержит несколько функций и они налеплены на другую функцию? Мне кажется, export default function стоит применять только там, где экспортируется одна функция. А так получается просто свалка.

Я тебе советую прежде чем писать код, попробовать описать АПИ модуля. Тогда сразу будут видны проблемы.

Ну вот возьмем, например, основную функцию validate(dispatch, index, valueName, value, inputsValidationRules = inputsValidationRules). Почему ей надо передавать dispatch? Почему она зависит от редукса? Она отдельно от него провести валидацию не способна? Я вижу тут явное нарушение разделения ответсвенности, ты разнес код по файлам, но без всякой логики, потому что эти файлы все спутаны друг с другом и должны быть объединены в один.

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

Нужно сделать хорошее АПИ модулей. То, что сейчас, это просто свалка из функций.

Посмотрим еще на apiCall.js:

- apiCall(middleware) - непонятно, почему для обращения к АПИ нужно middleware редукса. А что, без редукса обратиться к АПИ нельзя?
- apiCall.CONNECTION_ERROR
- apiCall.RECIEVE_RESPONSE
- apiCall.recieveResponse(dispatch, json, action)

Тоже лишние зависимости от редукса.

Далее, неправильно обрабатываются ошибки в промисах:

> fetch(url, request)
> .then(
> ...
> error => console.log('Error while connecting to server', error)
> .then(
> json => dispatch(recieveResponse(dispatch, json, action)),
> error => dispatch(connectionError(error))

Функция function (error) { return console.log('Error while connecting to server', error); } превращает ошибку в успешный результат (null) и на следующем шаге это приведет к вызову функции json => dispatch(recieveResponse(dispatch, json, action)).

Изучи промисы получше, можно например почитать статью https://www.promisejs.org/implementing/

Дальше, этот синтаксис мне кажется очень неудачным:

> const apiCall = store => next => action => {
Тут написано const, но объявляется не константа, а функцию (возвращающая функцию). Зачем запутывать читателя? Ну и выражение store => next => action => довольно тяжело воспринимать.

Вообще, стрелочные функции были придуманы для простых выражений вроде [].map(x => x * 2); Мне кажется, что не стоит использовать их везде, так как ухудшается читабельность.

Правила валидации на клиенте логично было бы генерировать из серверных.

Также, надо будет потом проверить, нет ли проблем с потреблением памяти при большом объеме данных или действий. Ну например, создать 10, 100, 1000 дней рождений и замерить потребление памяти браузером. Или пропустить через диспетчер 10, 100, 1000 действий и посмотреть, не течет ли (неограниченно увеличивается) потребление памяти.

Также, я мельком почитал гитхаб redux-thunk и сразу увидел там проблему: там никак не учитывается асинхронность функций. Ну например, когда ты делаешь 2 запроса к АПИ, сначала может придти ответ на второй, а только потом на первый. К примеру:

- пользователь вводит неправильное значение, отправляется запрос 1
- пользователь вводит правильное значение, отправляется запрос 2
- приходит ответ на запрос 2, отображается индикатор, что все правильно
- приходит ответ на запрос 1, отображается ошибка

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

> return {inputs: state.inputs}; //TODO: is it copy or link?
Если inputs это объект или массив, то, видимо, передача ссылки.

Меня еще немного беспокоит вот эта штука: https://github.com/enotocode/birthday_reminder/blob/master/src/client/Login/initialState.js - по мере усложнения приложения тут будет гигантский массив.

https://github.com/enotocode/birthday_reminder/blob/master/src/client/Login/actions.js
Тут по названиям функций трудно понять, что они делают. Что, например, делает функция userCreated? Обычно функции называют в стиле сделайЧтоТо().

Ну и наверно неплохо бы подумать об автоматизированном тестировании приложения.
Аноним 21/08/17 Пнд 22:40:22 #635 №1048220 
>>1047051

посчитать выплату в текущем месяце;
сделать выплату;
вывести результаты;
если долг дошел до нуля, выходим;

>>1047178

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

> зачем ОП использует конструкцию вроде {$month} вместо простого вывода
Почему бы и нет.

>>1047185

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

У потоков есть также специальный синтаксис для указания типа и параметров потока. Например, file://somefile.txt или http://example.com. Можно добавлять свои типы потоков, написав свой stream wrapper.

Мануал http://php.net/manual/ru/book.stream.php

Контекст потока - это дополнительные опции потока, у разных типов потоков они свои: http://php.net/manual/ru/stream.contexts.php . Ну например, для потока получения данных по HTTP они могут задавать таймаут ожидания ответа от сервера.

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

>>1047807

Лучше следовать MVC и вынести операции с данными в отдельные классы (модели, сервисы), а в контроллерах оставить обработку запроса и отдачу ответа.
Аноним 21/08/17 Пнд 22:46:35 #636 №1048222 
>>1047916

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

Также, ты там переусложнил, разве в Юи нет простого метода вроде findBy? Ну и может быть написать SQL запрос будет лаконичнее чем городить конструкции в Query Builder.

>>1047934

Вставлять циклом

>>1048053

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

Вообще, что касается ООП, там в PDO все довольно плохо, такое ощущение, что его авторы сами ООП толком не поняли. Ну например, по умолчанию FETCH_CLASS сначала создает объект, заполняет поля, и только потом вызывает конструктор.
Аноним 21/08/17 Пнд 23:57:37 #637 №1048278 
Слышал мнение, что цены и похожие дробные значения стоит хранить не в Decimal, а в двух полях Int ? MySql
Есть в этом смысл? Зачем так извращаться?
Ничего не смог нагулить по этой теме.
Аноним 22/08/17 Втр 00:55:16 #638 №1048334 
>>1048053
>>1048222
Понял, спасибо.
Аноним 22/08/17 Втр 01:39:22 #639 №1048364 
wp.png
Почаны, я тут ковыряюсь в вордпресе и азах php и не могу понять работает простой if.

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

Как она работает: если категория является подкатегорией родителя - напечатать название И ВСЕГДА печатает единицу.

Почему так происходит?
Аноним 22/08/17 Втр 04:01:05 #640 №1048400 
>>1048364
if ($govno==true){
}
else{
echo '1';
}
Аноним 22/08/17 Втр 06:27:14 #641 №1048411 
изображение.png
изображение.png
>>1047802
Лень разбирать детально твой код, но как я понял:

$customer_internet_ip = array(); //Массив назначенных абоненту адресов, определенных под интернет
$customer_ip = array(); //Массив назначенных абоненту адресов
$customer_free_ip = array(); //Массив свободных адресов абонента
Эти 3 массива из базы прилетает в метод?

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

И вообще это ведь не в контроллере у тебя этот код?
Если в контроллере то вынеси это в отдельный метод либы по работе с ip (если нет то создай её): https://www.codeigniter.com/userguide3/general/creating_libraries.html
В контроллере потом просто пишешь:

$this->load->library('ip_stuff');
$view_data['free_ips'] = $this->ip_stuff->get_free_ip($customer_internet_ip, $customer_ip, $customer_free_ip);
//$view_data - массив инфы который ты собираешь для вьюхи
$this->load->view('uslugi', $view_data);

То есть ты просто портянку кода перенес в отдельную функцию и поручаешь его ей.

>Игнайтер при инициализации библиотеки запускает конструктор
Во первых вот форк этой либы и чел что-то там работает над ней https://github.com/colinodell/php-ipv4

Во вторых ты когда создаешь новый объект у себя в коде, то это не игнайтер что-то требует, а у самого класса есть метод конструктор. Он на то и конструктор, что автоматически выполняется при создании объекта.
Пикрил1 - ты ему должен скормить ip туда
Там же есть примеры использования - пикрил2.

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

>>1047807
>чтобы не пилить в контроллерах методы по 500 строк их лучше разбить на отдельные функции, и вызывать их в контроллере.
Да. Любой код который ты можешь обернуть в функцию лучше обернуть и вынести в модель/либу.

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

Еще если у тебя например есть код который ты используешь в каждом методе контроллера, то ты его должен выносить в конструктор контроллера.
Скажем для доступа в контроллер личного кабинета юзер должен быть обязательно залогиненным, вот проверку на то что он залогиненность(куки или что у вас там) ты и выносишь в конструктор этого контроллера. И когда юзер будет ломиться в любой метод этого контроллера например /site/user/cabinet - то будет выполняться проверка его подлинности на этапе конструктора контроллера user

Далее если у тебя например есть код который используется во всех контроллерах на сайте: например подгрузка языка. То ты должен создать какой-то базовый контроллер который будет наследоваться от CI_controller - в его конструктор вынести этот код, и этого базового уже наследовать свои контроллеры, а в их конструкторах подгружать их конструкторы через parent::__construct
https://www.codeigniter.com/userguide3/general/core_classes.html


Аноним 22/08/17 Втр 06:36:47 #642 №1048412 
>>1048400
Так а я так и сколотил, уже, засунул в отдельную переменную и сравниваю отдельной строкой. Но почему изначальный if так не может?
Хуйня какая-то, чет я не понимаю азов.
Аноним 22/08/17 Втр 06:39:44 #643 №1048413 
>>1048412
>Но почему изначальный if так не может?
Может. Просто ты вместо сравнения делаешь непонять что.
Аноним 22/08/17 Втр 07:42:27 #644 №1048426 
изображение.png
>>1048412
Аноним 22/08/17 Втр 08:21:25 #645 №1048434 
>>1048413
Ну типа функцию вызываю которая должна вернуть false или true

>>1048426
Да, проебался при переносе.
Аноним 22/08/17 Втр 08:23:29 #646 №1048436 
pr - Клуб изучающих PHP и webdev #92 - Google Chrome 2017-0[...].jpg
>>1048426
>>1048434
трайй зис щит

Аноним 22/08/17 Втр 08:40:21 #647 №1048448 
>>1048436
Ой, хуй с ним. Я уже тупо вставил
> $test = true
>if $test == true
>echo "2"
И он где-то выдает одну двойку а где-то две. Видимо что-то там с массивом связано, а я слишком туп чтоб понять.
Эх хуле я такой безрукий по жизни.
Аноним 22/08/17 Втр 08:42:24 #648 №1048450 
>>1048448
Кидай ideone. Так понять не могу.
Аноним 22/08/17 Втр 08:58:04 #649 №1048460 
>>1048450
Да лано, без этой фигни сделаю, там не критично. Спс.
Аноним 22/08/17 Втр 09:20:21 #650 №1048478 
>>1048411
>Или ты просто либу засунул в папочку и игнайтер сам пытается создать объект без твоих выдзовов либы где-либо в коде?
Именно так. Просто загрузил либу и сразу эксепшн. Все остальные библиотеки, которыми я пользуюсь без конструкторов, поэтому у меня с этим проблема возникла.
Вообще, все что ты мне написал я и до этого знал, но все равно спасибо за развернутый ответ. Теперь буду выносить все методы в библиотеки.
Аноним 22/08/17 Втр 09:55:44 #651 №1048497 
>>1048478
Аноним 22/08/17 Втр 11:15:57 #652 №1048561 
33.png
>>1045051
Посмотрел этот курс от ntschool, как советовал анон. Выяснил для себя, что по видеоурокам учиться гораздо быстрее и легче.
Теперь вопрос: куда идти дальше? Проходить учебник на сайте ОПа? Пока что смотрю другие видео с того канала и начал проходить курс на html academy.
Откопал древний пост на хабре, и там автор пишет, что главное - это учиться у профессионалов. А как отличить хорошие книги от плохих?
Сам хочу работать в фулстеке, но для начала хорошо выучить именно php.
И еще - что скажете про этот сайт?: http://getjump.me/ru-php-the-right-way/
Аноним 22/08/17 Втр 11:21:52 #653 №1048564 
>>1048478
Мне кажется ты что-то не так сделал.
я поключал в игнайтере вот эту вот тяжеловесную поебень: https://github.com/tecnickcom/TCPDF
и там тоже есть конструктор и всё такое. И всё работало. Возможно ты всё таки как-то не так подключаешь. Ты через автолоад подгружаешь левые либы или в коде вручную?
Аноним 22/08/17 Втр 11:26:21 #654 №1048565 
>>1048561
Советую начать писать код - стало быть решать задачи. Учиться у профессионалов - это когда речь уже идет о сложной архитектуре. Когда ты решаешь простые задачи - это как арифметика - тут почти невозможно решать что-то неправильно. Поэтому просто сел и пошел хуярить код одну задачу за другой.

Ты же всегда будешь складывать 2 и 2 как 2+2, а не как (210 + 210)/10 правильно?
Аноним 22/08/17 Втр 11:28:20 #655 №1048567 
>>1048565
В том и дело, что я не знаю, какие задачи решать и что именно писать.
Аноним 22/08/17 Втр 11:49:39 #656 №1048584 
>>1048564
Положил файлы Address, Subnet и Subnetiteraror в папку libraries/ipv4. Подключаю так: $this->load->library('ipv4/Address');
И на этой строке эксепшн об отсутствующем параметре конструктора. Я понимаю что при подключении библиотеки вторым параметром можно передавать настройки для конструктора, но я все еще не знаю что за $long от меня хочет этот конструктор.
Аноним 22/08/17 Втр 11:51:12 #657 №1048587 
>>1048561
Дай ссылку.
Аноним 22/08/17 Втр 11:57:49 #658 №1048589 
>>1048587
Ссылку на что?
Аноним 22/08/17 Втр 11:59:39 #659 №1048592 
>>1048589
> курс от ntschool, как советовал анон.
Аноним 22/08/17 Втр 12:01:58 #660 №1048594 
Есть одна таблица, и я не хочу заводить вторую для хранения дополнительных данных, например: В таблице product хранятся продукты, а в дополнительной таблице хранится связь product_category один-ко-многим. Какие подводные камни если я заведу для категорий поле с битовой маской например и буду хранить в денормализованной таблице product ? Поиск будет на мой взгляд намного быстрее без лишнего джоина в виде SELECT * FROM product WHERE category_mask & '01000010';
Аноним 22/08/17 Втр 12:05:47 #661 №1048598 
>>1048594
>я заведу для категорий поле с битовой маской
В чём профит?
Аноним 22/08/17 Втр 12:09:29 #662 №1048599 
>>1048598
Избавляемся от JOIN'a избавляемся от больших условий: WHERE product_option in (2,4,6,25,52,152) OR product_option = 152 OR product_option = 242 и тд, мне идея только счас пришла в голову, дома попробую создать таблицу и поиграться с выборками.
Аноним 22/08/17 Втр 12:11:02 #663 №1048601 
>>1048592
https://www.youtube.com/playlist?list=PLplUVF5VxDlRXoKGfCn0vFn0bYA5JvSJ3
Аноним 22/08/17 Втр 12:11:51 #664 №1048602 
>>1048599
нет, почему именно битовая маска то? Извини если вопрос тупой.
Аноним 22/08/17 Втр 12:14:25 #665 №1048603 
>>1048602
К примеру: опция Цвет: товар А в есть в следующих цветах:
Синий - Нет, Красный - Да, Зеленый - нет, фиолетовый - да, Черный ДА
В битовой маске это будет как 01011
и с помощью операторов битового сравнения мы можем создавать выборки OR, EQUAL одним оператором
Аноним 22/08/17 Втр 12:14:42 #666 №1048605 
>>1045051
Не беда с книгами. Выбираешь всё что по PHP7 и читаешь. Рекомендую Котерова например.
Аноним 22/08/17 Втр 12:19:53 #667 №1048607 
>>1048601
Спасибо.
Аноним 22/08/17 Втр 12:21:06 #668 №1048608 
>>1048603
А это действительно сработает! И поиск будет быстрее в n раз. Где n - количество таблиц.
Аноним 22/08/17 Втр 12:33:44 #669 №1048611 
>>1048567 Вот это реши раз знаешь примитивы >>1044252

Вот эти задачи: http://archive-ipq-co.narod.ru/l1/mou-ikkai.html

Если не можешь то иди с 0 перечитывай всё и прорешивай начиная с http://archive-ipq-co.narod.ru/l1/conditions.html
Аноним 22/08/17 Втр 13:25:39 #670 №1048628 
>>1044252
>>1048611
>Вот это реши раз знаешь примитивы
Получилось как-то так: https://ideone.com/ZKc2yk
Аноним 22/08/17 Втр 14:15:39 #671 №1048644 
>>1048561
Реклама, я двачера издалека вижу.
Аноним 22/08/17 Втр 14:16:32 #672 №1048647 
1410539992658.gif
>>1048592
>По прохождению курса вы научитесь писать формы обратной связи на лендингах.
Аноним 22/08/17 Втр 14:17:10 #673 №1048648 
>>1048647
Я проиграл, он даже комменты трет.
Аноним 22/08/17 Втр 14:18:08 #674 №1048649 
>>1048561
>И еще - что скажете про этот сайт?
Обосрались с версткой.
Аноним 22/08/17 Втр 14:18:09 #675 №1048650 
Если в базе данных интернет-магазина сделать таблицу для корзины покупателей, то туда будут заноситься покупка отдельных товаров, так? То есть, Вася (юзер с id=15) заказал три карандаша, Петя (юзер с id=17) одну ручку, Вася (юзер с id=15) одну ручку. А когда нужно показать корзину для определённого заказчика, то вся таблица перебирается на заказы от нужного юзера (с нужным id), так? Но тогда если таблица разрастётся, то не будет ли сайт тормозить?

И второй вопрос: при покупке, есть ли смысл переносить купленное из корзины в отдельную таблицу покупок? Или просто в корзине сделать маркер "куплено"?
Аноним 22/08/17 Втр 14:23:08 #676 №1048651 
>>1048650
Используй индексы
Аноним 22/08/17 Втр 14:27:18 #677 №1048655 
>>1048650
В опенкарте например реализовали таким образом, что корзина хранится сериализованной строкой в колонке `cart` в таблице customer. При оформлении заказа создается запись в `order` и в `order_product`. По итогу в `cart` записывается пустой массив.
Не особо удобно, так как если админ захочет посмотреть статистику - кто какой товар добавлял в корзину - придется доставать все записи, прогонять по ансериалайзу и сортировать-фильтровать. А так да, если заводить отдельную таблицу по корзине покупателя один-к-одному, то при создании заказа - надо очищать запись в таблице хранения корзин для конкретного юзера и создавать запись в order.
Аноним 22/08/17 Втр 14:33:05 #678 №1048658 
>>1048651
Подробнее? Понятно, что в таблицу корзины идёт ид, ид юзера и ид товара. Что ещё?
>>1048655
>А так да, если заводить отдельную таблицу по корзине покупателя один-к-одному, то при создании заказа - надо очищать запись в таблице хранения корзин для конкретного юзера и создавать запись в order.
Ну а как быть с разрастанием? Допустим, в магазине 1000 человек в день что-то кладёт в корзину (даже если не все покупают). Спустя год таблица корзины разрастётся неимоверно. Чистить старые записи?
Аноним 22/08/17 Втр 14:35:34 #679 №1048659 
>>1048658
Даже если у тебя миллион юзеров с корзинами - это не большая база, правильно расставив индексы - ты даже не заметишь замедления в работе. Можно к примеру в таблице cart сделать user_id первичным ключом, выборка будет мгновенной так как mysql будет знать наперед что запись единичная в данной таблице
Аноним 22/08/17 Втр 14:42:14 #680 №1048661 
>>1048659
>в таблице cart сделать user_id первичным ключом
Не, не получится. Там же для каждого товара отдельная строка. Если Вася добавтил себе в корзину карандаши и ручки, то в таблице cart будет две строки: одна для карандашей и одна для ручек. И user_id у них будет одинаковый.
Аноним 22/08/17 Втр 14:44:12 #681 №1048662 
>>1048661
Сделай cart и cart_product, customer будет 1-к-1 к cart, а cart к cart_product будет один-ко-многим
Аноним 22/08/17 Втр 16:11:52 #682 №1048700 
>>1048561
Блин, анон, я хз конечно, не хочу никого обижать, но я просмотрел 2 часа 12 минут его видео и получил ровно хуй целых ноль десятых знаний. Даже первая страница опсайта дала в 100 раз больше инфы чем он.
Аноним 22/08/17 Втр 16:16:15 #683 №1048703 
>>1048700
Кого обижать и чем? Это же не мои видео, лол. Просто анон посоветовал, я и посмотрел.
Насчет второго не уверен. Разве что на опсайте больше практики.
Аноним 22/08/17 Втр 16:18:00 #684 №1048704 
>>1048700
И если ты знаешь какие-нибудь другие хорошие и бесплатные видеокурсы, то посоветуй.
Аноним 22/08/17 Втр 16:28:04 #685 №1048717 
>>1048704
Не посоветую, в том то и дело что сам ищу и никак найти не могу. Год назад тут кидали ссылку на LoftScool курсы. Вот там просто 10 из 10. С самого нуля сразу тебя заставляют писать скрипты, к 8 видео ты уде на Laravel пишешь, к 12 у тебя уже 3 своих пректа. Но они вовремя лавочку прикрыли, теперь там только за деньги доступ.
Аноним 22/08/17 Втр 16:44:39 #686 №1048725 
>>1048717
>LoftSchool
>за деньги
>nnm-club
>да простит меня ОП
Аноним 22/08/17 Втр 17:00:39 #687 №1048728 
>>1048717
Я тебя понял, спасибо.
Аноним 22/08/17 Втр 17:10:29 #688 №1048735 
>>1048222
>Вставлять циклом
Ты что, серьёзно? Бляяяяяяяяяяя.......
Аноним 22/08/17 Втр 17:20:25 #689 №1048740 
>$num = 51516665.7419439799951156;
>var_dump((string)$num);

>string(15) "51516665.741944"

Как перевести флоат в строку как есть, без вот этого окргулительства? Почему 15(16) символов, а остальное теряется?
Аноним 22/08/17 Втр 17:25:33 #690 №1048742 
>>1048436
Хочу себе IDE с такой подсветкой ошибок.
Аноним 22/08/17 Втр 17:43:07 #691 №1048748 
>>1048740
>Почему 15(16) символов, а остальное теряется?
Потому что в Си по умолчанию флоат выводится с 6 знаками после запятой.
Аноним 22/08/17 Втр 18:02:52 #692 №1048750 
>>1048748
NYET

>$num = 0.112233445566778899999;
>string(16) "0.11223344556678"

>$num = 1.112233445566778899999;
>string(15) "1.1122334455668"

>$num = 10.112233445566778899999;
>string(15) "10.112233445567"

>$num = 999.112233445566778899999;
>string(15) "999.11223344557"

6 знаков после запятой тут даже рядом не плавали.
Аноним 22/08/17 Втр 18:03:32 #693 №1048751 
>>1048740
Мне кажется компилятор обрезает твой флоат, поэтому и не получается привести к строке:

сравни
>var_dump(sprintf('%.16F', $num));
>string(25) "51516665.7419439777731895"
>должно быть 51516665.7419439799951156
Аноним 22/08/17 Втр 18:32:17 #694 №1048758 
>>1048740

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

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

00000001,00000000
99999999,00000000
00000000,50000000

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

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

То есть число переводится в двоичный вид, из него берется сколько-то знаков и положение запятой и сохраняется. И в памяти число представляется как (мантисса) x 2 ^ (экспонента). Мантисса это обычно дробное число, > 0 и < 1, то есть она всегда начинается с нуля и запятой, потому компьютер их не сохраняет, а хранит только идущие после запятой числа.

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

15600 = 0,156 x 10 ^ 5 (то есть в памяти сохраняется M=156, E=5)
0.002 = 0,2 x 10 ^ -2 (хранится как M=2, E=-2)
10 000 000 = 0,1 x 10 ^ 8 (хранится как M=1, E=8)
10 000 001 = 0,1 x 10 ^ 8 (M=1, E=8)

В последнем примере мы видим что из-за ограничения на размер мантиссы (4 цифры) число сохранилось с потерей точности.

Однако, такая система позволяет сохранять числа в гораздо большем диапазоне. Если мы вернемся к начальному примеру, где мы выделили память на хранение 16 цифр, то в системе с плавающей запятой мы бы могли выделить 12 цифр под мантиссу, 4 цифры под экспоненту и сохранять числа в диапазоне от 10 ^ -9999 до 10 ^ 9999 (10 ^ 9999 это очень большое число, которое состоит из 1 и 9999 нулей). То есть используя тот же объем памяти, мы можем записывать как очень крошечные, так и гиганстские числа. Конечно, мы теряем в точности - храним только первые 12 знаков числа, но на практике этого достаточно. Большинство реальных датчиков - измерители веса, напряжения, силы тока - все равно имеют меньшую точность.

Также, надо понимать, что некоторые числа нельзя представить точно в таком формате, сколько бы памяти мы не выделили. Например, возьмем число 1/3 = 0,33333... . Это бесконечная дробь, и сколько бы цифр не выделяли под мантиссу, все равно записанное число не будет точно совпадать с истинным.

То есть надо просто принять что числа с плавающей запятой имеют ограниченную точность, и могут не соответствовать исходному числу.

Возвращаясь к твоему вопросу: "как перевести флоат как есть" - да никак, когда ты делал $num = ...., произошло преобразование в формат с плавающей запятой и в память сохранилось число, отличающееся от исходного. Ты можешь потребовать вывести хоть 30 цифр после запятой, но последние цифры будут представлять просто случайный шум. Так как нужной информации для их вывода не сохранено.

В PHP используется стандарт IEEE754 (так как его поддержка встроена в процессоры), числа двойной точности, где под экспоненту выделено 10 бит (от 2 ^-1024 до 2 ^ +1024), что примерно равно 3 десятичным цифрам, а под мантиссу - 52 бита, что примерно равно 15 десятичным цифрам.

http://php.net/manual/ru/language.types.float.php
https://habrahabr.ru/post/112953/
https://ru.wikipedia.org/wiki/IEEE_754-2008

В твоем числе должны сохраниться (примерно) только первые 15 значащих цифр, то есть

51 516 665.7419439

"примерно 15" - так как число хранится в памяти в двоичном формате, а не в десятичном и последняя цифра может поменяться при преобразованиях.
Аноним 22/08/17 Втр 18:55:47 #695 №1048771 
Где-нибудь можно посмотреть, как устроены внутри встроенные в ядро языка функции? В частности, меня интересуют функции сортировки массивов.
Аноним 22/08/17 Втр 19:01:52 #696 №1048772 
>>1048740

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

Для таких случаев есть специальные библиотеки для вычислений повышенной точности:

http://php.net/manual/ru/book.bc.php
http://php.net/manual/ru/book.gmp.php

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

Аноним 22/08/17 Втр 19:03:11 #697 №1048773 
>>1048758
>>1048772
Спасибо.
Аноним 22/08/17 Втр 19:03:30 #698 №1048774 
>>1048748

В Си есть float (32-битные) и double (64-битные) типы. В PHP используется только double. На современных процессорах по моему особой выгоды в производительности от использования float нет, а в PHP ее нет тем более (так как там код выполняется не напрямую).
Аноним 22/08/17 Втр 19:10:59 #699 №1048778 
>>1048628
Вот видишь какой ты умный, намного круче меня(не сарказм). Хоть у меня и два года опыта, я только вот так вот смог высрать:
https://ideone.com/ULbjG8
И это хуевое решение, (https://www.codewars.com/ говорит что мой скрипт на тестах слишком много времени занимает, подозреваю что просто зависает, а твой проходит нормально)
Аноним 22/08/17 Втр 19:13:04 #700 №1048781 
>>1048774
>В PHP используется только double.
Хм, в мануале написано, что точность целых и дробных зависит от ОС(х32 или х64).
Аноним 22/08/17 Втр 19:16:13 #701 №1048782 
>>1048781

От архитектуры зависит размер целых чисел (int), на 32-битных системах это -2 млрд ... + 2 млрд, на 64-битных - это гораздо больше. Для дробных и огромных чисел используется double независимо от архитектуры. Легко это проверить, выполнив команду var_dump(1.23456789123456789); на 32-битной системе. У меня она выдает double(1.2345678912346) и мы видим что тут сохранены примерно 15 цифр.
Аноним 22/08/17 Втр 19:27:07 #702 №1048785 
Здравствуйте! Подскажите почему тупит код.
Задача про кредитный калькулятор и веб-сервер. Все работает. Но одна строчка очень тупит. Понять не могу что не так.
https://pastebin.com/eX1ATeNW
Аноним 22/08/17 Втр 19:27:12 #703 №1048786 
ОП, вопрос к тебе. Это я, кто мучается с задачей про Вектор. Времени нет пока код дописать, а сейчас уже поздно, завтра рано вставать. Короче, у меня тут несколько идей возникло, нужна оценка твоя, завтра может получится реализовать.
Значит, я добавил все свойства в класс emploee:

class Employee
//Сотрудник владеет полной информацией о себе
{
private $profession;
private $rate;
private $rank;
private $isBoss;
private $coffee;
private $reports;

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

По ходу раздумий появились идеи некоторые:
1. Может добавить в класс сотрудника поле - "Департамент". Это позволит всегда знать, в каком департаменте сотрудник.
2. Может сделать отдельный массив с сотрудниками за пределами объектов департаментов. Можно тогда вообще отказаться от объекта департамента. Спорный подход мне кажется.
3. На уровне идеи - в компании хранится массив с объектами-департаментами, внутри сотрудники, все как обычно. Но добавление сотрудника производить не методом addEmployee($employee) в объекте департамент, а методом самой компании - addEmployee($department, $employee) ну и дальше с сотрудниками работать через методы компании. Что-то подобное ты и упоминал, как мне кажется.
Аноним 22/08/17 Втр 19:40:47 #704 №1048788 
>>1048786

> 1. Может добавить в класс сотрудника поле - "Департамент". Это позволит всегда знать, в каком департаменте сотрудник.

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

То есть подумай, так ли оно тебе нужно.

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

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

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

> На уровне идеи - в компании хранится массив с объектами-департаментами, внутри сотрудники, все как обычно. Но добавление сотрудника производить не методом addEmployee($employee) в объекте департамент, а методом самой компании - addEmployee($department, $employee) ну и дальше с сотрудниками работать через методы компании.

Можно, а в чем выгода? Все равно же в итоге компания будет вызывать метод департамента для добавления сотрудника (если список сотрудников сделан приватным полем).

То есть по твоим предложениям - попробуй подумать, а зачем это нужно, какая от этого польза.
Аноним 22/08/17 Втр 19:52:14 #705 №1048792 
Вообще, раз уж зашла речь о форматах плавающих чисел, я почитал статью (англ) про историю IEEE 752: https://people.eecs.berkeley.edu/~wkahan/ieee754status/754story.html - довольно интересно, и это наверно тот случай, когда тщательное проектирование оправдалось. Хотя конечно сравнение 2 чисел на равенство они могли бы тоже встроить в стандарт!
Аноним 22/08/17 Втр 20:30:20 #706 №1048812 
>>1048774
>На современных процессорах по моему особой выгоды в производительности от использования float нет
Неправда, такая выгода есть и для ЦП, и для ГП (в которых есть даже FP16)
Аноним 22/08/17 Втр 20:49:37 #707 №1048831 
>>1048594
ОП отпишись пожалуйста, интересно услышать твоё мнение
Аноним 22/08/17 Втр 21:08:40 #708 №1048847 
>>1048594

> Какие подводные камни если я заведу для категорий поле с битовой маской например и буду хранить в денормализованной таблице product ?
Отступление от принципов нормализации, невозможность сделать внешний ключ с products на product_categories, проблемы, если категорий станет больше, невозможность использовать индекс при поиске по категории.

Какие ты там нашел плюсы?

> Поиск будет на мой взгляд намного быстрее без лишнего джоина

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

Алсо, мне не нравится, когда люди без пруфов пишут "джойн медленный". Кто вам такое сказал?
Аноним 22/08/17 Втр 21:11:40 #709 №1048850 
>>1048812

Тут написано https://stackoverflow.com/questions/4584637/double-or-float-which-is-faster что для интеловских архитектур разницы нет, и математический сопроцессор работает на даблах. Разница может быть только из-за увеличения объема памяти.

Что касается GPU, в них не силен.

В PHP все это разумеется значения не имеет в силу наличия накладных расходов на интерпретацию (а переменные в PHP вообще по 50 байт занимают если я не путаю).
Аноним 22/08/17 Втр 21:13:25 #710 №1048851 
>>1048812

Тут впрочем есть другое мнение: https://social.msdn.microsoft.com/Forums/en-US/2b190cfa-e221-4e91-b40c-c2a00aee4b36/float-vs-double-performance-on-arm?forum=winappswithnativecode

Опять же, к PHP это никак не относится.
Аноним 22/08/17 Втр 21:18:10 #711 №1048853 
>>1048847
>Отступление от принципов нормализации
От них отступают в любом инет-магазине все у кого больше 500к товаров. У меня на инет магазине с 1.2кк товаров только таблица product_attribute хранит 26кк записей, намного удобнее денормализировать данные 2 таблицы чем даже 3 джоина делать таблицы product_attribute (Красная блузка с 8 пуговицами, белым воротником и черно-белым принтом
>Алсо, мне не нравится, когда люди без пруфов пишут "джойн медленный"
Лучше сделать выборку из одной денормализированной таблицы чем 5 джоинов по нормализированным.
Пруфы могу запостить если мне не будет лень, у меня как раз есть подходящая база
Аноним 22/08/17 Втр 21:35:50 #712 №1048861 
>>1048853

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

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

Аноним 22/08/17 Втр 21:36:34 #713 №1048862 
>>1048853

Ну и поиск по битовой маске подразумевает full table scan. Я уже выше написал об этом.
Аноним 22/08/17 Втр 22:06:07 #714 №1048886 
>>1048862
Да, наверное ты прав, при поиске по битовой маске индекс не поможет совсем
Аноним 22/08/17 Втр 22:31:29 #715 №1048935 
http://php.net/manual/en/class.eventhttpconnection.php

Где есть вменяемый мануал о том, как это использовать?

inb4 запускаешь всё подряд и смотришь на ошибки
Аноним 22/08/17 Втр 22:33:56 #716 №1048941 
Этот тред закрыт. Дружно перекатываемся.

https://2ch.hk/pr/res/1048938.html
https://2ch.hk/pr/res/1048938.html
https://2ch.hk/pr/res/1048938.html
https://2ch.hk/pr/res/1048938.html
https://2ch.hk/pr/res/1048938.html
https://2ch.hk/pr/res/1048938.html
https://2ch.hk/pr/res/1048938.html
sageАноним 22/08/17 Втр 22:34:53 #717 №1048942 
>>1048941
Опять уёбок перекатил тред через жопу. Просили же не делать так, ты необучаемый?
Аноним 22/08/17 Втр 22:39:38 #718 №1048948 
>>1048941

Не перекатываемся. Сиди один в своем треде с шапкой на гитхабе.
Аноним 22/08/17 Втр 22:54:07 #719 №1048962 
>>1048935

http://php.net/manual/en/intro.event.php
Есть вступление. В нем написано

> This is a port of libevent to the PHP infrastructure.
Так что может быть полезно ознакомиться с сишной библиотекой libevent.

Ну или вообще с принципами работы таких библиотек (начать можно с знаменитой статьи про C10K Problem http://www.kegel.com/c10k.html можно попробовать нагуглить переводы ).



Аноним 23/08/17 Срд 02:31:35 #720 №1049105 
Testhub
Сделал форму создания/редактирования теста, вынес код из контроллеров в сервисы.

Накопилось "немного" вопросов
https://pastebin.com/qW5g4qZA
Аноним 23/08/17 Срд 04:28:01 #721 №1049164 
>>1048725
Сказать то что хотел? Ничего не понял.
Аноним 23/08/17 Срд 06:46:36 #722 №1049178 
Сап, почему у нас в 2017 году есть куча мидлов и синьоров которые до сих пор считают что одинарные кавычки это хороший тон и быстрая скорость выполнения? Причём вчера мне это заявил человек с 5 годами опыта и посылам "Я так делою и ты так делой".
Аноним 23/08/17 Срд 08:17:13 #723 №1049196 
>>1049178
Ты глупый? Он выучил что-то 6 лет назад и делает так ВСЁ ЭТО ВРЕМЯ, видит что кто-то делает не так, и его корежит. Я тоже постоянно функции описываю как:
function kek() {
....
}

function brek() {
...
}

А когда вижу код набитый таким синтаксисом:
function kek()
{
...
}
function brek()
{
...
}
то у меня всё начинает плыть перед глазами уже от непривычки.

Чем старше человек, тем он более черствый и всё менее гибкий в любых вопросах, привычки всё глубже укореняются и т.д.
Просто хуй забей.
Аноним 23/08/17 Срд 08:18:04 #724 №1049197 
>>1049178
Триггерни его еще на тему echo/print
Аноним 23/08/17 Срд 08:51:20 #725 №1049206 
>>1049196
>А когда вижу код набитый таким синтаксисом:
Вот с этого всегда проигрывал. Есть же требования и
ctrl
alt
L
Который сам тебе форматнёт за 2 секунды.
Аноним 23/08/17 Срд 08:52:22 #726 №1049208 
>>1049197
Я тригерю его на счёт кнкатенации. Там вообще разрыв шаблона.
Аноним 23/08/17 Срд 09:27:30 #727 №1049233 
>>1049206
так что:
function kek() {
....
}

что:
function kek()
{
...
}
- оба варианта являются приемлимыми, просто в итоге пишут все как кому нравится. Но я привык хуярить первый - так как меньше строк занимает, и для меня читабельнее, так как 1 строка открывающая и 1 закрывающая, а во втором варианте 2 открывающих как бы и просто непривычно видеть по 2 строки перед остумами тела функции.

И вот открываешь чужой файл что бы там что-то изменить, а там эта ебучая стена
}

}

}

}

}

}

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


>>1048592 >>1048601

Алсо вот это говно прочекал и теперь у меня весь ютуб этой парашей засран. пацаны не рекомендую тратить на это время. Пока вы посмотрите курс длиною в 20 часов или сколько он там длится, вы узнаете ровно нихуя - базарю. Вам будут рассказывать основы и пояснять про ловушки для лохов, которые вы тут же забудете из-за отсутствия практики и так далее. Цель таких курсов - срубить бабла на лохах же. Комменты вообще как будто ботами написаны. Лучше отдельно выучить пхп, а потом отдельно же постичь основы html, и ооокак отдавать или делать html динамическим с помощью php будет потом постичь куда проще, чем сидеть наблюдать на экране <p><? echo "helo world"; ?></p> И слушать про подводные камни этой хуйни.
Аноним 23/08/17 Срд 09:54:42 #728 №1049249 
12.jpg
>>1049233
А курс от loftschool? У них вроде как больше на практику направлено. Вот список тем.

>Лучше отдельно выучить пхп
По сайту ОПа?
Аноним 23/08/17 Срд 09:57:30 #729 №1049252 
>>1049249
Да, тым сразу идёт "Вот это говно вы будете использовать каждый день. Остальное мы рассказывать не будем". Но там курс насыщенный пипец просто.
Аноним 23/08/17 Срд 10:25:45 #730 №1049273 
>>1049249
Изучение кодинга можно разделить на 3 условно говоря части.

1. Изучение примитивов: Как работать с переменными, строками, массивами, как это всё создавать заполнять и так далее.
Операции арифметические и логические, присваивание, сравнение. Как и чем можно оперировать, что можно складывать и так далее.
Условия, циклы, как писать свои функции и как работать со встроенными функциями языка.

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

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

3. Архитектура - это то как у тебя в программе в итоге всё устроено, что куда берется, что куда ходит, что выходит и так далее. Где какой алгоритм опять же используется и как что с чем взаимодействует. Тоже может нарабатываться годами.
Опять же можно не касаться этого, когда просто берешь и начинаешь хуярить на готовых решениях по типу вордпрессов и прочих modx или на фреймворках, где ты в принципе тоже привязан к определенной парадигме

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

>По сайту ОПа?
Как угодно. Примитивы похуй как и где. Но оп еще и дроч на алгоритмы втихую под видом "простых" задачек для закрепления дает, что многие могут долго очень на них сидеть.
Аноним 23/08/17 Срд 10:33:26 #731 №1049284 
>>1049273
Ну я от курса и жду примерно как раз такой схемы: синтаксис, основы - алгоритмы, базы данных - субд, цмски, фреймворки.
ну и платить за курсы я никогда и не собирался, потому что результат весьма сомнительный
Аноним 23/08/17 Срд 10:59:28 #732 №1049300 
Жесть нахуй, я уже второй день ломаю голову над одним вопросом: как подключить ssh2 библиотеку к WAMP Server? Ну это пиздец, вот честно. Я испробовал наверное 10 разных способов, но ни один не работает. Может кто подскажет?
Аноним 23/08/17 Срд 11:09:44 #733 №1049308 
>>1049206
>ctrl
>alt
>L
У меня эта комбинация почему-то блокирует компьютер, как Win+L. При этом редактор успевает переформатировать текст. Дома нет такой хуйни, только на работе.
Аноним 23/08/17 Срд 11:12:25 #734 №1049313 
>>1049273
>Но оп еще и дроч на алгоритмы втихую под видом "простых" задачек для закрепления дает, что многие могут долго очень на них сидеть.
Есть такая тема, я уже запарился задачку про вектор ковырять, но тоже дело принципа, однако.
Аноним 23/08/17 Срд 11:50:57 #735 №1049341 
1what1.png
Есть клиентский и серверный сокеты. Клиентский коннектится к серверному, передав в него строку из формы. Сервер слушает и возвращает reversed строку клиенту, а клиент выводит эти строки. Но есть проблема с выводом русских символов. В .htaccess прописано utf-8, хотя от этого тут наверное ничего не зависит.

Server: https://ideone.com/siL9px
Client: https://ideone.com/6ZigUh

Если я на сервере (20 строка) буду возвращать строку, которую я считал (не новую реверсивную), то буквы на сайте нормальные, но в консоли по прежнему ебатня. Почему это происходит?
Аноним 23/08/17 Срд 14:13:43 #736 №1049428 
>>1049341
Вопрос исчерпан.
Аноним 23/08/17 Срд 14:52:13 #737 №1049467 
>>1049300
А, все, не надо. Кое как подключил phpseclib и оно работает.
Аноним 23/08/17 Срд 15:56:52 #738 №1049504 
>>1049313
Нет, в векторе нет никаких алгоритмов. Другое дело бонусные задачи про банкомат и прочее. В векторе ты как раз занимаешься тем что гоняешь туда-сюда строчки по сути и не более. Там как раз развиваются зачатки архитектуры.
someApprentice 23/08/17 Срд 16:16:35 #739 №1049510 
Функция gnupg_decrypt() игнорирует аргумент с passphrase, потому что, cо 2 версии, passphrase передается c помощью pinentry через gpg-agent.

В комментариях была указана ссылка на https://wiki.archlinux.org/index.php/GnuPG#Unattended_passphrase где говориться как вернуть старый функционал:

>First, edit the gpg-agent configuration to allow loopback pinentry mode:
>~/.gnupg/gpg-agent.conf
>allow-loopback-pinentry
Этого файла не было, и я создал его в ручную, но это не имеет значения, потому что эта опция включена по умолчанию.

https://www.gnupg.org/documentation/manuals/gnupg/Agent-Options.html#Agent-Options
>--no-allow-loopback-pinentry
>--allow-loopback-pinentry
>Disallow or allow clients to use the loopback pinentry features; see the option pinentry-mode for details. Allow is the default.

>Second...
>...add the option to the configuration:
>~/.gnupg/gpg.conf
>pinentry-mode loopback
После этого я не смог пользоваться gpg и получил ошибку:

gpg: .../gpg.conf:242: invalid option

Я не нашел эту опцию в списке опций gpg.conf ( https://www.gnupg.org/documentation/manuals/gnupg/GPG-Configuration-Options.html#GPG-Configuration-Options ), но нашёл в "Agent’s Assuan Protocol" https://www.gnupg.org/documentation/manuals/gnupg/Agent-OPTION.html#Agent-OPTION , где не понятно как устанавливать эти опции.

Есть какие-нибудь идеи как настроить этот протокол?


Кстати, зашифрованный, с помощью gnupg_encrypt(), текст замечательно расшифровался с помощью той js библиотеки.
Аноним 23/08/17 Срд 20:25:47 #740 №1049667 
Сделал новый тред для нетерпеливых тут >>1049651 (OP) . С нормальной шапкой, которая продумана, содержит полезные ссылки, задачи, итд. Может она конечно длинновата, ну тогда мы ее потом как-нибудь подсократим.

Так что кому не нравится тред в бамплимите, можно перейти и общаться там.

Я пока туда переходить не буду, еще дня 2-3 тут посижу, отвечая на неотвеченные посты.

Ну а автор треда, который решил, что шапка не нужна, без всякой аргументации, а просто потому что ему так больше нравится, пусть один и сидит в своем пустом треде.
Аноним 23/08/17 Срд 21:19:59 #741 №1049725 
>>1049510

> Я не нашел эту опцию в списке опций gpg.conf
Если подняться в мануале на 1 шаг вверх ( https://www.gnupg.org/documentation/manuals/gnupg/Invoking-GPG_002dAGENT.html#Invoking-GPG_002dAGENT ) то видно, что это опции для утилиты gpg-agent (которая, как я вроде упоминал, нужна для того, чтобы вводить пароль для расшифровки ключа только один раз, она расшифровывает ключ и держит его в памяти).

То есть эта опция тебе не поможет. Конечно, ты бы мог попробовать использовать gpg-agent: запускать его, написать специальную программу, которая будет выполнять роль программы pinentry, и получать откуда-то пароль, но это выглядит довольно громоздко и усложненно.

Попробуем посмотреть мануал по библиотеке gpgme:

> https://www.gnupg.org/documentation/manuals/gpgme/Decrypt.html#Decrypt
> Function: gpgme_error_t gpgme_op_decrypt (gpgme_ctx_t ctx, gpgme_data_t cipher, gpgme_data_t plain)
Здесь видно (методом исключения), что ключ и параметры шифрования хранятся в контексте ctx.

> https://www.gnupg.org/documentation/manuals/gpgme/Pinentry-Mode.html#Pinentry-Mode
> Function: gpgme_error_t gpgme_set_pinentry_mode (gpgme_ctx_t ctx, gpgme_pinentry_mode_t mode)
> The function gpgme_set_pinentry_mode specifies the pinentry mode to be used.
> For GnuPG >= 2.1 this option is required to be set to GPGME_PINENTRY_MODE_LOOPBACK to enable the passphrase callback mechanism in GPGME through gpgme_set_passphrase_cb.
> ...
> GPGME_PINENTRY_MODE_LOOPBACK
> Redirect Pinentry queries to the caller. This enables the use of gpgme_set_passphrase_cb whis pinentry queries redirected to gpgme.
Здесь можно задать способ получения пароля к ключу, в том числе с использование коллбека, который вызовет библиотека gpgme.

Там упоминается функция gpgme_set_passphrase_cb: https://www.gnupg.org/documentation/manuals/gpgme/Passphrase-Callback.html#Passphrase-Callback
> Function: void gpgme_set_passphrase_cb (gpgme_ctx_t ctx, gpgme_passphrase_cb_t passfunc, void *hook_value)

То есть концепция при работе с сишной библиотекой такая:

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

Но это все в сишной библиотеке, а реализована ли такая возможность в php-расширении? Поищем в коде, благо он почти весь там в одном файле, и находим:

https://github.com/php-gnupg/php-gnupg/blob/master/gnupg.c#L1438
Внутри функции gnupg_decrypt() есть вызов такой функции, задающей коллбек. Вот сам коллбек: https://github.com/php-gnupg/php-gnupg/blob/master/gnupg.c#L579

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

> gnupg_cleardecryptkeys
> gnupg_adddecryptkey

Последняя функция описана в комментарии как proto bool gnupg_adddecryptkey(string key), но почитав исходники, мы видим что у нее есть 2 варианта вызова:

- как метод на каком-то объекте (по-видимому, соответствующем контексту в библиотеке gpgme), с 2 строковыми аргументами
- как функция с 3 аргументами: ресурс (скорее всего контекст gpgme), и 2 строки (key_id, passphrase)

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

Соответственно, функция gnupg_adddecryptkey($ctx, $key_id, $passphrase) делает следующее:

- вызывает gpgme_get_key(PHPC_THIS->ctx, key_id, &gpgme_key, 1) - function gpgme_get_key gets the key with the fingerprint (or key ID) fpr from the crypto backend
- делает цикл по subkey в найденном ключе:

> gpgme_subkey = gpgme_key->subkeys;
> while (gpgme_subkey) {
> if (gpgme_subkey->secret == 1) {
> PHPC_HASH_CSTR_ADD_PTR(
> PHPC_THIS->decryptkeys, gpgme_subkey->keyid,
> passphrase, passphrase_len + 1);
> }
> gpgme_subkey = gpgme_subkey->next;
> }

- добавляет passphrase в массив decryptkeys для всех идентификаторов подключей

То есть, мне кажется, что функция gnupg_adddecryptkey должна задавать пароль для всех подключей указанного в key_id ключа. Она есть в мануале: http://php.net/manual/en/function.gnupg-adddecryptkey.php и там есть примеры использования.

Еще, может быть стоит посмотреть, может есть другие реализации pgp? Я вот беглым гуглением наткнулся на несколько проектов: https://www.google.ru/search?q=github+php+gnupg&newwindow=1&gbv=1&sei=hb-dWan1GKS56ASWraPgDQ

Также, я несколько раз видел упоминание библиотеки libsodium, которая содерждит готовые криптографические примитивы - может, можно просто на них повторить алгоритм gpg?
Аноним 23/08/17 Срд 22:09:51 #742 №1049750 
>>1049341

Виндовая консоль не выводит utf-8, увы.

Обработка ошибок у тебя не печатает причину ошибки.

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

Код написан не совсем верно, так как тебе стоит посмотреть мануал по socket_write/read:

> http://php.net/manual/ru/function.socket-write.php
> socket_write() не обязательно записывает все байты из указанного буфера. Нормально то, что, в зависимости от сетевых буферов и т. д., только некоторое количество данных, даже один байт, будет записан, хотя ваш буфер больше. Вы должны следить за тем, чтобы непреднамеренно не забыть передать остаток ваших данных.

То же касается и socket-read - она может возвращать данные в любых объемах, хоть по 1 байту за вызов, и надо это учесть.

в сервере $spawn открывается внутри цикла, но не закрывается.
Аноним 23/08/17 Срд 22:11:58 #743 №1049752 
>>1049273

Что касается "формочек" и "таблиц", у ОПа есть задача про студентов с комментариями, с паттернами работы с БД, с правилами обработки форм, с описанием уязвимостей, с советами по архитектуре. Не в каждом учебнике или курсе такие вещи описываются нормально (если бы описывались - я бы и не мучался, а просто дал ссылки).
Аноним 23/08/17 Срд 22:19:03 #744 №1049759 
>>1049249

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

https://docs.google.com/spreadsheets/d/1-ovmqMq-Un4NCvDTxyGRQOi282ZLf6ZqmpS_pB4o_pw/edit#gid=0

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

На phpunit отведен вообще кусочек занятия. Ну что они освоят за это время?

Сроки очень сжатые там. Сомневаюсь, что реально в них уложиться, особенно если человек еще где-то работает.
someApprentice 23/08/17 Срд 23:36:43 #745 №1049795 
>>1049725
Завтра, на свежую голову, ознакомлюсь подробнее! Это очень сложно.

>То есть, мне кажется, что функция gnupg_adddecryptkey должна задавать пароль для всех подключей указанного в key_id ключа.
Да, действительно, именно она задает пароль. Я перепутал эти функции в начале. Просто изначально ошибка выдавалась именно на функции decrypt, поэтому я предполагаю, что это именно из-за сломанной передачи passphrase, как было сказано в комментариях - сама функция decrypt, конечно же, не принимает его.

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

>Еще, может быть стоит посмотреть, может есть другие реализации pgp?
Да, я тоже думал прибегнуть к ним, но я немного сомневался в их надёжности. Я протестирую завтра библиотеку которую предлагал ранее для генерации ключей: https://pear.php.net/package/Crypt_GPG

>Также, я несколько раз видел упоминание библиотеки libsodium, которая содерждит готовые криптографические примитивы - может, можно просто на них повторить алгоритм gpg?
Это займет слишком много времени. Я хотел всего лишь написать качественный мессенджер, но с шифрованием оказалось слишком много подводных камней. Но это ничего, в Crypt_GPG должны работать эти функции. На самом деле, остается сделать только последний рывок.

Мне интересна задача с повторением алгоритма gpg, поэтому я оставлю это на дальнейшую реализацию. Ах как много ещё предстоит сделать

Так же, вы писали большой пост насчёт архитектуры приложения. На это тоже уйдет какое-то время. Я пока параллельно буду писать вариант без модели, чтобы не терять время, и потом ощутить на своей шкуре преимущество хорошей архитектуры (пока мне это не так очевидно).
Аноним 24/08/17 Чтв 02:53:56 #746 №1049917 

По phpunit почитал мануал, вроде все понятно.
Правда там примеры уровня assertEquals(0, count([])) и assertEquals(2, 1+1).

Это все замечательно, но как тестировать реальное mvc приложение? Где нет методов возведения числа в квадрат, а есть только получение данных из базы и вывод в html.
Допустим в контроллере я получаю данные из реквеста, передаю их в метод сервиса.
Сервис исполняет методы репозиториев, где тупо sql/dql/builder.
Что тут тестить? Ок, допустим у меня на главной странице выводятся 5 последних записей.
Логично проверить, что выводятся именно пять, и что эти записи действительно последние по дате.
Занести подготовленные данные в бд, выполнить тестируемый метод и проверить что он вернет ожидаемый результат?
Ок, а какие есть способы занесения этих данных в базу, ну то есть нельзя ли как-то подгрузить фикстуры из doctrine fixtures классов, потому что мне не очень хочется теперь дублировать их еще и в xml или yaml специально для phpunit.
И как указать базу для тестирования? В симфони почему-то есть отдельные конфиги для dev и prod, но я не вижу для test.
Аноним 24/08/17 Чтв 03:35:41 #747 №1049920 
>>1049917
Нагуглил пока что-то такое
https://stackoverflow.com/questions/9196035/temporary-doctrine2-fixtures-for-testing-with-phpunit

А, все, как сменить базу нашел.
http://symfony.com/doc/current/testing/database.html#changing-database-settings-for-functional-tests
Тут еще какие-то моки вместо реальных репозиториев.
// Now, mock the repository so it returns the mock of the employee
$employeeRepository = $this->createMock(ObjectRepository::class);

Из пасты опа
> Моки — это классы-заглушки, которые используются чтобы проверить, что определенная функция была вызвана (по моему, они не очень часто нужны).
Что сие значит? Что за моки и как их готовить?

Чет я не понял, они предлагают проверять не результат запроса (набор объектов), а сам запрос (sql строку)?
http://symfony2-document.readthedocs.io/en/latest/cookbook/testing/doctrine.html#writing-your-unit-test
Аноним 24/08/17 Чтв 03:50:45 #748 №1049923 
>>1049795

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

Насчет Crypt_gpg - сразу предупрежу, что по описанию:

> Crypt_GPG uses PHP's program execution functions to run GnuPG as a subprocess, performing the desired action. Crypt_GPG automatically handles process control, stream handling and error checking of the GnuPG subprocess. Crypt_GPG uses PHP streams internally for most actions, allowing (among other things) any streamable resource to be used with the Crypt_GPG file commands.

То есть он просто запускает процесс gpg.

>>1049233

Есть PSR, где написано как должна ставиться скобка. Свои стандарты придумывать не надо, от этого никакой выгоды.

>>1049917

А урок читал https://gist.github.com/codedokode/a455bde7d0748c0a351a ?

Вообще, я бы советовал для начала все же тестировать более мелкие компоненты, например, модели в рамках MVC. Так как GUI тесты - сложные и хрупкие.

> Сервис исполняет методы репозиториев, где тупо sql/dql/builder.
Его можно протестировать, что он не падает при вызове функций.

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

Для начала можно протестировать что страница вообще рендерится.

> Ок, а какие есть способы занесения этих данных в базу, ну то есть нельзя ли как-то подгрузить фикстуры из doctrine fixtures классов, потому что мне не очень хочется теперь дублировать их еще и в xml или yaml специально для phpunit.
Я думаю, можно. Дублировать не надо.

Вообще, с БД есть разные подходы:

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

Для ускорения некоторые используют sqlite с БД в памяти или mysql с данными в tmpfs (тоже в памяти по сути).

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

Ну например, если у тебя есть класс с методами addPost, getPosts, deletePost, то можно сделать такой тест:

- добавить пост через addPost
- проверить что getPosts его вернет
- удалить пост
- проверить, что getPosts его не возвращает

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

Этот подход хорошо работает с классами, которые что-нибудь кодируют/разбирают. Ну например, мы бы могли тестировать функции json_encode/json_decode, пропуская разные данные через обе эти функции и проверяя, что ничего не теряется.

Вообще, важно учитывать такие вещи:

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

> Где нет методов возведения числа в квадрат, а есть только получение данных из базы и вывод в html.
тестируй, что методы получения данных что-нибудь возвращают.

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

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

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

> И как указать базу для тестирования? В симфони почему-то есть отдельные конфиги для dev и prod, но я не вижу для test.

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

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

Аноним 24/08/17 Чтв 04:00:49 #749 №1049924 
>>1049920

Что такое моки и стабы (англ): https://www.google.ru/search?q=mock+stubs&newwindow=1&gbv=1&sei=5CKeWdriB-Kb6ATuj5CwAg

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

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

Вот есть у тебя функция, возвращающая 5 последних новостей:

function getLastNews(EntityManagerInterface $em)

Ты можешь передать вместо $em мок, в который положить мок репозитория NewsRepository. Но погоди! А откуда ты знаешь, что функция getlastNews будет обращаться к этому репозиторию? Ты закладываешь в тест знание того, как работает функция внутри и такой тест легко будет ломаться при любых изменениях в ней. Ну допустим, завтра кто-то добавит вывод рядом с новостью аватарки автора, а твой тест не предусмотрел мок репозитория аватарок.

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

- что она возвращает новости

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

> Чет я не понял, они предлагают проверять не результат запроса (набор объектов), а сам запрос (sql строку)?

Это какой-то очень странный пример, согласен. Ведь код-пользователь тестируемого метода createSearchByNameQueryBuilder($name) не будет анализировать SQL код, который он генерирует. А что он будет делать? Скорее всего, он использует этот query bulder для поиска данных в БД. Ну значит, тут нет смысла писать юнит-тест и надо делать функциональный тест, который проверяет, что полученный query builder ищет записи, подходящие под условие и не ищет неподходящие (такие записи можно вставить прямо перед тестом).

Вот я такие ошибки часто вижу, некоторые люди плохо знакомы с тестированием, возможно, только читали про него, но не применяли на практике и что-то не понимают.
Аноним 24/08/17 Чтв 04:01:49 #750 №1049925 
>>1049920

Начинать можно со smole test - просто проверить, то код не падает при вызове функции/контроллера/запросе страницы.
Аноним 24/08/17 Чтв 04:04:09 #751 №1049926 
>>1049920

Также, если надо, могу нескромно дать пример своего проекта с тестами. Вот тут есть smoke test например (testPagesAreWorking): https://github.com/codedokode/task-checker/blob/master/tests/Web/ControllersTest.php

Аноним 24/08/17 Чтв 12:44:42 #752 №1050039 
Задача про Вектор. Доделал вторую часть про оптимизацию, смотрите, пинайте.
https://github.com/telepok/php-test/blob/master/oop4.php

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

Получилось много методов вида getFoo и setFoo, может имеет смысл заменить на один метод Get и Set с параметрами? Как вообще правильно это делать?
Аноним 24/08/17 Чтв 17:36:27 #753 №1050204 
>>1050039

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

Когда ни одной ссылки на объект не остается, объект становится недоступным (то есть обратиться к нему больше невозможно) и будет удален сборщиком мусора рано или поздно. Соответственно, специально делать ничего не требуется.
Аноним 24/08/17 Чтв 17:52:35 #754 №1050212 
Какие элементы html по дефолту имеют градиент? Button только помню. Мне нужно придать объёмность полю ввода. Ну или ещё какому элементу, на котором можно выводить текст.
Аноним 24/08/17 Чтв 22:14:52 #755 №1050432 
>>1050212

Никакие. Используй CSS.
Аноним 25/08/17 Птн 00:10:08 #756 №1050480 
Как в if написать условие для переменной, что бы она была больше одного значения, но меньше другого? Например, что бы $z был больше 5, но меньше 1000?
Аноним 25/08/17 Птн 01:55:50 #757 №1050546 
>>1050480

if (первое условие && второе условие)

В PHP операторы сравнения вроде < или == возвращают специальное логическое значение true(истина) или false (ложь). Например var_dump(2 < 5); выведет true, а 2 > 5 вернет false.

Над логическими значениями можно делать операции:

&& значит "и", то есть оба условия должны выполняться
|| значит "или", то есть выполняться должно хотя бы одно из условий
!(условие) значит "не", то есть меняет результат проверки на протьивоположный

Подробнее советую почитать в мануале

http://php.net/manual/ru/language.types.boolean.php
http://php.net/manual/ru/control-structures.if.php
http://php.net/manual/ru/language.operators.logical.php

Изучи булев тип и обрати внимание, как изящно решена проблема объединения разных условий.
Аноним 25/08/17 Птн 10:08:16 #758 №1050623 
>>1050432
Именно для объёмности? Не просто для градиента.
Аноним 25/08/17 Птн 17:22:15 #759 №1050832 
Есть два массива. Нужно найти разницу.
Использую $diff = array_diff($array1, $array2);
И по нему выходит, что разницы нет, хотя массивы отличаются. Специально сделал вывод - ну отличаются же.

$array1
Array (
[0] => Array (
[id] => 1 )
[1] => Array (
[id] => 2 )
[2] => Array (
[id] => 3 )
[3] => Array (
[id] => 4 )
)

$array2
Array (
[0] => Array (
[id] => 1 )
[3] => Array (
[id] => 4 )
)

Что за ерунда? Ну не может же так быть. Перед diff я создал второй массив, как копию первого и выкусил у него через unset($array2[$value]); пару строчек. Может diff работает со старой версийй массива? Бред какой-то.

Аноним 25/08/17 Птн 17:28:06 #760 №1050836 
>>1050832

Мануал открыв, ты увидишь http://php.net/manual/ru/function.array-diff.php

> Замечание:
> Два элемента считаются одинаковыми тогда и только тогда, если (string) $elem1 === (string) $elem2. Другими словами, когда их строковое представление идентично.
> Замечание:
> Обратите внимание, что эта функция обрабатывает только одно измерение n-размерного массива. Естественно, вы можете обрабатывать и более глубокие уровни вложенности, например, используя array_diff($array1[0], $array2[0]);.
Аноним 25/08/17 Птн 18:50:16 #761 №1050889 
Здравствуйте! Подскажите почему тупит код.
Задача про кредитный калькулятор и веб-сервер. Все работает. Но одна строчка очень тупит. Понять не могу что не так.

https://pastebin.com/eX1ATeNW

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

Ничего лучше чем setcookie($login."count",($_COOKIE[$login."count"] + 1)) я не придумал.
Аноним 25/08/17 Птн 21:32:10 #762 №1050985 
>>1050889

Поясни пожалуйста, что значит "очень тупит"? Выдает ошибку? Долго выполняется? Если долго выполняется, то какая строчка и как ты определил, что проблема именно в ней?

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

в начале только php-код, сохраняющий результат в переменные
далее только HTML-код с выводом переменных

Либо на 2 отдельных файла: в одном логика, в другом HTML-код. Первый файл вычисляет значения, сохраняет в переменные и подключает через require второй файл.

Подробнее про шаблоны http://web.archive.org/web/20161119062218/http://www.phpinfo.su/articles/practice/shablony_v_php.html

> if (((int)$_GET[$key]==false)
Это условие бессмысленно так как в $_GET могут быть только строки или массивы строк. false там быть не может. Так как они берутся из URL (query string) который сам является строкой.

(int)$_GET[$key] дает int, который опять же не может быть равен false.

Чтобы твой HTML код всегда корректно отображался, добавь в начало тег meta с указанием кодировки: http://htmlbook.ru/html/meta/charset

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

- сделать функцию проверки правильности входных данных
- сделать функцию расчета кредита

При этом надо тщательно продумать, что функции получают на вход, что выдают на выходе.

Также, может быть тебе поможет урок про обработку форм: https://github.com/codedokode/pasta/blob/master/forms.md (там упоминается редирект, это нужно для защиты от повторной отправки при обновлении страницы, у тебя такой проблемы нет и редирект не требуется).

Если что-то непонятно - спрашивай.

> Ничего лучше чем setcookie($login."count",($_COOKIE[$login."count"] + 1)) я не придумал.
Это подойдет, только надо делать проверку, есть ли такая кука, чтобы не было обращения к несуществующему элементу массива. И хорошо бы и тут код разбить на функции, просто чтобы учиться писать в таком стиле, а не стеной.

$login там не нужен.
Аноним 25/08/17 Птн 21:33:16 #763 №1050986 
>>1050623

Внешний вид элементов задается в CSS. С помощью HTML разметки мы задаем не вид, а назначение элемента, чем он является - ссылкой, заголовком, иллюстрацией, абзацем текста и тд.
Аноним 25/08/17 Птн 22:35:18 #764 №1051018 
>>1050985
Просто в задании про куки нужно чтобы счетчик считался для разных пользователей. Вот я и подумал добавлять логин к имени куки, чтобы имя куки было уникальным.

А в первом задании 47 строка как раз и вызывает сообщение "что-то там дольше 30 секунд".
Аноним 25/08/17 Птн 22:56:49 #765 №1051028 
>>1051018

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

"дольше 30 секунд" - значит у тебя неправильно написан алгоритм, и получился вечный цикл, который никогда не закончится.
Аноним 26/08/17 Суб 11:29:28 #766 №1051183 
>>1051028
У каждого пользователя свои куки.

Ну вот если на одном компьютере заходят на сайт разные люди. Чтобы счетчик был у каждого свой. Я добавляю имя пользователя в имя счетчика куки.
Аноним 27/08/17 Вск 01:16:44 #767 №1051679 
Как мог, покрыл тестами
https://github.com/pricklynut/testhub

Прилинкую пасту с вопросами, чтобы не потерять >>1049105

По тестированию.
Как в постгрес создать бд для тестов в памяти, как в mysql? Ну или хотя бы просто создать бд из консоли.
doctrine:database:create выдает ошибку, что база данных не существует. Конечно не существует, я же
как раз этой командой хочу ее создать!
Если без шуток, я понимаю что проблема в этой "оригинальной" системе ролей и прав постгреса, он просто
не разрешает создать базу нерутовому пользователю. Вопрос как быть в такой ситуации? Я пока использую mysql для тестов, он разрешает создавать базу.

Пытаюсь в setUp запустить миграции и фикстуры через консольную команду, вроде тесты выполняются, но напоследок
ругается нотисами
The "ConsoleEvents::EXCEPTION" event is deprecated since Symfony 3.3 and will be removed in 4.0. Listen to the "ConsoleEvents::ERROR" event instead: 3x
2x in ApplicationAvailabilityFunctionalTest::setUpBeforeClass from Tests\AppBundle
1x in ApplicationAvailabilityFunctionalTest::tearDownAfterClass from Tests\AppBundle
Я вроде никаких ConsoleEvents не трогал, там приблизительно такой код:
$app = new Application(static::createClient()->getKernel());
$app->run(new StringInput("doctrine:create:database"));
В мануале вроде так рекомендуют вызывать консольные команды, не знаю, может я что-то не так делаю.
https://symfony.com/doc/current/console/command_in_controller.html

При установке symfony standard edition в папке с тестами был хелловорлд с ассертами
$this->assertEquals(200, $client->getResponse()->getStatusCode());
$this->assertContains('Welcome to Symfony', $crawler->filter('#container h1')->text());
Нужно проверять именно на 200 статус? Часто ли на практике встречаются другие 2xx статусы?
Просто в других примерах чаще используют response->isSuccessful().
По второму ассерту: логично ли проверять контент страницы, в данном случае содержимое h1?
А вдруг верстальщик его поменяет, или заменит h1 на див?
Короче я у себя проверил только наличие элементов с классом .item (на странице выводится список последних тестов),
и что у каждого из них есть заголовок (ну то есть что не выводятся пустые контейнеры).

В составе symfony standard edition идет в комплекте некий simple-phpunit.
Что это за зверь и в чем его особенности? Ну например я phpstorm под него не могу настроить, чтобы тесты запускались
из ide, пишет Class 'PHPUnit_TextUI_ResultPrinter' not found. Погуглил на stackoverflow, кажется phpstorm хочет старую
версию phpunit (без неймспейсов, с подчеркиваниями)? Или это связано с simple-phpunit, может у него чего-то не хватает?

Что делать с приватными методами? Как их тестить в смысле. И нужно ли тестить. Приватные методы используются внутри тестируемых, просто чтобы избежать дублирования или нагромождения кода.
Аноним 27/08/17 Вск 08:17:11 #768 №1051782 
>>1051679
http://www.restapitutorial.com/lessons/httpmethods.html
Например.
Аноним 28/08/17 Пнд 09:27:43 #769 №1052464 
>>1050836
Ну.Мануал. Открывал и читал. Вот пусть первый уровень вложденности и обрабатывает. В одном это строки [0] => Array и в другом тоже. Что не так-то?
Можешь дать пример, как эти массивы правильно сравнивать, чтобы получить разницу?
Аноним 28/08/17 Пнд 18:33:16 #770 №1052751 
>>1050832
>Сравнивает array1 с одним или несколькими другими массивами и возвращает значения из array1, которые отсутствуют во всех других массивах.

Толсто.
Аноним 28/08/17 Пнд 18:48:36 #771 №1052764 
>>1050832
https://ideone.com/WhnvHU

А разгадка проста: у тебя везде значение Array, поэтому и одинаковые.
Аноним 29/08/17 Втр 03:05:06 #772 №1053063 
>>1052464

Смысл в том, что array_diff работает только с массивами строк или чисел. С массивами массивов она не работает. Нужно либо писать свое решение, либо гуглить готовое (например по словам php array diff recursive).
https://github.com/pricklynut/testhub Аноним 29/08/17 Втр 03:08:33 #773 №1053064 
> Где можно почитать про кеши в симфони? (точное место в документации, я там пока не нашел ответа на свой вопрос)

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

Прежде чем ковырять исходники, стоит также почитать про бандлы и компоненты в Симфони. Компоненты - это независимые части, которые можно использовать отдельно, а бандлы - это части фреймворка Симфони.

Я попробовал вспомнить, какие кеши я знаю:

1) opcache - это не часть Симфони, а часть PHP5.5+. Он кеширует в shared memory (разделяемой памяти) скомпилированные PHP скрипты. Так как Симфони в ходе работы подключает много классов, на их компиляцию будет уходить заметное время без opcache. opcache на дев-сервере обычно настраивают, чтобы он проверял дату модификации файла, и компилировал его заново при изменении. На продакшене обычно эту проверку отключают, а для сброса кеша либо явно вызвыают opcache_clear() при деплое, либо делают новый деплой в новую папку, чтобы изменились путь к файлам (это позволяет сделать безшовное переключение между версиями).

Доки:

- https://symfony.com/doc/current/performance.html#use-a-byte-code-cache-e-g-opcache
- http://php.net/manual/en/book.opcache.php

Ты можешь себе также поставить https://github.com/amnuts/opcache-gui и посмотреть с его помощью, как у тебя работает этот кеш.

opache недоступен в командной строке, точнее, его можно включить, но смысла нет, так как он уничтожится при завершении процесса (update: в PHP7 кое-что доработали для командной строки, но пока плохо: https://stackoverflow.com/questions/25044817/zend-opcache-opcache-enable-cli-1-or-0-what-does-it-do/35880017#35880017 ).

2) bootstrap cache - это кеш, который содержит в одном файле классы, которые нужны на каждом запросе. Он описан тут https://symfony.com/doc/current/performance.html#use-bootstrap-files

Он создается автоматически после установки/обновления пакетов композером, его вызов виден тут:

- https://github.com/symfony/symfony-standard/blob/3.3/composer.json#L36
- https://github.com/sensiolabs/SensioDistributionBundle/blob/master/Composer/ScriptHandler.php#L59
- информация по событиям композера https://getcomposer.org/doc/articles/scripts.md

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

Раньше там было больше классов: https://github.com/sensiolabs/SensioDistributionBundle/blob/0db645c7e01286d7ca8fa79b61539f6aa644b25c/Composer/ScriptHandler.php#L158

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

3) Кеш (сборка) конфига, DI контейнера и роутера. Надеюсь, ты знаешь что такое DI, и что в Симфони есть DI контейнер, который конфигурируется с помощью YML файлов. А также роутер, который конфигурируется либо yml-файлами, либо аннотациями в контроллерах. А также куча файлов конфигов и параметров.

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

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

my_service:
class: MyClass
arguments: ['yes', @dependency1, @dependency2]

То из него будет сгенерирован примерно такой код:

public function get_my_service()
{
return new MyClass('yes', $this->get_dependency1(), $this->get_dependency2());
}

Параметры конфигурации также "впекаются" в этот класс в виде массива.

После генерации кеш сохраняется куда-то в файл вроде var/cache/prod/scontainer.php, обязательно найди его у себя и изучи.

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

Аналогично из конфигов роутера генерируются 2 php класса - для разбора URL (UrlMatcher) и для генерации (UrlGenerator).

Генерация этих кешей запускается командой cache:clear/cache:warmup, на dev запускается автоматически при отстутвии или устаревашии кеша относительно исходных файлов.

Документация:

- https://symfony.com/doc/current/components/dependency_injection/compilation.html
- https://symfony.com/doc/current/components/dependency_injection/workflow.html
- https://symfony.com/doc/current/components/config/caching.html
- https://blog.whiteoctober.co.uk/2014/02/25/symfony2-cache-warmup-explained/
- https://symfony.com/doc/current/deployment.html
- https://symfony.com/blog/new-in-symfony-3-3-deprecated-cache-clear-with-warmup

В исходном коде проверки и вызов генерации кеша делаются для контейнера в Kernel, а для роутера в Router:

- https://github.com/symfony/http-kernel/blob/master/Kernel.php#L102
- https://github.com/symfony/http-kernel/blob/master/Kernel.php#L484
- https://github.com/symfony/routing/blob/master/Router.php#L269

Изучи код, изучи сгенерированные у себя файлы.

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

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

4) Кеш шаблонов твига. Шаблоны твига компилируются в PHP-код перед выполнением, и этот PHP-код сохраняется на диск (а также кешируется в opache). На dev проверяется дата модификации исходного шаблона, на продакшене, разумеется, нет. Судя по документации, команда cache:warmup как-то находит (как?) все шаблоны и компилирует их в PHP-код. Разумно.

Вот, кстати, код команд cache:clear и warmup:

- https://github.com/symfony/symfony/blob/master/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php
- https://github.com/symfony/symfony/blob/master/src/Symfony/Bundle/FrameworkBundle/Command/CacheWarmupCommand.php

5) Кеши метаданных Доктрины, кеш DQL, прокси-классы сущностей Доктрины.

Доктрина читает метаданные сущностей из аннотаций. В результате чтения для каждой аннотации создается объект (пример объекта, соответствующего аннотации ORM\Column: https://github.com/doctrine/doctrine2/blob/master/lib/Doctrine/ORM/Mapping/Column.php ). Эти объекты кешируются, можно выбрать куда. На продакшене, по умолчанию они сохраняются в php-файлы, и соответственно в opcache, на dev - не помню, по моему аналогично. При желании это меняется через конфиг. Поищи эти файлы у себя в var/cache/doctrine/

Код, кеширующий аннотации: https://github.com/doctrine/annotations/blob/master/lib/Doctrine/Common/Annotations/CachedReader.php

Кстати, аннотации расширяемые, и ты можешь добавить свои аннотации. Например, ты можешь написать конвертор сущностей в JSON на основе аннотаций.

Далее, Доктрина тратит много времени на разбор DQL запросов, потому результаты разбора тоже кешируются, аналогичным образом. Код: https://github.com/doctrine/doctrine2/blob/master/lib/Doctrine/ORM/Query.php#L237

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

- https://github.com/doctrine/common/blob/master/lib/Doctrine/Common/Proxy/ProxyGenerator.php
- https://github.com/doctrine/doctrine2/blob/master/lib/Doctrine/ORM/Proxy/ProxyFactory.php
- https://github.com/doctrine/common/blob/master/lib/Doctrine/Common/Proxy/AbstractProxyFactory.php

Настройки кеширования в Симфони задаются либо в DoctrineBundle, либо используются те, что по умолчанию в Доктрине, можешь поискать самостоятельно.

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

Разобравшись с этим, надеюсь, ты сможешь понять, почему у тебя кеш не так генерируется. Я думаю, у тебя кривые конфиги или криво выбрано окружение, из-за того, что ты не разбирался, как все внутри устроено. Если ты используешь линукс, ты также можешь запустить cache:clear под strace, чтобы увидеть, какие именно файлы она генерирует.
https://github.com/pricklynut/testhub Аноним 29/08/17 Втр 03:09:59 #774 №1053065 
>>1049105
>>1051679

> И как правильно объявить переменную среды?
В Апаче и в настройках пользователя (.bashrc например). Вообще, идея задавать настройки через переменные окружения - описана в 12-factor app: https://12factor.net/ru/config и мне не нравится. Она хорошо работает только на хостингах с read-only файловой системой, и в докере. Представь, что у тебя несколько приложений с разными конфигурациями - замучаешься переменные переключать. Отчасти эту проблему можно решить, выделив на каждое приложение своего пользователя.

> Может в /etc/environment?
Это задает переменную для всех пользователей в системе и всех проектов, что плохо.

> Да, только в документации везде пишут пути типа {% javascripts '@AppBundle/Resources/public/js/*' %}
> а я теперь не могу понять как прописать путь к папке app/Resorces.
Ну это надо смотреть документацию либо код assetic, это тег из него. Ты смотрел? Если в документации нет, открой код assetic и найди там класс вроде TwigExtension и там код этого тега.

> Это composer.json который идет с фреймворком, я туда не заглядывал даже,
Это файл из шаблона (заготовки) приложения. То что идет с фреймворком, и что править нельзя, находится в vendor.

> И на что это влияет кстати? Композер просто откажется устанавливать зависимости, если версия php ниже требуемой?
Документирует зависимость явно, в машинно-читаемом виде. Да, композер это проверяет, изучи мануал: https://getcomposer.org/doc/01-basic-usage.md#platform-packages

> По доктрине, непонятен смысл этих owning и inverse side.
У нас есть 2 объекта и связь между ними, описанная в каждом из них. Представим, что A ссылается на B, но B не ссылается на A. Кому верить? owning side - это сторона, по которой определяется, есть связь или нет. inverse side не проверяется, связь в ней только для удобства использования.

В отношениях 1-1, 1-M owning side - это сторона, где хранится поле-внешний ключ.

> http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/unitofwork-associations.html
> Doctrine will only check the owning side of an association for changes.
> ManyToOne is always the owning side of a bidirectional association.
> The owning side of a OneToOne association is the entity with the table containing the foreign key.

> Что такое bidirectional associations?
Это когда в A объявления связь с B, а в B - обратная связь с A. Обратная связь не обязательна.

> Как правильно настроить эти связи, где писать mappedBy, где inverseBy,
Как описано в мануале, mappedBy - в owning side, inverseBy - в inverse side, если она тебе нужна.

> Как сохраняются связанные сущности? Сохранять (persist) нужно только одну сторону, или обе?
persist ничего не сохраняет. persist передает сущность под управление Доктрины. У Доктрины есть список всех сущностей, которыми она управляет. Это загруженные из БД сущности и добавленные в список через persist(). Когда ты делаешь flush(), Доктрина обходит список, вычисляет изменения и генерирует SQL запросы на обновление БД в соответствии с сизменениями.

Если ты не сделаешь persist, то разумеется, Доктрина твою сущность не увидит и в БД не сохранит. Если ты добавишь в отношение не управляемую доктриной сущность, то есть 2 варианта:

- по умолчанию, это вызовет ошибку
- если у тебя в owning сущности стоит параметр cascade=persist, то Доктрина автоматически сделает persist всем добавленным сущностям при вызове persist для родителя

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

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

http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/working-with-associations.html#transitive-persistence-cascade-operations

> Enum и доктрина. Доктрина всячески побуждает отказываться от enum в пользу единичек/ноликов.
все прекрасно работает если выставить тип поля string.

> Почему так, неужели enum так плох?
Есть мнение (я с ним согласен только частично): http://komlenic.com/244/8-reasons-why-mysqls-enum-data-type-is-evil/

> Просто если у меня поле типа is_correct('yes', 'no'), отказываются работать чекбоксы, они
ждут true/false.
Тогда надо использовать маппинг boolean, если у тебя true/false.

> Варианты, которые с вопросов в связи M-1, не удаляются.
По какой причине не удаляются? Может быть, нужен cascade remove в сущности?

Тут надо помнить, что формы по идее ничего про базу данных и доктрину не знают. Они работают с моделью. Они только могут вызывать у сущности removeItem(). И задача сущности и доктрины это корректно увидеть и сохранить.

Сделай тест: убери/добавь вручную вариант ответа к вопросу и проверь, сохраняется ли все. Может быть, сначала стоит написать тесты на модель данных (сущности), что любые их изменения корректно сохраняются в БД. Серьезно, попробуй для начала в тесте phpunit создать тест с вопросами и вариантами ответов и сохранить его, отредактировать, удалить итд. Протестируй, что все возможные операции работают.

Вообще, если ты почитаешь документацию и исходный код форм, ты узнаешь, что они взаимодействуют с моделью с помощью специального компонента property-access: https://symfony.com/doc/current/components/property_access.html

В документации этого нет, но в коде мы видим, что там есть специальный метод для обновления коллекции через вызовы add/remove: https://github.com/symfony/property-access/blob/master/PropertyAccessor.php#L568 и константа ACCESS_TYPE_ADDER_AND_REMOVER.

Мне кажется, что перенос данных между моделью и формой (которая представляет собой дерево объектов Form) может делаться тут: https://github.com/symfony/form/blob/master/Extension/Core/DataMapper/PropertyPathMapper.php

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

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

> Кстати, в некоторых связях в этих методах типа add вызывают аналогичный метод у связанного объекта,
Это можно делать, но только на одной стороне, чтобы не получился цикл.

> Только почему доктрина не может это сделать сама?
Как? Не забывай, что доктрина - это маппер, она находится сбоку от твоих сущностей и не может перехватить вызов setTask(). Вообще, ее задача просто синхронизировать данные в БД и в твоих сущностях.

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

Можешь попробовать написать расширение для этого.

> И на какой стороне (возвращаясь к этим owning/inverse side) нужно прописывать это повторное линкование (или как его вообще назвать)?
Не знаю, на практике обычно ты будешь делать его только на одной стороне, на ней и прописывай. ну то есть обычно мы делаем $task->addTag(), и почти никогда нам не нужно $tag->setTask (тег ведь не может поменять владельца). Исходя из этого и выбираешь сторону. Вообще, часто обратная связь вообще не нужна. Если у тебя миллион task, то при вызове tag->getTasks у тебя просто памяти не хватит. То есть ты должен подумать, как ты используешь свои модели и исходя из этого делать или не делать ассоциации, а не добавлять все связи подряд просто чтобы они "были".

> Исчерпывающее объяснение. Добавьте два метода (правило именования которых непонятно), и какую-то опцию в конфиг, и будет вам "easier". И потом кто-то удивляется, что люди копируют код не понимая что он делает. Может, потому что никто не объясняет?

Изменение очень логичное. Когда было так:

$task->getTags()->add($tag)

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

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

В новом варианте форма просто вызывает add/remove, а твоя модель уже решает, как их внутри и куда сохранять. Логично.

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

https://github.com/pricklynut/testhub Аноним 29/08/17 Втр 03:10:54 #775 №1053066 
>>1049105
>>1051679

> Что за ерунда с прототипами коллекций (т.е. шаблончиков, которые вставляет js)? Зачем их пихают в data-атрибут?
> При просмотре исходного кода выглядит жутко.
Я обычно такие шаблоны кладу в тег <script> с специальным типом, а в новом HTML добавили еще тег <template>, который может пригодиться.

> И как их кастомизировать? Может я в див хочу обернуть инпут, или класс добавить?
Изучай компонент форм, и темизацию (документация малополезна, придется код смотреть):

- https://symfony.com/doc/current/form/form_customization.html
- https://symfony.com/doc/current/form/form_themes.html

> По поводу тайпхинтов, а как прописать, чтобы они работали с null? Добавить по дефолту setTask(Task $task = null)?
Да.

> и полетели ошибки при пустом имени, например если создать объект через new и передать в форму.
Если у тебя в модели поле может иметь значение null - геттер должен иметь возможность вернуть null, смотри мануал http://php.net/manual/ru/migration71.new-features.php

Если поле не может быть null - нужно задать значение по умолчанию.

> AccessDeniedException почему-то дает 500 статус.
Надо смотреть код. Симфони генерирует событие KERNEL_EXCEPTION и в ответ на него обработчик должен сгенерировать объект REsponse с нужным кодом.

> Как работать с assetic? Почему-то в главном шаблоне получается подключать файлы через его теги, а во вложенном пишет
> "An exception has been thrown during the rendering of a template ("Unable to generate a URL for the named route "_assetic_2e1bfbf_0" as such route does not exist.")."

Боюсь, нужно смотреть исходный код тега в бандле assetic.

> В дев-режиме их типа отдают контроллеры симфони. Вроде так?
Да

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

> Как сделать свой валидатор со сложной логикой?
Придется изучать компонент Validator, там есть такая статья: https://symfony.com/doc/current/validation/custom_constraint.html

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

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

> К тому же важно чтобы сообщения моего валидатора транслировались именно в форму, чтобы под определенным
> вопросом вывелась ошибка о том что у него должно быть не меньше 2 вариантов ответа
Нужно возвращать ошибку валидации стандартным способом через $this->context->buildViolation()

> Там еще какой-то ад с формами ответа, когда приходит несколько ответов (при чекбоксах), смотри
AttemptService::populateAndPersistAnswers
Может быть там стоит создать 2 разных типа форм, для формы с единичным и множественным ответаим? При этом ты можешь использовать один Builder для них, просто добавить в нем параметр, задающий множественность ответов. И в зависимости от этого параметра в buildForm() что-то менять.

> Кстати по поводу автоматизированного тестирования, этот проект наглядно показывает зачем они нужны.
Если ты поддерживаешь 2 разных БД, то тесты точно нужны, так как иначе ты замучаешься вручную каждую фичу проверять по 2 раза. А если не проверять - будет ломаться.

> Как в постгрес создать бд для тестов в памяти, как в mysql?
Судя по гуглу, никак, единственный вариант - создать файловую систему tmpfs (это как RAM диск), и создать базу на ней. Постгрес конечно не знает, что это память, потому работать будет не так идеально, но быстрее чем с диском. Насчет mysql - будь осторожен, таблицы типа MEMORY могут иметь отличия от InnoDB, например, есть ли там внешние ключи и транзакции?

in-memory режим есть у sqlite кстати.

> Ну или хотя бы просто создать бд из консоли.
есть запрос https://www.postgresql.org/docs/9.1/static/sql-createdatabase.html который можно выполнить в консоли и есть команда https://www.postgresql.org/docs/9.1/static/app-createdb.html

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

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

https://dba.stackexchange.com/questions/33285/granting-a-user-account-permission-to-create-databases-in-postgresql/33291#33291

> The "ConsoleEvents::EXCEPTION" event is deprecated since Symfony 3.3 and will be removed in 4.0. Listen to the "ConsoleEvents::ERROR" event instead: 3x
Может где-то что-то старое установлено? надо будет composer.lock изучить. Я бы погуглил текст ошибки, а также посмотрел список issues в симфони на гитхабе, не ты один это видишь.

> Я вроде никаких ConsoleEvents не трогал, там приблизительно такой код:
Application наверно и использует эти events.

> Нужно проверять именно на 200 статус? Часто ли на практике встречаются другие 2xx статусы?
в REST API бывает 201 Created, но ты должен проверять тот статус, который ожидаешь, то есть 200.

> Просто в других примерах чаще используют response->isSuccessful().
В приципе тоже можно. Вообще, есть мнение, что в UI тестах лучше избегать того, что пользователь не видит - например, проверки HTTP заголовков, а проверять то, что видит ползователь. Но конечно код ошибки слишком удобная вещь, чтобы от него отказываться.
https://github.com/pricklynut/testhub Аноним 29/08/17 Втр 03:11:48 #776 №1053068 
>>1049105
>>1051679

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

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

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

Один из вариантов, которые мне известны - добавлять или использовать микроразметку, которая указывает на нужные элементы и сохраняется при правках верстки - например, классы с префиксом test- (которые должны использоваться только для тестов, не использоваться в CSS/JS), data-атрибуты. При желании такую разметку можно вырезать на продакшене. Также, есть стандартные виды микроразметки для некоторых сущностей, которые тебя скорее всего попросят сделать ради SEO оптимизации, можно использовать их:

- https://yandex.ru/support/webmaster/schema-org/what-is-schema-org.html
- https://yandex.ru/support/webmaster/microformats/what-is-microformat.html

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

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

- https://habrahabr.ru/company/yandex/blog/200968/
- https://habrahabr.ru/company/2gis/blog/246831/

Эти блоги очень интересные, так как про GUI тестирование информации в сети в принципе мало.

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

Еще у меня есть такая идея - преобразовывать DOM в формат, в котором страница представлена как набор элементов, у которых есть текст и координаты. И проверять, что под заголовком с таким-то текстом есть абзац с таким-то текстом.

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

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

Есть еще паттерн Page Object - это объект, который инкапсулирует поиск элементов на странице. При смене верстки ты только обновляешь Page Object (внезапно, этот паттерн тоже описан у Фаулера, какой он умный: https://martinfowler.com/bliki/PageObject.html ). Для каждой страницы сайта - свой Page Object:

- https://habrahabr.ru/company/yandex/blog/158787/

Page Object мне напоминают MVC, когда мы отделяем вывод данных в View, только тут мы выделяем ввод данных со страницы, а не вывод.

Я также попробовал гуглить "habr gui тестирование", "ui tests stability".

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

Вообще, веб еще относительно легко тестировать - есть HTML, DOM, есть эмуляторы и headless browsers, есть стандарты, а ты попробуй-ка протестируй десктопное или мобильное нативное приложение!

Если хороший сценарий тестирования придумать трудно, написание тестов трудоемко, можно уменьшить объем и упростить GUI тесты, компенсируя это более тщательными тестами сервисов (из соображений отношения затрат/выгоды). Вот статья Фаулера с пирамидой тестов: https://martinfowler.com/bliki/TestPyramid.html

Вот статья гугла: https://testing.googleblog.com/2015/04/just-say-no-to-more-end-to-end-tests.html

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

Но конечно GUI тесты нужны, особенно тесты различных flow - зайти на эту страницу, нажать кнопку, перейти на другую страницу, увидеть текст.

Насчет тестов, ты не хочешь подключить CI сервис, чтобы он автоматически прогонял тесты при каждом коммите? Вот есть список сервисов, не все бесплатные конечно:

- https://github.com/marketplace/category/continuous-integration
- https://github.com/ligurio/Continuous-Integration-services/blob/master/continuous-integration-services-list.md

Я у себя подключал Travis CI тут, правда пришлось немного помучаться, чтобы уведомления и расылки по email отключить: https://github.com/codedokode/task-checker/blob/master/.travis.yml

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

> В составе symfony standard edition идет в комплекте некий simple-phpunit.
> Что это за зверь и в чем его особенности?
Тут описаны отличия https://symfony.com/doc/current/components/phpunit_bridge.html вроде бы он идет как отдельный скрипт, не конфликтующий и не мешающий использованию phpunit. Он просто интегрирован с Симфони чуть плотнее. Можешь его использовать, если хочешь.

> Ну например я phpstorm под него не могу настроить, чтобы тесты запускались
из ide, пишет Class 'PHPUnit_TextUI_ResultPrinter' not found.
Это у тебя что-то криво настроено, проверь настройки своей IDE, что она запускает именно нужный скрипт, а не команду phpunit.

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

Если что-то непонятно - спрашивай.

Код пока не смотрел, позже посмотрю.

Аноним 29/08/17 Втр 03:38:47 #777 №1053069 
>>1049105

> Что такое настройка by_reference=false у коллекции? Что она делает?
Нужно смотреть код класса CollectionType в symfony/form.

Там есть описание в документации, но оно не очень понятное http://symfony.com/doc/current/reference/forms/types/collection.html#by-reference

Лучше изучить код.
https://github.com/telepok/php-test/blob/master/oop4.php Аноним 02/09/17 Суб 16:05:43 #778 №1056159 
>>1050039

> public function addDepartment($department)
Тут нужен тайп-хинт

> Получилось много методов вида getFoo и setFoo, может имеет смысл заменить на один метод Get и Set с параметрами?
Нет, не имеет, это только сохздаст путаницу. Есть в общем-то 2 варианта, как делать:

- публично доступные свойства
- приватные свойства + сеттеры/геттеры

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

> array_splice($this->employees, array_search($employee, $this->employees), 1);
Тут нет проверки, что сотрудник найден. array_search может вернуть false, и ты просто удалишь другого сотрудника.

> $employee->getiSBoss()
Было бы красивее конечно isBoss(). Но тогда придется свойство назвать boss.

Если объекта нет, обычно возвращают null, который традиционно обозначает отсутствие объекта.

> class Employee
> //Сотрудник владеет полной информацией о себе
Комментарий нужно писать надо словом class, а не под

> $this->isBoss = 1;
Вот тут как раз стоило использовать true/false.

> public function getCoffee()
> public function setCoffee($coffee)
Здесь не очень удачно названы функции, так как они задают и возвращают разные значения. Одна - базовое потребление кофе, другая - итоговое.

Профессии следовало бы обозначить константами (Employee::ROLE_MANAGER), если ты хочешь для них делать проверки в коде (например, проверка, является ли сотрудник менеджером). Так как "Менеджер" - это лишь представление профессии для вывода (оно нужно только при выводе данных и не нужно при расчетах). А у тебя есть сравнения вроде if ($profession == "Аналитик"). Использовать тут строки плохо, так как там легко опечататься или что-то перепутать, плюс неясно, какие вообще варианты профессий есть. Плюс при смене языка или написания придется лазать менять названия по всей программе, а не в одном месте. Константы с цифрами или латинскими идентификаторами лишены этих недостатков. Заодно, IDE умеет делать автодополнение при наборе константы.

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

Антикризисные функции надо сделать в классе (или классах). У нас же задача на ООП.

В функциях optimize1, optimize2 есть много похожего кода. Часть этого кода можно вынести в отдельные методы, а не копипастить. Ну например, поиск работников по критериям - чем не метод? Или замена босса - почему не сделать метод для этого?

При этом важно, чтобы методы в Сотруднике, Компании или Департаменте относились к этим сущностям и могли пригодиться где-то еще, а не занимающиеся только антикризисными мерами. Метод заменитьБосса - ок, метод уволитьNпроцентовИнженеров - не ок.

> $selectedEmployees[$i]->setRank($selectedEmployees[$i]->getRank() + 1);
Слишком длинно и тяжело читается, нужно что-то вынести в переменную (например, employee).

Вместо очистки компании лучше было бы сделать метод для ее клонирования. Изучи оператор clone.
Аноним 02/09/17 Суб 17:26:25 #779 №1056189 
>>1048771

Да, PHP написан на Си, исходники открыты. Вот пример функции сортировки: https://github.com/php/php-src/blob/master/ext/standard/array.c#L922

>>1048584

Тебе надо разобраться с библиотекой, я не видел код, но предполагаю, что long - это численное представление IP-адреса. Ну то есть число, которое получается, если взять 4 байта из IP адреса и представить как число.

Сторонние библиотеки лучше ставить через композер, на худой конец вручную в отдельную папку вне codeigniter. Подключать через автозагрузку или реквайрами.

Ну и справедливости ради, для преобразования IP сложный ООП не нужен, хватит статической функции.

>>1048364

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

>>1048278

В чем выгода? Для цен иногда используют числа с фиксированной запятой (DECIMAL в БД).

>>1046988

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

>>1046810

Обычно используют Sublime, Atom, Brackets, Notepad++, Netbeans, Eclipse PDT, PhpStorm.
Аноним 02/09/17 Суб 17:42:39 #780 №1056197 
Напомню, что новый тред тут >>1049651 (OP) . Здесь только ответы на старые вопросы.

>>1045048

Надо сохранять эти данные на клиенте и передавать вместе со следующим запросом.
comments powered by Disqus

Отзывы и предложения