Этого треда уже нет.
Это копия, сохраненная 11 августа 2017 года.

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

Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
Клуб изучающих PHP и webdev #91 #1019301 В конец треда | Веб
Добро пожаловать в наш уютный тред. Тут мы изучаем веб-разработку на языке PHP (а также JS/CSS/HTML/SQL), решаем задачки и делаем простые сайты! Зачем? Кто-то хочет сделать себе блог, кто-то приобрести новую профессию, кому-то просто нечего делать.

Пожалуйста, пишите один большой пост вместо нескольких маленьких и не флудите не по теме.

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

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

Предыдущий тред был тут: >>1000416 (OP) ( http://arhivach.org/thread/266631/ ). Еще предыдущие треды ищутся в гугле по словам "клуб php" или в архиваче. Еще есть такой архив тредов: phpclub.rf.gd

Мейлач лежит? Есть запасной тред: доброчан-орг/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 3/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. У нас в треде были люди, которые практически с нуля учились и смогли найти работу.
- Что будут спрашивать на собеседовании если 0 опыта - гонять по теории, по официальному мануалу PHP, давать дурацкие задачки на переворачивание строк, гонять по SQL (транзакции, внешние ключи, напиши запрос), по JS (как сделать анимацию при нажатии кнопки), ну погугли, не ленись
- Можно подробнее про поиск работы, собеседования - нет, ОП писать не будет, но может кто из анонов захочет рассказать. Поищите тред перезвонивших, а также раздел /wrk/.
- Сколько времени надо изучать все это? - все зависит от тебя, но не меньше 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 #1019303
Код нужно писать не как попало, а аккуратно и по правилам. Почему? Потому, что на неакуратно написанный код не хочется даже смотреть.

Если тебе лень выравнивать код руками, закачай его на 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 #1019303
Код нужно писать не как попало, а аккуратно и по правилам. Почему? Потому, что на неакуратно написанный код не хочется даже смотреть.

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

Этот проект https://github.com/Merkalov/Students я проверил тут >>1005550 (если тред утонул, ищите в архиваче)
#4 #1019372
Не заметил что уже перекат. Извините.

>>1019368
#5 #1019419
подписался
17 Кб, 159x159
IDE #6 #1019450
Какже мне горит, от моего старого ноута куплен в 2009 году. Решился установить PHPStorm - какаяже годнота, именно то, что нужно, но пиздец как тормозит, пришлось снести.

Юзаю codelobster. Пытался в netbeans, но во-первых: он тоже притормаивает, а во вторых - нет нормального автодополнения для laravel и blade.

Может кто-то посоветовать, что-то годной для старых компухтеров?
#7 #1019464
Есть ли пхпшнику профит от изучения C++?
Я имею в виду, есть ли проекты, требующие навыков написания кода на обоих этих языках. И насколько это экзотика?
#8 #1019562
>>1019464

хайлоад (хотя сейчас там чаще посматривают в сторону Го или Раста, но их без знания Си изучать трудно).
#9 #1019593
>>1019450
субллайм + плагины
#10 #1019597
>>1019593
сублайм терпеть не могу. Уж сорян, пытался его настроить даже поюзал какое-то время, но отсутствие тулбара, настройки через пизду, все на горячих клавишах, отсутствие проводника и самое главное черный цвет паталогически не могу кодить в темных редакторах заставили меня его снести, уж лучше codelobster. Может еще какие варики есть?
58 Кб, 540x542
#11 #1019622
>>1019450

>нет нормального автодополнения для laravel и blade


https://www.google.ru/search?q=netbeans+blade+syntax+highlighting&gws_rd=cr&ei=jEFiWaPzFcbC6QTpvrqoCA
Жёсткий диск заменил на ССД?
#12 #1019646
>>1019622
Ты конкретную ссылку дай, то, что ты умеешь запрос в гугле составить я понял. Есть полурабочие способы, где нужно плясать с бубном - это никак не подходит под определение "норальное"
#13 #1019750
>>1019646
Для блейда есть плагин, емнип
#14 #1019755
>>1002548

А почему тогда не сделаны сеттеры на ранг или на лидера?

И получается нужно на все вводимые данные делать сеттеры и на сеттеры ставить тайпхинты? А на все другие данные константы?
#15 #1019760
Сап, вебач. Тема такая - я не столь давно прошел курс макаки-верстальщика, но приложиться не было времени и возможности. Сейчас все заново преучиваю и у меня назрел вопрос: будучи веб-разрабом или просто версталкой, нужно ли мне будет создавать графическую часть? Иконки, дизайн и прочее? Или это задачи дизигнеров и заказчики этого не просят?
#16 #1019770
что почитать про создания сайтов с регистрацией,постингом,загрузки всяких файлов,взамодействие между юзерами сайта,гугление дает одну хуйню
sage #17 #1019771
>>1019760
Есть миллион готовых библиотек для иконок.
Если заказчик дает тебе эскиз (макет), то иконки все есть.
Если в студии с кем-то, то также - картинки даны.
Верстальщику рисовать не очень нужно.
sage #18 #1019772
>>1019770
Гуглишь курсхантерс, оплачиваешь подписку на Хекслете.
#19 #1019773
>>1019772
а обязательно платить,мож на английском че есть?
92 Кб, 688x460
#21 #1019868
>>1019301 (OP)

>


- сделать для каждой формы свой URL, который и выводит ее (при GET), и обрабатывает запрос (при POST). И форма с главной шлет запрос на этот URL, при ошибке выводится только сама форма с ошибкой.

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

> При ошибке выводится только сама форма с ошибкой



...это что, будет вью только с этой формой комментария? Т.е. шаблон без ничего (ну кроме шапки и подвала, которые везде инклюдятся), только эта форма?
Или же, если я правильно понял, эти две формы выводятся и в local.app/controller/indexAction и в local.app/controller/someAction, но как второй экшн вернет главному список ошибок? Можно немного псевдокода, что-то я давно мучаюсь с этими второстепенными экшнами и мой код сейчас выглядит как пикрелейтед (функции delFile, addComment, checkAccessPass являются не экшнами, а просто уменьшают толщину контроллера).
#22 #1019871
#23 #1019896
>>1019770
Тебе надо работать с БД, в которой ты будешь хранить юзеров и данные.
Для авторизации пользователя тебе надо куки.
Загрузка файлов - обычная работа с файлами, вида
...
<form enctype="multipart/form-data" action="addres" method="POST">
<input type="hidden" name="MAX_FILE_SIZE" value="44444" />
<input name="userfile" type="file" />
<p><input type="submit" value="Загрузить"></p>
</form>
...
$uploaddir = 'dir';
$uploadfile=$uploaddir.basename($_FILES['userfile']['name']);
...
#24 #1019935
>>1019896
почему везде все это дается кусками и приходить потом дрочить что бы все это собрать в одно?
#25 #1019948
>>1019896
сессии+куки
>>1019935
я бы дал тебе годных видеоуроков, блягодаря которым я это все постиг, но ты ведь не будешь смотреть, ибо там 200+ часов
#26 #1019988
>>1019948
Ну ты кинь линк, а там уже смотреть или нет - дело каждого.
#27 #1020006
>>1019988
Давно смотрел видосы от этого васяна: https://school-php.com/video
Они всратые, старые, в них много воды и они примитивные, но после них я научился строить какую-никакую архитектуру сайта, понял как делаются все эти авторизации и пр. Рекомендую их только потому, что не знаю смог бы я научится всему тому, по следующим урокам...
... а это уроки для илиты, это реально ахуенная хуйня, тут есть все: от самых основ (переменные, массивы, циклы и пр.) до ООП, паттернов, MVC, обзора по фреймворкам и т.пр. Качество плоховатое, но я реально ничего лучше не видел, просто посмотри на программу Кликни на "дополнительная информация" каждого из уроков:
1 уровень: http://nnm-club.me/forum/viewtopic.php?t=889322
2 уровень: http://nnm-club.me/forum/viewtopic.php?t=889427
3 уровень: http://nnm-club.me/forum/viewtopic.php?t=889601
4 уровень: http://nnm-club.me/forum/viewtopic.php?t=1014639
#28 #1020018
>>1020006
Спасибо.
#29 #1020029
Я сегодня у мамы быдло-верстальшик. Собираю Франкенштейна из деталек бутстрапа.

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

А вы что творите, аноны?
#30 #1020111
Если я напишу какуют приложуху и запихну ссылку с ее кодом на гитхабе и для пруфов работоспособнсти залью на хост и тоже укажу ссылку и укажу все это в резюме, мне необходимо будет пояснять за нее на собеседовании? Или это пук в воду и им насрать на мои старания?

И вообще, есть тут те, кто работает пхп джуном? Что вы вообще делаете?
#31 #1020139
>>1020029
ты так все время пердолишь окно?
и в фф и в хромиум-* вроде же есть эмуляция
и почему шиндовс?
#32 #1020143
>>1020111
По всякому. Бывают собеседования, где за каждую строчку пояснить просят.
#33 #1020145
антоны помогите плизке
сайт pisos.ru
как сделать, чтобы файл
/folderWithCandies/dick.html
открывался по адресу pisos.ru/dick ?
через редирект 301 или что-то типа того
2,7 Мб, 1440x1080
#34 #1020161
>>1020139
Какая эмуляция?

На мак денег пока нет. А в лиуксе интерфейс громоздкий, сжирает много экранного места по вертикали, и безбожно томозит, всё это в сравнении с виндой. Хостинг - выделенный на убунте, пердолю через ssh, гуй там не нужен.

Вчера открыл для себя, что вместо копирвоания файлов на хостинг через ftp или ssh можно просто сделать там пулл реквести из гит.
#35 #1020166
>>1020145

>/folderWithCandies/


На выделенном хостинге настроить апач или нгникс так чтобы корневой папкой была "/folderWithCandies/"

На виртуальном можно создать в корне dick.php который будет подтягивать "/folderWithCandies/dick.html" с помощью require или include. В адресной строке тогда останется "pisos.ru/dick"

htaccess может только перенаправить с "pisos.ru/dick" на "/folderWithCandies/dick.html" В адресной строке тогда будет "/folderWithCandies/dick.html" и ничего с этим не поделать

А вообще обязательно описывай зачем, может тебе вообще что-то другое пододёт
#36 #1020292

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



https://pastebin.com/ZZ687D7q
#37 #1020317
>>1020292

> Нужно для каждого статуса для заданного диапазона дат получить кол-во транзакций с данным статусом,


Группировка не годится? Только таблицу повернуть, чтобы были такие колонки

date | ok | wait | cancel
------------------------

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


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

> Чо они вагрантом не пользуются


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

Там ведь разные сервисы, хранилища файлов, базы данных, и тд.

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

> То есть persist на каждом шагу и не нужен.


persist используется для передачи новых созданных объектов под управление entity manager. На каждом шагу он не нужен, да.

> В этом и состоит суть паттерна, что изменения в сущностях отслеживаются автоматически и сохраняются в базу при коммите?


Вроде примерно это (судя по https://martinfowler.com/eaaCatalog/unitOfWork.html ). Но там написано, что главное преимущество UOW это запись изменений атомарно, одной транзакцией, а не кучей мелких транзакций.

Доктрина содержит в UOW ссылки на все управляемый ей сущности (загруженные из БД, а также добавленные через persist), а также их исходное состояние и при flush() сравнивает их текущее состояние с исходным, находит различия, формирует пакет изменений и сбрасывает эти изменения в базу одной транзакцией.

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

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


Нету там ни мапперов, ни репозиториев.

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

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


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

> при извлечении из бд в репозиторий


В репозитории ничего не хранится.

> сохраняется ссылка на модель с статусом типа "clean", когда мы меняем свойства модели через сеттер, статус меняется на "dirty"


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

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

> Я придумал новую интеллектуальную игру


Тут можно использовать метод деления пополам, чтобы найти прблемное слово за относительно небольшое число постов. Делим пост на 2 равные части, определяем в какой проблема, делим проблемную часть еще на 2, и так далее.
#37 #1020317
>>1020292

> Нужно для каждого статуса для заданного диапазона дат получить кол-во транзакций с данным статусом,


Группировка не годится? Только таблицу повернуть, чтобы были такие колонки

date | ok | wait | cancel
------------------------

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


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

> Чо они вагрантом не пользуются


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

Там ведь разные сервисы, хранилища файлов, базы данных, и тд.

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

> То есть persist на каждом шагу и не нужен.


persist используется для передачи новых созданных объектов под управление entity manager. На каждом шагу он не нужен, да.

> В этом и состоит суть паттерна, что изменения в сущностях отслеживаются автоматически и сохраняются в базу при коммите?


Вроде примерно это (судя по https://martinfowler.com/eaaCatalog/unitOfWork.html ). Но там написано, что главное преимущество UOW это запись изменений атомарно, одной транзакцией, а не кучей мелких транзакций.

Доктрина содержит в UOW ссылки на все управляемый ей сущности (загруженные из БД, а также добавленные через persist), а также их исходное состояние и при flush() сравнивает их текущее состояние с исходным, находит различия, формирует пакет изменений и сбрасывает эти изменения в базу одной транзакцией.

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

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


Нету там ни мапперов, ни репозиториев.

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

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


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

> при извлечении из бд в репозиторий


В репозитории ничего не хранится.

> сохраняется ссылка на модель с статусом типа "clean", когда мы меняем свойства модели через сеттер, статус меняется на "dirty"


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

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

> Я придумал новую интеллектуальную игру


Тут можно использовать метод деления пополам, чтобы найти прблемное слово за относительно небольшое число постов. Делим пост на 2 равные части, определяем в какой проблема, делим проблемную часть еще на 2, и так далее.
#38 #1020356
У меня тоже вопрос про .htacces есть.
Как закрыть папку, чтобы извне никто не мог смотреть/исполнять файлыы, а сам сервер мог к ним оборащаться?

Экспериментировал с такими конструкциями и либо не блокируется ничего, либо блокируется для всех:
<FilesMatch ".(htaccess|php|jpg)$">
Order Allow,Deny
Deny from all
</FilesMatch>

Order deny,allow
Deny from all
<Files ~ ".(xml|css|jpe?g|php)$">
Allow from all
</Files>
#39 #1020364
>>1019597

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


Open folder побывал ?
>черный цвет
white theme sublime text в гугл

>все на горячих клавишах


разве в шторме не тоже самое ?

>настройки через пизду


кто то не может в json объекты ?

не говорю что он пизже всех или замена IDE но имхо для моих задач хватает с головой и не жрёт 1000 ГБ рама , Atom есть , Brackets но они все чёрные , что при желании можно легко изменить
#40 #1020370
>>1019597

Зачем тулбар? Я наоборот рад, что в нем нет этих дурацких кнопок. Цвет меняется, я сам не могу читать на темном фоне, тем более на моей плохой матрице. Файлы открываются через Ctrl + P либо через Ctrl + O с вписыванием пути вручную (в Windows в диалоге открытия файла можно писать путь и он дополняется).

Плагинами лучше не увлекаться, так как какой-нибудь из них рано или поздно начнет все замедлять.
#41 #1020373
Помогите пожалуйста, как скачать апач?
#42 #1020375
>>1020373
Нашел
53 Кб, 493x387
#43 #1020408
Анончики, решаю задачу про компанию "Вектор". Только начал, пытался проверить вывод имени департамента в терминале, а оно ничего не пишет, что я делаю не так?
https://pastebin.com/8NkvceWp
#44 #1020434
>>1020408
Я не пхпшник, но разве buy->name не должно возвращать значение, например, с помощью return, как в других ЯП?
#45 #1020443
>>1020434
в учебнике все вроде также было.
создаю объект, вызываю свойство, без всяких return
#46 #1020445
>>1020408
Потому что у тебя у объекта поле name пустое.
#47 #1020457
>>1020445
но я же его с помощью конструктора создаю
#48 #1020463
>>1020457
Нет.
27 Кб, 343x256
#49 #1020465
>>1020463
сорян, я constructor пишу, а надо construct
58 Кб, 1014x948
#50 #1020506
>>1019301 (OP)
ОП, смотри на что наткнулся по пыхе и по ноде нашел такое же
https://phpschool.io/
Есть идея твои уроки перепилить в формат подачи воркшопов. Стоит ли?
#51 #1020712
>>1020166
хочу сокращатель ссылок сделать
только теперь еще больше запутался и не пойму как это сделать нормально
#52 #1020722
>>1020712
Тебе нужно динамически генерировать html с помощью php. Пользователь вводит адрес, ты проверяешь есть ли такой в базе, если есть даешь ему короткую ссылку из базы, если нет генерируешь короткую ссылку и кладешь в базу.
#53 #1020728
>>1020722
генерировать каждый раз новый хтмл?
#54 #1020732
>>1020728
Не обязательно.
#55 #1020733
>>1020712
Используй фреймворки. Попробуй Slim, он простой.
#56 #1020739
>>1020145
>>1020712
if ($url == >'dick') {
//render dick
}

// for more information
Google: php router
23 Кб, 921x117
#57 #1020741
граждане, кто то пользовался вагрантом?
ставлю коробку под ларавел, запускаю виртуалку, но проблема - не установлен в ней mcrypt. захожу по ssh, устанавливаю через apt php7.1-mcrypt и хуяк! все ломается, все к едрени бабушки перекосоебливается и не работает. Версия php на виртуалке 7.1
#58 #1020789
>>1020161

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


Да пребудет с тобой git clone.
#59 #1020821
Как можно определить 100% что кравлер попал в бан? Получаю 403 код, хотя из cli курлом получил 200 ответ один раз, пробовал полностью менять шапку реквеста, если использую прокси - в зависимости от работоспособности оной получаю 200 код. Мне админ доказывает, что забанили по какому-то параметру в реквеста, и говорит что у него в консоли все ок всегда и 403 ни разу не получил.
И второй вопрос, можно ли спуфить IP курлом при запросе из cli с параметром interface с учетом что использованный IP куплен и установлен на сервере тоже
#60 #1020834
>>1019301 (OP)
Как правильно использовать php. Писать html в php коде, или php код в html странице? Или может как то еще можно?
#61 #1020857
>>1020834
Если что-то простое, то юзать PageController, если посерьезнее - FrontController и ApplicatiobController
я у мамы зандстраёб
#62 #1020870
>>1020857
Спасибо. Щас по гуглю.
Ответь еще пожалуйста, в php есть встроенные обработчики, ну как в ноде например, пишешь обработчик для запроса и вызываешь функцию? Не смог нагуглить точный ответ.

И еще кое что, как делают так, что при запросе www.host.ru/page открывается страница без окончания index.php? Знаю что во фреймворках такое, но как сделать без фреймворков не могу нагуглить.
#63 #1020876
Ничего не понимаю, везде пишут только про обработку форм php. Запросы на страницы как обрабатывать? Хелп анончики.
#64 #1020900
ОП проверь плз. Задача про компанию вектор. http://ideone.com/UZfro9

Тайпхинты не использовал, смысл в них вообще.

А еще ошибки не знаю как исправить.
#65 #1020902
>>1020870
гугли ЧПУ , rewrite mod apache2
#66 #1020903
>>1020900
Тайпхинты для правильно DI же , что бы ты точно знал что тебе передаётся именно тот объект
#67 #1020904
>>1020876
либо ajax либо POST GET с перезагрузкой страницы , то есть отсылаешь все данные с формы на какой то скрипт обрабатываешь и получаешь результат
#68 #1020908
>>1020902
Как я понял апач будет переадресовывать на файлы, какждый файл это хост? Чет костыль какой то получается. Может у меня нжинкс будет.
Может кто-нибудь знает как нормально сделать, что при запросе отрабатывала функция? Хотя бы в теории как это в php, какие есть функции и структуры для этого.
#69 #1020911
>>1020904
Не понятно. Вот открыл юзер в браузере www.host.ru/page, предположим это главная страница, значит GET запрос, как этот запрос обработать?
Не пойму зачем мне форма, если нужно гет запросы обрабатывать.
513 Кб, 3840x2160
#70 #1020914
Товарищи, покажите пожалуйста свой Utility.service. Только начал себе собирать, хочется интересных идей подсмотреть на будущее.

https://ideone.com/FWNxh4
#71 #1020920
>>1020911
а в этом смысле www.host.ru/page пофакту должно быть www.host.ru/page.php но всякие мод реврайты умеют обрезать эту .php или например www.host.ru/index.php/page тоже умеют обрезать index.php

скрипт выполняется скрипт из этого самого page.php
#72 #1020922
>>1020908
так то да , по нормальному у тебя должен быть всего 1 входная точка это index.php и она обработает запрос на тот же page но тогда гугли простейшие route pattern
#73 #1020925
>>1020911
RewriteEngine on
RewriteRule page page.php

RewriteRule vasya/pupkin/khuy/zalupkin user.php?id=1488

Там много есть почитать.
https://habrahabr.ru/company/sprinthost/blog/129560/
http://htaccess.ru/
Мне лично вот этот помог разобраться на примерах:
http://ruseller.com/lessons.php?id=1916
#74 #1020928
>>1019301 (OP)
Кто нибудь может объяснить что не так с php. Можно ли как в ноде или в других языках запустить php файл на выполнение и чтобы он обрабатывал все запросы? Если я правильно понял, то нельзя, из-за того что php отрабатывает код файла и умирает.
#75 #1020932
>>1020925
Спасибо анон. Просто я хожу разобраться с тем как работает интерпретатор php, и как устроена работа с http. Не хочу ставить апач. Мне не горит решать это, мне нужно понять как работает сам php. Похоже в строке запроса php может получать только параметры после знака ?, это вообще печаль, как жить то???
#76 #1020937
>>1020932
это если передавать GET запрос , есть же ещё POST запросы
http://phpfaq.ru/newbie/na_tanke
#77 #1020945
>>1020900

### Тайп хинты

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

Мануал: http://php.net/manual/ru/language.oop5.typehinting.php

Обрати внимание, что php7 усовершенствовал систему тайп-хинтов - теперь можно в их качестве указывать примитивные типы вроде int/string, а в php7.1 стало можно указывать тайп-хинт для возвращаемого функцией значения: https://habrahabr.ru/post/267799/ (увы, возможность вернуть null пока не реализовали, так что ждем)
#78 #1020947
>>1020932

Здесь нет нужной информации? http://php.net/manual/ru/reserved.variables.server.php

Когда приходит HTTP запрос, PHP анализирует его и кладет информацию о нем в суперглобальные переменные $_SERVER, $_GET, $_POST, $_COOKIE, $_FILES, $_ENV - они описаны в документации.

Все, что выводит программа (echo и подобными функциями), PHP отправляет в теле HTTP ответа.

На заголовки HTTP ответа можно повлиять с помощью функций header, set_cookie и некоторых ini-настроек.
#79 #1020950
>>1020928

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

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

С PHP все в порядке.

>>1020876

Непонятно, в чем суть вопроса. Создаешь PHP файл и обрабатываешь.

>>1020911

Формы тут не при чем. Если тебе не нужны красивые URL то просто создаешь файлы index.php, page.php и так далее. Если нужны, то перенаправляешь настройками веб-сервера все запросы на index.php и в нем уже анализируешь URL и вызываешь нужный обработчик.

Вообще-то у меня это описано в уроке для встроенного в PHP сервера, почему не прочел? https://github.com/codedokode/pasta/blob/master/soft/web-server.md

Ссылка в ОП посте стоит.
#80 #1020958
Что вот это вот?
PHP Fatal error: Uncaught Error: Call to undefined function mb_internal_encoding() in /home/hIt56v/prog.php:5

Везде, даже в самых простых вещах вылезает эта лажа на ideone. Я косячу или такова воля Божья?
#81 #1020961
>>1020958
Все mb_* это дополнительная, не обязательная библиотека, видно на ideone она не установлена , оттуда и проблемы.
http://php.net/manual/en/book.mbstring.php
#82 #1020973
>>1020961
Раньше работала. А что же делать?
215 Кб, 1021x681
#83 #1021013
какого хуя это говно не работает я хочу выбрать все iblock_element у которых есть VALUE 423 и 408 в iblock_element_property
SELECT
`iblock_element`.`ID` AS `ID`
FROM `b_iblock_element` `iblock_element`
LEFT JOIN `b_iblock_element_property` `iblock_element_property` ON `iblock_element_property`.`IBLOCK_ELEMENT_ID` = `iblock_element`.`ID`
WHERE (`iblock_element_property`.`VALUE` = '423') AND (`iblock_element_property`.`VALUE` = '408')
160 Кб, 850x850
#84 #1021017
>>1021013
неужели так? а если у меня пиздец сложная логика на каждое значение по джоину?
SELECT
`iblock_element`.`ID` AS `ID`
FROM `b_iblock_element` `iblock_element`
LEFT JOIN `b_iblock_element_property` `iblock_element_property` ON `iblock_element_property`.`IBLOCK_ELEMENT_ID` = `iblock_element`.`ID`
LEFT JOIN `b_iblock_element_property` `iblock_element_property2` ON `iblock_element_property2`.`IBLOCK_ELEMENT_ID` = `iblock_element`.`ID`
WHERE (`iblock_element_property`.`VALUE` = '423' AND `iblock_element_property2`.`VALUE` = '408')
#85 #1021018
>>1020111
Какой-то код это обычно всегда плюс, особенно если он хороший. Это дает возможность более адекватно оценить навыки кандидата.

> И вообще, есть тут те, кто работает пхп джуном? Что вы вообще делаете?


Бэкэнд часть я делаю.

пхп-джун
#86 #1021023
ОП, в пасте про студентов ссылка http://www.phpinfo.su/articles/practice/shablony_v_php.html стала битой (встречается в нескольких местах).

>>1020945
В PHP 7.1 есть возвращаемый тип void: https://3v4l.org/0kuHL

>>1020973
https://3v4l.org/

>>1020914
Можешь объяснить, чем плохи чистые функции, зачем городить эти Utility service? Юнит-тесты ты ведь всё равно писать не будешь. Какое-то слепое следование паттернам ради усложнений.

>>1020834
Хороший вопрос, тут есть ответ: http://www.php.su/articles/?cat=examples&page=014

>>1020857
Эти паттерны не отвечают на вопрос как увязывать HTML и PHP.
Задачи #87 #1021030
ОП, проверь задачи, пожалуйста

Изменение номера - https://ideone.com/KJxmSg
Автозамена - https://ideone.com/LaOqC8
Вывод email - https://ideone.com/NCD54g
Grammar Nazi - https://ideone.com/BR95EM
#88 #1021050
>>1021023
Мне казалось, всякий код должен быть на своем месте. Что если мне понадобится вот этот rand() в любом месте кода, я позову его из сервиса и всё.

Предлагаешь лучше просто собрать их все в файл и подключать прямо к window?
sage #89 #1021061
Напоминаю, что если вы хотите потрогать SQL, то почитайте
стайлгайд http://www.sqlstyle.guide/ru/
Инфа от ОПа https://github.com/codedokode/pasta/blob/master/db/databases.md
https://youtu.be/REbsxmE5h4M проектирование базы в MySQL Workbench
#90 #1021072
>>1020364

>Open folder побывал ?


Что это? Папка как проект? Мне нужен проводник по всей системе - в notepad++, например, он сделан идеально.

>разве в шторме не тоже самое ?


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

>кто то не может в json объекты ?


а че ты в дефолтном виндовом блокноте не кодишь? Не можешь в него?

>>1020370

>Я наоборот рад, что в нем нет этих дурацких кнопок


только выиграл от отсутствия того, что всегда можно отключить?
#91 #1021099
Привет всем.
Последнее время, перед собеседованием просят показать небольшой файл с примером кода.
Я хочу отправлять это: https://pastebin.com/F9Cv1eXm
Рейт ми, как говорится. Может чего подправить стоит?
#92 #1021170
>>1021072

>а че ты в дефолтном виндовом блокноте не кодишь? Не можешь в него?


м манёвры ? сравнить json объекты с кучей формочек ? имхо мне даже удобнее поправить в файле нежели бегать по файл -> правка -> опция залупки
#93 #1021184
>>1021170

Это просто дело вкуса, я думаю. Кто-то любит кнопочки, кто-то конфиги. У конфигов в сравнении с GUI масса преимуществ - ими можно делиться, публиковать, бекапить, делать поиск, генерировать программно, но из минусов - нужно сначала потратить время на изучение.

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

Некоторые редакторы пытаются взять лучшее из обоих миров - давая и GUI и конфиг в XML, вроде eclipse, но по моим ощущениям, настройки у них совсем уж навороченные.
#94 #1021195
>>1021018

>Бэкэнд часть я делаю


это понятно, хотелось бы подробней. Прямо со старту ты пришел джуном и на тебя весь бэкэнд свалили?
#95 #1021262
Это снова https://github.com/tsubaku
Я поработал над указанными ошибками, но исправил не все.
Во-первых, что исправил:

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


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

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


Убрал

>Тут код отформатирован ужасно: https://github.com/tsubaku/flights/blob/master/submit.php


Переформатировал. Теперь правильно? Перевёл в camelCase названия пхп-функций. Переменные не переводил, их слишком много.

>Если ты отдаешь JSON, то тип ответа должен быть application/json, не надо изобретать свои стандарты. И логично заголовки ставить не в начале скрипта, а перед отдачей самого JSON


Заменил text/plain на application/json везде, где возвращается JSON. Перенёс хидеры к echo json_encode. Нужны ли хидеры там, где только echo? А там, где вообще ничего нет, просто вызов функции?

> $pass = md5(md5(trim($pass)));


>Безопаснее использовать соленый хеш, как описано в моем уроке https://github.com/codedokode/pasta/blob/master/security/password-hashing.md


Заменил md5 на password_hash/password_verify

>При загрузке картинок нет проверки типа файла, человек загрузит .png или .txt, а ты его переименуешь в .jpg например.


Сделал проверку и корректное расширение для jpg, png, gif, остальным типам скрипт отказывает в загрузке.

> https://github.com/tsubaku/flights/blob/master/show_list_clients.php#L10


> while(list ($key, $val) = each ($_POST)){


>Это давно устарело, нужно использовать foreach тут


Переделал

>Название функции должно начинаться с глагола, то есть не protection, а redirectIfNoPrivileges(...)


Заменил на verifyAuthorization

> <a href='#' class='a_button_delete'


Ссылка должна куда-то вести. Для создания кнопки есть тег button.
Оформил в виде button. Немного поехала вёрстка кнопки, потом поправить.

> while ($i <= count($ru_rows_array)-1){


Тут нужно использовать foreach. Ты сишник наверно? Не надо тянуть плохие практики из Си в язык, где есть foreach.
Заменил в нескольких местах count на foreach

> if (is_null($_COOKIE['id'])


Это неправильно и вызовет ошибку, если в массиве нет ключа 'id'. У тебя наверно включено игнорирование предупреждений, или же ты не смотришь в логи ошибок, раз этого не видишь. Нужно использовать array_key_exists или isset здесь.
Хм, никаких ошибок в логах. Хотя, может быть я просто проверил не все случаи. Заменил is_null на empty.
https://github.com/tsubaku/flights/blob/master/functions.php#L187

> $info = getimagesize($path);


>Тут не проверяется вариант, когда функция вернет вместо массива false.


Добавил проверку

Что исправил с оговорками:

>В шаблонах у тебя вроде бы есть повторяющиеся куски - шапка страницы.


Шапки немного повторяются, но всё же есть различия и не думаю, что сливать общие части имеет смысл. Плюс, так их легче воспринимать. Я разделил скрипт core.js, вынеся в отдельные файлы скрипты менеджера и охранника, а в шаблонах убрал загрузку лишних скриптов.

>https://github.com/tsubaku/flights/blob/master/index.php#L10


> if ($user_level == 9) {


>Тут нужно ииспользовать константу с понятным названием вместо цифры


> $level = 'manager';


>И тот тоже желательно константу.


Немного переписал функцию проверки, теперь она возвращает ид, уровень доступа и фамилию. Проверку оставил по тому же условию.

> echo "<br />";


В HTML слеш в конце тега не ставится, в отличие от XML/XHTML.
Так у меня как раз XHTML
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

> https://github.com/tsubaku/flights/blob/master/functions.php#L292


> header("Location: status_codes.php?result=403");


Если ты хочешь отдать код ответа HTTP, то надо его отдавать сразу. Потому что редирект - это код вроде 302. То есть ты вместо отдачи кода 403 отдаешь код 302 в ответ на запрос. И вместо "доступ запрещен" говоришь "страница переехала на другой адрес".
Я так и не понял, как сделать так, чтобы браузер при ошибках показывал суть ошибки. Ну или хотя бы стандартные коды. Так что просто заменил все редиректы на header("Location: login.php");

Что не удалось:

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


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

>Тут https://github.com/tsubaku/flights/blob/master/show_list_clients.php в одном файле смешана логика и вывод данных в HTML, почитай про шаблоны http://web.archive.org/web/20161119062218/www.phpinfo.su/articles/practice/shablony_v_php.html


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

>https://github.com/tsubaku/flights/blob/master/functions.php#L5


>Тут слишком сложная функция с слишком большой глубиной отступов


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

Что скажете?
#95 #1021262
Это снова https://github.com/tsubaku
Я поработал над указанными ошибками, но исправил не все.
Во-первых, что исправил:

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


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

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


Убрал

>Тут код отформатирован ужасно: https://github.com/tsubaku/flights/blob/master/submit.php


Переформатировал. Теперь правильно? Перевёл в camelCase названия пхп-функций. Переменные не переводил, их слишком много.

>Если ты отдаешь JSON, то тип ответа должен быть application/json, не надо изобретать свои стандарты. И логично заголовки ставить не в начале скрипта, а перед отдачей самого JSON


Заменил text/plain на application/json везде, где возвращается JSON. Перенёс хидеры к echo json_encode. Нужны ли хидеры там, где только echo? А там, где вообще ничего нет, просто вызов функции?

> $pass = md5(md5(trim($pass)));


>Безопаснее использовать соленый хеш, как описано в моем уроке https://github.com/codedokode/pasta/blob/master/security/password-hashing.md


Заменил md5 на password_hash/password_verify

>При загрузке картинок нет проверки типа файла, человек загрузит .png или .txt, а ты его переименуешь в .jpg например.


Сделал проверку и корректное расширение для jpg, png, gif, остальным типам скрипт отказывает в загрузке.

> https://github.com/tsubaku/flights/blob/master/show_list_clients.php#L10


> while(list ($key, $val) = each ($_POST)){


>Это давно устарело, нужно использовать foreach тут


Переделал

>Название функции должно начинаться с глагола, то есть не protection, а redirectIfNoPrivileges(...)


Заменил на verifyAuthorization

> <a href='#' class='a_button_delete'


Ссылка должна куда-то вести. Для создания кнопки есть тег button.
Оформил в виде button. Немного поехала вёрстка кнопки, потом поправить.

> while ($i <= count($ru_rows_array)-1){


Тут нужно использовать foreach. Ты сишник наверно? Не надо тянуть плохие практики из Си в язык, где есть foreach.
Заменил в нескольких местах count на foreach

> if (is_null($_COOKIE['id'])


Это неправильно и вызовет ошибку, если в массиве нет ключа 'id'. У тебя наверно включено игнорирование предупреждений, или же ты не смотришь в логи ошибок, раз этого не видишь. Нужно использовать array_key_exists или isset здесь.
Хм, никаких ошибок в логах. Хотя, может быть я просто проверил не все случаи. Заменил is_null на empty.
https://github.com/tsubaku/flights/blob/master/functions.php#L187

> $info = getimagesize($path);


>Тут не проверяется вариант, когда функция вернет вместо массива false.


Добавил проверку

Что исправил с оговорками:

>В шаблонах у тебя вроде бы есть повторяющиеся куски - шапка страницы.


Шапки немного повторяются, но всё же есть различия и не думаю, что сливать общие части имеет смысл. Плюс, так их легче воспринимать. Я разделил скрипт core.js, вынеся в отдельные файлы скрипты менеджера и охранника, а в шаблонах убрал загрузку лишних скриптов.

>https://github.com/tsubaku/flights/blob/master/index.php#L10


> if ($user_level == 9) {


>Тут нужно ииспользовать константу с понятным названием вместо цифры


> $level = 'manager';


>И тот тоже желательно константу.


Немного переписал функцию проверки, теперь она возвращает ид, уровень доступа и фамилию. Проверку оставил по тому же условию.

> echo "<br />";


В HTML слеш в конце тега не ставится, в отличие от XML/XHTML.
Так у меня как раз XHTML
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

> https://github.com/tsubaku/flights/blob/master/functions.php#L292


> header("Location: status_codes.php?result=403");


Если ты хочешь отдать код ответа HTTP, то надо его отдавать сразу. Потому что редирект - это код вроде 302. То есть ты вместо отдачи кода 403 отдаешь код 302 в ответ на запрос. И вместо "доступ запрещен" говоришь "страница переехала на другой адрес".
Я так и не понял, как сделать так, чтобы браузер при ошибках показывал суть ошибки. Ну или хотя бы стандартные коды. Так что просто заменил все редиректы на header("Location: login.php");

Что не удалось:

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


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

>Тут https://github.com/tsubaku/flights/blob/master/show_list_clients.php в одном файле смешана логика и вывод данных в HTML, почитай про шаблоны http://web.archive.org/web/20161119062218/www.phpinfo.su/articles/practice/shablony_v_php.html


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

>https://github.com/tsubaku/flights/blob/master/functions.php#L5


>Тут слишком сложная функция с слишком большой глубиной отступов


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

Что скажете?
#96 #1021332
>>1020900
http://ideone.com/lI5U84
Кто то может подсказать почему не работает функция увольнения. 168 Строка начала функции, в конце неё делаю ансет трём работникам. А в итоге все равно 101 работник.
#97 #1021359
>>1021332

>get_Workers_For_Destruction


:)

http://php.net/unset

>// удаляем один элемент массива


>unset($array['element']);



Больше Разрушителей в энтот тред!
#98 #1021421
ОП, какие есть способы оптимизировать вставку большого количества данных в БД, при условии использования доктрины? Я нагуглил это: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/batch-processing.html#bulk-inserts
Ещё что-то помню про отключение проверки внешних ключей на уровне СУБД. Это вопрос по поводу парсера старых/новых тредов: https://github.com/someApprentice/phpClub/tree/master/tests/ThreadParser
Прошу не проверять xpath-запросы, они скорее всего будут переписаны.
#99 #1021432
Как сделать конструктор лэндига для вордпресса в виде плагина с драг и дропом секций?
#100 #1021439
Кто-то под линупсом сидит? Все хочу перекатиться с винды, друг советует mint, посмотрел скрины - мне понравилось.

Удобно ли пхп-макаке кодить под линуксом? Есть некий аналог open server? Чтобы можно было легко переключаться между версиями апача, пхп, майэскьюэль без дрочки в консоле?

И раз уж спросил. я не шарю в линуксе и как там все устроено, поэтому вопрос возможно тупой, но Можно переустановить систему например с минт на убунту или наоборот без потери софтины и ее настроек?
#101 #1021482
>>1021439
перекатывайся в Debian, мне уже четвертый месяц нрааится. если будешь переустанавливать, то софт тоже постигнет сия участь.
просто приготовься к ебле с линухом(рано или поздно заебешься с какой нибудь проблемой)
#102 #1021504
>>1021439
Без консоли в линуксе никак, но в один момент ты поймешь, что это не минус, а преимущество. Возня есть, но если ты все поставил как надо, то оно будет стоят как надо годами. Алсо, в винде тоже закидонов хватает. Во многих ситуациях, где в линуксе надо прописать одну команду в консоли, которая гарантировано сработает, для винды надо скачивать какой-нибудь экзешник и молиться, чтобы все встало как надо.
#103 #1021505
>>1021439
Если есть деньги, то можешь купить мак. Это считай линукс, только удобный и красивый. Там тебе и МАМП будет, и нжинкс будет в родной среде вариться, и права доступа к файлам по человечески. В общем, все плюсы линукса в приятной оболочке.
#104 #1021509
>>1021439
хз что такое опенсервер, но по описанию унреал подходит генту
немного поебаться с установкой, если ты вообще не шаришь (но нужно уметь читать)
всякое лишнее говно супер легко убирается юз флагами
переключение между пхп\руби\питон\ядрами\видеодрайверами\почти-чем-угодно за 2 клика типа:
>eselect php list

>eselect php set 2


сам на линуксе <год, генту единственный юзабельный дистр
#105 #1021526
>>1021482

>если будешь переустанавливать, то софт тоже постигнет сия участь


да ну нах. Если я захочу перебить систему с линукса на линукс, то софтине пизда?

>Без консоли в линуксе никак


Я умею в консоль и понимаю, что пользоваться консолью это конечно круто, но я в рот ебал эти понты, когда можно два раза мышкой кликнуть
>>1021509
Я не шарю. Для меня дистрибутивы линукса отличаются только внешним видом
#106 #1021580
>>1021526

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


Я так понимаю, про композер ты даже и не слышал?
#107 #1021590
>>1021580
Причем тут композер?
#108 #1021591
>>1021590
Имеет отношение к понтам.
#109 #1021594
>>1021591
это я понял, но как он поможет мне также быстро сменить версию пхп или апача, как я делаю это в опен сервере?
#110 #1021609
>>1021594
меньше всего ебли из коробки с этим в генте
ставь генту
#111 #1021613
>>1021594
= тому сколько ебли поставить memcache в опенсервере , алсо для смены можно сделать скрипт который так же по запуску будет менять как и 2 щелчка в GUI
#112 #1021649
>>1021613
>>1021609
Спасибо за бесполезные советы, ребят
#113 #1021671
Как можно удалить элемент массива по ключу?
unset($arrays[1]);?
#114 #1021684
>>1021649
иди на форточки и ебись со своим дерьмом заебал
#115 #1021688
>>1021684
спасибо, добра
#116 #1021692
>>1021359
Спасибо.

>>1020900

>ОП проверь плз. Задача про компанию вектор


Теперь еще с одной антикризисной мерой.
http://ideone.com/4zGFfs
#117 #1021761
>>1021439
Линукс > Виндовс для разработчика
Бери mint с ним будет меньше всего мороки
С gentu тебя тролят, mac оверпрайс

Для смены версий пхп и прочего хорошо бы освоить вагрант или докер, т.к. модно, молодёжно и пригодится
#118 #1021803
>>1021692

>Departament


Незачет тебе по английскому.
#119 #1021821
>>1021692

> add_departament


> get_Count_Workers


Что за нестандартный стиль названий функций? PSR рекомендует camelCase для методов:

- https://svyatoslav.biz/misc/psr_translation/#_PSR-1
- https://svyatoslav.biz/misc/psr_translation/#_PSR-2

> public function print_Info()


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

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

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

> //Cократить в каждом департаменте 40% (округляя в большую сторону) инженеров,


> //преимущественно самого низкого ранга.


> public function Destruction_Workers


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

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

Гораздо аккуратнее будет если Компания будет заведовать списком департаментов, а специфичные вещи вроде "найти и уволить 40% рабочих" будут в отдельном классе для антикризисных мер.

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

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

> Destruction_Workers


Имена функций начинаются с глаголов, сделатьЧтоТо

> public function add_Workers($count, $rank, $proffesion, $is_Head)


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

> public function get_Workers_And_Destruction($count_in_percent,$proffesion)


Тут функция просто создана методом копирования кода. Так не годится. Нужно убрать повторяющийся код.

Такой код тяжело читать, так как трудно понять, чем именно один блок кода отличается от другого.

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

> PHP Notice: Undefined variable: sum_salary in /home/UH8YEW/prog.php on line 139


> PHP Notice: Undefined variable: sum_pages in /home/UH8YEW/prog.php on line 155


> PHP Notice: Undefined variable: sum_salary in /home/UH8YEW/prog.php on line 139


> PHP Notice: Undefined variable: sum_coffee in /home/UH8YEW/prog.php on line 147


> PHP Notice: Undefined variable: sum_pages in /home/UH8YEW/prog.php on line 155

#119 #1021821
>>1021692

> add_departament


> get_Count_Workers


Что за нестандартный стиль названий функций? PSR рекомендует camelCase для методов:

- https://svyatoslav.biz/misc/psr_translation/#_PSR-1
- https://svyatoslav.biz/misc/psr_translation/#_PSR-2

> public function print_Info()


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

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

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

> //Cократить в каждом департаменте 40% (округляя в большую сторону) инженеров,


> //преимущественно самого низкого ранга.


> public function Destruction_Workers


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

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

Гораздо аккуратнее будет если Компания будет заведовать списком департаментов, а специфичные вещи вроде "найти и уволить 40% рабочих" будут в отдельном классе для антикризисных мер.

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

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

> Destruction_Workers


Имена функций начинаются с глаголов, сделатьЧтоТо

> public function add_Workers($count, $rank, $proffesion, $is_Head)


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

> public function get_Workers_And_Destruction($count_in_percent,$proffesion)


Тут функция просто создана методом копирования кода. Так не годится. Нужно убрать повторяющийся код.

Такой код тяжело читать, так как трудно понять, чем именно один блок кода отличается от другого.

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

> PHP Notice: Undefined variable: sum_salary in /home/UH8YEW/prog.php on line 139


> PHP Notice: Undefined variable: sum_pages in /home/UH8YEW/prog.php on line 155


> PHP Notice: Undefined variable: sum_salary in /home/UH8YEW/prog.php on line 139


> PHP Notice: Undefined variable: sum_coffee in /home/UH8YEW/prog.php on line 147


> PHP Notice: Undefined variable: sum_pages in /home/UH8YEW/prog.php on line 155

#120 #1021823
>>1021684

Не надо добавлять бесполезные посты в этот тред

>>1021671

да

>>1021505

Это не линукс, например, там нет неймспейсов тех же.

>>1021439

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


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

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


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

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

Насчет разных версий PHP - в линуксе есть штука https://github.com/phpbrew/phpbrew которая умеет скачивать и компилировать нужные версии PHP, а потом переключать переменные окружения, чтобы их использовать. Разумеется, тебе придется изучить, как она работает. А так, большинство версий линукса не поддерживают стандартным способом установку 2 версий одной программы.

>>1021482

Только Debian лучше ставить Testing, а то в Stable софт стабильный, но старый.

>>1021432

В смысле, "как"? Не очень понятно, как ответить на твой вопрос. Проектируешь, как это должно работать, и реализуешь.
#120 #1021823
>>1021684

Не надо добавлять бесполезные посты в этот тред

>>1021671

да

>>1021505

Это не линукс, например, там нет неймспейсов тех же.

>>1021439

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


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

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


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

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

Насчет разных версий PHP - в линуксе есть штука https://github.com/phpbrew/phpbrew которая умеет скачивать и компилировать нужные версии PHP, а потом переключать переменные окружения, чтобы их использовать. Разумеется, тебе придется изучить, как она работает. А так, большинство версий линукса не поддерживают стандартным способом установку 2 версий одной программы.

>>1021482

Только Debian лучше ставить Testing, а то в Stable софт стабильный, но старый.

>>1021432

В смысле, "как"? Не очень понятно, как ответить на твой вопрос. Проектируешь, как это должно работать, и реализуешь.
#121 #1021824
>>1021421

Вообще, в MySQL есть раздел мануала на эту тему https://dev.mysql.com/doc/refman/5.5/en/optimizing-innodb-bulk-data-loading.html

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

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

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

Пример, который приведен в мануале, использует flush для группы записей, чтобы вставлять N записей одной транзакцией, и clear, чтобы очистить память (так как Доктрина хранит ссылки на все управляемые ей объекты и потребление памяти без этого будет быстро расти, а также будет змедляться flush, так как он обходит все объекты). Недостаток clear в том,что он убирает все объекты из-под управления доктрины (то есть делает на них detach) и его нельзя применять, если какой-то другой код держит ссылки на эти объекты, и планирует дальше с ними работать. То есть clear годится только для каких-то скриптов импорта, но его не стоит использовать в середине приложения, так как он сломает загруженные ранее сущности.
#122 #1021921
>>1021761
В генте быстрая смена версий пхп и прочего из коробки в виде системы слотов тащемта, не пизди если не шаришь. Гента ультрагибкая и удобная штука, ее можно подогнать под любые задачи, просто порог вхождения несколько выше чем у дебиана например. Если не гента, то только дебиан, все эти коляски в виде его форков типа минта или там убунты вообще не нужны.
#123 #1021975
>>1021195
Пришел джуном, поставили в парное программирование с более опытным специалистом, начал делать АПИ для одной системы. Работаю с фреймворком, оперативными хранилищами, серверами очереди, и очевидно с БД. Сейчас все примерно так же, только работаю один.
#124 #1021978
>>1021262

https://github.com/tsubaku

Сначала отвечу на пост:

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


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

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

> Переформатировал. Теперь правильно?


Не очень:

https://github.com/tsubaku/flights/blob/master/login.php
Тут нужно убрать самый первый отступ (после <?php), то есть строка require_once('./core/php/functions.php'); идет без отступа. Для отступов лучше использовать 4 пробела, а не таб.

https://github.com/tsubaku/flights/blob/master/core/php/submit.php
Тут отступы вообще разные. Почему отступ в строке 22 - 8 пробелов? должно быть 4. И почему там так много пустых строк? Пока что плохо.

Рекомендации PSR можно почитать тут в переводе

- https://svyatoslav.biz/misc/psr_translation/#_PSR-1
- https://svyatoslav.biz/misc/psr_translation/#_PSR-2

Код можно форматировать автоматически, через сайт или IDE, вот ссылка https://gist.github.com/codedokode/8759492

Не понимаю, в чем проблема прогнать файл через сайт или нажать комбинацию клавиш в IDE.

> Нужны ли хидеры там, где только echo? А там, где вообще ничего нет, просто вызов функции?


header логично ставить радом с echo так как они относятся к одной задаче, и header должен срабатывать только когда выводится JSON. А когда ты их ставишь в разных местах, то это во-первых нелогично (мы сначала сообщаем, что будет выведен JSON, а только потом где-то в другом месте его выводим), во-вторых может вести к ошибкам, когда выводится header с application/json а потом выводится не JSON, а обычный текст или например сообщение об ошибке.

То есть нелогично функцию вывода JSON разделять на 2 части и разбрасывать их в разные места кода.

Кстати, тут тоже нелогично: https://github.com/tsubaku/flights/blob/master/core/php/show_list_clients.php
В заголовках указан тип text/plain, а затем идет вывод HTML кода.

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

> Сделал проверку и корректное расширение для jpg, png, gif, остальным типам скрипт отказывает в загрузке.


Пока не очень удачно. Тут https://github.com/tsubaku/flights/blob/master/core/php/submit.php#L25 ты проверяешь тип файла, который берется из тела POST запроса и указывается браузером. Но браузер может там указать что угодно. Надежднее проверить расширение.

>> if (is_null($_COOKIE['id'])


>> Это неправильно и вызовет ошибку, если в массиве нет ключа 'id'.


> Хм, никаких ошибок в логах.


Вот пример, показывающий ошибку: http://ideone.com/bMeVWL

Возможно у тебя в php.ini включено игнорирование ошибок с помощью настройки error_reporting (зачем так делать??) или отключено их логгирование. Или у тебя всегда есть эта кука.

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


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

> Я так и не понял, как сделать так, чтобы браузер при ошибках показывал суть ошибки. Ну или хотя бы стандартные коды. Так что просто заменил все редиректы на header("Location: login.php");


Ты выводишь HTTP заголовок, затем тело страницы. Что тут сложного?

header("HTTP/1.0 500 Internal Error");
echo "Everything is broken, sorry\n";
die();

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

> Выделил папку core, в неё перенёс все НЕ публичные пхп, шаблоны и закачиваемые фотографии. Но как закрыть её, не понимаю.


У сервера есть такая настройка, как "корневая папка" (в Апаче она называется document root, в нгинксе root). Ты создаешь у себя папку public и в настройках веб-севрера прописываешь путь к ней как document root, например в Апаче:

DocumentRoot /var/www/example.com/public/

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

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


Элементарно это делается. В скрипте-контроллере ты подготавливаешь данные:

$guards = getGuardsList();
// подключаем шаблон
require 'templates/guards.phtml';

В шаблоне формируешь и выводишь HTML страницу:

<?php require __DIR__ . '/header.php'; ?>

<h1>Охранники</h1>
<ul>
<?php foreach ($guards as $guard): ?>
<li><?= htmlspecialchars($guard['name']) ?></li>
<?php endforeach ?>
</ul>

<?php require __DIR__ . '/footer.php'; ?>

> https://github.com/tsubaku/flights/blob/master/core/php/functions.php#L224


> unset($row_content); // разорвать ссылку на последний элемент


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

Вот еще проблемное место:

> function showTable($year, $month)


> ...


> $stmt = $pdo->query('INSERT INTO flights () VALUES()'); //Добавляем пустую строку


Функция вывода таблицы не должна ее модифицировать.

> https://github.com/tsubaku/flights/blob/master/core/php/write_in_table.php


Тут нечитаемая стена кода, надо выносить из нее отдельные функции.

> Вопрос про функцию showTable()


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


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

При этом часть кода можно выносить в отдельные функции. Вот например вначале идет кусок лапши, получающий список рейсов между 2 датами. Его легко вынести в отдельную функцию:

$flights = getFlightsInRange($fromDate, $toDate);

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

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

После того, как все данные выбраны в переменные, вызываем шаблон для вывода HTML кода.

HTML код выводить, как у тебя, с помощью echo, очень неудобно и неэффективно.

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

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

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

Соответственно, сейчас тебе надо работать над разделением:

- вынести весь HTML код в шаблоны
- вынести весь SQL-код в функции в отдельном файле или файлах, то есть сделать отдельный слой доступа к базе данных, а не размазывать это по всему коду

Я еще раз напомню, что у нас в ОП посте есть задача на список студентов. Хоть она и называется "задача", но там много комментариев и по сути это что-то вроде сборника полезных советов по написанию приложений с формами и таблицами. То есть приложение того же типа, что и у тебя. И тебе желательно найти время ее прочитать, так как у меня нет желания пересказывать тут все ее содержимое по второму разу.
#124 #1021978
>>1021262

https://github.com/tsubaku

Сначала отвечу на пост:

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


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

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

> Переформатировал. Теперь правильно?


Не очень:

https://github.com/tsubaku/flights/blob/master/login.php
Тут нужно убрать самый первый отступ (после <?php), то есть строка require_once('./core/php/functions.php'); идет без отступа. Для отступов лучше использовать 4 пробела, а не таб.

https://github.com/tsubaku/flights/blob/master/core/php/submit.php
Тут отступы вообще разные. Почему отступ в строке 22 - 8 пробелов? должно быть 4. И почему там так много пустых строк? Пока что плохо.

Рекомендации PSR можно почитать тут в переводе

- https://svyatoslav.biz/misc/psr_translation/#_PSR-1
- https://svyatoslav.biz/misc/psr_translation/#_PSR-2

Код можно форматировать автоматически, через сайт или IDE, вот ссылка https://gist.github.com/codedokode/8759492

Не понимаю, в чем проблема прогнать файл через сайт или нажать комбинацию клавиш в IDE.

> Нужны ли хидеры там, где только echo? А там, где вообще ничего нет, просто вызов функции?


header логично ставить радом с echo так как они относятся к одной задаче, и header должен срабатывать только когда выводится JSON. А когда ты их ставишь в разных местах, то это во-первых нелогично (мы сначала сообщаем, что будет выведен JSON, а только потом где-то в другом месте его выводим), во-вторых может вести к ошибкам, когда выводится header с application/json а потом выводится не JSON, а обычный текст или например сообщение об ошибке.

То есть нелогично функцию вывода JSON разделять на 2 части и разбрасывать их в разные места кода.

Кстати, тут тоже нелогично: https://github.com/tsubaku/flights/blob/master/core/php/show_list_clients.php
В заголовках указан тип text/plain, а затем идет вывод HTML кода.

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

> Сделал проверку и корректное расширение для jpg, png, gif, остальным типам скрипт отказывает в загрузке.


Пока не очень удачно. Тут https://github.com/tsubaku/flights/blob/master/core/php/submit.php#L25 ты проверяешь тип файла, который берется из тела POST запроса и указывается браузером. Но браузер может там указать что угодно. Надежднее проверить расширение.

>> if (is_null($_COOKIE['id'])


>> Это неправильно и вызовет ошибку, если в массиве нет ключа 'id'.


> Хм, никаких ошибок в логах.


Вот пример, показывающий ошибку: http://ideone.com/bMeVWL

Возможно у тебя в php.ini включено игнорирование ошибок с помощью настройки error_reporting (зачем так делать??) или отключено их логгирование. Или у тебя всегда есть эта кука.

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


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

> Я так и не понял, как сделать так, чтобы браузер при ошибках показывал суть ошибки. Ну или хотя бы стандартные коды. Так что просто заменил все редиректы на header("Location: login.php");


Ты выводишь HTTP заголовок, затем тело страницы. Что тут сложного?

header("HTTP/1.0 500 Internal Error");
echo "Everything is broken, sorry\n";
die();

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

> Выделил папку core, в неё перенёс все НЕ публичные пхп, шаблоны и закачиваемые фотографии. Но как закрыть её, не понимаю.


У сервера есть такая настройка, как "корневая папка" (в Апаче она называется document root, в нгинксе root). Ты создаешь у себя папку public и в настройках веб-севрера прописываешь путь к ней как document root, например в Апаче:

DocumentRoot /var/www/example.com/public/

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

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


Элементарно это делается. В скрипте-контроллере ты подготавливаешь данные:

$guards = getGuardsList();
// подключаем шаблон
require 'templates/guards.phtml';

В шаблоне формируешь и выводишь HTML страницу:

<?php require __DIR__ . '/header.php'; ?>

<h1>Охранники</h1>
<ul>
<?php foreach ($guards as $guard): ?>
<li><?= htmlspecialchars($guard['name']) ?></li>
<?php endforeach ?>
</ul>

<?php require __DIR__ . '/footer.php'; ?>

> https://github.com/tsubaku/flights/blob/master/core/php/functions.php#L224


> unset($row_content); // разорвать ссылку на последний элемент


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

Вот еще проблемное место:

> function showTable($year, $month)


> ...


> $stmt = $pdo->query('INSERT INTO flights () VALUES()'); //Добавляем пустую строку


Функция вывода таблицы не должна ее модифицировать.

> https://github.com/tsubaku/flights/blob/master/core/php/write_in_table.php


Тут нечитаемая стена кода, надо выносить из нее отдельные функции.

> Вопрос про функцию showTable()


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


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

При этом часть кода можно выносить в отдельные функции. Вот например вначале идет кусок лапши, получающий список рейсов между 2 датами. Его легко вынести в отдельную функцию:

$flights = getFlightsInRange($fromDate, $toDate);

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

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

После того, как все данные выбраны в переменные, вызываем шаблон для вывода HTML кода.

HTML код выводить, как у тебя, с помощью echo, очень неудобно и неэффективно.

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

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

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

Соответственно, сейчас тебе надо работать над разделением:

- вынести весь HTML код в шаблоны
- вынести весь SQL-код в функции в отдельном файле или файлах, то есть сделать отдельный слой доступа к базе данных, а не размазывать это по всему коду

Я еще раз напомню, что у нас в ОП посте есть задача на список студентов. Хоть она и называется "задача", но там много комментариев и по сути это что-то вроде сборника полезных советов по написанию приложений с формами и таблицами. То есть приложение того же типа, что и у тебя. И тебе желательно найти время ее прочитать, так как у меня нет желания пересказывать тут все ее содержимое по второму разу.
#125 #1021991
>>1021978

>https://github.com/tsubaku/flights/blob/master/login.php


>Тут нужно убрать самый первый отступ (после <?php), то есть строка require_once('./core/php/functions.php'); идет без отступа. Для отступов лучше использовать 4 пробела, а не таб.


Блин, про manager.php, index.php, guard.php и login.php я забыл. Сделаю.

>https://github.com/tsubaku/flights/blob/master/core/php/submit.php


>Тут отступы вообще разные. Почему отступ в строке 22 - 8 пробелов? должно быть 4. И почему там так много пустых строк? Пока что плохо.


Хм, submit.php тоже забыл. Странно. Вроде я все файлы по очереди переформатировал.

>Код можно форматировать автоматически, через сайт или IDE, вот ссылка https://gist.github.com/codedokode/8759492


Через него и делал.

>То есть нелогично функцию вывода JSON разделять на 2 части и разбрасывать их в разные места кода.


Не понял. Там же только одна команда вывода json. В каком смысле "разбивать на 2 части"?

>Кстати, тут тоже нелогично:


>https://github.com/tsubaku/flights/blob/master/core/php/show_list_clients.php


>В заголовках указан тип text/plain, а затем идет вывод HTML кода.


А html - это не text/plain?

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


Хорошо, функцию сделаю. Но вот именно проблему копипасты не понимаю. Если что-то работает, и работает правильно, то как это переписывать?

>Но браузер может там указать что угодно. Надежднее проверить расширение.


Я гуглил на эту тему и когда кто-то в похожей ситуации делал проверку по расширению, ему так же указывали, что "клиент может послать что угодно, надёжнее проверять по типу". Олсо, не всё ли равно? Законопослушный юзер отправить jpg под видом jpg и всё будет нормально. А незаконопослушный отправит какую-нибудь НЁХ, но сервер переименует её в jpg и при обращении просто не откроет.
>>1021978

>Возможно у тебя в php.ini включено игнорирование ошибок с помощью настройки error_reporting (зачем так делать??) или отключено их логгирование. Или у тебя всегда есть эта кука.


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

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


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

>Ты выводишь HTTP заголовок, затем тело страницы. Что тут сложного?


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


А, так это пишется вручную. Теперь понятно. А редирект для удобства юзера.

>и в настройках веб-севрера прописываешь путь к ней как document root, например в Апаче:


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

>Элементарно это делается. В скрипте-контроллере ты подготавливаешь данные:


Я попробую.

> unset($row_content); // разорвать ссылку на последний элемент


>Эта строчка вообще смысла не несет


Блин, точно.

> function showTable($year, $month)


> ...


> $stmt = $pdo->query('INSERT INTO flights () VALUES()'); //Добавляем пустую строку


>Функция вывода таблицы не должна ее модифицировать.


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

> https://github.com/tsubaku/flights/blob/master/core/php/write_in_table.php


>Тут нечитаемая стена кода, надо выносить из нее отдельные функции.


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

Остальные комментарии тоже приму к сведению.

>Я еще раз напомню, что у нас в ОП посте есть задача на список студентов.


Я с ней ознакомился. Кое-что применил, что смог. Мне кажется, у меня мозги слишком крепко пропитаны админством и сложно уловить подход программистов. Но я буду продолжать переписывать код и дальше.
#125 #1021991
>>1021978

>https://github.com/tsubaku/flights/blob/master/login.php


>Тут нужно убрать самый первый отступ (после <?php), то есть строка require_once('./core/php/functions.php'); идет без отступа. Для отступов лучше использовать 4 пробела, а не таб.


Блин, про manager.php, index.php, guard.php и login.php я забыл. Сделаю.

>https://github.com/tsubaku/flights/blob/master/core/php/submit.php


>Тут отступы вообще разные. Почему отступ в строке 22 - 8 пробелов? должно быть 4. И почему там так много пустых строк? Пока что плохо.


Хм, submit.php тоже забыл. Странно. Вроде я все файлы по очереди переформатировал.

>Код можно форматировать автоматически, через сайт или IDE, вот ссылка https://gist.github.com/codedokode/8759492


Через него и делал.

>То есть нелогично функцию вывода JSON разделять на 2 части и разбрасывать их в разные места кода.


Не понял. Там же только одна команда вывода json. В каком смысле "разбивать на 2 части"?

>Кстати, тут тоже нелогично:


>https://github.com/tsubaku/flights/blob/master/core/php/show_list_clients.php


>В заголовках указан тип text/plain, а затем идет вывод HTML кода.


А html - это не text/plain?

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


Хорошо, функцию сделаю. Но вот именно проблему копипасты не понимаю. Если что-то работает, и работает правильно, то как это переписывать?

>Но браузер может там указать что угодно. Надежднее проверить расширение.


Я гуглил на эту тему и когда кто-то в похожей ситуации делал проверку по расширению, ему так же указывали, что "клиент может послать что угодно, надёжнее проверять по типу". Олсо, не всё ли равно? Законопослушный юзер отправить jpg под видом jpg и всё будет нормально. А незаконопослушный отправит какую-нибудь НЁХ, но сервер переименует её в jpg и при обращении просто не откроет.
>>1021978

>Возможно у тебя в php.ini включено игнорирование ошибок с помощью настройки error_reporting (зачем так делать??) или отключено их логгирование. Или у тебя всегда есть эта кука.


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

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


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

>Ты выводишь HTTP заголовок, затем тело страницы. Что тут сложного?


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


А, так это пишется вручную. Теперь понятно. А редирект для удобства юзера.

>и в настройках веб-севрера прописываешь путь к ней как document root, например в Апаче:


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

>Элементарно это делается. В скрипте-контроллере ты подготавливаешь данные:


Я попробую.

> unset($row_content); // разорвать ссылку на последний элемент


>Эта строчка вообще смысла не несет


Блин, точно.

> function showTable($year, $month)


> ...


> $stmt = $pdo->query('INSERT INTO flights () VALUES()'); //Добавляем пустую строку


>Функция вывода таблицы не должна ее модифицировать.


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

> https://github.com/tsubaku/flights/blob/master/core/php/write_in_table.php


>Тут нечитаемая стена кода, надо выносить из нее отдельные функции.


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

Остальные комментарии тоже приму к сведению.

>Я еще раз напомню, что у нас в ОП посте есть задача на список студентов.


Я с ней ознакомился. Кое-что применил, что смог. Мне кажется, у меня мозги слишком крепко пропитаны админством и сложно уловить подход программистов. Но я буду продолжать переписывать код и дальше.
#126 #1021998
>>1021975

>оперативными хранилищами, серверами очереди


шо это за хуйня?
#127 #1022009
>>1021099

Работа с исключениями сделана абсолютно неправильно:

> try { }


> catch (\Exception $e) {


> Yii::warning($e->getMessage());


> return $this->redirect(Yii::$app->request->referrer);



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

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

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

Вот простой пример, чем плох твой код. У тебя есть действие контроллера для рассылки сообщений actionMassSend(). Но что, если нам понадобится вызвать это действие где-то программно? У тебя нет функции вроде sendMassMessage($message, $users) и нам придется писать код заново. Ты не почему-то не додумался вынести это действие в отдельную функцию, а вписал в контроллер, перемешав с кодом получения данные из формы и кодом отдачи ответа пользователю.

>>1021061

Спасибо, сайтгайд хороший.

>>1021030

> Изменение номера - https://ideone.com/KJxmSg


Ок, верно

> Автозамена - https://ideone.com/LaOqC8


Ок, тоже верно

> Вывод email - https://ideone.com/NCD54g


Не найдется email i[|JvanANUS0sqi2PUNCTUMcX,#om

> Grammar Nazi - https://ideone.com/BR95EM



Эти однотипные строки надо объединить в одну регулярку:
$text = preg_replace('/[,](\\S)/ui', ', $1', $text);
$text = preg_replace('/[;](\\S)/ui', '; $1', $text);
$text = preg_replace('/[!](\\S)/ui', '! $1', $text);

И эти объединить:

> $text = preg_replace('/жы/ui','жи', $text);


> $text = preg_replace('/шы/ui','ши', $text);



> $text = preg_replace('/(\\S) а /', '$1, а ', $text);


Нужно еще правило для "но"
#127 #1022009
>>1021099

Работа с исключениями сделана абсолютно неправильно:

> try { }


> catch (\Exception $e) {


> Yii::warning($e->getMessage());


> return $this->redirect(Yii::$app->request->referrer);



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

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

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

Вот простой пример, чем плох твой код. У тебя есть действие контроллера для рассылки сообщений actionMassSend(). Но что, если нам понадобится вызвать это действие где-то программно? У тебя нет функции вроде sendMassMessage($message, $users) и нам придется писать код заново. Ты не почему-то не додумался вынести это действие в отдельную функцию, а вписал в контроллер, перемешав с кодом получения данные из формы и кодом отдачи ответа пользователю.

>>1021061

Спасибо, сайтгайд хороший.

>>1021030

> Изменение номера - https://ideone.com/KJxmSg


Ок, верно

> Автозамена - https://ideone.com/LaOqC8


Ок, тоже верно

> Вывод email - https://ideone.com/NCD54g


Не найдется email i[|JvanANUS0sqi2PUNCTUMcX,#om

> Grammar Nazi - https://ideone.com/BR95EM



Эти однотипные строки надо объединить в одну регулярку:
$text = preg_replace('/[,](\\S)/ui', ', $1', $text);
$text = preg_replace('/[;](\\S)/ui', '; $1', $text);
$text = preg_replace('/[!](\\S)/ui', '! $1', $text);

И эти объединить:

> $text = preg_replace('/жы/ui','жи', $text);


> $text = preg_replace('/шы/ui','ши', $text);



> $text = preg_replace('/(\\S) а /', '$1, а ', $text);


Нужно еще правило для "но"
#128 #1022010
>>1021023

> Можешь объяснить, чем плохи чистые функции, зачем городить эти Utility service?


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

>>1020161

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

>>1020741

Какая версия дистрибутива? И почему версия PHP какая-то левая, что еще за blackfire? ты каких-то странных патчей туда наустанавливал, возможно в этом проблема?

Что значит "все ломается"

Из твоего поста ничего понять нельзя.

>>1020506

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

Ну и она не на русском.

А ты видел это? https://github.com/codedokode/task-checker

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

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

>>1020356

Нужно вынести файлы за пределы публичной папки (корня сервера).
#128 #1022010
>>1021023

> Можешь объяснить, чем плохи чистые функции, зачем городить эти Utility service?


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

>>1020161

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

>>1020741

Какая версия дистрибутива? И почему версия PHP какая-то левая, что еще за blackfire? ты каких-то странных патчей туда наустанавливал, возможно в этом проблема?

Что значит "все ломается"

Из твоего поста ничего понять нельзя.

>>1020506

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

Ну и она не на русском.

А ты видел это? https://github.com/codedokode/task-checker

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

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

>>1020356

Нужно вынести файлы за пределы публичной папки (корня сервера).
#129 #1022011
>>1021991

> Не понял. Там же только одна команда вывода json. В каком смысле "разбивать на 2 части"?


Вывод JSON ответа состоит из 2 действий:

- добавить заголовок Content-Type с значением application/json
- вывести тело ответа (JSON код)

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

> А html - это не text/plain?


Это text/html: https://ru.wikipedia.org/wiki/Список_MIME-типов

text/plain значит "обычный текст без тегов и форматрования". Браузер отобразит его просто черным текстом на белов фоне как есть.

> Но вот именно проблему копипасты не понимаю. Если что-то работает, и работает правильно, то как это переписывать?


Ты забываешь правило "код пишется для людей".

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

Также, в плане чтения кода строка

setNoCacheHeaders();

гораздо понятнее и читабельнее чем 2 строки с header.

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


Имя файла присылается всегда, а где гарантия, что браузер правильно определит и пришлет тип? У тебя есть информация, какие типы файлов какой браузер "знает", а какие нет? У меня нет такой информации например. Никто не запрещает прислать браузеру тип application/octet-stream например.

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


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

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


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

> У меня нет доступа к настройкам сервера. Вернее, на локалхосте есть, а вот на продакшене всё крутится у хостера (там всего-то статичный сайт нашей конторы, а этот сервис я делаю как бы его подсистемой).


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

Как костыль ты можешь попробовать загружать свой код на 1 папку выше корня сайта на сервере.

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



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

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


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

>>1021998

видимо redis/rabbitmq
#129 #1022011
>>1021991

> Не понял. Там же только одна команда вывода json. В каком смысле "разбивать на 2 части"?


Вывод JSON ответа состоит из 2 действий:

- добавить заголовок Content-Type с значением application/json
- вывести тело ответа (JSON код)

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

> А html - это не text/plain?


Это text/html: https://ru.wikipedia.org/wiki/Список_MIME-типов

text/plain значит "обычный текст без тегов и форматрования". Браузер отобразит его просто черным текстом на белов фоне как есть.

> Но вот именно проблему копипасты не понимаю. Если что-то работает, и работает правильно, то как это переписывать?


Ты забываешь правило "код пишется для людей".

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

Также, в плане чтения кода строка

setNoCacheHeaders();

гораздо понятнее и читабельнее чем 2 строки с header.

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


Имя файла присылается всегда, а где гарантия, что браузер правильно определит и пришлет тип? У тебя есть информация, какие типы файлов какой браузер "знает", а какие нет? У меня нет такой информации например. Никто не запрещает прислать браузеру тип application/octet-stream например.

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


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

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


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

> У меня нет доступа к настройкам сервера. Вернее, на локалхосте есть, а вот на продакшене всё крутится у хостера (там всего-то статичный сайт нашей конторы, а этот сервис я делаю как бы его подсистемой).


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

Как костыль ты можешь попробовать загружать свой код на 1 папку выше корня сайта на сервере.

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



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

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


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

>>1021998

видимо redis/rabbitmq
#130 #1022062
>>1021821

>Что за нестандартный стиль названий функций? PSR рекомендует camelCase для методов:



Думал что стиль названия для всего один. А оказывается для всего разные. fixed

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



А нормально что он будет в функции которая не в классе, а сама по себе?

>Гораздо аккуратнее будет если Компания будет заведовать списком департаментов, а специфичные вещи вроде "найти и уволить 40% рабочих" будут в отдельном классе для антикризисных мер.



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

>Имена функций начинаются с глаголов, сделатьЧтоТо



Заменил на destroy. А как я понимаю этот глагол пишется с маленькой буквы.

>> public function get_Workers_And_Destruction($count_in_percent,$proffesion)


>Тут функция просто создана методом копирования кода. Так не годится. Нужно убрать повторяющийся код.



Как я понял это про копирование foreach 3 раза. Сделал адекватно.

>Этот метод сам создает работников, и не позволяет добавить уже созданного где-то в другом месте работника. Лучше сделать добавление именно готового объекта, это будет универсальнее.



Добавил метод для поштучного добавления и для массива с кучей рабочих.

>Гораздо аккуратнее будет если Компания будет заведовать списком департаментов, а специфичные вещи вроде "найти и уволить 40% рабочих" будут в отдельном классе для антикризисных мер.



Я сделал отдельный класс. В нем функцию. и дальше если я пытаюсь эту фунецию на компанию использовать то ошибка. Не понимаю как сделать.

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

Еще вопрос что плохого в классе монстре. Хочешь использовать функцию или сделать. Через поиск проверяешь нет ли такой и используешь/делаешь.
#130 #1022062
>>1021821

>Что за нестандартный стиль названий функций? PSR рекомендует camelCase для методов:



Думал что стиль названия для всего один. А оказывается для всего разные. fixed

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



А нормально что он будет в функции которая не в классе, а сама по себе?

>Гораздо аккуратнее будет если Компания будет заведовать списком департаментов, а специфичные вещи вроде "найти и уволить 40% рабочих" будут в отдельном классе для антикризисных мер.



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

>Имена функций начинаются с глаголов, сделатьЧтоТо



Заменил на destroy. А как я понимаю этот глагол пишется с маленькой буквы.

>> public function get_Workers_And_Destruction($count_in_percent,$proffesion)


>Тут функция просто создана методом копирования кода. Так не годится. Нужно убрать повторяющийся код.



Как я понял это про копирование foreach 3 раза. Сделал адекватно.

>Этот метод сам создает работников, и не позволяет добавить уже созданного где-то в другом месте работника. Лучше сделать добавление именно готового объекта, это будет универсальнее.



Добавил метод для поштучного добавления и для массива с кучей рабочих.

>Гораздо аккуратнее будет если Компания будет заведовать списком департаментов, а специфичные вещи вроде "найти и уволить 40% рабочих" будут в отдельном классе для антикризисных мер.



Я сделал отдельный класс. В нем функцию. и дальше если я пытаюсь эту фунецию на компанию использовать то ошибка. Не понимаю как сделать.

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

Еще вопрос что плохого в классе монстре. Хочешь использовать функцию или сделать. Через поиск проверяешь нет ли такой и используешь/делаешь.
#131 #1022071
>>1022062
забыл код приложить
http://ideone.com/Vt2gpt
#132 #1022173
>>1019301 (OP)
Всем привет. Застрял в самом начале :с
Вот код:

1) <?php
2)
3) error_reporting(-1)
4)
5) echo "Бросаем кубик... \n";
6) $random = mt_rand(1,6) ;
echo "Выпало $random\n";

Выдает ошибку:
PHP Parse error: syntax error, unexpected 'echo' (T_ECHO) in /home/jZlt7x/prog.php on line 4

Я так понимаю у меня что-то не так с кавычками, а что сними не так? Или что не так?
#133 #1022181
>>1022173
Ты забыл точку с запятой в конце третьей строки.

>>1021824
Спасибо за ответ.
#134 #1022184
объясните дауну как решить задачу с сайта для начинающих из оп поста
http://codepad.org/nm9jPcpd
перебрал дохуа вариантов, боюсь окончательно ебанутся
#135 #1022194
>>1022009

>При ошибке надо вывести страницу ошибки


Ну она ругается в лог, а пользователю об это знать и не обязательно, хотя я наверное хотел проставлять там flash message ибо просто редирект это хрень конечно
Это единственная ошибка с исключениями?

> типичный толстый контроллер


Об этом я тоже думал, но я хз, как оценивают код и что там хотят увидеть те люди которые его просят ("Контроллер строк на 300, максимально написанных вами")
Вот я и запихнул туда этот метод, а то в контролере только вызовы сервисов и методов моделей и будут.
Или они хотят видеть патернизацию всего, а логика не так важна...
Увы у меня особо нет времени запилить годный большой резюме-проект, а на текущей работе говнокод и суровая реальность
#136 #1022210
>>1022010

>Какая версия дистрибутива? И почему версия PHP какая-то левая, что еще за blackfire? ты каких-то странных патчей туда наустанавливал, возможно в этом проблема?


Что значит "все ломается"
Из твоего поста ничего понять нельзя.

это версия пхп, который в коробке хомстед в вагранте скрин с терминала под ссх, там все настроено и установлено заранее, в этом и понт этого вагранта. а вот мкрипта нет. устанавливаю туда, по ссх мкрипт и вылазит при просмотре в браузере: No input file specified везде
#138 #1022273
>>1022194

>Или они хотят видеть патернизацию всего, а логика не так важна...


this
#139 #1022830
Но за большее количество раз и при этом
смотреть на нее
#140 #1023120
Рассердился на такое дело царевич, и как даст ему крапивой по правому яйцу!
#141 #1023888
>>1022265
спасибо,один в один делал так же, видимо ебаный синтаксис
#142 #1023903
>>1022181
Спасибо за ответ :)
#143 #1023904
>>1023888
я тоже тупил на этом месте чето
это математика, а не синтаксис, лол
выплатил 60000 = $paymentTotal
тебе нужно отдать 1270 = $creditBalance
ты отдаешь 5к $paymentTotal = 65k
долг $creditBalance = -3630
if ($creditBalance < 0)
тебе дают сдачу
$paymentTotal= $paymentTotal + $creditBalance;
#144 #1023912
>>1023904
ну что ты за человек, сделал так же говорю, но правильный результат не выводился
#145 #1023957
антоны есть какой-нибудь изи способ добавлять записи с какого-нибудь фейсбука\да и вообще любого сайта к себе на через пхп+мускл?
тупо в текстовом варианте
какие вообще есть способы для этого?
#146 #1023987
>>1023957
С фейсбука ты можешь воспользоваться их API, благо у них неплохая документация с Explorer'ом.

А с любого другого сайта могу посоветовать лишь парсить верстку, советую с мобильной версии.
Я пользовался несколькими библиотечками, быстрее всего оказалась pharse от ressio.
#147 #1024084
я не смог осилить пхп...
#148 #1024090
>>1024084
Я осилил php, когда мне было 11. Сейчас мне 26.
Тебе 10?
#149 #1024094
#150 #1024104
>>1024090
А когда мне было десять лет ПХП еще не изобрели и программировать я мол разве что на БЭСМ
#151 #1024105
какая разница между передачей по значению и по ссылке?
#153 #1024189
Кто-нибудь использует в продакшене?

https://github.com/nikic/scalar_objects
#154 #1024192
Господа, как сделать, чтобы strpos работало под кириллицей?
<?
$what="буквы";
$where="здесь буквы кириллицы";
echo mb_strpos($where, $what, 0, 'UTF-8');
?>
Этот код не хочет работать. PHP 7.
#155 #1024200
>>1024192

><?


>$what="буквы";


>$where="здесь буквы кириллицы";


>echo mb_strpos($where, $what, 0, 'UTF-8');


>?>



Попробуй

<?php
$what="буквы";
$where="здесь буквы кириллицы";
echo mb_strpos($where, $what, 0, 'UTF-8');
#156 #1024202
>>1024192

Если на ideone, то там не поддерживаются mb-функции, ищи другой сервис выполнения PHP кода.
#157 #1024205
>>1024202
>>1024200
Не работает.
Я на своем сервере запускаю, не ideone.
Может надо как-то настроить php-fpm?
#158 #1024211
>>1024205

В чем проявляется "не работает"? Ошибка какая-то пишется или что? Что в логах? Установлено ли расширение mbstring (можно посмотреть в phpinfo())?
#159 #1024217
фреймворки ставятся только на линукс?
#160 #1024219
>>1024211
FastCGI sent in stderr: "PHP message: PHP Fatal error: Uncaught Error: Call to undefined function mb_strpos() in /var/www/html/test.php:38

И где там посмотреть установлено ли оно? Ввел в поиск ctrf-f - не нашло mbstring.
У меня чистый php-fm на убунте. Как установить mbstring?
#161 #1024231
>>1024217
Только на macOS. Для установки необходимо смузи
#162 #1024242
изучаю пхп по этому курсу
https://www.w3schools.com/php/default.asp
#163 #1024244
>>1024242
Этого должно хватить http://php.net/manual/en/langref.php
#164 #1024247
>>1024244
знаю.но он у меня тяжелее пошел
#165 #1024248
>>1024219

Посмотреть с помощью php -m или функции phpinfo()

Установить так:

apt-cache search php

найти там mbstring и установить с помощью sudo apt-get install
#166 #1024253
>>1024248
Спасибо, установил через
sudo apt-get install php7.0-mbstring
Всё заработало.
#167 #1024255
>>1024247
От твоего учебника у тебя только мусор в голове останется.
w3schools не объясняет такие базовые вещи как
foreach ($arr as &$value) {
$value = $value * 2;
}
обрати внимание на амперсанд перед $value

Не говоря про темы, которые ты пропустишь, например:

http://php.net/manual/ru/language.oop5.autoload.php
http://php.net/manual/ru/language.namespaces.php
http://php.net/manual/ru/language.oop5.late-static-bindings.php
#168 #1024266
>>1024255
так этот курс не претендует на объемное изучение.но для быстрой базы самый раз
#169 #1024278
>>1024266
Базы для чего? Для натягивания шаблонов на вордпресс - возможно. Для уверенного пользования современными PSR фреймворками - нет не достаточно. Да и вообще, как я указал в начале, w3schools не дает правильного понимания php. Официальная документация методически правильно излагает материал от простого к сложному.
#170 #1024293
>>1024278
там много заумных объяснений,либо все кратко отчего местами нихуя не понятно,если ты изучал до этого к-л язык то все пойдет конечно норм
#171 #1024308
как в ХAMPP вручную через консоль, командами работать с БД?
#172 #1024337
<input type="hidden" name="the_checkbox" value="0" />
<input type="checkbox" name="the_checkbox" value="1" />

Можно ли писать такой код чтобы потом удобнее обрабатывать было в php форму? А то isset'ом проверять не очень как-то.
#173 #1024423

>Сколько времени надо изучать все это? - все зависит от тебя, но не меньше 6-8 месяцев


Это ебаша по пять часов в день? Сколько мне понадобится времени, если уделять по два часа в день, чтобы достигнуть такого уровня, чтобы взяли на работу хотя бы "за еду"?
Зачачи #174 #1024516
ОП, проверь задачи, пожалуйста

На словах ты Лев Толстой - https://ideone.com/S7Xrez
Поиск email - https://ideone.com/d2N8d6
Grammar Nazi - https://ideone.com/925aB2
Опечаточник - https://ideone.com/mpNbLd
#175 #1024555
>>1024516

>Опечаточник - https://ideone.com/mpNbLd



если в слове больше 1 енг буквы. то не показывает остальные
#176 #1024561
Задачу на банкомат можно решить следующим алгоритмом?
Сначала проверяет на наличие купюр, если ключ(кол-во купюр) таковой равен нулю, то удаляет её из массива. После сумма делится на последний элемент массива, попутно считая купюры и отнимая один от ключа до тех пор, пока он не станет равен нулю. После следующий и так далее.
#177 #1024652
>>1024189
БАМП
#178 #1024904
>>1022062
с антикризисными мерами
http://ideone.com/gap02Z
#179 #1024908
Почему symfony3 запущенный в dev моде работает с очень большой задержкой. Запускал на был в build-in сервере и на nginx+fpm
#180 #1024989
>>1024555
Так в задании написано "выделяет квадратными скобками первую замененную букву". Разве нужно остальные выделят?
#181 #1025212
Аноны, посоветуйте пожалуйста идеи для портфолио на гитхаб. Я только только выучил основы ооп php, хочу че нибудь сделать, что бы потом показать на собеседовании на стажера, но вобще ни одной мысли. Хелп!
#182 #1025247
>>1025212
Та же хуйня. Взялся делать хайп, мимо из прошлого треда
#183 #1025277
>>1022011
Я после твоих последних постов так и не смог найти силы переписывать программу. Руки опустились.
#184 #1025299
>>1025277
Когда ты вбрасывал программу в тред, ты думал, что за тебя найдут ошибки.
Теперь ты думаешь, что кто-то даст тебе мотивацию.
Потом у тебя что-то не получиться, и ты попросишь решить проблему за тебя.

Реши блядь уже свои собственные проблемы самостоятельно. Тебе уже охуительно сильно помогают искать ошибки. Цени чужое потраченное на тебя время.
#185 #1025304
>>1025299
Ценю. Реально дотошный разбор ошибок (это положительная оценка, если что).
#186 #1025305
>>1025304
Так делай, если не хочешь чтобы оно было потрачено зря.
#187 #1025319
>>1025212
>>1025247

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

>>1024908

Ну, если у сайта один пользователь то особой разницы между fpm и built-in сервером и нет.

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

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

Стоит помнить только, что включение отладки повлияет на код и он будет работать еще медленнее.

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

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

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

Я тебе советую сделать какой-то тестовый контроллер, который просто выводит hello world, чтобы исключить проблемы в твоем коде.

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

- включить opcache. Это расширение кеширует скомпилированные скрипты в памяти и избавляет от необходимости компилировать их повторно
- проверить настройки Доктрины, особенно если ты используешь много сущностей. Она в зависимости от настроек может собирать метаданные из кода сущностей и генерироват прокси классы на лету, что увеличивает время выполнения
#187 #1025319
>>1025212
>>1025247

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

>>1024908

Ну, если у сайта один пользователь то особой разницы между fpm и built-in сервером и нет.

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

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

Стоит помнить только, что включение отладки повлияет на код и он будет работать еще медленнее.

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

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

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

Я тебе советую сделать какой-то тестовый контроллер, который просто выводит hello world, чтобы исключить проблемы в твоем коде.

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

- включить opcache. Это расширение кеширует скомпилированные скрипты в памяти и избавляет от необходимости компилировать их повторно
- проверить настройки Доктрины, особенно если ты используешь много сущностей. Она в зависимости от настроек может собирать метаданные из кода сущностей и генерироват прокси классы на лету, что увеличивает время выполнения
#188 #1025359
Подскажите пожалуйста, где взять имя и временное имя файла?
И почему не добавляется запись в таблицу
CSS Animation goes back slower than forward. A html class toggles with delay. #190 #1025364
Hello,
I did a roll up/down menu with CSS transitions. It's based on toggling classes with different "max-height". Very simple case, but it doesn't work in a way I expect it to.

The problem is: the menu goes back only after a certain delay, (which is depends on an animation time). Maybe something wrong with my JS, bc it seems like the browser toggles the class with delay (and only then the animation fires).

Here's codepen. You click to open it - it rolls down fast, you click to close it - it waits 2 seconds and only then rolls down: https://codepen.io/anon/pen/dRrwQB
#191 #1025391

>Нихуя не понял генераторы


>первая же js задача ввела ступор


дайте решение.
#192 #1025394
>>1025359
>>1025361
Неактуально
#193 #1025419
>>1025391
Там не нужно использовать ES6 генераторы, если ты о них. Достаточно написать функцию, возвращающую функцию, которая в свою очередь инкрементирует и возвращает значение из замыкания. Почитай learn.javascript.ru
#194 #1025423
>>1025364
transition: cubic-bezier(0.17, 0.04, 0.03, 0.94);
#195 #1025428
>>1025419
В итоге это сделал
50 Кб, 843x202
#196 #1025430
Что ему не нравится-то?

100 $key = $_POST['key'];
101 $query="SELECT * FROM posts WHERE text LIKE '$key' OR WHERE title LIKE '$key' ORDER BY id DESC";
102 $result=$pdo->query($query)or die("Запрос не выполнен");
#197 #1025432
>>1025364
стыдно за тебя
#198 #1025433
>>1025430

>Что ему не нравится-то?


102я строка
#199 #1025434
>>1025433
Очень информативно. Обращаю внимание, что в посте указана 102-я строка.
#200 #1025440
>>1025430
У тебя 2 раза WHERE в запросе. Пиши так: "WHERE text LIKE :key OR title LIKE :key"

Ещё у тебя SQL-инъекция в коде (исправляй срочно) и дурацкий вызов die после $pdo->query
Читай пасты ОПа:
https://github.com/codedokode/pasta/blob/master/student-list.md#Работа-с-базой-данных-из-php
https://github.com/codedokode/pasta/blob/master/security/sql-injection.md
#201 #1025446
>>1025440
Спасибо, заработало.

Еще вопрос, как вынести подключение к БД за пределы страницы?У меня сейчас код вида
<? соединение с БД ?>
<html>
<? вывод данных из БД?>

но по логике пользователь не должен видеть операции с БД же.
#202 #1025450
>>1025446
Выбирай 2 стула
#203 #1025452
>>1025446
Да, хорошим тоном считается разделять PHP-код от шаблонов: http://web.archive.org/web/20161119062218/http://www.phpinfo.su/articles/practice/shablony_v_php.html
Видно, что ты начинающий и c MVC не знаком, советую почитать/выполнить эту задачу, сам многому научился: https://github.com/codedokode/pasta/blob/master/student-list.md

>>1025450
>>1025433
Зачем вы тут? Не хотите помогать - не засоряйте тред.
#204 #1025469
>>1024561

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

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


Многократное вычитание - это деление.

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

>>1024904

> public function addDepartament($departament)


Тут нужен тайп-хинт. Вот короткая копипаста:

--------
### Тайп хинты

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

Мануал: http://php.net/manual/ru/language.oop5.typehinting.php

Обрати внимание, что php7 усовершенствовал систему тайп-хинтов - теперь можно в их качестве указывать примитивные типы вроде int/string, а в php7.1 стало можно указывать тайп-хинт для возвращаемого функцией значения: https://habrahabr.ru/post/267799/ , причем можно указать тип void, значащий, что функция ничего не возвращает (увы, возможность вернуть null пока не реализовали, так что ждем)
--------

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

> public function deleteWorker($number)


Вот это неудачно спректированная функция. Чтобы удалить работника, надо узнать его номер в приватном списке внутри департамента. Как его узнать? Надо вместо номера передавать самого работника, которого надо уволить. Объект - это сам по себе уникальный идентификатор.

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

> $is_Head,


Стиль названия не соответствует другим переменным

> public function getSalary($worker)


Зачем сюда передается worker? Он еще и не используется никак.

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

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

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

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

> class Crisis


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

Отбор кандидатов на увольнение/повышени лучше сделать так:

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

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

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

Также, логично было сделать отдельный метод в департаменте для замены главы. А ты написал код смены главы где-то снаружи, что по моему не так логично. Это ведь явно область ответственности департамента - управлять списком своих работников и назначением главы.
#204 #1025469
>>1024561

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

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


Многократное вычитание - это деление.

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

>>1024904

> public function addDepartament($departament)


Тут нужен тайп-хинт. Вот короткая копипаста:

--------
### Тайп хинты

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

Мануал: http://php.net/manual/ru/language.oop5.typehinting.php

Обрати внимание, что php7 усовершенствовал систему тайп-хинтов - теперь можно в их качестве указывать примитивные типы вроде int/string, а в php7.1 стало можно указывать тайп-хинт для возвращаемого функцией значения: https://habrahabr.ru/post/267799/ , причем можно указать тип void, значащий, что функция ничего не возвращает (увы, возможность вернуть null пока не реализовали, так что ждем)
--------

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

> public function deleteWorker($number)


Вот это неудачно спректированная функция. Чтобы удалить работника, надо узнать его номер в приватном списке внутри департамента. Как его узнать? Надо вместо номера передавать самого работника, которого надо уволить. Объект - это сам по себе уникальный идентификатор.

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

> $is_Head,


Стиль названия не соответствует другим переменным

> public function getSalary($worker)


Зачем сюда передается worker? Он еще и не используется никак.

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

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

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

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

> class Crisis


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

Отбор кандидатов на увольнение/повышени лучше сделать так:

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

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

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

Также, логично было сделать отдельный метод в департаменте для замены главы. А ты написал код смены главы где-то снаружи, что по моему не так логично. Это ведь явно область ответственности департамента - управлять списком своих работников и назначением главы.
#205 #1025473
Поясните зачем нужен интерфейс Итератор? нужно ли тратить время на него так как вообще не пойму че он делает? Реализован ли он в современных фреймах? И если да то какие примеры.
#206 #1025474
>>1025473

> зачем нужен интерфейс Итератор?


Чтобы обходить объект в цикле.

> Реализован ли он в современных фреймах?


Да, любой класс коллекций, например коллекции ошибок валидации в symfony/form, коллекции сущностей в доктрине, коллекции HTTP-заголовков и т.д

> нужно ли тратить время на него


Однозначно, у меня даже на собесе про него спрашивали.
#207 #1025477
>>1025430

Вместо or die нужно включить в PDO режим выброса исключений (PDO::ERRMODE_EXCEPTION).

>>1025430

Обрати внимание на текст "right syntax to use near ..." - это значит, что ошибка в указанном месте, то есть лишний WHERE.

>>1025391

Там нужно использовать переменную в замыкании как счетчик. То есть ты создаешь переменную-счетчик, создаешь новую функцию, и она привязывается к этой переменной и может ее использовать.
Test #208 #1025478
>>1025364

Posted answer here because of spam filter: https://pastebin.com/4JXyVf0w
#209 #1025479
>>1025277

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

>>1024516

> На словах ты Лев Толстой - https://ideone.com/S7Xrez


Ок, верно

> Поиск email - https://ideone.com/d2N8d6


Все правильно

> Grammar Nazi - https://ideone.com/925aB2


> '/[,](\\S)/ui', '/[;](\\S)/ui', '/[!](\\S)/ui'


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

> Опечаточник - https://ideone.com/mpNbLd


Твоя программа просто ищет латинские буквы. Но надо искать слова, составленные из букв разных алфавитов. Слова вроде "HELLO" не должны вызывать ошибку.
#210 #1025481
>>1025473

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

foreach ($primeIterator as $number) {
echo "Число: $number\b";
}

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

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

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

Я советую изучить список встроенных итераторов: http://php.net/manual/ru/spl.iterators.php

Писать итераторы не очень удобно, удобнее сделать функцию-генератор, которая при вызове возвращает итератор: http://php.net/manual/ru/language.generators.overview.php
#211 #1025501
>>1025478
Да, проблема была с анимацией была именно в том, что CSS анимирует свойство max-height полностью, т.е несмотря на то, что размеры меню 200px, оно анимирует все 900px.
#212 #1025519
>>1025501
Why are you stopped speaking on english? That's weird.
#213 #1025530
В файлообменнике сущность файл должна агрегировать массив сущностей комментариев? Если да, то класс FileGateway должен агрегировать CommentGateway?
#214 #1025540
>>1007389

>>>Ну и подсчет высоты сообщений - это явно что-то неправильное. Это нужно для выравнивания сообщений вертикально? Неужели это нельзя было сделать средствами CSS? Задание размеров и расположения элементов через JS работает плохо, может влиять на производительность и работать с задержками.


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


>Это называется "вертикальное выравнивание". Я бы поискал варианты сделать это средствами CSS. Вот что приходит в голову:


>


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


>- display: table - работает начиная с ИЕ8 и древних фаерфоксов. Это как flex, только слабее по возможностям и со своими недостатками. Табличное отображение позволяет прижать содержимое ячейки (зоны сообщений) вниз. Тут есть проблемка - чтобы сделать прокрутку, блоку сообщений надо задать высоту, и задать ее в виде 100% (=высоте окна) наверно не получится, значит придется этот момент сделать через JS (определение доступной высоты блока и изменение ее при измнеении размера окна)


>- прижать блок сообщений вниз с помощью абс. поз. Работает тоже везде, и можно задать высоту как 100% от зоны для вывода сообщений (при условии что не используется display: table, так как абс. поз. не работает с элементами таблиц).

>


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


>


>Я могу подсказать по CSS, но имея частично работающий код, сделать это проще.


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

https://jsfiddle.net/55khok9f/1/
#214 #1025540
>>1007389

>>>Ну и подсчет высоты сообщений - это явно что-то неправильное. Это нужно для выравнивания сообщений вертикально? Неужели это нельзя было сделать средствами CSS? Задание размеров и расположения элементов через JS работает плохо, может влиять на производительность и работать с задержками.


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


>Это называется "вертикальное выравнивание". Я бы поискал варианты сделать это средствами CSS. Вот что приходит в голову:


>


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


>- display: table - работает начиная с ИЕ8 и древних фаерфоксов. Это как flex, только слабее по возможностям и со своими недостатками. Табличное отображение позволяет прижать содержимое ячейки (зоны сообщений) вниз. Тут есть проблемка - чтобы сделать прокрутку, блоку сообщений надо задать высоту, и задать ее в виде 100% (=высоте окна) наверно не получится, значит придется этот момент сделать через JS (определение доступной высоты блока и изменение ее при измнеении размера окна)


>- прижать блок сообщений вниз с помощью абс. поз. Работает тоже везде, и можно задать высоту как 100% от зоны для вывода сообщений (при условии что не используется display: table, так как абс. поз. не работает с элементами таблиц).

>


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


>


>Я могу подсказать по CSS, но имея частично работающий код, сделать это проще.


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

https://jsfiddle.net/55khok9f/1/
#215 #1025558
>>1025519
Просто учусь формулировать предложения на англ. Спасибо за помощь с вопросом.
#216 #1025559
>>1025558

Зарегистрируйся на Hacker News (новости IT) и участвуй там в дискуссиях.
#217 #1025560
>>1025558

Или на stack overflow. Или на lang-8 который специально для этого предназначен.
21 Кб, 429x454
#218 #1025582
Здравствуйте, у меня есть Many To Many связь между Link и Tag. Форма Link (на пике) позволяет редактировать теги для каждой ссылки. Это норма, что приходится извращаться с array_diff'ами при редактировании тегов, при условии что:
- теги можно удалять (значит нужно как использовать unlink)
- при добавлении новых тегов в БД нужно сначала их создать (save), а только потом присоединять к Link
- уже существующие теги не должны создаваться заново, Link нужно связывать с уже существующими тегами

Тут код: https://pastebin.com/56qq7Zdj
#219 #1025585
>>1025582

Ты зря все это пишешь в контроллере. Лучше сделать в модели функцию updateTags($newTags) и пусть она проверяет что там где изменилось.

Ну а вообще, если лень делать diff то можно просто очищать связь и создавать заново.
245 Кб, 600x1024
#220 #1025613
ПХП макаки, самые нищеброды. Golang разработчики самые оплачиваемые! Переходите на Go пока не поздно. Вся инфа в треде
https://2ch.hk/pr/res/1020995.html (М)
mb #221 #1025658
Аноны, на ideone не работает mb_strlen, mb_substr и т.д. не работают?
#222 #1025781
>>1025613
а на node уже переходить не надо?
#223 #1025819
>>1025585
Спасибо, это уменьшит количество diff'ов. А нормально ли для Active Record делать save() в цикле для новых сущностей? Ещё мой в транзакцию нужно обернуть.

>>1025658
Да, там обновили PHP до 7-й версии, а про расширение mbstring забыли. Как вариант можно использовать https://3v4l.org/
Ещё мне кажется, что этот вопрос за последние треды бьёт все рекорды популярности и может быть стоит об этом написать в ОП-посте. Или что хуже - редактировать сайт на народе, там ведь ссылки на ideone.
25 Кб, 600x391
#224 #1025828
Вскроем тему.
Что такое URI?
URL - ссылка, но нееет, это всё детские шалости, ссылкой это называют только не знающие.
URI - унифицированное имя ресурса.
URL - местонахождение ресурса(location)
URN(che za huiny?) - имя ресурса(name)

Так вот URL и URN являются частями URI.
Так блядь в чём смысл? URL - устарело, так? Теперь любые ссылки называть URI?

"http://docs.slimframework.com/request/paths/ "
ЭТО URI? Говорить URL не тру и вообще не правильно?

А вопрос встал ввиду не понимания информации ниже.
Root URI

The root URI is the physical URL path of the directory in which the Slim application is instantiated and run. If a Slim application is instantiated in index.php within the top-most directory of the virtual host’s document root, the root URI will be an empty string. If a Slim application is instantiated and run in index.php within a physical subdirectory of the virtual host’s document root, the root URI will be the path to that subdirectory with a leading slash and without a trailing slash pidor.

(поясните о чём тут)
#225 #1025838
>>1025828
url описывает МЕСТОНАХОЖДЕНИЕ ресурса.
uri - это не имя, а идентификатор ресурса. он может быть как и url так и urn, так и все в перемешку

url частный случай uri
у одного uri может быть множество url и urn

urn не описывает где лежит ресурс. а url не обязан отражать имя ресурса.
#226 #1025839
>>1025828

>"http://docs.slimframework.com/request/paths/ "


>ЭТО URI? Говорить URL не тру и вообще не правильно?



Человек играющий на скрипке - это музыкант? Говорить, что он скрипач вообще не правильно?
#227 #1025845
>>1025838

>у одного uri может быть множество url и urn


Вот тут по-подробней пожалуйста.
#228 #1025846
>>1025845
Что не ясного. URI это сам ресурс. Например какая-то книга. Представлена она тебе можеть быть либо ввиде URN (например isbn:NOMER_KNIGI), либо ввиде URL (ссылки туда где эта книга лежит). И то и другое ты потом передаешь нужной программе, и она тебе вытаскивает данные о твоей книге.

URI это АБСТРАКТНЫЙ КЛАСС. URN и URL классы, от него наследующиеся. Инстансов у URL быть не может. Но в то же время каждый инстанс URN или URL - это URI
#229 #1025847
>>1025846

>Инстансов у URL быть не может


у URI*
#230 #1025869
>>1025846
Ты пример может привести URI? Что значит сам ресурс? Я знаю адрес сайта - foobar.ru, это URL. URL часть URI, значит foobar.ru - это URI? Но URI может иметь несколько URL, и как блядь? Если имя уникально.
#231 #1025884
>>1025869
Ты дебил, нет?

http://foobar.ru - это как и URL так и URI
А http://www.foobar.ru или https://foobar.ru - это тебе примеры еще пары URL ссылающихся НА ТОТ ЖЕ САМЫЙ ресурс.

При этому у твоего foobar.ru URN может быть каким-нибудь website:foobarcompany

URL показывает где лежит ресурс. URN его уникальное имя в КАКОЙ-ТО СИСТЕМЕ. И то и другое это URI этого ресурса. Это ОБЩЕЕ ТВОЯ СУКА МАТЬ НАЗВАНИЕ . И у любого ресурса может быть миллионы URL или URN

Сука, ты понимаешь, что такое АБСТРАКТНЫЙ КЛАСС - нет?

Вот скажи мне блядь, человек играющий на гитаре - это гитарист или музыкант?
#232 #1025888
>>1025869

>уникально


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

URI - это уникальный идентификатор ресурса. Представлен он тебе может либо ввиде URL либо в виде URN. И то и другое это URI.
#233 #1025892
>>1025869

URI это обобщенное название для URL (обычных ссылок) и URN (всяких странных идентификаторов вроде номера книги или телефона) и может быть каких-то еще других видов ссылок на ресурсы. То есть любой URL или URN является URI.

Вот определения:

URL:

> A Uniform Resource Locator (URL), colloquially termed a web address,[1] is a reference to a web resource that specifies its location on a computer network and a mechanism for retrieving it.


> URLs occur most commonly to reference web pages (http), but are also used for file transfer (ftp), email (mailto), database access (JDBC), and many other applications.



Вот URN:

> In computing, a Uniform Resource Name (URN) is a Uniform Resource Identifier (URI) that uses the urn scheme.



URI:

> A URI is a string of characters used to identify or name a resource.



И вот еще:

> Since RFC 3986[5] in 2005, use of the terms "Uniform Resource Name" and "Uniform Resource Locator" has been deprecated in technical standards in favor of the term Uniform Resource Identifier (URI), which encompasses both



Дальше можно почитать статью https://en.wikipedia.org/wiki/Uniform_Resource_Name и сам RFC, если хочется точных определений.

Хоть авторы и пишут URI, там имеется в виду именно URL, причем не любой, а только URL с использованием протоколов HTTP/HTTPS. Так как это веб-фреймворк.
#234 #1025894
>>1025888

Вообще-то уникальность подразумевает, что у ресурса один URI, а не множество.
#235 #1025895
>>1025884

> А http://www.foobar.ru или https://foobar.ru - это тебе примеры еще пары URL ссылающихся НА ТОТ ЖЕ САМЫЙ ресурс.



Это как раз плохой пример, так как у ресурса должен быть один URI, а не несколько. Адреса http://www.foobar.ru или http://foobar.ru должны вместо отдачи контента редиректить на https://foobar.ru
#236 #1025901
>>1025895

>должен быть один URI, а не несколько


Потому что ты так сказал?
Ты идиот.
#237 #1025906
>>1025895
В твоем манямирке ресурсы должны быть доступны только по одному протоколу и только на одном хосте, ip? А со всех остальных надо редиректить?
#238 #1025935
>>1025901

Все понятно, не засоряй тогда дальше тред.
#239 #1025947
Делаю к файлообменнику регистрацию, есть сущности RegisteredUser, Admin и Visitor унаследованные от абстрактного класса User. Создал для каждой сущности свой TableDataGateway и свою таблицу sql. В классе AuthHelper все эти TDG агрегируются и в методе login($login, $pass) я обращаюсь к каждому чтобы проверить существует ли пользователь с данным логином. Мне кажется, я делаю что-то неправильно, потому что получается 3 запроса, а в sql запросах можно объединять таблицы. Есть ли альтернатива моему способу?
#240 #1025949
>>1025947

Если что, сущность Admin наследуется от RegisteredUser, и есть еще сущность SuperAdmin наследуемая соответственно от Admin.
#241 #1025951
>>1025949

А еще для Visitor я не создавал таблицу и TDG, гость у меня только куку получает без записи в таблице, так что мы говорим о сущностях Admin, SuperAdmin и RegisteredUser, вот.
#242 #1025969
>>1025781
Сравнил жопу с пальцем. JS в любом случае придётся учить. С ним на ноде и монге можно ебашить изоморфные приложения без ебли с парсингом. Смысл пхп - разбираться в чужих легаси конюшнях в разных мусохрансках за гроши.
#243 #1025977
>>1025947
>>1025949
Кажется, что ты переусложнил с четырьмя классами. Что мешает в таблице User держать колонку-дискриминатор, которая будет обозначать тип пользователя? В приложении может быть куча ролей у пользователей и неудобно создавать по классу для каждой роли. Наследование удобно использовать, когда у каждого наследника свой набор колонок в бд / свойств класса (советую почитать про STI, Class TI и Concrete TI).
12 Кб, 500x329
#244 #1025978
>>1025977

Я знаю про >STI, Class TI и Concrete TI. Разве не мой случай http://design-pattern.ru/patterns/concrete-table-inheritance.html ?
#245 #1025982
>>1025978

Хотя наверное не мой. Мой - это когда у перечисленных спортсменов определенные роли на поле.
8 Кб, 504x226
#246 #1025988
В чем проблема?

>


Parse error: syntax error, unexpected T_VARIABLE, expecting T_FUNCTION on line 40
#247 #1025997
>>1025906

Почитай справку для вебмастеров у Яндекса или Гугла.

>>1025947

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

>>1025988

public/private забыл
#248 #1026001
>>1025997

>URI


>вебмастеров


Все с тобой понятно.
#249 #1026061
В VS Code подсветка кода пыхи не работает. Может кто знает, как починить?
#250 #1026143
>>1026061
<?php или <? перед пыха кодом написал?
6 Кб, 543x133
#251 #1026151
>>1025997
Спасибо, все заработало. Но появилась следующая проблема, как присвоить значение которое возвращает метод класса данной переменной? Вот мой говнокод http://ideone.com/igRnFF
#252 #1026198
ОП, что скажешь? https://habrahabr.ru/post/333398/
Как раз начинать проект новый буду, собирался на Yii2 но теперь немного сомневаюсь
#253 #1026243
>>1026143
Есть такое. Я разобрался сам, но всё равно спасибо ещё миллион часов потратил,
чтобы xDebug настроить
.
#254 #1026257
Где в MVC вызывать session_start(), в начале каждого контроллере? И где проверять может ли пользователь находиться на странице, private метод контроллера checkAuth() в каждом экшне?
#255 #1026258
>>1026257

> private метод контроллера checkAuth()



Метод AuthHelper, а не контроллера, фикс.
#256 #1026317
>>1026151
Посмотри как вызывать метод в учебнике, нельзя просто так обращаться к нему как к функции.

>как присвоить значение которое возвращает метод класса данной переменной?


Можешь присвоить в конструкторе или создать отдельный метод setWorkers, например, который будет присваивать свойству workers массив из метода.
#257 #1026318
Привет, аноны.

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

В общем, в чем проблема. Я понимаю, что композитная форма имеется в виду форма, а в нее внутри формы (т.е. типичный такой пример -- корзина интернет-магазина), но у меня несколько другой случай. У меня практически идентичные формы, которые должны меняться от ситуации к ситуации, в зависимости от того какой контроллер вызывает. И как лучше всего это сделать? Кто мог бы посоветовать? Хотел похимичить с __call, и вроде как через это и нужно работать, но пока не очень выходит, и мне кажется, что это далеко не идеальное решение. Если кто-то подобное решал, то рад бы был подсмотреть код, ну или хотя бы в общих чертах опишите, что нужно сделать, собственно.
#258 #1026390
>>1025969

>Сравнил жопу с пальцем


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

>мусохрансках за гроши


а с го и нодой, ты хуй работу найдешь и если найдешь, то срок актуальности твоих знаний и умений - 2-3 года, после чего придется учить новую революционную все-убийцу, на ближайшие 2 года.
#259 #1026460
>>1026390

>да чет все никак не не взлетает.


Это ты так решил?

>а с го и нодой, ты хуй работу найдешь


Тож сам так решил?))Может стоит зайти хотя бы на hh и увидеть 900~ вакансий?

>то срок актуальности твоих знаний и умений - 2-3 года


И еще раз, ecma тебе в любом случае придется уметь.
#260 #1026470
>>1026460

>сам так решил?))


ага)))))

>увидеть 900~ вакансий


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

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


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

И нахуя мне нужна нода, чтобы использовать жквери?
62 Кб, 275x417
#261 #1026496
>>1026470

>и эти 900 высосаных из пальца и возникших на волне хайпа вакансии


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

>т.к. изучение одного из 100500 жс фреймворков сродни изучению нового языка.


Лол

>Одна из особенностей джаваскрипта в том, что ты можешь писать на нем, его не зная


>чтобы использовать жквери?

#262 #1026510
>>1026496

>Лол


Треснул квадратно-гнездовой шаблон? Бывает

>А какой процент из этого...


И, что ты хотел этим сказать, не пойму? точно также не пойму как необходимость знания екма связывает изучение ноды для того, чтобы уметь использовать жквери?
#263 #1026513
>>1026510

>И, что ты хотел этим сказать, не пойму?


Макака не смогла в контекст и зависла?

>жырквери


>кому-то про квадраты-гнёзда, да шаблоны заливает.

#264 #1026515
>>1026513
хайпошкольник порвался
#265 #1026920
можно ли силами CSS сделать симпотичный дизайн или все на фотошопе щас?
вопрос нуба
#266 #1027168
что такое статическая переменная?
#267 #1027245
>>1027168
это такой пруф
#268 #1027379
>>1027245
что?
#269 #1027482
>>1027379
пруф
#270 #1027487
>>1025613
Одно другому, тащем-та, не мешает. Бадушники тому — живой пример.
А есть статистика по пыхозарплатам без учета битриксов и прочих макак из уэб-студий?
#271 #1027490
Зацените задачку на пыхе:
https://www.codewars.com/kata/remove-first-and-last-character/
#272 #1027509
Напоминаю, что на Хабре выходит еженедельный дайджест со списком новостей, связанных с PHP. Там можно узнать про новые версии PHP, полезные библиотеки, почитать новые статьи на эту тему.

https://m.habrahabr.ru/company/zfort/blog/333458/
#273 #1027510
почему нет замены php в в современных реалиях?
#274 #1027569
>>1027510
почему нет? Есть, вон нода, го. Скоро пхп пизда
#275 #1027651
https://github.com/someApprentice/chat/blob/master/public/js/conversation.js#L82
Что можно сделать после успешной отправки сообщения?

Можно обновить все сообщения, но сообщения и так обновляются каждые пол секунды. Как-то не хочется оставлять пустую функцию. Или её можно не писать?

https://arhivach.org/thread/261841/#1000396

>Ты не обрабатываешь ошибки. Видимо, уроки, которые ты читал, упускают такие важные вещи. Вот тебе тогда мои маленькие советы про использование аякса: https://github.com/codedokode/pasta/blob/master/js/ajax.md


https://github.com/someApprentice/chat/blob/master/public/js/chat.js#L59-L69
https://github.com/someApprentice/chat/blob/master/public/js/conversation.js#L85-L92

Стоит ли так выборочно обрабатывать ошибки? Для пользователя достаточно вывести ошибку соединения, а для разработчиков выбросить в консоль статус и текст ошибки.

Почему у меня не вбрасываются эти ошибки (ошибки не появляются в консоле)? Это из-за асинхронного кода?

https://arhivach.org/thread/266631/#1010744

>> Кстати, это нормально делать перевод на новую строку в цикле https://github.com/someApprentice/chat/blob/master/public/js/conversation.js#L280-L284 ?


>Это какие-то кривые костыли. Получается, логика отображения разбросана между шаблоном и JS кодом. Мы ведь в PHP не пытаемся так делать после генерации HTML из шаблона? И тут не надо. Наверняка там есть какие-нибудь хелперы для таких преобразований. В чем проблема сделать какой-нибудь хелпер для преобразования текстов сообщений?


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

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

https://github.com/someApprentice/chat/blob/master/src/Controller/ConversationController.php#L78-L115
Это нормально, что у меня такая простыня с обработкой ошибок?

https://arhivach.org/thread/261841/#1000396

>Также, некоторые разработчики активно используют возможности HTTP (дополнительные заголовки, методы вроде PUT/DELETE, коды ответов), а некоторые не используют.


>Также, перед проектированием АПИ, советую почитать про REST и HATEOS (и далее, стандарт про шаблоны URL https://tools.ietf.org/html/rfc6570 ), но тут конечно есть разные мнения, ну к примеру в иделогии REST одним запросом нельзя получить несколько несвязанных массивов данных, а HATEOS раздувает размер ответа.


Я плохо понял что такое REST. Это просто архитектура которая позволяет обрабатывать запросы с методами вроде PUT\DELETE?

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

https://arhivach.org/thread/266631/#1010325

>Пересоздавать полный список сообщений неэффективно.


Я никак не могу придумать как выводить только новые сообщения. Определенно, нужен setTimeout\setInterval чтобы постоянно обновлять данные с сервера, но как при этом выводить только те сообщения которые ещё не выведены в шаблон?

https://github.com/someApprentice/chat/blob/master/src/Model/Database/MessageGateway.php#L25
Поскольку, я теперь вывожу сообщения за определённый период времени, то если за этот промежуток не было сообщений, при открытии диалога выведиться пустое окно сообщений из-за чего вытекает баг с автоматической подрузкой более старых сообщений, из-за того что отсутвует скролл блока сообщений. Это можно исправить увеличивая отрезок времени и повторном обращении к БД, до тех пор пока не получим нужное количество сообщений:

$count = $db->getMessagesCount();

$offset = 1;

if ($count > 10) {
while(count($messages) < 10) {
$offset++;
$messages = $db->getMessages(..., $offset);
}
}

Не будет ли это лишней нагрузкой на БД?

У меня есть идея как при отключенном js опускать окно диалога до последнего сообщения - использовать якори. Я уже делаю что-то подобное при получении более старых сообщениях (при выключенном js):

https://github.com/someApprentice/chat/blob/master/templates/chat.phtml#L24

><a ... href="conversation.php? ... #message-ID">Получить больше сообщений</a>



https://github.com/someApprentice/chat/blob/master/templates/chat.phtml#L32

><div id="message-ID ... class="message">



Точно так же можно сделать в ссылке контакта.

Но для этого нужно сделать несколько лишних запросов к БД:

$contacts = $db->getContacts();

$c = array();

foreach ($contacts as $contact) {
$lastMessage = $db->getLastMessage(...);

$c[] = array(
'contact' => $contact,
'lastMessage' => $lastMessage
);
}

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

Опять же, не создаст ли это большую нагрузку на БД? Учитывая, что с включенным js, при сортировке по последним сообщениям, обновление контактов будет происходить каждую секунду.

https://github.com/someApprentice/chat/blob/master/src/Controller/AuthController.php#L101-L103
https://github.com/someApprentice/chat/blob/master/public/js/conversation.js#L217
Не подвергаю ли я пользователей опасности, открывая кукисы для js?

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

У меня есть переменные, которые пишутся ни как camelCase или snake_case, например moremessages. Я знаю, что это плохой плохой вариант, но мне он кажется вполне читабельным. Лучше будет переимновать?
#275 #1027651
https://github.com/someApprentice/chat/blob/master/public/js/conversation.js#L82
Что можно сделать после успешной отправки сообщения?

Можно обновить все сообщения, но сообщения и так обновляются каждые пол секунды. Как-то не хочется оставлять пустую функцию. Или её можно не писать?

https://arhivach.org/thread/261841/#1000396

>Ты не обрабатываешь ошибки. Видимо, уроки, которые ты читал, упускают такие важные вещи. Вот тебе тогда мои маленькие советы про использование аякса: https://github.com/codedokode/pasta/blob/master/js/ajax.md


https://github.com/someApprentice/chat/blob/master/public/js/chat.js#L59-L69
https://github.com/someApprentice/chat/blob/master/public/js/conversation.js#L85-L92

Стоит ли так выборочно обрабатывать ошибки? Для пользователя достаточно вывести ошибку соединения, а для разработчиков выбросить в консоль статус и текст ошибки.

Почему у меня не вбрасываются эти ошибки (ошибки не появляются в консоле)? Это из-за асинхронного кода?

https://arhivach.org/thread/266631/#1010744

>> Кстати, это нормально делать перевод на новую строку в цикле https://github.com/someApprentice/chat/blob/master/public/js/conversation.js#L280-L284 ?


>Это какие-то кривые костыли. Получается, логика отображения разбросана между шаблоном и JS кодом. Мы ведь в PHP не пытаемся так делать после генерации HTML из шаблона? И тут не надо. Наверняка там есть какие-нибудь хелперы для таких преобразований. В чем проблема сделать какой-нибудь хелпер для преобразования текстов сообщений?


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

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

https://github.com/someApprentice/chat/blob/master/src/Controller/ConversationController.php#L78-L115
Это нормально, что у меня такая простыня с обработкой ошибок?

https://arhivach.org/thread/261841/#1000396

>Также, некоторые разработчики активно используют возможности HTTP (дополнительные заголовки, методы вроде PUT/DELETE, коды ответов), а некоторые не используют.


>Также, перед проектированием АПИ, советую почитать про REST и HATEOS (и далее, стандарт про шаблоны URL https://tools.ietf.org/html/rfc6570 ), но тут конечно есть разные мнения, ну к примеру в иделогии REST одним запросом нельзя получить несколько несвязанных массивов данных, а HATEOS раздувает размер ответа.


Я плохо понял что такое REST. Это просто архитектура которая позволяет обрабатывать запросы с методами вроде PUT\DELETE?

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

https://arhivach.org/thread/266631/#1010325

>Пересоздавать полный список сообщений неэффективно.


Я никак не могу придумать как выводить только новые сообщения. Определенно, нужен setTimeout\setInterval чтобы постоянно обновлять данные с сервера, но как при этом выводить только те сообщения которые ещё не выведены в шаблон?

https://github.com/someApprentice/chat/blob/master/src/Model/Database/MessageGateway.php#L25
Поскольку, я теперь вывожу сообщения за определённый период времени, то если за этот промежуток не было сообщений, при открытии диалога выведиться пустое окно сообщений из-за чего вытекает баг с автоматической подрузкой более старых сообщений, из-за того что отсутвует скролл блока сообщений. Это можно исправить увеличивая отрезок времени и повторном обращении к БД, до тех пор пока не получим нужное количество сообщений:

$count = $db->getMessagesCount();

$offset = 1;

if ($count > 10) {
while(count($messages) < 10) {
$offset++;
$messages = $db->getMessages(..., $offset);
}
}

Не будет ли это лишней нагрузкой на БД?

У меня есть идея как при отключенном js опускать окно диалога до последнего сообщения - использовать якори. Я уже делаю что-то подобное при получении более старых сообщениях (при выключенном js):

https://github.com/someApprentice/chat/blob/master/templates/chat.phtml#L24

><a ... href="conversation.php? ... #message-ID">Получить больше сообщений</a>



https://github.com/someApprentice/chat/blob/master/templates/chat.phtml#L32

><div id="message-ID ... class="message">



Точно так же можно сделать в ссылке контакта.

Но для этого нужно сделать несколько лишних запросов к БД:

$contacts = $db->getContacts();

$c = array();

foreach ($contacts as $contact) {
$lastMessage = $db->getLastMessage(...);

$c[] = array(
'contact' => $contact,
'lastMessage' => $lastMessage
);
}

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

Опять же, не создаст ли это большую нагрузку на БД? Учитывая, что с включенным js, при сортировке по последним сообщениям, обновление контактов будет происходить каждую секунду.

https://github.com/someApprentice/chat/blob/master/src/Controller/AuthController.php#L101-L103
https://github.com/someApprentice/chat/blob/master/public/js/conversation.js#L217
Не подвергаю ли я пользователей опасности, открывая кукисы для js?

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

У меня есть переменные, которые пишутся ни как camelCase или snake_case, например moremessages. Я знаю, что это плохой плохой вариант, но мне он кажется вполне читабельным. Лучше будет переимновать?
#276 #1027835
Котаны,вкатываюсь в ваш уютный клуб,проверьте задачки про кубы http://ideone.com/LitWO1 и айфон http://ideone.com/lHOqEL. Заранее пасяб.
З.Ы. А зачем в эхо выделять переменные фигурными скобками?
#277 #1027942
Расскажите пожалуйста про

>$example = function () use ($variable) { ... }



В мануале http://php.net/manual/ru/functions.anonymous.php
не понял что значит этот use, и когда надо и не надо его употреблять.
#278 #1027953
$STH->setFetchMode(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'secret_person');
Объясните, пожалуйста, что значит символ "|"? Это оператор? Гугл не помог. Я нашел только || - логическое ИЛИ.
#279 #1027968
Спрашивал уже раньше, но не могу найти свой пост: какие подводные камни в том, чтобы делать небольшой сайт в виде одной страницы, где весь контент разбит по динамически подгружающимся вкладкам? Просто у меня горит очко от мысли, что я буду копипастить кучу одинакового кода в разные страницы, шапку там, подвал. А если в них что-то нужно поменять будет? Это же пиздец.
Вот пример такого сайта: https://goo.gl/n7bfuT Сократил, потому что макака-пидор.
#280 #1027969
>>1027953

Чтобы разобраться в этой теме, придется почитать про двоичные числа. Любое число можно представить не только в обычной (10-ной) системе счисления, но и в двоичной. Например, 19 в десятичной = 10011 в двоичной.

https://ru.wikipedia.org/wiki/Двоичная_система_счисления

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

С числами в двоичной форме кроме обычных математических операций можно делать битовые операции вроде И или ИЛИ: https://ru.wikipedia.org/wiki/Битовые_операции

http://php.net/manual/ru/language.operators.bitwise.php

Если нам нужно как-то закодировать набор опций, каждая из которых может быть включена или выключена, мы можем использовать двоичные числа. То есть договориться, что например последний разряд в числе обозначает одну опцию (OPTION1 = 00001), предпоследний - другую (OPTION2 = 000010).

Тогда с помощью операции ИЛИ мы можем объединять эти опции: OPTION1 | OPTION2 = 0000011

В общем-то константы вроде PDO::FETCH_CLASS - это числа (можно проверить echo или var_dump), каждое из которых содержит одну единицу в двоичном виде, а с помощью операции ИЛИ их объединяют.

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

Чтобы проверить и закрепить знания, реши задачку:

- сделай набор из нескольких констант, каждая из которых будет представлять какую-то опцию, которая кодируется с помощью двоичных флагов (то есть константа хранит число, в двоичном виде содержащее ровно одну единицу)
- сделай функцию setBit, которая принимает на вход число и опцию, и возвращает число где установлен в единицу соответствующий опции бит
- сделай функцию clearBit, которая принимает на вход число и опцию, и возращает число, где соответствующий опции бит сброшен
- сделай функцию toggleBit, которая принимает на вход число и опцию и меняет соответствующий бит в числе на противоположный
- сделай функцию testBit, которая принимает на вход число и одну опцию и возвращает true/false в зависимости от того, включен в этом числе соответствующий флаг или нет
- сделай функцию countBits, которая принимает на вход число и возвращает число единиц в его двоичном представлении

Пример использования:

const OPTION_A= ...;
const OPTION_B = ...;
const OPTION_C = ...;

$flags = 0;
$flags = setBit($flags, OPTION_A);
$flags = setBit($flags, OPTION_B);

var_dump(testBit($flags, OPTION_A)); // true
var_dump(testBit($flags, OPTION_C)); // false

$flags = clearBit($flags, OPTION_A);
var_dump(testBit($flags, OPTION_A)); // false
var_dump(testBit($flags, OPTION_B)); // true

var_dump(countBits($flags)); // 1

Если что-то непонятно, уточняй.
#280 #1027969
>>1027953

Чтобы разобраться в этой теме, придется почитать про двоичные числа. Любое число можно представить не только в обычной (10-ной) системе счисления, но и в двоичной. Например, 19 в десятичной = 10011 в двоичной.

https://ru.wikipedia.org/wiki/Двоичная_система_счисления

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

С числами в двоичной форме кроме обычных математических операций можно делать битовые операции вроде И или ИЛИ: https://ru.wikipedia.org/wiki/Битовые_операции

http://php.net/manual/ru/language.operators.bitwise.php

Если нам нужно как-то закодировать набор опций, каждая из которых может быть включена или выключена, мы можем использовать двоичные числа. То есть договориться, что например последний разряд в числе обозначает одну опцию (OPTION1 = 00001), предпоследний - другую (OPTION2 = 000010).

Тогда с помощью операции ИЛИ мы можем объединять эти опции: OPTION1 | OPTION2 = 0000011

В общем-то константы вроде PDO::FETCH_CLASS - это числа (можно проверить echo или var_dump), каждое из которых содержит одну единицу в двоичном виде, а с помощью операции ИЛИ их объединяют.

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

Чтобы проверить и закрепить знания, реши задачку:

- сделай набор из нескольких констант, каждая из которых будет представлять какую-то опцию, которая кодируется с помощью двоичных флагов (то есть константа хранит число, в двоичном виде содержащее ровно одну единицу)
- сделай функцию setBit, которая принимает на вход число и опцию, и возвращает число где установлен в единицу соответствующий опции бит
- сделай функцию clearBit, которая принимает на вход число и опцию, и возращает число, где соответствующий опции бит сброшен
- сделай функцию toggleBit, которая принимает на вход число и опцию и меняет соответствующий бит в числе на противоположный
- сделай функцию testBit, которая принимает на вход число и одну опцию и возвращает true/false в зависимости от того, включен в этом числе соответствующий флаг или нет
- сделай функцию countBits, которая принимает на вход число и возвращает число единиц в его двоичном представлении

Пример использования:

const OPTION_A= ...;
const OPTION_B = ...;
const OPTION_C = ...;

$flags = 0;
$flags = setBit($flags, OPTION_A);
$flags = setBit($flags, OPTION_B);

var_dump(testBit($flags, OPTION_A)); // true
var_dump(testBit($flags, OPTION_C)); // false

$flags = clearBit($flags, OPTION_A);
var_dump(testBit($flags, OPTION_A)); // false
var_dump(testBit($flags, OPTION_B)); // true

var_dump(countBits($flags)); // 1

Если что-то непонятно, уточняй.
#281 #1027970
>>1027968

Если шапка одинаковая, зачем ее копипастить, когда можно просто вынести ее в отдельный файл? И объединить шапку с содержимым используя например PHP (это 2 строчки кода)?
105 Кб, 881x637
#282 #1027976
Кароч.
Я нихуя не понимаю что ему надо.
REEEE
#283 #1027987
>>1027976
Тебе же красным выделели условия, которые ты не выполнил, дебил.
#284 #1028003
>>1027942
Забирает себе значение $variable на время определения функции для дальнейшего использования. То есть если ты создал функцию, а $variable не определил ещё, то будет у твоей функции $variable будет всегда NULL. Иначе нужно &$variable писать, чтобы по ссылке передавало. Тогда берёт значение на момент выполнения.
#285 #1028008
>>1027976

Если ты вызываешь функцию sequence без указания step или start то они должны быть равны 1 и 0 соответственно.
#286 #1028010
>>1027987

Не надо писать комментарии, которые ничем не помогают и не содержат полезной информации.
98 Кб, 870x593
#287 #1028026
>>1028008
У меня почему-то в голове переклинило, что требования были к возвращаемой функции, и моск завис.
#288 #1028153
>>1028026

Да, там вообще не очень легко разобраться, так как тут функция возвращает другую функцию и не очень понятно, как их различать.
#289 #1028155
Может кто просветить про пхп-уязвмимости?
Как не обосраться в том случае, если какой нибудь мамкин мистер робот решит взломать твой сайт?
#291 #1028164
>>1027510

В данном случае это примерно такой же вопрос, а почему нет замены unix для серверных машин, потому что 80% на этом работает. Хорошо это или плохо -- вопрос уже сугубо субъективных частностей.
#292 #1028171
>>1028161
Годно, есть ещё?
#293 #1028172
>>1028164
Чем отличается какой нибудь питон/руби/ещё что то фреймворк от пхп?
Лёгкостью? А в чем эта легкость заключается?
сорре за тупой вопрос
someApprentice #295 #1028199
Важный вопрос которые мне не дает покоя, и я не могу продолжить решать задачу пока не разберусь с ним

https://arhivach.org/thread/261841/#1000397

>Насчет проектирования БД - там тоже много тонкостей есть, можно делать нормальзованную схему, но лучше денормализовывать ради повышения производительности. Ну например, возьмем то же сообщение. Можно хранить его в одном экземпляре, а можно в двух - в inbox получателя и в outbox отправителя. Это может облегчить выборку последних N сообщений, так как твой запрос с OR вряд ли хорошо ложится на индексы (вдобавок у тебя еще и сортировки там нет).


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

Думаю лучше отложить пока идею с редактированием\удалением.

Такой же вопрос, и с inbox и outbox - в них те же самые сообщения будут иметь разные ID. Это неизбежно делать отдельную колонку и генерировать ID программно?

Или я не правильно понял структуру этих таблиц?

Никак не могу сформулировать структуру при реализации конференций... Попробую представить это здесь

Conferences
id
tete-a-tete //true or false (приватные переписки тоже будут представлены как конференции из двух человек для унификации кода)

Participants
id //Не уверен что от этой колонки будет толк, обычно всегда делают id
conferenceID
userID

Contacts
id
userID
conferenceID

Inbox
id
conferenceID
userID // ID пользователя которому принадлежит ящик
messageID
authorID
content
...

Outbox
id
conferenceID
userID // ID пользователя которому принадлежит ящик
messageID
authorID
content
...

Соответственно получение сообщений происходит одним запросом SELECT FROM Inbox WHERE conferenceID = :conferenceID AND userID = :userID UNION SELECT FROM Outbox WHERE conferenceID = :conferenceID AND userID = :userID

Вроде должно быть так?

----

Забыл ещё спросить в предыдущем посте

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

https://jsfiddle.net/jsqt57hz/

MVC style:
https://jsfiddle.net/hmgz7200/

Чтобы это пификсить нужно убрать с элемента обработчик функцией .off()

//Странно что не получилось написать $('body).off('submit', form, handleFormSubmit), как в примере мануала
https://jsfiddle.net/jsqt57hz/1/

Я всё правильно делаю?

>>1027651

>У меня есть идея как при отключенном js опускать окно диалога до последнего сообщения - использовать якори. Я уже делаю что-то подобное при получении более старых сообщениях (при выключенном js):


>Но для этого нужно сделать несколько лишних запросов к БД:


Это должно быть сделано с помощью функций JOIN и GROUP:

SELECT Contacts.userID, Messages.messageID as lastMessage
FROM Contacts
INNER JOIN Messages ON Contacts.userID= Messages.userID
GROUP BY Contacts.userID
ORDER BY Messages.date DESC

Простите что трачу ваше время. Мне действительно очень очень жаль так поступать. Надеюсь у меня всё получиться чтобы всё было не зря.
someApprentice #295 #1028199
Важный вопрос которые мне не дает покоя, и я не могу продолжить решать задачу пока не разберусь с ним

https://arhivach.org/thread/261841/#1000397

>Насчет проектирования БД - там тоже много тонкостей есть, можно делать нормальзованную схему, но лучше денормализовывать ради повышения производительности. Ну например, возьмем то же сообщение. Можно хранить его в одном экземпляре, а можно в двух - в inbox получателя и в outbox отправителя. Это может облегчить выборку последних N сообщений, так как твой запрос с OR вряд ли хорошо ложится на индексы (вдобавок у тебя еще и сортировки там нет).


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

Думаю лучше отложить пока идею с редактированием\удалением.

Такой же вопрос, и с inbox и outbox - в них те же самые сообщения будут иметь разные ID. Это неизбежно делать отдельную колонку и генерировать ID программно?

Или я не правильно понял структуру этих таблиц?

Никак не могу сформулировать структуру при реализации конференций... Попробую представить это здесь

Conferences
id
tete-a-tete //true or false (приватные переписки тоже будут представлены как конференции из двух человек для унификации кода)

Participants
id //Не уверен что от этой колонки будет толк, обычно всегда делают id
conferenceID
userID

Contacts
id
userID
conferenceID

Inbox
id
conferenceID
userID // ID пользователя которому принадлежит ящик
messageID
authorID
content
...

Outbox
id
conferenceID
userID // ID пользователя которому принадлежит ящик
messageID
authorID
content
...

Соответственно получение сообщений происходит одним запросом SELECT FROM Inbox WHERE conferenceID = :conferenceID AND userID = :userID UNION SELECT FROM Outbox WHERE conferenceID = :conferenceID AND userID = :userID

Вроде должно быть так?

----

Забыл ещё спросить в предыдущем посте

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

https://jsfiddle.net/jsqt57hz/

MVC style:
https://jsfiddle.net/hmgz7200/

Чтобы это пификсить нужно убрать с элемента обработчик функцией .off()

//Странно что не получилось написать $('body).off('submit', form, handleFormSubmit), как в примере мануала
https://jsfiddle.net/jsqt57hz/1/

Я всё правильно делаю?

>>1027651

>У меня есть идея как при отключенном js опускать окно диалога до последнего сообщения - использовать якори. Я уже делаю что-то подобное при получении более старых сообщениях (при выключенном js):


>Но для этого нужно сделать несколько лишних запросов к БД:


Это должно быть сделано с помощью функций JOIN и GROUP:

SELECT Contacts.userID, Messages.messageID as lastMessage
FROM Contacts
INNER JOIN Messages ON Contacts.userID= Messages.userID
GROUP BY Contacts.userID
ORDER BY Messages.date DESC

Простите что трачу ваше время. Мне действительно очень очень жаль так поступать. Надеюсь у меня всё получиться чтобы всё было не зря.
#296 #1028309
>>1028199
Обратись в баз данных тред, может там помогут.
#297 #1028373
в Yii2 нельзя использовать CamelCase в названии контроллера с prettyUrl ? Если можно то как получить доступ к контроллеру SomeCamelCaseController к actionIndex ?
#298 #1028374
>>1020029
Хммм, феласаф
#299 #1028469
помогите решить задачку

Ответ на любой вопрос это же google!

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

Подсказка: здесь тебе могла бы помочь функция array_rand()

http://ideone.com/eyM8V0

главная проблема не выводится значение массива
#300 #1028470
>>1028003

>Тогда берёт значение на момент выполнения



Как это понять? Если у меня выше по коду например вообще нет такой переменной, что будет взято в &$variable?
#301 #1028473
>>1028470
NULL же.
#302 #1028488
>>1028172

>Чем отличается какой нибудь питон/руби/ещё что то фреймворк от пхп?


>Лёгкостью? А в чем эта легкость заключается?


>сорре за тупой вопрос



Да ничем, если так подумать. Большинство из этих фреймворков MVC, поэтому очень друг на друга похожи. В той или иной степени реализуют парадигму ООП. В общем, это вопрос вкусов, хотя где-то в виду хайлоада будет более применим какой-нибудь руби или питон, нежели пхп. Но не более того.
#303 #1028510
>>1028373
Дефисы у меня работали. Первая же ссылка в гугле подтверждает: https://github.com/yiisoft/yii2/issues/493

>>1028469

> главная проблема не выводится значение массива


В документации array_rand написано "returns the key (or keys) of the random entries.", то есть функция возвращает ключ (индекс элемента), а не значение: http://php.net/manual/en/function.array-rand.php
Тебе нужно обратиться к элементу массива под этим новым случайным индексом, тогда получишь значение.

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

$n = 3;
array_filter([1,2,3,4,5], function ($el) { return $el > $n; });

PHP скажет, что $n не определена внутри функции.
А с этим кодом всё ок:

$n = 3;
array_filter([1,2,3,4,5], function ($el) use ($n) { return $el > $n; });

>>1028470
Тебе же никто не запрещает просто взять и проверить.

>>1027969
Интересные задачи, нужно порешать.
#304 #1028550
>>1027942

use описан тут http://php.net/manual/ru/functions.anonymous.php

Он позволяет передать копию значения переменной снаружи внутрь анонимной функции (по умолчанию в функции доступны только созданные внутри нее переменные). Если использовать &$foo вместо $foo, то передается не копия значения, а ссылка на саму переменную, и код внутри функции может менять эту переменную.

>>1028199

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

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

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

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

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

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

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

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

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

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

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

В общем, есть 2 варианта, предлагаю сравнить их преимущества и недостатки.

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

Также, вопрос еще, где хранить ключи. Можно иметь единый ключ пользователя, хранящийся на сервере и зашифрованный паролем (устройства скачивает шифрованный ключ и расшифровывает локально). Либо же можно для каждого устройства иметь свой ключ и не сохранять его на сервер. Но тогда отправитель или сервер должен шифровать каждое сообщение всеми пользовательскими ключами, чтобы его можно было прочесть на любом устройстве. По моему так сделано в iMessage: https://images.apple.com/business/docs/iOS_Security_Guide.pdf , страница 43:

> When a user turns on iMessage on a device, the device generates two pairs of keys for


use with the service: an RSA 1280-bit key for encryption and an ECDSA 256-bit key on
the NIST P-256 curve for signing. The private keys for both key pairs are saved in the
device’s Keychain and the public keys are sent to Apple’s directory service (IDS), where
they are associated with the user’s phone number or email address, along with the
device’s APNs address.

> The user’s outgoing message is individually encrypted for each of the receiver’s


devices.

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

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

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


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

> Никак не могу сформулировать структуру при реализации конференций..


Таблица "чаты": chat.id, chat.name, таблица для хранения списка участников (с периодом времени): participant.userId, participant.chatId, participant.since, participant.till. Ну и соответственно таблицы для хранения сообщений, вид которых зависит от выбранной схемы.

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

Что касается твоей схемы, вместо 2 таблиц inbox/outbox можно сделать одну с полем типа сообщения.

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


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

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

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

В твоем примере кода, когда ты вставляешь HTML код из template в DOM, тогда же надо и ставить обработчики, и делать это только один раз. То есть сделать например так:

Widget.prototype.handleShowFormButton = function() {
this.view.button.click(this.showForm.bind(this));
}

Widget.prototype.showForm = function () {
if (!this.view.isFormCreated()) {
this.view.createForm(); // создает форму без проверки, есть она или нет
this.handleFormSubmit(); // ставит на нее обработчики
}
};

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

> Чтобы это пификсить нужно убрать с элемента обработчик функцией .off()


Выглядит как костыль. Проще просто не ставить обработчик несколько раз.

> У меня есть идея как при отключенном js опускать окно диалога до последнего сообщения - использовать якори.


> Это должно быть сделано с помощью функций JOIN и GROUP:


Я не очень понял, как выравнивание сообщений связано с SQL-запросами?

> трачу ваше время.


А я отвечаю только когда есть свободное время, так что ничего страшного
#304 #1028550
>>1027942

use описан тут http://php.net/manual/ru/functions.anonymous.php

Он позволяет передать копию значения переменной снаружи внутрь анонимной функции (по умолчанию в функции доступны только созданные внутри нее переменные). Если использовать &$foo вместо $foo, то передается не копия значения, а ссылка на саму переменную, и код внутри функции может менять эту переменную.

>>1028199

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

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

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

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

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

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

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

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

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

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

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

В общем, есть 2 варианта, предлагаю сравнить их преимущества и недостатки.

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

Также, вопрос еще, где хранить ключи. Можно иметь единый ключ пользователя, хранящийся на сервере и зашифрованный паролем (устройства скачивает шифрованный ключ и расшифровывает локально). Либо же можно для каждого устройства иметь свой ключ и не сохранять его на сервер. Но тогда отправитель или сервер должен шифровать каждое сообщение всеми пользовательскими ключами, чтобы его можно было прочесть на любом устройстве. По моему так сделано в iMessage: https://images.apple.com/business/docs/iOS_Security_Guide.pdf , страница 43:

> When a user turns on iMessage on a device, the device generates two pairs of keys for


use with the service: an RSA 1280-bit key for encryption and an ECDSA 256-bit key on
the NIST P-256 curve for signing. The private keys for both key pairs are saved in the
device’s Keychain and the public keys are sent to Apple’s directory service (IDS), where
they are associated with the user’s phone number or email address, along with the
device’s APNs address.

> The user’s outgoing message is individually encrypted for each of the receiver’s


devices.

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

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

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


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

> Никак не могу сформулировать структуру при реализации конференций..


Таблица "чаты": chat.id, chat.name, таблица для хранения списка участников (с периодом времени): participant.userId, participant.chatId, participant.since, participant.till. Ну и соответственно таблицы для хранения сообщений, вид которых зависит от выбранной схемы.

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

Что касается твоей схемы, вместо 2 таблиц inbox/outbox можно сделать одну с полем типа сообщения.

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


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

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

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

В твоем примере кода, когда ты вставляешь HTML код из template в DOM, тогда же надо и ставить обработчики, и делать это только один раз. То есть сделать например так:

Widget.prototype.handleShowFormButton = function() {
this.view.button.click(this.showForm.bind(this));
}

Widget.prototype.showForm = function () {
if (!this.view.isFormCreated()) {
this.view.createForm(); // создает форму без проверки, есть она или нет
this.handleFormSubmit(); // ставит на нее обработчики
}
};

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

> Чтобы это пификсить нужно убрать с элемента обработчик функцией .off()


Выглядит как костыль. Проще просто не ставить обработчик несколько раз.

> У меня есть идея как при отключенном js опускать окно диалога до последнего сообщения - использовать якори.


> Это должно быть сделано с помощью функций JOIN и GROUP:


Я не очень понял, как выравнивание сообщений связано с SQL-запросами?

> трачу ваше время.


А я отвечаю только когда есть свободное время, так что ничего страшного
#305 #1028560
>>1028199

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

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

Но тебе наверно пока лучше разобраться с тем, что есть.

Ну и если есть желание, то почитать информацию о протоколе Tox:

- https://en.wikipedia.org/wiki/Tox_(protocol)
- https://github.com/Tox-Docs/Text/tree/master/src_text

и Signal:

- https://en.wikipedia.org/wiki/Signal_Protocol
- https://whispersystems.org/docs/
#306 #1028568
>>1028560

>Вообще, мне тут пришла в голову мысль


http://graphql.org ???
7 Кб, 225x225
#307 #1028581
нахуя вы изучаете эту парашу?вам делать нехуй?
#308 #1028589
>>1028581
Так некуда деваться, в мухосрансках есть только два стула, 1C и сладкий хлебушек. Но 1C это вообще не программирование.
На фрилансе тоже хуй найдешь заказы на Java ну или desktop разработку.
#309 #1028597
А вообще у человека гибкая психика, он ко всему привыкает. Можно привыкнуть жрать тухлятину с червями. Можно привыкнуть к сидению у параши и ебле в жопу. А уж писать код на PHP это вообще ерунда, как нехуй делать. Только первый месяц неприятно, потом привыкаешь ко всему: и к доллару, и к переменным без объявления, и к другому порядку тернарного оператора, и к отсутствию code style в стандартных функциях... Главное, что за это тебе деньги платят.
#310 #1028606
>>1027969
Спасибо за ответ.
#311 #1028612
Аноны помогите пожалауйста не могу понять.

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

Гуглил но как то ничего не поняля тупой
#312 #1028655
>>1028597
Ваистену!

мимо 110k php-джун
#313 #1028673
>>1028510

> главная проблема не выводится значение массива


В документации array_rand написано "returns the key (or keys) of the random entries.", то есть функция возвращает ключ (индекс элемента), а не значение: http://php.net/manual/en/function.array-rand.php
Тебе нужно обратиться к элементу массива под этим новым случайным индексом, тогда получишь значение.

спасибо гуру
#314 #1028685
>>1028510
Теперь понятно.

Без use — undefined

use ($variable) — только внутрь

use (&$variable) — внутрь и наружу

Единственный вопрос остался: зачем это нужно вообще, если есть аргументы??
#315 #1028769
>>1028589
Много работы по верстке и жсу.
68 Кб, 500x657
#316 #1028780
>>1028769
А фронтенд прям не параша, да?
33 Кб, 720x304
#317 #1028781
>>1028769

>верстке и жсу.


Увлекательно.
#318 #1028818
>>1028780
>>1028781
а жаба типа круче?
#319 #1028838
>>1028818
При чём здесь жаба? Тут пхп-тред.
#320 #1029108
>>1027976
Это ПХП? Если так то синтаксис так на С похож.
Я нуфак, только вкатился в ваш тред.
#321 #1029130
Повесил функцию из замыкания на листенер, следящий за нажатиями клавиш. Она должна вызывать другую функцию из этого же замыкания, но не видит её. Теперь по this ей передаётся window!
Решил проблему, сославшись в функции на глобальную переменную самого замыкания. А как это сделать нормально?
1 Кб, 511x32
#323 #1029149
Как передавать в конструктор значение с поля класса? Мне лень в каждый объект ручками все добавлять, когда все эти значения и так есть в классе. Делаю задачу ОПа. http://ideone.com/1z228K
#324 #1029161
>>1029149

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



Убери параметры из конструктора( или сам конструктор, судя по описанию, он тебе только мешает), он просто будет выполнять код при создании объекта.
#325 #1029194
хочу сделать запись реквестов несуществующих страниц
по типу
кто-то пытается зайти на
site.com/analplugs
его редиректит на главную
site.com
а site.com/analplugs записывается в бд
редирект понятно через какой-нибудь htaccess можно сделать, но как это совместить с записью в бд?
#326 #1029221
>>1029194
Сервак и без тебя ведет логи запросов ко всем ресурсам, в том числе и несуществующим.
#327 #1029230
Привет, что почитать по паттернам?

И может кто, предложить решение этой задачи?
https://pastebin.com/Mmiz1HDU
Я смог наваять только такое:
https://pastebin.com/bwMZHvkg
Понимаю что криво, но куда копать не пойму.
Может, подскажите чего?
#328 #1029262
>>1029221
хочу именно через бд
#329 #1029274
>>1029147
Да, похоже, оно. Благодарю.
someApprentice #330 #1029290
>>1028550

>В общем, есть 2 варианта, предлагаю сравнить их преимущества и недостатки.


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

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


>Можно сделать 2 таблицы, одна для хранения id сообщений, другая для хранения зашифрованных копий сообщений для каждого получателя.


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


Действительно, можно создать таблицу специально чтобы только хранить id, а ящики Inbox и Outbox будут хранить ещё и всё остальное (автора, контент, дату и т.д.).

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


Да, я тоже размышлял об этом. Мне нужно ещё подумать как тут лучше поступить.

Шифрование

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

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

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


>устройства скачивает шифрованный ключ и расшифровывает локально


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

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


Значит нужно оставить это на дальнейшую реализацию.

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


>Это проблема в твоем коде, что ты так делаешь. Не надо назначать обработик несколько раз.


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


У меня элемент постоянно обновляется и постоянно нужно ставить новый обработчик.

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


Вот так https://jsfiddle.net/jsqt57hz/2/ ?

>В твоем примере кода, когда ты вставляешь HTML код из template в DOM, тогда же надо и ставить обработчики, и делать это только один раз.


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

https://arhivach.org/thread/266631/#1018809

>> А что если элемент появляется не сразу? Логично будет задать тогда при его выводе элемента (то есть обработчик будет частью отображения) или в контроллере?


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



> У меня есть идея как при отключенном js опускать окно диалога до последнего сообщения - использовать якори.


> Это должно быть сделано с помощью функций JOIN и GROUP:


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

Мы с помощью SQL-запросов получаем контакты и последние сообщения, и в ссылку контакта вставляем якорь на id последнего сообщения:

><a class="contact" ... href="conversation.php? ... #message-ID">someUser</a>


><div id="message-ID ... class="message">



Заодно можно сделать и сортировку контактов по последним полученным сообщениям.
someApprentice #330 #1029290
>>1028550

>В общем, есть 2 варианта, предлагаю сравнить их преимущества и недостатки.


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

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


>Можно сделать 2 таблицы, одна для хранения id сообщений, другая для хранения зашифрованных копий сообщений для каждого получателя.


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


Действительно, можно создать таблицу специально чтобы только хранить id, а ящики Inbox и Outbox будут хранить ещё и всё остальное (автора, контент, дату и т.д.).

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


Да, я тоже размышлял об этом. Мне нужно ещё подумать как тут лучше поступить.

Шифрование

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

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

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


>устройства скачивает шифрованный ключ и расшифровывает локально


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

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


Значит нужно оставить это на дальнейшую реализацию.

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


>Это проблема в твоем коде, что ты так делаешь. Не надо назначать обработик несколько раз.


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


У меня элемент постоянно обновляется и постоянно нужно ставить новый обработчик.

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


Вот так https://jsfiddle.net/jsqt57hz/2/ ?

>В твоем примере кода, когда ты вставляешь HTML код из template в DOM, тогда же надо и ставить обработчики, и делать это только один раз.


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

https://arhivach.org/thread/266631/#1018809

>> А что если элемент появляется не сразу? Логично будет задать тогда при его выводе элемента (то есть обработчик будет частью отображения) или в контроллере?


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



> У меня есть идея как при отключенном js опускать окно диалога до последнего сообщения - использовать якори.


> Это должно быть сделано с помощью функций JOIN и GROUP:


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

Мы с помощью SQL-запросов получаем контакты и последние сообщения, и в ссылку контакта вставляем якорь на id последнего сообщения:

><a class="contact" ... href="conversation.php? ... #message-ID">someUser</a>


><div id="message-ID ... class="message">



Заодно можно сделать и сортировку контактов по последним полученным сообщениям.
#331 #1029314
Привет, помогите советом

Как дебажить Request/Response между React+Redux и Silex?

Я пытаюсь отправить POST запрос с помощью метода Fetch() на api своего приложения.
В хроме я вижу что запрос отправлен, и содержит некоторые данные, которые я отправляю.
Но, не могу получить эти данные в контроллере из Request с помощью all() и записать их в лог,
Monolog пишет пустую строку (или ноль).
Данные перед отправкой обрабатываю JSON.stringify(data) https://github.com/enotocode/birthday_reminder/blob/master/src/client/Login/actions.js#L49
на сервере массив из реквеста превращаю в строку implode() и пишу info(printf(data)) https://github.com/enotocode/birthday_reminder/blob/master/src/server/Controllers/SignupController.php#L23
Лог https://github.com/enotocode/birthday_reminder/blob/master/src/server/public/development.log#L51
Почему не получается вытянуть из реквеста данные? В чем может быть проблема?
159 Кб, 1304x768
#332 #1029319
>>1029314
Скрин из Chrome Devtools
#333 #1029322
>>1029319
а что в $_POST то ?
#334 #1029324
>>1029322
А как посмотреть?
Monolog выводит в лог пустую строку: log=implode($_POST); info(log)
#335 #1029327
>>1029324
просто сделай
var_dump($_POST, $_GET);exit;
и глянь в хроме ответ сервера
#336 #1029332
>>1029327

>var_dump($_POST, $_GET);exit;



array(size=0)
array(size=0)
#337 #1029335
>>1029314
>>1029327
После того как указал заголовки для запроса в аргументах к fetch ('Content-type', 'application/json; charset=utf-8'), монолог записал данные из запроса в лог. Но $_POST все равно пустой на момент срабатывания request->all()
#338 #1029339
>>1029314

Смотреть надо в инструментах разработчика - на тип запроса, на Content-Type и тело запроса (можно нажать view source рядом с request payload).

PHP при поступлении POST-запроса разбирает тело запроса и помещает параметры в переменную $_POST, откуда их берет Request.

Но PHP разбирает не любые данные, а только данные в 2 форматах (которые использует браузер для форм):

http://php.net/manual/ru/reserved.variables.post.php

> Ассоциативный массив данных, переданных скрипту через HTTP метод POST в случае использования в запросе в качестве HTTP Content-Type application/x-www-form-urlencoded или multipart/form-data .



Ты передаешь данные в каком-то своем придуманном формате и естественно что PHP их игнорирует. Причем формат у тебя странный - данные передаешь как JSON но с типом plain/text.

Проще всего не использовать JSON, а использовать один из стандартных способов кодирования. Либо использовать JSON и в PHP самому разбирать тело запроса.

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

Также, завис на этом коде, пока не понял, что тут 2 функции:

> .then(


> response => response.json(),


> error => console.log('An error occured.', error)


> )



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

Также, по моему у тебя ошибка в обработчике ошибок. error => console.log('An error occured.', error) возвращает null и это значит что дальше выполнится блок then с этим null ( json => dispatch(recieveInputs(json)) ). То есть ты как бы "обработал" ошибку и превратил ее в успешный результат. Если ты не выбросил исключение то это значит что ошибка полностью обработана.

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

Чтобы проверить, что ты разбираешься, вот тебе вопрос.

Что если сервер вернет неправильный JSON? В этом случае response => response.json выкинет исключение, then() его перехватит и что будет дальше? Выведется ли сообщение об ошибке или будет потеряно?
#338 #1029339
>>1029314

Смотреть надо в инструментах разработчика - на тип запроса, на Content-Type и тело запроса (можно нажать view source рядом с request payload).

PHP при поступлении POST-запроса разбирает тело запроса и помещает параметры в переменную $_POST, откуда их берет Request.

Но PHP разбирает не любые данные, а только данные в 2 форматах (которые использует браузер для форм):

http://php.net/manual/ru/reserved.variables.post.php

> Ассоциативный массив данных, переданных скрипту через HTTP метод POST в случае использования в запросе в качестве HTTP Content-Type application/x-www-form-urlencoded или multipart/form-data .



Ты передаешь данные в каком-то своем придуманном формате и естественно что PHP их игнорирует. Причем формат у тебя странный - данные передаешь как JSON но с типом plain/text.

Проще всего не использовать JSON, а использовать один из стандартных способов кодирования. Либо использовать JSON и в PHP самому разбирать тело запроса.

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

Также, завис на этом коде, пока не понял, что тут 2 функции:

> .then(


> response => response.json(),


> error => console.log('An error occured.', error)


> )



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

Также, по моему у тебя ошибка в обработчике ошибок. error => console.log('An error occured.', error) возвращает null и это значит что дальше выполнится блок then с этим null ( json => dispatch(recieveInputs(json)) ). То есть ты как бы "обработал" ошибку и превратил ее в успешный результат. Если ты не выбросил исключение то это значит что ошибка полностью обработана.

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

Чтобы проверить, что ты разбираешься, вот тебе вопрос.

Что если сервер вернет неправильный JSON? В этом случае response => response.json выкинет исключение, then() его перехватит и что будет дальше? Выведется ли сообщение об ошибке или будет потеряно?
#339 #1029394
>>1029339

>Но PHP разбирает не любые данные, а только данные в 2 форматах (которые использует браузер для форм)


Значит переменные $_POST и $_GET будут всегда пусты, если передавать данные в JSON формате? Существуют еще удобные способы проверять данные, которые получил PHP в теле запроса POST?

>Причем формат у тебя странный - данные передаешь как JSON но с типом plain/text.


Исправил, добавив заголовок ('Content-type', 'application/json; charset=utf-8');

>Проще всего не использовать JSON, а использовать один из стандартных способов кодирования.


Почему так проще? Для urlenencoded и form-data нужно специально кодировать данные менее удобным способом, чем JSON.stringify(). Или ты имеешь ввиду если передавать их из формы?

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


>Также, по моему у тебя ошибка в обработчике ошибок.


Это условный код из мануала Redux, я еще не смотрел как сделаны реальные приложения. Но написано, что тут в конце цепочки не следует добавлять блок catch во избежание цикла с ошибкой 'Unexpected batch number' если рендеришь результат. Каменистое дно.

>Что если сервер вернет неправильный JSON? В этом случае response => response.json выкинет исключение, then() его перехватит и что будет дальше? Выведется ли сообщение об ошибке или будет потеряно?


Браузер вероятно выведет ошибку в консоли, и наверное она попадет в качестве аргумента в recieveInputs(json)
#340 #1029411
>>1029394

charset добавляется только для содержимого с типом text/*. В JSON кодировка определена стандартом и указывать ее не надо.
#341 #1029508
test
#342 #1029515
>>1029230
сохранение через сингелтон очевидно ,

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


тут я думаю нужно делать как то через фабрику

ну и точно нужно делить расчёт балов в модель\AR
#343 #1029518
>>1029194
нужно писать хендлер , и когда реквест будет на не существ страницу , ловить это и записывать в бд после делать редирект на главную
#344 #1029519
>>1029149
если они уже есть в классе то в методе класса ты можешь ими оперировать через $this->foo , очевидно если это не статический метод
#345 #1029521
>>1029108
это js , синтаксис на c похож у многих языков , так как они почти все дети с языка
#346 #1029522
>>1028612
запихнуть их очевидно в форму и делать сабмит
https://stackoverflow.com/questions/2309801/how-to-submit-checkbox-values-with-php-post-method
#347 #1029523
>>1029394

>Значит переменные $_POST и $_GET будут всегда пусты, если передавать данные в JSON формате? Существуют еще удобные способы проверять данные, которые получил PHP в теле запроса POST?


>


пост будет пуст да , способы есть https://stackoverflow.com/questions/40108736/php-get-json-post-data
#348 #1029537
>>1029522
пиздец. Просто пиздец всё оказалось настолько просто. Спасибо тебе огромнейшее я столько думал над этим.
#349 #1029538
Скока надо дрочиться, чтобы получать 100 к ? За год полтора так вырасти можно ??
#350 #1029540
>>1029538
Все же от тебя зависит. От того как ты усваиваешь информацию и от того, сколько времени ты будешь уделять своему обучению.

Всё в твоих руках.
#351 #1029553
>>1029538

Маловероятно. Если бы все было так просто, все бы давно уже устроились работать программистами. Так как в РФ средняя зарплата за апр. 2017 - 38906 руб, а медианная (50% людей получают меньше этой цифры) - около 30 000 р

Лучше поспрашивать у анонов, которые уже прошли обучение и устроились на работу. Например, в работа-треде который тут где-то есть.
#352 #1029569
>>1029538
если дрочиться только ради 100к то примерно никогда ...
#353 #1029579
>>1029521
Ну так то да.
#354 #1029581
>>1029394
>>1029339

>>Что если сервер вернет неправильный JSON? В этом случае response => response.json выкинет исключение, then() его перехватит и что будет дальше? Выведется ли сообщение об ошибке или будет потеряно?


>Браузер вероятно выведет ошибку в консоли, и наверное она попадет в качестве аргумента в recieveInputs(json)



Прочитал про промисы статью кантора внимательнее, и провел эксперимент, если метод response.json() выкинет ошибку, то она не будет отображаться в консоли пишет кантор (но Chrome ее выводит), и поскольку следующий блок then() не имеет функции rejected, чтобы его вызвать, и в конце цепочки нет catch, то можно считать, шибка будет потеряна.
#355 #1029583
>>1029411

>charset добавляется только для содержимого с типом text/*. В JSON кодировка определена стандартом и указывать ее не надо.


Лол, пример взял из учебника Кантора. Проверил сам, действительно в стандарте написано что JSON text SHALL be encoded in UTF-8, UTF-16, or UTF-32, и UTF-8 по дефолту. Но разве это не подходит под случай "явное лучше не явного"?
#356 #1029610
>>1029569
Почему ты так считаешь?
#357 #1029613
>>1029553

>средняя зарплата за апр. 2017 - 38906 руб


Чиво, блядь? Я про ДС, есличо. Тут стажёр эти ёбаные 40к будет получать уже в первый месяц работы.
#358 #1029614
>>1029540
Два чая, ток тут не про обучение будет верно, а вообще про все. Если сильно захочет то будет и 200к получать, конечно если хватит ума, а так если он обычный таракан который решил, что это легко и на этом можно навариться, то правильно его тралят.
#359 #1029617
Поцаны смотрите че сделал
file:///C:/Users/microwavenovka/Desktop/HTML5/Learning/Learn1.html
#360 #1029622
>>1029614

>конечно если хватит ума


Помимо ума ещё нужны soft skills. За 200к их от тебя будут требовать, ибо выполняемые тобой функции будут выходить за рамки тупого кодинга.
#361 #1029681
>>1029617
круто))))0000
someApprentice #362 #1029721
>>1028550

>Что касается твоей схемы, вместо 2 таблиц inbox/outbox можно сделать одну с полем типа сообщения.


А можно вообще не указывать этот тип. Зачем это может пригодиться?
#363 #1029807
Начал вкатываться, какую версию php ставить?
Пятую или седьмую?
#364 #1029813
>>1029807
можешь начать с 5.6 базовые знания применимы и для 7 , но на 5.6 ещё много легаси кода что == работе
#365 #1029817
>>1029813
А 7 и 5.6 совместимы или нет?
#366 #1029818
>>1029817
Всё, что написано на 5.6, будет работать на 7.
#367 #1029823
>>1029515

>сохранение через сингелтон очевидно


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

>через фабрику


Зачем фабрику, почему не декоратор?

>ну и точно нужно делить расчёт балов в модель\AR


Это вообще не понял.
69 Кб, 879x681
#368 #1029832
Аноны, почему ideone ничего не выводит?
#369 #1029839
>>1029581

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

Потому в спецификации добавили "костыль" (на мой взгляд костыль) - они сделали вывод необработанных ошибок в консоль на следующем шаге цикла событий и сделали событие, по моему unhandledrejection, чтобы ловить такие ошибки программно. Потому ты видишь сообщение в консоли.
#370 #1029845
>>1029823

>декоратор


так как декоратор расширяет класс , а фабрика описывает действие которое может быть реализовано в разных типах вопросов по разному
#371 #1029846
>>1029832
Потому что тело твоего цикла не выполняется ни разу. Уже в самом начале условие продолжения цикла $credit <= 5000 ложно.
#372 #1029847
>>1029832
так как 1 всегда будет меньше 5000 , перечитай как работают циклы
#373 #1029848
Почему здесь все таки няши, Рика в ОПпосте и хорошая шапка? Спасибо вам за то, что вы есть
#374 #1029859
>>1029846
>>1029847
Бля пиздец. Спасибо
#375 #1029861
Аноны, а как сделать, что бы вместо локалхост в адресной строке было название папки, в которой лежит сайт? Wamp сервер
#376 #1029878
>>1029861
1. Настроить сервер и C:\Windows\System32\drivers\etc\hosts
2. Использовать протухший денвер
3. Перестать насиловать мозг бессмысленной херней и использзваь php -S 127.0.0.1:8888
#377 #1029880
Блять как мне нравится название треда, благослави опа анон.
#378 #1029882
>>1029878

>использзваь


использовать
#379 #1029891
>>1029878
Про последнее не понял, что это такое, анон?
В денвере, кстати, тоже локалхост
49 Кб, 900x450
#380 #1029892
Анон, такое дело. Первый день вообще пытаюсь делать скрипты из мануала. Решил улучшить задание на "условия", сделав дополнительный 3-ий кубик. Дополнительное условие на "дабл" получилось, на трипл - нет. Подскажи, пожалуйста, как лучше вбить 3 параметра в условие. Алсо, может есть какие замечания по имеющемуся коду?
#381 #1029906
Аноны, как прикрутить дебаггер к phpStorm?
#383 #1029914
>>1029911
Ебать, я такое в жизни не осилю
348 Кб, 800x599
#384 #1029916
>>1029891
Учи матчасть. Браузер узнает ip адрес сайта c благодаря dns или файлу hosts. Денвер перезаписывал на лету hosts в соответствии с именем папки. Но это все мхом поросло, c тех пор как в php встроили сервер и все современные фреймворки умеют запускать сайт в режиме разработки через него. Это обязательная часть скафолдинга. Ты сам можешь сам запускать php -S ip:port из папки с сайтом. Открой папку в проводнике и введи адресной строке cmd, нажми enter. Появится консоль. Введи в нее php -S 127.0.0.1:8080, жми enter.
Открой в браузере адрес 127.0.0.1:8080 или пропиши в hosts:
название_сайта 127.0.0.1.
Тогда можешь открывать сайт по имени. Главное необходимо прописать путь к php в переменную среды Path, как на пике.
#385 #1029930
>>1029916
лол править hots , говорить что всё мхом поросло
не проше использовать тот же OpenServer который делает это всё автоматом при запуске
#386 #1029938
>>1029930
Нахуя вооще что-то править, превращать десктоп в сервер. Запускай laravel через artisan, попивая смузи.
Если надо больше - используй VM и готовые аплиансы или vargant https://app.vagrantup.com/boxes/search
#387 #1029941
>>1029938
vagrant
#388 #1029943
>>1029938
можно то и doker но проблема в том что зачем мне пердолиться с всей этой штукой день , если я могу поставить опен сервер и запустить вс в 2 клика ?
#389 #1029948
>>1029943
А зачем тогда сервер? Достаточно только php, ну и composer. В php есть сервер для разработки, есть sqlite
ОП, проверь задачи, пожалуйста #390 #1029961
Grammar Nazi - https://ideone.com/zli0sE
Опечаточник - https://ideone.com/eumFsz
Yoda Speak - https://3v4l.org/46mlk
Пиши верно - https://3v4l.org/OU9Ru
Сумма прописью - https://3v4l.org/GLjK8
Я у мамы калькулятор - https://3v4l.org/3O7ng
#391 #1029993
>>1029948
редисы , постгресы и тд
#392 #1029997
>>1027835

Про фигурные скобки - тут http://php.net/manual/ru/language.types.string.php#language.types.string.parsing

> кубы http://ideone.com/LitWO1



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

> айфон http://ideone.com/lHOqEL


Ок, тоже верно.

>>1029861

В случае с Апачем это делается так. Придумать домен, вписать его в hosts (чтобы браузер мог преобразовать домен в IP адрес), затем добавить VirtualHost в конфиг Апача, чтобы он знал, в какой папке лежит этот сайт. Но в слусае WAMP может это как-то по-другому делается, ты документацию смотреть не пробовал?

>>1029807

Любую, можно 7, только выучи отличия между этими версиями.

>>1029721

Не знаю, если ты можешь без этого обойтись, то можно и не делать.

>>1029617

Ты дал ссылку на файл на своем компьютере.
#392 #1029997
>>1027835

Про фигурные скобки - тут http://php.net/manual/ru/language.types.string.php#language.types.string.parsing

> кубы http://ideone.com/LitWO1



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

> айфон http://ideone.com/lHOqEL


Ок, тоже верно.

>>1029861

В случае с Апачем это делается так. Придумать домен, вписать его в hosts (чтобы браузер мог преобразовать домен в IP адрес), затем добавить VirtualHost в конфиг Апача, чтобы он знал, в какой папке лежит этот сайт. Но в слусае WAMP может это как-то по-другому делается, ты документацию смотреть не пробовал?

>>1029807

Любую, можно 7, только выучи отличия между этими версиями.

>>1029721

Не знаю, если ты можешь без этого обойтись, то можно и не делать.

>>1029617

Ты дал ссылку на файл на своем компьютере.
#393 #1029999
>>1029614

Сильно захотеть недостаточно.

>>1029613

Это в общем по стране, а не среди сотрудников определенной специальности в отдельном городе.

>>1029583

Я посмотрел RFC, который определяет тип application/json: https://tools.ietf.org/html/rfc4627

Там написано:

> The MIME media type for JSON text is application/json.


> Required parameters: n/a


> Optional parameters: n/a


charset - это именно parameter и тут он не определен.

Также, там написано, что кодировка определяется по кодированию первых 2 символов в JSON-данных.

Также, для надежности, я глянул еще RFC по MIME-типам: https://tools.ietf.org/html/rfc2046#section-4.1.2

> Charset Parameter


> A critical parameter that may be specified in the Content-Type field


> for "text/plain" data is the character set


> ....


> The specification for any future subtypes of "text" must specify


> whether or not they will also utilize a "charset" parameter, and may


> possibly restrict its values as well.


> ...


> Other media types than subtypes of "text" might choose to employ the


> charset parameter as defined here, but with the CRLF/line break


> restriction removed.


> ....


> The "charset" parameter has been defined primarily for the purpose of


> textual data, and is described in this section for that reason.


> However, it is conceivable that non-textual data might also wish to


> specify a charset value for some purpose, in which case the same


> syntax and values should be used.



То есть этот параметр определен для тестовых данных. Хотя там написано что он может использоваться и для других типов данных, в описании application/json мы такого не видим. И конечно, браузеры могут его интерпретировать или игнорировать, но стандартом поведение никак не определено.
#393 #1029999
>>1029614

Сильно захотеть недостаточно.

>>1029613

Это в общем по стране, а не среди сотрудников определенной специальности в отдельном городе.

>>1029583

Я посмотрел RFC, который определяет тип application/json: https://tools.ietf.org/html/rfc4627

Там написано:

> The MIME media type for JSON text is application/json.


> Required parameters: n/a


> Optional parameters: n/a


charset - это именно parameter и тут он не определен.

Также, там написано, что кодировка определяется по кодированию первых 2 символов в JSON-данных.

Также, для надежности, я глянул еще RFC по MIME-типам: https://tools.ietf.org/html/rfc2046#section-4.1.2

> Charset Parameter


> A critical parameter that may be specified in the Content-Type field


> for "text/plain" data is the character set


> ....


> The specification for any future subtypes of "text" must specify


> whether or not they will also utilize a "charset" parameter, and may


> possibly restrict its values as well.


> ...


> Other media types than subtypes of "text" might choose to employ the


> charset parameter as defined here, but with the CRLF/line break


> restriction removed.


> ....


> The "charset" parameter has been defined primarily for the purpose of


> textual data, and is described in this section for that reason.


> However, it is conceivable that non-textual data might also wish to


> specify a charset value for some purpose, in which case the same


> syntax and values should be used.



То есть этот параметр определен для тестовых данных. Хотя там написано что он может использоваться и для других типов данных, в описании application/json мы такого не видим. И конечно, браузеры могут его интерпретировать или игнорировать, но стандартом поведение никак не определено.
#394 #1030000
>>1029581

> и поскольку следующий блок then() не имеет функции rejected, чтобы его вызвать


Вот тут неточность. Ошибка теряется не поэтому.

Если ты не передаешь функцию onRejected в then, то вместо нее будет подставлена функция function Thrower(e) { throw e; }. Это не вызывает потерю ошибки.

Ошибка в твоем коде в том, что функция-обработчик ошибки error => console.log(error) не выкидывает исключение, а возвращает null и это значит, что ошибка обработана и новый промис резолвится в это значение, и этот null передается дальше по цепочке then.

То есть, разберем такой пример:

var p = new Promise(function (resolve, reject) {
reject(new Error);
});

var p2 = p.then(function () {}, function (e) {
console.log(e);
return null; // ошибка, должно быть throw
});

p2.then(....);

В данном примере - p будет rejected, но p2 будет resolved в значение null, так как мы обработали ошибку в then и вернули новое значение. Чтобы p2 также была rejected, мы должны вместо return null поставить throw e; то есть перевыбросить исключение.

То есть функция-обработчик (onFullfilled, onRejected) может либо выбросить исключение - в этом случае p2 будет rejected, либо что-то вернуть - в этом случае p2 ресолвится в это значение.

Ты не перевыбрасвыаешь исключение в onRejected, и это воспринимается, как будто бы ты обработал и исправил ошибку и вернул новое значение, и следующие then в цепочке будут работать с этим значением, как будто бы ошибки и не было.

Вообще, может быть, тебе стоит разобрать пример реализации промисов вот тут: https://www.promisejs.org/implementing/ ?

----

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

var result = array.filter(function (x) { return x > 0; });
var result = array.filter(x => x > 0);

В этом примере код со стрелочной функцией короче и читабельнее.

Но в твоем примере, error => console.log(error) - я не уверен, что использование стрелочной функции тут улучшает читабельность кода. Хотя бы потому, что в твоем коде подразумевается { return console.log(error); } и я не понимаю, зачем тут return.

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

К сожалению, и в официальных мануалах этого не понимают. Вот пример из документации MDN ( https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Functions/Arrow_functions ):

> // Destructuring within the parameter list is also supported


> var f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c;


Это какой-то антипример, как писать ни в коем случае не надо, так как я это даже прочесть не могу. Что это вообще такое?

К тому же они умудрились создать конфликт в синтаксисе стрелочных функций с синтаксисом литералов-объектов:

> var func = () => { foo: 1 };


> // Вызов func() возвращает undefined!



Впрочем, для тех, кто с веб-технологиями и JS знаком не первый день, ничего нового. Они всегда разрабатывались так же бестолково.
#394 #1030000
>>1029581

> и поскольку следующий блок then() не имеет функции rejected, чтобы его вызвать


Вот тут неточность. Ошибка теряется не поэтому.

Если ты не передаешь функцию onRejected в then, то вместо нее будет подставлена функция function Thrower(e) { throw e; }. Это не вызывает потерю ошибки.

Ошибка в твоем коде в том, что функция-обработчик ошибки error => console.log(error) не выкидывает исключение, а возвращает null и это значит, что ошибка обработана и новый промис резолвится в это значение, и этот null передается дальше по цепочке then.

То есть, разберем такой пример:

var p = new Promise(function (resolve, reject) {
reject(new Error);
});

var p2 = p.then(function () {}, function (e) {
console.log(e);
return null; // ошибка, должно быть throw
});

p2.then(....);

В данном примере - p будет rejected, но p2 будет resolved в значение null, так как мы обработали ошибку в then и вернули новое значение. Чтобы p2 также была rejected, мы должны вместо return null поставить throw e; то есть перевыбросить исключение.

То есть функция-обработчик (onFullfilled, onRejected) может либо выбросить исключение - в этом случае p2 будет rejected, либо что-то вернуть - в этом случае p2 ресолвится в это значение.

Ты не перевыбрасвыаешь исключение в onRejected, и это воспринимается, как будто бы ты обработал и исправил ошибку и вернул новое значение, и следующие then в цепочке будут работать с этим значением, как будто бы ошибки и не было.

Вообще, может быть, тебе стоит разобрать пример реализации промисов вот тут: https://www.promisejs.org/implementing/ ?

----

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

var result = array.filter(function (x) { return x > 0; });
var result = array.filter(x => x > 0);

В этом примере код со стрелочной функцией короче и читабельнее.

Но в твоем примере, error => console.log(error) - я не уверен, что использование стрелочной функции тут улучшает читабельность кода. Хотя бы потому, что в твоем коде подразумевается { return console.log(error); } и я не понимаю, зачем тут return.

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

К сожалению, и в официальных мануалах этого не понимают. Вот пример из документации MDN ( https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Functions/Arrow_functions ):

> // Destructuring within the parameter list is also supported


> var f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c;


Это какой-то антипример, как писать ни в коем случае не надо, так как я это даже прочесть не могу. Что это вообще такое?

К тому же они умудрились создать конфликт в синтаксисе стрелочных функций с синтаксисом литералов-объектов:

> var func = () => { foo: 1 };


> // Вызов func() возвращает undefined!



Впрочем, для тех, кто с веб-технологиями и JS знаком не первый день, ничего нового. Они всегда разрабатывались так же бестолково.
#395 #1030002
>>1029394

> Существуют еще удобные способы проверять данные, которые получил PHP в теле запроса POST?


Ты можешь прочитать тело POST и распарсить его самостоятельно или используя какую-нибудь библиотеку (а можешь даже написать и опубликовать свою): http://php.net/manual/ru/wrappers.php.php#wrappers.php.input

> Для urlenencoded и form-data нужно специально кодировать данные менее удобным способом, чем JSON.stringify().


Некоторые библиотеки (jQuery) умеют кодировать их автоматически, также доступен объект FormData, который умеет их кодировать. Наверно, кодировать на стороне клиента их было бы проще, чем впиливать поддержку на стороне PHP, но я в общем-то ничего против передачи JSON не имею - стандартам это никак не противоречит при указании корректных Content-Type/Content-Length

> Но написано, что тут в конце цепочки не следует добавлять блок catch во избежание цикла с ошибкой 'Unexpected batch number' если рендеришь результат.


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

В любом случае, ошибки нужно обрабатывать. Ты не должен полагаться на то, что сервер будет доступен в 100% случаев и всегда выдавать корректные ответы. Вот мой урок про аякс, перечитай его, если еще не читал, там упоминаются ошибки: https://github.com/codedokode/pasta/blob/master/js/ajax.md

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

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

>>1029324

Для дампа данных лучше использовать не implode, а print_r(..., true) или var_export или (внезапно) json_encode. Я обычно просто ставлю var_dump(); die() и смотрю в отладчике ответ.

Кстати, в отладчике Хрома в Network есть несколько полезных функций, вызываемых через правую кнопку. Это replay request и возможность скопировать командную строку для curl для отправки такого же запроса со всеми заголовками из консоли.
#395 #1030002
>>1029394

> Существуют еще удобные способы проверять данные, которые получил PHP в теле запроса POST?


Ты можешь прочитать тело POST и распарсить его самостоятельно или используя какую-нибудь библиотеку (а можешь даже написать и опубликовать свою): http://php.net/manual/ru/wrappers.php.php#wrappers.php.input

> Для urlenencoded и form-data нужно специально кодировать данные менее удобным способом, чем JSON.stringify().


Некоторые библиотеки (jQuery) умеют кодировать их автоматически, также доступен объект FormData, который умеет их кодировать. Наверно, кодировать на стороне клиента их было бы проще, чем впиливать поддержку на стороне PHP, но я в общем-то ничего против передачи JSON не имею - стандартам это никак не противоречит при указании корректных Content-Type/Content-Length

> Но написано, что тут в конце цепочки не следует добавлять блок catch во избежание цикла с ошибкой 'Unexpected batch number' если рендеришь результат.


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

В любом случае, ошибки нужно обрабатывать. Ты не должен полагаться на то, что сервер будет доступен в 100% случаев и всегда выдавать корректные ответы. Вот мой урок про аякс, перечитай его, если еще не читал, там упоминаются ошибки: https://github.com/codedokode/pasta/blob/master/js/ajax.md

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

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

>>1029324

Для дампа данных лучше использовать не implode, а print_r(..., true) или var_export или (внезапно) json_encode. Я обычно просто ставлю var_dump(); die() и смотрю в отладчике ответ.

Кстати, в отладчике Хрома в Network есть несколько полезных функций, вызываемых через правую кнопку. Это replay request и возможность скопировать командную строку для curl для отправки такого же запроса со всеми заголовками из консоли.
#396 #1030003
>>1029290

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

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

> Действительно, можно создать таблицу специально чтобы только хранить id, а ящики Inbox и Outbox будут хранить ещё и всё остальное (автора, контент, дату и т.д.).


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

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


Поискать готовую в библиотеке openssl: http://php.net/manual/ru/book.openssl.php

Вот статья например https://www.devco.net/archives/2006/02/13/public_-_private_key_encryption_using_openssl.php - можно то же самое делать с использованием функций openssl.

Погугли по "openssl encrypt data asymmetric"

Также, можно посмотреть протоколы Tox, Signal, и расширение OTR для Jabber и посмотреть как поступают они.

> Меня сначала смутило что без js тогда не будет работать приложение,


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

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

То есть чтобы работать без JS, нужно снизить степень защищенности и доверять серверу.

> У меня элемент постоянно обновляется и постоянно нужно ставить новый обработчик.


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

Я тут не вижу проблемы. Вот допустим, у нас есть кнопка на странице. Мы нашли ее, поставили на нее обработчик DOM события и больше не добавляем. Или мы создаем кнопку, вставляем в DOM, ставим один раз обработчик и больше не добавляем его. Не важно, контроллер это или view делает, лишь бы DOM-обработчик ставился один раз. Нужно это так спроектировать. MVC тут вообще не при чем.

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

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


> Вот так https://jsfiddle.net/jsqt57hz/2/ ?


да. Это обычно применяют для каких-то списков, где много однотипных элементов.

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



Когда я говорил, про "свои" события, я имел в виду систему, когда view сам ставит DOM-обработчик (например, клика на контакт в списке), обрабатывает это событие и генерирует свое, искуственное событие вроде onContactSelect. И контроллер подписывается именно на это искуственное событие, а не лезет в DOM.

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

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


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

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

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


Через группировку это будет неэффективно, так как будет обзодиться большое число записей (все сообщения для каждого контакта). Такую сортировку лучше сделать денормализацией, добавив поле lastMessageTime в таблицу контактов. Опять же, стоит помнить что это лишняя незащищенная информация.
#396 #1030003
>>1029290

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

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

> Действительно, можно создать таблицу специально чтобы только хранить id, а ящики Inbox и Outbox будут хранить ещё и всё остальное (автора, контент, дату и т.д.).


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

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


Поискать готовую в библиотеке openssl: http://php.net/manual/ru/book.openssl.php

Вот статья например https://www.devco.net/archives/2006/02/13/public_-_private_key_encryption_using_openssl.php - можно то же самое делать с использованием функций openssl.

Погугли по "openssl encrypt data asymmetric"

Также, можно посмотреть протоколы Tox, Signal, и расширение OTR для Jabber и посмотреть как поступают они.

> Меня сначала смутило что без js тогда не будет работать приложение,


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

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

То есть чтобы работать без JS, нужно снизить степень защищенности и доверять серверу.

> У меня элемент постоянно обновляется и постоянно нужно ставить новый обработчик.


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

Я тут не вижу проблемы. Вот допустим, у нас есть кнопка на странице. Мы нашли ее, поставили на нее обработчик DOM события и больше не добавляем. Или мы создаем кнопку, вставляем в DOM, ставим один раз обработчик и больше не добавляем его. Не важно, контроллер это или view делает, лишь бы DOM-обработчик ставился один раз. Нужно это так спроектировать. MVC тут вообще не при чем.

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

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


> Вот так https://jsfiddle.net/jsqt57hz/2/ ?


да. Это обычно применяют для каких-то списков, где много однотипных элементов.

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



Когда я говорил, про "свои" события, я имел в виду систему, когда view сам ставит DOM-обработчик (например, клика на контакт в списке), обрабатывает это событие и генерирует свое, искуственное событие вроде onContactSelect. И контроллер подписывается именно на это искуственное событие, а не лезет в DOM.

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

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


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

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

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


Через группировку это будет неэффективно, так как будет обзодиться большое число записей (все сообщения для каждого контакта). Такую сортировку лучше сделать денормализацией, добавив поле lastMessageTime в таблицу контактов. Опять же, стоит помнить что это лишняя незащищенная информация.
#397 #1030004
>>1029230

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

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

В checkAnswer ничего не передается - что он проверяет? Та же проблема в CalcScore.

SaveAndGEtResult явно должен быть в контроллере, а не в модели упражнения Exercise.

В твоем коде я вижу проблемные места - например, статический метод работы с БД, который не позволит тут использовать DI (урок по DI https://github.com/codedokode/pasta/blob/master/arch/di.md ). Мануалов по Юи перечитался?

Ну и по ощущениям, у тебя тут многовато интерфейсов, хотя не могу найти, почему бы это было плохо.

>>1029194

При заходе на несущ. страницу надо показывать страницу 404, а не редиректить. Редирект значит "эта страница есть, но по другому адресу".

Логгировать очень просто - пишешь данные в файл или вставляешь строку в таблицу в БД. Не понял, что именно тут непонятно. Ну и тебе правильно написали, Апач умеет логгировать такие обращения.

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


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

>>1029149

> Как передавать в конструктор значение с поля класса?


Обычным образом. Какого-то специального синтаксиса для этого нет.

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


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

Прокомментирую еще:

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


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

Ты задаешь при наследовании свойства данной профессии. Но это никак не документировано и никак не проверяется. Лучше использовать абстрактные функции, чтобы нельзя было унаследоваться от Worker и забыть что-то задать.

Также, у тебя список работников почему-то жестко прописан в департаменте. Не надо так, нужно сделать отдельно департамент (с методом принятия данного работника на работу) и отдельно список работников, и функция, которая по этому списку создает работников и вставляет в департамент. И тогда может быть не понадобится гора кода для заполнения этих свойтсв.
#397 #1030004
>>1029230

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

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

В checkAnswer ничего не передается - что он проверяет? Та же проблема в CalcScore.

SaveAndGEtResult явно должен быть в контроллере, а не в модели упражнения Exercise.

В твоем коде я вижу проблемные места - например, статический метод работы с БД, который не позволит тут использовать DI (урок по DI https://github.com/codedokode/pasta/blob/master/arch/di.md ). Мануалов по Юи перечитался?

Ну и по ощущениям, у тебя тут многовато интерфейсов, хотя не могу найти, почему бы это было плохо.

>>1029194

При заходе на несущ. страницу надо показывать страницу 404, а не редиректить. Редирект значит "эта страница есть, но по другому адресу".

Логгировать очень просто - пишешь данные в файл или вставляешь строку в таблицу в БД. Не понял, что именно тут непонятно. Ну и тебе правильно написали, Апач умеет логгировать такие обращения.

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


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

>>1029149

> Как передавать в конструктор значение с поля класса?


Обычным образом. Какого-то специального синтаксиса для этого нет.

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


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

Прокомментирую еще:

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


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

Ты задаешь при наследовании свойства данной профессии. Но это никак не документировано и никак не проверяется. Лучше использовать абстрактные функции, чтобы нельзя было унаследоваться от Worker и забыть что-то задать.

Также, у тебя список работников почему-то жестко прописан в департаменте. Не надо так, нужно сделать отдельно департамент (с методом принятия данного работника на работу) и отдельно список работников, и функция, которая по этому списку создает работников и вставляет в департамент. И тогда может быть не понадобится гора кода для заполнения этих свойтсв.
#398 #1030006
>>1028685

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

Вообще, реши такую задачу. Есть список допустим учеников в массиве - фамилия, оценка. Нужно сделать функции:

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

>>1028597

У тебя такие аналогии, я надеюсь, они не на твоем жизненном опыте основаны.

>>1028470

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

>>1027651

> Что можно сделать после успешной отправки сообщения?


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

> Как-то не хочется оставлять пустую функцию


Не вижу в чем тут проблема.

> Стоит ли так выборочно обрабатывать ошибки? Для пользователя достаточно вывести ошибку соединения, а для разработчиков выбросить в консоль статус и текст ошибки.


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

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

> Почему у меня не вбрасываются эти ошибки (ошибки не появляются в консоле)? Это из-за асинхронного кода?



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

// p резолвится в значение 1
var p = new Promise(function (resolve, reject) {
resolve(1);
});

// обработчик выбрасывает исключение, потому p2 реджектится в эту ошибку
var p2 = p.then(function (val) {
throw new Error();
});

Что-то ты не очень знаешь, как работают промисы. Может быть, тебе стоит разобрать пример реализации вот тут: https://www.promisejs.org/implementing/ ?

И еще, напомню, что промисы jQuery не соответствуюют спецификации Promise/A+, которая используется в языке JS. У них свои несовместимые промисы.

И еще, у тебя обработка ошибок странно сделана:

> that.backend.postMessage(to, message, token).then(


> ....


> function(jqXHR, textStatus) {


> ...


> that.backend.handleError(jqXHR, textStatus);


> }



Странно, что backend сначала отдает ошибку тебе, а ты потом ее отдаешь назад в backend. Он наверно и сам бы мог это делать.

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

> К сожалению, у меня не получилось найти в ejs аналог функции nl2br и при этом чтобы экранировались тэги. В таком случае, будет приемлемым оставить этот костыль?


nl2br не экранирует теги, она только заменяет \n на <br>, если я не путаю.

Насколько я понял, у тебя проблема в том, что ejs экранирует данные и твой <br> выводится как текст? В документации ( https://github.com/mde/ejs/blob/master/docs/syntax.md ) написано что есть 2 вида тегов, один принимают текст, экранируют его и выводят, другой тег принимает HTML код и вставляет его как есть.

В чем именно сложность-то? Можно сделать так <%- convertMessageToHtml(message) %>

> Это нормально, что у меня такая простыня с обработкой ошибок?


Повторяющийся код можно было бы вынести в функцию.

Сам метод public function send($apiMode = false) явно нарушает MVC и представляет пример "толстого" контроллера. Метод отправки должен быть в модели.

Что касается if ($apiMode), тут тоже все как-то странно, тут можно было бы это обобщить, например, сделать специальное исключение ApiError, ловить его и в зависимости от режима выдавать разный ответ.

То есть нет, сделано конечно неудачно. Стена кода какая-то с 7 уровнями вложенности.

> Я плохо понял что такое REST. Это просто архитектура которая позволяет обрабатывать запросы с методами вроде PUT\DELETE?



Это набор принципов, которые можно использовать при проектировании API. Что есть ресурсы (URL), с которыми можно делать разные действия (выражаемые методами). Ну например, PUT /user/ivan/inbox - отправить сообщение Ивану. Лучше посмотреть на примере REST API Яндекс-диска например.

Чистый REST не для каждой задачи хорошо подходит, конечно.

> Я никак не могу придумать как выводить только новые сообщения. Определенно, нужен setTimeout\setInterval чтобы постоянно обновлять данные с сервера, но как при этом выводить только те сообщения которые ещё не выведены в шаблон?


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

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

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

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


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

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

> У меня есть идея как при отключенном js опускать окно диалога до последнего сообщения - использовать якори


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

> Не подвергаю ли я пользователей опасности, открывая кукисы для js?


Нет наверно.

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


А зачем тебе нужна кука в JS коде? Ведь при отправке аякс-запроса куки и так отправляются на сервер.

И конечно, странно, что у тебя token хранится в view.

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


Да, переименовать. Я бы не сказал, что это читабельно.
#398 #1030006
>>1028685

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

Вообще, реши такую задачу. Есть список допустим учеников в массиве - фамилия, оценка. Нужно сделать функции:

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

>>1028597

У тебя такие аналогии, я надеюсь, они не на твоем жизненном опыте основаны.

>>1028470

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

>>1027651

> Что можно сделать после успешной отправки сообщения?


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

> Как-то не хочется оставлять пустую функцию


Не вижу в чем тут проблема.

> Стоит ли так выборочно обрабатывать ошибки? Для пользователя достаточно вывести ошибку соединения, а для разработчиков выбросить в консоль статус и текст ошибки.


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

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

> Почему у меня не вбрасываются эти ошибки (ошибки не появляются в консоле)? Это из-за асинхронного кода?



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

// p резолвится в значение 1
var p = new Promise(function (resolve, reject) {
resolve(1);
});

// обработчик выбрасывает исключение, потому p2 реджектится в эту ошибку
var p2 = p.then(function (val) {
throw new Error();
});

Что-то ты не очень знаешь, как работают промисы. Может быть, тебе стоит разобрать пример реализации вот тут: https://www.promisejs.org/implementing/ ?

И еще, напомню, что промисы jQuery не соответствуюют спецификации Promise/A+, которая используется в языке JS. У них свои несовместимые промисы.

И еще, у тебя обработка ошибок странно сделана:

> that.backend.postMessage(to, message, token).then(


> ....


> function(jqXHR, textStatus) {


> ...


> that.backend.handleError(jqXHR, textStatus);


> }



Странно, что backend сначала отдает ошибку тебе, а ты потом ее отдаешь назад в backend. Он наверно и сам бы мог это делать.

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

> К сожалению, у меня не получилось найти в ejs аналог функции nl2br и при этом чтобы экранировались тэги. В таком случае, будет приемлемым оставить этот костыль?


nl2br не экранирует теги, она только заменяет \n на <br>, если я не путаю.

Насколько я понял, у тебя проблема в том, что ejs экранирует данные и твой <br> выводится как текст? В документации ( https://github.com/mde/ejs/blob/master/docs/syntax.md ) написано что есть 2 вида тегов, один принимают текст, экранируют его и выводят, другой тег принимает HTML код и вставляет его как есть.

В чем именно сложность-то? Можно сделать так <%- convertMessageToHtml(message) %>

> Это нормально, что у меня такая простыня с обработкой ошибок?


Повторяющийся код можно было бы вынести в функцию.

Сам метод public function send($apiMode = false) явно нарушает MVC и представляет пример "толстого" контроллера. Метод отправки должен быть в модели.

Что касается if ($apiMode), тут тоже все как-то странно, тут можно было бы это обобщить, например, сделать специальное исключение ApiError, ловить его и в зависимости от режима выдавать разный ответ.

То есть нет, сделано конечно неудачно. Стена кода какая-то с 7 уровнями вложенности.

> Я плохо понял что такое REST. Это просто архитектура которая позволяет обрабатывать запросы с методами вроде PUT\DELETE?



Это набор принципов, которые можно использовать при проектировании API. Что есть ресурсы (URL), с которыми можно делать разные действия (выражаемые методами). Ну например, PUT /user/ivan/inbox - отправить сообщение Ивану. Лучше посмотреть на примере REST API Яндекс-диска например.

Чистый REST не для каждой задачи хорошо подходит, конечно.

> Я никак не могу придумать как выводить только новые сообщения. Определенно, нужен setTimeout\setInterval чтобы постоянно обновлять данные с сервера, но как при этом выводить только те сообщения которые ещё не выведены в шаблон?


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

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

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

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


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

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

> У меня есть идея как при отключенном js опускать окно диалога до последнего сообщения - использовать якори


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

> Не подвергаю ли я пользователей опасности, открывая кукисы для js?


Нет наверно.

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


А зачем тебе нужна кука в JS коде? Ведь при отправке аякс-запроса куки и так отправляются на сервер.

И конечно, странно, что у тебя token хранится в view.

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


Да, переименовать. Я бы не сказал, что это читабельно.
#399 #1030007
>>1027168

Тут написано http://php.net/manual/ru/language.variables.scope.php

>>1026920

Рисуют дизайн в графическом редакторе, а затем его верстают, то есть переводят в HTML/CSS/картинки. Браузер фотошопные файлы не отображает, и они фиксированного размера, не подстраиваются под размер экрана например. В отличие от HTML/CSS.

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

>>1026318

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

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

Наверно, тебе подойдут сценарии. Погугли.

>>1026257

В фронт-контроллере (или входном скрипте). Хочу только предупредить, что сессии плохо подходят для авторизации так как умирают через 30 минут неактивности.

> И где проверять может ли пользователь находиться на странице, private метод контроллера checkAuth() в каждом экшне?


Можно метод в базовом контроллере, можно отдельный класс для этого сделать.

>>1026198

Я Юи2 не использовал, так что сказать, увы, ничего не могу.
#399 #1030007
>>1027168

Тут написано http://php.net/manual/ru/language.variables.scope.php

>>1026920

Рисуют дизайн в графическом редакторе, а затем его верстают, то есть переводят в HTML/CSS/картинки. Браузер фотошопные файлы не отображает, и они фиксированного размера, не подстраиваются под размер экрана например. В отличие от HTML/CSS.

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

>>1026318

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

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

Наверно, тебе подойдут сценарии. Погугли.

>>1026257

В фронт-контроллере (или входном скрипте). Хочу только предупредить, что сессии плохо подходят для авторизации так как умирают через 30 минут неактивности.

> И где проверять может ли пользователь находиться на странице, private метод контроллера checkAuth() в каждом экшне?


Можно метод в базовом контроллере, можно отдельный класс для этого сделать.

>>1026198

Я Юи2 не использовал, так что сказать, увы, ничего не могу.
#400 #1030018
>>1029999

>Сильно захотеть недостаточно.


Поэтому ты на том уровне где ты и есть.
someApprentice #401 #1030039
>>1030003

>> Меня сначала смутило что без js тогда не будет работать приложение,


>Чтобы приложение работало без JS, мы должны доверить операции шифрования/расшифровки (и все наши ключи) серверу. То есть поступиться безопасностью.


>То есть чтобы работать без JS, нужно снизить степень защищенности и доверять серверу.


Можно сделать режим для шифрования\расшифровки сообщений.

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


>(так как код на сайте легко подменить, взломав сервер)


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

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

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

Иметь собственное приложение - это хорошо.

Если взломать сервер, то может произойти всё что угодно.

>> У меня элемент постоянно обновляется и постоянно нужно ставить новый обработчик.


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


Вот здесь

https://github.com/someApprentice/chat/blob/master/public/js/contacts.js#L71

Я вывожу окно переписки

и вот здесь

https://github.com/someApprentice/chat/blob/master/public/js/conversation.js#L121-L124

я вывожу форму и ставлю на неё обработчики.

Ну да, здесь можно было сделать обработчик частью отображения, либо просто сделать проверку что элемент уже выведен и ставить его только при создании формы.
someApprentice #401 #1030039
>>1030003

>> Меня сначала смутило что без js тогда не будет работать приложение,


>Чтобы приложение работало без JS, мы должны доверить операции шифрования/расшифровки (и все наши ключи) серверу. То есть поступиться безопасностью.


>То есть чтобы работать без JS, нужно снизить степень защищенности и доверять серверу.


Можно сделать режим для шифрования\расшифровки сообщений.

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


>(так как код на сайте легко подменить, взломав сервер)


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

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

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

Иметь собственное приложение - это хорошо.

Если взломать сервер, то может произойти всё что угодно.

>> У меня элемент постоянно обновляется и постоянно нужно ставить новый обработчик.


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


Вот здесь

https://github.com/someApprentice/chat/blob/master/public/js/contacts.js#L71

Я вывожу окно переписки

и вот здесь

https://github.com/someApprentice/chat/blob/master/public/js/conversation.js#L121-L124

я вывожу форму и ставлю на неё обработчики.

Ну да, здесь можно было сделать обработчик частью отображения, либо просто сделать проверку что элемент уже выведен и ставить его только при создании формы.
#402 #1030066
>>1029538
Можно.

мимо 110k php-джун
someApprentice #403 #1030074
>>1030003

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


>Поискать готовую в библиотеке openssl: http://php.net/manual/ru/book.openssl.php


А шифровать копию сообщения собеседника, если его ключ зашифрован паролем?
someApprentice #404 #1030075
>>1030074
как*
#405 #1030078
Заказчику нужно парсить выдачу гугла, какие подводные камни кроме возни с проксями? Это вообще законно?
#406 #1030104
ОП, выручай, вот мой говнокод по Вектору http://ideone.com/FMRyCa.
но функция которая возвращает окончательную ставку сотрудника работает неправильно, подскажи что не так
#407 #1030106
>>1030104
Откуда берётся ранг?
#408 #1030117
#409 #1030124
>>1030117
http://ideone.com/FMRyCa
>>1030106
из класса Департамент
#410 #1030132
>>1030124
А в какой момент ранг появляется в сотруднике? А в какой момент считается endStavka? А в какой момент в поле сотрудника записывается endStavka?
#411 #1030149
>>1030104
Честно говоря, ничего не понятно. Сам почему не можешь найти? xDebug не настроил?
#412 #1030152
>>1030104
Хотя. Ошибка в том, что ты создаёшь работника, не передавая ему ранг. Конструктор считает уже конечную ставку с коэффициентом 1, т.к. ранг у тебя не 2 и не 3 (null). Потом ты уже назначаешь работнику ранг (зп после этого, конечно, не пересчитывается) и загоняешь работника в массив.
#413 #1030153
>>1030152
Разобрался сам? Молодец!
Помог анону? Сомневаюсь.
Он получил бы больше, если бы нашёл свою ошибку сам, ответив на вопросы: >>1030132
#414 #1030174
Что лучше xDebug или ZenDebug?
#415 #1030176
>>1030132
Ранг присваивается в цикле, после создания объекта,но как заставить работать именно после присвоения ранга я не знаю, только если всегда повторно вызывать метод
#416 #1030184
>>1019301 (OP)
Няши,есть задача: распарсить при помощи xgettext все строки и создать словарь, но эта мразь парсит все,что в двойных кавычках. Как заставить эту пиздоту хватать только то, что обрамлено в _("хуй пизда сковорода")?
#417 #1030198
Пытаюсь заставить работать gettext и пока абсолютно безуспешно.
Что имею: OpenServer 5.2.2, PHP Version 5.5.38
Код скрипта: https://gist.github.com/anonymous/2a2fccdb72f02fef15847fbc633a24aa

Скрипт index.php, рядом с ним папка locale/en_EN/LC_ALL/mydomain.po и mydomain.po

Также есть папка с русскими переводами: locale/ru_RU
Содержимое po файлов: https://gist.github.com/anonymous/677ae340489f3db983c1270b194931b5

mo компилирую при помощи https://po2mo.net/

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

Пробовал папку LC_ALL переименовывать в LC_MESSAGES - толку никакого.

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

Надеюсь мудрый анон подскажет где здесь косяк.
#418 #1030199
>>1030174
Разные вещи, если ты об этом: https://github.com/zendframework/zend-debug
Эта штука по сути var_dump для HTML, но тот же symfony/var-dumper гораздо мощнее. xdebug это PHP расширение на Cи, которое позволяет отслеживать выполнение программы и изменять значения переменных во время исполнения кода. Пользуются им обычно через IDE.

>>1026198
Я не ОП, но то, что описано в статье - всем давно известно, странно что подобная статья тебя останавливает. Мне тоже в Yii не нравятся пустые интерфейсы, их собственные сеттеры/геттеры, доступность Yii::$app отовсюду и прочее, но Yii по-прежнему остаётся инструментом, с помощью которого можно быстро и эффективно решать задачи.

>>1030184

> мразь


> пиздоту


> хуй пизда


Ты из /b вылез?
#419 #1030200
>>1030199

>Ты из /b вылез?


С хуевыми инструментами только так и получается.
#420 #1030244
>>1030198
Не работает на винде, хоть и ошибок не выдает.
Вопрос решен.
#421 #1030299
>>1030074

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

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

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

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

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


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

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

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

Есть конечно еще промежуточный вариант - когда клиент доверяет серверу, но сервер с открытым кодом и пользователь может поднять свой сервер. Но тут все равно защищенность получается ниже чем у варианта с недоверием серверу.
#421 #1030299
>>1030074

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

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

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

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

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


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

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

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

Есть конечно еще промежуточный вариант - когда клиент доверяет серверу, но сервер с открытым кодом и пользователь может поднять свой сервер. Но тут все равно защищенность получается ниже чем у варианта с недоверием серверу.
Задание на побитовые операторы #422 #1030326
>>1027969
https://3v4l.org/GNWKP

> сделай функцию countBits, которая принимает на вход число и возвращает число единиц в его двоичном представлении


Тут ведь нужно без циклов через побитовые операторы делать? Не понимаю как сделать, можно подсказку?
#423 #1030330
>>1030326

clearBit сделан неправильно: clearBit(0, 0b001) должен давать 0.

countBits можно для начала сделать через цикл, а потом почитать вопросы вроде

https://stackoverflow.com/questions/109023/how-to-count-the-number-of-set-bits-in-a-32-bit-integer
http://www.geeksforgeeks.org/count-set-bits-in-an-integer/
https://www.google.ru/search?q=count+bits&newwindow=1&gbv=1&sei=zvV0WdeIC4XI6ATBj6DICg
#424 #1030557
Неплохая практика для нубов. MVC проект магазина с нуля https://www.youtube.com/watch?v=ba3M3_Myrqg&list=PLSdH7dYnlGYgQ6ElbHRpG2zRXbkgkO3zQ
#425 #1030786
Я только вкатываюсь, мне нужен XAMPP?
Или можно без него обойтись?
#426 #1030787
Аноны, я уже заебался. Решил поизучать Laravel.
В рот его топтать, это слишком тяжело - просто взять и установить эту хуету.
Устанавливал на мак.
С горем пополам у меня это получилось, я использовал их Homestead, для которого понадобился Vagrant и VirtualBox

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

Но как мне войти в свой проект-то?
Я смог написать php artisan serve и захожу на сайт через localhost:8000/.
Как это пофиксить? Что надо сделать?

Как мне подключиться к БД? Как использовать ебаный phpMyAdmin?

Почему все так сложно, а в документации этого нет?
#427 #1030798
>>1030787
The Hosts File

You must add the "domains" for your Nginx sites to the hosts file on your machine. The hosts file will redirect requests for your Homestead sites into your Homestead machine. On Mac and Linux, this file is located at /etc/hosts. On Windows, it is located at C:\Windows\System32\drivers\etc\hosts. The lines you add to this file will look like the following:

192.168.10.10 homestead.app
Make sure the IP address listed is the one set in your Homestead.yaml file. Once you have added the domain to your hosts file and launched the Vagrant box you will be able to access the site via your web browser:

http://homestead.app

https://laravel.com/docs/5.4/homestead
--------------------------------------------------------------------------------

ssh https://www.vagrantup.com/docs/cli/ssh.html

sudo apt-get install phpmyadmin
25 Кб, 329x104
#428 #1030799
>>1030557
Я толком не смотрел, но с ООП у автора серьёзные проблемы (пик).

>>1030786
Для начинающего гораздо проще встроенный в PHP веб-сервер, который не требует установки и настройки: https://github.com/codedokode/pasta/blob/master/soft/web-server.md#Встроенный-в-php-сервер/

>>1030787

> В рот его топтать, это слишком тяжело - просто взять и установить эту хуету.


Одна строчка в терминале, куда уже проще?

> я использовал их Homestead, для которого понадобился Vagrant и VirtualBox


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

> Я смог написать php artisan serve и захожу на сайт через localhost:8000/.


> Как это пофиксить?


Что фиксить? Команда artisan serve запускает встроенный веб-сервер в PHP, там нет виртуальных хостов как в апаче.

> Как использовать ебаный phpMyAdmin?


Laravel не имеет вообще никакого отношения к phpMyAdmin.

> Как мне подключиться к БД?


> а в документации этого нет?


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

>Одна строчка в терминале, куда уже проще?


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

>Для новичка это лишние стены абстракций, зачем они тебе? Читай о том, с чем работаешь и думай, нужно ли оно тебе. Бездумным перепечатыванием команд ничего не добьёшься.


Полностью согласен. Но я читал документацию с начала. Русскую. Там ребята начали с того, что хорошо было бы поставить homestead.
К слову, я на маке недавно и вполне представляю, как настраивается обычный AMP на винде. А для своих целей, так я бы вообще не парился и поставил Open Server, потому что у меня ничего, кроме самообразования особо-то и нет.

>Что фиксить? Команда artisan serve запускает встроенный веб-сервер в PHP, там нет виртуальных хостов как в апаче.


Ну хорошо, допустим. Но как мою проблему решить, я так и не догнал. У меня не работает http://homestead.app
Точнее, он как бы работает и пишет No input file specified.

>Laravel не имеет вообще никакого отношения к phpMyAdmin.


Ну и что? Я хочу использовать MySQL, а там привык юзать phpMyAdmin. Хотел бы знать, как это использовать в связке с Laravel. Как установить, как начать пользоваться.

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


Здесь я просто бомбанул. Все там про БД написано.
#430 #1030803
>>1030799

>с ООП у автора серьёзные проблемы (пик).


А как для нубов лучше реализовать M в паттерне MVC?
ActiveRecords? Новички в страхе убегут...
#431 #1030806
>>1030798
В /etc/hosts у меня добавлен 192.168.10.10 homestead.app все по гайду
Толку от этого?
У меня есть проект, который я создал через composer. Но он никак не связан с тем, что в hosts
#432 #1030813
>>1030806
Где добавлен? На маке или в убунте хомстид?
#433 #1030814
Ребят, я начал тут изучать веб-кодинг, и у меня возникла проблема с адресацией ссылок.

У меня в шапке сайта есть несколько кнопок, по нажатию которых я перемещаюсь в разные места своего высерасайта. Каждая из кнопок включает свой скрипт, который лежит по адресу php/скриптнейм.php. В каждом скрипте так же прогружается(require) эта самая шапка (файл main.php, из которого я щелкаю по кнопкам), которая лежит в одной директории с папкой php. Проблемы возникают тогда, когда мне нужно из любого из нескольких скриптов вернуться в main.php, либо из какого-либо скрипта переместиться в другой.

В main.php для всех кнопок (на самом деле это ссылки, но неважно) написан путь "php/скриптнейм1.php", "php/скриптнейм2.php" и т.д. Если я, будучи в одном из этих скриптов, захочу переместится в какой-либо из других оставшихся скриптов (или в main.php), браузер пошлет меня нахуй, ибо т.к я нахожусь уже в папке php, ссылку мне нужно задавать относительно нее, а она имеет вид "php/..." (такая же, как была загружена через require 'main.php').

Я бы конечно мог все эти файлы поместить в одну директорию, но так не интересно. Стили тоже не загружаются. Как можно решить данную проблему? Спасибо заранее! надеюсь нормально все объяснил.
#434 #1030818
>>1030814
Не делай так
http://yournet.kz/blog/project/koncepciya-edinoj-tochki-vxoda
Концепция «единой точки входа»
#435 #1030830
>>1030813
на маке
#436 #1030834
>>1030830
Может не будешь создавать себе трудности и установишь php и composer на мак. Ларавел устанавливай через композер. Апач не нужен.
#437 #1030840
Почему не работает? Как изъять элемент из массива, если его ключ равен нулю? https://ideone.com/Dtw40D
#438 #1030844
>>1030840

>for($z = 0; $z++; $z <= count($bills)) {


Чиво?
#439 #1030847
>>1030844
Он перебирает элементы массива по индексу, и если оный ключ сего индекса равен нулю, то изымает. Так я задумывал.
#440 #1030850
>>1030847
Перечитай еще раз мурзилку как пользоваться for.
#441 #1030863
>>1030834
попробовал через docker, один хуй не получается
не догоняю, что куда копировать, какие где файлы создавать
я сделал контейнер, все работать должно, куда сайт заливать не понимаю
пиздец, какой же я тупой
#442 #1030872
>>1030799

>Для начинающего гораздо проще встроенный в PHP веб-сервер, который не требует установки и настройки


Я хочу PhpStorm использовать, хз как там встроенный сервер. Он подойдет?
#443 #1030925
>>1030850
https://ideone.com/f5V9KI
Превышено ограничение на время
Значит массив бесконечный?
#444 #1030929
>>1030925

>if($bills[$z] = 0){


Чиво?
100 Кб, 960x640
#445 #1030930
Антоны, поясните ньюфагу за синтаксис:
$actionName = isset($_GET['action']) ? $_GET['action'] : 'index';

Если переданный гет парамент не null, то устанавливаем переменной его значение, иначе - индекс.
Почему условие прописано так? "?", ":" - dgthdst cnfkrbdf.cm
#446 #1030934
>>1030930
http://php720.com/lesson/19
Учи пхп с помощью учебник, а не двачей
#447 #1030957
>>1030814

Тебе правильно советуют сделать единую точку входа, и уже в этом скрипте смотреть, какой URL и что надо вызвать. Но советую тебе также почитать про относительные ссылки и научиться собирать любые виды ссылок: https://github.com/codedokode/pasta/blob/master/network/urls.md
26 Кб, 451x485
#448 #1030994
Почему он не умножает?
#449 #1030999
>>1030994
потому что знак умножения записан как строка
#450 #1031001
>>1030999
Спасибо, туплю-торможу.
#451 #1031009
>>1030929
Если z элемент массива равен нулю, то изымает.
#452 #1031010
>>1031009
Перечитай еще раз мурзилку как пользоваться = и ==
#453 #1031117
>>1029892
В даблах забыл сравнение кубов анон1 == анон3.
На трипл единственное, что приходит в голову - чтобы строка не была вырвиглазно большой, можно вынести сравнения в отдельные переменные и потом в проверку условия подставлять только их.
Мимо-3-день-в-клубе-кун
#454 #1031120
Как пофиксить ошибку 502 Bad Gateway когда запускаешь php сервер в phpstorm?
Делал по этому мануалу
https://www.jetbrains.com/help/phpstorm/php-built-in-web-server.html#d147912e141
#455 #1031122
Получается background-image запилить только для body, если делаю для какого-нибудь div'a, то оно не отображается. Как с этим разобраться, аноны?
9 Кб, 1186x117
#456 #1031129
Аноны, как сделать в шторме, чтобы в окне ошибок показывалось одно упоминание об ошибке, а не несколько?
#457 #1031132
>>1031129
Ну и что? Тут перекатывальщики тредов иногда пытаются всю шапку в заголовок запихнуть
#458 #1031136
#459 #1031138
Обязательно ли нужны регулярки в вебе?
Они нужны в каждом проекте?
#460 #1031139
>>1031117
насмотрелся чет на вас и вот такую хуетень написал: http://ideone.com/t1raXp
#461 #1031141
>>1031136
Очевидно первая строчка - заголовок сообщения, а вторая - само сообщение
#462 #1031144
>>1031141
Так в заголовке написано то же самое, что и в сообщении. Я хочу что-нибудь одно.
#463 #1031145
>>1031138
Какие проекты, если ты не знаешь даже регулярки
#464 #1031146
>>1031145
Ну так я и спрашиваю: они часто используются или нет?
#465 #1031148
>>1031138
Помню дрочил задачи по регуляркам уже почти 3 года назад, жаловался другу который уже работал в яндексе или еще где на тот момент, что мол хуево и сложно. Он сказал что нахуй их, они ирл не нужны почти, а если и нужны то простые которые за 3 сек гуглятся по типу https://code.tutsplus.com/tutorials/8-regular-expressions-you-should-know--net-6149

или заменяются знанием вот этой вот хуйни
http://php.net/manual/ru/function.filter-var.php

Но это что касается бекэнда, когда я немного ковырял фронтэнд, там нужны знания регулярок немного, потому что много хуеты с заполнением полей пользователем и прочее.
#466 #1031149
>>1031146
Тебя просто уволят за некомпетентность, если не "Рога и копыта"
#467 #1031157
>>1031149
Не, скорее в галере а собеседовании будет задача с регуляркой в тесте-хуесте. На которой если ты не обосрешься и устроишься, то больше никогда с регулярками не столкнешься.
#468 #1031171
>>1031157
Что за галера? Там код пишут?
#469 #1031176
>>1031171

>Что за галера?


Любая большая контора с кучей кодеров, штатом hr-шлюшек иерархией и прочим. Мб даже автоматизированным собеседованием, когда просто решаешь задачки или тесты проходишь как раз, вместо того что бы разговаривать со своим будущим начальником, как в какой-нибудь веб студии.
#470 #1031179
Что делать, если я тупой и не могу в решение задач?
Особенно тех, которые ближе к концу.
#471 #1031180
>>1031179
Какую задачу ты не можешь решить?

Надо раскладывать сложные задачи на подзадачи и решать каждую из них.
#472 #1031182
>>1031179
Ближе к концу основная задача как бы штаны не обосрать. На нее мозгов не надо.
52 Кб, 800x560
#473 #1031183
>>1031180
Почти все, лол.
Вот, например, вот эту.
Как вообще разбивать задачу на несколько маленьких? Я даже не могу придумать алгоритма к этой задаче.
#474 #1031188
>>1031139
А зачем арсорт?
3-день-кун
#475 #1031194
>>1031183
Даа, помню это, на таких задачах тоже сидел по неделе и не прогрессировал тупо чувствуя собственное бессилие. Это оп на самом деле тонкий троль, под видом простеньких задачек на 20 строк засунул пусть и типовые, но сложные алгоритмы, над которыми сотни людей ебутся в попытке их решиь наскоком без гугла.

Я вот сейчас хуй решу наверное опять его.

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

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

Остался остаток 4650, смотришь какие другие купюры идут следом у тебя, если тысячные есть в наличии, то ими выдаешь 4 * 1000, и далее остаток в виде 550 рублей добить.

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

Например: передаешь в неё, что разменять надо 12345 рублей пятитысячными, если в наличии много пятитысячных, то она тебе в ответ: 2, 2345
если у тебя одна пятитысячная, то она тебе: 1, 7345
ну и если нету, то: 0, 12345.

Далее думаю сообразишь, что остаток в виде 2345 можно отдавать опять же этой функции но уже с другими купюрами, и так далее пока всё не сойдется или не сойдется :(
2 Кб, 219x55
#476 #1031196
>>1031188
Там я игрался с большим количеством костей в процессе, и ели вардамп раскоментить, то что бы по возрастанию красиво всё выдавало (просто так кароче он там)
32 Кб, 643x356
#477 #1031198
Анончики, что не так?
#478 #1031199
>>1031198
Первым аргументом в preg_match() должна идти регулярка, а вторым - строка, к которой применяется регулярка.
#479 #1031202
>>1031199
Опять я обсираюсь на невнимательности.
Спасибо, анон
#480 #1031204
>>1031129

Это из-за настройки display_errors = 1 в php.ini. При ее включении, PHP выводит текст ошибки на экран (в данном случае в консоль). Плюс, в командной строке в качестве лога (журнала) ошибок используется стандартный поток ошибок, потому ошибка дополнительно еще раз логгируется в консоль.

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

Исправить сиутацию можно отключив display_errors только для консоли (иначе в браузере тоже перестанет отображаться ошибка). Это можно сделать с помощью настроек в php.ini или ключа командной строки -d error_reportng=0 в настройках, где указывается команда для запуска интерпретатора в командной строке.
#481 #1031207
>>1031204

>-d error_reportng=0


Это отключит все сообщения об ошибках.
Я же сделал -d log_errors=Off, чтобы лог не велся.
#482 #1031220
>>1029892

Тройного сравнения нет, потому надо сравнить

(кубик1 == кубик2) && (кубик2 == кубик3)

Для удобства (чтобы if не был гигантским) можно вынести результат сравнения (true/false) в переменную:

$isTripleAnon = ($кубик1 == $кубик2) && ($кубик2 == $кубик3);
$isTripleRobot = ...;

if ($isTripleAnon && $isTRipleRobot) { ... }

Но если это сложно, то можно все в if писать.

У тебя на скриншоте в проверке на трипл почему-то стоит "или" (||) в условии вместо "и".

А вообще, правильно делаешь, что усложняешь задачи.
#483 #1031221
>>1031207

А, перепутал, правильно display_error=0, точно, не надо писать error_reporting=0.
#484 #1031223
>>1031221

display_errors конечно: http://php.net/manual/ru/errorfunc.configuration.php#ini.display-errors

Логичнее отключать именно их.
#485 #1031227
я эти селекторы никогда не пройду
#486 #1031246
Делал кто телеграм бота?
Если да, то подскажите, как мне отправлять $bot->command каждую минуту бесконечно?
Если нет, то подскажите, почему while($i < 300){ $i++; code.... } не работает, а зависает?
#487 #1031372
>>1031246

>while($i < 300){ $i++; code.... }


http://ideone.com/0rBwBa
У меня не зависает. Ты вопрос неправильно задаешь.
#488 #1031384
Анончики, есть знатоки Лары?
Почему у меня после юнит-теста бд удаляется? Причем похуй успешно или нет.
#489 #1031397
>>1031384
Все пральна, за собой убирать надо.
При запуске тестов должна создаваться новая бд с фикстурами, а по окончании тестов — удаляться.
#490 #1031400
>>1031384
Лол. По хорошему, надо ещё и файлы на хостинге тереть, а домен разделегировать.
#491 #1031402
>>1031400
Когда становится скучно и нечего делать, мы запускаем тесты на прод-окружении?
#492 #1031408
>>1031402
Да шучу я, шучу.
#493 #1031410
>>1031397
Ну на видосах у челика не удаляется ничего после тестов, и да я в phpunit.xml вот такие строчки добавил:
<env name="DB_CONNECTION" value="sqlite"/>
<env name="DB_DATABASE" value=":memory:"/>
#494 #1031417
>>1031120
Ищи причину ошибки в логе, например. Или выведи их (подробные сообщения об ошибках) на экран.
47 Кб, 600x337
#495 #1031428
>>1030818
Народная казахская мудрость
#496 #1031431
>>1030802
Кто тебе вообще сказал, что будет легко? Приготовься учиться лет 10 до нормального уровня или сразу уёбывай.
#497 #1031432
>>1030786
Для винды XAMPP сейчас, пожалуй, самый удобный комплект разработчика из подобных "из коробки", юзай.
#498 #1031457
>>1031417
Собственно все в порядке, даже обычный хеловорлд не работает.
#500 #1031473
>>1031432
И чем же он удобнее чем OpenServer, например?
#501 #1031474
>>1030786
https://ospanel.io/

Лучше не найдешь.
#502 #1031475
>>1031467
Нихуя не помогло. Обычные скрипты работают нормально, а вот встроенные в phpstorm сервер никак не хочет работать.
#503 #1031477
>>1031473
>>1031474
Хуй знает, во всем мире используют XAMPP, а тут какая-то руснявая сборка
#504 #1031479
>>1031477
Ты еще расскажи о том, что Денвер в свое время был непопулярным.

ОпенСерверу уже хуй знает сколько лет и пришел он как раз на смену денверу.
#505 #1031490
>>1031477

>руснявая сборка


Ни один xampp/lamp/wamp не сравнится с этой сборкой по возможностям.
#506 #1031495
#507 #1031533
Сколько данных можно записывать в сессии? Через сколько мегабайт сервер начнет писать в штанишки?
#508 #1031534
>>1031490

>lamp


>не сравнится с этой сборкой по возможностям.


LoL. Прочувствовал расхожее мнение про пхпешников
#509 #1031558
>>1031533
сессия это просто файл
sessid - это просто кука
#510 #1031585
>>1031534
И не говори!
К нам джун из битриксоидов пришёл — такие темы задвигает, шояебал..
#511 #1031671
как мне печет,что много важной инфы только на ангельском
#512 #1031689
Допустим нужно написать нечто вроде словаря. На экране поле для ввода слов и кнопка Поиск, по которой делается запрос в БД и выводится перевод. Стоит ли ебаться в таком случае с фреймворками или лучше делать всё ручками?
#513 #1031692
нахуя нужны массивы на практике в вебе?
#514 #1031705
>>1031689
Зависит от:
- твоего уровня знаний
- объёма, по которому надо искать
- качества поиска

В простом случае это должна делать ровно 1 процедура (или запрос, в случае sqlite) в БД и 15 условно, мамкины оптимизаторы, спокойно строк на рнр
#515 #1031739
>>1031692
Для того же, для чего в реальной жизни полезны перечисления, то есть, для всего.

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

В РНР все запросы от пользователя тоже хранятся в глобальных массивах $_GET и $_POST:
в скрипте myscript.php
по адресу myscript.php?foo=bar&page=2
будет доступен массив
$_GET[
'foo'=>'bar',
'page'=>2,
];


А поле ввода <form action="script.php" method="POST"><input name='myfield'></form>
отправит информацию в массив
$_POST['myfield'];

Вывести массив на страницу можно так:
echo '<pre>'.print_r( $_GET, true ).'<pre>';
#516 #1031740
>>1031671
более того, на русском и та что есть запаздывает на несколько лет
#517 #1031742
>>1031739

>в массив $_POST['myfield'];


в значение массива $_POST по ключу 'myfield', если точнее
#518 #1031753
>>1027510
Вообще-то новые версии выходят каждые пару лет, язык развивается постоянно. Такие реалии.
#520 #1031769
>>1031705
>>1031689
Можно сделать два файла и ажакс. А так то да, проверка гета, запрос в бд, вывод и форма с инпутом и кнопкой, строчек двадцать максимум.
#521 #1031845
Анон, мне всегда казалось, что php это что-то типо javascript только намного пизже и эффективней, а язваскрипт для обсосков и т.д чтобы типо легко было.
В чем разница между php и javascript? Это ведь совершенно разные платформы для своих целей, не так ли?
На php можно делать форумы, а javascript это скриптовый язык для страниц? Объясните нуфаку. Я просто вот-вот начну изучать пхп и хочу не обосраться. Да я прекрасно понимаю, что пойму по мере изучения, но можно как нибудь поверхностно описать их работу двумя словами?
#522 #1031866
>>1031845
PHP работает на сервере: принимает и разбирает пользовательские запросы, работает с БД и сессиями.

Сейчас, в 2009, js тоже пытается это делать (node.js), но основная его роль -- выполнение прямо в браузере клиента: визуально изобразить что-нибудь (меняя html и css у клиента), отправить со страницы запрос к тому же РНР скрипту.
10 Кб, 416x180
#523 #1031873
Пиздец, какой же уебанский VS Code для написания пхп. Банальный вардамп не подсказывает. Накатываю атом, а если и там такая же хуйня, то пхпсторм.
#524 #1031882
>>1031873
Можешь сразу атом пропустить.
51 Кб, 656x431
#525 #1031884
>>1031882
Ну атом подсказывает, правда пришлось расширение добавить
#526 #1031889
для новичков советую потыкать данный фреймворк - https://phalconphp.com/ru/,
самый простой из всех mvc, достаточно чтобы познакомиться с WebMVC, и потом перейти на тотже Laravel. хотя самому всеравно больше нравится именно Phalcon
#527 #1031890
>>1031889
Туториалы есть? Туториалов нет. А значит для новичков это крайне плохой вариант. Сравни со слимом https://www.youtube.com/watch?v=RhcQXFeor9g&list=PLfdtiltiRHWGc_yY90XRdq6mRww042aEC&spfreload=10
#529 #1031894
>>1031893
Это официальная документация, которая есть у всех фреймворков, а не туториалы для ньюфагов с объяснением нюансов. Кроме того все видео на ютубе, которые я только что нашел, двухлетней давности, что многое говорит о его состоянии.

Вот я ньюфаг, выбирал вчера маленький фреймворк, и фалькон был в списке, да. И из-за отсутствия годных туториалов, он пошел нахуй. По слиму же всё есть.
33 Кб, 714x261
#530 #1031897
>>1031882
Атом тоже идет нахуй, не может в банальный extends и автокомплит имен файлов. Хоспаде, неужели пхпсторм единственный нормальный вариант.
#531 #1031902
>>1031894
я не пойму, шутишь ты или нет, вот пошаговый туториал как хелло ворлд сделать
https://olddocs.phalconphp.com/en/3.0.0/reference/tutorial.html
не смотри то что написано olddocs, текущая версия 3.3 полностью совместима с 3.0
вот тебе скелеты под приложения на все случаи жизни https://github.com/phalcon/mvc
просто не понятно, как ты искал, если это не нашел
8 Кб, 863x28
#532 #1031905
>>1031902

>пошаговый туториал как хелло ворлд сделать


Вот именно, хеллоу ворлд. А я хочу взять и сделать регистрацию на сайте, с валидацией и прочим CSRF. Зачем мне жрать кактус и гуглить в поисках крупиц информации на эту тему с фальконом, если я просто открою ссылку выше для слима, и там уже всё готовое с пояснением всех мелочей? А если мне не будет понятно, то я просто спрошу в треде, поскольку даже в шапке этот фреймворк рассматривается.
#533 #1031907
>>1031692
вот тебе псевдо код примерный, страницы каталога товаров
$products = SQL(SELECT * FROM PRODUCTS);
foreach $products as $product {
print product_card
}
#534 #1031908
>>1031905
а ты ниже смотрел?))) вторая часть туториала про форму регистрации с валидацией?
#535 #1031910
>>1031908
Нет, не заметил.
#536 #1031914
>>1031183
1) Смотришь делится ли число на 100, если нет -> еррор, если да -> п.2
2) далее смотришь хватает ли у тебя денег выдать, сумма всех купюр сравнивается с запрошенной суммой, если нет -> еррор, если да -> п.3
3) Идешь от большей купюры в меньшую, 23550 - 5000 - 5000, параллельно чекаешь чтобы купюр хватало, ну и тут либо не хватит соток например либо хватит, если нет -> еррор, если да -> то все ок
#537 #1031917
>>1031910
ну вот и я про то же, фв очень простой, дело освоения пары часов(если знаком с пхп хотябы на 4/10), если не знаком ну 1-2 дня(максимум около недели, зависит от общего понимания программирования и WebMVC паттерна)
#538 #1031919
>>1031917
А на слиме ты делал что-то? Можешь сравнить*?
#539 #1031922
>>1031897
Ну ты перебираешь блокноты какие-то.
Из бесплатных IDE можешь ещё помучиться с Eclipse, а так да -- плати за PHPStorm, это норма.
#540 #1031943
>>1031866
Спасибо анон, добра.
#541 #1031950
>>1031889

>данный фреймворк


пхалькон не фреймворк
#542 #1031956
>>1031919
Сам не писал, но почитал документацию сейчас, слим посложнее фалкона будет, да и выглядит слим как странная песочница а не фреймворк, тотже фалкон или ларавел, сразу написано что и как по структуре, есть дефолтный роутинг, который не нужно расписывать(SITEName/ControllerName/ActionName). в фалконе довольно хорошая орм, и querybuilder прекрасный просто. пишется очень легко и проблемы редко возникают с ним.
#543 #1031957
>>1031950
https://phalconphp.com/ru/
прочитай то что написано по центру экрана
#544 #1031962
>>1031919
вообще советую сильно не увлекаться ТОЛЬКО бэкендом, а посмотреть в сторону фронта еще, например Vue или React(ангулар кал)
#545 #1031963
>>1031962
Я планирую вью использовать.
#546 #1031967
анончики, кто писал бота под телеграм? Подскажите, где гуглить вопросы.
Интересует момент такой
$bot->command с аргументом, обрабатывая этот аргумент
#547 #1032002
Ребят, у меня очень странная проблема.

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

Это похоже на то, что я просто указал путь к файлу который не изменяется, а к тому файлу, который я изменяю, никаких путей подключения не проложено. Но это не так!. Этот styles.css единственный css файл в моем проекте, и только его удаление приводит к выводу на странице чистого html.

Данную проблему я решил переименовыванием этого файла, и собственно внесение этого нового имени в путь подключения, и это работает. Но я не могу понять почему происходит хуйня, описанная выше (у меня 2 раза такое было). Было у кого нибудь такое?
#548 #1032004
>>1032002
Хотя сейчас даже при его удалении выводятся его стили.
#549 #1032007
>>1032002
Ну обычно это кеш браузера, как бы ничего странного. Обновление по ctrl+f5 (без кеша) работает же?
#550 #1032008
>>1032007
Блять я дебил. Спасибо. Я блять даже про это не знал.
#551 #1032019
>>1032008
Для того и тред... Двуч образовательный
#552 #1032037
>>1031957
да но не забывай про м маркетинг , так как и все мвц фреймворки по факту строго не могут быть в полной мере мвц из за особенностей протокола , но это не мешает фиигачить на сайтах слово мвц верно?
#553 #1032038
>>1031957
алсо покажи мне ещё 1 фреймворк который надо устанавливать через php.ini в лучшем случае а то и компилить с его
#554 #1032041
>>1032038
ну это типа их плюс, что они написали свой фреймворк не на относительно-медленном интерпретируемом языке, а на быстром компилируемом.

Но чё-т после того, как недавно понадобилось что-то на их сайте, а он лежал лёжа несколько часов или даже дней подряд, мне чё-т расхотелось. Пусть сами свой велосипед крутят, на здоровье, а для меня РНР 7.1++ и так достаточно производительный.
#555 #1032047
>>1032041
Ну и на старте проекта вся эта избыточная оптимизация не в плюс, да ещё и хостинг надо отдельный искать под это дело. В общем, задумка хорошая, но спасибо, не ннада
#556 #1032059
#557 #1032063
>>1031957
использую фалкон, конкретно как апишку для фронта на реакте, он быстро позволяет реализовать нормальную апишку
50 Кб, 400x400
#558 #1032158
Есть файл генерящий капчу, где его расположить в ларавел, чтобы соответствовал файловой структуре?
#559 #1032192
>>1032158
В контроллере
#560 #1032208
>>1032158
Можно создать отдельный класс вроде CaptchaService, который будет заниматься генерацией и проверкой капчи.

>>1032192
Прочитай про толстый контроллер, советчик. Что если капча ему в нескольких местах на сайте понадобится?
#561 #1032222
>>1032208

>Можно создать отдельный класс


и это норма, если я в методе этого класса буду отправлять mime заголовок чтобы отдавалась картинка и писать код каптчи в сессию?
#562 #1032235
Какие книги почитать про PHP7?
#563 #1032241
>>1032235
Никакие, почитай migration guide для PHP 7.0 и 7.1 на php.net или выжимки вроде этих:
- https://github.com/tpunt/PHP7-Reference
- https://github.com/tpunt/PHP7-Reference/blob/master/php71-reference.md
#564 #1032249
Помогите написать микрофреймворк, я что-то не понимаю как всё должно быть устроено.

Например я написал автолоад через
spl_autoload_register
В нем указал 1 папку с файлами, допустим это папка Core
Теперь у меня подгружаются Классы из папки Core

Но как использователь неймспейсы вместе с этим всем? Я проставил классам неймспейсы, и всё сломалось.
Классу роутер который лежит в Core/Router.php например я пишу namespace Core;
Но если я пишу в файле индекс, который лежит снаружи папки Core такую штуку как:
use Core\Router;
то всё ломается. Не понимаю чего-то.
#565 #1032253
>>1032249

Почитай урок про автозагрузку и неймспейсы https://github.com/codedokode/pasta/blob/master/php/autoload.md
#566 #1032255
>>1032235
про РНР вообще или РНР7?

кстати, странно что в шапке нет http://www.phptherightway.com/
sage #567 #1032276
>>1032255
Есть, там ссылка на русскую версию.
#568 #1032278
>>1032158
Бамп
#569 #1032281
Заметил, что тут есть пара матёрых дядек,
кто-нибудь может подсказать:

в PHP 7.1 на этапе исполнения есть ли какая-то разница
между [] и array() //для совместимости со старым PHP5 ?
#570 #1032292
>>1032281
только для совместимости с <5.4
#571 #1032296
>>1032292
ну для выполнения на РНР7 или 7.1 будет какая-то разница, или нет (просто написание)?
#572 #1032300
>>1032281

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

Информации про это расширение на русском мало:

- рус https://habrahabr.ru/company/mailru/blog/305906/
- рус https://habrahabr.ru/post/211156/
- англ https://derickrethans.nl/more-source-analysis-with-vld.html

Запустим 2 варианта кода и посмотрим на результат компиляции:

php -dvld.active=1 -r '$a = array();'

INIT_ARRAY ~0
ASSIGN !0, ~0
RETURN null

php -dvld.active=1 -r '$a = [];'

INIT_ARRAY ~0
ASSIGN !0, ~0
RETURN null

результат в PHP5, как мы видим, идентичен.

Также, VLD-дизассемблер есть на сайте 3v4l.org, там я тоже попробовал сделать 2 варианта кода:

https://3v4l.org/lKUHM/vld#output
https://3v4l.org/fnVqn/vld#output

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

Но вообще, даже если бы разница и была, не стоит о ней беспокоиться, это вряд ли будет заметно на общем времени выполнения программы.
#572 #1032300
>>1032281

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

Информации про это расширение на русском мало:

- рус https://habrahabr.ru/company/mailru/blog/305906/
- рус https://habrahabr.ru/post/211156/
- англ https://derickrethans.nl/more-source-analysis-with-vld.html

Запустим 2 варианта кода и посмотрим на результат компиляции:

php -dvld.active=1 -r '$a = array();'

INIT_ARRAY ~0
ASSIGN !0, ~0
RETURN null

php -dvld.active=1 -r '$a = [];'

INIT_ARRAY ~0
ASSIGN !0, ~0
RETURN null

результат в PHP5, как мы видим, идентичен.

Также, VLD-дизассемблер есть на сайте 3v4l.org, там я тоже попробовал сделать 2 варианта кода:

https://3v4l.org/lKUHM/vld#output
https://3v4l.org/fnVqn/vld#output

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

Но вообще, даже если бы разница и была, не стоит о ней беспокоиться, это вряд ли будет заметно на общем времени выполнения программы.
#573 #1032301
>>1032300
Спасибо, буду пробовать

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


вы совершенно правы, разве что для оптимизации узких мест, потому и спросил
#574 #1032306
Блять, когда перекат?
#575 #1032307
>>1032158
>>1032278

Во-первых, в MVC логично разделить генерацию картинки и ее отдачу. Генерирует картинку класс капчи, а отдает ее и добавляет нужные заголовки контроллер капчи.

Куда поместить класс, генерирующий картинку? Такие классы называют сервисы (или хелперы), логично поместить его в папку App/Service или App/Helper.
#576 #1032308
>>1032307
ларавел - не мвц фреймворк
#577 #1032314
>>1032308
прочитай как расшифровывается mvc, а потом подумай еще раз, пожалуйста
#578 #1032315
>>1032308
а так же посмотри, что есть несколько интерпретаций mvc паттерна
#579 #1032317
>>1032315
>>1032314
а знаю что, что в MVC обработка данных происходит в моделе. Ларавел не соответствует этому
#580 #1032319
>>1032317

А что-то запрещает реализовать MVC в Ларавеле и поместить бизнес-логику в отдельные классы?
#581 #1032324
>>1032319
Ничто не запрещает, только MVC оно от этого не станет, т.к. бизнес-логика должна быть не в "отдельных классах", а в моделях
#582 #1032329
>>1032324

Так а чем эти "отдельные" классы отличаются от "модели"? У тебя по моему путаница в терминологии.

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

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

В Симфони например вообще классов с названием "модель" нет.

Что ты подразумеваешь под "моделью"?
#583 #1032332
Аноны, выручайте.
Решаю задачку на проверку телефонов
http://archive-ipq-co.narod.ru/l1/regexp.html
Какой метод и как мне использовать, чтобы сформировать новый массив просто с цифрами, чтобы потом отсортировать номера?
match_all через цикл я прогоняю в новый массив, но он туда вписывает ересь на пиках.
Может я пропустил что-то?
#584 #1032333
>>1032329

>Что ты подразумеваешь под "моделью"?


Класс содержащий бизнес-логику. А ларавел под моделью подразумевает класс являющийся ссылкой на таблицу БД, а классы в которых должна быть логика, называет контроллерами
#585 #1032334
>>1032332
А как делается "или" чтобы стоял вначале?
Типа ab?c но только чтобы выбирал между 7 и 8 вначале.
113 Кб, 820x680
#586 #1032354
>>1032332
Как имплодом воспользоваться теперь, аноны? Вот что выдает
#587 #1032381
>>1032354
Вроде воспользовался. Другое дело, что эта функция возвращает строку, а не присваивает ее. Попробуй сдампить implode(parts)
http://ideone.com/BgpC6G
302 Кб, 757x1136
#588 #1032398
Зашел в ваш тред от скуки, пока ничего интересного для себя не нашел. Давно пишу на ПОХАПЕ различные темы и плагины на продажу (wordpress, themeforest). Общаюсь с клиентами каждый день, работаю в качестве техсаппорта. Отвечу на любые вопросы если есть (о клиентах, разработке, о чем угодно).
#589 #1032446
>>1032332
Твое регулярное выражение ищет просто одну цифру в любом месте строки. Не удивительно, что у тебя каждое число помещается в массив $совпаден(ие)ий.
Тебе нужно добавить в регулярное выражение метасимвол означающий повторение один или несколько раз +

http://php.net/manual/ru/regexp.reference.meta.php

>+ квантификатор, означающий 1 или более вхождений



Ещё ты при каждом обходе итерации цикла выводишь массив совпадений, а не выводишь его один раз при завершении цикла.

Почитай ещё про оформление кода >>1019303

>>1032334
http://php.net/manual/ru/regexp.reference.alternation.php

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

http://php.net/manual/ru/regexp.reference.subpatterns.php

>1. Локализирует набор альтернатив. Например, шаблон cat(aract|erpillar|) соответствует одному из слов "cat", "cataract" или "caterpillar". Без использования скобок он соответствовал бы строкам "cataract", "erpillar" или пустой строке.



>>1032354
Почему ты пользуешься функцией preg_split, когда для нахождения совпадений есть preg_match?

http://php.net/manual/ru/function.preg-match.php

Функция implode() объединяет массив в строку, а ты пытаешься передать в эту функцию строку.

http://php.net/manual/ru/function.implode.php

>>1032381
Как неожиданно, но чтобы присвоить нужно воспользоваться оператором присваивания =

$variable = implode(...);
#589 #1032446
>>1032332
Твое регулярное выражение ищет просто одну цифру в любом месте строки. Не удивительно, что у тебя каждое число помещается в массив $совпаден(ие)ий.
Тебе нужно добавить в регулярное выражение метасимвол означающий повторение один или несколько раз +

http://php.net/manual/ru/regexp.reference.meta.php

>+ квантификатор, означающий 1 или более вхождений



Ещё ты при каждом обходе итерации цикла выводишь массив совпадений, а не выводишь его один раз при завершении цикла.

Почитай ещё про оформление кода >>1019303

>>1032334
http://php.net/manual/ru/regexp.reference.alternation.php

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

http://php.net/manual/ru/regexp.reference.subpatterns.php

>1. Локализирует набор альтернатив. Например, шаблон cat(aract|erpillar|) соответствует одному из слов "cat", "cataract" или "caterpillar". Без использования скобок он соответствовал бы строкам "cataract", "erpillar" или пустой строке.



>>1032354
Почему ты пользуешься функцией preg_split, когда для нахождения совпадений есть preg_match?

http://php.net/manual/ru/function.preg-match.php

Функция implode() объединяет массив в строку, а ты пытаешься передать в эту функцию строку.

http://php.net/manual/ru/function.implode.php

>>1032381
Как неожиданно, но чтобы присвоить нужно воспользоваться оператором присваивания =

$variable = implode(...);
#590 #1032448
>>1032398
Изучать PHP можно сразу после того как изучишь html5/css3?
#591 #1032449
>>1032002
Как выше обяснили это браузер кеширует стили. И например он зашел на твой сайт hueta.loc, скачал твой style.css и всё. Потом если ты вносишь правки в стили, но может смотреть что ситил уже скачаны и подгружать те что скачивал когда-то давно.

Причем если ты шарящий чел, то какие-нибудь клиенты нихуя не такие и что бы избежать того, что бы отвечать в последствии на звонки с разъяснениями ЭС как доллар и нажмите CTRL+F5, ты в шапке или где у тебя там подгружается стиль дописывай ему версию.

<link rel="stylesheet" type="text/css" href="style.css?ver=111" />

А после того как внес изменения в файл то эту версию в шапке обновляй

<link rel="stylesheet" type="text/css" href="style.css?ver=112" />

Браузеры всех кто зайдет после этого автоматически будут обязаны скачать обновленный файл.
#592 #1032454
>>1032398

>бя не нашел. Давно пишу на ПОХАПЕ различные темы и плагины на продажу (wordpress, themeforest). Общаюсь с клиентами каждый день, работаю в качес


Очень интересно было бы кулстори про themeforest послушать. А дизайн тем сами пилите? Или просто сотрудничаете с дизайнерами?
#593 #1032460
Стоит ли заморачиваться с ларавелом для хобби проекта? Или это из пушки по воробьям и для работы с ним нужна целая команда?
#594 #1032548
>>1032460
отвечу так: почему бы и нет?
в свое время ларавел,вуе,реакт,ангулар,фалкон сидел тыкал как хобби, потом уже пилил коммерс проекты на них
#595 #1032659
>>1030299
Я придумал алгоритм шифрования, но у меня есть несколько вопросов

При регистрации пользователя мы генерируем закртый\открытый ключ

$privateKey = openssl_pkey_new(array(
"digest_alg" => $method,
"private_key_bits" => 4096
));

$publicKey = openssl_pkey_get_details($privateKey)['key'];

Закрытый ключ шифруем паролем

$encryptedKey = openssl_encrypt($privateKey, $method, str2hex($password));

И помещаем их в БД

http://php.net/manual/ru/function.openssl-get-cipher-methods.php#refsect1-function.openssl-get-cipher-methods-examples
Почему нету метода RSA? Однако, в опциях создания ключа можно указать этот тип Что это вообще может значить??. Эти все методы сделаны на его основе?

Какой метод лучше выбрать?

http://php.net/manual/ru/function.openssl-public-encrypt.php#118466
В комментариях сказано, что RSA начинает устаревать и пора переходить на ECDH вместе с EdDSA. Что вы думаете по этому поводу?

Насколько я помню, протокол Диффи - Хеллмана генерирует общий ключ на основе закрытых\открытых ключей. Можно ли сказать, что этот протокол приводит асимметричное шифрование к симметричному?
Эллиптические кривые только добавляют надёжности, я правильно понимаю?

Такой алгоритм подошел бы если бы мы реализовывали вариант с шифрованием сообщений конференции общим ключем.

Далее

Сообщения шифруются но основе открытых ключей собеседников

// Ничего особенно за исключением опции добавления OPENSSL_PKCS1_OAEP_PADDING,
// которое рекомендуется из комментария выше
openssl_public_encrypt($message, $crypted, $publicKey, OPENSSL_PKCS1_OAEP_PADDING);

Расшифровка происходит аналогичным способом

openssl_private_decrypt($message, $decrypted, $privateKey, OPENSSL_PKCS1_OAEP_PADDING);

Остается только найти js библиотеку для шифровки\дешифровки аналогичным способом.

Я нашел вот эту http://www-cs-students.stanford.edu/~tjw/jsbn/ , но я не уверен что библиотека которая содержится в PHP использует алгоритм RSA (там какие-то методы (ссылаюсь на тот же вопрос выше о методах)).

К тому же, я не знаю как с помощью RSA т.е. js библиотеки реализующей его расшифровать ключ который мы шифровали паролем, потому что нет возможности получить пары {e, n}\{d, n} из произвольной hex-строки.
Я бы смог решить эту проблему, если бы знал каким образом функция openssl_encrypt() шифрует данные из этой строки. Всё ещё запутан вопросом о методах шифрования Вы случайно не знаете что-нибудь об этом?

http://php.net/manual/ru/function.openssl-encrypt.php

>jsbn.js


>jsbn2.js


Зачем разделять код на две части? Это не более чем прихоть автора?
#595 #1032659
>>1030299
Я придумал алгоритм шифрования, но у меня есть несколько вопросов

При регистрации пользователя мы генерируем закртый\открытый ключ

$privateKey = openssl_pkey_new(array(
"digest_alg" => $method,
"private_key_bits" => 4096
));

$publicKey = openssl_pkey_get_details($privateKey)['key'];

Закрытый ключ шифруем паролем

$encryptedKey = openssl_encrypt($privateKey, $method, str2hex($password));

И помещаем их в БД

http://php.net/manual/ru/function.openssl-get-cipher-methods.php#refsect1-function.openssl-get-cipher-methods-examples
Почему нету метода RSA? Однако, в опциях создания ключа можно указать этот тип Что это вообще может значить??. Эти все методы сделаны на его основе?

Какой метод лучше выбрать?

http://php.net/manual/ru/function.openssl-public-encrypt.php#118466
В комментариях сказано, что RSA начинает устаревать и пора переходить на ECDH вместе с EdDSA. Что вы думаете по этому поводу?

Насколько я помню, протокол Диффи - Хеллмана генерирует общий ключ на основе закрытых\открытых ключей. Можно ли сказать, что этот протокол приводит асимметричное шифрование к симметричному?
Эллиптические кривые только добавляют надёжности, я правильно понимаю?

Такой алгоритм подошел бы если бы мы реализовывали вариант с шифрованием сообщений конференции общим ключем.

Далее

Сообщения шифруются но основе открытых ключей собеседников

// Ничего особенно за исключением опции добавления OPENSSL_PKCS1_OAEP_PADDING,
// которое рекомендуется из комментария выше
openssl_public_encrypt($message, $crypted, $publicKey, OPENSSL_PKCS1_OAEP_PADDING);

Расшифровка происходит аналогичным способом

openssl_private_decrypt($message, $decrypted, $privateKey, OPENSSL_PKCS1_OAEP_PADDING);

Остается только найти js библиотеку для шифровки\дешифровки аналогичным способом.

Я нашел вот эту http://www-cs-students.stanford.edu/~tjw/jsbn/ , но я не уверен что библиотека которая содержится в PHP использует алгоритм RSA (там какие-то методы (ссылаюсь на тот же вопрос выше о методах)).

К тому же, я не знаю как с помощью RSA т.е. js библиотеки реализующей его расшифровать ключ который мы шифровали паролем, потому что нет возможности получить пары {e, n}\{d, n} из произвольной hex-строки.
Я бы смог решить эту проблему, если бы знал каким образом функция openssl_encrypt() шифрует данные из этой строки. Всё ещё запутан вопросом о методах шифрования Вы случайно не знаете что-нибудь об этом?

http://php.net/manual/ru/function.openssl-encrypt.php

>jsbn.js


>jsbn2.js


Зачем разделять код на две части? Это не более чем прихоть автора?
#596 #1032663
>>1032460
По опыту работы на Codeigniter скажу что поначалу всё кажется пиздец сложно просто потому что там много всего и с ходу непонятная иерархия и бла бла, но сейчас я бы оповские задачи (которые я на пьюр-пхп ща пытаюсь осилить и сосу в них) по типу студентов на нем худо-бедно накидал буквально за час в силу того что там всё уже написано и на фреймворке хуярить модельки и контроллеры куда проще в итоге.
#597 #1032686
Можете помочь с составлением eloquent запроса в ларавеле?

>>1032548
И ты тоже.
70 Кб, 787x572
#598 #1032703
>>1032446
Понял свою ошибку.
Не использую match, потому что хотел сделать по-своему без сложной регулярки.
Сейчас попробую сделать с ней.
#599 #1032705
3-день-в-клубе-кун репортинг.
Проверьте пжлст задачки:
Имя кошки - http://ideone.com/9gYMJD
Лев Толстой: http://ideone.com/c7jA9P
Палиндром: http://ideone.com/k76YfM (внезапно на ideone не работает утф-8, на пхптестере вроде все норм)
Заранее пасяб.
#600 #1032711
>>1032703
>>1032446

>сначала идет +7 или 8, за ними ровно 10 цифр, между которыми может быть любое число скобок, минусов, пробелов


(+7|8)
Ну а как написать чтобы между ними может быть любое число скобок и прочего дерьма я не нашел в уроке
#601 #1032720
>>1032711
Там есть про поиск специальных символов и как искать "любой символ, кроме" каретом ^
#602 #1032729
>>1032720
Нет, как мне написать, что между цифрами может быть S+-_ и т д
#603 #1032730
https://ideone.com/4M2YGS
Это опять я, короче все збс работает, теперь мне нужно обратиться к свойству объекта, который находится в массиве $workers, а это в cвою очередь свойство объекта $quest, как это реализовывается?
#604 #1032731
>>1032729
>>1032720
([+7]|8)[0-9(\/S+)?]{10}
Вот такое не работает.
#605 #1032881
Есть одна таблица в PostgreSQL - id SERIAL PRIMARY KEY, data JSONB NOT NULL. Есть один запрос, который пытается пихнуть в таблицу json-строку и достать её уникальный идентификатор:

if(isset($_POST['data']) && !empty($_POST['data'])) {
$data = json_encode($_POST['data'], JSON_UNESCAPED_UNICODE);
//DB
$db = getdb();
$query = "INSERT INTO searches (data) VALUES ('$data') RETURNING id";
$result = pg_query($query) or die('Query failed: ' . pg_last_error());
pg_close($db);
echo $result;
}

Так вот какого-то хуя echo $result возвращает мне не id, а какую-то хуйню вроде Resource id #4 или Resource id #5. Какого хуя блядь?
#606 #1032887
>>1032881
всё правильно , что бы получить результат нужно использовать ещё функцию
#607 #1032888
>>1032881
Возвращается резалтсет, как и при обычном селекте. Его надо разобрать
http://php.net/manual/en/pdostatement.fetchall.php
#608 #1032893
>>1032888
Вот это оно? $result = $sth->fetchAll();

И почему оно мне возвращает то 4, то 5?
#609 #1032902
Почему он не работает? Он не должен 1000 показывать? https://ideone.com/6VKG0m
#610 #1032906
>>1032902
Потому что у тебя нет в массиве элемента с ключём 0
#611 #1032910
>>1032906
Как нет? 1000 => 0, почему не считается? Ключ первым должен идти?
#612 #1032912
>>1032906
Всё.
#613 #1032917
>>1032906
А если у меня ключи числами, то будет ли работать действие с указанием элемента массива? Смогу ли я изъять третий по счёту массив, или он будет изничтожать элемент с ключом 3?
#614 #1032923
>>1032917
Переформулируй вопрос пожалуйста, вообще не понятно как-то что ты хочешь?
#615 #1032927
>>1032917
Можешь вот так хранить значения если тебе именно нужно обращаться к элементам.
https://ideone.com/5nE5SR
#616 #1032928
>>1032923
Я задал элементам массива ключи числами, 1, 2 и т.д. Но мне нужно изъять третий элемент массива. Если я напишу unset($arrays{3}); то что будет изъято? Третий по счёту элемент, или тот, что имеет ключ 3? Чому не работает? https://ideone.com/H6wN3Y
#617 #1032941
Какой стоит скачать учебник, чтобы в свободное время можно было читать с телефона, не имея пеки и доступа в интернет?
323 Кб, 410x600
#618 #1032947
Нормальный? Если я немного глуповат, то пойму?
Автор: Игорь Симдянов, Дмитрий Котеров Издательство: БХВ-Петербург Год: 2016 Язык: Русский ISBN: 978-5-9775-3725-4 Страниц: 1073
#619 #1032960
>>1032928

unset($array[0]) - удаляет элемент массива с ключом 0;

if($bills[$z] == 0){
unset($bills[$z]);
}
если элемент массива с ключом $z равен нулю, то удаляем его.

Ты вообще массивы проходил? Нахуя ты сложные задачи лезешь решать, если ты нихуя основ базовых не понимаешь? Как тебе повезло что у нас тут приличный тред, в соседнем ты бы уже захлебнулся в ссанине, смекаешь?
#620 #1032967
>>1032960
Я их проходил, но давно. Забыл, видать.
#621 #1032988
>>1032887
>>1032888
Разобрался.

$row = pg_fetch_row($result);
$user_id = $row[0];
#622 #1032995
>>1032448
Чем раньше начнешь изучать ПОХАПЕ, тем лучше. Даже не обязательно пхп, а просто любой серверный язык программирования, хоть перл, хоть руби, хоть джаваскрипт. Я бы посоветовал изучать что-нибудь асинхронное. Потому что бекэнд намного интереснее фронтэнда (хоть на фронтэнде тоже интересно бывает, иногда).

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

Бекэнд:
Как организовать структуру проекта? Как реализовать алгоритм разбивки по страницам? Как вынести повторяющийся функционал в отдельный класс? Как реализовать rest api? Кеширование? Оптимизировать скорость работы?

И т.д. То есть он интереснее для программистов, да и многие бекэндщики - это матерые фронтэндщики, перекатившиеся на server-side.

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

Про клиентов я писал тут >>935109 >>935303 >>938423. Вкратце, работенка пиздец. Любая хуйня что случится - винят автора темы. Например, купили хостинг за 3 копейки, там оперативной памяти меньше, чем в калькуляторе. А это всё автор виноват! Хуле ты не мог сделать так, чтобы сайт даже на калькуляторе работал?! ИЛИ я поставили плагин и страница вылетает с фатальной ошибкой, скрипты не загружаются. ПОЧЕМУ ВЫ НЕ МОГЛИ СДЕЛАТЬ ЧЕЛОВЕКОПОНЯТНЫЕ СООБЩЕНИЯ ОБ ОШИБКАХ?

Постоянная ебля с обновлениями - Visual Composer обновляется и там постоянно что-то отваливаются, то шорткоды, то настройки pricing table пропадут, то ещё что. WooCommerce обновляется практически каждые две недели, заебешься его шаблоны обновлять. У них там то конфликт с ACF, то ещё че...

+ Конкуренция + у самого themeforest'a ещё и комиссии пиздецовые + он душит своей политикой. Они запускают хуйню, что-то вроде Envato Elements, там оформляешь подписку на год по-моему за 50-60 долларов и весь год качаешь любые темы. Нам это вообще не выгодно, собираемся уйти с тимфореста, открывать свой сайт-магазин.
#622 #1032995
>>1032448
Чем раньше начнешь изучать ПОХАПЕ, тем лучше. Даже не обязательно пхп, а просто любой серверный язык программирования, хоть перл, хоть руби, хоть джаваскрипт. Я бы посоветовал изучать что-нибудь асинхронное. Потому что бекэнд намного интереснее фронтэнда (хоть на фронтэнде тоже интересно бывает, иногда).

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

Бекэнд:
Как организовать структуру проекта? Как реализовать алгоритм разбивки по страницам? Как вынести повторяющийся функционал в отдельный класс? Как реализовать rest api? Кеширование? Оптимизировать скорость работы?

И т.д. То есть он интереснее для программистов, да и многие бекэндщики - это матерые фронтэндщики, перекатившиеся на server-side.

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

Про клиентов я писал тут >>935109 >>935303 >>938423. Вкратце, работенка пиздец. Любая хуйня что случится - винят автора темы. Например, купили хостинг за 3 копейки, там оперативной памяти меньше, чем в калькуляторе. А это всё автор виноват! Хуле ты не мог сделать так, чтобы сайт даже на калькуляторе работал?! ИЛИ я поставили плагин и страница вылетает с фатальной ошибкой, скрипты не загружаются. ПОЧЕМУ ВЫ НЕ МОГЛИ СДЕЛАТЬ ЧЕЛОВЕКОПОНЯТНЫЕ СООБЩЕНИЯ ОБ ОШИБКАХ?

Постоянная ебля с обновлениями - Visual Composer обновляется и там постоянно что-то отваливаются, то шорткоды, то настройки pricing table пропадут, то ещё что. WooCommerce обновляется практически каждые две недели, заебешься его шаблоны обновлять. У них там то конфликт с ACF, то ещё че...

+ Конкуренция + у самого themeforest'a ещё и комиссии пиздецовые + он душит своей политикой. Они запускают хуйню, что-то вроде Envato Elements, там оформляешь подписку на год по-моему за 50-60 долларов и весь год качаешь любые темы. Нам это вообще не выгодно, собираемся уйти с тимфореста, открывать свой сайт-магазин.
#623 #1032996
>>1032995
https://2ch.hk/biz/res/927632.html (М) вот ссылка на тред, в конце мои ответы.
#624 #1033000
>>1032995

>перл


>руби


Да ну в пизду это хипстерское поделие.

Другой анон

Я пару дней назад решил начать вкатываться в MongoDB и вообще в базы данных. Последний раз я базу данных видел в универе в прошлом году, где мы изучали азы БД на примере Access, а потом MySQL и phpMyAdmin. Мне казалось, что MySQL старьё, и все эти реляционные БД - нахуй их, миром правит NoSQL и JSON. Это всё лирика. Боже, блядь, как же я ошибался. Я за двое суток так люто наебался с Mongo, что теперь я даже лучше говна сожру, чем буду пытаться в этой поделке что-то разобрать. Поставил PostgreSQL, пару часов курения доки, пару вопросов на StackOverflow, 1 вопрос в /pr/ и у меня всё закрутилось-завертелось. Та же хуйня с Ruby/Perl/etc. Лучше выбирать классический джентельменский набор - PHP + MySQL/Postgre + JS на фронте. А то напридумывают свои какие-то моднявые связки Go + TypeScript, а потом молодняк приходят на StackOverflow с каким-то вопросом и ждёт ответа по 6-7 часов от того несчастного мелкого комьюнити, которое образовалось в следствие саздания новага язига, каторый, сматрите, бистрее пыхыпы на 5%!. Фу блять.
#625 #1033005
MariaDB-что скажете?
#626 #1033008
Ссылки для унижения пистонистов,
современный PHP 7 в среднем в 2-3 раза быстрее Python:

https://benchmarksgame.alioth.debian.org/u64q/php.html

https://benchmarksgame.alioth.debian.org/u64q/compare.php?lang=php&lang2=hack

https://benchmarksgame.alioth.debian.org/u64q/compare.php?lang=php&lang2=yarv

(выше в тестах сложные алгоритмы, а на базовых операция -- циклы, динамические массивы, простые мат.операции PHP быстрее в 3 раза)
#627 #1033016
>>1032947
Ну как-то поймёшь, вопрос -- на каком уровне. Не попробуешь -- не узнаешь, опять же.
#628 #1033017
>>1032995
Проиграл с матёрого фронтендщика
#629 #1033018
>>1033000
Так он и не быстрее, как правило... Там выше есть ссылки.
#630 #1033019
>>1033005
Юзаю в конторе, всё нормально, подводных не обнаружено.
#631 #1033020
>>1033008
А теперь давай то же для жс на ноде.
#632 #1033021
>>1032548
>>1032663
Вы заебали, помогите нуфагу с ларавелем. Допустим есть несколько связанных таблиц, в чистом пхп я бы сделал по классу на каждую таблицу с полями колонок, а потом имел массивы объектов. Как это делается правильно в ларавеле???
#633 #1033029
>>1033018
Я не столько хотел заострить внимание на производительности, сколько на объёме комьюнити. На PHP уже столько гайдов и мануалов, столько собак съедено, что в него достаточно просто войти имея желание, терпение и умение правильно формировать поисковые запросы в гугле. А они продолжают создавать Ruby, Go, Rust, Perl, etc тем самым разбивая комьюнити на меньшие группки.
#634 #1033037
>>1033020
у дж на ноде есть проблема ака каждую неделю учи новый фреймворк , алсо там нормальное ООП ещё не подвезли даже с ES6
#635 #1033039
>>1033008
я думаю ты же понимаешь в чём разница работы ужа и пыхи ?
#636 #1033040
>>1033021
гугли доктрину , или Eloquent
#637 #1033041
>>1033029
Ruby вышел в том же году что и php , но как не странно на борту у него уже тогда был бест практис , что и стало даже + ибо не было тонны говнокода

Go мимо ибо он убийца С\С++ потому ниша в вебе у него не велика

Rust туда же к GO

Perl - старый пережиток был ранее PHP
#638 #1033064
>>1033040
Я спрашиваю о логике, а он меня посылает гуглить синтаксис.
#639 #1033068
>>1033041
>>1033037
Хорошь флеймить, идите в срач-тред
#640 #1033093
А я просто зашёл поблагодарить ОП за его задачки и сайт. Ты помог найти мне работу, а не оставаться тухнуть в универе на даунской специальности технолог нефтепереработки
#641 #1033099
>>1033041

Руби (точнее популярный фреймворк Руби он Рейлс) за образец точно брать не стоит, там были приняты такие вещи, как патчинг одним модулем другого: https://habrahabr.ru/company/Voximplant/blog/269467/

Ну и вообще там много неоднозначного, везде статические вызовы, в тех же моделях замешаны active record, валидация, генерация ссылок.

>>1033029

В создании новых языков нет ничего плохого - потому что часто старые языки (PHP) нельзя так просто переделать из-за проблем совместимости.

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

>>1032928

Удаление делается по ключу. Вообще, ключи в массиве сделаны специально, чтобы искать по ним элементы.

> for($z = 0; $z <= count($bills); $z++) {


> if($bills[$z] == 0){


Ты в цикле ищешь элементы с ключами 0, 1, 2 ..., а у тебя в массиве таких ключей нет. Для перебора массива лучше использовать foreach, а не for.

>>1032910

Ключ элемента массива указан слева, значение элемента справа.
#642 #1033100
>>1032893

Посмотри мануал по функции pg_query: http://php.net/manual/ru/function.pg-query.php

> Возвращаемые значения


> Ресурс результата запроса в случае успеха или FALSE в случае возникновения ошибки



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

Я советую почитать про то, как пользоваться pg-функциями, начать можно отсюда: http://php.net/manual/ru/pgsql.examples-basic.php

Вот инфа про ресурсы, если надо: http://php.net/manual/ru/language.types.resource.php

Также, у тебя в коде SQL инъекция, нельзя вставлять данные прямо в запрос: https://github.com/codedokode/pasta/blob/master/security/sql-injection.md

>>1032731

Потому что неправильно написано. Давай на это посмотрим:

[+7] - это обозначает "ровно один символ из набора '+' или '7'". Перечитай, что обозначают разные виды скобок. Квадратные скобки обозначают "один любой из указанных символов".

>>1032730

> foreach ($quest->workers->w as $w->endStavka = $value)


так писать нельзя, справа от as нужно указать одну или две переменных, а не выражение. Перечитай пожалуйста про цикл foreach: http://php.net/manual/ru/control-structures.foreach.php

И тогда наверно ошибка исчезнет.

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

>>1032729

А ты попробуй написать такое выражение:

- цифра, за ней любой из символов \s ( ) -, повторяющийся любое число раз

После чего возьми его в скобки и укажи, что оно повторяется ровно 10 раз.
#642 #1033100
>>1032893

Посмотри мануал по функции pg_query: http://php.net/manual/ru/function.pg-query.php

> Возвращаемые значения


> Ресурс результата запроса в случае успеха или FALSE в случае возникновения ошибки



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

Я советую почитать про то, как пользоваться pg-функциями, начать можно отсюда: http://php.net/manual/ru/pgsql.examples-basic.php

Вот инфа про ресурсы, если надо: http://php.net/manual/ru/language.types.resource.php

Также, у тебя в коде SQL инъекция, нельзя вставлять данные прямо в запрос: https://github.com/codedokode/pasta/blob/master/security/sql-injection.md

>>1032731

Потому что неправильно написано. Давай на это посмотрим:

[+7] - это обозначает "ровно один символ из набора '+' или '7'". Перечитай, что обозначают разные виды скобок. Квадратные скобки обозначают "один любой из указанных символов".

>>1032730

> foreach ($quest->workers->w as $w->endStavka = $value)


так писать нельзя, справа от as нужно указать одну или две переменных, а не выражение. Перечитай пожалуйста про цикл foreach: http://php.net/manual/ru/control-structures.foreach.php

И тогда наверно ошибка исчезнет.

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

>>1032729

А ты попробуй написать такое выражение:

- цифра, за ней любой из символов \s ( ) -, повторяющийся любое число раз

После чего возьми его в скобки и укажи, что оно повторяется ровно 10 раз.
#643 #1033102
>>1032705

> Имя кошки - http://ideone.com/9gYMJD


Верно

> Лев Толстой: http://ideone.com/c7jA9P


Верно, но слишком длинные конструкции вроде $word1[array_rand($word1)] лучше было бы не писать прямо в строке, а вынести в отдельную переменную.

> Палиндром: http://ideone.com/k76YfM


Ок, верно

>>1032449

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

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

>>1032333

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

>>1032306

После 700-900 постов
#644 #1033103
>>1032249

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

>>1032222

Заголовки отдавать - это дело контроллера в MVC.

>>1032041

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

Ну и вопрос еще, сколько ты процентов времени сэкономишь, перенеся класс Request в C++. Может быть, большая часть времени не в нем теряется.

>>1032002

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

https://developer.mozilla.org/ru/docs/Web/HTTP/Кэширование

Ну а также научиться чистить кеш в браузере.

>>1031692

- для хранения списка чего-либо, каких-то значений или сущностей
- для задания соответствия между одними значениями и другими (код ошибки -> текст ошибки, фамилия ученика -> оценка по математике)
#644 #1033103
>>1032249

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

>>1032222

Заголовки отдавать - это дело контроллера в MVC.

>>1032041

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

Ну и вопрос еще, сколько ты процентов времени сэкономишь, перенеся класс Request в C++. Может быть, большая часть времени не в нем теряется.

>>1032002

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

https://developer.mozilla.org/ru/docs/Web/HTTP/Кэширование

Ну а также научиться чистить кеш в браузере.

>>1031692

- для хранения списка чего-либо, каких-то значений или сущностей
- для задания соответствия между одними значениями и другими (код ошибки -> текст ошибки, фамилия ученика -> оценка по математике)
#645 #1033104
>>1031671

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

>>1031533

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

>>1031384

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

>>1031410

А эти строчки влияют на выбор БД Ларавелем? И не переопределяются ли параметры где-то в коде?

>>1031490

начинающим вместо сборок стоило бы сначала научиться использовать встроенный PHP-сервер, настраивать Апач или нгинкс. Которые и используются в сборках.

>>1031474

Что-то по набору программ это ZverCD напоминает, он случайно винду не заменяет при установке?

Я бы побоялся себе столько программ сразу ставить. Тем более что многие из них закрытые и неизвестно что делают.
#645 #1033104
>>1031671

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

>>1031533

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

>>1031384

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

>>1031410

А эти строчки влияют на выбор БД Ларавелем? И не переопределяются ли параметры где-то в коде?

>>1031490

начинающим вместо сборок стоило бы сначала научиться использовать встроенный PHP-сервер, настраивать Апач или нгинкс. Которые и используются в сборках.

>>1031474

Что-то по набору программ это ZverCD напоминает, он случайно винду не заменяет при установке?

Я бы побоялся себе столько программ сразу ставить. Тем более что многие из них закрытые и неизвестно что делают.
#646 #1033105
>>1031120

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

Если да, то правильно ли в настройках PHPStorm указан путь к интерпретатору PHP?

Какая версия PHP?

>>1031432

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

>>1031179

Просить советов, потом просить дополнительную усложненную задачу по той же теме.

>>1031122

Открыть отладчик (Ctrl + Shift + I), посмотреть свойства, примененные к диву, его размеры.

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

>>1030925

Знак = добавляет новый элемент массива, массив постоянно растет и цикл никогда не закончится. тут правильнее использовать == вместо = и foreach вместо for.

>>1030872

В PhpStorm нет встроенного сервера, он лишь умеет запускать встроенный в PHP сервер. Да, подойдет.
#646 #1033105
>>1031120

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

Если да, то правильно ли в настройках PHPStorm указан путь к интерпретатору PHP?

Какая версия PHP?

>>1031432

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

>>1031179

Просить советов, потом просить дополнительную усложненную задачу по той же теме.

>>1031122

Открыть отладчик (Ctrl + Shift + I), посмотреть свойства, примененные к диву, его размеры.

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

>>1030925

Знак = добавляет новый элемент массива, массив постоянно растет и цикл никогда не закончится. тут правильнее использовать == вместо = и foreach вместо for.

>>1030872

В PhpStorm нет встроенного сервера, он лишь умеет запускать встроенный в PHP сервер. Да, подойдет.
#647 #1033106
>>1030863

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

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

>>1030803

Если изучить сначала ООП, а потом почитать мое описание паттернов работы с БД, то, наверно, не убегут.

>>1030787

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

Чтобы пользоваться Homestead (образом для виртуальной машины) нужно разумеется знать основы командной строки, основные команды линукса, администрирование сервера на линуксе, наверно немного прочесть про сам Вагрант, а также изучить документацию по образу: https://laravel.com/docs/5.4/homestead#introduction

Прочел ли ты эту документацию?

Что касается файлов, там предлагается расшарить папку с хоста в виртуальную машину. Хотя, можно и копировать файлы в виртуальную машину через scp, sftp или другие протоколы. Опять же, из-за того что ты не изучал линукс и возможности расшаривания папок/копирования файлов, ты и путаешься.

Кроме виртуальной машины, в PHP можно использовать разные варианты серверов:

- встроенный в PHP веб-сервер
- Апач + mod_php
- Нгинкс + php-fpm

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

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

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

Не спеши, изучи сначала более базовые вещи, а потом берись за сложные.

Я всегда готов помочь, если после чтения документации что-то осталось непонятно.

> Как мне подключиться к БД?


Через какой клиент? Где у тебя установлена БД и какая?

> Как использовать phpMyAdmin?


А ты его установил? Куда и как он настроен?
#647 #1033106
>>1030863

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

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

>>1030803

Если изучить сначала ООП, а потом почитать мое описание паттернов работы с БД, то, наверно, не убегут.

>>1030787

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

Чтобы пользоваться Homestead (образом для виртуальной машины) нужно разумеется знать основы командной строки, основные команды линукса, администрирование сервера на линуксе, наверно немного прочесть про сам Вагрант, а также изучить документацию по образу: https://laravel.com/docs/5.4/homestead#introduction

Прочел ли ты эту документацию?

Что касается файлов, там предлагается расшарить папку с хоста в виртуальную машину. Хотя, можно и копировать файлы в виртуальную машину через scp, sftp или другие протоколы. Опять же, из-за того что ты не изучал линукс и возможности расшаривания папок/копирования файлов, ты и путаешься.

Кроме виртуальной машины, в PHP можно использовать разные варианты серверов:

- встроенный в PHP веб-сервер
- Апач + mod_php
- Нгинкс + php-fpm

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

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

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

Не спеши, изучи сначала более базовые вещи, а потом берись за сложные.

Я всегда готов помочь, если после чтения документации что-то осталось непонятно.

> Как мне подключиться к БД?


Через какой клиент? Где у тебя установлена БД и какая?

> Как использовать phpMyAdmin?


А ты его установил? Куда и как он настроен?
#648 #1033107
>>1030798

Я подозреваю, что просто apt-get install для phpmyadmin может быть недостаточно, там еще может понадобиться что-то настроить, например, включить демон веб-сервера.

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

>>1030806

> У меня есть проект, который я создал через composer. Но он никак не связан с тем, что в hosts


Я не очень понял, а что значит "не связан с тем, что в hosts"? hosts используется для добавления доменов без использования DNS-сервера. Там не пишутся названия проектов, а только доменные имена и соответсвующие им IP адреса.

Ты бы почитал хоть немного про то, что это за файл.

>>1030802

> Но я читал документацию с начала. Русскую. Там ребята начали с того, что хорошо было бы поставить homestead.


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

> У меня не работает http://homestead.app


> Точнее, он как бы работает и пишет No input file specified.


Нужно смотреть логи веб-сервера либо php-fpm, в зависимости от того, как там это настроено (внутри виртуальной машины).

> Я хочу использовать MySQL, а там привык юзать phpMyAdmin. Хотел бы знать, как это использовать в связке с Laravel. Как установить, как начать пользоваться.


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

> Но как мне войти в свой проект-то?


Не понял что значит "войти в проект". Подсоединиться по SSH к виртуальной машине с веб-сервером? Или что?
#648 #1033107
>>1030798

Я подозреваю, что просто apt-get install для phpmyadmin может быть недостаточно, там еще может понадобиться что-то настроить, например, включить демон веб-сервера.

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

>>1030806

> У меня есть проект, который я создал через composer. Но он никак не связан с тем, что в hosts


Я не очень понял, а что значит "не связан с тем, что в hosts"? hosts используется для добавления доменов без использования DNS-сервера. Там не пишутся названия проектов, а только доменные имена и соответсвующие им IP адреса.

Ты бы почитал хоть немного про то, что это за файл.

>>1030802

> Но я читал документацию с начала. Русскую. Там ребята начали с того, что хорошо было бы поставить homestead.


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

> У меня не работает http://homestead.app


> Точнее, он как бы работает и пишет No input file specified.


Нужно смотреть логи веб-сервера либо php-fpm, в зависимости от того, как там это настроено (внутри виртуальной машины).

> Я хочу использовать MySQL, а там привык юзать phpMyAdmin. Хотел бы знать, как это использовать в связке с Laravel. Как установить, как начать пользоваться.


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

> Но как мне войти в свой проект-то?


Не понял что значит "войти в проект". Подсоединиться по SSH к виртуальной машине с веб-сервером? Или что?
#649 #1033108
>>1030198

В такой ситуации проще всего с помощью strace (под линукс) или procmon (винда) посмотреть, к каким файлам идет обращение при вызове gettext().

На винде в PHP5.4 у меня твой скрипт выдает:

> setlocale failed: locale function is not available on this platform....



Это и понятно, так как локали это линуксовая вещь и, хотя в винде есть их аналог, и PHP пытается его использовать, но называются сами локали там по-другому.

Например, у меня в винде var_dump(setlocale(LC_ALL, null)); выдает:

> string(26) "English_United States.1252"



В MSDN наверно можно найти, какие конкретно локали есть в винде.

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

На линуксе выдается ошибка в setlocale, из-за того, что у меня нет русской локали. Исправил локаль на "C", и увидел через strace, что код пытается лезть в /locale за сообщениями.

Просмотреть список доступных локалей в линуксе можно через locale -a, а текущую - набрав просто команду locale. В винде - в MSDN наверно.

Я вижу такие ссылки на MSDN:

- https://msdn.microsoft.com/en-us/library/x99tb11d.aspx
- https://msdn.microsoft.com/en-us/library/hzz3tw78.aspx

И вот тут интересная инфорамция на русском: https://anton-pribora.ru/articles/php/locales/

Видно, что в любом случае имена локалей не совпадают с линуксовыми.

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

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

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

Переменные окружения хорошо подходят для задания локали по 2 причинам:

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

Увы, тут есть и недостаток: переменные окружения общие для всех тредов многотредового процесса, то есть в случае с многопотоным PHP (например в mod_php) нельзя ставить независимо разные локали для разных потоков.

Локали влияют и на работу PHP, так как он использует библиотеки, которые смотрят на переменные окружения LC_.... и используют функции, зависящие от текущей локали. Локаль можно задавать через переменную LANG (общая настройка), LC_ALL или отдельно для каждой категории вроде LC_TIME.

То есть в Линуксе эти локали хорошо интегрированы, и разработчики программ ими пользуются. Что касается винды, надо читать доки по setlocale в MSDN.

Вернемся к gettext.

Если что, документация по сишной библиотеке gettext (а в PHP функции расширения gettext по сути просто вызывают эту библиотеку) есть тут: https://www.gnu.org/software/gettext/manual/gettext.html#gettext

Конкретно, вот документация по пути к файлам gettext: https://www.gnu.org/software/gettext/manual/gettext.html#Locating-Catalogs

> Because many different languages for many different packages have to be stored we need some way to add these information to file message catalog files. The way usually used in Unix environments is have this encoding in the file name. This is also done here. The directory name given in bindtextdomains second argument (or the default directory), followed by the name of the locale, the locale category, and the domain name are concatenated:



> dir_name/locale/LC_category/domain_name.mo



> The default value for dir_name is system specific. For the GNU library, and for packages adhering to its conventions, it’s:



> /usr/local/share/locale



> locale is the name of the locale category which is designated by LC_category. For gettext and dgettext this LC_category is always LC_MESSAGES. The name of the locale category is determined through setlocale (LC_category, NULL). When using the function dcgettext, you can specify the locale category through the third argument.



То есть самый надежный способ, получается такой:

- ставить дефолтную локаль (чтобы все встроенные функции работали одинаково независимо от внешних настроек)
- задать язык с помощью выбора домена (например: myapp-ru)
- задать базовый путь для сообщений в bindtextdomain (например /x/y/z/messages/)

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

Я проверил, локаль "C" работает и в линуксах, и в винде. Однако, при ее использовании gettext даже не пытается искать файл с сообщениям.

При выборе локали en_US.utf8 (только линукс, в винде не поддерживается), домена mydomain, папки /tmp, strace показывает, что gettext ищет файл переводов по следующим путям:

- /tmp/en_US/LC_MESSAGES/mydomain.mo
- /tmp/en/LC_MESSAGES/mydomain.mo

(так как в линуксе есть еще синонимы (алиасы) локалей и он их тоже перебирает).

То, что gettext не выводит никаких ошибок, это конечно, неудачное решение.

Также можно попробовать не использовать gettext, а например, стороннюю библиотеку Symfony Translator: https://symfony.com/doc/current/components/translation.html

Это примерно то же, но написано на PHP. Надо понимать, что в отличие от сишного расширения, которое умеет загружать данные один раз в память процесса при первом запуске скрипта, тут загрузка сообщений может работать медленнее (например чтение данных из mo-файла сделано на PHP и будет работать небыстро) и будет происходить при каждом выполнении скрипта. Однако, если использовать загрузку из PHP файлов, и opcache, то может быть, эти данные закешируются в shared memory и не будут грузиться при каждом запуске скрипта.

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

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

Для форматирования строк (вставки чисел, подстрок, изменния формы слов в зависимости от числа или пола) стоит использовать возможности MessageFormatter в расширении Intl. То, что есть в gettext (ngettext) и в Symfony (transChoice) - это пародия на нормальный форматтер сообщений.

Я, признаюсь, сколько-то лет назад не знал про Intl и изобретал свои форматтеры со своим синтаксисом.

Также, я не уверен, что putenv на что-то влияет, так как она может быть только переопределяет переменные окружения внутри PHP для процессов-потомков и для getenv(), но не влияет на то, что прочитает библиотека gettext. Но я не уверен.
#649 #1033108
>>1030198

В такой ситуации проще всего с помощью strace (под линукс) или procmon (винда) посмотреть, к каким файлам идет обращение при вызове gettext().

На винде в PHP5.4 у меня твой скрипт выдает:

> setlocale failed: locale function is not available on this platform....



Это и понятно, так как локали это линуксовая вещь и, хотя в винде есть их аналог, и PHP пытается его использовать, но называются сами локали там по-другому.

Например, у меня в винде var_dump(setlocale(LC_ALL, null)); выдает:

> string(26) "English_United States.1252"



В MSDN наверно можно найти, какие конкретно локали есть в винде.

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

На линуксе выдается ошибка в setlocale, из-за того, что у меня нет русской локали. Исправил локаль на "C", и увидел через strace, что код пытается лезть в /locale за сообщениями.

Просмотреть список доступных локалей в линуксе можно через locale -a, а текущую - набрав просто команду locale. В винде - в MSDN наверно.

Я вижу такие ссылки на MSDN:

- https://msdn.microsoft.com/en-us/library/x99tb11d.aspx
- https://msdn.microsoft.com/en-us/library/hzz3tw78.aspx

И вот тут интересная инфорамция на русском: https://anton-pribora.ru/articles/php/locales/

Видно, что в любом случае имена локалей не совпадают с линуксовыми.

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

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

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

Переменные окружения хорошо подходят для задания локали по 2 причинам:

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

Увы, тут есть и недостаток: переменные окружения общие для всех тредов многотредового процесса, то есть в случае с многопотоным PHP (например в mod_php) нельзя ставить независимо разные локали для разных потоков.

Локали влияют и на работу PHP, так как он использует библиотеки, которые смотрят на переменные окружения LC_.... и используют функции, зависящие от текущей локали. Локаль можно задавать через переменную LANG (общая настройка), LC_ALL или отдельно для каждой категории вроде LC_TIME.

То есть в Линуксе эти локали хорошо интегрированы, и разработчики программ ими пользуются. Что касается винды, надо читать доки по setlocale в MSDN.

Вернемся к gettext.

Если что, документация по сишной библиотеке gettext (а в PHP функции расширения gettext по сути просто вызывают эту библиотеку) есть тут: https://www.gnu.org/software/gettext/manual/gettext.html#gettext

Конкретно, вот документация по пути к файлам gettext: https://www.gnu.org/software/gettext/manual/gettext.html#Locating-Catalogs

> Because many different languages for many different packages have to be stored we need some way to add these information to file message catalog files. The way usually used in Unix environments is have this encoding in the file name. This is also done here. The directory name given in bindtextdomains second argument (or the default directory), followed by the name of the locale, the locale category, and the domain name are concatenated:



> dir_name/locale/LC_category/domain_name.mo



> The default value for dir_name is system specific. For the GNU library, and for packages adhering to its conventions, it’s:



> /usr/local/share/locale



> locale is the name of the locale category which is designated by LC_category. For gettext and dgettext this LC_category is always LC_MESSAGES. The name of the locale category is determined through setlocale (LC_category, NULL). When using the function dcgettext, you can specify the locale category through the third argument.



То есть самый надежный способ, получается такой:

- ставить дефолтную локаль (чтобы все встроенные функции работали одинаково независимо от внешних настроек)
- задать язык с помощью выбора домена (например: myapp-ru)
- задать базовый путь для сообщений в bindtextdomain (например /x/y/z/messages/)

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

Я проверил, локаль "C" работает и в линуксах, и в винде. Однако, при ее использовании gettext даже не пытается искать файл с сообщениям.

При выборе локали en_US.utf8 (только линукс, в винде не поддерживается), домена mydomain, папки /tmp, strace показывает, что gettext ищет файл переводов по следующим путям:

- /tmp/en_US/LC_MESSAGES/mydomain.mo
- /tmp/en/LC_MESSAGES/mydomain.mo

(так как в линуксе есть еще синонимы (алиасы) локалей и он их тоже перебирает).

То, что gettext не выводит никаких ошибок, это конечно, неудачное решение.

Также можно попробовать не использовать gettext, а например, стороннюю библиотеку Symfony Translator: https://symfony.com/doc/current/components/translation.html

Это примерно то же, но написано на PHP. Надо понимать, что в отличие от сишного расширения, которое умеет загружать данные один раз в память процесса при первом запуске скрипта, тут загрузка сообщений может работать медленнее (например чтение данных из mo-файла сделано на PHP и будет работать небыстро) и будет происходить при каждом выполнении скрипта. Однако, если использовать загрузку из PHP файлов, и opcache, то может быть, эти данные закешируются в shared memory и не будут грузиться при каждом запуске скрипта.

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

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

Для форматирования строк (вставки чисел, подстрок, изменния формы слов в зависимости от числа или пола) стоит использовать возможности MessageFormatter в расширении Intl. То, что есть в gettext (ngettext) и в Symfony (transChoice) - это пародия на нормальный форматтер сообщений.

Я, признаюсь, сколько-то лет назад не знал про Intl и изобретал свои форматтеры со своим синтаксисом.

Также, я не уверен, что putenv на что-то влияет, так как она может быть только переопределяет переменные окружения внутри PHP для процессов-потомков и для getenv(), но не влияет на то, что прочитает библиотека gettext. Но я не уверен.
#650 #1033109
>>1030184

В документации xgettext нет параметра, описывающего метку, по которой надо искать строки?

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

>>1030104

Функция getEndStavka вызывается когда значение поля $this->rang еще не задано.

Потому надо сначала его задать (в конструкторе), а только потом вызывать. Ну и я выше писал, что поле endStavka делать вообще плохая идея.
#651 #1033111
>>1032995
по описанию какая-то шарашкина контора, в нормальных компаниях с заказчиком общаются менеджер+тимлид(коим я являюсь), никто в никого говном не кидается(такие заказчики были, но уже как пару лет шлём таких нахуй при первом признаке аутиста).
по процессу работы, ничего не отваливается само и просто так. юзать ебучие цмс без которые постоянно обновляются без обратной поддержки апи, чтобы ничего не отваливалось советую прочитать про continuous integration
#652 #1033187
>>1033064
с начало нужно погуглить , а потом уже говорить такие глупости
#654 #1033229
>>1033211

>Фишка в том, что наши программисты гуглеры, а не ученые. Это обычно молодые, только выпустившиеся пацаны, которые возможно выучили Java, возможно даже C/C++ и может быть Python. Они не в состоянии понимать пробздетый язык, но мы все равно хотим, чтобы они делали хороший софт. Таким образом, мы даем им легкопонимаемый язык, к которому они быстро привыкнут.



и чем это отменяет что он легче чем кресты но сохраняет их профит ?
#655 #1033237
>>1033211

Я сильно сомневаюсь в том, что там написано, про корпорации. По моим ощущениям, Го сделан на замену Си, а не Си++ (он отличается от Си в первую очередь добавлением ООП, классов, нейсмпейсов, исключений).

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

Насчет больших приложений (убийца Явы и PHP конечно) - тут я не уверен, там пока банально дженериков нет, то есть вы например не можете объявить тип "Коллекция объектов класса Пользователь". Исключений нет, ООП есть, но немного странный. Я писал небольшую утилиту на Го ( https://github.com/codedokode/guarddog ) но напрочь позабыл, что там неудобно.

А, вспомнил, одна из неудачных имхо фич - это разделение функций на public/private по регистру первой буквы метода. Сильно портит код, имхо.
#656 #1033241
>>1033211

> Посудите: можно нанять 100 посредственных программистов, дать им в руки Go и эта армия обезьян будет генерить вам много «неплохого» и очень даже поддерживаемого кода!



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

Там много низкоуровневых моментов, без знания Си будет тяжко.
#657 #1033263
>>1033237
Нет ничего лучше Си и С++ в совокупности. Двачую бро.
Можно нубский вопрос, елси С++ так шикарно работает, производительность - Великая и т.д Почему на нем пишут мало корпорации и игроделов? На нем же можно отлично оптимизироваться.
#658 #1033269
>>1033241
Если выучишь Си - С легкостью выучишь и С++, зачем тратить время на Го, когда ты уже считай профи?
#659 #1033272
>>1033269
Го можно выучить отвлеченно и зная задачи которые он выполняет, ну типа как если ты выучил пару языков и чтобы увеличить свои критерии выучиваешь остальные языки для гибкости. Страуструп рекомендует знать как минимум 5 языков фундаментально.

Нас потрут за оффтоп
#660 #1033275
>>1033272
>>1033269
>>1033263
Если что это все писал один анон.
#661 #1033280
>>1033263

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

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

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

Ну и много неудобных оставшихся по наследству вещей:

- нет модулей
- макросы
- нет проверки границ массивов
- заголовочные файлы

Потому когда хотят написать простой сайт, на PHP это будет сделать гораздо быстрее и потребует менее опытных разработчиков.
#662 #1033316
Нужна помощь.
Есть массив, внутри массива каждый ключ содержит значение в виде массива.
Требуется отсортировать массив так, что если больше n-значений в массиве, то добавляем в другой массив ключ-значение подходящего.
#663 #1033322
Есть 2 файла: 1.php 2.php. В первом я написал:

<a href="2.php?name=1">LINK</a>

Во втором написано:

$name;
echo $name;

Пишет: Undefined variable: name. Как я понял, он значение не передает. Вопрос: почему?
#664 #1033323
>>1033322
$name = $_GET['name'];
#665 #1033332
>>1033323
Благодарю.
#666 #1033375
>>1033316
уже не надо. сам додумался:

foreach ($foo as $key => $value) {
if (count($value) >= n ) {
$bar[$key] = $value;
}
}
#667 #1033386
если в пыхе таймер на выполнение скрипта в нужное время нужное количество раз?
#668 #1033387
Нашёл учебник, издание от 2008. Он актуален ещё?
#669 #1033411
>>1033187
Что гуглить, мань, если у меня документация по ларавелю по умолчанию открыта на элоквенте? Я умею в зависимости one2one, one2many и тд. Я задал вопрос по архитектуре, логике, а не синтаксису.
#670 #1033443
>>1033411
а что по логике ? на каждую таблицу делаешь по модели , конектишь их через отношения , там где нужно взять что то зависимое делаешь $model->find(10)->sense(); и получаешь тот же массив всех связанных ? Какая ещё тебе архитектура нужна поверх MVC ?
#671 #1033454
>>1033411
По тому как ты задал вопрос , твои классы = моделям , связать через отношения , и будешь получать свой обьект с значениями колонок
#672 #1033466
>>1033443
>>1033454
Может я и правда плохо сформулировал вопрос, прошу прощения, попробую переформулировать.

В самом конце я бы хотел иметь объект (или массив объектов), например user с полями id:int, firstName:string, secondName:string, rentedBooks:object[]. Здесь первые три поля из таблички юзеров, а арендованные книжки из таблички книжек. Хочу обращаться потом к объекту user->rentedBooks[7], например, ну вы поняли.

В обычном пхп я бы создал класс User и класс Book, а потом вытаскивал данные и создавал бы инстансы этих классов. Но как это сделать в ларавеле? Где прописывать запросы к БД и создавать инстансы?
#673 #1033513
Делаю запрос к Postgre:

$query = "SELECT data FROM searches WHERE id = $id";
$result = pg_query($query) or die('Query failed: ' . pg_last_error());

Если ID существует, то выводится JSON-массив, записанный мною ранее под этим ID. Если ID нет, то на фронте тригерится .fail().

Чо делать?
#674 #1033529
>>1033466
по классике MVC вся работа с бизнес логикой должна быть в моделе , выходи так ты делаешь модель User делаешь отношение что у 1 User может быть много книг (я думаю с этим ты разобрался) , так как книга арендованная (видно так) то в модели Book ты ставишь что у книги может быть 1 User , в контроллере ты создаёшь инстанс пользователя , находишь пользователя по id например и через эти отношения получаешь массив объектов Book вот пример кода
$user->book();
#676 #1033572
>>1033565
Нет
#677 #1033575
>>1033572
Тред давно ушел в бамплимит, его уже тяжело найти.
#678 #1033596
>>1033575
Ты тут новенький?
#679 #1033602
>>1033596
Нет, а что?
#680 #1033603
>>1033596
>>1033572
В предыдущем было 939 постов, мы будем ждать?
#681 #1033626
Стрим PHP с решением задачек ОПа.
#683 #1033693
>>1033565

Шапка плохая если честно. Никто в ваш пастебин не полезет читать неформатированный текст.
#684 #1033710
Помогите, пожалуйста.
Сказано, что если заключить регулярное выражение между % и $, то оно будет искать только фразу в регулярном выражении и не будет искать фразу, где есть лишние символы(ну например не найдет "кот" в слове "скотина", как написал ОП-доброкун, нувыпонели).
Если я пишу вот так:

$regexp = '/^[(+7)|8][0-9]{4}$/u';

то почему-то цифры, начинающиеся на +7, не соответствуют регулярному выражению.
Если пишу без шапочки и доллара, то все норм, цифры начинающиеся на +7 валидность проходят, и на 8 тоже.
#685 #1033712
>>1033628

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

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

Также, немного неудобно, что там у автора высокое разрешение и мелкие буквы и даже в 720p символы вроде "равно" плохо видны. Я бы советовал, если это нетрудно, увеличивать шрифт в редакторе, да и в браузере, раза в полтора-два.

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

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

---

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

---

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

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

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

Иначе перенос строки будет в исходном коде страницы (его можно увидеть нажав Ctrl + U), но на самой странице его не будет.

---

Также, оператора из 2 звездочек нет, для возведения в степень (в том числе дробную, возведение в 1/3 = корень третьей степени и отрицательную, x ^ -3 = 1 / (x ^ 3)) есть функция pow() , но по моему она не умеет возводить в степень отрицательные числа.
#685 #1033712
>>1033628

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

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

Также, немного неудобно, что там у автора высокое разрешение и мелкие буквы и даже в 720p символы вроде "равно" плохо видны. Я бы советовал, если это нетрудно, увеличивать шрифт в редакторе, да и в браузере, раза в полтора-два.

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

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

---

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

---

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

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

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

Иначе перенос строки будет в исходном коде страницы (его можно увидеть нажав Ctrl + U), но на самой странице его не будет.

---

Также, оператора из 2 звездочек нет, для возведения в степень (в том числе дробную, возведение в 1/3 = корень третьей степени и отрицательную, x ^ -3 = 1 / (x ^ 3)) есть функция pow() , но по моему она не умеет возводить в степень отрицательные числа.
#686 #1033715
>>1033710

Не так. Не %, а ^.

^ обозначает "в этом месте должно быть начало строки". То есть ^abc ищет abc только если эти буквы идут в самом начале строки.

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

Внутри квадратных скобок ^ имеет другой смысл и значит "любой символ, кроме указанных".

$ обозначает "здесь должен быть конец строки", и abc$ найдет abc только если они идут в самом конце строки.

По твоей регулярке, ты не понял, как работают квадратные скобки. Они значат "один любой из указанных символов". Соответственно [(+7)|8] значит "один любой символ из набора: круглые скобки, плюс, семерка, вертикальная черта. восьмерка". Внутри квадратных скобок почти все символы, кроме ^ - \ ] не имеют специального значения и обозначают сами себя.

Мануал http://php.net/manual/ru/regexp.reference.character-classes.php
#687 #1033717
>>1033710

>цифры начинающиеся на +7 валидность проходят, и на 8 тоже


забыл сказать: но валидность проходят и наборы символов, где в начале и в конце стоят другие символы.
#688 #1033722
>>1033715

>Соответственно [(+7)|8] значит "один любой символ из набора: круглые скобки, плюс, семерка, вертикальная черта. восьмерка"


А если экранировать круглые скобки, то будет искаться либо +7, либо 8?
#689 #1033725
>>1033722

Экранирование лишает символ специального смысла. Например, + значит повторение, а \+ просто символ "плюс".

Соответственно экранирование ничего не даст. Квадратные скобки обозначают "один из указанных символов" и внутри них строить какие-то конструкции нельзя.
#690 #1033726
>>1033725
Ну вроде понял, спасибо большое.
#691 #1033732
>>1033725
Все, я окончательно понял.
Спасибо большое, ты очень добр. ^____^
#692 #1033733
Реально ли устроиться джуном без образования в 27, при условии, что я шарю и предоставлю пруфы в виде готовых проектов и смогу пояснить каждую строчку кода?
#693 #1033742
>>1033712
Спасибо за замечание, в следующей трансляции постараюсь исправить.
#694 #1033749
>>1033733
Реально, на хекслете и за 40+ учатся мужики, а потом устраиваются джунами и устраивают карьеру погромиста.
#695 #1033757
>>1033280
Спасибо за инфу. Да Си тугой язык, я вечерами ломал голову чтобы обыкновенный цикл сделать. Даже не думал что это так глобально.
#696 #1033764
>>1033712

> Также, оператора из 2 звездочек нет, для возведения ...


https://3v4l.org/u4Gnp

>>1033733
Оно-то реально, но подумай как ты себя в коллективе чувствовать будешь, насколько комфортно будет другим учить великовозрастного дядю. У нас есть тимлиды в 25-27 лет с 7+ годами коммерческого опыта, джунов обычно набирают молодыми.

>>1033749

> 40+ мужики


> джунами


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

> при условии, что я шарю и предоставлю пруфы


"Болтовня ничего не стоит. Покажите мне код" как говорил Торвальдс.

>>1033565
Никогда больше не перекатывай треды, лентяй. Шапку на pastebin никто читать не будет + ты забыл про этот >>1019303 пост.
#697 #1033797
Что скажете про книгу
PHP 7. В подлиннике ?
#698 #1033799
Котаны, я взял основы HTML 5.1, CSS3. Преподаватель сказал изучать дальше ASP.NET чтобы понять как работают сервера.
Щас буду практиковать верстку. Когда можно будет начать ПХП?
#699 #1033800
>>1033799
Перед асп.нет
#700 #1033801
>>1033800
Спасибо, добра.
#701 #1033831
>>1033764

>как ты себя в коллективе чувствовать будешь


А хуле мне их дискомфорт? Пусть учат
#702 #1033854
>>1033797
Просмотрел.
1000+ страниц и ни одного приличного листинга с кодом. В основном это краткий пересказ мануала, который ничему не учит.
Можно купить на рутрекере и листать иногда на предмет незнакомых слов если гугль отключили, денег за такое платить конечно не нужно.
#703 #1033876
Задача про l33t speak в учебнике из шапки, что там надо исправить? На первый взгляд и так все работает, заданная фраза переводится в литспик. Добавить буквы недостающие в массив?
#704 #1033889
>>1033854
А какие есть годные книги по PHP, которые надо читать после уроков опа?
#705 #1033904
>>1033876
TaM 6ykBbI "JI", HaIIPuMeP, HeT.
Я просто дописал некоторые буквы, которые захотел, например.
Там, мне кажется, все равно ничего более сложного и не придумаешь. Иди лучше дальше.
#706 #1033908
А у меня вопрос назрел такой.
Скажем, есть чел, который не получил образования в сфере IT, учился там на какого-нибудь юриста, но знал php, вертску, js, mysql, вот это все, и фрилансом выполнил овер9000 заказов. Он будет считаться джуниором, если он пойдет на постоянную работу, где его деятельность не будет отличаться от той, когда он фрилансил? Почему?
#707 #1033911
>>1033889
Ты задачи Студенты и Файлообменник делал?
Если нет, то делай студентов, ОП написал к ней кучу статей.
По книгам: классика жанра Мэтт Зандстра "Объекты, Шаблоны и Методики Программирования". Потом думаю Фаулер.
#708 #1033923
>>1033908
У него нет опыта командной разработки.
Его код с большой долей вероятности, будет "попахивать", т.к. нет постоянного контроля качества.
Конечно зависит от конторы и реального уровня фрилансера. Понятно, что между 3 у.е час крудошлепом и 30 у.е. час лара/симфони ангуляр/реакт специалистом довольно чувствительная разница.
#709 #1033926
>>1033908

Может быть этот человек привык писать процедурную лапшу, а в компании используют ООП фреймворк вроде Симфони и его код не произведет впечатления. С другой стороны, может в компании тоже пишут процедурную лапшу, и тогда он хорошо впишется.
#710 #1033943
>>1033923
>>1033926
Ясно, понятно.
#711 #1034845
есть одна страница stranica.com
1. пишешь туда ссылку ssilka.com
2. генерирует рандом 4 символа и записывает в бд ссылку\символы asdf
3. апачь редиректет 404 запросы на страницу с пхп кодом stranica.com/asdf -> stranica.com/phpscript
4. смотрит _$SERVER[HTTP_REQUEST] = asdf и из бд вытаскивает ssilka.com
5. выводит на страницу жс скрипт с редиректом на ssilka.com

Как это сделать без редиректа на stranica.com/phpscript, через htaccess?
И что вообще еще можно поменять?
#712 #1034927
Сделал вам шапку на гитхабе:

https://github.com/phpguron/php_thead/wiki
#713 #1035222
>>1034927

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

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

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

Шапка на гитхабе не нужна. Это лишь поспособствует тому, что меньше людей ее прочтет.
#714 #1035234
>>1033103

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



Не понимаю до сих пор почему так.

Еси закоментить строчки:

namespace Core;
use Core\Router;

То всё начинает нормально работать как бы.
#715 #1035284
>>1035234

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

Также, в линуксе важен регистр букв в имени файлов и папок. Должно быть именно Core, с большой буквы.

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

Помни, что автозагрузчик получает полное имя класса на вход, со всеми неймспейсами.
#716 #1035285
>>1035234

Также, всегда используй <?php вместо <? так как короткие php-теги могут быть отключены в конфиге.
#717 #1035289
>>1035284
То есть проблема в моем автозагрузчике, который я просто спиздил с дефолтного примера из интернета?

Если я пишу в index.php use Core\Router;

То он ищет его вот так:
string(51) "C:\OpenServer\domains\link.loc\Core\Core\Router.php"

Что делать то в итоге с этим?
#718 #1035290
>>1035289

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

Тебе надо подумать, почитать в моем уроке про PSR-4 и написать поддерживающий этот стандарт автозагрузчик. Включая поддержку неймспейсов.

Также, в PHP уже есть реализация похожего на PSR-4 автозагрузчика: http://php.net/manual/ru/function.spl-autoload.php . По моему он не на 100% соответствует спецификации PSR-4. Было бы хорошо, если бы ты прочел документацию и проверил, соответствует он PSR-4 или нет, если нет, то в чем.

Можно использовать готовый автозагрузчик, но конечно написать сначала свой будет и интереснее и полезнее.
#719 #1035296
>>1035290
Спасибо, сейчас попытаюсь въехать. Алсо иметь в итоге в ооп-проекте старую добрую functions.php считается зашкваром или как? Или делают какой-то статический класс с глобальной видимостью что бы ему кормить когда нужно переменные?

И еще, пытаюсь тут понять про Dependency Injection, и у меня вопрос. А чем это по сути отличается от процедурной лапши?

Вместо обычной functionname() влюбом месте кода мы просто пишем в итоге
$this->someshit->functionname()

Как и всевозможные
$a = $this->config->get('varname);

по сути ни что иное как сделать:
global $config = array(...);
и писать в коде
$a = $config['varname'];
#720 #1035303
>>1033386
Нет, этим занимается планировщик ос

>>1033387
Азы -- да, в целом по-хорошему -- нет

>>1033513
А что надо делать?
Ррррряяяягулярки #721 #1035461
Котаны,объясните пжлст дебилу, что с моей регуляркой (задача про номера телефонов) не так?

(\+\-\ 7|8\-\ \()(\d?\-\ \(\)*){10}

Вот как это вижу я:
первая часть: символ +, возможные пробелы-тире, 7 ИЛИ 8, возможные пробелы-тире-скобки;
вторая часть: цифра 0-9, возможные пробелы-тире-скобки, всё это повторить 10 раз.

ЧЯДНТ?
#722 #1035463
Звёздочки съелись, лучше ссылкой https://regex101.com/r/t0lc8H/1
#723 #1035542
>>1035461
>>1035463
Уже сам неспортивно нагуглил,косяк в том,что надо писать все воможные символы одним куском в квадратных скобках,а уже к нему применять *
#724 #1035603
А в регулярках можно сделать так, чтобы из результатов исключались все символы с конца до пробела (от последнего пробела до конца)?
#725 #1035612
>>1035603
А, дошло:
(?!\w+$)
#726 #1035650
Пилю сайт, на котором много всякой статистики и цифр. Например: на главной странице отображается число зарегистрированных частников. Как правильно сделать? При загрузке страницы подсчитывать число участников из БД или завести отдельную таблицу со всей статистикой, куда при регистрации нового участника просто добавлять единицу и соответственно при загрузке страницы отображать эту цифру?

Статистических данных дохуя. Например есть таблица операций участников куда заносится тип операции в соответствии с которым у него отбавляются/прибавляются очки (изымаются/умножаются проценты в соответствии с кол-вом рефералов и прочими деталями). Лучше завести отдельную таблицу куда записывать эти цифры или подсчитывать их при загрузке станицы?
#727 #1035683
>>1035650

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



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

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

> Лучше завести отдельную таблицу куда записывать эти цифры или подсчитывать их при загрузке станицы?


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

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

>>1035603

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

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

По фрагменту регулярки (?!\w+$), трудно понять, праивльно ли она будет работать или нет.
#728 #1035687
>>1035461

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

\-*\ *\(*\)*

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

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

Также, минус вне квадратных скобок не требует экранирования бекслешем. Пробел не требует бекслеша.

Спецсимволы, которые надо экранировать, перечислены тут: http://php.net/manual/ru/regexp.reference.meta.php
#729 #1035695
>>1035650
Если у тебя каждый юзер постоянно влияет на других юзеров, и 1 его клик в системе вызывает цепную реакцию, то нагрузка на бд будет расти очень быстро. С поправкой конечно на то что число активных юзеров тоже постоянно растет. Если у тебя проект на 2000 тел то там не важно даже наверное как ты сделаешь. В статистике хостинга будешь видеть 1-5% нагрузку на бд в любом случае в пиковые моменты.

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

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

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

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

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

Всё зависит в итоге только какая нужна актуальность. Если у тебя подобие биржи какой-нибудь, и инфа должна всегда быть без задержки, то тогда и надо вокруг этого плясать - тут я хз.
#729 #1035695
>>1035650
Если у тебя каждый юзер постоянно влияет на других юзеров, и 1 его клик в системе вызывает цепную реакцию, то нагрузка на бд будет расти очень быстро. С поправкой конечно на то что число активных юзеров тоже постоянно растет. Если у тебя проект на 2000 тел то там не важно даже наверное как ты сделаешь. В статистике хостинга будешь видеть 1-5% нагрузку на бд в любом случае в пиковые моменты.

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

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

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

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

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

Всё зависит в итоге только какая нужна актуальность. Если у тебя подобие биржи какой-нибудь, и инфа должна всегда быть без задержки, то тогда и надо вокруг этого плясать - тут я хз.
#730 #1035714
>>1035296

Функции можно использовать, но стоит также рассмотреть возможность использовать utility-класс ( https://en.wikipedia.org/wiki/Helper_class ). Интересно, что при попытке погуглить "utility class" выпадает много результатов вроде "utility class pattern is evil", предлагаю читателю самостоятельно изучить указанные статьи и решить, веские ли аргументы там указаны.

Ну например, utility class дает возможность группировать функции по смыслу (впрочем, простые функции можно группировать по неймспейсам), автозагрузку.

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

ООП:

$form = new RegisterForm;
$form->parseData($request);
if ($form->isValid()) { ..

То же самое на функциях писать будет неудобно:

$form = createRegisterForm();
formParseData($form, $request);
if (formIsValid($form)) { ...

Получается какая-то неуклюжая имитация ООП, где информация о форме ($form) передается первым аргументом.

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


Это называется utility class

> И еще, пытаюсь тут понять про Dependency Injection, и у меня вопрос. А чем это по сути отличается от процедурной лапши?


> В чем разница между


> $a = $this->config->get('varname');


> $a = getConfig('varname');



В первом случае мы обращаемся к конфигу в поле $this->config, в программе может быть много разных конфигов. Конфиг доступен не везде, а только там, куда мы его явно передали. Видно по конструктору, что классу для работы нужен конфиг. В случае функции конфиг во всей программе может быть только один (нельзя создать объект с другими настройками, а это часто нужно при тестировании), доступен он везде, даже там, где не нужен, не видно, кому он нужен, а кому нет.

Советую прочесть мой урок по DI ( https://github.com/codedokode/pasta/blob/master/arch/di.md ), если не читал, там это разбирается, чем плохи глобальные переменные, почему плохо, когда класс сам получает нужные ему настройки (или у тебя вопросы после прочтения появились?).

> global $config = array(...);


> $a = $config['varname'];


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

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

Ну и я могу привести другие примеры, когда DI полезна. Ну например, возьмем объект соединения с БД. Допустим, у нас он самостоятельно берет параметры подключения из функции:

$dbal = new Dbal();
$dbal->makeQuery('SELECT .. FROM ...');

Вопрос: как с таким объектом сделать подключение к 2 разным БД? Тут как раз и поможет DI:

$dbal1 = new Dbal('db1', 'password1');
$dbal2 = new Dbal('db2', 'password2');

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

Вот тебе задачка для размышлений. Допустим, нам в приложении нужна функция конвертации валют: на вход даем сумму в одной валюте (например, рубль), на выходе получаем сумму в долларах. Курс перевода необходимо брать с удаленного сервера (например, ЦБ РФ предоставляет API для получения курса). Однако, мы не хотим при каждой конвертации делать запрос в сеть, так как курс меняется раз в сутки, мы хотим сохранять этот курс локально (например, в файл или кеш вроде redis) и использовать его в течение суток.

Также, мы хотим протестировать эти функции по отдельности, а именно:

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

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

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

Также, в моем уроке есть пункт "Пример использования преимуществ DI". Посмотри на написанный там код и предложит альтернативные варианты, как можно сделать такое же без DI или без ООП.

Если тебе что-то непонятно, спрашивай. Вопросы после прочтения урока помогают мне понять, что можно в нем улучшить.
#730 #1035714
>>1035296

Функции можно использовать, но стоит также рассмотреть возможность использовать utility-класс ( https://en.wikipedia.org/wiki/Helper_class ). Интересно, что при попытке погуглить "utility class" выпадает много результатов вроде "utility class pattern is evil", предлагаю читателю самостоятельно изучить указанные статьи и решить, веские ли аргументы там указаны.

Ну например, utility class дает возможность группировать функции по смыслу (впрочем, простые функции можно группировать по неймспейсам), автозагрузку.

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

ООП:

$form = new RegisterForm;
$form->parseData($request);
if ($form->isValid()) { ..

То же самое на функциях писать будет неудобно:

$form = createRegisterForm();
formParseData($form, $request);
if (formIsValid($form)) { ...

Получается какая-то неуклюжая имитация ООП, где информация о форме ($form) передается первым аргументом.

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


Это называется utility class

> И еще, пытаюсь тут понять про Dependency Injection, и у меня вопрос. А чем это по сути отличается от процедурной лапши?


> В чем разница между


> $a = $this->config->get('varname');


> $a = getConfig('varname');



В первом случае мы обращаемся к конфигу в поле $this->config, в программе может быть много разных конфигов. Конфиг доступен не везде, а только там, куда мы его явно передали. Видно по конструктору, что классу для работы нужен конфиг. В случае функции конфиг во всей программе может быть только один (нельзя создать объект с другими настройками, а это часто нужно при тестировании), доступен он везде, даже там, где не нужен, не видно, кому он нужен, а кому нет.

Советую прочесть мой урок по DI ( https://github.com/codedokode/pasta/blob/master/arch/di.md ), если не читал, там это разбирается, чем плохи глобальные переменные, почему плохо, когда класс сам получает нужные ему настройки (или у тебя вопросы после прочтения появились?).

> global $config = array(...);


> $a = $config['varname'];


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

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

Ну и я могу привести другие примеры, когда DI полезна. Ну например, возьмем объект соединения с БД. Допустим, у нас он самостоятельно берет параметры подключения из функции:

$dbal = new Dbal();
$dbal->makeQuery('SELECT .. FROM ...');

Вопрос: как с таким объектом сделать подключение к 2 разным БД? Тут как раз и поможет DI:

$dbal1 = new Dbal('db1', 'password1');
$dbal2 = new Dbal('db2', 'password2');

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

Вот тебе задачка для размышлений. Допустим, нам в приложении нужна функция конвертации валют: на вход даем сумму в одной валюте (например, рубль), на выходе получаем сумму в долларах. Курс перевода необходимо брать с удаленного сервера (например, ЦБ РФ предоставляет API для получения курса). Однако, мы не хотим при каждой конвертации делать запрос в сеть, так как курс меняется раз в сутки, мы хотим сохранять этот курс локально (например, в файл или кеш вроде redis) и использовать его в течение суток.

Также, мы хотим протестировать эти функции по отдельности, а именно:

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

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

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

Также, в моем уроке есть пункт "Пример использования преимуществ DI". Посмотри на написанный там код и предложит альтернативные варианты, как можно сделать такое же без DI или без ООП.

Если тебе что-то непонятно, спрашивай. Вопросы после прочтения урока помогают мне понять, что можно в нем улучшить.
#731 #1035881
>>1035714
Я может что-то не понимаю, но мне казалось, что депенденси инджекшн - это когда допустим работаешь с фреймворком, и прямо внутри контроллера можешь обратиться к модели через:
$this->modelName->methodName();
Ну и прочие встроенные во фреймворк штуки обычно точно так же уже доступны как я выше писал:

> $a = $this->config->get('varname');



Так вот для меня это как раз всё выглядит как тупо функциональный код.
Когда вместо
saveUserToDb($user);

тупо пишется:
$this->userModel->saveUser($user);

Теперь я вообще запутался
#732 #1035894
>>1035881

А прочел ли ты урок, ссылку на который я дал? Там многое объясняется.

Во-вторых, а прочел ли ты внимательно мой пост? Я же тебе написал, в чем разница.

В-третьих, это назывеатся, не функциональный, а процедурный код ( https://ru.wikipedia.org/wiki/Парадигма_программирования )

То, что ты упоминаешь, к DI отношения не имеет.
#733 #1035896
>>1035881

И я тебе там предложил задачку, попробуй ее решить в процедурном стиле.
#734 #1035901
>>1035894
>>1035896
Спасибо за ответы, попробую вдумчиво сейчас разобрать всё снова и задачу обдумать.
33 Кб, 720x304
#735 #1035915
После студентов таки взялся за Файлообменик. Буду писать на Слиме, с twig, monolog, может Medoo(хотя надо бы наконец выучить PDO). Так вот, сижу блядь и не знаю с чего начать. Почитал документацию по слиму, вроде можно разобраться.
Так вот, собираюсь уже написать стартовую страницу но возникла проблема со структурой проекта.
Пожалуйста напишите ТОЧНУЮ файловую-структуру. Где какие папки и где что должно лежать, используя MVC.

Например:
Slim.loc (название проекта)
/scr/public
/scr/public/css
/scr/public/fonts
/scr/public/js
/scr/templates(он же views?)
/scr/models
/vendor

Пожалуйста.
#736 #1035916
>>1035915
А так же index.php(точка входа) и .htaccess должны лежать я так понимаю в /scr/public
Туда же скинуть и composer.json and composer .lock and .ignore?
5 Кб, 275x183
#737 #1035955

>Самоучитель HTML4

#738 #1035979
>>1034845

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

Ну и непонятно, зачем там нужен яваскрипт, редирект делается через HTTP заголовки ответа.

>>1033764

Действительно, добавили такой оператор, я ошибся.

>>1033466

А ты читал вообще мануал по Eloquent?

Задаешь отношения между моделями как, например, описано тут: https://laravel.ru/docs/v5/eloquent-relationships

После чего легко можно получить связанные сущности, как описано в мануале. Затем делаешь метод $user->getRentedBooks() который получает, что тебе нужно. Это в любом случае лучше, чем публично доступное поле. Писать запросы и создавать объекты вручную скорее всего не надо, ORM сделает это за тебя.

>>1033386

Используй крон

>>1033269

В Го есть сборщик мусора например и синтаксис в некоторых местах более удобный, чем в Си++. И не надо писать деструкторы например.

>>1033263

Что значит "на Си++ мало пишут"? Откуда такая информация? Многие (топовые, а не от мамкиных самодельщиков) игры на Си++, офисные программы вроде Openoffice на Си++, браузер Хром на Си++, и еще куча софта.

Как я уже писал выше, производительность у него хорошая, но код на нем писать и отлаживать долго. Код быстро писать на HTML/JS, но производительность получается минимальная.
#738 #1035979
>>1034845

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

Ну и непонятно, зачем там нужен яваскрипт, редирект делается через HTTP заголовки ответа.

>>1033764

Действительно, добавили такой оператор, я ошибся.

>>1033466

А ты читал вообще мануал по Eloquent?

Задаешь отношения между моделями как, например, описано тут: https://laravel.ru/docs/v5/eloquent-relationships

После чего легко можно получить связанные сущности, как описано в мануале. Затем делаешь метод $user->getRentedBooks() который получает, что тебе нужно. Это в любом случае лучше, чем публично доступное поле. Писать запросы и создавать объекты вручную скорее всего не надо, ORM сделает это за тебя.

>>1033386

Используй крон

>>1033269

В Го есть сборщик мусора например и синтаксис в некоторых местах более удобный, чем в Си++. И не надо писать деструкторы например.

>>1033263

Что значит "на Си++ мало пишут"? Откуда такая информация? Многие (топовые, а не от мамкиных самодельщиков) игры на Си++, офисные программы вроде Openoffice на Си++, браузер Хром на Си++, и еще куча софта.

Как я уже писал выше, производительность у него хорошая, но код на нем писать и отлаживать долго. Код быстро писать на HTML/JS, но производительность получается минимальная.
#739 #1035981
>>1035915

Ошибки в твоем варианте:

- public должен быть отдельно от src, в src мы держим код, который не отдаем наружу
- папку models лучше не делать. В MVC почти все, кроме контроллеров и вида относится к модели, соответственно не имеет смысла условно говоря делать папку для 75% кода. Лучше сделать отдельно папку для валидаторов, отдельно для классов работы с БД и тд.

Если классов мало, можно вообще свалить их в src без подпапок.

Также, прочти про PSR-4. У меня есть урок на гитхабе.

> А так же index.php(точка входа) и .htaccess должны лежать я так понимаю в /scr/public


Да, в public

> Туда же скинуть и composer.json and composer .lock and .ignore?


Ты хочешь всем пользователя сайта раздавать эти файлы? Зачем?

Эти файлы обычно кладут в корень.

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

> и не знаю с чего начать.


Начни с вывода страницы с текстом Hello World используя Слим.
#740 #1035983
>>1035915

Еще часто templates делают отдельной папкой, чтобы в src был php-код, а в tenplates - шаблона на твиге.
#741 #1035984
>>1033000

Справедливости ради, проблема ведь не в том, что Го или Монго "плохие". Проблема в том, что это инструменты со своими особенностями, которые хорошо работают в одной ситуации и не очень хорошо - в другой. Но блогеры-идиоты вместо объективного сравнения засоряют интернет высказываниями вроде "в 2017 году вместо A все используют B", а пользователи-идиоты бездумно следуют этим советам.

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

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

>>1032941

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

Также, на тот же андроид реально установить PHP/MySQL/Апач (но надо помучаться), редактор кода и что-то пытаться кодить, хотя конечно на маленькой клавиатуре будет печатать неудобно.
#742 #1035985
>>1032659

Для начала, стоит почитать ответы на эти вопросы:

- https://unix.stackexchange.com/questions/12260/how-to-encrypt-messages-text-with-rsa-openssl
- https://stackoverflow.com/questions/7143514/how-to-encrypt-a-large-file-in-openssl-using-public-key

(нашел гуглением по openssl rsa).

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

И вот это: https://www.sitepoint.com/encrypt-large-messages-asymmetric-keys-phpseclib/

> The nature of the RSA algorithm is such that it is only able to encrypt a limited amount of plaintext. For example, if your key size is 2048 bits, then you are limited to 256 bytes (at most) of plaintext data that can be encrypted


> The solution to the problem is to encrypt the message with a symmetric key, then asymmetrically encrypt the key and attach it to the message.



Также, гуглением я нашел такие функции:

- http://php.net/manual/ru/function.openssl-public-encrypt.php
- http://php.net/manual/ru/function.openssl-private-encrypt.php

Обрати внимание на комментарии под ними. Расширение openssl является лишь интерфейсом к библиотеке openssl, потому подробности стоит смотреть еще и в описании этой библиотеки, например https://wiki.openssl.org/index.php/Main_Page

Также, я еще нашел вот это: https://en.wikipedia.org/wiki/Public-key_cryptography#Examples

Тут есть примеры конкретных методов ( Examples of protocols using asymmetric key algorithms include ): S/MIME, GPG, Off-the-record-messaging. Посмотри их - так как всегда лучше брать проверенную схему шифрования, чем с нуля изобретать свою. GPG - известная программа для шифрования почты, OTR используется в джаббере.

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

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

> При регистрации пользователя мы генерируем закртый\открытый ключ


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

> Почему нету метода RSA? Однако, в опциях создания ключа можно указать этот тип


Думаю, потому, что RSA это не поточный шифр (не шифр, которым можно зашифровать произвольно большое сообщение).

Если у тебя установлена библиотека (не расширение PHP) openssl, то там есть команды:

openssl list-cipher-algorithms - дает тот же список что функция в PHP, без RSA
openssl list-public-key-algorithms - дает список с RSA, DH, DSA, EC, HMAC, CMAC

То есть это алгоритм не поточного шифрования, а чего-то другого.

> Эти все методы сделаны на его основе?


Стоит погуглить названия методов и посмотреть в общих чертах, как они работают. Ну например, AES-128-CBC, гуглим:

- AES: симметричный алгоритм блочного шифрования (размер блока 128 бит, ключ 128/192/256 бит), принятый в качестве стандарта шифрования правительством США по результатам конкурса AES
- 128: очевидно, размер ключа
- CBC: Cipher block chaining - режим шифрования, определяющий правила шифрования большого сообщения из нескольких блоков ( https://ru.wikipedia.org/wiki/Режим_шифрования )

Или SEED-CBC - SEED is a block cipher developed by the Korea Information Security Agency (KISA)...SEED is a 16-round Feistel network with 128-bit blocks and a 128-bit key

> В комментариях сказано, что RSA начинает устаревать и пора переходить на ECDH вместе с EdDSA. Что вы думаете по этому поводу?



Это по моему немного разные вещи, RSA это протокол асимметричного шифрования, DH - обмен ключами. Увы, не знаю, что лучше. Может быть стоит погуглить и посмотреть.

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


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

> Эллиптические кривые только добавляют надёжности, я правильно понимаю?


Не знаю.

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


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

> каким образом функция openssl_encrypt() шифрует данные из этой строки.


Судя по коду расширения https://github.com/php/php-src/blob/master/ext/openssl/openssl.c , строка 6523, там идет примерно такой алгоритм:

> cipher_type = EVP_get_cipherbyname(method);


> cipher_ctx = EVP_CIPHER_CTX_new();


> php_openssl_load_cipher_mode(&mode, cipher_type);


> php_openssl_cipher_init(...)


> EVP_EncryptFinal(cipher_ctx, (unsigned char )ZSTR_VAL(outbuf) + outlen, &i)


> base64_str = php_base64_encode((unsigned char)ZSTR_VAL(outbuf), outlen);


> RETVAL_STR(base64_str);



Функции, начинающиеся с EVP - это сишные функции библиотеки OpenSSL, документация по которым есть например тут: https://www.openssl.org/docs/man1.1.0/crypto/EVP_EncryptFinal.html

php_openssl_load_cipher_mode() и php_openssl_cipher_init() описаны в том же файле расширения (openssl.c) и являются обертками над функциями OpenSSL.

Тут конечно лучше попробовать найти статью "как зашифровать что-нибудь библиотекой OpenSSL".

> Зачем разделять код на две части? Это не более чем прихоть автора?


Чтобы те, кому не нужна вторая часть, не грузили ее.
#742 #1035985
>>1032659

Для начала, стоит почитать ответы на эти вопросы:

- https://unix.stackexchange.com/questions/12260/how-to-encrypt-messages-text-with-rsa-openssl
- https://stackoverflow.com/questions/7143514/how-to-encrypt-a-large-file-in-openssl-using-public-key

(нашел гуглением по openssl rsa).

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

И вот это: https://www.sitepoint.com/encrypt-large-messages-asymmetric-keys-phpseclib/

> The nature of the RSA algorithm is such that it is only able to encrypt a limited amount of plaintext. For example, if your key size is 2048 bits, then you are limited to 256 bytes (at most) of plaintext data that can be encrypted


> The solution to the problem is to encrypt the message with a symmetric key, then asymmetrically encrypt the key and attach it to the message.



Также, гуглением я нашел такие функции:

- http://php.net/manual/ru/function.openssl-public-encrypt.php
- http://php.net/manual/ru/function.openssl-private-encrypt.php

Обрати внимание на комментарии под ними. Расширение openssl является лишь интерфейсом к библиотеке openssl, потому подробности стоит смотреть еще и в описании этой библиотеки, например https://wiki.openssl.org/index.php/Main_Page

Также, я еще нашел вот это: https://en.wikipedia.org/wiki/Public-key_cryptography#Examples

Тут есть примеры конкретных методов ( Examples of protocols using asymmetric key algorithms include ): S/MIME, GPG, Off-the-record-messaging. Посмотри их - так как всегда лучше брать проверенную схему шифрования, чем с нуля изобретать свою. GPG - известная программа для шифрования почты, OTR используется в джаббере.

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

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

> При регистрации пользователя мы генерируем закртый\открытый ключ


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

> Почему нету метода RSA? Однако, в опциях создания ключа можно указать этот тип


Думаю, потому, что RSA это не поточный шифр (не шифр, которым можно зашифровать произвольно большое сообщение).

Если у тебя установлена библиотека (не расширение PHP) openssl, то там есть команды:

openssl list-cipher-algorithms - дает тот же список что функция в PHP, без RSA
openssl list-public-key-algorithms - дает список с RSA, DH, DSA, EC, HMAC, CMAC

То есть это алгоритм не поточного шифрования, а чего-то другого.

> Эти все методы сделаны на его основе?


Стоит погуглить названия методов и посмотреть в общих чертах, как они работают. Ну например, AES-128-CBC, гуглим:

- AES: симметричный алгоритм блочного шифрования (размер блока 128 бит, ключ 128/192/256 бит), принятый в качестве стандарта шифрования правительством США по результатам конкурса AES
- 128: очевидно, размер ключа
- CBC: Cipher block chaining - режим шифрования, определяющий правила шифрования большого сообщения из нескольких блоков ( https://ru.wikipedia.org/wiki/Режим_шифрования )

Или SEED-CBC - SEED is a block cipher developed by the Korea Information Security Agency (KISA)...SEED is a 16-round Feistel network with 128-bit blocks and a 128-bit key

> В комментариях сказано, что RSA начинает устаревать и пора переходить на ECDH вместе с EdDSA. Что вы думаете по этому поводу?



Это по моему немного разные вещи, RSA это протокол асимметричного шифрования, DH - обмен ключами. Увы, не знаю, что лучше. Может быть стоит погуглить и посмотреть.

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


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

> Эллиптические кривые только добавляют надёжности, я правильно понимаю?


Не знаю.

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


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

> каким образом функция openssl_encrypt() шифрует данные из этой строки.


Судя по коду расширения https://github.com/php/php-src/blob/master/ext/openssl/openssl.c , строка 6523, там идет примерно такой алгоритм:

> cipher_type = EVP_get_cipherbyname(method);


> cipher_ctx = EVP_CIPHER_CTX_new();


> php_openssl_load_cipher_mode(&mode, cipher_type);


> php_openssl_cipher_init(...)


> EVP_EncryptFinal(cipher_ctx, (unsigned char )ZSTR_VAL(outbuf) + outlen, &i)


> base64_str = php_base64_encode((unsigned char)ZSTR_VAL(outbuf), outlen);


> RETVAL_STR(base64_str);



Функции, начинающиеся с EVP - это сишные функции библиотеки OpenSSL, документация по которым есть например тут: https://www.openssl.org/docs/man1.1.0/crypto/EVP_EncryptFinal.html

php_openssl_load_cipher_mode() и php_openssl_cipher_init() описаны в том же файле расширения (openssl.c) и являются обертками над функциями OpenSSL.

Тут конечно лучше попробовать найти статью "как зашифровать что-нибудь библиотекой OpenSSL".

> Зачем разделять код на две части? Это не более чем прихоть автора?


Чтобы те, кому не нужна вторая часть, не грузили ее.
#743 #1036016
>>1035687
Я вчера сам уже понял, но все равно спасибо,добра тебе ^_^
#744 #1036018
>>1035983
Твиг вообще актуален?
В чём реальное, а не рекламное преимущество перед шаблонами на обычном рнр?
#745 #1036038
>>1036018
Преимущество в удобстве. И какая реклама, он разве платный?

1. Наследование.
Допустим, есть две страницы, на одной выводятся 5 самых популярных записей, сайдбар, на второй странице эти же записи с пагинацией и сайдбар с другим контентом/стилями.
С твигом создаешь один общий шаблон и обозначаешь в нем блоками места, которые можно переопределить в дочернем шаблоне.
Без твига будет либо копипаст, либо дикие джунгли с условными операторами.
2. Множество функций и фильтров, например вместо
<?php echo htmlspecialchars($var, ENT_QUOTES, 'UTF-8') ?>
{{ var|e }}
Или вообще включить экранирование по умолчанию (в последних версиях оно и так включено).
Еще вспомнил фичу, обращение через точку {{ variable.property }} работает как с массивами, так и с объектами, так что если понадобится извлекать из бд массивы, а не объекты, не придется переписывать представление (скобки и кавычки вместо стрелочек).

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

Но по сути да, это синтаксический сахар.
#746 #1036070
>>1035981
Спасибо. Начал.
someApprentice #747 #1036395
>>1035985

>Тут есть примеры конкретных методов ( Examples of protocols using asymmetric key algorithms include ): S/MIME, GPG, Off-the-record-messaging. Посмотри их - так как всегда лучше брать проверенную схему шифрования, чем с нуля изобретать свою. GPG - известная программа для шифрования почты, OTR используется в джаббере.


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


Ок.

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

Я нашёл вот эти вот:

http://php.net/manual/ru/ref.gnupg.php

Только почему-то я не вижу методов генерации ключей. Нужно найти другую в таком случае?

http://php.net/manual/ru/function.gnupg-import.php
http://php.net/manual/ru/function.gnupg-addencryptkey.php
http://php.net/manual/ru/function.gnupg-adddecryptkey.php
Почему несколько методов для добавления ключей?

Вообще, функции add..cryptkey выглядят довольно странно, в аргументы принимают отпечаток, а не сам ключи. Это и есть функции генерации ключей?

Отпечаток и подпись служат для одной цели - идентификации владельца ключа. Вы ранее советовали предусмотреть подпись, поэтому, имея возможность легко получить отпечаток, следует ли предусматривать ещё и подпись?

http://php.net/manual/ru/function.gnupg-addencryptkey.php#112979

>When you've successfully installed gnupg, you should define the GNUPGHOME environment variable and make sure the directory is writeable by the Apache user.


>putenv("GNUPGHOME=/var/www/example.com/.gnupg");


Почему ключи должны храниться где-то на диске?

https://openpgpjs.org/
https://github.com/openpgpjs/openpgpjs

https://github.com/openpgpjs/openpgpjs#getting-started

>Or just fetch a minified build under dist.


Они же предлагают это сделать в случае браузерной версии?
Я пробежался по этому коду (https://github.com/openpgpjs/openpgpjs/blob/master/dist/openpgp.js) и вроде там есть нужные функции. Сложно разобраться в их коде, очень всё запутанно, а в документации вообще некоторые страницы выдают 404.

https://openpgpjs.org/openpgpjs/doc/module-openpgp.html
https://openpgpjs.org/openpgpjs/doc/module-key.html

>encrypt(..., signature)


В отличии от php-библиотеки, js-библиотека использует подпись. Это одно и тоже, в этом случае?

https://openpgpjs.org/openpgpjs/doc/module-signature.html

>armoredText


Что такое armoredText?

http://php.net/manual/ru/function.gnupg-adddecryptkey.php
https://openpgpjs.org/openpgpjs/doc/module-openpgp.html (generateKey)
Обе эти функции используют passphrase, этой фразой шифруется приватный ключ и можно использовать эту опции в нашем случае?

https://openpgpjs.org/openpgpjs/doc/

>openpgp.encrypt(options).then


Зачем здесь может быть нужен Promise?

>> При регистрации пользователя мы генерируем закртый\открытый ключ


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


Для этого придётся усложнить код. Я оставлю это на дальнейшую реализацию (обмен ключами и др. данными через p2p), а пока пусть будет так.
someApprentice #747 #1036395
>>1035985

>Тут есть примеры конкретных методов ( Examples of protocols using asymmetric key algorithms include ): S/MIME, GPG, Off-the-record-messaging. Посмотри их - так как всегда лучше брать проверенную схему шифрования, чем с нуля изобретать свою. GPG - известная программа для шифрования почты, OTR используется в джаббере.


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


Ок.

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

Я нашёл вот эти вот:

http://php.net/manual/ru/ref.gnupg.php

Только почему-то я не вижу методов генерации ключей. Нужно найти другую в таком случае?

http://php.net/manual/ru/function.gnupg-import.php
http://php.net/manual/ru/function.gnupg-addencryptkey.php
http://php.net/manual/ru/function.gnupg-adddecryptkey.php
Почему несколько методов для добавления ключей?

Вообще, функции add..cryptkey выглядят довольно странно, в аргументы принимают отпечаток, а не сам ключи. Это и есть функции генерации ключей?

Отпечаток и подпись служат для одной цели - идентификации владельца ключа. Вы ранее советовали предусмотреть подпись, поэтому, имея возможность легко получить отпечаток, следует ли предусматривать ещё и подпись?

http://php.net/manual/ru/function.gnupg-addencryptkey.php#112979

>When you've successfully installed gnupg, you should define the GNUPGHOME environment variable and make sure the directory is writeable by the Apache user.


>putenv("GNUPGHOME=/var/www/example.com/.gnupg");


Почему ключи должны храниться где-то на диске?

https://openpgpjs.org/
https://github.com/openpgpjs/openpgpjs

https://github.com/openpgpjs/openpgpjs#getting-started

>Or just fetch a minified build under dist.


Они же предлагают это сделать в случае браузерной версии?
Я пробежался по этому коду (https://github.com/openpgpjs/openpgpjs/blob/master/dist/openpgp.js) и вроде там есть нужные функции. Сложно разобраться в их коде, очень всё запутанно, а в документации вообще некоторые страницы выдают 404.

https://openpgpjs.org/openpgpjs/doc/module-openpgp.html
https://openpgpjs.org/openpgpjs/doc/module-key.html

>encrypt(..., signature)


В отличии от php-библиотеки, js-библиотека использует подпись. Это одно и тоже, в этом случае?

https://openpgpjs.org/openpgpjs/doc/module-signature.html

>armoredText


Что такое armoredText?

http://php.net/manual/ru/function.gnupg-adddecryptkey.php
https://openpgpjs.org/openpgpjs/doc/module-openpgp.html (generateKey)
Обе эти функции используют passphrase, этой фразой шифруется приватный ключ и можно использовать эту опции в нашем случае?

https://openpgpjs.org/openpgpjs/doc/

>openpgp.encrypt(options).then


Зачем здесь может быть нужен Promise?

>> При регистрации пользователя мы генерируем закртый\открытый ключ


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


Для этого придётся усложнить код. Я оставлю это на дальнейшую реализацию (обмен ключами и др. данными через p2p), а пока пусть будет так.
#748 #1036511
>>1036070

Не scr, а src (от source, сокращенное до 3 букв на манер линуксовых директорий).

Кстати, я думаю, можно писать и source, сейчас ведь нет таких ограничений на длину имени файлов.
#749 #1039102
В задаче на регулярки, где надо телефоны заменить на единый формат(заменить +7 на 8, убрать все скобки, пробелы и т.д.) я нашел решение только с помощью двух разных регулярок: одна заменяет +7 на 8, вторая ищет пробелы, скобки etc между цифрами и заменяет их на пустые строки. У меня вопрос: а можно ли это сделать с помощью одной регулярки?
someApprentice #750 #1039350
>>1030006

>> К сожалению, у меня не получилось найти в ejs аналог функции nl2br и при этом чтобы экранировались тэги. В таком случае, будет приемлемым оставить этот костыль?


>nl2br не экранирует теги, она только заменяет \n на <br>, если я не путаю.


>


>Насколько я понял, у тебя проблема в том, что ejs экранирует данные и твой <br> выводится как текст? В документации ( https://github.com/mde/ejs/blob/master/docs/syntax.md ) написано что есть 2 вида тегов, один принимают текст, экранируют его и выводят, другой тег принимает HTML код и вставляет его как есть.


>


>В чем именно сложность-то? Можно сделать так <%- convertMessageToHtml(message) %>


Проблема в том что ejs вообще не переводит с помощью \n на новую строку. Нужно заменять его на <br>, но ejs экранирует его тоже.
Можно не экранировать, а фильтровать с помощью какого-нибудь стороннего html-фильтра, но всё равно нужно как-то заменить \n на <br>.

>> Я никак не могу придумать как выводить только новые сообщения. Определенно, нужен setTimeout\setInterval чтобы постоянно обновлять данные с сервера, но как при этом выводить только те сообщения которые ещё не выведены в шаблон?


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


>Для этого клиент должен "знать", какие сообщения выведены


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

var messages = getMessages(...).then(...);

messages.then(...);

мы выполним тот же самый запрос getMessages(...) и получим тот же самый результат.

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

Ещё есть вариант сохранять сообщения в sessionStorage, где ключем будет ID сообщения, а значением сам его объект. Затем сравнивать программно результаты запросов и sessionStorage, и выводить\сохранять уникальные значения.

>> Не подвергаю ли я пользователей опасности, открывая кукисы для js?


>Нет наверно.


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


>А зачем тебе нужна кука в JS коде? Ведь при отправке аякс-запроса куки и так отправляются на сервер.


Чтобы вывести токен в шаблон формы для csrf-защиты.

>И конечно, странно, что у тебя token хранится в view.


Конечно, я вынесу его из view.
someApprentice #750 #1039350
>>1030006

>> К сожалению, у меня не получилось найти в ejs аналог функции nl2br и при этом чтобы экранировались тэги. В таком случае, будет приемлемым оставить этот костыль?


>nl2br не экранирует теги, она только заменяет \n на <br>, если я не путаю.


>


>Насколько я понял, у тебя проблема в том, что ejs экранирует данные и твой <br> выводится как текст? В документации ( https://github.com/mde/ejs/blob/master/docs/syntax.md ) написано что есть 2 вида тегов, один принимают текст, экранируют его и выводят, другой тег принимает HTML код и вставляет его как есть.


>


>В чем именно сложность-то? Можно сделать так <%- convertMessageToHtml(message) %>


Проблема в том что ejs вообще не переводит с помощью \n на новую строку. Нужно заменять его на <br>, но ejs экранирует его тоже.
Можно не экранировать, а фильтровать с помощью какого-нибудь стороннего html-фильтра, но всё равно нужно как-то заменить \n на <br>.

>> Я никак не могу придумать как выводить только новые сообщения. Определенно, нужен setTimeout\setInterval чтобы постоянно обновлять данные с сервера, но как при этом выводить только те сообщения которые ещё не выведены в шаблон?


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


>Для этого клиент должен "знать", какие сообщения выведены


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

var messages = getMessages(...).then(...);

messages.then(...);

мы выполним тот же самый запрос getMessages(...) и получим тот же самый результат.

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

Ещё есть вариант сохранять сообщения в sessionStorage, где ключем будет ID сообщения, а значением сам его объект. Затем сравнивать программно результаты запросов и sessionStorage, и выводить\сохранять уникальные значения.

>> Не подвергаю ли я пользователей опасности, открывая кукисы для js?


>Нет наверно.


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


>А зачем тебе нужна кука в JS коде? Ведь при отправке аякс-запроса куки и так отправляются на сервер.


Чтобы вывести токен в шаблон формы для csrf-защиты.

>И конечно, странно, что у тебя token хранится в view.


Конечно, я вынесу его из view.
#751 #1039991
>>1035714
Сори что долго не отвечал, то как я бы решал задчу значит в реальном проекте (у меня опыт работы только в небольших проектах)

Для начала в базе заводим табличку с курсом обмена в которой есть как минимум такие столбцы как: курс, дата выставления.

Далее пишу 3 функции, будь это просто в functions.php или методы модельного класса который будет отвечать за работу с баблом.

1. Добавляет в эту табличку новую запись курса обмена
2. Взять из таблички последнюю запись курса обмена.
3. Спросить с удаленного сервера текущий курс.

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

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

Ну а дальше всё просто.
Функция конвертации рубли в доллары в 2 строчки:
На вход курс и рубли, на выходе доллары.

В приложении когда юзер будет что-то хотеть сконвертить, то в контроллере который принимает юзерский инпут с рублями, будет примерно так всё:
Если есть инпут то валидируем инпут, если ок то:
Спрашиваем последнюю запись с таблицы курсов.
Кормим инпут и курс функции конвертации
Отдать ответ в массив инфы который полетит во вьюху.
иначе отдать сообщение что инпут неверен.
#751 #1039991
>>1035714
Сори что долго не отвечал, то как я бы решал задчу значит в реальном проекте (у меня опыт работы только в небольших проектах)

Для начала в базе заводим табличку с курсом обмена в которой есть как минимум такие столбцы как: курс, дата выставления.

Далее пишу 3 функции, будь это просто в functions.php или методы модельного класса который будет отвечать за работу с баблом.

1. Добавляет в эту табличку новую запись курса обмена
2. Взять из таблички последнюю запись курса обмена.
3. Спросить с удаленного сервера текущий курс.

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

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

Ну а дальше всё просто.
Функция конвертации рубли в доллары в 2 строчки:
На вход курс и рубли, на выходе доллары.

В приложении когда юзер будет что-то хотеть сконвертить, то в контроллере который принимает юзерский инпут с рублями, будет примерно так всё:
Если есть инпут то валидируем инпут, если ок то:
Спрашиваем последнюю запись с таблицы курсов.
Кормим инпут и курс функции конвертации
Отдать ответ в массив инфы который полетит во вьюху.
иначе отдать сообщение что инпут неверен.
#752 #1039992
Компетентный ОП в этом треде, или писать в новый, где чат?

Сделал первую часть TestHub.
https://github.com/pricklynut/testhub

Накопилось некоторое кол-во вопросов.

Симфони странно себя ведет после установки, я имею ввиду точки входа.
Если сначала запросить корень сайта / напрямую, выдает 500.
Однако если зайти на /app.php, редиректит на /, и с этого момента
/ доступен напрямую. Однако если почистить кеш, та же фигня. Что он там
кеширует, это так и должно быть?
Странно, больше не повторяется.
update: развернул на другом компе, теперь наоборот редиректит с / на /app.php.
htaccess стандартный, который идет в комплекте с фреймворком.

через раз (буквально) вылетает ошибка
php bin/console cache:clear --no-warmup -e prod
PHP Notice: Undefined index: host in /home/pricklynut/www/testhub.com/app/config/parameters_prod.php on line 6
PHP Notice: Undefined index: port in /home/pricklynut/www/testhub.com/app/config/parameters_prod.php on line 7
PHP Notice: Undefined index: user in /home/pricklynut/www/testhub.com/app/config/parameters_prod.php on line 9
PHP Notice: Undefined index: pass in /home/pricklynut/www/testhub.com/app/config/parameters_prod.php on line 10
PHP Fatal error: Uncaught PDOException: SQLSTATE[08006] [7] ВАЖНО: база данных "connect_timeout=30" не существует in /home/inside/www/testhub.com/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOConnection.php:43
Я понял, что он не может подключиться к бд, но почему через раз, что за магия? Там настройки подключения к бд берутся из переменной среды, но почему один раз эта переменная доступна, другой нет? Переменная среды объявлена в конфиге виртуального хоста.

Как в симфони делать виджеты? В yii виджет это просто класс, который подставляет
переменные из своего конфига в шаблон и возвращает эту строку.
Например echo SidebarWidget::widget(['class' => 'abc', 'title' => 'asdfad']);
В симфони не понимаю, как из модели вызвать render какого-нибудь шаблона.
Допустим, я хотел сделать виджет для пагинации. Класс написал, шаблон пришлось положить
к общим шаблонам, хотя как бы он относится именно к виджету, а не к проекту.

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

По структуре проекта на симфони: куды вообще что писать?
Представления-вьюшки кидать в app/Resources, или в аналогичную папку AppBundle?
Стили, js, тоже в AppBundle/Resources?
Еще в контроллерах у меня скопилось много логики, не знаю куда ее вынести. В модели (entity)
не получится, там нет доступа в бд.
В репозитории тоже как-то неуместно, по сути репозитории должны только извлекать из бд сущности,
желательно одноименные с названием репозитория или связанные.

Короче нужны советы по рефакторингу этого дела.

Пока почитаю, как сделать добавление новых тестов.
Нужно именно одной формой, сам тест, все его вопросы, все варианты ответов на каждый вопрос?
Какая-то жесть получается, а если в тесте сто вопросов по 8 вариантов на каждый? И если на 69 вопросе
пользователь случайно закроет браузер, начинать все сначала? Может, сохранять куда-то (куда?)
промежуточные данные в процессе редактирования?
Пока не представляю как это делать.
#752 #1039992
Компетентный ОП в этом треде, или писать в новый, где чат?

Сделал первую часть TestHub.
https://github.com/pricklynut/testhub

Накопилось некоторое кол-во вопросов.

Симфони странно себя ведет после установки, я имею ввиду точки входа.
Если сначала запросить корень сайта / напрямую, выдает 500.
Однако если зайти на /app.php, редиректит на /, и с этого момента
/ доступен напрямую. Однако если почистить кеш, та же фигня. Что он там
кеширует, это так и должно быть?
Странно, больше не повторяется.
update: развернул на другом компе, теперь наоборот редиректит с / на /app.php.
htaccess стандартный, который идет в комплекте с фреймворком.

через раз (буквально) вылетает ошибка
php bin/console cache:clear --no-warmup -e prod
PHP Notice: Undefined index: host in /home/pricklynut/www/testhub.com/app/config/parameters_prod.php on line 6
PHP Notice: Undefined index: port in /home/pricklynut/www/testhub.com/app/config/parameters_prod.php on line 7
PHP Notice: Undefined index: user in /home/pricklynut/www/testhub.com/app/config/parameters_prod.php on line 9
PHP Notice: Undefined index: pass in /home/pricklynut/www/testhub.com/app/config/parameters_prod.php on line 10
PHP Fatal error: Uncaught PDOException: SQLSTATE[08006] [7] ВАЖНО: база данных "connect_timeout=30" не существует in /home/inside/www/testhub.com/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOConnection.php:43
Я понял, что он не может подключиться к бд, но почему через раз, что за магия? Там настройки подключения к бд берутся из переменной среды, но почему один раз эта переменная доступна, другой нет? Переменная среды объявлена в конфиге виртуального хоста.

Как в симфони делать виджеты? В yii виджет это просто класс, который подставляет
переменные из своего конфига в шаблон и возвращает эту строку.
Например echo SidebarWidget::widget(['class' => 'abc', 'title' => 'asdfad']);
В симфони не понимаю, как из модели вызвать render какого-нибудь шаблона.
Допустим, я хотел сделать виджет для пагинации. Класс написал, шаблон пришлось положить
к общим шаблонам, хотя как бы он относится именно к виджету, а не к проекту.

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

По структуре проекта на симфони: куды вообще что писать?
Представления-вьюшки кидать в app/Resources, или в аналогичную папку AppBundle?
Стили, js, тоже в AppBundle/Resources?
Еще в контроллерах у меня скопилось много логики, не знаю куда ее вынести. В модели (entity)
не получится, там нет доступа в бд.
В репозитории тоже как-то неуместно, по сути репозитории должны только извлекать из бд сущности,
желательно одноименные с названием репозитория или связанные.

Короче нужны советы по рефакторингу этого дела.

Пока почитаю, как сделать добавление новых тестов.
Нужно именно одной формой, сам тест, все его вопросы, все варианты ответов на каждый вопрос?
Какая-то жесть получается, а если в тесте сто вопросов по 8 вариантов на каждый? И если на 69 вопросе
пользователь случайно закроет браузер, начинать все сначала? Может, сохранять куда-то (куда?)
промежуточные данные в процессе редактирования?
Пока не представляю как это делать.
#753 #1040025
>>1039350

> Проблема в том что ejs вообще не переводит с помощью \n на новую строку.


А почему он должен? Он просто выводит этот \n в итоговый HTML, а дальше уже браузер его игнорирует.

Нужно использовать функцию, заменяющую \n на <br> и экранирующую спецсиволы, и выводить результат через неэкранирующий тег (<%- ... ). Либо, как альтернативу, можно использовать свойство CSS white-space, чтобы переводы строк выводились как в исходном коде: https://developer.mozilla.org/ru/docs/Web/CSS/white-space

> Нужно заменять его на <br>, но ejs экранирует его тоже.


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

> Вероятно, мы не можем даже к этому обещанию добавить ещё результаты, потому что, вероятно, если мы напишем


> var messages = getMessages(...).then(...);


> messages.then(...);


> мы выполним тот же самый запрос getMessages(...) и получим тот же самый результат.


Нет, второй раз запрос не выполнится. Просто последний then() получит на вход значение, которое вернул через return предпоследний then.

> Ещё есть вариант сохранять сообщения в sessionStorage, где ключем будет ID сообщения, а значением сам его объект. Затем сравнивать программно результаты запросов и sessionStorage, и выводить\сохранять уникальные значения.


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

>>А зачем тебе нужна кука в JS коде?


> Чтобы вывести токен в шаблон формы для csrf-защиты.


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

>>1039102

Я думаю, что нет.
#753 #1040025
>>1039350

> Проблема в том что ejs вообще не переводит с помощью \n на новую строку.


А почему он должен? Он просто выводит этот \n в итоговый HTML, а дальше уже браузер его игнорирует.

Нужно использовать функцию, заменяющую \n на <br> и экранирующую спецсиволы, и выводить результат через неэкранирующий тег (<%- ... ). Либо, как альтернативу, можно использовать свойство CSS white-space, чтобы переводы строк выводились как в исходном коде: https://developer.mozilla.org/ru/docs/Web/CSS/white-space

> Нужно заменять его на <br>, но ejs экранирует его тоже.


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

> Вероятно, мы не можем даже к этому обещанию добавить ещё результаты, потому что, вероятно, если мы напишем


> var messages = getMessages(...).then(...);


> messages.then(...);


> мы выполним тот же самый запрос getMessages(...) и получим тот же самый результат.


Нет, второй раз запрос не выполнится. Просто последний then() получит на вход значение, которое вернул через return предпоследний then.

> Ещё есть вариант сохранять сообщения в sessionStorage, где ключем будет ID сообщения, а значением сам его объект. Затем сравнивать программно результаты запросов и sessionStorage, и выводить\сохранять уникальные значения.


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

>>А зачем тебе нужна кука в JS коде?


> Чтобы вывести токен в шаблон формы для csrf-защиты.


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

>>1039102

Я думаю, что нет.
#754 #1040027
>>1036395

> Только почему-то я не вижу методов генерации ключей. Нужно найти другую в таком случае?



Для начала, надо разобраться, что это за расширение и как оно вообще работает. Идем сюда: http://php.net/manual/ru/gnupg.installation.php , отсюда сюда: http://pecl.php.net/package/gnupg и тут видим "wrapper around the gpgme library". Находим мануал к этой библиотеке: https://www.gnupg.org/documentation/manuals/gpgme/

К сожалению, в мануале разобраться сложно, потому пойдем другим путем. Упомянутая там библиотека GPGME - это библиотека, которая позволяет выполнять те же функции, что и команда gpg, только вызывая их программно. Потому почитаем мануал по gpg ( https://www.gnupg.org/gph/en/manual.html ). Там это явно не написано (видимо все и так должны это знать), но можно догадаться, что у этой программы есть хранилище ключей (keyring) - по сути просто файл в домашнем каталоге пользователя. И ты можешь генерировать новые ключи, а также импортировать ключи других людей в этот самый keyring. И при подписывании/шифровании/проверке подписи/расшифровке испоьзуются именно ключи из keyring.

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

Теперь принцип работы функций из gnupg становится понятен. Если мы откроем пример кода из мануала: http://php.net/manual/ru/gnupg.examples-clearsign.php

> // добавить ключ для подписания с паролем 'test'


> $gnupg->addsignkey("8660281B6051D071D94B5B230549F9DC851566DC", "test");


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

> $signed = $gnupg->sign("просто тест");



Соответственно, вот что получается:

> Только почему-то я не вижу методов генерации ключей.


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

> Почему несколько методов для добавления ключей?


Наверно потому что это ключи для разных целей.

> Вообще, функции add..cryptkey выглядят довольно странно, в аргументы принимают отпечаток, а не сам ключи


Они ищут ключ внутри keyring по отпечатку.

> Почему ключи должны храниться где-то на диске?


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

>>Or just fetch a minified build under dist.


> Они же предлагают это сделать в случае браузерной версии?


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

> В отличии от php-библиотеки, js-библиотека использует подпись. Это одно и тоже, в этом случае?


Нет. PHP библиотека использовала отпечаток (fingerprint), чтобы идентифицировать ключ в keyring, а здесь другое:

> signature Signature (optional) a detached signature to add to the encrypted message


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

> Что такое armoredText?


Нужно почитать мануал к gpg:

> Create ASCII-armored output that can be safely e-mailed, instead of binary output:


> -a, --armor



Это значит, что данные представлены в виде печатаемых символов (текста), и их можно например скопировать и переслать в письме или опублировать (то есть вроде кодировки base64). Другой вариант - это использовать бинарное кодирование, когда данные представлены просто в виде набора байт, которые могут не соответствовать тексту (так как в utf-8 например не все последовательности байт соответствуют символам, и при попытке скопировать кракозябры что-то может потеряться). Бинарный формат компактнее.

> Обе эти функции используют passphrase, этой фразой шифруется приватный ключ и можно использовать эту опции в нашем случае?


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

> Зачем здесь может быть нужен Promise?


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

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

Почитай про веб воркеры: https://developer.mozilla.org/ru/docs/DOM/Using_web_workers

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

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

Плюс, я тут подумал, может это позволит как-то интегрироваться с GPG, то есть, например, обмениваться сообщениями с теми, кто использует обычную почту с шифрованием через gpg.
#754 #1040027
>>1036395

> Только почему-то я не вижу методов генерации ключей. Нужно найти другую в таком случае?



Для начала, надо разобраться, что это за расширение и как оно вообще работает. Идем сюда: http://php.net/manual/ru/gnupg.installation.php , отсюда сюда: http://pecl.php.net/package/gnupg и тут видим "wrapper around the gpgme library". Находим мануал к этой библиотеке: https://www.gnupg.org/documentation/manuals/gpgme/

К сожалению, в мануале разобраться сложно, потому пойдем другим путем. Упомянутая там библиотека GPGME - это библиотека, которая позволяет выполнять те же функции, что и команда gpg, только вызывая их программно. Потому почитаем мануал по gpg ( https://www.gnupg.org/gph/en/manual.html ). Там это явно не написано (видимо все и так должны это знать), но можно догадаться, что у этой программы есть хранилище ключей (keyring) - по сути просто файл в домашнем каталоге пользователя. И ты можешь генерировать новые ключи, а также импортировать ключи других людей в этот самый keyring. И при подписывании/шифровании/проверке подписи/расшифровке испоьзуются именно ключи из keyring.

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

Теперь принцип работы функций из gnupg становится понятен. Если мы откроем пример кода из мануала: http://php.net/manual/ru/gnupg.examples-clearsign.php

> // добавить ключ для подписания с паролем 'test'


> $gnupg->addsignkey("8660281B6051D071D94B5B230549F9DC851566DC", "test");


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

> $signed = $gnupg->sign("просто тест");



Соответственно, вот что получается:

> Только почему-то я не вижу методов генерации ключей.


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

> Почему несколько методов для добавления ключей?


Наверно потому что это ключи для разных целей.

> Вообще, функции add..cryptkey выглядят довольно странно, в аргументы принимают отпечаток, а не сам ключи


Они ищут ключ внутри keyring по отпечатку.

> Почему ключи должны храниться где-то на диске?


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

>>Or just fetch a minified build under dist.


> Они же предлагают это сделать в случае браузерной версии?


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

> В отличии от php-библиотеки, js-библиотека использует подпись. Это одно и тоже, в этом случае?


Нет. PHP библиотека использовала отпечаток (fingerprint), чтобы идентифицировать ключ в keyring, а здесь другое:

> signature Signature (optional) a detached signature to add to the encrypted message


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

> Что такое armoredText?


Нужно почитать мануал к gpg:

> Create ASCII-armored output that can be safely e-mailed, instead of binary output:


> -a, --armor



Это значит, что данные представлены в виде печатаемых символов (текста), и их можно например скопировать и переслать в письме или опублировать (то есть вроде кодировки base64). Другой вариант - это использовать бинарное кодирование, когда данные представлены просто в виде набора байт, которые могут не соответствовать тексту (так как в utf-8 например не все последовательности байт соответствуют символам, и при попытке скопировать кракозябры что-то может потеряться). Бинарный формат компактнее.

> Обе эти функции используют passphrase, этой фразой шифруется приватный ключ и можно использовать эту опции в нашем случае?


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

> Зачем здесь может быть нужен Promise?


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

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

Почитай про веб воркеры: https://developer.mozilla.org/ru/docs/DOM/Using_web_workers

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

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

Плюс, я тут подумал, может это позволит как-то интегрироваться с GPG, то есть, например, обмениваться сообщениями с теми, кто использует обычную почту с шифрованием через gpg.
#755 #1040028
>>1036018

Меньше писать приходится, синтакси более лаконичный. А вообще, это подробно разобрано на сайте самого твига: https://twig.symfony.com/

>>1039991

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

> Также, мы хотим протестировать эти функции по отдельности, а именно:


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


> - проверить, что функция запроса курса с сервера работает, то есть возвращает адекватное число, при этом не сохранять результат никуда


> - проверить, что кеширование работает, что курс в течение дня запрашивается только один раз



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

Один из вариантов реализовать код как несколько независимых модулей - использовать ООП и упоминавшийся где-то выше Dependeny Injection. В моем уроке по DI ( https://github.com/codedokode/pasta/blob/master/arch/di.md ) есть похожий пример кода, с разбиением на отдельные классы.

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

Если ты хочешь понять, как именно, то для начала нужно хорошо разобраться в ООП, потом изучить DI, ну а потом наверно у тебя появятся идеи, что можно сделать. Чтобы разобраться в ООП, я тебе могу посоветовать взять мой учебник из ОП поста, и там прочитать главу про ООП и решить задачи в ней (если только ты их уже не решил).
#756 #1040029
>>1039992

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

> Однако если зайти на /app.php, редиректит на /, и с этого момента / доступен напрямую. Однако если почистить кеш, та же фигня. Что он там кеширует, это так и должно быть?



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

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

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

> PHP Notice: Undefined index: host in /home/pricklynut/www/testhub.com/app/config/parameters_prod.php on line 6



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

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


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

> Как в симфони делать виджеты?


Нет готового решения? Нельзя виджет представить в виде объекта с данными, и отдельного шаблона twig, в который мы передаем этот объект?

> В симфони не понимаю, как из модели вызвать render какого-нибудь шаблона.


В MVC за отображение данных отвечает Вид, а модель ничего не рендерит.

> Допустим, я хотел сделать виджет для пагинации. Класс написал, шаблон пришлось положить к общим шаблонам, хотя как бы он относится именно к виджету, а не к проекту.


Можно сделать для таких шаблонов отдельную папку, например, views/widgets/. И сделать объект, содержащий информацию о пагинации (число страниц, текущая страница и тд). Я вижу, у тебя есть класс, представляющий пагинацию.

Также, в Симфони есть бандлы, можно сделать бандл и в него класть виджеты, но не вижу выгоды.

> Странно, что в бутстрапе в пагинации текущая страница и неактивная ссылка на предыдущую содержат кликабельную ссылку


Можно вместо <a> использовать <span> для текущей страницы и ссылки не будет.

> По-моему эти ссылки вообще нужно удалить, но если это сделать, ломается верстка.


Нужно спан поставить, смотри мануал по бутстрапу.

> Представления-вьюшки кидать в app/Resources, или в аналогичную папку AppBundle?


Насчет бандлов, там не все так просто. Вообще бандлы - это что-то вроде библиотек, или даже мини-приложений, так как бандл может содержать свои шаблоны, сущности доктрины, контроллеры, сервисы, параметры конфига. Ну например, можно форум или блог оформить как бандл так, что его можно добавить на любой сайт на Симфони и все будет работать из коробки. Это описано тут: https://symfony.com/doc/current/bundles/best_practices.html

Если тебе такая возможность не требуется, то по идее ты оформляешь свое приложение как один AppBundle. Но в новых версиях Симфони все идет к тому, чтобы вообще отказаться от AppBundle и испоьзовать просто папку app или src, вот почитай:

- https://knpuniversity.com/screencast/symfony3-upgrade/new-dir-structure
- http://fabien.potencier.org/symfony4-directory-structure.html

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

По поводу твоего вопроса, ответ на него тут: http://symfony.com/doc/current/quick_tour/the_architecture.html

> app/


> The application configuration, templates and translations.


Шаблоны в Симфони 3 должны быть тут.

> Стили, js, тоже в AppBundle/Resources?


Можно в web, если ты не используешь управление статикой (assetic например).

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


В сервисы (они же хелперы). Прочитай внимательно мой урок по MVC: https://github.com/codedokode/pasta/blob/master/arch/mvc.md

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

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

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

> В модели (entity) не получится, там нет доступа в бд.


модель это не только entity и не только код работы с БД, почитай мой урок про MVC

> Нужно именно одной формой, сам тест, все его вопросы, все варианты ответов на каждый вопрос?


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

> Какая-то жесть получается, а если в тесте сто вопросов по 8 вариантов на каждый?


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

> Может, сохранять куда-то (куда?) промежуточные данные в процессе редактирования?


Можно в localStorage, можно на сервер в фоновом режиме.

-----

По коду: если у тебя требуется PHP7, то напиши это в composer.json, сейчас там указан php5.

По поводу Симфони: там есть одна вещь, которая мне не нравится. Они в продакшене (в отличие от dev) не превращают ошибки в исключения и не используют strict_variables в твиге. Я думаю, это плохая идея и надо переделать это. Это идет вразрез в принципом fail fast и способствует более низкому качеству кода.

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

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

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

В Postgres можно использовать CHECK на колонках для ограничения вставляемых значений.

Поиск данных через связи не всегда эффективен.

Пока код выгодит нормально, надо только контроллер разгрузить.

Также, если есть время и возможность, советую подумать про добавление автоматизированных тестов, в ОП посте есть урок. Раз за Симфони взялся, надо бы и тестирование подучить.
#756 #1040029
>>1039992

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

> Однако если зайти на /app.php, редиректит на /, и с этого момента / доступен напрямую. Однако если почистить кеш, та же фигня. Что он там кеширует, это так и должно быть?



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

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

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

> PHP Notice: Undefined index: host in /home/pricklynut/www/testhub.com/app/config/parameters_prod.php on line 6



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

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


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

> Как в симфони делать виджеты?


Нет готового решения? Нельзя виджет представить в виде объекта с данными, и отдельного шаблона twig, в который мы передаем этот объект?

> В симфони не понимаю, как из модели вызвать render какого-нибудь шаблона.


В MVC за отображение данных отвечает Вид, а модель ничего не рендерит.

> Допустим, я хотел сделать виджет для пагинации. Класс написал, шаблон пришлось положить к общим шаблонам, хотя как бы он относится именно к виджету, а не к проекту.


Можно сделать для таких шаблонов отдельную папку, например, views/widgets/. И сделать объект, содержащий информацию о пагинации (число страниц, текущая страница и тд). Я вижу, у тебя есть класс, представляющий пагинацию.

Также, в Симфони есть бандлы, можно сделать бандл и в него класть виджеты, но не вижу выгоды.

> Странно, что в бутстрапе в пагинации текущая страница и неактивная ссылка на предыдущую содержат кликабельную ссылку


Можно вместо <a> использовать <span> для текущей страницы и ссылки не будет.

> По-моему эти ссылки вообще нужно удалить, но если это сделать, ломается верстка.


Нужно спан поставить, смотри мануал по бутстрапу.

> Представления-вьюшки кидать в app/Resources, или в аналогичную папку AppBundle?


Насчет бандлов, там не все так просто. Вообще бандлы - это что-то вроде библиотек, или даже мини-приложений, так как бандл может содержать свои шаблоны, сущности доктрины, контроллеры, сервисы, параметры конфига. Ну например, можно форум или блог оформить как бандл так, что его можно добавить на любой сайт на Симфони и все будет работать из коробки. Это описано тут: https://symfony.com/doc/current/bundles/best_practices.html

Если тебе такая возможность не требуется, то по идее ты оформляешь свое приложение как один AppBundle. Но в новых версиях Симфони все идет к тому, чтобы вообще отказаться от AppBundle и испоьзовать просто папку app или src, вот почитай:

- https://knpuniversity.com/screencast/symfony3-upgrade/new-dir-structure
- http://fabien.potencier.org/symfony4-directory-structure.html

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

По поводу твоего вопроса, ответ на него тут: http://symfony.com/doc/current/quick_tour/the_architecture.html

> app/


> The application configuration, templates and translations.


Шаблоны в Симфони 3 должны быть тут.

> Стили, js, тоже в AppBundle/Resources?


Можно в web, если ты не используешь управление статикой (assetic например).

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


В сервисы (они же хелперы). Прочитай внимательно мой урок по MVC: https://github.com/codedokode/pasta/blob/master/arch/mvc.md

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

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

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

> В модели (entity) не получится, там нет доступа в бд.


модель это не только entity и не только код работы с БД, почитай мой урок про MVC

> Нужно именно одной формой, сам тест, все его вопросы, все варианты ответов на каждый вопрос?


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

> Какая-то жесть получается, а если в тесте сто вопросов по 8 вариантов на каждый?


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

> Может, сохранять куда-то (куда?) промежуточные данные в процессе редактирования?


Можно в localStorage, можно на сервер в фоновом режиме.

-----

По коду: если у тебя требуется PHP7, то напиши это в composer.json, сейчас там указан php5.

По поводу Симфони: там есть одна вещь, которая мне не нравится. Они в продакшене (в отличие от dev) не превращают ошибки в исключения и не используют strict_variables в твиге. Я думаю, это плохая идея и надо переделать это. Это идет вразрез в принципом fail fast и способствует более низкому качеству кода.

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

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

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

В Postgres можно использовать CHECK на колонках для ограничения вставляемых значений.

Поиск данных через связи не всегда эффективен.

Пока код выгодит нормально, надо только контроллер разгрузить.

Также, если есть время и возможность, советую подумать про добавление автоматизированных тестов, в ОП посте есть урок. Раз за Симфони взялся, надо бы и тестирование подучить.
#757 #1040030
Аноны, переходите в новый тред >>1033564 (OP)

Также, те, кому я еще не ответил, напомните о себе в новом треде
someApprentice #758 #1040147
>>1040025

>> Ещё есть вариант сохранять сообщения в sessionStorage, где ключем будет ID сообщения, а значением сам его объект. Затем сравнивать программно результаты запросов и sessionStorage, и выводить\сохранять уникальные значения.


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


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

>> Вероятно, мы не можем даже к этому обещанию добавить ещё результаты, потому что, вероятно, если мы напишем


>> var messages = getMessages(...).then(...);


>> messages.then(...);


>> мы выполним тот же самый запрос getMessages(...) и получим тот же самый результат.


>Нет, второй раз запрос не выполнится. Просто последний then() получит на вход значение, которое вернул через return предпоследний then.


Значит можно будет написать так

function chat() {
this.messages;
}

chat.runMessages(...) {
this.messages = getMessages(...).then(...);

refreshMessages(...);
}

chat.refreshMessages(...) {
this.messages.then(

function(messages) {
// Получаем дату\ID последнего сообщения
var lastDate = messages.lastMessage.date;

// Получаем новые сообщения
getNewMessages(lastDate).then(

function(data) {
//Выводим новые сообщения
showMessages(data);

// и добавляем их к остальным
messages.lastMessage = data.lastMessage;

var length = Object.keys(messages.m).length; // m - хэш с самими сообщениями

for (var key in data.m) {
messages.m[length] = data.m[key];

length++;
}

return messages;
},

...
);

return messages;
},

...
);
}

Я ведь правильно объединил массивы сообщений из двух разных обещаний?
someApprentice #758 #1040147
>>1040025

>> Ещё есть вариант сохранять сообщения в sessionStorage, где ключем будет ID сообщения, а значением сам его объект. Затем сравнивать программно результаты запросов и sessionStorage, и выводить\сохранять уникальные значения.


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


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

>> Вероятно, мы не можем даже к этому обещанию добавить ещё результаты, потому что, вероятно, если мы напишем


>> var messages = getMessages(...).then(...);


>> messages.then(...);


>> мы выполним тот же самый запрос getMessages(...) и получим тот же самый результат.


>Нет, второй раз запрос не выполнится. Просто последний then() получит на вход значение, которое вернул через return предпоследний then.


Значит можно будет написать так

function chat() {
this.messages;
}

chat.runMessages(...) {
this.messages = getMessages(...).then(...);

refreshMessages(...);
}

chat.refreshMessages(...) {
this.messages.then(

function(messages) {
// Получаем дату\ID последнего сообщения
var lastDate = messages.lastMessage.date;

// Получаем новые сообщения
getNewMessages(lastDate).then(

function(data) {
//Выводим новые сообщения
showMessages(data);

// и добавляем их к остальным
messages.lastMessage = data.lastMessage;

var length = Object.keys(messages.m).length; // m - хэш с самими сообщениями

for (var key in data.m) {
messages.m[length] = data.m[key];

length++;
}

return messages;
},

...
);

return messages;
},

...
);
}

Я ведь правильно объединил массивы сообщений из двух разных обещаний?
#759 #1040638
>>1040028
Не понимаю что значит модули. Это когда библиотеку типа пишешь, а потом её подгружают все кто хочет и в коде у себя использует?

Под каждый модуль писать класс?

И всё таки не понятно что такое DI и DI-контейнер. В двух словах можно описать как-нибудь какую он проблему именно решает и что делает?

Очень сложно когда все кругом говорят языком продакшена или другими заумными терминами, а по факту от тебя хотят не такие уж и сложные вещи, но ты просто не можешь понять.
#760 #1041109
>>1040638

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

Я не стал писать "класс", так как это подразумевало бы использование ООП, а код на фукциях тоже по идее можно поделить на модули (например, разложив функции по разным файлам или неймспейсам).

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

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

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

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

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

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

А то, что ты описал, не разбито на модули. У тебя по твоему описанию все эти части спутаны и зависят одна от другой.

------

DI (dependency injection) - это внедрение зависимостей в ООП. Это подход, когда классу передают его зависимости снаружи ("внедряют"), а не он ищет или получает их самостоятельно. Что такое "зависимость", описано в моем уроке про DI ( https://github.com/codedokode/pasta/blob/master/arch/di.md )

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

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

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


Ты скорее всего просто пропустил какие-то базовые вещи, берешься сразу за сложное, оттого и не понимаешь.
#760 #1041109
>>1040638

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

Я не стал писать "класс", так как это подразумевало бы использование ООП, а код на фукциях тоже по идее можно поделить на модули (например, разложив функции по разным файлам или неймспейсам).

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

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

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

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

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

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

А то, что ты описал, не разбито на модули. У тебя по твоему описанию все эти части спутаны и зависят одна от другой.

------

DI (dependency injection) - это внедрение зависимостей в ООП. Это подход, когда классу передают его зависимости снаружи ("внедряют"), а не он ищет или получает их самостоятельно. Что такое "зависимость", описано в моем уроке про DI ( https://github.com/codedokode/pasta/blob/master/arch/di.md )

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

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

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


Ты скорее всего просто пропустил какие-то базовые вещи, берешься сразу за сложное, оттого и не понимаешь.
#761 #1041166
антоны стоит ли учиться навечку в cms?
или забить и вкатиться в ворпресс\т.п.?
#762 #1041219
>>1041166
Вам в новый тред,вьюноша
>>1040030

>>>1033564 (OP)

#763 #1042467
Норот.
Помогите с проблемой.
Кароч есть скрипт для CLI. Изначально был сделан для работы в связке с AJAX. AJAX продолжал вызывать скрипт с разными параметрами, пока не было встречено определенное условие. Затем поставили задачу переделать под работу с CRON. CRON подходит в качестве инициатора, но не связующего звена, т.к. может выполняться не чаще раза в минуту, а скрипт должен вызывать сам себя, как только текущая операция завершена.
Сделал следующее:
передал register_shutdown_function коллбэк, в котором делаю дисконнект с БД и затем использую команду passthru, чтобы начать следующую итерацию.
В итоге столкнулся с проблемой "открыто слишком много файлов". Скрипт выполняет под рутом и где-то на 50-ой итерации php крашится, т.к. рут превышает ulimit использования файлов.
Подозреваю, что это вызвано тем, что изначальный скрипт никогда толком не завершается и ждет результата выполнения passthru. По сути, получается рекурсия, которая сжирает ресурсы.
Вопрос: как решить задачу связывания вызовов скрипта и при этом высвобождать ресурсы?
Тред утонул или удален.
Это копия, сохраненная 11 августа 2017 года.

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

Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
« /pr/В начало тредаВеб-версияНастройки
/a//b//mu//s//vg/Все доски