Двач.hk не отвечает.
Вы видите копию треда, сохраненную 21 декабря 2016 года.

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

Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
33 Кб, 500x500
157 Кб, 1024x683
188 Кб, 853x480
181 Кб, 500x676
Клуб изучающих PHP #83 #880700 В конец треда | Веб
Добро пожаловать в наш уютный тред. Тут мы изучаем язык PHP (а также JS/CSS/HTML/SQL), решаем задачки и даже делаем простые сайты! Зачем? Кто-то хочет научиться программировать, кто-то - делать сайты, кто-то - просто размять мозги и заняться чем-то полезным.

Это не чат! Высказывайтесь одним большим постом, а не цепочкой мелких

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

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

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

Мейруч лежит? Есть запасной тред: http://dobrochan.org/s/res/23225.xhtml#i46467

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

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

У нас есть уроки по основам PHP, они собраны и выложены по адресу http://archive-ipq-co.narod.ru/ Это учебник для изучающих с нуля, то есть если ты вообще ничего не знаешь, то надо начать с него. Он простой и понятный (по крайней мере в начале). Там есть задачи, их надо решать обязательно (чтобы стать программистом, надо писать код — иначе никак). Пости ссылки на решения в тред, мы их проверим, напишем замечания и дадим советы по улучшению.

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

Ты прошел весь учебник? Молодец, но это были лишь основы языка PHP, этого недостаточно. Вот что в идеале надо изучить еще: ООП, как работает веб-сервер, HTML/CSS, SQL, PDO, работа с таблицами в БД, работа с формами, MVC, git, composer, JS, фреймворки, автоматизированное тестирование.

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

- для начала прочти урок https://github.com/codedokode/pasta/blob/master/soft/web-server.md
- установи Апач + PHP (советы выше и ниже) и читай туториал http://php.net/manual/ru/tutorial.php
- Учи HTML/CSS и SQL, PDO, хотя бы основы
- Далее простая, но полезная задача сделать список студентов, в ней много полезных советов: https://github.com/codedokode/pasta/blob/master/student-list.md
- Более сложная задача сделать файлообменник на микрофреймворке Slim: https://gist.github.com/codedokode/9424217
- Еще более сложная и долгая задача на Yii/Symfony: https://gist.github.com/codedokode/8733007
- После нее можно изучать автоматизированное тестирование https://gist.github.com/codedokode/a455bde7d0748c0a351a
- Если ты все решил, переходи к Symfony 2/Doctrine 2
- Почитать про паттерны http://designpatternsphp.readthedocs.org/ru/latest/README.html (если ты не изучил ни одного фреймворка, то это будет рановато), тут с примерами кода http://designpatternsphp.readthedocs.org/ru/latest/README.html . Имей в виду что без примеров использования их учить бесполезно - не поймешь, хочешь увидеть примеры использования паттернов - ковыряй исходники Симфони, например Symfony Forms. Не заучивай паттерны - смотри код и думай, зачем тут они использованы.

Чтобы делать эти задания, тебе надо установить Апач + PHP (можно заодно сразу и MySQL) на компьютер. Вот полезные инструкции:

https://github.com/codedokode/pasta/blob/master/soft/php-install.md
https://github.com/codedokode/pasta/blob/master/soft/apache-install.md

Может тебе понадобится пользоваться командной строкой, вот гайд https://github.com/codedokode/pasta/blob/master/soft/cli.md

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

Также, у нас есть задачи которые позволят тебе изучить или подтянуть до нормального уровня знания JS/HTML/CSS/SQL. Решай их параллельно с задачами выше.

- HTML/CSS: https://github.com/codedokode/pasta/blob/master/html/html.md
- JS: https://gist.github.com/codedokode/ce30e7a036f18f416ae0
- SPA (сложно): https://github.com/codedokode/pasta/blob/master/js/spa.md
- Проверялка решений на JS: http://dkab.github.io/jasmine-tests/
- MySQL: https://github.com/codedokode/pasta/blob/master/db/databases.md

Что почитать

- Мануал по PHP — http://www.php.net/manual/ru/langref.php
- Сайт phptherightway (перевод на русский: http://getjump.me/ru-php-the-right-way/ )
- По PHP: Профессиональное программирование на PHP Джордж Шлосснейгл
- По PHP: Мэтт Зандстра — PHP: Объекты, шаблоны, методики программирования
- JS: learn.javascript.ru
- Про Git: https://git-scm.com/book/ru/v1

Оформляй код аккуратно!!! — например пропусти через phpformatter.com . Также, если ты пользуешься IDE вроде PhpStorm, Netbeans, Eclipse, то в них эта опция встроена, подробнее: https://gist.github.com/codedokode/8759492

Платиновые вопросы

- Почему PHP? Потому что фейсбук и википедия на нем написаны, и вакансий море, и учить легко.
- Сайт опять упал!!!!! — Не паникуй, а открой http://rghost.ru/6bfCY9lfl и получи личную немного устаревшую оффлайновую копию сайта (можно читать хоть на андроиде без интернета)
- Что надо знать чтобы найти работу - разработчику: PHP, SQL, HTML/CSS, JS, ООП, Git, композер, MVC, фреймворк. Верстальщику - HTML/CSS, JS, jQuery
- Сколько времени надо изучать все это? - все зависит от тебя, но не меньше 6-8 месяцев
- Посоветуйте редактор кода - Sublime Text 3, Notepad++, PhpStorm
- Нужен ли ООП, фреймворки, MVC, git, composer? — Да, однозначно. Посмотри любую вакансию.
- Что самое главное для программиста? Умение аккуратно оформлять код.
- ОП, сделай за меня мою работу или домашнее задание? — Это конечно, хорошая идея, но нет.
- Подскажи сайты для поиска работы, я не умею гуглить? — hh.ru, geekjob.ru, moikrug.ru (склеен с brainstorage.me), fl.ru, upwork.com (бывший одеск). Имей в виду, что кроме фриланса есть еще постоянная удаленная работа (remote job) когда тебе не надо тратить время на поиск заказов и переговоры с неадекватными заказчиками.
56 Кб, 500x644
Прочитай #2 #880701
Код нужно писать не как попало, а аккуратно и по правилам. Почему? Потому, что на неакуратно написанный код не хочется даже смотреть.

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

Горячие клавиши для форматирования кода в разных IDE: https://gist.github.com/codedokode/8759492

Вообще, в PHP долгое время не было единого стандарта оформления кода, все писали как попало и было много бардака, но сейчас дело лучше — есть стандарты PSR-1 и 2. Вот как надо оформлять код:

- переменные и функции пишутся с маленькой буквы, подчеркивание не используется, используется camelCase, пример: $x, $numberOfPeople, printResults()
- Название функции начинается с глагола, в стиле «сделайЧтоТо»
- не знаешь английский? Не беда, в 21 веке есть решение этой проблемы. Не пиши транслитом, открой лучше Гугл Транслейт или slovari.yandex.ru и найди название для переменной там
- в именах классов используется CamelCase, первая буква большая, «_» может использоваться
- мы предпочитаем подстановку переменных вместо конкатенации строк: "I am $age years old" — хорошо, 'I am ' . $age . ' years old' — плохо из-за обилия точек и кавычек
- мы используем для отступов 4 пробела (можно настроить редактор, чтобы при нажатии Tab он вставлял 4 пробела)

Вот ссылка на стандарты, где все это описано подробнее и даны примеры оформления:

PSR-1: https://github.com/samdark/fig-standards-ru/blob/master/accepted/ru/PSR-1-basic-coding-standard.md
PSR-2: https://github.com/samdark/fig-standards-ru/blob/master/accepted/ru/PSR-2-coding-style-guide.md

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

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

Давай удочку, а не рыбу

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

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

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

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

Объясняй

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

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

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

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

Ах да. Если тебе кажется, что что-то в учебнике или задачах можно сделать лучше — пиши, обратная связь всегда очень полезна.
56 Кб, 500x644
Прочитай #2 #880701
Код нужно писать не как попало, а аккуратно и по правилам. Почему? Потому, что на неакуратно написанный код не хочется даже смотреть.

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

Горячие клавиши для форматирования кода в разных IDE: https://gist.github.com/codedokode/8759492

Вообще, в PHP долгое время не было единого стандарта оформления кода, все писали как попало и было много бардака, но сейчас дело лучше — есть стандарты PSR-1 и 2. Вот как надо оформлять код:

- переменные и функции пишутся с маленькой буквы, подчеркивание не используется, используется camelCase, пример: $x, $numberOfPeople, printResults()
- Название функции начинается с глагола, в стиле «сделайЧтоТо»
- не знаешь английский? Не беда, в 21 веке есть решение этой проблемы. Не пиши транслитом, открой лучше Гугл Транслейт или slovari.yandex.ru и найди название для переменной там
- в именах классов используется CamelCase, первая буква большая, «_» может использоваться
- мы предпочитаем подстановку переменных вместо конкатенации строк: "I am $age years old" — хорошо, 'I am ' . $age . ' years old' — плохо из-за обилия точек и кавычек
- мы используем для отступов 4 пробела (можно настроить редактор, чтобы при нажатии Tab он вставлял 4 пробела)

Вот ссылка на стандарты, где все это описано подробнее и даны примеры оформления:

PSR-1: https://github.com/samdark/fig-standards-ru/blob/master/accepted/ru/PSR-1-basic-coding-standard.md
PSR-2: https://github.com/samdark/fig-standards-ru/blob/master/accepted/ru/PSR-2-coding-style-guide.md

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

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

Давай удочку, а не рыбу

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

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

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

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

Объясняй

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

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

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

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

Ах да. Если тебе кажется, что что-то в учебнике или задачах можно сделать лучше — пиши, обратная связь всегда очень полезна.
#3 #880716
Проверил в старом треде:

https://github.com/TheSidSpears/Students >>880707
#4 #880735
Подскажите как можно в пхп сгенерировать массив из последовательных дат?

Например как примерно выглядит функция, которой я кормлю
скажем

$a = some_func('2016-09-28, '2016-11-23');

и в а в итоге лежал последовательный массив вида:
[
'2016-09-28',
'2016-09-29',
'2016-09-30',
'2016-10-01',
'2016-10-02',
...
'2016-10-30',
'2016-10-31',
'2016-11-01',
'2016-11-02',
...
'2016-11-22',
'2016-11-23'
]

может быть есть уже какое-то готовое решение в самой пхп? Нужно для построения графиков в общем, что бы потом к к каждому элементу с датой какую-то инфу добовлять.
>>880744>>880752
#5 #880744
>>880735
Если тебе нужен именно массив и дата окончания включительно, то вряд ли получится что-то короче этого: http://ideone.com/GtvENn

А так хватит следущих строк:
$period = new DatePeriod(
____new DateTime($from),
____new DateInterval('P1D'),
____new DateTime($to)
);
>>880873
#6 #880752
>>880735

Взять timestamp первого дня и прибавлять по 24 * 3600.
>>880873
#7 #880795
Подскажите где поискать готовые проекты на yii2 с исходниками?
На русскоязычном форуме чет не густо.
>>880845
#8 #880845
>>880795
У Макарова на гитхабе (samdark)
#9 #880873
>>880744
>>880752
Спасибо ребят, уже сам залез в самые дебри мануала куда не ступала нога современных школьников и прокурил DateTime класс в php
#10 #880900
Сап зекач, студент 3 курсник. Сам вкатываюсь в JEE, нравится. Тут недавно приходили работодатели в универ и приглашали писать на magento, что за говно и стоит ли бросать, то что нравится, только для того что бы сейчас начать работать ?
>>895687
Курсы #11 #880980
У меня есть возможность пойти на курсы PHP, или выучить его самостоятельно. Что лучше?Сейчас заканчиваю курсы Html, а после них куда пойти?
>>883228
#12 #881329
Аноны, если вы понимаете английский, можете поиграть в игру по поиску XSS от Гугл. Ничего устанавливать не надо, все в браузере: https://xss-game.appspot.com/

Если вы не знаете, что такое XSS, у меня есть урок по ней: https://github.com/codedokode/pasta/blob/master/security/xss.md

Ну и разумеется, вам надо знать основы HTML и JS (из JS нужна функция alert).
#13 #881470
https://github.com/codedokode/pasta/blob/master/html/html.md#Главное-задание-на-верстку-макета

Размеры макета конечны?
Шапка высотой 200px на экране с большим разрешением -- смех, а буквы не читаются: как исправить?

Возможно ли проставить высоту в% без потери возможности скроллить вниз?

Если возможно - пару комментариев

>не используй <a href="#" или <a href="javascript:void(0)" никогда. Для этого есть кнопки или <span>

>>885044
#14 #881635
Добрый вечер. Знаком с программированием аж 20 минут. И назрел вопрос
if(a1==a2 && a3==a4)

if(a1==a2)&&(a3=0a4)

Как правильней и как грамотней?
#15 #881640
>>881635
да, я один из тех, которые не дочитали второй пост. Сорян, ухожу из программирования
45 Кб, 1360x607
#16 #881676
>>880411
А как мне это поможет?
>>885072
#17 #881710
Помогите с циклами, ребята.
<?php
error_reporting(-1);

for ($i = 1; $i<=10; $i++) {
$b =$i$i;
echo "$i
$i = $b \n";

}
Вот данный код, возводит каждое следующее число в квадрат. До 10 включительно.
Но как сделать так, чтобы цикл работал до того момента, пока результат квадрата числа меньше 1000 например.
#18 #881715
>>881710
задай условие типа если результат равен н выход или же пока н меньше условия сорян в синтаксе пхп не очень как именно не могу точно написать
>>881718
#19 #881716
>>881710
там еще знак умножения между $i*$i
#20 #881718
>>881715
а это где записывать ? На русском объясни, хз)Спасибо
>>881721
#21 #881721
>>881718
Все, понял .Спасибо огромное
#22 #881722
Тогда другой вопрос, товарищи.
<?php
error_reporting(-1);

for ($i = 1; $b<10; $i++) {
$b =$i$i;
echo "$i
$i = $b \n";

}
Вот результат этого :
Успешноtime: 0.01 memory: 52488 signal:0
11 = 1
2
2 = 4
33 = 9
4
4 = 16
.
А как сделать так, чтобы на 9 заканчивался цикл? Понять не могут ? В принципе, логика понятно, почему 16 получается . 33 = 9;, проверяется это условие , потом выполняется действие и выводится 16. А как сделать так, чтоб на 33 цикл заканчивался ?
Сори за спам
>>881724>>885072
#23 #881724
>>881722
дак задай конкретное условие
если известен результат то укажи в условии
если нет то сделай типа пока b!=i
хз че первое в голову пришло
#24 #881760
>>880700 (OP)
http://ideone.com/MkzJXE
как оформил? еле заставил прибавить к сабстр
>>885072
#25 #881820
>>881635
Правильней if (($a1 === $a2) && ($a3 === $a4)) (если тебе нужно зачем-то сравнивать с автоприведением типов, то используй ===)
Ну а совсем правильно будет книжки читать.
>>881821
#26 #881821
>>881820
...если не нужно сравнивать с автоприведением...
самофикс
#27 #881835
возьмите кто-нибудь 30летнюю пхп макаку без образования, опыта, знания матана и алгоритмов в ДСаъх за еду.
._.
>>885072
#28 #881873
Наткнулся в статье ( https://m.habrahabr.ru/company/badoo/blog/316050/ ) на скриншот: https://habrastorage.org/files/4a5/5fc/929/4a55fc9297e14722bc9508f0fa1c8fda.png

А вы бы обратили внимание на чебокс, старательно замаскированный под серую галочку? Это же прекрасно. Впрочем, что еще ждать от убогой устаревшей системы платежей с технологиями транзисторной эры, которая позволяет такие трюки. Я бы никогда не стал платить настоящей картой в интернете.
>>881926
279 Кб, 589x678
#29 #881926
>>881873
Вот пидорасы.

Хотя, пользователям-социоблядкам с баду и прочих параш, тащемта, так и надо.
#30 #882063
Добрый вечер. Вопрос по структуре директории хранения изображений, как лучше всего хранить? Есть к примеру товары и есть категория. К примеру 28 миллионов товаров, и 40 категорий. Связь примерно такая: Главная категория -> категория X -> Товар
То-есть хранить в data/categoryX/product_id уже не выйдет из за того что в среднем будет 500к+ товаров в одной категории. Есть так же производители, но неизвестно есть ли приозводитель со 100к+ товаров и будет ли в будущем.
#31 #882142
>>882063
Ну то-есть я не прошу за меня придумать это, у меня есть пару идей к примеру: "категория > производитель > [0] > photo.png" по достижению первой директории лимита ( к примеру 1к фото ) создавать вторую и заливать туда.
Просто может есть какие то паттерны общепринятые или идеи, я конечно поискал, но ничего занимательного не нашел.
#32 #882163
>>882063

1) делать папки по дате загрузки
2) делать папки по первым цифрам id товара, например id 12345678 -> 123/123456/12345678.png. Тут правда надо помнить, что мы обязаны сохранять картинку до записи информации в базу и придется изворачиваться с транзакциями, чтобы это обеспечить.
#33 #882165
>>882063

Или 123/123456/12345678-телевизор-самсунг.jpg если ты хочешь читабельные имена которые возможно улучшат позицию в поиске по картинкам.
361 Кб, 1024x772
#34 #882285
>>880700 (OP)
Антоши, элементарный для вас, знатоков, вопрос: как красиво вывести данные из БД в html в виде таблицы, чтоб без <tr><td>? Без шаблонизаторов специальных не обойтись?
>>882288>>882290
#35 #882288
>>882285
Без <tr><td> непосредственно в коде php, естественно.
>>882290
#36 #882290
>>882285
>>882288
Ты хочешь разделить HTML разметку и PHP код? Хорошая мысль, для этого можно использовать шаблонизатор вроде Twig. Если не хочешь, можно использовать сам PHP, он имеет встроенный шаблонизатор. Почитай советы в пасте про список студентов из ОП-поста, там были ссылки на статьи в которых объяснялось как это работает.
>>882323>>882645
facebook api ACCESS TOKEN #37 #882320
Сап аноны, кто работал с апи фейсбука? хочу получить токен на доступ, постоянный токен, не тестовый, чтоб мне не приходилось его вводить каждый день. долго гуглил ( на самом деле не пойму почему такая простая вещь столь не доступна)
нашел этот сайт https://smashballoon.com/custom-facebook-feed/access-token/ который как бы поясняет как его получить и в конце статьи показывает его ( что мне показалось сомнительным). Получил , значит, этот токен доступа, вставил в положенное место и в итоге получил такое сообщение
"An active access token must be used to query information about the current user."
в общем реквестую помощь. Как справиться с этим говном, как мне без жопоболи работать с этим приложением?
По аналогии с тестовыми токенами все нормально работает, только вот их каждый день нужно новые постить
>>895687
#38 #882323
>>882290
Спасибо, анончик. Изучаю.
#39 #882344
Оффтоп, душу излить

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

Теперь вот задумываюсь над тем, чтобы начать искать работу сейчас или после НГ. Задачи на студентов и файлхостинг у меня сделаны на хорошем уровне. На тестхаб, видимо, придётся забить. Надо подтянуть CSS, JS, подготовиться к вопросам собеседований и вперёд
>>882361
#40 #882361
>>882344

> Задачи на студентов и файлхостинг у меня сделаны на хорошем уровне.


Покажешь?
>>882378
#41 #882369
Напомню себе проверить https://github.com/TheSidSpears/FileHosting отсюда >>866133
#42 #882378
>>882361
https://github.com/TheSidSpears/

http://dkab.github.io/jasmine-tests/?spec=4
Чёт сложно

> Возвращаемая функция должна принимать любое количество аргументов и передавать их функции fn



Это как можно сделать?
>>882408
#43 #882390
Решаю задачки с оп-поста. Не могу раздуплить о кредитах

Школьник решил купить айфон и для этой цели взял кредит. Сумма кредита — 40000 р., банк в начале каждого месяца (включая первый) начисляет 3% от остатка долга за пользование кредитом и 1000 р. комиссии (да, а ты думал, обойдешься процентами?). После этого, в конце каждого месяца, наш герой идет в банк и пытается выплатить долг, но он не может заплатить более 5000 р за раз (сэкономленных на школьных завтраках). Вопрос, когда он избавится от долга? Во сколько школьнику обошелся айфон?

<?php

error_reporting(-1);

$creditBalance = 4000; / Долг анона перед банком /
$percent = 1.03; / Банк начисляет 3% в месяц от суммы /
$servicePayment = 1000; / А также 1000 рублей в месяц комиссии за обслуживание счета /
$monthlyPayment = 5000; / Анон платит 5000 р в месяц, это все, что ему дает мама на завтраки /
$paymentTotal = 0; / Сколько всего отдал банку анон /

/ Посчитаем расходы 20 раз на 20 месяцев вперед /
for ($month = 1; $month <= 20; $month ++) {
$creditBalance = ( $creditBalance $percent ) + $servicePayment - $monthlyPayment;
$paymentTotal = ($paymentTotal + $monthlyPayment)+$creditBalance;
echo "{$month} месяц спустя: долг = {$creditBalance} руб, выплачено всего {$paymentTotal} руб. \n";

/
Если баланс отрицательный — хватит считать */
if ($creditBalance < 5000) {
echo "С меня хватит!\n";
break;
}
}
>>882411>>882420
#44 #882404
>>880700 (OP)
Вы пока выучите пыхапы, он устареет окончательно и исчезнет с рынка.
>>882410
#45 #882407
Проверил студентов https://github.com/anotherCodeMunkey/studentsList отсюда >>867331 , комментарии: >>882403 >>882405
#46 #882408
>>882378

Функция в JS это объект. И у него есть полезные методы: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Function/prototype

Поищи там.
>>882964
#47 #882410
>>882404
Я это слышу с 2002 года.
#48 #882411
>>882390
Код в тред не кидай. Читай внимательнее оппост и задачник, там всё расписано для новичков. Или посмотри как местные код кидают хоть.
#49 #882420
>>882390

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

Чтобы не уходить в минус, надо перед тем как платить, посмотреть, какая сумма долга, если маленькая, то платить не 5000, а сколько осталось.
>>882477
51 Кб, 660x495
Satosi #50 #882445
Сап тред. Пробую с переменным успехов вкатиться в MVC (Отчасти поэтому не постил тут недели 2).
Пока изучал не по ОП мануалам, но блииин.
Какой-же MVC сложный. Просто ужос. Я не могу понять буквально ничего. Ну то-есть я понимаю как всё работает, как всё теоретически устроено, но как например прикрутить сбор данных из БД - это для меня загадка, прикрутить новый функционал - тоже. Вообще не понимаю как происходит наследование в некоторых случаях. Не могу понять как происходит передача данных по структуре от POST.
Антоны, я последню неделю я только и делал что ковырял всякие MVC по мануалам с сайтов и ютюбов, но я уже просто отчаялся.
Неужели я просто тупой и не судьба мне в программирование?
#51 #882451
>>882445
Не ссы, продолжай учить, пока осознание не придёт само.
#52 #882477
>>882420
вот примерно до этого я дошел, но не знаю как выразить оплату только остачи. гуглил, но по теме не нашел
>>882480
#53 #882480
>>882477

>перед тем как платить, посмотреть, какая сумма долга, если маленькая, то платить не 5000, а сколько осталось.

>>882500
#54 #882500
>>882480
вот это я и не понимаю.
додумался до такого костыля, но он не работает
if ($creditBalance < 0) {
$paymentTotal = $paymentTotal + $creditBalance;
$creditBalance = 0;
echo "С меня хватит!\n";
break;
>>882502
#55 #882502
>>882500
Анон, хватит постить код.
http://ideone.com/
Суй туда, сюда только ссылки.
>>882515
#56 #882515
>>882502
http://ideone.com/SahU06
костыль заработал, но проблема с 13м месяцем
>>895687
#57 #882588
Собираюсь заниматься версткой, нужно ли мне знать php?
И совсем не в том местеспрашиваю, но сколько времени займет путь от "полный 0" до создание сайта по шаблонам?
>>882609>>882610
#58 #882609
>>882588
чисто для вёрстки - нет. для создания возможности общения между клиентом и сервером - да.
#60 #882619
Привет ребята, начал осваивать php и решил свой старый сайт перенести на php. Начал все делать по модулям, но столкнулся с такой проблемой в модуле "header" ( меню сайта ) как не удивительно есть гиперссылки. Вопрос, нужно создавать каждую страницу заново? Или можно как-то с помощью хитроумного кода менять содержимое основной страницы.
>>895687
35 Кб, 530x300
#61 #882645
>>882290
Итак, нихуя я и не нашёл как вывести таблицу без смешивания кода html с php. Придётся хуячить по воробьям с ионной пушки.
>>882669>>895687
#62 #882653
Для чего указывается префикс @ перед обращением к переменной?
Например,
@$array[z]=round($array[x]/$array[y]);
>>882691
#63 #882669
>>882645

> как вывести таблицу без смешивания кода html с php.


<td>{$data}</td>
Не?
>>882673>>895687
#64 #882673
>>882669
До такого и я додумался, а как со строками быть? Предполагается, что количество строк динамическое.
>>882686>>882691
#65 #882686
>>882673
Что такое строки? Я тебя не понимаю?
>>882690
#66 #882690
>>882686
HTML-таблица состоит из тегов <tr>, строк таблицы, и <td>, колонок таблицы. Есть двумерный массив, которым эту таблицу нужно заполнить. Предполагается, что массив расширяемый.
Как создать таблицу, не выводя тегов в php, а используя шаблон максимально эффективно? Или таблица в хтмл - это настолько рудиментарное говно, что даже и пытаться не стоит?
>>882692>>882696
#67 #882691
>>882445

Почему бы не почитать мануал ОПа? https://github.com/codedokode/pasta/blob/master/arch/mvc.md

>>882653

Мануал: http://php.net/manual/ru/language.operators.errorcontrol.php

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

>>882673

Прочитай http://www.phpinfo.su/articles/practice/shablony_v_php.html
#68 #882692
>>882690
Как-то так.
<table>
<?php for($i=0;$i<$colls;$i++){?>
<tr><td>{$data}</td><td>{$data2}</td><td>{$data3}</td>
</tr>
<?php } ?>
</table>
>>882694
#69 #882694
>>882695
#70 #882695
>>882694
Насколько я понял вопрос, у него не та ситуация, когда шаблоны можно было-бы применить.
>>882701
29 Кб, 400x600
#71 #882696
>>882690
Таки кошерно.
Премного благодарю. До сих пор плохо понимаю что в альтернативном синтаксисе писать можно, а что нельзя.
>>882701
#72 #882697
>>882691
Про шаблоны прочёл, иначе вопросов бы не задавал.
>>882700
#73 #882698
>>882445

> Вообще не понимаю как происходит наследование в некоторых случаях.


А какое отношение это имеет к MVC? Наследование изучают в теме про ООП. Если что, в моем учебнике в главе про ООП это немного изучается.

> Не могу понять как происходит передача данных по структуре от POST.


Удобно данные из POST внести в объект-модель и дальше работать с ней. Хотя некоторые предпочитают гонять туда-сюда большие массивы.
>>882704
#74 #882700
>>882697

> используя шаблон максимально эффективно?


Вообще, да
>>882691 - прав конечно. Максимально эффективно только как он посоветовал. С этим не спорю ни разу.
#75 #882701
>>882695

Какие шаблоны нельзя применить? Шаблоны на PHP? Шаблоны на twig? Оба этих варианта решают его проблему.

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

>>882696

МАнуал объясняет http://php.net/manual/ru/control-structures.alternative-syntax.php
>>882703
#76 #882703
>>882701

>Или ты имел в виду какие-то придуманные тобой самодельные шаблоны?


Я имел ввиде что у человека наверное MVC вообще нет.Иначе-бы такие вопросы он не стал задавать.
>>882705
38 Кб, 480x310
Satosi #77 #882704
>>882698

>Удобно данные из POST внести в объект-модель и дальше работать с ней.


Я про то, что POST теряется пока до модели доходит. И не могу понять почему.

>А какое отношение это имеет к MVC?


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

>>882691
Как ни странно времени не было, сейчас уже буду его усиленно учить.
>>885080
#78 #882705
>>882703
Да, mvc там и рядом не валялось. Это простецкая визитка с вау-вау, динамическим выводом прайслиста. Тупо нужно быстрее сделать, но чтобы я это потом ещё мог поддерживать и допиливать туда разные элементы, не дёргая верстальщика по пятнадцать раз в день.
>>882707
#79 #882707
>>882705
Можно сложнее сделать, с div и прочее. Но с таблицей вариант очень хорош тем, что его я тебе накидал за минуту и он работает вообще во всех браузерах одинаково. Даже в IE 4.5!
>>882708
#80 #882708
>>882707
Вот я и говорю, что наикошернейше. Благодарю вас, товарищ.
#81 #882712
Как сохранить файл, загружаемый через
<form>
<input type="file"/>
</form>
на сервере? Пытаюсь сделать по инструкции с w3school
if (move_uploaded_file($_FILES["filename"]["tmp_name"], $target_file))
echo "done";
Но у меня move_uploaded_file ничего не возвращает, ну и файл не появляется, разумеется. В php.ini file_uploads=On.
>>882726>>885086
#82 #882726
>>882712
$target_file
А тут что? Скорее всего в этой переменой проблема.
if (move_uploaded_file($_FILES["filename"]["tmp_name"], $target_file)){
echo "Загрузилось";
}else{
echo "Сообщение об ошибке";
}
>>882727
#83 #882727
>>882726
В $target_file - путь к файлу, который составляется следующим образом:
$target_file="/"."uploads/" . basename($_FILES["filename"]["name"]);
>>882728>>882731
#84 #882728
>>882727
Папка "uploads" лежит в папке с .php файлом, в котором происходят описанные выше действия, да.
>>882731
#85 #882731
>>882728
>>882727
Пиздец, ладно, проехали. Не знаю, что за хуйня творится в вашем PHP, но я заменил значение атрибута name у <input type="file"...> и эта сука заработала. У вас всегда так, или я совсем криворукий уебан?
#86 #882737
Поясните за обращения к свойствам объекта user-defined класса с помощью оператора []? Где то читал, что можно обращаться к свойству объекта подобным образом:
echo $classInstance['propertyName'];
Но именно такой синтаксис у меня не работает. Или для того, чтобы он работал, нужно кастовать объект к массиву, и только потом уже брать значения свойств по ключу-названию свойства?
>>883494>>885086
#87 #882741
Посоны, импортирую csv файл в sql-таблицу, проблема в том, что в одной из строчек в имени есть ', и при запросе естественно пидорасит все, и эта строчка не попадает в базу, как исправить?
>>882746>>885086
#88 #882746
>>882741
mysql_escape_string
#89 #882747
>>882731
В инпуте имя файла должно совпадать с тем. что в пхп-файле.
>>882748
#90 #882748
>>882747
Дак оно и так совпадало. Потом я сменил имя файла в инпуте и в пхп файле, и только тогда заработало. Скорее всего, я еще помимо этого делал какие то мелкие изменения, которые повлияли на результат, но чё то в голове из последних действий отложилось только изменение атрибута name
>>882753
#91 #882753
>>882748
Может имя было ЗАРЕЗЕРВИРОВАНО?
>>882759
#92 #882759
>>882753
да не должно быть. datDB было, FUCKTHAT стало.
41 Кб, 799x462
42 Кб, 797x521
36 Кб, 799x364
#93 #882762
Оцени резюме, анон.

Через какое-то время допишу о знаниях JS и CSS, как доделаю задачки в ОП-посте
#94 #882782
>>882762
А ты на ИБ учился?
>>882809
#95 #882804
>>882762
А почему среднее специальное? В колледже учился?
>>882809
#96 #882809
>>882804
>>882782
Институт у него еще не окончен.
#97 #882957
>>880700 (OP)
буду писать ломатель куков на пхп ^^
пока что только для фейсбука но мы будем расширяться.
#98 #882958
Можно ли убить процесс firedox.exe как в питоне средствами пхп?

#kill firefox
PROCNAME = "firefox.exe"

def kill_firefox():
for proc in psutil.process_iter():
try:
if proc.name() == PROCNAME:
proc.kill()
except:
pass
kill_firefox()
>>885086
3 Кб, 367x122
#99 #882963
Мне всё равно сложно. Я хоть в правильном направлении двигаюсь?
>>882964>>885086
#100 #882964
17 Кб, 468x237
#101 #882978
>>885086
#102 #882999
php-анон, у меня есть один сырой движок говнофорума для обучения погромированию. Так вот, он настолько убогий что не поддерживает создание тематических разделов. Следовательно у меня вопрос: как сделать несколько разделов?
#103 #883035
>>882999
Найди другой движок.
>>883045
#104 #883042
Искал небольшую cms для личного бложика, нашел Pico cms.
О нем пишут, что он работает без использования базы данных.
Отзываются о нем так, например:

>>Pico is another really simply CMS. It doesn't have a backend to edit (there is a plugin to enable that). It doesn't use database queries therefore making it super fast.


>>It doesn't use database queries therefore making it super fast.


Неужели использование базы данных медленне, чем использование файлов?
>>885089
#105 #883045
>>883035

>для обучения погромированию


Жопой читаешь?
#106 #883077
>>882999
Толстота.
#107 #883087
Поясните за пхп7. Понятно, что если и возьмут джуниором чистить вилкой легаси пхп4, но всё же.
>>883089>>885101
#108 #883089
>>883087

>если и возьмут джуниором чистить вилкой легаси пхп4


Тут тебе не Java уже везде где только можно 7 версия, и 7.1 на подходе.
#109 #883101
>>880700 (OP)

>На 2016 год писать на ES5 рановато


Что-то проигрунькал.
>>883102
#110 #883102
>>883101
Тредом ошибся?
>>883103
#111 #883103
>>883102
В мануале по жс из ОП-поста написано.
>>883104
#112 #883104
>>883103
Их есть несколько версий? Срисли? А как же обратная совместимость? Или у JS с этим совсем беда?
>>885101
#113 #883199
http://ideone.com/1Oh1QV echo сервер
>>885101>>885107
#114 #883206
Есть ли в php встроенные агрегатные функции типа avg, count, которые можно было бы использовать на массивах, и при этом ставить ограничение. Например, если в элементы в массиве - экземпляры класса, у которого есть некоторое поле "Х", посчитать сколько у скольких объектов Х больше Y?
#115 #883228
>>880980
Пару месяцев кручусь в веб-разработке. Учил PHP сам, методом проб и ошибок(не было денег на курсы какие-то, да и курсов полноценных в моем мухосранске нету). Так что, если у тебя есть шанс пойти на такие курсы, я рекомендую сделать это. Это в том случае, если ты всерьез хочешь заняться веб-разработкой. Мне, например, сейчас иногда аукается мое самообучение, иногда не в очень хорошую сторону.
#116 #883301
PHP'ч, какую IDE посоветуешь для учёбы/работы? Сейчас использую atom, да да, это и не ИДЕ вовсе, а редактор кода но хотелось бы функционала как на visual studio, ну или максимально приближенного к ней.
#117 #883306
>>883301
Присоединяюсь к вопросу, только мне требуется отладчик и ничего больше.
>>883310
#118 #883310
>>883301
>>883306
NetBeans, Eclipse из бесплатных.
PhpStorm от JetBrains из платных (для студентов бесплатно, при желании можно взять торрент-эдишен).
По поводу отладчика - для PHP это xdebug и необязательно для его использования иметь ИДЕ.
Я всегда пользовался атомом, для него есть пакет php-debug который добавляет функционал отладчика в редактор.
https://atom.io/packages/php-debug
По поводу других редакторов вроде Sublime Text когда-то в треде писали что дополнения тоже существуют.
>>883321>>885107
#119 #883321
>>883310
Благодарю.
194 Кб, 1024x768
#120 #883374
#121 #883410
>>883206

>если в элементы в массиве - экземпляры класса


Это зачем так?
>>885107
#122 #883411
>>883301

>функционала как на visual studio


Там же был бесплатный плагин к ней. По крайней мере в 2011 году. А сейчас все на PHPStorm перекатились. Удобнее ничего не найти.
#123 #883466
Господа, как мне найти первую часть директории, если мне известна только последняя часть ее поддиректории? по всем директориям в папке дуже долго проходить...
#124 #883475
>>883466
никак
#125 #883494
>>882737
Реализуешь интерфейс ArrayAccess для класса: http://php.net/manual/en/class.arrayaccess.php

>>883206
В PHP нет, так как обычно достаточно встроенных функций. Если не достаточно, то есть обёртки-коллекции, предоставляющие как раз нужные тебе методы, пример: https://laravel.com/docs/5.3/collections#method-avg

Но конкретно в твоём случае, если я правильно понял, хватит функций array_filter и count. Вбрось на ideone пример исходного массива и то, что тебе нужно из него получить.

>>883466
http://php.net/manual/en/function.realpath.php
Может это?
Что значит последняя часть поддиректории? Просто вбрось пример.
>>883495
#126 #883495
>>883494
Например, есть такой путь.
C:/Users/Dima/AppData/Mozilla/Firefox/Profiles/kslj498/cookies.sqlite

Я точно знаю, что AppData/Mozilla/Firefox/Profiles и cookies.sqlite должны быть в поддиректории, а другие папки, например Dima и kslj498 находятся динамически. из них строится путь до файла
мне придется все директории и поддиректории в диске С обходить?
>>883621
18 Кб, 215x119
#127 #883499
Привет, анонас.
Есть вопросцы, в юношеском запале клепал магазины на wp и woocommerce, но потом очнулся и понял что это раковник. Вкатился в yii2 (пара успешных крупных проектов и куча опыта) и для своего бизнеса (оптовый портал с 1000+ позиции (раковый webasyst - достался в наследство, от предыдущего хозяина) и розничный(wp+woo)) делаю новый магаз с преферансом и куртизанками. Работают у меня макаки на кассах которые и вордпресс ложили на пол, поэтому неубиваемая трехкнопочная система - это мой выбор. В целом я добрался до отличного результата с rbac, виджетами, но все равно ощущение что что-то забыл. Точнее, что можно больше.

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

Больше мотивационно хочется пообщаться, а то очень иногда грустно одному сидеть в тоске.
>>895687
#128 #883563
В чём разница между :: и -> ? Что делает эта строчка:

>$Frame::getInstance()->startDynamicWithID("delivery-info");


Заранее спасибо.
>>883566>>885119
#129 #883566
>>883563
Первое статический метод вызывает
#130 #883621
>>883495
Есть функция glob: http://php.net/manual/en/function.glob.php
Но она не умеет в рекурсивный поиск, чтобы найти cookies.sqlite нужно точно знать на каком уровне вложенности находится файл, т.е. писать как-то так: glob('folder/✱/✱/cookies.sqlite')

Для произвольной вложенности нужно всё обходить ручками. Но есть готовые итераторы из SPL: http://php.net/manual/en/class.recursivedirectoryiterator.php
Использовать как-то так: http://stackoverflow.com/a/36912410

А на линуксе есть find, с помощью которого задача решается одной короткой строчкой.
>>884867>>885119
#131 #883720
Есть следующий код http://ideone.com/x1B5CD
Вопрос - можно ли как-то так заюзать тернарный оператор, что бы сократить немного этот код? Думал что это будет что-то такое (empty($_COOKIE['user_id'])) ? $this->actionRegistr() : $this->action(), но не работает.
>>885119
#132 #883745
На проверку:

Граммар Наци

http://ideone.com/uNsBBv - первое задание с выделением текста. У меня сложилось ощущение, что тут нужно больший кусок текста выводить с ошибкой, но я без понятия как это сделать. В голову приходит работа с флагом PREG_OFFSET_CAPTURE, но как на деле это все применить - хз...

http://ideone.com/XHg06L - вторая часть с тихим исправлением полегче.
>>885119
#133 #883810
В PHP есть какие нибудь особенности работы со ссылками имею в виду в описании сигнатур функций параметры указывать со знаком ссылки - &$a_variable? Должен ли я знать при работе с ними что нибудь кроме того, что по умолчанию параметры всех типов при передаче в функции копируются? Используются ли ещё ссылки как нибудь кроме передачи параметров?
>>885119
#134 #883842
Ребят, есть интересный вопрос. Какой самый тяжелый этап в изучении программирования? Может есть какая-то тяжелая тема, или тяжелый этап это теория и тд. Что самое тяжело, когда прям хочется забросить изучения программирования ?
#135 #883849
>>883842
поиск вакансий.
>>883857
#136 #883851
>>883842
Нет такого этапа, каждый раз когда я думал, что все самое тяжелое уже позади и дальше осталось только попивать смузи, читая хабр, меня настигала еще большая жопа и осознание того, что я нихуя не знаю.
#137 #883857
>>883849
а фрилансер 300/сек?
>>883865
#138 #883863
>>883842

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


Архитектурные всякие дела, ну и всякие алгоритмы сложные. Если освоишь это - считай ты понял программирование как таковое.
#139 #883865
>>883857
Что бы стать таким фрилансером надо сначала минимум пару лет бичпакетами питаться.
#140 #883894
Как вызвать функцию у объекта некоторого класса, который является элементом массива? PHPSTORM при операции
$x = $somearray[$i]->SomeFunction();
ругается, что не найдена функция SomeFunction();
Я так понимаю, надо кастовать элемент массива к классу, и потом только вызывать функцию?
>>883909>>885119
#141 #883909
>>883894

> $x = $somearray[$i]->SomeFunction();


Ничего кастовать не нужно, такой код должен работать, если в массиве под индексом $i действительно есть объект с методом SomeFunction().
Ты лучше вбрасывай код на ideone, а не рассказывай что там IDE показывает. IDE не знает, что добавится в массив во время выполнения программы.
Можно использовать докблоки для помощи IDE: http://stackoverflow.com/a/29999292
#142 #883980
Вопрос по задачке из курса.
"W5.2 Некто кладет в банк 10000 р. Банк начисляет 10% годовых (то есть, каждый год на счету становится на 10% больше, чем в прошлом году). Напиши программу, считающую, через сколько лет в банке будет миллион? Сколько лет будет этому некто? Доживет ли некто до этого дня, если сегодня ему 16 лет?"
Решаю так:

for ($l=1000;$l<1000000;$l=$l+$l*0.1) {
echo "l=$l\n";
}

Получаю столбец результатов.
Собсн вопрос: как вывести в конце число строк (лет)?
И является ли решение правильным, если крайнее число в столбце равно l=955593.81772732 ?
>>883982>>885119
#143 #883982
>>883980
Фикс.
for ($l=1000;$l<1000000;$l=$l+$l*0.1) {
echo "l=$l\n";
}
>>884036
#144 #884036
>>883982
зачем кучу раз выводить, сколько денег и когда?
невыводи ничего, а сделай counter на года типа кол-во год депозита ++
for ($l=1000;$l<1000000;$l=$l+$l0.1) {
$goda ++;
$babki =$l;
}
if $babki<1kk {
$goda ++;
$babk=$babki+$babki
0.1
}
echo $goda;
echo $babki;
это хоть и говнокод, но получше твоего варианта
>>884250>>885119
#145 #884130
>>880700 (OP)
Девушка с оппика позожа на мою коллегу просто 1 в 1!
#146 #884250
>>884036
Код не пашет даже после исправления опечаток. Я только начинаю, не мог бы подробнее расписать что к чему? Просто ума не приложу что делает вот эта команда "$goda ++;" (ну кроме того что с каждым разом эта переменная должна расти) во второй строке, этой переменной даже начальное значение не присваивалось, не говоря уже о том, что она никак не связана с основным вычислением.
>>884272>>885119
#147 #884272
>>884250
<?php
$goda =0; //ставишь сколько изначально лет вкладчику этк. это входное значение годов.
for ($l = 1000 ;$l < 1000000; $l=$l+$l0.1) {
$goda ++;
$babki =$l;// после конца цикла переменная $l превратится в тыкву(на нормальных языках, на пхп останется, собственно этот костыль необязателен)
}
if ($babki < 1000000) {// при значении меньше 1кк цыкл выше перестает работать, потому как делать надо было через do while, фиксим это проверкой, если мы вышли из предыдущего цыкла, а бабки меньше ляма, нада еще на 1 год оставить на депозите.
$goda ++ ; //увеличит на 1 значения года
$babki = $babki + ($babki
0.1) ; //добавит бабки заработаные за этот дополнительный год
}
echo $goda;
echo $babki;
?>
>>884298>>885119
98 Кб, 807x900
#148 #884298
>>884272
Нихуя не понимаю.
>>884303
106 Кб, 811x872
#149 #884303
>>884298
Так лучше, но почему у автора ответ 42?
>>884329>>885119
#150 #884323
Почему так много заданий, связанных с регулярками в стартовом гайде ? Решил все задачки со страницы "регулярные выражения", уже тошнит от них. В надежде на что-то более интересное перехожу на страницу "повторим", а там снова они.... То, что это офигенно мощный инструмент я понимаю, но неужели он настолько часто используется в реальной работе, что нужно их настолько задрачивать ?
>>884393>>885119
#151 #884329
>>884303
Потому-что у тебя неправильное решение например.
#152 #884393
>>884323
Почему ^[+7|8][ --()]{1,}[0-9]{10}$ не пашет?
#153 #884396
решаю задачки. возникла проблема со стихом
http://codepad.org/JrKDe8It
выводит 2 раза одно и тоже, а надо чтобы разное.
>>884402>>885119
#154 #884402
>>884396
Сначала первую строку выводишь, затем рандомишь опять и снова выводишь
#155 #884415
Аноны, если чей-то вопрос я пропустил, можете напомнить о себе в этом треде.

Напомню себе, что надо будет глянуть https://github.com/never3ver/students_list из >>873486 >>873545 и там почти все готово.

Напомню, что надо глянуть https://github.com/someApprentice/maintaskforlayout из >>874239 .

Подождите еще немного, доберусь и до вас.
>>888303>>892266
#156 #884454
Напомню, что надо проверить https://github.com/InitF/StudentList из >>874960 >>876772
>>894463
#157 #884795
В старом треде я проверил все посты. Если кого-то пропустил - напомните о себе тут.

Вот, в частности, последние ответы:

>>884783 - тут https://bitbucket.org/learningacc/file-downloader/
>>884472 - про аякс и почему не работает класс alert-success
>>884470 - про ООП, и что значит атрибут form action
#158 #884867
>>883621
спасибо
#159 #884908
Вопрос по задачкам. Задача на палиндром. Нашел вариант с strrev для кириллицы. Подходит ли такое решение или думать еще?
https://web2033.com/strrev-php/
>>884924
#160 #884924
>>884908

Нет. Программа должна вывести, является ли слово палиндромом или нет. Программа по ссылке этого не делает.

Также, код избыточен и его можно упростить.
>>884939
#161 #884939
>>884924
там только часть кода.
вот другой пример, вроде все верно работает
http://ideone.com/utCnEg
>>885033
#162 #885027
Скажите, вот с помощью пхп можно записать на комп экзешник, а как сделать, чтобы он самозапустился?
>>885037>>885041
#163 #885033
>>884939

Ты можешь объяснить, какие недостатки имеет используемый тобой подход? Ну например, будет ли работать проверка на палиндром для любого текста в кодировке utf-8 или не для любого? Если нет, то для каких входных данных программа будет работать правильно?

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

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

> function strrev_enc($text2)


Надо писать названия не через подчеркивания, а кемел кейсом. Название функции желательно начинать с глагола. Переменную надо назвать не text2, а просто text, так как в этой функции нет text1 и это просто выглядит нелогично.
#164 #885037
>>885027

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

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

Если ты хочешь писать консольные скрипты (или тем более десктопные программы), которые надо запускать без PHP, я бы советовал использовать другие языки. Для десктопных программ хорош C# (но ему нужен дотнет) или Java (тоже надо сначала саму Яву ставить), еще можно писать на C++, но это намного сложнее и неудобнее.

Для консольных программ можно использовать Го, но не уверен, что у него все хорошо с поддержкой винды. Он в первую очередь на Линукс ориентирован.
>>885053
#165 #885041
>>885027

Или я не понял вопрос и ты просто хочешь чтобы Апач с PHP в составе запускался сам при загрузке ОС? Тогда достаточно просто добавить Апач как службу.

Чистый PHP самозапускать немного странно - зачем? Если ты используешь его как сервер, то можно записать код запуска сервера в bat-файл и перетащить этот файл в раздел "автозагрузка" в меню Пуск -> Программы.
>>885053
#166 #885044
>>881470

> Размеры макета конечны?


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

- зафиксировать максимальную ширину содержимого (например 1200-1400px), если окно шире то центрировать содержимое, добавив поля с краев
- на ширине от ~600-800 до максимальной - сделать верстку резиновой, чтобы содержимое растягивалось на эту ширину. Ну например, блок с картинками может на узкой ширине превращаться в 3 колонки вместо 4, а на большой - в 5.
- на ширине меньше 600-800 переходить на мобильную верстку - обычно там все содержимое выводится в 1-2 колонки

Вот в помощь таблица размеров экранов мобильных устройств: http://mydevice.io/devices/

Если ты не знаком с адаптивной версткой, то погугли "примеры адаптивных сайтов", или просто используй кнопку "тестирование адаптивной верстки" в инструментах разработчика в Хроме/ФФ (Ctrl + SHift + I).

> Шапка высотой 200px на экране с большим разрешением -- смех, а буквы не читаются: как исправить?


Почему не читаются? Они довольно большие в макете. И как на этом экране выглядят другие сайты, например Хабр?

> Возможно ли проставить высоту в% без потери возможности скроллить вниз?


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

>>не используй <a href="#" или <a href="javascript:void(0)" никогда. Для этого есть кнопки или <span>


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

Если есть какие-то еще вопросы - задавай.
#167 #885053
>>885041
>>885037
Нет, я с помощью пхп хочу создать и записать на компе юзера ехе файл. Это можно сделать, вот только как его запустить - не знаю. Можно сделать так, чтобы юзер кликнул на этот файл, но как сделать шоб .ехе файл запустился без клика.
>>885120
#168 #885072
>>881635

Выражение в if (а также в for, while, switch) всегда должно быть заключено в скобки, так что второй вариант неправильный.

>>881676

Я из скриншота вижу, что правило в файле uploader-master.css перекрывает правила в бутстрапе. Приоритет у них равный, скорее просто причина в том что тот файле позже подключен.

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

>>881710

Тебе надо вместо $i <= 10 написать кое-что другое.

>>881722

У тебя в коде есть ошибка. Условие $b < 10 проверяется в первый раз до того, как переменная будет создана, и происходит ошибка обращения к несуществующей переменной.

Также, условие фактически проверяет значение переменной с предыдущего шага. То есть сначала выводится 4x4 = 16, а только потом идет проверка и обнаруживается, что из цикла пора выходить. Посмотри в моем учебнике картинку с порядком выполнения цикла.

>>881760

Код для любых слов пишет, что это палиндром: http://ideone.com/Uw7SWV

Ведь фактически ты проверяешь только средние 2 буквы. У тебя в коде вообще нет слова "не палиндром".

>>881835

Боюсь, что у нас не тред поиска работы. Чтобы быть востребованным для работодателей, я советую изучать разные языки и технологии (в том числе решив например все наши задачки), а также делать учебные проекты (вроде тех что в ОП посте).
#168 #885072
>>881635

Выражение в if (а также в for, while, switch) всегда должно быть заключено в скобки, так что второй вариант неправильный.

>>881676

Я из скриншота вижу, что правило в файле uploader-master.css перекрывает правила в бутстрапе. Приоритет у них равный, скорее просто причина в том что тот файле позже подключен.

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

>>881710

Тебе надо вместо $i <= 10 написать кое-что другое.

>>881722

У тебя в коде есть ошибка. Условие $b < 10 проверяется в первый раз до того, как переменная будет создана, и происходит ошибка обращения к несуществующей переменной.

Также, условие фактически проверяет значение переменной с предыдущего шага. То есть сначала выводится 4x4 = 16, а только потом идет проверка и обнаруживается, что из цикла пора выходить. Посмотри в моем учебнике картинку с порядком выполнения цикла.

>>881760

Код для любых слов пишет, что это палиндром: http://ideone.com/Uw7SWV

Ведь фактически ты проверяешь только средние 2 буквы. У тебя в коде вообще нет слова "не палиндром".

>>881835

Боюсь, что у нас не тред поиска работы. Чтобы быть востребованным для работодателей, я советую изучать разные языки и технологии (в том числе решив например все наши задачки), а также делать учебные проекты (вроде тех что в ОП посте).
>>886803
#169 #885080
>>882704

> Я про то, что POST теряется пока до модели доходит. И не могу понять почему.


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

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


Выглядит странно. Наследование не для этого придумано.

По поводу работы с БД - у меня есть урок - https://github.com/codedokode/pasta/blob/master/db/patterns-oop.md - читал? Если да, то напиши какой паттерн используешь.
#170 #885086
>>882712

Проверь с помощью var_dump, что в переменных ($_FILES и других). Проверь, что возвращает функция move_uploaded_file и прочти мануал по ней, а также это целиком: http://php.net/manual/ru/features.file-upload.php

Открой отладчик в браузере (Ctrl +Shift + I) и проверь на вкладке Network, отправляется ли файл вообще.

Проверь лог ошибок PHP, нет ли ошибок.

> ничего не возвращает


Что значит "ничего"? Проверь с помощью var_dump что именно.

>>882731

Что значит "у нас"? Кривой код у тебя, а не у нас.

>>882737

Надо реализовать ArrayAccess.

>>882741

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

>>882762

2017 год рано писать.

>>882958

Твой вопрос неудачно сформулирован. Что значит "можно"? В теории на PHP сделать такое можно, на практике не факт что есть нужная библиотека. Ну например, под виндой можно использовать утилиту pskill или как-то так от Русиновича. Но это уже не совсем PHP.

>>882963

Нет. Ты вызываешь функцию N раз, передавая ей 1 аргумент, а надо вызвать 1 раз, передав все аругменты.

Ты почитал про apply() и call() ? Сделай-ка пример кода для каждой функции, если не пробовал.

>>882978

Откуда ты пытаешься прочитать эти директивы? Куда ты пытаешься вывести их названия? В браузер?

В браузере воспринимаемая кодировка зависит от тега meta charset и HTTP заголовка Content-Type.
#170 #885086
>>882712

Проверь с помощью var_dump, что в переменных ($_FILES и других). Проверь, что возвращает функция move_uploaded_file и прочти мануал по ней, а также это целиком: http://php.net/manual/ru/features.file-upload.php

Открой отладчик в браузере (Ctrl +Shift + I) и проверь на вкладке Network, отправляется ли файл вообще.

Проверь лог ошибок PHP, нет ли ошибок.

> ничего не возвращает


Что значит "ничего"? Проверь с помощью var_dump что именно.

>>882731

Что значит "у нас"? Кривой код у тебя, а не у нас.

>>882737

Надо реализовать ArrayAccess.

>>882741

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

>>882762

2017 год рано писать.

>>882958

Твой вопрос неудачно сформулирован. Что значит "можно"? В теории на PHP сделать такое можно, на практике не факт что есть нужная библиотека. Ну например, под виндой можно использовать утилиту pskill или как-то так от Русиновича. Но это уже не совсем PHP.

>>882963

Нет. Ты вызываешь функцию N раз, передавая ей 1 аргумент, а надо вызвать 1 раз, передав все аругменты.

Ты почитал про apply() и call() ? Сделай-ка пример кода для каждой функции, если не пробовал.

>>882978

Откуда ты пытаешься прочитать эти директивы? Куда ты пытаешься вывести их названия? В браузер?

В браузере воспринимаемая кодировка зависит от тега meta charset и HTTP заголовка Content-Type.
#171 #885089
>>883042

Базы данных в конечном итоге тоже хранят данные в файлах. Где тут выигрыш? Разве что могут быть накладные расходы на передачу данных из приложения в СУБД по сети.

Я думаю, что "super fast" это маркетинговое заявление. Там есть примеры тестов, показывающих разницу в скорости с обычными СУБД? Нет. Ну а слово "super fast", как ты понимаешь, может значить что угодно.

Я не сравнивал, но Бд вроде MySQL не медленные, я добивался там тысяч вставок в секунду при грамотном использовании, Бд поддерживают язык SQL , транзакции, параллельный доступ. Я сильно сомневаюсь что самописный движок на PHP будет работать лучше чем отлаживаемый годами профессиональный продукт.

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

Если тебе надо хранить базу в файле для каких-то целей (например для простоты установки или переноса), есть SQlite - это однопользовательская БД на файлах. Она используется в iOs, андроиде, Хроме (хранить историю и закладки), скайпе. Но она рассчитана на "встраиваемое" использование, когда ей пользуется только одна программа, а веб - это много параллельно работающих скриптов и там она не так эффективна как отдельная БД.
#172 #885101
>>882999

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

>>883087

Изучи, чем отличается от PHP5, что нового, какую выгоду это дает.

>>883104

Забили на нее. Если у тебя андроид 2-летней давности то хипстеров твои проблемы не волнуют.

Я конечно советую пока писать на ES3.

Также есть транспайлеры, которые могут транслировать код в более раннюю версию, но они пока умеют только превращать ES6 -> ES5. Никто не хочет попробовать в ES3 транспайлер написать? Тут конечно надо понимать, что часть кода все равно преобразовать не удастся.

>>883199

Стену кода тяжеловато читать, инициализацию стоило засунуть в функцию.

Эхо сервер должен читать 1 строку (до первого \n). Ты вместо этого читаешь 1 пакет, это может быть несколько строк или кусок строки.

socket_close может выдать ошибку.

> $buf = trim($buf);


> if ($buf == "\r\n") {


Это никогда не сработает. Догадайся, почему.

Советую не требовать наличия \r для совместимости с теми кто использует только \n (но при этом слать \r\n в ответе).
#172 #885101
>>882999

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

>>883087

Изучи, чем отличается от PHP5, что нового, какую выгоду это дает.

>>883104

Забили на нее. Если у тебя андроид 2-летней давности то хипстеров твои проблемы не волнуют.

Я конечно советую пока писать на ES3.

Также есть транспайлеры, которые могут транслировать код в более раннюю версию, но они пока умеют только превращать ES6 -> ES5. Никто не хочет попробовать в ES3 транспайлер написать? Тут конечно надо понимать, что часть кода все равно преобразовать не удастся.

>>883199

Стену кода тяжеловато читать, инициализацию стоило засунуть в функцию.

Эхо сервер должен читать 1 строку (до первого \n). Ты вместо этого читаешь 1 пакет, это может быть несколько строк или кусок строки.

socket_close может выдать ошибку.

> $buf = trim($buf);


> if ($buf == "\r\n") {


Это никогда не сработает. Догадайся, почему.

Советую не требовать наличия \r для совместимости с теми кто использует только \n (но при этом слать \r\n в ответе).
#173 #885107
>>883199

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

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

>>883206

Нет, но можно написать цикл, либо array_filter, либо использовать array_reduce с анонимной функцией.

>>883310

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

>>883410

А как еще хранить набор объектов, если не класть их в массив? Ну например, список новостей?
#174 #885119
>>883466

Можно составить индекс (список всех путей) заранее и искать в нем.

>>883563

http://php.net/manual/ru/language.oop5.paamayim-nekudotayim.php
http://php.net/manual/ru/language.oop5.basic.php

это из ООП. Изучи его сначала.

>>883621

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

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

>>883720

Тут нужен именно иф, сокращать нечего, код станет хуже читаемым.

>>883745

Отвител тут >>884790

>>883810

Надо полностью прочесть этот раздел http://php.net/manual/ru/language.references.php

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

>>883894

Класс не может быть элементом массива. Правильно писать "объект класса X хранится в массиве/является значением элемента массива"

Твой код должен работать.

Кастовать объекты нельзя.

>>883980

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

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

>>884036

Не надо писать переменные русскими словами. Используй Гугл транслейт.

Иф в коде лишний - зачем он?

>>884250

$x++ равносильно $x += 1 или $x = $x + 1

>>884272

Иф не нужен.

>>884303

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

>>884323

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

Пригодятся они не раз. даже в редакторе кода в поиске их можно использовать.

>>884396

Ну так ты выводишь одну и ту же переменную 2 раза. Или ты думаешь, она сама по себе поменяет значение? Переменная - это просто хранилище, что ты в нее кладешь, то в ней и останется лежать, пока не поменяешь.
#174 #885119
>>883466

Можно составить индекс (список всех путей) заранее и искать в нем.

>>883563

http://php.net/manual/ru/language.oop5.paamayim-nekudotayim.php
http://php.net/manual/ru/language.oop5.basic.php

это из ООП. Изучи его сначала.

>>883621

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

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

>>883720

Тут нужен именно иф, сокращать нечего, код станет хуже читаемым.

>>883745

Отвител тут >>884790

>>883810

Надо полностью прочесть этот раздел http://php.net/manual/ru/language.references.php

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

>>883894

Класс не может быть элементом массива. Правильно писать "объект класса X хранится в массиве/является значением элемента массива"

Твой код должен работать.

Кастовать объекты нельзя.

>>883980

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

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

>>884036

Не надо писать переменные русскими словами. Используй Гугл транслейт.

Иф в коде лишний - зачем он?

>>884250

$x++ равносильно $x += 1 или $x = $x + 1

>>884272

Иф не нужен.

>>884303

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

>>884323

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

Пригодятся они не раз. даже в редакторе кода в поиске их можно использовать.

>>884396

Ну так ты выводишь одну и ту же переменную 2 раза. Или ты думаешь, она сама по себе поменяет значение? Переменная - это просто хранилище, что ты в нее кладешь, то в ней и останется лежать, пока не поменяешь.
#175 #885120
>>885053

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

Ну и это плохая идея, писать инсталляторы на PHP. Есть гораздо более подходящие для этого средства.
>>885351
#176 #885155
"Внедрение зависимости (англ. Dependency injection, DI) — процесс предоставления внешней зависимости программному компоненту. Является специфичной формой «инверсии управления» (англ. Inversion of control, IoC), когда она применяется к управлению зависимостями. В полном соответствии с принципом единой обязанности объект отдаёт заботу о построении требуемых ему зависимостей внешнему, специально предназначенному для этого общему механизму[1].

JNDI-запросы сервиса, когда объект запрашивает сервис по имени, реализуют внедрение зависимости лишь частично."

Перечитываю и перечитываю раз за разом, это какой-то мертвый язык? Как это можно понимать вообще?
>>885192
#177 #885192
>>885155

Почитай у меня: https://github.com/codedokode/pasta/blob/master/arch/di.md

Или у Фаулера (он очень умный) (англ): http://www.martinfowler.com/articles/injection.html
Перевод не очень читабельного качества: http://yugeon-dev.blogspot.ru/2010/07/inversion-of-control-containers-and_21.html

Также предлагаю, если есть желающие, составить нормальное определение для Вики, желательно опирающееся на труды Фаулера.
>>885761
#178 #885216
Привет, я снова на связи

переделал 13 задачу по JS: http://ideone.com/7lG98j

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

>> @param {сonst} timesOfDay - Константы класса DepartmentOfEnergy


>Мне стало интересно, а можно ли описать как-то что тут константы, с помощью jsdoc? Я нашел такое:



>- http://usejsdoc.org/tags-enum.html


>- https://github.com/jsdoc3/jsdoc/issues/629



>Но это по моему все не то. В TypeScript вроде есть enum для этого.



Для обозначения констант решил сделать так:
* @param {(PowerDepartment.DAY|PowerDepartment.NIGHT)}
Так как, данная конкретная константа сама по себе является новым, определенным типом данных,
я указываю ее название в качестве этого типа данных. А варианты показаны как Multiple types (type union) http://usejsdoc.org/tags-type.html
Хотя, если констант больше двух, запись будет очень длинной. Но зато, название константы сообщает о том, что она константа, и дополнительно то, в каком месте кода она объявлена. А ее значение {string}, не важно для метода класса, который с ней непосредственно работает, т. к. значение может поменяться в том месте, где она объявляется, без нарушений в работе данного метода.
#179 #885240
Что то торможу, что значит в Yii2 вот это \Yii это же не псевдоним который должен начинаться с @?
#180 #885262
В общем я походу совсем деградировал, только начал, и сразу затрял.
Не могу понять как решить задачу с годовыми процентами.
http://ideone.com/wmAd6C
Намекните что делать.
>>885307
#181 #885263
Может кто пояснить неофиту следующий аспект работы с PDO:
что происходит при использовании следующей конструкции:
http://ideone.com/IYyjOd

Вот я создал database handler, и вот мне нужно запросить с БД х строк из представления. На W3schools я прочел, что в контексте работы с БД рекомендуется запрашивать хэндлер подгатавливать некий стейтмент (чё вообще возвращает DBH->prepare()?), после чего указанный в prepare() запрос компилируется на сервере
и тут вопрос номеро один: только компилируется запрос, не подгатавливаются никакие данные? Сколько потом на сервере хранится скомпилированный скрипт, и вообще, важно ли это, что он там хранится с какой либо другой точки зрения, кроме как серверу не придется парсить текст запроса и компилировать запрос по новой и той, что подготовленные запросы якобы уменьшают риск сикуль инъекций?
Далее, вот есть объект, возвращенный prepare()'ом - некоторый statement. Далее, на w3schools'е в примерах его тут же вызывали через
$statement->execute();
тут вопрос нумеро дос. Что происходит при вызове execute()? Интуитивно из названия функции мне казалось, что execute() тут же выполняет подготовленный запрос в БД и, следовательно, если это селект-запрос, то сервер тут же предоставляет мне информацию в полном объеме
Но тут я наткнулся на $statement->fetch(...)
И здесь вопрос нумеро трес - что происходит при вызове функции fetch()? Как я понял, считывается одна строка из результирующей таблицы, ну и интерпретируется в соответствии с аргументами. Но что происходит с точки зрения взаимодействия с БД? fetch каждый раз обращается к БД за очередной строчкой, или извлекает из результата работы (не возвращаемого значения) $statement->execute() строку?

И ещё, если после $statement->execute() данные всё таки в полном объеме берутся из БД, то где и как они хранятся после этого, когда удаляются?
>>885391>>885402
#182 #885307
>>885262
а как же основной баланс?
#183 #885337
Объясните, пожалуйста, это:

function test_global_ref() {
global $obj;
$obj = &new stdclass;
}

>$obj = &new stdclass;


Что, черт возьми, это значит?
Я понимаю, что "$obj = new stdclass;" - это создать экземпляр класса и присвоить его переменной $obj. Но если перед new стоит &, как это понимать? Ссылка на экземпляр класса? Но ведь он еще не создан и ничему не присвоен.
Пример взят из справочника с php.net.
>>885366
#184 #885351
>>885120
Я тебе еще раз объясняю, с помощью пхп я смогу создать на компе юзера файл с расширением ехе, который будет написан на крестах или шарпе. Вопрос как с помощью пхп или того яп, на котором он написан, сделать, чтобы файл с расширением ехе самозапустился. Или ты других яп кроме пхп не знаешь?
>>885366
#185 #885366
>>885337

Это ссылка и я подозреваю, что это устаревший пример кода, так как в PHP5 объекты передаются как бы по ссылке и & не нужен:

- http://php.net/manual/ru/language.references.php
- http://php.net/manual/ru/language.oop5.references.php

>>885351

Но что тебе мешает сделать нормальный инсталлятор? Некоторые программы позволяют создать инсталлятор даже без программирования. Я не вижу смысла городить какую-то сложную схему с установкой PHP, затем установкой через него программы - это слишком переусложнено.
>>885372
#186 #885372
>>885366
огоспади. смотри, я вешаю скрипт на сервер в публичный доступ. сторонний юзер переходит по ссылке и у него на компе (не на моем) создается файл екзешник. теперь мне надо чтобы у него на компе этот файл самозапустился. не на моем. грубо говоря, вирусняк хочу через ссылку юзеру закинуть.
>>885373
#187 #885373
>>885372

Тогда уходи. Наш тред не для создателей вирусов. Ну и дополню, чтобы ты не тратил время, юный вирусописатель, что с помощью PHP екзешник ты создать можешь разве что на сервере.
>>885379
#188 #885374
ОП ответь на regex, плис
>>885391
#189 #885379
>>885373
не правда, я могу создать файл с помощью fopen и присвоить ему расширение .ехе. Причем на компе у того, кто открыл ссылку
>>885391
#190 #885384
я слишком ахуел с таким решением задачи?
for($age=16, $money = 10000;$money<1000000;$age++,$money+=$money*0.1){

}
echo $age."\n";
echo $money;
>>885986
#191 #885391
>>885379

Перечитай теорию про то, как взаимодействует браузер и сервер.

>>885374

А номер поста?

>>885263

Для начала почитай мануал по PDO::prepare http://php.net/manual/ru/pdo.prepare.php

Там написано, что возвращается объект PDOStatement.

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

> Сколько потом на сервере хранится скомпилированный скрипт


В мануале не написано явно: "так как позволяет драйверу кэшировать на клиенте и/или сервере план выполнения запроса и метаданные". Это потому что у разных баз данных могут быть разные принципы работы, PDO ведь несколько видов баз поддерживает.

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

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

Идем на сайт MysQL: http://dev.mysql.com/doc/refman/5.7/en/sql-syntax-prepared-statements.html

Видим там пункт "Prepared Statements in Application Programs" - это как раз наш случай, речь о подготовке запроса клиентом. Конечно, там описана поставляемая с MySQL библиотека-клиент, но я думаю что та что в PHP работает аналогично. По крайней мере она использует тот же протокол и серверный код одинаков. Идем по ссылке и находим статьи

1) http://dev.mysql.com/doc/refman/5.7/en/c-api-prepared-statements.html
2) http://dev.mysql.com/doc/refman/5.7/en/c-api-prepared-statement-problems.html

Открываем 1 и там мы видим " For more information, see Section 9.10.4, “Caching of Prepared Statements and Stored Programs”." и снова идем по ссылке http://dev.mysql.com/doc/refman/5.7/en/statement-caching.html

Видим: "The max_prepared_stmt_count system variable controls the total number of statements the server caches. (The sum of the number of prepared statements across all sessions.)" - то есть есть ограничение на общее число закешированных в памяти подготовленных запросов. Можешь просмотреть эту переменную запросом SHOW VARIABLES LIKE 'max_prepared%';

> The server maintains caches for prepared statements and stored programs on a per-session basis. Statements cached for one session are not accessible to other sessions. When a session ends, the server discards any statements cached for it.



Кеш свой для каждого соединения с БД. Он очищается при отсоединении от нее.

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

Их используют в основном ради плейсхолдеров.
#191 #885391
>>885379

Перечитай теорию про то, как взаимодействует браузер и сервер.

>>885374

А номер поста?

>>885263

Для начала почитай мануал по PDO::prepare http://php.net/manual/ru/pdo.prepare.php

Там написано, что возвращается объект PDOStatement.

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

> Сколько потом на сервере хранится скомпилированный скрипт


В мануале не написано явно: "так как позволяет драйверу кэшировать на клиенте и/или сервере план выполнения запроса и метаданные". Это потому что у разных баз данных могут быть разные принципы работы, PDO ведь несколько видов баз поддерживает.

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

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

Идем на сайт MysQL: http://dev.mysql.com/doc/refman/5.7/en/sql-syntax-prepared-statements.html

Видим там пункт "Prepared Statements in Application Programs" - это как раз наш случай, речь о подготовке запроса клиентом. Конечно, там описана поставляемая с MySQL библиотека-клиент, но я думаю что та что в PHP работает аналогично. По крайней мере она использует тот же протокол и серверный код одинаков. Идем по ссылке и находим статьи

1) http://dev.mysql.com/doc/refman/5.7/en/c-api-prepared-statements.html
2) http://dev.mysql.com/doc/refman/5.7/en/c-api-prepared-statement-problems.html

Открываем 1 и там мы видим " For more information, see Section 9.10.4, “Caching of Prepared Statements and Stored Programs”." и снова идем по ссылке http://dev.mysql.com/doc/refman/5.7/en/statement-caching.html

Видим: "The max_prepared_stmt_count system variable controls the total number of statements the server caches. (The sum of the number of prepared statements across all sessions.)" - то есть есть ограничение на общее число закешированных в памяти подготовленных запросов. Можешь просмотреть эту переменную запросом SHOW VARIABLES LIKE 'max_prepared%';

> The server maintains caches for prepared statements and stored programs on a per-session basis. Statements cached for one session are not accessible to other sessions. When a session ends, the server discards any statements cached for it.



Кеш свой для каждого соединения с БД. Он очищается при отсоединении от нее.

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

Их используют в основном ради плейсхолдеров.
#192 #885401
>>885391
сам почитай. я прямо сейчас так и делаю.
#193 #885402
>>885263

> тут вопрос нумеро дос. Что происходит при вызове execute()? Интуитивно из названия функции мне казалось, что execute() тут же выполняет подготовленный запрос в БД


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

Далее, возможны вариации. Сервер обычно старается вернуть данные как можно раньше, по мере выполнения запроса. Но с PHP не все так просто. Он может прочитать результат полностью, а может не дожидаться окончания и возвращать данные тоже по мере поступления. Это называется буферизация результата. Отсутствие буферизации ограничивает наши возможности: к примеру, мы не можем узнать общее число результатов и не можем вернуться к уже полученному ранее результату. Мы не можем запустить второй запрос, не дождавшись окончания первого. Но зато это позволяет обрабатывать огромные результаты, не занимая много памяти и не дожидаясь окончания запроса.

Библиотека mysqli умеет работать с небуферизованными данными ( http://php.net/manual/ru/mysqlinfo.concepts.buffering.php ). Умеет ли PDO?

Тут http://php.net/manual/ru/ref.pdo-mysql.php есть константа PDO::MYSQL_ATTR_USE_BUFFERED_QUERY. Я предлагаю тебе выяснить, работает ли она?

Выяснить, какой способ используется, можно так:

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

SELECT 1
UNION ALL
SELECT SLEEP(3)
UNION ALL
SELECT 2
UNION ALL
...

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

Попробуй потестировать, интересно, что получится.

> И здесь вопрос нумеро трес - что происходит при вызове функции fetch()? Как я понял, считывается одна строка из результирующей таблицы, ну и интерпретируется в соответствии с аргументами


При буферизации PHP прочитает весь ответ в память во время execute (я так думаю, надо проверять) и вернет ответ из памяти. При отсутствии буферизации fetch должна ждать прихода следующей строки результата от MySQL и сразу возвращать ее.

> данные всё таки в полном объеме берутся из БД, то где и как они хранятся после этого, когда удаляются?


В полном объеме в БД данные не хранятся так как это не позволяет возвращать много результатов. Как я понимаю, они шлются клиенту (в PHP), если он их не спешит забирать, то запрос приостанавливается, пока он их не примет: http://stackoverflow.com/questions/33573434/how-does-mysql-server-retrieve-and-send-data-to-clients/33573678#33573678

Сетевой протокол TCP имеет небольшой буфер и имеет обратную связь, то есть MySQL знает, сколько именно данных успешно передано в PHP, и знает, если он приостановил их прием.

Казалось бы, при такой схеме памяти много в MYSQL не израсходуется. Но не все так просто. Для некоторых запросов MySQL придется создавать буфера в памяти. Ну например, для сортировки не по индексу
мы должны выбрать все нужные данные в память mysql, отсортировать их там и только после этого можем передавать. также, огромные временные таблицы могут получаться при использовании JOIN без индексов + сортировка. Для временного хранения исплоьзуется либо буфер в памяти либо временный файл:

- http://dev.mysql.com/doc/refman/5.7/en/memory-use.html
- https://dev.mysql.com/doc/refman/5.7/en/internal-temporary-tables.html

> Most requests that perform a sort allocate a sort buffer and zero to two temporary files depending on the result set size. See Section B.5.3.5, “Where MySQL Stores Temporary Files”.


> All joins are executed in a single pass, and most joins can be done without even using a temporary table. Most temporary tables are memory-based hash tables. Temporary tables with a large row length (calculated as the sum of all column lengths) or that contain BLOB columns are stored on disk.



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

Большинство ссылок на английском, но ты написал что читаешь w3schools, а на русском ты нигде эту ценную информацию не найдешь. Советую собраться с силами и почитать.
#193 #885402
>>885263

> тут вопрос нумеро дос. Что происходит при вызове execute()? Интуитивно из названия функции мне казалось, что execute() тут же выполняет подготовленный запрос в БД


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

Далее, возможны вариации. Сервер обычно старается вернуть данные как можно раньше, по мере выполнения запроса. Но с PHP не все так просто. Он может прочитать результат полностью, а может не дожидаться окончания и возвращать данные тоже по мере поступления. Это называется буферизация результата. Отсутствие буферизации ограничивает наши возможности: к примеру, мы не можем узнать общее число результатов и не можем вернуться к уже полученному ранее результату. Мы не можем запустить второй запрос, не дождавшись окончания первого. Но зато это позволяет обрабатывать огромные результаты, не занимая много памяти и не дожидаясь окончания запроса.

Библиотека mysqli умеет работать с небуферизованными данными ( http://php.net/manual/ru/mysqlinfo.concepts.buffering.php ). Умеет ли PDO?

Тут http://php.net/manual/ru/ref.pdo-mysql.php есть константа PDO::MYSQL_ATTR_USE_BUFFERED_QUERY. Я предлагаю тебе выяснить, работает ли она?

Выяснить, какой способ используется, можно так:

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

SELECT 1
UNION ALL
SELECT SLEEP(3)
UNION ALL
SELECT 2
UNION ALL
...

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

Попробуй потестировать, интересно, что получится.

> И здесь вопрос нумеро трес - что происходит при вызове функции fetch()? Как я понял, считывается одна строка из результирующей таблицы, ну и интерпретируется в соответствии с аргументами


При буферизации PHP прочитает весь ответ в память во время execute (я так думаю, надо проверять) и вернет ответ из памяти. При отсутствии буферизации fetch должна ждать прихода следующей строки результата от MySQL и сразу возвращать ее.

> данные всё таки в полном объеме берутся из БД, то где и как они хранятся после этого, когда удаляются?


В полном объеме в БД данные не хранятся так как это не позволяет возвращать много результатов. Как я понимаю, они шлются клиенту (в PHP), если он их не спешит забирать, то запрос приостанавливается, пока он их не примет: http://stackoverflow.com/questions/33573434/how-does-mysql-server-retrieve-and-send-data-to-clients/33573678#33573678

Сетевой протокол TCP имеет небольшой буфер и имеет обратную связь, то есть MySQL знает, сколько именно данных успешно передано в PHP, и знает, если он приостановил их прием.

Казалось бы, при такой схеме памяти много в MYSQL не израсходуется. Но не все так просто. Для некоторых запросов MySQL придется создавать буфера в памяти. Ну например, для сортировки не по индексу
мы должны выбрать все нужные данные в память mysql, отсортировать их там и только после этого можем передавать. также, огромные временные таблицы могут получаться при использовании JOIN без индексов + сортировка. Для временного хранения исплоьзуется либо буфер в памяти либо временный файл:

- http://dev.mysql.com/doc/refman/5.7/en/memory-use.html
- https://dev.mysql.com/doc/refman/5.7/en/internal-temporary-tables.html

> Most requests that perform a sort allocate a sort buffer and zero to two temporary files depending on the result set size. See Section B.5.3.5, “Where MySQL Stores Temporary Files”.


> All joins are executed in a single pass, and most joins can be done without even using a temporary table. Most temporary tables are memory-based hash tables. Temporary tables with a large row length (calculated as the sum of all column lengths) or that contain BLOB columns are stored on disk.



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

Большинство ссылок на английском, но ты написал что читаешь w3schools, а на русском ты нигде эту ценную информацию не найдешь. Советую собраться с силами и почитать.
>>885525
#194 #885405
>>885391
на почте, но вот: " ^[\+]?[\ ]?(7|8)([-]?[ ]?[(]?[)]?){1,}[0-9]{10}$ почему пробел\скобка\- в номерах не ищутся между цифрами? Кучу вариантов перепробовал пиздос"
>>885411
#195 #885411
>>885405

Потому, что [0-9]{10} значит "10 идущих подряд цифр". Минусы и скобки у тебя разрешены только между цифрой 7/8 и второй цифрой номера.

Я советую написать так:

- 10 раз повторить: "1 любая цифра, за ней любое число минусов/скобок в любом порядке"

Кстати, у тебя заложен порядок знаков (что минус идет до пробела и до скобок). Не советую так делать. Лучше написать "любое число знаков в любом порядке". Для этого надо использовать либо квадратные скобки, либо вертикальную черту.
#196 #885467
http://sandbox.onlinephpfunctions.com/code/b3365ec9fbe287f8009da0f694957913c450dfb3
Анон, я ща сдохну нахуй, почему вместо всей строчки вывод заканчивается на арозаупала а не полной фразе!?
#197 #885473
>>885467
$str обращается к байту строки под номером i. Юникод строка использует 2 байта для хранения символа. Поэтому выводится первые $length-1 байт сроки. Используй mb_substr например.
>>885475
#198 #885475
>>885473
Чет пол сообщения пропало. Ну надеюсь ты понял куда копать.
#199 #885491
Добрый анон, можешь подсказать курсы по PHP, где за всё поясняет битард с картинками, а в конце каждой темы даёт задания вроде написания кода с кубиками или шифратором и т.д
>>885493
#200 #885493
>>885491

Няша, а в Оп посте нет ли случайно того, что ты ищешь?
>>885496
#201 #885496
>>885493
Ой лол, спасибо анон, я дебил
#202 #885497
Есть ли компании или какие-то организации, которые берут тебя учить программированию, чтобы потом настажировать и взять к себе? Прост самому 18, времени свободного много, родители обеспечивают, хоть за нихуя готов
#203 #885499
>>885467

$str[$i] возвращает i-й байт, а не букву. Урок: https://gist.github.com/codedokode/ff99e357e9860ea169b8
#204 #885510
>>885467
$str = $text;
$length= mb_strlen($str);
Крутой код.
А почему не
$length= mb_strlen($text);

?
#205 #885525
>>885402
>>885391
Спасибо вам (тебе?), что вы есть. Впервые в /pr встречаю такую активную помощь новеньким.
#206 #885608
Добрый день, в общем дали один говносайт какой-то.

Зашел на фтп, слил себе папку сайт\паблик_хтмл на локалку.

сделал локальный домен, залил её туда.

Захожу значит на локальный домен - меня редиректит на основной сайт.
до index.php даже не доходит дело.

.htacess вообще удалял, всё равно редиректит.

Дошло до того, что я вырубил локальынй сервер и всё равно всё редиректит. Что это за пакость прописалась у меня?
>>885975
#207 #885630
Блин, объясните кто-то тупице, почему при выводе массива $matches - он выводится без изменений, которые в цикле производятся ?
http://ideone.com/ZULwK4
>>885658
#208 #885658
>>885630
Во-первых, твоя функция makeFirstLetterUppercase ничего не возвращает. Она принимает строку, делает её копию, изменяет эту копию и всё.
Во-вторых цикл foreach работает с копиями элементов массива $matches. То есть ты в foreach'е изменяешь копию элемента, а не сам элемент массива, следовательно все твои изменения сохраняются в копиях и на исходный массив никак не влияют. Плохой способ решения проблемы - использовать ссылки - &, выше вбрасывали где почитать о них. Способ получше - добавлять новые апперкейсные значения в другой массив. В PHP есть удобная функция array_map, но тебе наверное будет проще циклом сделать. Если ты зачем-то хочешь менять именно исходный массив $matches, то тебе нужен цикл for и обращения по индексу.
>>885690
#209 #885682
>>885497
Ты че, сука, думаешь тебе весь мир должен?
Просто в ахуе, таких родителей стерилизовать нужно. Нарожают бля трутней.
>>885713>>885970
#210 #885690
>>885658
благодарю за ответ.
Где, кроме оф мануала можно почитать подробно про колбэк функции ?
>>885975
6 Кб, 250x250
#211 #885699
Анонс у меня к тебе вопрос. Я не понимаю как это реализовать.
Длинный текст писал, потом подумал и решил не удалять, мало ли. В коротком тексте вроде короче и понятней
У меня некоторые проблемы с ООП и я решил попробовать реализовать получение данных через API, чтобы понять некоторые особенности этого самого ООП. Данные получаются по ссылке с непостоянным количеством параметров, которое указано в методе, и в xml.
Нужно:
1. Получить с помощью CURL файл
2. Получить объект SimpleXML и отдать его.
Это самое минимальное.
У меня есть:
Класс со всеми доступными вызовами в виде методов, ни от кого не наследуется.
Как я представляю работу:
1. Вызывается метод $api->accountData(); Это один из возможных вызовов в API.
2. Он должен взять BASE_URL(адрес api), которую я не знаю где объявить, присоединить к нему адрес конкретного метода, BASE_URL.'/account_info.xml', получить это по CURL и через SimpleXML вернуть объект с данными. Причем к ссылке должен быть постоянно подставлен id и password, которые я думаю передавать в конструктор при создании экземпляра объекта


Пока писал, продумал часть.
$api = new Api($login,$password);
Api ничего не наследует.
Такой вызов $api->get('accountData'); Возвращает просто готовую ссылку на xml, как сделать так, чтоб он возвращал объект? То есть обрабатывался тем же CURL и SimpleXML?
>>885970>>885971
#212 #885713
>>885682
Это да или нет?
>>885791>>885970
#213 #885750
>>885497
Знакомый так устроился 1ass ковырять. Но это не программирование.
#214 #885761
>>885192
Вот, вот оно! И почему дядьки стараются писать заумно? Оп-няшка, #спасибо_что_живой. Разжевано, понравилось, почитал еще твои статьи, кто-нибудь пробовал делать задание на браузерный проект (рассчитанный на 2-3 месяца): https://github.com/codedokode/pasta/blob/master/js/spa.md ?
>>885970
#215 #885775
>>885497
у нас в новосибе есть noveo среди таких, но там надо хотя бы учебник из этого треда знать да, прям блядь так и спрашивают, прошел ли ты учебник из пхп треда на дваче нет
В общем примитивы самые учишь и дуешь к ним на стажировку.
#216 #885777
for($i = 0; $i < 10; $i++) {

if($www == true) {
echo $correctNumbers[$i];
echo "verno ";

почему перед Иф элемент массива показывает, а в иф уже нет? через foreach тоже
>>885970>>886054
#217 #885791
>>885713
Так ты еще и тупой...
>>886021
#218 #885801
Есть ответ к задаче про 3 стула из задачника в шапке?
http://sandbox.onlinephpfunctions.com/code/fe037e0a55113cfd26d1699ec29f03295d2d27f9
Я так сделал
>>885950
#219 #885813
Господа, как мне зайти через куки манагер в соц. сеть, если мне известны куки? Я вбиваю туда куки, запускаю facebook.com, а на страницу от кук не входит и они пропадают потом из манагера.
>>885950
#220 #885850
не могу разобратся в регулярках, что вот тут не правильно например?
/8|(\+ *7)/
в идеале оно должно ловить начало либо с 8 либо с +, потом любое кол-во пробелов, потом 7рка?
>>885852>>885950
#221 #885852
>>885850
Сейчас уже есть примерно такой регексп, не пойму только как сделать, что б любое колво пробелов черточек и дужек между цифрами не ловилось =(
^(8|(\+ *7))[0-9]{10}$
>>885950
#222 #885908
Откуда берётся переменная $content в yii2? Что в ней содержится?
>>885986
#223 #885926
Секунду назад исчез прошлый тред. Можно где-нибудь посмотреть архив?
>>885946>>886835
#225 #885950
>>885850

Тут почти правильно, только нет привязки к началу строки так что он будет искать цифру 8 или + не только в начале, но и в середине.

>>885852

[0-9]{10} значит 10 идущих подряд цифр

Напиши выражение "ровно 1 минус, скобка или пробел". Затем сделай из этого "любое число минусов/скобок/пробелов в любом порядке". затем сделай "1 цифра, за ней любое число минусов/скобок/пробелов" . затем добавь, что это должно повторяться ровно 10 раз.

>>885813

заходи через логин с паролем.

>>885801

Есть. В одном из банков должно получиться около 61270. Срок выплаты по моему там 13 месяцев.

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

В твоем коде число 5000 повторяется много раз. Что если мы захотим его поменять на другое? Надо вынести его в переменную, чтобы оно передавалось при вызове функции.
>>886085
#226 #885970
>>885682

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

>>885777

Можешь дать пример кода на ideone или аналогичном сайте, чтобы видно было, в чем проблема? Я пока не очень понял, что не так.

>>885761

Смелых не нашлось. Перед этой задачей надо пройти задачник по JS и ОП поста, и дойдя до середины, аноны переполняются уверенностью в своих силах и пропадают из треда.

>>885713

Это мусорный комментарий не по теме.

>>885699

В общем, ты мыслишь в верном направлении. Для работы с АПИ действительно удобно сделать объект, методы которого соответствуют вызовам АПИ. Единственное, что имена методов принято начинать с глагола и вместо accountData логичнее писать getAccountData(...), но и странно, что у этого метода нет аргументов - надо же указать, чьи данные мы хотим получить.

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

$apiClient = new TradingApiClient('http://www.api.dev/endpoint');

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

$apiClient->setTimeout(3);
$apiClient = new TradingApiClient('http://', ['timeout' => 3]);

Далее, у АПИ часто бывает авторизация. Как ее реализовать? Тут есть 2 варианта.

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

Ошибки в АПИ (при передаче данных итд) обычно принято показывать с помощью исключений. Разные классы исключений соотвествуют разным видам ошибок.

Ну и еще. В простом варианте конечно можно вписать работу с курлом прямо в класс АПИ, но это в общем плохая идея. Например, как задать дополнительные опции курла, если вся работа с курлом спрятана внутри класса? Очевидно, что здесь имеет смысл разделить код на 2 класса:

- низкоуровневый HTTP клиент
- высокоуровневый API клиент, использующий объект HTTP клиента

(когда ты начнешь писать HTTP клиент, классы запросов и ответов, тебе может придти в голову мысль что наверно такие клиенты уже написаны. И действительно, поиск выдаст тебе множество библиотек, например, Guzzle)

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

Насчет SimpleXML - я бы не советовал особо обольщаться названием simple, у него куча неудобных моментов, наверно удобнее с XML работать через DOM, хотя это твое дело.
#226 #885970
>>885682

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

>>885777

Можешь дать пример кода на ideone или аналогичном сайте, чтобы видно было, в чем проблема? Я пока не очень понял, что не так.

>>885761

Смелых не нашлось. Перед этой задачей надо пройти задачник по JS и ОП поста, и дойдя до середины, аноны переполняются уверенностью в своих силах и пропадают из треда.

>>885713

Это мусорный комментарий не по теме.

>>885699

В общем, ты мыслишь в верном направлении. Для работы с АПИ действительно удобно сделать объект, методы которого соответствуют вызовам АПИ. Единственное, что имена методов принято начинать с глагола и вместо accountData логичнее писать getAccountData(...), но и странно, что у этого метода нет аргументов - надо же указать, чьи данные мы хотим получить.

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

$apiClient = new TradingApiClient('http://www.api.dev/endpoint');

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

$apiClient->setTimeout(3);
$apiClient = new TradingApiClient('http://', ['timeout' => 3]);

Далее, у АПИ часто бывает авторизация. Как ее реализовать? Тут есть 2 варианта.

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

Ошибки в АПИ (при передаче данных итд) обычно принято показывать с помощью исключений. Разные классы исключений соотвествуют разным видам ошибок.

Ну и еще. В простом варианте конечно можно вписать работу с курлом прямо в класс АПИ, но это в общем плохая идея. Например, как задать дополнительные опции курла, если вся работа с курлом спрятана внутри класса? Очевидно, что здесь имеет смысл разделить код на 2 класса:

- низкоуровневый HTTP клиент
- высокоуровневый API клиент, использующий объект HTTP клиента

(когда ты начнешь писать HTTP клиент, классы запросов и ответов, тебе может придти в голову мысль что наверно такие клиенты уже написаны. И действительно, поиск выдаст тебе множество библиотек, например, Guzzle)

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

Насчет SimpleXML - я бы не советовал особо обольщаться названием simple, у него куча неудобных моментов, наверно удобнее с XML работать через DOM, хотя это твое дело.
>>886054>>886183
#227 #885971
>>885699

И обрати внимание, что ты неудачно выбрал название класса.
>>886183
#228 #885975
>>885608

Открой инструменты разработчика (Ctrl + Shift + I) на вкладке Network. Ввведи в адресную строку УРЛ локального сайта и нажми Enter. Посмотри что появится в инструментах разработчика.

>>885690

На хабре врод было что-то https://www.google.ru/search?q=habr+php+анонимные+функции&newwindow=1&gbv=1&sei=N39AWMbjHILN6QSfoqLYCQ

Анонимные функции удобно использовать, когда надо передать какое-то условие, записанное в виде кода. Ну например вместе с array_map, array_filter, preg_replace_callback.
#229 #885986
>>885384

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

>>885908

Если это переменная в шаблоне layout, то подозреваю, что в ней отрендеренный в HTML строку шаблон серединки страницы. Ты код самого Юи смотреть не пробовал и поискать там по этому слову?

>>885497

Есть. Например:

- Школа Анализа Данных Яндекса
- Java школа Дойче Банка

Подробнее https://habrahabr.ru/company/tceh/blog/250333/

Вот например про Дойче Банк (это было в 2013 году, может сейчас поменялось): https://habrahabr.ru/company/changellenge/blog/196664/

> Во время обучения каждый студент получает заработную плату в размере 100 тысяч рублей. Лучшие ученики по окончании Школы приглашаются на работу в Центр Разработки Дойче Банка.



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

При желании на Хабре можно найти отзывы тех, кто например, в ШАД учился.
#230 #886021
>>885791
Ты очень плохой человек. И злой
#232 #886059
>>886054
Вот это регекс!
#233 #886085
>>885950

>заходи через логин с паролем.


нет, мне нужно через куки)
#234 #886183
>>885971
>>885970
Спасибо тебе за такой полный ответ. SimpleXML был выбран просто как пример. Имя Api знаю что не сильно хороший выбор, но пока это не имеет значения.
Я понял твои мысли насчет разделения и думаю действительно так и сделать, я просто не понимаю как мне использовать другие классы в моем. Мне просто создать где-нибудь вне методов объект того-же HTTP клиента и DOM? Или наследовать? Если наследовать то что? Мне нужен и HTTP и DOM одновременно. Вернее последовательно, сначала первое, потом второе.
>>886737>>886740
#235 #886189
PHPч, PAMAGI.
Есть файл, в котором csv-данные. Есть задача - перенести данные в MySQL-БД. Запихиваю данные через подготовленные запросы с параметрами (пробовал как именованные, так и анонимные) посредством PDO. Всё бы хорошо, но один из столбцов в csv-файле - дата в формате "дд.мм.гггг", и эта сука постоянно делает дату 0000:00:00 (вот что то меня немного напрягает, что формат другой - не ДД.ММ.ГГГГ, как в csv-файле, а ГГГГ,ДД,ММ или ГГГГ.ММ.ДД). Так вот, вопрос - как запихать в MySQL строковое представление даты в столбец с типом Date?
>>886193>>886230
#236 #886193
>>886189
strtotime
>>886196
13 Кб, 300x200
#238 #886198
>>886196
php.net не читай, функцию применяй
#239 #886199
Какие сейчас на рынке самые востребованные фреймворки?
>>886201
#240 #886201
>>886199
yii, laravel, symfony, 1с битрикс
#241 #886230
>>886189
>>886196
всё, отбой, разобрался.
#242 #886274
Аноны, такой вопрос.
Каким образом формируются веб-странички для каждого из элементов списка?
Например интернет-магазин. Есть список товаров, для каждого товара отдельная страничка формируется. Но я так понимаю на сервере для каждого элемента не создается файл "id12344567.php", а как-то динамически туда данные идут. В какую сторону копать?
>>886286
#243 #886286
>>886274
Это и есть так сказать эссенция веб-разработки, и то чем мы тут занимаемся.

Есть сервер, на котором верится скрипт, в нашем случае это пхп.

И например там есть "страничка", которая называется show_item.php в которой будет лежать скрипт, ответственный за то, что ты сказал.

Например так же у тебя есть база, в которой лежат товары, у них есть id, name, price например

Когда пользователь бегает по каталогу, ему опять же скрипт, формирует хитрые ссылки, по которым можно пройти на каждый товар.
ссылка будет вида shop.sru/show_item.php?id=123

Чувак кликает по этой ссылке, скрипт который сидит в show_item.php видит что прилетел get запрос: https://ru.wikipedia.org/wiki/HTTP#GET
(бывают и другие способы спросить что-то у сервера)

И он значит понимает (потому что программист так запрограммировал заранее), что нужно из базы спросить инфу о товаре с таким id
он отправляет в базу запрос что-то вида ВЫБРАТЬ ИЗ таблица_товаров, ГДЕ id = 123.
Прилетает ответ от базы с информацией о товаре с нужным id которая лежит в полях name и price (полей может туча)

далее скриптик берет заранее заготовленную html-ку (шаблон) и подставляет в нужные места всю информацию в этот шаблон.

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

В теории всё будет примерно так. Даже на дваче всё на этом же принципе. Посты хранятся в базе. Спрашиваешь у базы все посты такого-то треда. Он собирает их в кучу и отрисовывает тебе по порядку циклом.
>>886353>>886359
#244 #886353
>>886286
Да, база есть, но я именно на могу понять как формируются отдельные странички для каждого элемента. Я могу тупо выгрузить, скажем, в индекс, табличку с базы, можно там с определенными параметрами.
Могу также допустим к тексту позиции присобачить уникальный урл(ну можно по тому же айдишнику)
Но как сделать так, чтобы кликая на этот урл я переходил бы на страничку, где отображалась конкретная информация по определенной записи?
Какой модуль копать? Или может есть какие примеры? Как ни гуглю, а найти не могу.

Или вот пример. Могу сделать блог, с добавлением записей. Но как сделать так, чтобы каждая запись была доступна отдельно? То есть получается на ходу формируется страничка, а там уже выгрузка по определённым параметрам?
>>886453>>886725
#245 #886359
>>886286
А, прости, не развернулся полностью пост. Значит скрипт и шаблон. Будем копать
>>886453
#246 #886430
Как правильно открывать и закрывать подключения к MySQL c использованием PDO? В интернете разное пишут.

Конкретные пункты:

1) Можно ли написать класс, с помощью которого, передавая различные аргументы - опции подключения через __construct() мы будем создавать и возвращать PDO-подключения с нужными параметрами, а также закрывать их когда хотим (как раньше $mysqli->close())? Или это черезчур?

2) Если: $a = new PDO(); $b = $a; $a = null; , экземпляр подключения сохраняется, так как есть на него ссылка $b. Как реально убить подключение (ведь, возможно, у нас десятки таких ссылок разбросаны по программе).

3) Не париться, ибо все подключения завершаются по окончании скрипта (все ли?), а вручную закрывать вредно в принципе. Есть ли какие подводные камни?
>>886721
#247 #886453
>>886359
>>886353

ты можешь хоть самим скриптом генерировать html после того как собрал все нужные тебе данные, тупо через примерно такой вот способ:
echo '<html>';
echo '<head>';
...
и потом подставляя переменные где нужно прям в это всё
echo '<p>наименование товара: ' . $name . ' </p>;
...
echo '</body>;
echo '</html>;
//конец скрипта
?>
Но это самый примитивный способ, что бы ты просто понял как это работает.

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

//отдельный_документ-шаблон.php
<html>
.....
.....
<p>Наименование товара: <?=$item_name?></p>
...
>>886740
#248 #886623
Торможу и никак не могу вспомнить для чего и как применяется наследование __construct Вот например здесь http://ideone.com/vJVWeb можно через наследника спокойно задать все необходимые свойства, для чего и как используется parent::__construct ?
#249 #886634
>>886623
если бы у тебя в родительском классе было бы больше полей/свойств, да ещё и часть из них были бы private, то тогда тебе было бы более выгодно/пришлось бы вызывать родительский конструктор, которому ты бы передал соответствующие параметры из конструктора класса-наследника.
>>886641
#250 #886641
>>886634
Спасибо, тебе вспомнилось
#251 #886721
>>886430

> Можно ли написать класс, с помощью которого, передавая различные аргументы - опции подключения через __construct() мы будем создавать и возвращать PDO-подключения с нужными параметрами,


Этот класс уже написан, он называется PDO. Ему в конструктор как раз передаются параметры соединения. Зачем писать еще один?

> Если: $a = new PDO(); $b = $a; $a = null; , экземпляр подключения сохраняется, так как есть на него ссылка $b. Как реально убить подключение (ведь, возможно, у нас десятки таких ссылок разбросаны по программе).


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

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

Бывают случаи, когда приложение обрабатывает не один запрос, а много, в цикле, не умирая. Ну например приложения на Яве или на ReactPHP так работают. В таких случаях надо подсоединяться/отсоединяться от БД. Обычно для этого реализуют так называемый "пул". Пул позволяет как создавать каждый раз новое соединение, так и вместо закрытия возвращать соединение в пул и использовать позже.

Вот пример (англ) пула соединений на Яве:

http://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html#How_to_use

(JDBC это Ява-библиотека для взаимодействия с разными БД, напоминающая PDO)

(кстати ниже, под заголовком "And here is an example on how to configure a resource for JNDI lookups" ты можешь увидеть пример XML-конфигурации для DI контейнера в Яве).

Вот ключевое место кода на Яве:

// создаем объект настроек пула
PoolProperties p = new PoolProperties();
....
// создаем пул и задаем его настройки
DataSource datasource = new DataSource();
datasource.setPoolProperties(p);

try {
// получаем из пула новое или, может быть, старое соединение (аналог PDO)
con = datasource.getConnection();
// создаем объект запроса (аналог PDOStatement)
Statement st = con.createStatement();
// выполняем запрос
ResultSet rs = st.executeQuery("select * from user");
...
// освобождаем результат и запрос
rs.close();
st.close();
} finally {
// в любом случае (даже при выбросе исключения) закрываем соединение
if (con!=null) {con.close();}
}

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

В некоторых языках, вроде C#, можно обойтись без ручного написания этих close(), там есть конструкция using ( https://msdn.microsoft.com/ru-ru/library/yh598w02.aspx ), которая говорит что объект нужно "очистить" при выходе из блока:

using (con = datasource.GetConnection()) {
using (st = con.createStatement()) {
...
}
}

Это упрощает код и защищает от ошибок, когда что-то забыли закрыть.

В PHP для этого вместо пулов можно использовать persistent connections. Надо помнить, что хотя ты экономишь время на установку соединения, у этого подхода есть недостатки. Что если один процесс PHP оставит соединение в каким-то измененном состоянии, например оставит незакрытую транзакцию или поменяет какую-то переменную MySQL? Может быть баг. В Яве это чуть упрощается за счет того, что там ведется учет открытых/закрытых транзакций.

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


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

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


Никаких, так и делают. Просто это не работает, если ты обрабатываешь не один, а много запросов в цикле. Тогда тебе понадобятся пулы и явное закрытие соединения. Тут конечно в PDO отсутствие close не очень удобно и возможно стоит использовать что-то на основе mysqli.
#251 #886721
>>886430

> Можно ли написать класс, с помощью которого, передавая различные аргументы - опции подключения через __construct() мы будем создавать и возвращать PDO-подключения с нужными параметрами,


Этот класс уже написан, он называется PDO. Ему в конструктор как раз передаются параметры соединения. Зачем писать еще один?

> Если: $a = new PDO(); $b = $a; $a = null; , экземпляр подключения сохраняется, так как есть на него ссылка $b. Как реально убить подключение (ведь, возможно, у нас десятки таких ссылок разбросаны по программе).


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

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

Бывают случаи, когда приложение обрабатывает не один запрос, а много, в цикле, не умирая. Ну например приложения на Яве или на ReactPHP так работают. В таких случаях надо подсоединяться/отсоединяться от БД. Обычно для этого реализуют так называемый "пул". Пул позволяет как создавать каждый раз новое соединение, так и вместо закрытия возвращать соединение в пул и использовать позже.

Вот пример (англ) пула соединений на Яве:

http://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html#How_to_use

(JDBC это Ява-библиотека для взаимодействия с разными БД, напоминающая PDO)

(кстати ниже, под заголовком "And here is an example on how to configure a resource for JNDI lookups" ты можешь увидеть пример XML-конфигурации для DI контейнера в Яве).

Вот ключевое место кода на Яве:

// создаем объект настроек пула
PoolProperties p = new PoolProperties();
....
// создаем пул и задаем его настройки
DataSource datasource = new DataSource();
datasource.setPoolProperties(p);

try {
// получаем из пула новое или, может быть, старое соединение (аналог PDO)
con = datasource.getConnection();
// создаем объект запроса (аналог PDOStatement)
Statement st = con.createStatement();
// выполняем запрос
ResultSet rs = st.executeQuery("select * from user");
...
// освобождаем результат и запрос
rs.close();
st.close();
} finally {
// в любом случае (даже при выбросе исключения) закрываем соединение
if (con!=null) {con.close();}
}

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

В некоторых языках, вроде C#, можно обойтись без ручного написания этих close(), там есть конструкция using ( https://msdn.microsoft.com/ru-ru/library/yh598w02.aspx ), которая говорит что объект нужно "очистить" при выходе из блока:

using (con = datasource.GetConnection()) {
using (st = con.createStatement()) {
...
}
}

Это упрощает код и защищает от ошибок, когда что-то забыли закрыть.

В PHP для этого вместо пулов можно использовать persistent connections. Надо помнить, что хотя ты экономишь время на установку соединения, у этого подхода есть недостатки. Что если один процесс PHP оставит соединение в каким-то измененном состоянии, например оставит незакрытую транзакцию или поменяет какую-то переменную MySQL? Может быть баг. В Яве это чуть упрощается за счет того, что там ведется учет открытых/закрытых транзакций.

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


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

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


Никаких, так и делают. Просто это не работает, если ты обрабатываешь не один, а много запросов в цикле. Тогда тебе понадобятся пулы и явное закрытие соединения. Тут конечно в PDO отсутствие close не очень удобно и возможно стоит использовать что-то на основе mysqli.
#252 #886725
>>886623

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

Если ты определил в наследнике конструктор, то автоматически конструктор предка не вызывается.

>>886353

- пользователь набирает в браузере УРЛ http://example.com/product/123
- браузер отправляет на HTTP сервер HTTP-запрос
- сервер запускает PHP скрипт
- скрипт смотрит на УРЛ и видит что надо показать страницу товара № 123
- он берет из БД свойства этого товара
- он берет HTML шаблон страницы и подставляет туда свойства товара
- отдает ответ в браузер

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


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

Прочти например это: https://github.com/codedokode/pasta/blob/master/soft/web-server.md
#253 #886734
Какой фреймворк посоветует учить анон? Yii или Laravel?
>>886835
#254 #886737
>>886623

> можно через наследника спокойно задать все необходимые свойства



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

>>886183

Ты читал урок по DI? Прочитай: https://github.com/codedokode/pasta/blob/master/arch/di.md

"HTTP клиент" - это зависимость для класса Api и урок как раз разбирает, как их связать.

Наследование используют только тогда когда можно сказать "A является разновидностью B". ApiClient это не разновидность HTTP клиента или DOM и наследование тут применять нельзя.
>>886899
#255 #886740
>>886453

Где htmlspecialchars? Вот люди по таким примерам учатся, а потом оставляют XSS.

>>886196

С таким количество параметров удобнее использовать плейсхолдеры с двоеточием и передавать массив в execute.

>>886183

Объект DOM, я думаю, тут не зависимость, так как он просто создается заново на каждый документ через new.

>>886054

> {1,}


Это то же самое, что и плюс

> ((-| )?[()]?){1,}


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

Вместо повторения выражения 10 раз надо использовать {10}.
>>886899
#256 #886803
>>885072

> Я из скриншота вижу, что правило в файле uploader-master.css перекрывает правила в бутстрапе. Приоритет у них равный, скорее просто причина в том что тот файле позже подключен.



Я понял. В скачаном плагине был такой же селектор, как и в бутстрапе
2 Кб, 625x26
#257 #886814
Скобки после скобок? Такое возможно?
>>886835
#258 #886835
>>886814
Конечно возможно, для этого функция должна возвращать функцию. Можно даже строить цепочки произвольной длины.
У Кантора, например, об этом написано.

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

>>885926
Ещё есть на архиваче: https://arhivach.org/thread/213097/
>>886953
#259 #886899
>>886737
>>886740
То есть его нужно создавать в классе?
#260 #886953
>>886835

>Посмотри, на что спрос у тебя в городе


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

Хочу чтобы анон сказал с аргументами а я подчинился пусть и субъективное мнение
#261 #886975
вот такой вот у меня регек:
^[ ]?(8|(\+ 7))(([-]|[(]|[)]|[ ])[0-9]([-]|[(]|[)]|[ ])*){10}$
Я даун или маладца?
>>886978
#262 #886978
>>886975
криво скопировалось
http://ideone.com/FMacU9
#263 #886982
Зашел на http://www.yiiframework.com/download/

хотел скачать дистрибутив себе для винды что бы научиться в халоворлд, а хуй там плавал, архивы в формате tgz, ладно няши из 7zip предусмотрели это и с их помощью можно открыть архив, но хуй там плавал и внутри был лишь TAR файл. Хотя и его вроде как можно открыть. Но блин, что это за флагман такой, который не может иметь дистрибутив под винду :(
>>886986>>886989
#264 #886986
>>886982

gz - это сжатие, но gzip умеет сжимать только один файл
tar - это формат для сборки нескольких файлов в один (с сохранением имен и других метаданных), но без сжатия

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

Форматы довольно старые, им лет 20, если не больше.
#265 #886988
Что не так, ребята? Пишет что в строке с if ошибка, но я чет не понимаю какая. http://ideone.com/fGnpUt
>>886999
#266 #886989
>>886982

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

- PHP в принципе кроссплатформенный и не нужна отдельная версия под винду
- на сервере обычно стоит Линукс
#268 #886999
>>886988
Помогите ньюфагу, очень прошу.
>>887005
#269 #887005
>>886999

>PHP Notice: Undefined variable: totalPayed2 in /home/SWobaS/prog.php on line 28


>PHP Notice: Undefined variable: totalPayed3 in /home/SWobaS/prog.php on line 28


неопределенные переменные в строке 28, так так что же там у нас???

>$totalPayed1=credit($balance, $monthly, $percents[0], $comission[0]);


>//$totalPayed2=credit($balance, $monthly, $percents[1], $comission[1]);


>//$totalPayed3=credit($balance, $monthly, $percents[2], $comission[2]);


>echo "first: $totalPayed1 second: $totalPayed2 third: $totalPayed3 \n";



Ну всё очевидно блядь, эти переменные неопределятся потому, что должны быть определены в тех строчках которые закоменченны, элементрано.
>>887008
#270 #887008
>>887005
Я уже разобрался, это я сейчас редактирую код просто вот и закомментил эти строки. Все равно спасибо.
>>887018
#271 #887018
>>887008
Так, я сделал задачу, а где сравнить ответы? На сайте они замазаны.
>>887027
#272 #887027
>>887018
Если что задача про айпад из раздела "Функции".
#273 #887037
Собираюсь в этом месяце полностью выучить пых. знаю только синтаксис + порешал пару задачек из оп-поста
Вопрос : смогу ли я через месяц обучения написать движок для имиджбода?
>>887042>>887270
#274 #887042
>>887037
имиджборда

фикс
#275 #887270
>>887037
Сможешь, но будешь долго ковыряться и учиться в процессе написания. И это не плохо, так как практика. Только через полгода-год тебе будет стыдно за этот код.
#276 #887300
Хочу стать back end разработчиком, что для этого знать надо?
>>887349
#277 #887308
http://lurkmore.to/Php
Чет почитал и расстроился посоны.
#278 #887348
>>887308
А чего расстроился? Вообще похуй что там пишут.
#279 #887349
>>887300
знать как пользоваться гуглом
#280 #887381
>>887308
вот про неймспейсы хорошо, например, почти как у опа. https://habrahabr.ru/post/212773/
Вдруг кому поможет.
#281 #887386
[code lang="php"] echo "hello, world"; [/code]
#282 #887387
[code] echo "hello, world"; [/code]
#283 #887390
Ребят, доброй ночи. Подскажите, нормально ли реализовал блокировку просроченных заказов
http://pastebin.com/mJd4vdxz
>>887490
#284 #887476
>>887308
Чего расстроился-то? Мы быдлокодеры, гордись этим!
#285 #887490
>>887390
Какая-то критика на самом деле странная. Ну вот например

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


Ну и что? По моему это плюс. К тому-же у Objective-C, Swift, и С++ тоже самое, но никто не жалуется. Я уже не говорю про JAVA, где вообще можно всю программу написать вызовом стандартных функций.

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


>var_dump($php == "хуита");


Написал говнокод.
@
Это PHP виновато что он работает не так, как я хочу.

>Переменные по умолчанию могут быть не объявлены;


Вообще не проблема.

>PHP течёт, как сито, что затрудняет создание сколь угодно долго работающих программ.


Потому-что PHP не предназначен для написания программ. Есть C++ и C#, нет мы хотим страдать.

>Отсутствует такая кошерная вещь, как CPAN в perl, которая позволяет огромному числу разработчиков по всему миру писать новые либы в составе комьюнити. Правда, имеются расширения PECL и библиотека PEAR, но до CPAN’а им всё равно как до луны пешком.


Вообще бред чистой воды. PHP стал популярен только потому, что может в расширения, и под него написано 100500 расширений. А CPAN удобен только если им долго учиться пользоваться.
>Всё-таки отсутствует многопоточность — потоков как таковых нет
Чтобы многопоточно отдавать данные из БД одному юзеру? Что?

>Большие проблемы с реализацией utf-8.


Одна единственная проблема, в том, что он по дефолту не UTF-8 и надо явно указывать кодировки. 1 строка кода это недостаток?
>>887554
#286 #887514
Проверьте задачу на функции
http://ideone.com/rW81Hw
>>887545
#287 #887545
>>887514
http://ideone.com/OAyQXi
быстрофикс. не сразу осилил константу
#288 #887554
>>887490

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

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



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

В то время как в популярных языках Питон, Руби, Лисп, Яваскрипт вообще их нету. Но про них почему-то такую критику не пишут. Свое бревно не видят.

> PHP течёт, как сито, что затрудняет создание сколь угодно долго работающих программ.


Это было акутально до появления сборщика мусора в 5.3.

> Отсутствует такая кошерная вещь, как CPAN в perl, которая позволяет огромному числу разработчиков по всему миру писать новые либы в составе комьюнити. Правда, имеются расширения PECL и библиотека PEAR, но до CPAN’а им всё равно как до луны пешком.



Опять же информация устарела. Есть PECL, (старый) PEAR и новый composer. С этим как раз все в порядке.

> Большие проблемы с реализацией utf-8.


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

А вообще, вот набор претензий для троллинга других языков: https://habrahabr.ru/post/315152/
>>887566
#289 #887566
>>887554

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


Двачую.
#290 #887599
И мое проверьте. Задание "Пиши верно". Делал не как оп в подсказке написал, подсказку увидел только после того как сам доделал.
http://ideone.com/Mc3n1q
#291 #887753
PHPч, расскажи мне, как разрулить следующую ситуацию:
есть код jQuery, который через ajax обращается к PHP скрипту с некоторыми параметрами посредством гет-запроса (https://jsfiddle.net/x9no97vd/1/).

Дак вот, что мне нужно сделать так, чтобы при определенном условии в ходе работы php скрипта я отсылал ошибку ajax'овой функции, причем вызывалась бы именно функция - параметр "error:" ajax-овой функции. Как это сделать? Пока что я знаю только о следующем способе обмена информацией между сервером и клиентом посредством связи PHP-AJAX: на PHP при вызове некоторо скрипта ajax'ом весь вывод от "echo 'somehtml';" попадает в параметр result у AJAX'а.
>>887814
#292 #887814
>>887753

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

Удобно возвращать в JSON-ответе либо поле success = true если все ок (а в поле html - HTML-код), либо такой ответ при ошибке:

{
"success": false,
"error": "....."
}

Но в твоем случае, как я понимаю, там даже не ошибка, а признак, что данных больше нет. Раз так, надо возвращать с ответом флаг "haveMore": true/false. Узнать, есть ли еще данные, просто: надо просто выбирать из БД на 1 запись больше, чем просят.

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

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

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

> $("#tableDIV").find("table").find("tbody").find("tr:last-child")


Это можно написать одним выражением. table и tbody не нужно указывать.

> '../phps/database stuff/GetTablePage.php?page='+ CurrentPage++ + "&FetchType=2"


Не стоит совмещать в одной строке увеличение переменной и сборку URL. Также вместо ручной сборки лучше параметры передавать в свойстве data функции $.ajax

> FetchType=2


Магические числа

> if (data!="")


А что если равно пустой строке? Это никак не обрабатывается.

> if (errorThrown=="ALL_DATA_LOADED")


Это еще что? errorThrown это же вроде объект исключения

Кстати, у нас есть задачки по JS и JQuery в ОП посте.
#292 #887814
>>887753

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

Удобно возвращать в JSON-ответе либо поле success = true если все ок (а в поле html - HTML-код), либо такой ответ при ошибке:

{
"success": false,
"error": "....."
}

Но в твоем случае, как я понимаю, там даже не ошибка, а признак, что данных больше нет. Раз так, надо возвращать с ответом флаг "haveMore": true/false. Узнать, есть ли еще данные, просто: надо просто выбирать из БД на 1 запись больше, чем просят.

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

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

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

> $("#tableDIV").find("table").find("tbody").find("tr:last-child")


Это можно написать одним выражением. table и tbody не нужно указывать.

> '../phps/database stuff/GetTablePage.php?page='+ CurrentPage++ + "&FetchType=2"


Не стоит совмещать в одной строке увеличение переменной и сборку URL. Также вместо ручной сборки лучше параметры передавать в свойстве data функции $.ajax

> FetchType=2


Магические числа

> if (data!="")


А что если равно пустой строке? Это никак не обрабатывается.

> if (errorThrown=="ALL_DATA_LOADED")


Это еще что? errorThrown это же вроде объект исключения

Кстати, у нас есть задачки по JS и JQuery в ОП посте.
>>887829
#293 #887822
Учу Ларавел. В этом туториале http://laravel.su/docs/5.2/quickstart говорят создать файл app/Http/routes.php и прописывать роуты в нём. Я создал и прописал, но роуты, очевидно, не работают - ведь этот файл нигде не вызывается. Я неправильно прочитал туториал или там ошибка? Как надо сделать?
#294 #887829
>>887814
Спасибо за совет по поводу JSON, сейчас пока ждал ответа тоже наткнулся на него в похожих вопросах на SO.

>У тебя вроде нет блокировок. Что, если пользователь прокруткой отправит несколько параллельных запросов, и данные придут в другом порядке? Надо блокировать отправку запросов на время загрузки.



Блокировку ajax'а достаточно реализовать переменной-флагом, который переключаю в false в ajax'овском параметре-функции beforesent и в true в параметре-функции complete?

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



Та це не мой каприз, так поставлена задача в лабораторной. Я думал, что было бы неплохо реализовать выгрузку лишних первых 100 строк данных из html при прокрутке вниз на 500-600 строк, ну и соответственно их обратную подгрузку при скроллинге вверх а потом посмотрел на аналогичную систему в вконтактике и подумал, что для лабораторной и так сойдёт. Будет ли такой вариант сильно плох, если в таблице не предусмотрена возможность редактирования, то есть не нужно хранить состояние измененных строк при их выгрузке?

>Это можно написать одним выражением. table и tbody не нужно указывать.


разве не лучше сужать пространство для работы each()? Она же вроде как собирает ссылки на все соответствующие html-элементы, следовательно, ей надо пробежать по всему document'у для этого, типа лишние задачи вседела тыры-пыры.

>Не стоит совмещать в одной строке увеличение переменной и сборку URL. Также вместо ручной сборки лучше параметры передавать в свойстве data функции $.ajax


це я знаю, просто только изучаю ajax, ну и реализовал все способы его использования, которые смог найти $("element").load(), $.get(),$.ajax() у jQuery, XMLHttpRequest с чистого js c различными параметрами.

>Магические числа


Вот тут не понял, типа плохой тон передавать неименованными константами какую либо информацию?
>>887839
#295 #887832
http://ideone.com/GBiMK2 echo сервер
http://ideone.com/cJR4UT клиент загрузчик.
>>887862
#296 #887839
>>887829

> Я думал, что было бы неплохо реализовать выгрузку лишних первых 100 строк данных из html при прокрутке вниз на 500-600 строк



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

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

> Блокировку ajax'а достаточно реализовать переменной-флагом, который переключаю в false в ajax'овском параметре-функции beforesent и в true в параметре-функции complete?


Да.

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

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


Это разве все? Ты официальный мануал jQuery не пробовал открыть? Там еще куча функций и параметров.

> Вот тут не понял, типа плохой тон передавать неименованными константами какую либо информацию?


Глядя на код трудно понять, что значит эта цифра. Текст был бы лучше, а константа - еще лучше.
#297 #887848

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


Nyet, а что может пойти не так? Для мобильных браузеров как то иначе обрабатываются scrollTop() или document.height() и window.height() расчитываются не так, как на десктопных браузерах?

>Это разве все? Ты официальный мануал jQuery не пробовал открыть? Там еще куча функций и параметров.



я про вышеперечисленные ajax'овские собсно на http://api.jquery.com/ и смотрел. Просто, возможно, под мою задачу мне приглянулись именно те функции, сейчас уже не вспомню.
#298 #887862
>>887832

В задаче "echo server" есть функция readSocket, как она должна работать по задумке? Я вижу там yield, как это должно использоваться?

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

Во второй задаче, почему не используешь функции socketRead/Write из первой?

> (.*)[;\r\n]


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

> $response = preg_split('/\r\n\r\n/', $response);


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

> $file = fopen(__DIR__ . '/test' . $extension, 'wb');


есть file_put_contents

Также, ты не учел что ответ может быть передаваться с кодировкой вроде Transfer-Encoding: chunked. Или это не требовалось в задании?

> while ($out = socket_read($socket, 2048)) {


Это неправильный код, так как при чтении пакета с байтом "0" он примет его за конец данных.

Также не проверяются ошибки которые могут возникнуть в процессе чтения.
#299 #887886
Кстати, в контексте работы с таблицами и вообще большими объемами невизуальной в плане не связанной с версткой информации, какой вариант предпочтительней в плане быстродействия если такой вообще есть:
1. На сервере подготавливать информацию в json-объект, и отсылать клиенту его, и чтобы на стороне клиента посредством JSON.Parse() распарсить json-пакет и модифицировать информацию внутри json-пакета по необходимости ну, например, в случае работы с таблицами - добавлять для каждого объекта <tr></tr>, и для каждого параметра - <td></td>
2. Прям в php подготавливать информацию и обрамлять её соответствующими html-элементами и посылать пользователю уже готовый блок html-разметки, только вставляй её в нужное место.
>>887889
#300 #887889
>>887886

Подозреваю, что особой разницы нет. А так, можешь сделать и сравнить.

Первый вариант называется "шаблонизация на клиенте" и на практике там просто дописать tr/td будет недостаточно. Как миниумм надо еще спецсимволы экранировать.
23 Кб, 730x236
#301 #887957
Что за хуйня? В PHP что, переменные, объявленные в функции не видны в if-блоках?
>>887958>>887974
#302 #887958
>>887957
Ты читать не умеешь? Ясно же написано "не используется" - это значит не считывается нигде. Ты ее только пишешь, а не читаешь.
#303 #887974
>>887957

Ну и еще у тебя проблема, что ты используешь какие-то магические числа вместо констант. И еще вдобавок глобальные переменные. Да еще и большими буквами написанные.
#304 #888015
Оп, посмотри пожалуйста мое поделие: github.com/fidnex/filehost
#305 #888155
Есть ли в этом языке сотоны нормальный способ забить массив латинскими буквами? В C я с хз какого класса писал
for (int i = 0; i < 26; i++) alphabet = i + 65;
и оно работало.
А в php везде в ручную забивают. Как-то поуебански, не?
#306 #888165
>>888155
Тоесть ты не знаешь способа забить автоматом, и в этом, по твоему виноват язык? Ты вообще нормальный?

>А в php везде в ручную забивают.


Где везде то? В учебнике опа 100500 примеров автоматического забивания.
#307 #888179
ну чо здарова пыхепач, сразу с платины начну, чому я ни могу в архитектуру и патерны? Понимаю синглетон, понимаю мвс, датамаперы, актив рекорды. Но когда дело доходит до создание структуры кода, получается какая то костылепараша. Уже года три как пытаюсь раскурить, да юзал ларавели, юии, ки, могу на них сайт пилить, расширять в рамках их архитектуры по образу и подобию, но стоит попытаться свой модуль писать, тоска и уныние, этот код только в горы бросать в воду. Есть тут аноны с похожим?
#308 #888180
>>888179
Довен, когда там тебя уже с зоны на свободу выпустят?
>>888182
#309 #888181
>>888155
Ебать дибил.
75 Кб, 640x1136
#310 #888182
#311 #888183
>>888155
пиздец а у меня не все так плохо походу
>>888179 - кун
0 Кб, 512x490
#312 #888192
>>888155

>забить массив латинскими буквами


>for (int i = 0; i < 26; i++) alphabet = i + 65;

48 Кб, 668x610
#313 #888244
Что за алгоритмы?
>>888245
#314 #888245
>>888244
Очевидно они хотят человека который знает О нотацию и умеет разработать или выбрать оптимальный алгоритм для поставленой задачи.
>>888249
#315 #888249
>>888245

>О нотацию и умеет разработать или выбрать оптимальный алгоритм


На этом месте поподробнее объяснить можешь?или информацию какую-то скинуть.
>>888449
#316 #888250
JS задачи
15 http://ideone.com/vNpDUL
16 http://ideone.com/7wtxZj

Зацените, плиз
#317 #888266
>>888179
ну чо пехепач, бампчик, как дальше развивацо то епт, а то скурвлюсь и пойду битрикс макакой от безысходности, выручайти. Потом сами спасибо скажите, когда мой код перенимать на поддержку будете.
>>888267
#318 #888267
>>888266
покури cms, modx, вордпресс. Вкатись к кому-нибудь джуниором, да задай вопросы.
разбери чужой код и посмотри как там устроено.
>>888270
#319 #888270
>>888267
раскуривал уже, дак чо просто копировать чужой код? точнее его логику? Был жуном, хз все отвечают абстрактно в стиле все абстрактно и зависит от ситуации.
Вротпрес помоему не самая лучшая архитектура.

Раскуривал исходники ларавели кодигнайтера юи, да там все круто, но типа как самому хотябы на 1% так же писать.
>>888271>>888288
#320 #888271
>>888270
Решай задачи про файлообменник и тест.
>>888508
#321 #888288
>>888270
Я бы тебе обьяснил, если бы сам до этого дошел, лол.
>>888503
someApprentice #322 #888303
>>884415

>Напомню, что надо глянуть https://github.com/someApprentice/maintaskforlayout из >>874239 .


У меня вроде бы всё проверенно. Только сейчас начну всё исправлять из прошлого треда, так что с этим можно не торопиться.
33 Кб, 293x457
34 Кб, 293x457
#323 #888312
Почему во втором случае ничего не получается?
>>888317
#324 #888317
>>888312
И почему в первом случае есть пробелы перед и после х, а во втором нет?
>>888400
#325 #888389
Помогите понять в каком формате закодированы
http://ideone.com/lpZyA8
массивы с именами text и value?

Как их декодировать в вид обычного php-массива??
>>888399
#326 #888399
>>888389
Попробуй unserialize($array['text'])
>>888929
#327 #888400
>>888317
Потому что в первом случае ты выводишь значение выражения $a x $a в переменной $b, а во втором выводишь строку "$a x $a". Переменная $b так же преобразуется в строку,потому что ты берешь её в кавычки "$b", и переменные $a, они тоже становится строкой. А в строковом значении выражения не выполняются, потому что, привычные для нас операторы, операторы, это тоже строки, т.е. просто символ, например, + или -.
>>888420
#328 #888420
>>888400
Что-то понял, спасибо. А можно этот пример решить без создания переменной $b?
>>888581
73 Кб, 902x1200
#329 #888449
#330 #888475
Компадрес, для HTML есть какой нибудь инструмент-аналог инструмента в Visual Studio, который позволяет брать контролы из списка, накидывать их на сетку, а потом автоматически генерирует соответствующую разметку?
>>888479
#331 #888479
>>888475
К сожалению нету.
#332 #888503
>>888288
и до чего же ты дошел?
#333 #888508
>>888271
ну тип я в детстве написал еще файло объебник, говнокодище говнокодское, недавно пытался сделать коменты типа с ветвями как на хубре, у сука напилил там дата маперов , моделей, контролеров, дбконекторов, еще пару синглетонов. Сказать что я ахуел ниче не сказать бошка готова была взорваться. Я начал путаться среди этого говна и сходить с ума. Поэтому дропнул.

Как избежать такого дерьма?
#334 #888510
>>888508
и нет я не шизик
#335 #888524
проверьте задачу на функции плес
http://ideone.com/OAyQXi
>>888579
#336 #888579
>>888524
быдлокод
#337 #888581
>>888420
Конечно. Достаточно не преобразовывать выражение в строку (не ставить кавычки): echo $a + $b;
Если нужно что-то ещё вывести можно разделить с помощью разделителя . : echo "$a + $b = " . $a + $b . "\n";
>>888622
#338 #888599
>>888508
Решать задачи и показывать свой код в этом треде
>>888678
#339 #888622
>>888581
Спасибо большое, получилось.
#340 #888678
>>888599
ы чо за фетиш у вас на чужой говнокод?
ну типа решу и чо будет дальше я просветление получу?
#341 #888737
Господа, есть такой массив.

array (size=2)
0 =>
array (size=1)
'foo' => string 'Test' (length=4)
1 =>
array (size=1)
'bar' => string 'Test' (length=4)

Как мне проверить и вывести тру, если значения у foo и bar cовпадают?
>>888739
#342 #888739
>>888737
выложи нормальный код
>>888744
#343 #888744
>>888739
["0"=>["foo"=>"test"], "1" => ["bar"=>"test"]]
как мне проверить, что значения foo and bar совпадают?
>>888750
#344 #888750
>>888744
$a = ["0"=>["foo"=>"test"], "1" => ["bar"=>"test"]];
if ($a[0]['foo'] == $a[1]['bar']) {}
>>888754
#345 #888754
>>888750
ты дебил что ли? массив формируется динамически таких значений там может и не быть. для этого есть проверка.
>>888759
#346 #888759
>>888754
эт ты дебил,как ты спросил так тебе ответили, пшел нах отсюда щенок
#347 #888805
ну чо анонасы, я докатился, буду битрикс делать вскоре, прохожу собеседование скоро. Можете обоссать, мне похуй, где тут тред зашквареных?
>>888807
#348 #888807
>>888805
тоже иду на собес в битрикс
>>888812>>888814
#349 #888812
>>888807
пздц докатились да? Изучал пхп думал буду супер сеньером архитектором пхп, и вот сижу дрочу шляпу и ковыряю инфаблохи
>>888841
#350 #888814
>>888807
почаще говори про папку локал на собеседовании они это любят ты сразу в глазах чуваков гуру битрикса становишся
#351 #888840
>>880700 (OP)
бля я не могу средствами пхп распарсить джейсон, они че прикалываются такие тестовые присылать? на жаве или жс это вообще легко библиотеками делается. пиздец какой-то уже второе такое тестовое.
#352 #888841
>>888812
да это лучше чем джейсон пхп парсить. наверное.
алсо решите мне задачку на собес плз
https://2ch.hk/pr/res/882422.html#888476 (М)
>>888873
#353 #888872
>>888840
тоисть ты не можешь http://php.net/manual/ru/function.json-decode.php
сделать? скожи сколько процентов мозга у тебя ампутировали и пощему?
>>888873
#354 #888873
>>888841
и чо там решать юзаешь >>888872
потому по масиву гоняешь лысого чекаешь, либо регулярку пилишь которая в этом жисоне ищет фу и блять бар ебаный
>>888991
#355 #888876
>>888840

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


>на жаве или жс это вообще легко библиотеками делается


>Библиотеками


>парсить json


>библиотеками


Лучше-бы мозги подключили вместо библиотек. Так рекурсивная функция строк на 5 всего.
#356 #888892
>>888876
не слушайте его он тролит, надо поставить ларавель, запустить через доктрину, когда все настроите на локальном хоместед вагранте, у вас не составит парсить жсон через пхп, возможно нужно смотреть в сторону композера
>>888893>>888896
#357 #888893
>>888892

>парсить json на ларавеле


>без композаре и элокента


Толсто.
>>888896
#358 #888896
>>888840
>>888893
>>888892
>>888876

Прекратите флуд. Ваши даунские шуточки уровня 7Б и демонстрация неграмотного правописания не интересны и не соответствуют тематике треда.
>>888899>>888901
#359 #888899
>>888896
тогда ответь на это
>>888179
>>888508
или только можешь кукарекупокпок?
69 Кб, 534x424
#360 #888901
>>888896

>уровня 7Б


если тебя твои однокласники из паралельного 7б загнобили это не повод тут высказывать свое недовольство бедненький, смирись тряпка
#361 #888929
>>888399
это не работает, там видно на глаз что это массивы зашиты в строках, но формат какой-то странный. Всё еще нужна помощь.
>>888930>>888931
#362 #888930
>>888929

Это обычный json.
>>888933
#363 #888931
>>888929
Что ты делаешь няша? Ну есть же jsondecode. Гугли и юзай.
>>888933
#364 #888933
>>888930
>>888931

http://ideone.com/8CDOc8

я пытался, ее перед тем как к вам запостить
>>888935
#365 #888935
>>888933
Ты декодируешь не JSON. А просто string текст.
>>888937
#366 #888937
>>888935
спасибо, разобрался, костыль который мне пришлось применить:
$json = "{" . $string . "}";

- это конечно же кек.
>>888938
#367 #888938
>>888937
Внезапно. Но примерно это я и имел ввиду. Хоть и не думал что это так повернётся у тебя в коде. Удачи.
#368 #888944
Принес вам еще задачку, с которой обосрался на собеседовании.

В общем условие такое.

На вход подается массив монет.
Монет может быть от 0 до 10, номинал монет может быть от 1 до 9, монеты могут повторяться, то есть входной массив может выглядеть: 1,2,2,3,7 например.

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

Например, если у нас есть монеты 1,2,5, то ответом должно быть 4. Потому что суммы в 1,2,3 - можно оплатить имеющимися монетами, а вот что бы оплатить 4, то придется дать 5, и получить сдачу 1.

Если есть монеты 2,5, то ответ должен быть 1.

В галере в котрую я ходил нужно такое решить "на бумаге" То есть пишешь код без гугла по памяти и без возможности запускать скрипт, и у тебя всё должно сразу заработать считаю это тупостью, ну да ладно, ведь ца такой конторки как раз студенты-олимпиадники. Дерзайте.
#369 #888945
>>888944

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


Я не понял условия. Что оплатить то?
>>888949
#370 #888949
>>888945

> Что оплатить то?


минимальную положительную сумму, которую нельзя оплатить этими монетами без сдачи.
>>888950
#371 #888950
>>888949
Если я оплачиваю товар за 6 рублей, я плачу 6 рублей без сдачи. Очевидно же. Откуда мне знать будет сдача или нет, если я не знаю цену товара?
>>888952
#372 #888952
>>888950
речь в этой задаче не о цене покупки, а о том что у тебя есть мелочь в кармане, и ты приходишь в киоск на котором висит табличка "НЕТ СДАЧИ, ВООБЩЕ"
И ты смотришь на товары, все все они стоят от 1 рубля до бесконечности по нарастающей. И должен назвать мне первый товар, который ты не сможешь купить на свои монетки, потому что у тебя нету нужной комбинации, понимаешь???
>>888953
#373 #888953
>>888952

>все они стоят от 1 рубля до бесконечности по нарастающей.


Тогда в киоске есть все цены, на любое количество денег без сдачи.
>>888954
#374 #888954
>>888953
да, но у тебя например в кармане есть монетки с номиналом в 1, 2 и 5.
И ты должен мне сказать, что не можешь купить хуйню за 4 рубля. Потому что из твоих монет можно скомбинить только 1,2,3,5,6,7,8 ясно?
>>888956
#375 #888956
>>888954
Как ты определил что я не могу купить хуйню за 4 рубля а не за 8? Я не понимаю.
>>888959
#376 #888959
>>888956
ты не можешь купить за 4, 9, 10, 11...
но ты должен назвать минимальное из этих.
В общем мне кажется что ты толстишь, так что больше я на твои вопросы не отвечаю, думай сам. Если ты тебе надо настолько разжевать задачу, то иди решай лучше учебник опа уебок жирный
#377 #888962
>>888944
иди ты нахуй с такими задачами уровня ебанутой /b/изнес логики, за решение и расшифровку таких задач бабло должны платить. Постоянно такое встречается, Хотим чтобы скидка была у каждого третьего товара притом что каждый 4 товар имел уменьшеную скидку от предыдущего товара на 3 процента. Плюс вычитать ндс когда полнолуние и марс заходит за юпитер.

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

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

Да пригорело у меня знатно сука.
>>889542
#378 #888991
>>888873
Аа регулярку. попробую
#379 #888992
>>888876
на жаве есть удобные библиотеки по работе с джейсоном, даунидзе. а тут регулярки какие-то, рекурсии по массиву. вообще ахуеть.
#380 #889010
Тебя тоже читать противно, просто поразмыслив, я пришел к тому, что в этой задаче всё сводится к тому, что тебе нужно написать функцию, которая высчитывает все возможные суммы элементов массива:

то есть например у тебя если есть массив [1,3,4], то на выходе ты должен дать массив вида: [1,3,4,5,7,8], ну а дальше всё легко, ты просто проходишь циклом от 1 до 91 и находишь первую дырку.
#381 #889025
PHPч, подскажи, как лучше решить следующую задачу: есть некоторая форма с большим количеством полей. При редактировании уже существующей формы пользователь может изменить не все поля, а лишь несколько, дак вот - как лучше сделать так, чтобы обновлялись только те поля в БД, которые были изменены в форме? Пока что в голову пришёл только следующий вариант: делать невидимый инпут внизу формы, в value которого я бы через js запихивал бы имена измененных полей, разделенных каким нибудь ";", чтоб потом, во время обработки post-запроса сервером я просто прошёлся бы по массиву параметров из hidden-инпута и обновлял именно их.
>>889246
#382 #889033
ну вот, с горем пополам написал такую байду на рекурсиях (ибо в жопу регулярки).
https://2ch.hk/pr/res/882422.html#888476 (М)
http://ideone.com/1oqh9Z
#383 #889048
Как в Ларавеле подключить новый роутер? Я создал класс с роутами, как теперь сделать, чтобы приложние его видело?
>>889056
#384 #889056
>>889048
нужна кровь девственицы
#385 #889175
Анонимные, а как реализуется редактирование уже имеющихся данных?
Допустим пост на форуме, в форме открывается уже готовый текст, его можно отредактировать.

Это просто идет селект текста и он заново пересобирается?
#386 #889193
С чего начать, чтоб попроще уроков в ОП-посте? Они сделаны для тех, кто понимает, что и как надо бы сделать, но не знает как, а я вообще темный лес, парюсь над задачей с айфонами, с математикой и логикой беда видимо. Надо с совсем простенького начинать.
>>889196>>889199
#387 #889196
>>889193

Лучше запостить ссылку на код и написать что именно непонятно. Что касается задачи с айфном, на ней все спотыкаются.
>>889203
#388 #889199
>>889193
Читай документацию ПХП, например. Я так его выучил за неделю.
>>889203>>889208
#389 #889203
>>889196
Пока еще сам попробую решить, если совсем невмоготу станет, вброшу.
>>889199
Точно, спасибо.
#390 #889207
Задача про студентов. Считай все сделал, но спотыкнулся на формировании ссылок для получения типа сортировки и номера страницы для отображения(постраничная навигация). Пока делаю тип того что-то <td> <a href="/index/?sort=name">Имя</a> </td> но проблема естественно в том, что таким образом нельзя через адресную стоку передавать еще какие-то переменные, а мне надо что бы было что-то вроде того: index/?sort=name&page=2, ну вы понели. В уроках ОПа есть что-то про построение ссылок стандартными функциями пхп, но я ничего не понял из этого. Научите меня как делать правильно позязь.
>>889255>>889269
#391 #889208
>>889199
неделю не поработаешь снова учить неделю потом будешь
>>889213
#392 #889213
>>889208
Один раз выучил, могу не работать год, и снова писать на нём. Никаких затруднений, максимум - освежить в памяти какие-то тонкие вопросы, это легко сделать из того же мануала.
>>889262
45 Кб, 694x625
#393 #889218
Анон, пишущий API-клиент снова тут, не было времени поковыряться, пару часов назад появилось.
Разделил методы на категории и создал для каждой категории класс. Один из классов: http://pastebin.com/dw2uaFCH
Base класс: http://pastebin.com/AvsCw8Ar
Создание объекта и вызов выглядят так:
$server = new Server($keyId,$vCode);
$url = $server->get('ServerStatus');
В $url идет ссылка со всеми параметрами, которые передаются в get вторым параметром массивом. Собственно вопрос остался тот же - как мне правильно получить файл с помощью того же Guzzle и обработать с помощью DOM?
Это прочитал https://github.com/codedokode/pasta/blob/master/arch/di.md но ничего не изменилось, я все равно не понимаю как это сделать. Разумеется можно после получения ссылки в том же место объявить экземпляр Guzzle и с помощью его получить файл и еще ниже сразу же объявить DOM и обработать, но это неправильно, или я не прав?
>>889221>>889318
#394 #889221
>>889218
В результате я хочу двумя строчками получить массив данных.
#395 #889235
Я хотя бы на правильном пути? http://ideone.com/fjpyYl
А в цикле во втором действии можно столько вычислений проводить за раз?
>>889317
#396 #889240
Второй вопрос снимается, можно, проверил. Совсем туплю уже.
#397 #889246
>>889025
ну у тебя прилетает $_POST, когда пользователь заполнил поля.
Пробегаешь форичем по этому массиву и проверяешь каждый элемент на !empty

$bdUpdate = [];

for ($_POST as $key => $value) {
____if(!empty($value)) {
________$bdUpdate[$key] = $value;
____}
}

и им уже апдейтишь базу.
>>889247
#398 #889247
>>889246
Дык а если это не добавление объекта, а редактирование уже существующего? У меня же в посте все поля прилетят, и мне нужно как то дифференцировать измененные от неизмененных.
>>889260>>889317
#399 #889255
>>889207
схерали нельзя? ты же сам ответил на свой вопрос? у тебя есть эти переменные. Скажем человек перешел на вторую страницу. Стало быть в контроллере ты оперируешь тем что у тебя $page = 2, и передаешь потом эту инфу во вьюху, и стало быть все ссылки, которые в пределах этой страницы строишь с гет-параметром &page=2, хули сложного? Отсортировал он по какому-то столбцу, sort=name, стало быть у тебя появилась переменная, что $sort = "name" и допустим ты знаешь что у тебя по дефолту стоит $defaultOrder = "ASC";
значит ты прямо в мускуль и отправишь эти сортить по name ASC, и хуяришь на выходе уже ссылки вида sort=name&order=asc&page=2

Кароче чет меня повело, прост блядь переменные гоняй через гет запрос и себе же их передавай и во вьюхе с их использованием берешь и строишь переменные прост.
>>889271>>889317
#400 #889260
>>889247
что мешает апдейтить всю запись в базе? Ну или тогда если хочешь апдейтить только часть, то селекти перед апдейтом и сравнивай 2 массива.

>делать невидимый инпут внизу формы


мм, вкусно, уже заапдейтил в твоей базе пароль админу)))
>>889264>>889286
#401 #889262
>>889213
ЗАВИСТЬ
#402 #889264
>>889260

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



А ВОТ ЭТО КАК ЭТО? Я НУФАК ПРОСТО
#403 #889269
>>889207
Можно создать объект СтрокаЗапроса, который будет хранить все возможные параметры запроса, вроде sort, page и т.д. Каждый раз, при переходе по ссылке, меняется только один параметр. Т.е. пользователь может либо кликнуть на заголовок столбца - изменится порядок сортировки, либо перейти на другую страницу - изменится номер страницы, но не сортировка. Начинает он всегда с первой страницы, т.е. все начальные параметры строки тебе известны.
А ссылки будет формировать класс СсылкоФормировщик, который получает на вход объект СтрокаЗапроса.
>>889317
#404 #889271
>>889255
Не очень понял о чем ты. http://ideone.com/ppPhO0 вот мой шаблон, чую я вообще не с той стороны захожу.
>>889300>>889317
#405 #889279
ОПушка, и интересующиеся, выскажите пожалуйста свои замечания:

http://ideone.com/rJWsZN
>>889317
#406 #889286
>>889260

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


Ну а если всю запись обновлять слишком затратно в плане объема информации? Следовательно, и селектить лишний раз нежелательно.
И в чем заключается уязвимость невидимого инпута? Я же с него только считываю информацию
>>889317
#407 #889300
>>889271
http://ideone.com/ppPhO0 тащемта сделал вот так, просто передаю во вью параметры сорт и пейдж и показываю их в ссылке. Работает как надо, только вот все равно не покидает ощущение того, что можно сделать куда лучше, слишком уж это на наебку похоже.
#408 #889313
два года прошло. люди все еще делают студентов. ппц
>>889318>>889319
#409 #889317
>>889255

Можно сделать функцию для генерации ссылок, вроде такой

generateTableLink($sort, $dir, $search, $page)

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

>>889269

Можно, но тут наверно проще функцией сделать.

>>889247

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

Кстати, ORM вроде Доктрины умеют сравнивать сами.

>>889286

Что там затратного? Ты по 10 мегабайт текста каждый раз выбираешь? По моему ты сам себе придумываешь усложнение. Можно сделать список полей, но не забудь проверить его по списку разрешенных полей.

>>889235

Можно, но читабельность страдает и лучше лишнее перенести в тело цикла.

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

>>889279

> $tdg->getBalance(); / $tdg->getBalance(0); / $tdg->getBalance(NULL);


Не должно быть 3 варианта сделать одно и то же. Надо строже определить тип данных.

> $tdg->getBalance(); --> если в базе 0 записей, выбрасывает исключение


не понятна логика, почему исключение

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

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

>>889271

Символ & в HTML тексте или атрибуте надо писать как & amp ;
#409 #889317
>>889255

Можно сделать функцию для генерации ссылок, вроде такой

generateTableLink($sort, $dir, $search, $page)

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

>>889269

Можно, но тут наверно проще функцией сделать.

>>889247

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

Кстати, ORM вроде Доктрины умеют сравнивать сами.

>>889286

Что там затратного? Ты по 10 мегабайт текста каждый раз выбираешь? По моему ты сам себе придумываешь усложнение. Можно сделать список полей, но не забудь проверить его по списку разрешенных полей.

>>889235

Можно, но читабельность страдает и лучше лишнее перенести в тело цикла.

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

>>889279

> $tdg->getBalance(); / $tdg->getBalance(0); / $tdg->getBalance(NULL);


Не должно быть 3 варианта сделать одно и то же. Надо строже определить тип данных.

> $tdg->getBalance(); --> если в базе 0 записей, выбрасывает исключение


не понятна логика, почему исключение

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

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

>>889271

Символ & в HTML тексте или атрибуте надо писать как & amp ;
#410 #889318
>>889218

Класс неправильно назван. У тебя не сервер, а клиент. Сервер - это тот, кто отвечает на запросы, а клиент - тот, кто отправляет. Также, неправильно писать просто "сервер", надо писать, для чего этот сервер или клиент.

> namespace libs;


Название тоже не по PSR-4 выбрано.

> $this->$api($params);


Зачем это? Динамические вызовы только усложняют понимание кода и их не стоит использовать без необходимости.

> $url = $server->get('ServerStatus');


Чем это лучше чем $client->getServerStatus() ? Какой смысл вместо вызова метода напрямую как-то это все усложнять? Ну например в случае с отдельными методами мы можем писать тайп-хинты, а как это сделать в твоем случае? Да даже просто комментарий к методу непонятно, как написать. как узнать, какие методы доступны?

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

Зачем использовано наследование? Я пока не вижу смысла писать в виде 2 классов то, что можно написать в одном. Наследование иногда используют для возможности расширения пользователем стороннего кода, но вряд ли имеет смысл расширять клиент АПИ, так как он жестко привязан к функционалу сервера.

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

> В $url идет ссылка со всеми параметрами, которые передаются в get вторым параметром массивом.


Ну так это получается не клиент АПИ, а HTTP клиент. Ты с таким же успехом можешь дать пользователю Гуззл, и пусть он сам делает там запросы.

> Разумеется можно после получения ссылки в том же место объявить экземпляр Guzzle и с помощью его получить файл и еще ниже сразу же объявить DOM и обработать, но это неправильно, или я не прав?


DI используется для передачи объектов-сервисов, которые могут использоваться многократно. Пользователь может выбирать, какую именно версию объекта передать. DOM это не сервис (он каждый раз создается заново) и его передавать через конструктор не надо, да и нет смысла, непонятно, зачем? Что ты в нем можешь поменять? DOM объекты ты просто создаешь и используешь.

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

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

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


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

> Разумеется можно после получения ссылки в том же место объявить экземпляр Guzzle и с помощью его получить файл


Это будет не DI.

>>889313

А в школах до сих пор пишут буквы прописью.
#410 #889318
>>889218

Класс неправильно назван. У тебя не сервер, а клиент. Сервер - это тот, кто отвечает на запросы, а клиент - тот, кто отправляет. Также, неправильно писать просто "сервер", надо писать, для чего этот сервер или клиент.

> namespace libs;


Название тоже не по PSR-4 выбрано.

> $this->$api($params);


Зачем это? Динамические вызовы только усложняют понимание кода и их не стоит использовать без необходимости.

> $url = $server->get('ServerStatus');


Чем это лучше чем $client->getServerStatus() ? Какой смысл вместо вызова метода напрямую как-то это все усложнять? Ну например в случае с отдельными методами мы можем писать тайп-хинты, а как это сделать в твоем случае? Да даже просто комментарий к методу непонятно, как написать. как узнать, какие методы доступны?

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

Зачем использовано наследование? Я пока не вижу смысла писать в виде 2 классов то, что можно написать в одном. Наследование иногда используют для возможности расширения пользователем стороннего кода, но вряд ли имеет смысл расширять клиент АПИ, так как он жестко привязан к функционалу сервера.

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

> В $url идет ссылка со всеми параметрами, которые передаются в get вторым параметром массивом.


Ну так это получается не клиент АПИ, а HTTP клиент. Ты с таким же успехом можешь дать пользователю Гуззл, и пусть он сам делает там запросы.

> Разумеется можно после получения ссылки в том же место объявить экземпляр Guzzle и с помощью его получить файл и еще ниже сразу же объявить DOM и обработать, но это неправильно, или я не прав?


DI используется для передачи объектов-сервисов, которые могут использоваться многократно. Пользователь может выбирать, какую именно версию объекта передать. DOM это не сервис (он каждый раз создается заново) и его передавать через конструктор не надо, да и нет смысла, непонятно, зачем? Что ты в нем можешь поменять? DOM объекты ты просто создаешь и используешь.

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

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

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


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

> Разумеется можно после получения ссылки в том же место объявить экземпляр Guzzle и с помощью его получить файл


Это будет не DI.

>>889313

А в школах до сих пор пишут буквы прописью.
122 Кб, 800x573
#411 #889319
>>889313
47 лет прошло, люди все еще не могут передать некоторые заглавные буквы.
#412 #889322
>>889317
Сперва это и были две разные функции, но так как в них много общего, были объединены в одну. Выходит, меньше кода не всегда хорошо? Ну а вообще, концепция правильная? Передавать в этот класс pdo-объект, а в методы все условия и ничего более, а внутри только операции с базой данных, никакой внешней логики? (Супер удобно, в общем, получается на самом деле! Если надо что-то изменить, трогаешь только один метод, блин, это вообще...).
>>889324
#413 #889324
>>889322

Концепция, что вся работа с определенной сущностью в Бд собрана в одном классе - да, именно для этого TDG и придуман. Но объединение методов в один только ухудшило код.
>>889331
#414 #889328
>>889317

>Символ & в HTML тексте или атрибуте надо писать как & amp ;


В чем суть?
>>889338
#415 #889331
>>889324
А что насчет проверок на правильность вставляемых / запрашиваемых данных, можно ли их (эти проверки) держать внутри методов или нужно обрабатывать до того, как передадим данные в метод TDG?

Например:

1) внешний файл

if (условия, что данные правильны) {
$tdg->функция(данные);
} else {
...
}

2) внешний файл

$tdg->функция(данные);

наш класс

функция(данные)
{
if (условия, что данные правильны) {
манипуляции с бд
} else {
исключение
}
}
#415 #889331
>>889324
А что насчет проверок на правильность вставляемых / запрашиваемых данных, можно ли их (эти проверки) держать внутри методов или нужно обрабатывать до того, как передадим данные в метод TDG?

Например:

1) внешний файл

if (условия, что данные правильны) {
$tdg->функция(данные);
} else {
...
}

2) внешний файл

$tdg->функция(данные);

наш класс

функция(данные)
{
if (условия, что данные правильны) {
манипуляции с бд
} else {
исключение
}
}
>>889336
#416 #889336
>>889331

В маленьких приложениях в простых случаях можно совмещать все в TDG (хотя конечно получается не очень чисто и уже не совсем TDG), в больших обычно делают более высокоуровневый сервис, который делает проверки/преобразования и после вызывает TDG.
>>889344
#417 #889338
>>889328
Сам по себе & может являться служебным символом для других символов (&nbsp; , < , &copy;). Поэтому для самого символа & пишем &amp; - так мы точно определим, что этот & набранан для текста.
>>889340
#418 #889340
>>889338
Лол, вот и оно, & lt; поменялось на кавычку.
#419 #889341
5 лет прошло, люди все еще на битриксе пишут.
#420 #889342
Прошло 3 года, как я сделал оповские задачки на студентов и обменник. Все еще не работаю кодером.
>>889532
#421 #889344
>>889336
То есть настоящий, годный TDG например http://ideone.com/zfx99w
#422 #889346
хотел погуглить задачки на сортировку и массивы по пхп. нагуглил это:
https://school-php.com/tasks
какой-то ппц, как будто шизик писал, условия понять не могу.
>>889355
#423 #889352
>>889317

>Ну и второе действие у тебя никуда не сохраняет результат вычисления.


Вот я даун!
#424 #889353
СПАСИБО
#425 #889355
>>889346

>ИГРА НА СЕССИЯХ (БИТВА АЛКОГОЛИКОВ)



>СОРТИРОВКА МНОГОМЕРНОГО МАССИВА


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

>ORDER BY `age` ASC


Зачем там sql?
#427 #889381
>>889380
йА думаю што существуют стандарты кодирования, и надо их соблюдать. Вот и всё.
>>889391
#428 #889391
>>889381

>giveMeAnotherAnswerThatContainsJustBooleanThatIGiveToYou(true)


?
#429 #889408
Чё то я тут формами начал заморачиваться, и у меня появился вопрос: допустим, есть форма редактирования записи из БД. На action этой формы воткнут некоторый PHP скрипт, потом через $_POST[] я считываю все нужные параметры, НО! Где и как мне хранить ID, который я буду указывать в "update ... set ... where ID=:ID". Сначала мне показалось охуенным вариантом хранить ID там же в форме, правда потом перспектива того, что value инпута можно изменить через браузер мне показалось нежелательной. Потом я подумал, что в момент нажатия кнопки, которая предоставит мне форму для редактирования, в JS можно хранить значение ID допустим, отображен где то на странице в какой нибудь переменной, которая потом добавится в форму при событии onsubmit. Но как я понял, её значение можно изменить через консоль. Как быть тогда то?

И ещё, дайте ссылку на хорошийгодный мануал по формам типа советы, практические рекомендации, рекомендуемые правила построения и обработки данных, если таковой имеется.
>>889416>>889540
#430 #889416
>>889408
В сессии пользователя, например.
#431 #889523
Добрый вечер, есть тут люди с опытом написания парсеров/грабберов? Интересует вопрос: какое количество страниц обработки за один запуск является оптимальным (с учетом проксей и мультикурла) ? К примеру сайт с миллионом страниц - сколько времени нужно в среднем для полного парсинга?
>>889834
#432 #889532
>>889342
Сделал студентов но не обменник и работаю уже полтора года.
>>889732
#433 #889540
>>889408
Зачем извращаться? Проверь после сабмита есть ли права на редактирование переданного id у текущего юзера.
#434 #889542
>>888962
У меня тоже подгарело от задачи. Но я отдаю себе отчет что отчасти это потому что я не могу её решить так сразу.
>>889662
31 Кб, 900x556
#435 #889564
Ребята, помогите с SMTP, PHPMailer и Yii2.
Суть такова: не могу добиться работы из-за того, что Мейлеру не нравится статический вызов.
ЧЯДНТ?
>>889778>>889801
#436 #889638
>>888944
Я буду долго гнать велосипед: http://ideone.com/wM6UiW
Как сделать проще и правильнее?
>>889639>>889662
#437 #889639
>>889638
Забыл: там если ещё монету прибавить номиналом 1 - считает неверно.
Из-за того, что исключает единицу при прибавлении к другим монетам - и первую, и вторую.
#438 #889662
>>889542
>>889638
Просто мы веб макаки, а эта задача расчитанна на выпускников вузов которые на сях дрочили алгоритмы несколько курсов. Если свести эту задачу к совсем простой теме, то там будет что-то комбинаторное, и надо написать лагоритм который выдает нам все возможные варианты суммы этихмонет, при которых у тебя монета принимает либо 0, либо своё значение. Вот так как-то.

То есть покажу пример для монет в 1, 2, 5.
В общем варианты:
1 + 0 + 0 = 1
0 + 2 + 0 = 2
1 + 2 + 0 = 3
0 + 0 + 5 = 5
1 + 0 + 5 = 6
0 + 2 + 5 = 7
1 + 2 + 5 = 8

Вот так как-то надо вложенным циклом или еще чем пройтись и получить массив, портом по этому массиву циклом до первой дыры и выдать ответ 4.

Для монет в 1,3 это
1 + 0 = 1
0 + 3 = 3
1 + 3 = 4
Ответ соотстввенно 2

для 1, 2, 2
1 + 0 + 0 = 1
0 + 2 + 0 = 2
0 + 2 + 2 = 2
1 + 2 + 0 = 3
1 + 0 + 2 = 3
0 + 2 + 2 = 4
1 + 2 + 2 = 5
Ответ - 6.

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

Ну и что еще могу сказать, так на самом деле это лотерея, потому что я ходил в эту контору уже второй раз, и в первый раз мне выпали на рандоме другие задачи, которые в тот раз я обе решил минут за 50, но завалил уже устное собеседование после этого :(
#438 #889662
>>889542
>>889638
Просто мы веб макаки, а эта задача расчитанна на выпускников вузов которые на сях дрочили алгоритмы несколько курсов. Если свести эту задачу к совсем простой теме, то там будет что-то комбинаторное, и надо написать лагоритм который выдает нам все возможные варианты суммы этихмонет, при которых у тебя монета принимает либо 0, либо своё значение. Вот так как-то.

То есть покажу пример для монет в 1, 2, 5.
В общем варианты:
1 + 0 + 0 = 1
0 + 2 + 0 = 2
1 + 2 + 0 = 3
0 + 0 + 5 = 5
1 + 0 + 5 = 6
0 + 2 + 5 = 7
1 + 2 + 5 = 8

Вот так как-то надо вложенным циклом или еще чем пройтись и получить массив, портом по этому массиву циклом до первой дыры и выдать ответ 4.

Для монет в 1,3 это
1 + 0 = 1
0 + 3 = 3
1 + 3 = 4
Ответ соотстввенно 2

для 1, 2, 2
1 + 0 + 0 = 1
0 + 2 + 0 = 2
0 + 2 + 2 = 2
1 + 2 + 0 = 3
1 + 0 + 2 = 3
0 + 2 + 2 = 4
1 + 2 + 2 = 5
Ответ - 6.

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

Ну и что еще могу сказать, так на самом деле это лотерея, потому что я ходил в эту контору уже второй раз, и в первый раз мне выпали на рандоме другие задачи, которые в тот раз я обе решил минут за 50, но завалил уже устное собеседование после этого :(
>>889767>>889797
#439 #889663
Вторая задача с собеседования:

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

Простой - делится только на себя и 1
Палиндром - числа как 101, 30403, 4004 и так далее.
#440 #889732
>>889532
а я в шоколадницу или аэрофлот пытаюсь трудоустроиться. назначили пару собесов на пхп кодеров, но там шараги в каких-то ебенях, я даже не доехал.
#441 #889735
Господа, мой вопросец касается буквы M в MVC, т.е. моделей. Что это такое и как их правильно готовить? Сколько видов моделей бывают? Что это за domain models, repositories и прочая байда? Понятно, что пихать всю логику в один класс это неправильно. Для того, чтобы получить данные от пользователя из какой-то формы делаем одну модель, для работы непосредственно с SQL делаем другую модель, для того, чтобы полученные данные из БД иметь в виде какой-то структуры данных делаем третью модель и так до скольки уровней вообще? Где можно почитать годную инфу по организации бизнес логики в PHP? Ну, чтобы все по как по маслу - инверсия зависимостей, подстановка разных источников данных при юнит тестировании и прочее-прочее.
>>889742>>889820
#442 #889742
>>889735
просто классы туда выносишь. всю работу приложения. чтобы из контроллеров чисто классы вызывались, а вся работа и обработка проходили в моделях. контроллеры должны быть максимально короткими, т.к. весь код в моделях
>>889745>>889757
#443 #889745
>>889742
Это и так все понятно. Вопрос был про немного другое - про архитектуру самих моделей и всей бизнес-логики приложения.
#444 #889757
>>889742

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


кек

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


кек^2

>контроллеры должны быть максимально короткими, т.к. весь код в моделях


кек^3

А в моем фреймворке например приветствуются тонкие модели и толстые контроллеры, но раз васян с двача так сказал, то буду ща хуярить толстые модели и всю логику в них))))
>>889758
#445 #889758
>>889757
в твоем самописном фреймворке?
>>889761
#446 #889761
>>889758
я просто намекнул тебе, что бывает два подхода, погугли что ли, чем бугуртить тут __)_)_)
>>889820
#447 #889767
>>889662

>Вот так как-то надо вложенным циклом или еще чем пройтись и получить массив, портом по этому массиву циклом до первой дыры и выдать ответ 4


Получается, нужен цикл в цикле.
Один идёт по количеству монет, а второй внутри каждый раз складывает все монеты.
Ну вот я так и хотел сделать, но где-то обкакунькался.
Я хотел так сделать, а потом просто unset из массива со сдачей от 1 до 9.
Сейчас посижу, подумаю.
#448 #889778
>>889564
Блин, ну как сделать этот вызов не статическим:
protected function doCallback($isSent, $to, $cc, $bcc, $subject, $body, $from = null)
{
if (!empty($this->action_function) && is_callable($this->action_function)) {
$params = array($isSent, $to, $cc, $bcc, $subject, $body, $from);
call_user_func_array($this->action_function, $params);
}
}
>>889801
#449 #889797
>>889662
Так ты решил эту задачу на собесе или сейчас такой умный? Вот этот вот алгоритм, который ты изложил, за решение не прокатил?

Алсо, я нашел два алгоритма решения, с помощью генерации массива биткарты (побитовая маска), и с помощью циклов, вложенных в друг-друга, количество которых равно количеству элементов исходного массива. Твой вариант - это почти что вариант биткарты, без бит карты, лол.
Без специальной подготовки, такую задачу я бы решить не смог. Но читая статьи из цикла "как я устроился в гугол и получаю 1000$ в секунду" часто встречал описания штудирования всевозможных хитрых олимпиадных задачек перед очередным собеседованием. Поэтому мне кажется, хватит ныть, садись и учи.
>>889805>>889908
#450 #889801
>>889564
>>889778

Это проблема в сторонней библиотеке. В таком случае первым делом надо погуглить:

http://www.yiiframework.ru/forum/viewtopic.php?t=32889

Затем мы идем в гитхаб разработчика, и ищем в issues - не писал ли кто-то об этом? Действительно, есть такой баг: https://github.com/SDKiller/zyx-phpmailer/issues/2

Там написано, что все исправлено аж в 2014.

Открыв код https://github.com/SDKiller/zyx-phpmailer/blob/master/Mailer.php видим - действительно, исправлено.

Теперь вопрос к тебе:

Почему у тебя такая старая версия? как ты устанавливал это расширение? через композер? если да, то какая версия стоит в composer.lock и в composer.json? если нет, то почему?
>>889951
#451 #889805
>>888944
>>889797

Есть раздел математики комбинаторика ( https://ru.wikipedia.org/wiki/Комбинаторика ), которая как раз изучает всякие комбинации и перестановки, и есть стандартные алгоритмы их генерации.

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

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

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

Монет максимум 10, каждая из них может быть взята или нет. Это дает нам 2^10 = 1024 варианта. Немного, так что можно решать задачу тупо перебором без особых оптимизаций (оптимизацией будет выбор такого порядка перебора, чтобы сумма шла по возрастанию).

Как сгенерировать комбинации монет? Да очень просто, можно циклом, можно рекурсией. Например, комбинации можно представить двоичным 10-значным числом от 0000...0 до 1111...1, по сути надо сделать перебор этих чисел.
>>890335
#452 #889814
Только так смог решить задачу про айфон http://ideone.com/fjpyYl
Самому кажется, что кривоватое решение, стоит по другому попробовать?
>>889953
#453 #889820
>>889761

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

>>889735

> Сколько видов моделей бывают?


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

> domain models


> repositories


Лучше всего почитать у Фаулера, который эти паттерны в книге описал:

http://design-pattern.ru/patterns/domain-model.html
http://design-pattern.ru/patterns/repository.html

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

Общая архитектура обычно представляется в виде слоев: http://design-pattern.ru/patterns/service-layer.html

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

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

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

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

Хочу еще дать такую статью про хлеб: https://habrahabr.ru/post/153225/

Ты не дал никаких примеров, потому придется пример придумать мне. Ну вот возьмем например, файлообменник. Так как сущность там только одна - файл, то и сервис пока у нас будет один - СервисФайлов. Подумаем, какие нужны ему методы:

- проверитьФайл (можно ли такой файл загрузить к нам, правильно ли указан комментарий и тд)
- сохранитьФайл (и на диск, и в БД)
- получитьФайлПоId
- получитьСсылкуНаСкачивание
- получитьСсылкуНаСтраницуФайла
- получитьПутьКФайлуНаДиске
- удалитьФайл

Ну а дальше, может быть, эта схема будет как-то усложняться. Ну например, мы захотим для более аккуратного кода убрать из сервиса работу с БД в отдельный класс, реализующий Table Data Gateway. Затем, захотим сделать объект, представляющий Файл. Затем вынесем работу с URL в отдельный класс.

Затем вспомним, что нам надо для медиафайлов показывать информацию о них, и сделаем классы МедиаИнформация и ПолучательМедиаИнформации.

Вот я бы рассуждал примерно так. Ну и еще, можно посмотреть, как это делается в той же Симфони 2, там довольно неплохая архитектура.
#453 #889820
>>889761

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

>>889735

> Сколько видов моделей бывают?


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

> domain models


> repositories


Лучше всего почитать у Фаулера, который эти паттерны в книге описал:

http://design-pattern.ru/patterns/domain-model.html
http://design-pattern.ru/patterns/repository.html

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

Общая архитектура обычно представляется в виде слоев: http://design-pattern.ru/patterns/service-layer.html

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

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

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

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

Хочу еще дать такую статью про хлеб: https://habrahabr.ru/post/153225/

Ты не дал никаких примеров, потому придется пример придумать мне. Ну вот возьмем например, файлообменник. Так как сущность там только одна - файл, то и сервис пока у нас будет один - СервисФайлов. Подумаем, какие нужны ему методы:

- проверитьФайл (можно ли такой файл загрузить к нам, правильно ли указан комментарий и тд)
- сохранитьФайл (и на диск, и в БД)
- получитьФайлПоId
- получитьСсылкуНаСкачивание
- получитьСсылкуНаСтраницуФайла
- получитьПутьКФайлуНаДиске
- удалитьФайл

Ну а дальше, может быть, эта схема будет как-то усложняться. Ну например, мы захотим для более аккуратного кода убрать из сервиса работу с БД в отдельный класс, реализующий Table Data Gateway. Затем, захотим сделать объект, представляющий Файл. Затем вынесем работу с URL в отдельный класс.

Затем вспомним, что нам надо для медиафайлов показывать информацию о них, и сделаем классы МедиаИнформация и ПолучательМедиаИнформации.

Вот я бы рассуждал примерно так. Ну и еще, можно посмотреть, как это делается в той же Симфони 2, там довольно неплохая архитектура.
>>889959
#454 #889834
#455 #889908
>>889797
я на собесе дошел мыслями до этого, но не смог на бумажке написать алгоритм этот.
>>889921
#456 #889921
>>889908
на кого ты там собеседовал чтобы такие задачи решать?
>>889948>>889949
#457 #889948
>>889921
пхп - джун в noveo
>>890042
#458 #889949
>>889921
ну и там электронный тест, плюс на самом деле ideone, ты просто выбираешь язык и пишешь код в форму, там и явисты и сишники какие-нибудь эти же задачи решают, просто на своём языке.
#459 #889951
>>889801
Я так-то посмотрел, это всё прочитал, но ничего не понял всё-таки.

>Почему у тебя такая старая версия? как ты устанавливал это расширение? через композер? если да, то какая версия стоит в composer.lock и в composer.json? если нет, то почему?


Через Композер устанавливал в середине этого лета.
4-я версия, как я понял.
У меня нет файла composer.loc - не нахожу его.
Что мне можно сделать в этой ситуации, обновить PHPMailer через Composer?
Вроде как не советуют просто сами файлы обновлять в папке vendor, только через Композер.
#460 #889953
>>889814
Вполне хорошо, только ещё можно было бы сократить на echo "{$month} месяц спустя: долг = {$creditBalance} руб, выплачено всего {$paymentTotal} руб. \n";
Для этого надо прямо в цикле поставить условие: если осталось с процентами и 1000 меньше 5000, то $lastPayment = $creditBalance;
$creditBalance = $creditBalance - $lastPayment;
$paymentTotal = $paymentTotal + $lastPayment;
>>890316
#461 #889956
>>880700 (OP)
Анончики, хочу вкотится в это ваше веб-погромирование в 25
До этого 3 года работал версталой/фронтендом

Так вот, для работодателей опыт верстки хоть как-то будет учитываться или как нулевого долбоеба будут оценивать?
>>889963
#462 #889959
>>889820
Спасибо за развернутый ответ.

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

Пока что я в голове набросал следующую архитектуру моделей, которая в целом устраивает мои привычки работы с MVC:
1 - Storage Models - модели самого низкого уровня, работают непосредственно с данными (БД, XML, json). Есть некий общий класс StorageCore, который включает в себя экземпляры всех storage models и через этот общий класс происходит работа с этими экземлярами. Сам по себе Storage Core является реализацией интерфейса IStorage, что позволяет подставлять нужную реализацию в любой момент времени. Например, для unit-тестов не вижу особого смысла работать напрямую с рабочей БД и подставить для этого реализацию Storage Core для работы с предустановленными json-файлами.
2 - Domain Models - модели-объекты записей данных. Т.е. каждый экземпляр этого класса представляет собой конкретную запись в БД.
3 - Service Models - модели-сервисы, по сути тупо хелперы, в которых непосредственно и реализована вся бизнес-логика, все связи между сущностями, все сортировки и прочие выборки. Является надстройкой над Storage Core.
4 - Bind Models - модели, которые получают данные от пользователя (формы, get-запросы) и затем обращаются к service models, получая необходимые данные (в виде набора domain models) и совершая действия. Контроллеры работают именно с bind models, не затрагивая все остальные вышеперечисленные модели. По сути вся работа контроллера это инициализировать нужный в этот момент bind model и далее смотреть, что этот BM вытворяет.
5 - View Models - модели, которые являются тем же набором разного рода domain models. Эти модели далее передаются во View (т.е. внутри себя содержат еще какие-то вспомогательные методы, к которым мы обращаемся из View.

Примерно такая структура, к которой я стремлюсь. Но в силу недостатка опыта не могу оценить адекватность этой архитектуры. Есть мнение?
#463 #889963
>>889956
Зависит от конкретной задачи. Но в целом, да. Опыт верстки для веб-разработчика большой плюс, при условии, что твой уровень пхп их устроит. Если же нет, то будут смотреть как на переводчика, который пришел на должность бизнес-аналитика.
>>889973
#464 #889973
>>889963
Отлично, спасибо за ответ. Значит вкатываюсь.
#465 #889974
>>889959

А какие методы будут у IStorage?
>>889977
#466 #889976

>If you:



>Use Modern Versions of MySQL (late 5.1, all 5.5, 5.6, etc) AND PDO's DSN charset parameter (in PHP ≥ 5.3.6)


OR

>Don't use a vulnerable character set for connection encoding (you only use utf8 / latin1 / ascii / etc)


OR

>Enable NO_BACKSLASH_ESCAPES SQL mode



>You're 100% safe from SQL injections.



>Otherwise, you're vulnerable even though you're using PDO Prepared Statements...

#467 #889977
>>889974
Я чутка попутал. Storage Models будут реализациями своих интерфейсов. А StorageCore будет подгружать нужную реализацию этих моделей, чтобы в одном случае работать с БД, а в другом работать, например, с файлами, не меняя при этом всю остальную логику.
#468 #890042
>>889948
пиздец от джуна требуют, как будто он там будет архитектуру пилить. Хотя кого я обманываю просто я тупой и долго такое говно думаю.
#469 #890069
Как мне обновить PHPMailer?
cmd.exe, composer require phpmailer/phpmailer - это ведь нужно в директории vendor делать?
Подскажите, пожалуйста!
Боюсь сломать проект, там уже многое готово.
>>890078
#470 #890078
>>890069

Что у тебя в composer.json написано? Ты обновляешь не то. Ты хочешь обнвоить phpmailer, а надо обновить расширение xyz-phpmailer от Юи.
>>890083
#471 #890083
>>890078
Вот: http://ideone.com/GttUX6
Сейчас уже 4.7 версия его, а у меня ещё 4.0.
Да, Mailer.php ведь в xyz-phpmailer находится.
И как же его обновить теперь?
php composer.phar require --prefer-dist zyx/zyx-phpmailer "@stable" в папке vendor?
Я уже забыл, как устанавливал что через Composer.
>>890085
#472 #890085
>>890083

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

composer.json ты дал не тот. Ты зачем-то мне дал composer.json от библиотеки phpmailer которая вообще отношения к проблеме не имеет.

И composer.json от xyz-phpmailer тоже не нужен.

Нужен основной composer.json, с помощью которого ты устанавливал Юи и плагины.

И что-то у меня ощущение, что ты фреймворк откуда-то скачал, а не композером ставил.
>>890135
123 Кб, 1920x925
48 Кб, 360x624
#473 #890132
https://github.com/someApprentice/maintaskforlayout
https://someapprentice.github.io/maintaskforlayout/

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

>>874513


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


>>875380


>> Firefox, кстати, всё равно выдает ошибки парсинга font-weight на значения bolder и lighter (если их убрать то ничего не изменится). Как такое может быть?


>Это относительный вес ("чуть потяжелее") и его не стоит указывать внутри font-face в любом случае, так как непонятно относительно чего его отсчитывать.


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

>>875380


>Вот скриншот из ИЕ11: https://www.browserstack.com/screenshots/b5bec7763e6986c4898f75ece20e9d312e81834b/win10_ie_11.0.jpg


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


А можно уточнить где эта белая полоска? У меня на скриншоте ничего не видно. Я такую белую полосу вижу когда сжимаю окно меньше 320px - это оно?

>Когда задаешь font-size, стоит задавать и line-height. В абзаце текста под заголовком "Consectetur" например строки стоят очень тесно, правильный ли там line-height?


Я просто не заметил это, в фш интерлиньяж где-то явно не соответствует реальному. Приходиться на глаз определять или я что-то не знаю.

>Для иконок соцсетей надо сделать реакцию на наведение.


А что за реакцию? Когда мы наводим на них и так меняется указатель. Я думаю этого достаточно.

>>srcset="img\home_0003s_0001s_0022_Layer-1-Large.jpg"


>Я вижу, ты используешь srcset, но почему тут не указано разрешение картинки? Так и должно быть? Вот я статью нашел по теме, если что: http://frontender.info/webkit-implements-srcset-and-why-its-a-good-thing/


Не смог разобраться с этим, нужно писать srcset="img\home_0003s_0001s_0022_Layer-1-Large.jpg 270w 1x"?
123 Кб, 1920x925
48 Кб, 360x624
#473 #890132
https://github.com/someApprentice/maintaskforlayout
https://someapprentice.github.io/maintaskforlayout/

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

>>874513


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


>>875380


>> Firefox, кстати, всё равно выдает ошибки парсинга font-weight на значения bolder и lighter (если их убрать то ничего не изменится). Как такое может быть?


>Это относительный вес ("чуть потяжелее") и его не стоит указывать внутри font-face в любом случае, так как непонятно относительно чего его отсчитывать.


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

>>875380


>Вот скриншот из ИЕ11: https://www.browserstack.com/screenshots/b5bec7763e6986c4898f75ece20e9d312e81834b/win10_ie_11.0.jpg


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


А можно уточнить где эта белая полоска? У меня на скриншоте ничего не видно. Я такую белую полосу вижу когда сжимаю окно меньше 320px - это оно?

>Когда задаешь font-size, стоит задавать и line-height. В абзаце текста под заголовком "Consectetur" например строки стоят очень тесно, правильный ли там line-height?


Я просто не заметил это, в фш интерлиньяж где-то явно не соответствует реальному. Приходиться на глаз определять или я что-то не знаю.

>Для иконок соцсетей надо сделать реакцию на наведение.


А что за реакцию? Когда мы наводим на них и так меняется указатель. Я думаю этого достаточно.

>>srcset="img\home_0003s_0001s_0022_Layer-1-Large.jpg"


>Я вижу, ты используешь srcset, но почему тут не указано разрешение картинки? Так и должно быть? Вот я статью нашел по теме, если что: http://frontender.info/webkit-implements-srcset-and-why-its-a-good-thing/


Не смог разобраться с этим, нужно писать srcset="img\home_0003s_0001s_0022_Layer-1-Large.jpg 270w 1x"?
>>890182
27 Кб, 690x588
#474 #890133
тест на знание пхп от битрикса
>>890147
#475 #890135
>>890085
{
"name": "yiisoft/yii2-app-advanced",
"description": "Yii 2 Advanced Project Template",
"keywords": ["yii2", "framework", "advanced", "project template"],
"homepage": "http://www.yiiframework.com/",
"type": "project",
"license": "BSD-3-Clause",
"support": {
"issues": "https://github.com/yiisoft/yii2/issues?state=open",
"forum": "http://www.yiiframework.com/forum/",
"wiki": "http://www.yiiframework.com/wiki/",
"irc": "//irc.freenode.net/yii",
"source": "https://github.com/yiisoft/yii2"
},
"minimum-stability": "stable",
"require": {
"php": ">=5.4.0",
"yiisoft/yii2": ">=2.0.4",
"yiisoft/yii2-bootstrap": "",
"yiisoft/yii2-swiftmailer": "
",
"zyx/zyx-phpmailer": "@stable"
},
"require-dev": {
"yiisoft/yii2-codeception": "",
"yiisoft/yii2-debug": "
",
"yiisoft/yii2-gii": "",
"yiisoft/yii2-faker": "
"
},
"config": {
"process-timeout": 1800
},
"extra": {
"asset-installer-paths": {
"npm-asset-library": "vendor/npm",
"bower-asset-library": "vendor/bower"
}
}
}

Вот основной composer.json.
Я ставил через Composer в режиме Development - иду по курсу от GeekBrains, расписываю подробно всё то, что говорит преподаватель, потом покажу анонам текст.
Я устанавливал ещё Bower и NPM, сам PHPMailer у меня в режиме stable.
Может, в этом причина? Там он мог давно не обновляться, конечно, но не с 2014-го же года...
Про Composer я почитаю, но мне бы ответ на этот вопрос помог, да.
Там вряд ли что найду - как обновить, там везде как установить просто.
Ну, попробую просто заново установить, да.
#475 #890135
>>890085
{
"name": "yiisoft/yii2-app-advanced",
"description": "Yii 2 Advanced Project Template",
"keywords": ["yii2", "framework", "advanced", "project template"],
"homepage": "http://www.yiiframework.com/",
"type": "project",
"license": "BSD-3-Clause",
"support": {
"issues": "https://github.com/yiisoft/yii2/issues?state=open",
"forum": "http://www.yiiframework.com/forum/",
"wiki": "http://www.yiiframework.com/wiki/",
"irc": "//irc.freenode.net/yii",
"source": "https://github.com/yiisoft/yii2"
},
"minimum-stability": "stable",
"require": {
"php": ">=5.4.0",
"yiisoft/yii2": ">=2.0.4",
"yiisoft/yii2-bootstrap": "",
"yiisoft/yii2-swiftmailer": "
",
"zyx/zyx-phpmailer": "@stable"
},
"require-dev": {
"yiisoft/yii2-codeception": "",
"yiisoft/yii2-debug": "
",
"yiisoft/yii2-gii": "",
"yiisoft/yii2-faker": "
"
},
"config": {
"process-timeout": 1800
},
"extra": {
"asset-installer-paths": {
"npm-asset-library": "vendor/npm",
"bower-asset-library": "vendor/bower"
}
}
}

Вот основной composer.json.
Я ставил через Composer в режиме Development - иду по курсу от GeekBrains, расписываю подробно всё то, что говорит преподаватель, потом покажу анонам текст.
Я устанавливал ещё Bower и NPM, сам PHPMailer у меня в режиме stable.
Может, в этом причина? Там он мог давно не обновляться, конечно, но не с 2014-го же года...
Про Composer я почитаю, но мне бы ответ на этот вопрос помог, да.
Там вряд ли что найду - как обновить, там везде как установить просто.
Ну, попробую просто заново установить, да.
>>890189
#476 #890147
>>890133
Б и В.
Потому что в Б цикл цикл выполнится хотя бы 1 раз, а потом проверится. В первом варианте вообще не выполнится.
>>890192>>890329
#477 #890182
>>890132

Белая полоска на скриншоте https://www.browserstack.com/screenshots/b5bec7763e6986c4898f75ece20e9d312e81834b/win10_ie_11.0.jpg расположена между темным блоком в шапке (ниже кнопки See Portfolio) и светло-серым блоком с заголовком Consectetur. Полоска горизонтальная, высотой пикселей 20-30.

Если ее не видно, значит монитор плохо отображает оттенки серого, можно попробовать загрузить скриншот в графический редактор и повысить контраст/понизить яркость и я думаю тогда полоска станет видна. Ну или можно временно сделать фон на блоке Consectetur темнее.
>>890818
#478 #890189
>>890135

У тебя там указана версия @stable. Я к сожалению, не знаю, как именно определяется "стабильность", скорее всего берется максимальная версия, в которой нет слов вроде dev.

Зайдем на packagist (официальный репозиторий композера), чтобы посмотреть, какая версия считается сейчас стабильной:

https://packagist.org/packages/zyx/zyx-phpmailer

Это 0.9.2

Зайдем в проект на гитхабе, в releases и найдем там 0.9.2, которой уже как 2 года с лишним: https://github.com/SDKiller/zyx-phpmailer/commits/0.9.2

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

Еще конечно есть вариант с помощью error_reporting игнорировать сообщения уровня E_DEPRECATED, но это по моему плохая идея.

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

надо исправить composer.json и сделать update.

Также, если есть желание, можно написать авторам этого composer.json (я не знаю, где ты го взял, это ведь не от разработчиков Юи наверно, а какая-то левая сборка?) и предложить им исправить версию пакета.

> Про Composer я почитаю, но мне бы ответ на этот вопрос помог, да.


Ты бы понял, как определить версию установленного пакета (по composer.json), ты бы нашел гитхаб проекта и issue с проблемой в нем. Просто у меня сложилось ощущение, что для тебя композер это черный ящик, и ты просто следуешь инструкциям в курсе, а как только что-то идет не так, теряешься. Потому стоит понимать, что в композере ничего такого необычного нет, он просто подбирает пакеты исходя их требований в разных composer.json и устанавливает их.
>>890193
#479 #890192
>>890147
можно, но зачем?
#480 #890193
>>890189
Огромное человеческое спасибо, ОП!
#481 #890316
>>889953

>если осталось с процентами и 1000 меньше 5000


Не понимаю.
#482 #890329
>>890147
неправильно йоба, хули ты всех в заблуждения вводишь
#483 #890335
>>889805
А почему ты считаешь комбинацию, при которой все монеты не выбраны? Я просто хочу понять, нужно ли ее считать, или нет?
Если все возможные суммы исходных чисел находить как сумму всех возможных сочетаний, то получается другой ответ С1монетыИз10+С2монетИз10+...С10монетИз10 = 1023. Но можно прибавить С0из10, тогда получится 1024. На эту сумму нельзя что-либо купить, и соответственно дать сдачу. Т.е. ряд двоичных чисел можно начать с 0000000001 а не с 0000000000.
>>890343
#484 #890343
>>890335
монеты считаете,что все так плохо в пидорахии?
#485 #890347
Тут задание на должность джуниора проскакивало несколько месяцев назад, там давалась база данных и кажется надо было написать роутинг в MVC стиле. Можете скинуть условия они ещё были в гугл доке?
>>890378>>890448
#486 #890378
>>890347
поищи на архиваче
>>890448
#487 #890416
ОП, проверь пожалуйста.
https://github.com/never3ver/fileshare
Попытался разобраться с тестированием, что-то там сделал, но наверно отложу эту тему, думаю лучше сначала с большими фреймворками познакомиться а потом уже в это лезть.
#488 #890448
>>890347
>>890378

Вот ссылки на архивач: https://www.google.ru/search?q=клуб+php+site:arhivach.org&btnG=Поиск&newwindow=1

Алсо в предыдущем треде (который я в архиваче не нахожу) есть ссылка https://docs.google.com/document/d/1H2H9h-UtaBGjrfmHh1ClbdJl1nH1Vx9wA6rAfcVbyEo/edit
>>890632
#489 #890457
Никак не могу 4 рандомных результата объединить в одну строку, задача про генератор имен http://ideone.com/FhSLUw http://ideone.com/jgRSPJ
Блин, опять засиделся за задачками, на работу опаздываю уже.
>>890498>>890892
#490 #890498
>>890457
Тебе надо конкатинировать переменную $randomText в $name внутри цикла.
А потом $name вывести, как ты и выводишь.
Всё.
>>890499>>890956
#491 #890499
>>890498
*конкатенировать
#492 #890632
>>890448
Очень сильно спасибо
#493 #890637
Как можно обучиться адаптивной вёрстке? Выучил уже практически всё что надо для джуниора ПХП, базы данных, вордпресс, даже yii2 немного, MVC, обычную вёрстку, js, jQuery но что-то никак не даётся адптивная вёрстка, когда сталкиваюсь с реальным заданием всё как-то получается криво. Я заметил одну вещь, если у всего остального что я учил вроде ООП на ПХП был чёткий алгоритм работы и обучения, то в адаптивной вёрстке всё как-то меняется в зависимости от случая, поэтому я никак не могу понять само ядро этой технологии. Может быть есть хорошие курсы именно по адаптивной вёрстке? Я даже готов заплатить если они не очень дорогие.
>>890697>>890860
#494 #890697
>>890637
Курсы пройди какие-нибудь, есть же. В принципе, что там может быть сложного? Скажешь, что работал с несколькими фреймворками, с тем же Бутстрапом, да и хватит, я думаю.
#495 #890712
Давно уже не использовал регулярные выражения, можете подсказать что обозначает этот паттерн:

'^(?P<controller>[a-z-]+)/?(?P<action>[a-z-]+)?$'

Точнее меня интересует для чего здесь <controller> и <action>, какую роль они выполняют в этом случае? Всё остальное вроде бы понятно. Под этот паттерн подходят выражения вроде post/create и т.д. Сама регулярка используется при создании роутинга, как правила для названий контроллера и экшена
>>890860
35 Кб, 829x616
23 Кб, 515x566
33 Кб, 543x363
#496 #890740
ПАСАНЫ ПРОБЛЕМЕСЫ.. Что я делаю не так?
По сути, должно апдейтить цены, но нихуя не происходит, оптные макаки, подскажите.
#497 #890761
>>890740
даже вникать лень, нахуй сразу послан мешать верстку с пыхо кодом, перейди для начала на фреймворки, и делай rest контроллеры, а на клиенте angular\react\хоть небо, хоть аллаха
#498 #890763
>>890761
фреймворкобляди не нужны, что я захочу то сам сделаю на чистом ПХП и хуй соси Я УЖЕ ВСЕ ПОФИКСИЛ
#499 #890767
>>890763

>на чистом ПХП


Орнул с неосилятора.

ttyk ты?
>>890770
#500 #890768
>>890763
>>890740
Я думал, что я видел дохуя хуевого когда на пыхе, но смотря на это у меня мигрень началась.
>>890769
#501 #890769
>>890768
*кода
>>890770
#502 #890770
>>890767
нет
>>890769
Слушай, я всего 3 месяца на пыхе кодю, хуй знает что к чему вообще
>>890773>>890776
#503 #890773
>>890770
Если хочешь вкатиться нормально и чтобы люди не плевались от твоего кода - в шапке треда есть всё для новичков и для не новичков тоже есть много интересных вещей.
>>890774>>890776
#504 #890774
>>890773
Я прочитал основы, у меня был опыт [h]говно[/h]кода на C#, дальше разбираюсь сам
>>890777
#505 #890776
>>890770
Он к тому, что ты - быдлокодер.

>фреймворкобляди не нужны



>>890773

>фреймворкобляди не нужны


>Слушай, я всего 3 месяца на пыхе кодю, хуй знает что к чему вообще



Не надо переделывать собаку в человека, а человека — в собаку. Ничего хорошего из этого не получится.(с) профессор Преображенский
>>890780
#506 #890777
>>890774
Даже с разметкой проебался.
Ты будущий аутсайдер.
>>890780
#507 #890780
>>890776
не понял прикол с собакой.
Суть в том что если хочешь помочь, можешь мыльцо оставить своё. Все совершали ошибки по началу, в чем твоя проблема?
>>890777
Каким образом проебался?
>>890783
someApprentice #508 #890782
Наконец-то дошли руки до очень старого аж с 79 треда но не сложного замечания

>>856303


https://arhivach.org/thread/193343/#819083
https://arhivach.org/thread/204328/#849196
https://arhivach.org/thread/204328/#856303

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


>>Перенес рендеры из контроллера в шаблоны:


>>https://github.com/someApprentice/Students/commit/6b1fb52461786f9fe0966562c73b9f6f99968d5c


>Нет. ты пока не все перенес...


https://github.com/someApprentice/Students/commit/679a05c33e5ea62efb6e11c82c90c72e65cf33c1

Остальные исправления были здесь https://arhivach.org/thread/197740/#836646

В этих ссылках можно запутаться, но можете не сомневаться - ~99.9% ваших замечаний исправлены 0.1% это те которые я мог не заметить\забыть\потерять

Со Студентами мы разобрались?
#509 #890783
>>890780

>не понял прикол с собакой.


Лол, блджад.
И не надо, я не тебе писал.

>Суть в том что если хочешь помочь, можешь мыльцо оставить своё. Все совершали ошибки по началу, в чем твоя проблема?


>Каким образом проебался?



Просто ты хапанул лишнюю пару хромосом.
>>890788
#510 #890788
>>890783

>Просто ты хапанул лишнюю пару хромосом.


А я вижу ты с рождения умеешь и на пыхе писать, и на чем угодно
>>890794
#511 #890794
>>890788
Дело даже не в твоем говнокоде, а в том, что ты "с тугой резьбой"тупорылый.

>А я вижу ты с рождения умеешь и на пыхе писать, и на чем угодно


А тебе, с таким подходом к делу, и жизни не хватит, чтобы научиться нормально программировать хоть на чем-то.
Ожидаю вопроса: "скаким таким подходом?"
Отвечаю сразу: "иди нахуй тупица, даже это не можешь понять"
>>890798>>890849
#512 #890798
>>890794

>Ожидаю вопроса: "скаким таким подходом?"


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

>ты "с тугой резьбой"


Очень огромный смысл, говорить это человеку, который пытается хоть что-то сделать с минимальным опытом.
Я же хочу чтоб мне на ошибки показали, а не хуйню писали такие как ты, строя из себя Аллаха
>>890806
10 Кб, 1336x120
#513 #890800

>Я же хочу чтоб мне на ошибки показали, а не хуйню писали такие как ты, строя из себя Аллаха



Ясно.
>>890804
#514 #890804
>>890800
Просто сейчас - это не реально.
А я про ошибки непосредственно в моём говнокоде. Я учел совет про фреймворки.

>мешать верстку с пыхо кодом


Ну тут уж извини, пока-что не умею по-другому.
>>890813>>890849
81 Кб, 760x854
#515 #890806
>>890813
#516 #890813
>>890804

>Ну тут уж извини, пока-что не умею по-другому.


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

Поясняю на пальцах.
В одном файле .php ты описываешь логику.
А в другом ты пишешь весь html+все эти вызовы "echo".
Понимаешь?

>>890806
Я думал демчиками уже никто не пользуется.
>>890816
#517 #890816
>>890813
А в этот дургой уже где-то в начале пишешь include_once("Ссылка на файл с логикой") ?
>>890821
76 Кб, 1280x720
1343 Кб, 1433x846
#518 #890818
>>890182
Что-то не получается у меня найти её
В графическом редакторе при увеличении должно хоть что-то показаться

Может это исправилось уже само?
>>890837
37 Кб, 347x90
#519 #890821
>>890816
Да.
Можно использовать еще require, он в случае ошибки остановит скрипт и плюнет ошибкой.
И скобки не обязательны.

И давай всему, что есть ИНФОРМАТИВНЫЕ имена (файлам, переменным, функциям и тд). Загугли как называть переменные или как оформлять код на php ну ты понел.
Хорошие люди даже сделали хорошую штуку - PSR
>>890827
#520 #890827
>>890821
Просто знакомые попросили им сайт сделать, а я на отъебись начал клепать ибо правок у них дохуя, платить не хотят. Да и не спал день, туплю сильно.
>>890829
#521 #890829
>>890827

>правок у них дохуя


>платить не хотят



Можешь ничего не менять в коде все идеально.
>>890834
#522 #890834
>>890829
Спор наш решился сам собой. могу ссылку дать на сие чудо
>>890838
#523 #890837
>>890818

Может быть. Если взять скриншот https://www.browserstack.com/screenshots/b5bec7763e6986c4898f75ece20e9d312e81834b/win10_ie_11.0.jpg - полоса есть. Видно ее?

Проверим, исправилась ли проблема. Я зашел на modern.ie и сделал там новый скриншот: https://www.browserstack.com/screenshots/5e7365e06a803d67a956cebf9704fc0ca6a4fc4c/win10_ie_11.0.jpg

Полосы больше нет. Но я вижу такие вещи:

- меню упирается в правый край без паддинга, надо хотя бы 5px паддинга, ведь в книгах и журналах буквы не налезают на самый край странице (хотя может это из-за несовершенства технологий печати конечно). То же касается логотипа.
- список consecuter, tristlquet на такой ширине было бы выгоднее выводить в 2-3 колонки, а не вертикально. Если там сделать верстку теми же инлайн-блоками, то они будут подстраиваться сами под ширину страницы.

В версии для ИЕ8 ( https://www.browserstack.com/screenshots/5e7365e06a803d67a956cebf9704fc0ca6a4fc4c/win7_ie_8.0.jpg ) отвалились картинки в блоке consecuter (там используется что-то из CSS3? В принипе, можно и без них конечно) и в блоке социальных кнопок внизу появились надписи.

В мобильной версии ( https://www.browserstack.com/screenshots/5e7365e06a803d67a956cebf9704fc0ca6a4fc4c/ios_iPhone-6-Plus_8.3_portrait.jpg ) шрифт в шапке слишком большой. Наверно надо для мобильных устройств его уменьшить.
>>891479
#524 #890838
>>890834
Оно уже на хостинге?
Давай.
>>890848
#525 #890848
>>890838
http://ekbkrasota.ru/
Да пожалуйста, блять, я уже недели 3-4 делаю эту хуйню. Заебался. Не дай аллах кому попадется такой чел.
Знаешь что самое интересное, ведь по началу был хороший код.
>>890853>>890860
#526 #890849
И не разводите тут флуд по 20 постов без полезного содержания. Посты не по теме треда тут не нужны. Собак идите в /zoo обсуждать.

>>890794

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

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

>>890763

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

>>890761

Если вникать лень, может и комментарий писать не стоит?

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

>>890740

- разнеси отдельно логику и шаблоны в соответствие с MVC ( http://www.phpinfo.su/articles/practice/shablony_v_php.html https://github.com/codedokode/pasta/blob/master/arch/mvc.md )
- не пиши HTML код внутри echo, это неудобно
- вынеси код работы с БД отдельно от работы с формой

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

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

>>890804

Тебе рано брать фреймворки. Для начала стоит поизучать функции, ООП, MVC.
#526 #890849
И не разводите тут флуд по 20 постов без полезного содержания. Посты не по теме треда тут не нужны. Собак идите в /zoo обсуждать.

>>890794

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

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

>>890763

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

>>890761

Если вникать лень, может и комментарий писать не стоит?

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

>>890740

- разнеси отдельно логику и шаблоны в соответствие с MVC ( http://www.phpinfo.su/articles/practice/shablony_v_php.html https://github.com/codedokode/pasta/blob/master/arch/mvc.md )
- не пиши HTML код внутри echo, это неудобно
- вынеси код работы с БД отдельно от работы с формой

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

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

>>890804

Тебе рано брать фреймворки. Для начала стоит поизучать функции, ООП, MVC.
#527 #890853
>>890848
Работает.
Форма ПОЛУЧИТЬ КОНСУЛЬТАЦИЮ не работает.

Такое кстать и без php можно сделать за часик. Это если еще такие просьбы будут.
>>890859
#528 #890855
Анон, помоги.
Что я делаю не так?
Задача "На словах ты Лев Толстой"
http://ideone.com/ZGNHrv
>>890894
#529 #890859
>>890853
а что ты там потыкал?
>>890890
#530 #890860
>>890848

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

>>890761

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

>>890763

И в такой тоже.

>>890712

Это именованные подмаски: http://php.net/manual/ru/regexp.reference.subpatterns.php

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

http://php.net/manual/ru/function.preg-match.php - тут смотри примеры кода.

>>890637

Вот ты говоришь, что знаешь обычную верстку, но не знаешь адаптированную, это как? Это ведь скорее всего значит что ты и обычную не знаешь.

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

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

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

Технически это делается с помощью @media-правил (медиазапросов) и метатега meta viewport. Погугли и изучи их.

ну например:

- https://habrahabr.ru/company/google/blog/173861/
- https://html5book.ru/css3-mediazaprosy/
- http://frontender.com.ua/mobile-web/wtf-viewport/

Также погугли статьи вроде "лучшие отзывчивые сайты" и посмотри примеры там. Ты можешь имитировать узкий экран, сделав окно браузера узким или исплоьзуя "режим тестирования адаптивной верстки" (иконка смартфона) в отладчике браузера (Ctrl + SHift + I). А если у тебя есть смартфон, ты можешь открывать сайты на нем и сравнивать с обычной версией.

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



А ты сам CSS изучил хорошо? Например, знаешь отличия вестки горизонтально идущих блоков инлайн-блоками от верстки флоатами? Если нет, то тебе надо изучить позиционирование, то есть способы, с помощью которых мы задаем относительное расположение блоков.Также, надо изучать, как верстать резиново, то есть с укзанием размеров в процентах либо с автоматическим определением размеров. То есть прежде чем браться за адаптивность, стоит полностью разобраться с позиционированием и резиновой (подстраивающейся под ширину) версткой. У нас в Оп посте есть задачки по теме.
#530 #890860
>>890848

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

>>890761

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

>>890763

И в такой тоже.

>>890712

Это именованные подмаски: http://php.net/manual/ru/regexp.reference.subpatterns.php

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

http://php.net/manual/ru/function.preg-match.php - тут смотри примеры кода.

>>890637

Вот ты говоришь, что знаешь обычную верстку, но не знаешь адаптированную, это как? Это ведь скорее всего значит что ты и обычную не знаешь.

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

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

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

Технически это делается с помощью @media-правил (медиазапросов) и метатега meta viewport. Погугли и изучи их.

ну например:

- https://habrahabr.ru/company/google/blog/173861/
- https://html5book.ru/css3-mediazaprosy/
- http://frontender.com.ua/mobile-web/wtf-viewport/

Также погугли статьи вроде "лучшие отзывчивые сайты" и посмотри примеры там. Ты можешь имитировать узкий экран, сделав окно браузера узким или исплоьзуя "режим тестирования адаптивной верстки" (иконка смартфона) в отладчике браузера (Ctrl + SHift + I). А если у тебя есть смартфон, ты можешь открывать сайты на нем и сравнивать с обычной версией.

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



А ты сам CSS изучил хорошо? Например, знаешь отличия вестки горизонтально идущих блоков инлайн-блоками от верстки флоатами? Если нет, то тебе надо изучить позиционирование, то есть способы, с помощью которых мы задаем относительное расположение блоков.Также, надо изучать, как верстать резиново, то есть с укзанием размеров в процентах либо с автоматическим определением размеров. То есть прежде чем браться за адаптивность, стоит полностью разобраться с позиционированием и резиновой (подстраивающейся под ширину) версткой. У нас в Оп посте есть задачки по теме.
>>891622
#531 #890872
>>890761

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

В твоем случае у нам фактически получается 2 приложения (клиент + сервер), которые надо поддержвать, плюс АПИ между ними. Код получается сложнее, сайт грузится и работает медленнее.

Не так давно какие-то иностранные чуваки решили похвастаться сделанным сайтом на HN: https://whosfiring.com/ (всего 3 недели прошло и уже не работает)

дискуссия на HN: https://news.ycombinator.com/item?id=12956243

Эти чуваки сделали мегабайтное яваскрипт-приложение на Ember, чтобы отправить запрос через REST API и вывести на странице 10 ссылок с абзацем текста. Любому понятно, что сразу отдать с сервера страницу с 10 ссылками было бы быстрее и с точки зрения времени загрузки сайта, и с точки зрения разработки. (Ну ОП конечно зашел в тред и пояснил им, в чем они не правы).

Не надо тащить клиенсткие приложения там, где они не нужны и не дают преимуществ. Так же как не надо арендовать строительный кран для постройки собачьей будки.
#532 #890890
>>890859
Ввел имя и телефон. Нажал на кнопку.
>>891018
#533 #890892
>>890457

Ты можешь сделать так:

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

>>889959

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

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

> Есть некий общий класс StorageCore, который включает в себя экземпляры всех storage models и через этот общий класс происходит работа с этими экземлярами


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

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


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

Майкрософт пытался решить эту проблему в C#. Они сделали LINQ, это напоминающий SQL синтаксис, который позволяет одинаково работать с коллекицями (массивами) как с базой данных. Также есть библиотеки, которые транслируют LINQ в SQL запросы и таким образом, один и тот же код может выбирать данные как из таблицы, так и из массива. Вот пример:

... result = from u in users
where u.CreditLimit.Value > 20000
select new
{
u.FirstName,
u.LastName,
u.Address1_City
};

Это очень продвинутая штука. Ну например, ты можешь в условие WHERE передать анонимную функцию вида x => x > 10 и она сама разберет код этой функции и сделает из нее аналогичное SQL условие. Ты замучаешься делать аналог этой технологии.

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

В PHP что-то отдаленно похожее есть в ORM Доктрине. Там есть свой язык DQL, и она разбирает запросы на нем, генерируя SQL. Теоретически можно написать интерпретатор таких запросов, который позволит их выполнять не на базе данных, а на массиве. Это долго и сложно. Я предложил использовать DQL вместо SQL, так как для него уже есть парсер. Хотя если погуглить, можно и для SQL найти парсер: https://github.com/greenlion/PHP-SQL-Parser

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

Другой подход - отказаться от чистого SQL и составлять запросы с помощью Query Builder, так:

$b = $em->createQueryBuilder();
$b->from('users', 'u');
$b->andWhere('u.karma > 10');
$b->orderBy('u.name');

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

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

Есть разные варианты, например, можно перед тестом очищать базу и загружать в нее заранее опрделенные данные (fixtures). Можно тест заворачивать в транзакцию, и делать rollback (откат) в конце.
#533 #890892
>>890457

Ты можешь сделать так:

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

>>889959

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

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

> Есть некий общий класс StorageCore, который включает в себя экземпляры всех storage models и через этот общий класс происходит работа с этими экземлярами


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

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


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

Майкрософт пытался решить эту проблему в C#. Они сделали LINQ, это напоминающий SQL синтаксис, который позволяет одинаково работать с коллекицями (массивами) как с базой данных. Также есть библиотеки, которые транслируют LINQ в SQL запросы и таким образом, один и тот же код может выбирать данные как из таблицы, так и из массива. Вот пример:

... result = from u in users
where u.CreditLimit.Value > 20000
select new
{
u.FirstName,
u.LastName,
u.Address1_City
};

Это очень продвинутая штука. Ну например, ты можешь в условие WHERE передать анонимную функцию вида x => x > 10 и она сама разберет код этой функции и сделает из нее аналогичное SQL условие. Ты замучаешься делать аналог этой технологии.

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

В PHP что-то отдаленно похожее есть в ORM Доктрине. Там есть свой язык DQL, и она разбирает запросы на нем, генерируя SQL. Теоретически можно написать интерпретатор таких запросов, который позволит их выполнять не на базе данных, а на массиве. Это долго и сложно. Я предложил использовать DQL вместо SQL, так как для него уже есть парсер. Хотя если погуглить, можно и для SQL найти парсер: https://github.com/greenlion/PHP-SQL-Parser

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

Другой подход - отказаться от чистого SQL и составлять запросы с помощью Query Builder, так:

$b = $em->createQueryBuilder();
$b->from('users', 'u');
$b->andWhere('u.karma > 10');
$b->orderBy('u.name');

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

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

Есть разные варианты, например, можно перед тестом очищать базу и загружать в нее заранее опрделенные данные (fixtures). Можно тест заворачивать в транзакцию, и делать rollback (откат) в конце.
>>890956
#534 #890893
>>889959

Ну и вместо написания своих Storage Models, советую рассмотреть вариант использовать готовый ORM вроде Doctrine или другой. Хотя у них и недостатки тоже есть.

> 2 - Domain Models - модели-объекты записей данных. Т.е. каждый экземпляр этого класса представляет собой конкретную запись в БД.



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

> Service Models - модели-сервисы,


Правильнее просто сервисы. Сервисы это часть модели в MVC, но их так, как ты, никто не называет.

> Bind Models - модели, которые получают данные от пользователя (формы, get-запросы)


Это называется формы. В Симфони есть компонент Symfony Forms (его можно использовать отдельно) для работы с формами и валидации. Он умеет автоматически переносить данные из моделей в форму и обратно.

> и затем обращаются к service models, получая необходимые данные


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

> View Models - модели, которые являются тем же набором разного рода domain models. Эти модели далее передаются во View (т.е. внутри себя содержат еще какие-то вспомогательные методы, к которым мы обращаемся из View.



Опять выглядит как усложнение, что мешает передавать во вью сразу Domain Models? view model как правило не используется в серверном коде, только в клиентском варианте MVC с паттернами вроде data binding.

Я советую тебе не усложнять без надобности и почитать туториалы по Симфони. Многие компоненты Симфони можно использовать отдельно, и ты можешь даже собрать из них свой фреймворк.
#535 #890894
>>890855

Код вроде работает. Но выражение в строке лучше заключать в фигурные скобки ( http://php.net/manual/ru/language.types.string.php#language.types.string.parsing ) и избавиться от повтора кода, например, циклом.

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

[$word1, ' ', $word2, ' ', ...]

И генерировать стих по нему.
#536 #890895
Кстати, аноны, которые интересуются ООП и архитектурой, и хотят поучиться разбирать чужой код, можете поломать себе мозги. Есть библиотека-парсер SQL запросов: https://github.com/greenlion/PHP-SQL-Parser

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

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

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

Что бы вы предложили поменять? Как бы вы решали такую задачу?

Заметьте, что в библиотеке есть тесты. В них можно посмотреть примеры ее использования.
>>890907
#537 #890907
ИМХО.

>>890895

>искать в нем баги и исправлять их


Система ошибок так себе

>>890895
Нужен парсер грамматики

>>использовать код, ну допустим у вас есть задача найти все упоминаемые в SQL запросе названия таблиц или например оценить число строк, которое выберет запрос


PVS Studio только для SQL

>- поддерживать код


Ну вы понели))
Да у вас архитектуры как таковой я и не заметил.
#538 #890920
Поясните мне за алгоритмы, стоит ли их учить?
Просмотрел вакансии на back-end разработчика, и практически нигде не написано в требованиях "алгоритмы".
Это маст хэв вещь?
#539 #890956
>>890498
>>890892
Спасибо, попробовал оба способа, все заработало.
1 Кб, 339x75
#540 #891018
>>890890
ты ето прислал? Просто я сейчас ввел все и у меня заработало.
#541 #891027
Не могу понять одну вещь:

Есть абстрактный класс Model, у него наследники Employee и Department.

Есть абстрактный класс TableDataGateway, у него наследники EmployeeTDGW и DepartmentTDGW

Я в классе TableDataGateway пишу: abstract public function add(Model $object); - подразумевая, что можно передавать только Model и её наследников

В дочерних классах я хочу видеть что-то типа public function add(Department $department) - уточняю, что не любой Model, а только Department

Но выскакивает warning кричащий о несоответствии типов. Пришлось в наследниках так-же прописывать Model в качестве переданных параметров.

Как можно сделать такое уточнение и что-бы валидатору понравилось моё решение?
#542 #891046
>>891027
Наследование это вид отношения "А является подмножеством B", то есть мы в любой момент можем подставить вместо родительского класса дочерний и всё должно быть ок, так как наследник именно расширяет родительский класс, а не уточняет, в противном случае нарушается контракт. Это один из принципов SOLID.
Я бы взял готовую ОРМ в твоём случае.
>>891524
#543 #891122
>>891027
Либо делай отдельный
public function addDepartment (Department $department)

Либо в методе проверяй тип с помощью instanceof
>>891524
#544 #891208
>>891027

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

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

Можно считать это особенностью наследования. Есть еще другие известные проблемы, например проблема квадрата и прямоугольника: http://sergeyteplyakov.blogspot.ru/2014/09/liskov-substitution-principle.html

В твоем случае можно конечно в классе-наследнике поставить проверку через if .. instanceof, но это будет лишь попытка костылем обойти принцип Лисков.

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

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

Возможно ты хотел сделать абстрактный метод, чтобы требовать от наследников возможность делать вставку. В этом случае надо сделать один метод add в базовом классе, а абстрактным сделать метод вроде getTableName().
>>891524
#545 #891225
Ребят, решил изучить ларавел после джанго. Для него критично знать пхп ? Руби на рельсах трогал без знания рубей и дискомофорта не испытовал. И как по сложности изучения данный фреймворк? говорят как рельсы в мире пхп, так еще и вьюжс как свой фронтенд взяли.
>>891234>>891356
#546 #891234
>>891225
Если программировать умеешь (независимо от языка), то можешь и не трогать.
#547 #891356
>>891225

Лучше брось эту идею и иди изучать Node.JS. Там синтаксис почти повторяет Питон и Руби, это более модная технология, и наверняка ты уже яваскрипт знаешь на достаточном уровне.
>>891393
#548 #891393
>>891356
Пробовал примерно год назад - слишком много жс-лапшы получается(ну это я еще пхп не пробовал, лол). Модная технология, то модная. Но с таким же успехом можно и в сторону го какого-нибудь посмотреть
>>891396
#549 #891396
>>891393

У тебя на PHP код будет еще хуже. Иди изучай какой-нибудь другой язык.
#550 #891435
>>891027
Не делай так, это говнокод. Методы дочерних классов должны полностью соответствовать методам родительских. Если нужно что-то новое, пиши новый метод или используй композицию.
>>891524
#551 #891454
Узнал, что в России оказывается есть "госмониторинг" для госсайтов: https://gosmonitor.ru/

Рисует всякие интересные графики: https://gosmonitor.ru/mob/229

И отчеты: https://gosmonitor.ru/expertresult/82982

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

Если вспомнить провал с дорогущим американским сайтом по здравоохранению, то у нас все не так и плохо. Потихоньку все это развивается, что радует.

Хотя конечно методику оценки открытых данных, на мой взгляд, переусложнили: https://gosmonitor.ru/expertresult/235712

> 20


> Информация о приложениях, разработанных на основе размещенных наборов открытых данных



Не думаю, что это нужно.
#552 #891455
>>891454

Сделан кстати на Друпале и PHP (а я думал, на дотнете).
>>891457
#553 #891456
>>891454
ого гусьмонитор есть ахуеть прогресс, заживем, завтра же доктора перестанут всем зеленкой мазать анус, прописывать глицын, свежий воздух сон и утреннюю зарядку вместо блять реальных лекарств, ВСД и астения станут страшной байкой для молодых врачей.
#554 #891457
>>891455

>2k16


>дауннет


лулирую
#555 #891479
>>890837

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


Добавил отступы: https://github.com/someApprentice/maintaskforlayout/commit/d3fc44bc664b9ea61a7aefef33a072e2fec35a64

>- список consecuter, tristlquet на такой ширине было бы выгоднее выводить в 2-3 колонки, а не вертикально. Если там сделать верстку теми же инлайн-блоками, то они будут подстраиваться сами под ширину страницы.


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

>В версии для ИЕ8 ( https://www.browserstack.com/screenshots/5e7365e06a803d67a956cebf9704fc0ca6a4fc4c/win7_ie_8.0.jpg ) отвалились картинки в блоке consecuter (там используется что-то из CSS3? В принипе, можно и без них конечно) и в блоке социальных кнопок внизу появились надписи.


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

>В мобильной версии ( https://www.browserstack.com/screenshots/5e7365e06a803d67a956cebf9704fc0ca6a4fc4c/ios_iPhone-6-Plus_8.3_portrait.jpg ) шрифт в шапке слишком большой. Наверно надо для мобильных устройств его уменьшить.


Уменьшил шрифт (и нечаянно вместе с этим закоммитил исправление с двойными двоеточиями): https://github.com/someApprentice/maintaskforlayout/commit/97590807dc8da1d88e4e738b7f0c8a336ecf585b
#556 #891482
>>891454

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


А я никогда не сомневался в отечественных ИТ'шниках. Уверен что в службе безопасности всё на высшем мировом уровне с этим. Если по вашему мнению это только начало развития, то меня это только радует, потому что это даёт большой простор для меня где можно заработать.
#557 #891497
ОП, салам, вот в задание про проверку номеров("Регулярные выражения")

>^\\s(8|([+]\\s7))...


Дальше нужно чекать 10цифр, пока придумал просто написать кусок, а потом его 10раз скопировать, но есть ли способ лучше? Уже 3-тий или 4-ый день пытаюсь придумать, чёто нихуя.
>>891502>>893882
9 Кб, 400x159
#558 #891502
>>891497
Можно ещё вот так как-нибудь сократить, но всё равно, может целиком выражение можно записать?
>>891503>>893882
#559 #891503
>>891502
http://ideone.com/B84CCu
вот если так удобней.
#560 #891514
Как из базы данных извлечь последнюю строку?
>>891522>>893882
8615 Кб, Webm
Файлообменник #561 #891520
Оп, я опять выхожу на связь со своим говнокодом. Много еще не сделано, но нужны твои советы. Верстки пока почти нет и почему-то не отображаются превью для картинок.
https://github.com/anotherCodeMunkey/fileshare
>>891523
#562 #891522
>>891514
LIMIT 1
ORDER BY `ID` DESC
>>891596
#563 #891523
>>891520
Почему их никто не научил, что собаки и кошки должны ненавидеть друг друга?
>>891853
#564 #891524
>>891046
>>891122
>>891208
>>891435

Спасибо большое! Я сделал костыль instanceof. Исправлять не буду - уже отправил и человеку понравилось (это тестовое на вакансию). Зато новое узнал о наследовании
#565 #891596
>>891522
Что-то нихуя не работает. Если точнее, то надо вытащить из БД цифру последнюю самую.
>>891598
#566 #891598
>>891596
Все, отбой, заработало.
#567 #891621
Есть класс форумов, на которых ссылки в постах не закрываются тегами noindex и nofollow. Можно ли написать парсер на ПХП для поиска таких форумов? И если да, то как его писать? С ПХП знаком, но если честно не представляю как сделать поиск такой форумов. Может кто подсказать? надо каким-то образом перебирать адреса сайтов, исследовать ссылки в постах на наличие этих тегов, но как знать какие адреса перебирать?
>>893881
#568 #891622
>>890860

>Вот ты говоришь, что знаешь обычную верстку, но не знаешь адаптированную, это как? Это ведь скорее всего значит что ты и обычную не знаешь.


Возможно ты прав, я знаю принципы адаптивной вёрстки, и вроде бы их применяю, но когда дело доходит до реального проекта вылезают всякие недочёты, что-то не получается выравнять так как нужно потому что что-то другое мешает. Ну а вообще мне не принципиально считать сейчас знаю я обычную вёрстку или нет, мне надо изучить адаптивную вёрстку, чтобы иметь все необходимые скилы для получения работы. Для меня адаптивная вёрстка сложнее даже чем ООП в ПХП, не знаю почему
>>891713>>893881
#569 #891707
Добрый день, работал ли кто-нибудь с этой оберткой над курлом/мультикурлом? Не могу найти инфы либо я неверно формирую вопрос: К примеру у меня миллион ссылок, я же не могу весь миллион сразу добавить через addGet и потом в конце запустить start, но вот вопрос, к примеру есть цикл который достается из базы по (ну к примеру 2к) ссылок и добавляет их через addGet() потом запускаю через метод start() и вот на следующем витке цикла (следующие 2к ссылок) будет ли очищен предыдущий список ссылок мультикурла и не будет ли addGet() добавлять их к прошлому списку. И не надо ли создавать новый экземпляр мультикурла в начале каждого цикла? Не нашел развернутой документации по обертке, только простенькие примеры и общий перечень методов.
#570 #891709
#571 #891713
>>891622
Новички часто верстают абсолютами и/или жестким позиционированием, с виду получается похоже на макет, но такой метод верстки чреват бессонными ночами в будущем, потому что тебе придется практически заново всё верстать под каждый медиа.
То-есть не зацикливайся над каким-то конкретным элементом конкретной страницы, сперва сделай каркас без жестких рамок и он будет уже по своему адаптивным, пользуйся REM, EM для font-size. Пользуйся процентами и готовыми grid'ами, но если тебе нужна только сетка в проекте - не тащи весь пак того же бутстрапа, возьми только сетку. Я не верстальщик, могу в чем-то быть не прав, но версткой занимался когда только взяли на работу.
#572 #891853
>>891523
Две половинки твоего мозга ненавидят друг друга, из-за этого должны ненавидеть друг друга животные?
#573 #892109
>>891707
Ты настолько даун, что свою обертку для curla написать не можешь? Даже я их пишу, уж на что юниор.
>>892423>>893881
https://github.com/TheSidSpears/FileHosting #574 #892217
>>882369

>>866133



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

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

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

Там, где выводятся подробности о файле, не хватает единиц измерения. "Частота дискретизации: 44100". 44100 чего?

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

"Подтвердите... Подумай..." - лучше тогда было написать "Подтверди". Да, это не замечания по коду, но в реальном проекте у тебя вряд ли будет персональный корректор, который будет за тобой исправлять сообщения и лучше учиться обращать внимание на такие вещи. И сразу же на будущее скажу, не смешивай английские и русские сообщения в одном интерфейсе ("размер: 11.3 Mb" -> "размер: 11,3 Мб").

> Время загрузки: 2016-10-31



Ой-ой, какой роботизированный формат. В русском языке даты обычно пишут либо как "31.10.2016", либо "31 октября 2016".

> composer.phar


Это не твой код, ему в репозитории делать нечего. Стоит добавить его в gitignore и убрать из репозитория.

https://github.com/TheSidSpears/FileHosting/blob/master/httpd.conf
Тут в примере конфига блок с localhost явно лишний и не относится к файлообменнику.

https://github.com/TheSidSpears/FileHosting/blob/master/filehosting.sql#L31

> `path` mediumtext NOT NULL,


MEDIUMTEXT - это текст размером до 16 мегабайт по моему, и это многовато для пути. Также, по полям типа TEXT по моему нельзя делать индексы, так что тут однозначно лучше исплоьзовать varchar. Индексы обязательно нужны, иначе после нескольких тысяч комментариев в таблице все начнет работать небыстро (советую статью http://ruhighload.com/post/Работа+с+индексами+в+MySQL для ознакомления).

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

В таблице файлов не очень понятно зачем разделять путь к файлу на path и name.

> `size` int(11)


int принимает значения от -2 до +2 млрд. То есть у тебя нельзя хранить файлы больше 2 Гб.

> `mime` text,


TEXT содержит до 65535 байт. Многовато для маленькой строки.

> `numberOfDownloads` int(255)


255 тут рекомендуемая ширина колонки для вывода числа (на хранение оно никак не влияет). Не многовато ли?

https://github.com/TheSidSpears/FileHosting/blob/master/public/index.php#L3

> if (PHP_SAPI == 'cli-server') {


Хотя так можно, я бы вынес код роутинга для встроенного в php сервера в отдельный файл, например cli-server.php. Хотя с другой стороны, он небольшой и особо не мешает. И это, как я понимаю, разработчики Слима такое придумали.

https://github.com/TheSidSpears/FileHosting/blob/master/src/settings.php#L9

> 'addContentLengthHeader' => false, // Allow the web server to send the content-length header


А в чем смысл этой настройки? Зачем отключать этот заголовок?

Мне, конечно, кажется, что файл настроек получился какой-то громоздкий. Хорошо бы хранить там только те настройки, которые пользователь может поменять, а те, что не может, хранить где-то в коде. Как я понимаю, это опять же придумали разработчики Слима, что-то мне это не очень нравится. Какой смысл смешивать пользовательские и внутренние настройки? Вообще, мне это разделение на seetings.php/dependencies и так далее, не нравится. Во втором слиме все просто писалось в одном файле, и предполагалось, что кода будет немного, и потому можно его хранить в одном файле. Ну и читать было легко и удобно. А сейчас они раскидали все по 4 файлам, и я не вижу, какие это преимущества дает.

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

Ну к примеру, представим, что мы хотим сделать программу для командной строки и в ней использовать контейнер. Как ее инициализировать? В студентах мы делали файл bootstrap.php, который инициализирует приложение, а тут - придется видимо копипастить код из index.php.

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

https://github.com/TheSidSpears/FileHosting/blob/master/src/middleware.php
тут остался бесполезный код

> //Определяем переменные, которые используются в >1 роутере


> function init_vars($container){


Там по моему просто можно как-то добавить переменную во вью. В Слим 2 это было что-то вроде $app->view->set('x', 1); Посмотри-ка, нельзя ли тут так же сделать. А то какие-то костыли идут. И плюс, из-за объявления функции файл routes.php стало нельзя подключать дважды (в тестах там на каждый тест приложение инициализируется заново).

> $app->get('/[message/{code}]'


Я думаю, неправильно использовать путь в URL для уведомления. Ведь новый путь в УРЛ обычно соответствует новой странице. Но страница-то одна, значит и путь у нее должен быть один. А для передачи уведомления лучше использовать параметр в query string: /?notify=deleted.

> $messager=new CodeMessager();


> $isValidCode=$messager->setCode($args['code']);


Мне не оченть нравится такой способ использования класса. Вот у тебя сделано так:

$m->setCode(..);
echo $m->getText();

Но ведь есть минимум 2 других способа:

1) объект представляет собой 1 сообщение: $m = new Message($code); echo $m->getText();
2) объект является сервисом для работы с разными кодами сообщений $m = new Message(); echo $m->getText($code);

Твой способ выглядит как без надобности усложненный вариант 2. При твоем подходе сложнее понять, как использовать класс, так как не очевидно, что надо вызвать setCode перед getText.
https://github.com/TheSidSpears/FileHosting #574 #892217
>>882369

>>866133



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

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

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

Там, где выводятся подробности о файле, не хватает единиц измерения. "Частота дискретизации: 44100". 44100 чего?

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

"Подтвердите... Подумай..." - лучше тогда было написать "Подтверди". Да, это не замечания по коду, но в реальном проекте у тебя вряд ли будет персональный корректор, который будет за тобой исправлять сообщения и лучше учиться обращать внимание на такие вещи. И сразу же на будущее скажу, не смешивай английские и русские сообщения в одном интерфейсе ("размер: 11.3 Mb" -> "размер: 11,3 Мб").

> Время загрузки: 2016-10-31



Ой-ой, какой роботизированный формат. В русском языке даты обычно пишут либо как "31.10.2016", либо "31 октября 2016".

> composer.phar


Это не твой код, ему в репозитории делать нечего. Стоит добавить его в gitignore и убрать из репозитория.

https://github.com/TheSidSpears/FileHosting/blob/master/httpd.conf
Тут в примере конфига блок с localhost явно лишний и не относится к файлообменнику.

https://github.com/TheSidSpears/FileHosting/blob/master/filehosting.sql#L31

> `path` mediumtext NOT NULL,


MEDIUMTEXT - это текст размером до 16 мегабайт по моему, и это многовато для пути. Также, по полям типа TEXT по моему нельзя делать индексы, так что тут однозначно лучше исплоьзовать varchar. Индексы обязательно нужны, иначе после нескольких тысяч комментариев в таблице все начнет работать небыстро (советую статью http://ruhighload.com/post/Работа+с+индексами+в+MySQL для ознакомления).

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

В таблице файлов не очень понятно зачем разделять путь к файлу на path и name.

> `size` int(11)


int принимает значения от -2 до +2 млрд. То есть у тебя нельзя хранить файлы больше 2 Гб.

> `mime` text,


TEXT содержит до 65535 байт. Многовато для маленькой строки.

> `numberOfDownloads` int(255)


255 тут рекомендуемая ширина колонки для вывода числа (на хранение оно никак не влияет). Не многовато ли?

https://github.com/TheSidSpears/FileHosting/blob/master/public/index.php#L3

> if (PHP_SAPI == 'cli-server') {


Хотя так можно, я бы вынес код роутинга для встроенного в php сервера в отдельный файл, например cli-server.php. Хотя с другой стороны, он небольшой и особо не мешает. И это, как я понимаю, разработчики Слима такое придумали.

https://github.com/TheSidSpears/FileHosting/blob/master/src/settings.php#L9

> 'addContentLengthHeader' => false, // Allow the web server to send the content-length header


А в чем смысл этой настройки? Зачем отключать этот заголовок?

Мне, конечно, кажется, что файл настроек получился какой-то громоздкий. Хорошо бы хранить там только те настройки, которые пользователь может поменять, а те, что не может, хранить где-то в коде. Как я понимаю, это опять же придумали разработчики Слима, что-то мне это не очень нравится. Какой смысл смешивать пользовательские и внутренние настройки? Вообще, мне это разделение на seetings.php/dependencies и так далее, не нравится. Во втором слиме все просто писалось в одном файле, и предполагалось, что кода будет немного, и потому можно его хранить в одном файле. Ну и читать было легко и удобно. А сейчас они раскидали все по 4 файлам, и я не вижу, какие это преимущества дает.

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

Ну к примеру, представим, что мы хотим сделать программу для командной строки и в ней использовать контейнер. Как ее инициализировать? В студентах мы делали файл bootstrap.php, который инициализирует приложение, а тут - придется видимо копипастить код из index.php.

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

https://github.com/TheSidSpears/FileHosting/blob/master/src/middleware.php
тут остался бесполезный код

> //Определяем переменные, которые используются в >1 роутере


> function init_vars($container){


Там по моему просто можно как-то добавить переменную во вью. В Слим 2 это было что-то вроде $app->view->set('x', 1); Посмотри-ка, нельзя ли тут так же сделать. А то какие-то костыли идут. И плюс, из-за объявления функции файл routes.php стало нельзя подключать дважды (в тестах там на каждый тест приложение инициализируется заново).

> $app->get('/[message/{code}]'


Я думаю, неправильно использовать путь в URL для уведомления. Ведь новый путь в УРЛ обычно соответствует новой странице. Но страница-то одна, значит и путь у нее должен быть один. А для передачи уведомления лучше использовать параметр в query string: /?notify=deleted.

> $messager=new CodeMessager();


> $isValidCode=$messager->setCode($args['code']);


Мне не оченть нравится такой способ использования класса. Вот у тебя сделано так:

$m->setCode(..);
echo $m->getText();

Но ведь есть минимум 2 других способа:

1) объект представляет собой 1 сообщение: $m = new Message($code); echo $m->getText();
2) объект является сервисом для работы с разными кодами сообщений $m = new Message(); echo $m->getText($code);

Твой способ выглядит как без надобности усложненный вариант 2. При твоем подходе сложнее понять, как использовать класс, так как не очевидно, что надо вызвать setCode перед getText.
https://github.com/TheSidSpears/FileHosting #575 #892218
>>882369

>>866133



> https://github.com/TheSidSpears/FileHosting/blob/master/src/routes.php#L39


Вот тут многовато что-то кода получается. Я бы стремился к такому:

$fileModel = $fileService->prepareFile(...);
$errors = $fileService->storeFile($fileModel);

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

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

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

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

Вместо COOKIE/setcookie лучше использовать объекты запроса/ответа Слима. Тогда например можно будет как-то тестировать этот роут.

> $userId['files']=$this->filesGW->getFile($_COOKIE['fileId'])->userId;


Не очень понимаю, зачем нужна кука fileId. id файла, для которого делается описание, надо передавать в запросе. А с кукой все как-то переусложнено получается.

> ($_POST['description']


надо использовать объект запроса

> $messager=new OutMessager();


> $messager->setType(OutMessager::TYPE_ERROR);


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

Вместо возврата массива или true из функции валидации лучше возвращать массив или пустой массив. Плохо делать у функции нескоько типов возвращаемых значений.

> $userId['files']=$this->filesGW->getFile($_COOKIE['fileId'])->userId;


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

> if (isset($url)) {


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

> if ($validErrors===true) {


> //Записываем в БД


> $this->commentsGW->addComment($comment);


После успешной обработки POST запроса надо делать редирект. Это по моему было написано в моем уроке про формы. Иначе обновление страницы отправит второй запрос.

Когда ты пишешь if/else, где одна ветка маленькая, а другая большая, и маленькая содержит что-нибудь вроде показа 404 страницы, она должна идти первой ради читабельности.

> $fileUri=Helper::getPathForFile($this->settings['uploadUri'],$fileModel);


Неудобно каждый раз передавать URL папки с файлами. Лучше передать ее в конструктор класса-хелпера.

Плохо, что ты используешь один и тот же массив $args, и для хранения пришедших из роута аргументов, и для передачи во view.

> if ($_POST['nick']==NULL) {


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

> //Средствами PHP


> $file=readfile($path);


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

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

Тебе также надо разобраться, что такое и зачем нужны объекты request/response в Слиме.

> $app->get('/delete/{id}'


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

Проверку прав тоже можно бы вынести в функцию вида:

...->canModify($user, $file)

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

Удаление у тебя опять же, сделано простыней в контроллере. Лучше сделать нормальную функцию где-то в сервисе, которая позволит за 1 вызов удалить файл отовсюду. Также, порядок удаления неправильный. Что будет, если скрипт упадет после удаления файла из ФС, но до удаления из БД?

https://github.com/TheSidSpears/FileHosting/blob/master/src/classes/FilesFileManager.php
Этот класс назван неправильно. По определению, "менеджер файлов" - это класс, который позволяет обработать несколько файлов, но у тебя там есть поля вроде $path, и класс видимо рассчитан на работу с единственным файлом.

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

> execDisable($fileName)


Имя функции должно начинаться с глагола.

> if (!preg_match("/^((\w)|(\d)|[ -_])(.)(".implode('|', $this->validTypes).")$/iu", $fileName)){


Вместо этой сложной регулярки лучше получить расширение файла и сравнить со списком.

https://github.com/TheSidSpears/FileHosting/blob/master/src/classes/FilesFileManager.php#L45

> if (copy($_FILES['file']['tmp_name'],


Почему у тебя в модели идет работа с параметрами из HTTP-запроса? Это не соответствует идее MVC.

> public function addComment(Comment $comment){


> @return bool status of adding to DB


У тебя же стоит режим ERRMODE_EXCEPTION? Тогда exec не должен вернуть false.

https://github.com/TheSidSpears/FileHosting/blob/master/src/classes/DataBase/CommentsTDGW.php#L60
Тут в generatePath нет проверки на случай, если указан несуществующий parentId.

> //Выбираем путь самого последнего дочернего коммента (001.003.007)


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

Вообще, мне кажется там можно было бы получить самый последний коммент одним запросом c MAX()/ORDER BY DESC, а не двумя, как у тебя.

> AND `path` LIKE '$path.%'


данные надо передавать через плейсхолдеры.

> AND `path` LIKE '___' /три символа*/


Этот запрос не оптимизировать индексами. Надо выбирать по parentId IS NULL + MAX или ORDER BY.

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

> $nulls = ($len==1) ? '00' : '0';


Есть str_pad и sprintf для этого.

> return $this->db->lastInsertId();


Можно этот id сразу проставлять в объект File.

https://github.com/TheSidSpears/FileHosting/blob/master/src/classes/Models/Comment.php#L48
Вот здесь записано число символов в пути. Но еще оно записано в классе CommentGW. Нехорошо. Я думаю, лучше сделать у commentsGW статический метод для вычисления глубины (или для разбиения пути на части) и тут его вызывать.

> public function addInfo


Вот название не очень. Info ничего не значит, потому получается просто add(). Лучше бы назвать setAttributes или setProperties.

https://github.com/TheSidSpears/FileHosting/blob/master/src/classes/Helpers/CodeMessager.php#L23

> foreach ($this->messages as $key => &$code) {


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

> abstract class Messager{


Правильнее передавать код в конструктор и назвать класс Message. OutMessager тоже переименовать нормально.
https://github.com/TheSidSpears/FileHosting #575 #892218
>>882369

>>866133



> https://github.com/TheSidSpears/FileHosting/blob/master/src/routes.php#L39


Вот тут многовато что-то кода получается. Я бы стремился к такому:

$fileModel = $fileService->prepareFile(...);
$errors = $fileService->storeFile($fileModel);

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

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

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

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

Вместо COOKIE/setcookie лучше использовать объекты запроса/ответа Слима. Тогда например можно будет как-то тестировать этот роут.

> $userId['files']=$this->filesGW->getFile($_COOKIE['fileId'])->userId;


Не очень понимаю, зачем нужна кука fileId. id файла, для которого делается описание, надо передавать в запросе. А с кукой все как-то переусложнено получается.

> ($_POST['description']


надо использовать объект запроса

> $messager=new OutMessager();


> $messager->setType(OutMessager::TYPE_ERROR);


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

Вместо возврата массива или true из функции валидации лучше возвращать массив или пустой массив. Плохо делать у функции нескоько типов возвращаемых значений.

> $userId['files']=$this->filesGW->getFile($_COOKIE['fileId'])->userId;


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

> if (isset($url)) {


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

> if ($validErrors===true) {


> //Записываем в БД


> $this->commentsGW->addComment($comment);


После успешной обработки POST запроса надо делать редирект. Это по моему было написано в моем уроке про формы. Иначе обновление страницы отправит второй запрос.

Когда ты пишешь if/else, где одна ветка маленькая, а другая большая, и маленькая содержит что-нибудь вроде показа 404 страницы, она должна идти первой ради читабельности.

> $fileUri=Helper::getPathForFile($this->settings['uploadUri'],$fileModel);


Неудобно каждый раз передавать URL папки с файлами. Лучше передать ее в конструктор класса-хелпера.

Плохо, что ты используешь один и тот же массив $args, и для хранения пришедших из роута аргументов, и для передачи во view.

> if ($_POST['nick']==NULL) {


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

> //Средствами PHP


> $file=readfile($path);


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

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

Тебе также надо разобраться, что такое и зачем нужны объекты request/response в Слиме.

> $app->get('/delete/{id}'


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

Проверку прав тоже можно бы вынести в функцию вида:

...->canModify($user, $file)

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

Удаление у тебя опять же, сделано простыней в контроллере. Лучше сделать нормальную функцию где-то в сервисе, которая позволит за 1 вызов удалить файл отовсюду. Также, порядок удаления неправильный. Что будет, если скрипт упадет после удаления файла из ФС, но до удаления из БД?

https://github.com/TheSidSpears/FileHosting/blob/master/src/classes/FilesFileManager.php
Этот класс назван неправильно. По определению, "менеджер файлов" - это класс, который позволяет обработать несколько файлов, но у тебя там есть поля вроде $path, и класс видимо рассчитан на работу с единственным файлом.

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

> execDisable($fileName)


Имя функции должно начинаться с глагола.

> if (!preg_match("/^((\w)|(\d)|[ -_])(.)(".implode('|', $this->validTypes).")$/iu", $fileName)){


Вместо этой сложной регулярки лучше получить расширение файла и сравнить со списком.

https://github.com/TheSidSpears/FileHosting/blob/master/src/classes/FilesFileManager.php#L45

> if (copy($_FILES['file']['tmp_name'],


Почему у тебя в модели идет работа с параметрами из HTTP-запроса? Это не соответствует идее MVC.

> public function addComment(Comment $comment){


> @return bool status of adding to DB


У тебя же стоит режим ERRMODE_EXCEPTION? Тогда exec не должен вернуть false.

https://github.com/TheSidSpears/FileHosting/blob/master/src/classes/DataBase/CommentsTDGW.php#L60
Тут в generatePath нет проверки на случай, если указан несуществующий parentId.

> //Выбираем путь самого последнего дочернего коммента (001.003.007)


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

Вообще, мне кажется там можно было бы получить самый последний коммент одним запросом c MAX()/ORDER BY DESC, а не двумя, как у тебя.

> AND `path` LIKE '$path.%'


данные надо передавать через плейсхолдеры.

> AND `path` LIKE '___' /три символа*/


Этот запрос не оптимизировать индексами. Надо выбирать по parentId IS NULL + MAX или ORDER BY.

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

> $nulls = ($len==1) ? '00' : '0';


Есть str_pad и sprintf для этого.

> return $this->db->lastInsertId();


Можно этот id сразу проставлять в объект File.

https://github.com/TheSidSpears/FileHosting/blob/master/src/classes/Models/Comment.php#L48
Вот здесь записано число символов в пути. Но еще оно записано в классе CommentGW. Нехорошо. Я думаю, лучше сделать у commentsGW статический метод для вычисления глубины (или для разбиения пути на части) и тут его вызывать.

> public function addInfo


Вот название не очень. Info ничего не значит, потому получается просто add(). Лучше бы назвать setAttributes или setProperties.

https://github.com/TheSidSpears/FileHosting/blob/master/src/classes/Helpers/CodeMessager.php#L23

> foreach ($this->messages as $key => &$code) {


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

> abstract class Messager{


Правильнее передавать код в конструктор и назвать класс Message. OutMessager тоже переименовать нормально.
https://github.com/TheSidSpears/FileHosting #576 #892219
>>882369

>>866133



https://github.com/TheSidSpears/FileHosting/blob/master/src/classes/Helpers/ID3Choser.php#L55
Вместо этих плясок с заменой ключей, возможно, лучше сделать объект, представляющий информацию о файле, и имеющий методы для ее получения в нужном виде. Хотя, может, можно и так оставить.

> Добавляет хеш к имени файла, игнорируя разрешение (любой вложенности вроде: archive.tar.gz)


> static function addHashToFileName(string $filename)


А ты тестировал эту функцию на файлах без расширения и файлах, начинающихся с точки?

> https://github.com/TheSidSpears/FileHosting/blob/master/src/classes/Validators/Comments.php#L10


> 'message' => 'может состоять из любых символов' //по-идее, это никогда не выводится


Может тогда такое правило вадидации и не требуется?

> {% if messagers is defined %}


Лучше сделать, чтобы эта переменная была всегда.

> alert-{{ messager.getType() }}


Метод надо назвать getCssClass и возвращать название класса целиком, чтобы по нему можно было искать.

https://github.com/TheSidSpears/FileHosting/blob/master/templates/comment_form.html#L5

> aria-describedby="sizing-addon3"


Что-то я сомневаюсь, что символ "@" может служить описанием поля.

> <img src="{{ uploadUri }}{{ file.path }}{{ file.name }}">


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

> {% elseif file.getType() == 'audio' or file.getType() == 'video' %}


> <div class="player" id="uppod_player"></div>


Ты делаешь воспроизведение видео в браузера, а ты знаешь, какие форматы какие бразеры поддерживают? И что надо делать, чтобы, как на ютубе или википедии, работало (почти) везде?

> https://github.com/TheSidSpears/FileHosting/blob/master/public/css/uploader-master.css#L59


> .uploader div.browser label


div в этом правиле явно лишний.

https://github.com/TheSidSpears/FileHosting/blob/master/public/css/uploader-master.css#L91
Здесь странно, что есть -o-transform и -moz-transform, но нет правила без префикса.

Советую не использовать id в верстке, так как преимуществ у них никаких, а недостаток, что два id не могут встречаться на одной странице.

> glyphicon-preview


Плохо, что ты используешь имя класса, похожее на название из бутстрапа. Неочевидно, что это твой класс. Вообще, мне не нравится, что бутстрап не использует префиксы. Я погуглил тут https://github.com/twbs/bootstrap/issues/1235 и как я понимаю, их мнение такое, что они не библиотека, а фреймворк и им незачем ставить префиксы.

https://github.com/TheSidSpears/FileHosting/blob/master/public/js/helper.js#L4

> создаем в форме переменную, содержащую id отвечаемого коммента


Проще было сразу создать это поле в шаблоне.

> Добавляем кнопку "Написать коммент без ответа"


Проще вставить ее в шаблон, но скрыть. Так при изменениях в верстке нам не придется лезть в JS. Вообще, старайся избегать вынесения верстки из HTML в JS.

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

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

И кстати, а ты автоматизированные тесты написать к файлообменнику не хочешь? У меня есть обзорный урок по тестированию, если что: https://gist.github.com/codedokode/a455bde7d0748c0a351a
https://github.com/TheSidSpears/FileHosting #576 #892219
>>882369

>>866133



https://github.com/TheSidSpears/FileHosting/blob/master/src/classes/Helpers/ID3Choser.php#L55
Вместо этих плясок с заменой ключей, возможно, лучше сделать объект, представляющий информацию о файле, и имеющий методы для ее получения в нужном виде. Хотя, может, можно и так оставить.

> Добавляет хеш к имени файла, игнорируя разрешение (любой вложенности вроде: archive.tar.gz)


> static function addHashToFileName(string $filename)


А ты тестировал эту функцию на файлах без расширения и файлах, начинающихся с точки?

> https://github.com/TheSidSpears/FileHosting/blob/master/src/classes/Validators/Comments.php#L10


> 'message' => 'может состоять из любых символов' //по-идее, это никогда не выводится


Может тогда такое правило вадидации и не требуется?

> {% if messagers is defined %}


Лучше сделать, чтобы эта переменная была всегда.

> alert-{{ messager.getType() }}


Метод надо назвать getCssClass и возвращать название класса целиком, чтобы по нему можно было искать.

https://github.com/TheSidSpears/FileHosting/blob/master/templates/comment_form.html#L5

> aria-describedby="sizing-addon3"


Что-то я сомневаюсь, что символ "@" может служить описанием поля.

> <img src="{{ uploadUri }}{{ file.path }}{{ file.name }}">


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

> {% elseif file.getType() == 'audio' or file.getType() == 'video' %}


> <div class="player" id="uppod_player"></div>


Ты делаешь воспроизведение видео в браузера, а ты знаешь, какие форматы какие бразеры поддерживают? И что надо делать, чтобы, как на ютубе или википедии, работало (почти) везде?

> https://github.com/TheSidSpears/FileHosting/blob/master/public/css/uploader-master.css#L59


> .uploader div.browser label


div в этом правиле явно лишний.

https://github.com/TheSidSpears/FileHosting/blob/master/public/css/uploader-master.css#L91
Здесь странно, что есть -o-transform и -moz-transform, но нет правила без префикса.

Советую не использовать id в верстке, так как преимуществ у них никаких, а недостаток, что два id не могут встречаться на одной странице.

> glyphicon-preview


Плохо, что ты используешь имя класса, похожее на название из бутстрапа. Неочевидно, что это твой класс. Вообще, мне не нравится, что бутстрап не использует префиксы. Я погуглил тут https://github.com/twbs/bootstrap/issues/1235 и как я понимаю, их мнение такое, что они не библиотека, а фреймворк и им незачем ставить префиксы.

https://github.com/TheSidSpears/FileHosting/blob/master/public/js/helper.js#L4

> создаем в форме переменную, содержащую id отвечаемого коммента


Проще было сразу создать это поле в шаблоне.

> Добавляем кнопку "Написать коммент без ответа"


Проще вставить ее в шаблон, но скрыть. Так при изменениях в верстке нам не придется лезть в JS. Вообще, старайся избегать вынесения верстки из HTML в JS.

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

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

И кстати, а ты автоматизированные тесты написать к файлообменнику не хочешь? У меня есть обзорный урок по тестированию, если что: https://gist.github.com/codedokode/a455bde7d0748c0a351a
#577 #892234
Есть файл-интерпретора php.exe, есть PHP-скрипт. Подскажите, пожалуйста, как сделать из всего этого дела один .exe-шник? Нет, я не какер, просто нужна "одна красная кнопка для запуска", вместо того, чтобы каждый раз открывать cmd и вбивать там php.exe path/to/script.php
>>892267
https://github.com/never3ver/studentslist #578 #892266
>>884415

>>873486


>>873545



Ну вот, а я надеялся закрыть уже эту задачу. Нет, рано.

Во-первых, отвалилась регистрация. То есть запись добавляется в БД, но с cookie IS NULL. И соответственно после регистрации я снова вижу предложение зарегистрироваться.

Во-вторых, кто-то подменяет емайлы вроде ?\2saaANUSпримеGn}рPUNCTUM9uYрф на punycode (*VNsaaANUSxn--e1afmkf9 UdPUNCTUMc>Lxn--p1ai). Оказалось, виноват Хром (и спецификации, которым он следует). Введенный в поле формы адрес на русском перекодируется и отправляется на сервер в punycode. Кошмар какой-то. Получается, инпуты с типом email не всегда желательно использовать. Век живи - век учись.

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

Не проверяется уникальность email. При попытке второй раз зарегистрироваться с тем же email вместо ошибки вылетает исключение. Поскажу: дело в том, что значение нельзя сравнивать с NULL через = или <>. NULL в базах данных значит "неизвестно", и сравнение с неизвестным дает такой же результат. Сделай запрос SELECT NULL = NULL, NULL != NULL, NULL = 1, NULL != 1 и посмотри сам (какой результат ты ожидаешь?).

Поскольку NULL значит "неизвестно", то результат сравнения NULL с NULL тоже неизвестен.

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

https://github.com/never3ver/students_list/blob/master/app/Pager.php#L54

Тут ссылка подставляется в HTML без htmspecialchars, нехорошо. Вообще, вынести HTML код сюда, как мне кажется, плохая идея. Код в public function getNumbersLinks() и похожих функциях вполне можно перенести в шаблон.

https://github.com/never3ver/students_list/blob/master/app/Helper.php#L37

> public static function getPlaceholder() {


> return htmlspecialchars(trim(strval($_GET['search'])));


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

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

https://github.com/never3ver/students_list/blob/master/templates/index.html#L10
То же самое. view не должен лезть в GET-переменные. Ты пытаешься к ним пробраться в обход контроллера.

Если открыть пустой сайт, без студентов, то надпись "Ничего не найдено" оказывается частично перекрыта шапкой.
https://github.com/never3ver/studentslist #578 #892266
>>884415

>>873486


>>873545



Ну вот, а я надеялся закрыть уже эту задачу. Нет, рано.

Во-первых, отвалилась регистрация. То есть запись добавляется в БД, но с cookie IS NULL. И соответственно после регистрации я снова вижу предложение зарегистрироваться.

Во-вторых, кто-то подменяет емайлы вроде ?\2saaANUSпримеGn}рPUNCTUM9uYрф на punycode (*VNsaaANUSxn--e1afmkf9 UdPUNCTUMc>Lxn--p1ai). Оказалось, виноват Хром (и спецификации, которым он следует). Введенный в поле формы адрес на русском перекодируется и отправляется на сервер в punycode. Кошмар какой-то. Получается, инпуты с типом email не всегда желательно использовать. Век живи - век учись.

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

Не проверяется уникальность email. При попытке второй раз зарегистрироваться с тем же email вместо ошибки вылетает исключение. Поскажу: дело в том, что значение нельзя сравнивать с NULL через = или <>. NULL в базах данных значит "неизвестно", и сравнение с неизвестным дает такой же результат. Сделай запрос SELECT NULL = NULL, NULL != NULL, NULL = 1, NULL != 1 и посмотри сам (какой результат ты ожидаешь?).

Поскольку NULL значит "неизвестно", то результат сравнения NULL с NULL тоже неизвестен.

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

https://github.com/never3ver/students_list/blob/master/app/Pager.php#L54

Тут ссылка подставляется в HTML без htmspecialchars, нехорошо. Вообще, вынести HTML код сюда, как мне кажется, плохая идея. Код в public function getNumbersLinks() и похожих функциях вполне можно перенести в шаблон.

https://github.com/never3ver/students_list/blob/master/app/Helper.php#L37

> public static function getPlaceholder() {


> return htmlspecialchars(trim(strval($_GET['search'])));


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

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

https://github.com/never3ver/students_list/blob/master/templates/index.html#L10
То же самое. view не должен лезть в GET-переменные. Ты пытаешься к ним пробраться в обход контроллера.

Если открыть пустой сайт, без студентов, то надпись "Ничего не найдено" оказывается частично перекрыта шапкой.
>>892439>>893571
#579 #892267
>>892234

Делать из этого екзешник не надо. Ты ведь не хочешь перекомпилировать все при каждой правке.

Команды командной строки можно записать в .bat-скрипт. При двойном клике (или при вызове из командной строки) этот скрипт выполнит все записанные в нем команды.

Погугли про bat-скрипты.

В линуксе есть bash-скрипты, то же самое, но во много раз мощнее. В новой винде есть Powershell.

Если окно консоли закрывается после выполнения скрипта, либо поставь галочку в его настройках, либо допиши команду pause в конец.
>>892271
#580 #892269
http://javarush.ru/ Посоветуйте подобные сайты по пхп.
#581 #892271
>>892267
Совсем забыл про них, спасибо!
#582 #892272
Учебник ОПа второй в гугле, после мануала, по запросу "php программирование".
>>893881
#583 #892325
Если я полный новичок, с изучения чего лучше начать, php или html?
>>892581>>893881
#584 #892423
>>892109
При чем тут обертку написать, видимо даун ты так изобретаешь велосипеды когда есть удобные AngryCurl/RollingCurl и тд.
Вопрос был именно по той библиотеке, и к тем кто пользовался ею. Не люблю таких джуниоров как ты, они нихуя не знаю но везде носятся со своим компетентным мнением.
>>892430>>893881
#585 #892430
>>892423
Guzzle почему не хочешь?
>>892667
#586 #892439
>>892266

>Вообще, вынести HTML код сюда, как мне кажется, плохая идея. Код в public function getNumbersLinks() и похожих функциях вполне можно перенести в шаблон.


Оно раньше и было в шаблоне, но ты (или не ты?) сказал что так нельзя. В остальном все понял, спасибо, переделаю.
#587 #892581
>>892325
Можно делать это и параллельно. Если ты хочешь программировать на php, то html знать обязательно. Выясни лучше сначала что тебе нужно просто html (статичная страница) или php (работа с формами\запросами\функциями короче полное погружение в программирование)
#588 #892667
>>892430
Не пользовался, только слышал, он поддерживает смену проксей и юзерагента на лету?
#589 #892902
Сегодня исполняется ровно год с того момента, как я впервые открыл учебник ОПа и начал изучать PHP.
>>893092>>893363
#590 #892952
ОП. Пожалуйста поделись решением задачки про айфон! Я 4 часа сижу, не могу решить.
>>892962
#591 #892962
>>892952
UPDATE.

Все таки решил!

http://codepad.org/vGMSTcpQ
>>893881
#592 #892996
аноны, никак не могу решить задачку на регулярные выражения. как заставить программу искать номера телефонов типа +7 (432) 5233 432 (чтобы между ними могли быть минусы и пробелы, а могли и не быть) и как поставить альтернативу между +7 и 8 ([+]7 | 8 не работает)
#593 #893092
>>892902
с др
>>893141
#594 #893141
>>893092
Спасибо!
За это время учебник пройден (кроме маршрутизатора - той задачи на поиск кратчайших путей), к Студентам и Файлообменнику не приступал.
Работаю над своим проектом на Yii2 с хорошим знакомым программистом.
#595 #893257
Написал урок про строки и кодировки. И почему некоторые функции не поддерживают utf-8: https://github.com/codedokode/pasta/blob/master/cs/strings.md

Получилось конечно как-то сложнее и больше текста, чем я задумывал. Аноны, почитайте, напишите, что непонятно.
>>894535
#596 #893363
>>892902
И каких результатов достиг?
>>893659
#597 #893375
Тест
#598 #893423
Вопрос по реализации MVC в javascript (сапер). Нужно ли разделять код на файлы, как это делали в задаче про студентов? Как подключить все файлы, не в head же прописывать link для десятка файлов? Разделяются ли классы на различные файлы? Как обернуть весь код в модуль, если файлов несколько?
>>893879
#599 #893571
#600 #893659
>>893363
Работаю над контентной частью проекта, расписал ТЗ по максимуму - всё описано, что нужно.
Просто перестал бояться программирования, многие процессы стал осознавать.
Надеюсь, в будущем году проект будет запущен для целевой аудитории.
#601 #893879
>>893423

> Нужно ли разделять код на файлы, как это делали в задаче про студентов?


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

> Как подключить все файлы, не в head же прописывать link для десятка файлов?


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

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

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

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

Есть несколько систем модулей:

- common.js, основанная на модулях Node.JS, в браузере она работать сама по себе не будет (так как там используется синхронная функция require), надо либо подгружать файлы аяксом, либо обрабатывать, то есть работать с ними будет неудобно
- AMD, где модули определяются внутри функции и их можно подгружать асинхронно. Но минус в том, что синтаксис довольно грромоздкий
- стандартные модули из ES6: http://frontender.info/es6-modules/ - будущий стандарт, который имеет удобный синтаксис и не требует предварительной обработки, но поддерживается только в новых браузерах. Эту проблему можно решить использованием сборщика, который понимает этот формат, но генерирует на выходе совместимый со старыми браузерами код.

Из популярных сборщиков я слышал про RequireJS (ориентирован по моему на AMD) и более новый WebPack.

В общем, изучи все эти системы.

> Разделяются ли классы на различные файлы?


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

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


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

Вообще, ты можешь еще посмотреть, как устроена Google Closure Library. Это не очень новый проект (потому они изобрели свою систему модулей), и не модный (как какой-нибудь React) и его структура во многом скопирована с Явы, но его полезно посмотреть в плане того, как там все организовано. В том числе, как код разбит на файлы.

Вот пример класса: https://github.com/google/closure-library/blob/master/closure/goog/events/eventhandler.js (они используют свой формат модулей)
Вот пример модной библиотеки React, опять же посмотри, как у них сделано разделение на модули: https://github.com/facebook/react (они используют CommonJS)
Ну и пример Angular 2, который использует модули ES6 и TypeScript: https://github.com/angular/angular/
#601 #893879
>>893423

> Нужно ли разделять код на файлы, как это делали в задаче про студентов?


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

> Как подключить все файлы, не в head же прописывать link для десятка файлов?


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

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

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

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

Есть несколько систем модулей:

- common.js, основанная на модулях Node.JS, в браузере она работать сама по себе не будет (так как там используется синхронная функция require), надо либо подгружать файлы аяксом, либо обрабатывать, то есть работать с ними будет неудобно
- AMD, где модули определяются внутри функции и их можно подгружать асинхронно. Но минус в том, что синтаксис довольно грромоздкий
- стандартные модули из ES6: http://frontender.info/es6-modules/ - будущий стандарт, который имеет удобный синтаксис и не требует предварительной обработки, но поддерживается только в новых браузерах. Эту проблему можно решить использованием сборщика, который понимает этот формат, но генерирует на выходе совместимый со старыми браузерами код.

Из популярных сборщиков я слышал про RequireJS (ориентирован по моему на AMD) и более новый WebPack.

В общем, изучи все эти системы.

> Разделяются ли классы на различные файлы?


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

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


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

Вообще, ты можешь еще посмотреть, как устроена Google Closure Library. Это не очень новый проект (потому они изобрели свою систему модулей), и не модный (как какой-нибудь React) и его структура во многом скопирована с Явы, но его полезно посмотреть в плане того, как там все организовано. В том числе, как код разбит на файлы.

Вот пример класса: https://github.com/google/closure-library/blob/master/closure/goog/events/eventhandler.js (они используют свой формат модулей)
Вот пример модной библиотеки React, опять же посмотри, как у них сделано разделение на модули: https://github.com/facebook/react (они используют CommonJS)
Ну и пример Angular 2, который использует модули ES6 и TypeScript: https://github.com/angular/angular/
>>894160
#602 #893881
>>892962

> if ($creditBalance < 0 && $creditBalance < $monthlyPayment) {


Тут одно из условий лишнее, если первое выполняется, то второе можно уже не проверять.

Считает верно.

>>892325

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

>>892423

С "даунами" иди в какой-нибудь другой тред.

>>892272

Это хорошо. А то много всяких сомнительных учебников с устаревшим или небезопасным кодом или без ООП.

>>892109

С "даунами" в другой тред.

>>891622

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

>>891707

Изучи исходный код.

>>891621

Какое это отношение имеет к изучению PHP? Создай сам свой форум и пости туда что хочешь.
#602 #893881
>>892962

> if ($creditBalance < 0 && $creditBalance < $monthlyPayment) {


Тут одно из условий лишнее, если первое выполняется, то второе можно уже не проверять.

Считает верно.

>>892325

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

>>892423

С "даунами" иди в какой-нибудь другой тред.

>>892272

Это хорошо. А то много всяких сомнительных учебников с устаревшим или небезопасным кодом или без ООП.

>>892109

С "даунами" в другой тред.

>>891622

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

>>891707

Изучи исходный код.

>>891621

Какое это отношение имеет к изучению PHP? Создай сам свой форум и пости туда что хочешь.
#603 #893882
>>891514

Для начала надо определить, что такое "последняя" строка. В базе строки не хранятся в каком-то определенном порядке. Порядок определяется при выборке с помощью ORDER.

>>891502

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

>>891497

Попробуй написать такие регулярки:

- один из символов "минус", "скобка", "пробел"
- любое число таких символов
- цифра, за ней любое число таких символов
- (цифра, за ней любое число таких символов) повторяется 10 раз

Для повторения N раз есть квантификатор {N}, он есть у меня в учебнике и в мануале: http://php.net/manual/ru/regexp.reference.repetition.php
#604 #894160
>>893879
Большое спасибо за очень подробный ответ!
#605 #894374
Можете объяснить смысл датамаппера? Я понял так, но не уверен что правильно

Первый класс в первом файле :

class User {
public $name;
public $lastname;
//и остальные свойства которые есть у юзера
}

Второй класс во втором файле:

class User_mapper {

public $db;

function __construct(PDO $db) {
$this->db = $db;
}

public function add_user($user) {
//Описание метода
}

public function out_user() {
//Описание метода
}

}

Теперь чтобы использовать в главном файле прописываем:
$db = new PDO("Здесь разные настройки и т.д.");

$user_mapper = User_maper($db);
$user = new User();
$user->name = "Админ";
$user->lastname = "Тожеадмин";

//Если нужно передать в метод маппера какие-то свойства метода Юзер, тогда делаем так

$user_mapper->add_user($user);

Я правильно понял смысл дата маппера или нет?
#605 #894374
Можете объяснить смысл датамаппера? Я понял так, но не уверен что правильно

Первый класс в первом файле :

class User {
public $name;
public $lastname;
//и остальные свойства которые есть у юзера
}

Второй класс во втором файле:

class User_mapper {

public $db;

function __construct(PDO $db) {
$this->db = $db;
}

public function add_user($user) {
//Описание метода
}

public function out_user() {
//Описание метода
}

}

Теперь чтобы использовать в главном файле прописываем:
$db = new PDO("Здесь разные настройки и т.д.");

$user_mapper = User_maper($db);
$user = new User();
$user->name = "Админ";
$user->lastname = "Тожеадмин";

//Если нужно передать в метод маппера какие-то свойства метода Юзер, тогда делаем так

$user_mapper->add_user($user);

Я правильно понял смысл дата маппера или нет?
>>894385
#606 #894385
>>894374

Класс User представляет информацию о пользователе (надо же как-то ее хранить в программе?).

Класс UserMapper позволяет загружать и сохранять объекты User в базу данных.

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

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

> //Если нужно передать в метод маппера какие-то свойства метода Юзер, тогда делаем так


Мы передаем не какие-то свойства, а все. Объект User должен быть заполнен полностью, иначе как с ним работать, если непонятно, заполнено поле или нет?
#607 #894441
>>880700 (OP)
Анон, вопрос по урокам, которые были в шапке. Задача на регулярные выражения.

Задачка на проверку телефонов

Дан текст, который по идее должен быть номером телефона в виде 8-(911)-506 56 56 (т.е. человек может ввести не только цифры, но и скобки, минусы, может что-то еще). Но в реальности, пользователь может вместо номера написать что угодно. Напиши скрипт для проверки правильности введенного номера («8(911)-506 56 56» — правильный номер, «8-911-50-656-56» — правильный, «89115065656» — правильный, «02» — неправильный, «89115065656 позвать Люду» — неправильный).

Вот список номеров:

// Правильные:
$correctNumbers = [
'84951234567', '+74951234567', '8-495-1-234-567',
' 8 (8122) 56-56-56', '8-911-1234567', '8 (911) 12 345 67',
'8-911 12 345 67', '8 (911) - 123 - 45 - 67', '+ 7 999 123 4567',
'8 ( 999 ) 1234567', '8 999 123 4567'
];

// Неправильные:
$incorrectNumbers = [
'02', '84951234567 позвать люсю', '849512345', '849512345678',
'8 (409) 123-123-123', '7900123467', '5005005001', '8888-8888-88',
'84951a234567', '8495123456a',
'+1 234 5678901', / неверный код страны /
'+8 234 5678901', / либо 8 либо +7 /
'7 234 5678901' / нет + /
];
#607 #894441
>>880700 (OP)
Анон, вопрос по урокам, которые были в шапке. Задача на регулярные выражения.

Задачка на проверку телефонов

Дан текст, который по идее должен быть номером телефона в виде 8-(911)-506 56 56 (т.е. человек может ввести не только цифры, но и скобки, минусы, может что-то еще). Но в реальности, пользователь может вместо номера написать что угодно. Напиши скрипт для проверки правильности введенного номера («8(911)-506 56 56» — правильный номер, «8-911-50-656-56» — правильный, «89115065656» — правильный, «02» — неправильный, «89115065656 позвать Люду» — неправильный).

Вот список номеров:

// Правильные:
$correctNumbers = [
'84951234567', '+74951234567', '8-495-1-234-567',
' 8 (8122) 56-56-56', '8-911-1234567', '8 (911) 12 345 67',
'8-911 12 345 67', '8 (911) - 123 - 45 - 67', '+ 7 999 123 4567',
'8 ( 999 ) 1234567', '8 999 123 4567'
];

// Неправильные:
$incorrectNumbers = [
'02', '84951234567 позвать люсю', '849512345', '849512345678',
'8 (409) 123-123-123', '7900123467', '5005005001', '8888-8888-88',
'84951a234567', '8495123456a',
'+1 234 5678901', / неверный код страны /
'+8 234 5678901', / либо 8 либо +7 /
'7 234 5678901' / нет + /
];
>>894443
#608 #894443
>>894441
Помоги регулярное выражение составить. Как я понимаю, должно получится нечто подобное: $regexp = '/^([+7]|[+ 7]|[8])(???)$/m';
>>894465
https://github.com/InitF/StudentList #609 #894463
>>884454

>>874960


>>876772



Ты зря взял структуру файлов с Юи, так как она довольно неудачная. Чем например, components отличается от models? Также, имена неймспейсов с маленькой буквы не соответствуют рекомендациям PSR-4.

https://github.com/InitF/StudentList/blob/master/components/DbConnector.php
Этот класс довольно бесполезен. Зачем он нужен, если можно и без него создать объект PDO?

> } catch (\PDOException $e){


> echo $e->getMessage();


Это неправильно, читай урок по исключениям и в следующий раз не копируй бездумно код: https://github.com/codedokode/pasta/blob/master/php/exceptions.md

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

https://github.com/InitF/StudentList/blob/master/components/Route.php
Неудачное название. Route значит "маршрут", а "маршрутизатор" будет Router. Более того, твой роутер вызывает контроллеры и правильнее его называть FrontController.

> if (($pos = strpos($path, '?')) !== false) {


> $path = substr($path, 0, $pos);


Лучше использовать parse_url.

> }elseif ($path == '/reg' || $path == '/reg/'){


Желательно, чтобы у страницы был один URL, а не два.

> IndexController::action();


Статические методы это не ООП. В уроке про DI кратко описано, чем они плохи: https://github.com/codedokode/pasta/blob/master/arch/di.md

https://github.com/InitF/StudentList/blob/master/components/StudentValidation.php#L11

> private $_student;


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

> 'Максимальная длина имени 50 символов, а вы ввели' . mb_strlen($this->_student->name);


Нету пробела между сообщением и числом.

> [a-яёА-ЯЁ]{1,}


{1,} это тоже самое, что знак плюс.

> if (mb_strlen($this->_student->last_name) > 50){


> $this->errors['last_name'][] = 'Максимальная длина фамилии 70 символов


Числа не совпадают.

https://github.com/InitF/StudentList/blob/master/components/StudentValidation.php#L120
Лучше передавать StudentTableGateway через DI как описано в уроке про DI по ссылке выше.

> public function runValidate()


Функция не очищает массив ошибок и при повторном вызове там будут старые ошибки перемешаны с новыми.

Вместо public $errors стоило сделать методы для получения ошибок, например, проверить, есть ли ошибки, получить список ошибок для поля и тд.

https://github.com/InitF/StudentList/blob/master/composer.json
тут поля вроде name, descrption, authors можно было не указывать. Они нужны для оформления библиотек, а если тебе нужна только автозагрузка, то достаточно ключа autoload.

https://github.com/InitF/StudentList/blob/master/controllers/ErrorController.php
При ошибке 404 надо выдавать соответствующий HTTP код. Ты же выдаешь страницу с кодом 200, как будто бы все в порядке. Прочитай про коды состояния в HTTP: https://ru.wikipedia.org/wiki/Список_кодов_состояния_HTTP (если не знаешь HTTP, то почитай сначала про сам HTTP, например в моем уроке https://github.com/codedokode/pasta/blob/master/network/http.md)

https://github.com/InitF/StudentList/blob/master/view/main.html#L27
View не должен обращаться к кукам, это задача контроллера.

> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>


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

Не вижу пагинации. Надо бы ее сделать.

При поиске стоит показывать введенное слово в поле поиска.

> https://github.com/InitF/StudentList/blob/master/view/index.html#L12


<?php foreach ($students as $student) {
В шаблонах используют версии с двоеточием: http://www.phpinfo.su/articles/practice/shablony_v_php.html

При выводе надо экранировать данные, чтобы не получить XSS: https://github.com/codedokode/pasta/blob/master/security/xss.md

Вообще, я советую перечитать замечания к задаче, там вроде это упоминается.

> if (isset($_POST)


Это бессмысленная проверка, так как POST существует всегда.

> $student->nonresident = $post['nonresident'] == 1 ? 'Да' : 'Нет';


Тут стоит использовать латинские идентификаторы и в коде указывать их как константы в классе Student: https://github.com/codedokode/pasta/blob/master/good-code.md#Используй-константы-когда-есть-выбор-из-нескольких-вариантов

> $student->reg_date = date("Y-m-d H:i:s");


При редактировании дату обновлять не надо.

> echo json_encode($response);


Надо выдавать правильный Content-Type, указывающий, что ответ в формате JSON.

>$response['state'] = 'not_done';


Что обозначает это состояние? По моему, результат валидации - либо да, либо нет. Я бы использовал true/false вместо строковых констант, в которых легко опечататься.

https://github.com/InitF/StudentList/blob/master/controllers/RegController.php#L67

> public static function generateString($length = 40){


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

Способ использования класса валидации нелогичный:

> $validation = new StudentValidation($student);


> $validation->runValidate();


> if (empty($validation->errors)) {


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

> $studentTable = new StudentTableGateway();


Это разбросано много раз по коду. По моему, сервис удобнее создать 1 раз в 1 месте и использовать далее один и тот же экземпляр.

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

Нет защиты от CSRF.

https://github.com/InitF/StudentList/blob/master/model/StudentTableGateway.php#L21

> $result = $stmt->execute((array)$student);


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

Создание нового StudentTableGateway у тебя создает новое соединение с базой. Надо тут использовать принцип DI.

> public function checkEmail($email)


Неудачное название, из названия не понятно, как интерпретировать результат. Если вернется true, то что это значит? Надо называть вроде isEmailUsed/isEmailAvailable/isEmailUnique

При редактировании не будет ошибки об использованном email?

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

> $(document).ready(function () {


> $(document).on('click', '.js-submit-student', Form.submit)


зачем дожидаться document.ready? А если в конце страницы какой-нибудь рекламный баннер долго инициализируется, и в это время отправить форму? Не лучше ли вписать вызов в onsubmit на теге form?

> Form.response = JSON.parse(data);


Не лучше ли использовать $.ajax с dataType = 'json', он будет работать во всех браузерах, а не только в новых, где есть объект JSON? Вот ты исплоьзуешь объект JSON, а ты проверил, какие браузеры его поддерживают?

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

Код работы с формой написан так, что он не поддерживает более 1 формы на странице. Ну например, эта строка $('.form-group').removeClass('has-error'); очищает ошибки на всех формах на странице. Лучше делать все в передлах одной формы. Также лучше на мой взгляд, было бы использовать тут нормальный ООП, а не класс на статических методах.

> if (Form.errors[key][+i+1] !== undefined){


> message += '<br>'


Использование <br> для верстки говорит о том, что ты плоховато знаешь HTML. У нас в ОП посте есть задачи, если что.
https://github.com/InitF/StudentList #609 #894463
>>884454

>>874960


>>876772



Ты зря взял структуру файлов с Юи, так как она довольно неудачная. Чем например, components отличается от models? Также, имена неймспейсов с маленькой буквы не соответствуют рекомендациям PSR-4.

https://github.com/InitF/StudentList/blob/master/components/DbConnector.php
Этот класс довольно бесполезен. Зачем он нужен, если можно и без него создать объект PDO?

> } catch (\PDOException $e){


> echo $e->getMessage();


Это неправильно, читай урок по исключениям и в следующий раз не копируй бездумно код: https://github.com/codedokode/pasta/blob/master/php/exceptions.md

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

https://github.com/InitF/StudentList/blob/master/components/Route.php
Неудачное название. Route значит "маршрут", а "маршрутизатор" будет Router. Более того, твой роутер вызывает контроллеры и правильнее его называть FrontController.

> if (($pos = strpos($path, '?')) !== false) {


> $path = substr($path, 0, $pos);


Лучше использовать parse_url.

> }elseif ($path == '/reg' || $path == '/reg/'){


Желательно, чтобы у страницы был один URL, а не два.

> IndexController::action();


Статические методы это не ООП. В уроке про DI кратко описано, чем они плохи: https://github.com/codedokode/pasta/blob/master/arch/di.md

https://github.com/InitF/StudentList/blob/master/components/StudentValidation.php#L11

> private $_student;


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

> 'Максимальная длина имени 50 символов, а вы ввели' . mb_strlen($this->_student->name);


Нету пробела между сообщением и числом.

> [a-яёА-ЯЁ]{1,}


{1,} это тоже самое, что знак плюс.

> if (mb_strlen($this->_student->last_name) > 50){


> $this->errors['last_name'][] = 'Максимальная длина фамилии 70 символов


Числа не совпадают.

https://github.com/InitF/StudentList/blob/master/components/StudentValidation.php#L120
Лучше передавать StudentTableGateway через DI как описано в уроке про DI по ссылке выше.

> public function runValidate()


Функция не очищает массив ошибок и при повторном вызове там будут старые ошибки перемешаны с новыми.

Вместо public $errors стоило сделать методы для получения ошибок, например, проверить, есть ли ошибки, получить список ошибок для поля и тд.

https://github.com/InitF/StudentList/blob/master/composer.json
тут поля вроде name, descrption, authors можно было не указывать. Они нужны для оформления библиотек, а если тебе нужна только автозагрузка, то достаточно ключа autoload.

https://github.com/InitF/StudentList/blob/master/controllers/ErrorController.php
При ошибке 404 надо выдавать соответствующий HTTP код. Ты же выдаешь страницу с кодом 200, как будто бы все в порядке. Прочитай про коды состояния в HTTP: https://ru.wikipedia.org/wiki/Список_кодов_состояния_HTTP (если не знаешь HTTP, то почитай сначала про сам HTTP, например в моем уроке https://github.com/codedokode/pasta/blob/master/network/http.md)

https://github.com/InitF/StudentList/blob/master/view/main.html#L27
View не должен обращаться к кукам, это задача контроллера.

> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>


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

Не вижу пагинации. Надо бы ее сделать.

При поиске стоит показывать введенное слово в поле поиска.

> https://github.com/InitF/StudentList/blob/master/view/index.html#L12


<?php foreach ($students as $student) {
В шаблонах используют версии с двоеточием: http://www.phpinfo.su/articles/practice/shablony_v_php.html

При выводе надо экранировать данные, чтобы не получить XSS: https://github.com/codedokode/pasta/blob/master/security/xss.md

Вообще, я советую перечитать замечания к задаче, там вроде это упоминается.

> if (isset($_POST)


Это бессмысленная проверка, так как POST существует всегда.

> $student->nonresident = $post['nonresident'] == 1 ? 'Да' : 'Нет';


Тут стоит использовать латинские идентификаторы и в коде указывать их как константы в классе Student: https://github.com/codedokode/pasta/blob/master/good-code.md#Используй-константы-когда-есть-выбор-из-нескольких-вариантов

> $student->reg_date = date("Y-m-d H:i:s");


При редактировании дату обновлять не надо.

> echo json_encode($response);


Надо выдавать правильный Content-Type, указывающий, что ответ в формате JSON.

>$response['state'] = 'not_done';


Что обозначает это состояние? По моему, результат валидации - либо да, либо нет. Я бы использовал true/false вместо строковых констант, в которых легко опечататься.

https://github.com/InitF/StudentList/blob/master/controllers/RegController.php#L67

> public static function generateString($length = 40){


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

Способ использования класса валидации нелогичный:

> $validation = new StudentValidation($student);


> $validation->runValidate();


> if (empty($validation->errors)) {


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

> $studentTable = new StudentTableGateway();


Это разбросано много раз по коду. По моему, сервис удобнее создать 1 раз в 1 месте и использовать далее один и тот же экземпляр.

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

Нет защиты от CSRF.

https://github.com/InitF/StudentList/blob/master/model/StudentTableGateway.php#L21

> $result = $stmt->execute((array)$student);


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

Создание нового StudentTableGateway у тебя создает новое соединение с базой. Надо тут использовать принцип DI.

> public function checkEmail($email)


Неудачное название, из названия не понятно, как интерпретировать результат. Если вернется true, то что это значит? Надо называть вроде isEmailUsed/isEmailAvailable/isEmailUnique

При редактировании не будет ошибки об использованном email?

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

> $(document).ready(function () {


> $(document).on('click', '.js-submit-student', Form.submit)


зачем дожидаться document.ready? А если в конце страницы какой-нибудь рекламный баннер долго инициализируется, и в это время отправить форму? Не лучше ли вписать вызов в onsubmit на теге form?

> Form.response = JSON.parse(data);


Не лучше ли использовать $.ajax с dataType = 'json', он будет работать во всех браузерах, а не только в новых, где есть объект JSON? Вот ты исплоьзуешь объект JSON, а ты проверил, какие браузеры его поддерживают?

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

Код работы с формой написан так, что он не поддерживает более 1 формы на странице. Ну например, эта строка $('.form-group').removeClass('has-error'); очищает ошибки на всех формах на странице. Лучше делать все в передлах одной формы. Также лучше на мой взгляд, было бы использовать тут нормальный ООП, а не класс на статических методах.

> if (Form.errors[key][+i+1] !== undefined){


> message += '<br>'


Использование <br> для верстки говорит о том, что ты плоховато знаешь HTML. У нас в ОП посте есть задачи, если что.
>>897195
#610 #894465
>>894443

Составляй по шагам:

- напиши выражение для "ровно одна скобка, минус или пробел"
- любое число минусов, скобок, пробелов
- ровно 1 цифра, за ней любое число минусов, скобок, пробелов
- то же самое, повторяется 10 раз
335 Кб, 1600x900
#611 #894477
Можно спросить по JavaScript?
Укажите на проблемы, если они есть (конечно есть):
https://jsfiddle.net/9ypeL84s/
а) общая концепция (сам думаю, что говнокод)
, если не пиздец, то
б) неучтенные ошибки
в) краткость
г) понятность приведенного кода с точки зрения стилистики
д) отвечает ли требованиям ООП?

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

P.S.: как и любой говнокод, работает как задумано, как аллах.
>>894884>>894888
#612 #894535
>>893257
Спасибо. Попробовал решить первую задачу http://ideone.com/5l3ws7
В процессе возникло пару вопросов:
$str = iconv("utf-8","utf-16", $str);
Кодирует в utf-16le и ставит впереди BOM FFFE. Если указать utf-16be (или le), то BOM не ставится (потому что считается мы ты точно знаем кодировку и BOM не понадобится?). Бывают ли ситуации когда BOM придется добавлять в ручную, если например, мы отдаем данные куда-нибудь?
>>894882
Задачки #613 #894815
Два наибольших числа: https://github.com/codedokode/pasta/blob/master/interview-tasks.md#Два-наибольших-числа
Я не уверен, что хорошо понимаю, как анализировать эффективность алгоритма. Возьму эту задачку, мыслю так: раз элементы в массиве в произвольном порядке, то алгоритм будет линейным и невозможно написать ничего эффективней O(n). Дальше подразумеваю, что n - количество элементов в массиве и n > 2
Первое решение: http://ideone.com/LSTgO2
Лучшее время будет у массива одинаковых элементов, в алгоритме произойдёт n-1 итераций цикла, n-1 сравнений, 0 присвоений
У массива, отсортированного по убыванию: n-1 итераций цикла, (n-1)5 сравнений, n-1 присвоений.
У массива, отсортированного по возрастанию: n-1 итераций цикла, (n-1)
3 сравнений, (n-1)2 присвоений.
Я так понимаю, что сложность алгоритма O(n)? Константы, то есть значения, которые не зависят от количества элементов в массиве, можно опустить.
Второе решение: http://ideone.com/8ascih
Решение использует array_unique, rsort и array_slice. Я нагуглил, что array_unique использует сортировку (уже n
logn), у быстрой сортировки сложность nlogn, array_slice не учитываем, так как в моём случае эта функция для всех входных данных вырезает первые 2 элемента. Итого выходит nlogn+n*logn?

Угол между стрелками: https://github.com/codedokode/pasta/blob/master/interview-tasks.md#Угол-между-стрелками
http://ideone.com/kbwyYu

Дерево: https://github.com/codedokode/pasta/blob/master/interview-tasks.md#Дерево
https://jsfiddle.net/5L14too1/3/
Сделал на JS, так как в браузере легко отладить программу, а за отладчик PHP я пока не садился. Это, видимо, сигнал к тому, что мой подход к решению задачи слишком запутанный, раз без отладчика я не могу его реализовать.

Задачи по датам: https://gist.github.com/codedokode/10539805#Задачи
Чувствую, что очень переусложнил обе.
1. http://ideone.com/Kqcxgc
2. http://ideone.com/E1Ig43
Здесь не понимаю, как лучше указывать формат праздника. Например, здесь http://php.net/manual/en/function.date.php пишут, что можно использовать d и j для дней 1-30 и 01-30 соответственно.

Качалка файлов: https://arhivach.org/thread/213097/#884783

> Небольшая мелочь. Функция curl_init может вернуть false, у тебя это не проверяется.


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

> Для курла нет ограничения на скорость скачивания.


Я нашёл такой пакет: https://github.com/bandwidth-throttle/bandwidth-throttle
Но я не осилил исходник, там используются stream/resource с которыми я не знаком. Исходный код Guzzle так же не могу осилить по той же причине. В общем, пока забил на загрузчик.
Задачки #613 #894815
Два наибольших числа: https://github.com/codedokode/pasta/blob/master/interview-tasks.md#Два-наибольших-числа
Я не уверен, что хорошо понимаю, как анализировать эффективность алгоритма. Возьму эту задачку, мыслю так: раз элементы в массиве в произвольном порядке, то алгоритм будет линейным и невозможно написать ничего эффективней O(n). Дальше подразумеваю, что n - количество элементов в массиве и n > 2
Первое решение: http://ideone.com/LSTgO2
Лучшее время будет у массива одинаковых элементов, в алгоритме произойдёт n-1 итераций цикла, n-1 сравнений, 0 присвоений
У массива, отсортированного по убыванию: n-1 итераций цикла, (n-1)5 сравнений, n-1 присвоений.
У массива, отсортированного по возрастанию: n-1 итераций цикла, (n-1)
3 сравнений, (n-1)2 присвоений.
Я так понимаю, что сложность алгоритма O(n)? Константы, то есть значения, которые не зависят от количества элементов в массиве, можно опустить.
Второе решение: http://ideone.com/8ascih
Решение использует array_unique, rsort и array_slice. Я нагуглил, что array_unique использует сортировку (уже n
logn), у быстрой сортировки сложность nlogn, array_slice не учитываем, так как в моём случае эта функция для всех входных данных вырезает первые 2 элемента. Итого выходит nlogn+n*logn?

Угол между стрелками: https://github.com/codedokode/pasta/blob/master/interview-tasks.md#Угол-между-стрелками
http://ideone.com/kbwyYu

Дерево: https://github.com/codedokode/pasta/blob/master/interview-tasks.md#Дерево
https://jsfiddle.net/5L14too1/3/
Сделал на JS, так как в браузере легко отладить программу, а за отладчик PHP я пока не садился. Это, видимо, сигнал к тому, что мой подход к решению задачи слишком запутанный, раз без отладчика я не могу его реализовать.

Задачи по датам: https://gist.github.com/codedokode/10539805#Задачи
Чувствую, что очень переусложнил обе.
1. http://ideone.com/Kqcxgc
2. http://ideone.com/E1Ig43
Здесь не понимаю, как лучше указывать формат праздника. Например, здесь http://php.net/manual/en/function.date.php пишут, что можно использовать d и j для дней 1-30 и 01-30 соответственно.

Качалка файлов: https://arhivach.org/thread/213097/#884783

> Небольшая мелочь. Функция curl_init может вернуть false, у тебя это не проверяется.


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

> Для курла нет ограничения на скорость скачивания.


Я нашёл такой пакет: https://github.com/bandwidth-throttle/bandwidth-throttle
Но я не осилил исходник, там используются stream/resource с которыми я не знаком. Исходный код Guzzle так же не могу осилить по той же причине. В общем, пока забил на загрузчик.
>>897666
#614 #894882
>>894535

Интересно, я про такое не знал. Давай я тогда тогда научу тебя, как определить, кто отвечает за работу этой функции.

iconv - это не функция самого PHP. PHP лишь предоставляет доступ к сишной функции (это понятно отсюда: http://php.net/manual/ru/iconv.requirements.php ), которая в linux системе может либо входить в состав стандартной библиотеки (glibc), либо поставляться отдельно в библиотеке libiconv. Я думаю, отдельная версия используется на Windows, где нет glibc.

Если функция берется из библиотеки glibc (GNU libc), которая поставляется отдельно от PHP (от нее зависят почти все программы, так что я думаю она идет как часть базовой системы), можно посмотреть ее официальный сайт: https://www.gnu.org/software/libc/ . На нем есть документация, и описание сишной функции iconv: https://www.gnu.org/software/libc/manual/html_mono/libc.html#Generic-Charset-Conversion которое довольно длинное, запутанное и не дает нам ответа.

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

echo Hello | iconv -f utf-8 -t utf-16 | od -t x1

Результат: 0000000 ff fe 48 00 65 00 6c 00 6c 00 6f 00 0a 00

То есть BOM вставляет не PHP, а сишная функция iconv.

На всякий случай заглянем еще в исходники PHP. Зайдем сюда: https://github.com/php/php-src/blob/master/ext/iconv/iconv.c , заметим что PHP-функции iconv соответствует функция с немного другим именем php_if_iconv, и найдем ее код: https://github.com/php/php-src/blob/master/ext/iconv/iconv.c#L2442

Видно, что она почти ничего не делает, кроме вызова другой функции php_iconv_string: https://github.com/php/php-src/blob/master/ext/iconv/iconv.c#L553 Почитаем код, и видим что в общем-то тут тоже специально BOM не добавляется.

Дальше можно поковырять исходники glibc, тут https://sourceware.org/git/?p=glibc.git;a=tree;f=iconv;hb=refs/heads/master , но что-то там все запутанно.

По коду:

Я думаю, что незачем создавать промежуточный массив 2-байтных строк. Выгоднее создавать сразу массив кодов. Или выводить их. У тебя есть массив отдельных символов - можно сделать функцию, которая получает 1 utf-8 символ на вход и выдает его codepoint.

Также, предлагаю доработать код для поддержки utf-32, чтобы для символов, не входящих в UCS-2, код отображался бы тоже правильно, а не как 2 суррогатных символа.
#614 #894882
>>894535

Интересно, я про такое не знал. Давай я тогда тогда научу тебя, как определить, кто отвечает за работу этой функции.

iconv - это не функция самого PHP. PHP лишь предоставляет доступ к сишной функции (это понятно отсюда: http://php.net/manual/ru/iconv.requirements.php ), которая в linux системе может либо входить в состав стандартной библиотеки (glibc), либо поставляться отдельно в библиотеке libiconv. Я думаю, отдельная версия используется на Windows, где нет glibc.

Если функция берется из библиотеки glibc (GNU libc), которая поставляется отдельно от PHP (от нее зависят почти все программы, так что я думаю она идет как часть базовой системы), можно посмотреть ее официальный сайт: https://www.gnu.org/software/libc/ . На нем есть документация, и описание сишной функции iconv: https://www.gnu.org/software/libc/manual/html_mono/libc.html#Generic-Charset-Conversion которое довольно длинное, запутанное и не дает нам ответа.

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

echo Hello | iconv -f utf-8 -t utf-16 | od -t x1

Результат: 0000000 ff fe 48 00 65 00 6c 00 6c 00 6f 00 0a 00

То есть BOM вставляет не PHP, а сишная функция iconv.

На всякий случай заглянем еще в исходники PHP. Зайдем сюда: https://github.com/php/php-src/blob/master/ext/iconv/iconv.c , заметим что PHP-функции iconv соответствует функция с немного другим именем php_if_iconv, и найдем ее код: https://github.com/php/php-src/blob/master/ext/iconv/iconv.c#L2442

Видно, что она почти ничего не делает, кроме вызова другой функции php_iconv_string: https://github.com/php/php-src/blob/master/ext/iconv/iconv.c#L553 Почитаем код, и видим что в общем-то тут тоже специально BOM не добавляется.

Дальше можно поковырять исходники glibc, тут https://sourceware.org/git/?p=glibc.git;a=tree;f=iconv;hb=refs/heads/master , но что-то там все запутанно.

По коду:

Я думаю, что незачем создавать промежуточный массив 2-байтных строк. Выгоднее создавать сразу массив кодов. Или выводить их. У тебя есть массив отдельных символов - можно сделать функцию, которая получает 1 utf-8 символ на вход и выдает его codepoint.

Также, предлагаю доработать код для поддержки utf-32, чтобы для символов, не входящих в UCS-2, код отображался бы тоже правильно, а не как 2 суррогатных символа.
>>895746
#615 #894884
>>894477

Насчет ООП: прототипы используются неправильно. Рекомендую почитать например тут https://learn.javascript.ru/prototypes (вообще, learn.javascript.ru стоит прочесть целиком, много полезного).

Замечания по коду:

Переменные надо называть нормально. Непонятно, что такое o или t, и это замедляет чтение кода. Надо дать им нормальные имена.

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

Ну например, что касается функции повтора запросов. Это можно сделать отдельной функцией вида:

sendRequestWithRetry(options, maxRetries)

где options - опции для $.ajax.

> if (t-- > 0


тут совмещено 2 действия (уменьшение переменной и проверка), и такой код тяжело читать. И вообще, не очень нормально, что if что-то модифицирует. Не надо стремиться записать код в одну длинную строку.

> && XMLHttpRequest.status != 404


Это явно неправильное условие. Ну например, сервер может вернуть 400 или 403, которые явно не требуют повтора. Логично делать повтор при TCp ошибках (обычно это код 0), или ошибках 5xx. Советую почитать про коды состояния HTTP.

> MyClass.prototype.myErrorHandler(


Это неправильно. При прототипном ООП мы вызываем метод как obj.method(), а prototype используем только при описании метода. Советую решить задачу про гамбургеры из JS-задач из ОП поста.

> function(XMLHttpRequest) {


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

> success: function(jsonapi) {


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

> switch (jsonapi.data.meta) {


> case 'imeta':


> this[jsonapi.data.meta] = jsonapi.data.values;


Это какой-то странный код. Во-первых, он добавляет неочевидные побочные эффекты к функции, по-вторых, this тут будет указывать на другой объект (скорее всего на window). А, хотя там есть context. Но все равно неправильно так исплоьзовать свойств prototype так как он не для этого предназначен, не для хранения свойств объекта, а для описания методов, которые есть у всех объектов одного класса.

> switch (jsonapi.data.meta) {


> case 'imeta':


Непонятно, зачем тут switch, а не if.

Комментарий к функции написан с исплоьзованием какого синтаксиса? В jsDoc имена переменных вроде не берутся в квадратные скобки.
#615 #894884
>>894477

Насчет ООП: прототипы используются неправильно. Рекомендую почитать например тут https://learn.javascript.ru/prototypes (вообще, learn.javascript.ru стоит прочесть целиком, много полезного).

Замечания по коду:

Переменные надо называть нормально. Непонятно, что такое o или t, и это замедляет чтение кода. Надо дать им нормальные имена.

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

Ну например, что касается функции повтора запросов. Это можно сделать отдельной функцией вида:

sendRequestWithRetry(options, maxRetries)

где options - опции для $.ajax.

> if (t-- > 0


тут совмещено 2 действия (уменьшение переменной и проверка), и такой код тяжело читать. И вообще, не очень нормально, что if что-то модифицирует. Не надо стремиться записать код в одну длинную строку.

> && XMLHttpRequest.status != 404


Это явно неправильное условие. Ну например, сервер может вернуть 400 или 403, которые явно не требуют повтора. Логично делать повтор при TCp ошибках (обычно это код 0), или ошибках 5xx. Советую почитать про коды состояния HTTP.

> MyClass.prototype.myErrorHandler(


Это неправильно. При прототипном ООП мы вызываем метод как obj.method(), а prototype используем только при описании метода. Советую решить задачу про гамбургеры из JS-задач из ОП поста.

> function(XMLHttpRequest) {


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

> success: function(jsonapi) {


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

> switch (jsonapi.data.meta) {


> case 'imeta':


> this[jsonapi.data.meta] = jsonapi.data.values;


Это какой-то странный код. Во-первых, он добавляет неочевидные побочные эффекты к функции, по-вторых, this тут будет указывать на другой объект (скорее всего на window). А, хотя там есть context. Но все равно неправильно так исплоьзовать свойств prototype так как он не для этого предназначен, не для хранения свойств объекта, а для описания методов, которые есть у всех объектов одного класса.

> switch (jsonapi.data.meta) {


> case 'imeta':


Непонятно, зачем тут switch, а не if.

Комментарий к функции написан с исплоьзованием какого синтаксиса? В jsDoc имена переменных вроде не берутся в квадратные скобки.
>>894918
#616 #894888
>>894477

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

Ну представим, что у пользователя периодически пропадает связь и запросы отваливаются после долгого таймаута. Может пользователь бы хотел что-то другое сделать, но ему придется ждать пока все попытки отработают.
>>894918
#617 #894918
>>894884
>>894888
Спасибо, буду разбираться!
77 Кб, 604x511
#618 #895119
>>895230>>895322
#619 #895230
>>895119
Шта?..
#620 #895322
>>895119

В чем боль-то? Добавляют в PHP7.2 функции для получения кода многобайтового символа и генерации символа по коду.
>>895613
#621 #895613
>>895322
Весь похапе боль не ври мне тут говно
Старые ответы за ноябрь #622 #895687
>>882515

Отрицательная сумма получается из-за того, что когда там остается 1200 долга, ты все равно платишь банку 5000. А надо эти оставшиеся 1200 и платить.

Я бы написал так:

если (долг больше чем плата в месяц) {
платим = плата в месяц;
} иначе {
платим = сумма долга;
}

Ну и далее этот if можно заменить на min() или max().

>>880900

Не знаю, не писал ничего под magento. Попробуй посмотреть код и почитать документацию.

>>882320

Не знаю, я бы начал с изучения документации самого фейсбука.

>>882619

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

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


Не понял вопрос. зачем "создавать каждую страницу заново"?

>>882645

Смешивать PHP c HTML можно, не надо просто смешивать логику получения данных и логику их отображения. Таблица генерируется циклом вроде foreach.

>>882669

Не надо изобретать свой шаблонизатор. Надо брать готовый.

>>882731

Что значит "у нас"? За отправку файлов отвечает браузер, его разработчики и HTML стандарты.

>>883499

Не знаю. Я бы нашел сайт или статью с обзорами разных CMS и фреймворков для начала. Ну и далее сам бы уже смотрел проекты, которые там упоминаются.
Старые ответы за ноябрь #622 #895687
>>882515

Отрицательная сумма получается из-за того, что когда там остается 1200 долга, ты все равно платишь банку 5000. А надо эти оставшиеся 1200 и платить.

Я бы написал так:

если (долг больше чем плата в месяц) {
платим = плата в месяц;
} иначе {
платим = сумма долга;
}

Ну и далее этот if можно заменить на min() или max().

>>880900

Не знаю, не писал ничего под magento. Попробуй посмотреть код и почитать документацию.

>>882320

Не знаю, я бы начал с изучения документации самого фейсбука.

>>882619

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

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


Не понял вопрос. зачем "создавать каждую страницу заново"?

>>882645

Смешивать PHP c HTML можно, не надо просто смешивать логику получения данных и логику их отображения. Таблица генерируется циклом вроде foreach.

>>882669

Не надо изобретать свой шаблонизатор. Надо брать готовый.

>>882731

Что значит "у нас"? За отправку файлов отвечает браузер, его разработчики и HTML стандарты.

>>883499

Не знаю. Я бы нашел сайт или статью с обзорами разных CMS и фреймворков для начала. Ну и далее сам бы уже смотрел проекты, которые там упоминаются.
#623 #895746
>>894882
http://ideone.com/82ziTH
Переделал задачу. Тема мне понравилась. Было интересно посмотреть, как по разному можно упаковывать данные в бинарные формы в зависимости от поставленных требований.
>>895938
#624 #895861
Ребят помогите плиз, я даунич, но мне нужно это реализовать: Реализовать класс вектора, у этого класса будет поле массив и следующие методы: сложение с вектором, умножение на число ,возвращение модуля вектора и скалярное произведение 2-х векторов и вывод на экран, хелп плиииз!
>>896088
#625 #895872
Почему вы не перекатываете тред при >500? Он в результате на дне, не виден людям, а виден только тред-параша.
>>895925>>895932
#626 #895925
>>895872
Вынужденные жертвы.
Потому что загаживают тред оффтопиком в стиле пэхапэ против бэтмана, сделайте мой фриланс и т.д. Посмотри в архиваче на начало тредов и на конец. Почувствуй разницу. Когда то было два php треда: учебный и для бурных дискуссий, тогда было полегче.
>>895932
#627 #895932
>>891454
Интересно, а как они оценивают эту "информационную открытость"? Лазают вручную смотрят? Или ботов заставляют по определенным алгоритмам? И конечно же вопрос: я тупой, зачем вся эта хрень вообще нужна?
>>895872
>>895925
Еще бы конеш не удаляли треды, как например на доброчане.
>>896096
#628 #895938
>>895746

Кстати, еще строку превратить в коды байт можно функцией bin2hex, но она генерирует 16-чные цифры без пробелов между ними.

> utf-32 string starts with 4 bytes BOM and 2 "empty" bytes (FFFE + 0000)


Неточно, в utf-32 символ занимает 4 байта и последовательность ff fe 00 00 - это и есть 1 символ BOM, а далее 4 байта - это код символа. Я думаю, надо было использовать utf-32 le или be с явным указанием вида кодировки (чтобы байты там шли в нужном порядке) и не мучаться с определением, где что.

Я вижу, ты там получаешь 16-чный код склеиванием побайтово, если бы тебе нужен был 10-чный код то пришлось бы умножать на степени числа 256:

b3 * 256 ^ 3 + b2 *256 ^ 2 + b1 * 256 ^ 1 + b0 * 256 ^ 0.

Я может еще потом сделаю урок про представление чисел в памяти, там тоже много интересного. Вот например, как представляются числа с плавающей запятой: https://habrahabr.ru/post/112953/

Но в общем, я думаю, эта задача решена.

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

preg_match("//u", $string) вернет false, а не 0 или 1.
#629 #896088
>>895861

И что именно из этого ты не можешь сделать? Если ничего,то стоит начать с теории и изучения учебника в ОП посте.
>>896432
#630 #896096
>>895932

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

Мониторинг используют и коммерческие компании.

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

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

В любом случае, наличие данных лучше их отсутствия.

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

Вот например московские открытые данные: https://data.mos.ru/

Там можно узнать к примеру, что в Москве 48 снегоплавильных пунктов: https://data.mos.ru/opendata/7701236617-statsionarnye-snegoplavilnye-punkty
#631 #896432
>>896088
>>896088
Мне зачет нужно сдать, а я ничего не знаю, ибо долбоеб
#632 #896666
Вы не боитесь такую охуенную шапку потерять? Там у вашего переката уже 100+ постов, скоро ведь смоет ентот тредю.
>>896674
#633 #896674
>>896666

мы пока на 6-й странице, успеем еще.
#634 #896680
Подскажите пожалуйста как сделать так что бы опечатки выделялись в скобки, у меня почему то скобки заменяют англ букву

https://ideone.com/LO13Fo
>>896712>>896719
#635 #896712
>>896680
Вот тут написано про подмаски: http://php.net/manual/ru/function.preg-replace.php
Переменные $n содержат то, что захватила регулярка скобочками. Попробуй добавить их в регулярку.
#636 #896719
>>896680
Я уже разобрался в preg_replace заменил $1 на $0 и все сработало
#637 #896946
ОП, скажи пожалуйста, почему в примере класса EventDispatcher (https://github.com/mrdoob/eventdispatcher.js/) из задачи Сапер.MVC в качестве наследования используют метод Object.assign() вместо конструкции class {method: {} } и class Extends {} ?
>>896983
#638 #896983
>>896946

Я думаю, потому что классы только относительно недавно в ES5 или ES6 появились, а не в ES3. Хуже совместимость будет.

Object.assign это просто неглубокое копирование свойств. Код там равносилен коду вроде

X.prototype.method =function () { ... };
>>897004
#639 #897004
>>896983

>классы только относительно недавно в ES5 или ES6 появились, а не в ES3



Проверил, и классы и Object.assign описаны в ECMAScript 2015 (6th Edition, ECMA-262)

В соседней ветке мне объяснили так:

>assign копирует.


>extends наследует.


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


>ассигн используют тут вместо clone.



Но в примере свойства копируются в прототип:

Object.assign( Car.prototype, EventDispatcher.prototype );
или
Object.assign( EventDispatcher.prototype, {...} )

Следовательно все экземпляры класса Car и EventDispatcher унаследуют свойства, скопированные в прототипы этих классов? Т.е. тут .assign не копирует а наследует, как ты и написал: равносильно X.prototype.method =function () { ... }; ??? Вопрос все еще открыт, зачем автор в примере так извращается, или что я упускаю?
>>897043>>897045
#640 #897043
>>897004

А, я сначала не так понял и не так ответил. Я думал вопрос был про использование assign в этом файле https://github.com/mrdoob/eventdispatcher.js/blob/master/src/EventDispatcher.js

Насчет es5 ты прав, я что-то не подумал. Можно было использовать синтаксис с class.

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

В чистом ООП, если мы не хотим применять наследование (так как наследование это отношение вида "A является B", а нам нужно "A содержит B"), мы используем аггрегирование: https://ru.wikipedia.org/wiki/Агрегирование_(программирование)

То есть мы создаем объект Event Dispatcher внутри car:

function Car() {
this._eventDispatcher = new EventDispatcher();
}

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

Car.prototype.addEventListener = function ( ... ) {
this._eventDispatcher.addEventListener(...);
};

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

Автор решил упростить код и просто скопировать методы из прототипа EventDispatcher в прототип Car. Это еще называется "mixin", примешивание. Оно имеет свои недостатки, ну например:

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

Тем не менее такой подход иногда используют.

В общем, в данном случае автор решил использовать mixin.

Насчет событий, я видел разные подходы:

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

this.onDataLoaded = new EventSource;
this.onError = new EventSource;
...
this.onError.trigger('Some error text');

А подписка делается так:

x.onDataLoaded.subscribe(function (event) { ... });

В языке C# даже сделали специальный тип поля "событие", хотя я не уверен что для событий нужно что-то специально делать на уровне языка. Там в класс добавляется специальное поле-источник событий, а при обращении к нему как к функции происходит вызов подписчиков: https://msdn.microsoft.com/ru-ru/library/edzehd2t(v=vs.110).aspx
#640 #897043
>>897004

А, я сначала не так понял и не так ответил. Я думал вопрос был про использование assign в этом файле https://github.com/mrdoob/eventdispatcher.js/blob/master/src/EventDispatcher.js

Насчет es5 ты прав, я что-то не подумал. Можно было использовать синтаксис с class.

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

В чистом ООП, если мы не хотим применять наследование (так как наследование это отношение вида "A является B", а нам нужно "A содержит B"), мы используем аггрегирование: https://ru.wikipedia.org/wiki/Агрегирование_(программирование)

То есть мы создаем объект Event Dispatcher внутри car:

function Car() {
this._eventDispatcher = new EventDispatcher();
}

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

Car.prototype.addEventListener = function ( ... ) {
this._eventDispatcher.addEventListener(...);
};

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

Автор решил упростить код и просто скопировать методы из прототипа EventDispatcher в прототип Car. Это еще называется "mixin", примешивание. Оно имеет свои недостатки, ну например:

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

Тем не менее такой подход иногда используют.

В общем, в данном случае автор решил использовать mixin.

Насчет событий, я видел разные подходы:

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

this.onDataLoaded = new EventSource;
this.onError = new EventSource;
...
this.onError.trigger('Some error text');

А подписка делается так:

x.onDataLoaded.subscribe(function (event) { ... });

В языке C# даже сделали специальный тип поля "событие", хотя я не уверен что для событий нужно что-то специально делать на уровне языка. Там в класс добавляется специальное поле-источник событий, а при обращении к нему как к функции происходит вызов подписчиков: https://msdn.microsoft.com/ru-ru/library/edzehd2t(v=vs.110).aspx
>>897082
#641 #897045
>>897004

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

https://github.com/mrdoob/eventdispatcher.js/blob/master/src/EventDispatcher.js#L11

if ( this._listeners === undefined ) this._listeners = {};
#642 #897082
>>897043

>автор кода не хочет наследовать Car от EventDispatcher, например, может он хочет его от чего-то другого унаследовать


>машина это ведь не улучшенный вариант EventDispatcher



Вот теперь дошло, спасибо большое.
#643 #897195
>>894463
Спасибо, замечания учту.
js someApprentice #644 #897432
Уже прошло два месяца с тех пор как я не могу решить ту задачу по js. Всё это время как я брался за эту задачу у меня возникало непонимание чем я сейчас занимаюсь. Каждый раз она буквально вызывала у меня физическую боль, потому что у меня появлялись мысли что раз я не могу решить её, значит я не смогу заниматься программированием. Это каждый раз бросало меня в глубокие прострации. У меня ещё пару таких же задач вызывали трудности, но с ними ещё я догадался как справляться, но от этой у меня полнейшая пустота в голове... Можем быть это потому что я полностью не читал учебник по js а лишь бегло пробежался по нему Я старался вчитываться, но это вызывало глубочайщую скуку.

Буквально сегодня я отчаялся и решил спросить ещё одну подсказку здесь, но пока я пытался сформулировать вопросы, я решил её сам:

https://dkab.github.io/jasmine-tests/?spec=6
https://jsfiddle.net/92nc4fj2/

Только один вопрос

http://pastebin.ru/yLh80hF8

>> var args = [].slice.call(arguments);


>> args.shift();


>можно без shift, указать аргумент для slice


А как указать его? Через .slice(1).call(...) или .slice.call(1)(...) не получилось...

Скоро будут исправлены остальные замечания

Большое спасибо!!!
#645 #897449
>>897432

> Через .slice(1).call(...) или .slice.call(1)(...) не получилось


И не должно, ты пытаешься вызвать call у результата функции, а нужно вызывать у самой функции. Вот тут написано как использовать call: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call
И да, эта тема хорошо разжёвано у Кантора.

А насчёт сложности заданий, то у меня от четвёртой были такие же ощущения как и у тебя, так что всё норм, проходят дни и мозг сам по-немногу раскладывает непонятное по полочкам.
>>897453
someApprentice #646 #897453
>>897449
Если честно, то я действительно взялся за эту задачу только пару дней назад. Остальное время я ужасался сложностью этой задачи и впадал в прострацию.
>>897549
#647 #897549
>>897453

Лучше не ужасаться, а написать, что именно непонятно, и попросить совет. В нашем треде обычно всегда что-нибудь посоветуют.

>>897432

>>> var args = [].slice.call(arguments);


>>> args.shift();


>>можно без shift, указать аргумент для slice


> А как указать его? Через .slice(1).call(...) или .slice.call(1)(...) не получилось...


А ты пробовал читать справку по методу call и разобраться, как работает [].slice.call? Например тут:

- https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Function/call
- https://learn.javascript.ru/call-apply

Тут надо понимать такие вещи:

- "методом" в других языках принято называть функцию, которая объявлена в классе и вызывается не сама по себе, а на каком-то объекте: someObject.someMethod(); Но в JS как таковых до ES5, методов не было и не было специального синтаксиса их создания - есть просто обычные функции, записанные в свойства объекта. Мы добавлям функцию объект или прототип объекта - и получается что-то похожее на метод. Для сравнения, в PHP есть специальный синтаксис для методов: class X { public function () { ... }; }

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

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

function x() {};
x.something = 1;
x.someMethod = function () {};

или так:

var x = new Function(...);
x();

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

var x = [1, 2, 3];
x.test = function () { return 5; };
console.log(x.test());

- у массивов есть метод slice (который тоже является объектом), а когда мы пишем [].slice без скобок, то мы не вызвыаем его, а просто получаем этот объект. Сравни:

var x = [].slice; - копируем в переменную x ссылку на метод slice у массива.
[].slice() - вызваем метод slice()

- у функций есть метод call, который позволяет вызвать функцию с заданным значением this и аргументами

- есть особые правила, как именно определяется значение this при вызове функции. Описано например тут: https://learn.javascript.ru/objects-more

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

1)
function x() { }; x();
2)
var z = {};
z.test = function () {};
z.test();
3)
var z = {};
z.test = function() {};
var fn = z.test;
fn();
#647 #897549
>>897453

Лучше не ужасаться, а написать, что именно непонятно, и попросить совет. В нашем треде обычно всегда что-нибудь посоветуют.

>>897432

>>> var args = [].slice.call(arguments);


>>> args.shift();


>>можно без shift, указать аргумент для slice


> А как указать его? Через .slice(1).call(...) или .slice.call(1)(...) не получилось...


А ты пробовал читать справку по методу call и разобраться, как работает [].slice.call? Например тут:

- https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Function/call
- https://learn.javascript.ru/call-apply

Тут надо понимать такие вещи:

- "методом" в других языках принято называть функцию, которая объявлена в классе и вызывается не сама по себе, а на каком-то объекте: someObject.someMethod(); Но в JS как таковых до ES5, методов не было и не было специального синтаксиса их создания - есть просто обычные функции, записанные в свойства объекта. Мы добавлям функцию объект или прототип объекта - и получается что-то похожее на метод. Для сравнения, в PHP есть специальный синтаксис для методов: class X { public function () { ... }; }

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

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

function x() {};
x.something = 1;
x.someMethod = function () {};

или так:

var x = new Function(...);
x();

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

var x = [1, 2, 3];
x.test = function () { return 5; };
console.log(x.test());

- у массивов есть метод slice (который тоже является объектом), а когда мы пишем [].slice без скобок, то мы не вызвыаем его, а просто получаем этот объект. Сравни:

var x = [].slice; - копируем в переменную x ссылку на метод slice у массива.
[].slice() - вызваем метод slice()

- у функций есть метод call, который позволяет вызвать функцию с заданным значением this и аргументами

- есть особые правила, как именно определяется значение this при вызове функции. Описано например тут: https://learn.javascript.ru/objects-more

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

1)
function x() { }; x();
2)
var z = {};
z.test = function () {};
z.test();
3)
var z = {};
z.test = function() {};
var fn = z.test;
fn();
>>897617
#648 #897608
У кого впска под рукой? Поставьте это говно, а то на моем хостинге не встает нихуя
https://github.com/lordelph/pastebin
#649 #897617
>>897549

>в JS функции являются еще и объектами с конструктором Function. Потому у них самих могут быть и свойства, и "методы". И можно даже делать так (но не нужно, чтобы не путать людей):



>function x() {};


>x.something = 1;


>x.someMethod = function () {};



или так:

>var x = new Function(...);


>x();



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



>var x = [1, 2, 3];


>x.test = function () { return 5; };


>console.log(x.test());



Объясни пожалуйста понятно, почему не нужно? Как лучше? Просто я вот знаю только эти способы как раз, и считал что это и есть магия ООП в js! Теперь твой пост вогнал меня в фрустрацию.
>>897623>>897628
#650 #897623
>>897617

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

class SomeClass {
someMethod: function () { ... }
}

где-то в другом используем объект этого класса:

/**
*@param obj {SomeClass}
*/
function doSomething(obj) {
obj.someMethod(...);
...
}

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

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

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

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

Конечно, если у тебя программа из 100 строк, то о таких вещах можно не беспокоиться и писать как угодно. Но реальные проекты - большие, в них сотни тысяч строк, над ними может работать десяток людей, и терять время на выяснение, как работает какой-то нестандартный код, недопустимо. Код должен быть простым и понятным.
#650 #897623
>>897617

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

class SomeClass {
someMethod: function () { ... }
}

где-то в другом используем объект этого класса:

/**
*@param obj {SomeClass}
*/
function doSomething(obj) {
obj.someMethod(...);
...
}

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

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

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

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

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


У кого впска под рукой? Поставьте это говно, а то на моем хостинге не встает нихуя
https://github.com/lordelph/pastebin

>>897650
#652 #897628
>>897617

Теперь конкретнее:

>function x() {};


>x.something = 1;


>x.someMethod = function () {};



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

>var x = [1, 2, 3];


>x.test = function () { return 5; };


То же самое, если тебе хочется что-то сделать с массивом, лучше сделать отдельную функцию и передать в нее массив как аргумент. Массив - это стандартный объект в JS и разработчик не ожидает, что у него есть какие-то дополнительные методы, не описанные в документации.
>>897665
#653 #897643
>>897432

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

Если тебе не очень нравятся абстрактные задачи, ты ведь знаешь HTML, ты можешь попробовать начинать параллельно делать что-нибудь посложнее, можно игру в сапера, можно игру "арканоид" ( https://gist.github.com/codedokode/9933897 ) или, например, какое-нибудь простое приложение, если тебе не нравятся игры (например, написать простую электронную таблицу вроде экселя). Главное, чтобы это было на какую-то интересную тебе тему.

Что касается задачи:

> var args = [].slice.call(arguments);


> args.shift();


Было бы хорошо, если бы ты понял, как сделать это без shift(). call тут по сути вызывает функцию [].slice, подсовывая в this ей вместо массива переменную arguments. Надо подумать, как тут передать в эту функцию еще и аргумент, чтобы она сделала копию, начиная с 1-го, а не с 0-го элемента.

> for(var i = 0; i < args.length; i++) {


> oldArgs = args;


Скопировать массив можно методом slice: https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Array/slice

Решено верно.
>>897665
#654 #897650
>>897627
На локалхосте ставь, ленивое говно.
#655 #897665
>>897628
Ну, второе конечно пушка.

Но вот первый пример:

>function x() {};


конструктор

>x.something = 1;


>x.someMethod = function () {};


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

> function x((obj)arg) {


> this.something = arg.something;


> };


>x.prototype.someMethod = function() {};


>...


);

var example = new x(arg);

и понеслась... Получается, это тоже неправильно так делать.

>>897643
Мне например программирование не нужно как профессия, и просто люблю понемножку разбираться (ооочень медленно), как работают те или иные подходы; но считаю если ты хочешь зарабатывать этим, сделать это своим главным занятием в жизни - НУЖНО МНОГО РАБОТАТЬ. Прям просто ДОФИГА, в идеале каждый возможный вариант разобрать, разложить для себя по полочкам возможности и баги, потом приступать к следующему шагу, а не просто блин

>Можем быть это потому что я полностью не читал учебник по js а лишь бегло пробежался по нему


это хуйня подход. Умные люди уже обожглись не раз и пытаются преподнести материал чтобы он легче усвоился (ОП например или автор того сайта по javascript). Это не мануалы и не справочники, тут живые люди с тобой работают, которые тоже с чего-то начинали и подсказывают тебе как тебе, да ТЕБЕ, будет проще начать самому. Такое вот мнение. >>897432
Например, ты на CodeCademy базовый курс хотя бы прошел?
#655 #897665
>>897628
Ну, второе конечно пушка.

Но вот первый пример:

>function x() {};


конструктор

>x.something = 1;


>x.someMethod = function () {};


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

> function x((obj)arg) {


> this.something = arg.something;


> };


>x.prototype.someMethod = function() {};


>...


);

var example = new x(arg);

и понеслась... Получается, это тоже неправильно так делать.

>>897643
Мне например программирование не нужно как профессия, и просто люблю понемножку разбираться (ооочень медленно), как работают те или иные подходы; но считаю если ты хочешь зарабатывать этим, сделать это своим главным занятием в жизни - НУЖНО МНОГО РАБОТАТЬ. Прям просто ДОФИГА, в идеале каждый возможный вариант разобрать, разложить для себя по полочкам возможности и баги, потом приступать к следующему шагу, а не просто блин

>Можем быть это потому что я полностью не читал учебник по js а лишь бегло пробежался по нему


это хуйня подход. Умные люди уже обожглись не раз и пытаются преподнести материал чтобы он легче усвоился (ОП например или автор того сайта по javascript). Это не мануалы и не справочники, тут живые люди с тобой работают, которые тоже с чего-то начинали и подсказывают тебе как тебе, да ТЕБЕ, будет проще начать самому. Такое вот мнение. >>897432
Например, ты на CodeCademy базовый курс хотя бы прошел?
>>897697
#656 #897666
В дополнение к этому >>894815 посту.
Упростил вывод дерева и переписал на PHP: http://ideone.com/2fkGTp

Дом 1. https://jsfiddle.net/z49dssxz/

> Сделай функции dom.hasClass(node, klass)


А в тестах написано так: l(hasClass(createNode('div'..., то есть без объекта dom. Я просто не совсем понял зачем он здесь нужен, для группировки методовкак в случае с Math.pow/Math.sin?

Дом 2: https://jsfiddle.net/je858mz4/1/

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


Я лихорадочно кликал по таблице из-под Хрома 50, Мозиллы 41,49, IE11, но так и смог добиться этого эффекта.
Полагаю, для решения должно хватить таких CSS-правил: http://stackoverflow.com/a/6382492

Было бы удобно, если бы эти задания были в репозитории pasta
#657 #897697
>>897665

> var example = new x(arg);


> и понеслась... Получается, это тоже неправильно так делать.


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

В моем примере метод добавляется в один экземпляр объекта - функцию или массив, и смысла как раз это не имеет. Вместо x.something можно просто написать var something = 1.

Насчет разбраться - это хорошая идея, я когда был начинающим, тоже мог зарыться в мануалы или спецификации, чтобы выяснить что как работает. Или мерять размеры инпутов в разных браузерах. Это полезный подход, и я думаю, на собеседовании это произведет хорошее впечатление.
Обновить тред
Двач.hk не отвечает.
Вы видите копию треда, сохраненную 21 декабря 2016 года.

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

Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
« /pr/В начало тредаВеб-версияНастройки
/a//b//mu//s//vg/Все доски